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
86
//#define ADC_LOW 130 // When do we start ramping
87
//#define ADC_CRIT 120 // When do we shut the light off
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?
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
96
#define BATTCHECK_VpT // Use the volts+tenths battcheck style
97
//#define BATTCHECK_4bars // Use the volts+tenths battcheck style
99
#include "brass-edc-calibration.h"
99
102
* =========================================================================
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)
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); }
118
#include <util/delay.h>
105
#include "tk-delay.h"
121
107
#include <avr/pgmspace.h>
122
108
#include <avr/interrupt.h>
123
#include <avr/eeprom.h>
124
109
#include <avr/sleep.h>
126
#define STAR2_PIN PB0
127
#define STAR3_PIN PB4
128
#define STAR4_PIN PB3
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
135
#define PWM_LVL OCR0B // OCR0B is the output compare register for PB1
111
#include "tk-voltage.h"
138
114
* global variables
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)
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%
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)) {
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
187
inline void ADC_off() {
188
ADCSRA &= ~(1<<7); //ADC off
192
uint8_t get_voltage() {
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
150
#define BLINK_BRIGHTNESS MODE_MED
151
#define BLINK_SPEED 500
153
void blink(uint8_t val, uint16_t speed)
157
PWM_LVL = BLINK_BRIGHTNESS;
164
void blink(uint8_t val)
168
PWM_LVL = BLINK_BRIGHTNESS;
239
209
// set noinit data for next boot
240
210
noinit_decay = 0;
243
TCCR0A = 0x21; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
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
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
220
TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
245
222
// Now just fire up the mode
246
223
PWM_LVL = modes[mode_idx];
256
233
if(mode_idx < SOLID_MODES) { // Just stay on at a given brightness
258
} else if (mode_idx < DUAL_BEACON_MODES) { // two-level fast strobe pulse at about 1 Hz
260
PWM_LVL = modes[mode_idx-SOLID_MODES+2];
262
PWM_LVL = modes[mode_idx];
235
} else if (mode_idx < BATT_CHECK_MODE) {
237
get_voltage(); _delay_ms(200); // the first reading is junk
239
uint8_t result = battcheck();
240
blink(result >> 5, BLINK_SPEED/8);
241
_delay_ms(BLINK_SPEED);
243
_delay_ms(BLINK_SPEED*3/2);
244
blink(result & 0b00011111, BLINK_SPEED/8);
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];
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
298
280
if (j<50) { strobe_len = j; }
299
281
else { strobe_len = 100-j; }
300
282
_delay_ms(strobe_len+9);
302
} else if (mode_idx < BATT_CHECK_MODE) {
304
// turn off and wait one second before showing the value
305
// (also, ensure voltage is measured while not under load)
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)) {
319
// blink up to five times to show voltage
320
// (~0%, ~25%, ~50%, ~75%, ~100%, >100%)
321
for(i=0; i<blinks; i++) {
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
286
PWM_LVL = modes[mode_idx-SOLID_MODES+2];
288
PWM_LVL = modes[mode_idx];
330
293
#ifdef VOLTAGE_MON
331
294
if (ADCSRA & (1 << ADIF)) { // if a voltage reading is ready