Advertisement
Guest User

Untitled

a guest
Sep 27th, 2016
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 42.06 KB | None | 0 0
  1. /*
  2.  * "Bistro" firmware
  3.  * This code runs on a single-channel or dual-channel driver (FET+7135)
  4.  * with an attiny25/45/85 MCU and a capacitor to measure offtime (OTC).
  5.  *
  6.  * Copyright (C) 2015 Selene Scriven
  7.  *
  8.  * This program is free software: you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation, either version 3 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20.  *
  21.  *
  22.  * ATTINY25/45/85 Diagram
  23.  *           ----
  24.  *         -|1  8|- VCC
  25.  *     OTC -|2  7|- Voltage ADC
  26.  *  Star 3 -|3  6|- PWM (FET, optional)
  27.  *     GND -|4  5|- PWM (1x7135)
  28.  *           ----
  29.  *
  30.  * FUSES
  31.  *      I use these fuse settings on attiny25
  32.  *      Low:  0xd2
  33.  *      High: 0xde
  34.  *      Ext:  0xff
  35.  *
  36.  *      For more details on these settings:
  37.  *      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
  38.  *
  39.  * STARS
  40.  *      Star 3 = unused
  41.  *
  42.  * CALIBRATION
  43.  *
  44.  *   To find out what values to use, flash the driver with battcheck.hex
  45.  *   and hook the light up to each voltage you need a value for.  This is
  46.  *   much more reliable than attempting to calculate the values from a
  47.  *   theoretical formula.
  48.  *
  49.  *   Same for off-time capacitor values.  Measure, don't guess.
  50.  */
  51. // Choose your MCU here, or in the build script
  52. //#define ATTINY 13
  53. //#define ATTINY 25
  54. // FIXME: make 1-channel vs 2-channel power a single #define option
  55. //#define FET_7135_LAYOUT  // specify an I/O pin layout
  56. #define TRIPLEDOWN_LAYOUT  // specify an I/O pin layout
  57. // Also, assign I/O pins in this file:
  58. #ifndef TK_ATTINY_H
  59. #define TK_ATTINY_H
  60. // Choose your MCU here, or in the main .c file, or in the build script
  61. //#define ATTINY 13
  62. //#define ATTINY 25
  63.  
  64. /******************** hardware-specific values **************************/
  65. #if (ATTINY == 13)
  66.     #define F_CPU 4800000UL
  67.     #define EEPSIZE 64
  68.     #define V_REF REFS0
  69.     #define BOGOMIPS 950
  70. #elif (ATTINY == 25)
  71.     // TODO: Use 6.4 MHz instead of 8 MHz?
  72.     #define F_CPU 8000000UL
  73.     #define EEPSIZE 128
  74.     #define V_REF REFS1
  75.     #define BOGOMIPS (F_CPU/3200)
  76. #else
  77.     Hey, you need to define ATTINY.
  78. #endif
  79.  
  80.  
  81. /******************** I/O pin and register layout ************************/
  82. #ifdef FET_7135_LAYOUT
  83. /*
  84.  *           ----
  85.  *   Reset -|1  8|- VCC
  86.  *     OTC -|2  7|- Voltage ADC
  87.  *  Star 3 -|3  6|- PWM (FET)
  88.  *     GND -|4  5|- PWM (1x7135)
  89.  *           ----
  90.  */
  91.  
  92. #define STAR2_PIN   PB0     // If this pin isn't used for ALT_PWM
  93. #define STAR3_PIN   PB4     // pin 3
  94.  
  95. #define CAP_PIN     PB3     // pin 2, OTC
  96. #define CAP_CHANNEL 0x03    // MUX 03 corresponds with PB3 (Star 4)
  97. #define CAP_DIDR    ADC3D   // Digital input disable bit corresponding with PB3
  98.  
  99. #define PWM_PIN     PB1     // pin 6, FET PWM
  100. #define PWM_LVL     OCR0B   // OCR0B is the output compare register for PB1
  101. #define ALT_PWM_PIN PB0     // pin 5, 1x7135 PWM
  102. #define ALT_PWM_LVL OCR0A   // OCR0A is the output compare register for PB0
  103.  
  104. #define VOLTAGE_PIN PB2     // pin 7, voltage ADC
  105. #define ADC_CHANNEL 0x01    // MUX 01 corresponds with PB2
  106. #define ADC_DIDR    ADC1D   // Digital input disable bit corresponding with PB2
  107. #define ADC_PRSCL   0x06    // clk/64
  108.  
  109. //#define TEMP_DIDR   ADC4D
  110. #define TEMP_CHANNEL 0b00001111
  111.  
  112. #endif  // FET_7135_LAYOUT
  113.  
  114. #ifdef TRIPLEDOWN_LAYOUT
  115. /*
  116.  *             ----
  117.  *     Reset -|1  8|- VCC
  118.  *       OTC -|2  7|- Voltage ADC
  119.  * PWM (FET) -|3  6|- PWM (6x7135)
  120.  *       GND -|4  5|- PWM (1x7135)
  121.  *             ----
  122.  */
  123.  
  124. #define STAR2_PIN   PB0     // If this pin isn't used for ALT_PWM
  125.  
  126. #define CAP_PIN     PB3     // pin 2, OTC
  127. #define CAP_CHANNEL 0x03    // MUX 03 corresponds with PB3 (Star 4)
  128. #define CAP_DIDR    ADC3D   // Digital input disable bit corresponding with PB3
  129.  
  130. #define PWM_PIN     PB1     // pin 6, 6x7135 PWM
  131. #define PWM_LVL     OCR0B   // OCR0B is the output compare register for PB1
  132. #define ALT_PWM_PIN PB0     // pin 5, 1x7135 PWM
  133. #define ALT_PWM_LVL OCR0A   // OCR0A is the output compare register for PB0
  134. #define FET_PWM_PIN PB4     // pin 3
  135. #define FET_PWM_LVL OCR1B   // output compare register for PB4
  136.  
  137. #define VOLTAGE_PIN PB2     // pin 7, voltage ADC
  138. #define ADC_CHANNEL 0x01    // MUX 01 corresponds with PB2
  139. #define ADC_DIDR    ADC1D   // Digital input disable bit corresponding with PB2
  140. #define ADC_PRSCL   0x06    // clk/64
  141.  
  142. //#define TEMP_DIDR   ADC4D
  143. #define TEMP_CHANNEL 0b00001111
  144.  
  145. #endif  // FET_7135_LAYOUT
  146.  
  147. #ifdef FERRERO_ROCHER_LAYOUT
  148. /*
  149.  *            ----
  150.  *    Reset -|1  8|- VCC
  151.  * E-switch -|2  7|- Voltage ADC
  152.  *  Red LED -|3  6|- PWM
  153.  *      GND -|4  5|- Green LED
  154.  *            ----
  155.  */
  156. // TODO: fill in this section, update Ferrero_Rocher code to use it.
  157. #endif  // FERRERO_ROCHER_LAYOUT
  158.  
  159. #ifdef NANJG_LAYOUT
  160. #define STAR2_PIN   PB0
  161. #define STAR3_PIN   PB4
  162. #define STAR4_PIN   PB3
  163. #define PWM_PIN     PB1
  164. #define VOLTAGE_PIN PB2
  165. #define ADC_CHANNEL 0x01    // MUX 01 corresponds with PB2
  166. #define ADC_DIDR    ADC1D   // Digital input disable bit corresponding with PB2
  167. #define ADC_PRSCL   0x06    // clk/64
  168.  
  169. #define PWM_LVL     OCR0B   // OCR0B is the output compare register for PB1
  170. #endif  // NANJG_LAYOUT
  171.  
  172. #ifndef PWM_LVL
  173.     Hey, you need to define an I/O pin layout.
  174. #endif
  175.  
  176. #endif  // TK_ATTINY_H
  177.  
  178.  
  179.  
  180. /*
  181.  * =========================================================================
  182.  * Settings to modify per driver
  183.  */
  184.  
  185. // FIXME: make 1-channel vs 2-channel power a single #define option
  186. //#define FAST 0x23           // fast PWM channel 1 only
  187. //#define PHASE 0x21          // phase-correct PWM channel 1 only
  188. #define FAST 0xA3           // fast PWM both channels
  189. #define PHASE 0xA1          // phase-correct PWM both channels
  190.  
  191. #define VOLTAGE_MON         // Comment out to disable LVP
  192.  
  193. #define OFFTIM3             // Use short/med/long off-time presses
  194.                             // instead of just short/long
  195.  
  196. // ../../bin/level_calc.py 64 1 10 1300 y 3 0.23 140
  197. #define RAMP_SIZE  40
  198. // log curve
  199. //#define RAMP_7135  3,3,3,3,3,3,4,4,4,4,4,5,5,5,6,6,7,7,8,9,10,11,12,13,15,16,18,21,23,27,30,34,39,44,50,57,65,74,85,97,111,127,145,166,190,217,248,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
  200. //#define RAMP_FET   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,6,11,17,23,30,39,48,59,72,86,103,121,143,168,197,255
  201. // x**2 curve
  202. //#define RAMP_7135  3,5,8,12,17,24,32,41,51,63,75,90,105,121,139,158,178,200,223,247,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
  203. //#define RAMP_FET   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,6,9,12,16,19,22,26,30,33,37,41,45,50,54,59,63,68,73,78,84,89,94,100,106,111,117,123,130,136,142,149,156,162,169,176,184,191,198,206,214,221,255
  204. // x**3 curve
  205. // ../../bin/level_calc.py 3 40 7135 3 0.25 140 7135 3 1.5 840 FET 1 10 3000
  206. // (with some manual tweaks to exactly hit 1x7135 and Nx7135 in the middle)
  207. //#define ONE7135 14
  208. //#define ALL7135s 27
  209. //#define RAMP_7135  3,4,7,11,18,27,40,57,77,103,133,169,211,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
  210. //#define RAMP_7135s 0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,22,35,49,64,82,101,122,144,169,195,224,255,255,255,255,255,255,255,255,255,255,255,255,255,0
  211. //#define RAMP_FET   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,24,39,55,73,91,111,132,154,177,202,228,255
  212. // testing only: First 3 modes show each channel individually
  213. //#define RAMP_7135  255,0,0,11,18,27,40,57,77,103,133,169,211,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
  214. //#define RAMP_7135s 0,255,0,0,0,0,0,0,0,0,0,0,0,0,11,22,35,49,64,82,101,122,144,169,195,224,255,255,255,255,255,255,255,255,255,255,255,255,255,0
  215. //#define RAMP_FET   0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,24,39,55,73,91,111,132,154,177,202,228,255
  216. // 1200-lm single LED: ../../bin/level_calc.py 3 40 7135 3 0.25 160 7135 3 1.5 760 FET 1 3 1200
  217. #define RAMP_7135   3,4,5,7,10,14,19,25,33,43,54,67,83,101,121,144,170,198,230,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
  218. #define RAMP_7135s  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,18,28,40,52,65,78,92,107,124,143,163,184,207,230,255,255,255,255,0
  219. #define RAMP_FET    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33,103,177,255
  220. #define ONE7135 20
  221. #define ALL7135s 36
  222. // x**5 curve
  223. //#define RAMP_7135  3,3,3,4,4,5,5,6,7,8,10,11,13,15,18,21,24,28,33,38,44,50,57,66,75,85,96,108,122,137,154,172,192,213,237,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
  224. //#define RAMP_FET   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,6,9,13,17,21,25,30,35,41,47,53,60,67,75,83,91,101,111,121,132,144,156,169,183,198,213,255
  225.  
  226. // uncomment to ramp up/down to a mode instead of jumping directly
  227. #define SOFT_START
  228.  
  229. // Enable battery indicator mode?
  230. #define USE_BATTCHECK
  231. // Choose a battery indicator style
  232. //#define BATTCHECK_4bars  // up to 4 blinks
  233. //#define BATTCHECK_8bars  // up to 8 blinks
  234. #define BATTCHECK_VpT  // Volts + tenths
  235.  
  236. // output to use for blinks on battery check (and other modes)
  237. #define BLINK_BRIGHTNESS    RAMP_SIZE/4
  238. // ms per normal-speed blink
  239. #define BLINK_SPEED         500
  240.  
  241. // Hidden modes are *before* the lowest (moon) mode, and should be specified
  242. // in reverse order.  So, to go backward from moon to turbo to strobe to
  243. // battcheck, use BATTCHECK,STROBE,TURBO .
  244. //#define HIDDENMODES         BIKING_STROBE,BATTCHECK,POLICE_STROBE,TURBO
  245. #define HIDDENMODES         BATTCHECK,RAMP,TURBO
  246.  
  247. #define TURBO     RAMP_SIZE       // Convenience code for turbo mode
  248. #define BATTCHECK 254       // Convenience code for battery check mode
  249. #define GROUP_SELECT_MODE 253
  250. #define TEMP_CAL_MODE 252
  251. // Uncomment to enable tactical strobe mode
  252. //#define STROBE    251       // Convenience code for strobe mode
  253. // Uncomment to unable a 2-level stutter beacon instead of a tactical strobe
  254. //#define BIKING_STROBE 250   // Convenience code for biking strobe mode
  255. // comment out to use minimal version instead (smaller)
  256. #define FULL_BIKING_STROBE
  257. #define RAMP 249       // ramp test mode for tweaking ramp shape
  258. //#define POLICE_STROBE 248
  259. //#define RANDOM_STROBE 247
  260.  
  261. // thermal step-down
  262. #define TEMPERATURE_MON
  263.  
  264. // Calibrate voltage and OTC in this file:
  265. #ifndef TK_CALIBRATION_H
  266. #define TK_CALIBRATION_H
  267.  
  268. /********************** Voltage ADC calibration **************************/
  269. // These values were measured using RMM's FET+7135.
  270. // See battcheck/readings.txt for reference values.
  271. // the ADC values we expect for specific voltages
  272. #define ADC_44     194
  273. #define ADC_43     189
  274. #define ADC_42     184
  275. #define ADC_41     178
  276. #define ADC_40     173
  277. #define ADC_39     168
  278. #define ADC_38     163
  279. #define ADC_37     158
  280. #define ADC_36     152
  281. #define ADC_35     147
  282. #define ADC_34     142
  283. #define ADC_33     137
  284. #define ADC_32     131
  285. #define ADC_31     126
  286. #define ADC_30     121
  287. #define ADC_29     116
  288. #define ADC_28     111
  289. #define ADC_27     105
  290. #define ADC_26     100
  291. #define ADC_25     95
  292. #define ADC_24     90
  293. #define ADC_23     84
  294. #define ADC_22     79
  295. #define ADC_21     74
  296. #define ADC_20     69
  297.  
  298. #define ADC_100p   ADC_42  // the ADC value for 100% full (resting)
  299. #define ADC_75p    ADC_40  // the ADC value for 75% full (resting)
  300. #define ADC_50p    ADC_38  // the ADC value for 50% full (resting)
  301. #define ADC_25p    ADC_35  // the ADC value for 25% full (resting)
  302. #define ADC_0p     ADC_30  // the ADC value for 0% full (resting)
  303. #define ADC_LOW    ADC_28  // When do we start ramping down
  304. #define ADC_CRIT   ADC_27  // When do we shut the light off
  305.  
  306.  
  307. /********************** Offtime capacitor calibration ********************/
  308. // Values are between 1 and 255, and can be measured with offtime-cap.c
  309. // See battcheck/otc-readings.txt for reference values.
  310. // These #defines are the edge boundaries, not the center of the target.
  311. #ifdef OFFTIM3
  312. // The OTC value 0.5s after being disconnected from power
  313. // (anything higher than this is a "short press")
  314. #define CAP_SHORT           190
  315. // The OTC value 1.5s after being disconnected from power
  316. // Between CAP_MED and CAP_SHORT is a "medium press"
  317. #define CAP_MED             94
  318. // Below CAP_MED is a long press
  319. #else
  320. // The OTC value 1.0s after being disconnected from power
  321. // Anything higher than this is a short press, lower is a long press
  322. #define CAP_SHORT           115
  323. #endif
  324.  
  325.  
  326. #endif  // TK_CALIBRATION_H
  327.  
  328.  
  329.  
  330. /*
  331.  * =========================================================================
  332.  */
  333.  
  334. // Ignore a spurious warning, we did the cast on purpose
  335. #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
  336.  
  337. #include <avr/pgmspace.h>
  338. //#include <avr/io.h>
  339. //#include <avr/interrupt.h>
  340. #include <avr/eeprom.h>
  341. #include <avr/sleep.h>
  342. //#include <avr/power.h>
  343. #include <string.h>
  344.  
  345. #define OWN_DELAY           // Don't use stock delay functions.
  346. #define USE_DELAY_S         // Also use _delay_s(), not just _delay_ms()
  347. #ifndef TK_DELAY_H
  348. #define TK_DELAY_H
  349.  *
  350.  */
  351.  
  352. #ifdef OWN_DELAY
  353. #include "tk-attiny.h"
  354. #include <util/delay_basic.h>
  355. // Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
  356. void _delay_ms(uint16_t n)
  357. {
  358.     // TODO: make this take tenths of a ms instead of ms,
  359.     // for more precise timing?
  360.     //#ifdef USE_FINE_DELAY
  361.     //if (n==0) { _delay_loop_2(BOGOMIPS/3); }
  362.     //else {
  363.     //    while(n-- > 0) _delay_loop_2(BOGOMIPS);
  364.     //}
  365.     //#else
  366.     while(n-- > 0) _delay_loop_2(BOGOMIPS);
  367.     //#endif
  368. }
  369. #ifdef USE_FINE_DELAY
  370. void _delay_zero() {
  371.     _delay_loop_2(BOGOMIPS/3);
  372. }
  373. #endif
  374. #ifdef USE_DELAY_S
  375. void _delay_s()  // because it saves a bit of ROM space to do it this way
  376. {
  377.     _delay_ms(1000);
  378. }
  379. #endif
  380. #else
  381. #include <util/delay.h>
  382. #endif
  383.  
  384.  
  385. #endif  // TK_DELAY_H
  386.  
  387.  
  388.  
  389. #ifndef TK_VOLTAGE_H
  390. #define TK_VOLTAGE_H
  391.  
  392. #include "tk-attiny.h"
  393. #include "tk-calibration.h"
  394.  
  395. #ifdef TEMPERATURE_MON
  396. inline void ADC_on_temperature() {
  397.     // TODO: (?) enable ADC Noise Reduction Mode, Section 17.7 on page 128
  398.     //       (apparently can only read while the CPU is in idle mode though)
  399.     // select ADC4 by writing 0b00001111 to ADMUX
  400.     // 1.1v reference, left-adjust, ADC4
  401.     ADMUX  = (1 << V_REF) | (1 << ADLAR) | TEMP_CHANNEL;
  402.     // disable digital input on ADC pin to reduce power consumption
  403.     //DIDR0 |= (1 << TEMP_DIDR);
  404.     // enable, start, prescale
  405.     ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;
  406. }
  407. #endif  // TEMPERATURE_MON
  408.  
  409. #ifdef VOLTAGE_MON
  410. inline void ADC_on() {
  411.     // disable digital input on ADC pin to reduce power consumption
  412.     DIDR0 |= (1 << ADC_DIDR);
  413.     // 1.1v reference, left-adjust, ADC1/PB2
  414.     ADMUX  = (1 << V_REF) | (1 << ADLAR) | ADC_CHANNEL;
  415.     // enable, start, prescale
  416.     ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;
  417. }
  418.  
  419. uint8_t get_voltage() {
  420.     // Start conversion
  421.     ADCSRA |= (1 << ADSC);
  422.     // Wait for completion
  423.     while (ADCSRA & (1 << ADSC));
  424.     // Send back the result
  425.     return ADCH;
  426. }
  427. #else
  428. inline void ADC_off() {
  429.     ADCSRA &= ~(1<<7); //ADC off
  430. }
  431. #endif
  432.  
  433. #ifdef USE_BATTCHECK
  434. #ifdef BATTCHECK_4bars
  435. PROGMEM const uint8_t voltage_blinks[] = {
  436.                // 0 blinks for less than 1%
  437.     ADC_0p,    // 1 blink  for 1%-25%
  438.     ADC_25p,   // 2 blinks for 25%-50%
  439.     ADC_50p,   // 3 blinks for 50%-75%
  440.     ADC_75p,   // 4 blinks for 75%-100%
  441.     ADC_100p,  // 5 blinks for >100%
  442.     255,       // Ceiling, don't remove  (6 blinks means "error")
  443. };
  444. #endif  // BATTCHECK_4bars
  445. #ifdef BATTCHECK_8bars
  446. PROGMEM const uint8_t voltage_blinks[] = {
  447.                // 0 blinks for less than 1%
  448.     ADC_30,    // 1 blink  for 1%-12.5%
  449.     ADC_33,    // 2 blinks for 12.5%-25%
  450.     ADC_35,    // 3 blinks for 25%-37.5%
  451.     ADC_37,    // 4 blinks for 37.5%-50%
  452.     ADC_38,    // 5 blinks for 50%-62.5%
  453.     ADC_39,    // 6 blinks for 62.5%-75%
  454.     ADC_40,    // 7 blinks for 75%-87.5%
  455.     ADC_41,    // 8 blinks for 87.5%-100%
  456.     ADC_42,    // 9 blinks for >100%
  457.     255,       // Ceiling, don't remove  (10 blinks means "error")
  458. };
  459. #endif  // BATTCHECK_8bars
  460. #ifdef BATTCHECK_VpT
  461. /*
  462. PROGMEM const uint8_t v_whole_blinks[] = {
  463.                // 0 blinks for (shouldn't happen)
  464.     0,         // 1 blink for (shouldn't happen)
  465.     ADC_20,    // 2 blinks for 2V
  466.     ADC_30,    // 3 blinks for 3V
  467.     ADC_40,    // 4 blinks for 4V
  468.     255,       // Ceiling, don't remove
  469. };
  470. PROGMEM const uint8_t v_tenth_blinks[] = {
  471.                // 0 blinks for less than 1%
  472.     ADC_30,
  473.     ADC_33,
  474.     ADC_35,
  475.     ADC_37,
  476.     ADC_38,
  477.     ADC_39,
  478.     ADC_40,
  479.     ADC_41,
  480.     ADC_42,
  481.     255,       // Ceiling, don't remove
  482. };
  483. */
  484. PROGMEM const uint8_t voltage_blinks[] = {
  485.     // 0 blinks for (shouldn't happen)
  486.     ADC_25,(2<<5)+5,
  487.     ADC_26,(2<<5)+6,
  488.     ADC_27,(2<<5)+7,
  489.     ADC_28,(2<<5)+8,
  490.     ADC_29,(2<<5)+9,
  491.     ADC_30,(3<<5)+0,
  492.     ADC_31,(3<<5)+1,
  493.     ADC_32,(3<<5)+2,
  494.     ADC_33,(3<<5)+3,
  495.     ADC_34,(3<<5)+4,
  496.     ADC_35,(3<<5)+5,
  497.     ADC_36,(3<<5)+6,
  498.     ADC_37,(3<<5)+7,
  499.     ADC_38,(3<<5)+8,
  500.     ADC_39,(3<<5)+9,
  501.     ADC_40,(4<<5)+0,
  502.     ADC_41,(4<<5)+1,
  503.     ADC_42,(4<<5)+2,
  504.     ADC_43,(4<<5)+3,
  505.     ADC_44,(4<<5)+4,
  506.     255,   (1<<5)+1,  // Ceiling, don't remove
  507. };
  508. inline uint8_t battcheck() {
  509.     // Return an composite int, number of "blinks", for approximate battery charge
  510.     // Uses the table above for return values
  511.     // Return value is 3 bits of whole volts and 5 bits of tenths-of-a-volt
  512.     uint8_t i, voltage;
  513.     voltage = get_voltage();
  514.     // figure out how many times to blink
  515.     for (i=0;
  516.          voltage > pgm_read_byte(voltage_blinks + i);
  517.          i += 2) {}
  518.     return pgm_read_byte(voltage_blinks + i + 1);
  519. }
  520. #else  // #ifdef BATTCHECK_VpT
  521. inline uint8_t battcheck() {
  522.     // Return an int, number of "blinks", for approximate battery charge
  523.     // Uses the table above for return values
  524.     uint8_t i, voltage;
  525.     voltage = get_voltage();
  526.     // figure out how many times to blink
  527.     for (i=0;
  528.          voltage > pgm_read_byte(voltage_blinks + i);
  529.          i ++) {}
  530.     return i;
  531. }
  532. #endif  // BATTCHECK_VpT
  533. #endif
  534.  
  535.  
  536. #endif  // TK_VOLTAGE_H
  537.  
  538.  
  539.  
  540. #ifdef RANDOM_STROBE
  541. #ifndef TK_RANDOM_H
  542. #define TK_RANDOM_H
  543.  
  544. uint8_t pgm_rand() {
  545.     static uint16_t offset = 255;
  546.     offset = (offset + 1) & 0x3ff | 0x0100;
  547.     return pgm_read_byte(offset);
  548. }
  549.  
  550. #endif  // TK_RANDOM_H
  551.  
  552. #endif
  553.  
  554. /*
  555.  * global variables
  556.  */
  557.  
  558. // Config option variables
  559. #define FIRSTBOOT 0b01010101
  560. uint8_t firstboot = FIRSTBOOT;  // detect initial boot or factory reset
  561. uint8_t modegroup = 8;     // which mode group
  562. uint8_t enable_moon = 1;   // Should we add moon to the set of modes?
  563. uint8_t reverse_modes = 0; // flip the mode order?
  564. uint8_t memory = 0;        // mode memory, or not (set via soldered star)
  565. #ifdef OFFTIM3
  566. uint8_t offtim3 = 1;       // enable medium-press?
  567. #endif
  568. #ifdef TEMPERATURE_MON
  569. uint8_t maxtemp = 79;      // temperature step-down threshold
  570. #endif
  571. uint8_t muggle_mode = 0;   // simple mode designed for muggles
  572. // Other state variables
  573. uint8_t mode_override = 0; // do we need to enter a special mode?
  574. uint8_t mode_idx = 0;      // current or last-used mode number
  575. uint8_t eepos = 0;
  576. // counter for entering config mode
  577. // (needs to be remembered while off, but only for up to half a second)
  578. uint8_t fast_presses __attribute__ ((section (".noinit")));
  579.  
  580. // total length of current mode group's array
  581. uint8_t mode_cnt;
  582. // number of regular non-hidden modes in current mode group
  583. uint8_t solid_modes;
  584. // number of hidden modes in the current mode group
  585. // (hardcoded because both groups have the same hidden modes)
  586. //uint8_t hidden_modes = NUM_HIDDEN;  // this is never used
  587.  
  588.  
  589. PROGMEM const uint8_t hiddenmodes[] = { HIDDENMODES };
  590. // default values calculated by group_calc.py
  591. // Each group must be 8 values long, but can be cut short with a zero.
  592. #define NUM_MODEGROUPS 9  // don't count muggle mode
  593. PROGMEM const uint8_t modegroups[] = {
  594.      //1,  2,  3,  BATTCHECK,  RAMP,  0,  0,  0,
  595.     40,  0,  0,  0,  0,  0,  0,  0,
  596.      6, 40,  0,  0,  0,  0,  0,  0,
  597.      6, 23, 40,  0,  0,  0,  0,  0,
  598.      6, 17, 28, 40,  0,  0,  0,  0,
  599.      6, 14, 23, 31, 40,  0,  0,  0,
  600.      6, 12, 19, 26, 33, 40,  0,  0,
  601.     ONE7135, TURBO, RAMP,0,0,0,0,0,  // 7: special group A
  602.     RAMP,BATTCHECK,6,ONE7135,TURBO,0,0,0,  // 8: special group B
  603.     RAMP, 6, 12, 19, 29, 40,  0,  0,  // 9: special group C
  604.      6, 19, 32,  0,                  // muggle mode, exception to "must be 8 bytes long"
  605. };
  606. uint8_t modes[] = { 1,2,3,4,5,6,7,8,9, HIDDENMODES };  // make sure this is long enough...
  607.  
  608. // Modes (gets set when the light starts up based on saved config values)
  609. PROGMEM const uint8_t ramp_7135[] = { RAMP_7135 };
  610. PROGMEM const uint8_t ramp_7135s[] = { RAMP_7135s };
  611. PROGMEM const uint8_t ramp_FET[]  = { RAMP_FET };
  612.  
  613. void save_mode() {  // save the current mode index (with wear leveling)
  614.     uint8_t oldpos=eepos;
  615.  
  616.     eepos = (eepos+1) & ((EEPSIZE/2)-1);  // wear leveling, use next cell
  617.  
  618.     eeprom_write_byte((uint8_t *)(eepos), mode_idx);  // save current state
  619.     eeprom_write_byte((uint8_t *)(oldpos), 0xff);     // erase old state
  620. }
  621.  
  622. #define OPT_firstboot (EEPSIZE-1)
  623. #define OPT_modegroup (EEPSIZE-2)
  624. #define OPT_memory (EEPSIZE-3)
  625. #define OPT_offtim3 (EEPSIZE-4)
  626. #define OPT_maxtemp (EEPSIZE-5)
  627. #define OPT_mode_override (EEPSIZE-6)
  628. #define OPT_moon (EEPSIZE-7)
  629. #define OPT_revmodes (EEPSIZE-8)
  630. #define OPT_muggle (EEPSIZE-9)
  631. void save_state() {  // central method for writing complete state
  632.     save_mode();
  633.     eeprom_write_byte((uint8_t *)OPT_firstboot, firstboot);
  634.     eeprom_write_byte((uint8_t *)OPT_modegroup, modegroup);
  635.     eeprom_write_byte((uint8_t *)OPT_memory, memory);
  636. #ifdef OFFTIM3
  637.     eeprom_write_byte((uint8_t *)OPT_offtim3, offtim3);
  638. #endif
  639. #ifdef TEMPERATURE_MON
  640.     eeprom_write_byte((uint8_t *)OPT_maxtemp, maxtemp);
  641. #endif
  642.     eeprom_write_byte((uint8_t *)OPT_mode_override, mode_override);
  643.     eeprom_write_byte((uint8_t *)OPT_moon, enable_moon);
  644.     eeprom_write_byte((uint8_t *)OPT_revmodes, reverse_modes);
  645.     eeprom_write_byte((uint8_t *)OPT_muggle, muggle_mode);
  646. }
  647.  
  648. void restore_state() {
  649.     uint8_t eep;
  650.  
  651.     // check if this is the first time we have powered on
  652.     eep = eeprom_read_byte((uint8_t *)OPT_firstboot);
  653.     if (eep != FIRSTBOOT) {
  654.         // not much to do; the defaults should already be set
  655.         // while defining the variables above
  656.         save_state();
  657.         return;
  658.     }
  659.  
  660.     // find the mode index data
  661.     for(eepos=0; eepos<(EEPSIZE/2); eepos++) {
  662.         eep = eeprom_read_byte((const uint8_t *)eepos);
  663.         if (eep != 0xff) {
  664.             mode_idx = eep;
  665.             break;
  666.         }
  667.     }
  668.  
  669.     // load other config values
  670.     modegroup = eeprom_read_byte((uint8_t *)OPT_modegroup);
  671.     memory    = eeprom_read_byte((uint8_t *)OPT_memory);
  672. #ifdef OFFTIM3
  673.     offtim3   = eeprom_read_byte((uint8_t *)OPT_offtim3);
  674. #endif
  675. #ifdef TEMPERATURE_MON
  676.     maxtemp   = eeprom_read_byte((uint8_t *)OPT_maxtemp);
  677. #endif
  678.     mode_override = eeprom_read_byte((uint8_t *)OPT_mode_override);
  679.     enable_moon   = eeprom_read_byte((uint8_t *)OPT_moon);
  680.     reverse_modes = eeprom_read_byte((uint8_t *)OPT_revmodes);
  681.     muggle_mode   = eeprom_read_byte((uint8_t *)OPT_muggle);
  682.  
  683.     // unnecessary, save_state handles wrap-around
  684.     // (and we don't really care about it skipping cell 0 once in a while)
  685.     //else eepos=0;
  686. }
  687.  
  688. inline void next_mode() {
  689.     mode_idx += 1;
  690.     if (mode_idx >= solid_modes) {
  691.         // Wrap around, skipping the hidden modes
  692.         // (note: this also applies when going "forward" from any hidden mode)
  693.         // FIXME? Allow this to cycle through hidden modes?
  694.         mode_idx = 0;
  695.     }
  696. }
  697.  
  698. #ifdef OFFTIM3
  699. inline void prev_mode() {
  700.     // simple mode has no reverse
  701.     if (muggle_mode) { return next_mode(); }
  702.  
  703.     if (mode_idx == solid_modes) {
  704.         // If we hit the end of the hidden modes, go back to moon
  705.         mode_idx = 0;
  706.     } else if (mode_idx > 0) {
  707.         // Regular mode: is between 1 and TOTAL_MODES
  708.         mode_idx -= 1;
  709.     } else {
  710.         // Otherwise, wrap around (this allows entering hidden modes)
  711.         mode_idx = mode_cnt - 1;
  712.     }
  713. }
  714. #endif
  715.  
  716. void count_modes() {
  717.     /*
  718.      * Determine how many solid and hidden modes we have.
  719.      *
  720.      * (this matters because we have more than one set of modes to choose
  721.      *  from, so we need to count at runtime)
  722.      */
  723.     // copy config to local vars to avoid accidentally overwriting them in muggle mode
  724.     // (also, it seems to reduce overall program size)
  725.     uint8_t my_modegroup = modegroup;
  726.     uint8_t my_enable_moon = enable_moon;
  727.     uint8_t my_reverse_modes = reverse_modes;
  728.  
  729.     // override config if we're in simple mode
  730.     if (muggle_mode) {
  731.         my_modegroup = NUM_MODEGROUPS;
  732.         my_enable_moon = 0;
  733.         my_reverse_modes = 0;
  734.     }
  735.  
  736.     uint8_t *dest;
  737.     const uint8_t *src = modegroups + (my_modegroup<<3);
  738.     dest = modes;
  739.  
  740.     // Figure out how many modes are in this group
  741.     //solid_modes = modegroup + 1;  // Assume group N has N modes
  742.     // No, how about actually counting the modes instead?
  743.     // (in case anyone changes the mode groups above so they don't form a triangle)
  744.     for(solid_modes=0;
  745.         (solid_modes<8) && pgm_read_byte(src + solid_modes);
  746.         solid_modes++ ) {}
  747.  
  748.     // add moon mode (or not) if config says to add it
  749.     if (my_enable_moon) {
  750.         modes[0] = 1;
  751.         dest ++;
  752.     }
  753.  
  754.     // add regular modes
  755.     memcpy_P(dest, src, solid_modes);
  756.     // add hidden modes
  757.     memcpy_P(dest + solid_modes, hiddenmodes, sizeof(hiddenmodes));
  758.     // final count
  759.     mode_cnt = solid_modes + sizeof(hiddenmodes);
  760.     if (my_reverse_modes) {
  761.         // TODO: yuck, isn't there a better way to do this?
  762.         int8_t i;
  763.         src += solid_modes;
  764.         dest = modes;
  765.         for(i=0; i<solid_modes; i++) {
  766.             src --;
  767.             *dest = pgm_read_byte(src);
  768.             dest ++;
  769.         }
  770.         if (my_enable_moon) {
  771.             *dest = 1;
  772.         }
  773.         mode_cnt --;  // get rid of last hidden mode, since it's a duplicate turbo
  774.     }
  775.     if (my_enable_moon) {
  776.         mode_cnt ++;
  777.         solid_modes ++;
  778.     }
  779. }
  780.  
  781. inline void set_output(uint8_t pwm1, uint8_t pwm2, uint8_t pwm3) {
  782.     /* This is no longer needed since we always use PHASE mode.
  783.     // Need PHASE to properly turn off the light
  784.     if ((pwm1==0) && (pwm2==0)) {
  785.         TCCR0A = PHASE;
  786.     }
  787.     */
  788.     FET_PWM_LVL = pwm1;
  789.     PWM_LVL = pwm2;
  790.     ALT_PWM_LVL = pwm3;
  791. }
  792.  
  793. void set_level(uint8_t level) {
  794.     if (level == 0) {
  795.         set_output(0,0,0);
  796.     } else {
  797.         level -= 1;
  798.         set_output(pgm_read_byte(ramp_FET   + level),
  799.                    pgm_read_byte(ramp_7135s + level),
  800.                    pgm_read_byte(ramp_7135  + level));
  801.     }
  802. }
  803.  
  804. void set_mode(uint8_t mode) {
  805. #ifdef SOFT_START
  806.     static uint8_t actual_level = 0;
  807.     uint8_t target_level = mode;
  808.     int8_t shift_amount;
  809.     int8_t diff;
  810.     do {
  811.         diff = target_level - actual_level;
  812.         shift_amount = (diff >> 2) | (diff!=0);
  813.         actual_level += shift_amount;
  814.         set_level(actual_level);
  815.         //_delay_ms(RAMP_SIZE/20);  // slow ramp
  816.         _delay_ms(RAMP_SIZE/4);  // fast ramp
  817.     } while (target_level != actual_level);
  818. #else
  819.     set_level(mode);
  820. #endif  // SOFT_START
  821. }
  822.  
  823. void blink(uint8_t val, uint16_t speed)
  824. {
  825.     for (; val>0; val--)
  826.     {
  827.         set_level(BLINK_BRIGHTNESS);
  828.         _delay_ms(speed);
  829.         set_level(0);
  830.         _delay_ms(speed<<2);
  831.     }
  832. }
  833.  
  834. void strobe(uint8_t ontime, uint8_t offtime) {
  835.     set_level(RAMP_SIZE);
  836.     _delay_ms(ontime);
  837.     set_level(0);
  838.     _delay_ms(offtime);
  839. }
  840.  
  841. void toggle(uint8_t *var, uint8_t num) {
  842.     // Used for config mode
  843.     // Changes the value of a config option, waits for the user to "save"
  844.     // by turning the light off, then changes the value back in case they
  845.     // didn't save.  Can be used repeatedly on different options, allowing
  846.     // the user to change and save only one at a time.
  847.     blink(num, BLINK_SPEED/8);  // indicate which option number this is
  848.     *var ^= 1;
  849.     save_state();
  850.     // "buzz" for a while to indicate the active toggle window
  851.     for(uint8_t i=0; i<32; i++) {
  852.         set_level(BLINK_BRIGHTNESS * 3 / 4);
  853.         _delay_ms(20);
  854.         set_level(0);
  855.         _delay_ms(20);
  856.     }
  857.     // if the user didn't click, reset the value and return
  858.     *var ^= 1;
  859.     save_state();
  860.     _delay_s();
  861. }
  862.  
  863. #ifdef TEMPERATURE_MON
  864. uint8_t get_temperature() {
  865.     ADC_on_temperature();
  866.     // average a few values; temperature is noisy
  867.     uint16_t temp = 0;
  868.     uint8_t i;
  869.     get_voltage();
  870.     for(i=0; i<16; i++) {
  871.         temp += get_voltage();
  872.         _delay_ms(5);
  873.     }
  874.     temp >>= 4;
  875.     return temp;
  876. }
  877. #endif  // TEMPERATURE_MON
  878.  
  879. inline uint8_t read_otc() {
  880.     // Read and return the off-time cap value
  881.     // Start up ADC for capacitor pin
  882.     // disable digital input on ADC pin to reduce power consumption
  883.     DIDR0 |= (1 << CAP_DIDR);
  884.     // 1.1v reference, left-adjust, ADC3/PB3
  885.     ADMUX  = (1 << V_REF) | (1 << ADLAR) | CAP_CHANNEL;
  886.     // enable, start, prescale
  887.     ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;
  888.  
  889.     // Wait for completion
  890.     while (ADCSRA & (1 << ADSC));
  891.     // Start again as datasheet says first result is unreliable
  892.     ADCSRA |= (1 << ADSC);
  893.     // Wait for completion
  894.     while (ADCSRA & (1 << ADSC));
  895.  
  896.     // ADCH should have the value we wanted
  897.     return ADCH;
  898. }
  899.  
  900. int main(void)
  901. {
  902.     // check the OTC immediately before it has a chance to charge or discharge
  903.     uint8_t cap_val = read_otc();  // save it for later
  904.  
  905.     // Charge up the capacitor by setting CAP_PIN to output
  906.     DDRB  |= (1 << CAP_PIN);    // Output
  907.     PORTB |= (1 << CAP_PIN);    // High
  908.  
  909.     // Set PWM pin to output
  910.     DDRB |= (1 << PWM_PIN);     // enable main channel
  911.     DDRB |= (1 << ALT_PWM_PIN); // enable second channel
  912.  
  913.     // enable second PWM counter (OC1B) and third channel (FET, PB4)
  914.     DDRB |= (1 << FET_PWM_PIN); // enable third channel (DDB4)
  915.  
  916.     // Set timer to do PWM for correct output pin and set prescaler timing
  917.     //TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
  918.     //TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
  919.     TCCR0A = PHASE;
  920.     // Set timer to do PWM for correct output pin and set prescaler timing
  921.     TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
  922.  
  923.     // Second PWM counter is ... weird
  924.     //GTCCR = (1<<PWM1B) | (2<<COM1B0);  // enable pwm on pb4, clear output
  925.     //GTCCR |= (1<<PWM1B | 1<<COM1B0);  // enable pwm on pb4, toggle output
  926.     //TCCR1 = 1<<COM1A0 | 1<<CS10;  // toggle, pre-scaler=1
  927.     //TCCR1 = (2<<COM1A0) | (1<<CS10);  // clear, pre-scaler=1
  928.     //TCCR1 = 3<<COM1A0 | 1<<CS10;  // set, pre-scaler=1
  929.     //TCCR1 = (1<<PWM1A) | (2<<COM1A0) | (1<<CS10);  // pre-scaler=1
  930.     TCCR1 = _BV (CS10);
  931.     GTCCR = _BV (COM1B1) | _BV (PWM1B);
  932.     OCR1C = 255;  // Set ceiling value to maximum
  933.  
  934.     // Read config values and saved state
  935.     restore_state();
  936.  
  937.     // Enable the current mode group
  938.     count_modes();
  939.  
  940.  
  941.     // TODO: Enable this?  (might prevent some corner cases, but requires extra room)
  942.     // memory decayed, reset it
  943.     // (should happen on med/long press instead
  944.     //  because mem decay is *much* slower when the OTC is charged
  945.     //  so let's not wait until it decays to reset it)
  946.     //if (fast_presses > 0x20) { fast_presses = 0; }
  947.  
  948.     // check button press time, unless the mode is overridden
  949.     if (! mode_override) {
  950.         if (cap_val > CAP_SHORT) {
  951.             // Indicates they did a short press, go to the next mode
  952.             // We don't care what the fast_presses value is as long as it's over 15
  953.             fast_presses = (fast_presses+1) & 0x1f;
  954.             next_mode(); // Will handle wrap arounds
  955. #ifdef OFFTIM3
  956.         } else if (cap_val > CAP_MED) {
  957.             // User did a medium press, go back one mode
  958.             fast_presses = 0;
  959.             if (offtim3) {
  960.                 prev_mode();  // Will handle "negative" modes and wrap-arounds
  961.             } else {
  962.                 next_mode();  // disabled-med-press acts like short-press
  963.                               // (except that fast_presses isn't reliable then)
  964.             }
  965. #endif
  966.         } else {
  967.             // Long press, keep the same mode
  968.             // ... or reset to the first mode
  969.             fast_presses = 0;
  970.             if (muggle_mode  || (! memory)) {
  971.                 // Reset to the first mode
  972.                 mode_idx = 0;
  973.             }
  974.         }
  975.     }
  976.     save_mode();
  977.  
  978.     // Turn features on or off as needed
  979.     #ifdef VOLTAGE_MON
  980.     ADC_on();
  981.     #else
  982.     ADC_off();
  983.     #endif
  984.  
  985.     uint8_t output;
  986.     uint8_t actual_level;
  987. #ifdef TEMPERATURE_MON
  988.     uint8_t overheat_count = 0;
  989. #endif
  990. #ifdef VOLTAGE_MON
  991.     uint8_t lowbatt_cnt = 0;
  992.     uint8_t i = 0;
  993.     uint8_t voltage;
  994.     // Make sure voltage reading is running for later
  995.     ADCSRA |= (1 << ADSC);
  996. #endif
  997.     //output = pgm_read_byte(modes + mode_idx);
  998.     output = modes[mode_idx];
  999.     actual_level = output;
  1000.     // handle mode overrides, like mode group selection and temperature calibration
  1001.     if (mode_override) {
  1002.         // do nothing; mode is already set
  1003.         //mode_idx = mode_override;
  1004.         fast_presses = 0;
  1005.         output = mode_idx;
  1006.     }
  1007.     while(1) {
  1008.         if (fast_presses > 0x0f) {  // Config mode
  1009.             _delay_s();       // wait for user to stop fast-pressing button
  1010.             fast_presses = 0; // exit this mode after one use
  1011.             mode_idx = 0;
  1012.  
  1013.             // Enter or leave "muggle mode"?
  1014.             toggle(&muggle_mode, 1);
  1015.             if (muggle_mode) { continue; };  // don't offer other options in muggle mode
  1016.  
  1017.             toggle(&memory, 2);
  1018.  
  1019.             toggle(&enable_moon, 3);
  1020.  
  1021.             toggle(&reverse_modes, 4);
  1022.  
  1023.             // Enter the mode group selection mode?
  1024.             mode_idx = GROUP_SELECT_MODE;
  1025.             toggle(&mode_override, 5);
  1026.             mode_idx = 0;
  1027.  
  1028. #ifdef OFFTIM3
  1029.             toggle(&offtim3, 6);
  1030. #endif
  1031.  
  1032. #ifdef TEMPERATURE_MON
  1033.             // Enter temperature calibration mode?
  1034.             mode_idx = TEMP_CAL_MODE;
  1035.             toggle(&mode_override, 7);
  1036.             mode_idx = 0;
  1037. #endif
  1038.  
  1039.             toggle(&firstboot, 8);
  1040.  
  1041.             //output = pgm_read_byte(modes + mode_idx);
  1042.             output = modes[mode_idx];
  1043.             actual_level = output;
  1044.         }
  1045. #ifdef STROBE
  1046.         else if (output == STROBE) {
  1047.             // 10Hz tactical strobe
  1048.             strobe(50,50);
  1049.         }
  1050. #endif // ifdef STROBE
  1051. #ifdef POLICE_STROBE
  1052.         else if (output == POLICE_STROBE) {
  1053.             // police-like strobe
  1054.             for(i=0;i<8;i++) {
  1055.                 strobe(20,40);
  1056.             }
  1057.             for(i=0;i<8;i++) {
  1058.                 strobe(40,80);
  1059.             }
  1060.         }
  1061. #endif // ifdef POLICE_STROBE
  1062. #ifdef RANDOM_STROBE
  1063.         else if (output == RANDOM_STROBE) {
  1064.             // pseudo-random strobe
  1065.             uint8_t ms = 34 + (pgm_rand() & 0x3f);
  1066.             strobe(ms, ms);
  1067.             strobe(ms, ms);
  1068.         }
  1069. #endif // ifdef RANDOM_STROBE
  1070. #ifdef BIKING_STROBE
  1071.         else if (output == BIKING_STROBE) {
  1072.             // 2-level stutter beacon for biking and such
  1073. #ifdef FULL_BIKING_STROBE
  1074.             // normal version
  1075.             for(i=0;i<4;i++) {
  1076.                 set_level(TURBO);
  1077.                 //set_output(255,0,0);
  1078.                 _delay_ms(5);
  1079.                 set_level(ONE7135);
  1080.                 //set_output(0,0,255);
  1081.                 _delay_ms(65);
  1082.             }
  1083.             _delay_ms(720);
  1084. #else
  1085.             // small/minimal version
  1086.             set_level(TURBO);
  1087.             //set_output(255,0,0);
  1088.             _delay_ms(10);
  1089.             set_level(ONE7135);
  1090.             //set_output(0,0,255);
  1091.             _delay_s();
  1092. #endif
  1093.         }
  1094. #endif  // ifdef BIKING_STROBE
  1095. #ifdef RAMP
  1096.         else if (output == RAMP) {
  1097.             int8_t r;
  1098.             // simple ramping test
  1099.             for(r=1; r<=RAMP_SIZE; r++) {
  1100.                 set_level(r);
  1101.                 _delay_ms(40);
  1102.             }
  1103.             for(r=RAMP_SIZE; r>0; r--) {
  1104.                 set_level(r);
  1105.                 _delay_ms(40);
  1106.             }
  1107.         }
  1108. #endif  // ifdef RAMP
  1109. #ifdef BATTCHECK
  1110.         else if (output == BATTCHECK) {
  1111. #ifdef BATTCHECK_VpT
  1112.             // blink out volts and tenths
  1113.             _delay_ms(50);
  1114.             uint8_t result = battcheck();
  1115.             blink(result >> 5, BLINK_SPEED/8);
  1116.             _delay_ms(BLINK_SPEED);
  1117.             blink(1,5);
  1118.             _delay_ms(BLINK_SPEED*3/2);
  1119.             blink(result & 0b00011111, BLINK_SPEED/8);
  1120. #else  // ifdef BATTCHECK_VpT
  1121.             // blink zero to five times to show voltage
  1122.             // (~0%, ~25%, ~50%, ~75%, ~100%, >100%)
  1123.             blink(battcheck(), BLINK_SPEED/8);
  1124. #endif  // ifdef BATTCHECK_VpT
  1125.             // wait between readouts
  1126.             _delay_s(); _delay_s();
  1127.         }
  1128. #endif // ifdef BATTCHECK
  1129.         else if (output == GROUP_SELECT_MODE) {
  1130.             // exit this mode after one use
  1131.             mode_idx = 0;
  1132.             mode_override = 0;
  1133.  
  1134.             for(i=0; i<NUM_MODEGROUPS; i++) {
  1135.                 modegroup = i;
  1136.                 save_state();
  1137.  
  1138.                 blink(1, BLINK_SPEED/3);
  1139.             }
  1140.             _delay_s(); _delay_s();
  1141.         }
  1142. #ifdef TEMP_CAL_MODE
  1143.         else if (output == TEMP_CAL_MODE) {
  1144.             // make sure we don't stay in this mode after button press
  1145.             mode_idx = 0;
  1146.             mode_override = 0;
  1147.  
  1148.             // Allow the user to turn off thermal regulation if they want
  1149.             maxtemp = 255;
  1150.             save_state();
  1151.             set_mode(RAMP_SIZE/4);  // start somewhat dim during turn-off-regulation mode
  1152.             _delay_s(); _delay_s();
  1153.  
  1154.             // run at highest output level, to generate heat
  1155.             set_mode(RAMP_SIZE);
  1156.  
  1157.             // measure, save, wait...  repeat
  1158.             while(1) {
  1159.                 maxtemp = get_temperature();
  1160.                 save_state();
  1161.                 _delay_s(); _delay_s();
  1162.             }
  1163.         }
  1164. #endif  // TEMP_CAL_MODE
  1165.         else {  // Regular non-hidden solid mode
  1166.             set_mode(actual_level);
  1167. #ifdef TEMPERATURE_MON
  1168.             uint8_t temp = get_temperature();
  1169.  
  1170.             // step down? (or step back up?)
  1171.             if (temp >= maxtemp) {
  1172.                 overheat_count ++;
  1173.                 // reduce noise, and limit the lowest step-down level
  1174.                 if ((overheat_count > 15) && (actual_level > (RAMP_SIZE/8))) {
  1175.                     actual_level --;
  1176.                     //_delay_ms(5000);  // don't ramp down too fast
  1177.                     overheat_count = 0;  // don't ramp down too fast
  1178.                 }
  1179.             } else {
  1180.                 // if we're not overheated, ramp up to the user-requested level
  1181.                 overheat_count = 0;
  1182.                 if ((temp < maxtemp - 2) && (actual_level < output)) {
  1183.                     actual_level ++;
  1184.                 }
  1185.             }
  1186.             set_mode(actual_level);
  1187.  
  1188.             ADC_on();  // return to voltage mode
  1189. #endif
  1190.             // Otherwise, just sleep.
  1191.             _delay_ms(500);
  1192.  
  1193.             // If we got this far, the user has stopped fast-pressing.
  1194.             // So, don't enter config mode.
  1195.             fast_presses = 0;
  1196.         }
  1197. #ifdef VOLTAGE_MON
  1198.         if (ADCSRA & (1 << ADIF)) {  // if a voltage reading is ready
  1199.             voltage = ADCH;  // get the waiting value
  1200.             // See if voltage is lower than what we were looking for
  1201.             if (voltage < ADC_LOW) {
  1202.                 lowbatt_cnt ++;
  1203.             } else {
  1204.                 lowbatt_cnt = 0;
  1205.             }
  1206.             // See if it's been low for a while, and maybe step down
  1207.             if (lowbatt_cnt >= 8) {
  1208.                 // DEBUG: blink on step-down:
  1209.                 //set_level(0);  _delay_ms(100);
  1210.  
  1211.                 if (actual_level > RAMP_SIZE) {  // hidden / blinky modes
  1212.                     // step down from blinky modes to medium
  1213.                     actual_level = RAMP_SIZE / 2;
  1214.                 } else if (actual_level > 1) {  // regular solid mode
  1215.                     // step down from solid modes somewhat gradually
  1216.                     // drop by 25% each time
  1217.                     actual_level = (actual_level >> 2) + (actual_level >> 1);
  1218.                     // drop by 50% each time
  1219.                     //actual_level = (actual_level >> 1);
  1220.                 } else { // Already at the lowest mode
  1221.                     //mode_idx = 0;  // unnecessary; we never leave this clause
  1222.                     //actual_level = 0;  // unnecessary; we never leave this clause
  1223.                     // Turn off the light
  1224.                     set_level(0);
  1225.                     // Power down as many components as possible
  1226.                     set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  1227.                     sleep_mode();
  1228.                 }
  1229.                 set_mode(actual_level);
  1230.                 output = actual_level;
  1231.                 //save_mode();  // we didn't actually change the mode
  1232.                 lowbatt_cnt = 0;
  1233.                 // Wait at least 2 seconds before lowering the level again
  1234.                 _delay_ms(250);  // this will interrupt blinky modes
  1235.             }
  1236.  
  1237.             // Make sure conversion is running for next time through
  1238.             ADCSRA |= (1 << ADSC);
  1239.         }
  1240. #endif  // ifdef VOLTAGE_MON
  1241.     }
  1242.  
  1243.     //return 0; // Standard Return Code
  1244. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement