~gabe/flashlight-firmware/anduril2

« back to all changes in this revision

Viewing changes to ToyKeeper/s7/brass-edc.c

  • Committer: Selene Scriven
  • Date: 2015-11-24 09:48:09 UTC
  • mfrom: (150.1.16 sandbox)
  • Revision ID: ubuntu@toykeeper.net-20151124094809-gkxohuxfrre3aucx
Merged updates to s7 and brass-edc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
57
57
 *          value = (V * 4700 * 255) / (23800 * 1.1)
58
58
 *
59
59
 */
60
 
#define F_CPU 4800000UL
 
60
#define NANJG_LAYOUT
 
61
#include "tk-attiny.h"
 
62
#undef BOGOMIPS  // this particular driver runs slower
 
63
#define BOGOMIPS 1050
61
64
 
62
65
/*
63
66
 * =========================================================================
66
69
 
67
70
#define VOLTAGE_MON                 // Comment out to disable
68
71
#define OWN_DELAY                   // Should we use the built-in delay or our own?
 
72
#define USE_FINE_DELAY
69
73
 
 
74
#define FAST_PWM_START      10      // Anything under this will use phase-correct
70
75
// Lumen measurements used a Nichia 219B at 1900mA in a Convoy S7 host
71
76
#define MODE_MOON           4       // 6: 0.14 lm (6 through 9 may be useful levels)
72
77
#define MODE_LOW            14      // 14: 7.3 lm
74
79
#define MODE_HIGH           110     // 120: 155 lm
75
80
#define MODE_HIGHER         255     // 255: 342 lm
76
81
// If you change these, you'll probably want to change the "modes" array below
77
 
#define SOLID_MODES         5       // How many non-blinky modes will we have?
78
 
#define DUAL_BEACON_MODES   5+3     // How many beacon modes will we have (with background light on)?
79
 
#define SINGLE_BEACON_MODES 5+3+1   // How many beacon modes will we have (without background light on)?
80
 
#define FIXED_STROBE_MODES  5+3+1+3 // How many constant-speed strobe modes?
81
 
#define VARIABLE_STROBE_MODES 5+3+1+3+2 // How many variable-speed strobe modes?
82
 
#define BATT_CHECK_MODE     5+3+1+3+2+1 // battery check mode index
83
 
// Note: don't use more than 32 modes, or it will interfere with the mechanism used for mode memory
84
 
#define TOTAL_MODES         BATT_CHECK_MODE
85
 
 
86
 
//#define ADC_LOW             130     // When do we start ramping
87
 
//#define ADC_CRIT            120     // When do we shut the light off
88
 
 
89
 
#define ADC_42          185 // the ADC value we expect for 4.20 volts
90
 
#define ADC_100         185 // the ADC value for 100% full (4.2V resting)
91
 
#define ADC_75          175 // the ADC value for 75% full (4.0V resting)
92
 
#define ADC_50          164 // the ADC value for 50% full (3.8V resting)
93
 
#define ADC_25          154 // the ADC value for 25% full (3.6V resting)
94
 
#define ADC_0           139 // the ADC value for 0% full (3.3V resting)
95
 
#define ADC_LOW         123 // When do we start ramping down
96
 
#define ADC_CRIT        113 // When do we shut the light off
 
82
// How many non-blinky modes will we have?
 
83
#define SOLID_MODES           5
 
84
// battery check mode index
 
85
#define BATT_CHECK_MODE       1+SOLID_MODES
 
86
// How many beacon modes will we have (without background light on)?
 
87
#define SINGLE_BEACON_MODES   1+BATT_CHECK_MODE
 
88
// How many constant-speed strobe modes?
 
89
#define FIXED_STROBE_MODES    3+SINGLE_BEACON_MODES
 
90
// How many variable-speed strobe modes?
 
91
#define VARIABLE_STROBE_MODES 2+FIXED_STROBE_MODES
 
92
// How many beacon modes will we have (with background light on)?
 
93
#define DUAL_BEACON_MODES     3+VARIABLE_STROBE_MODES
 
94
 
 
95
#define USE_BATTCHECK
 
96
#define BATTCHECK_VpT  // Use the volts+tenths battcheck style
 
97
//#define BATTCHECK_4bars  // Use the volts+tenths battcheck style
 
98
 
 
99
#include "brass-edc-calibration.h"
97
100
 
98
101
/*
99
102
 * =========================================================================
100
103
 */
101
104
 
102
 
#ifdef OWN_DELAY
103
 
#include <util/delay_basic.h>
104
 
// Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
105
 
static void _delay_ms(uint16_t n)
106
 
{
107
 
    // TODO: make this take tenths of a ms instead of ms,
108
 
    // for more precise timing?
109
 
    // (would probably be better than the if/else here for a special-case
110
 
    // sub-millisecond delay)
111
 
    if (n==0) { _delay_loop_2(300); }
112
 
    else {
113
 
        while(n-- > 0)
114
 
            _delay_loop_2(1050);
115
 
    }
116
 
}
117
 
#else
118
 
#include <util/delay.h>
119
 
#endif
 
105
#include "tk-delay.h"
120
106
 
121
107
#include <avr/pgmspace.h>
122
108
#include <avr/interrupt.h>
123
 
#include <avr/eeprom.h>
124
109
#include <avr/sleep.h>
125
110
 
126
 
#define STAR2_PIN   PB0
127
 
#define STAR3_PIN   PB4
128
 
#define STAR4_PIN   PB3
129
 
#define PWM_PIN     PB1
130
 
#define VOLTAGE_PIN PB2
131
 
#define ADC_CHANNEL 0x01    // MUX 01 corresponds with PB2
132
 
#define ADC_DIDR    ADC1D   // Digital input disable bit corresponding with PB2
133
 
#define ADC_PRSCL   0x06    // clk/64
134
 
 
135
 
#define PWM_LVL     OCR0B   // OCR0B is the output compare register for PB1
 
111
#include "tk-voltage.h"
136
112
 
