~gabe/flashlight-firmware/anduril2

« back to all changes in this revision

Viewing changes to ToyKeeper/battcheck/offtime-cap.c

  • Committer: Selene Scriven
  • Date: 2015-09-14 19:23:29 UTC
  • mto: (153.1.18 tiny25)
  • mto: This revision was merged to the branch mainline in revision 156.
  • Revision ID: ubuntu@toykeeper.net-20150914192329-0ean5s8qpnnkdbub
updated to BLF-VLD 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This firmware simply helps calibrate values for voltage readings.
 
3
 * It is not intended to be used as an actual flashlight.
 
4
 *
 
5
 * It will read the voltage, then read out the raw value as a series of
 
6
 * blinks.  It will provide up to three groups of blinks, representing the
 
7
 * hundreds digit, the tens digit, then the ones.  So, for a raw value of 183,
 
8
 * it would blink once, pause, blink eight times, pause, then blink three times.
 
9
 * It will then wait longer and re-read the voltage, then repeat.
 
10
 *
 
11
 * NANJG 105C Diagram
 
12
 *           ---
 
13
 *         -|   |- VCC
 
14
 *  Star 4 -|   |- Voltage ADC
 
15
 *  Star 3 -|   |- PWM
 
16
 *     GND -|   |- Star 2
 
17
 *           ---
 
18
 *
 
19
 * CPU speed is 4.8Mhz without the 8x divider when low fuse is 0x75
 
20
 *
 
21
 * define F_CPU 4800000  CPU: 4.8MHz  PWM: 9.4kHz       ####### use low fuse: 0x75  #######
 
22
 *                             /8     PWM: 1.176kHz     ####### use low fuse: 0x65  #######
 
23
 * define F_CPU 9600000  CPU: 9.6MHz  PWM: 19kHz        ####### use low fuse: 0x7a  #######
 
24
 *                             /8     PWM: 2.4kHz       ####### use low fuse: 0x6a  #######
 
25
 *
 
26
 * Above PWM speeds are for phase-correct PWM.  This program uses Fast-PWM,
 
27
 * which when the CPU is 4.8MHz will be 18.75 kHz
 
28
 *
 
29
 * FUSES
 
30
 *      I use these fuse settings
 
31
 *      Low:  0x75
 
32
 *      High: 0xff
 
33
 *
 
34
 * STARS (not used)
 
35
 *
 
36
 */
 
37
// set some hardware-specific values...
 
38
// (while configuring this firmware, skip this section)
 
39
#if (ATTINY == 13)
 
40
#define F_CPU 4800000UL
 
41
#define EEPLEN 64
 
42
#define DELAY_TWEAK 950
 
43
#elif (ATTINY == 25)
 
44
#define F_CPU 8000000UL
 
45
#define EEPLEN 128
 
46
#define DELAY_TWEAK 2000
 
47
#else
 
48
Hey, you need to define ATTINY.
 
49
#endif
 
50
 
 
51
 
 
52
/*
 
53
 * =========================================================================
 
54
 * Settings to modify per driver
 
55
 */
 
56
 
 
57
#define OWN_DELAY   // Should we use the built-in delay or our own?
 
58
 
 
59
#define BLINK_PWM   20
 
60
 
 
61
/*
 
62
 * =========================================================================
 
63
 */
 
64
 
 
65
#ifdef OWN_DELAY
 
66
#include <util/delay_basic.h>
 
67
// Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
 
68
static void _delay_ms(uint16_t n)
 
69
{
 
70
    while(n-- > 0)
 
71
        _delay_loop_2(DELAY_TWEAK);
 
72
}
 
73
#else
 
74
#include <util/delay.h>
 
75
#endif
 
76
 
 
77
#include <avr/pgmspace.h>
 
78
#include <avr/interrupt.h>
 
79
#include <avr/wdt.h>
 
80
#include <avr/eeprom.h>
 
81
#include <avr/sleep.h>
 
82
 
 
83
#define STAR2_PIN   PB0
 
84
#define STAR3_PIN   PB4
 
85
#define STAR4_PIN   PB3
 
86
#define CAP_PIN     PB3
 
87
#define CAP_CHANNEL 0x03    // MUX 03 corresponds with PB3 (Star 4)
 
88
#define CAP_DIDR    ADC3D   // Digital input disable bit corresponding with PB3
 
89
#define PWM_PIN     PB1
 
90
#define VOLTAGE_PIN PB2
 
91
#define ADC_CHANNEL 0x01    // MUX 01 corresponds with PB2
 
92
#define ADC_DIDR    ADC1D   // Digital input disable bit corresponding with PB2
 
93
#define ADC_PRSCL   0x06    // clk/64
 
94
 
 
95
#define PWM_LVL     OCR0B   // OCR0B is the output compare register for PB1
 
96
 
 
97
inline void ADC_on() {
 
98
#if (ATTINY == 13)
 
99
    ADMUX  = (1 << REFS0) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
 
100
#elif (ATTINY == 25)
 
101
    ADMUX  = (1 << REFS1) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
 
102
#endif
 
103
    DIDR0 |= (1 << ADC_DIDR);                           // disable digital input on ADC pin to reduce power consumption
 
104
    ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;   // enable, start, prescale
 
105
}
 
106
 
 
107
inline void ADC_off() {
 
108
    ADCSRA &= ~(1<<7); //ADC off
 
109
}
 
110
 
 
111
uint8_t get_reading() {
 
112
    // Start up ADC for capacitor pin
 
113
    DIDR0 |= (1 << CAP_DIDR);                           // disable digital input on ADC pin to reduce power consumption
 
114
#if (ATTINY == 13)
 
115
    ADMUX  = (1 << REFS0) | (1 << ADLAR) | CAP_CHANNEL; // 1.1v reference, left-adjust, ADC3/PB3
 
116
#elif (ATTINY == 25)
 
117
    ADMUX  = (1 << REFS1) | (1 << ADLAR) | CAP_CHANNEL; // 1.1v reference, left-adjust, ADC3/PB3
 
118
#endif
 
119
    ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;   // enable, start, prescale
 
120
    // Wait for completion
 
121
    while (ADCSRA & (1 << ADSC));
 
122
#if 1
 
123
    // Start again as datasheet says first result is unreliable
 
124
    ADCSRA |= (1 << ADSC);
 
125
    // Wait for completion
 
126
    while (ADCSRA & (1 << ADSC));
 
127
#endif
 
128
    // just return the value
 
129
    return ADCH;
 
130
}
 
131
 
 
132
void noblink() {
 
133
    PWM_LVL = (BLINK_PWM>>2);
 
134
    _delay_ms(5);
 
135
    PWM_LVL = 0;
 
136
    _delay_ms(200);
 
137
}
 
138
 
 
139
void blink() {
 
140
    PWM_LVL = BLINK_PWM;
 
141
    _delay_ms(150);
 
142
    PWM_LVL = 0;
 
143
    _delay_ms(200);
 
144
}
 
145
 
 
146
int main(void)
 
147
{
 
148
    uint16_t value;
 
149
 
 
150
    // Set PWM pin to output
 
151
    DDRB = (1 << PWM_PIN);
 
152
 
 
153
    // Set timer to do PWM for correct output pin and set prescaler timing
 
154
    TCCR0A = 0x21; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
 
155
    TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
 
156
 
 
157
    // Turn features on or off as needed
 
158
    ADC_on();
 
159
    ACSR   |=  (1<<7); //AC off
 
160
 
 
161
    // get an average of several readings
 
162
    /*
 
163
    uint8_t i;
 
164
    value = 0;
 
165
    for (i=0; i<8; i++) {
 
166
        value += get_reading();
 
167
        _delay_ms(50);
 
168
    }
 
169
    value = value >> 3;
 
170
    */
 
171
    value = get_reading();
 
172
 
 
173
    // Turn off ADC
 
174
    ADC_off();
 
175
 
 
176
    // Charge up the capacitor by setting CAP_PIN to output
 
177
    DDRB  |= (1 << CAP_PIN);    // Output
 
178
    PORTB |= (1 << CAP_PIN);    // High
 
179
 
 
180
 
 
181
    // blink once on receiving power
 
182
    //PWM_LVL = 255;
 
183
    //_delay_ms(5);
 
184
    //PWM_LVL = 0;
 
185
 
 
186
    // hundreds
 
187
    while (value >= 100) {
 
188
        value -= 100;
 
189
        blink();
 
190
    }
 
191
    _delay_ms(1000);
 
192
 
 
193
    // tens
 
194
    if (value < 10) {
 
195
        noblink();
 
196
    }
 
197
    while (value >= 10) {
 
198
        value -= 10;
 
199
        blink();
 
200
    }
 
201
    _delay_ms(1000);
 
202
 
 
203
    // ones
 
204
    if (value <= 0) {
 
205
        noblink();
 
206
    }
 
207
    while (value > 0) {
 
208
        value -= 1;
 
209
        blink();
 
210
    }
 
211
    _delay_ms(1000);
 
212
 
 
213
    while(1) {
 
214
        _delay_ms(1000);
 
215
    }
 
216
}