Skip to content

Commit

Permalink
hexbright.h: split out set_light_level, allow for #define selection o…
Browse files Browse the repository at this point in the history
…f alternatives
  • Loading branch information
dhiltonp committed Feb 4, 2014
1 parent 3d711f6 commit e139051
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 40 deletions.
7 changes: 5 additions & 2 deletions libraries/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ Planned structure in moving to a framework:
3 key directories:

hb_modes - a collection of light modes (like light_spin, light_down, strobe_serial, selector_tap)<br>
hb_utilities - things like print_number, click_counter, advanced accelerometer interfaces<br>
hexbright - core library, plus .h files for overridable options/behavior (low_battery, overheat)<br>
hb_utilities - things like print_number, click_counter, advanced
accelerometer interfaces. In general, code that expands on the core
library without any dependencies.<br>
hexbright - core library, plus .h files for overridable
options/behavior (low_battery, overheat, set_light_level)<br>

hexbright functions by itself, but hb_utilities provide convenience functions and in some cases alter the behavior of the core library.

Expand Down
45 changes: 8 additions & 37 deletions libraries/hexbright/hexbright.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class hexbright {
// 1000 = MAX_LEVEL, max high power mode
// max change time is about 4.5 minutes ((2^15-1)*8.333 milliseconds).
// I have had weird issues when passing in 3*60*1000, 180000 works fine though.
// Specific algorithms can be customized via #defines (see set_light_level.h)
static void set_light(int start_level, int end_level, long time);
// get light level (before overheat protection adjustment)
static int get_light_level();
Expand Down Expand Up @@ -365,7 +366,6 @@ class hexbright {

private:
static void adjust_light();
static void set_light_level(unsigned long level);
static void apply_max_light_level();
static void detect_overheating();
static void detect_low_battery();
Expand Down Expand Up @@ -421,11 +421,18 @@ class hexbright {
#include "../digitalWriteFast/digitalWriteFast.h"
#endif


/// set #define-based options

// select the appropriate set_light_level based on #defines...
#include "set_light_level.h"

// default to no debug mode if no override has been set
#ifndef DEBUG
#define DEBUG DEBUG_OFF
#endif


///////////////////////////////////////////////
/////////////HARDWARE INIT, UPDATE/////////////
///////////////////////////////////////////////
Expand Down Expand Up @@ -652,43 +659,7 @@ int hexbright::light_change_remaining() {
return tmp*update_delay;
}

void hexbright::set_light_level(unsigned long level) {
// LOW 255 approximately equals HIGH 48/49. There is a color change.
// Values < 4 do not provide any light.
// I don't know about relative power draw.

// look at linearity_test.ino for more detail on these algorithms.

#if (DEBUG==DEBUG_LIGHT)
Serial.print("light level: ");
Serial.println(level);
#endif
digitalWriteFast(DPIN_PWR, HIGH);
if(level == 0) {
// lowest possible power, but cpu still running (DPIN_PWR still high)
digitalWriteFast(DPIN_DRV_MODE, LOW);
analogWrite(DPIN_DRV_EN, 0);
} else if(level == OFF_LEVEL) {
// power off (DPIN_PWR LOW)
digitalWriteFast(DPIN_PWR, LOW);
digitalWriteFast(DPIN_DRV_MODE, LOW);
analogWrite(DPIN_DRV_EN, 0);
} else {
byte value;
if(level<=500) {
digitalWriteFast(DPIN_DRV_MODE, LOW);
value = (byte)(.000000633*(level*level*level)+.000632*(level*level)+.0285*level+3.98);
} else {
level -= 500;
digitalWriteFast(DPIN_DRV_MODE, HIGH);
value = (byte)(.00000052*(level*level*level)+.000365*(level*level)+.108*level+44.8);
}
analogWrite(DPIN_DRV_EN, value);
}
}

void hexbright::adjust_light() {
// sets actual light level, altering value to be perceptually linear, based on steven's area brightness (cube root)
if(change_done<=change_duration) {
int light_level = hexbright::get_max_light_level();
set_light_level(light_level);
Expand Down
57 changes: 57 additions & 0 deletions libraries/hexbright/set_light_level.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "hexbright.h"

void set_light_level_linear(unsigned long level) {
// sets actual light level, altering value to be perceptually linear, based on steven's area brightness (cube root)

// LOW 255 approximately equals HIGH 48/49. There is a color change.
// Values < 4 do not provide any light.
// I don't know about relative power draw.

// look at linearity_test.ino for more detail on these algorithms.

digitalWriteFast(DPIN_PWR, HIGH);
if(level == 0) {
// lowest possible power, but cpu still running (DPIN_PWR still high)
digitalWriteFast(DPIN_DRV_MODE, LOW);
analogWrite(DPIN_DRV_EN, 0);
} else if(level == OFF_LEVEL) {
// power off (DPIN_PWR LOW)
digitalWriteFast(DPIN_PWR, LOW);
digitalWriteFast(DPIN_DRV_MODE, LOW);
analogWrite(DPIN_DRV_EN, 0);
} else {
byte value;
if(level<=500) {
digitalWriteFast(DPIN_DRV_MODE, LOW);
value = (byte)(.000000633*(level*level*level)+.000632*(level*level)+.0285*level+3.98);
} else {
level -= 500;
digitalWriteFast(DPIN_DRV_MODE, HIGH);
value = (byte)(.00000052*(level*level*level)+.000365*(level*level)+.108*level+44.8);
}
analogWrite(DPIN_DRV_EN, value);
}
}


void set_light_level_simple(unsigned long level) {
// Values < 4 do not provide any light.
digitalWriteFast(DPIN_PWR, HIGH);
if(level == OFF_LEVEL) {
// power off (DPIN_PWR LOW)
digitalWriteFast(DPIN_PWR, LOW);
digitalWriteFast(DPIN_DRV_MODE, LOW);
analogWrite(DPIN_DRV_EN, 0);
} else {
byte value;
if(level<=500) {
digitalWriteFast(DPIN_DRV_MODE, LOW);
value = level/1.96078431373; // costs about 40 bytes more than a bit-shift
} else {
level -= 500;
value = level/1.96078431373;
digitalWriteFast(DPIN_DRV_MODE, HIGH);
}
analogWrite(DPIN_DRV_EN, value);
}
}
43 changes: 43 additions & 0 deletions libraries/hexbright/set_light_level.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef SET_LIGHT_LEVEL_H
#define SET_LIGHT_LEVEL_H

// All set_light_level versions accept values from -1 to 1000 (-1==OFF_LEVEL);
// the specific version chosen is called internal to the hexbright library.
// Calling directly should work, but you may have some weird bugs.

// A perceptually linear light output function.
// Sets actual light level, altering value to
// be perceptually linear, based on steven's
// area brightness (cube root)
extern void set_light_level_linear(unsigned long level);

// WIP
// A perceptually linear light output function.
// Sets actual light level, altering value to
// be perceptually linear, based on steven's
// area brightness (cube root)
// Also tries to avoid glitches as we transition
// between low/high output by carefully timing
// pwm transitions
extern void set_light_level_smooth(unsigned long level);

// A simple light output function
// 0-500: 0-256 low
// 501-1000: 0-256 high
extern void set_light_level_simple(unsigned long level);



////// actually do selection...
// set_light_level_simple requested?
#ifdef SET_LIGHT_LEVEL_SIMPLE
#define set_light_level set_light_level_simple
#endif

// default to set_light_level_linear
#ifndef set_light_level
#define set_light_level set_light_level_linear
#endif


#endif // SET_LIGHT_LINEAR_H
9 changes: 8 additions & 1 deletion tests/light_test/light_test.ino
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#include <hexbright.h> // include DEBUG definitions

// alter the default behavior of the hexbright library
#define SET_LIGHT_LEVEL_SIMPLE
#define DEBUG DEBUG_LIGHT

// These next two lines must come after all other library #includes
#define BUILD_HACK
#include <hexbright.h>
Expand All @@ -24,4 +30,5 @@ void loop() {
mode = OFF_MODE;
}
}
}
}

0 comments on commit e139051

Please sign in to comment.