137
113
/*
138
114
 * global variables
150
126
#define memory 0
151
127
 
152
128
// Modes (hardcoded to save space)
153
 
static uint8_t modes[TOTAL_MODES] = { // high enough to handle all
 
129
const uint8_t modes[] = { // high enough to handle all
154
130
    MODE_MOON, MODE_LOW, MODE_MED, MODE_HIGH, MODE_HIGHER, // regular solid modes
155
 
    MODE_MOON, MODE_LOW, MODE_MED, // dual beacon modes (this level and this level + 2)
 
131
    MODE_MED, // battery check mode
156
132
    MODE_HIGHER, // heartbeat beacon
157
133
    82, 41, 15, // constant-speed strobe modes (12 Hz, 24 Hz, 60 Hz)
158
134
    MODE_HIGHER, MODE_HIGHER, // variable-speed strobe modes
159
 
    MODE_MED, // battery check mode
 
135
    MODE_MOON, MODE_LOW, MODE_MED, // dual beacon modes (this level and this level + 2)
160
136
};
161
137
volatile uint8_t mode_idx = 0;
162
138
// 1 or -1. Do we increase or decrease the idx when moving up to a higher mode?
163
139
// Is set by checking stars in the original STAR firmware, but that's removed to save space.
164
140
#define mode_dir 1
165
 
PROGMEM const uint8_t voltage_blinks[] = {
166
 
    ADC_0,    // 1 blink  for 0%-25%
167
 
    ADC_25,   // 2 blinks for 25%-50%
168
 
    ADC_50,   // 3 blinks for 50%-75%
169
 
    ADC_75,   // 4 blinks for 75%-100%
170
 
    ADC_100,  // 5 blinks for >100%
171
 
};
172
141
 
173
142
inline void next_mode() {
174
143
    mode_idx += mode_dir;
175
 
    if (mode_idx > (TOTAL_MODES - 1)) {
 
144
    if (mode_idx > (sizeof(modes) - 1)) {
176
145
        // Wrap around
177
146
        mode_idx = 0;
178
147
    }
179
148
}
180
149
 
181
 
inline void ADC_on() {
182
 
    ADMUX  = (1 << REFS0) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
183
 
    DIDR0 |= (1 << ADC_DIDR);                           // disable digital input on ADC pin to reduce power consumption
184
 
    ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;   // enable, start, prescale
185
 
}
186
 
 
187
 
inline void ADC_off() {
188
 
    ADCSRA &= ~(1<<7); //ADC off
189
 
}
190
 
 
191
 
#ifdef VOLTAGE_MON
192
 
uint8_t get_voltage() {
193
 
    // Start conversion
194
 
    ADCSRA |= (1 << ADSC);
195
 
    // Wait for completion
196
 
    while (ADCSRA & (1 << ADSC));
197
 
    // See if voltage is lower than what we were looking for
198
 
    return ADCH;
 
150
#define BLINK_BRIGHTNESS MODE_MED
 
151
#define BLINK_SPEED 500
 
152
#ifdef BATTCHECK_VpT
 
153
void blink(uint8_t val, uint16_t speed)
 
154
{
 
155
    for (; val>0; val--)
 
156
    {
 
157
        PWM_LVL = BLINK_BRIGHTNESS;
 
158
        _delay_ms(speed);
 
159
        PWM_LVL = 0;
 
160
        _delay_ms(speed<<2);
 
161
    }
 
162
}
 
163
#else
 
164
void blink(uint8_t val)
 
165
{
 
166
    for (; val>0; val--)
 
167
    {
 
168
        PWM_LVL = BLINK_BRIGHTNESS;
 
169
        _delay_ms(100);
 
170
        PWM_LVL = 0;
 
171
        _delay_ms(400);
 
172
    }
199
173
}
200
174
#endif
201
175
 
209
183
    // Set PWM pin to output
210
184
    DDRB = (1 << PWM_PIN);
211
185
 
212
 
    // Set timer to do PWM for correct output pin and set prescaler timing
213
 
    TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
214
 
    TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
215
 
 
216
186
    // Turn features on or off as needed
217
187
    #ifdef VOLTAGE_MON
218
188
    ADC_on();
239
209
    // set noinit data for next boot
240
210
    noinit_decay = 0;
241
211
 
242
 
    if (mode_idx == 0) {
243
 
       TCCR0A = 0x21; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
 
212
    // set PWM mode
 
213
    if (modes[mode_idx] < FAST_PWM_START) {
 
214
        // Set timer to do PWM for correct output pin and set prescaler timing
 
215
        TCCR0A = 0x21; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
 
216
    } else {
 
217
        // Set timer to do PWM for correct output pin and set prescaler timing
 
218
        TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
244
219
    }
 
220
    TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
 
221
 
245
222
    // Now just fire up the mode
246
223
    PWM_LVL = modes[mode_idx];
247
224
 
255
232
    while(1) {
256
233
        if(mode_idx < SOLID_MODES) { // Just stay on at a given brightness
257
234
            sleep_mode();
258
 
        } else if (mode_idx < DUAL_BEACON_MODES) { // two-level fast strobe pulse at about 1 Hz
259
 
            for(i=0; i<4; i++) {
260
 
                PWM_LVL = modes[mode_idx-SOLID_MODES+2];
261
 
                _delay_ms(5);
262
 
                PWM_LVL = modes[mode_idx];
263
 
                _delay_ms(65);
264
 
            }
265
 
            _delay_ms(720);
 
235
        } else if (mode_idx < BATT_CHECK_MODE) {
 
236
            PWM_LVL = 0;
 
237
            get_voltage();  _delay_ms(200);  // the first reading is junk
 
238
#ifdef BATTCHECK_VpT
 
239
            uint8_t result = battcheck();
 
240
            blink(result >> 5, BLINK_SPEED/8);
 
241
            _delay_ms(BLINK_SPEED);
 
242
            blink(1,5);
 
243
            _delay_ms(BLINK_SPEED*3/2);
 
244
            blink(result & 0b00011111, BLINK_SPEED/8);
 
245
#else
 
246
            blink(battcheck());
 
247
#endif  // BATTCHECK_VpT
 
248
            _delay_ms(2000);  // wait at least 2 seconds between readouts
266
249
        } else if (mode_idx < SINGLE_BEACON_MODES) { // heartbeat flasher
267
250
            PWM_LVL = modes[SOLID_MODES-1];
268
251
            _delay_ms(1);
273
256
            PWM_LVL = 0;
274
257
            _delay_ms(749);
275
258
        } else if (mode_idx < FIXED_STROBE_MODES) { // strobe mode, fixed-speed
276
 
            strobe_len = 1;
277
 
            if (modes[mode_idx] < 50) { strobe_len = 0; }
278
259
            PWM_LVL = modes[SOLID_MODES-1];
279
 
            _delay_ms(strobe_len);
 
260
            if (modes[mode_idx] < 50) { _delay_zero(); }
 
261
            else { _delay_ms(1); }
280
262
            PWM_LVL = 0;
281
263
            _delay_ms(modes[mode_idx]);
282
264
        } else if (mode_idx == VARIABLE_STROBE_MODES-2) {
293
275
            // strobe mode, smoothly oscillating frequency ~16 Hz to ~100 Hz
294
276
            for(j=0; j<100; j++) {
295
277
                PWM_LVL = modes[SOLID_MODES-1];
296
 
                _delay_ms(0); // less than a millisecond
 
278
                _delay_zero(); // less than a millisecond
297
279
                PWM_LVL = 0;
298
280
                if (j<50) { strobe_len = j; }
299
281
                else { strobe_len = 100-j; }
300
282
                _delay_ms(strobe_len+9);
301
283
            }
302
 
        } else if (mode_idx < BATT_CHECK_MODE) {
303
 
            uint8_t blinks = 0;
304
 
            // turn off and wait one second before showing the value
305
 
            // (also, ensure voltage is measured while not under load)
306
 
            PWM_LVL = 0;
307
 
            _delay_ms(1000);
308
 
            voltage = get_voltage();
309
 
            voltage = get_voltage(); // the first one is unreliable
310
 
            // division takes too much flash space
311
 
            //voltage = (voltage-ADC_LOW) / (((ADC_42 - 15) - ADC_LOW) >> 2);
312
 
            // a table uses less space than 5 logic clauses
313
 
            for (i=0; i<sizeof(voltage_blinks); i++) {
314
 
                if (voltage > pgm_read_byte(voltage_blinks + i)) {
315
 
                    blinks ++;
316
 
                }
317
 
            }
318
 
 
319
 
            // blink up to five times to show voltage
320
 
            // (~0%, ~25%, ~50%, ~75%, ~100%, >100%)
321
 
            for(i=0; i<blinks; i++) {
322
 
                PWM_LVL = MODE_MED;
323
 
                _delay_ms(100);
324
 
                PWM_LVL = 0;
325
 
                _delay_ms(400);
326
 
            }
327
 
 
328
 
            _delay_ms(1000);  // wait at least 1 second between readouts
 
284
        } else if (mode_idx < DUAL_BEACON_MODES) { // two-level fast strobe pulse at about 1 Hz
 
285
            for(i=0; i<4; i++) {
 
286
                PWM_LVL = modes[mode_idx-SOLID_MODES+2];
 
287
                _delay_ms(5);
 
288
                PWM_LVL = modes[mode_idx];
 
289
                _delay_ms(65);
 
290
            }
 
291
            _delay_ms(720);
329
292
        }
330
293
#ifdef VOLTAGE_MON
331
294
        if (ADCSRA & (1 << ADIF)) {  // if a voltage reading is ready
337
300
                lowbatt_cnt = 0;
338
301
            }
339
302
            // See if it's been low for a while, and maybe step down
340
 
            if (lowbatt_cnt >= 4) {
341
 
                if (mode_idx > 1) {
342
 
                    mode_idx = 1;
 
303
            if (lowbatt_cnt >= 3) {
 
304
                if (mode_idx > 0) {
 
305
                    mode_idx = 0;
343
306
                } else { // Already at the lowest mode
344
307
                    // Turn off the light
345
308
                    PWM_LVL = 0;