dhiltonp

hexbright.cpp sensor prints

Feb 16th, 2013
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 38.00 KB | None | 0 0
  1. /*
  2. Copyright (c) 2012, "David Hilton" <[email protected]>
  3. All rights reserved.
  4.  
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions are met:
  7.  
  8. 1. Redistributions of source code must retain the above copyright notice, this
  9. list of conditions and the following disclaimer.
  10. 2. Redistributions in binary form must reproduce the above copyright notice,
  11. this list of conditions and the following disclaimer in the documentation
  12. and/or other materials provided with the distribution.
  13.  
  14. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  18. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24.  
  25. The views and conclusions contained in the software and documentation are those
  26. of the authors and should not be interpreted as representing official policies,
  27. either expressed or implied, of the FreeBSD Project.
  28. */
  29.  
  30.  
  31. #include "hexbright.h"
  32. #include <limits.h>
  33.  
  34. #ifndef __AVR // we're not compiling for arduino (probably testing), use these stubs
  35. #include "NotArduino.h"
  36. #else
  37. #include "pin_interface.h"
  38. #include "../digitalWriteFast/digitalWriteFast.h"
  39. #endif
  40.  
  41. // Pin assignments
  42. #define DPIN_RLED_SW 2 // both red led and switch. pinMode OUTPUT = led, pinMode INPUT = switch
  43. #define DPIN_GLED 5
  44. #define DPIN_PWR 8
  45. #define DPIN_DRV_MODE 9
  46. #define DPIN_DRV_EN 10
  47. #define APIN_TEMP 0
  48. #define APIN_CHARGE 3
  49. #define APIN_BAND_GAP 14
  50.  
  51.  
  52. ///////////////////////////////////////////////
  53. /////////////HARDWARE INIT, UPDATE/////////////
  54. ///////////////////////////////////////////////
  55.  
  56. const float update_delay = 8.3333333; // in lock-step with the accelerometer
  57. unsigned long continue_time;
  58.  
  59. #ifdef STROBE
  60. unsigned long next_strobe = STROBE_OFF;
  61. unsigned long strobe_delay = 0;
  62. int strobe_duration = 100;
  63. #endif
  64.  
  65. hexbright::hexbright() {
  66. }
  67.  
  68. #ifdef FLASH_CHECKSUM
  69. int hexbright::flash_checksum() {
  70.   int checksum = 0;
  71.   for(int i=0; i<16384; i++) {
  72.     checksum+=pgm_read_byte(i);
  73.   }
  74.   return checksum;
  75. }
  76. #endif
  77.  
  78. void hexbright::init_hardware() {
  79.   // We just powered on! That means either we got plugged
  80.   // into USB, or the user is pressing the power button.
  81.   pinModeFast(DPIN_PWR, INPUT);
  82.   digitalWriteFast(DPIN_PWR, LOW);
  83.   // Initialize GPIO
  84.   pinModeFast(DPIN_RLED_SW, INPUT);
  85.   pinModeFast(DPIN_GLED, OUTPUT);
  86.   pinModeFast(DPIN_DRV_MODE, OUTPUT);
  87.   pinModeFast(DPIN_DRV_EN, OUTPUT);
  88.   digitalWriteFast(DPIN_DRV_MODE, LOW);
  89.   digitalWriteFast(DPIN_DRV_EN, LOW);
  90.  
  91. #if (DEBUG!=DEBUG_OFF)
  92.   // Initialize serial busses
  93.   Serial.begin(9600);
  94.   Wire.begin();
  95.   Serial.println("DEBUG MODE ON");
  96. #endif
  97. #if (DEBUG!=DEBUG_OFF && DEBUG!=DEBUG_PRINT)
  98.   if(DEBUG==DEBUG_LIGHT) {
  99.     // do a full light range sweep, (printing all light intensity info)
  100.     set_light(0,1000,update_delay*1002);
  101.   } else if (DEBUG==DEBUG_TEMP) {
  102.     set_light(0, MAX_LEVEL, NOW);
  103.   } else if (DEBUG==DEBUG_LOOP) {
  104.     // note the use of TIME_MS/update_delay.
  105.     set_light(0, MAX_LEVEL, 2500/update_delay);
  106.   }
  107.  
  108. #ifdef FREE_RAM
  109.   Serial.print("Ram available: ");
  110.   Serial.print(freeRam());
  111.   Serial.println("/1024 bytes");
  112. #endif
  113. #ifdef FLASH_CHECKSUM
  114.   Serial.print("Flash checksum: ");
  115.   Serial.println(flash_checksum());
  116. #endif
  117.  
  118. #endif // DEBUG!=DEBUG_OFF
  119.  
  120. #ifdef ACCELEROMETER
  121.   Serial.println("eas");
  122.   enable_accelerometer();
  123.   Serial.println("ead");
  124. #endif
  125.  
  126.   continue_time = micros();
  127. }
  128.  
  129. void hexbright::update() {
  130.   unsigned long now;
  131.  
  132. #if (DEBUG==DEBUG_LOOP)
  133.   unsigned long start_time=micros();
  134. #endif
  135.  
  136.  
  137. #ifdef STROBE
  138.   while (true) {
  139.     do {
  140.       now = micros();
  141.     } while (next_strobe > now && // not ready for strobe
  142. continue_time > now); // not ready for update
  143.  
  144.     if (next_strobe <= now) {
  145.       if (now - next_strobe <26) {
  146. digitalWriteFast(DPIN_DRV_EN, HIGH);
  147. delayMicroseconds(strobe_duration);
  148. digitalWriteFast(DPIN_DRV_EN, LOW);
  149.       }
  150.       next_strobe += strobe_delay;
  151.     }
  152.     if(continue_time <= now) {
  153.       if(strobe_delay>update_delay && // we strobe less than once every 8333 microseconds
  154. next_strobe-continue_time < 4000) // and the next strobe is within 4000 microseconds (may occur before we return)
  155. continue;
  156.       else
  157. break;
  158.     }
  159.   } // do nothing... (will short circuit once every 70 minutes (micros maxint))
  160. #else
  161.     do {
  162.       now = micros();
  163.     } while (continue_time > now); // not ready for update
  164. #endif
  165.  
  166.   // if we're in debug mode, let us know if our loops are too large
  167. #if (DEBUG!=DEBUG_OFF && DEBUG!=DEBUG_PRINT)
  168.   static int i=0;
  169. #if (DEBUG==DEBUG_LOOP)
  170.   static unsigned long last_time = 0;
  171.   if(!i) {
  172.     Serial.print("Time used: ");
  173.     Serial.print(start_time-last_time);
  174.     Serial.println("/8333");
  175.   }
  176.   last_time = now;
  177. #endif
  178.   if(now-continue_time>5000 && !i) {
  179.     // This may be caused by too much processing for our update_delay, or by too many print statements)
  180.     // If you're triggering this, your button and light will react more slowly, and some accelerometer
  181.     // data is being missed.
  182.     Serial.println("WARNING: code is too slow");
  183.   }
  184.   if (!i)
  185.     i=1000/update_delay; // display loop output every second
  186.   else
  187.     i--;
  188. #endif
  189.  
  190.  
  191.   // power saving modes described here: http://www.atmel.com/Images/2545s.pdf
  192.   //run overheat protection, time display, track battery usage
  193.  
  194. #ifdef LED
  195.   // regardless of desired led state, turn it off so we can read the button
  196.   _led_off(RLED);
  197.   delayMicroseconds(50); // let the light stabilize...
  198.   read_button();
  199.   // turn on (or off) the leds, if appropriate
  200.   adjust_leds();
  201. #ifdef PRINT_NUMBER
  202.   update_number();
  203. #endif
  204. #else
  205.   read_button();
  206. #endif
  207.  
  208.   Serial.println("rts");
  209.   read_thermal_sensor(); // takes about .2 ms to execute (fairly long, relative to the other steps)
  210.   Serial.println("rcs");
  211.   read_charge_state();
  212.   Serial.println("rav");
  213.   read_avr_voltage();
  214.  
  215. #ifdef ACCELEROMETER
  216.   Serial.println("ra");
  217.   read_accelerometer();
  218.   Serial.println("done");
  219.   find_down();
  220. #endif
  221.   detect_overheating();
  222.   detect_low_battery();
  223.   apply_max_light_level();
  224.  
  225.   // change light levels as requested
  226.   adjust_light();
  227.  
  228.   // advance time at the same rate as values are changed in the accelerometer.
  229.   // advance continue_time here, so the first run through short-circuits,
  230.   // meaning we will read hardware immediately after power on.
  231.   continue_time = continue_time+(1000*update_delay);
  232. }
  233.  
  234. #ifdef FREE_RAM
  235. //// freeRam function from: http://playground.arduino.cc/Code/AvailableMemory
  236. int hexbright::freeRam () {
  237.   extern int __heap_start, *__brkval;
  238.   int v;
  239.   return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
  240. }
  241. #endif
  242.  
  243.  
  244. ///////////////////////////////////////////////
  245. ///////////////////Filters/////////////////////
  246. ///////////////////////////////////////////////
  247.  
  248. inline int hexbright::low_pass_filter(int last_estimate, int current_reading) {
  249.   // The sum of these two constant multipliers (which equals the divisor),
  250.   // should not exceed 210 (to avoid integer overflow)
  251.   // the individual values selected do effect the resulting sketch size :/
  252.   return (2*last_estimate + 3*current_reading)/5;
  253. }
  254.  
  255. inline int hexbright::stdev_filter(int last_estimate, int current_reading) {
  256.   float stdev = 3.3; // our standard deviation due to noise (pre calculated using accelerometer data at rest)
  257.   int diff = -abs(last_estimate-current_reading);
  258.   float deviation = diff/stdev;
  259.   float probability = exp(deviation)/1.25; // 2.5 ~= M_SQRT2PI, /2 because cdf is only one way
  260.   // exp by itself takes 400-500 bytes. This isn't good.
  261.   return probability*last_estimate + (1-probability)*current_reading;
  262. }
  263.  
  264.  
  265. inline int hexbright::stdev_filter2(int last_estimate, int current_reading) {
  266.   // uses 1/deviation^2 for our cdf approximation
  267.   float stdev = 3.5; // our standard deviation due to noise (pre calculated using accelerometer data at rest)
  268.   int diff = abs(last_estimate-current_reading);
  269.   float deviation = diff/stdev;
  270.   float probability;
  271.   if(deviation>1) // estimate where we fall on the cdf
  272.     probability = 1/(deviation*deviation);
  273.   else
  274.     probability = .65;
  275.   // exp by itself takes 400-500 bytes. This isn't good.
  276.   return probability*last_estimate + (1-probability)*current_reading;
  277. }
  278.  
  279. inline int hexbright::stdev_filter3(int last_estimate, int current_reading) {
  280.   // uses 1/deviation^2 for our cdf approximation, switched to ints
  281.   int stdev = 3.5*10; // our standard deviation due to noise (pre calculated using accelerometer data at rest)
  282.   int diff = abs(last_estimate-current_reading)*10;
  283.   // differences < 4 have a deviation of 0
  284.   int deviation = diff/stdev;
  285.   int probability;
  286.   if(deviation>1) // estimate where we fall on the cdf
  287.     probability = 100/(deviation*deviation);
  288.   else
  289.     probability = 70;
  290.   return (probability*last_estimate + (100-probability)*current_reading)/100;
  291. }
  292.  
  293.  
  294. ///////////////////////////////////////////////
  295. ////////////////LIGHT CONTROL//////////////////
  296. ///////////////////////////////////////////////
  297.  
  298. // Light level must be sufficiently precise for quality low-light brightness and accurate power adjustment at high brightness.
  299. // light level should be converted to logarithmic, square root or cube root values (from lumens), so as to be perceptually linear...
  300. // http://www.candlepowerforums.com/vb/newreply.php?p=3889844
  301. // This is handled inside of set_light_level.
  302.  
  303.  
  304. int start_light_level = 0;
  305. int end_light_level = 0;
  306. int change_duration = 0;
  307. int change_done = 0;
  308.  
  309. int max_light_level = MAX_LEVEL;
  310.  
  311.  
  312. void hexbright::set_light(int start_level, int end_level, long time) {
  313.   // duration ranges from 1-MAXINT
  314.   // light_level can be from 0-1000
  315.   int current_level = get_light_level();
  316.   if(start_level == CURRENT_LEVEL) {
  317.     start_light_level = current_level;
  318.   } else {
  319.     start_light_level = start_level;
  320.   }
  321.   if (end_level == CURRENT_LEVEL) {
  322.     end_light_level = get_light_level();
  323.   } else {
  324.     end_light_level = end_level;
  325.   }
  326.  
  327.   change_duration = ((float)time)/update_delay;
  328.   change_done = 0;
  329. #if (DEBUG==DEBUG_LIGHT)
  330.   Serial.print("Light adjust requested, start level: ");
  331.   Serial.println(start_light_level);
  332.   Serial.print("Over ");
  333.   Serial.print(change_duration);
  334.   Serial.println(" updates");
  335. #endif
  336.  
  337. }
  338.  
  339. int hexbright::get_light_level() {
  340.   if(change_done>=change_duration)
  341.     return end_light_level;
  342.   else
  343.     return (end_light_level-start_light_level)*((float)change_done/change_duration) +start_light_level;
  344. }
  345.  
  346. int hexbright::get_max_light_level() {
  347.   int light_level = get_light_level();
  348.  
  349.   if(light_level>max_light_level)
  350.     return max_light_level;
  351.   return light_level;
  352. }
  353.  
  354. int hexbright::light_change_remaining() {
  355.   // change_done ends up at -1, add one to counter
  356.   // return (change_duration-change_done+1)*update_delay;
  357.   int tmp = change_duration-change_done;
  358.   if(tmp<=0)
  359.     return 0;
  360.   return tmp*update_delay;
  361. }
  362.  
  363. void hexbright::set_light_level(unsigned long level) {
  364.   // LOW 255 approximately equals HIGH 48/49. There is a color change.
  365.   // Values < 4 do not provide any light.
  366.   // I don't know about relative power draw.
  367.  
  368.   // look at linearity_test.ino for more detail on these algorithms.
  369.  
  370. #if (DEBUG==DEBUG_LIGHT)
  371.   Serial.print("light level: ");
  372.   Serial.println(level);
  373. #endif
  374.   pinModeFast(DPIN_PWR, OUTPUT);
  375.   digitalWriteFast(DPIN_PWR, HIGH);
  376.   if(level == 0) {
  377.     // lowest possible power, but cpu still running (DPIN_PWR still high)
  378.     digitalWriteFast(DPIN_DRV_MODE, LOW);
  379.     analogWrite(DPIN_DRV_EN, 0);
  380.   } else if(level == OFF_LEVEL) {
  381.     // power off (DPIN_PWR LOW)
  382.     pinModeFast(DPIN_PWR, OUTPUT);
  383.     digitalWriteFast(DPIN_PWR, LOW);
  384.     digitalWriteFast(DPIN_DRV_MODE, LOW);
  385.     analogWrite(DPIN_DRV_EN, 0);
  386.   } else if(level<=500) {
  387.     digitalWriteFast(DPIN_DRV_MODE, LOW);
  388.     analogWrite(DPIN_DRV_EN, .000000633*(level*level*level)+.000632*(level*level)+.0285*level+3.98);
  389.   } else {
  390.     level -= 500;
  391.     digitalWriteFast(DPIN_DRV_MODE, HIGH);
  392.     analogWrite(DPIN_DRV_EN, .00000052*(level*level*level)+.000365*(level*level)+.108*level+44.8);
  393.   }
  394. }
  395.  
  396. void hexbright::adjust_light() {
  397.   // sets actual light level, altering value to be perceptually linear, based on steven's area brightness (cube root)
  398.   if(change_done<=change_duration) {
  399.     int light_level = hexbright::get_max_light_level();
  400.     set_light_level(light_level);
  401.    
  402.     change_done++;
  403.   }
  404. }
  405.  
  406. void hexbright::apply_max_light_level() {
  407.   // if max_light_level has changed, guarantee a light adjustment:
  408.   // the second test guarantees that we won't turn on if we are
  409.   // overheating and just shut down
  410.   if(max_light_level < MAX_LEVEL && get_light_level()>MIN_OVERHEAT_LEVEL) {
  411. #if (DEBUG!=DEBUG_OFF && DEBUG!=DEBUG_PRINT)
  412.     Serial.print("Max light level: ");
  413.     Serial.println(max_light_level);
  414. #endif
  415.     change_done = change_done < change_duration ? change_done : change_duration;
  416.   }
  417. }
  418.  
  419.  
  420. #ifdef STROBE
  421.  
  422. ///////////////STROBE CONTROL//////////////////
  423.  
  424. void hexbright::set_strobe_delay(unsigned long delay) {
  425.   strobe_delay = delay;
  426.   next_strobe = micros()+strobe_delay;
  427. }
  428.  
  429. void hexbright::set_strobe_duration(int duration) {
  430.   strobe_duration = duration;
  431. }
  432.  
  433. void hexbright::set_strobe_fpm(unsigned int fpm) {
  434.   set_strobe_delay(60000000/fpm);
  435. }
  436.  
  437. unsigned int hexbright::get_strobe_fpm() {
  438.   return 60000000 / (strobe_delay/8*8);
  439. }
  440.  
  441. unsigned int hexbright::get_strobe_error() {
  442.   // 90000000 because we have an error of 3*8 microseconds; 1.5 above, 1.5 below
  443.   return 90000000 / ((strobe_delay/8)*8) - 90000000 / ((strobe_delay/8+1)*8);
  444. }
  445.  
  446. #endif
  447.  
  448. ///////////////////////////////////////////////
  449. ///////////////////LED CONTROL/////////////////
  450. ///////////////////////////////////////////////
  451.  
  452. #ifdef LED
  453.  
  454. // >0 = countdown, 0 = change state, -1 = state changed
  455. int led_wait_time[2] = {-1, -1};
  456. int led_on_time[2] = {-1, -1};
  457. unsigned char led_brightness[2] = {0, 0};
  458.  
  459. void hexbright::set_led(unsigned char led, int on_time, int wait_time, unsigned char brightness) {
  460. #if (DEBUG==DEBUG_LED)
  461.   Serial.println("activate led");
  462. #endif
  463.   led_on_time[led] = on_time/update_delay;
  464.   led_wait_time[led] = wait_time/update_delay;
  465.   led_brightness[led] = brightness;
  466. }
  467.  
  468.  
  469. unsigned char hexbright::get_led_state(unsigned char led) {
  470.   //returns true if the LED is on
  471.   if(led_on_time[led]>=0) {
  472.     return LED_ON;
  473.   } else if(led_wait_time[led]>0) {
  474.     return LED_WAIT;
  475.   } else {
  476.     return LED_OFF;
  477.   }
  478. }
  479.  
  480. inline void hexbright::_led_on(unsigned char led) {
  481.   if(led == RLED) { // DPIN_RLED_SW
  482.     pinModeFast(DPIN_RLED_SW, OUTPUT);
  483.     analogWrite(DPIN_RLED_SW, led_brightness[RLED]);
  484.   } else { // DPIN_GLED
  485.     analogWrite(DPIN_GLED, led_brightness[GLED]);
  486.   }
  487. }
  488.  
  489. inline void hexbright::_led_off(unsigned char led) {
  490.   if(led == RLED) { // DPIN_RLED_SW
  491.     digitalWriteFast(DPIN_RLED_SW, LOW);
  492.     pinModeFast(DPIN_RLED_SW, INPUT);
  493.   } else { // DPIN_GLED
  494.     digitalWriteFast(DPIN_GLED, LOW);
  495.   }
  496. }
  497.  
  498. inline void hexbright::adjust_leds() {
  499.   // turn off led if it's expired
  500. #if (DEBUG==DEBUG_LED)
  501.   if(led_on_time[GLED]>=0) {
  502.     Serial.print("green on countdown: ");
  503.     Serial.println(led_on_time[GLED]*update_delay);
  504.   } else if (led_on_time[GLED]<0 && led_wait_time[GLED]>=0) {
  505.     Serial.print("green wait countdown: ");
  506.     Serial.println((led_wait_time[GLED])*update_delay);
  507.   }
  508.   if(led_on_time[RLED]>=0) {
  509.     Serial.print("red on countdown: ");
  510.     Serial.println(led_on_time[RLED]*update_delay);
  511.   } else if (led_on_time[RLED]<0 && led_wait_time[RLED]>=0) {
  512.     Serial.print("red wait countdown: ");
  513.     Serial.println((led_wait_time[RLED])*update_delay);
  514.   }
  515. #endif
  516.   int i=0;
  517.   for(i=0; i<2; i++) {
  518.     if(led_on_time[i]>0) {
  519.       _led_on(i);
  520.       led_on_time[i]--;
  521.     } else if(led_on_time[i]==0) {
  522.       _led_off(i);
  523.       led_on_time[i]--;
  524.     } else if (led_wait_time[i]>=0) {
  525.       led_wait_time[i]--;
  526.     }
  527.   }
  528. }
  529.  
  530. #endif
  531.  
  532.  
  533. ///////////////////////////////////////////////
  534. /////////////////////BUTTON////////////////////
  535. ///////////////////////////////////////////////
  536.  
  537. #define BUTTON_FILTER 7 // 00000111 (this is applied at read time)
  538. #define BUTTON_JUST_OFF(state) (state==4) // 100 = just off
  539. #define BUTTON_JUST_ON(state) (state==1) // 001 = just on
  540. #define BUTTON_STILL_OFF(state) (state==0) // 000 = still off
  541. // 010, 011, 101, 110, 111 = still on
  542. #define BUTTON_STILL_ON(state) !(BUTTON_JUST_OFF(state) | BUTTON_JUST_ON(state) | BUTTON_STILL_OFF(state))
  543. #define BUTTON_ON(state) (state & 3) // either of right most bits is on: 00000011 (not 100 or 000)
  544. #define BUTTON_OFF(state) !BUTTON_ON(state)
  545.  
  546. // button state could hold a history of the last 8 switch values, 1 == on, 0 == off.
  547. // for debouncing, we only need the most recent 3, so BUTTON_FILTER=7, 00000111
  548. // This is applied during the read process.
  549. unsigned char button_state = 0;
  550.  
  551. unsigned long time_last_pressed = 0; // the time that button was last pressed
  552. unsigned long time_last_released = 0; // the time that the button was last released
  553.  
  554. BOOL hexbright::button_pressed() {
  555.   return BUTTON_ON(button_state);
  556. }
  557.  
  558. BOOL hexbright::button_just_pressed() {
  559.   return BUTTON_JUST_ON(button_state);
  560. }
  561.  
  562. BOOL hexbright::button_just_released() {
  563.   return BUTTON_JUST_OFF(button_state);
  564. }
  565.  
  566. int hexbright::button_pressed_time() {
  567.   if(BUTTON_ON(button_state)) {
  568.     return millis()-time_last_pressed;
  569.   } else {
  570.     return time_last_released - time_last_pressed;
  571.   }
  572. }
  573.  
  574. int hexbright::button_released_time() {
  575.   if(BUTTON_ON(button_state)) {
  576.     return time_last_pressed-time_last_released;
  577.   } else {
  578.     return millis()-time_last_released;
  579.   }
  580. }
  581.  
  582. void hexbright::read_button() {
  583.   /*button_state = button_state << 1; // make space for the new value
  584. button_state = button_state | digitalReadFast(DPIN_RLED_SW); // add the new value
  585. button_state = button_state & BUTTON_FILTER; // remove excess values */
  586.   // Doing the three commands above on one line saves 2 bytes. We'll take it!
  587.   button_state = ((button_state<<1) | digitalReadFast(DPIN_RLED_SW)) & BUTTON_FILTER;
  588.  
  589.   if(BUTTON_JUST_ON(button_state)) {
  590.     time_last_pressed=millis();
  591. #if (DEBUG==DEBUG_BUTTON)
  592.     Serial.println("Button just pressed");
  593.     Serial.print("Time spent released (ms): ");
  594.     Serial.println(time_last_pressed-time_last_released);
  595. #endif
  596.   } else if(BUTTON_JUST_OFF(button_state)) {
  597.     time_last_released=millis();
  598. #if (DEBUG==DEBUG_BUTTON)
  599.     Serial.println("Button just released");
  600.     Serial.print("Time spent pressed (ms): ");
  601.     Serial.println(time_last_released-time_last_pressed);
  602. #endif
  603.   }
  604. }
  605.  
  606.  
  607. ///////////////////////////////////////////////
  608. ////////////////ACCELEROMETER//////////////////
  609. ///////////////////////////////////////////////
  610.  
  611. #ifdef ACCELEROMETER
  612.  
  613. // return degrees of movement?
  614. // Possible things to work with:
  615. //MOVE_TYPE, value returned from a successful detect_movement
  616. #define ACCEL_NONE 0 // nothing
  617. #define ACCEL_TWIST 1 // return degrees - light axis remains constant
  618. #define ACCEL_TURN 2 // return degrees - light axis changes
  619. #define ACCEL_DROP 3 // return change of velocity - period of no acceleration before impact?
  620. #define ACCEL_TAP 4 // return change of velocity - acceleration before impact
  621.  
  622. // I considered operating with bytes to save space, but the savings were
  623. // offset by still needing to do /some/ things as ints. I've not completely
  624. // tested which is more compact, but preliminary work suggests difficulty
  625. // in the implementation with little to no benefit.
  626.  
  627.  
  628. unsigned char tilt = 0;
  629. int vectors[] = {0,0,0, 0,0,0, 0,0,0, 0,0,0};
  630. int current_vector = 0;
  631. unsigned char num_vectors = 4;
  632. int down_vector[] = {0,0,0};
  633.  
  634. /// SETUP/MANAGEMENT
  635.  
  636. void hexbright::enable_accelerometer() {
  637.   // Configure accelerometer
  638.   unsigned char config[] = {
  639.     ACC_REG_INTS, // First register (see next line)
  640.     0xE4, // Interrupts: shakes, taps
  641.     0x00, // Mode: not enabled yet
  642.     0x00, // Sample rate: 120 Hz (see datasheet page 19)
  643.     0x0F, // Tap threshold
  644.     0x05 // Tap debounce samples
  645.   };
  646.   Wire.beginTransmission(ACC_ADDRESS);
  647.   Wire.write(config, sizeof(config));
  648.   Wire.endTransmission();
  649.  
  650.   // Enable accelerometer
  651.   unsigned char enable[] = {ACC_REG_MODE, 0x01}; // Mode: active!
  652.   Wire.beginTransmission(ACC_ADDRESS);
  653.   Wire.write(enable, sizeof(enable));
  654.   Wire.endTransmission();
  655.  
  656.   // pinModeFast(DPIN_ACC_INT, INPUT);
  657.   // digitalWriteFast(DPIN_ACC_INT, HIGH);
  658. }
  659.  
  660. void hexbright::read_accelerometer() {
  661.   /*unsigned long time = 0;
  662. if((millis()-init_time)>*/
  663.   // advance which vector is considered the first
  664.   next_vector();
  665.   while(1) {
  666.     Wire.beginTransmission(ACC_ADDRESS);
  667.     Wire.write(ACC_REG_XOUT); // starting with ACC_REG_XOUT,
  668.     Wire.endTransmission(false);
  669.     Wire.requestFrom(ACC_ADDRESS, 4); // read 4 registers (X,Y,Z), TILT
  670.     for(int i=0; i<4; i++) {
  671.       if (!Wire.available())
  672.         continue;
  673.       char tmp = Wire.read();
  674.       if(tmp & 0x40) // Bx1xxxxxx, re-read per data sheet page 14
  675.         continue;
  676.       if(i==3){ //read tilt register
  677.         tilt = tmp;
  678.       } else { // read vector
  679.         if(tmp & 0x20) // Bxx1xxxxx, it's negative
  680.           tmp |= 0xC0; // extend to B111xxxxx
  681. vectors[current_vector+i] = stdev_filter3(vector(1)[i], tmp*(100/21.3));
  682.       }
  683.     }
  684.     break;
  685.   }
  686. }
  687.  
  688. unsigned char hexbright::read_accelerometer(unsigned char acc_reg) {
  689.   if (!digitalReadFast(DPIN_ACC_INT)) {
  690.     Wire.beginTransmission(ACC_ADDRESS);
  691.     Wire.write(acc_reg);
  692.     Wire.endTransmission(false); // End, but do not stop!
  693.     Wire.requestFrom(ACC_ADDRESS, 1);
  694.     return Wire.read();
  695.   }
  696.   return 0;
  697. }
  698.  
  699.  
  700. inline void hexbright::find_down() {
  701.   // currently, we're just averaging the last four data points.
  702.   // Down is the strongest constant acceleration we experience
  703.   // (assuming we're not dropped). Heuristics to only find down
  704.   // under specific circumstances have been tried, but they only
  705.   // tell us when down is less certain, not where it is...
  706.   copy_vector(down_vector, vector(0)); // copy first vector to down
  707.   double magnitudes = magnitude(vector(0));
  708.   for(int i=1; i<num_vectors; i++) { // go through, summing everything up
  709.     int* vtmp = vector(i);
  710.     sum_vectors(down_vector, down_vector, vtmp);
  711.     magnitudes+=magnitude(vtmp);
  712.   }
  713.   normalize(down_vector, down_vector, magnitudes!=0 ? magnitudes : 1);
  714. }
  715.  
  716. /// tilt register interface
  717.  
  718. unsigned char hexbright::get_tilt_register() {
  719.   return tilt;
  720. }
  721.  
  722. BOOL hexbright::tapped() {
  723.   return tilt & 0x20;
  724. }
  725.  
  726. BOOL hexbright::shaked() {
  727.   return tilt & 0x80;
  728. }
  729.  
  730. unsigned char hexbright::get_tilt_orientation() {
  731.   unsigned char tmp = tilt & (0x1F | 0x03); // filter out the tap/shake registers, and the back/front register
  732.   tmp = tmp>>2; // shift us all the way to the right
  733.   // PoLa: 5, 6 = horizontal, 1 = up, 2 = down, 0 = unknown
  734.   if(tmp & 0x04)
  735.     return TILT_HORIZONTAL;
  736.   return tmp;
  737. }
  738.  
  739. char hexbright::get_tilt_rotation() {
  740.   static unsigned char last = 0;
  741.   unsigned char current = tilt & 0x1F; // filter out tap/shake registers
  742.   // 21,22,26,25 (in order, rotating when horizontal)
  743.   switch(current ) {
  744.   case 21: // 10101
  745.     current = 1;
  746.     break;
  747.   case 22: // 10110
  748.     current = 2;
  749.     break;
  750.   case 26: // 11010
  751.     current = 3;
  752.     break;
  753.   case 25: // 11001
  754.     current = 4;
  755.     break;
  756.   default: // we can't determine orientation with this reading
  757.     last = 0;
  758.     return 0;
  759.   }
  760.  
  761.   if(last==0) { // previous reading wasn't usable
  762.     last = current;
  763.     return 0;
  764.   }
  765.  
  766.   // we have two valid values, calculate!
  767.   char retval = last-current;
  768.   last = current;
  769.   if(retval*retval>1) { // switching from a 4 to a 1 or vice-versa
  770.     retval = -(retval%2);
  771.   }
  772. #if (DEBUG==DEBUG_ACCEL)
  773.   if(retval!=0) {
  774.     Serial.print("tilt rotation: ");
  775.     Serial.println((int)retval);
  776.   }
  777. #endif
  778.   return retval;
  779. }
  780.  
  781. /// some sample functions using vector operations
  782.  
  783. double hexbright::angle_change() {
  784.   int* vec1 = vector(0);
  785.   int* vec2 = vector(1);
  786.   return angle_difference(dot_product(vec1, vec2),
  787.                           magnitude(vec1),
  788.                           magnitude(vec2));
  789. }
  790.  
  791. void hexbright::absolute_vector(int* out_vector, int* in_vector) {
  792.   sub_vectors(out_vector, in_vector, down_vector);
  793. }
  794.  
  795. double hexbright::difference_from_down() {
  796.   int light_axis[3] = {0, -100, 0};
  797.   return (angle_difference(dot_product(light_axis, down_vector), 100, 100));
  798. }
  799.  
  800. BOOL hexbright::stationary(int tolerance) {
  801.   // low acceleration vectors
  802.   return abs(magnitude(vector(0))-100)<tolerance && abs(magnitude(vector(1))-100)<tolerance;
  803. }
  804.  
  805. BOOL hexbright::moved(int tolerance) {
  806.   return abs(magnitude(vector(0))-100)>tolerance;
  807. }
  808.  
  809. char hexbright::get_spin() {
  810.   // quick formula:
  811.   //(atan2(vector(1)[0], vector(1)[2]) - atan2(vector(0)[0], vector(0)[2]))*32;
  812.   // we cache the last position, because it takes up less space.
  813.   static char last_spin = 0;
  814.   // 2*PI*32 = 200
  815.   return atan2(down()[0], down()[2])*32 - atan2(vector(0)[0], vector(0)[2])*32;
  816.   char spin = atan2(vector(0)[0], vector(0)[2])*32;
  817.   if(abs(last_spin)-10<0) {
  818.  
  819.   }
  820.  
  821.   return spin;
  822. }
  823.  
  824. /// VECTOR TOOLS
  825. int* hexbright::vector(unsigned char back) {
  826.   return vectors+((current_vector/3+back)%num_vectors)*3;
  827. }
  828.  
  829. int* hexbright::down() {
  830.   return down_vector;
  831. }
  832.  
  833. void hexbright::next_vector() {
  834.   current_vector=((current_vector/3+(num_vectors-1))%num_vectors)*3;
  835. }
  836.  
  837. double hexbright::angle_difference(int dot_product, double magnitude1, double magnitude2) {
  838.   // multiply to account for 100 being equal to one for our vectors
  839.   double tmp = dot_product*100/(magnitude1*magnitude2);
  840.   return acos(tmp)/3.14159;
  841. }
  842.  
  843. int hexbright::dot_product(int* vector1, int* vector2) {
  844.   // the max value sum could hit is technically > 2^16.
  845.   // However, the only instance where this is possible is if both vectors have
  846.   // experienced maximum acceleration on all axes - with 4 of the 6 being the max in the negative
  847.   // direction (-32 min, 31 max), (31*100/21.3) = 145, (-32*100/21.3) = -150
  848.   // 3*(150^2) = 67500 (not safe)
  849.   // (150*150)+(150*150)+(145*145) = 66025 (not safe)
  850.   // (150*150)+(150*145)+(145*145) = 65275 (safe)
  851.   // 3*(145^2) = 63075 (safe)
  852.   // Given the difficulty of triggering this condition, I'm using an int.
  853.   // This could also be avoided by /100 inside the loop, costing 12 bytes.
  854.   // We should revisit this decision when drop detect code has been written.
  855.   // An alternate solution would be to convert using READING*100/21.65, giving
  856.   // a max of 147. 3*(147^2) = 64827 (safe). A max of 148 would be safe so
  857.   // long as no more than 5 values are -32.
  858.   unsigned int sum = 0; // max value is about 3*(150^2), a tad over the maximum unsigned int
  859.   for(int i=0;i<3;i++) {
  860.     //sum+=vector1[i]*vector2[i]/100; // avoids overflow, but costs space
  861.     sum+=vector1[i]*vector2[i];
  862.   }
  863.   return sum/100; // small danger of overflow
  864. }
  865.  
  866. void hexbright::cross_product(int * axes_rotation,
  867.                               int* in_vector1,
  868.                               int* in_vector2,
  869.                               double angle_difference) {
  870.   for(int i=0; i<3; i++) {
  871.     axes_rotation[i] = (in_vector1[(i+1)%3]*in_vector2[(i+2)%3] \
  872.                         - in_vector1[(i+2)%3]*in_vector2[(i+1)%3]);
  873.     //axes_rotation[i] /= magnitude(in_vector1)*magnitude(in_vector2);
  874.     //axes_rotation[i] /= asin(angle_difference*3.14159);
  875.   }
  876. }
  877.  
  878. double hexbright::magnitude(int* vector) {
  879.   // This has a small possibility of failure, see the comments at the start
  880.   // of dot_product. A long would cost another 28 bytes, a double 42.
  881.   // A cheaper solution (costing 20 bytes) is to divide the squaring by 100,
  882.   // then multiply the sqrt by 10 (commented out).
  883.   unsigned int result = 0;
  884.   for(int i=0; i<3;i++) {
  885.     result += vector[i]*vector[i]; // vector[i]*vector[i]/100;
  886.   }
  887.   return sqrt(result); // sqrt(result)*10;
  888. }
  889.  
  890. void hexbright::normalize(int* out_vector, int* in_vector, double magnitude) {
  891.   for(int i=0; i<3; i++) {
  892.     // normalize to 100, not 1
  893.     out_vector[i] = in_vector[i]/magnitude*100;
  894.   }
  895. }
  896.  
  897. void hexbright::sum_vectors(int* out_vector, int* in_vector1, int* in_vector2) {
  898.   for(int i=0; i<3;i++) {
  899.     out_vector[i] = in_vector1[i]+in_vector2[i];
  900.   }
  901. }
  902.  
  903. void hexbright::sub_vectors(int* out_vector, int* in_vector1, int* in_vector2) {
  904.   for(int i=0; i<3;i++) {
  905.     out_vector[i] = in_vector1[i]-in_vector2[i];
  906.   }
  907. }
  908.  
  909. void hexbright::copy_vector(int* out_vector, int* in_vector) {
  910.   for(int i=0; i<3;i++) {
  911.     out_vector[i] = in_vector[i];
  912.   }
  913. }
  914.  
  915. void hexbright::print_vector(int* vector, const char* label) {
  916. #if (DEBUG!=DEBUG_OFF)
  917.   for(int i=0; i<3; i++) {
  918.     Serial.print(vector[i]);
  919.     Serial.print("/");
  920.   }
  921.   Serial.println(label);
  922. #endif
  923. }
  924.  
  925. #endif
  926.  
  927.  
  928. ///////////////////////////////////////////////
  929. //////////////////UTILITIES////////////////////
  930. ///////////////////////////////////////////////
  931.  
  932. long _number = 0;
  933. unsigned char _color = GLED;
  934. int print_wait_time = 0;
  935.  
  936. #if (defined(LED) && defined(PRINT_NUMBER))
  937. BOOL hexbright::printing_number() {
  938.   return _number || print_wait_time;
  939. }
  940.  
  941. void hexbright::reset_print_number() {
  942.   _number = 1;
  943.   print_wait_time = 0;
  944. }
  945.  
  946. void hexbright::update_number() {
  947.   if(_number>0) { // we have something to do...
  948. #if (DEBUG==DEBUG_NUMBER)
  949.     static int last_printed = 0;
  950.     if(last_printed != _number) {
  951.       last_printed = _number;
  952.       Serial.print("number remaining (read from right to left): ");
  953.       Serial.println(_number);
  954.     }
  955. #endif
  956.     if(!print_wait_time) {
  957.       if(_number==1) { // minimum delay between printing numbers
  958.         print_wait_time = 2500/update_delay;
  959.         _number = 0;
  960.         return;
  961.       } else {
  962.         print_wait_time = 300/update_delay;
  963.       }
  964.       if(_number/10*10==_number) {
  965. #if (DEBUG==DEBUG_NUMBER)
  966.         Serial.println("zero");
  967. #endif
  968.         // print_wait_time = 500/update_delay;
  969.         set_led(_color, 400);
  970.       } else {
  971.         set_led(_color, 120);
  972.         _number--;
  973.       }
  974.       if(_number && !(_number%10)) { // next digit?
  975.         print_wait_time = 600/update_delay;
  976.         _color = flip_color(_color);
  977.         _number = _number/10;
  978.       }
  979.     }
  980.   }
  981.  
  982.   if(print_wait_time) {
  983.     print_wait_time--;
  984.   }
  985. }
  986.  
  987. unsigned char hexbright::flip_color(unsigned char color) {
  988.   return (color+1)%2;
  989. }
  990.  
  991.  
  992. void hexbright::print_number(long number) {
  993.   // reverse number (so it prints from left to right)
  994.   BOOL negative = false;
  995.   if(number<0) {
  996.     number = 0-number;
  997.     negative = true;
  998.   }
  999.   _color = GLED;
  1000.   _number=1; // to guarantee printing when dealing with trailing zeros (100 can't be stored as 001, use 1001)
  1001.   do {
  1002.     _number = _number * 10 + (number%10);
  1003.     number = number/10;
  1004.     _color = flip_color(_color);
  1005.   } while(number>0);
  1006.   if(negative) {
  1007.     set_led(flip_color(_color), 500);
  1008.     print_wait_time = 600/update_delay;
  1009.   }
  1010. }
  1011.  
  1012.  
  1013.  
  1014. //// Numeric entry
  1015. static unsigned int read_value = 0;
  1016.  
  1017. unsigned int hexbright::get_input_digit() {
  1018.   return read_value;
  1019. }
  1020.  
  1021. void hexbright::input_digit(unsigned int min_digit, unsigned int max_digit) {
  1022.   unsigned int tmp2 = 999 - atan2(vector(0)[0], vector(0)[2])*159 - 500; // scale from 0-999, counterclockwise = higher
  1023.   tmp2 = (tmp2*(max_digit-min_digit))/1000+min_digit;
  1024.   if(tmp2 == read_value) {
  1025.     if(!printing_number()) {
  1026.       print_number(tmp2);
  1027.     }
  1028.   } else {
  1029.     reset_print_number();
  1030.     set_led(GLED,100);
  1031.   }
  1032.   read_value = tmp2;
  1033. }
  1034. #endif
  1035.  
  1036.  
  1037. ///////////////////////////////////////////////
  1038. ////////////////TEMPERATURE////////////////////
  1039. ///////////////////////////////////////////////
  1040.  
  1041. int thermal_sensor_value = 0;
  1042. void hexbright::read_thermal_sensor() {
  1043.   // do not call this directly. Call get_temperature()
  1044.   // read temperature setting
  1045.   // device data sheet: http://ww1.microchip.com/downloads/en/devicedoc/21942a.pdf
  1046.  
  1047.   thermal_sensor_value = read_adc(APIN_TEMP);
  1048. }
  1049.  
  1050. int hexbright::get_thermal_sensor() {
  1051.   return thermal_sensor_value;
  1052. }
  1053.  
  1054. int hexbright::get_celsius() {
  1055.   // 0C ice water bath for 20 minutes: 153.
  1056.   // 40C water bath for 20 minutes (measured by medical thermometer): 275
  1057.   // intersection with 0: 50 = (40C-0C)/(275-153)*153
  1058.  
  1059.   // 40.05 is to force the division to floating point. The extra parenthesis are to
  1060.   // tell the compiler to pre-evaluate the expression.
  1061.   return thermal_sensor_value * ((40.05-0)/(275-153)) - 50;
  1062. }
  1063.  
  1064.  
  1065. int hexbright::get_fahrenheit() {
  1066.   //return get_celsius()*18/10+32;
  1067.   // algebraic form of (get_celsius' formula)*18/10+32
  1068.   // I was lazy and pasted (x*((40.05-0)/(275-153)) - 50)*18/10+32 into wolfram alpha
  1069.   return .590902*thermal_sensor_value-58;
  1070. }
  1071.  
  1072. // If the ambient temperature is above your max temp, your light is going to be pretty dim...
  1073.  
  1074. void hexbright::detect_overheating() {
  1075.   unsigned int temperature = get_thermal_sensor();
  1076.  
  1077.   max_light_level = max_light_level+(OVERHEAT_TEMPERATURE-temperature);
  1078.   // min, max levels...
  1079.   max_light_level = max_light_level > MAX_LEVEL ? MAX_LEVEL : max_light_level;
  1080.   max_light_level = max_light_level < MIN_OVERHEAT_LEVEL ? MIN_OVERHEAT_LEVEL : max_light_level;
  1081. #if (DEBUG==DEBUG_TEMP)
  1082.   static float printed_temperature = 0;
  1083.   static float average_temperature = -1;
  1084.   if(average_temperature < 0) {
  1085.     average_temperature = temperature;
  1086.     Serial.println("Have you calibrated your thermometer?");
  1087.     Serial.println("Instructions are in get_celsius.");
  1088.   }
  1089.   average_temperature = (average_temperature*4+temperature)/5;
  1090.   if (abs(printed_temperature-average_temperature)>1) {
  1091.     printed_temperature = average_temperature;
  1092.     Serial.print(millis());
  1093.     Serial.print(" ms, average reading: ");
  1094.     Serial.print(printed_temperature);
  1095.     Serial.print(" (celsius: ");
  1096.     Serial.print(get_celsius());
  1097.     Serial.print(") (fahrenheit: ");
  1098.     Serial.print(get_fahrenheit());
  1099.     Serial.println(")");
  1100.   }
  1101. #endif
  1102. }
  1103.  
  1104.  
  1105. ///////////////////////////////////////////////
  1106. ////////////////AVR VOLTAGE////////////////////
  1107. ///////////////////////////////////////////////
  1108.  
  1109. int band_gap_reading = 0;
  1110. int lowest_band_gap_reading = 1000;
  1111.  
  1112. void hexbright::read_avr_voltage() {
  1113.   band_gap_reading = read_adc(APIN_BAND_GAP);
  1114.   lowest_band_gap_reading = band_gap_reading < lowest_band_gap_reading ? band_gap_reading : lowest_band_gap_reading;
  1115. }
  1116.  
  1117. int hexbright::get_avr_voltage() {
  1118.   // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  1119.   // this is the only place we actually convert to voltage, reducing the space used for most programs.
  1120.   return ((long)1023*1100) / band_gap_reading;
  1121. }
  1122.  
  1123. BOOL hexbright::low_voltage_state() {
  1124.   static BOOL low = false;
  1125.   // lower band gap value corresponds to a higher voltage, trigger
  1126.   // low voltage state if band gap value goes too high.
  1127.   // I need have a value of 5 for this to work (with a 150 ms delay in read_adc).
  1128.   // I'm increasing that for some room for error (8).
  1129.   // NEW CHANGE:
  1130.   // 40 is enough to account for the drop from usb to regular power.
  1131.   // This approach is imperfect: if you hit a low battery mark, then run it down for 15 minutes and turn it off, you will be unable to turn it back on again until it is recharged
  1132.   if (band_gap_reading > lowest_band_gap_reading+40) {
  1133.     low = true;
  1134.   }
  1135.   return low;
  1136. }
  1137.  
  1138. void hexbright::detect_low_battery() {
  1139.   if (low_voltage_state() == true && max_light_level>500) {
  1140.     max_light_level = 500;
  1141.   }
  1142. }
  1143.  
  1144.  
  1145. ///////////////////////////////////////////////
  1146. //////////////////CHARGING/////////////////////
  1147. ///////////////////////////////////////////////
  1148.  
  1149. // we store the last two charge readings in charge_state, and due to the specific
  1150. // values chosen for the #defines, we greatly decrease the possibility of returning
  1151. // BATTERY when we are still connected over USB. This costs 14 bytes.
  1152.  
  1153. // BATTERY is the median value, which is only returned if /both/ halves are BATTERY.
  1154. // If one of the two values is CHARGING, we return CHARGING
  1155. // If one of the two values is CHARGED (and neither CHARGING), we return CHARGED
  1156. // Otherwise, BATTERY is both values and is returned
  1157. unsigned char charge_state = BATTERY;
  1158.  
  1159. void hexbright::read_charge_state() {
  1160.   unsigned int charge_value = read_adc(APIN_CHARGE);
  1161. #if (DEBUG==DEBUG_CHARGE)
  1162.   Serial.print("Current charge reading: ");
  1163.   Serial.println(charge_value);
  1164. #endif
  1165.   // <128 charging, >768 charged, battery
  1166.   charge_state <<= 4;
  1167.   if(charge_value<128)
  1168.     charge_state += CHARGING;
  1169.   else if (charge_value>768)
  1170.     charge_state += CHARGED;
  1171.   else
  1172.     charge_state += BATTERY;
  1173. }
  1174.  
  1175. unsigned char hexbright::get_charge_state() {
  1176.   // see more details on how this works at the top of this section
  1177.   return charge_state & (charge_state>>4);
  1178. }
  1179.  
  1180. void hexbright::print_charge(unsigned char led) {
  1181.   unsigned char charge_state = get_charge_state();
  1182.   if(charge_state == CHARGING && get_led_state(led) == LED_OFF) {
  1183.     set_led(led, 350, 350);
  1184.   } else if (charge_state == CHARGED) {
  1185.     set_led(led,50);
  1186.   }
  1187. }
  1188.  
  1189.  
  1190. ///////////////////////////////////////////////
  1191. //////////////////SHUTDOWN/////////////////////
  1192. ///////////////////////////////////////////////
  1193.  
  1194. void hexbright::shutdown() {
  1195. #if (DEBUG!=DEBUG_OFF)
  1196.   Serial.println("don't use shutdown, use set_light(,OFF_LEVEL,)");
  1197. #endif
  1198.   set_light(MAX_LOW_LEVEL, OFF_LEVEL, NOW);
  1199. }
  1200.  
  1201.  
  1202. ///////////////////////////////////////////////
  1203. //KLUDGE BECAUSE ARDUINO DOESN'T SUPPORT CLASS VARIABLES/INSTANTIATION
  1204. ///////////////////////////////////////////////
  1205.  
  1206. void hexbright::fake_read_accelerometer(int* new_vector) {
  1207.   next_vector();
  1208.   for(int i=0; i<3; i++) {
  1209.     vector(0)[i] = stdev_filter3(vector(1)[i], new_vector[i]);
  1210.     //vector(0)[i] = new_vector[i];
  1211.   }
  1212. }
Advertisement
Add Comment
Please, Sign In to add comment