~gabe/flashlight-firmware/anduril2

« back to all changes in this revision

Viewing changes to Mike_C/X85/X85.c

  • Committer: Selene Scriven
  • Date: 2016-09-09 21:15:38 UTC
  • mto: This revision was merged to the branch mainline in revision 172.
  • Revision ID: ubuntu@toykeeper.net-20160909211538-71x5r1r03ls6xjvq
Added X85 firmware by Mike C.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/****************************************************************************
 
3
*                                                                                                                                                       *
 
4
*                                                       X85 v1 - Mike C                                                                 *
 
5
*                                                                                                                                                       *
 
6
*                               ATtiny85 firmware for Mike C drivers.                                           *
 
7
*                               Support for Dual Switch and Off Switch setups.                          *
 
8
*                                                                                                                                                       *
 
9
*                               Driver type and setup selected by #defines                                      *
 
10
*                                                                                                                                                       *
 
11
****************************************************************************/
 
12
 
 
13
// ======================== DEFAULT SETTINGS ===============================
 
14
 
 
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.
 
19
 
 
20
        #define DUALSWITCH
 
21
//      #define OFFSWITCH
 
22
 
 
23
//      #define DOUBLE_CELL                                                                                                                     //      Comment out for single cell drivers.
 
24
//      #define PB5_IO                                                                                                                          //      Comment out if PB5 is NOT enabled as IO.
 
25
 
 
26
        #define UI                                      1                                                                                               //      Default UI, 1 to 4.
 
27
        #define MODECOUNT                       4                                                                                               //      Default mode count, max 4.
 
28
 
 
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.
 
31
        #define MODE3                           0,2
 
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.
 
35
 
 
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
 
38
 
 
39
// ======================== DUAL SWITCH INTERFACE ==========================
 
40
/*
 
41
        UI 1
 
42
        ----
 
43
        Next mode:                      Short E or P press.
 
44
        Previous mode:          Long E or P press.
 
45
        Boost:                          In mode cycle.
 
46
 
 
47
        UI 2
 
48
        ----
 
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.
 
52
 
 
53
        UI 3
 
54
        ----
 
55
        Adjust mode:            Short P press enables mode adjustment.
 
56
        Boost:                          E press. Hold for 1.5 seconds to lock.
 
57
 
 
58
        UI 4 & 5
 
59
        --------
 
60
        Adjust mode:            Constant adjustable.
 
61
        Boost:                          N/A.
 
62
 
 
63
        Adjusting output
 
64
        ----------------
 
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.
 
69
 
 
70
// ======================== OFF SWITCH INTERFACE ===========================
 
71
 
 
72
        UI 1
 
73
        ----
 
74
        Next mode:                      Short P press.
 
75
        Previous mode:          Long P press.
 
76
        Boost:                          In mode cycle.
 
77
 
 
78
        UI 2
 
79
        ----
 
80
        Next mode:                      Short P press.
 
81
        Previous mode:          N/A.
 
82
        Boost:                          Long P press (not in mode cycle).
 
83
 
 
84
        UI 3
 
85
        ----
 
86
        Adjust mode:            Long P press enables mode adjustment.
 
87
        Boost:                          Short P press.
 
88
 
 
89
        UI 4 & 5
 
90
        --------
 
91
        Adjust mode:            Constant adjustable.
 
92
        Boost:                          N/A.
 
93
 
 
94
        Adjusting output
 
95
        ----------------
 
96
        Increase:                       Short press starts ramp up. Stop with short press.
 
97
        Decrease:                       Double short press starts ramp down. Stop with short press.
 
98
 
 
99
 
 
100
// ======================== DUAL SWITCH *SETUP* ============================
 
101
 
 
102
  --- *MENU ---    Accessed by holding E-switch on startup.
 
103
                   Menu selection by blinks, rest by E-switch presses.
 
104
 
 
105
    READOUTS       1 = Voltage level 1 to 5.
 
106
                   2 = Real voltage X,XX.
 
107
                   3 = Temperature.
 
108
                   4 = Mode level.
 
109
                   5 = Calibration values (after SOS confirmation timeout, endless loop).
 
110
 
 
111
    SPECIALMODES   5 = SOS (confirmation required).
 
112
 
 
113
1   LOCK / UI      L = Safety lock.
 
114
                   1-4 = UI.
 
115
                   9 = Noob mode toggle on/off.
 
116
 
 
117
2   SPECIALMODES   1 = Beacon.
 
118
                   2 = Strobe.
 
119
                   3 = Prog mode.
 
120
                  (4)= RND Strobe.
 
121
 
 
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.
 
125
                                     1 = Ex Boost.
 
126
                                     2 = Inc Boost.
 
127
                   3 = BoostTimer:   1-9 = 10, 20, 30, 45, 1:00, 1:30, 2:00, 3:00, 5:00.
 
128
                                     L = No timer.
 
129
                                     0 = Readout timer.
 
130
                   0 = SOS on/off    Confirmation required.
 
131
 
 
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.
 
141
 
 
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.
 
151
 
 
152
6   RESET2DEFAULT  1 = Reset modes & settings, not calibrations or offsets.
 
153
                   L = Full reset.
 
154
                   Additional confirmation required.
 
155
 
 
156
 
 
157
// ======================== OFF SWITCH *SETUP* =============================
 
158
 
 
159
  --- *MENU ---    Accessed by 3 to 9 short presses directly after cold start.
 
160
                   All selections by off switch presses.
 
161
 
 
162
    READOUTS       3 = Voltage level.
 
163
                   4 = Real voltage.
 
164
                   5 = Temperature (after SOS confirmation timeout).
 
165
                   6 = Mode level.
 
166
                   7 = Calibration values (endless loop).
 
167
 
 
168
    SPECIALMODES   5 = SOS (confirmation required).
 
169
                   9 = NOOB mode.
 
170
 
 
171
3   LOCK / UI      L = Safety lock.
 
172
                   1-4 = UI.
 
173
 
 
174
4   SPECIALMODES   1 = Beacon.
 
175
                   2 = Strobe.
 
176
                   3 = Prog mode.
 
177
 
 
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.
 
181
                                     1 = Ex Boost.
 
182
                                     2 = Inc Boost.
 
183
                   3 = BoostTimer:   1-9 = 10, 20, 30, 45, 1:00, 1:30, 2:00, 3:00, 5:00.
 
184
                                     L = No timer.
 
185
                                     0 = Readout timer.
 
186
                   0 = SOS on/off    Confirmation required.
 
187
 
 
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.
 
197
 
 
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.
 
207
 
 
208
8   RESET2DEFAULT  1 = Reset modes & settings.
 
209
                   L = Full reset.
 
210
                   Additional confirmation required.
 
211
 
 
212
9   NOOB MODE      Noob mode toggle on/off.
 
213
 
 
214
 
 
215
// ======================== COMMON SHARED INTERFACE ========================
 
216
 
 
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.
 
222
 
 
223
        Memory
 
224
        ------
 
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.
 
229
 
 
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.
 
239
 
 
240
*/
 
241
// =========================================================================
 
242
 
 
243
#include <avr/io.h>
 
244
#include <avr/interrupt.h>
 
245
#include <avr/wdt.h>
 
246
#include <avr/eeprom.h>
 
247
#include <avr/sleep.h>
 
248
 
 
249
// ==================== DRIVER DEFAULT *SETTINGS* ==========================
 
250
 
 
251
//      GENERAL SETTINGS
 
252
 
 
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.
 
256
 
 
257
#define NOOBMODE1                               20                                                                                              //      Noob mode levels, 255 is max.
 
258
#define NOOBMODE2                               75
 
259
#define NOOBMODE3                               255
 
260
 
 
261
// -------------------- COMMON DEFAULT *SETTINGS* --------------------------
 
262
 
 
263
#ifndef TEMPOFFSET
 
264
        #define TEMPOFFSET                      0                                                                                               //      Default uncalibrated temperature offset.
 
265
#endif
 
266
#ifndef MAXTEMP
 
267
        #define MAXTEMP                         50                                                                                              //      Default temperature threshold. One below does step down, one above activates critical mode.
 
268
#endif
 
269
#ifndef TEMPPROFILE
 
270
        #define TEMPPROFILE                     15                                                                                              //      Time in seconds to resume temp monitoring after temp step-down/warning. *EXPERIMENTAL*
 
271
#endif
 
272
#define UIHOLD                                  UI                                                                                              //      UI memory used for toggle SOS & NOOB mode.
 
273
#define MODE                                    0
 
274
#define MODEHOLD                                0
 
275
#define STROBESPEED                             0
 
276
#define INTREFVOLTB1                    INTREFVOLT % 256
 
277
#define INTREFVOLTB2                    INTREFVOLT / 256
 
278
 
 
279
// -------------------- SINGLE CELL VOLTAGE LEVELS -------------------------
 
280
 
 
281
#ifndef DOUBLE_CELL
 
282
        #ifndef INTREFVOLT
 
283
                #define INTREFVOLT              11000                                                                                   //      Default uncalibrated internal ref voltage: 11000 = 1.1V.
 
284
        #endif
 
285
        #ifndef OFF_SHORT
 
286
                #define OFF_SHORT               205                                                                                             //      Voltage threshold for off time cap short press detection.
 
287
        #endif
 
288
        #ifndef OFF_LONG
 
289
                #define OFF_LONG                165                                                                                             //      Voltage threshold for off time cap long press detection.
 
290
        #endif
 
291
        #ifndef LOWVOLT
 
292
                #define LOWVOLT                 32
 
293
        #endif
 
294
        #ifndef CRITVOLT
 
295
                #define CRITVOLT                29
 
296
        #endif
 
297
 
 
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
 
303
 
 
304
        #ifndef INTREFVOLT
 
305
                #define INTREFVOLT              11000                                                                                   //      Default uncalibrated internal reference voltage. 11000 = 1.1V.
 
306
        #endif
 
307
 
 
308
// -------------------- DOUBLE CELL VOLTAGE LEVELS -------------------------
 
309
 
 
310
#else
 
311
        #ifndef INTREFVOLT
 
312
                #define INTREFVOLT              25600                                                                                   //      Default uncalibrated internal ref voltage: 25600 = 2.56V.
 
313
        #endif
 
314
        #ifndef OFF_SHORT
 
315
                #define OFF_SHORT               410                                                                                             //      Voltage threshold of off time cap for short off press detection.
 
316
        #endif
 
317
        #ifndef OFF_LONG
 
318
                #define OFF_LONG                310                                                                                             //      Voltage threshold of off time cap for long off press detection.
 
319
        #endif
 
320
        #ifndef LOWVOLT
 
321
                #define LOWVOLT                 65
 
322
        #endif
 
323
        #ifndef CRITVOLT
 
324
                #define CRITVOLT                60
 
325
        #endif
 
326
 
 
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
 
332
 
 
333
        #ifndef INTREFVOLT
 
334
                #define INTREFVOLT              25600                                                                                   //      Default uncalibrated internal reference voltage. 25600 = 2.56V.
 
335
        #endif
 
336
 
 
337
#endif
 
338
 
 
339
// ------------------------ LOW V/HIGH T MODE LIMITS -----------------------
 
340
 
 
341
        #ifndef LOW
 
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.
 
344
        #endif
 
345
 
 
346
// ------------------------ LOW OUTPUT SETTINGS ----------------------------
 
347
 
 
348
        #ifdef LOW
 
349
                #define MODE1                   9,0
 
350
                #define MODE2                   15,0
 
351
                #define MODE3                   40,0
 
352
                #define BOOST                   80,0
 
353
 
 
354
                #define LOWVOLTMAX              35
 
355
                #define CRITICALMAX             15
 
356
        #endif
 
357
 
 
358
// ======================== DRIVER DEFINITIONS =============================
 
359
 
 
360
#ifdef LOW
 
361
        #define RAMPMAX                         1*256
 
362
        #define MAX                                     1
 
363
#endif
 
364
 
 
365
#ifdef F8
 
366
        #ifdef PB5_IO
 
367
                #define RAMPMAX                 8*256
 
368
        #endif
 
369
        #define MAX                                     111
 
370
#endif
 
371
 
 
372
#ifdef G12
 
373
        #ifdef PB5_IO
 
374
                #define RAMPMAX                 12*256
 
375
        #endif
 
376
        #define MAX                                     12
 
377
#endif
 
378
 
 
379
#ifdef G16
 
380
        #ifdef PB5_IO
 
381
                #define RAMPMAX                 16*256
 
382
        #endif
 
383
        #define MAX                                     16
 
384
#endif
 
385
 
 
386
//      PB5 NOT IO:
 
387
 
 
388
#ifndef RAMPMAX
 
389
        #define RAMPMAX                         4*256
 
390
#endif
 
391
 
 
392
// ------------------------ COMMON DEFINITIONS -----------------------------
 
393
 
 
394
#define RAW                                             0
 
395
#define CAP                                             1
 
396
#define VOLT                                    2
 
397
#define VOLT_READOUT                    3
 
398
#define TEMP                                    4
 
399
#define TEMP_READOUT                    5
 
400
 
 
401
#define VOLTAGE_LOW                             sLOWVOLT*10
 
402
#define VOLTAGE_CRIT                    sCRITVOLT*10
 
403
 
 
404
#define ALERT_LOWVOLT                   1
 
405
#define ALERT_CRITVOLT                  2
 
406
#define ALERT_HIGHTEMP                  3
 
407
#define ALERT_CRITTEMP                  4
 
408
 
 
409
#define FLASH_ONOROFF                   254                                                                                             //      Flash routine needs to use BlinkOnOffThreshold.
 
410
#define FLASH_LIGHTMODE                 255
 
411
 
 
412
// -------------------- PIN & E-SWITCH CONFIGURATION -----------------------
 
413
 
 
414
#define ESWITCH                                 (eswLevel < 20)                                                                 //      Check if E-switch is pressed.
 
415
#define NO_PRESS                                0
 
416
#define LONG_PRESS                              255
 
417
#define PWM                                             OCR0A                                                                                   //      PWM output.
 
418
 
 
419
// ======================== MODE VARIABLES =================================
 
420
 
 
421
uint8_t MODE_AMC =                              0;
 
422
uint8_t MODE_PWM =                              0;
 
423
 
 
424
#define BOOSTMODE                               3                                                                                               //      Mode number for boost.
 
425
#define RAMPMODE1                               4
 
426
#define RAMPMODE2                               5
 
427
 
 
428
// ------------------------ UI VARIABLES -----------------------------------
 
429
 
 
430
#define SAFETYLOCK                              (sUI & (1 << 7))                                                                //      Highest bit in UI byte used for safety lock.
 
431
 
 
432
#define SOS                                             6
 
433
#define BEACON                                  7
 
434
#define STROBE                                  8
 
435
#define UI_NOOB                                 9
 
436
 
 
437
// ------------------------ *SETTINGS* -------------------------------------
 
438
 
 
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.
 
444
 
 
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.
 
448
 
 
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]
 
455
 
 
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]
 
461
 
 
462
#define sINTREFVOLT                             Modes[12]                                                                               //      Settings[24] & [25].
 
463
#define sTEMPOFFSET                             Settings[26]
 
464
#define sTEMPPROFILE                    Settings[27]
 
465
 
 
466
// ------------------------ GENERIC SETTINGS -------------------------------
 
467
 
 
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.
 
476
 
 
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))
 
