Advertisement
Guest User

Untitled

a guest
Nov 5th, 2016
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 28.56 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. #include "tk-attiny.h"
  59.  
  60. /*
  61.  * =========================================================================
  62.  * Settings to modify per driver
  63.  */
  64.  
  65. // FIXME: make 1-channel vs 2-channel power a single #define option
  66. //#define FAST 0x23           // fast PWM channel 1 only
  67. //#define PHASE 0x21          // phase-correct PWM channel 1 only
  68. #define FAST 0xA3           // fast PWM both channels
  69. #define PHASE 0xA1          // phase-correct PWM both channels
  70.  
  71. #define VOLTAGE_MON         // Comment out to disable LVP
  72.  
  73. #define OFFTIM3             // Use short/med/long off-time presses
  74.                             // instead of just short/long
  75.  
  76. // ../../bin/level_calc.py 64 1 10 1300 y 3 0.23 140
  77. #define RAMP_SIZE  12
  78. #define RAMP_7135   5,0,0,0,0,0,0,0,0,0,31,145
  79. #define RAMP_7135s  0,0,7,8,20,24,120,245,255,0,0,0
  80. #define RAMP_FET    0,0,0,0,0,0,0,0,70,255,0,0
  81. #define OFF 2
  82. #define REDMOON 1
  83. #define REDLOW 11
  84. #define REDHI 12
  85. #define MOON1 3
  86. #define MOON2 4
  87. #define LOWLOW 5
  88. #define LOW 6
  89. #define MED 7
  90. #define HIGH 8
  91. #define LOWTURBO 9
  92. #define TURBO 10
  93.  
  94.  
  95. // x**5 curve
  96. //#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
  97. //#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
  98.  
  99. // uncomment to ramp up/down to a mode instead of jumping directly
  100. //#define SOFT_START
  101.  
  102. // Enable battery indicator mode?
  103. #define USE_BATTCHECK
  104. // Choose a battery indicator style
  105. //#define BATTCHECK_4bars  // up to 4 blinks
  106. //#define BATTCHECK_8bars  // up to 8 blinks
  107. #define BATTCHECK_VpT  // Volts + tenths
  108.  
  109. // output to use for blinks on battery check (and other modes)
  110. #define BLINK_BRIGHTNESS    11
  111. // ms per normal-speed blink
  112. #define BLINK_SPEED         500
  113.  
  114. // Hidden modes are *before* the lowest (moon) mode, and should be specified
  115. // in reverse order.  So, to go backward from moon to turbo to strobe to
  116. // battcheck, use BATTCHECK,STROBE,TURBO .
  117. //#define HIDDENMODES         BATTCHECK,REDHIGH,REDLOW
  118. #define HIDDENMODES         OFF,BATTCHECK,REDHI,REDLOW
  119.  
  120. //#define TURBO     RAMP_SIZE       // Convenience code for turbo mode
  121. #define BATTCHECK 254       // Convenience code for battery check mode
  122. #define GROUP_SELECT_MODE 253
  123. #define TEMP_CAL_MODE 252
  124. // Uncomment to enable tactical strobe mode
  125. #define STROBE    251       // Convenience code for strobe mode
  126. // Uncomment to unable a 2-level stutter beacon instead of a tactical strobe
  127. #define BIKING_STROBE 250   // Convenience code for biking strobe mode
  128. // comment out to use minimal version instead (smaller)
  129. #define FULL_BIKING_STROBE
  130. #define RAMP 249       // ramp test mode for tweaking ramp shape
  131. #define POLICE_STROBE 248
  132. #define RANDOM_STROBE 247
  133.  
  134. // thermal step-down
  135. #define TEMPERATURE_MON
  136.  
  137. /*
  138.  * =========================================================================
  139.  */
  140.  
  141. // Ignore a spurious warning, we did the cast on purpose
  142. #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
  143.  
  144. #include <avr/pgmspace.h>
  145. //#include <avr/io.h>
  146. //#include <avr/interrupt.h>
  147. #include <avr/eeprom.h>
  148. #include <avr/sleep.h>
  149. //#include <avr/power.h>
  150. #include <string.h>
  151.  
  152. #define OWN_DELAY           // Don't use stock delay functions.
  153. #define USE_DELAY_S         // Also use _delay_s(), not just _delay_ms()
  154. #include "tk-delay.h"
  155.  
  156. #include "tk-voltage.h"
  157.  
  158. #ifdef RANDOM_STROBE
  159. #include "tk-random.h"
  160. #endif
  161.  
  162. /*
  163.  * global variables
  164.  */
  165.  
  166. // Config option variables
  167. #define FIRSTBOOT 0b01010101
  168. uint8_t firstboot = FIRSTBOOT;  // detect initial boot or factory reset
  169. uint8_t modegroup = 0;     // which mode group
  170. uint8_t enable_moon = 1;   // Should we add moon to the set of modes?
  171. uint8_t reverse_modes = 0; // flip the mode order?
  172. uint8_t memory = 0;        // mode memory, or not (set via soldered star)
  173. #ifdef OFFTIM3
  174. uint8_t offtim3 = 1;       // enable medium-press?
  175. #endif
  176. #ifdef TEMPERATURE_MON
  177. uint8_t maxtemp = 79;      // temperature step-down threshold
  178. #endif
  179. uint8_t muggle_mode = 0;   // simple mode designed for muggles
  180. // Other state variables
  181. uint8_t mode_override = 0; // do we need to enter a special mode?
  182. uint8_t mode_idx = 0;      // current or last-used mode number
  183. uint8_t eepos = 0;
  184. // counter for entering config mode
  185. // (needs to be remembered while off, but only for up to half a second)
  186. uint8_t fast_presses __attribute__ ((section (".noinit")));
  187.  
  188. // total length of current mode group's array
  189. uint8_t mode_cnt;
  190. // number of regular non-hidden modes in current mode group
  191. uint8_t solid_modes;
  192. // number of hidden modes in the current mode group
  193. // (hardcoded because both groups have the same hidden modes)
  194. //uint8_t hidden_modes = NUM_HIDDEN;  // this is never used
  195.  
  196.  
  197. PROGMEM const uint8_t hiddenmodes[] = { HIDDENMODES };
  198. // default values calculated by group_calc.py
  199. // Each group must be 8 values long, but can be cut short with a zero.
  200. #define NUM_MODEGROUPS 6  // don't count muggle mode
  201. PROGMEM const uint8_t modegroups[] = {
  202.     //1,  2,  3,  BATTCHECK,  RAMP,  0,  0,  0,
  203.     MOON1,  MOON2,  LOWLOW,  MED,  TURBO,  0,  0,  0,
  204.     LOWLOW,  HIGH,  TURBO,  0,  0,  0,  0,  0,
  205.     MOON2, LOW,  HIGH,  TURBO,  0,  0,  0,  0,
  206.     BATTCHECK, STROBE, OFF, POLICE_STROBE, OFF, RANDOM_STROBE, OFF, BIKING_STROBE,      // 8: special group B
  207.     REDLOW, LOWLOW, MED, LOWTURBO, 0                  // muggle mode, exception to "must be 8 bytes long"
  208. };
  209.  
  210. uint8_t modes[] = { 1,2,3,4,5,6,7,8,9, HIDDENMODES };  // make sure this is long enough...
  211.  
  212. // Modes (gets set when the light starts up based on saved config values)
  213. PROGMEM const uint8_t ramp_7135[] = { RAMP_7135 };
  214. PROGMEM const uint8_t ramp_7135s[] = { RAMP_7135s };
  215. PROGMEM const uint8_t ramp_FET[]  = { RAMP_FET };
  216.  
  217. void save_mode() {  // save the current mode index (with wear leveling)
  218.     uint8_t oldpos=eepos;
  219.  
  220.     eepos = (eepos+1) & ((EEPSIZE/2)-1);  // wear leveling, use next cell
  221.  
  222.     eeprom_write_byte((uint8_t *)(eepos), mode_idx);  // save current state
  223.     eeprom_write_byte((uint8_t *)(oldpos), 0xff);     // erase old state
  224. }
  225.  
  226. #define OPT_firstboot (EEPSIZE-1)
  227. #define OPT_modegroup (EEPSIZE-2)
  228. #define OPT_memory (EEPSIZE-3)
  229. #define OPT_offtim3 (EEPSIZE-4)
  230. #define OPT_maxtemp (EEPSIZE-5)
  231. #define OPT_mode_override (EEPSIZE-6)
  232. #define OPT_moon (EEPSIZE-7)
  233. #define OPT_revmodes (EEPSIZE-8)
  234. #define OPT_muggle (EEPSIZE-9)
  235. void save_state() {  // central method for writing complete state
  236.     save_mode();
  237.     eeprom_write_byte((uint8_t *)OPT_firstboot, firstboot);
  238.     eeprom_write_byte((uint8_t *)OPT_modegroup, modegroup);
  239.     eeprom_write_byte((uint8_t *)OPT_memory, memory);
  240. #ifdef OFFTIM3
  241.     eeprom_write_byte((uint8_t *)OPT_offtim3, offtim3);
  242. #endif
  243. #ifdef TEMPERATURE_MON
  244.     eeprom_write_byte((uint8_t *)OPT_maxtemp, maxtemp);
  245. #endif
  246.     eeprom_write_byte((uint8_t *)OPT_mode_override, mode_override);
  247.     eeprom_write_byte((uint8_t *)OPT_moon, enable_moon);
  248.     eeprom_write_byte((uint8_t *)OPT_revmodes, reverse_modes);
  249.     eeprom_write_byte((uint8_t *)OPT_muggle, muggle_mode);
  250. }
  251.  
  252. void restore_state() {
  253.     uint8_t eep;
  254.  
  255.     // check if this is the first time we have powered on
  256.     eep = eeprom_read_byte((uint8_t *)OPT_firstboot);
  257.     if (eep != FIRSTBOOT) {
  258.         // not much to do; the defaults should already be set
  259.         // while defining the variables above
  260.         save_state();
  261.         return;
  262.     }
  263.  
  264.     // find the mode index data
  265.     for(eepos=0; eepos<(EEPSIZE/2); eepos++) {
  266.         eep = eeprom_read_byte((const uint8_t *)eepos);
  267.         if (eep != 0xff) {
  268.             mode_idx = eep;
  269.             break;
  270.         }
  271.     }
  272.  
  273.     // load other config values
  274.     modegroup = eeprom_read_byte((uint8_t *)OPT_modegroup);
  275.     memory    = eeprom_read_byte((uint8_t *)OPT_memory);
  276. #ifdef OFFTIM3
  277.     offtim3   = eeprom_read_byte((uint8_t *)OPT_offtim3);
  278. #endif
  279. #ifdef TEMPERATURE_MON
  280.     maxtemp   = eeprom_read_byte((uint8_t *)OPT_maxtemp);
  281. #endif
  282.     mode_override = eeprom_read_byte((uint8_t *)OPT_mode_override);
  283.     enable_moon   = eeprom_read_byte((uint8_t *)OPT_moon);
  284.     reverse_modes = eeprom_read_byte((uint8_t *)OPT_revmodes);
  285.     muggle_mode   = eeprom_read_byte((uint8_t *)OPT_muggle);
  286.  
  287.     // unnecessary, save_state handles wrap-around
  288.     // (and we don't really care about it skipping cell 0 once in a while)
  289.     //else eepos=0;
  290. }
  291.  
  292. inline void next_mode() {
  293.     mode_idx += 1;
  294.     if (mode_idx >= solid_modes) {
  295.         // Wrap around, skipping the hidden modes
  296.         // (note: this also applies when going "forward" from any hidden mode)
  297.         // FIXME? Allow this to cycle through hidden modes?
  298.         mode_idx = 0;
  299.     }
  300. }
  301.  
  302. #ifdef OFFTIM3
  303. inline void prev_mode() {
  304.     // simple mode has no reverse
  305.     if (muggle_mode) { return next_mode(); }
  306.  
  307.     if (mode_idx == solid_modes) {
  308.         // If we hit the end of the hidden modes, go back to moon
  309.         mode_idx = 0;
  310.     } else if (mode_idx > 0) {
  311.         // Regular mode: is between 1 and TOTAL_MODES
  312.         mode_idx -= 1;
  313.     } else {
  314.         // Otherwise, wrap around (this allows entering hidden modes)
  315.         mode_idx = mode_cnt - 1;
  316.     }
  317. }
  318. #endif
  319.  
  320. void count_modes() {
  321.     /*
  322.      * Determine how many solid and hidden modes we have.
  323.      *
  324.      * (this matters because we have more than one set of modes to choose
  325.      *  from, so we need to count at runtime)
  326.      */
  327.     // copy config to local vars to avoid accidentally overwriting them in muggle mode
  328.     // (also, it seems to reduce overall program size)
  329.     uint8_t my_modegroup = modegroup;
  330.     uint8_t my_enable_moon = enable_moon;
  331.     uint8_t my_reverse_modes = reverse_modes;
  332.  
  333.     // override config if we're in simple mode
  334.     if (muggle_mode) {
  335.         my_modegroup = NUM_MODEGROUPS;
  336.         my_enable_moon = 0;
  337.         my_reverse_modes = 0;
  338.     }
  339.  
  340.     uint8_t *dest;
  341.     const uint8_t *src = modegroups + (my_modegroup<<3);
  342.     dest = modes;
  343.  
  344.     // Figure out how many modes are in this group
  345.     //solid_modes = modegroup + 1;  // Assume group N has N modes
  346.     // No, how about actually counting the modes instead?
  347.     // (in case anyone changes the mode groups above so they don't form a triangle)
  348.     for(solid_modes=0;
  349.         (solid_modes<8) && pgm_read_byte(src + solid_modes);
  350.         solid_modes++ ) {}
  351.  
  352.     // add moon mode (or not) if config says to add it
  353.     if (my_enable_moon) {
  354.         modes[0] = 1;
  355.         dest ++;
  356.     }
  357.  
  358.     // add regular modes
  359.     memcpy_P(dest, src, solid_modes);
  360.     // add hidden modes
  361.     memcpy_P(dest + solid_modes, hiddenmodes, sizeof(hiddenmodes));
  362.     // final count
  363.     mode_cnt = solid_modes + sizeof(hiddenmodes);
  364.     if (my_reverse_modes) {
  365.         // TODO: yuck, isn't there a better way to do this?
  366.         int8_t i;
  367.         src += solid_modes;
  368.         dest = modes;
  369.         for(i=0; i<solid_modes; i++) {
  370.             src --;
  371.             *dest = pgm_read_byte(src);
  372.             dest ++;
  373.         }
  374.         if (my_enable_moon) {
  375.             *dest = 1;
  376.         }
  377.         mode_cnt --;  // get rid of last hidden mode, since it's a duplicate turbo
  378.     }
  379.     if (my_enable_moon) {
  380.         mode_cnt ++;
  381.         solid_modes ++;
  382.     }
  383. }
  384.  
  385. inline void set_output(uint8_t pwm1, uint8_t pwm2, uint8_t pwm3) {
  386.     /* This is no longer needed since we always use PHASE mode.
  387.     // Need PHASE to properly turn off the light
  388.     if ((pwm1==0) && (pwm2==0)) {
  389.         TCCR0A = PHASE;
  390.     }
  391.     */
  392.     FET_PWM_LVL = pwm1;
  393.     PWM_LVL = pwm2;
  394.     ALT_PWM_LVL = pwm3;
  395. }
  396.  
  397. void set_level(uint8_t level) {
  398.     if (level == 0) {
  399.         set_output(0,0,0);
  400.     } else {
  401.         level -= 1;
  402.         set_output(pgm_read_byte(ramp_FET   + level),
  403.                    pgm_read_byte(ramp_7135s + level),
  404.                    pgm_read_byte(ramp_7135  + level));
  405.     }
  406. }
  407.  
  408. void set_mode(uint8_t mode) {
  409. #ifdef SOFT_START
  410.     static uint8_t actual_level = 0;
  411.     uint8_t target_level = mode;
  412.     int8_t shift_amount;
  413.     int8_t diff;
  414.     do {
  415.         diff = target_level - actual_level;
  416.         shift_amount = (diff >> 2) | (diff!=0);
  417.         actual_level += shift_amount;
  418.         set_level(actual_level);
  419.         //_delay_ms(RAMP_SIZE/20);  // slow ramp
  420.         _delay_ms(RAMP_SIZE/4);  // fast ramp
  421.     } while (target_level != actual_level);
  422. #else
  423.     set_level(mode);
  424. #endif  // SOFT_START
  425. }
  426.  
  427. void blink(uint8_t val, uint16_t speed)
  428. {
  429.     for (; val>0; val--)
  430.     {
  431.         set_level(BLINK_BRIGHTNESS);
  432.         _delay_ms(speed);
  433.         set_level(0);
  434.         _delay_ms(speed<<2);
  435.     }
  436. }
  437.  
  438. void strobe(uint8_t ontime, uint8_t offtime) {
  439.     set_level(TURBO);
  440.     _delay_ms(ontime);
  441.     set_level(0);
  442.     _delay_ms(offtime);
  443. }
  444.  
  445. void toggle(uint8_t *var, uint8_t num) {
  446.     // Used for config mode
  447.     // Changes the value of a config option, waits for the user to "save"
  448.     // by turning the light off, then changes the value back in case they
  449.     // didn't save.  Can be used repeatedly on different options, allowing
  450.     // the user to change and save only one at a time.
  451.     blink(num, BLINK_SPEED/8);  // indicate which option number this is
  452.     *var ^= 1;
  453.     save_state();
  454.     // "buzz" for a while to indicate the active toggle window
  455.     for(uint8_t i=0; i<20; i++) {
  456.         set_level(BLINK_BRIGHTNESS);
  457.         _delay_ms(30);
  458.         set_level(0);
  459.         _delay_ms(30);
  460.     }
  461.     // if the user didn't click, reset the value and return
  462.     *var ^= 1;
  463.     save_state();
  464.     _delay_s();
  465. }
  466.  
  467. #ifdef TEMPERATURE_MON
  468. uint8_t get_temperature() {
  469.     ADC_on_temperature();
  470.     // average a few values; temperature is noisy
  471.     uint16_t temp = 0;
  472.     uint8_t i;
  473.     get_voltage();
  474.     for(i=0; i<16; i++) {
  475.         temp += get_voltage();
  476.         _delay_ms(5);
  477.     }
  478.     temp >>= 4;
  479.     return temp;
  480. }
  481. #endif  // TEMPERATURE_MON
  482.  
  483. inline uint8_t read_otc() {
  484.     // Read and return the off-time cap value
  485.     // Start up ADC for capacitor pin
  486.     // disable digital input on ADC pin to reduce power consumption
  487.     DIDR0 |= (1 << CAP_DIDR);
  488.     // 1.1v reference, left-adjust, ADC3/PB3
  489.     ADMUX  = (1 << V_REF) | (1 << ADLAR) | CAP_CHANNEL;
  490.     // enable, start, prescale
  491.     ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;
  492.  
  493.     // Wait for completion
  494.     while (ADCSRA & (1 << ADSC));
  495.     // Start again as datasheet says first result is unreliable
  496.     ADCSRA |= (1 << ADSC);
  497.     // Wait for completion
  498.     while (ADCSRA & (1 << ADSC));
  499.  
  500.     // ADCH should have the value we wanted
  501.     return ADCH;
  502. }
  503.  
  504. int main(void)
  505. {
  506.     // check the OTC immediately before it has a chance to charge or discharge
  507.     uint8_t cap_val = read_otc();  // save it for later
  508.  
  509.     // Charge up the capacitor by setting CAP_PIN to output
  510.     DDRB  |= (1 << CAP_PIN);    // Output
  511.     PORTB |= (1 << CAP_PIN);    // High
  512.  
  513.     // Set PWM pin to output
  514.     DDRB |= (1 << PWM_PIN);     // enable main channel
  515.     DDRB |= (1 << ALT_PWM_PIN); // enable second channel
  516.  
  517.     // enable second PWM counter (OC1B) and third channel (FET, PB4)
  518.     DDRB |= (1 << FET_PWM_PIN); // enable third channel (DDB4)
  519.  
  520.     // Set timer to do PWM for correct output pin and set prescaler timing
  521.     //TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
  522.     //TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
  523.     TCCR0A = PHASE;
  524.     // Set timer to do PWM for correct output pin and set prescaler timing
  525.     TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
  526.  
  527.     // Second PWM counter is ... weird
  528.     //GTCCR = (1<<PWM1B) | (2<<COM1B0);  // enable pwm on pb4, clear output
  529.     //GTCCR |= (1<<PWM1B | 1<<COM1B0);  // enable pwm on pb4, toggle output
  530.     //TCCR1 = 1<<COM1A0 | 1<<CS10;  // toggle, pre-scaler=1
  531.     //TCCR1 = (2<<COM1A0) | (1<<CS10);  // clear, pre-scaler=1
  532.     //TCCR1 = 3<<COM1A0 | 1<<CS10;  // set, pre-scaler=1
  533.     //TCCR1 = (1<<PWM1A) | (2<<COM1A0) | (1<<CS10);  // pre-scaler=1
  534.     TCCR1 = _BV (CS10);
  535.     GTCCR = _BV (COM1B1) | _BV (PWM1B);
  536.     OCR1C = 255;  // Set ceiling value to maximum
  537.  
  538.     // Read config values and saved state
  539.     restore_state();
  540.  
  541.     // Enable the current mode group
  542.     count_modes();
  543.  
  544.  
  545.     // TODO: Enable this?  (might prevent some corner cases, but requires extra room)
  546.     // memory decayed, reset it
  547.     // (should happen on med/long press instead
  548.     //  because mem decay is *much* slower when the OTC is charged
  549.     //  so let's not wait until it decays to reset it)
  550.     //if (fast_presses > 0x20) { fast_presses = 0; }
  551.  
  552.     // check button press time, unless the mode is overridden
  553.     if (! mode_override) {
  554.         if (cap_val > CAP_SHORT) {
  555.             // Indicates they did a short press, go to the next mode
  556.             // We don't care what the fast_presses value is as long as it's over 15
  557.             fast_presses = (fast_presses+1) & 0x1f;
  558.             next_mode(); // Will handle wrap arounds
  559. #ifdef OFFTIM3
  560.         } else if (cap_val > CAP_MED) {
  561.             // User did a medium press, go back one mode
  562.             fast_presses = 0;
  563.             if (offtim3) {
  564.                 prev_mode();  // Will handle "negative" modes and wrap-arounds
  565.             } else {
  566.                 next_mode();  // disabled-med-press acts like short-press
  567.                               // (except that fast_presses isn't reliable then)
  568.             }
  569. #endif
  570.         } else {
  571.             // Long press, keep the same mode
  572.             // ... or reset to the first mode
  573.             fast_presses = 0;
  574.             if (muggle_mode  || (! memory)) {
  575.                 // Reset to the first mode
  576.                 mode_idx = 0;
  577.             }
  578.         }
  579.     }
  580.     save_mode();
  581.  
  582.     // Turn features on or off as needed
  583.     #ifdef VOLTAGE_MON
  584.     ADC_on();
  585.     #else
  586.     ADC_off();
  587.     #endif
  588.  
  589.     uint8_t output;
  590.     uint8_t actual_level;
  591. #ifdef TEMPERATURE_MON
  592.     uint8_t overheat_count = 0;
  593. #endif
  594. #ifdef VOLTAGE_MON
  595.     uint8_t lowbatt_cnt = 0;
  596.     uint8_t i = 0;
  597.     uint8_t voltage;
  598.     // Make sure voltage reading is running for later
  599.     ADCSRA |= (1 << ADSC);
  600. #endif
  601.     //output = pgm_read_byte(modes + mode_idx);
  602.     output = modes[mode_idx];
  603.     actual_level = output;
  604.     // handle mode overrides, like mode group selection and temperature calibration
  605.     if (mode_override) {
  606.         // do nothing; mode is already set
  607.         //mode_idx = mode_override;
  608.         fast_presses = 0;
  609.         output = mode_idx;
  610.     }
  611.     while(1) {
  612.         if (fast_presses > 0x0f) {  // Config mode
  613.             _delay_s();       // wait for user to stop fast-pressing button
  614.             fast_presses = 0; // exit this mode after one use
  615.             mode_idx = 0;
  616.  
  617.             // Enter or leave "muggle mode"?
  618.             toggle(&muggle_mode, 1);
  619.             if (muggle_mode) { continue; };  // don't offer other options in muggle mode
  620.            
  621.             mode_idx = GROUP_SELECT_MODE;
  622.             toggle(&mode_override, 2);
  623.             mode_idx = 0;
  624.            
  625.             toggle(&memory, 3);
  626.  
  627.             toggle(&enable_moon, 4);
  628. #ifdef TEMPERATURE_MON
  629. // Enter temperature calibration mode?
  630. mode_idx = TEMP_CAL_MODE;
  631. toggle(&mode_override, 5);
  632. mode_idx = 0;
  633. #endif
  634.  
  635.             toggle(&reverse_modes, 6);
  636.  
  637.             // Enter the mode group selection mode?
  638.            
  639.  
  640. #ifdef OFFTIM3
  641.             toggle(&offtim3, 7);
  642. #endif
  643.  
  644.  
  645.  
  646.             toggle(&firstboot, 8);
  647.  
  648.             //output = pgm_read_byte(modes + mode_idx);
  649.             output = modes[mode_idx];
  650.             actual_level = output;
  651.         }
  652. #ifdef STROBE
  653.         else if (output == STROBE) {
  654.             // 10Hz tactical strobe
  655.             strobe(50,50);
  656.         }
  657. #endif // ifdef STROBE
  658. #ifdef POLICE_STROBE
  659.         else if (output == POLICE_STROBE) {
  660.             // police-like strobe
  661.             for(i=0;i<8;i++) {
  662.                 strobe(20,40);
  663.             }
  664.             for(i=0;i<8;i++) {
  665.                 strobe(40,80);
  666.             }
  667.         }
  668. #endif // ifdef POLICE_STROBE
  669. #ifdef RANDOM_STROBE
  670.         else if (output == RANDOM_STROBE) {
  671.             // pseudo-random strobe
  672.             uint8_t ms = 34 + (pgm_rand() & 0x3f);
  673.             strobe(ms, ms);
  674.             strobe(ms, ms);
  675.         }
  676. #endif // ifdef RANDOM_STROBE
  677. #ifdef BIKING_STROBE
  678.         else if (output == BIKING_STROBE) {
  679.             // 2-level stutter beacon for biking and such
  680. #ifdef FULL_BIKING_STROBE
  681.             // normal version
  682.             for(i=0;i<4;i++) {
  683.                 set_level(TURBO);
  684.                 //set_output(255,0,0);
  685.                 _delay_ms(5);
  686.                 set_level(LOW);
  687.                 //set_output(0,0,255);
  688.                 _delay_ms(65);
  689.             }
  690.             _delay_ms(720);
  691. #else
  692.             // small/minimal version
  693.             set_level(TURBO);
  694.             //set_output(255,0,0);
  695.             _delay_ms(10);
  696.             set_level(ONE7135);
  697.             //set_output(0,0,255);
  698.             _delay_s();
  699. #endif
  700.         }
  701. #endif  // ifdef BIKING_STROBE
  702. #ifdef RAMP
  703.         else if (output == RAMP) {
  704.             int8_t r;
  705.             // simple ramping test
  706.             for(r=1; r<=RAMP_SIZE; r++) {
  707.                 set_level(r);
  708.                 _delay_ms(90);
  709.             }
  710.             for(r=RAMP_SIZE; r>0; r--) {
  711.                 set_level(r);
  712.                 _delay_ms(90);
  713.             }
  714.         }
  715. #endif  // ifdef RAMP
  716. #ifdef BATTCHECK
  717.         else if (output == BATTCHECK) {
  718. #ifdef BATTCHECK_VpT
  719.             // blink out volts and tenths
  720.             _delay_ms(50);
  721.             uint8_t result = battcheck();
  722.             blink(result >> 5, BLINK_SPEED/8);
  723.             _delay_ms(BLINK_SPEED);
  724.             blink(1,5);
  725.             _delay_ms(BLINK_SPEED*3/2);
  726.             blink(result & 0b00011111, BLINK_SPEED/8);
  727. #else  // ifdef BATTCHECK_VpT
  728.             // blink zero to five times to show voltage
  729.             // (~0%, ~25%, ~50%, ~75%, ~100%, >100%)
  730.             blink(battcheck(), BLINK_SPEED/8);
  731. #endif  // ifdef BATTCHECK_VpT
  732.             // wait between readouts
  733.             _delay_s(); _delay_s();
  734.         }
  735. #endif // ifdef BATTCHECK
  736.         else if (output == GROUP_SELECT_MODE) {
  737.             // exit this mode after one use
  738.             mode_idx = 0;
  739.             mode_override = 0;
  740.  
  741.             for(i=0; i<NUM_MODEGROUPS; i++) {
  742.                 modegroup = i;
  743.                 save_state();
  744.  
  745.                 blink(1, BLINK_SPEED/3);
  746.             }
  747.             _delay_s(); _delay_s();
  748.         }
  749. #ifdef TEMP_CAL_MODE
  750.         else if (output == TEMP_CAL_MODE) {
  751.             // make sure we don't stay in this mode after button press
  752.             mode_idx = 0;
  753.             mode_override = 0;
  754.  
  755.             // Allow the user to turn off thermal regulation if they want
  756.             maxtemp = 255;
  757.             save_state();
  758.             set_mode(REDLOW);  // start somewhat dim during turn-off-regulation mode
  759.             _delay_s(); _delay_s();
  760.  
  761.             // run at highest output level, to generate heat
  762.             set_mode(TURBO);
  763.  
  764.             // measure, save, wait...  repeat
  765.             while(1) {
  766.                 maxtemp = get_temperature();
  767.                 save_state();
  768.                 _delay_s(); _delay_s();
  769.             }
  770.         }
  771. #endif  // TEMP_CAL_MODE
  772.         else {  // Regular non-hidden solid mode
  773.             set_mode(actual_level);
  774. #ifdef TEMPERATURE_MON
  775.             uint8_t temp = get_temperature();
  776.  
  777.             // step down? (or step back up?)
  778.             if (temp >= maxtemp) {
  779.                 overheat_count ++;
  780.                 // reduce noise, and limit the lowest step-down level
  781.                 if ((overheat_count > 15) && (actual_level > (HIGH))) {
  782.                     actual_level --;
  783.                     _delay_ms(5000);  // don't ramp down too fast
  784.                     overheat_count = 0;  // don't ramp down too fast
  785.                 }
  786.             } else {
  787.                 // if we're not overheated, ramp up to the user-requested level
  788.                 overheat_count = 0;
  789.                 if ((temp < maxtemp - 2) && (actual_level < output)) {
  790.                     actual_level ++;
  791.                 }
  792.             }
  793.             set_mode(actual_level);
  794.  
  795.             ADC_on();  // return to voltage mode
  796. #endif
  797.             // Otherwise, just sleep.
  798.             _delay_ms(500);
  799.  
  800.             // If we got this far, the user has stopped fast-pressing.
  801.             // So, don't enter config mode.
  802.             fast_presses = 0;
  803.         }
  804. #ifdef VOLTAGE_MON
  805.         if (ADCSRA & (1 << ADIF)) {  // if a voltage reading is ready
  806.             voltage = ADCH;  // get the waiting value
  807.             // See if voltage is lower than what we were looking for
  808.             if (voltage < ADC_LOW) {
  809.                 lowbatt_cnt ++;
  810.             } else {
  811.                 lowbatt_cnt = 0;
  812.             }
  813.             // See if it's been low for a while, and maybe step down
  814.             if (lowbatt_cnt >= 8) {
  815.                 // DEBUG: blink on step-down:
  816.                 //set_level(0);  _delay_ms(100);
  817.  
  818.                 if (actual_level > RAMP_SIZE) {  // hidden / blinky modes
  819.                     // step down from blinky modes to medium
  820.                     actual_level = RAMP_SIZE / 2;
  821.                 } else if (actual_level > 1) {  // regular solid mode
  822.                     // step down from solid modes somewhat gradually
  823.                     // drop by 25% each time
  824.                     actual_level = (actual_level >> 2) + (actual_level >> 1);
  825.                     // drop by 50% each time
  826.                     //actual_level = (actual_level >> 1);
  827.                 } else { // Already at the lowest mode
  828.                     //mode_idx = 0;  // unnecessary; we never leave this clause
  829.                     //actual_level = 0;  // unnecessary; we never leave this clause
  830.                     // Turn off the light
  831.                     set_level(0);
  832.                     // Power down as many components as possible
  833.                     set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  834.                     sleep_mode();
  835.                 }
  836.                 set_mode(actual_level);
  837.                 output = actual_level;
  838.                 //save_mode();  // we didn't actually change the mode
  839.                 lowbatt_cnt = 0;
  840.                 // Wait at least 2 seconds before lowering the level again
  841.                 _delay_ms(250);  // this will interrupt blinky modes
  842.             }
  843.  
  844.             // Make sure conversion is running for next time through
  845.             ADCSRA |= (1 << ADSC);
  846.         }
  847. #endif  // ifdef VOLTAGE_MON
  848.     }
  849.  
  850.     //return 0; // Standard Return Code
  851. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement