Last active
November 19, 2017 22:58
-
-
Save eighthree/cc8c640cb6b0898cfc6d7130f8ae3f4d to your computer and use it in GitHub Desktop.
Code that runs a bunch of things for diy retropie build
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Hyperbox 1.0 | |
* USB Serial interface using a Cortex M0 dev board + sensors for use with | |
* a Raspberry Pi. | |
* | |
* Current Consumption/Battery Level monitor + Keyboard HID | |
* | |
* Made specifically for use with a Hyperpixel display from Pimoroni | |
* https://github.com/pimoroni/hyperpixel | |
* as it uses up all the GPIO's on a Pi. | |
* | |
* Controller based on: | |
* https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/master/Joy_game_controller/Joy_game_controller.ino | |
* | |
* Uses an Adafruit Joy Featherwing (for now) | |
* but I recommend you omit this. | |
* | |
* BOM: | |
* Sparkfun Lipo Fuel Gauge | |
* Adafruit INA219 Current Breakout Board | |
* Adafruit Feather M0 Express | |
* Adafruit Joy Featherwing (w/Seesaw) | |
* Adafruit Powerboost 1000c | |
* Raspberry Pi Zero W | |
* LM75A Temperature Sensor | |
*/ | |
#include <Wire.h> | |
#include <Adafruit_INA219.h> | |
#include "Adafruit_seesaw.h" | |
#include <Keyboard.h> | |
#include <M2M_LM75A.h> | |
#include "MAX17043.h" | |
#include <Adafruit_NeoPixel.h> | |
Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, 8, NEO_GRB + NEO_KHZ800); | |
Adafruit_INA219 ina219; | |
Adafruit_seesaw ss; | |
M2M_LM75A lm75a; | |
MAX17043 batteryMonitor; | |
#define BUTTON_RIGHT 6 | |
#define BUTTON_DOWN 7 | |
#define BUTTON_LEFT 9 | |
#define BUTTON_UP 10 | |
#define BUTTON_SEL 14 | |
uint32_t button_mask = (1 << BUTTON_RIGHT) | (1 << BUTTON_DOWN) | | |
(1 << BUTTON_LEFT) | (1 << BUTTON_UP) | (1 << BUTTON_SEL); | |
#define IRQ_PIN 5 | |
struct { | |
uint32_t lastChangeTime; | |
} jbutton[] = { | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
}; | |
struct { // Button structure: | |
int8_t pin; // Button is wired between this pin and GND | |
uint8_t key; // Corresponding key code to send | |
bool prevState; | |
uint32_t lastChangeTime; | |
} button[] = { | |
{ A0, 'r' }, // Button 0 Blue | |
{ A1, 'l'}, // Button 1 Pink | |
{ A2, 'x' }, // Button 2 Yellow | |
{ A3, 'y' }, // Button 3 Green | |
{ A4, 'b' }, // Joystick select click | |
{ A5, 'a' }, // Joystick select click | |
}; | |
#define N_BUTTONS (sizeof(button) / sizeof(button[0])) | |
#define DEBOUNCE_US 600 // Button debounce time, microseconds | |
struct { // Joystick axis structure (2 axes per stick): | |
int8_t pin; // Analog pin where stick axis is connected | |
int lower; // Typical value in left/upper position | |
int upper; // Typical value in right/lower positionax | |
uint8_t key1; // Key code to send when left/up | |
uint8_t key2; // Key code to send when down/right | |
int value; // Last-read-and-mapped value (0-1023) | |
int8_t state; | |
} axis[] = { | |
{ 3, 65, 1023, KEY_LEFT_ARROW, KEY_RIGHT_ARROW }, // X axis | |
{ 2, 1023, 65, KEY_DOWN_ARROW , KEY_UP_ARROW }, // Y axis | |
}; | |
#define N_AXES (sizeof(axis) / sizeof(axis[0])) | |
int last_x = 0, last_y = 0; | |
uint8_t state = 0; | |
float previousVoltage; | |
volatile byte jstate = LOW; | |
void setup(void) | |
{ | |
Serial.begin(115200); | |
while (!Serial) { | |
// will pause Zero, Leonardo, etc until serial console opens | |
delay(1); | |
} | |
uint8_t i; | |
strip.begin(); | |
strip.setBrightness(40); | |
strip.show(); // Initialize all pixels to 'off' | |
/* INA219 */ | |
uint32_t currentFrequency; | |
ina219.begin(); | |
ina219.setCalibration_32V_1A(); | |
lm75a.begin(); | |
// Serial.println("HypeM0 - Services Starting"); | |
/* SEESAW */ | |
if(!ss.begin(0x49)){ | |
// Serial.println("SYS: Adafruit Seesaw connection ERROR!"); | |
while(1); | |
} | |
else{ | |
//Serial.println("SYS: Adafruit Seesaw started"); | |
//Serial.println(ss.getVersion(), HEX); | |
} | |
/* KEYBOARD */ | |
Keyboard.begin(); | |
// Initialize button states... | |
for(i=0; i<N_BUTTONS; i++) { | |
pinMode(button[i].pin, INPUT_PULLUP); | |
button[i].prevState = digitalRead(button[i].pin); | |
button[i].lastChangeTime = micros(); | |
} | |
for(i=0; i<N_AXES; i++) { | |
int value = map(ss.analogRead(axis[i].pin), axis[i].lower, axis[i].upper, 0, 1023); | |
if(value > (1023 * 4 / 5)) { | |
Keyboard.press(axis[i].key2); | |
axis[i].state = 1; | |
} else if(value < (1023 / 5)) { | |
Keyboard.press(axis[i].key1); | |
axis[i].state = -1; | |
} else { | |
axis[i].state = 0; | |
} | |
} | |
batteryMonitor.reset(); | |
batteryMonitor.quickStart(); | |
previousVoltage = batteryMonitor.getVCell(); | |
ss.pinModeBulk(button_mask, INPUT_PULLUP); | |
ss.setGPIOInterrupts(button_mask, 1); | |
pinMode(IRQ_PIN, INPUT); | |
attachInterrupt(IRQ_PIN, joyint, CHANGE); | |
} | |
int interval = 10000; | |
unsigned long previousMillis = 0; | |
void joyint() { | |
jstate = !jstate; | |
} | |
void loop(void) | |
{ | |
unsigned long currentMillis = millis(); | |
float shuntvoltage = 0; | |
float busvoltage = 0; | |
float current_mA = 0; | |
float loadvoltage = 0; | |
if ((unsigned long)(currentMillis - previousMillis) >= interval && state > 2) { | |
shuntvoltage = ina219.getShuntVoltage_mV(); | |
busvoltage = ina219.getBusVoltage_V(); | |
current_mA = ina219.getCurrent_mA(); | |
loadvoltage = busvoltage + (shuntvoltage / 1000); | |
float cellVoltage = batteryMonitor.getVCell(); | |
Serial.print(String(cellVoltage, 4) + ","); | |
float stateOfCharge = int(batteryMonitor.getSoC()); | |
Serial.print(String(stateOfCharge) + ","); | |
Serial.print(String(current_mA) + ","); | |
Serial.print(String(lm75a.getTemperature()) + ","); | |
int batSlope = (currentMillis - previousMillis)/(cellVoltage - previousVoltage); | |
if( batSlope >= 0.1 ) { | |
Serial.print("1\n"); | |
} else { | |
Serial.print("0\n"); | |
} | |
if (current_mA > 100) { | |
if(stateOfCharge >= 90) { | |
colorWipe(strip.Color(0, 0, 40), 50); | |
} else if (stateOfCharge >= 70) { | |
colorWipe(strip.Color(0, 40, 0), 50); | |
} else if (stateOfCharge >= 60) { | |
colorWipe(strip.Color(0, 100, 90), 50); | |
} else if (stateOfCharge >= 50) { | |
colorWipe(strip.Color(30, 180, 0), 50); | |
} else if (stateOfCharge >= 30) { | |
colorWipe(strip.Color(100, 150, 0), 50); | |
} else | |
colorWipe(strip.Color(100,0,0), 50); | |
} | |
else if (batSlope >= 0.1) { | |
colorWipe(strip.Color(200,120,0), 50); | |
} else { | |
colorWipe(strip.Color(128,0,128), 50); | |
} | |
previousVoltage = cellVoltage; | |
previousMillis = currentMillis; | |
} | |
/* Joy Featherwing Read */ | |
if(!jstate){ | |
delay(10); | |
uint32_t buttons = ss.digitalReadBulk(button_mask); | |
//Serial.println(buttons, BIN); | |
if (! (buttons & (1 << BUTTON_RIGHT))) { | |
if( currentMillis - jbutton[0].lastChangeTime >= 50) | |
{ | |
Serial.println("CMD_RIGHT\n"); | |
} | |
jbutton[0].lastChangeTime = currentMillis; | |
} | |
if (! (buttons & (1 << BUTTON_DOWN))) { | |
if( currentMillis - jbutton[1].lastChangeTime >= 75) | |
{ | |
Serial.println("CMD_DOWN\n"); | |
} | |
jbutton[1].lastChangeTime = currentMillis; | |
} | |
if (! (buttons & (1 << BUTTON_LEFT))) { | |
if( currentMillis - jbutton[2].lastChangeTime >= 75) | |
{ | |
Serial.println("CMD_LEFT\n"); | |
} | |
jbutton[2].lastChangeTime = currentMillis; | |
} | |
if (! (buttons & (1 << BUTTON_UP))) { | |
if( currentMillis - jbutton[3].lastChangeTime >= 75) | |
{ | |
Serial.println("CMD_VOL_UP\n"); | |
} | |
jbutton[3].lastChangeTime = currentMillis; | |
} | |
if (! (buttons & (1 << BUTTON_SEL))) { | |
if( currentMillis- jbutton[4].lastChangeTime >= 75) | |
{ | |
Serial.println("CMD_SELECT\n"); | |
} | |
jbutton[4].lastChangeTime = currentMillis; | |
} | |
if (! (buttons & (1 << BUTTON_SEL)) && ! (buttons & (1 << BUTTON_DOWN))) { | |
if( currentMillis- jbutton[5].lastChangeTime >= 50) | |
{ | |
Serial.println("shutdown-please\n"); | |
} | |
jbutton[5].lastChangeTime = currentMillis; | |
} | |
} | |
/* Analog Button Read*/ | |
uint32_t t; | |
bool s; | |
int i, value, dx, dy; | |
float a; | |
uint16_t *buf; | |
// Read and debounce button inputs... | |
for(i=0; i<N_BUTTONS; i++) { | |
s = digitalRead(button[i].pin); // Current button state | |
if(s != button[i].prevState) { // Changed from before? | |
t = micros(); // Check time; wait for debounce | |
if((t - button[i].lastChangeTime) >= DEBOUNCE_US) { | |
if(s) Keyboard.release(button[i].key); // Button released | |
else Keyboard.press(button[i].key); // Button pressed | |
button[i].prevState = state; // Save new button state | |
button[i].lastChangeTime = t; // and time of change | |
} | |
} | |
} | |
// Read joystick axes | |
for(i=0; i<N_AXES; i++) { | |
// Remap analog reading to 0-1023 range (0=top/left, 1023=down/right) | |
value = map(ss.analogRead(axis[i].pin), axis[i].lower, axis[i].upper, 0, 1023); | |
if(axis[i].state == 1) { // Axis previously down/right? | |
if(value < (1023 * 3 / 5)) { // Moved up/left past hysteresis threshold? | |
Keyboard.release(axis[i].key2); // Release corresponding key | |
axis[i].state = 0; // and set state to neutral center zone | |
} | |
} else if(axis[i].state == -1) { // Else axis previously up/left? | |
if(value > (1023 * 2 / 5)) { // Moved down/right past hysteresis threshold? | |
Keyboard.release(axis[i].key1); // Release corresponding key | |
axis[i].state = 0; // and set state to neutral center zone | |
} | |
} // This is intentionally NOT an 'else' -- state CAN change twice here! | |
if(!axis[i].state) { // Axis previously in neutral center zone? | |
if(value > (1023 * 4 / 5)) { // Moved down/right? | |
Keyboard.press(axis[i].key2); // Press corresponding key | |
axis[i].state = 1; // and set state to down/right | |
} else if(value < (1023 / 5)) { // Else axis moved up/left? | |
Keyboard.press(axis[i].key1); // Press corresponding key | |
axis[i].state = -1; | |
} | |
} | |
axis[i].value = value; // Save for later | |
} | |
if(++state > 3) state = 0; | |
} | |
// Fill the dots one after the other with a color | |
void colorWipe(uint32_t c, uint8_t wait) { | |
for(uint16_t i=0; i<strip.numPixels(); i++) { | |
strip.setPixelColor(i, c); | |
strip.show(); | |
delay(wait); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment