~gabe/flashlight-firmware/anduril2

« back to all changes in this revision

Viewing changes to Flintrock/bistro-hd/bistro-HD.c

  • Committer: Selene Scriven
  • Date: 2017-09-12 23:34:36 UTC
  • mto: (188.1.3 trunk)
  • mto: This revision was merged to the branch mainline in revision 331.
  • Revision ID: bzr@toykeeper.net-20170912233436-d3w6nln0ts1subue
Added Flintrock's Bistro-HD 1.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * "Bistro-HD" firmware  
 
3
 * This code runs on a single-channel or dual-channel (or tripple or quad) driver (FET+7135)
 
4
 * with an attiny13/25/45/85 MCU and several options for measuring off time.
 
5
 *
 
6
 * Original version Copyright (C) 2015 Selene Scriven, 
 
7
 * Modified significantly by Texas Ace (triple mode groups) and 
 
8
 * Flintrock (code size, Vcc, OTSM, eswitch, 4-chan, delay-sleep,.. more, see manual) 
 
9
 *
 
10
 * This program is free software: you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation, either version 3 of the License, or
 
13
 * (at your option) any later version.
 
14
 *
 
15
 * This program is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
22
 *
 
23
 *  TA adds many great custom mode groups and nice build scripts
 
24
 *  Flintrock Updates:
 
25
 *    Implements OTSM "off-time sleep mode" to determine click length based on watchdog timer with mcu powered by CAP.
 
26
 *    Adds Vcc inverted voltage read option, with calibration table, allows voltage read of 1S lights without R1/R2 divider hardware.
 
27
 *    Implemented 4th PWM channel. (untested, it could even work!)
 
28
 *    Now supports E-switches.
 
29
 *    Algorithm-generated calibration tables now allow voltage adjustment with one or two configs in fr-calibration.h
 
30
 *    Modified tk-attiny.h to simplify layout definitions and make way for more easily-customizable layouts.     
 
31
 *    Added BODS to voltage shutdown (and E-switch poweroff) to protect low batteries longer (~4uA for supported chips).
 
32
 *    Implements space savings (required for other features):
 
33
 *    ... See Changes.txt for details.
 
34
 *
 
35
 *    see fr-tk-attiny.h for mcu layout.
 
36
 *
 
37
 * FUSES
 
38
 *
 
39
 * #fuses (for attin25/45/85): high: 
 
40
 *            DD => BOD disabled early revision chips may not work with BOD and OTSM, but disabling it risks corruption.
 
41
 *                        DE => BOD set to 1.8V  Non V-version chips are still not specced for this and may corrupt.  late model V chips with this setting is best.
 
42
 *            DF => BOD set to 2.7V  Safe on all chips, but may not work well with OTSM, without huge caps.
 
43
 *
 
44
 *       low  C2, 0ms startup time.  Probably won't work with BODS capable late model chips, but should improve OTSM a little if not using one anyway. 
 
45
 *            D2, 4ms  Testing finds this seems to work well on attiny25 BODS capable chip, datasheet maybe implies 64 is safer (not clear and hardware dependent). 
 
46
              E2  64ms startup.  Will probably consume more power during off clicks and might break click timing.
 
47
 *      
 
48
 *        Ext: 0xff
 
49
 *       Tested with high:DE low:D2, Ext 0xff on non-V attiny25, but it's probably not spec compliant with that chip.
 
50
 *
 
51
 *      For more details on these settings
 
52
 *      http://www.engbedded.com/cgi-bin/fcx.cgi?P_PREV=ATtiny25&P=ATtiny25&M_LOW_0x3F=0x12&M_HIGH_0x07=0x06&M_HIGH_0x20=0x00&B_SPIEN=P&B_SUT0=P&B_CKSEL3=P&B_CKSEL2=P&B_CKSEL0=P&B_BODLEVEL0=P&V_LOW=E2&V_HIGH=DE&V_EXTENDED=FF
 
53
 *
 
54
 *
 
55
 * CALIBRATION
 
56
 *   FR's new method Just adjust parameters in fr-calibration.h
 
57
 *   Now uses something between fully calculated and fully measured method.
 
58
 *   You can make simple adjustments to the calculations to get a good result.
 
59
 *
 
60
 *   To find out what values to use, flash the driver with battcheck.hex
 
61
 *   and hook the light up to each voltage you need a value for.  This is
 
62
 *   much more reliable than attempting to calculate the values from a
 
63
 *   theoretical formula.
 
64
 *
 
65
 *   Same for off-time capacitor values.  Measure, don't guess.
 
66
 *
 
67
 * 
 
68
 */
 
69
 
 
70
 
 
71
/* Latest Changes
 
72
 * Fixed minor startup lag. (hopefully doesn't mess up voltage or temp ADC stabilization).
 
73
 * Fixed an array overwrite, in some cases messed up first boot initialization.
 
74
 *
 
75
 */ 
 
76
 
 
77
#ifndef ATTINY
 
78
/************ Choose your MCU here, or override in Makefile or build script*********/
 
79
// The build script will override choices here
 
80
 
 
81
//  choices are now 13, 25, 45, and 85.  Yes, 45 and 85 are now different
 
82
 
 
83
//#define ATTINY 13
 
84
#define ATTINY 25
 
85
//#define ATTINY 45  // yes these are different now, hopefully only in ways we already know.
 
86
//#define ATTINY 85  //   bust specifically they have a 2 byte stack pointer that OTSM accesses.
 
87
#endif
 
88
 
 
89
#ifndef CONFIG_FILE_H
 
90
/**************Select config file here or in build script*****************/
 
91
 
 
92
 
 
93
///// Use the default CONFIG FILE? /////
 
94
// This one will be maintained with all the latest configs available even if commented out.
 
95
// It should be the template for creating new custom configs.
 
96
#define CONFIG_FILE_H "configs/config_default.h"
 
97
 
 
98
///Or select alternative configuration file, last one wins.///
 
99
#define CONFIG_FILE_H "configs/config_testing-HD.h"
 
100
//#define CONFIG_FILE_H "configs/config_BLFA6_EMU-HD.h"
 
101
//#define CONFIG_FILE_H "configs/config_biscotti-HD.h"
 
102
//#define CONFIG_FILE_H "configs/config_trippledown-HD.h"
 
103
//#define CONFIG_FILE_H "configs/config_classic-HD.h"
 
104
//#define CONFIG_FILE_H "configs/config_TAv1-OTC-HD.h"
 
105
//#define CONFIG_FILE_H "configs/config_dual-switch-TA-HD.h"
 
106
//#define CONFIG_FILE_H "configs/config_4channel-dual-switch-HD.h"
 
107
 
 
108
//Make it a battcheck build? 
 
109
//#define VOLTAGE_CAL
 
110
 
 
111
//Note: the modegroups file is specified in the config file, since they must be compatible.
 
112
#endif
 
113
 
 
114
 
 
115
/**********************************************************************************
 
116
**********************END OF CONFIGURATION*****************************************
 
117
***********************************************************************************/
 
118
 
 
119
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // this is here for actual_level.
 
120
#include <avr/pgmspace.h>
 
121
//#include <avr/io.h>
 
122
#include <avr/interrupt.h>
 
123
#include <avr/eeprom.h>
 
124
#include <avr/sleep.h>
 
125
#include <avr/power.h>
 
126
#include <util/delay_basic.h>
 
127
//#include <string.h>
 
128
 
 
129
#include CONFIG_FILE_H
 
130
 
 
131
void blink_value(uint8_t value); // declare early so we can use it anywhere
 
132
 
 
133
//*************** Defaults, including ones needed before modegroups.h ***********/
 
134
#ifdef NO_LOOP_TOGGLES
 
135
  #undef LOOP_TOGGLES
 
136
#else
 
137
  #define LOOP_TOGGLES  
 
138
#endif
 
139
 
 
140
#ifndef INLINE_STROBE
 
141
  #define INLINE_STROBE  //inline keyword for strobe function.
 
142
#endif
 
143
 
 
144
#if defined(USE_ESWITCH) && (OTSM_PIN != ESWITCH_PIN) && defined(USE_ESWITCH_LOCKOUT_TOGGLE)
 
145
 #define USE_LOCKSWITCH
 
146
#endif
 
147
 
 
148
#ifndef TURBO_STEPDOWN
 
149
 #define TURBO_STEPDOWN RAMP_SIZE/2
 
150
#endif
 
151
 
 
152
#define GROUP_SELECT_MODE 254
 
153
#ifdef USE_TEMP_CAL
 
154
#define TEMP_CAL_MODE 253
 
155
#endif
 
156
 
 
157
 
 
158
#if defined(FULL_BIKING_STROBE) && !defined(BIKING_STROBE)
 
159
#define BIKING_STROBE
 
160
#endif
 
161
 
 
162
#define OWN_DELAY           // Don't use stock delay functions.
 
163
// This is actually not optional anymore. since built in delay requires a compile time constant and strobe()
 
164
// cannot provide that.
 
165
 
 
166
#define USE_DELAY_S         // Also use _delay_s(), not just _delay_ms()
 
167
 
 
168
#if !defined(OFFTIM3)
 
169
  #define HIDDENMODES       // No hiddenmodes.
 
170
#endif
 
171
 
 
172
#include "fr-tk-attiny.h" // should be compatible with old ones, but it might not be, so renamed it.
 
173
 
 
174
#include MODEGROUPS_H
 
175
 
 
176
#define LOOP_SLEEP 500 // in ms, how many ms to sleep between voltage/temp/stepdown checks.
 
177
 
 
178
 
 
179
// Won't compile with -O0 (sometimes useful for debugging) without following:
 
180
#ifndef __OPTIMIZE__
 
181
#define inline
 
182
#endif
 
183
 
 
184
 
 
185
#define Q(x) #x
 
186
#define Quote(x) Q(x)  // for placing expanded defines into inline assembly with quotes around them.
 
187
// the double expansion is a weird but necessary quirk, found this SO I think.
 
188
 
 
189
//#define IDENT(x) x
 
190
//#define PATH(x,y) Quote(IDENT(x)IDENT(y))
 
191
//#include PATH(CONFIG_DIR,CONFIG_FILE_H)
 
192
 
 
193
 
 
194
 
 
195
#if (ATTINY==13)  && defined (TEMPERATURE_MON)
 
196
  #undef TEMPERATURE_MON
 
197
  #warning disabling TEMPERATURE_MON for attiny13
 
198
#endif
 
199
 
 
200
#if (ATTINY==13)  && defined (OTSM_powersave)
 
201
#undef OTSM_powersave
 
202
#warning disabling OTSM_powersave for attiny13
 
203
#endif
 
204
 
 
205
 
 
206
 
 
207
 
 
208
uint8_t modes[MAX_MODES + sizeof(hiddenmodes)];  // make sure this is long enough
 
209
 
 
210
// Modes (gets set when the light starts up based on saved config values)
 
211
#if defined(PWM1_LVL)&&defined(RAMP_PWM1)
 
212
  PROGMEM const uint8_t ramp_pwm1[] = { RAMP_PWM1 };
 
213
  #define USE_PWM1
 
214
#endif
 
215
#if defined(PWM2_LVL)&&defined(RAMP_PWM2)
 
216
  PROGMEM const uint8_t ramp_pwm2[] = { RAMP_PWM2 };
 
217
  #define USE_PWM2
 
218
#endif
 
219
#if defined(PWM3_LVL)&&defined(RAMP_PWM3)
 
220
  PROGMEM const uint8_t ramp_pwm3[] = { RAMP_PWM3 };
 
221
  #define USE_PWM3
 
222
#endif
 
223
#if defined(PWM4_LVL)&&defined(RAMP_PWM4)
 
224
  PROGMEM const uint8_t ramp_pwm4[] = { RAMP_PWM4 };
 
225
  #define USE_PWM4
 
226
#endif
 
227
 
 
228
 
 
229
// Calibrate voltage and OTC in this file:
 
230
#include "fr-calibration.h"
 
231
 
 
232
#ifdef OTSM_powersave
 
233
#include "fr-delay.h" // must include them in this order.
 
234
#define _delay_ms _delay_sleep_ms
 
235
#define _delay_s _delay_sleep_s
 
236
#else
 
237
#include "tk-delay.h"
 
238
#endif
 
239
 
 
240
 
 
241
#ifdef RANDOM_STROBE
 
242
#include "tk-random.h"
 
243
#endif
 
244
 
 
245
#include "tk-voltage.h"
 
246
 
 
247
 
 
248
///////////////////////REGISTER VARIABLES///////////////////////////////////
 
