Advertisement
Guest User

Untitled

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