2
/****************************************************************************
6
* ATtiny85 firmware for Mike C drivers. *
7
* Support for Dual Switch and Off Switch setups. *
9
* Driver type and setup selected by #defines *
11
****************************************************************************/
13
// ======================== DEFAULT SETTINGS ===============================
15
#define F8 // F8 & ZY-T08
16
// #define G12 // G-12
17
// #define G16 // G-16 & BMF-SRK
18
// #define LOW // Low output modes for development testing.
23
// #define DOUBLE_CELL // Comment out for single cell drivers.
24
// #define PB5_IO // Comment out if PB5 is NOT enabled as IO.
26
#define UI 1 // Default UI, 1 to 4.
27
#define MODECOUNT 4 // Default mode count, max 4.
29
#define MODE1 20,0 // PWM, AMC. (PWM on single dedicated AMC, number of AMCs turned on in constant current).
30
#define MODE2 100,0 // MODECOUNT=3 skips MODE3, MODECOUNT=2 skips MODE2 & MODE3, MODECOUNT=1 is MODE1.
32
#define BOOST 0,MAX // MAX for max output. Differs depending on driver, defined per driver type.
33
#define RAMP1 15,0 // Default output in UI 3.
34
#define RAMP2 15,0 // Default output in UI 4.
36
#define BOOSTTIMER 5 // 0, 10, 20, 30, 45, 1:00, 1:30, 2:00, 3:00 ,5:00.
37
#define GENERICSETTINGS 0b111111 // CRITSHUTDOWN, LOWVOLTMON, TEMPMONITOR, MODEDIRL2H, BOOSTMEM, MODEMEM
39
// ======================== DUAL SWITCH INTERFACE ==========================
43
Next mode: Short E or P press.
44
Previous mode: Long E or P press.
49
Next mode: Short P press.
50
Previous mode: Long P press.
51
Boost: E press (not in mode cycle). Hold for 1.5 seconds to lock.
55
Adjust mode: Short P press enables mode adjustment.
56
Boost: E press. Hold for 1.5 seconds to lock.
60
Adjust mode: Constant adjustable.
65
Increase: E press and hold.
66
Decrease: Double E press, hold on second press.
67
Increase 1 step: Short E press.
68
Decrease 1 step: Double short E press.
70
// ======================== OFF SWITCH INTERFACE ===========================
74
Next mode: Short P press.
75
Previous mode: Long P press.
80
Next mode: Short P press.
82
Boost: Long P press (not in mode cycle).
86
Adjust mode: Long P press enables mode adjustment.
91
Adjust mode: Constant adjustable.
96
Increase: Short press starts ramp up. Stop with short press.
97
Decrease: Double short press starts ramp down. Stop with short press.
100
// ======================== DUAL SWITCH *SETUP* ============================
102
--- *MENU --- Accessed by holding E-switch on startup.
103
Menu selection by blinks, rest by E-switch presses.
105
READOUTS 1 = Voltage level 1 to 5.
106
2 = Real voltage X,XX.
109
5 = Calibration values (after SOS confirmation timeout, endless loop).
111
SPECIALMODES 5 = SOS (confirmation required).
113
1 LOCK / UI L = Safety lock.
115
9 = Noob mode toggle on/off.
117
2 SPECIALMODES 1 = Beacon.
122
3 MODESETTINGS 1 = ModeCount: 1-4 = Mode count (UI 1/2).
123
L = Toggle mode direction (UI 1/2).
124
2 = ModeMem: L = No memory.
127
3 = BoostTimer: 1-9 = 10, 20, 30, 45, 1:00, 1:30, 2:00, 3:00, 5:00.
130
0 = SOS on/off Confirmation required.
132
4 MONITORING 1 = MaxTemp: 1 = Start (turn off at max temp).
133
L = Toggle Temp Monitor on/off.
134
0 = Readout max temp.
135
2 = LowVolt: X.X = V, readout, confirm.
136
L = Toggle Low Volt Monitor on/off.
137
0 = Readout threshold value.
138
3 = CritVolt: X.X = V, readout, confirm.
139
L = Toggle Crit shutdown on/off.
140
0 = Readout threshold value.
142
5 CALIBRATIONS 1 = VoltCalib: XXX = X.XX Volt, readout, confirm.
143
L = Reset INTREFVOLT to default.
144
0 = Readout INTREFVOLT.
145
2 = TempCalib: XX = Temp, readout, confirm.
146
L = Reset TEMPOFFSET to default.
147
0 = Readout TEMPOFFSET.
148
3 = TempProfile: 1 = Starts temp profiling.
149
L = Reset TEMPPROFILE to default.
150
0 = Readout TEMPPROFILE.
152
6 RESET2DEFAULT 1 = Reset modes & settings, not calibrations or offsets.
154
Additional confirmation required.
157
// ======================== OFF SWITCH *SETUP* =============================
159
--- *MENU --- Accessed by 3 to 9 short presses directly after cold start.
160
All selections by off switch presses.
162
READOUTS 3 = Voltage level.
164
5 = Temperature (after SOS confirmation timeout).
166
7 = Calibration values (endless loop).
168
SPECIALMODES 5 = SOS (confirmation required).
171
3 LOCK / UI L = Safety lock.
174
4 SPECIALMODES 1 = Beacon.
178
5 MODESETTINGS 1 = ModeCount: 1-4 = Mode count (UI 1/2).
179
L = Toggle mode direction (UI 1/2).
180
2 = ModeMem: L = No memory.
183
3 = BoostTimer: 1-9 = 10, 20, 30, 45, 1:00, 1:30, 2:00, 3:00, 5:00.
186
0 = SOS on/off Confirmation required.
188
6 MONITORING 1 = MaxTemp: 1 = Start (turn off at max temp).
189
L = Toggle Temp Monitor on/off.
190
0 = Readout max temp.
191
2 = LowVolt: X.X = V, readout, confirm.
192
L = Toggle Low Volt Monitor on/off.
193
0 = Readout threshold value.
194
3 = CritVolt: X.X = V, readout, confirm.
195
L = Toggle Crit shutdown on/off.
196
0 = Readout threshold value.
198
7 CALIBRATIONS 1 = VoltCalib: XXX = X.XX Volt, readout, confirm.
199
L = Reset INTREFVOLT to default.
200
0 = Readout INTREFVOLT.
201
2 = TempCalib: XX = Temp, readout, confirm.
202
L = Reset TEMPOFFSET to default.
203
0 = Readout TEMPOFFSET.
204
3 = TempProfile: 1 = Starts temp profiling.
205
L = Reset TEMPPROFILE to default.
206
0 = Readout TEMPPROFILE.
208
8 RESET2DEFAULT 1 = Reset modes & settings.
210
Additional confirmation required.
212
9 NOOB MODE Noob mode toggle on/off.
215
// ======================== COMMON SHARED INTERFACE ========================
217
Mode level programming
218
----------------------
219
UI 1 & 2: Blink writes mode, then double blink exits programming mode.
220
UI 3: Single blink writes mode and exists programming mode.
221
UI 4: Constant programming mode, writes mode without blinks.
225
No memory: Always starts in lowest mode on cold start.
226
Mode memory: Mode restored on cold start. Does not include boost by default.
227
Boost memory: Includes boost mode in mode memory.
228
UI change: Lowest mode set on UI change.
230
Low voltage or high temp
231
------------------------
232
On low voltage, high temperature or critical levels the light steps down to a
233
mode or mode level that is at or below the allowed limit for low/high or
234
critical levels after blinking warning.
235
2 blinks for voltage, 3 blinks for temperature, followed by 3 quick flashes if critical.
236
The light continues to warn every 30 seconds without interaction.
237
If critical and the critical shutdown setting is enabled the light will enter sleep mode.
238
A power off cycle will wake up the light from sleep mode.
241
// =========================================================================
244
#include <avr/interrupt.h>
246
#include <avr/eeprom.h>
247
#include <avr/sleep.h>
249
// ==================== DRIVER DEFAULT *SETTINGS* ==========================
253
#define LVL_READOUT 18 // Level for programming blinks
254
#define LVL_READOUTLOW 11 // Lower level for programming blinks
255
#define LVL_ONOROFF 9 // Level threshold to blink on or off.
257
#define NOOBMODE1 20 // Noob mode levels, 255 is max.
259
#define NOOBMODE3 255
261
// -------------------- COMMON DEFAULT *SETTINGS* --------------------------
264
#define TEMPOFFSET 0 // Default uncalibrated temperature offset.
267
#define MAXTEMP 50 // Default temperature threshold. One below does step down, one above activates critical mode.
270
#define TEMPPROFILE 15 // Time in seconds to resume temp monitoring after temp step-down/warning. *EXPERIMENTAL*
272
#define UIHOLD UI // UI memory used for toggle SOS & NOOB mode.
275
#define STROBESPEED 0
276
#define INTREFVOLTB1 INTREFVOLT % 256
277
#define INTREFVOLTB2 INTREFVOLT / 256
279
// -------------------- SINGLE CELL VOLTAGE LEVELS -------------------------
283
#define INTREFVOLT 11000 // Default uncalibrated internal ref voltage: 11000 = 1.1V.
286
#define OFF_SHORT 205 // Voltage threshold for off time cap short press detection.
289
#define OFF_LONG 165 // Voltage threshold for off time cap long press detection.
298
#define VOLTAGE_LEVEL5 400
299
#define VOLTAGE_LEVEL4 380
300
#define VOLTAGE_LEVEL3 360
301
#define VOLTAGE_LEVEL2 330
302
#define VOLTAGE_LEVEL1 300
305
#define INTREFVOLT 11000 // Default uncalibrated internal reference voltage. 11000 = 1.1V.
308
// -------------------- DOUBLE CELL VOLTAGE LEVELS -------------------------
312
#define INTREFVOLT 25600 // Default uncalibrated internal ref voltage: 25600 = 2.56V.
315
#define OFF_SHORT 410 // Voltage threshold of off time cap for short off press detection.
318
#define OFF_LONG 310 // Voltage threshold of off time cap for long off press detection.
327
#define VOLTAGE_LEVEL5 800
328
#define VOLTAGE_LEVEL4 760
329
#define VOLTAGE_LEVEL3 720
330
#define VOLTAGE_LEVEL2 660
331
#define VOLTAGE_LEVEL1 600
334
#define INTREFVOLT 25600 // Default uncalibrated internal reference voltage. 25600 = 2.56V.
339
// ------------------------ LOW V/HIGH T MODE LIMITS -----------------------
342
#define LOWVOLTMAX 2*256 // Highest output level allowed when voltage is low. AMC * 256 + PWM.
343
#define CRITICALMAX 1*256 // Highest output level allowed when voltage is critical.
346
// ------------------------ LOW OUTPUT SETTINGS ----------------------------
354
#define LOWVOLTMAX 35
355
#define CRITICALMAX 15
358
// ======================== DRIVER DEFINITIONS =============================
361
#define RAMPMAX 1*256
367
#define RAMPMAX 8*256
374
#define RAMPMAX 12*256
381
#define RAMPMAX 16*256
389
#define RAMPMAX 4*256
392
// ------------------------ COMMON DEFINITIONS -----------------------------
397
#define VOLT_READOUT 3
399
#define TEMP_READOUT 5
401
#define VOLTAGE_LOW sLOWVOLT*10
402
#define VOLTAGE_CRIT sCRITVOLT*10
404
#define ALERT_LOWVOLT 1
405
#define ALERT_CRITVOLT 2
406
#define ALERT_HIGHTEMP 3
407
#define ALERT_CRITTEMP 4
409
#define FLASH_ONOROFF 254 // Flash routine needs to use BlinkOnOffThreshold.
410
#define FLASH_LIGHTMODE 255
412
// -------------------- PIN & E-SWITCH CONFIGURATION -----------------------
414
#define ESWITCH (eswLevel < 20) // Check if E-switch is pressed.
416
#define LONG_PRESS 255
417
#define PWM OCR0A // PWM output.
419
// ======================== MODE VARIABLES =================================
421
uint8_t MODE_AMC = 0;
422
uint8_t MODE_PWM = 0;
424
#define BOOSTMODE 3 // Mode number for boost.
428
// ------------------------ UI VARIABLES -----------------------------------
430
#define SAFETYLOCK (sUI & (1 << 7)) // Highest bit in UI byte used for safety lock.
437
// ------------------------ *SETTINGS* -------------------------------------
439
uint8_t SettingsDefault[] = {MODE1, MODE2, MODE3, BOOST, RAMP1, RAMP2, // 0-11 All mode levels use two bytes each.
440
UI, UIHOLD, MODE, MODEHOLD, MODECOUNT-1, STROBESPEED, // 12-17
441
GENERICSETTINGS, BOOSTTIMER, LOWVOLT, CRITVOLT, MAXTEMP,0, // 18-23
442
INTREFVOLTB1, INTREFVOLTB2,TEMPOFFSET, TEMPPROFILE, // 24-27
443
0,0,0,0}; // 28-31 0 = Unused bytes.
445
uint8_t NoobModes[] = {NOOBMODE1,NOOBMODE2,NOOBMODE3};
446
uint8_t BoostTimeouts[] = {0,2,4,6,9,12,18,24,36,60}; // X * 5 sec = 0, 10, 20, 30, 45, 1:00, 1:30, 2:00, 3:00 ,5:00.
447
uint8_t StrobeSpeeds[] = {127,100,80,60,45,30,20,14,10,7,5,3,2,1}; // Ticks.
449
#define sUI Settings[12]
450
#define sUIHOLD Settings[13]
451
#define sMODE Settings[14]
452
#define sMODEHOLD Settings[15]
453
#define sMODECOUNT Settings[16]
454
#define sSTROBESPEED Settings[17]
456
#define sGENERICSETTINGS Settings[18]
457
#define sBOOSTTIMER Settings[19]
458
#define sLOWVOLT Settings[20]
459
#define sCRITVOLT Settings[21]
460
#define sMAXTEMP Settings[22]
462
#define sINTREFVOLT Modes[12] // Settings[24] & [25].
463
#define sTEMPOFFSET Settings[26]
464
#define sTEMPPROFILE Settings[27]
466
// ------------------------ GENERIC SETTINGS -------------------------------
468
#define gsModeMemory 0
469
#define gsBoostMemory 1
470
#define gsModeDirection 2
471
#define gsTempMonitor 3
472
#define gsLowVoltMon 4
473
#define gsCritShutdown 5
474
//#define - 6 // Available bit, currently not used.
475
//#define - 7 // Available bit, currently not used.
477
#define sMODEMEM (sGENERICSETTINGS % 4) // Mode memory.
478
#define sMODEDIRL2H (sGENERICSETTINGS & (1 << gsModeDirection))
479
#define sTEMPMONITOR (sGENERICSETTINGS & (1 << gsTempMonitor))
480
#define sLOWVOLTMON (sGENERICSETTINGS & (1 << gsLowVoltMon))
481
#define sCRITSHUTDOWN (sGENERICSETTINGS & (1 << gsCritShutdown))
483
// ------------------------ TIMER DEFINITIONS ------------------------------
485
#define SEC 66 // WDT ticks per second.
486
#define BOOST_PERIOD 165 // 1 Boost period = 2.5 seconds.
488
#define MULTIPRESSTIME 15 // Time to consider if presses are multi-presses.
489
#define LONGPRESSTIME 27 // Time to consider if press is long press.
490
#define BOOSTFREERUN 80 // Time to set boost free running.
491
#define FUNCTIONBLINKTIME 1*SEC // Time between E-switch setup blinks.
493
#define MENUSTARTTIME 20
495
#define PROGMODETIMER (2*SEC) // Programming mode save/exit timeout, seconds.
497
// ------------------------ *DELAY* DEFINITIONS ----------------------------
499
#define DELAY_FLASH 2
501
#define DELAY_BLINK 4
502
#define DELAY_ENTRY 6
503
#define DELAY_SHORT 16
504
#define DELAY_MEDIUM 33
505
#define DELAY_LONG 66
507
#define DELAY_SW 100 // Duration for switch input.
508
#define DELAY_VOLTCALIB 2*SEC // Cell recovery delay for voltage calibration.
509
#define DELAY_VOLTREADOUT DELAY_VOLTCALIB-DELAY_SW // Cell recovery delay for voltage readout.
511
#define DELAY_SETUPWINDOW 66 // Window of opportunity to enter setup from cold start.
512
#define DELAY_SETUPPRESS 33 // Window of opportunity for multiple off switch press detection.
514
#define STARTDELAY_NONE 0
515
#define STARTDELAY_SHORT 251
516
#define STARTDELAY_MEDIUM 252
517
#define STARTDELAY_LONG 253
518
#define STARTDELAY_LONG_KEEPMEM 254
520
// ------------------------ SETUP DEFINITIONS ------------------------------
525
#define sSPECIALMODES 20
526
#define sMODESETTINGS 30
527
#define sMONITORING 40
528
#define sCALIBRATIONS 50
529
#define sRESET2DEF 60
533
#define sSETMODECNT 31
534
#define sSETMODEMEM 32
535
#define sSETBOOSTIME 33
538
// MONITORING SETTINGS
540
#define sSETMAXTEMP 41
541
#define sSETLOWVMON 42
542
#define sSETCRITVMON 43
546
#define sVOLTCALIB 51
547
#define sTEMPCALIB 52
548
#define sTEMPPROFILING 53
550
// OFFSWITCH INPUT ENTRY
552
#define RESET_CONFIRM_1 61
553
#define RESET_CONFIRM_SHORT 62
554
#define RESET_CONFIRM_LONG 63
556
#define SECOND_DIGIT 100
557
#define THIRD_DIGIT 150
558
#define CONFIRMATION 200
560
// ------------------------ EEPROM VARIABLES ------------------------------- *EEPROM*
562
#define eeBlockSize 32 // Size of settings array. Must be evenly multipliable to 512.
563
uint16_t eePos = 0; // Address in memory block.
564
uint8_t eeSettingsRead = 0; // Flag that indicates settings have been read from EEPROM.
565
uint8_t Settings[eeBlockSize]= {0}; // Settings array.
566
uint16_t* Modes = (uint16_t*)Settings; // Settings array as uint16 values.
568
// ------------------------ TIMER VARIABLES -------------------------------- // *ISR*
570
volatile uint8_t WdtTicks = 0; // Watchdog timer counter.
571
volatile uint8_t WdtSecs = 0; // Watchdog timer counter in seconds.
572
volatile uint8_t WdtStartup = 0; // Startup delay.
573
volatile uint8_t DelayTicks = 0; // Timer for Delay routine.
575
volatile uint8_t SwitchTicks = 0; // Timer for E-switch.
576
volatile uint8_t NoSwitchTicks= 0; // E-switch not pressed counter for detecting multiple short E-presses.
577
volatile uint8_t swPressed = 0; // E-switch press counter for quick or multi-presses. Set but not cleared in ISR.
578
volatile uint8_t swLongPressed= 0; // Flag for E-switch long pressed. Set but not cleared in ISR.
579
volatile uint8_t swPressCounter=0; // E-switch press counter with no timeout. Set but not cleared in ISR.
580
volatile uint8_t swMultiDetect= 0; // Flag for E-switch detecting multiple presses.
582
volatile uint8_t BOOSTSTATUS = 0; // Integer for boost mode status.
583
volatile uint16_t BoostTicks = 0; // Timer for boost.
584
volatile uint16_t ProgModeTicks=0; // Timer for Mode programming mode.
587
volatile uint8_t SetupTicks=0; // Timer for settings menu access.
590
// ------------------------ VOLT VARIABLES ---------------------------------
592
volatile uint16_t Voltage = 0; // Converted voltage level from ADC.
593
volatile uint16_t NormVoltTicks=0; // Normal voltage level tick counter.
594
volatile uint16_t LowVoltTicks= 0; // Low voltage level tick counter.
595
volatile uint16_t CritVoltTicks=0; // Critical voltage level tick counter.
597
// ------------------------ TEMP VARIABLES ---------------------------------
599
volatile uint8_t Temperature = 0; // For storing current temperature.
600
volatile uint16_t NormTempTicks=0; // Normal temperature level tick counter.
601
volatile uint16_t CritTempTicks=0; // Critical temperature level tick counter.
603
// ------------------------ NO-INIT VARIABLES ------------------------------
605
volatile uint8_t bVOLTSTATUS __attribute__ ((section (".noinit"))); // 0 = normal, 1 = low, 2 = low warned, 3 = critical, 4 = critical warned.
606
volatile uint8_t bTEMPSTATUS __attribute__ ((section (".noinit"))); // 0 = normal, 1 = high, 2 = critical.
607
volatile uint8_t bPROGSTATUS __attribute__ ((section (".noinit"))); // Programming mode status.
610
volatile uint8_t swSETUP __attribute__ ((section (".noinit"))); // Settings menu access status.
611
volatile uint8_t swCOUNT __attribute__ ((section (".noinit"))); // Settings menu press counter.
612
volatile uint16_t swVALUE __attribute__ ((section (".noinit"))); // Settings menu value input.
613
volatile uint8_t swRAMP __attribute__ ((section (".noinit"))); // Used for ramp up or down in mode programming.
614
volatile uint16_t bMODE __attribute__ ((section (".noinit"))); // Mode level storage in no init, used in mode programming and mode readout.
617
// ------------------------ MISC VARIABLES ---------------------------------
619
volatile uint8_t eswLevel = 100; // Raw value from each ADC volt read before conversion to volt, used for ESWITCH.
620
volatile uint8_t StatusAlert = 0; // To trigger actions based on volt/temp monitoring.
621
volatile uint8_t BreakStrobe = 0; // Breaks strobe delays on E-switch presses.
623
// ======================== READ FROM *EEPROM* =============================
625
inline void eeRead() {
626
while (!eeSettingsRead && eePos < 512) { // Loop through EEPROM until settings are read or end is reached.
627
while (EECR & (1<<EEPE)); // Halt while EEPROM is busy.
628
eeprom_read_block(&Settings, (const void*)(eePos), eeBlockSize); // Read current block of EEPROM.
629
while (EECR & (1<<EEPE)); // Halt while EEPROM is busy.
630
if (Settings[0] != 0xff) eeSettingsRead = 1; // Set flag that settings have been read.
631
else eePos += eeBlockSize;
634
if (!eeSettingsRead) { // If no settings where found in EEPROM:
635
eePos = 0; // Reset eePos 0.
636
for (uint8_t i=0; i < eeBlockSize; i++) {
637
Settings[i] = SettingsDefault[i]; // Load default settings into settings array.
642
// ======================== WRITE TO *EEPROM* ==============================
646
uint16_t eePosOld = eePos;
648
if (eeSettingsRead) { // Increase memory address only if settings have been read.
649
eePos += eeBlockSize; // Go to next block to write settings array (wear leveling).
650
if (eePos == 512) eePos = 0; // If it end, wrap around to start of EEPROM memory.
653
while (EECR & (1<<EEPE)); // Halt while EEPROM is busy.
654
eeprom_write_block(&Settings, (void *)(eePos), eeBlockSize); // Write settings array to EEPROM before erasing old.
656
if (eeSettingsRead) { // Erase old only if settings have been read. Erases only first byte of old array.
657
while (EECR & (1<<EEPE)); // Halt while EEPROM is busy.
658
EECR = (0<<EEPM1) | (1<<EEPM0); // Mode erase: 01 = erase, 10 = write, 00 = erase & write.
660
EECR |= (1<<EEMPE); // Enable writing.
661
EECR |= (1<<EEPE); // Start writing.
665
// ------------------------ RESET MODE -------------------------------------
670
if (sUI == 3) sMODE = RAMPMODE1;
671
if (sUI == 4) sMODE = RAMPMODE2;
675
// ======================== SET/RESET TO DEFAULT ===========================
677
void ResetToDefault(uint8_t iSwConfirm) {
679
uint8_t iSettings = eeBlockSize;
680
if (iSwConfirm == 1) iSettings = 24; // iSettings = 24 does not restore calibrations.
682
for (uint8_t i=0; i < iSettings; i++) {
683
Settings[i] = SettingsDefault[i]; // Load default settings into settings array, except last three.
686
ResetMode(); // Reset modes and write default settings to EEPROM.
689
// ======================== *INITIALIZING* ROUTINES =========================
691
// ------------------------ *PWM* ON/OFF ------------------------------------
693
void PWM_on(uint8_t MODE_PWM) {
694
TCCR0A = 0b10000001; // Clear 0C0A on match and set phase correct PWM (WGM01 = 0, WGM00 = 1).
695
TCCR0B = 0b00000001; // Prescaler for timer (1 => 1, 2 => 8, 3 => 64...).
705
// ------------------------ WATCHDOG TIMER ON ------------------------------
707
inline void WDT_on() { // Set watchdog timer only to interrupt, not reset, every 500ms.
708
cli(); // Disable interrupts.
709
wdt_reset(); // Reset the WDT.
710
WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence.
711
WDTCR = (1<<WDIE); // Enable interrupt every 16ms.
712
sei(); // Enable interrupts.
715
// ------------------------ WATCHDOG TIMER OFF -----------------------------
717
inline void WDT_off() {
720
MCUSR = 0; // Clear MCU status register.
721
WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence.
722
WDTCR = 0x00; // Disable WDT.
726
// ======================== CRITICAL SHUTDOWN ==============================
730
PORTB = 0; // Turn off PORTB pins.
731
ADCSRA &= ~(1 << ADEN); // Make sure ADC is off.
732
WDT_off(); // Turn off watchdog timer.
734
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Power down as many components as possible.
736
uint8_t mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); // Turn off brown-out detection.
737
uint8_t mcucr2 = mcucr1 & ~_BV(BODSE);
743
while (1) {} // ZZzzZZzz...
746
// ======================== *DELAY* AND RESETS =============================
748
void Delay(uint8_t iDelay) {
750
while (DelayTicks < iDelay && !BreakStrobe) {}
759
void ResetVoltTimers() {
765
void WriteAndResetVoltStatus() {
766
bVOLTSTATUS = 0; // Set voltage status to normal.
771
void ResetTempTimers() {
776
void ClearSwitch() { // Clears all switch flags and counters.
795
if (bPROGSTATUS != 6) bPROGSTATUS = 0; // PROGSTATUS = 6 is when programming mode is selected from setup.
804
void StatusAfterSwitch() {
805
if (bVOLTSTATUS == 2 || bVOLTSTATUS == 4) bVOLTSTATUS--; // Forces warning blink after every E-switch press.
806
if (bTEMPSTATUS) CritTempTicks = (sTEMPPROFILE * SEC) - 2*SEC; // If TEMP status is critical force flash after two seconds.
807
ResetVoltTimers(); // Reset voltage counters if E-switch pressed under normal operation.
810
// ------------------------ STATUS CHECKS ----------------------------------
812
uint8_t CheckStatus() {
814
if (bVOLTSTATUS || bTEMPSTATUS) iStatus++;
815
if (bVOLTSTATUS >= 3 || bTEMPSTATUS >= 2) iStatus++;
819
// ------------------------ SPLIT MODE LEVEL -------------------------------
821
void ModeToBytes() { // Splits 16 bit mode value into two separate bytes. In separate function to optimize space.
822
MODE_AMC = Modes[sMODE] / 256;
823
MODE_PWM = Modes[sMODE] % 256;
826
// ================ TURN *LIGHT* ON ACCORDING TO MODE ======================
832
if (sUI == UI_NOOB) {
834
MODE_PWM = NoobModes[sMODE];
837
if (MODE_PWM) PWM_on(MODE_PWM);
840
// -------------------- PB5 NOT ENABLED AS IO ------------------------------
843
if (MODE_AMC < 4) PORTB = MODE_AMC * 2;
845
if (MODE_AMC == 4) PORTB = 7;
851
// -------------------- PB5 IS ENABLED AS IO -------------------------------
854
if (MODE_AMC < 8) PORTB = MODE_AMC * 2;
856
if (MODE_AMC == 8) PORTB = 15;
863
if (MODE_AMC < 8) PORTB = MODE_AMC * 2;
865
if (MODE_AMC < 12) PORTB = ((MODE_AMC - 8) * 2) + 40;
872
if (MODE_AMC < 8) PORTB = MODE_AMC * 2;
874
if (MODE_AMC < 16) PORTB = (MODE_AMC * 2) + 16;
882
// ------------------------ LED OFF ---------------------------------------
889
// ======================== *BLINKOUT ROUTINES* ============================
891
// ------------------------ SHORT FLASHES/BLINKS ---------------------------
893
inline void FlashOn() {
899
inline void FlashOff() {
904
inline void FlashLow() {
905
PWM_on(LVL_READOUTLOW);
910
void FlashReadout() {
916
inline void BlinkOn() {
922
inline void BlinkOff() {
927
// ------------------------ BLINK ON/OFF THRESHOLD -------------------------
929
void BlinkOnOffThreshold(uint8_t iLightMode) {
930
if (Modes[sMODE] > LVL_ONOROFF) {
931
if (iLightMode) FlashOn();
939
// ------------------------ *FLASH* ----------------------------------------
941
void Flash(uint8_t iTimes, uint8_t iStrength, uint8_t iDuration) {
944
if (!iStrength) LED_off();
945
if (iStrength == FLASH_LIGHTMODE) LightMode();
946
if (iStrength == FLASH_ONOROFF) BlinkOnOffThreshold(1);
947
else Delay(iDuration);
949
if (!iStrength) LightMode();
955
// ------------------------ BLINK VALUE ------------------------------------
957
void BlinkValue(uint8_t iValue, uint8_t iDigits) {
960
while (iValue--) Flash(1,LVL_READOUT,DELAY_SHORT);
970
for (uint8_t i=LVL_READOUT; i; i--){
980
// ------------------- BLINK MULTI DIGIT NUMBER ---------------------------
982
void BlinkNumValue(uint16_t iValue, uint8_t iDigits) { // iDigits = digits to blink out, X, 0X, 00X, 000X, etc etc.
984
if (!(iValue + iDigits)) BlinkValue(0,0);
985
uint16_t iDivider = 10000;
986
for (uint8_t i=5; i; i--) {
987
uint8_t vValue = iValue / iDivider;
988
if (vValue || iDigits >= i) {
990
BlinkValue(vValue,1);
998
// ------------------- BLINK WITH MINUS NUMBER ----------------------------
1000
void BlinkMinusValue(uint8_t iValue) {
1003
if (iValue >= 128) {
1004
iValue = 256 - iValue;
1005
PWM = LVL_READOUTLOW; // If value is -, start with long low 0.
1010
BlinkNumValue(iValue,1);
1015
// ------------------------ BLINK CONFIRMATION -----------------------------
1017
void BlinkConfirm() {
1018
PWM_on(LVL_READOUTLOW - 2);
1020
PWM = LVL_READOUTLOW;
1022
PWM = LVL_READOUTLOW * 2;
1024
PWM = LVL_READOUTLOW * 3;
1026
PWM = LVL_READOUTLOW * 4;
1028
PWM = LVL_READOUTLOW * 3;
1030
PWM = LVL_READOUTLOW * 2;
1032
PWM = LVL_READOUTLOW;
1034
PWM = LVL_READOUTLOW - 2;
1040
// ------------------------ BLINK SETTING STATUS ---------------------------
1042
inline void BlinkSettingUp() {
1043
PWM_on(LVL_READOUTLOW);
1044
Delay(DELAY_MEDIUM);
1046
Delay(DELAY_MEDIUM);
1050
void BlinkSettingDown() {
1051
PWM_on(LVL_READOUT);
1052
Delay(DELAY_MEDIUM);
1053
PWM = LVL_READOUTLOW;
1054
Delay(DELAY_MEDIUM);
1058
// ------------------------ FLASH ON ERROR ---------------------------------
1063
PWM_on(LVL_READOUTLOW);
1067
PWM = LVL_READOUTLOW;
1071
for (uint8_t i=LVL_READOUT; i; i--){
1078
// ------------------------ GET VOLTAGE BLINKS -----------------------------
1080
uint8_t GetVoltBlinks(uint16_t v) {
1082
if (v >= VOLTAGE_LEVEL1) i++;
1083
if (v >= VOLTAGE_LEVEL2) i++;
1084
if (v >= VOLTAGE_LEVEL3) i++;
1085
if (v >= VOLTAGE_LEVEL4) i++;
1086
if (v >= VOLTAGE_LEVEL5) i++;
1090
// ======================== *MODE* FUNCTIONS ===============================
1092
// ------------------------ BOOST IN CYCLE ---------------------------------
1094
void BoostIfInCycle() { // Made as function to save space as it's called on from two functions.
1095
if (!CheckStatus() && (sUI == 1 || (sUI >= SOS && sUI <= STROBE) || bPROGSTATUS)) {
1101
// ------------------------ *MODE* UP --------------------------------------
1104
uint8_t iMODECOUNT = sMODECOUNT;
1105
if (sUI == UI_NOOB) iMODECOUNT = 3;
1111
if (sMODE == BOOSTMODE+1) sMODE = 0;
1112
if (sMODE == iMODECOUNT) {
1114
BoostIfInCycle(); // Changes mode from 0 to BOOST if in cycle.
1116
if ((CheckStatus() == 1 && Modes[sMODE] > LOWVOLTMAX) || (CheckStatus() == 2 && Modes[sMODE] > CRITICALMAX)) sMODE = 0;
1120
// ------------------------ *MODE* DOWN ------------------------------------
1123
uint8_t iMODECOUNT = sMODECOUNT;
1124
if (sUI == UI_NOOB) iMODECOUNT = 3;
1128
if (sMODE == BOOSTMODE) sMODE = iMODECOUNT;
1132
sMODE = iMODECOUNT - 1;
1133
BoostIfInCycle(); // Changes mode from sMODECOUNT - 1 to BOOST if in cycle.
1135
while ((CheckStatus() == 1 && Modes[sMODE] > LOWVOLTMAX) || (CheckStatus() == 2 && Modes[sMODE] > CRITICALMAX)) sMODE--;
1139
// ---------------- NEXT/PREV MODE ACCORDING TO DIRECTION ------------------
1142
if (sMODEDIRL2H) ModeUp();
1147
if (sMODEDIRL2H) ModeDwn();
1151
// ------------------------ *STEPDOWN* ROUTINE -----------------------------
1153
void StepDown(uint8_t iBlinks, uint8_t iCritical) {
1155
Flash(iBlinks,0,DELAY_SHORT); // Step-down blink.
1159
if (BOOSTSTATUS) { // Boost mode all UIs.
1164
while ((sUI <= 2 || sUI == BEACON || sUI == STROBE) && sMODE && Modes[sMODE]>LOWVOLTMAX) {
1165
sMODE--; // UI 1/2/Strobe mode level higher than allowed, lower until below limit or lowest mode.
1167
if ((sUI == 3 || sUI == 4) && Modes[sMODE] > LOWVOLTMAX) {
1168
Modes[sMODE] = LOWVOLTMAX;
1175
Flash(3,0,DELAY_BLINK); // Critical blink.
1176
if (sCRITSHUTDOWN || sUI == UI_NOOB) Shutdown(); // Shut down if set to turn off when levels are critical, or Noob mode is active.
1178
while ((sUI <=2 || sUI == BEACON || sUI==STROBE) && sMODE && Modes[sMODE] > CRITICALMAX) {
1179
sMODE--; // UI 1/2/Strobe mode level higher than allowed, lower until below limit or lowest mode.
1181
if ((sUI == 3 || sUI == 4) && Modes[sMODE] > CRITICALMAX) {
1182
Modes[sMODE] = CRITICALMAX;
1186
eeWrite(); // Save new lower mode to memory.
1190
// ======================== READ *ADC* =====================================
1192
uint16_t ADC_read(uint8_t adc) {
1194
// ------------------------ ADC ON -----------------------------------------
1196
DIDR0 |= (1 << ADC2D); // Disable digital input on ADC2/PB4.
1197
if (adc <= VOLT_READOUT) { // ADC is for voltage reading.
1199
ADMUX = (0<<REFS0) | (1<<REFS1) | (0<<REFS2) | (0<<ADLAR) | 0b0010; // 1.1v reference (single cell), right-adjust, connect ADC2/PB4 to ADC.
1201
ADMUX = (0<<REFS0) | (1<<REFS1) | (1<<REFS2) | (0<<ADLAR) | 0b0010; // 2.56v reference (double cell), right-adjust, connect ADC2/PB4 to ADC.
1204
else { // ADC is for temperature reading.
1205
ADMUX = (0<<REFS0) | (1<<REFS1) | (0<<REFS2) | (0<<ADLAR) | 0b1111; // 1.1v reference, right-adjust, connect ADC4/TEMP to ADC.
1207
ADCSRA = (1 << ADEN ) | 0b111; // ADC on, prescaler division factor 128.
1209
// ------------------------ ADC READ ---------------------------------------
1212
uint8_t iReadings = 20; // 20 readings to average readouts and calibrations.
1213
if (adc == VOLT || adc == TEMP) iReadings = 5; // 5 readings to average level monitoring.
1215
for (uint8_t i=0; i <= iReadings; i++) { // Loop ADC readings.
1216
ADCSRA |= (1 << ADSC); // Start conversion.
1217
while (ADCSRA & (1 << ADSC)); // Wait for completion.
1218
uint8_t L = ADCL; uint8_t H = ADCH; // Obtain the result.
1219
if (i) iADC += ((H << 8) | L); // If not the first reading, add to stack of readings.
1222
iADC /= iReadings; // Get the average.
1224
// ------------------------ ADC OFF ----------------------------------------
1226
ADCSRA &= ~(1 << ADEN);
1228
// ------------------------ RETURN VALUE -----------------------------------
1230
if (adc && adc <= VOLT_READOUT) {
1232
eswLevel = iADC / 4; // Left adjust raw value for E-switch reading.
1235
iADC=(uint16_t)(((uint32_t)iADC*(uint32_t)sINTREFVOLT)/(uint32_t)20480);// Convert raw ADC value to voltage value.
1239
iADC = (iADC - 285) + (int8_t)sTEMPOFFSET; // Convert raw ADC to temperature-ish value apply offset.
1240
if (iADC > 0x7FFF) iADC = 0; // Result is below scope of measurement.
1241
if (iADC > 255) iADC = 255; // Result is above scope of measurement.
1244
return iADC; // Return value.
1247
// ======================== *ISR* WATCHDOG TIMER ===========================
1251
// ------------------------ GENERAL TIMER ----------------------------------
1253
DelayTicks++; // Tick counter for Delay routine.
1255
if (++WdtTicks == SEC) { // WdtTicks per second.
1257
if (WdtSecs < 255) WdtSecs++; // Increase watchdog timer seconds, max 255.
1260
// -------------------- *OFFSWITCH* FUNCTION TIMING ------------------------
1263
if (SetupTicks < 255) SetupTicks++;
1264
if (SetupTicks >= DELAY_SETUPWINDOW && swSETUP == 1) swSETUP = 0; // Window of opportunity to enter setup with off-switch.
1265
if (SetupTicks >= DELAY_SETUPPRESS) swRAMP = 0;
1268
// ------------------------ WAIT STARTUP DELAY -----------------------------
1272
// ------------------------ READ *VOLTAGE* LEVEL ---------------------------
1274
Voltage = ADC_read(VOLT); // Also determines E-switch status.
1275
// Voltage = 300; // *TEST* emulated voltage.
1277
if (!ESWITCH && WdtStartup == 2) {
1279
// NORMAL VOLTAGE LEVEL:
1281
if ((sLOWVOLTMON && Voltage > VOLTAGE_LOW) || (!sLOWVOLTMON && Voltage > VOLTAGE_CRIT)) {
1282
if (NormVoltTicks++ >= SEC) {
1283
bVOLTSTATUS = 0; // Set voltage status to normal.
1288
// LOW VOLTAGE LEVEL:
1290
if (sLOWVOLTMON && (Voltage <= VOLTAGE_LOW && Voltage > VOLTAGE_CRIT) && BOOSTSTATUS < 3) {
1291
if ((LowVoltTicks++ >= 2*SEC && bVOLTSTATUS <= 1) || (LowVoltTicks >= 30*SEC && bVOLTSTATUS >= 2)) {
1292
if (!bVOLTSTATUS) bVOLTSTATUS = 1;
1293
StatusAlert = ALERT_LOWVOLT;
1298
// CRITICAL VOLTAGE LEVEL:
1300
if (Voltage <= VOLTAGE_CRIT) {
1301
if ((CritVoltTicks++ >= 2*SEC && bVOLTSTATUS <= 3) || (CritVoltTicks >= 30*SEC && bVOLTSTATUS >= 4)) {
1303
if (BOOSTSTATUS >= 3) {
1304
bVOLTSTATUS = 1; // If Boost, set voltage status to low, not critical.
1305
StatusAlert = ALERT_LOWVOLT;
1308
if (bVOLTSTATUS < 3) bVOLTSTATUS = 3;
1309
StatusAlert = ALERT_CRITVOLT;
1316
// ------------------------ E-SWITCH TIMER ---------------------------------
1322
if (ESWITCH) { // E-switch pressed:
1323
if (!swPressed) swPressed = 1; // Set switch pressed for main loop to handle.
1324
if (swMultiDetect) { // Multiple press detection.
1328
if (!SwitchTicks) swPressCounter++;
1329
if (SwitchTicks < 255) SwitchTicks++;
1330
if (SwitchTicks == LONGPRESSTIME) swLongPressed = 1; // Set switch long pressed for main loop to handle.
1331
if (SwitchTicks == LONGPRESSTIME*2) swLongPressed = 3; // Set switch longer pressed for main loop to handle.
1334
ProgModeTicks = 0; // Always reset ProgModeTicks on E-switch press.
1339
if (NoSwitchTicks < 255) NoSwitchTicks++; // Increase ticks not pressed but do not wrap around to 0.
1340
if (NoSwitchTicks < MULTIPRESSTIME) swMultiDetect = 1; // Set for multiple press detection.
1350
if (SwitchTicks < 255) SwitchTicks++;
1351
ProgModeTicks = 0; // Always reset ProgModeTicks on E-switch press.
1353
else SwitchTicks = 0;
1357
// ------------------------ BOOST TIMER ------------------------------------
1359
if (BOOSTSTATUS >= 3 && BoostTimeouts[sBOOSTTIMER]) {
1360
if (++BoostTicks >= (BoostTimeouts[sBOOSTTIMER]*5)*SEC ) { // If boost timer enabled and times out:
1362
BOOSTSTATUS = 1; // Turn off boost and set boost status to timed out.
1365
else BoostTicks = 0;
1367
// ------------------------ PROGRAMMING MODE TIMER -------------------------
1369
if (bPROGSTATUS == 2 || bPROGSTATUS == 4) {
1371
if (ProgModeTicks == PROGMODETIMER) bPROGSTATUS--;
1373
else ProgModeTicks = 0;
1375
// -------------------- *STROBE* SPEED CHANGE ------------------------------
1379
if ((sUI >= SOS && sUI <= STROBE) && swPressed && !ESWITCH && WdtStartup == 2) {
1381
if (!swLongPressed) NextMode();
1385
if (!swLongPressed) {
1386
if (sSTROBESPEED++ == 13) sSTROBESPEED = 0;
1389
if (sSTROBESPEED-- == 0) sSTROBESPEED = 13;
1392
BreakStrobe = 1; // Setting to 1 breaks waiting for long strobe/sos blinks to finish.
1393
eeWrite(); // Save mode or speed change.
1399
// -------------------- READ *TEMPERATURE* ---------------------------------
1401
Temperature = (uint8_t)ADC_read(TEMP);
1402
// Temperature = 80; // *TEST* emulated temperatures.
1404
if (sTEMPMONITOR && WdtStartup == 2) {
1406
// NORMAL TEMPERATURE LEVEL:
1408
if (Temperature < sMAXTEMP) {
1409
if (NormTempTicks++ >= SEC/2) {
1410
bTEMPSTATUS = 0; // Set Temperature status to normal.
1415
// HIGH TEMPERATURE LEVEL:
1419
if ((CritTempTicks >= 1*SEC && bTEMPSTATUS == 0) || CritTempTicks >= sTEMPPROFILE * SEC) {
1420
if (Temperature < sMAXTEMP+2) {
1421
bTEMPSTATUS = 1; // Set Temperature status to high.
1422
StatusAlert = ALERT_HIGHTEMP;
1425
StatusAlert = ALERT_CRITTEMP;
1426
bTEMPSTATUS = 2; // Set Temperature status to critical.
1433
// ======================== END OF ISR ROUTINE =============================
1438
// ======================== *ESWITCH* FUNCTIONS ============================
1442
// ------------------------ E-SWITCH PRESS COUNTER -------------------------
1444
inline uint8_t EswPressCounter() { // Detect and return number of short presses or single long press during a delay.
1446
uint8_t iEswCounter = 0;
1447
while (DelayTicks < DELAY_SW) {
1451
iEswCounter = swPressCounter;
1452
if (swPressCounter == 1 && swLongPressed) { // Long press.
1453
while (ESWITCH); // Hold until switch release.
1454
Delay(DELAY_MEDIUM); // Delay before exiting.
1456
return 255; // Exit, return long press.
1459
if (iEswCounter > 9) iEswCounter = 9; // Highest number 9.
1466
// ------------------------ E-SWITCH ENTER VALUE ---------------------------
1468
uint16_t EswGetValue(uint8_t iDigits) { // Overly complicated routine to allow different results depending on conditions.
1469
// 1,2 or 3 expects 1,2 or 3 digits to be entered. Exceptions:
1470
uint8_t i = iDigits; // Long press on first digit returns 255 (except if code), is 0 on following digits.
1471
// No press on first returns 0. No press on following returns error (except if Temperature).
1473
if (iDigits == TEMP) i = 2; // Temperature takes 1 or 2 digits.
1474
uint8_t iFirst = i - 1;
1475
uint16_t iNumber = 0;
1478
uint8_t iEswDigit = EswPressCounter();
1479
if (iEswDigit == 255 && i == iFirst) return 255; // First long press exits and returns 255 (if not a code).
1480
if (!iEswDigit) { // No input for digit:
1481
if (i == iFirst) return 0; // Was first digit, return 0.
1482
else { // Was a following digit when no input.
1483
if (iDigits == TEMP) return iNumber; // No input on following digits only allowed for temperature values.
1484
else return 1; // Not a temperature value, return error.
1487
if (iEswDigit == 255) iEswDigit = 0;
1489
iNumber += iEswDigit;
1492
if (iDigits == 3) iNumber+= 1000; // Adding 1000 to 3 digit values at end so 255 can be entered.
1498
// ------------------------ SWITCH CONFIRMATION ----------------------------
1500
uint8_t SwConfirm() { // Confirmation flash.
1505
Delay(DELAY_MEDIUM);
1508
while (!WdtSecs) Flash(1,LVL_READOUT,DELAY_FLASH);
1511
return 0; // Non void function, return something.
1515
Delay(DELAY_MEDIUM);
1518
while (!ESWITCH && !WdtSecs) Flash(1,LVL_READOUT,DELAY_FLASH);
1520
if (!WdtSecs) { // Switch was pressed during flashing.
1521
while (ESWITCH) {} // Make sure switch is released before continuing.
1522
if (!swLongPressed) {
1524
return 1; // Short confirmation press returns 1.
1528
return 255; // Long confirmation press returns 255.
1532
return 0; // No confirmation press returns 0.
1538
// ======================== *OFFSWITCH* FUNCTIONS ==========================
1542
// ------------------------ O-SWITCH INPUT DELAY ---------------------------
1545
if (swCOUNT < LONG_PRESS) Delay(DELAY_SW); // If press count not long press, delay for switch input.
1546
else Delay(DELAY_SHORT); // Else short delay.
1551
// ************************ *MAIN* ROUTINE *********************************
1556
uint8_t swSETUP = 0; // Settings menu access status.
1557
uint8_t swCOUNT = 0;
1558
uint16_t swVALUE = 0;
1561
uint8_t offTime = 0;
1562
uint8_t swStartup = 0; // Used for switch startup menu, then startup delays.
1564
// ======================== *SETUP* FUNCTIONS ============================== // Inline functions that don't take any memory if not called on.
1566
// ------------------------ *READOUTS* -------------------------------------
1570
void Readout_VoltLevel() {
1572
Delay(DELAY_VOLTREADOUT); // Long delay so voltage reading is taken from cell under no load.
1573
BlinkValue(GetVoltBlinks(ADC_read(VOLT_READOUT)),0); // Convert voltage value to voltage level blinks.
1574
swStartup = STARTDELAY_LONG;
1579
void Readout_RealVolt() {
1581
Delay(DELAY_VOLTREADOUT); // Long delay so voltage reading is taken from cell under no load.
1582
BlinkNumValue(ADC_read(VOLT_READOUT),3); // Readout full voltage value X.XX volts.
1583
swStartup = STARTDELAY_LONG;
1588
void Readout_Temperature() {
1590
uint8_t iTemp = ADC_read(TEMP_READOUT);
1591
if (iTemp) BlinkNumValue(iTemp,2);
1592
else BlinkValue(0,0);
1593
swStartup = STARTDELAY_LONG;
1598
void Readout_ModeLevel() {
1602
sMODE = (uint8_t)bMODE; // Copy stored mode to keep mode in mode level readout when memory disabled.
1609
Delay(DELAY_MEDIUM);
1610
BlinkNumValue(MODE_AMC,1); // Readout AMC value first.
1615
Flash(3,LVL_READOUTLOW,DELAY_FADE); // Flash to indicate next readout is PWM level.
1617
BlinkNumValue(MODE_PWM,3);
1620
swStartup = STARTDELAY_LONG_KEEPMEM;
1625
void Readout_Calibrations() {
1629
BlinkNumValue(sINTREFVOLT,5);
1631
BlinkMinusValue(sTEMPOFFSET);
1635
// ------------------------ TOGGLE *SOS* -----------------------------------
1645
swStartup = STARTDELAY_SHORT;
1648
// ------------------------ TOGGLE *NOOB* ----------------------------------
1651
if (sUI != UI_NOOB) {
1659
swStartup = STARTDELAY_SHORT;
1662
// ------------------------ SELECT *UI* ------------------------------------
1669
swCOUNT = EswGetValue(1);
1673
if (sUI == UI_NOOB || (sUI != UI_NOOB && swCOUNT == 9)) {
1674
if (swCOUNT == 9) ToggleNoob();
1683
if (swCOUNT == NO_PRESS) Readout_VoltLevel();
1688
if (swCOUNT == LONG_PRESS) { // Long E-switch press for safety lock.
1689
sUI ^= (1 << 7); // Toggle safety lock bit.
1690
eeWrite(); // Write safety lock setting.
1694
WdtSecs = 2; // Set so first safety lock blink after engaging is after 1 second.
1702
sUI &= ~(1 << 7); // UI change always disengages safety lock.
1706
swStartup = STARTDELAY_SHORT; // Short startup delay.
1710
// ERROR: PRESS COUNT OUT OF RANGE
1720
// ------------------------ *SPECIAL* MODES --------------------------------
1722
void SpecialModes() {
1727
swCOUNT = EswGetValue(1);
1730
if (swCOUNT == NO_PRESS) Readout_RealVolt();
1733
// PRESS COUNT: SPECIAL MODES
1737
if (swCOUNT == 1) { // BEACON mode.
1739
if (sMODE >= RAMPMODE1) sMODE = 0;
1741
swStartup = STARTDELAY_NONE;
1744
if (swCOUNT == 2) { // STROBE mode.
1746
if (sMODE >= RAMPMODE1) sMODE = 0;
1748
swStartup = STARTDELAY_NONE;
1751
if (swCOUNT == 3) { // *PROGRAMMING* mode.
1753
Delay(DELAY_MEDIUM);
1759
sMODE = (uint8_t)bMODE; // Copy stored mode to keep mode for level programming when memory disabled.
1767
// ERROR: PRESS COUNT OUT OF RANGE
1773
// ------------------------ *SETTINGS* -------------------------------------
1780
swCOUNT = EswGetValue(1);
1783
if (swCOUNT == NO_PRESS) { // *SOS AND *READOUTS*
1787
if (swSETUP == sMODESETTINGS) {
1791
// NO CONFIRMATION: READOUT TEMPERATURE
1793
if (swCOUNT == NO_PRESS) {
1795
Readout_Temperature();
1799
if (swSETUP == sMONITORING) Readout_ModeLevel();
1800
if (swSETUP == sCALIBRATIONS) Readout_Calibrations();
1804
if (swSETUP == sMODESETTINGS) Readout_Temperature();
1805
if (swSETUP == sMONITORING) Readout_ModeLevel();
1807
if (swSETUP == sCALIBRATIONS) {
1809
swCOUNT = SwConfirm();
1811
// NO CONFIRMATION: READOUT TEMPERATURE
1813
if (swCOUNT == NO_PRESS) {
1815
Readout_Calibrations();
1824
// PRESS COUNT: SETTING
1829
if (swSETUP == sSETMODECNT && sUI > 2) { // ERROR if UI is not 1 or 2.
1834
if (swSETUP != sSETMAXTEMP) BlinkConfirm();
1841
// ------------------------ SET MODE COUNT ---------------------------------
1843
void SetModeCount() {
1848
swCOUNT = EswGetValue(1);
1853
// LONG PRESS: MODE DIRECTION
1855
if (swCOUNT == LONG_PRESS) {
1856
sGENERICSETTINGS ^= (1 << gsModeDirection); // Toggle flag.
1857
if (sMODEDIRL2H) BlinkSettingUp();
1858
else BlinkSettingDown();
1863
// PRESS COUNT: MODE COUNT
1866
sMODECOUNT = swCOUNT - 1;
1871
// ERROR: PRESS COUNT OUT OF RANGE
1878
// ------------------------ SET MODE MEMORY --------------------------------
1880
void SetModeMemory() {
1885
swCOUNT = EswGetValue(1);
1890
// PRESS COUNT OR LONG PRESS: SET MODE MEMORY
1892
if (swCOUNT <= 2 || swCOUNT == LONG_PRESS) {
1894
if (swCOUNT == LONG_PRESS) { // No mode memory.
1895
sGENERICSETTINGS &= ~(1 << gsModeMemory); // Clear flag.
1896
sGENERICSETTINGS &= ~(1 << gsBoostMemory); // Clear flag.
1899
if (swCOUNT == 1) { // Mode memory excluding boost.
1900
sGENERICSETTINGS |= (1 << gsModeMemory); // Set flag.
1901
sGENERICSETTINGS &= ~(1 << gsBoostMemory); // Clear flag.
1904
if (swCOUNT == 2) { // Mode memory including boost.
1905
sGENERICSETTINGS |= (1 << gsModeMemory); // Set flag.
1906
sGENERICSETTINGS |= (1 << gsBoostMemory); // Set flag.
1912
// ERROR: PRESS COUNT OUT OF RANGE
1918
// ------------------------ SET BOOST TIMER --------------------------------
1920
void SetBoostTimer() {
1925
swCOUNT = EswGetValue(1);
1928
if (swCOUNT == NO_PRESS) {
1929
BlinkValue(sBOOSTTIMER,0);
1930
swStartup = STARTDELAY_LONG;
1933
if (swCOUNT == LONG_PRESS) swCOUNT = 0;
1934
if (swCOUNT <= 9) { // 0-9 = 0, 10, 20, 30, 45, 1:00, 1:30, 2:00, 3:00 ,5:00.
1935
sBOOSTTIMER = swCOUNT;
1943
// ------------------------- *CALIBRATE* TEMPERATURE -----------------------
1945
void CalibrateTemperature() {
1946
sTEMPOFFSET = 0; // Delete current temp offset so new reading is without.
1947
sTEMPOFFSET = (int8_t)(swVALUE-ADC_read(TEMP_READOUT)); // Get current temperature, calculate and store offset.
1952
// ---------------- *VOLT* MONITORING / TEMP CALIBRATE ---------------------
1954
void VoltMonTempCalibSet() {
1958
if (swSETUP == sSETLOWVMON+CONFIRMATION) {
1959
sLOWVOLT = swVALUE; // Copy new value.
1960
sGENERICSETTINGS |= (1 << gsLowVoltMon); // Always turn on low voltage monitoring when new value is entered.
1962
WriteAndResetVoltStatus(); // Save new settings and clear low voltage.
1965
if (swSETUP == sSETCRITVMON+CONFIRMATION) {
1966
sCRITVOLT = swVALUE; // Copy new value.
1968
WriteAndResetVoltStatus(); // Save new settings and clear low voltage.
1971
if (swSETUP == sTEMPCALIB+CONFIRMATION) CalibrateTemperature();
1975
if (swSETUP == sSETLOWVMON) {
1976
sLOWVOLT = swVALUE; // Copy new value.
1977
sGENERICSETTINGS |= (1 << gsLowVoltMon); // Always turn on low voltage monitoring when new value is entered.
1979
WriteAndResetVoltStatus(); // Save new settings and clear low voltage.
1982
if (swSETUP == sSETCRITVMON) {
1983
sCRITVOLT = swVALUE; // Copy new value.
1985
WriteAndResetVoltStatus(); // Save new settings and clear low voltage.
1988
if (swSETUP == sTEMPCALIB) CalibrateTemperature();
1993
// ---------------- VOLT MON / TEMP CALIB READ OUT -------------------------
1995
void VoltMonTempCalibReadout() {
1996
Delay(DELAY_MEDIUM);
1998
if (swSETUP == sSETLOWVMON) {
1999
if (sLOWVOLTMON) BlinkNumValue(sLOWVOLT,2); // Readout low voltage threshold if monitoring active.
2000
else BlinkValue(0,0); // Low voltage monitoring is deactivated.
2002
if (swSETUP == sSETCRITVMON) BlinkNumValue(sCRITVOLT,2); // Readout current critical voltage threshold.
2003
if (swSETUP == sTEMPCALIB) BlinkMinusValue(sTEMPOFFSET);
2004
if (swSETUP == sTEMPCALIB) BlinkError();
2006
swStartup = STARTDELAY_LONG;
2009
// ---------------- VOLT MON / TEMP CALIB RESET ----------------------------
2011
void VoltMonTempCalibReset() {
2012
if (swSETUP == sSETLOWVMON) {
2013
sGENERICSETTINGS ^= (1 << gsLowVoltMon); // Toggle flag.
2014
if (sLOWVOLTMON) BlinkConfirm(); // Then readout voltage monitoring on/off setting.
2015
else BlinkValue(0,0);
2018
if (swSETUP == sSETCRITVMON) {
2019
sGENERICSETTINGS ^= (1 << gsCritShutdown); // Toggle flag.
2020
if (sCRITSHUTDOWN) BlinkValue(0,0); // Then readout critical shutdown setting.
2021
else BlinkSettingDown();
2024
if (swSETUP == sTEMPCALIB) {
2025
sTEMPOFFSET = TEMPOFFSET;
2030
else WriteAndResetVoltStatus(); // Save new settings and voltage status.
2033
// ---------------- *VOLT* MONITORING / *TEMP* *CALIBRATE* -----------------
2035
void VoltMonTempCalib() {
2041
swVALUE = EswGetValue(2);
2044
// NO PRESS: READOUT SETTING
2046
if (swVALUE == NO_PRESS) VoltMonTempCalibReadout();
2049
// LONG PRESS: TOGGLE VOLT SETTING / RESET TEMPOFFSET
2051
if (swVALUE == LONG_PRESS) VoltMonTempCalibReset();
2053
// ESWITCH CONFIRM VALUE: SAVE NEW SETTING
2058
// PRESS VALUE: CHECK IF IN RANGE
2060
if ((swVALUE < 20 || swVALUE > 90) && swSETUP != sTEMPCALIB) BlinkError();
2062
BlinkNumValue(swVALUE,2);
2063
if (SwConfirm()) VoltMonTempCalibSet();
2068
// OFFSWITCH: FIRST DIGIT
2073
swVALUE = swCOUNT * 10;
2075
swSETUP += SECOND_DIGIT;
2088
// OFFSWITCH: SECOND DIGIT
2092
void VoltMonTempCalib_OswDigit2() {
2094
if (swCOUNT == NO_PRESS) BlinkError();
2096
if (swCOUNT <= 9 || swCOUNT == LONG_PRESS) {
2097
if (swCOUNT == LONG_PRESS) swCOUNT = 0;
2101
// PRESS VALUE: CHECK IF IN RANGE
2103
if ((swVALUE < 20 || swVALUE > 90) && swSETUP != sTEMPCALIB+SECOND_DIGIT) BlinkError();
2105
BlinkNumValue(swVALUE,2);
2106
swSETUP = swSETUP - SECOND_DIGIT + CONFIRMATION;
2117
// ------------------------ SET MAX TEMPERATURE ----------------------------
2124
swCOUNT = SwConfirm();
2127
// NO CONFIRMATION: READOUT MAX TEMPERATURE
2129
if (swCOUNT == NO_PRESS) {
2131
if (sTEMPMONITOR) BlinkNumValue(sMAXTEMP,2); // Readout max temperature...
2132
else BlinkValue(0,0); // Except if temperature monitor is off.
2133
swStartup = STARTDELAY_LONG;
2136
// LONG CONFIRMATION: RESET MAX TEMPERATURE
2138
if (swCOUNT == LONG_PRESS) {
2139
sGENERICSETTINGS ^= (1 << gsTempMonitor); // Toggle flag.
2140
if (sTEMPMONITOR) BlinkConfirm(); // Then readout temperature monitoring on/off setting.
2141
else BlinkValue(0,0);
2142
bTEMPSTATUS = 0; // Set Temperature status to normal.
2143
eeWrite(); // Write setting change to EEPROM.
2146
// SHORT CONFIRMATION: SET MAX TEMPERATURE
2150
if (CheckStatus()) BlinkValue(0,0); // Levels not normal, abort.
2153
// LEVELS NORMAL: START SET MAX TEMPERATURE
2155
sGENERICSETTINGS |= (1 << gsTempMonitor); // Automatically enable temp monitoring.
2158
Delay(DELAY_MEDIUM);
2159
PORTB = MAX; // Turn on light full blast.
2160
uint8_t TemperatureOld = Temperature + 1; // For storing previous temperature.
2163
if (Temperature > TemperatureOld) { // Temperature rising one degree-ish unit.
2164
if (++CritTempTicks >= SEC/2) {
2167
sMAXTEMP = Temperature;
2168
TemperatureOld = Temperature;
2171
PORTB = MAX; // Turn on light full blast.
2182
// ------------------------- *CALIBRATE* VOLTAGE ---------------------------
2184
void CalibrateVoltage() {
2185
Delay(DELAY_VOLTCALIB); // Long delay so cell recovers from load.
2186
uint32_t iADC = ADC_read(RAW);
2187
uint32_t iIntRefVolt = (uint32_t)(((uint32_t)swVALUE * (uint32_t)2048000) / iADC);
2189
sINTREFVOLT = (uint16_t)(iIntRefVolt / 100);
2190
if (iIntRefVolt % 100 >= 50) sINTREFVOLT++;
2193
WriteAndResetVoltStatus(); // Save new settings and clear low voltage.
2196
// ------------------------ VOLTAGE CALIBRATE ------------------------------
2204
swVALUE = EswGetValue(3);
2207
// NO PRESS: READOUT INTERNAL REFERENCE VOLTAGE
2209
if (swVALUE == NO_PRESS) {
2210
Delay(DELAY_MEDIUM);
2211
BlinkNumValue(sINTREFVOLT,5);
2213
swStartup = STARTDELAY_LONG;
2216
// LONG PRESS: RESET VOLT OFFSET TO DEFAULT
2219
if (swVALUE == LONG_PRESS) {
2220
sINTREFVOLT = INTREFVOLT;
2222
WriteAndResetVoltStatus(); // Save new settings and clear low voltage.
2225
// ESWITCH: CHECK IF IN RANGE
2231
if (swVALUE < 200 || swVALUE > 900) BlinkError(); // Minimum value 2V, maximum value 9V.
2233
// CONFIRM VALUE: CALCULATE AND SAVE NEW *CALIBRATED* INTERNAL REFERENCE VOLTAGE
2236
BlinkNumValue(swVALUE,3);
2237
if (SwConfirm()) CalibrateVoltage();
2243
// OFFSWITCH: FIRST DIGIT
2248
swVALUE = swCOUNT * 100;
2250
swSETUP += SECOND_DIGIT;
2263
// OFFSWITCH: FOLLOWING DIGITS AND CONFIRMATION
2267
void VoltCalib_OswPart2() {
2269
// PRESS VALUE: SECOND DIGIT:
2271
if (swSETUP == sVOLTCALIB+SECOND_DIGIT) {
2273
if (swCOUNT == NO_PRESS) BlinkError();
2275
if (swCOUNT <= 9 || swCOUNT == LONG_PRESS) {
2276
if (swCOUNT == LONG_PRESS) swCOUNT = 0;
2277
swVALUE += swCOUNT*10;
2279
swSETUP = sVOLTCALIB+THIRD_DIGIT;
2289
// PRESS VALUE: THIRD DIGIT:
2291
if (swSETUP == sVOLTCALIB+THIRD_DIGIT) {
2293
if (swCOUNT == NO_PRESS) BlinkError();
2295
if (swCOUNT <= 9 || swCOUNT == LONG_PRESS) {
2296
if (swCOUNT == LONG_PRESS) swCOUNT = 0;
2300
// PRESS VALUE: CHECK IF IN RANGE
2302
if (swVALUE < 200 || swVALUE > 900) BlinkError(); // Minimum value 2V, maximum value 9V.
2304
BlinkNumValue(swVALUE,3);
2305
swSETUP = sVOLTCALIB+CONFIRMATION;
2314
// CONFIRM VALUE: CALCULATE AND SAVE NEW *CALIBRATED* INTERNAL REFERENCE VOLTAGE
2316
if (swSETUP == sVOLTCALIB+CONFIRMATION) CalibrateVoltage();
2321
// ------------------------ SET TEMPERATURE PROFILE ------------------------
2323
void TempProfile() {
2328
uint8_t swCOUNT = SwConfirm();
2333
// NO CONFIRMATION: READOUT TEMPERATURE PROFILE
2335
if (swCOUNT == NO_PRESS) {
2336
if (sTEMPMONITOR) BlinkNumValue(sTEMPPROFILE,1); // Readout temperature profile value...
2337
else BlinkValue(0,0); // Except if temperature monitor is off.
2338
swStartup = STARTDELAY_LONG;
2342
// LONG CONFIRMATION: RESET TEMPERATURE PROFILE
2344
if (swCOUNT == LONG_PRESS) {
2345
sTEMPPROFILE = TEMPPROFILE;
2350
// SHORT CONFIRMATION: TEMPERATURE PROFILING
2354
if (CheckStatus()) BlinkValue(0,0); // Levels not normal, abort.
2357
// LEVELS NORMAL: START TEMPERATURE PROFILING
2361
uint8_t iTemp = Temperature + 5;
2362
uint8_t iMaxTemp = iTemp;
2363
uint8_t iWdtTicks = 0;
2364
uint8_t iTempReadings = 0;
2365
uint8_t iModeHold = sMODE;
2369
while (iTempReadings < 5) { // 5 readings at target before turning LED off.
2370
if (Temperature >= iTemp) {
2372
iWdtTicks = WdtTicks;
2373
while (iWdtTicks == WdtTicks);
2384
while (iTempReadings < 5) { // 5 readings at target before stopping.
2385
if (Temperature < iTemp) {
2387
iWdtTicks = WdtTicks;
2388
while (iWdtTicks == WdtTicks);
2391
if (Temperature > iMaxTemp) {
2392
iMaxTemp = Temperature; // If temperature rises after LED off.
2399
sTEMPPROFILE = WdtSecs + 1;
2400
BlinkNumValue(sTEMPPROFILE,1);
2402
BlinkNumValue(iMaxTemp,1);
2403
sGENERICSETTINGS |= (1 << gsTempMonitor); // Automatically enable temp monitoring.
2405
eeWrite(); // Write setting change to EEPROM.
2410
// ------------------------ RESET TO DEFAULT -------------------------------
2416
if (swSETUP == sRESET2DEF) {
2417
swSETUP = RESET_CONFIRM_1;
2425
uint8_t iEswConfirm = SwConfirm();
2430
while (!ESWITCH && WdtSecs < 4) { // Confirmation flash. Pressing here will reset.
2431
if (WdtSecs % 2) PWM = LVL_READOUT+7;
2432
else PWM = LVL_READOUTLOW;
2438
uint8_t i = WdtSecs; // Save WDT second counter before delay.
2439
Delay(DELAY_MEDIUM);
2440
if (i < 4) { // If switch was pressed during confirmation flash, reset.
2441
BlinkConfirm(); // Reset to default confirmed.
2443
if (iEswConfirm == 255) BlinkConfirm(); // Two confirmation blinks for reset, three for full reset.
2444
ResetToDefault(iEswConfirm); // Passes on short or long confirmation press.
2451
// OFFSWITCH CONFIRMATION:
2453
void Reset2Def_OswConfirm() {
2454
if (swSETUP == RESET_CONFIRM_1) {
2455
if (swCOUNT == 1) swSETUP = RESET_CONFIRM_SHORT;
2456
if (swCOUNT == LONG_PRESS) swSETUP = RESET_CONFIRM_LONG;
2460
while (WdtSecs < 4) { // Confirmation flash. Pressing here will reset.
2461
if (WdtSecs % 2) PWM = LVL_READOUT+7;
2462
else PWM = LVL_READOUTLOW;
2470
if (swSETUP == RESET_CONFIRM_SHORT && swCOUNT) {
2476
if (swSETUP == RESET_CONFIRM_LONG && swCOUNT) {
2484
// ======================== *MAIN* *STARTUP* ===============================
2486
eeRead(); // Read in all settings.
2488
uint16_t iADC = ADC_read(CAP); // Read off time capacitor.
2489
if (iADC >= OFF_SHORT) offTime = 2; // Check for short off press (2), long off press (1) or cold start (0).
2490
else if (iADC >= OFF_LONG) offTime = 1;
2492
DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3) | (1 << PB5); // Set PB0 to PB3 and PB5 as output.
2495
if (bVOLTSTATUS > 4) bVOLTSTATUS = 0; // Check Voltage status for decay.
2496
if (bTEMPSTATUS > 2) bTEMPSTATUS = 0; // Check Temperature status for decay.
2498
WDT_on(); // Watch dog timer on.
2499
set_sleep_mode(SLEEP_MODE_IDLE); // Enable sleep mode between WDT interrupts. Triggered by sleep_mode().
2500
while (WdtTicks < 5); // Slight delay so charge of COT avoids triggering ESWITCH.
2502
ADC_read(VOLT); // First read to get E-switch status.
2504
if (offTime == 0) ColdStart();
2506
// ------------------------ *ESWITCH* *SETUP* ------------------------------ // *ESETUP*
2512
offTime = 0; // Clear off time cap readings.
2515
while (ESWITCH) { // Switch hold blink to number of functions before timing out.
2517
if (SwitchTicks == FUNCTIONBLINKTIME) {
2518
swStartup++; // Increase menu selection.
2520
if ((SAFETYLOCK || sUI == UI_NOOB) && swSETUP == 10) swStartup = sRESET2DEF+1;
2521
if (swStartup < (sRESET2DEF/10)+1) {
2523
swSETUP = swStartup * 10;
2524
if (swSETUP == sCALIBRATIONS) { // Small delay before proceeding to reset2default.
2525
while (ESWITCH && SwitchTicks < FUNCTIONBLINKTIME + (SEC/2));
2534
swStartup = STARTDELAY_MEDIUM;
2539
// ------------------------ *OFFSWITCH* *SETUP* ---------------------------- // *OSETUP*
2546
if (swSETUP > 1) swCOUNT = LONG_PRESS;
2550
// SETUP PRESS COUNT:
2552
if (offTime == 2 || (offTime == 1 && swSETUP == 1)) {
2556
Delay(DELAY_SETUPPRESS);
2557
if (swSETUP ==1) swSETUP = 2;
2560
// SETUP ACCESS: THREE TO EIGHT PRESSES AFTER COLD START
2563
if (sUI == UI_NOOB || (sUI != UI_NOOB && swCOUNT == 9)) {
2564
if (swCOUNT == 9) ToggleNoob();
2571
if (swCOUNT >= 3 && swCOUNT <=8) {
2573
swSETUP = (swCOUNT-2)*10;
2581
if (swSETUP >= 10) {
2583
swStartup = STARTDELAY_MEDIUM; // Standard startup delay after setup routine done.
2588
// ------------------------ *SETUP* MENU -----------------------------------
2590
if (swSETUP == sSELECTUI) SelectUI();
2591
if (swSETUP == sSPECIALMODES) SpecialModes();
2592
if (swSETUP == sMODESETTINGS || swSETUP == sMONITORING || swSETUP == sCALIBRATIONS) Setup();
2593
if (swSETUP == sSOS) ToggleSOS();
2595
if (swSETUP == sSETMODECNT) SetModeCount();
2596
if (swSETUP == sSETMODEMEM) SetModeMemory();
2597
if (swSETUP == sSETBOOSTIME) SetBoostTimer();
2599
if (swSETUP == sSETMAXTEMP) SetMaxTemp();
2600
if (swSETUP == sTEMPPROFILING) TempProfile();
2601
if (swSETUP == sSETLOWVMON || swSETUP == sSETCRITVMON || swSETUP == sTEMPCALIB) VoltMonTempCalib();
2603
if (swSETUP == sVOLTCALIB) VoltCalib();
2604
if (swSETUP == sRESET2DEF) Reset2Def();
2607
if (swSETUP == sSETLOWVMON+SECOND_DIGIT || swSETUP == sSETCRITVMON+SECOND_DIGIT || swSETUP == sTEMPCALIB+SECOND_DIGIT) VoltMonTempCalib_OswDigit2();
2608
VoltMonTempCalibSet();
2609
VoltCalib_OswPart2();
2610
Reset2Def_OswConfirm();
2613
// -------------------- END OF SETUP *FUNCTIONS* ---------------------------
2615
while (ESWITCH); // If E-switch still pressed after startup, halt to avoid going directly to boost.
2618
// ------------------------ *SAFETY* LOCK CHECK ----------------------------
2620
if (SAFETYLOCK) { // If safety lock is engaged:
2621
uint8_t SafetyLockblinked = 0;
2627
SafetyLockblinked = 0;
2632
if (!(WdtSecs % 4)) {
2633
if (!SafetyLockblinked) {
2634
PWM_on(LVL_READOUT);
2637
SafetyLockblinked = 1;
2642
SafetyLockblinked = 0;
2647
// ======================== LIGHT *STARTUP* ================================
2649
if (swStartup == STARTDELAY_SHORT) Delay(DELAY_SHORT);
2650
if (swStartup == STARTDELAY_MEDIUM) Delay(DELAY_MEDIUM);
2651
if (swStartup == STARTDELAY_LONG) Delay(DELAY_LONG);
2652
if (swStartup == STARTDELAY_LONG_KEEPMEM) Delay(DELAY_LONG);
2656
// ------------------------ COLD STARTUP ----------------------------------
2659
if (sUI != SOS && swStartup < STARTDELAY_LONG_KEEPMEM) { // SOS and mode level readout always keep current mode despite memory setting.
2661
bMODE = sMODE; // Copy current mode to keep mode in mode level readout when memory disabled.
2664
if (sMODE == BOOSTMODE && sMODEMEM == 1) { // Boost was last mode but boost memory disabled.
2665
if (sUI == 3) sMODE = RAMPMODE1;
2666
else sMODE = sMODEHOLD;
2671
if (bPROGSTATUS != 6) ResetMode(); // Keep mode if programming mode selected and mode memory is off.
2676
// ==================== ESWITCH *OFFTIME* CAP FUNCTIONS ====================
2680
if (sUI <= 3 || (sUI >= SOS && sUI <= STROBE) || sUI == UI_NOOB) {
2682
// SHORT OFF PRESS : UI 1/2/STROBE NEXT MODE, UI 3 ENABLE LEVEL PROGRAMMING.
2685
if (sUI == 3) bPROGSTATUS = 2;
2692
// LONG OFF PRESS : UI 1/2/STROBE PREVIOUS MODE, UI 3 EXIT LEVEL PROGRAMMING.
2695
if (sUI == 3) bPROGSTATUS = 0;
2705
// ==================== OSWITCH *OFFTIME* CAP FUNCTIONS ====================
2709
if ((sUI <= 3 && !bPROGSTATUS) || sUI == SOS || sUI == UI_NOOB) {
2711
// SHORT OFF PRESS : UI 1/2/SOS NEXT MODE, UI 3 ENABLE LEVEL PROGRAMMING.
2715
if (sMODE == RAMPMODE1) sMODE = BOOSTMODE; // Activate boost.
2716
else sMODE = RAMPMODE1; // Deactivate boost.
2720
if (sUI == 2 && sMODE == BOOSTMODE) sMODE = sMODEHOLD;
2727
// LONG OFF PRESS : UI 1/2/SOS PREVIOUS MODE.
2731
if (sMODE != BOOSTMODE) sMODEHOLD = sMODE; // Store the mode in use before boost.
2732
sMODE = BOOSTMODE; // Activate boost.
2748
// ------------------------ MODE PROGRAMMING -------------------------------
2750
if (sUI == 4 || (sUI <= 3 && bPROGSTATUS)) {
2752
if (!bPROGSTATUS || bPROGSTATUS == 4 || swRAMP || (sUI <= 3 && bPROGSTATUS != 5)) {
2755
swPressed = 1; // Set switch to ramp up.
2756
if (swRAMP >= 2) swPressed = 2; // Set switch to ramp down.
2757
if (bPROGSTATUS == 4) Modes[sMODE] = bMODE;
2759
else { // If was in programming mode:
2760
Modes[sMODE] = bMODE; // Copy mode level from no init to current mode.
2761
bPROGSTATUS = 4; // Start save mode timer.
2765
if (sUI <= 2) { // Long presses in UI 1 & 2 changes mode.
2771
else bPROGSTATUS = 0; // If was in programming mode, abort.
2775
// ------------------------ *BEACON* & *STROBE* ----------------------------
2777
if (sUI == BEACON || sUI == STROBE) {
2780
uint8_t iRamp = swRAMP;
2781
Delay(DELAY_SETUPPRESS);
2783
if (sSTROBESPEED++ == 13) sSTROBESPEED = 0;
2786
if (sSTROBESPEED-- == 0) sSTROBESPEED = 13;
2796
// -------------------- END OF *OFFTIME* CAP FUNCTIONS ---------------------
2800
// ======================== *INITIALIZE* LIGHT =============================
2802
if (sMODE == BOOSTMODE) BOOSTSTATUS = 3;
2803
if (bPROGSTATUS == 6) bPROGSTATUS = 2;
2807
if (sUI == 4) bPROGSTATUS = 0;
2811
Flash(5,FLASH_ONOROFF,DELAY_FLASH);
2812
bPROGSTATUS = 2; // PROGSTATUS 2 sets timer to count down to exit programming mode.
2813
ProgModeTicks = 0; // Reset programming mode timer on every startup in mode programming.
2818
if (bPROGSTATUS && bPROGSTATUS < 4 && sUI != 4 && !swPressed) {
2820
Flash(5,FLASH_ONOROFF,DELAY_FLASH);
2821
ProgModeTicks = 0; // Reset programming mode timer on every startup in mode programming.
2825
if (bTEMPSTATUS) CritTempTicks = (sTEMPPROFILE * SEC) - 2*SEC; // If TEMP status is critical force flash after two seconds.
2828
WdtStartup = 2; // Enables voltage and temperature monitoring.
2829
StatusAfterSwitch();
2831
// ------------------------ *STROBE* MODES ---------------------------------
2835
while (sUI == SOS) {
2836
Flash(3,FLASH_LIGHTMODE,14);
2838
Flash(3,FLASH_LIGHTMODE,50);
2839
Flash(3,FLASH_LIGHTMODE,14);
2843
// *BEACON* & STROBE:
2845
while (sUI == BEACON || sUI == STROBE) {
2847
if (StatusAlert == 1) StepDown(0,0);
2854
if (sUI == BEACON) {
2858
Delay(StrobeSpeeds[sSTROBESPEED] * 2);
2861
if (sUI == STROBE) {
2862
Flash(1,FLASH_LIGHTMODE,StrobeSpeeds[sSTROBESPEED]);
2866
// ************************ *MAIN* LOOP ************************************
2868
while (1) { // *WHILE*
2870
// ======================== *ESWITCH* HANDLING =============================
2874
if (ESWITCH) StatusAfterSwitch();
2876
// -------------------- UI 1 SHORT PRESS : NEXT MODE -----------------------
2878
if ((sUI == 1 || sUI == UI_NOOB) && !bPROGSTATUS) {
2880
if (swPressed && !ESWITCH && !swLongPressed) { // Short press with E-switch.
2885
// -------------------- UI 1 LONG PRESS : PREVIOUS MODE --------------------
2887
if (ESWITCH) { // Complicated routine that allows rap around to boost only from lowest mode.
2888
if (swLongPressed == 1) {
2893
if (swLongPressed == 3) {
2894
if ((sMODEDIRL2H && sMODE) || (!sMODEDIRL2H && sMODE < BOOSTMODE)) {
2898
SwitchTicks = LONGPRESSTIME+1;
2904
// -------------------- UI 2 & 3 : *BOOST* ---------------------------------
2907
5 = Switch pressed, on.
2908
4 = On and free running time met (switch not yet released).
2909
3 = On and free running (switch released).
2910
2 = Boost turned off while in free running (switch not yet released).
2911
1 = Off due to timeout.
2912
0 = Off and in standby.
2915
if (((sUI == 2 && sMODECOUNT) || sUI == 3) && !bPROGSTATUS) {
2917
if (ESWITCH && !BOOSTSTATUS && !CheckStatus()) { // If E-switch, boost in standby, volt / temp levels are normal.
2918
BOOSTSTATUS = 5; // Activate boost while switch pressed.
2919
sMODEHOLD = sMODE; // Store current mode before switching to boost.
2924
if (ESWITCH && BOOSTSTATUS==5 && SwitchTicks >= BOOSTFREERUN) { // If E-switch, boost on and free running duration has been met:
2925
BOOSTSTATUS = 4; // Set boost in free running, button is still pressed though.
2928
LightMode(); // Short blink to indicate free running press time met.
2931
if (!ESWITCH && BOOSTSTATUS == 5) { // If switch released before free run duration met:
2932
BOOSTSTATUS = 0; // Turn off boost.
2933
sMODE = sMODEHOLD; // Restore mode to the mode prior to engaging boost.
2937
if (!ESWITCH && BOOSTSTATUS == 4) { // If switch released while boost on and free run duration was met:
2938
BOOSTSTATUS = 3; // Let boost free run (until timeout or new switch press).
2942
if (ESWITCH && BOOSTSTATUS == 3) { // If switch pressed while boost was free running:
2943
BOOSTSTATUS = 2; // Boost off and wait until switch is released.
2944
sMODE = sMODEHOLD; // Restore mode to the mode prior to engaging boost.
2951
// ------------------- UI 4 OR PROGRAM MODE -------------------------------
2953
if (sUI == 4 || bPROGSTATUS) {
2955
uint16_t *pMode = &Modes[sMODE]; // Pointer for ramping.
2959
if (ESWITCH && SwitchTicks >= 40) {
2961
bPROGSTATUS = 5; // PROGSTATUS 5: Switch pressed and level is adjusting.
2962
if (SwitchTicks >= 30) SwitchTicks = 30;
2963
BoostTicks = 0; // Boost can only be active here if in programming mode. Reset boost timer while mode programming.
2965
uint8_t iMultiplier = 50;
2967
if (swPressed == 1) {
2968
#if !defined(PB5_IO) || defined(F8)
2969
if (*pMode >= RAMPMAX) {
2973
*pMode += ((*pMode + iMultiplier) / iMultiplier);
2974
if (*pMode > RAMPMAX) *pMode = RAMPMAX;
2977
*pMode += ((*pMode + iMultiplier) / iMultiplier);
2978
if (*pMode > RAMPMAX) *pMode = RAMPMAX;
2982
if (*pMode) *pMode -= ((*pMode + iMultiplier) / iMultiplier);
2983
if (*pMode > RAMPMAX) *pMode = RAMPMAX;
2986
if (*pMode < 12) { // Slower brightness adjusting for lower values.
3000
uint8_t iRampMax = 0;
3002
if (CheckStatus() == 1 && *pMode > LOWVOLTMAX) {
3003
*pMode = LOWVOLTMAX;
3007
if (CheckStatus() == 2 && *pMode > CRITICALMAX) {
3008
*pMode = CRITICALMAX;
3013
bMODE = *pMode; // Store adjusted mode level in no init, saves a lot of eeprom writing.
3016
if (*pMode >= RAMPMAX || iRampMax) {
3017
FlashOff(); // Short blink off to notify max level reached.
3019
Delay(DELAY_MEDIUM);
3023
if (bPROGSTATUS == 3) { // PROGSTATUS 3: Level save timer timed out.
3025
bPROGSTATUS = 0; // Will exit programming mode directly if UI 3/4/5.
3026
if (sUI <= 2) bPROGSTATUS = 2; // PROGSTATUS 2: Start countdown to exit programming mode.
3027
if (sUI <= 3) BlinkOnOffThreshold(0); // Blink once on mode level save in UI 1/2/3.
3029
if (sUI == 3) Delay(DELAY_SHORT); // Small delay to avoid accidental boost if pressed slightly after timeout.
3034
if (bPROGSTATUS == 1) { // PROGSTATUS 1: Programming mode timer timed out.
3038
BlinkOnOffThreshold(0); // UI 1/2/3 blink exit programming mode. UI 3 blinks only if level not adjusted.
3042
BlinkOnOffThreshold(0); // UI 1/2 second blink exiting programming mode.
3051
if (!ESWITCH && bPROGSTATUS == 5) bPROGSTATUS = 4; // PROGSTATUS 4: Switch released, start countdown to EEPROM save.
3057
// -------------------- E-SWITCH PRESS RELEASE -----------------------------
3061
if (!ESWITCH && (swPressed || swLongPressed)) { // E-switch released after press:
3063
if ((sUI <= 2 || sUI == UI_NOOB || BOOSTSTATUS==3) && (CheckStatus() < 2) && !bPROGSTATUS) eeWrite();
3068
// -------------------- *BOOST MODE TIMEOUT* -------------------------------
3070
if (!ESWITCH && (BOOSTSTATUS==1 || BOOSTSTATUS==2 )) StepDown(0,0); // Boost timed out, or switch released after turning off.
3072
// ======================== *MONITORING* ===================================
3074
// -------------------- *LOW* *VOLTAGE* LEVEL ------------------------------
3076
if (StatusAlert == ALERT_LOWVOLT) {
3078
if (sUI < 3) bPROGSTATUS = 0; // If in programming mode, exit.
3080
// OUTPUT AT OR BELLOW ALLOWED LIMIT:
3082
if (BOOSTSTATUS <=2 && (Modes[sMODE]<=LOWVOLTMAX)) bVOLTSTATUS= 2; // Set voltage status to low in lowest.
3086
StatusAlert = 0; // Status alert dealt with, reset.
3090
// -------------------- *CRITICAL* VOLTAGE LEVEL ---------------------------
3092
if (StatusAlert == ALERT_CRITVOLT) {
3094
if (sUI < 3) bPROGSTATUS = 0; // If in programming mode, exit.
3096
// NOT BOOST MODE AND OUTPUT ABOVE ALLOWED LIMIT:
3099
if (bVOLTSTATUS < 4 || Modes[sMODE] > CRITICALMAX) { // If first critical warning or output above limit.
3101
bVOLTSTATUS = 4; // Set voltage status to critical.
3104
// OUTPUT ALREADY AT OR BELLOW ALLOWED LIMIT:
3109
StatusAlert = 0; // Status alert dealt with, reset.
3112
// -------------------- *TEMPERATURE* MONITORING ---------------------------
3114
if (StatusAlert >= ALERT_HIGHTEMP) {
3116
if (sUI < 3) bPROGSTATUS = 0; // If in programming mode, exit.
3118
if (StatusAlert == ALERT_HIGHTEMP) StepDown(3,0);
3121
StatusAlert = 0; // Status alert dealt with, reset.
3124
// ======================== END MONITORING =================================
3129
// ************************ END MAIN LOOP **********************************