249
// make it a register variable.  Saves many i/o instructions.
 
250
// but could change as code evolves.  Worth testing what works best again later.
 
251
 
 
252
// ************NOTE global_counter is now reserved as r2 in tk-delay.h. (well, commented out maybe)**********
 
253
 
 
254
register uint8_t  mode_idx asm("r6");           // current or last-used mode number
 
255
register uint8_t eepos asm("r7");
 
256
//uint8_t eepos
 
257
 
 
258
#if defined(USE_OTSM) || defined(USE_ESWITCH)
 
259
//Reserving a register for this allows checking it in re-entrant interrupt without needing register maintenance
 
260
// as a side effect it saves several in/out operations that save more space.
 
261
register uint8_t wake_count asm  ("r8");
 
262
#endif
 
263
/////////////////////END REGISTERVARIABLE/////////////////////////////////
 
264
 
 
265
// fast_presses
 
266
// counter for entering config mode, remembers click count with tk noinit trick.
 
267
// If No OTC or OTSM is used it also detects off time by RAM decay
 
268
// However that's very unreliable with one byte.  
 
269
// FR adds USE_SAFE_PRESSES options that compares 4 bytes to detect RAM decay
 
270
// if 0 is equal probability to 1 (maybe not quite true) this gives a safety factor of 2^24 so about 16 million.
 
271
// (needs to be remembered while off, but only for up to half a second)
 
272
 
 
273
 
 
274
#if !(defined(USE_OTC)||defined(USE_OTSM))&& defined(USE_SAFE_PRESSES)
 
275
 #define SAFE_PRESSES
 
276
#endif
 
277
#ifndef N_SAFE_BYTES
 
278
 #define N_SAFE_BYTES 4
 
279
#endif
 
280
 
 
281
#ifdef SAFE_PRESSES
 
282
  uint8_t fast_presses_array[N_SAFE_BYTES] __attribute__ ((section (".noinit")));
 
283
  #define fast_presses fast_presses_array[0]
 
284
#else // using fast presses for click timing, use redundancy to check RAM decay:
 
285
  uint8_t fast_presses __attribute__ ((section (".noinit")));
 
286
#endif
 
287
 
 
288
 
 
289
 
 
290
// total length of current mode group's array
 
291
uint8_t mode_cnt;
 
292
// number of regular non-hidden modes in current mode group
 
293
uint8_t solid_modes;
 
294
// number of hidden modes in the current mode
 
295
// (hardcoded because both groups have the same hidden modes)
 
296
//uint8_t hidden_modes = NUM_HIDDEN;  // this is never used
 
297
 
 
298
 
 
299
#define FAST 0x03           // fast PWM
 
300
#define PHASE 0x01         // phase-correct PWM
 
301
 
 
302
// FR makes these all aray variables now
 
303
// can now loop to save, loop to load, and loop to toggle
 
304
// saves about 30 subtroutine calls, so a bunch of flash space.
 
305
 
 
306
// define the order of save variables
 
307
// Yes, they could just be put in the array aliases below
 
308
// This a messy way to allow not allocating a couple of bytes later.
 
309
#define muggle_mode_IDX     1 // start at 1 to match EEPSIZE math
 
310
#define memory_IDX          2 // these all get saved at EEPSIZE-N
 
311
#define enable_moon_IDX     3
 
312
#define reverse_modes_IDX   4
 
313
#define MODEGROUP_IDX       5  //GROUP_SELECT don't need to define mod_override entries here, just leave a space.
 
314
#define offtim3_IDX         6
 
315
#define TEMP_CAL_IDX        7 // TEMPERATURE_MON
 
316
#define firstboot_IDX       8
 
317
#define lockswitch_IDX      9  // don't forget to update n_saves above.
 
318
#define TOTAL_TOGGLES    9         // all saves above are toggle variables
 
319
 
 
320
// assign aliases for array entries for toggle variables.
 
321
#define OPT_firstboot (EEPSIZE-1-8) // only one that uses individual reads.
 
322
#define muggle_mode   OPT_array[muggle_mode_IDX] // start at 1 to match EEPSIZE math
 
323
#define memory        OPT_array[memory_IDX] // these all get saved at EEPSIZE-N
 
324
#define enable_moon   OPT_array[enable_moon_IDX]
 
325
#define reverse_modes OPT_array[reverse_modes_IDX]
 
326
// next memory element will serve as a dummy toggle variable for all mode-override toggles.
 
327
#define mode_override OPT_array[5]  //GROUP_SELECT 
 
328
#define offtim3       OPT_array[offtim3_IDX]
 
329
//#define TEMPERATURE_MON_IDX OPT_array[7] // TEMPERATURE_MON
 
330
#define firstboot     OPT_array[firstboot_IDX]  
 
331
#define lockswitch    OPT_array[lockswitch_IDX]  // don't forget to update n_saves above.
 
332
 
 
333
// this allows to save a few bytes by not initializing unneeded toggles at end of array:
 
334
// hmm, heck of a bunch of mess just to save 2 to 8 bytes though.
 
335
#if defined(USE_ESWITCH_LOCKOUT_TOGGLE)
 
336
  #define n_toggles (TOTAL_TOGGLES)   // number  of options to save/restore
 
337
#elif defined(USE_FIRSTBOOT)
 
338
  #define n_toggles (TOTAL_TOGGLES - 1)  // number  of options to save/restore
 
339
#elif defined(TEMPERATURE_MON)
 
340
  #define n_toggles (TOTAL_TOGGLES - 2)  // number  of options to save/restore
 
341
#elif defined(OFFTIM3)
 
342
  #define n_toggles (TOTAL_TOGGLES - 3)  // number  of options to save/restore
 
343
#else
 
344
  #define n_toggles (TOTAL_TOGGLES - 4)  
 
345
#endif  // we must have the MODEGROUP menu, so can't go below here.
 
346
 
 
347
// defined non-toggles saves:
 
348
#define modegroup     OPT_array[n_toggles+1]
 
349
#define maxtemp       OPT_array[n_toggles+2]
 
350
  #define n_extra_saves 2   //  non-toggle saves
 
351
#ifdef USE_TURBO_TIMEOUT
 
352
  #undef n_extra_saves
 
353
//  #define disable_next      OPT_array[n_toggles+3]
 
354
  #define NEXT_LOCKOUT  1     
 
355
  #define n_extra_saves 3
 
356
#else
 
357
  #define NEXT_LOCKOUT  0
 
358
#endif
 
359
#define DISABLE_NEXT 255
 
360
 
 
361
#define n_saves (n_toggles + n_extra_saves)
 
362
  uint8_t OPT_array[n_saves+1] ;
 
363
#ifndef LOOP_TOGGLES
 
364
  #define final_toggles  (-1) //disable loop toggles.
 
365
                       // redefining n_toggles breaks modegroup macro and fixing that situation seems ugly.
 
366
#endif
 
367
//#define _configs      OPT_array[12]
 
368
 
 
369
uint8_t overrides[n_toggles+1]; // will hold values override mode_idx if any for each toggle.
 
370
 
 
371
 
 
372
#define FIRSTBOOT 0b01010101
 
373
 
 
374
// define a bit field in an I/O register with sbi/cbi support, for efficient boolean manipulation:
 
375
 
 
376
typedef struct
 
377
{
 
378
        unsigned char bit0:1;
 
379
        unsigned char bit1:1;
 
380
        unsigned char bit2:1;
 
381
        unsigned char bit3:1;
 
382
        unsigned char bit4:1;
 
383
        unsigned char bit5:1;
 
384
        unsigned char bit6:1;
 
385
        unsigned char bit7:1;
 
386
}io_reg;
 
387
/***************LETS RESERVE GPIOR0 FOR LOCAL VARIABLE USE ********************/
 
388
// This seemed more useful at one point than it maybe actually is, but it works.
 
389
//define a global bitfield in lower 32 IO space with in/out sbi/cbi access
 
390
// unfortunately, attiny13 has no GPIORs,.
 
391
 
 
392
                #define gbit            *((volatile uint8_t*)_SFR_MEM_ADDR(GPIOR2)) // pointer to whole status byte.
 
393
                #define gbit_pwm4zero                   ((volatile io_reg*)_SFR_MEM_ADDR(GPIOR2))->bit0 // pwm4 disable toggle.
 
394
                #define gbit_epress             ((volatile io_reg*)_SFR_MEM_ADDR(GPIOR2))->bit1  // eswitch was pressed.
 
395
//      ...
 
396
        #define gbit_addr  "0x13"  // hack, but whatever, 0x13 is GPIOR2 but GPIOR2 macro is just too clever to work.
 
397
                                            //There's surely a better way, but not worth finding out.
 
398
                #define gbit_pwm4zero_bit "0"  // This gets used for inline asm in PWM ISR.
 
399
 
 
400
 
 
401
 
 
402
#if defined(USE_OTSM) || defined(USE_ESWITCH)
 
403
// convert wake time thresholds to counts, math done by compiler, not runtime:
 
404
// plus 1 because there's always an extra un-timed pin-change wake:
 
405
#define wake_count_short (uint8_t)(1+((double)wake_time_short)*((uint16_t)1<<(6-SLEEP_TIME_EXPONENT)))
 
406
#define wake_count_med (uint8_t)(1+((double)wake_time_med)*((uint16_t)1<<(6-SLEEP_TIME_EXPONENT)))
 
407
#endif
 
408
 
 
409
 
 
410
/**************WARN ON SOME BROKEN COMBINATIONS******************/
 
411
#ifndef ATTINY
 
412
 #error You must define ATTINY inbistro.c or in the build script/Makefile.
 
413
#endif
 
414
 
 
415
#ifndef CONFIG_FILE_H
 
416
 #error You must define CONFIG_FILE_H inbistro.c or in the build script/Makefile.
 
417
#endif
 
418
 
 
419
#ifndef MODEGROUPS_H
 
420
  #error You must define MODEGROUPS_H in the configuration file.
 
421
#endif
 
422
 
 
423
#ifdef USE_ESWITCH
 
424
   #ifndef ESWITCH_PIN
 
425
    #error You must define an ESWITCH_PIN in fr-tk-attiny.h or undefine USE_ESWITCH
 
426
   #endif
 
427
#endif
 
428
 
 
429
#ifdef USE_OTC
 
430
   #ifndef CAP_PIN
 
431
    #error You must define a CAP_PIN in fr-tk-attiny.h or undefine USE_OTC
 
432
   #endif
 
433
#endif
 
434
 
 
435
#ifdef USE_OTSM
 
436
  #ifndef OTSM_PIN
 
437
    #error You must define an OTSM_PIN in fr-tk-attiny.h or undefine USE_OTSM
 
438
  #endif
 
439
#endif
 
440
 
 
441
#if ATTINY==13 && defined(READ_VOLTAGE_FROM_VCC)
 
442
  #error You cannot use READ_VOLTAGE_FROM_VCC with the attiny 13.
 
443
#endif
 
444
 
 
445
#if ATTINY==13 && (defined(PWM3_LVL)||defined (PWM4_LVL))
 
446
#error attiny13 does not support PWM3 or PWM4, modify layout or select a new one.
 
447
#endif
 
448
 
 
449
 
 
450
#if defined(VOLTAGE_MON)&&!(defined(READ_VOLTAGE_FROM_VCC)||defined(READ_VOLTAGE_FROM_DIVIDER))
 
451
  #error You must define READ_VOLTAGE_FROM_VCC or READ_VOLTAGE_FROM_DIVEDER when VOLTAGE_MON is defined
 
452
#endif
 
453
 
 
454
#if defined(VOLTAGE_MON)&&defined(READ_VOLTAGE_FROM_VCC)&&defined(READ_VOLTAGE_FROM_DIVIDER)
 
455
  #error You cannot define READ_VOLTAGE_FROM_VCC at the same time as READ_VOLTAGE_FROM_DIVIDER
 
456
#endif
 
457
 
 
458
#if defined(READ_VOLTAGE_FROM_DIVIDER)&&!defined(REFERENCE_DIVIDER_READS_TO_VCC)&&defined(USE_OTSM)&&(OTSM_PIN==VOLTAGE_PIN)&&defined(VOLTAGE_MON)
 
459
  #error You cannot use 1.1V reference to read voltage on the same pin as the OTSM.  OTSM power-on voltage must be >1.8V.
 
460
  #error Use REFERENCE_DIVIDER_READS_TO_VCC instead and set divider resistors to provide > 1.8V on-voltage to voltage pin.
 
461
  #error For 1S non-LDO or 1-S 5.0V LDO lights you can use READ_VOLTAGE_FROM_VCC instead
 
462
#endif
 
463
 
 
464
#if defined(READ_VOLTAGE_FROM_DIVIDER)&&!defined(REFERENCE_DIVIDER_READS_TO_VCC)&&defined(USE_ESWITCH)&&(ESWITCH_PIN==VOLTAGE_PIN)&&defined(VOLTAGE_MON)
 
465
  #error You cannot use 1.1V reference to read voltage on the same pin as the e-switch.  E-switch on-voltage must be >1.8V.
 
466
  #error Use REFERENCE_DIVIDER_READS_TO_VCC instead and set divider resistors to provide > 1.8V on-voltage to voltage pin.
 
467
  #error For 1S non-LDO or 1-S 5.0V-LDO lights you can use READ_VOLTAGE_FROM_VCC instead.
 
468
#endif
 
469
 
 
470
#if !defined(USE_OTC)&&!defined(USE_OTSM)&&!defined(USE_ESWITCH)&&defined(OFFTIM3)
 
471
  #error You must define either USE_OTC or USE_OTSM or USE_ESWITCH when OFFTIM3 is defined.
 
472
#endif
 
473
 
 
474
/* If the eswitch is used it's impossible to know if there's also a clicky switch
 
475
So this warning doesn't catch everything */
 
476
#if !defined(USE_OTC)&&!defined(USE_OTSM)&&!defined(USE_SAFE_PRESSES)&&!defined(USE_ESWITCH)
 
477
  #warning It is highly recommend to define USE_SAFE_PRESSES for capacitor-less off-time detection
 
478
#endif
 
479
 
 
480
 
 
481
// Not really used
 
482
//#define DETECT_ONE_S  // auto-detect 1s vs multi-s light make prev.
 
483
// requiers 5V LDO for multi-s light and will use VCC for 1S.
 
484
// incomplete, needs calibration table switching, costs memory, probably 160 bytes when done.
 
485
 
 
486
 
 
487
/****************************END OF PREPROCESSOR DEFINES**************************/
 
488
 
 
489
#ifdef USE_STARS
 
490
inline void check_stars() { // including from BLFA6
 
491
        // Configure options based on stars
 
492
        // 0 being low for soldered, 1 for pulled-up for not soldered
 
493
        #if 0  // not implemented, STAR2_PIN is used for second PWM channel
 
494
        // Moon
 
495
        // enable moon mode?
 
496
        if ((PINB & (1 << STAR2_PIN)) == 0) {
 
497
                modes[mode_cnt++] = MODE_MOON;
 
498
        }
 
499
        #endif
 
500
        #if 0  // Mode order not as important as mem/no-mem
 
501
        // Mode order
 
502
        if ((PINB & (1 << STAR3_PIN)) == 0) {
 
503
                // High to Low
 
504
                mode_dir = -1;
 
505
                } else {
 
506
                mode_dir = 1;
 
507
        }
 
508
        #endif
 
509
        // Memory
 
510
        if ((PINB & (1 << STAR3_PIN)) == 0) {
 
511
                memory = 1;  // solder to enable memory
 
512
                } else {
 
513
                memory = 0;  // unsolder to disable memory
 
514
        }
 
515
}
 
516
#endif
 
517
 
 
518
#ifdef SAFE_PRESSES 
 
519
// FR 2017 adds redundancy to check RAM decay without flakiness.
 
520
// Expand fast_presses to mulitple copies.  Set and increment all.
 
521
// Check that all are equal to see if RAM has is still intact (short click) and value still valid.
 
522
void clear_presses() {
 
523
        for (uint8_t i=0;i<N_SAFE_BYTES;++i){
 
524
                fast_presses_array[i]=0;
 
525
        }
 
526
}
 
527
inline uint8_t check_presses(){
 
528
    uint8_t i=N_SAFE_BYTES-1;
 
529
        while (i&&(fast_presses_array[i]==fast_presses_array[i-1])){
 
530
                --i;
 
531
        }
 
532
        return !i; // if we got to 0, they're all equal
 
533
}
 
534
inline void inc_presses(){
 
535
        for (uint8_t i=0;i<N_SAFE_BYTES;++i){
 
536
                ++fast_presses_array[i];
 
537
        }
 
538
}
 
539
inline void set_presses(uint8_t val){
 
540
        for (uint8_t i=0;i<N_SAFE_BYTES;++i){
 
541
                fast_presses_array[i]=val;
 
542
        }
 
543
}
 
544
#else 
 
545
  #define check_presses() (fast_presses < 0x20)
 
546
  #define clear_presses() fast_presses=0
 
547
  #define inc_presses() fast_presses=(fast_presses+1)& 0x1f     
 
548
  #define set_presses(val) fast_presses=(val)   
 
549
#endif
 
550
 
 
551
uint8_t mode_idx;
 
552
inline void initial_values() {//FR 2017
 
553
        //for (uint8_t i=1;i<n_toggles+1;i++){ // disable all toggles, enable one by one.
 
554
                //OPT_array[i]=255;
 
555
        //}
 
556
         // configure initial values here, 255 disables the toggle... doesn't save space.
 
557
    #ifdef USE_FIRSTBOOT
 
558
         firstboot = FIRSTBOOT;               // detect initial boot or factory reset
 
559
        #elif firstboot_IDX <= final_toggles
 
560
//      #elif defined(LOOP_TOGGLES)
 
561
         firstboot=255;                       // disables menu toggle
 
562
        #endif
 
563
 
 
564
    #ifdef USE_MOON
 
565
         enable_moon = INIT_ENABLE_MOON;      // Should we add moon to the set of modes?
 
566
        #elif enable_moon_IDX <= final_toggles
 
567
//      #elif defined(LOOP_TOGGLES)
 
568
         enable_moon=255;                   //disable menu toggle,       
 
569
        #endif
 
570
 
 
571
        #if defined(USE_REVERSE_MODES) && defined(OFFTIM3)
 
572
         reverse_modes = INIT_REVERSE_MODES;  // flip the mode order?
 
573
        #elif reverse_modes_IDX <= final_toggles
 
574
//      #elif defined(LOOP_TOGGLES)
 
575
         reverse_modes=255;                   //disable menu toggle,
 
576
        #endif
 
577
         memory = INIT_MEMORY;                // mode memory, or not
 
578
 
 
579
        #ifdef OFFTIM3
 
580
         offtim3 = INIT_OFFTIM3;              // enable medium-press?
 
581
        #elif offtim3_IDX <= final_toggles
 
582
//      #elif defined(LOOP_TOGGLES)
 
583
         offtim3=255;                         //disable menu toggle, 
 
584
        #endif
 
585
 
 
586
        #ifdef USE_MUGGLE_MODE
 
587
         muggle_mode = INIT_MUGGLE_MODE;      // simple mode designed for muggles
 
588
        #elif muggle_mode_IDX <= final_toggles
 
589
//      #elif defined(LOOP_TOGGLES)
 
590
         muggle_mode=255;                     //disable menu toggle,
 
591
        #endif
 
592
 
 
593
        #ifdef USE_LOCKSWITCH
 
594
         lockswitch=INIT_LOCKSWITCH;          // E-swtich enabled.
 
595
        #elif lockswitch_IDX <= final_toggles
 
596
//      #elif defined(LOOP_TOGGLES)
 
597
         lockswitch=255;
 
598
        #endif
 
599
 
 
600
    #ifdef LOOP_TOGGLES
 
601
            overrides[5]=GROUP_SELECT_MODE; 
 
602
        #if defined(TEMPERATURE_MON)&&defined(TEMP_CAL_MODE)
 
603
          overrides[7]=TEMP_CAL_MODE, //7
 
604
        #elif TEMP_CAL_IDX <= final_toggles
 
605
//              #else
 
606
              OPT_array[7]=255;
 
607
                #endif
 
608
        #endif
 
609
 
 
610
// Handle non-toggle saves.
 
611
        modegroup = INIT_MODEGROUP;          // which mode group will be default, mode groups below start at zero, select the mode group you want and subtract one from the number to get it by defualt here
 
612
        #ifdef TEMPERATURE_MON
 
613
        maxtemp = INIT_MAXTEMP;              // temperature step-down threshold, each number is roughly equal to 4c degrees
 
614
        #endif
 
615
        mode_idx=0;                          // initial mode
 
616
 
 
617
        #ifdef USE_STARS
 
618
          check_stars();
 
619
        #endif
 
620
}
 
621
 
 
622
 
 
623
void save_mode() {  // save the current mode index (with wear leveling)
 
624
    uint8_t oldpos=eepos;
 
625
 
 
626
    eepos = (eepos+1) & ((EEPSIZE/2)-1);  // wear leveling, use next cell
 
627
 
 
628
    eeprom_write_byte((uint8_t *)((uint16_t)eepos),mode_idx);  // save current state
 
629
    eeprom_write_byte((uint8_t *)((uint16_t)oldpos), 0xff);     // erase old state
 
630
}
 
631
 
 
632
 
 
633
#define gssWRITE 1
 
634
#define gssREAD 0
 
635
 
 
636
 
 
637
void getsetstate(uint8_t rw){// double up the function to save space.
 
638
   uint8_t i; 
 
639
   i=n_saves;
 
640
   do{
 
641
       if (rw==gssWRITE){// conditional inside loop for space.
 
642
               eeprom_write_byte((uint8_t *)(EEPSIZE-i-1),OPT_array[i]);
 
643
           } else {
 
644
               OPT_array[i]=eeprom_read_byte((uint8_t *)(EEPSIZE-i-1));
 
645
       }
 
646
           i--;
 
647
    } while(i); // don't include 0
 
648
}
 
649
 
 
650
 
 
651
void save_state() {  // central method for writing complete state
 
652
        save_mode();
 
653
        getsetstate(gssWRITE);
 
654
}
 
655
 
 
656
 
 
657
//#ifndef USE_FIRSTBOOT // obsolete
 
658
//inline void reset_state() {
 
659
////    mode_idx = 0;
 
660
////    modegroup = 0;
 
661
    //save_state();
 
662
//}
 
663
//#endif
 
664
 
 
665
inline void restore_state() {
 
666
 
 
667
#ifdef USE_FIRSTBOOT
 
668
    uint8_t eep;
 
669
     //check if this is the first time we have powered on
 
670
    eep = eeprom_read_byte((uint8_t *)OPT_firstboot);
 
671
    if (eep != FIRSTBOOT) {// confusing: if eep = FIRSTBOOT actually means the first boot already happened
 
672
                                   // so eep != FIRSTBOOT means this IS the first boot.
 
673
        // not much to do; the defaults should already be set
 
674
        // while defining the variables above
 
675
        save_state(); // this will save FIRSTBOOT to the OPT_firstboot byte.
 
676
        return;
 
677
    }
 
678
#endif
 
679
    eepos=0; 
 
680
    do { // Read until we get a result. Tightened this up slightly -FR
 
681
            mode_idx = eeprom_read_byte((const uint8_t *)((uint16_t)eepos));
 
682
    } while((mode_idx == 0xff) && eepos++<(EEPSIZE/2) ) ; // the && left to right eval prevents the last ++.
 
683
#ifndef USE_FIRSTBOOT
 
684
 
 
685
    // if no mode_idx was found, assume this is the first boot
 
686
    if (mode_idx==0xff) {
 
687
          save_state(); //redundant with check below -FR
 
688
        return; 
 
689
    }
 
690
#endif
 
691
    // load other config values
 
692
    getsetstate(gssREAD);
 
693
 
 
694
#ifndef USE_FIRSTBOOT
 
695
//    if (modegroup >= NUM_MODEGROUPS) reset_state(); // redundant with check above
 
696
// With this commented out, disabling firstboot just eeks out 12 bytes of saving,
 
697
// largely because reset_state can now become = save_state above.
 
698
// before doing getsetstate, the initial values are still good for the save.
 
699
// this is a nice safety check, but that's not what it's here for.
 
700
#endif
 
701
}
 
702
 
 
703
 
 
704
inline void next_mode() {
 
705
    mode_idx += 1;
 
706
    if (mode_idx >= solid_modes) {
 
707
        // Wrap around, skipping the hidden modes
 
708
        // (note: this also applies when going "forward" from any hidden mode)
 
709
        // FIXME? Allow this to cycle through hidden modes?
 
710
        mode_idx = 0;
 
711
    }
 
712
}
 
713
 
 
714
#ifdef OFFTIM3
 
