diff --git a/hexbright-dazzle b/hexbright-dazzle new file mode 100644 index 0000000..b2a2032 --- /dev/null +++ b/hexbright-dazzle @@ -0,0 +1,415 @@ +/* Test firmware for HexBright + +Notes: +Requires Arduino 1.0.1! + +Modified by Jason Oglesby - phibroptk@gmail.com + +Modified Hexbright4.ino with the following changes: +Left Accel and other settings intact. +Changed modes to Off/Low/High and if button held and tapped, goto Dazzle. Press button again and it turns off. +Temp has been set to shut off at 420 - why? Thats a good number. +All the Blinking Previews are left in palce, just commented/rem'd out. If you wish to revert, please see the notes as I changed the code. +Changed Temperature posting to 3 Seconds from 1 Second and includes Charge Status. Hit "S" for More Stats. +You can still rotate the flashlight while holding the button to change the brightness. + + +*/ + +#include +#include + +// Settings +#define OVERTEMP 420 +// 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); +// digitalWrite(DPIN_RLED_SW, (time&0x03FF)?LOW:HIGH); //-Added this but have not tested, wanted to blink red/green leds on button - green was oem- + + // 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); + + int charge = analogRead(APIN_CHARGE); //Added this for Charge Status + Serial.print("Charge = "); + Serial.println(charge); + + 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 > 3000) + { + lastTempTime = time; + int charge = analogRead(APIN_CHARGE); //Added this for Charge Status + Serial.print("Charge = "); + Serial.println(charge); + + 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; +//---Begin REM--- +// case MODE_BLINKING: +// case MODE_BLINKING_PREVIEW: +// if (time-lastTime < 250) break; +// lastTime = time; +// +// blink = !blink; +// digitalWrite(DPIN_DRV_EN, blink); +// break; +//---End REM--- + + 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_DAZZLING_PREVIEW; //-Changed this from Mode_Blinking_Preview to Mode_Dazzling_Preview, only one tap to goto Dazzle- + break; + case MODE_KNOBBED: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; +//---Begin REM--- +// 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; +//--End REM-- + 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_DAZZLING_PREVIEW; //Changed Mode_Dazzling_Preview from Mode_Blinking_Preview - puts it back into a loop + 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; + //---Begin REM--- +// 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; +//---END REM--- + 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]); +} +