Advertisement
Guest User

bistro

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