715
inline void prev_mode() {
 
716
    // simple mode has no reverse
 
717
        #ifdef USE_MUGGLE_MODE
 
718
      if (muggle_mode) { return next_mode(); }
 
719
    #endif
 
720
    if (mode_idx == solid_modes) { 
 
721
        // If we hit the end of the hidden modes, go back to first mode
 
722
        mode_idx = 0;
 
723
    } else if (mode_idx > 0) {
 
724
        // Regular mode: is between 1 and TOTAL_MODES
 
725
        mode_idx -= 1;
 
726
    } else {
 
727
        // Otherwise, wrap around (this allows entering hidden modes)
 
728
        mode_idx = mode_cnt - 1;
 
729
    }
 
730
}
 
731
#endif
 
732
 
 
733
inline void copy_hidden_modes(uint8_t mode_cnt){
 
734
//  Helper for count_modes. At one point seemed potentially
 
735
// useful to break it out for preprocessor choices.  -FR
 
736
// copy starting from end, so takes mode_cnt as input.
 
737
        for(uint8_t j=mode_cnt, i=sizeof(hiddenmodes);i>0; )
 
738
        {
 
739
                // predecrement to get the minus 1 for free and avoid the temp,
 
740
                // probably optimizer knows all this anyway.
 
741
                modes[--j] = pgm_read_byte((uint8_t *)(hiddenmodes+(--i)));
 
742
        }
 
743
}
 
744
 
 
745
inline void count_modes() {
 
746
    /*
 
747
     * Determine how many solid and hidden modes we have.
 
748
     *
 
749
     * (this matters because we have more than one set of modes to choose
 
750
     *  from, so we need to count at runtime)
 
751
     */
 
752
        /*  
 
753
         * FR: What this routine really does is combine the moon mode, the defined group modes, 
 
754
         * and the hidden modes into one array according to configuration options
 
755
         * such as mode reversal, enable mood mode etc.
 
756
         * The list should like this:
 
757
         * modes ={ moon, solid1, solid2,...,last_solid,hidden1,hidden2,...,last_hidden}
 
758
         * unless reverse_modes is enabled then it looks like this:
 
759
         * modes={last_solid,last_solid-1,..solid1,moon,hidden1,hidden2,...last_hidden}
 
760
         * or if moon is disabled it is just left out of either ordering.
 
761
         * If reverse clicks are disabled the hidden modes are left out.
 
762
         * mode_cnt will hold the final count of modes  -FR.
 
763
         *
 
764
         * Now updated to construct the modes in one pass, even for reverse modes.
 
765
         * Reverse modes are constructed backward and pointer gets moved to begining when done.
 
766
         */      
 
767
        
 
768
    // copy config to local vars to avoid accidentally overwriting them in muggle mode
 
769
    // (also, it seems to reduce overall program size)
 
770
    uint8_t my_modegroup = modegroup;
 
771
        #ifdef USE_MOON
 
772
      uint8_t my_enable_moon = enable_moon;
 
773
        #else
 
774
          #define my_enable_moon 0
 
775
        #endif
 
776
        #if defined(USE_REVERSE_MODES) && defined(OFFTIM3)
 
777
     uint8_t my_reverse_modes = reverse_modes;
 
778
        #else
 
779
          #define my_reverse_modes 0
 
780
        #endif
 
781
 
 
782
    // override config if we're in simple mode
 
783
        #ifdef USE_MUGGLE_MODE
 
784
    if (muggle_mode) {
 
785
        my_modegroup = NUM_MODEGROUPS;
 
786
          #ifdef USE_MOON
 
787
        my_enable_moon = 0;
 
788
          #endif
 
789
          #if defined(USE_REVERSE_MODES)&&defined(OFFTIM3)
 
790
        my_reverse_modes = 0;
 
791
          #endif
 
792
    }
 
793
        #endif
 
794
    //my_modegroup=11;
 
795
    //my_reverse_modes=0; // FOR TESTING
 
796
        //my_enable_moon=1;
 
797
        uint8_t i=0;
 
798
//    const uint8_t *src = modegroups + (my_modegroup<<3);
 
799
 
 
800
    uint8_t *src=(void *)modegroups;
 
801
    // FR adds 0-terminated variable length mode groups, saves a bunch in big builds.
 
802
        // some inspiration from gchart here too in tightening this up even more.
 
803
    // scan for enough 0's, leave the pointer on the first mode of the group.
 
804
    i=my_modegroup+1;
 
805
        uint8_t *start=0;
 
806
        solid_modes=0;
 
807
 
 
808
    // now find start and end in one pass
 
809
        // for 
 
810
    while(i) {
 
811
                start=src; // set start to beginning of mode group
 
812
            #if defined(USE_REVERSE_MODES)&&defined(OFFTIM3) //Must find end before we can reverse the copy
 
813
                                                // so copy will happen in second pass below.
 
814
              while(pgm_read_byte(src++)){
 
815
            #else // if no reverse, can do the copy here too.
 
816
          while((modes[solid_modes+my_enable_moon]=pgm_read_byte(src++))){
 
817
                #endif
 
818
                                         solid_modes=(uint8_t)(src-start);
 
819
                                } // every 0 starts a new modegroup, decrement i
 
820
            i--;
 
821
    }
 
822
 
 
823
 
 
824
//     Now handle reverse order in same step. -FR
 
825
    #if defined(USE_REVERSE_MODES)&&defined(OFFTIM3)
 
826
    uint8_t j;
 
827
    j=solid_modes; // this seems a little redundant now.
 
828
          do{
 
829
     //note my_enable_moon and my_reverse_modes are either 1 or 0, unlike solid_modes.
 
830
      modes[(my_reverse_modes?solid_modes-j:j-1+my_enable_moon)] = pgm_read_byte(start+(j-1));
 
831
       j--;
 
832
      } while (j);
 
833
        #endif
 
834
 
 
835
    #ifdef USE_MOON
 
836
        solid_modes+=my_enable_moon;
 
837
    if (my_enable_moon) {// moon placement already handled, but have to fill in the value.
 
838
            modes[(my_reverse_modes?solid_modes-1:0)] = 1;
 
839
    }
 
840
        #endif
 
841
        
 
842
 
 
843
// add hidden modes
 
844
#ifdef OFFTIM3
 
845
    mode_cnt = solid_modes+sizeof(hiddenmodes);
 
846
    copy_hidden_modes(mode_cnt); // copy hidden modes starts at the end.
 
847
 
 
848
   mode_cnt-=!(modes[0]^modes[mode_cnt-1]);// cheapest syntax I could find, but the check still costs 20 bytes. -FR
 
849
 
 
850
#else
 
851
mode_cnt = solid_modes; 
 
852
#endif
 
853
}
 
854
 
 
855
// This is getting too silly
 
856
// and tk already removed all usages of it anyway, except from set_level, so just do it there.
 
857
//#ifdef PWM4_LVL
 
858
  //inline void set_output(uint8_t pwm1, uint8_t pwm2, uint8_t pwm3, uint8_t pwm4) {
 
859
//#elif defined(PWM3_LVL)
 
860
  //inline void set_output(uint8_t pwm1, uint8_t pwm2, uint8_t pwm3) {
 
861
//#elif defined(PWM2_LVL)
 
862
  //inline void set_output(uint8_t pwm1, uint8_t pwm2) {
 
863
//#else
 
864
  //inline void set_output(uint8_t pwm1,) {
 
865
//#endif
 
866
//#endif
 
867
  //inline void set_output() {
 
868
    ///* This is no longer needed since we always use PHASE mode.
 
869
    //// Need PHASE to properly turn off the light
 
870
    //if ((pwm1==0) && (pwm2==0)) {
 
871
        //TCCR0A = PHASE;
 
872
    //}
 
873
    //*/
 
874
    //FET_PWM1_LVL = pwm1;
 
875
    //PWM1_LVL = pwm2;
 
876
//#ifdef ALT_PWM1_LVL
 
877
      //ALT_PWM1_LVL = pwm3;
 
878
//#endif
 
879
////return;
 
880
//}
 
881
 
 
882
void set_level(uint8_t level) {
 
883
    if (level == 0) {
 
884
#ifdef USE_PWM4
 
885
        gbit_pwm4zero=1; // we can't disable the interrupt because we use it for other timing
 
886
                                 // so have to signal the interrupt instead.
 
887
        PWM4_LVL=0;
 
888
#endif
 
889
#if defined(USE_PWM3)
 
890
        PWM3_LVL=0;
 
891
#endif
 
892
#if defined(USE_PWM2)
 
893
        PWM2_LVL=0;
 
894
#endif
 
895
#ifdef USE_PWM1
 
896
        PWM1_LVL=0;
 
897
#endif
 
898
    } else {
 
899
        level -= 1;
 
900
#ifdef USE_PWM4
 
901
       PWM4_LVL=pgm_read_byte(ramp_pwm4   + level);
 
902
       gbit_pwm4zero=0;
 
903
#endif
 
904
#ifdef USE_PWM3
 
905
       PWM3_LVL=pgm_read_byte(ramp_pwm3   + level);
 
906
#endif
 
907
#ifdef USE_PWM2
 
908
       PWM2_LVL=pgm_read_byte(ramp_pwm2   + level);
 
909
#endif
 
910
#ifdef USE_PWM1
 
911
       PWM1_LVL=pgm_read_byte(ramp_pwm1   + level);
 
912
#endif
 
913
    }
 
914
}
 
915
 
 
916
 
 
917
void set_mode(uint8_t mode) {
 
918
#ifdef SOFT_START
 
919
    static uint8_t actual_level = 0;
 
920
    uint8_t target_level = mode;
 
921
    int8_t shift_amount;
 
922
    int8_t diff;
 
923
    do {
 
924
        diff = target_level - actual_level;
 
925
        shift_amount = (diff >> 2) | (diff!=0);
 
926
        actual_level += shift_amount;
 
927
        set_level(actual_level);
 
928
        _delay_ms(RAMP_SIZE/20);  // slow ramp
 
929
        //_delay_ms(RAMP_SIZE/4);  // fast ramp
 
930
    } while (target_level != actual_level);
 
931
#else
 
932
#define set_mode set_level
 
933
    //set_level(mode);
 
934
#endif  // SOFT_START
 
935
}
 
936
 
 
937
void blink(uint8_t val, uint16_t speed)
 
938
{
 
939
    for (; val>0; val--)
 
940
    {
 
941
        set_level(BLINK_BRIGHTNESS);
 
942
        _delay_ms(speed);
 
943
        set_level(0);
 
944
        _delay_ms(speed);
 
945
        _delay_ms(speed);
 
946
    }
 
947
}
 
948
 
 
949
// utility routine to blink out 8bit value as a 3 digit decimal.
 
950
// The compiler will omit it if it's not used.  Good for debugging.  -FR.
 
951
// uses much memory though.
 
952
inline void blink_value(uint8_t value){
 
953
        blink (10,20);
 
954
        _delay_ms(500);
 
955
        blink((value/100)%10,200); // blink hundreds
 
956
        _delay_s();
 
957
        blink((value/10)%10,200); // blink tens
 
958
        _delay_s();
 
959
        blink(value % 10,200); // blink ones
 
960
        _delay_s();
 
961
        blink(10,20);
 
962
        _delay_ms(500);
 
963
}
 
964
 
 
965
 
 
966
INLINE_STROBE void strobe(uint8_t ontime, uint8_t offtime) {
 
967
// TK added this loop.  The point seems to be to slow down one strobe cycle
 
968
// so fast_presses timeout is not reached too quickly.
 
969
// FR has a partial implementation of a global clock in tk-delay
 
970
// that would solve this more generally, but for now this is slightly smaller and does the job.
 
971
    uint8_t i;
 
972
    for(i=0;i<8;i++) {
 
973
            set_level(RAMP_SIZE);
 
974
            _delay_ms(ontime);
 
975
            set_level(0);
 
976
            _delay_ms(offtime);
 
977
    }
 
978
}
 
979
 
 
980
#ifdef SOS
 
981
inline void SOS_mode() {
 
982
#define SOS_SPEED 200
 
983
    blink(3, SOS_SPEED);
 
984
    _delay_ms(SOS_SPEED*5/2);
 
985
    blink(3, SOS_SPEED*5/2);
 
986
    //_delay_ms(SOS_SPEED);
 
987
    blink(3, SOS_SPEED);
 
988
    _delay_s(); _delay_s();
 
989
}
 
990
#endif
 
991
 
 
992
#ifdef LOOP_TOGGLES
 
993
inline void toggles() {
 
994
        // New FR version loops over all toggles, avoids variable passing, saves ~50 bytes.
 
995
        // mode_overrides ( toggles that cause startup in a special mode or menu) 
 
996
        // are handled by an array entry for each toggle that provides the  mod_idx to set.
 
997
        // For normal config toggles, the array value is 0, so the light starts in 
 
998
        // the first normal mode.
 
999
        // For override toggles the array value is an identifier for the special mode
 
1000
        // All special modes have idx values above MINUMUM_OVERRIDE_MODE.
 
1001
        // On startup mode_idx is checked to be in the override range or not. 
 
1002
        //
 
1003
        // Used for config mode
 
1004
        // Changes the value of a config option, waits for the user to "save"
 
1005
        // by turning the light off, then changes the value back in case they
 
1006
        // didn't save.  Can be used repeatedly on different options, allowing
 
1007
        // the user to change and save only one at a time.
 
1008
        uint8_t i=0;
 
1009
        do {
 
1010
                i++;
 
1011
                if(OPT_array[i]!=255){
 
1012
                        blink(i, BLINK_SPEED/8);  // indicate which option number this is
 
1013
                        mode_idx=overrides[i];
 
1014
                        OPT_array[i] ^= 1;
 
1015
                        save_state();
 
1016
                        // "buzz" for a while to indicate the active toggle window
 
1017
                        blink(32, 500/32);
 
1018
                        OPT_array[i] ^= 1;
 
1019
                        save_state();
 
1020
                        _delay_s();
 
1021
                        #ifdef USE_MUGGLE_MODE
 
1022
                        if (muggle_mode) {break;} // go through once on muggle mode
 
1023
                        // this check adds 10 bytes. Is it really needed?
 
1024
                        #endif
 
1025
                }
 
1026
        }while((i<n_toggles));
 
1027
}
 
1028
 
 
1029
#else // use the old way, can come close in space for simple menus:
 
1030
 
 
1031
void toggle(uint8_t *var, uint8_t num) {
 
1032
    // Used for config mode
 
1033
    // Changes the value of a config option, waits for the user to "save"
 
1034
    // by turning the light off, then changes the value back in case they
 
1035
    // didn't save.  Can be used repeatedly on different options, allowing
 
1036
    // the user to change and save only one at a time.
 
1037
    blink(num, BLINK_SPEED/8);  // indicate which option number this is
 
1038
    *var ^= 1;
 
1039
    save_state();
 
1040
    // "buzz" for a while to indicate the active toggle window
 
1041
    blink(32, 500/32);
 
1042
    /*
 
1043
    for(uint8_t i=0; i<32; i++) {
 
1044
        set_level(BLINK_BRIGHTNESS * 3 / 4);
 
1045
        _delay_ms(20);
 
1046
        set_level(0);
 
1047
        _delay_ms(20);
 
1048
    }
 
1049
    */
 
1050
    // if the user didn't click, reset the value and return
 
1051
    *var ^= 1;
 
1052
    save_state();
 
1053
    _delay_s();
 
1054
}
 
1055
 
 
1056
 
 
1057
inline void toggles(){
 
1058
// The old way to do the toggles, in case we need it back.
 
1059
// Enter or leave "muggle mode"?
 
1060
   #ifdef USE_MUGGLE_MODE
 
1061
    toggle(&muggle_mode, 1);
 
1062
    if (muggle_mode)  return;  // don't offer other options in muggle mode
 
1063
  #endif
 
1064
    toggle(&memory, 2);
 
1065
  #ifdef USE_MOON
 
1066
    toggle(&enable_moon, 3);
 
1067
  #endif
 
1068
  #if defined(USE_REVERSE_MODES) && defined(OFFTIM3)
 
1069
    toggle(&reverse_modes, 4);
 
1070
  #endif
 
1071
// Enter the mode group selection mode?
 
1072
    mode_idx = GROUP_SELECT_MODE;
 
1073
    toggle(&mode_override, 5);
 
1074
    mode_idx = 0;
 
1075
 
 
1076
  #ifdef OFFTIM3
 
1077
    toggle(&offtim3, 6);
 
1078
  #endif
 
1079
 
 
1080
  #ifdef TEMPERATURE_MON
 
1081
// Enter temperature calibration mode?
 
1082
    mode_idx = TEMP_CAL_MODE;
 
1083
    toggle(&mode_override, 7);
 
1084
    mode_idx = 0;
 
1085
  #endif
 
1086
 
 
1087
  #ifdef USE_FIRSTBOOT
 
1088
    toggle(&firstboot, 8);
 
1089
  #endif
 
1090
  
 
1091
  #ifdef USE_LOCKSWITCH
 
1092
      toggle(&lockswitch, 9);
 
1093
  #endif
 
1094
}
 
1095
 
 
1096
#endif
 
1097
 
 
1098
 
 
1099
#ifdef TEMPERATURE_MON
 
1100
uint8_t  get_temperature() {
 
1101
    // average a few values; temperature is noisy
 
1102
    uint16_t temp = 0;
 
1103
    uint8_t i;
 
1104
    ADC_on_temperature(); // do it before calling, inconsistent with get_voltage and
 
1105
                           
 
1106
    for(i=0; i<16; i++) {
 
1107
        _delay_ms(5);  // 
 
1108
        temp += get_voltage();
 
1109
    }
 
1110
    temp >>= 4;
 
1111
    return temp;
 
1112
}
 
1113
#endif  // TEMPERATURE_MON
 
1114
 
 
1115
#if defined(OFFTIM3)&&defined(USE_OTC)
 
1116
inline uint8_t read_otc() {
 
1117
    // Read and return the off-time cap value
 
1118
    // Start up ADC for capacitor pin
 
1119
    // disable digital input on ADC pin to reduce power consumption
 
1120
    //DIDR0 |= (1 << CAP_DIDR); // will just do it for all pins on init.
 
1121
    // 1.1v reference, left-adjust, ADC3/PB3
 
1122
    ADMUX  = (1 << V_REF) | (1 << ADLAR) | CAP_PIN;
 
1123
    // enable, start, prescale
 
1124
    ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;
 
1125
    // Wait for completion
 
1126
    while (ADCSRA & (1 << ADSC));
 
1127
    // Start again as datasheet says first result is unreliable
 
1128
    ADCSRA |= (1 << ADSC);
 
1129
    // Wait for completion
 
1130
    while (ADCSRA & (1 << ADSC));
 
1131
 
 
1132
    // ADCH should have the value we wanted
 
1133
    return ADCH;
 
1134
}
 
1135
#endif
 
1136
 
 
1137
inline void init_mcu(){ // complete revamp by FR to allow use of any combination of 4 outputs, OTSM, and more
 
1138
        // 2017 by Flintrock (C)
 
1139
        //
 
1140
        // setup all our initial mcu configuration, mostly including interrupts.
 
1141
    //DDRB, 1 bit per pin, 1=output default =0.
 
1142
        //PORTB 1 is ouput-high or input-pullup.  0 is output-low or input floating/tri-stated.  Default=0.
 
1143
        //DIDR0 Digital input disable, 1 disable, 0 enable. disable for analog pins to save power. Default 0 (enabled) 
 
1144
 
 
1145
    // start by disabling all digital input.
 
1146
    // PWM pins will get set as output anyway.
 
1147
    DIDR0=0b00111111 ; // tests say makes no difference during sleep,
 
1148
                           // but datasheet claims it helps drain in middle voltages, so during power-off detection maybe.
 
1149
        
 
1150
        // Charge up the capacitor by setting CAP_PIN to output
 
1151
#ifdef CAP_PIN
 
1152
    // if using OTSM but no OTC cap, probably better to stay input high on the unused pin.
 
1153
        // If USE_ESWITCH and eswitch pin is defined same as cap pin, the eswitch define overrides, 
 
1154
        //  so again, leave it as input (but not high).
 
1155
    #if ( (defined(USE_OTSM) && !defined(OTSM_USES_OTC) ) || (defined(USE_ESWITCH) && ESWITCH_PIN == CAP_PIN ) )
 
1156
       // just leave cap_pin as an input pin (raised high by default lower down)
 
1157
    #else
 
1158
        // Charge up the capacitor by setting CAP_PIN to output
 
1159
          DDRB  |= (1 << CAP_PIN);    // Output
 
1160
          PORTB |= (1 << CAP_PIN);    // High
 
1161
    #endif
 
1162
#endif
 
1163
        
 
1164
        // Set PWM pins to output 
 
1165
        // Regardless if in use or not, we can't set them input high (might have a chip even if unused in config)
 
1166
        // so better set them as output low.
 
1167
    #ifdef PWM_PIN
 
1168
           DDRB |= (1 << PWM_PIN) ;    
 
1169
        #endif
 
1170
        #ifdef PWM2_PIN
 
1171
           DDRB |= (1 << PWM2_PIN);
 
1172
        #endif 
 
1173
    #ifdef PWM3_PIN
 
1174
           DDRB |= (1 << PWM3_PIN); 
 
1175
    #endif
 
1176
    #ifdef PWM4_PIN
 
1177
       DDRB |= (1 << PWM4_PIN); 
 
1178
    #endif
 
1179
          
 
1180
        
 
1181
        // Set Timer 0 to do PWM1 and PWM2 or for OTSM powersave timing
 
1182
    #if defined(USE_PWM1) || defined (USE_PWM2) || defined OTSM_powersave // should alias the last one to something better      
 
1183
     
 
1184
           TCCR0A = PHASE; // phase means counter counts up and down and 
 
1185
                       // compare register triggers on and off symmetrically at same value.
 
1186
                                   // This doubles the time so half the max frequency.
 
1187
        // Set prescaler timing
 
1188
        // This and the phase above now directly impact the delay function in tk-delay.h..
 
1189
        //  make changes there to compensate if this is changed
 
1190
             TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)  1 => 16khz in phase mode or 32 in fast mode.
 
1191
 
 
1192
       #ifdef  USE_PWM1
 
1193
             TCCR0A |= (1<<COM0B1);  // enable PWM on PB1
 
1194
           #endif
 
1195
           #ifdef USE_PWM2
 
1196
             TCCR0A |= (1<<COM0A1);  // enable PWM on PB0
 
1197
           #endif
 
1198
        #endif       
 
1199
 
 
1200
   //Set Timer1 to do PWM3 and PWM4
 
1201
        #if defined(USE_PWM3) || defined (USE_PWM4)
 
1202
          OCR1C = 255;  
 
1203
        // FR: this timer does not appear to have any phase mode.
 
1204
        // The frequency appears to be just system clock/255
 
1205
        #endif
 
1206
        #ifdef USE_PWM3
 
1207
          TCCR1 = _BV (CS10);  // prescale of 1 (32 khz PWM)
 
1208
          GTCCR = (1<<COM1B1) | (1<<PWM1B) ; // enable pwm on OCR1B but not OCR1B compliment (PB4 only). 
 
1209
                                            // FR: this timer does not appear to have any phase mode.
 
1210
                                                                                // The frequency appears to be just system clock/255
 
1211
    #endif                                                                              
 
1212
        #ifdef USE_PWM4
 
1213
          TCCR1 = _BV (CS11);  // override, use prescale of 2 (16khz PWM) for PWM4 because it will have high demand from interrupts.
 
1214
                               // This will still be just as fast as timer 0 in phase mode.
 
1215
          TCCR1 |=  _BV (PWM1A) ;           // for PB3 enable pwm for OCR1A but leave it disconnected.  
 
1216
                                                // Its pin is already in use.
 
1217
                                                                    // Must handle it with an interrupt.
 
1218
      TIMSK |= (1<<OCIE1A) | (1<<TOIE1);        // enable interrupt for compare match and overflow on channel 4 to control PB3 output
 
1219
          // Note: this will then override timer0 as the delay clock interrupt for tk-delay.h.
 
1220
        #endif
 
1221
        
 
1222
                
 
1223
        
 
1224
        PORTB|=~DDRB&~(1<<VOLTAGE_PIN); // Anything that is not an output 
 
1225
                                       // or the voltage sense pin, gets a pullup resistor
 
1226
        // again, no change measured during sleep, but maybe helps with shutdown?
 
1227
        // exceptions handled below.
 
1228
#ifdef USE_ESWITCH
 
1229
         // leave pullup set on E-switch pin
 
1230
          PCMSK |= 1<< ESWITCH_PIN;  // catch pin change on eswitch pin
 
1231
#endif
 
1232
#if defined(USE_OTSM) 
 
1233
//  no pull-up on OTSM-PIN. 
 
1234
      PORTB=PORTB&~(1<<OTSM_PIN); 
 
1235
          PCMSK |= 1<< OTSM_PIN;  // catch pin change on OTSM PIn
 
1236
#endif
 
1237
#if defined(USE_ESWITCH) || defined(USE_OTSM)
 
1238
        GIMSK |= 1<<PCIE;       // enable PIN change interrupt
 
1239
 
 
1240
        GIFR |= PCIF;  //    Clear pin change interrupt flag
 
1241
#endif
 
1242
#if defined(USE_ESWITCH) || defined(USE_OTSM) || defined(OTSM_powersave)
 
1243
        sleep_enable();     // just leave it enabled.  It's fine and will help elsewhere.
 
1244
        sei();                          //Enable Global Interrupt
 
1245
#endif
 
1246
 
 
1247
//timer overflow interrupt is presently setup in tk-delay.h for OTS_powersave
 
1248
 
 
1249
}
 
1250
 
 
1251
#if defined(USE_OTSM) || defined(USE_ESWITCH) || !defined(USE_OTC)
 
1252
// decide which mode to switch to based on user input
 
1253
inline void change_mode() {  // just use global  variable
 
1254
#else
 
1255
inline void change_mode(uint8_t cap_val) {
 
1256
#endif
 
1257
 
 
1258
//      if (! mode_override) {
 
1259
  if (mode_idx<MINIMUM_OVERRIDE_MODE) {
 
1260
   #if defined(USE_OTSM) || defined(USE_ESWITCH)
 
1261
            if (wake_count < wake_count_short   )  { 
 
1262
   #elif defined(USE_OTC)               
 
1263
                if (cap_val > CAP_SHORT) {
 
1264
   #else
 
1265
//              if (fast_presses < 0x20) { // fallback, but this trick needs improvements.
 
1266
                if ( check_presses() ) {// Indicates they did a short press, go to the next mode
 
1267
   #endif
 
1268
                                // after turbo timeout, forward click "stays" in turbo (never truly left).
 
1269
                                // conditional gets optimized out if NEXT_LOCKOUT is 0
 
1270
                                if ( (NEXT_LOCKOUT) && fast_presses == DISABLE_NEXT ){
 
1271
                                        clear_presses(); // one time only.
 
1272
                                } else {
 
1273
                                   next_mode(); // Will handle wrap arounds
 
1274
                                }
 
1275
                                //// We don't care what the fast_presses value is as long as it's over 15
 
1276
                                //                              fast_presses = (fast_presses+1) & 0x1f;
 
1277
                inc_presses();
 
1278
   #ifdef OFFTIM3
 
1279
      #if defined(USE_OTSM) || defined(USE_ESWITCH)
 
1280
                 } else if (wake_count < wake_count_med   )  {
 
1281
      #else
 
1282
                 } else if (cap_val > CAP_MED) {
 
1283
      #endif
 
1284
 
 
1285
                        // User did a medium press, go back one mode
 
1286
//                      fast_presses = 0;
 
1287
                        clear_presses();
 
1288
                        if (offtim3) {
 
1289
                                prev_mode();  // Will handle "negative" modes and wrap-arounds
 
1290
                        } else {
 
1291
                                next_mode();  // disabled-med-press acts like short-press
 
1292
                                        // (except that fast_presses isn't reliable then)
 
1293
                    }
 
1294
          #endif
 
1295
                } else {
 
1296
                                // Long press, keep the same mode
 
1297
                                // ... or reset to the first mode
 
1298
//                              fast_presses = 0;
 
1299
            clear_presses();
 
1300
                    #ifdef USE_MUGGLE_MODE
 
1301
                        if (muggle_mode  || (! memory)) {
 
1302
                        #else 
 
1303
                        if (!memory) {
 
1304
                        #endif
 
1305
                                        // Reset to the first mode
 
1306
                                        mode_idx = 0;
 
1307
                    }
 
1308
           } // short/med/long
 
1309
  }// mode override
 
1310
}
 
1311
 
 
1312
#ifdef VOLTAGE_CAL
 
1313
inline void voltage_cal(){
 
1314
        ADC_on();
 
1315
        while(1){
 
1316
          _delay_ms(300);
 
1317
          blink_value(get_voltage());
 
1318
        }
 
1319
}
 
1320
#endif
 
1321
 
 
1322
 
 
1323
/*********************ISRs***************************************************/
 
1324
/******One more is in FR-delay.h*******************************************/
 
1325
 
 
1326
#ifdef USE_PWM4
 
1327
// 2017 by Flintrock.
 
1328
// turn on PWM4_PIN at bottom of clock ramp
 
1329
// this will also replace the delay-clock interrupt used in fr-delay.h
 
1330
// Since SBI,CBI, and SBIC touch no registers, so no register protection is needed:
 
1331
// PWM this way without a phase-mode counter would not shut off the light completely
 
1332
// Added a control flag for 0 level to disable the light. We need the interrupts running for the delay clock.
 
1333
 
 
1334
ISR(TIMER1_OVF_vect,ISR_NAKED){ // hits when counter 1 reaches max
 
1335
          __asm__ __volatile__ (    //0x18 is PORTB
 
1336
          "cbi 0x18 , " Quote(PWM4_PIN) " \n\t"
 
1337
          "reti" "\n\t"
 
1338
          :::);
 
1339
}
 
1340
 
 
1341
// turn off PWM4_PIN at COMPA register match
 
1342
// this one is only defined here though:
 
1343
ISR(TIMER1_COMPA_vect, ISR_NAKED){ //hits when counter 1 reaches compare value
 
1344
        __asm__ __volatile__ (    //0x18 is PORTB
 
1345
          "sbic  " gbit_addr " , " gbit_pwm4zero_bit " \n\t" // if pwm4zero isn't set...
 
1346
      "rjmp .+2 " "\n\t"
 
1347
          "sbi 0x18 , " Quote(PWM4_PIN) " \n\t"  //set bit in PORTB (0x18) to make PW4_PIN high.
 
1348
          "reti" "\n\t"
 
1349
          :::);
 
1350
}
 
1351
#endif
 
1352
 
 
1353
#if defined(USE_OTSM) || defined(USE_ESWITCH)
 
1354
// Off-time sleep mode by -FR, thanks to flashy Mike and Mike C for early feasibility test with similar methods.
 
1355
 
 
1356
//need to declare main here to jump to it from ISR.
 
1357
int main();
 
1358
 
 
1359
// OS_task is a bit safer than naked,still allocates locals on stack if needed, although presently avoided.
 
1360
void __attribute__((OS_task, used, externally_visible)) PCINT0_vect (void) { 
 
1361
//ISR(PCINT0_vect, ISR_NAKED){// Dual watchdog pin change power-on wake by FR
 
1362
 
 
1363
        // 2017 by Flintrock (C)
 
1364
    //
 
1365
//PIN change interrupt.  This serves as the power down and power up interrupt, and starts the watchdog.
 
1366
//
 
1367
        /* IS_NAKED (or OS_task) IS ***DANGEROUS** remove it if you edit this function significantly
 
1368
         *  and aren't sure. You can remove it, and change the asm reti call below to a return.
 
1369
         * and remove the CLR R1. However, it saves about 40 bytes, which matters.
 
1370
         * The idea here, the compiler normally stores all registers used by the interrupt and
 
1371
         * restores them at the end of the interrupt.  This costs instructions (space).
 
1372
     * We won't return to the caller anyway, we're going to reset (so this is similar to a 
 
1373
         * tail call optimization).
 
1374
         * One tricky bit then is that we  get a re-entrant call here because 
 
1375
         * sleep and wake use the same interrupt, so we'll interrupt the sleep command below with a re-entry
 
1376
         * into this function on wake. The re-entry will pass the "if wake_count" conditional and immediately 
 
1377
         * return to the original instance. 
 
1378
         * We avoid touching much there by using a global register variable for wake_count.
 
1379
         * SREG is probably changed but since it only breaks out of the sleep there are
 
1380
         * no pending checks of result flags occurring. 
 
1381
         *
 
1382
         * Another issue is allocation of locals. Naked has no stack frame,
 
1383
         * but seems to properly force variables to register (better anyway) until it can't, 
 
1384
         * and then fails to compile (gcc 4.9.2) OS_task however will create a stack frame if needed and is 
 
1385
         * more documented/gauranteed/future-proof probably.
 
1386
         */
 
1387
//** For debugging
 
1388
        //cli();
 
1389
        //sei();
 
1390
       //#if defined(USE_OTSM)
 
1391
              //DIDR0&=~(1<<OTSM_PIN);
 
1392
           //#endif
 
1393
       //#if defined(USE_ESWITCH)
 
1394
          //DIDR0&=~(1<<ESWITCH_PIN);
 
1395
       //#endif
 
1396
 
 
1397
        __asm__ __volatile__ ("CLR R1"); // We do need a clean zero-register (yes, that's R1).
 
1398
        #ifdef USE_ESWITCH // for eswtich we'll modify the sleep loop after a few seconds.
 
1399
            register uint8_t sleep_time_exponent=SLEEP_TIME_EXPONENT; 
 
1400
        #else
 
1401
            #define sleep_time_exponent SLEEP_TIME_EXPONENT
 
1402
        #endif
 
1403
        if( wake_count ){// if we've already slept, so we're waking up. 
 
1404
                             // This is a register variable; no need to clean space for it.
 
1405
//              return; // we are waking up, do nothing and continue from where we slept (below).
 
1406
                __asm__ __volatile__ ("reti");
 
1407
        } // otherwise, we're  going to sleep
 
1408
// we only pass this section once, can do initialization here:  
 
1409
//    e_status=0b00000001;       //startoff in standby with pin low (button pressed)
 
1410
        cli();
 
1411
    ADCSRA = 0; //disable the ADC.  We're not coming back, no need to save it.
 
1412
        set_level(0); // Set all the outputs low.       
 
1413
        // Just the output-low of above, by itself, doesn't play well with 7135s.  Input high doesn't either
 
1414
        //  Even though in high is high impedance, I guess it's still too much current.
 
1415
        // What does work.. is input low:
 
1416
        #ifdef PWM_PIN
 
1417
            DDRB &= ~(1 << PWM_PIN) ;
 
1418
        #endif
 
1419
        #ifdef PWM2_PIN
 
1420
            DDRB &= ~(1 << PWM2_PIN) ;
 
1421
        #endif
 
1422
        #ifdef PWM3_PIN
 
1423
            DDRB &= ~(1 << PWM3_PIN) ;
 
1424
        #endif
 
1425
        #ifdef PWM4_PIN
 
1426
            DDRB &= ~(1 << PWM4_PIN) ;
 
1427
        #endif
 
1428
 
 
1429
#ifdef USE_ESWITCH
 
1430
     register uint8_t e_standdown=1; // pressing off, where we start
 
1431
     register uint8_t e_standby=0;  // pressing on
 
1432
         register uint8_t pins_state=0; // state of all switch pins.
 
1433
//     register uint8_t old_pins_state=0; // detect a change (a sane one at least).
 
1434
#endif
 
1435
 
 
1436
        while(1) { // keep going to sleep until power is on
 
1437
 
 
1438
         #ifdef USE_ESWITCH
 
1439
         /*  Three phases, 
 
1440
           * 1:standown: Still armed for short click restart on button release, counting time.
 
1441
           * 2:full off (neither standby nor standown). Long press time-out ocurerd, 
 
1442
           *           -button release does nothing on eswitch.
 
1443
           *           -button press arms standby mode.
 
1444
           * 3:standby:  Button is pressed for turn on, restart on release. No timing presently.
 
1445
           */
 
1446
          
 
1447
// enable digital input (want it off during shutdown to save power according to manual)
 
1448
//  not sure how we ever read these pins with this not done.
 
1449
       #if defined(USE_OTSM) && (OTSM_PIN != ESWITCH_PIN) 
 
1450
              register uint8_t e_pin_state = (lockswitch||(PINB&(1<<ESWITCH_PIN))); 
 
1451
              pins_state = e_pin_state&&(PINB&(1<<OTSM_PIN)); // if either switch is "pressed" (0) this is 0.
 
1452
           #else
 
1453
              pins_state=(PINB&(1<<ESWITCH_PIN));
 
1454
                  #if !defined(USE_OTSM)  // just an alias in this case to merge code paths:
 
1455
                    register uint8_t e_pin_state=pins_state; 
 
1456
                  #endif
 
1457
           #endif
 
1458
            if ( e_standdown){                  
 
1459
                   if ( pins_state ) {// if button released and still in standown, restart 
 
1460
                       break; // goto reset 
 
1461
          #if defined(USE_OTSM) && (OTSM_PIN == ESWITCH_PIN)
 
1462
                        } else if ( (wake_count>wake_count_med)) { // it's a long press
 
1463
                            e_standdown=0; // go to full off, this will stop the wake counter.
 
1464
                           _delay_loop_2(F_CPU/400); // if this was a clicky switch.. this will bring it down, 
 
1465
                                                     // don't want to come on in off mode.
 
1466
                          sleep_time_exponent=9; // 16ms*2^9=8s, maximum watchod timeout.
 
1467
                        }
 
1468
          #else 
 
1469
                        } else if (wake_count>wake_count_med && (!e_pin_state)) { // it's a long e-switch press
 
1470
                          e_standdown=0; // only go full off on e-switch press, count on cap to prevent counter overflow
 
1471
                                            // for clickly.
 
1472
                          sleep_time_exponent=9; // 16ms*2^9=8s, maximum watchod timeout.
 
1473
                        }
 
1474
                  #endif
 
1475
                continue; // still in standby, go back to sleep.
 
1476
            }
 
1477
        if (e_standby && pins_state  ) { // if button release while in standby, restart
 
1478
                break; // goto reset         //could merge this with e_standdown & pins_state above, might be smaller, might not.
 
1479
        }
 
1480
        if (!e_standdown && !e_standby && !pins_state   ) { // if button pressed while off, restart
 
1481
                           e_standby=1; // going to standby, will light when button is released         
 
1482
                } 
 
1483
            wake_count+= e_standdown; // increment click time if still in standdown mode.
 
1484
                // continue.. sleep more.
 
1485
         #else  // for simple OTSM, if power comes back, we're on:
 
1486
                if(PINB&(1<<OTSM_PIN)) {
 
1487
                         break; // goto reset
 
1488
            }  
 
1489
                wake_count++;
 
1490
         #endif
 
1491
 
 
1492
/***************** Wake on either a power-up (pin change) or a watchdog timeout************/
 
1493
                // At every watchdog wake, increment the wake counter and go back to sleep.
 
1494
         
 
1495
            set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 
1496
//              WDTCR = (1<<WDCE) |(1<<WDE);
 
1497
//              WDTCR = (0<<WDE);  // might already be in use, so we have to clear it.
 
1498
                WDTCR = (1<<WDIE) |(!!(sleep_time_exponent&8)<<WDP3)|(sleep_time_exponent&7<<WDP0); // set the watchdog timer: 2^n *16 ms datasheet pg 46 for table.
 
1499
                sleep_bod_disable();
 
1500
                sei(); // yep, we're going to nest interrupts, even re-entrenty into this one!
 
1501
                sleep_cpu();
 
1502
                        // return from wake ISR's here, both watchdog and pin change.
 
1503
                cli();
 
1504
                // Now just figure out what pins are pressed and if we're coming or going, not as simple as it sounds.
 
1505
 
 
1506
     }   
 
1507
         /*** Do a soft "reset" of sorts. **/
 
1508
     //
 
1509
         asm volatile ("" ::: "memory"); // just in case, no i/o reordering around these. It's a noop.
 
1510
     SPL = (RAMEND&0xff); // reset stack pointer, so if we keep going around we don't get a stack overflow. 
 
1511
#if (ATTINY == 45 ) || ( ATTINY == 85 )
 
1512
         SPH = RAMEND>>8; 
 
1513
#endif
 
1514
         SREG=0;  // clear status register
 
1515
     main(); // start over, bypassing initialization.
 
1516
                
 
1517
 
1518
 
 
1519
ISR(WDT_vect, ISR_NAKED) // watchdog interrupt handler -FR
 
1520
{ // gcc avr stacks empty interrupts with a bunch of un-needed initialization.
 
1521
  // do this in assembly and we get one instruction instead about 15.
 
1522
        __asm__ volatile("reti");
 
1523
}
 
1524
 
 
1525
#endif // OTSM
 
1526
 
 
1527
 
 
1528
 
 
1529
 
 
1530
// initializer added by Flintrock.  This goes into a "secret" code segment that gets run before main. 
 
1531
// It cannot be called. It's cheaper than breaking main into another sub.
 
1532
// It initializes "cold boot" values. A "reset" instead jumps to main after a switch press
 
1533
// and must then bypass the wake_counter initializer.
 
1534
// be careful in here, local variables are not technically allowed (no stack exists), but subroutine calls are.
 
1535
void __attribute__ ((naked)) __attribute__ ((section (".init8"))) \
 
1536
main_init () { 
 
1537
         initial_values(); // load defaults for eeprom config variables.
 
1538
   // initialize register variables, since gcc stubornly won't do it for us.
 
1539
         eepos=0;
 
1540
#if defined(USE_OTSM) || defined(USE_ESWITCH)
 
1541
     wake_count=255; // initial value on cold reboot, represents large click time.
 
1542
#endif
 
1543
}
 
1544
 
 
1545
int __attribute__((OS_task)) main()  { // Jump here from a wake interrupt, skipping initialization of wake_count.
 
1546
 
 
1547
// read OTC if needed, and translate it to an OTSM/E_switch wake_count value if using both:
 
1548
// If only OTC is used, the click decision in change modes is based directly on OTC value.
 
1549
// If OTSM and/or E_SWITCH is used, it's based on the OTSM/E_SWITCH wake_count.
 
1550
// If both E_SWITCH and OTC are used, for two switches (no OTSM), 
 
1551
//  wake_count is used, and the OTC value first gets translated to a wake_count value if we had a clicking switch press.
 
1552
// Could just always translate to wake_count, but it adds size.
 
1553
 
 
1554
 
 
1555
#if defined(OFFTIM3)&&defined(USE_OTC) 
 
1556
   #if !(defined(USE_OTSM)||defined(USE_ESWITCH))
 
1557
    // check the OTC immediately before it has a chance to charge or discharge
 
1558
      uint8_t cap_val = read_otc();
 
1559
   #elif defined(USE_ESWITCH)&!defined(USE_OTSM) 
 
1560
     if(wake_count==255) { //255 is re-initialized value, so we had a timed-out clicky press, must use OTC
 
1561
                                   // translate OTC readings to wake_count
 
1562
                                                   // could simplify and do this for normal OTC too (adds a few lines, but for a simple build anyway).
 
1563
                 uint8_t cap_val = read_otc();
 
1564
                 if (cap_val>CAP_MED) {
 
1565
                         wake_count=wake_count_med; // long press (>= is long)
 
1566
                 }else if (cap_val>CAP_SHORT){
 
1567
                         wake_count=wake_count_short; // med press
 
1568
                 }else{
 
1569
                         wake_count=0;               // short press                  
 
1570
             }
 
1571
         }
 
1572
   #elif defined(USE_OTSM)
 
1573
     #error You cannot define USE_OTSM and USE_OTC at the same time.
 
1574
   #endif
 
1575
#endif
 
1576
 
 
1577
    init_mcu(); // setup pins, prescalers etc, configure/enable interrupts, etc.
 
1578
 
 
1579
#ifdef VOLTAGE_CAL
 
1580
        voltage_cal();
 
1581
#endif
 
1582
 
 
1583
#ifdef OTC_debug
 
1584
blink_value(cap_val);
 
1585
 return 0;
 
1586
#endif
 
1587
 
 
1588
    restore_state(); // loads user configurations
 
1589
 
 
1590
#ifdef OTSM_debug // for testing your OTSM hardware 
 
1591
                 // blink out the wake count, then continue into mode as normal.                 
 
1592
    if (wake_count!=255) {
 
1593
      uint8_t temp=wake_count;
 
1594
          wake_count=0; // this just resets wake_count while blinking so we can click off early and it still works.
 
1595
                      // use 0 for debugging but will start at 255 in real use.
 
1596
      blink_value(temp);
 
1597
        } 
 
1598
        //else {
 
1599
        //cli(); 
 
1600
        //_delay_s(); _delay_s(); // this will increase current for two seconds if otsm_powersave is used.
 
1601
                              //// provides a debug singal through the ameter. 
 
1602
        //sei();
 
1603
        //}
 
1604
//    wake_time=0;  // use this to make every click act like a fast one for debugging.
 
1605
#endif
 
1606
    count_modes(); // build the working mode group using configured choices.
 
1607
 
 
1608
#if defined(USE_OTSM) || defined(USE_ESWITCH) 
 
1609
        change_mode(); // advance, reverse, stay put?
 
1610
        wake_count=0; // reset the wake counter.
 
1611
#elif !defined(USE_OTC) // no cap_val but no wake_count either (fast_presses method)
 
1612
        change_mode(); // advance, reverse, stay put?
 
1613
#else // use the cap value, note eswitch+OTC does NOT use cap_val here, cap val is translated above to wake_count in that case.
 
1614
        change_mode(cap_val); // advance, reverse, stay put?
 
1615
#endif
 
1616
//blink_value(cap_val);
 
1617
//blink_value(mode_idx);
 
1618
 
 
1619
        save_mode();
 
1620
#ifdef VOLTAGE_MON
 
1621
    ADC_on(); 
 
1622
#endif
 
1623
 
 
1624
 
 
1625
    uint8_t output; // defines the nominal mode for program control.
 
1626
    uint8_t actual_level; // allows modifications for stepdown etc.
 
1627
#if defined(TEMPERATURE_MON)||defined(USE_TURBO_TIMEOUT)
 
1628
    uint8_t overheat_count = 0;
 
1629
#endif
 
1630
    uint8_t i = 0;
 
1631
#ifdef VOLTAGE_MON
 
1632
    uint8_t lowbatt_cnt = 0;
 
1633
#endif
 
1634
    // handle mode overrides, like mode group selection and temperature calibration
 
1635
//    if (mode_override) {
 
1636
    if (mode_idx>=MINIMUM_OVERRIDE_MODE) {
 
1637
        // do nothing; mode is already set
 
1638
//        fast_presses = 0;
 
1639
//              clear_presses(); // redundant, already clear on menu entry
 
1640
                         // and had to go through menu to get to an override mode.
 
1641
                                                 // at most fast_presses now is 1, saves 6 bytes.
 
1642
        output = mode_idx; // not a typo. override modes don't get converted to an actual output level.
 
1643
    } else {
 
1644
      output = modes[mode_idx];
 
1645
      actual_level = output;
 
1646
        }
 
1647
    while(1) {
 
1648
         if (fast_presses > 0x0f) {  // Config mode
 
1649
            _delay_s();       // wait for user to stop fast-pressing button
 
1650
//            fast_presses = 0; // exit this mode after one use
 
1651
                        clear_presses();
 
1652
//            mode_idx = 0;
 
1653
                        toggles(); // this is the main menu
 
1654
// The old way: (commented out at bottom of file)       
 
1655
 
 
1656
            mode_idx = 0;
 
1657
            output = modes[mode_idx];  
 
1658
            actual_level = output; 
 
1659
        }
 
1660
#if !defined(NO_STROBES)
 
1661
 
 
1662
// Tried saving some space on these strobes, but it's not easy. gcc does ok though.
 
1663
// Using a switch does create different code (more jump-table-ish, kind of), but it's not shorter.
 
1664
#ifdef STROBE_10HZ
 
1665
        else if (output == STROBE_10HZ) {
 
1666
            // 10Hz tactical strobe
 
1667
            strobe(33,67);
 
1668
        }
 
1669
#endif // ifdef STROBE_10HZ
 
1670
#ifdef STROBE_16HZ
 
1671
        else if (output == STROBE_16HZ) {
 
1672
            // 16.6Hz tactical strobe
 
1673
            strobe(20,40);
 
1674
        }
 
1675
#endif // ifdef STROBE_16HZ
 
1676
#ifdef STROBE_8HZ
 
1677
        else if (output == STROBE_8HZ) {
 
1678
            // 8.3Hz Tactical strobe
 
1679
            strobe(40,80);
 
1680
        }
 
1681
#endif // ifdef STROBE_8HZ
 
1682
#ifdef STROBE_OLD_MOVIE
 
1683
        else if (output == STROBE_OLD_MOVIE) {
 
1684
            // Old movie effect strobe, like you some stop motion?
 
1685
            strobe(1,41);
 
1686
        }
 
1687
#endif // ifdef STROBE_OLD_MOVIE
 
1688
#ifdef STROBE_CREEPY
 
1689
        else if (output == STROBE_CREEPY) {
 
1690
            // Creepy effect strobe stop motion effect that is quite cool or quite creepy, dpends how many friends you have with you I suppose.
 
1691
            strobe(1,82);
 
1692
        }
 
1693
#endif // ifdef STROBE_CREEPY
 
1694
 
 
1695
#ifdef POLICE_STROBE
 
1696
        else if (output == POLICE_STROBE) {
 
1697
 
 
1698
            // police-like strobe
 
1699
            //for(i=0;i<8;i++) {
 
1700
                 strobe(20,40);
 
1701
            //}
 
1702
            //for(i=0;i<8;i++) {
 
1703
                 strobe(40,80);
 
1704
            //}
 
1705
        }
 
1706
#endif // ifdef POLICE_STROBE
 
1707
#ifdef RANDOM_STROBE
 
1708
        else if (output == RANDOM_STROBE) {
 
1709
            // pseudo-random strobe
 
1710
            uint8_t ms = 34 + (pgm_rand() & 0x3f);
 
1711
            strobe(ms, ms);
 
1712
            //strobe(ms, ms);
 
1713
        }
 
1714
#endif // ifdef RANDOM_STROBE
 
1715
#ifdef BIKING_STROBE
 
1716
        else if (output == BIKING_STROBE) {
 
1717
            // 2-level stutter beacon for biking and such
 
1718
#ifdef FULL_BIKING_STROBE
 
1719
            // normal version
 
1720
            for(i=0;i<4;i++) {
 
1721
                set_level(TURBO);
 
1722
                //set_output(255,0,0);
 
1723
                _delay_ms(5);
 
1724
                set_level(ONE7135);
 
1725
                //set_output(0,0,255);
 
1726
                _delay_ms(65);
 
1727
            }
 
1728
            _delay_ms(720);
 
1729
#else
 
1730
            // small/minimal version
 
1731
            set_level(TURBO);
 
1732
            //set_output(255,0,0);
 
1733
            _delay_ms(10);
 
1734
            set_level(ONE7135);
 
1735
            //set_output(0,0,255);
 
1736
            _delay_s();
 
1737
#endif
 
1738
        }
 
1739
#endif  // ifdef BIKING_STROBE
 
1740
#ifdef SOS
 
1741
        else if (output == SOS) { SOS_mode(); }
 
1742
#endif // ifdef SOS
 
1743
#ifdef RAMP
 
1744
        else if (output == RAMP) {
 
1745
            int8_t r;
 
1746
            // simple ramping test
 
1747
            for(r=1; r<=RAMP_SIZE; r++) {
 
1748
                set_level(r);
 
1749
                _delay_ms(40);
 
1750
            }
 
1751
            for(r=RAMP_SIZE; r>0; r--) {
 
1752
                set_level(r);
 
1753
                _delay_ms(40);
 
1754
            }
 
1755
        }
 
1756
#endif  // ifdef RAMP
 
1757
#endif // if !defined(NO_STROBES)
 
1758
#ifdef USE_BATTCHECK
 
1759
        else if (output == BATTCHECK) {
 
1760
#ifdef BATTCHECK_VpT
 
1761
                        //blink_value(get_voltage()); // for debugging
 
1762
            // blink out volts and tenths
 
1763
            _delay_ms(100);
 
1764
            uint8_t result = battcheck();
 
1765
            blink(result >> 5, BLINK_SPEED/6);
 
1766
            _delay_ms(BLINK_SPEED);
 
1767
            blink(1,5);
 
1768
            _delay_ms(BLINK_SPEED*3/2);
 
1769
            blink(result & 0b00011111, BLINK_SPEED/6);
 
1770
#else  // ifdef BATTCHECK_VpT
 
1771
            // blink zero to five times to show voltage
 
1772
            // (~0%, ~25%, ~50%, ~75%, ~100%, >100%)
 
1773
            blink(battcheck(), BLINK_SPEED/6);
 
1774
#endif  // ifdef BATTCHECK_VpT
 
1775
            // wait between readouts
 
1776
            _delay_s(); _delay_s();
 
1777
        }
 
1778
#endif // ifdef USE_BATTCHECK
 
1779
        else if (output == GROUP_SELECT_MODE) {
 
1780
            // exit this mode after one use
 
1781
            mode_idx = 0;
 
1782
//            mode_override = 0;
 
1783
 
 
1784
            for(i=0; i<NUM_MODEGROUPS; i++) {
 
1785
                modegroup = i;
 
1786
                save_state();
 
1787
 
 
1788
                blink(1, BLINK_SPEED/3);
 
1789
            }
 
1790
            _delay_s(); _delay_s();
 
1791
        }
 
1792
#ifdef TEMP_CAL_MODE
 
1793
#ifdef TEMPERATURE_MON
 
1794
        else if (output == TEMP_CAL_MODE) {
 
1795
            // make sure we don't stay in this mode after button press
 
1796
            mode_idx = 0;
 
1797
//            mode_override = 0;
 
1798
 
 
1799
            // Allow the user to turn off thermal regulation if they want
 
1800
            maxtemp = 255;
 
1801
            save_state(); 
 
1802
            set_mode(RAMP_SIZE/4);  // start somewhat dim during turn-off-regulation mode
 
1803
            _delay_s(); _delay_s();
 
1804
 
 
1805
            // run at highest output level, to generate heat
 
1806
            set_mode(RAMP_SIZE);
 
1807
 
 
1808
            // measure, save, wait...  repeat
 
1809
            while(1) {
 
1810
                maxtemp = get_temperature();
 
1811
                save_state();
 
1812
                _delay_s(); _delay_s();
 
1813
            }
 
1814
        }
 
1815
#endif
 
1816
#endif  // TEMP_CAL_MODE
 
1817
        else {  // Regular non-hidden solid mode
 
1818
//  moved this before temp check.  Temp check result will still apply on next loop.
 
1819
// reason is with Vcc reads, we switch back and forth between ADC channels.
 
1820
//  The get temperature includes a delay to stabilize ADC (maybe not needed)
 
1821
//   That delay results in hesitation at turn on.
 
1822
//  So turn on first.
 
1823
               set_mode(actual_level);             
 
1824
#ifdef TEMPERATURE_MON  
 
1825
            uint8_t temp=get_temperature();
 
1826
 
 
1827
            // step down? (or step back up?)
 
1828
            if (temp >= maxtemp) {
 
1829
                overheat_count ++;
 
1830
                // reduce noise, and limit the lowest step-down level
 
1831
                if ((overheat_count > 8) && (actual_level > (RAMP_SIZE/8))) {
 
1832
                    actual_level --;
 
1833
                    //_delay_ms(5000);  // don't ramp down too fast
 
1834
                    overheat_count = 0;  // don't ramp down too fast
 
1835
                }
 
1836
            } else {
 
1837
                // if we're not overheated, ramp up  the user-requested level
 
1838
                overheat_count = 0;
 
1839
                if ((temp < maxtemp - 2) && (actual_level < output)) {
 
1840
                    actual_level ++;
 
1841
                }
 
1842
            }
 
1843
//            set_mode(actual_level); // redundant
 
1844
                        #ifdef VOLTAGE_MON
 
1845
                            ADC_on();  // switch back to voltage mode
 
1846
                        #endif
 
1847
 
 
1848
#endif
 
1849
            _delay_ms(LOOP_SLEEP); // sleep then check vital signs.
 
1850
                                               // do the sleep after temp check to create stabilization time after switching adc channel
 
1851
                                  // this does create a slight feedback delay, but not much.
 
1852
#ifdef USE_TURBO_TIMEOUT
 
1853
            // modified from BLFA6
 
1854
                        if (output == TURBO) {
 
1855
            overheat_count++;  // actually, we don't care about roll-over prevention
 
1856
              if (overheat_count > (uint8_t)((double)(TURBO_TIMEOUT)*(double)1000/(double)LOOP_SLEEP)) {
 
1857
                        // can't use BLFA6 mode change since we don't have predictable modes.
 
1858
                        // Must change actual_level, and lockout mode advance on next click.
 
1859
                output=TURBO_STEPDOWN;
 
1860
                actual_level=TURBO_STEPDOWN;
 
1861
                                         set_presses(DISABLE_NEXT); // next forward press will keep turbo mode.
 
1862
              }
 
1863
                        }
 
1864
#endif
 
1865
        } // end regular mode
 
1866
 
 
1867
//****** Now things to do in loop after every mode **************/
 
1868
 
 
1869
        clear_presses(); //Theory here requires that every mode/strobe takes at least some time to get here.
 
1870
                                  // see note in strobe() function.
 
1871
#ifdef VOLTAGE_MON
 
1872
        //if (ADCSRA & (1 << ADIF)) {  // if a voltage reading is ready
 
1873
                                                    //  FR says good idea, but it only takes 100us at worst.
 
1874
                                                                                // let's save a few bytes of code instead.
 
1875
            // See if voltage is lower than what we were looking for
 
1876
            //uint8_t temp=get_voltage();
 
1877
                        //blink_value(temp);
 
1878
            //if (temp < ADC_LOW) {
 
1879
            if (get_voltage() < ADC_LOW) {
 
1880
                lowbatt_cnt ++;
 
1881
            } else {
 
1882
                lowbatt_cnt = 0;
 
1883
            }
 
1884
            // See if it's been low for a while, and maybe step down
 
1885
            if (lowbatt_cnt >= 8) {
 
1886
                // DEBUG: blink on step-down:
 
1887
                //set_level(0);  _delay_ms(100);
 
1888
 
 
1889
                if (actual_level > RAMP_SIZE) {  // hidden / blinky modes
 
1890
                    // step down from blinky modes to medium
 
1891
                    actual_level = RAMP_SIZE / 2;
 
1892
                } else if (actual_level > 1) {  // regular solid mode
 
1893
                    // step down from solid modes somewhat gradually
 
1894
                    // drop by 25% each time
 
1895
                    actual_level = (actual_level >> 2) + (actual_level >> 1);
 
1896
                    // drop by 50% each time
 
1897
                    //actual_level = (actual_level >> 1);
 
1898
                } else { // Already at the lowest mode
 
1899
                    // Turn off the light
 
1900
                    set_level(0);
 
1901
                    // Power down as many components as possible
 
1902
                    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 
1903
                                        cli(); // make sure not to wake back up.
 
1904
                                #if (ATTINY>13)
 
1905
                                        sleep_bod_disable();// power goes from 25uA to 4uA.
 
1906
                                #endif
 
1907
                    sleep_mode();
 
1908
                }
 
1909
//                set_mode(actual_level); // redundant
 
1910
                output = actual_level;
 
1911
                lowbatt_cnt = 0;
 
1912
                // Wait before lowering the level again
 
1913
                //_delay_ms(250);
 
1914
            }
 
1915
            // Make sure conversion is running for next time through
 
1916
            //ADCSRA |= (1 << ADSC);
 
1917
        //}
 
1918
#endif  // ifdef VOLTAGE_MON
 
1919
    }// end of main while loop
 
1920
    //return 0; // Standard Return Code
 
1921
}
 
1922
 
 
1923
 
 
1924
// The old way to do the toggles, in case we need it back:
 
1925
            //// Enter or leave "muggle mode"?
 
1926
            //toggle(&muggle_mode, 1);
 
1927
            //if (muggle_mode) { continue; };  // don't offer other options in muggle mode
 
1928
//
 
1929
            //toggle(&memory, 2);
 
1930
//
 
1931
            //toggle(&enable_moon, 3);
 
1932
//
 
1933
            //toggle(&reverse_modes, 4);
 
1934
//
 
1935
            //// Enter the mode group selection mode?
 
1936
            //mode_idx = GROUP_SELECT_MODE;
 
1937
            //toggle(&mode_override, 5);
 
1938
            //mode_idx = 0;
 
1939
//
 
1940
//#ifdef OFFTIM3
 
1941
            //toggle(&offtim3, 6);
 
1942
//#endif
 
1943
//
 
1944
//#ifdef TEMPERATURE_MON
 
1945
            //// Enter temperature calibration mode?
 
1946
            //mode_idx = TEMP_CAL_MODE;
 
1947
            //toggle(&mode_override, 7);
 
1948
            //mode_idx = 0;
 
1949
//#endif
 
1950
 
 
1951
//#ifdef USE_FIRSTBOOT
 
1952
            //toggle(&firstboot, 8);
 
1953
//#endif
 
1954
//#if defined(USE_ESWITCH) && (OTSM_PIN != ESWITCH_PIN)
 
1955
            //toggle(&lockswitch, 9);
 
1956
//#endif