482
 
 
483
// ------------------------ TIMER DEFINITIONS ------------------------------
 
484
 
 
485
#define SEC                                             66                                                                                              //      WDT ticks per second.
 
486
#define BOOST_PERIOD                    165                                                                                             //      1 Boost period = 2.5 seconds.
 
487
 
 
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.
 
492
 
 
493
#define MENUSTARTTIME                   20
 
494
 
 
495
#define PROGMODETIMER                   (2*SEC)                                                                                 //      Programming mode save/exit timeout, seconds.
 
496
 
 
497
// ------------------------ *DELAY* DEFINITIONS ----------------------------
 
498
 
 
499
#define DELAY_FLASH                             2
 
500
#define DELAY_FADE                              3
 
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
 
506
 
 
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.
 
510
 
 
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.
 
513
 
 
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
 
519
 
 
520
// ------------------------ SETUP DEFINITIONS ------------------------------
 
521
 
 
522
//      SETUP MENU
 
523
 
 
524
#define sSELECTUI                               10
 
525
#define sSPECIALMODES                   20
 
526
#define sMODESETTINGS                   30
 
527
#define sMONITORING                             40
 
528
#define sCALIBRATIONS                   50
 
529
#define sRESET2DEF                              60
 
530
 
 
531
//      MODE SETTINGS
 
532
 
 
533
#define sSETMODECNT                             31
 
534
#define sSETMODEMEM                             32
 
535
#define sSETBOOSTIME                    33
 
536
#define sSOS                                    34
 
537
 
 
538
//      MONITORING SETTINGS
 
539
 
 
540
#define sSETMAXTEMP                             41
 
541
#define sSETLOWVMON                             42
 
542
#define sSETCRITVMON                    43
 
543
 
 
544
//      CALIBRATIONS
 
545
 
 
546
#define sVOLTCALIB                              51
 
547
#define sTEMPCALIB                              52
 
548
#define sTEMPPROFILING                  53
 
549
 
 
550
//      OFFSWITCH INPUT ENTRY
 
551
 
 
552
#define RESET_CONFIRM_1                 61
 
553
#define RESET_CONFIRM_SHORT             62
 
554
#define RESET_CONFIRM_LONG              63
 
555
 
 
556
#define SECOND_DIGIT                    100
 
557
#define THIRD_DIGIT                             150
 
558
#define CONFIRMATION                    200
 
559
 
 
560
// ------------------------ EEPROM VARIABLES -------------------------------    *EEPROM*
 
561
 
 
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.
 
567
 
 
568
// ------------------------ TIMER VARIABLES --------------------------------    //      *ISR*
 
569
 
 
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.
 
574
 
 
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.
 
581
 
 
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.
 
585
 
 
586
#ifdef OFFSWITCH
 
587
        volatile uint8_t SetupTicks=0;                                                                                          //      Timer for settings menu access.
 
588
#endif
 
589
 
 
590
// ------------------------ VOLT VARIABLES ---------------------------------
 
591
 
 
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.
 
596
 
 
597
// ------------------------ TEMP VARIABLES ---------------------------------
 
598
 
 
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.
 
602
 
 
603
// ------------------------ NO-INIT VARIABLES ------------------------------
 
604
 
 
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.
 
608
 
 
609
#ifdef OFFSWITCH
 
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.
 
615
#endif
 
616
 
 
617
// ------------------------ MISC VARIABLES ---------------------------------
 
618
 
 
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.
 
622
 
 
623
// ======================== READ FROM *EEPROM* =============================
 
624
 
 
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;
 
632
        }
 
633
 
 
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.
 
638
                }
 
639
        }
 
640
}
 
641
 
 
642
// ======================== WRITE TO *EEPROM* ==============================
 
643
 
 
644
void eeWrite() {
 
645
 
 
646
        uint16_t eePosOld = eePos;
 
647
 
 
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.
 
651
        }
 
652
 
 
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.
 
655
 
 
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.
 
659
                EEAR = eePosOld;
 
660
                EECR |= (1<<EEMPE);                                                                                                             //      Enable writing.
 
661
                EECR |= (1<<EEPE);                                                                                                              //      Start writing.
 
662
        }
 
663
}
 
664
 
 
665
// ------------------------ RESET MODE -------------------------------------
 
666
 
 
667
void ResetMode() {
 
668
        sMODE = 0;
 
669
        sMODEHOLD = 0;
 
670
        if (sUI == 3) sMODE = RAMPMODE1;
 
671
        if (sUI == 4) sMODE = RAMPMODE2;
 
672
        eeWrite();
 
673
}
 
674
 
 
675
// ======================== SET/RESET TO DEFAULT ===========================
 
676
 
 
677
void ResetToDefault(uint8_t iSwConfirm) {
 
678
 
 
679
        uint8_t iSettings = eeBlockSize;
 
680
        if (iSwConfirm == 1) iSettings = 24;                                                                            //      iSettings = 24 does not restore calibrations.
 
681
 
 
682
        for (uint8_t i=0; i < iSettings; i++) {
 
683
                Settings[i] = SettingsDefault[i];                                                                               //      Load default settings into settings array, except last three.
 
684
        }
 
685
 
 
686
        ResetMode();                                                                                                                            //      Reset modes and write default settings to EEPROM.
 
687
}
 
688
 
 
689
// ======================== *INITIALIZING* ROUTINES =========================
 
690
 
 
691
// ------------------------ *PWM* ON/OFF ------------------------------------
 
692
 
 
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...).
 
696
        PWM = MODE_PWM;
 
697
}
 
698
 
 
699
void PWM_off() {
 
700
        PWM = 0;
 
701
        TCCR0A = 0;
 
702
        TCCR0B = 0;
 
703
}
 
704
 
 
705
// ------------------------ WATCHDOG TIMER ON ------------------------------
 
706
 
 
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.
 
713
}
 
714
 
 
715
// ------------------------ WATCHDOG TIMER OFF -----------------------------
 
716
 
 
717
inline void WDT_off() {
 
718
        cli();
 
719
        wdt_reset();
 
720
        MCUSR = 0;                                                                                                                                      //      Clear MCU status register.
 
721
        WDTCR |= (1<<WDCE) | (1<<WDE);                                                                                          //      Start timed sequence.
 
722
        WDTCR = 0x00;                                                                                                                           //      Disable WDT.
 
723
        cli();
 
724
}
 
725
 
 
726
// ======================== CRITICAL SHUTDOWN ==============================
 
727
 
 
728
void Shutdown() {
 
729
        PWM_off();
 
730
        PORTB = 0;                                                                                                                                      //      Turn off PORTB pins.
 
731
        ADCSRA &= ~(1 << ADEN);                                                                                                         //      Make sure ADC is off.
 
732
        WDT_off();                                                                                                                                      //      Turn off watchdog timer.
 
733
 
 
734
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);                                                                            //      Power down as many components as possible.
 
735
 
 
736
        uint8_t mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);                                                        //      Turn off brown-out detection.
 
737
    uint8_t mcucr2 = mcucr1 & ~_BV(BODSE);
 
738
    MCUCR = mcucr1;
 
739
    MCUCR = mcucr2;
 
740
 
 
741
        sleep_enable();
 
742
        sleep_cpu();
 
743
        while (1) {}                                                                                                                            //      ZZzzZZzz...
 
744
}
 
745
 
 
746
// ======================== *DELAY* AND RESETS =============================
 
747
 
 
748
void Delay(uint8_t iDelay) {
 
749
        DelayTicks = 0;
 
750
        while (DelayTicks < iDelay && !BreakStrobe) {}
 
751
        BreakStrobe = 0;
 
752
}
 
753
 
 
754
void ResetTimer() {
 
755
        WdtTicks = 0;
 
756
        WdtSecs = 0;
 
757
}
 
758
 
 
759
void ResetVoltTimers() {
 
760
        NormVoltTicks = 0;
 
761
        LowVoltTicks = 0;
 
762
        CritVoltTicks = 0;
 
763
}
 
764
 
 
765
void WriteAndResetVoltStatus() {
 
766
        bVOLTSTATUS = 0;                                                                                                                        //      Set voltage status to normal.
 
767
        ResetVoltTimers();
 
768
        eeWrite();
 
769
}
 
770
 
 
771
void ResetTempTimers() {
 
772
        NormTempTicks = 0;
 
773
        CritTempTicks = 0;
 
774
}
 
775
 
 
776
void ClearSwitch() {                                                                                                                    //      Clears all switch flags and counters.
 
777
        #ifdef OFFSWITCH
 
778
                if (swSETUP != 1) {
 
779
                        swSETUP =       0;
 
780
                        swCOUNT =       0;
 
781
                }
 
782
                swVALUE =               0;
 
783
        #else
 
784
                SwitchTicks =   0;
 
785
                swPressed =             0;
 
786
                swLongPressed = 0;
 
787
                swPressCounter= 0;
 
788
                swMultiDetect = 0;
 
789
        #endif
 
790
}
 
791
 
 
792
void ColdStart() {
 
793
        bVOLTSTATUS = 0;
 
794
        bTEMPSTATUS = 0;
 
795
        if (bPROGSTATUS != 6) bPROGSTATUS = 0;                                                                          //      PROGSTATUS = 6 is when programming mode is selected from setup.
 
796
        #ifdef OFFSWITCH
 
797
                swSETUP = 1;
 
798
                swCOUNT = 0;
 
799
                swVALUE = 0;
 
800
                swRAMP = 0;
 
801
        #endif
 
802
}
 
803
 
 
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.
 
808
}
 
809
 
 
810
// ------------------------ STATUS CHECKS ----------------------------------
 
811
 
 
812
uint8_t CheckStatus() {
 
813
        uint8_t iStatus = 0;
 
814
        if (bVOLTSTATUS || bTEMPSTATUS) iStatus++;
 
815
        if (bVOLTSTATUS >= 3 || bTEMPSTATUS >= 2) iStatus++;
 
816
        return iStatus;
 
817
}
 
818
 
 
819
// ------------------------ SPLIT MODE LEVEL -------------------------------
 
820
 
 
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;
 
824
}
 
825
 
 
826
// ================ TURN *LIGHT* ON ACCORDING TO MODE ======================
 
827
 
 
828
void LightMode() {
 
829
 
 
830
        ModeToBytes();
 
831
 
 
832
        if (sUI == UI_NOOB) {
 
833
                MODE_AMC = 0;
 
834
                MODE_PWM = NoobModes[sMODE];
 
835
        }
 
836
 
 
837
        if (MODE_PWM) PWM_on(MODE_PWM);
 
838
        else PWM_off();
 
839
 
 
840
// -------------------- PB5 NOT ENABLED AS IO ------------------------------
 
841
 
 
842
        #ifndef PB5_IO
 
843
                if (MODE_AMC < 4) PORTB = MODE_AMC * 2;
 
844
                else {
 
845
                        if (MODE_AMC == 4) PORTB = 7;
 
846
                        else PORTB = 15;
 
847
                }
 
848
 
 
849
        #else
 
850
 
 
851
// -------------------- PB5 IS ENABLED AS IO -------------------------------
 
852
 
 
853
                #ifdef F8
 
854
                        if (MODE_AMC < 8) PORTB = MODE_AMC * 2;
 
855
                        else {
 
856
                                if (MODE_AMC == 8) PORTB = 15;
 
857
                                else PORTB = 47;
 
858
                        }
 
859
                #endif
 
860
 
 
861
 
 
862
                #ifdef G12
 
863
                        if (MODE_AMC < 8) PORTB = MODE_AMC * 2;
 
864
                        else {
 
865
                                if (MODE_AMC < 12) PORTB = ((MODE_AMC - 8) * 2) + 40;
 
866
                                else PORTB = 47;
 
867
                        }
 
868
                #endif
 
869
 
 
870
 
 
871
                #ifdef G16
 
872
                        if (MODE_AMC < 8) PORTB = MODE_AMC * 2;
 
873
                        else {
 
874
                                if (MODE_AMC < 16) PORTB = (MODE_AMC * 2) + 16;
 
875
                                else PORTB = 47;
 
876
                        }
 
877
                #endif
 
878
 
 
879
        #endif
 
880
}
 
881
 
 
882
// ------------------------ LED OFF ---------------------------------------
 
883
 
 
884
void LED_off() {
 
885
        PWM_off();
 
886
        PORTB = 0;
 
887
}
 
888
 
 
889
// ======================== *BLINKOUT ROUTINES* ============================
 
890
 
 
891
// ------------------------ SHORT FLASHES/BLINKS ---------------------------
 
892
 
 
893
inline void FlashOn() {
 
894
        LightMode();
 
895
        Delay(DELAY_FLASH);
 
896
        LED_off();
 
897
}
 
898
 
 
899
inline void FlashOff() {
 
900
        LED_off();
 
901
        Delay(DELAY_FLASH);
 
902
}
 
903
 
 
904
inline void FlashLow() {
 
905
        PWM_on(LVL_READOUTLOW);
 
906
        Delay(DELAY_FLASH);
 
907
        PWM_off();
 
908
}
 
909
 
 
910
void FlashReadout() {
 
911
        PWM_on(LVL_READOUT);
 
912
        Delay(DELAY_FLASH);
 
913
        PWM_off();
 
914
}
 
915
 
 
916
inline void BlinkOn() {
 
917
        LightMode();
 
918
        Delay(DELAY_BLINK);
 
919
        LED_off();
 
920
}
 
921
 
 
922
inline void BlinkOff() {
 
923
        LED_off();
 
924
        Delay(DELAY_BLINK);
 
925
}
 
926
 
 
927
// ------------------------ BLINK ON/OFF THRESHOLD -------------------------
 
928
 
 
929
void BlinkOnOffThreshold(uint8_t iLightMode) {
 
930
        if (Modes[sMODE] > LVL_ONOROFF) {
 
931
                if (iLightMode) FlashOn();
 
932
                else FlashOff();
 
933
        }
 
934
        else {
 
935
                FlashReadout();
 
936
        }
 
937
}
 
938
 
 
939
// ------------------------ *FLASH* ----------------------------------------
 
940
 
 
941
void Flash(uint8_t iTimes, uint8_t iStrength, uint8_t iDuration) {
 
942
        while (iTimes--) {
 
943
                PWM_on(iStrength);
 
944
                if (!iStrength) LED_off();
 
945
                if (iStrength == FLASH_LIGHTMODE) LightMode();
 
946
                if (iStrength == FLASH_ONOROFF) BlinkOnOffThreshold(1);
 
947
                else Delay(iDuration);
 
948
 
 
949
                if (!iStrength) LightMode();
 
950
                else LED_off();
 
951
                Delay(iDuration);
 
952
        }
 
953
}
 
954
 
 
955
// ------------------------ BLINK VALUE ------------------------------------
 
956
 
 
957
void BlinkValue(uint8_t iValue, uint8_t iDigits) {
 
958
        PWM_on(LVL_READOUT);
 
959
        if (iValue) {
 
960
                while (iValue--) Flash(1,LVL_READOUT,DELAY_SHORT);
 
961
        }
 
962
        else {          
 
963
                if (iDigits) {
 
964
                        Delay(DELAY_FLASH);
 
965
                        PWM = 0;
 
966
                        Delay(DELAY_SHORT);
 
967
                }
 
968
                else {
 
969
                        Delay(DELAY_SHORT);
 
970
                        for (uint8_t i=LVL_READOUT; i; i--){
 
971
                                PWM = i;
 
972
                                Delay(DELAY_FADE);
 
973
                        }
 
974
                        Delay(DELAY_SHORT);
 
975
                }
 
976
        }
 
977
        PWM_off();
 
978
}
 
