79
77
#define PHASE 0xA1 // phase-correct PWM both channels
81
79
#define VOLTAGE_MON // Comment out to disable LVP
80
#define OWN_DELAY // Should we use the built-in delay or our own?
81
// Adjust the timing per-driver, since the hardware has high variance
82
// Higher values will run slower, lower values run faster.
83
#define DELAY_TWEAK 950
83
85
#define OFFTIM3 // Use short/med/long off-time presses
84
86
// instead of just short/long
86
88
// comment out to use extended config mode instead of a solderable star
87
89
// (controls whether mode memory is on the star or if it's a setting in config mode)
88
//#define CONFIG_STARS
90
// output to use for blinks on battery check mode (primary PWM level, alt PWM level)
91
// Use 20,0 for a single-channel driver or 0,20 for a two-channel driver
92
#define BLINK_BRIGHTNESS 0,20
95
93
#define NUM_MODES1 7
96
94
// PWM levels for the big circuit (FET or Nx7135)
97
#define MODESNx1 0,0,0,7,56,137,255
95
#define MODESNx1 0,0,0,6,56,135,255
98
96
// PWM levels for the small circuit (1x7135)
99
#define MODES1x1 3,20,110,255,255,255,0
100
// My sample: 6=0..6, 7=2..11, 8=8..21(15..32)
101
// Krono sample: 6=5..21, 7=17..32, 8=33..96(50..78)
102
// Manker2: 2=21, 3=39, 4=47, ... 6?=68
97
#define MODES1x1 3,20,100,255,255,255,0
103
98
// PWM speed for each mode
104
99
#define MODES_PWM1 PHASE,FAST,FAST,FAST,FAST,FAST,PHASE
106
101
#define NUM_MODES2 4
107
#define MODESNx2 0,0,90,255
108
#define MODES1x2 20,230,255,0
102
#define MODESNx2 0,0,79,255
103
#define MODES1x2 20,200,255,0
109
104
#define MODES_PWM2 FAST,FAST,FAST,PHASE
110
105
// Hidden modes are *before* the lowest (moon) mode, and should be specified
111
106
// in reverse order. So, to go backward from moon to turbo to strobe to
112
107
// battcheck, use BATTCHECK,STROBE,TURBO .
114
#define HIDDENMODES BIKING_STROBE,BATTCHECK,STROBE,TURBO
115
#define HIDDENMODES_PWM PHASE,PHASE,PHASE,PHASE
116
#define HIDDENMODES_ALT 0,0,0,0 // Zeroes, same length as NUM_HIDDEN
109
#define HIDDENMODES BATTCHECK,STROBE,TURBO
110
#define HIDDENMODES_PWM PHASE,PHASE,PHASE
118
#define TURBO 255 // Convenience code for turbo mode
119
#define BATTCHECK 254 // Convenience code for battery check mode
120
// Uncomment to enable tactical strobe mode
121
#define STROBE 253 // Convenience code for strobe mode
122
// Uncomment to unable a 2-level stutter beacon instead of a tactical strobe
123
#define BIKING_STROBE 252 // Convenience code for biking strobe mode
124
// comment out to use minimal version instead (smaller)
125
#define FULL_BIKING_STROBE
112
// Uncomment to use a 2-level stutter beacon instead of a tactical strobe
113
//#define BIKING_STROBE
127
115
#define NON_WDT_TURBO // enable turbo step-down without WDT
128
116
// How many timer ticks before before dropping down.
129
117
// Each timer tick is 500ms, so "60" would be a 30-second stepdown.
130
118
// Max value of 255 unless you change "ticks"
131
#define TURBO_TIMEOUT 90
133
// Calibrate voltage and OTC in this file:
134
#include "../tk-calibration.h"
119
#define TURBO_TIMEOUT 60
121
// These values were measured using wight's "A17HYBRID-S" driver built by DBCstm.
122
// Your mileage may vary.
123
#define ADC_42 174 // the ADC value we expect for 4.20 volts
124
#define ADC_100 174 // the ADC value for 100% full (4.2V resting)
125
#define ADC_75 165 // the ADC value for 75% full (4.0V resting)
126
#define ADC_50 155 // the ADC value for 50% full (3.8V resting)
127
#define ADC_25 141 // the ADC value for 25% full (3.5V resting)
128
#define ADC_0 118 // the ADC value for 0% full (3.0V resting)
129
#define ADC_LOW 109 // When do we start ramping down (2.8V)
130
#define ADC_CRIT 104 // When do we shut the light off (2.7V)
131
// These values were copied from s7.c.
132
// Your mileage may vary.
133
//#define ADC_42 185 // the ADC value we expect for 4.20 volts
134
//#define ADC_100 185 // the ADC value for 100% full (4.2V resting)
135
//#define ADC_75 175 // the ADC value for 75% full (4.0V resting)
136
//#define ADC_50 164 // the ADC value for 50% full (3.8V resting)
137
//#define ADC_25 154 // the ADC value for 25% full (3.5V resting)
138
//#define ADC_0 139 // the ADC value for 0% full (3.0V resting)
139
//#define ADC_LOW 123 // When do we start ramping down (2.8V)
140
//#define ADC_CRIT 113 // When do we shut the light off (2.7V)
141
// Values for testing only:
142
//#define ADC_LOW 125 // When do we start ramping down (2.8V)
143
//#define ADC_CRIT 124 // When do we shut the light off (2.7V)
145
// the BLF EE A6 driver may have different offtime cap values than most other drivers
147
#define CAP_SHORT 250 // Value between 1 and 255 corresponding with cap voltage (0 - 1.1v) where we consider it a short press to move to the next mode
148
#define CAP_MED 190 // Value between 1 and 255 corresponding with cap voltage (0 - 1.1v) where we consider it a short press to move to the next mode
150
#define CAP_SHORT 190 // Value between 1 and 255 corresponding with cap voltage (0 - 1.1v) where we consider it a short press to move to the next mode
151
// Not sure the lowest you can go before getting bad readings, but with a value of 70 and a 1uF cap, it seemed to switch sometimes
152
// even when waiting 10 seconds between presses.
155
#define TURBO 255 // Convenience code for turbo mode
156
#define STROBE 254 // Convenience code for strobe mode
157
#define BATTCHECK 253 // Convenience code for battery check mode
137
160
* =========================================================================
140
// Ignore a spurious warning, we did the cast on purpose
141
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
164
#include <util/delay_basic.h>
165
// Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
166
void _delay_ms(uint16_t n)
168
// TODO: make this take tenths of a ms instead of ms,
169
// for more precise timing?
170
while(n-- > 0) _delay_loop_2(DELAY_TWEAK);
172
void _delay_s() // because it saves a bit of ROM space to do it this way
177
#include <util/delay.h>
143
180
#include <avr/pgmspace.h>
144
181
//#include <avr/io.h>
188
228
PROGMEM const uint8_t modesNx2[] = { MODESNx2, HIDDENMODES };
189
229
const uint8_t *modesNx; // gets pointed at whatever group is current
191
PROGMEM const uint8_t modes1x1[] = { MODES1x1, HIDDENMODES_ALT };
192
PROGMEM const uint8_t modes1x2[] = { MODES1x2, HIDDENMODES_ALT };
231
PROGMEM const uint8_t modes1x1[] = { MODES1x1, HIDDENMODES };
232
PROGMEM const uint8_t modes1x2[] = { MODES1x2, HIDDENMODES };
193
233
const uint8_t *modes1x;
195
235
PROGMEM const uint8_t modes_pwm1[] = { MODES_PWM1, HIDDENMODES_PWM };
196
236
PROGMEM const uint8_t modes_pwm2[] = { MODES_PWM2, HIDDENMODES_PWM };
197
237
const uint8_t *modes_pwm;
239
PROGMEM const uint8_t voltage_blinks[] = {
240
ADC_0, // 1 blink for 0%-25%
241
ADC_25, // 2 blinks for 25%-50%
242
ADC_50, // 3 blinks for 50%-75%
243
ADC_75, // 4 blinks for 75%-100%
244
ADC_100, // 5 blinks for >100%
199
247
void save_state() { // central method for writing (with wear leveling)
248
uint8_t oldpos=eepos;
200
249
// a single 16-bit write uses less ROM space than two 8-bit writes
202
uint8_t oldpos=eepos;
204
eepos = (eepos+1) & (EEPSIZE-1); // wear leveling, use next cell
252
eepos=(eepos+2)&63; // wear leveling, use next cell
206
254
#ifdef CONFIG_STARS
207
eep = mode_idx | (modegroup << 5);
255
eep = mode_idx | (fast_presses << 12) | (modegroup << 8);
209
eep = mode_idx | (modegroup << 5) | (memory << 6);
257
eep = mode_idx | (fast_presses << 12) | (modegroup << 8) | (memory << 9);
211
eeprom_write_byte((uint8_t *)(eepos), eep); // save current state
212
eeprom_write_byte((uint8_t *)(oldpos), 0xff); // erase old state
259
eeprom_write_word((uint16_t *)(eepos), eep); // save current state
260
eeprom_write_word((uint16_t *)(oldpos), 0xffff); // erase old state
215
263
void restore_state() {
264
// two 8-bit reads use less ROM space than a single 16-bit write
217
267
// find the config data
218
for(eepos=0; eepos<EEPSIZE; eepos++) {
219
eep = eeprom_read_byte((const uint8_t *)eepos);
220
if (eep != 0xff) break;
268
for(eepos=0; eepos<64; eepos+=2) {
269
eep1 = eeprom_read_byte((const uint8_t *)eepos);
270
eep2 = eeprom_read_byte((const uint8_t *)eepos+1);
271
if (eep1 != 0xff) break;
222
273
// unpack the config data
223
if (eepos < EEPSIZE) {
224
mode_idx = eep & 0x0f;
225
modegroup = (eep >> 5) & 1;
276
fast_presses = (eep2 >> 4);
277
modegroup = eep2 & 1;
226
278
#ifndef CONFIG_STARS
227
memory = (eep >> 6) & 1;
279
memory = (eep2 >> 1) & 1;
230
// unnecessary, save_state handles wrap-around
231
// (and we don't really care about it skipping cell 0 once in a while)
282
//else eepos=0; // unnecessary, save_state handles wrap-around
235
285
inline void next_mode() {
507
// small/minimal version
554
// 10Hz tactical strobe
514
559
#endif // ifdef BIKING_STROBE
516
561
else if (output == BATTCHECK) {
517
// blink zero to five times to show voltage
563
// turn off and wait one second before showing the value
564
// (also, ensure voltage is measured while not under load)
567
voltage = get_voltage();
568
voltage = get_voltage(); // the first one is unreliable
569
// division takes too much flash space
570
//voltage = (voltage-ADC_LOW) / (((ADC_42 - 15) - ADC_LOW) >> 2);
571
// a table uses less space than 5 logic clauses
572
for (i=0; i<sizeof(voltage_blinks); i++) {
573
if (voltage > pgm_read_byte(voltage_blinks + i)) {
578
// blink up to five times to show voltage
518
579
// (~0%, ~25%, ~50%, ~75%, ~100%, >100%)
520
// wait between readouts
521
_delay_s(); _delay_s();
581
_delay_s(); // wait at least 1 second between readouts
523
#endif // ifdef BATTCHECK
524
583
else { // Regular non-hidden solid mode
525
584
set_mode(mode_idx);
526
585
// This part of the code will mostly replace the WDT tick code.
527
586
#ifdef NON_WDT_TURBO
528
587
// Do some magic here to handle turbo step-down
529
//if (ticks < 255) ticks++; // don't roll over
530
ticks ++; // actually, we don't care about roll-over prevention
588
if (ticks < 255) ticks++;
531
589
if ((ticks > TURBO_TIMEOUT)
532
590
&& (output == TURBO)) {
533
591
mode_idx = solid_modes - 2; // step down to second-highest mode