Advertisement
Guest User

Untitled

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