979
 
 
980
//      ------------------- BLINK MULTI DIGIT NUMBER ---------------------------
 
981
 
 
982
void BlinkNumValue(uint16_t iValue, uint8_t iDigits) {                                                  //      iDigits = digits to blink out, X, 0X, 00X, 000X, etc etc.
 
983
 
 
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) {
 
989
                        iDigits = i;
 
990
                        BlinkValue(vValue,1);
 
991
                        Delay(DELAY_MEDIUM);
 
992
                }
 
993
                iValue %= iDivider;
 
994
                iDivider /= 10;
 
995
        }
 
996
}
 
997
 
 
998
//      ------------------- BLINK WITH MINUS NUMBER ----------------------------
 
999
 
 
1000
void BlinkMinusValue(uint8_t iValue) {
 
1001
        PWM_on(0);
 
1002
 
 
1003
        if (iValue >= 128) {
 
1004
                iValue = 256 - iValue;
 
1005
                PWM = LVL_READOUTLOW;                                                                                                   //      If value is -, start with long low 0.
 
1006
                Delay(DELAY_LONG);
 
1007
                PWM = 0;
 
1008
                Delay(DELAY_LONG);
 
1009
        }
 
1010
        BlinkNumValue(iValue,1);
 
1011
 
 
1012
        PWM_off();
 
1013
}
 
1014
 
 
1015
// ------------------------ BLINK CONFIRMATION -----------------------------
 
1016
 
 
1017
void BlinkConfirm() {
 
1018
        PWM_on(LVL_READOUTLOW - 2);
 
1019
        Delay(DELAY_FADE);
 
1020
        PWM = LVL_READOUTLOW;
 
1021
        Delay(DELAY_FADE);
 
1022
        PWM = LVL_READOUTLOW * 2;
 
1023
        Delay(DELAY_FADE);
 
1024
        PWM = LVL_READOUTLOW * 3;
 
1025
        Delay(DELAY_FADE);
 
1026
        PWM = LVL_READOUTLOW * 4;
 
1027
        Delay(DELAY_FADE);
 
1028
        PWM = LVL_READOUTLOW * 3;
 
1029
        Delay(DELAY_FADE);
 
1030
        PWM = LVL_READOUTLOW * 2;
 
1031
        Delay(DELAY_FADE);
 
1032
        PWM = LVL_READOUTLOW;
 
1033
        Delay(DELAY_FADE);
 
1034
        PWM = LVL_READOUTLOW - 2;
 
1035
        Delay(DELAY_FADE);
 
1036
        PWM_off();
 
1037
        Delay(DELAY_BLINK);
 
1038
}
 
1039
 
 
1040
// ------------------------ BLINK SETTING STATUS ---------------------------
 
1041
 
 
1042
inline void BlinkSettingUp() {
 
1043
        PWM_on(LVL_READOUTLOW);
 
1044
        Delay(DELAY_MEDIUM);
 
1045
        PWM = LVL_READOUT;
 
1046
        Delay(DELAY_MEDIUM);
 
1047
        PWM_off();
 
1048
}
 
1049
 
 
1050
void BlinkSettingDown() {
 
1051
        PWM_on(LVL_READOUT);
 
1052
        Delay(DELAY_MEDIUM);
 
1053
        PWM = LVL_READOUTLOW;
 
1054
        Delay(DELAY_MEDIUM);
 
1055
        PWM_off();
 
1056
}
 
1057
 
 
1058
// ------------------------ FLASH ON ERROR ---------------------------------
 
1059
 
 
1060
void BlinkError() {
 
1061
        ClearSwitch();
 
1062
 
 
1063
        PWM_on(LVL_READOUTLOW);
 
1064
        Delay(DELAY_SHORT);
 
1065
        PWM = LVL_READOUT;
 
1066
        Delay(DELAY_SHORT);
 
1067
        PWM = LVL_READOUTLOW;
 
1068
        Delay(DELAY_SHORT);
 
1069
        PWM = LVL_READOUT;
 
1070
        Delay(DELAY_SHORT);
 
1071
        for (uint8_t i=LVL_READOUT; i; i--){
 
1072
                PWM = i;
 
1073
                Delay(DELAY_FADE);
 
1074
        }
 
1075
        PWM_off();
 
1076
}
 
1077
 
 
1078
// ------------------------ GET VOLTAGE BLINKS -----------------------------
 
1079
 
 
1080
uint8_t GetVoltBlinks(uint16_t v) {
 
1081
        uint8_t i = 0;
 
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++;
 
1087
        return i;
 
1088
}
 
1089
 
 
1090
// ======================== *MODE* FUNCTIONS ===============================
 
1091
 
 
1092
// ------------------------ BOOST IN CYCLE ---------------------------------
 
1093
 
 
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)) {
 
1096
                BOOSTSTATUS = 3;
 
1097
                sMODE = BOOSTMODE;
 
1098
        }
 
1099
}
 
1100
 
 
1101
// ------------------------ *MODE* UP --------------------------------------
 
1102
 
 
1103
void ModeUp() {
 
1104
        uint8_t iMODECOUNT = sMODECOUNT;
 
1105
        if (sUI == UI_NOOB) iMODECOUNT = 3;
 
1106
 
 
1107
        if (iMODECOUNT) {
 
1108
                sMODEHOLD = sMODE;
 
1109
                sMODE++;
 
1110
                BOOSTSTATUS = 0;
 
1111
                if (sMODE == BOOSTMODE+1) sMODE = 0;
 
1112
                if (sMODE == iMODECOUNT) {
 
1113
                        sMODE = 0;
 
1114
                        BoostIfInCycle();                                                                                                       //      Changes mode from 0 to BOOST if in cycle.
 
1115
                }
 
1116
                if ((CheckStatus() == 1 && Modes[sMODE] > LOWVOLTMAX) || (CheckStatus() == 2 && Modes[sMODE] > CRITICALMAX)) sMODE = 0;
 
1117
        }
 
1118
}
 
1119
 
 
1120
// ------------------------ *MODE* DOWN ------------------------------------
 
1121
 
 
1122
void ModeDwn() {
 
1123
        uint8_t iMODECOUNT = sMODECOUNT;
 
1124
        if (sUI == UI_NOOB) iMODECOUNT = 3;
 
1125
 
 
1126
        if (iMODECOUNT) {
 
1127
                sMODEHOLD = sMODE;
 
1128
                if (sMODE == BOOSTMODE) sMODE = iMODECOUNT;
 
1129
                sMODE--;
 
1130
                BOOSTSTATUS = 0;
 
1131
                if (sMODE == 255) {
 
1132
                        sMODE = iMODECOUNT - 1;
 
1133
                        BoostIfInCycle();                                                                                                       //      Changes mode from sMODECOUNT - 1 to BOOST if in cycle.
 
1134
                }
 
1135
                while ((CheckStatus() == 1 && Modes[sMODE] > LOWVOLTMAX) || (CheckStatus() == 2 && Modes[sMODE] > CRITICALMAX)) sMODE--;
 
1136
        }
 
1137
}
 
1138
 
 
1139
// ---------------- NEXT/PREV MODE ACCORDING TO DIRECTION ------------------
 
1140
 
 
1141
void NextMode() {
 
1142
        if (sMODEDIRL2H) ModeUp();
 
1143
        else ModeDwn();
 
1144
}
 
1145
 
 
1146
void PrevMode() {
 
1147
        if (sMODEDIRL2H) ModeDwn();
 
1148
        else ModeUp();
 
1149
}
 
1150
 
 
1151
// ------------------------ *STEPDOWN* ROUTINE -----------------------------
 
1152
 
 
1153
void StepDown(uint8_t iBlinks, uint8_t iCritical) {
 
1154
 
 
1155
        Flash(iBlinks,0,DELAY_SHORT);                                                                                           //      Step-down blink.
 
1156
        Delay(DELAY_SHORT);
 
1157
 
 
1158
        if (!iCritical) {
 
1159
                if (BOOSTSTATUS) {                                                                                                              //      Boost mode all UIs.
 
1160
                        BOOSTSTATUS = 0;
 
1161
                        sMODE = sMODEHOLD;
 
1162
                }
 
1163
                else {
 
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.
 
1166
                        }
 
1167
                        if ((sUI == 3 || sUI == 4) && Modes[sMODE] > LOWVOLTMAX) {
 
1168
                                Modes[sMODE] = LOWVOLTMAX;
 
1169
                        }
 
1170
 
 
1171
                }
 
1172
        }
 
1173
 
 
1174
        else {
 
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.
 
1177
 
 
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.
 
1180
                }
 
1181
                if ((sUI == 3 || sUI == 4) && Modes[sMODE] > CRITICALMAX) {
 
1182
                        Modes[sMODE] = CRITICALMAX;
 
1183
                }
 
1184
        }
 
1185
 
 
1186
        eeWrite();                                                                                                                                      //      Save new lower mode to memory.
 
1187
        LightMode();
 
1188
}
 
1189
 
 
1190
// ======================== READ *ADC* =====================================
 
1191
 
 
1192
uint16_t ADC_read(uint8_t adc) {
 
1193
 
 
1194
// ------------------------ ADC ON -----------------------------------------
 
1195
 
 
1196
        DIDR0 |= (1 << ADC2D);                                                                                                          //      Disable digital input on ADC2/PB4.
 
1197
        if (adc <= VOLT_READOUT) {                                                                                                      //      ADC is for voltage reading.
 
1198
                #ifndef DOUBLE_CELL
 
1199
                        ADMUX = (0<<REFS0) | (1<<REFS1) | (0<<REFS2) | (0<<ADLAR) | 0b0010;     //      1.1v reference (single cell), right-adjust, connect ADC2/PB4 to ADC.
 
1200
                #else
 
1201
                        ADMUX = (0<<REFS0) | (1<<REFS1) | (1<<REFS2) | (0<<ADLAR) | 0b0010;     //      2.56v reference (double cell), right-adjust, connect ADC2/PB4 to ADC.
 
1202
                #endif
 
1203
        }
 
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.
 
1206
        }
 
1207
        ADCSRA = (1 << ADEN ) | 0b111;                                                                                          //      ADC on, prescaler division factor 128.
 
1208
 
 
1209
// ------------------------ ADC READ ---------------------------------------
 
1210
 
 
1211
        uint16_t iADC = 0;
 
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.
 
1214
 
 
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.
 
1220
        }
 
1221
 
 
1222
        iADC /= iReadings;                                                                                                                      //      Get the average.
 
1223
 
 
1224
// ------------------------ ADC OFF ----------------------------------------
 
1225
 
 
1226
        ADCSRA &= ~(1 << ADEN);
 
1227
 
 
1228
// ------------------------ RETURN VALUE -----------------------------------
 
1229
 
 
1230
        if (adc && adc <= VOLT_READOUT) {
 
1231
                #ifdef DUALSWITCH
 
1232
                        eswLevel = iADC / 4;                                                                                            //      Left adjust raw value for E-switch reading.
 
1233
                #endif
 
1234
 
 
1235
                iADC=(uint16_t)(((uint32_t)iADC*(uint32_t)sINTREFVOLT)/(uint32_t)20480);//      Convert raw ADC value to voltage value.
 
1236
        }
 
1237
 
 
1238
        if (adc >= TEMP) {
 
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.
 
1242
        }
 
1243
 
 
1244
        return iADC;                                                                                                                            //      Return value.
 
1245
}
 
1246
 
 
1247
// ======================== *ISR* WATCHDOG TIMER ===========================
 
1248
 
 
1249
ISR(WDT_vect) {
 
1250
 
 
1251
// ------------------------ GENERAL TIMER ----------------------------------
 
1252
 
 
1253
        DelayTicks++;                                                                                                                           //      Tick counter for Delay routine.
 
1254
 
 
1255
        if (++WdtTicks == SEC) {                                                                                                        //      WdtTicks per second.
 
1256
                WdtTicks = 0;
 
1257
                if (WdtSecs < 255) WdtSecs++;                                                                                   //      Increase watchdog timer seconds, max 255.
 
1258
        }
 
1259
 
 
1260
// -------------------- *OFFSWITCH* FUNCTION TIMING ------------------------
 
1261
 
 
1262
        #ifdef OFFSWITCH
 
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;
 
1266
        #endif
 
1267
 
 
1268
// ------------------------ WAIT STARTUP DELAY -----------------------------
 
1269
 
 
1270
        if (WdtStartup) {
 
1271
 
 
1272
// ------------------------ READ *VOLTAGE* LEVEL ---------------------------
 
1273
 
 
1274
                Voltage = ADC_read(VOLT);                                                                                               //      Also determines E-switch status.
 
1275
//              Voltage = 300;                                                                                                                  //      *TEST* emulated voltage.
 
1276
 
 
1277
                if (!ESWITCH && WdtStartup == 2) {
 
1278
 
 
1279
                //      NORMAL VOLTAGE LEVEL:
 
1280
 
 
1281
                        if ((sLOWVOLTMON && Voltage > VOLTAGE_LOW) || (!sLOWVOLTMON && Voltage > VOLTAGE_CRIT)) {
 
1282
                                if (NormVoltTicks++ >= SEC) {
 
1283
                                        bVOLTSTATUS = 0;                                                                                        //      Set voltage status to normal.
 
1284
                                        ResetVoltTimers();
 
1285
                                }
 
1286
                        }
 
1287
 
 
1288
                //      LOW VOLTAGE LEVEL:
 
1289
 
 
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;
 
1294
                                        ResetVoltTimers();
 
1295
                                }
 
1296
                        }
 
1297
 
 
1298
                //      CRITICAL VOLTAGE LEVEL:
 
1299
 
 
1300
                        if (Voltage <= VOLTAGE_CRIT) {
 
1301
                                if ((CritVoltTicks++ >= 2*SEC && bVOLTSTATUS <= 3) || (CritVoltTicks >= 30*SEC && bVOLTSTATUS >= 4)) {
 
1302
 
 
1303
                                        if (BOOSTSTATUS >= 3) {
 
1304
                                                bVOLTSTATUS = 1;                                                                                //      If Boost, set voltage status to low, not critical.
 
1305
                                                StatusAlert = ALERT_LOWVOLT;
 
1306
                                        }
 
1307
                                        else {
 
1308
                                                if (bVOLTSTATUS < 3) bVOLTSTATUS = 3;
 
1309
                                                StatusAlert = ALERT_CRITVOLT;
 
1310
                                        }
 
1311
                                        ResetVoltTimers();
 
1312
                                }
 
1313
                        }
 
1314
                }
 
1315
 
 
1316
// ------------------------ E-SWITCH TIMER ---------------------------------
 
1317
 
 
1318
        //      DUALSWITCH:
 
1319
 
 
1320
                #ifdef DUALSWITCH
 
1321
 
 
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.
 
1325
                                        swPressed++;
 
1326
                                        swMultiDetect = 0;
 
1327
                                }
 
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.
 
1332
 
 
1333
                                NoSwitchTicks = 0;
 
1334
                                ProgModeTicks = 0;                                                                                              //      Always reset ProgModeTicks on E-switch press.
 
1335
                        }
 
1336
                        else {
 
1337
                                SwitchTicks = 0;
 
1338
                                swMultiDetect = 0;
 
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.
 
1341
                        }
 
1342
 
 
1343
                #endif
 
1344
 
 
1345
        //      OFFSWITCH:
 
1346
 
 
1347
                #ifdef OFFSWITCH
 
1348
 
 
1349
                        if (ESWITCH) {
 
1350
                                if (SwitchTicks < 255) SwitchTicks++;
 
1351
                                ProgModeTicks = 0;                                                                                              //      Always reset ProgModeTicks on E-switch press.
 
1352
                        }
 
1353
                        else SwitchTicks = 0;
 
1354
 
 
1355
                #endif
 
1356
 
 
1357
// ------------------------ BOOST TIMER ------------------------------------
 
1358
 
 
1359
                if (BOOSTSTATUS >= 3 && BoostTimeouts[sBOOSTTIMER]) {
 
1360
                        if (++BoostTicks >= (BoostTimeouts[sBOOSTTIMER]*5)*SEC ) {                      //      If boost timer enabled and times out:
 
1361
                                BoostTicks = 0;
 
1362
                                BOOSTSTATUS = 1;                                                                                                //      Turn off boost and set boost status to timed out.
 
1363
                        }
 
1364
                }
 
1365
                else BoostTicks = 0;
 
1366
 
 
1367
// ------------------------ PROGRAMMING MODE TIMER -------------------------
 
1368
 
 
1369
                if (bPROGSTATUS == 2 || bPROGSTATUS == 4) {
 
1370
                        ProgModeTicks++;
 
1371
                        if (ProgModeTicks == PROGMODETIMER) bPROGSTATUS--;
 
1372
                }
 
1373
                else ProgModeTicks = 0;
 
1374
 
 
1375
// -------------------- *STROBE* SPEED CHANGE ------------------------------
 
1376
 
 
1377
                #ifdef DUALSWITCH
 
1378
 
 
1379
                        if ((sUI >= SOS && sUI <= STROBE) && swPressed && !ESWITCH && WdtStartup == 2) {
 
1380
                                if (sUI == SOS) {
 
1381
                                        if (!swLongPressed) NextMode();
 
1382
                                        else PrevMode();
 
1383
                                }
 
1384
                                else {
 
1385
                                        if (!swLongPressed) {
 
1386
                                                if (sSTROBESPEED++ == 13) sSTROBESPEED = 0;
 
1387
                                        }
 
1388
                                        else  {
 
1389
                                                if (sSTROBESPEED-- == 0) sSTROBESPEED = 13;
 
1390
                                        }
 
1391
                                }
 
1392
                                BreakStrobe = 1;                                                                                                        //      Setting to 1 breaks waiting for long strobe/sos blinks to finish.
 
1393
                                eeWrite();                                                                                                                      //      Save mode or speed change.
 
1394
                                ClearSwitch();
 
1395
                        }
 
1396
 
 
1397
                #endif
 
1398
 
 
1399
// -------------------- READ *TEMPERATURE* ---------------------------------
 
1400
 
 
1401
                Temperature = (uint8_t)ADC_read(TEMP);
 
1402
//              Temperature = 80;                                                                                                               //      *TEST* emulated temperatures.
 
1403
 
 
1404
                if (sTEMPMONITOR && WdtStartup == 2) {
 
1405
 
 
1406
                //      NORMAL TEMPERATURE LEVEL:
 
1407
 
 
1408
                        if (Temperature < sMAXTEMP) {
 
1409
                                if (NormTempTicks++ >= SEC/2) {
 
1410
                                        bTEMPSTATUS = 0;                                                                                        //      Set Temperature status to normal.
 
1411
                                        ResetTempTimers();
 
1412
                                }
 
1413
                        }
 
1414
 
 
1415
                //      HIGH TEMPERATURE LEVEL:
 
1416
 
 
1417
                        else {
 
1418
                                CritTempTicks++;
 
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;
 
1423
                                        }
 
1424
                                        else {
 
1425
                                                StatusAlert = ALERT_CRITTEMP;
 
1426
                                                bTEMPSTATUS = 2;                                                                                //      Set Temperature status to critical.
 
1427
                                        }
 
1428
                                        ResetTempTimers();
 
1429
                                }
 
1430
                        }
 
1431
                }
 
1432
 
 
1433
// ======================== END OF ISR ROUTINE =============================
 
1434
 
 
1435
        }
 
1436
}
 
1437
 
 
1438
// ======================== *ESWITCH* FUNCTIONS ============================
 
1439
 
 
1440
#ifdef DUALSWITCH
 
1441
 
 
1442
// ------------------------ E-SWITCH PRESS COUNTER -------------------------
 
1443
 
 
1444
inline uint8_t EswPressCounter() {                                                                                              //      Detect and return number of short presses or single long press during a delay.
 
1445
        DelayTicks = 0;
 
1446
        uint8_t iEswCounter = 0;
 
1447
        while (DelayTicks < DELAY_SW) {
 
1448
                if (ESWITCH) {
 
1449
                        DelayTicks = 0;
 
1450
                }
 
1451
                iEswCounter = swPressCounter;
 
1452
                if (swPressCounter == 1 && swLongPressed) {                                                             //      Long press.
 
1453
                        while (ESWITCH);                                                                                                        //      Hold until switch release.
 
1454
                        Delay(DELAY_MEDIUM);                                                                                            //      Delay before exiting.
 
1455
                        ClearSwitch();
 
1456
                        return 255;                                                                                                                     //      Exit, return long press.
 
1457
                }
 
1458
                else {
 
1459
                        if (iEswCounter > 9) iEswCounter = 9;                                                           //      Highest number 9.
 
1460
                }
 
1461
        }
 
1462
        ClearSwitch();
 
1463
        return iEswCounter;
 
1464
}
 
1465
 
 
1466
// ------------------------ E-SWITCH ENTER VALUE ---------------------------
 
1467
 
 
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).
 
1472
 
 
1473
        if (iDigits == TEMP) i = 2;                                                                                                     //      Temperature takes 1 or 2 digits.
 
1474
        uint8_t iFirst = i - 1;
 
1475
        uint16_t iNumber = 0;
 
1476
 
 
1477
        while (i--) {
 
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.
 
1485
                        }
 
1486
                }
 
1487
                if (iEswDigit == 255) iEswDigit = 0;
 
1488
                iNumber *= 10;
 
1489
                iNumber += iEswDigit;
 
1490
                if (i) FlashLow();
 
1491
        }
 
1492
        if (iDigits == 3) iNumber+= 1000;                                                                                       //      Adding 1000 to 3 digit values at end so 255 can be entered.
 
1493
        return iNumber;
 
1494
}
 
1495
 
 
1496
#endif
 
1497
 
 
1498
// ------------------------ SWITCH CONFIRMATION ----------------------------
 
1499
 
 
1500
uint8_t SwConfirm() {                                                                                                                   //      Confirmation flash.
 
1501
 
 
1502
        #ifdef OFFSWITCH
 
1503
 
 
1504
                if (!swCOUNT) {
 
1505
                        Delay(DELAY_MEDIUM);
 
1506
                        PWM_on(0);
 
1507
                        ResetTimer();
 
1508
                        while (!WdtSecs) Flash(1,LVL_READOUT,DELAY_FLASH);
 
1509
                        PWM_off();
 
1510
                }
 
1511
                return 0;                                                                                                                               //      Non void function, return something.
 
1512
 
 
1513
        #else
 
1514
 
 
1515
                Delay(DELAY_MEDIUM);
 
1516
                PWM_on(0);
 
1517
                ResetTimer();
 
1518
                while (!ESWITCH && !WdtSecs) Flash(1,LVL_READOUT,DELAY_FLASH);
 
1519
                PWM_off();
 
1520
                if (!WdtSecs) {                                                                                                                 //      Switch was pressed during flashing.
 
1521
                        while (ESWITCH) {}                                                                                                      //      Make sure switch is released before continuing.
 
1522
                        if (!swLongPressed) {
 
1523
                                ClearSwitch();
 
1524
                                return 1;                                                                                                               //      Short confirmation press returns 1.
 
1525
                        }
 
1526
                        else {
 
1527
                                ClearSwitch();
 
1528
                                return 255;                                                                                                             //      Long confirmation press returns 255.
 
1529
                        }
 
1530
                }
 
1531
                else {
 
1532
                        return 0;                                                                                                                       //      No confirmation press returns 0.
 
1533
                }
 
1534
 
 
1535
        #endif
 
1536
}
 
1537
 
 
1538
// ======================== *OFFSWITCH* FUNCTIONS ==========================
 
1539
 
 
1540
#ifdef OFFSWITCH
 
1541
 
 
1542
// ------------------------ O-SWITCH INPUT DELAY ---------------------------
 
1543
 
 
1544
void OswDelay() {
 
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.
 
1547
}
 
1548
 
 
1549
#endif
 
1550
 
 
1551
// ************************ *MAIN* ROUTINE *********************************
 
1552
 
 
1553
int main(void) {
 
1554
 
 
1555
        #ifdef DUALSWITCH
 
1556
                uint8_t swSETUP = 0;                                                                                                    //      Settings menu access status.
 
1557
                uint8_t swCOUNT = 0;
 
1558
                uint16_t swVALUE = 0;
 
1559
        #endif
 
1560
        
 
1561
        uint8_t offTime = 0;
 
1562
        uint8_t swStartup = 0;                                                                                                          //      Used for switch startup menu, then startup delays.
 
1563
 
 
1564
// ======================== *SETUP* FUNCTIONS ==============================    //      Inline functions that don't take any memory if not called on.
 
1565
 
 
1566
// ------------------------ *READOUTS* -------------------------------------
 
1567
 
 
1568
        //      VOLT LEVEL:
 
1569
 
 
1570
        void Readout_VoltLevel() {
 
1571
                ClearSwitch();
 
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;
 
1575
        }
 
1576
 
 
1577
        //      REAL VOLTAGE:
 
1578
 
 
1579
        void Readout_RealVolt() {
 
1580
                ClearSwitch();
 
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;
 
1584
        }
 
1585
 
 
1586
        //      TEMPERATURE:
 
1587
 
 
1588
        void Readout_Temperature() {
 
1589
                ClearSwitch();
 
1590
                uint8_t iTemp = ADC_read(TEMP_READOUT);
 
1591
                if (iTemp) BlinkNumValue(iTemp,2);
 
1592
                else BlinkValue(0,0);
 
1593
                swStartup = STARTDELAY_LONG;
 
1594
        }
 
1595
 
 
1596
        //      MODE LEVEL:
 
1597
 
 
1598
        void Readout_ModeLevel() {
 
1599
                ClearSwitch();
 
1600
 
 
1601
                #ifdef OFFSWITCH
 
1602
                        sMODE = (uint8_t)bMODE;                                                                                         //      Copy stored mode to keep mode in mode level readout when memory disabled.
 
1603
                        eeWrite();
 
1604
                #endif
 
1605
 
 
1606
                ModeToBytes();
 
1607
 
 
1608
                if (MODE_AMC) {
 
1609
                        Delay(DELAY_MEDIUM);
 
1610
                        BlinkNumValue(MODE_AMC,1);                                                                                      //      Readout AMC value first.
 
1611
                }
 
1612
 
 
1613
                if (MODE_PWM) {
 
1614
                        Delay(DELAY_LONG);
 
1615
                        Flash(3,LVL_READOUTLOW,DELAY_FADE);                                                                     //      Flash to indicate next readout is PWM level.
 
1616
                        Delay(DELAY_LONG);
 
1617
                        BlinkNumValue(MODE_PWM,3);
 
1618
                }
 
1619
 
 
1620
                swStartup = STARTDELAY_LONG_KEEPMEM;
 
1621
        }
 
1622
 
 
1623
        //      CALIBRATIONS:
 
1624
 
 
1625
        void Readout_Calibrations() {
 
1626
                ClearSwitch();
 
1627
                while (1) {
 
1628
                        Delay(DELAY_SW);
 
1629
                        BlinkNumValue(sINTREFVOLT,5);
 
1630
                        Delay(DELAY_SW);
 
1631
                        BlinkMinusValue(sTEMPOFFSET);
 
1632
                }
 
1633
        }
 
1634
 
 
1635
// ------------------------ TOGGLE *SOS* -----------------------------------
 
1636
 
 
1637
        void ToggleSOS() {
 
1638
                if (sUI != SOS) {
 
1639
                        sUIHOLD = sUI;
 
1640
                        sUI = SOS;
 
1641
                }
 
1642
                else sUI = sUIHOLD;
 
1643
                eeWrite();
 
1644
                BlinkConfirm();
 
1645
                swStartup = STARTDELAY_SHORT;
 
1646
        }
 
1647
 
 
1648
// ------------------------ TOGGLE *NOOB* ----------------------------------
 
1649
 
 
1650
        void ToggleNoob() {
 
1651
                if (sUI != UI_NOOB) {
 
1652
                        sUIHOLD = sUI;
 
1653
                        sUI = UI_NOOB;
 
1654
                }
 
1655
                else sUI = sUIHOLD;
 
1656
                ResetMode();
 
1657
                eeWrite();
 
1658
                BlinkConfirm();
 
1659
                swStartup = STARTDELAY_SHORT;
 
1660
        }
 
1661
 
 
1662
// ------------------------ SELECT *UI* ------------------------------------
 
1663
 
 
1664
        void SelectUI() {
 
1665
 
 
1666
                #ifdef OFFSWITCH
 
1667
                        OswDelay();
 
1668
                #else
 
1669
                        swCOUNT = EswGetValue(1);
 
1670
                #endif
 
1671
 
 
1672
                #ifdef DUALSWITCH
 
1673
                        if (sUI == UI_NOOB || (sUI != UI_NOOB && swCOUNT == 9)) {
 
1674
                                if (swCOUNT == 9) ToggleNoob();
 
1675
                                else {
 
1676
                                        swCOUNT = 0;
 
1677
                                        swSETUP = 0;
 
1678
                                }
 
1679
                        }
 
1680
                        else {
 
1681
                #endif
 
1682
 
 
1683
                if (swCOUNT == NO_PRESS) Readout_VoltLevel();
 
1684
 
 
1685
                //      SAFETY LOCK:
 
1686
 
 
1687
                else {
 
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.
 
1691
                                BlinkConfirm();
 
1692
                                if (SAFETYLOCK) {
 
1693
                                        ResetTimer();
 
1694
                                        WdtSecs = 2;                                                                                    //      Set so first safety lock blink after engaging is after 1 second.
 
1695
                                }
 
1696
                        }
 
1697
                        else {
 
1698
 
 
1699
                //      SELECT UI:
 
1700
 
 
1701
                                if (swCOUNT <= 4) {
 
1702
                                        sUI &= ~(1 << 7);                                                                               //      UI change always disengages safety lock.
 
1703
                                        sUI = swCOUNT;
 
1704
                                        BlinkConfirm();
 
1705
                                        ResetMode();
 
1706
                                        swStartup = STARTDELAY_SHORT;                                                   //      Short startup delay.
 
1707
                                }
 
1708
 
 
1709
 
 
1710
        //      ERROR: PRESS COUNT OUT OF RANGE
 
1711
 
 
1712
                                else BlinkError();
 
1713
                        }
 
1714
                }
 
1715
                #ifdef DUALSWITCH
 
1716
                }
 
1717
                #endif
 
1718
        }
 
1719
 
 
1720
// ------------------------ *SPECIAL* MODES --------------------------------
 
1721
 
 
1722
        void SpecialModes() {
 
1723
 
 
1724
                #ifdef OFFSWITCH
 
1725
                        OswDelay();
 
1726
                #else
 
1727
                        swCOUNT = EswGetValue(1);
 
1728
                #endif
 
1729
 
 
1730
                if (swCOUNT == NO_PRESS) Readout_RealVolt();
 
1731
                else {
 
1732
 
 
1733
        //      PRESS COUNT: SPECIAL MODES
 
1734
 
 
1735
                        if (swCOUNT <= 3) {
 
1736
 
 
1737
                                if (swCOUNT == 1) {                                                                                             //      BEACON mode.
 
1738
                                        sUI = BEACON;
 
1739
                                        if (sMODE >= RAMPMODE1) sMODE = 0;
 
1740
                                        eeWrite();
 
1741
                                        swStartup = STARTDELAY_NONE;
 
1742
                                }
 
1743
 
 
1744
                                if (swCOUNT == 2) {                                                                                             //      STROBE mode.
 
1745
                                        sUI = STROBE;
 
1746
                                        if (sMODE >= RAMPMODE1) sMODE = 0;
 
1747
                                        eeWrite();
 
1748
                                        swStartup = STARTDELAY_NONE;
 
1749
                                }
 
1750
 
 
1751
                                if (swCOUNT == 3) {                                                                                             //      *PROGRAMMING* mode.
 
1752
                                        if (sUI > 2) {
 
1753
                                                Delay(DELAY_MEDIUM);
 
1754
                                                BlinkError();
 
1755
                                        }
 
1756
                                        else {
 
1757
                                                bPROGSTATUS = 6;
 
1758
                                                #ifdef OFFSWITCH
 
1759
                                                        sMODE = (uint8_t)bMODE;                                                         //      Copy stored mode to keep mode for level programming when memory disabled.
 
1760
                                                        eeWrite();
 
1761
                                                #endif
 
1762
                                                BlinkConfirm();
 
1763
                                        }
 
1764
                                }
 
1765
                        }
 
1766
 
 
1767
        //      ERROR: PRESS COUNT OUT OF RANGE
 
1768
 
 
1769
                        else BlinkError();
 
1770
                }
 
1771
        }
 
1772
 
 
1773
// ------------------------ *SETTINGS* -------------------------------------
 
1774
 
 
1775
        void Setup() {
 
1776
 
 
1777
                #ifdef OFFSWITCH
 
1778
                        OswDelay();
 
1779
                #else
 
1780
                        swCOUNT = EswGetValue(1);
 
1781
                #endif
 
1782
 
 
1783
                if (swCOUNT == NO_PRESS) {                                                                                              //      *SOS AND *READOUTS*
 
1784
 
 
1785
                        #ifdef OFFSWITCH
 
1786
 
 
1787
                                if (swSETUP == sMODESETTINGS) {
 
1788
                                        swSETUP = sSOS;
 
1789
                                        SwConfirm();
 
1790
 
 
1791
                                //      NO CONFIRMATION: READOUT TEMPERATURE
 
1792
 
 
1793
                                        if (swCOUNT == NO_PRESS) {
 
1794
                                                Delay(DELAY_LONG);
 
1795
                                                Readout_Temperature();
 
1796
                                        }
 
1797
                                }
 
1798
 
 
1799
                                if (swSETUP == sMONITORING) Readout_ModeLevel();
 
1800
                                if (swSETUP == sCALIBRATIONS) Readout_Calibrations();
 
1801
 
 
1802
                        #else
 
1803
 
 
1804
                                if (swSETUP == sMODESETTINGS) Readout_Temperature();
 
1805
                                if (swSETUP == sMONITORING) Readout_ModeLevel();
 
1806
 
 
1807
                                if (swSETUP == sCALIBRATIONS) {
 
1808
                                        swSETUP = sSOS;
 
1809
                                        swCOUNT = SwConfirm();
 
1810
 
 
1811
                                //      NO CONFIRMATION: READOUT TEMPERATURE
 
1812
 
 
1813
                                        if (swCOUNT == NO_PRESS) {
 
1814
                                                Delay(DELAY_LONG);
 
1815
                                                Readout_Calibrations();
 
1816
                                                swSETUP = 0;
 
1817
                                        }
 
1818
                                }
 
1819
 
 
1820
                        #endif
 
1821
                }
 
1822
                else {
 
1823
 
 
1824
        //      PRESS COUNT: SETTING
 
1825
 
 
1826
                        if (swCOUNT <= 3) {
 
1827
                                swSETUP += swCOUNT;
 
1828
                                swCOUNT = 0;
 
1829
                                if (swSETUP == sSETMODECNT && sUI > 2) {                                                //      ERROR if UI is not 1 or 2.
 
1830
                                        BlinkError();
 
1831
                                        swSETUP = 0;
 
1832
                                }
 
1833
                                else {
 
1834
                                        if (swSETUP != sSETMAXTEMP) BlinkConfirm();
 
1835
                                }
 
1836
                        }
 
1837
                        else BlinkError();
 
1838
                }
 
1839
        }
 
1840
 
 
1841
// ------------------------ SET MODE COUNT ---------------------------------
 
1842
 
 
1843
        void SetModeCount() {
 
1844
 
 
1845
                #ifdef OFFSWITCH
 
1846
                        OswDelay();
 
1847
                #else
 
1848
                        swCOUNT = EswGetValue(1);
 
1849
                #endif
 
1850
 
 
1851
                if (swCOUNT) {
 
1852
 
 
1853
        //      LONG PRESS: MODE DIRECTION
 
1854
 
 
1855
                        if (swCOUNT == LONG_PRESS) {
 
1856
                                sGENERICSETTINGS ^= (1 << gsModeDirection);                                             //      Toggle flag.
 
1857
                                if (sMODEDIRL2H) BlinkSettingUp();
 
1858
                                else BlinkSettingDown();
 
1859
                                eeWrite();
 
1860
                        }
 
1861
                        else {
 
1862
 
 
1863
        //      PRESS COUNT: MODE COUNT
 
1864
 
 
1865
                                if (swCOUNT <= 4) {
 
1866
                                        sMODECOUNT = swCOUNT - 1;
 
1867
                                        BlinkConfirm();
 
1868
                                        ResetMode();
 
1869
                                }
 
1870
 
 
1871
        //      ERROR: PRESS COUNT OUT OF RANGE
 
1872
 
 
1873
                                else BlinkError();
 
1874
                        }
 
1875
                }
 
1876
        }
 
1877
 
 
1878
// ------------------------ SET MODE MEMORY --------------------------------
 
1879
 
 
1880
        void SetModeMemory() {
 
1881
 
 
1882
                #ifdef OFFSWITCH
 
1883
                        OswDelay();
 
1884
                #else
 
1885
                        swCOUNT = EswGetValue(1);
 
1886
                #endif
 
1887
 
 
1888
                if (swCOUNT) {
 
1889
 
 
1890
        //      PRESS COUNT OR LONG PRESS: SET MODE MEMORY
 
1891
 
 
1892
                        if (swCOUNT <= 2 || swCOUNT == LONG_PRESS) {
 
1893
 
 
1894
                                if (swCOUNT == LONG_PRESS) {                                                                    //      No mode memory.
 
1895
                                        sGENERICSETTINGS &= ~(1 << gsModeMemory);                                       //      Clear flag.
 
1896
                                        sGENERICSETTINGS &= ~(1 << gsBoostMemory);                                      //      Clear flag.
 
1897
                                        BlinkConfirm();
 
1898
                                }
 
1899
                                if (swCOUNT == 1) {                                                                                             //      Mode memory excluding boost.
 
1900
                                        sGENERICSETTINGS |= (1 << gsModeMemory);                                        //      Set flag.
 
1901
                                        sGENERICSETTINGS &= ~(1 << gsBoostMemory);                                      //      Clear flag.
 
1902
                                        BlinkConfirm();
 
1903
                                }
 
1904
                                if (swCOUNT == 2) {                                                                                             //      Mode memory including boost.
 
1905
                                        sGENERICSETTINGS |= (1 << gsModeMemory);                                        //      Set flag.
 
1906
                                        sGENERICSETTINGS |= (1 << gsBoostMemory);                                       //      Set flag.
 
1907
                                        BlinkConfirm();
 
1908
                                }
 
1909
                                ResetMode();
 
1910
                        }
 
1911
 
 
1912
        //      ERROR: PRESS COUNT OUT OF RANGE
 
1913
 
 
1914
                        else BlinkError();
 
1915
                }
 
1916
        }
 
1917
 
 
1918
// ------------------------ SET BOOST TIMER --------------------------------
 
1919
 
 
1920
        void SetBoostTimer() {
 
1921
 
 
1922
                #ifdef OFFSWITCH
 
1923
                        OswDelay();
 
1924
                #else
 
1925
                        swCOUNT = EswGetValue(1);
 
1926
                #endif
 
1927
 
 
1928
                if (swCOUNT == NO_PRESS) {
 
1929
                        BlinkValue(sBOOSTTIMER,0);
 
1930
                        swStartup = STARTDELAY_LONG;
 
1931
                }
 
1932
                else {
 
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;
 
1936
                                BlinkConfirm();
 
1937
                                eeWrite();
 
1938
                        }
 
1939
                        else BlinkError();
 
1940
                }
 
1941
        }
 
1942
 
 
1943
// ------------------------- *CALIBRATE* TEMPERATURE -----------------------
 
1944
 
 
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.
 
1948
                BlinkConfirm();
 
1949
                eeWrite();
 
1950
        }
 
1951
 
 
1952
// ---------------- *VOLT* MONITORING / TEMP CALIBRATE ---------------------
 
1953
 
 
1954
        void VoltMonTempCalibSet() {
 
1955
 
 
1956
                #ifdef OFFSWITCH
 
1957
 
 
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.
 
1961
                                BlinkConfirm();
 
1962
                                WriteAndResetVoltStatus();                                                                              //      Save new settings and clear low voltage.
 
1963
                        }
 
1964
 
 
1965
                        if (swSETUP == sSETCRITVMON+CONFIRMATION) {
 
1966
                                sCRITVOLT = swVALUE;                                                                                    //      Copy new value.
 
1967
                                BlinkConfirm();
 
1968
                                WriteAndResetVoltStatus();                                                                              //      Save new settings and clear low voltage.
 
1969
                        }
 
1970
 
 
1971
                        if (swSETUP == sTEMPCALIB+CONFIRMATION)  CalibrateTemperature();
 
1972
 
 
1973
                #else
 
1974
 
 
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.
 
1978
                                BlinkConfirm();
 
1979
                                WriteAndResetVoltStatus();                                                                              //      Save new settings and clear low voltage.
 
1980
                        }
 
1981
 
 
1982
                        if (swSETUP == sSETCRITVMON) {
 
1983
                                sCRITVOLT = swVALUE;                                                                                    //      Copy new value.
 
1984
                                BlinkConfirm();
 
1985
                                WriteAndResetVoltStatus();                                                                              //      Save new settings and clear low voltage.
 
1986
                        }
 
1987
 
 
1988
                        if (swSETUP == sTEMPCALIB) CalibrateTemperature();
 
1989
 
 
1990
                #endif
 
1991
        }
 
1992
 
 
1993
// ---------------- VOLT MON / TEMP CALIB READ OUT -------------------------
 
1994
 
 
1995
        void VoltMonTempCalibReadout() {
 
1996
                Delay(DELAY_MEDIUM);
 
1997
 
 
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.
 
2001
                }
 
2002
                if (swSETUP == sSETCRITVMON) BlinkNumValue(sCRITVOLT,2);                                //      Readout current critical voltage threshold.
 
2003
                if (swSETUP == sTEMPCALIB) BlinkMinusValue(sTEMPOFFSET);
 
2004
                if (swSETUP == sTEMPCALIB) BlinkError();
 
2005
 
 
2006
                swStartup = STARTDELAY_LONG;
 
2007
        }
 
2008
 
 
2009
// ---------------- VOLT MON / TEMP CALIB RESET ----------------------------
 
2010
 
 
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);
 
2016
                }
 
2017
 
 
2018
                if (swSETUP == sSETCRITVMON) {
 
2019
                        sGENERICSETTINGS ^= (1 << gsCritShutdown);                                                      //      Toggle flag.
 
2020
                        if (sCRITSHUTDOWN) BlinkValue(0,0);                                                                     //      Then readout critical shutdown setting.
 
2021
                        else BlinkSettingDown();
 
2022
                }
 
2023
 
 
2024
                if (swSETUP == sTEMPCALIB) {
 
2025
                        sTEMPOFFSET = TEMPOFFSET;
 
2026
                        BlinkConfirm();
 
2027
                        eeWrite();
 
2028
                }
 
2029
 
 
2030
                else WriteAndResetVoltStatus();                                                                                 //      Save new settings and voltage status.
 
2031
        }
 
2032
 
 
2033
// ---------------- *VOLT* MONITORING / *TEMP* *CALIBRATE* -----------------
 
2034
 
 
2035
        void VoltMonTempCalib() {
 
2036
 
 
2037
                #ifdef OFFSWITCH
 
2038
                        OswDelay();
 
2039
                        swVALUE = swCOUNT;
 
2040
                #else
 
2041
                        swVALUE = EswGetValue(2);
 
2042
                #endif
 
2043
 
 
2044
        //      NO PRESS: READOUT SETTING
 
2045
 
 
2046
                if (swVALUE == NO_PRESS) VoltMonTempCalibReadout();
 
2047
                else {
 
2048
 
 
2049
        //      LONG PRESS: TOGGLE VOLT SETTING / RESET TEMPOFFSET
 
2050
 
 
2051
                        if (swVALUE == LONG_PRESS) VoltMonTempCalibReset();
 
2052
 
 
2053
        //      ESWITCH CONFIRM VALUE: SAVE NEW SETTING
 
2054
 
 
2055
                        #ifdef DUALSWITCH
 
2056
                                else {
 
2057
 
 
2058
        //      PRESS VALUE: CHECK IF IN RANGE
 
2059
 
 
2060
                                        if ((swVALUE < 20 || swVALUE > 90) && swSETUP != sTEMPCALIB) BlinkError();
 
2061
                                        else {
 
2062
                                                BlinkNumValue(swVALUE,2);
 
2063
                                                if (SwConfirm()) VoltMonTempCalibSet();
 
2064
                                        }
 
2065
                                }
 
2066
                        #endif
 
2067
 
 
2068
        //      OFFSWITCH: FIRST DIGIT
 
2069
 
 
2070
                        #ifdef OFFSWITCH
 
2071
                                else {
 
2072
                                        if (swCOUNT <= 9) {
 
2073
                                                swVALUE = swCOUNT * 10;
 
2074
                                                swCOUNT = 0;
 
2075
                                                swSETUP += SECOND_DIGIT;
 
2076
                                                FlashReadout();
 
2077
                                                OswDelay();
 
2078
                                                BlinkError();
 
2079
                                        }
 
2080
                                        else BlinkError();
 
2081
                                }
 
2082
                        #endif
 
2083
 
 
2084
                }
 
2085
                ClearSwitch();
 
2086
        }
 
2087
 
 
2088
        //      OFFSWITCH: SECOND DIGIT
 
2089
 
 
2090
        #ifdef OFFSWITCH
 
2091
 
 
2092
        void VoltMonTempCalib_OswDigit2() {
 
2093
                OswDelay();
 
2094
                if (swCOUNT == NO_PRESS) BlinkError();
 
2095
                else {
 
2096
                        if (swCOUNT <= 9 || swCOUNT == LONG_PRESS) {
 
2097
                                if (swCOUNT == LONG_PRESS) swCOUNT = 0;
 
2098
                                swVALUE += swCOUNT;
 
2099
                                swCOUNT = 0;
 
2100
 
 
2101
        //      PRESS VALUE: CHECK IF IN RANGE
 
2102
 
 
2103
                                if ((swVALUE < 20 || swVALUE > 90) && swSETUP != sTEMPCALIB+SECOND_DIGIT) BlinkError();
 
2104
                                else {
 
2105
                                        BlinkNumValue(swVALUE,2);
 
2106
                                        swSETUP = swSETUP - SECOND_DIGIT + CONFIRMATION;
 
2107
                                        SwConfirm();
 
2108
                                        ClearSwitch();
 
2109
                                }
 
2110
                        }
 
2111
                        else BlinkError();
 
2112
                }
 
2113
        }
 
2114
 
 
2115
        #endif
 
2116
 
 
2117
// ------------------------ SET MAX TEMPERATURE ----------------------------
 
2118
 
 
2119
        void SetMaxTemp() {
 
2120
 
 
2121
                #ifdef OFFSWITCH
 
2122
                        SwConfirm();
 
2123
                #else
 
2124
                        swCOUNT = SwConfirm();
 
2125
                #endif
 
2126
 
 
2127
        //      NO CONFIRMATION: READOUT MAX TEMPERATURE
 
2128
 
 
2129
                if (swCOUNT == NO_PRESS) {
 
2130
                        Delay(DELAY_LONG);
 
2131
                        if (sTEMPMONITOR) BlinkNumValue(sMAXTEMP,2);                                            //      Readout max temperature...
 
2132
                        else BlinkValue(0,0);                                                                                           //      Except if temperature monitor is off.
 
2133
                        swStartup = STARTDELAY_LONG;
 
2134
                }
 
2135
 
 
2136
        //      LONG CONFIRMATION: RESET MAX TEMPERATURE
 
2137
 
 
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.
 
2144
                }
 
2145
 
 
2146
        //      SHORT CONFIRMATION: SET MAX TEMPERATURE
 
2147
 
 
2148
                if (swCOUNT == 1) {
 
2149
 
 
2150
                        if (CheckStatus()) BlinkValue(0,0);                                                                     //      Levels not normal, abort.
 
2151
                        else {
 
2152
        
 
2153
        //      LEVELS NORMAL: START SET MAX TEMPERATURE
 
2154
 
 
2155
                                sGENERICSETTINGS |= (1 << gsTempMonitor);                                               //      Automatically enable temp monitoring.
 
2156
                                BlinkConfirm();
 
2157
                                ClearSwitch();
 
2158
                                Delay(DELAY_MEDIUM);
 
2159
                                PORTB = MAX;                                                                                                    //      Turn on light full blast.
 
2160
                                uint8_t TemperatureOld = Temperature + 1;                                               //      For storing previous temperature.
 
2161
 
 
2162
                                while (1) {
 
2163
                                        if (Temperature > TemperatureOld) {                                                     //      Temperature rising one degree-ish unit.
 
2164
                                                if (++CritTempTicks >= SEC/2) {
 
2165
                                                        CritTempTicks = 0;
 
2166
                                                        LED_off();
 
2167
                                                        sMAXTEMP = Temperature;
 
2168
                                                        TemperatureOld = Temperature;
 
2169
                                                        eeWrite();
 
2170
                                                        Delay(DELAY_FLASH);
 
2171
                                                        PORTB = MAX;                                                                            //      Turn on light full blast.
 
2172
                                                }
 
2173
                                        }
 
2174
                                        else {
 
2175
                                                CritTempTicks = 0;
 
2176
                                        }
 
2177
                                }
 
2178
                        }
 
2179
                }
 
2180
        }
 
2181
 
 
2182
// ------------------------- *CALIBRATE* VOLTAGE ---------------------------
 
2183
 
 
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);
 
2188
 
 
2189
                sINTREFVOLT = (uint16_t)(iIntRefVolt / 100);
 
2190
                if (iIntRefVolt % 100 >= 50) sINTREFVOLT++;
 
2191
 
 
2192
                BlinkConfirm();
 
2193
                WriteAndResetVoltStatus();                                                                                              //      Save new settings and clear low voltage.
 
2194
        }
 
2195
 
 
2196
// ------------------------ VOLTAGE CALIBRATE ------------------------------
 
2197
 
 
2198
        void VoltCalib() {
 
2199
 
 
2200
                #ifdef OFFSWITCH
 
2201
                        OswDelay();
 
2202
                        swVALUE = swCOUNT;
 
2203
                #else
 
2204
                        swVALUE = EswGetValue(3);
 
2205
                #endif
 
2206
 
 
2207
        //      NO PRESS: READOUT INTERNAL REFERENCE VOLTAGE
 
2208
 
 
2209
                if (swVALUE == NO_PRESS) {
 
2210
                        Delay(DELAY_MEDIUM);
 
2211
                        BlinkNumValue(sINTREFVOLT,5);
 
2212
                        BlinkError();
 
2213
                        swStartup = STARTDELAY_LONG;
 
2214
                }
 
2215
 
 
2216
        //      LONG PRESS: RESET VOLT OFFSET TO DEFAULT
 
2217
 
 
2218
                else {
 
2219
                        if (swVALUE == LONG_PRESS) {
 
2220
                                sINTREFVOLT = INTREFVOLT;
 
2221
                                BlinkConfirm();
 
2222
                                WriteAndResetVoltStatus();                                                                              //      Save new settings and clear low voltage.
 
2223
                        }
 
2224
 
 
2225
        //      ESWITCH: CHECK IF IN RANGE
 
2226
 
 
2227
                        #ifdef DUALSWITCH
 
2228
 
 
2229
                                else {
 
2230
                                        swVALUE -= 1000;
 
2231
                                        if (swVALUE < 200 || swVALUE > 900) BlinkError();                               //      Minimum value 2V, maximum value 9V.
 
2232
 
 
2233
        //      CONFIRM VALUE: CALCULATE AND SAVE NEW *CALIBRATED* INTERNAL REFERENCE VOLTAGE
 
2234
 
 
2235
                                        else {
 
2236
                                                BlinkNumValue(swVALUE,3);
 
2237
                                                if (SwConfirm()) CalibrateVoltage();
 
2238
                                        }
 
2239
                                }
 
2240
 
 
2241
                        #endif
 
2242
 
 
2243
        //      OFFSWITCH: FIRST DIGIT
 
2244
 
 
2245
                        #ifdef OFFSWITCH
 
2246
 
 
2247
                                if (swCOUNT <= 9) {
 
2248
                                        swVALUE = swCOUNT * 100;
 
2249
                                        swCOUNT = 0;
 
2250
                                        swSETUP += SECOND_DIGIT;
 
2251
                                        FlashReadout();
 
2252
                                        OswDelay();
 
2253
                                        BlinkError();
 
2254
                                }
 
2255
                                else BlinkError();
 
2256
 
 
2257
                        #endif
 
2258
 
 
2259
                }
 
2260
                ClearSwitch();
 
2261
        }
 
2262
 
 
2263
        //      OFFSWITCH: FOLLOWING DIGITS AND CONFIRMATION
 
2264
 
 
2265
        #ifdef OFFSWITCH
 
2266
 
 
2267
        void VoltCalib_OswPart2() {
 
2268
 
 
2269
        //      PRESS VALUE: SECOND DIGIT:
 
2270
 
 
2271
                if (swSETUP == sVOLTCALIB+SECOND_DIGIT) {
 
2272
                        OswDelay();
 
2273
                        if (swCOUNT == NO_PRESS) BlinkError();
 
2274
                        else {
 
2275
                                if (swCOUNT <= 9 || swCOUNT == LONG_PRESS) {
 
2276
                                        if (swCOUNT == LONG_PRESS) swCOUNT = 0;
 
2277
                                        swVALUE += swCOUNT*10;
 
2278
                                        swCOUNT = 0;
 
2279
                                        swSETUP = sVOLTCALIB+THIRD_DIGIT;
 
2280
                                        FlashReadout();
 
2281
                                        OswDelay();
 
2282
                                        BlinkError();
 
2283
                                }
 
2284
                                else BlinkError();
 
2285
                        }
 
2286
                        ClearSwitch();
 
2287
                }
 
2288
 
 
2289
        //      PRESS VALUE: THIRD DIGIT:
 
2290
 
 
2291
                if (swSETUP == sVOLTCALIB+THIRD_DIGIT) {
 
2292
                        OswDelay();
 
2293
                        if (swCOUNT == NO_PRESS) BlinkError();
 
2294
                        else {
 
2295
                                if (swCOUNT <= 9 || swCOUNT == LONG_PRESS) {
 
2296
                                        if (swCOUNT == LONG_PRESS) swCOUNT = 0;
 
2297
                                        swVALUE += swCOUNT;
 
2298
                                        swCOUNT = 0;
 
2299
 
 
2300
        //      PRESS VALUE: CHECK IF IN RANGE
 
2301
 
 
2302
                                        if (swVALUE < 200 || swVALUE > 900) BlinkError();                               //      Minimum value 2V, maximum value 9V.
 
2303
                                        else {
 
2304
                                                BlinkNumValue(swVALUE,3);
 
2305
                                                swSETUP = sVOLTCALIB+CONFIRMATION;
 
2306
                                                SwConfirm();
 
2307
                                        }
 
2308
                                }
 
2309
                                else BlinkError();
 
2310
                        }
 
2311
                        ClearSwitch();
 
2312
                }
 
2313
 
 
2314
        //      CONFIRM VALUE: CALCULATE AND SAVE NEW *CALIBRATED* INTERNAL REFERENCE VOLTAGE
 
2315
 
 
2316
                if (swSETUP == sVOLTCALIB+CONFIRMATION) CalibrateVoltage();
 
2317
        }
 
2318
 
 
2319
        #endif
 
2320
 
 
2321
// ------------------------ SET TEMPERATURE PROFILE ------------------------
 
2322
 
 
2323
        void TempProfile() {
 
2324
 
 
2325
                #ifdef OFFSWITCH
 
2326
                        SwConfirm();
 
2327
                #else
 
2328
                        uint8_t swCOUNT = SwConfirm();
 
2329
                #endif
 
2330
 
 
2331
                Delay(DELAY_LONG);
 
2332
 
 
2333
        //      NO CONFIRMATION: READOUT TEMPERATURE PROFILE
 
2334
 
 
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;
 
2339
                        BlinkError();
 
2340
                }
 
2341
 
 
2342
        //      LONG CONFIRMATION: RESET TEMPERATURE PROFILE
 
2343
 
 
2344
                if (swCOUNT == LONG_PRESS) {
 
2345
                        sTEMPPROFILE = TEMPPROFILE;
 
2346
                        BlinkConfirm();
 
2347
                        eeWrite();
 
2348
                }
 
2349
 
 
2350
        //      SHORT CONFIRMATION: TEMPERATURE PROFILING
 
2351
 
 
2352
                if (swCOUNT == 1) {
 
2353
 
 
2354
                        if (CheckStatus()) BlinkValue(0,0);                                                                     //      Levels not normal, abort.
 
2355
                        else {
 
2356
 
 
2357
        //      LEVELS NORMAL: START TEMPERATURE PROFILING
 
2358
 
 
2359
                                BlinkConfirm();
 
2360
                                Delay(DELAY_LONG);
 
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;
 
2366
 
 
2367
                                sMODE = BOOSTMODE;
 
2368
                                LightMode();
 
2369
                                while (iTempReadings < 5) {                                                                             //      5 readings at target before turning LED off.
 
2370
                                        if (Temperature >= iTemp) {
 
2371
                                                iTempReadings++;
 
2372
                                                iWdtTicks = WdtTicks;
 
2373
                                                while (iWdtTicks == WdtTicks);
 
2374
                                        }
 
2375
                                        else {
 
2376
                                                iTempReadings = 0;
 
2377
                                        }
 
2378
                                }
 
2379
 
 
2380
                                iTempReadings = 0;
 
2381
                                LED_off();
 
2382
                                ResetTimer();
 
2383
 
 
2384
                                while (iTempReadings < 5) {                                                                             //      5 readings at target before stopping.
 
2385
                                        if (Temperature < iTemp) {
 
2386
                                                iTempReadings++;
 
2387
                                                iWdtTicks = WdtTicks;
 
2388
                                                while (iWdtTicks == WdtTicks);
 
2389
                                        }
 
2390
                                        else {
 
2391
                                                if (Temperature > iMaxTemp) {
 
2392
                                                        iMaxTemp = Temperature;                                                         //      If temperature rises after LED off.
 
2393
                                                        FlashReadout();
 
2394
                                                }
 
2395
                                                iTempReadings = 0;
 
2396
                                        }
 
2397
                                }
 
2398
 
 
2399
                                sTEMPPROFILE = WdtSecs + 1;
 
2400
                                BlinkNumValue(sTEMPPROFILE,1);
 
2401
                                Delay(DELAY_LONG);
 
2402
                                BlinkNumValue(iMaxTemp,1);
 
2403
                                sGENERICSETTINGS |= (1 << gsTempMonitor);                                               //      Automatically enable temp monitoring.
 
2404
                                sMODE = iModeHold;
 
2405
                                eeWrite();                                                                                                              //      Write setting change to EEPROM.
 
2406
                        }
 
2407
                }
 
2408
        }
 
2409
 
 
2410
// ------------------------ RESET TO DEFAULT -------------------------------
 
2411
 
 
2412
        void Reset2Def() {
 
2413
 
 
2414
                #ifdef OFFSWITCH
 
2415
 
 
2416
                        if (swSETUP == sRESET2DEF) {
 
2417
                                swSETUP = RESET_CONFIRM_1;
 
2418
                                swCOUNT = 0;
 
2419
                                SwConfirm();
 
2420
                                ClearSwitch();
 
2421
                        }
 
2422
 
 
2423
                #else
 
2424
 
 
2425
                        uint8_t iEswConfirm = SwConfirm();
 
2426
 
 
2427
                        if (iEswConfirm) {
 
2428
                                ResetTimer();
 
2429
                                PWM_on(0);
 
2430
                                while (!ESWITCH && WdtSecs < 4) {                                                               //      Confirmation flash. Pressing here will reset.
 
2431
                                        if (WdtSecs % 2) PWM = LVL_READOUT+7;
 
2432
                                        else PWM = LVL_READOUTLOW;
 
2433
                                        Delay(DELAY_FLASH);
 
2434
                                        PWM = 0;
 
2435
                                        Delay(DELAY_FLASH);
 
2436
                                }
 
2437
                                PWM_off();
 
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.
 
2442
                                        BlinkConfirm();
 
2443
                                        if (iEswConfirm == 255) BlinkConfirm();                                         //      Two confirmation blinks for reset, three for full reset.
 
2444
                                        ResetToDefault(iEswConfirm);                                                            //      Passes on short or long confirmation press.
 
2445
                                }
 
2446
                        }
 
2447
 
 
2448
                #endif
 
2449
        }
 
2450
 
 
2451
        //      OFFSWITCH CONFIRMATION:
 
2452
 
 
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;
 
2457
                        swCOUNT = 0;
 
2458
                        ResetTimer();
 
2459
                        PWM_on(0);
 
2460
                        while (WdtSecs < 4) {                                                                                           //      Confirmation flash. Pressing here will reset.
 
2461
                                if (WdtSecs % 2) PWM = LVL_READOUT+7;
 
2462
                                else PWM = LVL_READOUTLOW;
 
2463
                                Delay(DELAY_FLASH);
 
2464
                                PWM = 0;
 
2465
                                Delay(DELAY_FLASH);
 
2466
                        }
 
2467
                        ClearSwitch();
 
2468
                }
 
2469
 
 
2470
                if (swSETUP == RESET_CONFIRM_SHORT && swCOUNT) {
 
2471
                        BlinkConfirm();
 
2472
                        BlinkConfirm();
 
2473
                        ResetToDefault(1);
 
2474
                }
 
2475
 
 
2476
                if (swSETUP == RESET_CONFIRM_LONG && swCOUNT) {
 
2477
                        BlinkConfirm();
 
2478
                        BlinkConfirm();
 
2479
                        BlinkConfirm();
 
2480
                        ResetToDefault(0);
 
2481
                }
 
2482
        }
 
2483
 
 
2484
// ======================== *MAIN* *STARTUP* ===============================
 
2485
 
 
2486
        eeRead();                                                                                                                                       //      Read in all settings.
 
2487
 
 
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;
 
2491
 
 
2492
        DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3) | (1 << PB5);          //      Set PB0 to PB3 and PB5 as output.
 
2493
        PORTB = 0;
 
2494
 
 
2495
        if (bVOLTSTATUS > 4) bVOLTSTATUS = 0;                                                                           //      Check Voltage status for decay.
 
2496
        if (bTEMPSTATUS > 2) bTEMPSTATUS = 0;                                                                           //      Check Temperature status for decay.
 
2497
 
 
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.
 
2501
 
 
2502
        ADC_read(VOLT);                                                                                                                         //      First read to get E-switch status.
 
2503
        WdtStartup = 1;
 
2504
        if (offTime == 0) ColdStart();
 
2505
 
 
2506
// ------------------------ *ESWITCH* *SETUP* ------------------------------    //      *ESETUP*
 
2507
 
 
2508
        #ifdef DUALSWITCH
 
2509
 
 
2510
        if (ESWITCH) {
 
2511
 
 
2512
                offTime = 0;                                                                                                                    //      Clear off time cap readings.
 
2513
                ColdStart();
 
2514
 
 
2515
                while (ESWITCH) {                                                                                                               //      Switch hold blink to number of functions before timing out.
 
2516
 
 
2517
                        if (SwitchTicks == FUNCTIONBLINKTIME) {
 
2518
                                swStartup++;                                                                                                    //      Increase menu selection.
 
2519
 
 
2520
                                if ((SAFETYLOCK || sUI == UI_NOOB) && swSETUP == 10) swStartup = sRESET2DEF+1;
 
2521
                                if (swStartup < (sRESET2DEF/10)+1) {
 
2522
                                        FlashReadout();
 
2523
                                        swSETUP = swStartup * 10;
 
2524
                                        if (swSETUP == sCALIBRATIONS) {                                                         //      Small delay before proceeding to reset2default.
 
2525
                                                while (ESWITCH && SwitchTicks < FUNCTIONBLINKTIME + (SEC/2));
 
2526
                                        }
 
2527
                                }
 
2528
                                else swSETUP = 0;
 
2529
                                SwitchTicks = 0;
 
2530
                        }
 
2531
                }
 
2532
                while (ESWITCH);
 
2533
                ClearSwitch();
 
2534
                swStartup = STARTDELAY_MEDIUM;
 
2535
        }
 
2536
 
 
2537
        #endif
 
2538
 
 
2539
// ------------------------ *OFFSWITCH* *SETUP* ----------------------------    //      *OSETUP*
 
2540
 
 
2541
        #ifdef OFFSWITCH
 
2542
 
 
2543
        //      LONG PRESS
 
2544
 
 
2545
        if (offTime == 1) {
 
2546
                if (swSETUP > 1) swCOUNT = LONG_PRESS;
 
2547
                swRAMP = 0;
 
2548
        }
 
2549
 
 
2550
        //      SETUP PRESS COUNT:
 
2551
 
 
2552
        if (offTime == 2 || (offTime == 1 && swSETUP == 1)) {
 
2553
                if (swSETUP) {
 
2554
                        if (swCOUNT < 9) {
 
2555
                                swCOUNT++;
 
2556
                                Delay(DELAY_SETUPPRESS);
 
2557
                                if (swSETUP ==1) swSETUP = 2;
 
2558
                        }
 
2559
 
 
2560
        //      SETUP ACCESS: THREE TO EIGHT PRESSES AFTER COLD START
 
2561
 
 
2562
                        if (swSETUP == 2) {
 
2563
                                if (sUI == UI_NOOB || (sUI != UI_NOOB && swCOUNT == 9)) {
 
2564
                                        if (swCOUNT == 9) ToggleNoob();
 
2565
                                        else {
 
2566
                                                swCOUNT = 0;
 
2567
                                                swSETUP = 0;
 
2568
                                        }
 
2569
                                }
 
2570
                                else {
 
2571
                                        if (swCOUNT >= 3 && swCOUNT <=8) {
 
2572
                                                BlinkConfirm();
 
2573
                                                swSETUP = (swCOUNT-2)*10;
 
2574
                                                swCOUNT = 0;
 
2575
                                        }
 
2576
                                }
 
2577
                        }
 
2578
                }
 
2579
        }
 
2580
 
 
2581
        if (swSETUP >= 10) {
 
2582
                offTime = 0;
 
2583
                swStartup = STARTDELAY_MEDIUM;                                                                                  //      Standard startup delay after setup routine done.
 
2584
        }
 
2585
 
 
2586
        #endif
 
2587
 
 
2588
// ------------------------ *SETUP* MENU -----------------------------------
 
2589
 
 
2590
        if (swSETUP == sSELECTUI) SelectUI();
 
2591
        if (swSETUP == sSPECIALMODES) SpecialModes();
 
2592
        if (swSETUP == sMODESETTINGS || swSETUP == sMONITORING || swSETUP == sCALIBRATIONS) Setup();
 
2593
        if (swSETUP == sSOS) ToggleSOS();
 
2594
 
 
2595
        if (swSETUP == sSETMODECNT) SetModeCount();
 
2596
        if (swSETUP == sSETMODEMEM) SetModeMemory();
 
2597
        if (swSETUP == sSETBOOSTIME) SetBoostTimer();
 
2598
 
 
2599
        if (swSETUP == sSETMAXTEMP) SetMaxTemp();
 
2600
        if (swSETUP == sTEMPPROFILING) TempProfile();
 
2601
        if (swSETUP == sSETLOWVMON || swSETUP == sSETCRITVMON || swSETUP == sTEMPCALIB) VoltMonTempCalib();
 
2602
 
 
2603
        if (swSETUP == sVOLTCALIB) VoltCalib();
 
2604
        if (swSETUP == sRESET2DEF) Reset2Def();
 
2605
 
 
2606
        #ifdef OFFSWITCH
 
2607
                if (swSETUP == sSETLOWVMON+SECOND_DIGIT || swSETUP == sSETCRITVMON+SECOND_DIGIT || swSETUP == sTEMPCALIB+SECOND_DIGIT) VoltMonTempCalib_OswDigit2();
 
2608
                VoltMonTempCalibSet();
 
2609
                VoltCalib_OswPart2();
 
2610
                Reset2Def_OswConfirm();
 
2611
        #endif
 
2612
 
 
2613
// -------------------- END OF SETUP *FUNCTIONS* ---------------------------
 
2614
 
 
2615
        while (ESWITCH);                                                                                                                        //      If E-switch still pressed after startup, halt to avoid going directly to boost.
 
2616
        ClearSwitch();
 
2617
 
 
2618
// ------------------------ *SAFETY* LOCK CHECK ----------------------------
 
2619
 
 
2620
        if (SAFETYLOCK) {                                                                                                                       //      If safety lock is engaged:
 
2621
                uint8_t SafetyLockblinked = 0;
 
2622
                while (1) {
 
2623
 
 
2624
                        #ifdef DUALSWITCH
 
2625
                                if (ESWITCH) {
 
2626
                                        ResetTimer();
 
2627
                                        SafetyLockblinked = 0;
 
2628
                                        while (ESWITCH) {}
 
2629
                                }
 
2630
                        #endif
 
2631
 
 
2632
                        if (!(WdtSecs % 4)) {
 
2633
                                if (!SafetyLockblinked) {
 
2634
                                        PWM_on(LVL_READOUT);
 
2635
                                        Delay(DELAY_FLASH);
 
2636
                                        PWM_off();
 
2637
                                        SafetyLockblinked = 1;
 
2638
                                        sleep_mode();
 
2639
                                }
 
2640
                        }
 
2641
                        else {
 
2642
                                SafetyLockblinked = 0;
 
2643
                        }
 
2644
                }
 
2645
        }
 
2646
 
 
2647
// ======================== LIGHT *STARTUP* ================================
 
2648
 
 
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);
 
2653
 
 
2654
        ResetTimer();
 
2655
 
 
2656
// ------------------------ COLD STARTUP ----------------------------------
 
2657
 
 
2658
        if (offTime == 0) {
 
2659
                if (sUI != SOS && swStartup < STARTDELAY_LONG_KEEPMEM) {                                //      SOS and mode level readout always keep current mode despite memory setting.
 
2660
                        #ifdef OFFSWITCH
 
2661
                                bMODE = sMODE;                                                                                                  //      Copy current mode to keep mode in mode level readout when memory disabled.
 
2662
                        #endif
 
2663
                        if (sMODEMEM) {
 
2664
                                if (sMODE == BOOSTMODE && sMODEMEM == 1) {                                              //      Boost was last mode but boost memory disabled.
 
2665
                                        if (sUI == 3) sMODE = RAMPMODE1;
 
2666
                                        else sMODE = sMODEHOLD;
 
2667
                                        eeWrite();
 
2668
                                }
 
2669
                        }
 
2670
                        else {
 
2671
                                if (bPROGSTATUS != 6) ResetMode();                                                              //      Keep mode if programming mode selected and mode memory is off.
 
2672
                        }
 
2673
                }
 
2674
        }
 
2675
 
 
2676
// ==================== ESWITCH *OFFTIME* CAP FUNCTIONS ====================
 
2677
 
 
2678
        #ifdef DUALSWITCH
 
2679
 
 
2680
                if (sUI <= 3 || (sUI >= SOS && sUI <= STROBE) || sUI == UI_NOOB) {
 
2681
 
 
2682
        //      SHORT OFF PRESS : UI 1/2/STROBE NEXT MODE, UI 3 ENABLE LEVEL PROGRAMMING.
 
2683
 
 
2684
                        if (offTime == 2) {
 
2685
                                if (sUI == 3) bPROGSTATUS = 2;
 
2686
                                else {
 
2687
                                        NextMode();
 
2688
                                        eeWrite();
 
2689
                                }
 
2690
                        }
 
2691
 
 
2692
        //      LONG OFF PRESS : UI 1/2/STROBE PREVIOUS MODE, UI 3 EXIT LEVEL PROGRAMMING.
 
2693
 
 
2694
                        if (offTime == 1) {
 
2695
                                if (sUI == 3) bPROGSTATUS = 0;
 
2696
                                else {
 
2697
                                        PrevMode();
 
2698
                                        eeWrite();
 
2699
                                }
 
2700
                        }
 
2701
                }
 
2702
 
 
2703
        #endif
 
2704
 
 
2705
// ==================== OSWITCH *OFFTIME* CAP FUNCTIONS ====================
 
2706
 
 
2707
        #ifdef OFFSWITCH
 
2708
 
 
2709
                if ((sUI <= 3 && !bPROGSTATUS) || sUI == SOS || sUI == UI_NOOB) {
 
2710
 
 
2711
        //      SHORT OFF PRESS : UI 1/2/SOS NEXT MODE, UI 3 ENABLE LEVEL PROGRAMMING.
 
2712
 
 
2713
                        if (offTime == 2) {
 
2714
                                if (sUI == 3) {
 
2715
                                        if (sMODE == RAMPMODE1) sMODE = BOOSTMODE;                                      //      Activate boost.
 
2716
                                        else sMODE = RAMPMODE1;                                                                         //      Deactivate boost.
 
2717
                                        eeWrite();
 
2718
                                }
 
2719
                                else {
 
2720
                                        if (sUI == 2 && sMODE == BOOSTMODE) sMODE = sMODEHOLD;
 
2721
                                        else NextMode();
 
2722
                                        eeWrite();
 
2723
                                }
 
2724
                                offTime = 0;
 
2725
                        }
 
2726
 
 
2727
        //      LONG OFF PRESS : UI 1/2/SOS PREVIOUS MODE.
 
2728
 
 
2729
                        if (offTime == 1) {
 
2730
                                if (sUI == 2) {
 
2731
                                        if (sMODE != BOOSTMODE) sMODEHOLD = sMODE;                                      //      Store the mode in use before boost.
 
2732
                                        sMODE = BOOSTMODE;                                                                                      //      Activate boost.
 
2733
                                        eeWrite();
 
2734
                                }
 
2735
                                else {
 
2736
                                        if (sUI == 3) {
 
2737
                                                bPROGSTATUS = 2;
 
2738
                                        }
 
2739
                                        else {
 
2740
                                                PrevMode();
 
2741
                                                eeWrite();
 
2742
                                        }
 
2743
                                }
 
2744
                                offTime = 0;
 
2745
                        }
 
2746
                }
 
2747
 
 
2748
// ------------------------ MODE PROGRAMMING -------------------------------
 
2749
 
 
2750
                if (sUI == 4 || (sUI <= 3 && bPROGSTATUS)) {
 
2751
                        if (offTime == 2) {
 
2752
                                if (!bPROGSTATUS || bPROGSTATUS == 4 || swRAMP || (sUI <= 3 && bPROGSTATUS != 5)) {
 
2753
                                        swRAMP++;
 
2754
                                        eswLevel = 0;
 
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;
 
2758
                                }
 
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.
 
2762
                                }
 
2763
                        }
 
2764
                        if (offTime == 1) {
 
2765
                                if (sUI <= 2) {                                                                                                 //      Long presses in UI 1 & 2 changes mode.
 
2766
                                        NextMode();
 
2767
                                        eeWrite();
 
2768
                                        swPressed = 0;
 
2769
                                        bPROGSTATUS = 2;
 
2770
                                }
 
2771
                                else bPROGSTATUS = 0;                                                                                   //      If was in programming mode, abort.
 
2772
                        }
 
2773
                }
 
2774
 
 
2775
// ------------------------ *BEACON* & *STROBE* ----------------------------
 
2776
 
 
2777
                if (sUI == BEACON || sUI == STROBE) {
 
2778
                        if (offTime == 2) {
 
2779
                                swRAMP++;
 
2780
                                uint8_t iRamp = swRAMP;
 
2781
                                Delay(DELAY_SETUPPRESS);
 
2782
                                if (iRamp == 1) {
 
2783
                                        if (sSTROBESPEED++ == 13) sSTROBESPEED = 0;
 
2784
                                }
 
2785
                                if (iRamp >= 2) {
 
2786
                                        if (sSTROBESPEED-- == 0) sSTROBESPEED = 13;
 
2787
                                }
 
2788
                                eeWrite();
 
2789
                        }
 
2790
                        if (offTime == 1) {
 
2791
                                NextMode();
 
2792
                                eeWrite();
 
2793
                        }
 
2794
                }
 
2795
 
 
2796
// -------------------- END OF *OFFTIME* CAP FUNCTIONS ---------------------
 
2797
 
 
2798
        #endif
 
2799
 
 
2800
// ======================== *INITIALIZE* LIGHT =============================
 
2801
 
 
2802
        if (sMODE == BOOSTMODE) BOOSTSTATUS = 3;
 
2803
        if (bPROGSTATUS == 6) bPROGSTATUS = 2;
 
2804
 
 
2805
        #ifdef DUALSWITCH
 
2806
 
 
2807
                if (sUI == 4) bPROGSTATUS = 0;
 
2808
 
 
2809
                if (bPROGSTATUS) {
 
2810
                        Delay(DELAY_BLINK);
 
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.
 
2814
                }
 
2815
        #endif
 
2816
 
 
2817
        #ifdef OFFSWITCH
 
2818
                if (bPROGSTATUS && bPROGSTATUS < 4 && sUI != 4 && !swPressed) {
 
2819
                        Delay(DELAY_BLINK);
 
2820
                        Flash(5,FLASH_ONOROFF,DELAY_FLASH);
 
2821
                        ProgModeTicks = 0;                                                                                                      //      Reset programming mode timer on every startup in mode programming.
 
2822
                }
 
2823
        #endif
 
2824
 
 
2825
        if (bTEMPSTATUS) CritTempTicks = (sTEMPPROFILE * SEC) - 2*SEC;                          //      If TEMP status is critical force flash after two seconds.
 
2826
 
 
2827
        LightMode();
 
2828
        WdtStartup = 2;                                                                                                                         //      Enables voltage and temperature monitoring.
 
2829
        StatusAfterSwitch();
 
2830
 
 
2831
// ------------------------ *STROBE* MODES ---------------------------------
 
2832
 
 
2833
        //      *SOS* STROBE:
 
2834
 
 
2835
        while (sUI == SOS) {
 
2836
                Flash(3,FLASH_LIGHTMODE,14);
 
2837
                Delay(50);
 
2838
                Flash(3,FLASH_LIGHTMODE,50);
 
2839
                Flash(3,FLASH_LIGHTMODE,14);
 
2840
                Delay(SEC*2);
 
2841
        }
 
2842
 
 
2843
        //      *BEACON* & STROBE:
 
2844
 
 
2845
        while (sUI == BEACON || sUI == STROBE) {
 
2846
                if (StatusAlert) {
 
2847
                        if (StatusAlert == 1) StepDown(0,0);
 
2848
                        else StepDown(0,1);
 
2849
                        ResetVoltTimers();
 
2850
                        ResetTempTimers();
 
2851
                        StatusAlert = 0;
 
2852
                }
 
2853
 
 
2854
                if (sUI == BEACON) {
 
2855
                        BlinkOn();
 
2856
                        Delay(DELAY_SHORT);
 
2857
                        BlinkOn();
 
2858
                        Delay(StrobeSpeeds[sSTROBESPEED] * 2);
 
2859
                }
 
2860
 
 
2861
                if (sUI == STROBE) {
 
2862
                        Flash(1,FLASH_LIGHTMODE,StrobeSpeeds[sSTROBESPEED]);
 
2863
                }
 
2864
        }
 
2865
 
 
2866
// ************************ *MAIN* LOOP ************************************
 
2867
 
 
2868
        while (1) {                                                                                                                                     //      *WHILE*
 
2869
 
 
2870
// ======================== *ESWITCH* HANDLING =============================
 
2871
        
 
2872
        #ifdef DUALSWITCH
 
2873
 
 
2874
                if (ESWITCH) StatusAfterSwitch();
 
2875
 
 
2876
// -------------------- UI 1 SHORT PRESS : NEXT MODE -----------------------
 
2877
 
 
2878
                if ((sUI == 1 || sUI == UI_NOOB) && !bPROGSTATUS) {
 
2879
 
 
2880
                        if (swPressed && !ESWITCH && !swLongPressed) {                                          //      Short press with E-switch.
 
2881
                                NextMode();
 
2882
                                LightMode();
 
2883
                        }
 
2884
 
 
2885
// -------------------- UI 1 LONG PRESS : PREVIOUS MODE --------------------
 
2886
 
 
2887
                        if (ESWITCH) {                                                                                                          //      Complicated routine that allows rap around to boost only from lowest mode.
 
2888
                                if (swLongPressed == 1) {
 
2889
                                        PrevMode();
 
2890
                                        LightMode();
 
2891
                                        swLongPressed = 2;
 
2892
                                }
 
2893
                                if (swLongPressed == 3) {
 
2894
                                        if ((sMODEDIRL2H && sMODE) || (!sMODEDIRL2H && sMODE < BOOSTMODE)) {
 
2895
                                                PrevMode();
 
2896
                                                LightMode();
 
2897
                                                swLongPressed = 2;
 
2898
                                                SwitchTicks = LONGPRESSTIME+1;
 
2899
                                        }
 
2900
                                }
 
2901
                        }
 
2902
                }
 
2903
 
 
2904
// -------------------- UI 2 & 3 : *BOOST* ---------------------------------
 
2905
/*
 
2906
                BOOSTSTATUS:
 
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.
 
2913
*/
 
2914
 
 
2915
                if (((sUI == 2 && sMODECOUNT) || sUI == 3) && !bPROGSTATUS) {
 
2916
 
 
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.
 
2920
                                sMODE = BOOSTMODE;
 
2921
                                LightMode();
 
2922
                        }
 
2923
 
 
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.
 
2926
                                LED_off();
 
2927
                                Delay(DELAY_FLASH);
 
2928
                                LightMode();                                                                                                    //      Short blink to indicate free running press time met.
 
2929
                        }
 
2930
 
 
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.
 
2934
                                LightMode();
 
2935
                        }
 
2936
 
 
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).
 
2939
                                LightMode();
 
2940
                        }
 
2941
 
 
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.
 
2945
                                LightMode();
 
2946
                        }
 
2947
                }
 
2948
 
 
2949
        #endif
 
2950
 
 
2951
//      ------------------- UI 4 OR PROGRAM MODE -------------------------------
 
2952
 
 
2953
                if (sUI == 4 || bPROGSTATUS) {
 
2954
 
 
2955
                        uint16_t *pMode = &Modes[sMODE];                                                                        //      Pointer for ramping.
 
2956
 
 
2957
                //      *ADJUST*
 
2958
 
 
2959
                        if (ESWITCH && SwitchTicks >= 40) {
 
2960
 
 
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.
 
2964
 
 
2965
                                uint8_t iMultiplier = 50;
 
2966
 
 
2967
                                if (swPressed == 1) {
 
2968
                                        #if !defined(PB5_IO) || defined(F8)
 
2969
                                                if (*pMode >= RAMPMAX) {
 
2970
                                                        *pMode = MAX * 256;
 
2971
                                                }
 
2972
                                                else {
 
2973
                                                        *pMode += ((*pMode + iMultiplier) / iMultiplier);
 
2974
                                                        if (*pMode > RAMPMAX) *pMode = RAMPMAX;
 
2975
                                                }                                                       
 
2976
                                        #else
 
2977
                                                *pMode += ((*pMode + iMultiplier) / iMultiplier);
 
2978
                                                if (*pMode > RAMPMAX) *pMode = RAMPMAX;
 
2979
                                        #endif
 
2980
                                }
 
2981
                                else {
 
2982
                                        if (*pMode) *pMode -= ((*pMode + iMultiplier) / iMultiplier);
 
2983
                                        if (*pMode > RAMPMAX) *pMode = RAMPMAX;
 
2984
                                }
 
2985
 
 
2986
                                if (*pMode < 12) {                                                                                              //      Slower brightness adjusting for lower values.
 
2987
                                        SwitchTicks = 8;
 
2988
                                }
 
2989
                                else {
 
2990
                                        if (*pMode < 22) {
 
2991
                                                SwitchTicks = 35;
 
2992
                                        }
 
2993
                                        else {
 
2994
                                                SwitchTicks = 38;
 
2995
                                        }
 
2996
                                }
 
2997
 
 
2998
                        //      Level limiters:
 
2999
 
 
3000
                                uint8_t iRampMax = 0;
 
3001
 
 
3002
                                if (CheckStatus() == 1 && *pMode > LOWVOLTMAX) {
 
3003
                                        *pMode = LOWVOLTMAX;
 
3004
                                        iRampMax = 1;
 
3005
                                }
 
3006
 
 
3007
                                if (CheckStatus() == 2 && *pMode > CRITICALMAX) {
 
3008
                                        *pMode = CRITICALMAX;
 
3009
                                        iRampMax = 1;
 
3010
                                }
 
3011
 
 
3012
                                #ifdef OFFSWITCH
 
3013
                                        bMODE = *pMode;                                                                                         //      Store adjusted mode level in no init, saves a lot of eeprom writing.
 
3014
                                #endif
 
3015
 
 
3016
                                if (*pMode >= RAMPMAX || iRampMax) {
 
3017
                                        FlashOff();                                                                                                     //      Short blink off to notify max level reached.
 
3018
                                        LightMode();
 
3019
                                        Delay(DELAY_MEDIUM);
 
3020
                                }
 
3021
                        }
 
3022
 
 
3023
                        if (bPROGSTATUS == 3) {                                                                                         //      PROGSTATUS 3: Level save timer timed out.
 
3024
                                eeWrite();
 
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.
 
3028
                                LightMode();
 
3029
                                if (sUI == 3) Delay(DELAY_SHORT);                                                               //      Small delay to avoid accidental boost if pressed slightly after timeout.
 
3030
                                while (ESWITCH);
 
3031
                                ProgModeTicks = 0;
 
3032
                        }
 
3033
 
 
3034
                        if (bPROGSTATUS == 1) {                                                                                         //      PROGSTATUS 1: Programming mode timer timed out.
 
3035
                                bPROGSTATUS = 0;
 
3036
                                ProgModeTicks = 0;
 
3037
                                if (sUI <= 3) {
 
3038
                                        BlinkOnOffThreshold(0);                                                                         //      UI 1/2/3 blink exit programming mode. UI 3 blinks only if level not adjusted.
 
3039
                                        LightMode();
 
3040
                                        if (sUI <= 2) {
 
3041
                                                Delay(DELAY_SHORT);
 
3042
                                                BlinkOnOffThreshold(0);                                                                 //      UI 1/2 second blink exiting programming mode.
 
3043
                                        }
 
3044
                                        LightMode();
 
3045
                                        Delay(DELAY_SHORT);
 
3046
                                        while (ESWITCH);
 
3047
                                }
 
3048
                        }
 
3049
 
 
3050
                        #ifdef DUALSWITCH
 
3051
                                if (!ESWITCH && bPROGSTATUS == 5) bPROGSTATUS = 4;                              //      PROGSTATUS 4: Switch released, start countdown to EEPROM save.
 
3052
                        #endif
 
3053
 
 
3054
                        LightMode();
 
3055
                }
 
3056
 
 
3057
// -------------------- E-SWITCH PRESS RELEASE -----------------------------
 
3058
 
 
3059
                #ifdef DUALSWITCH
 
3060
 
 
3061
                        if (!ESWITCH && (swPressed || swLongPressed)) {                                         //      E-switch released after press:
 
3062
                                ClearSwitch();
 
3063
                                if ((sUI <= 2 || sUI == UI_NOOB || BOOSTSTATUS==3) && (CheckStatus() < 2) && !bPROGSTATUS) eeWrite();
 
3064
                        }
 
3065
 
 
3066
                #endif
 
3067
 
 
3068
// -------------------- *BOOST MODE TIMEOUT* -------------------------------
 
3069
 
 
3070
                if (!ESWITCH && (BOOSTSTATUS==1 || BOOSTSTATUS==2 )) StepDown(0,0);             //      Boost timed out, or switch released after turning off.
 
3071
 
 
3072
// ======================== *MONITORING* ===================================
 
3073
 
 
3074
// -------------------- *LOW* *VOLTAGE* LEVEL ------------------------------
 
3075
 
 
3076
                if (StatusAlert == ALERT_LOWVOLT) {
 
3077
 
 
3078
                        if (sUI < 3) bPROGSTATUS = 0;                                                                           //      If in programming mode, exit.
 
3079
 
 
3080
                        //      OUTPUT AT OR BELLOW ALLOWED LIMIT:
 
3081
 
 
3082
                        if (BOOSTSTATUS <=2 && (Modes[sMODE]<=LOWVOLTMAX)) bVOLTSTATUS= 2;      //      Set voltage status to low in lowest.
 
3083
 
 
3084
                        StepDown(2,0);
 
3085
 
 
3086
                        StatusAlert = 0;                                                                                                        //      Status alert dealt with, reset.
 
3087
                        ResetVoltTimers();
 
3088
                }
 
3089
 
 
3090
// -------------------- *CRITICAL* VOLTAGE LEVEL ---------------------------
 
3091
 
 
3092
                if (StatusAlert == ALERT_CRITVOLT) {
 
3093
 
 
3094
                        if (sUI < 3) bPROGSTATUS = 0;                                                                           //      If in programming mode, exit.
 
3095
 
 
3096
                        //      NOT BOOST MODE AND OUTPUT ABOVE ALLOWED LIMIT:
 
3097
 
 
3098
 
 
3099
                        if (bVOLTSTATUS < 4 || Modes[sMODE] > CRITICALMAX) {                            //      If first critical warning or output above limit.
 
3100
                                StepDown(2,1);
 
3101
                                bVOLTSTATUS = 4;                                                                                                //      Set voltage status to critical.
 
3102
                        }
 
3103
 
 
3104
                        //      OUTPUT ALREADY AT OR BELLOW ALLOWED LIMIT:
 
3105
 
 
3106
                        else StepDown(0,1);
 
3107
 
 
3108
                        ResetVoltTimers();
 
3109
                        StatusAlert = 0;                                                                                                        //      Status alert dealt with, reset.
 
3110
                }
 
3111
 
 
3112
// -------------------- *TEMPERATURE* MONITORING ---------------------------
 
3113
 
 
3114
                if (StatusAlert >= ALERT_HIGHTEMP) {
 
3115
 
 
3116
                        if (sUI < 3) bPROGSTATUS = 0;                                                                           //      If in programming mode, exit.
 
3117
 
 
3118
                        if (StatusAlert == ALERT_HIGHTEMP) StepDown(3,0);
 
3119
                        else StepDown(3,1);
 
3120
                        ResetTempTimers();
 
3121
                        StatusAlert = 0;                                                                                                        //      Status alert dealt with, reset.
 
3122
                }
 
3123
 
 
3124
// ======================== END MONITORING =================================
 
3125
 
 
3126
                sleep_mode();
 
3127
    }
 
3128
 
 
3129
// ************************ END MAIN LOOP **********************************
 
3130
    return 0;
 
3131
}