Guest User

pilotdog68 S8 code

a guest
Jun 1st, 2015
351
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * BLF EE A6 firmware (special-edition group buy light)
  3.  * This light uses a FET+1 style driver, with a FET on the main PWM channel
  4.  * for the brightest high modes and a single 7135 chip on the secondary PWM
  5.  * channel so we can get stable, efficient low / medium modes.  It also
  6.  * includes a capacitor for measuring off time.
  7.  *
  8.  * Copyright (C) 2015 Selene Scriven
  9.  *
  10.  * This program is free software: you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation, either version 3 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22.  *
  23.  *
  24.  * NANJG 105C Diagram
  25.  *           ---
  26.  *         -|   |- VCC
  27.  *     OTC -|   |- Voltage ADC
  28.  *  Star 3 -|   |- PWM (FET)
  29.  *     GND -|   |- PWM (1x7135)
  30.  *           ---
  31.  *
  32.  * FUSES
  33.  *      I use these fuse settings
  34.  *      Low:  0x75  (4.8MHz CPU without 8x divider, 9.4kHz phase-correct PWM or 18.75kHz fast-PWM)
  35.  *      High: 0xfd  (to enable brownout detection)
  36.  *
  37.  *      For more details on these settings, visit http://github.com/JCapSolutions/blf-firmware/wiki/PWM-Frequency
  38.  *
  39.  * STARS
  40.  *      Star 2 = second PWM output channel
  41.  *      Star 3 = mode memory if soldered, no memory by default
  42.  *      Star 4 = Capacitor for off-time
  43.  *
  44.  * VOLTAGE
  45.  *      Resistor values for voltage divider (reference BLF-VLD README for more info)
  46.  *      Reference voltage can be anywhere from 1.0 to 1.2, so this cannot be all that accurate
  47.  *
  48.  *           VCC
  49.  *            |
  50.  *           Vd (~.25 v drop from protection diode)
  51.  *            |
  52.  *          1912 (R1 19,100 ohms)
  53.  *            |
  54.  *            |---- PB2 from MCU
  55.  *            |
  56.  *          4701 (R2 4,700 ohms)
  57.  *            |
  58.  *           GND
  59.  *
  60.  *   To find out what values to use, flash the driver with battcheck.hex
  61.  *   and hook the light up to each voltage you need a value for.  This is
  62.  *   much more reliable than attempting to calculate the values from a
  63.  *   theoretical formula.
  64.  *
  65.  *   Same for off-time capacitor values.  Measure, don't guess.
  66.  */
  67. #define F_CPU 4800000UL
  68.  
  69. /*
  70.  * =========================================================================
  71.  * Settings to modify per driver
  72.  */
  73.  
  74. //#define FAST 0x23           // fast PWM channel 1 only
  75. //#define PHASE 0x21          // phase-correct PWM channel 1 only
  76. #define FAST 0xA3           // fast PWM both channels
  77. #define PHASE 0xA1          // phase-correct PWM both channels
  78.  
  79. #define VOLTAGE_MON         // Comment out to disable LVP
  80. #define OWN_DELAY           // Should we use the built-in delay or our own?
  81. // Adjust the timing per-driver, since the hardware has high variance
  82. // Higher values will run slower, lower values run faster.
  83. #define DELAY_TWEAK         950
  84.  
  85. //#define OFFTIM3             // Use short/med/long off-time presses
  86.                             // instead of just short/long
  87.  
  88. // comment out to use extended config mode instead of a solderable star
  89. // (controls whether mode memory is on the star or if it's a setting in config mode)
  90. //#define CONFIG_STARS
  91.  
  92. // output to use for blinks on battery check mode (primary PWM level, alt PWM level)
  93. // Use 20,0 for a single-channel driver or 0,20 for a two-channel driver
  94. #define BLINK_BRIGHTNESS    0,20
  95.  
  96. // Mode group 1
  97. #define NUM_MODES1          4
  98. // PWM levels for the big circuit (FET or Nx7135)
  99. #define MODESNx1            0,14,88,255
  100. // PWM levels for the small circuit (1x7135)
  101. #define MODES1x1            8,14,88,255
  102. // PWM speed for each mode
  103. #define MODES_PWM1          PHASE,FAST,FAST,FAST
  104. // Mode group 2
  105. #define NUM_MODES2          5
  106. #define MODESNx2            0,16,90,255,0
  107. #define MODES1x2            7,0,0,0,254
  108. #define MODES_PWM2          PHASE,FAST,FAST,FAST,PHASE
  109. // Hidden modes are *before* the lowest (moon) mode, and should be specified
  110. // in reverse order.  So, to go backward from moon to turbo to strobe to
  111. // battcheck, use BATTCHECK,STROBE,TURBO .
  112. #define NUM_HIDDEN          0
  113. #define HIDDENMODES        
  114. #define HIDDENMODES_PWM    
  115. #define HIDDENMODES_ALT     // Zeroes, same length as NUM_HIDDEN
  116.  
  117. #define TURBO     255       // Convenience code for turbo mode
  118. //#define BATTCHECK 254       // Convenience code for battery check mode
  119. // Uncomment to enable tactical strobe mode
  120. #define STROBE    253       // Convenience code for strobe mode
  121. // Uncomment to unable a 2-level stutter beacon instead of a tactical strobe
  122. //#define BIKING_STROBE 252   // Convenience code for biking strobe mode
  123. // comment out to use minimal version instead (smaller)
  124. #define FULL_BIKING_STROBE
  125.  
  126. #define NON_WDT_TURBO            // enable turbo step-down without WDT
  127. // How many timer ticks before before dropping down.
  128. // Each timer tick is 500ms, so "60" would be a 30-second stepdown.
  129. // Max value of 255 unless you change "ticks"
  130. #define TURBO_TIMEOUT       90
  131.  
  132. // These values were measured using wight's "A17HYBRID-S" driver built by DBCstm.
  133. // Your mileage may vary.
  134. #define ADC_42          174 // the ADC value we expect for 4.20 volts
  135. #define ADC_100         174 // the ADC value for 100% full (4.2V resting)
  136. #define ADC_75          166 // the ADC value for 75% full (4.0V resting)
  137. #define ADC_50          158 // the ADC value for 50% full (3.8V resting)
  138. #define ADC_25          145 // the ADC value for 25% full (3.5V resting)
  139. #define ADC_0           124 // the ADC value for 0% full (3.0V resting)
  140. #define ADC_LOW         126 // When do we start ramping down (2.8V)
  141. #define ADC_CRIT        118 // When do we shut the light off (2.7V)
  142. // These values were copied from s7.c.
  143. // Your mileage may vary.
  144. //#define ADC_42          185 // the ADC value we expect for 4.20 volts
  145. //#define ADC_100         185 // the ADC value for 100% full (4.2V resting)
  146. //#define ADC_75          175 // the ADC value for 75% full (4.0V resting)
  147. //#define ADC_50          164 // the ADC value for 50% full (3.8V resting)
  148. //#define ADC_25          154 // the ADC value for 25% full (3.5V resting)
  149. //#define ADC_0           139 // the ADC value for 0% full (3.0V resting)
  150. //#define ADC_LOW         123 // When do we start ramping down (2.8V)
  151. //#define ADC_CRIT        113 // When do we shut the light off (2.7V)
  152. // Values for testing only:
  153. //#define ADC_LOW         125 // When do we start ramping down (2.8V)
  154. //#define ADC_CRIT        124 // When do we shut the light off (2.7V)
  155.  
  156. // the BLF EE A6 driver may have different offtime cap values than most other drivers
  157. // Values are between 1 and 255, and can be measured with offtime-cap.c
  158. // These #defines are the edge boundaries, not the center of the target.
  159. #ifdef OFFTIM3
  160. #define CAP_SHORT           250  // Anything higher than this is a short press
  161. #define CAP_MED             190  // Between CAP_MED and CAP_SHORT is a medium press
  162.                                  // Below CAP_MED is a long press
  163. #else
  164. #define CAP_SHORT           160  // Anything higher than this is a short press, lower is a long press
  165. #endif
  166.  
  167. /*
  168.  * =========================================================================
  169.  */
  170.  
  171. // Ignore a spurious warning, we did the cast on purpose
  172. #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
  173.  
  174. #ifdef OWN_DELAY
  175. #include <util/delay_basic.h>
  176. // Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
  177. void _delay_ms(uint16_t n)
  178. {
  179.     // TODO: make this take tenths of a ms instead of ms,
  180.     // for more precise timing?
  181.     while(n-- > 0) _delay_loop_2(DELAY_TWEAK);
  182. }
  183. void _delay_s()  // because it saves a bit of ROM space to do it this way
  184. {
  185.     _delay_ms(1000);
  186. }
  187. #else
  188. #include <util/delay.h>
  189. #endif
  190.  
  191. #include <avr/pgmspace.h>
  192. //#include <avr/io.h>
  193. //#include <avr/interrupt.h>
  194. #include <avr/eeprom.h>
  195. #include <avr/sleep.h>
  196. //#include <avr/power.h>
  197.  
  198. #define STAR2_PIN   PB0     // But note that there is no star 2.
  199. #define STAR3_PIN   PB4
  200. #define CAP_PIN     PB3
  201. #define CAP_CHANNEL 0x03    // MUX 03 corresponds with PB3 (Star 4)
  202. #define CAP_DIDR    ADC3D   // Digital input disable bit corresponding with PB3
  203. #define PWM_PIN     PB1
  204. #define ALT_PWM_PIN PB0
  205. #define VOLTAGE_PIN PB2
  206. #define ADC_CHANNEL 0x01    // MUX 01 corresponds with PB2
  207. #define ADC_DIDR    ADC1D   // Digital input disable bit corresponding with PB2
  208. #define ADC_PRSCL   0x06    // clk/64
  209.  
  210. #define PWM_LVL     OCR0B   // OCR0B is the output compare register for PB1
  211. #define ALT_PWM_LVL OCR0A   // OCR0A is the output compare register for PB0
  212.  
  213. /*
  214.  * global variables
  215.  */
  216.  
  217. // Config / state variables
  218. uint8_t eepos = 0;
  219. uint8_t memory = 0;        // mode memory, or not (set via soldered star)
  220. uint8_t modegroup = 0;     // which mode group (set above in #defines)
  221. uint8_t mode_idx = 0;      // current or last-used mode number
  222. // counter for entering config mode
  223. // (needs to be remembered while off, but only for up to half a second)
  224. uint8_t fast_presses __attribute__ ((section (".noinit")));
  225.  
  226. // NOTE: Only '1' is known to work; -1 will probably break and is untested.
  227. // In other words, short press goes to the next (higher) mode,
  228. // medium press goes to the previous (lower) mode.
  229. #define mode_dir 1
  230. // total length of current mode group's array
  231. uint8_t mode_cnt;
  232. // number of regular non-hidden modes in current mode group
  233. uint8_t solid_modes;
  234. // number of hidden modes in the current mode group
  235. // (hardcoded because both groups have the same hidden modes)
  236. //uint8_t hidden_modes = NUM_HIDDEN;  // this is never used
  237.  
  238.  
  239. // Modes (gets set when the light starts up based on saved config values)
  240. PROGMEM const uint8_t modesNx1[] = { MODESNx1, HIDDENMODES };
  241. PROGMEM const uint8_t modesNx2[] = { MODESNx2, HIDDENMODES };
  242. const uint8_t *modesNx;  // gets pointed at whatever group is current
  243.  
  244. PROGMEM const uint8_t modes1x1[] = { MODES1x1, HIDDENMODES_ALT };
  245. PROGMEM const uint8_t modes1x2[] = { MODES1x2, HIDDENMODES_ALT };
  246. const uint8_t *modes1x;
  247.  
  248. PROGMEM const uint8_t modes_pwm1[] = { MODES_PWM1, HIDDENMODES_PWM };
  249. PROGMEM const uint8_t modes_pwm2[] = { MODES_PWM2, HIDDENMODES_PWM };
  250. const uint8_t *modes_pwm;
  251.  
  252. PROGMEM const uint8_t voltage_blinks[] = {
  253.     ADC_0,    // 1 blink  for 0%-25%
  254.     ADC_25,   // 2 blinks for 25%-50%
  255.     ADC_50,   // 3 blinks for 50%-75%
  256.     ADC_75,   // 4 blinks for 75%-100%
  257.     ADC_100,  // 5 blinks for >100%
  258.     255,      // Ceiling, don't remove
  259. };
  260.  
  261. void save_state() {  // central method for writing (with wear leveling)
  262.     // a single 16-bit write uses less ROM space than two 8-bit writes
  263.     uint8_t eep;
  264.     uint8_t oldpos=eepos;
  265.  
  266.     eepos = (eepos+1) & 63;  // wear leveling, use next cell
  267.  
  268. #ifdef CONFIG_STARS
  269.     eep = mode_idx | (modegroup << 5);
  270. #else
  271.     eep = mode_idx | (modegroup << 5) | (memory << 6);
  272. #endif
  273.     eeprom_write_byte((uint8_t *)(eepos), eep);      // save current state
  274.     eeprom_write_byte((uint8_t *)(oldpos), 0xff);    // erase old state
  275. }
  276.  
  277. void restore_state() {
  278.     uint8_t eep;
  279.     // find the config data
  280.     for(eepos=0; eepos<64; eepos++) {
  281.         eep = eeprom_read_byte((const uint8_t *)eepos);
  282.         if (eep != 0xff) break;
  283.     }
  284.     // unpack the config data
  285.     if (eepos < 64) {
  286.         mode_idx = eep & 0x0f;
  287.         modegroup = (eep >> 5) & 1;
  288. #ifndef CONFIG_STARS
  289.         memory = (eep >> 6) & 1;
  290. #endif
  291.     }
  292.     // unnecessary, save_state handles wrap-around
  293.     // (and we don't really care about it skipping cell 0 once in a while)
  294.     //else eepos=0;
  295. }
  296.  
  297. inline void next_mode() {
  298.     mode_idx += 1;
  299.     if (mode_idx >= solid_modes) {
  300.         // Wrap around, skipping the hidden modes
  301.         // (note: this also applies when going "forward" from any hidden mode)
  302.         mode_idx = 0;
  303.     }
  304. }
  305.  
  306. #ifdef OFFTIM3
  307. inline void prev_mode() {
  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. #ifdef CONFIG_STARS
  322. inline void check_stars() {
  323.     // Configure options based on stars
  324.     // 0 being low for soldered, 1 for pulled-up for not soldered
  325. #if 0  // not implemented, STAR2_PIN is used for second PWM channel
  326.     // Moon
  327.     // enable moon mode?
  328.     if ((PINB & (1 << STAR2_PIN)) == 0) {
  329.         modes[mode_cnt++] = MODE_MOON;
  330.     }
  331. #endif
  332. #if 0  // Mode order not as important as mem/no-mem
  333.     // Mode order
  334.     if ((PINB & (1 << STAR3_PIN)) == 0) {
  335.         // High to Low
  336.         mode_dir = -1;
  337.     } else {
  338.         mode_dir = 1;
  339.     }
  340. #endif
  341.     // Memory
  342.     if ((PINB & (1 << STAR3_PIN)) == 0) {
  343.         memory = 1;  // solder to enable memory
  344.     } else {
  345.         memory = 0;  // unsolder to disable memory
  346.     }
  347. }
  348. #endif  // ifdef CONFIG_STARS
  349.  
  350. void count_modes() {
  351.     /*
  352.      * Determine how many solid and hidden modes we have.
  353.      * The modes_pwm array should have several values for regular modes
  354.      * then some values for hidden modes.
  355.      *
  356.      * (this matters because we have more than one set of modes to choose
  357.      *  from, so we need to count at runtime)
  358.      */
  359.     if (modegroup == 0) {
  360.         solid_modes = NUM_MODES1;
  361.         modesNx = modesNx1;
  362.         modes1x = modes1x1;
  363.         modes_pwm = modes_pwm1;
  364.     } else {
  365.         solid_modes = NUM_MODES2;
  366.         modesNx = modesNx2;
  367.         modes1x = modes1x2;
  368.         modes_pwm = modes_pwm2;
  369.     }
  370.     mode_cnt = solid_modes + NUM_HIDDEN;
  371. }
  372.  
  373. #ifdef VOLTAGE_MON
  374. inline void ADC_on() {
  375.     DIDR0 |= (1 << ADC_DIDR);                           // disable digital input on ADC pin to reduce power consumption
  376.     ADMUX  = (1 << REFS0) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
  377.     ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;   // enable, start, prescale
  378. }
  379. #else
  380. inline void ADC_off() {
  381.     ADCSRA &= ~(1<<7); //ADC off
  382. }
  383. #endif
  384.  
  385. void set_output(uint8_t pwm1, uint8_t pwm2) {
  386.     // Need PHASE to properly turn off the light
  387.     if ((pwm1==0) && (pwm2==0)) {
  388.         TCCR0A = PHASE;
  389.     }
  390.     PWM_LVL = pwm1;
  391.     ALT_PWM_LVL = pwm2;
  392. }
  393.  
  394. void set_mode(uint8_t mode) {
  395.     TCCR0A = pgm_read_byte(modes_pwm + mode);
  396.     set_output(pgm_read_byte(modesNx + mode), pgm_read_byte(modes1x + mode));
  397.     /*
  398.     // Only set output for solid modes
  399.     uint8_t out = pgm_read_byte(modesNx + mode);
  400.     if ((out < 250) || (out == 255)) {
  401.         set_output(pgm_read_byte(modesNx + mode), pgm_read_byte(modes1x + mode));
  402.     }
  403.     */
  404. }
  405.  
  406. #ifdef VOLTAGE_MON
  407. uint8_t get_voltage() {
  408.     // Start conversion
  409.     ADCSRA |= (1 << ADSC);
  410.     // Wait for completion
  411.     while (ADCSRA & (1 << ADSC));
  412.     // See if voltage is lower than what we were looking for
  413.     return ADCH;
  414. }
  415. #endif
  416.  
  417. void blink(uint8_t val)
  418. {
  419.     for (; val>0; val--)
  420.     {
  421.         set_output(BLINK_BRIGHTNESS);
  422.         _delay_ms(100);
  423.         set_output(0,0);
  424.         _delay_ms(400);
  425.     }
  426. }
  427.  
  428. #ifndef CONFIG_STARS
  429. void toggle(uint8_t *var) {
  430.     // Used for extended config mode
  431.     // Changes the value of a config option, waits for the user to "save"
  432.     // by turning the light off, then changes the value back in case they
  433.     // didn't save.  Can be used repeatedly on different options, allowing
  434.     // the user to change and save only one at a time.
  435.     *var ^= 1;
  436.     save_state();
  437.     blink(2);
  438.     *var ^= 1;
  439.     save_state();
  440.     _delay_s();
  441. }
  442. #endif // ifndef CONFIG_STARS
  443.  
  444. int main(void)
  445. {
  446.     uint8_t cap_val;
  447.  
  448.     // Read the off-time cap *first* to get the most accurate reading
  449.     // Start up ADC for capacitor pin
  450.     DIDR0 |= (1 << CAP_DIDR);                           // disable digital input on ADC pin to reduce power consumption
  451.     ADMUX  = (1 << REFS0) | (1 << ADLAR) | CAP_CHANNEL; // 1.1v reference, left-adjust, ADC3/PB3
  452.     ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;   // enable, start, prescale
  453.  
  454.     // Wait for completion
  455.     while (ADCSRA & (1 << ADSC));
  456.     // Start again as datasheet says first result is unreliable
  457.     ADCSRA |= (1 << ADSC);
  458.     // Wait for completion
  459.     while (ADCSRA & (1 << ADSC));
  460.     cap_val = ADCH; // save this for later
  461.  
  462. #ifdef CONFIG_STARS
  463.     // All ports default to input, but turn pull-up resistors on for the stars (not the ADC input!  Made that mistake already)
  464.     // only one star, because one is used for PWM channel 2
  465.     // and the other is used for the off-time capacitor
  466.     PORTB = (1 << STAR3_PIN);
  467. #endif
  468.  
  469.     // Set PWM pin to output
  470.     DDRB |= (1 << PWM_PIN);     // enable main channel
  471.     DDRB |= (1 << ALT_PWM_PIN); // enable second channel
  472.  
  473.     // Set timer to do PWM for correct output pin and set prescaler timing
  474.     //TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
  475.     //TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
  476.     TCCR0A = PHASE;
  477.     // Set timer to do PWM for correct output pin and set prescaler timing
  478.     TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
  479.  
  480.     // Read config values and saved state
  481. #ifdef CONFIG_STARS
  482.     check_stars();
  483. #endif
  484.     restore_state();
  485.     // Enable the current mode group
  486.     count_modes();
  487.  
  488.  
  489.     // memory decayed, reset it
  490.     // (should happen on med/long press instead
  491.     //  because mem decay is *much* slower when the OTC is charged
  492.     //  so let's not wait until it decays to reset it)
  493.     //if (fast_presses > 0x20) { fast_presses = 0; }
  494.  
  495.     if (cap_val > CAP_SHORT) {
  496.         // We don't care what the value is as long as it's over 15
  497.         fast_presses = (fast_presses+1) & 0x1f;
  498.         // Indicates they did a short press, go to the next mode
  499.         next_mode(); // Will handle wrap arounds
  500. #ifdef OFFTIM3
  501.     } else if (cap_val > CAP_MED) {
  502.         fast_presses = 0;
  503.         // User did a medium press, go back one mode
  504.         prev_mode(); // Will handle "negative" modes and wrap-arounds
  505. #endif
  506.     } else {
  507.         // Long press, keep the same mode
  508.         // ... or reset to the first mode
  509.         fast_presses = 0;
  510.         if (! memory) {
  511.             // Reset to the first mode
  512.             mode_idx = 0;
  513.         }
  514.     }
  515.     save_state();
  516.  
  517.     // Turn off ADC
  518.     //ADC_off();
  519.  
  520.     // Charge up the capacitor by setting CAP_PIN to output
  521.     DDRB  |= (1 << CAP_PIN);    // Output
  522.     PORTB |= (1 << CAP_PIN);    // High
  523.  
  524.     // Turn features on or off as needed
  525.     #ifdef VOLTAGE_MON
  526.     ADC_on();
  527.     #else
  528.     ADC_off();
  529.     #endif
  530.     //ACSR   |=  (1<<7); //AC off
  531.  
  532.     // Enable sleep mode set to Idle that will be triggered by the sleep_mode() command.
  533.     // Will allow us to go idle between WDT interrupts
  534.     //set_sleep_mode(SLEEP_MODE_IDLE);  // not used due to blinky modes
  535.  
  536.     uint8_t output;
  537. #ifdef NON_WDT_TURBO
  538.     uint8_t ticks = 0;
  539. #endif
  540. #ifdef VOLTAGE_MON
  541.     uint8_t lowbatt_cnt = 0;
  542.     uint8_t i = 0;
  543.     uint8_t voltage;
  544.     // Make sure voltage reading is running for later
  545.     ADCSRA |= (1 << ADSC);
  546. #endif
  547.     while(1) {
  548.         output = pgm_read_byte(modesNx + mode_idx);
  549.         if (fast_presses > 0x0f) {  // Config mode
  550.             _delay_s();       // wait for user to stop fast-pressing button
  551.             fast_presses = 0; // exit this mode after one use
  552.             mode_idx = 0;
  553.  
  554. #ifdef CONFIG_STARS
  555.             // Short/small version of the config mode
  556.             // Toggle the mode group, blink, then exit
  557.             modegroup ^= 1;
  558.             save_state();
  559.             count_modes();  // reconfigure without a power cycle
  560.             blink(1);
  561. #else
  562.             // Longer/larger version of the config mode
  563.             // Toggle the mode group, blink, un-toggle, continue
  564.             toggle(&modegroup);
  565.  
  566.             // Toggle memory, blink, untoggle, exit
  567.             toggle(&memory);
  568. #endif  // ifdef CONFIG_STARS
  569.         }
  570. #ifdef STROBE
  571.         else if (output == STROBE) {
  572.             // 10Hz tactical strobe
  573.             set_output(255,0);
  574.             _delay_ms(50);
  575.             set_output(0,0);
  576.             _delay_ms(50);
  577.         }
  578. #endif // ifdef STROBE
  579. #ifdef BIKING_STROBE
  580.         else if (output == BIKING_STROBE) {
  581.             // 2-level stutter beacon for biking and such
  582. #ifdef FULL_BIKING_STROBE
  583.             // normal version
  584.             for(i=0;i<4;i++) {
  585.                 set_output(255,0);
  586.                 _delay_ms(5);
  587.                 set_output(0,255);
  588.                 _delay_ms(65);
  589.             }
  590.             _delay_ms(720);
  591. #else
  592.             // small/minimal version
  593.             set_output(255,0);
  594.             _delay_ms(10);
  595.             set_output(0,255);
  596.             _delay_s();
  597. #endif
  598.         }
  599. #endif  // ifdef BIKING_STROBE
  600. #ifdef BATTCHECK
  601.         else if (output == BATTCHECK) {
  602.             voltage = get_voltage();
  603.             // figure out how many times to blink
  604.             for (i=0;
  605.                     voltage > pgm_read_byte(voltage_blinks + i);
  606.                     i ++) {}
  607.  
  608.             // blink zero to five times to show voltage
  609.             // (~0%, ~25%, ~50%, ~75%, ~100%, >100%)
  610.             blink(i);
  611.             // wait between readouts
  612.             _delay_s(); _delay_s();
  613.         }
  614. #endif // ifdef BATTCHECK
  615.         else {  // Regular non-hidden solid mode
  616.             set_mode(mode_idx);
  617.             // This part of the code will mostly replace the WDT tick code.
  618. #ifdef NON_WDT_TURBO
  619.             // Do some magic here to handle turbo step-down
  620.             //if (ticks < 255) ticks++;  // don't roll over
  621.             ticks ++;  // actually, we don't care about roll-over prevention
  622.             if ((ticks > TURBO_TIMEOUT)
  623.                     && (output == TURBO)) {
  624.                 mode_idx = mode_idx - 1; // step down one mode
  625.                 set_mode(mode_idx);
  626.                 save_state();
  627.             }
  628. #endif
  629.             // Otherwise, just sleep.
  630.             _delay_ms(500);
  631.  
  632.             // If we got this far, the user has stopped fast-pressing.
  633.             // So, don't enter config mode.
  634.             fast_presses = 0;
  635.         }
  636. #ifdef VOLTAGE_MON
  637. #if 1
  638.         if (ADCSRA & (1 << ADIF)) {  // if a voltage reading is ready
  639.             voltage = ADCH; // get_voltage();
  640.             // See if voltage is lower than what we were looking for
  641.             //if (voltage < ((mode_idx <= 1) ? ADC_CRIT : ADC_LOW)) {
  642.             if (voltage < ADC_LOW) {
  643.                 lowbatt_cnt ++;
  644.             } else {
  645.                 lowbatt_cnt = 0;
  646.             }
  647.             // See if it's been low for a while, and maybe step down
  648.             if (lowbatt_cnt >= 8) {
  649.                 // DEBUG: blink on step-down:
  650.                 //set_output(0,0);  _delay_ms(100);
  651.                 i = mode_idx; // save space by not accessing mode_idx more than necessary
  652.                 // properly track hidden vs normal modes
  653.                 if (i >= solid_modes) {
  654.                     // step down from blinky modes to medium
  655.                     i = 2;
  656.                 } else if (i > 0) {
  657.                     // step down from solid modes one at a time
  658.                     i -= 1;
  659.                 } else { // Already at the lowest mode
  660.                     i = 0;
  661.                     // Turn off the light
  662.                     set_output(0,0);
  663.                     // Power down as many components as possible
  664.                     set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  665.                     sleep_mode();
  666.                 }
  667.                 set_mode(i);
  668.                 mode_idx = i;
  669.                 save_state();
  670.                 lowbatt_cnt = 0;
  671.                 // Wait at least 2 seconds before lowering the level again
  672.                 _delay_ms(250);  // this will interrupt blinky modes
  673.             }
  674.  
  675.             // Make sure conversion is running for next time through
  676.             ADCSRA |= (1 << ADSC);
  677.         }
  678. #endif
  679. #endif  // ifdef VOLTAGE_MON
  680.         //sleep_mode();  // incompatible with blinky modes
  681.  
  682.         // If we got this far, the user has stopped fast-pressing.
  683.         // So, don't enter config mode.
  684.         //fast_presses = 0;  // doesn't interact well with strobe, too fast
  685.     }
  686.  
  687.     //return 0; // Standard Return Code
  688. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×