From 003b6b8cc7925251b26bdcd3f1329de8aa4d8fda Mon Sep 17 00:00:00 2001 From: jae Date: Sun, 16 Dec 2012 19:48:40 -0600 Subject: [PATCH 1/8] Added quick power off in all states and added SOS mode --- hexbright_factory.ino | 88 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/hexbright_factory.ino b/hexbright_factory.ino index 8a6a8db..7cea3b7 100755 --- a/hexbright_factory.ino +++ b/hexbright_factory.ino @@ -3,6 +3,12 @@ Factory firmware for HexBright FLEX v2.4 Dec 6, 2012 + CHANGELOG : + + Dec 16, 2012 + * Added quick power off in all states. Press and hold pwr button to turn off flashlight. + * Added SOS to blinky mode. To get there: press and hold pwr button to get blinky, then short press button again for SOS + */ #include @@ -10,6 +16,7 @@ // Settings #define OVERTEMP 340 + // Pin assignments #define DPIN_RLED_SW 2 #define DPIN_GLED 5 @@ -18,6 +25,7 @@ #define DPIN_DRV_EN 10 #define APIN_TEMP 0 #define APIN_CHARGE 3 + // Modes #define MODE_OFF 0 #define MODE_LOW 1 @@ -25,13 +33,18 @@ #define MODE_HIGH 3 #define MODE_BLINKING 4 #define MODE_BLINKING_PREVIEW 5 +#define MODE_SOS 6 + +#define MODE_SOS_S 0 +#define MODE_SOS_O 1 +#define MODE_SOS_S_ 2 // State byte mode = 0; +byte sos_mode = 0; unsigned long btnTime = 0; boolean btnDown = false; - void setup() { // We just powered on! That means either we got plugged @@ -54,6 +67,7 @@ void setup() btnTime = millis(); btnDown = digitalRead(DPIN_RLED_SW); mode = MODE_OFF; + sos_mode = MODE_SOS_S; Serial.println("Powered up!"); } @@ -61,7 +75,11 @@ void setup() void loop() { static unsigned long lastTempTime; + static unsigned long ditdah; + static int ledState = LOW; + unsigned long time = millis(); + static unsigned long previousTime = 0; // Check the state of the charge controller int chargeState = analogRead(APIN_CHARGE); @@ -109,6 +127,52 @@ void loop() case MODE_BLINKING_PREVIEW: digitalWrite(DPIN_DRV_EN, (time%300)<75); break; + case MODE_SOS: + // 200 ms is the frame for each dit "on", the larger this number the slower the SOS + if (time - previousTime > 200) { + previousTime = time; + switch (sos_mode) + { + case MODE_SOS_S: + if (ditdah <= 6) { + ledState = (ledState == LOW) ? ledState = HIGH : ledState = LOW; + ditdah++; + } + else { + ditdah = 1; + sos_mode = MODE_SOS_O; + } + break; + case MODE_SOS_O: + if (ditdah <= 12) { + if (ledState == LOW) + ledState = HIGH; + else if (ditdah % 4 == 0) + ledState = LOW; + ditdah++; + } + else { + ditdah = 1; + sos_mode = MODE_SOS_S_; + } + break; + case MODE_SOS_S_: + if (ditdah <= 6) { + ledState = (ledState == LOW) ? ledState = HIGH : ledState = LOW; + ditdah++; + } + else if (ditdah < 10) + ditdah++; + else { + ditdah = 1; + sos_mode = MODE_SOS_S; + } + break; + } + + digitalWrite(DPIN_DRV_EN, ledState); + } + break; } // Periodically pull down the button's pin, since @@ -130,10 +194,14 @@ void loop() case MODE_LOW: if (btnDown && !newBtnDown && (time-btnTime)>50) newMode = MODE_MED; + if (btnDown && !newBtnDown && (time-btnTime)>500) + newMode = MODE_OFF; break; case MODE_MED: if (btnDown && !newBtnDown && (time-btnTime)>50) newMode = MODE_HIGH; + if (btnDown && !newBtnDown && (time-btnTime)>500) + newMode = MODE_OFF; break; case MODE_HIGH: if (btnDown && !newBtnDown && (time-btnTime)>50) @@ -145,6 +213,16 @@ void loop() newMode = MODE_BLINKING; break; case MODE_BLINKING: + if (btnDown && !newBtnDown && (time-btnTime)>50) { + newMode = MODE_SOS; + sos_mode = MODE_SOS_S; + // reset ditdah to 1, 1 based due to use of modulo + ditdah = 1; + } + if (btnDown && !newBtnDown && (time-btnTime)>500) + newMode = MODE_OFF; + break; + case MODE_SOS: if (btnDown && !newBtnDown && (time-btnTime)>50) newMode = MODE_OFF; break; @@ -190,6 +268,12 @@ void loop() digitalWrite(DPIN_PWR, HIGH); digitalWrite(DPIN_DRV_MODE, HIGH); break; + case MODE_SOS: + Serial.println("Mode = SOS"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + break; } mode = newMode; @@ -203,4 +287,4 @@ void loop() delay(50); } } - + From 4dec928690b77f445e1c8d88a635c7a20739f5da Mon Sep 17 00:00:00 2001 From: jae Date: Sun, 16 Dec 2012 20:31:14 -0600 Subject: [PATCH 2/8] Cherry-picked bhimoff dazzle and accelerometer inactivity --- README.md | 5 ++ hexbright_factory.ino | 139 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 124 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 15abb13..1be1fa7 100755 --- a/README.md +++ b/README.md @@ -7,6 +7,11 @@ This is the software that ships with the Hexbright Flex. Button presses cycle through off, low, medium, and high modes. Hold down the button while off for blinky mode. +Modified: +* Added quick power off in all states. Press and hold pwr button for 0.5 sec to turn off flashlight. +* Cherry-picked Brandon Himoff changes: Changed blinky mode to dazzle and added accelerometer inactivity power off. +* Added SOS to dazzle mode. To get there: press and hold pwr button to get dazzle, then short press button again for SOS + hexbright4 --------------------- Fancier than the factory program, but designed for everyday usability. Button diff --git a/hexbright_factory.ino b/hexbright_factory.ino index 7cea3b7..c7ef478 100755 --- a/hexbright_factory.ino +++ b/hexbright_factory.ino @@ -6,8 +6,9 @@ CHANGELOG : Dec 16, 2012 - * Added quick power off in all states. Press and hold pwr button to turn off flashlight. - * Added SOS to blinky mode. To get there: press and hold pwr button to get blinky, then short press button again for SOS + * Added quick power off in all states. Press and hold pwr button for 0.5 sec to turn off flashlight. + * Cherry-picked Brandon Himoff changes: Changed blinky mode to dazzle and added accelerometer inactivity power off. + * Added SOS to dazzle mode. To get there: press and hold pwr button to get dazzle, then short press button again for SOS */ @@ -17,22 +18,37 @@ // Settings #define OVERTEMP 340 +// Constants +#define ACC_ADDRESS 0x4C +#define ACC_REG_XOUT 0 +#define ACC_REG_YOUT 1 +#define ACC_REG_ZOUT 2 +#define ACC_REG_TILT 3 +#define ACC_REG_INTS 6 +#define ACC_REG_MODE 7 + // Pin assignments #define DPIN_RLED_SW 2 #define DPIN_GLED 5 +#define DPIN_PGOOD 7 #define DPIN_PWR 8 #define DPIN_DRV_MODE 9 #define DPIN_DRV_EN 10 +#define DPIN_ACC_INT 3 #define APIN_TEMP 0 #define APIN_CHARGE 3 +// Interrupts +#define INT_SW 0 +#define INT_ACC 1 + // Modes #define MODE_OFF 0 #define MODE_LOW 1 #define MODE_MED 2 #define MODE_HIGH 3 -#define MODE_BLINKING 4 -#define MODE_BLINKING_PREVIEW 5 +#define MODE_DAZZLE 4 +#define MODE_DAZZLE_PREVIEW 5 #define MODE_SOS 6 #define MODE_SOS_S 0 @@ -57,13 +73,35 @@ void setup() pinMode(DPIN_GLED, OUTPUT); pinMode(DPIN_DRV_MODE, OUTPUT); pinMode(DPIN_DRV_EN, OUTPUT); + pinMode(DPIN_ACC_INT, INPUT); + pinMode(DPIN_PGOOD, INPUT); digitalWrite(DPIN_DRV_MODE, LOW); digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_ACC_INT, HIGH); // Initialize serial busses Serial.begin(9600); Wire.begin(); + // Configure accelerometer + byte config[] = { + ACC_REG_INTS, // First register (see next line) + 0xE4, // Interrupts: shakes, taps + 0x00, // Mode: not enabled yet + 0x00, // Sample rate: 120 Hz + 0x0F, // Tap threshold + 0x10 // Tap debounce samples + }; + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(config, sizeof(config)); + Wire.endTransmission(); + + // Enable accelerometer + byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(enable, sizeof(enable)); + Wire.endTransmission(); + btnTime = millis(); btnDown = digitalRead(DPIN_RLED_SW); mode = MODE_OFF; @@ -74,12 +112,11 @@ void setup() void loop() { - static unsigned long lastTempTime; + static unsigned long lastDazzleTime, lastTempTime, lastModeTime, lastAccTime, lastModeSOSTime; static unsigned long ditdah; static int ledState = LOW; unsigned long time = millis(); - static unsigned long previousTime = 0; // Check the state of the charge controller int chargeState = analogRead(APIN_CHARGE); @@ -120,17 +157,44 @@ void loop() } } + // Check if the accelerometer wants to interrupt + byte tapped = 0, shaked = 0; + if (!digitalRead(DPIN_ACC_INT)) + { + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(ACC_REG_TILT); + Wire.endTransmission(false); // End, but do not stop! + Wire.requestFrom(ACC_ADDRESS, 1); // This one stops. + byte tilt = Wire.read(); + + if (time-lastAccTime > 500) + { + lastAccTime = time; + + tapped = !!(tilt & 0x20); + shaked = !!(tilt & 0x80); + + if (tapped) Serial.println("Tap!"); + if (shaked) Serial.println("Shake!"); + } + } + // Do whatever this mode does switch (mode) { - case MODE_BLINKING: - case MODE_BLINKING_PREVIEW: - digitalWrite(DPIN_DRV_EN, (time%300)<75); + case MODE_DAZZLE: + case MODE_DAZZLE_PREVIEW: + //digitalWrite(DPIN_DRV_EN, (time%200)<25); + if (time - lastDazzleTime > 10) + { + digitalWrite(DPIN_DRV_EN, random(4)<1); + lastDazzleTime = time; + } break; case MODE_SOS: // 200 ms is the frame for each dit "on", the larger this number the slower the SOS - if (time - previousTime > 200) { - previousTime = time; + if (time-lastModeSOSTime > 200) { + lastModeSOSTime = time; switch (sos_mode) { case MODE_SOS_S: @@ -189,7 +253,7 @@ void loop() if (btnDown && !newBtnDown && (time-btnTime)>20) newMode = MODE_LOW; if (btnDown && newBtnDown && (time-btnTime)>500) - newMode = MODE_BLINKING_PREVIEW; + newMode = MODE_DAZZLE_PREVIEW; break; case MODE_LOW: if (btnDown && !newBtnDown && (time-btnTime)>50) @@ -207,12 +271,12 @@ void loop() if (btnDown && !newBtnDown && (time-btnTime)>50) newMode = MODE_OFF; break; - case MODE_BLINKING_PREVIEW: + case MODE_DAZZLE_PREVIEW: // This mode exists just to ignore this button release. if (btnDown && !newBtnDown) - newMode = MODE_BLINKING; + newMode = MODE_DAZZLE; break; - case MODE_BLINKING: + case MODE_DAZZLE: if (btnDown && !newBtnDown && (time-btnTime)>50) { newMode = MODE_SOS; sos_mode = MODE_SOS_S; @@ -228,9 +292,14 @@ void loop() break; } + //activity power down + if (time-max(lastAccTime,lastModeTime) > 1800000UL) { //30 minutes + newMode = MODE_OFF; + } + // Do the mode transitions - if (newMode != mode) - { + if (newMode != mode) { + lastModeTime = millis(); switch (newMode) { case MODE_OFF: @@ -261,9 +330,9 @@ void loop() digitalWrite(DPIN_DRV_MODE, HIGH); analogWrite(DPIN_DRV_EN, 255); break; - case MODE_BLINKING: - case MODE_BLINKING_PREVIEW: - Serial.println("Mode = blinking"); + case MODE_DAZZLE: + case MODE_DAZZLE_PREVIEW: + Serial.println("Mode = dazzle"); pinMode(DPIN_PWR, OUTPUT); digitalWrite(DPIN_PWR, HIGH); digitalWrite(DPIN_DRV_MODE, HIGH); @@ -288,3 +357,33 @@ void loop() } } +void readAccel(char *acc) +{ + while (1) + { + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(ACC_REG_XOUT); + Wire.endTransmission(false); // End, but do not stop! + Wire.requestFrom(ACC_ADDRESS, 3); // This one stops. + + for (int i = 0; i < 3; i++) + { + if (!Wire.available()) + continue; + acc[i] = Wire.read(); + if (acc[i] & 0x40) // Indicates failed read; redo! + continue; + if (acc[i] & 0x20) // Sign-extend + acc[i] |= 0xC0; + } + break; + } +} + +float readAccelAngleXZ() +{ + char acc[3]; + readAccel(acc); + return atan2(acc[0], acc[2]); +} + From a70cf73a11c2a693a1d957aa0eff940fae8231b3 Mon Sep 17 00:00:00 2001 From: jae Date: Fri, 21 Dec 2012 20:22:06 -0600 Subject: [PATCH 3/8] Cherry picked more changes from https://github.com/digitalmisery/HexBrightFLEX which improve the handling of SOS and dazzle. --- README.md | 1 + hexbright_factory.ino | 187 +++++++++++++++++------------------------- 2 files changed, 77 insertions(+), 111 deletions(-) diff --git a/README.md b/README.md index 1be1fa7..42c2195 100755 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Modified: * Added quick power off in all states. Press and hold pwr button for 0.5 sec to turn off flashlight. * Cherry-picked Brandon Himoff changes: Changed blinky mode to dazzle and added accelerometer inactivity power off. * Added SOS to dazzle mode. To get there: press and hold pwr button to get dazzle, then short press button again for SOS +* Added better SOS handling, dazzle and exempted SOS mode from inactivity shutdown hexbright4 --------------------- diff --git a/hexbright_factory.ino b/hexbright_factory.ino index c7ef478..bd5501f 100755 --- a/hexbright_factory.ino +++ b/hexbright_factory.ino @@ -4,6 +4,8 @@ v2.4 Dec 6, 2012 CHANGELOG : + Dec 21, 2012 + * Cherry picked more changes from https://github.com/digitalmisery/HexBrightFLEX which improve the handling of SOS and dazzle. Dec 16, 2012 * Added quick power off in all states. Press and hold pwr button for 0.5 sec to turn off flashlight. @@ -18,7 +20,7 @@ // Settings #define OVERTEMP 340 -// Constants +// Accelerometer defines #define ACC_ADDRESS 0x4C #define ACC_REG_XOUT 0 #define ACC_REG_YOUT 1 @@ -28,15 +30,15 @@ #define ACC_REG_MODE 7 // Pin assignments -#define DPIN_RLED_SW 2 -#define DPIN_GLED 5 -#define DPIN_PGOOD 7 -#define DPIN_PWR 8 -#define DPIN_DRV_MODE 9 -#define DPIN_DRV_EN 10 -#define DPIN_ACC_INT 3 -#define APIN_TEMP 0 -#define APIN_CHARGE 3 +#define DPIN_RLED_SW 2 //PD2, INT0, MLF PIN 28 +#define DPIN_ACC_INT 3 //PD3, INT1, MLF PIN 1 +#define DPIN_GLED 5 //PD5, OC0B, MLF PIN 7 +#define DPIN_PGOOD 7 //PD7, MLF PIN 9 +#define DPIN_PWR 8 //PB0, MLF PIN 10 +#define DPIN_DRV_MODE 9 //PB1, OC1A, MLF PIN 11 +#define DPIN_DRV_EN 10 //PB2, OC1B, MLF PIN 12 +#define APIN_TEMP 0 //PC0, ADC0, MLF PIN 19 +#define APIN_CHARGE 3 //PC3, ADC3, MLF PIN 22 // Interrupts #define INT_SW 0 @@ -51,15 +53,12 @@ #define MODE_DAZZLE_PREVIEW 5 #define MODE_SOS 6 -#define MODE_SOS_S 0 -#define MODE_SOS_O 1 -#define MODE_SOS_S_ 2 - // State byte mode = 0; -byte sos_mode = 0; unsigned long btnTime = 0; boolean btnDown = false; +boolean dazzle_on = true; +long dazzle_period = 100; void setup() { @@ -88,31 +87,25 @@ void setup() ACC_REG_INTS, // First register (see next line) 0xE4, // Interrupts: shakes, taps 0x00, // Mode: not enabled yet - 0x00, // Sample rate: 120 Hz + 0x00, // Sample rate: 120 Hz active 0x0F, // Tap threshold 0x10 // Tap debounce samples }; Wire.beginTransmission(ACC_ADDRESS); Wire.write(config, sizeof(config)); Wire.endTransmission(); - - // Enable accelerometer - byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(enable, sizeof(enable)); - Wire.endTransmission(); btnTime = millis(); btnDown = digitalRead(DPIN_RLED_SW); mode = MODE_OFF; - sos_mode = MODE_SOS_S; Serial.println("Powered up!"); + randomSeed(analogRead(1)); } void loop() { - static unsigned long lastDazzleTime, lastTempTime, lastModeTime, lastAccTime, lastModeSOSTime; + static unsigned long lastDazzleTime, lastTempTime, lastModeTime, lastAccTime; static unsigned long ditdah; static int ledState = LOW; @@ -184,58 +177,16 @@ void loop() { case MODE_DAZZLE: case MODE_DAZZLE_PREVIEW: - //digitalWrite(DPIN_DRV_EN, (time%200)<25); - if (time - lastDazzleTime > 10) + if (time - lastDazzleTime > dazzle_period) { - digitalWrite(DPIN_DRV_EN, random(4)<1); + digitalWrite(DPIN_DRV_EN, dazzle_on); + dazzle_on = !dazzle_on; lastDazzleTime = time; + dazzle_period = random(25,100); } break; case MODE_SOS: - // 200 ms is the frame for each dit "on", the larger this number the slower the SOS - if (time-lastModeSOSTime > 200) { - lastModeSOSTime = time; - switch (sos_mode) - { - case MODE_SOS_S: - if (ditdah <= 6) { - ledState = (ledState == LOW) ? ledState = HIGH : ledState = LOW; - ditdah++; - } - else { - ditdah = 1; - sos_mode = MODE_SOS_O; - } - break; - case MODE_SOS_O: - if (ditdah <= 12) { - if (ledState == LOW) - ledState = HIGH; - else if (ditdah % 4 == 0) - ledState = LOW; - ditdah++; - } - else { - ditdah = 1; - sos_mode = MODE_SOS_S_; - } - break; - case MODE_SOS_S_: - if (ditdah <= 6) { - ledState = (ledState == LOW) ? ledState = HIGH : ledState = LOW; - ditdah++; - } - else if (ditdah < 10) - ditdah++; - else { - ditdah = 1; - sos_mode = MODE_SOS_S; - } - break; - } - - digitalWrite(DPIN_DRV_EN, ledState); - } + digitalWrite(DPIN_DRV_EN, morseCodeSOS(time - lastModeTime)); break; } @@ -277,29 +228,35 @@ void loop() newMode = MODE_DAZZLE; break; case MODE_DAZZLE: - if (btnDown && !newBtnDown && (time-btnTime)>50) { + if (btnDown && !newBtnDown && (time-btnTime)>50) newMode = MODE_SOS; - sos_mode = MODE_SOS_S; - // reset ditdah to 1, 1 based due to use of modulo - ditdah = 1; - } - if (btnDown && !newBtnDown && (time-btnTime)>500) - newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) + newMode = MODE_OFF; break; case MODE_SOS: - if (btnDown && !newBtnDown && (time-btnTime)>50) + if (btnDown && !newBtnDown && (time-btnTime)>500) // SOS emergency on unless long press newMode = MODE_OFF; break; } - - //activity power down - if (time-max(lastAccTime,lastModeTime) > 1800000UL) { //30 minutes + + //activity power down EXCLUDES SOS MODE! + if (time-max(lastAccTime,lastModeTime) > 600000UL && newMode != MODE_SOS) { //10 minutes newMode = MODE_OFF; } - + // Do the mode transitions if (newMode != mode) { lastModeTime = millis(); + + // Enable or Disable accelerometer + byte disable[] = {ACC_REG_MODE, 0x00}; // Mode: standby! + byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! + Wire.beginTransmission(ACC_ADDRESS); + if (newMode == MODE_OFF) { + Wire.write(disable, sizeof(disable)); + } else Wire.write(enable, sizeof(enable)); + Wire.endTransmission(); + switch (newMode) { case MODE_OFF: @@ -357,33 +314,41 @@ void loop() } } -void readAccel(char *acc) -{ - while (1) - { - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(ACC_REG_XOUT); - Wire.endTransmission(false); // End, but do not stop! - Wire.requestFrom(ACC_ADDRESS, 3); // This one stops. - - for (int i = 0; i < 3; i++) - { - if (!Wire.available()) - continue; - acc[i] = Wire.read(); - if (acc[i] & 0x40) // Indicates failed read; redo! - continue; - if (acc[i] & 0x20) // Sign-extend - acc[i] |= 0xC0; - } - break; - } -} +bool morseCodeSOS(unsigned long time){ + const unsigned long dit = 180; + // 180 ms is the frame for each dit "on", the larger this number the slower the SOS -float readAccelAngleXZ() -{ - char acc[3]; - readAccel(acc); - return atan2(acc[0], acc[2]); + // Morse Code: + // S = ... O = --- + // SOS word = ...---... + + // word space = 7 dits duration + // S = 5 dits duration + // char space = 3 dits duration + // O = 11 dits duration + // char space = 3 dits duration + // S = 5 dits duration + // total duration = 34 + + byte step = (time / dit) % 34; //dit number modulo the length of the sequence; + // Start with word space + if (step < 7) return false; + step -= 7; + // First S + if (step < 5) return (step % 2) == 0; // every second dit is off + step -= 5; + // Char space + if (step < 3) return false; + step -= 3; + // O + if (step < 11) return (step % 4) != 3; // every fourth dit is off + step -= 11; + // Char space + if (step < 3) return false; + step -= 3; + // Last S + if (step < 5) return (step % 2) == 0; // every second dit is off + // Should never get here + Serial.println("Morse SOS overrun error"); + return false; } - From 2fa95527b88e4dd0947c33d1a2957ddffe49b3da Mon Sep 17 00:00:00 2001 From: jae Date: Fri, 21 Dec 2012 20:32:38 -0600 Subject: [PATCH 4/8] Cherry picked more changes from https://github.com/bhimoff/HexBrightFLEX which improve the handling of SOS and dazzle. --- hexbright_factory.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hexbright_factory.ino b/hexbright_factory.ino index bd5501f..04013c0 100755 --- a/hexbright_factory.ino +++ b/hexbright_factory.ino @@ -5,7 +5,7 @@ CHANGELOG : Dec 21, 2012 - * Cherry picked more changes from https://github.com/digitalmisery/HexBrightFLEX which improve the handling of SOS and dazzle. + * Cherry picked more changes from https://github.com/bhimoff/HexBrightFLEX which improve the handling of SOS and dazzle. Dec 16, 2012 * Added quick power off in all states. Press and hold pwr button for 0.5 sec to turn off flashlight. From 5ab07eaa4c8b2764d194bfb714a478c8daa1629b Mon Sep 17 00:00:00 2001 From: jae Date: Sat, 22 Dec 2012 10:58:05 -0600 Subject: [PATCH 5/8] Rename, directory structure change, fix dazzle Long Press --- README.md | 23 ++- hexbright4.ino | 388 ----------------------------------- hexbright_demo_dazzle.ino | 49 ----- hexbright_demo_fades.ino | 96 --------- hexbright_demo_momentary.ino | 41 ---- hexbright_demo_morse.ino | 137 ------------- hexbright_demo_taps.ino | 174 ---------------- hexbright_factory.ino | 354 -------------------------------- 8 files changed, 17 insertions(+), 1245 deletions(-) mode change 100755 => 100644 README.md delete mode 100755 hexbright4.ino delete mode 100755 hexbright_demo_dazzle.ino delete mode 100755 hexbright_demo_fades.ino delete mode 100755 hexbright_demo_momentary.ino delete mode 100755 hexbright_demo_morse.ino delete mode 100644 hexbright_demo_taps.ino delete mode 100755 hexbright_factory.ino diff --git a/README.md b/README.md old mode 100755 new mode 100644 index 42c2195..0245e5a --- a/README.md +++ b/README.md @@ -1,18 +1,29 @@ HexBright Demo Code ======================= +hexbright_extra +----------------- +This similar to the software that ships with the Hexbright Flex. Button presses cycle +through off, low, medium, and high modes. Long Press while off for extended modes (dazzle, SOS). + +Button Presses: +* Normal Press is less than 0.5 Sec +* Long Press is more than 0.5 Sec + +Extra: +* Added quick power off in all modes. Use Long Press to turn off flashlight. +* Changed factory blinky mode to dazzle mode +* Added SOS. To get there: Long Press for dazzle, then Normal Press for SOS. The only way to turn of SOS is long press +* Inactivity shutdown after 10 min unless in SOS mode. + +NOTE: Some features cherry picked from Brandon Himoff in loose collaboration (https://github.com/bhimoff/HexBrightFLEX) + hexbright_factory ----------------- This is the software that ships with the Hexbright Flex. Button presses cycle through off, low, medium, and high modes. Hold down the button while off for blinky mode. -Modified: -* Added quick power off in all states. Press and hold pwr button for 0.5 sec to turn off flashlight. -* Cherry-picked Brandon Himoff changes: Changed blinky mode to dazzle and added accelerometer inactivity power off. -* Added SOS to dazzle mode. To get there: press and hold pwr button to get dazzle, then short press button again for SOS -* Added better SOS handling, dazzle and exempted SOS mode from inactivity shutdown - hexbright4 --------------------- Fancier than the factory program, but designed for everyday usability. Button diff --git a/hexbright4.ino b/hexbright4.ino deleted file mode 100755 index 1c78f6d..0000000 --- a/hexbright4.ino +++ /dev/null @@ -1,388 +0,0 @@ -/* Test firmware for HexBright - -Notes: - Requires Arduino 1.0.1! - -*/ - -#include -#include - -// Settings -#define OVERTEMP 315 -// Constants -#define ACC_ADDRESS 0x4C -#define ACC_REG_XOUT 0 -#define ACC_REG_YOUT 1 -#define ACC_REG_ZOUT 2 -#define ACC_REG_TILT 3 -#define ACC_REG_INTS 6 -#define ACC_REG_MODE 7 -// Pin assignments -#define DPIN_RLED_SW 2 -#define DPIN_GLED 5 -#define DPIN_PGOOD 7 -#define DPIN_PWR 8 -#define DPIN_DRV_MODE 9 -#define DPIN_DRV_EN 10 -#define DPIN_ACC_INT 3 -#define APIN_TEMP 0 -#define APIN_CHARGE 3 -// Interrupts -#define INT_SW 0 -#define INT_ACC 1 -// Modes -#define MODE_POWERUP 0 -#define MODE_OFF 1 -#define MODE_LOW 2 -#define MODE_HIGH 3 -#define MODE_KNOBBING 4 -#define MODE_KNOBBED 5 -#define MODE_BLINKING 6 -#define MODE_BLINKING_PREVIEW 7 -#define MODE_DAZZLING 8 -#define MODE_DAZZLING_PREVIEW 9 - -// State -byte mode = 0; -unsigned long btnTime = 0; -boolean btnDown = false; - - -void setup() -{ - // We just powered on! That means either we got plugged - // into USB, or (more likely) the user is pressing the - // power button. We need to pull up the enable pin of - // the regulator very soon so we don't lose power. - pinMode(DPIN_PWR, INPUT); - digitalWrite(DPIN_PWR, LOW); -// pinMode(DPIN_PWR, OUTPUT); -// digitalWrite(DPIN_PWR, LOW); - - // Initialize GPIO - pinMode(DPIN_RLED_SW, INPUT); - pinMode(DPIN_GLED, OUTPUT); - pinMode(DPIN_DRV_MODE, OUTPUT); - pinMode(DPIN_DRV_EN, OUTPUT); - pinMode(DPIN_ACC_INT, INPUT); - pinMode(DPIN_PGOOD, INPUT); - digitalWrite(DPIN_DRV_MODE, LOW); - digitalWrite(DPIN_DRV_EN, LOW); - digitalWrite(DPIN_ACC_INT, HIGH); - - // Initialize serial busses - Serial.begin(9600); - Wire.begin(); - - // Configure accelerometer - byte config[] = { - ACC_REG_INTS, // First register (see next line) - 0xE4, // Interrupts: shakes, taps - 0x00, // Mode: not enabled yet - 0x00, // Sample rate: 120 Hz - 0x0F, // Tap threshold - 0x10 // Tap debounce samples - }; - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(config, sizeof(config)); - Wire.endTransmission(); - - // Enable accelerometer - byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(enable, sizeof(enable)); - Wire.endTransmission(); - - btnTime = millis(); - btnDown = digitalRead(DPIN_RLED_SW); - mode = MODE_OFF; - - Serial.println("Powered up!"); -} - -void loop() -{ - static unsigned long lastTime, lastTempTime, lastAccTime; - static float lastKnobAngle, knob; - static byte blink; - unsigned long time = millis(); - - // Blink the indicator LED now and then - digitalWrite(DPIN_GLED, (time&0x03FF)?LOW:HIGH); - - // Check the serial port - if (Serial.available()) - { - char c = Serial.read(); - switch (c) - { - case 's': - { - int temperature = analogRead(APIN_TEMP); - Serial.print("Temperature = "); - Serial.println(temperature); - - char accel[3]; - readAccel(accel); - Serial.print("Acceleration = "); - Serial.print(accel[0], DEC); - Serial.print(", "); - Serial.print(accel[1], DEC); - Serial.print(", "); - Serial.println(accel[2], DEC); - - byte pgood = digitalRead(DPIN_PGOOD); - Serial.print("LED driver power good = "); - Serial.println(pgood?"Yes":"No"); - } - break; - } - } - - // Check the temperature sensor - if (time-lastTempTime > 1000) - { - lastTempTime = time; - int temperature = analogRead(APIN_TEMP); - Serial.print("Temperature = "); - Serial.println(temperature); - if (temperature > OVERTEMP) - { - Serial.println("Overheat shutdown!"); - mode = MODE_OFF; - digitalWrite(DPIN_DRV_MODE, LOW); - digitalWrite(DPIN_DRV_EN, LOW); - digitalWrite(DPIN_PWR, LOW); - } - } - - // Check if the accelerometer wants to interrupt - byte tapped = 0, shaked = 0; - if (!digitalRead(DPIN_ACC_INT)) - { - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(ACC_REG_TILT); - Wire.endTransmission(false); // End, but do not stop! - Wire.requestFrom(ACC_ADDRESS, 1); // This one stops. - byte tilt = Wire.read(); - - if (time-lastAccTime > 500) - { - lastAccTime = time; - - tapped = !!(tilt & 0x20); - shaked = !!(tilt & 0x80); - - if (tapped) Serial.println("Tap!"); - if (shaked) Serial.println("Shake!"); - } - } - - // Do whatever this mode does - switch (mode) - { - case MODE_KNOBBING: - { - if (time-lastTime < 100) break; - lastTime = time; - - float angle = readAccelAngleXZ(); - float change = angle - lastKnobAngle; - lastKnobAngle = angle; - if (change > PI) change -= 2.0*PI; - if (change < -PI) change += 2.0*PI; - knob += -change * 40.0; - if (knob < 0) knob = 0; - if (knob > 255) knob = 255; - - // Make apparent brightness changes linear by squaring the - // value and dividing back down into range. This gives us - // a gamma correction of 2.0, which is close enough. - byte bright = (long)(knob * knob) >> 8; - // Avoid ever appearing off in this mode! - if (bright < 8) bright = 8; - analogWrite(DPIN_DRV_EN, bright); - - Serial.print("Ang = "); - Serial.print(angle); - Serial.print("\tChange = "); - Serial.print(change); - Serial.print("\tKnob = "); - Serial.print(knob); - Serial.print("\tBright = "); - Serial.println(bright); - } - break; - case MODE_BLINKING: - case MODE_BLINKING_PREVIEW: - if (time-lastTime < 250) break; - lastTime = time; - - blink = !blink; - digitalWrite(DPIN_DRV_EN, blink); - break; - case MODE_DAZZLING: - case MODE_DAZZLING_PREVIEW: - if (time-lastTime < 10) break; - lastTime = time; - - digitalWrite(DPIN_DRV_EN, random(4)<1); - break; - } - - // Check for mode changes - byte newMode = mode; - byte newBtnDown = digitalRead(DPIN_RLED_SW); - switch (mode) - { - case MODE_OFF: - if (btnDown && !newBtnDown) // Button released - newMode = MODE_LOW; - if (btnDown && newBtnDown && (time-btnTime)>500) // Held - newMode = MODE_KNOBBING; - break; - case MODE_LOW: - if (btnDown && !newBtnDown) // Button released - newMode = MODE_HIGH; - if (btnDown && newBtnDown && (time-btnTime)>500) // Held - newMode = MODE_KNOBBING; - break; - case MODE_HIGH: - if (btnDown && !newBtnDown) // Button released - newMode = MODE_OFF; - if (btnDown && newBtnDown && (time-btnTime)>500) // Held - newMode = MODE_KNOBBING; - break; - case MODE_KNOBBING: - if (btnDown && !newBtnDown) // Button released - newMode = MODE_KNOBBED; - if (btnDown && newBtnDown && tapped) - newMode = MODE_BLINKING_PREVIEW; - break; - case MODE_KNOBBED: - if (btnDown && !newBtnDown) // Button released - newMode = MODE_OFF; - if (btnDown && newBtnDown && (time-btnTime)>500) // Held - newMode = MODE_KNOBBING; - break; - case MODE_BLINKING: - if (btnDown && !newBtnDown) // Button released - newMode = MODE_OFF; - if (btnDown && newBtnDown && (time-btnTime)>500) // Held - newMode = MODE_BLINKING_PREVIEW; - break; - case MODE_BLINKING_PREVIEW: - if (btnDown && !newBtnDown) // Button released - newMode = MODE_BLINKING; - if (btnDown && newBtnDown && tapped) - newMode = MODE_DAZZLING_PREVIEW; - break; - case MODE_DAZZLING: - if (btnDown && !newBtnDown) // Button released - newMode = MODE_OFF; - if (btnDown && newBtnDown && (time-btnTime)>500) // Held - newMode = MODE_DAZZLING_PREVIEW; - break; - case MODE_DAZZLING_PREVIEW: - if (btnDown && !newBtnDown) // Button released - newMode = MODE_DAZZLING; - if (btnDown && newBtnDown && tapped) - newMode = MODE_BLINKING_PREVIEW; - break; - } - - // Do the mode transitions - if (newMode != mode) - { - switch (newMode) - { - case MODE_OFF: - Serial.println("Mode = off"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, LOW); - digitalWrite(DPIN_DRV_MODE, LOW); - digitalWrite(DPIN_DRV_EN, LOW); - break; - case MODE_LOW: - Serial.println("Mode = low"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - digitalWrite(DPIN_DRV_MODE, LOW); - analogWrite(DPIN_DRV_EN, 255); - break; - case MODE_HIGH: - Serial.println("Mode = high"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - digitalWrite(DPIN_DRV_MODE, HIGH); - analogWrite(DPIN_DRV_EN, 255); - break; - case MODE_KNOBBING: - Serial.println("Mode = knobbing"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - lastKnobAngle = readAccelAngleXZ(); - knob = (mode==MODE_OFF) ? 0 : 255; - break; - case MODE_KNOBBED: - Serial.println("Mode = knobbed"); - break; - case MODE_BLINKING: - case MODE_BLINKING_PREVIEW: - Serial.println("Mode = blinking"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - digitalWrite(DPIN_DRV_MODE, LOW); - break; - case MODE_DAZZLING: - case MODE_DAZZLING_PREVIEW: - Serial.println("Mode = dazzling"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - digitalWrite(DPIN_DRV_MODE, HIGH); - break; - } - - mode = newMode; - } - - // Remember button state so we can detect transitions - if (newBtnDown != btnDown) - { - btnTime = time; - btnDown = newBtnDown; - delay(50); - } -} - -void readAccel(char *acc) -{ - while (1) - { - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(ACC_REG_XOUT); - Wire.endTransmission(false); // End, but do not stop! - Wire.requestFrom(ACC_ADDRESS, 3); // This one stops. - - for (int i = 0; i < 3; i++) - { - if (!Wire.available()) - continue; - acc[i] = Wire.read(); - if (acc[i] & 0x40) // Indicates failed read; redo! - continue; - if (acc[i] & 0x20) // Sign-extend - acc[i] |= 0xC0; - } - break; - } -} - -float readAccelAngleXZ() -{ - char acc[3]; - readAccel(acc); - return atan2(acc[0], acc[2]); -} - diff --git a/hexbright_demo_dazzle.ino b/hexbright_demo_dazzle.ino deleted file mode 100755 index 5b193fd..0000000 --- a/hexbright_demo_dazzle.ino +++ /dev/null @@ -1,49 +0,0 @@ -/* - Hexbright demo firmware: Dazzle - Andrew Magill 9/2012 - - Dazzler flashes while the button is down. -*/ - -// Pin assignments -#define DPIN_RLED_SW 2 -#define DPIN_GLED 5 -#define DPIN_PWR 8 -#define DPIN_DRV_MODE 9 -#define DPIN_DRV_EN 10 - - -void setup() -{ - // If we leave the regulator's enable pin as high-impedance, - // the regulator will power down the board about a half - // second after release of the button. - pinMode(DPIN_PWR, INPUT); - digitalWrite(DPIN_PWR, LOW); - - // Initialize GPIO - pinMode(DPIN_RLED_SW, INPUT); - pinMode(DPIN_GLED, OUTPUT); - pinMode(DPIN_DRV_MODE, OUTPUT); - pinMode(DPIN_DRV_EN, OUTPUT); - digitalWrite(DPIN_DRV_MODE, HIGH); - digitalWrite(DPIN_DRV_EN, LOW); - digitalWrite(DPIN_GLED, HIGH); -} - -void loop() -{ - static unsigned long lastTime; - - if (digitalRead(DPIN_RLED_SW)) - { - if (millis() - lastTime > 10) - { - digitalWrite(DPIN_DRV_EN, random(4)<1); - lastTime = millis(); - } - } - else - digitalWrite(DPIN_DRV_EN, LOW); -} - diff --git a/hexbright_demo_fades.ino b/hexbright_demo_fades.ino deleted file mode 100755 index c05da9e..0000000 --- a/hexbright_demo_fades.ino +++ /dev/null @@ -1,96 +0,0 @@ -/* - Hexbright demo firmware: Fades - Andrew Magill 9/2012 - - 1. Hold button down. Light fades up and down. - 2. Let go of button. Light holds current brightness. - 3. Press button. Light turns off. -*/ - -// Pin assignments -#define DPIN_RLED_SW 2 -#define DPIN_GLED 5 -#define DPIN_PWR 8 -#define DPIN_DRV_MODE 9 -#define DPIN_DRV_EN 10 -// Modes -#define MODE_OFF 0 -#define MODE_FADE 1 -#define MODE_ON 2 - -byte mode; -boolean btnDown; -unsigned long lastTime, btnTime; -int bright, fadeDir; - -void setup() -{ - pinMode(DPIN_PWR, INPUT); - digitalWrite(DPIN_PWR, LOW); - - // Initialize GPIO - pinMode(DPIN_RLED_SW, INPUT); - pinMode(DPIN_GLED, OUTPUT); - pinMode(DPIN_DRV_MODE, OUTPUT); - pinMode(DPIN_DRV_EN, OUTPUT); - digitalWrite(DPIN_DRV_MODE, HIGH); - digitalWrite(DPIN_DRV_EN, LOW); - digitalWrite(DPIN_GLED, HIGH); - - mode = MODE_OFF; - btnDown = digitalRead(DPIN_RLED_SW); - btnTime = millis(); -} - -void loop() -{ - unsigned long time = millis(); - boolean newBtnDown = digitalRead(DPIN_RLED_SW); - - switch (mode) - { - case MODE_OFF: - if (btnDown && newBtnDown && time-btnTime>50) - { - mode = MODE_FADE; - bright = 0; - fadeDir = 1; - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - } - break; - case MODE_FADE: - if (time-lastTime > 5) - { - lastTime = time; - if (fadeDir>0 && bright==255) fadeDir = -1; - if (fadeDir<0 && bright==0 ) fadeDir = 1; - bright += fadeDir; - unsigned int gamma = (bright*bright)>>8; - if (gamma < 6) gamma = 6; - analogWrite(DPIN_DRV_EN, gamma); - } - if (!btnDown && !newBtnDown && time-btnTime>50) - mode = MODE_ON; - break; - case MODE_ON: - if (btnDown && newBtnDown && time-btnTime>200) - mode = MODE_FADE; - if (btnDown && !newBtnDown) - { - mode = MODE_OFF; - digitalWrite(DPIN_DRV_EN, LOW); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, LOW); - } - break; - } - - if (newBtnDown != btnDown) - { - btnTime = time; - btnDown = newBtnDown; - delay(50); - } -} - diff --git a/hexbright_demo_momentary.ino b/hexbright_demo_momentary.ino deleted file mode 100755 index 268bd46..0000000 --- a/hexbright_demo_momentary.ino +++ /dev/null @@ -1,41 +0,0 @@ -/* - Hexbright demo firmware: Momentary - Andrew Magill 9/2012 - - Light turns on when the button is down. That's it. -*/ - -// Pin assignments -#define DPIN_RLED_SW 2 -#define DPIN_GLED 5 -#define DPIN_PWR 8 -#define DPIN_DRV_MODE 9 -#define DPIN_DRV_EN 10 - - -void setup() -{ - // If we leave the regulator's enable pin as high-impedance, - // the regulator will power down the board about a half - // second after release of the button. - pinMode(DPIN_PWR, INPUT); - digitalWrite(DPIN_PWR, LOW); - - // Initialize GPIO - pinMode(DPIN_RLED_SW, INPUT); - pinMode(DPIN_GLED, OUTPUT); - pinMode(DPIN_DRV_MODE, OUTPUT); - pinMode(DPIN_DRV_EN, OUTPUT); - digitalWrite(DPIN_DRV_MODE, HIGH); - digitalWrite(DPIN_DRV_EN, LOW); - digitalWrite(DPIN_GLED, HIGH); -} - -void loop() -{ - if (digitalRead(DPIN_RLED_SW)) - digitalWrite(DPIN_DRV_EN, HIGH); - else - digitalWrite(DPIN_DRV_EN, LOW); -} - diff --git a/hexbright_demo_morse.ino b/hexbright_demo_morse.ino deleted file mode 100755 index 86aca40..0000000 --- a/hexbright_demo_morse.ino +++ /dev/null @@ -1,137 +0,0 @@ -/* - Hexbright demo firmware: Morse - Andrew Magill 9/2012 - - On each button press, flashes out a message in morse code - and then turns off. Message and speed are configurable - just below. -*/ - -char message[] = "SOS HEXBRIGHT SOS"; -int millisPerBeat = 75; - - -// Pin assignments -#define DPIN_RLED_SW 2 -#define DPIN_GLED 5 -#define DPIN_PWR 8 -#define DPIN_DRV_MODE 9 -#define DPIN_DRV_EN 10 - -// High byte = length -// Low byte = morse code, LSB first, 0=dot 1=dash -word morse[] = { - 0x0202, // A .- - 0x0401, // B -... - 0x0405, // C -.-. - 0x0301, // D -.. - 0x0100, // E . - 0x0404, // F ..-. - 0x0303, // G --. - 0x0400, // H .... - 0x0200, // I .. - 0x040E, // J .--- - 0x0305, // K -.- - 0x0402, // L .-.. - 0x0203, // M -- - 0x0201, // N -. - 0x0307, // O --- - 0x0406, // P .--. - 0x040B, // Q --.- - 0x0302, // R .-. - 0x0300, // S ... - 0x0101, // T - - 0x0304, // U ..- - 0x0408, // V ...- - 0x0306, // W .-- - 0x0409, // X -..- - 0x040D, // Y -.-- - 0x0403, // Z --.. - 0x051F, // 0 ----- - 0x051E, // 1 .---- - 0x051C, // 2 ..--- - 0x0518, // 3 ...-- - 0x0510, // 4 ....- - 0x0500, // 5 ..... - 0x0501, // 6 -.... - 0x0503, // 7 --... - 0x0507, // 8 ---.. - 0x050F, // 9 ----. -}; - -void setup() -{ - pinMode(DPIN_PWR, INPUT); - digitalWrite(DPIN_PWR, LOW); - - // Initialize GPIO - pinMode(DPIN_RLED_SW, INPUT); - pinMode(DPIN_GLED, OUTPUT); - pinMode(DPIN_DRV_MODE, OUTPUT); - pinMode(DPIN_DRV_EN, OUTPUT); - digitalWrite(DPIN_DRV_MODE, LOW); - digitalWrite(DPIN_DRV_EN, LOW); -} - -void loop() -{ - // Expect a button press to start - if (!digitalRead(DPIN_RLED_SW)) return; - - // Ensure the regulator stays enabled - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - - for (int i = 0; i < sizeof(message); i++) - { - char ch = message[i]; - if (ch == ' ') - { - // 7 beats between words, but 3 have already passed - // at the end of the last character - delay(millisPerBeat * 4); - } - else - { - // Remap ASCII to the morse table - if (ch >= 'A' && ch <= 'Z') ch -= 'A'; - else if (ch >= 'a' && ch <= 'z') ch -= 'a'; - else if (ch >= '0' && ch <= '9') ch -= '0' - 26; - else continue; - - // Extract the symbols and length - byte curChar = morse[ch] & 0x00FF; - byte nSymbols = morse[ch] >> 8; - - // Play each symbol - for (int j = 0; j < nSymbols; j++) - { - digitalWrite(DPIN_DRV_EN, HIGH); - if (curChar & 1) // Dash - 3 beats - delay(millisPerBeat * 3); - else // Dot - 1 beat - delay(millisPerBeat); - digitalWrite(DPIN_DRV_EN, LOW); - // One beat between symbols - delay(millisPerBeat); - curChar >>= 1; - } - // 3 beats between characters, but one already - // passed after the last symbol. - delay(millisPerBeat * 2); - } - } - - // Flash the green LED to indicate we're done - for (int k = 0; k < 3; k++) - { - digitalWrite(DPIN_GLED, HIGH); - delay(50); - digitalWrite(DPIN_GLED, LOW); - delay(50); - } - // Disable the regulator to power off - // This won't work on USB power. - digitalWrite(DPIN_PWR, LOW); -} - diff --git a/hexbright_demo_taps.ino b/hexbright_demo_taps.ino deleted file mode 100644 index 272e64e..0000000 --- a/hexbright_demo_taps.ino +++ /dev/null @@ -1,174 +0,0 @@ -/* - Hexbright demo firmware: Tap flash! - Andrew Magill 9/2012 - - Hold down the button, and tap out a rhythm against - the light. It will then flash out the same rhythm - until you turn it off by pressing the button again. -*/ - -#include - -// Settings -#define BUFSIZE 64 -// Constants -#define ACC_ADDRESS 0x4C -#define ACC_REG_XOUT 0 -#define ACC_REG_YOUT 1 -#define ACC_REG_ZOUT 2 -#define ACC_REG_TILT 3 -#define ACC_REG_INTS 6 -#define ACC_REG_MODE 7 -// Pin assignments -#define DPIN_RLED_SW 2 -#define DPIN_GLED 5 -#define DPIN_PWR 8 -#define DPIN_DRV_MODE 9 -#define DPIN_DRV_EN 10 -// Modes -#define MODE_OFF 0 -#define MODE_RECORD 1 -#define MODE_PLAY 2 - -// State -byte mode; -unsigned long btnTime, tapTime; -unsigned long recording[BUFSIZE]; -int nTaps, curTap; - -void setup() -{ - // We just powered on! That means either we got plugged - // into USB, or the user is pressing the power button. - pinMode(DPIN_PWR, INPUT); - digitalWrite(DPIN_PWR, LOW); - - // Initialize GPIO - pinMode(DPIN_RLED_SW, INPUT); - pinMode(DPIN_GLED, OUTPUT); - pinMode(DPIN_DRV_MODE, OUTPUT); - pinMode(DPIN_DRV_EN, OUTPUT); - digitalWrite(DPIN_DRV_MODE, LOW); - digitalWrite(DPIN_DRV_EN, LOW); - - // Initialize serial busses - Serial.begin(9600); - Wire.begin(); - - // Configure accelerometer - byte config[] = { - ACC_REG_INTS, // First register (see next line) - 0xE4, // Interrupts: shakes, taps - 0x00, // Mode: not enabled yet - 0x00, // Sample rate: 120 Hz - 0x0F, // Tap threshold - 0x05 // Tap debounce samples - }; - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(config, sizeof(config)); - Wire.endTransmission(); - - // Enable accelerometer - byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(enable, sizeof(enable)); - Wire.endTransmission(); - - - mode = MODE_OFF; - btnTime = 0; - Serial.println("Powered up!"); -} - -void loop() -{ - switch (mode) - { - case MODE_OFF: - if (digitalRead(DPIN_RLED_SW)) - { // Button is down.. - if (btnTime==0) - { // ..and just went down - btnTime = millis(); - } - else if (millis()-btnTime > 200) - { // ..and has been down for a little while - Serial.println("Recording!"); - nTaps = 0; - tapTime = 0; - for (int i=0; i200) - { // Tap detected! - Serial.println("Tap!"); - tapTime = millis(); - recording[nTaps++] = tapTime-btnTime; - analogWrite(DPIN_DRV_EN, 255); - delay(100); - analogWrite(DPIN_DRV_EN, 32); - } - } - else - { // Time to transition to playback mode - Serial.println("Playback!"); - for (int i = 0; i < nTaps; i++) - { - Serial.print(recording[i]); - Serial.print(" "); - } - recording[nTaps] = millis()-btnTime; // End time - Serial.println(recording[nTaps]); - curTap = 0; - btnTime = millis(); - mode = MODE_PLAY; - } - break; - case MODE_PLAY: - if (digitalRead(DPIN_RLED_SW)) - { // Buton pressed again. Turn off. - Serial.println("Off!"); - digitalWrite(DPIN_DRV_EN, LOW); - digitalWrite(DPIN_PWR, LOW); - btnTime = 0; - mode = MODE_OFF; - while (digitalRead(DPIN_RLED_SW)); - delay(200); - } - else - { // No button, keep playing. - if (millis()-btnTime > recording[curTap]) - { // Time to flash out this tap! - if (curTap < nTaps) - { - analogWrite(DPIN_DRV_EN, 255); - delay(100); - analogWrite(DPIN_DRV_EN, 32); - curTap++; - } - else - { - curTap = 0; - btnTime = millis(); - } - } - } - break; - } -} - diff --git a/hexbright_factory.ino b/hexbright_factory.ino deleted file mode 100755 index 04013c0..0000000 --- a/hexbright_factory.ino +++ /dev/null @@ -1,354 +0,0 @@ -/* - - Factory firmware for HexBright FLEX - v2.4 Dec 6, 2012 - - CHANGELOG : - Dec 21, 2012 - * Cherry picked more changes from https://github.com/bhimoff/HexBrightFLEX which improve the handling of SOS and dazzle. - - Dec 16, 2012 - * Added quick power off in all states. Press and hold pwr button for 0.5 sec to turn off flashlight. - * Cherry-picked Brandon Himoff changes: Changed blinky mode to dazzle and added accelerometer inactivity power off. - * Added SOS to dazzle mode. To get there: press and hold pwr button to get dazzle, then short press button again for SOS - -*/ - -#include -#include - -// Settings -#define OVERTEMP 340 - -// Accelerometer defines -#define ACC_ADDRESS 0x4C -#define ACC_REG_XOUT 0 -#define ACC_REG_YOUT 1 -#define ACC_REG_ZOUT 2 -#define ACC_REG_TILT 3 -#define ACC_REG_INTS 6 -#define ACC_REG_MODE 7 - -// Pin assignments -#define DPIN_RLED_SW 2 //PD2, INT0, MLF PIN 28 -#define DPIN_ACC_INT 3 //PD3, INT1, MLF PIN 1 -#define DPIN_GLED 5 //PD5, OC0B, MLF PIN 7 -#define DPIN_PGOOD 7 //PD7, MLF PIN 9 -#define DPIN_PWR 8 //PB0, MLF PIN 10 -#define DPIN_DRV_MODE 9 //PB1, OC1A, MLF PIN 11 -#define DPIN_DRV_EN 10 //PB2, OC1B, MLF PIN 12 -#define APIN_TEMP 0 //PC0, ADC0, MLF PIN 19 -#define APIN_CHARGE 3 //PC3, ADC3, MLF PIN 22 - -// Interrupts -#define INT_SW 0 -#define INT_ACC 1 - -// Modes -#define MODE_OFF 0 -#define MODE_LOW 1 -#define MODE_MED 2 -#define MODE_HIGH 3 -#define MODE_DAZZLE 4 -#define MODE_DAZZLE_PREVIEW 5 -#define MODE_SOS 6 - -// State -byte mode = 0; -unsigned long btnTime = 0; -boolean btnDown = false; -boolean dazzle_on = true; -long dazzle_period = 100; - -void setup() -{ - // We just powered on! That means either we got plugged - // into USB, or the user is pressing the power button. - pinMode(DPIN_PWR, INPUT); - digitalWrite(DPIN_PWR, LOW); - - // Initialize GPIO - pinMode(DPIN_RLED_SW, INPUT); - pinMode(DPIN_GLED, OUTPUT); - pinMode(DPIN_DRV_MODE, OUTPUT); - pinMode(DPIN_DRV_EN, OUTPUT); - pinMode(DPIN_ACC_INT, INPUT); - pinMode(DPIN_PGOOD, INPUT); - digitalWrite(DPIN_DRV_MODE, LOW); - digitalWrite(DPIN_DRV_EN, LOW); - digitalWrite(DPIN_ACC_INT, HIGH); - - // Initialize serial busses - Serial.begin(9600); - Wire.begin(); - - // Configure accelerometer - byte config[] = { - ACC_REG_INTS, // First register (see next line) - 0xE4, // Interrupts: shakes, taps - 0x00, // Mode: not enabled yet - 0x00, // Sample rate: 120 Hz active - 0x0F, // Tap threshold - 0x10 // Tap debounce samples - }; - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(config, sizeof(config)); - Wire.endTransmission(); - - btnTime = millis(); - btnDown = digitalRead(DPIN_RLED_SW); - mode = MODE_OFF; - - Serial.println("Powered up!"); - randomSeed(analogRead(1)); -} - -void loop() -{ - static unsigned long lastDazzleTime, lastTempTime, lastModeTime, lastAccTime; - static unsigned long ditdah; - static int ledState = LOW; - - unsigned long time = millis(); - - // Check the state of the charge controller - int chargeState = analogRead(APIN_CHARGE); - if (chargeState < 128) // Low - charging - { - digitalWrite(DPIN_GLED, (time&0x0100)?LOW:HIGH); - } - else if (chargeState > 768) // High - charged - { - digitalWrite(DPIN_GLED, HIGH); - } - else // Hi-Z - shutdown - { - digitalWrite(DPIN_GLED, LOW); - } - - // Check the temperature sensor - if (time-lastTempTime > 1000) - { - lastTempTime = time; - int temperature = analogRead(APIN_TEMP); - Serial.print("Temp: "); - Serial.println(temperature); - if (temperature > OVERTEMP && mode != MODE_OFF) - { - Serial.println("Overheating!"); - - for (int i = 0; i < 6; i++) - { - digitalWrite(DPIN_DRV_MODE, LOW); - delay(100); - digitalWrite(DPIN_DRV_MODE, HIGH); - delay(100); - } - digitalWrite(DPIN_DRV_MODE, LOW); - - mode = MODE_LOW; - } - } - - // Check if the accelerometer wants to interrupt - byte tapped = 0, shaked = 0; - if (!digitalRead(DPIN_ACC_INT)) - { - Wire.beginTransmission(ACC_ADDRESS); - Wire.write(ACC_REG_TILT); - Wire.endTransmission(false); // End, but do not stop! - Wire.requestFrom(ACC_ADDRESS, 1); // This one stops. - byte tilt = Wire.read(); - - if (time-lastAccTime > 500) - { - lastAccTime = time; - - tapped = !!(tilt & 0x20); - shaked = !!(tilt & 0x80); - - if (tapped) Serial.println("Tap!"); - if (shaked) Serial.println("Shake!"); - } - } - - // Do whatever this mode does - switch (mode) - { - case MODE_DAZZLE: - case MODE_DAZZLE_PREVIEW: - if (time - lastDazzleTime > dazzle_period) - { - digitalWrite(DPIN_DRV_EN, dazzle_on); - dazzle_on = !dazzle_on; - lastDazzleTime = time; - dazzle_period = random(25,100); - } - break; - case MODE_SOS: - digitalWrite(DPIN_DRV_EN, morseCodeSOS(time - lastModeTime)); - break; - } - - // Periodically pull down the button's pin, since - // in certain hardware revisions it can float. - pinMode(DPIN_RLED_SW, OUTPUT); - pinMode(DPIN_RLED_SW, INPUT); - - // Check for mode changes - byte newMode = mode; - byte newBtnDown = digitalRead(DPIN_RLED_SW); - switch (mode) - { - case MODE_OFF: - if (btnDown && !newBtnDown && (time-btnTime)>20) - newMode = MODE_LOW; - if (btnDown && newBtnDown && (time-btnTime)>500) - newMode = MODE_DAZZLE_PREVIEW; - break; - case MODE_LOW: - if (btnDown && !newBtnDown && (time-btnTime)>50) - newMode = MODE_MED; - if (btnDown && !newBtnDown && (time-btnTime)>500) - newMode = MODE_OFF; - break; - case MODE_MED: - if (btnDown && !newBtnDown && (time-btnTime)>50) - newMode = MODE_HIGH; - if (btnDown && !newBtnDown && (time-btnTime)>500) - newMode = MODE_OFF; - break; - case MODE_HIGH: - if (btnDown && !newBtnDown && (time-btnTime)>50) - newMode = MODE_OFF; - break; - case MODE_DAZZLE_PREVIEW: - // This mode exists just to ignore this button release. - if (btnDown && !newBtnDown) - newMode = MODE_DAZZLE; - break; - case MODE_DAZZLE: - if (btnDown && !newBtnDown && (time-btnTime)>50) - newMode = MODE_SOS; - if (btnDown && newBtnDown && (time-btnTime)>500) - newMode = MODE_OFF; - break; - case MODE_SOS: - if (btnDown && !newBtnDown && (time-btnTime)>500) // SOS emergency on unless long press - newMode = MODE_OFF; - break; - } - - //activity power down EXCLUDES SOS MODE! - if (time-max(lastAccTime,lastModeTime) > 600000UL && newMode != MODE_SOS) { //10 minutes - newMode = MODE_OFF; - } - - // Do the mode transitions - if (newMode != mode) { - lastModeTime = millis(); - - // Enable or Disable accelerometer - byte disable[] = {ACC_REG_MODE, 0x00}; // Mode: standby! - byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! - Wire.beginTransmission(ACC_ADDRESS); - if (newMode == MODE_OFF) { - Wire.write(disable, sizeof(disable)); - } else Wire.write(enable, sizeof(enable)); - Wire.endTransmission(); - - switch (newMode) - { - case MODE_OFF: - Serial.println("Mode = off"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, LOW); - digitalWrite(DPIN_DRV_MODE, LOW); - digitalWrite(DPIN_DRV_EN, LOW); - break; - case MODE_LOW: - Serial.println("Mode = low"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - digitalWrite(DPIN_DRV_MODE, LOW); - analogWrite(DPIN_DRV_EN, 64); - break; - case MODE_MED: - Serial.println("Mode = medium"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - digitalWrite(DPIN_DRV_MODE, LOW); - analogWrite(DPIN_DRV_EN, 255); - break; - case MODE_HIGH: - Serial.println("Mode = high"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - digitalWrite(DPIN_DRV_MODE, HIGH); - analogWrite(DPIN_DRV_EN, 255); - break; - case MODE_DAZZLE: - case MODE_DAZZLE_PREVIEW: - Serial.println("Mode = dazzle"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - digitalWrite(DPIN_DRV_MODE, HIGH); - break; - case MODE_SOS: - Serial.println("Mode = SOS"); - pinMode(DPIN_PWR, OUTPUT); - digitalWrite(DPIN_PWR, HIGH); - digitalWrite(DPIN_DRV_MODE, HIGH); - break; - } - - mode = newMode; - } - - // Remember button state so we can detect transitions - if (newBtnDown != btnDown) - { - btnTime = time; - btnDown = newBtnDown; - delay(50); - } -} - -bool morseCodeSOS(unsigned long time){ - const unsigned long dit = 180; - // 180 ms is the frame for each dit "on", the larger this number the slower the SOS - - // Morse Code: - // S = ... O = --- - // SOS word = ...---... - - // word space = 7 dits duration - // S = 5 dits duration - // char space = 3 dits duration - // O = 11 dits duration - // char space = 3 dits duration - // S = 5 dits duration - // total duration = 34 - - byte step = (time / dit) % 34; //dit number modulo the length of the sequence; - // Start with word space - if (step < 7) return false; - step -= 7; - // First S - if (step < 5) return (step % 2) == 0; // every second dit is off - step -= 5; - // Char space - if (step < 3) return false; - step -= 3; - // O - if (step < 11) return (step % 4) != 3; // every fourth dit is off - step -= 11; - // Char space - if (step < 3) return false; - step -= 3; - // Last S - if (step < 5) return (step % 2) == 0; // every second dit is off - // Should never get here - Serial.println("Morse SOS overrun error"); - return false; -} From d350a590cad74e08bad1bf68200b78a7ab4dcc5b Mon Sep 17 00:00:00 2001 From: jae Date: Sat, 22 Dec 2012 11:00:52 -0600 Subject: [PATCH 6/8] Rename, directory structure change, fix dazzle Long Press --- hexbright4/hexbright4.ino | 388 ++++++++++++++++++ .../hexbright_demo_dazzle.ino | 49 +++ hexbright_demo_fades/hexbright_demo_fades.ino | 96 +++++ .../hexbright_demo_momentary.ino | 41 ++ hexbright_demo_morse/hexbright_demo_morse.ino | 137 +++++++ hexbright_demo_taps/hexbright_demo_taps.ino | 174 ++++++++ hexbright_extra/hexbright_extra.ino | 345 ++++++++++++++++ hexbright_factory/hexbright_factory.ino | 206 ++++++++++ 8 files changed, 1436 insertions(+) create mode 100644 hexbright4/hexbright4.ino create mode 100644 hexbright_demo_dazzle/hexbright_demo_dazzle.ino create mode 100644 hexbright_demo_fades/hexbright_demo_fades.ino create mode 100644 hexbright_demo_momentary/hexbright_demo_momentary.ino create mode 100644 hexbright_demo_morse/hexbright_demo_morse.ino create mode 100644 hexbright_demo_taps/hexbright_demo_taps.ino create mode 100644 hexbright_extra/hexbright_extra.ino create mode 100644 hexbright_factory/hexbright_factory.ino diff --git a/hexbright4/hexbright4.ino b/hexbright4/hexbright4.ino new file mode 100644 index 0000000..1c78f6d --- /dev/null +++ b/hexbright4/hexbright4.ino @@ -0,0 +1,388 @@ +/* Test firmware for HexBright + +Notes: + Requires Arduino 1.0.1! + +*/ + +#include +#include + +// Settings +#define OVERTEMP 315 +// Constants +#define ACC_ADDRESS 0x4C +#define ACC_REG_XOUT 0 +#define ACC_REG_YOUT 1 +#define ACC_REG_ZOUT 2 +#define ACC_REG_TILT 3 +#define ACC_REG_INTS 6 +#define ACC_REG_MODE 7 +// Pin assignments +#define DPIN_RLED_SW 2 +#define DPIN_GLED 5 +#define DPIN_PGOOD 7 +#define DPIN_PWR 8 +#define DPIN_DRV_MODE 9 +#define DPIN_DRV_EN 10 +#define DPIN_ACC_INT 3 +#define APIN_TEMP 0 +#define APIN_CHARGE 3 +// Interrupts +#define INT_SW 0 +#define INT_ACC 1 +// Modes +#define MODE_POWERUP 0 +#define MODE_OFF 1 +#define MODE_LOW 2 +#define MODE_HIGH 3 +#define MODE_KNOBBING 4 +#define MODE_KNOBBED 5 +#define MODE_BLINKING 6 +#define MODE_BLINKING_PREVIEW 7 +#define MODE_DAZZLING 8 +#define MODE_DAZZLING_PREVIEW 9 + +// State +byte mode = 0; +unsigned long btnTime = 0; +boolean btnDown = false; + + +void setup() +{ + // We just powered on! That means either we got plugged + // into USB, or (more likely) the user is pressing the + // power button. We need to pull up the enable pin of + // the regulator very soon so we don't lose power. + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); +// pinMode(DPIN_PWR, OUTPUT); +// digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + pinMode(DPIN_ACC_INT, INPUT); + pinMode(DPIN_PGOOD, INPUT); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_ACC_INT, HIGH); + + // Initialize serial busses + Serial.begin(9600); + Wire.begin(); + + // Configure accelerometer + byte config[] = { + ACC_REG_INTS, // First register (see next line) + 0xE4, // Interrupts: shakes, taps + 0x00, // Mode: not enabled yet + 0x00, // Sample rate: 120 Hz + 0x0F, // Tap threshold + 0x10 // Tap debounce samples + }; + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(config, sizeof(config)); + Wire.endTransmission(); + + // Enable accelerometer + byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(enable, sizeof(enable)); + Wire.endTransmission(); + + btnTime = millis(); + btnDown = digitalRead(DPIN_RLED_SW); + mode = MODE_OFF; + + Serial.println("Powered up!"); +} + +void loop() +{ + static unsigned long lastTime, lastTempTime, lastAccTime; + static float lastKnobAngle, knob; + static byte blink; + unsigned long time = millis(); + + // Blink the indicator LED now and then + digitalWrite(DPIN_GLED, (time&0x03FF)?LOW:HIGH); + + // Check the serial port + if (Serial.available()) + { + char c = Serial.read(); + switch (c) + { + case 's': + { + int temperature = analogRead(APIN_TEMP); + Serial.print("Temperature = "); + Serial.println(temperature); + + char accel[3]; + readAccel(accel); + Serial.print("Acceleration = "); + Serial.print(accel[0], DEC); + Serial.print(", "); + Serial.print(accel[1], DEC); + Serial.print(", "); + Serial.println(accel[2], DEC); + + byte pgood = digitalRead(DPIN_PGOOD); + Serial.print("LED driver power good = "); + Serial.println(pgood?"Yes":"No"); + } + break; + } + } + + // Check the temperature sensor + if (time-lastTempTime > 1000) + { + lastTempTime = time; + int temperature = analogRead(APIN_TEMP); + Serial.print("Temperature = "); + Serial.println(temperature); + if (temperature > OVERTEMP) + { + Serial.println("Overheat shutdown!"); + mode = MODE_OFF; + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_PWR, LOW); + } + } + + // Check if the accelerometer wants to interrupt + byte tapped = 0, shaked = 0; + if (!digitalRead(DPIN_ACC_INT)) + { + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(ACC_REG_TILT); + Wire.endTransmission(false); // End, but do not stop! + Wire.requestFrom(ACC_ADDRESS, 1); // This one stops. + byte tilt = Wire.read(); + + if (time-lastAccTime > 500) + { + lastAccTime = time; + + tapped = !!(tilt & 0x20); + shaked = !!(tilt & 0x80); + + if (tapped) Serial.println("Tap!"); + if (shaked) Serial.println("Shake!"); + } + } + + // Do whatever this mode does + switch (mode) + { + case MODE_KNOBBING: + { + if (time-lastTime < 100) break; + lastTime = time; + + float angle = readAccelAngleXZ(); + float change = angle - lastKnobAngle; + lastKnobAngle = angle; + if (change > PI) change -= 2.0*PI; + if (change < -PI) change += 2.0*PI; + knob += -change * 40.0; + if (knob < 0) knob = 0; + if (knob > 255) knob = 255; + + // Make apparent brightness changes linear by squaring the + // value and dividing back down into range. This gives us + // a gamma correction of 2.0, which is close enough. + byte bright = (long)(knob * knob) >> 8; + // Avoid ever appearing off in this mode! + if (bright < 8) bright = 8; + analogWrite(DPIN_DRV_EN, bright); + + Serial.print("Ang = "); + Serial.print(angle); + Serial.print("\tChange = "); + Serial.print(change); + Serial.print("\tKnob = "); + Serial.print(knob); + Serial.print("\tBright = "); + Serial.println(bright); + } + break; + case MODE_BLINKING: + case MODE_BLINKING_PREVIEW: + if (time-lastTime < 250) break; + lastTime = time; + + blink = !blink; + digitalWrite(DPIN_DRV_EN, blink); + break; + case MODE_DAZZLING: + case MODE_DAZZLING_PREVIEW: + if (time-lastTime < 10) break; + lastTime = time; + + digitalWrite(DPIN_DRV_EN, random(4)<1); + break; + } + + // Check for mode changes + byte newMode = mode; + byte newBtnDown = digitalRead(DPIN_RLED_SW); + switch (mode) + { + case MODE_OFF: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_LOW; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; + case MODE_LOW: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_HIGH; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; + case MODE_HIGH: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; + case MODE_KNOBBING: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_KNOBBED; + if (btnDown && newBtnDown && tapped) + newMode = MODE_BLINKING_PREVIEW; + break; + case MODE_KNOBBED: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; + case MODE_BLINKING: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_BLINKING_PREVIEW; + break; + case MODE_BLINKING_PREVIEW: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_BLINKING; + if (btnDown && newBtnDown && tapped) + newMode = MODE_DAZZLING_PREVIEW; + break; + case MODE_DAZZLING: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_DAZZLING_PREVIEW; + break; + case MODE_DAZZLING_PREVIEW: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_DAZZLING; + if (btnDown && newBtnDown && tapped) + newMode = MODE_BLINKING_PREVIEW; + break; + } + + // Do the mode transitions + if (newMode != mode) + { + switch (newMode) + { + case MODE_OFF: + Serial.println("Mode = off"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, LOW); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + break; + case MODE_LOW: + Serial.println("Mode = low"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + analogWrite(DPIN_DRV_EN, 255); + break; + case MODE_HIGH: + Serial.println("Mode = high"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + analogWrite(DPIN_DRV_EN, 255); + break; + case MODE_KNOBBING: + Serial.println("Mode = knobbing"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + lastKnobAngle = readAccelAngleXZ(); + knob = (mode==MODE_OFF) ? 0 : 255; + break; + case MODE_KNOBBED: + Serial.println("Mode = knobbed"); + break; + case MODE_BLINKING: + case MODE_BLINKING_PREVIEW: + Serial.println("Mode = blinking"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + break; + case MODE_DAZZLING: + case MODE_DAZZLING_PREVIEW: + Serial.println("Mode = dazzling"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + break; + } + + mode = newMode; + } + + // Remember button state so we can detect transitions + if (newBtnDown != btnDown) + { + btnTime = time; + btnDown = newBtnDown; + delay(50); + } +} + +void readAccel(char *acc) +{ + while (1) + { + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(ACC_REG_XOUT); + Wire.endTransmission(false); // End, but do not stop! + Wire.requestFrom(ACC_ADDRESS, 3); // This one stops. + + for (int i = 0; i < 3; i++) + { + if (!Wire.available()) + continue; + acc[i] = Wire.read(); + if (acc[i] & 0x40) // Indicates failed read; redo! + continue; + if (acc[i] & 0x20) // Sign-extend + acc[i] |= 0xC0; + } + break; + } +} + +float readAccelAngleXZ() +{ + char acc[3]; + readAccel(acc); + return atan2(acc[0], acc[2]); +} + diff --git a/hexbright_demo_dazzle/hexbright_demo_dazzle.ino b/hexbright_demo_dazzle/hexbright_demo_dazzle.ino new file mode 100644 index 0000000..5b193fd --- /dev/null +++ b/hexbright_demo_dazzle/hexbright_demo_dazzle.ino @@ -0,0 +1,49 @@ +/* + Hexbright demo firmware: Dazzle + Andrew Magill 9/2012 + + Dazzler flashes while the button is down. +*/ + +// Pin assignments +#define DPIN_RLED_SW 2 +#define DPIN_GLED 5 +#define DPIN_PWR 8 +#define DPIN_DRV_MODE 9 +#define DPIN_DRV_EN 10 + + +void setup() +{ + // If we leave the regulator's enable pin as high-impedance, + // the regulator will power down the board about a half + // second after release of the button. + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + digitalWrite(DPIN_DRV_MODE, HIGH); + digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_GLED, HIGH); +} + +void loop() +{ + static unsigned long lastTime; + + if (digitalRead(DPIN_RLED_SW)) + { + if (millis() - lastTime > 10) + { + digitalWrite(DPIN_DRV_EN, random(4)<1); + lastTime = millis(); + } + } + else + digitalWrite(DPIN_DRV_EN, LOW); +} + diff --git a/hexbright_demo_fades/hexbright_demo_fades.ino b/hexbright_demo_fades/hexbright_demo_fades.ino new file mode 100644 index 0000000..c05da9e --- /dev/null +++ b/hexbright_demo_fades/hexbright_demo_fades.ino @@ -0,0 +1,96 @@ +/* + Hexbright demo firmware: Fades + Andrew Magill 9/2012 + + 1. Hold button down. Light fades up and down. + 2. Let go of button. Light holds current brightness. + 3. Press button. Light turns off. +*/ + +// Pin assignments +#define DPIN_RLED_SW 2 +#define DPIN_GLED 5 +#define DPIN_PWR 8 +#define DPIN_DRV_MODE 9 +#define DPIN_DRV_EN 10 +// Modes +#define MODE_OFF 0 +#define MODE_FADE 1 +#define MODE_ON 2 + +byte mode; +boolean btnDown; +unsigned long lastTime, btnTime; +int bright, fadeDir; + +void setup() +{ + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + digitalWrite(DPIN_DRV_MODE, HIGH); + digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_GLED, HIGH); + + mode = MODE_OFF; + btnDown = digitalRead(DPIN_RLED_SW); + btnTime = millis(); +} + +void loop() +{ + unsigned long time = millis(); + boolean newBtnDown = digitalRead(DPIN_RLED_SW); + + switch (mode) + { + case MODE_OFF: + if (btnDown && newBtnDown && time-btnTime>50) + { + mode = MODE_FADE; + bright = 0; + fadeDir = 1; + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + } + break; + case MODE_FADE: + if (time-lastTime > 5) + { + lastTime = time; + if (fadeDir>0 && bright==255) fadeDir = -1; + if (fadeDir<0 && bright==0 ) fadeDir = 1; + bright += fadeDir; + unsigned int gamma = (bright*bright)>>8; + if (gamma < 6) gamma = 6; + analogWrite(DPIN_DRV_EN, gamma); + } + if (!btnDown && !newBtnDown && time-btnTime>50) + mode = MODE_ON; + break; + case MODE_ON: + if (btnDown && newBtnDown && time-btnTime>200) + mode = MODE_FADE; + if (btnDown && !newBtnDown) + { + mode = MODE_OFF; + digitalWrite(DPIN_DRV_EN, LOW); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, LOW); + } + break; + } + + if (newBtnDown != btnDown) + { + btnTime = time; + btnDown = newBtnDown; + delay(50); + } +} + diff --git a/hexbright_demo_momentary/hexbright_demo_momentary.ino b/hexbright_demo_momentary/hexbright_demo_momentary.ino new file mode 100644 index 0000000..268bd46 --- /dev/null +++ b/hexbright_demo_momentary/hexbright_demo_momentary.ino @@ -0,0 +1,41 @@ +/* + Hexbright demo firmware: Momentary + Andrew Magill 9/2012 + + Light turns on when the button is down. That's it. +*/ + +// Pin assignments +#define DPIN_RLED_SW 2 +#define DPIN_GLED 5 +#define DPIN_PWR 8 +#define DPIN_DRV_MODE 9 +#define DPIN_DRV_EN 10 + + +void setup() +{ + // If we leave the regulator's enable pin as high-impedance, + // the regulator will power down the board about a half + // second after release of the button. + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + digitalWrite(DPIN_DRV_MODE, HIGH); + digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_GLED, HIGH); +} + +void loop() +{ + if (digitalRead(DPIN_RLED_SW)) + digitalWrite(DPIN_DRV_EN, HIGH); + else + digitalWrite(DPIN_DRV_EN, LOW); +} + diff --git a/hexbright_demo_morse/hexbright_demo_morse.ino b/hexbright_demo_morse/hexbright_demo_morse.ino new file mode 100644 index 0000000..86aca40 --- /dev/null +++ b/hexbright_demo_morse/hexbright_demo_morse.ino @@ -0,0 +1,137 @@ +/* + Hexbright demo firmware: Morse + Andrew Magill 9/2012 + + On each button press, flashes out a message in morse code + and then turns off. Message and speed are configurable + just below. +*/ + +char message[] = "SOS HEXBRIGHT SOS"; +int millisPerBeat = 75; + + +// Pin assignments +#define DPIN_RLED_SW 2 +#define DPIN_GLED 5 +#define DPIN_PWR 8 +#define DPIN_DRV_MODE 9 +#define DPIN_DRV_EN 10 + +// High byte = length +// Low byte = morse code, LSB first, 0=dot 1=dash +word morse[] = { + 0x0202, // A .- + 0x0401, // B -... + 0x0405, // C -.-. + 0x0301, // D -.. + 0x0100, // E . + 0x0404, // F ..-. + 0x0303, // G --. + 0x0400, // H .... + 0x0200, // I .. + 0x040E, // J .--- + 0x0305, // K -.- + 0x0402, // L .-.. + 0x0203, // M -- + 0x0201, // N -. + 0x0307, // O --- + 0x0406, // P .--. + 0x040B, // Q --.- + 0x0302, // R .-. + 0x0300, // S ... + 0x0101, // T - + 0x0304, // U ..- + 0x0408, // V ...- + 0x0306, // W .-- + 0x0409, // X -..- + 0x040D, // Y -.-- + 0x0403, // Z --.. + 0x051F, // 0 ----- + 0x051E, // 1 .---- + 0x051C, // 2 ..--- + 0x0518, // 3 ...-- + 0x0510, // 4 ....- + 0x0500, // 5 ..... + 0x0501, // 6 -.... + 0x0503, // 7 --... + 0x0507, // 8 ---.. + 0x050F, // 9 ----. +}; + +void setup() +{ + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); +} + +void loop() +{ + // Expect a button press to start + if (!digitalRead(DPIN_RLED_SW)) return; + + // Ensure the regulator stays enabled + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + + for (int i = 0; i < sizeof(message); i++) + { + char ch = message[i]; + if (ch == ' ') + { + // 7 beats between words, but 3 have already passed + // at the end of the last character + delay(millisPerBeat * 4); + } + else + { + // Remap ASCII to the morse table + if (ch >= 'A' && ch <= 'Z') ch -= 'A'; + else if (ch >= 'a' && ch <= 'z') ch -= 'a'; + else if (ch >= '0' && ch <= '9') ch -= '0' - 26; + else continue; + + // Extract the symbols and length + byte curChar = morse[ch] & 0x00FF; + byte nSymbols = morse[ch] >> 8; + + // Play each symbol + for (int j = 0; j < nSymbols; j++) + { + digitalWrite(DPIN_DRV_EN, HIGH); + if (curChar & 1) // Dash - 3 beats + delay(millisPerBeat * 3); + else // Dot - 1 beat + delay(millisPerBeat); + digitalWrite(DPIN_DRV_EN, LOW); + // One beat between symbols + delay(millisPerBeat); + curChar >>= 1; + } + // 3 beats between characters, but one already + // passed after the last symbol. + delay(millisPerBeat * 2); + } + } + + // Flash the green LED to indicate we're done + for (int k = 0; k < 3; k++) + { + digitalWrite(DPIN_GLED, HIGH); + delay(50); + digitalWrite(DPIN_GLED, LOW); + delay(50); + } + // Disable the regulator to power off + // This won't work on USB power. + digitalWrite(DPIN_PWR, LOW); +} + diff --git a/hexbright_demo_taps/hexbright_demo_taps.ino b/hexbright_demo_taps/hexbright_demo_taps.ino new file mode 100644 index 0000000..272e64e --- /dev/null +++ b/hexbright_demo_taps/hexbright_demo_taps.ino @@ -0,0 +1,174 @@ +/* + Hexbright demo firmware: Tap flash! + Andrew Magill 9/2012 + + Hold down the button, and tap out a rhythm against + the light. It will then flash out the same rhythm + until you turn it off by pressing the button again. +*/ + +#include + +// Settings +#define BUFSIZE 64 +// Constants +#define ACC_ADDRESS 0x4C +#define ACC_REG_XOUT 0 +#define ACC_REG_YOUT 1 +#define ACC_REG_ZOUT 2 +#define ACC_REG_TILT 3 +#define ACC_REG_INTS 6 +#define ACC_REG_MODE 7 +// Pin assignments +#define DPIN_RLED_SW 2 +#define DPIN_GLED 5 +#define DPIN_PWR 8 +#define DPIN_DRV_MODE 9 +#define DPIN_DRV_EN 10 +// Modes +#define MODE_OFF 0 +#define MODE_RECORD 1 +#define MODE_PLAY 2 + +// State +byte mode; +unsigned long btnTime, tapTime; +unsigned long recording[BUFSIZE]; +int nTaps, curTap; + +void setup() +{ + // We just powered on! That means either we got plugged + // into USB, or the user is pressing the power button. + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + + // Initialize serial busses + Serial.begin(9600); + Wire.begin(); + + // Configure accelerometer + byte config[] = { + ACC_REG_INTS, // First register (see next line) + 0xE4, // Interrupts: shakes, taps + 0x00, // Mode: not enabled yet + 0x00, // Sample rate: 120 Hz + 0x0F, // Tap threshold + 0x05 // Tap debounce samples + }; + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(config, sizeof(config)); + Wire.endTransmission(); + + // Enable accelerometer + byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(enable, sizeof(enable)); + Wire.endTransmission(); + + + mode = MODE_OFF; + btnTime = 0; + Serial.println("Powered up!"); +} + +void loop() +{ + switch (mode) + { + case MODE_OFF: + if (digitalRead(DPIN_RLED_SW)) + { // Button is down.. + if (btnTime==0) + { // ..and just went down + btnTime = millis(); + } + else if (millis()-btnTime > 200) + { // ..and has been down for a little while + Serial.println("Recording!"); + nTaps = 0; + tapTime = 0; + for (int i=0; i200) + { // Tap detected! + Serial.println("Tap!"); + tapTime = millis(); + recording[nTaps++] = tapTime-btnTime; + analogWrite(DPIN_DRV_EN, 255); + delay(100); + analogWrite(DPIN_DRV_EN, 32); + } + } + else + { // Time to transition to playback mode + Serial.println("Playback!"); + for (int i = 0; i < nTaps; i++) + { + Serial.print(recording[i]); + Serial.print(" "); + } + recording[nTaps] = millis()-btnTime; // End time + Serial.println(recording[nTaps]); + curTap = 0; + btnTime = millis(); + mode = MODE_PLAY; + } + break; + case MODE_PLAY: + if (digitalRead(DPIN_RLED_SW)) + { // Buton pressed again. Turn off. + Serial.println("Off!"); + digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_PWR, LOW); + btnTime = 0; + mode = MODE_OFF; + while (digitalRead(DPIN_RLED_SW)); + delay(200); + } + else + { // No button, keep playing. + if (millis()-btnTime > recording[curTap]) + { // Time to flash out this tap! + if (curTap < nTaps) + { + analogWrite(DPIN_DRV_EN, 255); + delay(100); + analogWrite(DPIN_DRV_EN, 32); + curTap++; + } + else + { + curTap = 0; + btnTime = millis(); + } + } + } + break; + } +} + diff --git a/hexbright_extra/hexbright_extra.ino b/hexbright_extra/hexbright_extra.ino new file mode 100644 index 0000000..7760e88 --- /dev/null +++ b/hexbright_extra/hexbright_extra.ino @@ -0,0 +1,345 @@ +/* + + Hexbright Extra (Dec 22, 2012) + + Based on the factory firmware for HexBright FLEX from v2.4 Dec 6, 2012 + NOTE: Some features cherry picked from Brandon Himoff in loose collaboration (https://github.com/bhimoff/HexBrightFLEX) + + CHANGELOG : + Dec 21, 2012 + * Improved the handling of SOS and dazzle. + + Dec 16, 2012 + * Added quick power off in all states. Press and hold pwr button for 0.5 sec to turn off flashlight. + * Changed blinky mode to dazzle and added accelerometer inactivity power off. + * Added SOS to dazzle mode. To get there: press and hold pwr button to get dazzle, then short press button again for SOS + +*/ + +#include +#include + +// Settings +#define OVERTEMP 340 //~1.1V = 60C = 140F + +// Accelerometer defines +#define ACC_ADDRESS 0x4C +#define ACC_REG_XOUT 0 +#define ACC_REG_YOUT 1 +#define ACC_REG_ZOUT 2 +#define ACC_REG_TILT 3 +#define ACC_REG_INTS 6 +#define ACC_REG_MODE 7 + +// Pin assignments +#define DPIN_RLED_SW 2 //PD2, INT0, MLF PIN 28 +#define DPIN_ACC_INT 3 //PD3, INT1, MLF PIN 1 +#define DPIN_GLED 5 //PD5, OC0B, MLF PIN 7 +#define DPIN_PGOOD 7 //PD7, MLF PIN 9 +#define DPIN_PWR 8 //PB0, MLF PIN 10 +#define DPIN_DRV_MODE 9 //PB1, OC1A, MLF PIN 11 +#define DPIN_DRV_EN 10 //PB2, OC1B, MLF PIN 12 +#define APIN_TEMP 0 //PC0, ADC0, MLF PIN 19 +#define APIN_CHARGE 3 //PC3, ADC3, MLF PIN 22 + +// Interrupts +#define INT_SW 0 +#define INT_ACC 1 + +// Modes +#define MODE_OFF 0 +#define MODE_LOW 1 +#define MODE_MED 2 +#define MODE_HIGH 3 +#define MODE_DAZZLE 4 +#define MODE_DAZZLE_PREVIEW 5 +#define MODE_SOS 6 + +// State +byte mode = 0; +unsigned long btnTime = 0; +boolean btnDown = false; +boolean dazzle_on = true; +long dazzle_period = 100; + +void setup() +{ + // We just powered on! That means either we got plugged + // into USB, or the user is pressing the power button. + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + pinMode(DPIN_ACC_INT, INPUT); + pinMode(DPIN_PGOOD, INPUT); + + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_ACC_INT, HIGH); + + // Initialize serial busses + Serial.begin(9600); + Wire.begin(); + + // Configure accelerometer + byte config[] = { + ACC_REG_INTS, // First register (see next line) + 0xE4, // Interrupts: shakes, taps + 0x00, // Mode: not enabled yet + 0x00, // Sample rate: 120 Hz active + 0x0F, // Tap threshold + 0x10 // Tap debounce samples + }; + + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(config, sizeof(config)); + Wire.endTransmission(); + + btnTime = millis(); + btnDown = digitalRead(DPIN_RLED_SW); + mode = MODE_OFF; + + Serial.println("Powered up!"); + randomSeed(analogRead(1)); +} + +void loop() +{ + static unsigned long lastDazzleTime, lastTempTime, lastModeTime, lastAccTime; + unsigned long time = millis(); + + // Check the state of the charge controller + int chargeState = analogRead(APIN_CHARGE); + if (chargeState < 128) { // Low - charging + digitalWrite(DPIN_GLED, (time&0x0100)?LOW:HIGH); + } + else if (chargeState > 768) { // High - charged + digitalWrite(DPIN_GLED, HIGH); + } + else { // Hi-Z - shutdown + digitalWrite(DPIN_GLED, LOW); + } + + // Check the temperature sensor + if (time-lastTempTime > 1000) { + lastTempTime = time; + int temperature = analogRead(APIN_TEMP); + Serial.print("Temp: "); + Serial.println(temperature); + if (temperature > OVERTEMP && mode != MODE_OFF) { + Serial.println("Overheating!"); + + for (int i = 0; i < 6; i++) { + digitalWrite(DPIN_DRV_MODE, LOW); + delay(100); + digitalWrite(DPIN_DRV_MODE, HIGH); + delay(100); + } + digitalWrite(DPIN_DRV_MODE, LOW); + + mode = MODE_LOW; + } + } + + // Check if the accelerometer wants to interrupt + byte tapped = 0, shaked = 0; + if (!digitalRead(DPIN_ACC_INT)) { + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(ACC_REG_TILT); + Wire.endTransmission(false); // End, but do not stop! + Wire.requestFrom(ACC_ADDRESS, 1); // This one stops. + byte tilt = Wire.read(); + + if (time-lastAccTime > 500) { + lastAccTime = time; + + tapped = !!(tilt & 0x20); + shaked = !!(tilt & 0x80); + + if (tapped) Serial.println("Tap!"); + if (shaked) Serial.println("Shake!"); + } + } + + // Do whatever this mode does + switch (mode) + { + case MODE_DAZZLE: + case MODE_DAZZLE_PREVIEW: + if (time - lastDazzleTime > dazzle_period) { + digitalWrite(DPIN_DRV_EN, dazzle_on); + dazzle_on = !dazzle_on; + lastDazzleTime = time; + dazzle_period = random(25,100); + } + break; + case MODE_SOS: + digitalWrite(DPIN_DRV_EN, morseCodeSOS(time - lastModeTime)); + break; + } + + // Periodically pull down the button's pin, since + // in certain hardware revisions it can float. + pinMode(DPIN_RLED_SW, OUTPUT); + pinMode(DPIN_RLED_SW, INPUT); + + // Check for mode changes + byte newMode = mode; + byte newBtnDown = digitalRead(DPIN_RLED_SW); + switch (mode) + { + case MODE_OFF: + if (btnDown && !newBtnDown && (time-btnTime)>20) + newMode = MODE_LOW; + if (btnDown && newBtnDown && (time-btnTime)>500) + newMode = MODE_DAZZLE_PREVIEW; + break; + case MODE_LOW: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_MED; + if (btnDown && !newBtnDown && (time-btnTime)>500) + newMode = MODE_OFF; + break; + case MODE_MED: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_HIGH; + if (btnDown && !newBtnDown && (time-btnTime)>500) + newMode = MODE_OFF; + break; + case MODE_HIGH: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_OFF; + break; + case MODE_DAZZLE_PREVIEW: + // This mode exists just to ignore this button release. + if (btnDown && !newBtnDown) + newMode = MODE_DAZZLE; + break; + case MODE_DAZZLE: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_SOS; + if (btnDown && !newBtnDown && (time-btnTime)>500) + newMode = MODE_OFF; + break; + case MODE_SOS: + if (btnDown && !newBtnDown && (time-btnTime)>500) // SOS emergency on unless long press + newMode = MODE_OFF; + break; + } + + //activity power down EXCLUDES SOS MODE! + if (time-max(lastAccTime,lastModeTime) > 600000UL && newMode != MODE_SOS) { //10 minutes + newMode = MODE_OFF; + } + + // Do the mode transitions + if (newMode != mode) { + lastModeTime = millis(); + + // Enable or Disable accelerometer + byte disable[] = {ACC_REG_MODE, 0x00}; // Mode: standby! + byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! + Wire.beginTransmission(ACC_ADDRESS); + if (newMode == MODE_OFF) { + Wire.write(disable, sizeof(disable)); + } else Wire.write(enable, sizeof(enable)); + Wire.endTransmission(); + + switch (newMode) + { + case MODE_OFF: + Serial.println("Mode = off"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, LOW); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + break; + case MODE_LOW: + Serial.println("Mode = low"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + analogWrite(DPIN_DRV_EN, 64); + break; + case MODE_MED: + Serial.println("Mode = medium"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + analogWrite(DPIN_DRV_EN, 255); + break; + case MODE_HIGH: + Serial.println("Mode = high"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + analogWrite(DPIN_DRV_EN, 255); + break; + case MODE_DAZZLE: + case MODE_DAZZLE_PREVIEW: + Serial.println("Mode = dazzle"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + break; + case MODE_SOS: + Serial.println("Mode = SOS"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + break; + } + + mode = newMode; + } + + // Remember button state so we can detect transitions + if (newBtnDown != btnDown) { + btnTime = time; + btnDown = newBtnDown; + delay(50); + } +} + +bool morseCodeSOS(unsigned long time) { + const unsigned long dit = 180; + // 180 ms is the frame for each dit "on", the larger this number the slower the SOS + + // Morse Code: + // S = ... O = --- + // SOS word = ...---... + + // word space = 7 dits duration + // S = 5 dits duration + // char space = 3 dits duration + // O = 11 dits duration + // char space = 3 dits duration + // S = 5 dits duration + // total duration = 34 + + byte step = (time / dit) % 34; //dit number modulo the length of the sequence; + // Start with word space + if (step < 7) return false; + step -= 7; + // First S + if (step < 5) return (step % 2) == 0; // every second dit is off + step -= 5; + // Char space + if (step < 3) return false; + step -= 3; + // O + if (step < 11) return (step % 4) != 3; // every fourth dit is off + step -= 11; + // Char space + if (step < 3) return false; + step -= 3; + // Last S + if (step < 5) return (step % 2) == 0; // every second dit is off + // Should never get here + Serial.println("Morse SOS overrun error"); + return false; +} diff --git a/hexbright_factory/hexbright_factory.ino b/hexbright_factory/hexbright_factory.ino new file mode 100644 index 0000000..8a6a8db --- /dev/null +++ b/hexbright_factory/hexbright_factory.ino @@ -0,0 +1,206 @@ +/* + + Factory firmware for HexBright FLEX + v2.4 Dec 6, 2012 + +*/ + +#include +#include + +// Settings +#define OVERTEMP 340 +// Pin assignments +#define DPIN_RLED_SW 2 +#define DPIN_GLED 5 +#define DPIN_PWR 8 +#define DPIN_DRV_MODE 9 +#define DPIN_DRV_EN 10 +#define APIN_TEMP 0 +#define APIN_CHARGE 3 +// Modes +#define MODE_OFF 0 +#define MODE_LOW 1 +#define MODE_MED 2 +#define MODE_HIGH 3 +#define MODE_BLINKING 4 +#define MODE_BLINKING_PREVIEW 5 + +// State +byte mode = 0; +unsigned long btnTime = 0; +boolean btnDown = false; + + +void setup() +{ + // We just powered on! That means either we got plugged + // into USB, or the user is pressing the power button. + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + + // Initialize serial busses + Serial.begin(9600); + Wire.begin(); + + btnTime = millis(); + btnDown = digitalRead(DPIN_RLED_SW); + mode = MODE_OFF; + + Serial.println("Powered up!"); +} + +void loop() +{ + static unsigned long lastTempTime; + unsigned long time = millis(); + + // Check the state of the charge controller + int chargeState = analogRead(APIN_CHARGE); + if (chargeState < 128) // Low - charging + { + digitalWrite(DPIN_GLED, (time&0x0100)?LOW:HIGH); + } + else if (chargeState > 768) // High - charged + { + digitalWrite(DPIN_GLED, HIGH); + } + else // Hi-Z - shutdown + { + digitalWrite(DPIN_GLED, LOW); + } + + // Check the temperature sensor + if (time-lastTempTime > 1000) + { + lastTempTime = time; + int temperature = analogRead(APIN_TEMP); + Serial.print("Temp: "); + Serial.println(temperature); + if (temperature > OVERTEMP && mode != MODE_OFF) + { + Serial.println("Overheating!"); + + for (int i = 0; i < 6; i++) + { + digitalWrite(DPIN_DRV_MODE, LOW); + delay(100); + digitalWrite(DPIN_DRV_MODE, HIGH); + delay(100); + } + digitalWrite(DPIN_DRV_MODE, LOW); + + mode = MODE_LOW; + } + } + + // Do whatever this mode does + switch (mode) + { + case MODE_BLINKING: + case MODE_BLINKING_PREVIEW: + digitalWrite(DPIN_DRV_EN, (time%300)<75); + break; + } + + // Periodically pull down the button's pin, since + // in certain hardware revisions it can float. + pinMode(DPIN_RLED_SW, OUTPUT); + pinMode(DPIN_RLED_SW, INPUT); + + // Check for mode changes + byte newMode = mode; + byte newBtnDown = digitalRead(DPIN_RLED_SW); + switch (mode) + { + case MODE_OFF: + if (btnDown && !newBtnDown && (time-btnTime)>20) + newMode = MODE_LOW; + if (btnDown && newBtnDown && (time-btnTime)>500) + newMode = MODE_BLINKING_PREVIEW; + break; + case MODE_LOW: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_MED; + break; + case MODE_MED: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_HIGH; + break; + case MODE_HIGH: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_OFF; + break; + case MODE_BLINKING_PREVIEW: + // This mode exists just to ignore this button release. + if (btnDown && !newBtnDown) + newMode = MODE_BLINKING; + break; + case MODE_BLINKING: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_OFF; + break; + } + + // Do the mode transitions + if (newMode != mode) + { + switch (newMode) + { + case MODE_OFF: + Serial.println("Mode = off"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, LOW); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + break; + case MODE_LOW: + Serial.println("Mode = low"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + analogWrite(DPIN_DRV_EN, 64); + break; + case MODE_MED: + Serial.println("Mode = medium"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + analogWrite(DPIN_DRV_EN, 255); + break; + case MODE_HIGH: + Serial.println("Mode = high"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + analogWrite(DPIN_DRV_EN, 255); + break; + case MODE_BLINKING: + case MODE_BLINKING_PREVIEW: + Serial.println("Mode = blinking"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + break; + } + + mode = newMode; + } + + // Remember button state so we can detect transitions + if (newBtnDown != btnDown) + { + btnTime = time; + btnDown = newBtnDown; + delay(50); + } +} + From 6f49214f53e1c7f37f43b7fa274ce0ccc0845764 Mon Sep 17 00:00:00 2001 From: jae Date: Sat, 22 Dec 2012 11:14:29 -0600 Subject: [PATCH 7/8] Added readme to hardware section and renamed boards.txt --- README.md | 2 +- hardware/hexbright/bootloader/ATmegaBOOT_168.c | 0 .../bootloader/ATmegaBOOT_168_hexbright.hex | 0 hardware/hexbright/bootloader/Makefile | 0 .../{boards.txt => hexbright_board_def.txt} | 0 hardware/hexbright/readme.txt | 15 +++++++++++++++ 6 files changed, 16 insertions(+), 1 deletion(-) mode change 100755 => 100644 hardware/hexbright/bootloader/ATmegaBOOT_168.c mode change 100755 => 100644 hardware/hexbright/bootloader/ATmegaBOOT_168_hexbright.hex mode change 100755 => 100644 hardware/hexbright/bootloader/Makefile rename hardware/hexbright/{boards.txt => hexbright_board_def.txt} (100%) mode change 100755 => 100644 create mode 100644 hardware/hexbright/readme.txt diff --git a/README.md b/README.md index 0245e5a..e1fa37f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ HexBright Demo Code hexbright_extra ----------------- -This similar to the software that ships with the Hexbright Flex. Button presses cycle +This is similar to the software that ships with the Hexbright FLEX. Button presses cycle through off, low, medium, and high modes. Long Press while off for extended modes (dazzle, SOS). Button Presses: diff --git a/hardware/hexbright/bootloader/ATmegaBOOT_168.c b/hardware/hexbright/bootloader/ATmegaBOOT_168.c old mode 100755 new mode 100644 diff --git a/hardware/hexbright/bootloader/ATmegaBOOT_168_hexbright.hex b/hardware/hexbright/bootloader/ATmegaBOOT_168_hexbright.hex old mode 100755 new mode 100644 diff --git a/hardware/hexbright/bootloader/Makefile b/hardware/hexbright/bootloader/Makefile old mode 100755 new mode 100644 diff --git a/hardware/hexbright/boards.txt b/hardware/hexbright/hexbright_board_def.txt old mode 100755 new mode 100644 similarity index 100% rename from hardware/hexbright/boards.txt rename to hardware/hexbright/hexbright_board_def.txt diff --git a/hardware/hexbright/readme.txt b/hardware/hexbright/readme.txt new file mode 100644 index 0000000..80235c5 --- /dev/null +++ b/hardware/hexbright/readme.txt @@ -0,0 +1,15 @@ +In order for the Arduino IDE to understand the hardware specifics of the HexBright FLEX you must do the following. + +Linux (Ubuntu) +------- +For system wide configuration, add the contents of the hexbright_board_def.txt to: +/usr/share/arduino/hardware/arduino/boards.txt + +Mac +------- +To Be Added + +Windows +------- +To Be Added + From 46f68691f99ce1f314f0ece8f24c80d4a41215c2 Mon Sep 17 00:00:00 2001 From: jae Date: Sat, 22 Dec 2012 12:32:09 -0600 Subject: [PATCH 8/8] Updated readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e1fa37f..5a731eb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ -HexBright Demo Code +HexBright Code (jaebird) ======================= +Wiki of mods here: https://github.com/jaebird/HexBrightFLEX/wiki + hexbright_extra ----------------- This is similar to the software that ships with the Hexbright FLEX. Button presses cycle