-
-
Save tarnak/d95d2ce8b0d5419efa234e55d9d28c50 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| #include <IRremote.h> | |
| #define NO_IR 0 | |
| #define NO_BTN -1 | |
| #define IR_REPEAT 0xFFFFFFFF | |
| #define IR_SEND_MODE 1 | |
| #define IR_STORE_MODE 2 | |
| #define BUFSIZE 128 | |
| typedef struct { | |
| int button; | |
| bool pressed; | |
| uint64_t pressedTime; | |
| } ButtonState; | |
| typedef enum { | |
| NONE = 0, | |
| BUTTON_PRESSED = 1, | |
| IR_RECV = 2 | |
| } State; | |
| typedef enum { | |
| RED = 0, | |
| GREEN = 1, | |
| BLUE = 2 | |
| } Color; | |
| //// Constants | |
| // Time constants | |
| const float longPressDelay = 2.0; | |
| // Buttons | |
| const int buttonPins[] = {8, 9}; | |
| const int nButtons = (int) (sizeof(buttonPins) / sizeof(int)); | |
| // IR interface | |
| const int irRecvPin = 7; | |
| // LED interface | |
| const int ledPins[] = {5, 6, 10}; // RGB | |
| const uint8_t nColors = sizeof(ledPins) / sizeof(ledPins[0]); | |
| const uint8_t modeColors[][nColors] = { | |
| {0, 0, 0}, // NONE | |
| {0, 255, 0}, // BUTTON_PRESSED: LED green | |
| {255, 0, 120}, // IR_RECV: LED purple | |
| }; | |
| //// Variables | |
| ButtonState buttonStates[nButtons]; | |
| decode_results irButtonData[nButtons]; | |
| unsigned int irBuffer[BUFSIZE]; | |
| IRsend irsend; | |
| IRrecv irrecv(irRecvPin); | |
| void setup() { | |
| Serial.begin(9600); | |
| irrecv.enableIRIn(); | |
| irrecv.blink13(true); | |
| for (int i=0; i < nButtons; i++) { | |
| pinMode(buttonPins[i], INPUT_PULLUP); | |
| decode_results irData; | |
| irData.value = NO_IR; | |
| ButtonState buttonState = { | |
| .button = i, | |
| .pressed = false, | |
| .pressedTime = 0 | |
| }; | |
| memset(irButtonData, 0, nButtons * sizeof(decode_results)); | |
| memcpy(&(buttonStates[i]), &buttonState, sizeof(ButtonState)); | |
| } | |
| for (int i=0; i < nColors; i++) { | |
| pinMode(ledPins[i], OUTPUT); | |
| analogWrite(ledPins[i], 0); | |
| } | |
| } | |
| float getButtonDelay(uint64_t pressedTime) { | |
| return (((uint64_t) (millis() - pressedTime)) / 1000.0); | |
| } | |
| void printButtonState(ButtonState* state) { | |
| Serial.print("{\"button\":"); | |
| Serial.print(state->button); | |
| if (state->pressedTime) { | |
| Serial.print(", \"delay\":"); | |
| Serial.print(getButtonDelay(state->pressedTime)); | |
| } | |
| Serial.print(", \"pressed\":"); | |
| Serial.print(state->pressed); | |
| Serial.println("}"); | |
| } | |
| void printIrState(uint32_t irState) { | |
| Serial.print("{\"ir\":"); | |
| Serial.print(irState, HEX); | |
| Serial.println("}"); | |
| } | |
| void printNewIrButtonData(int button) { | |
| Serial.print("{\"action\":\"store_new_data\", \"button\":"); | |
| Serial.print(button); | |
| Serial.print(", \"ir\":\""); | |
| Serial.print(irButtonData[button].value, HEX); | |
| Serial.println("\"}"); | |
| } | |
| ButtonState getPressedButton() { | |
| ButtonState noBtn = { | |
| .button = NO_BTN, | |
| .pressed = false, | |
| .pressedTime = 0 | |
| }; | |
| for (int i=0; i < nButtons; i++) { | |
| int state = digitalRead(buttonPins[i]); | |
| if (state == HIGH) { | |
| buttonStates[i].pressed = true; | |
| if (buttonStates[i].pressedTime == 0) { | |
| printButtonState(&buttonStates[i]); | |
| buttonStates[i].pressedTime = millis(); | |
| } | |
| return buttonStates[i]; | |
| } else { | |
| buttonStates[i].pressed = false; | |
| if (buttonStates[i].pressedTime != 0) { | |
| printButtonState(&buttonStates[i]); | |
| buttonStates[i].pressedTime = 0; | |
| } | |
| } | |
| } | |
| return noBtn; | |
| } | |
| uint32_t getIrValue(decode_results* irResults) { | |
| uint32_t value = NO_IR; | |
| if (irrecv.decode(irResults)) { | |
| if (irResults->value && irResults->value != REPEAT) { | |
| value = irResults->value; | |
| printIrState(value); | |
| } | |
| irrecv.resume(); | |
| } | |
| return value; | |
| } | |
| void storeNewIrButtonData(int button, decode_results* irData) { | |
| memcpy(&(irButtonData[button]), irData, sizeof(decode_results)); | |
| printNewIrButtonData(button); | |
| } | |
| void sendIrCommand(int button) { | |
| decode_results irData = irButtonData[button]; | |
| if (irData.value == NO_IR) | |
| return; | |
| switch (irData.decode_type) { | |
| case NEC: | |
| irsend.sendNEC(irData.value, 32); | |
| break; | |
| case SONY: | |
| irsend.sendSony(irData.value, 12); | |
| break; | |
| case PANASONIC: | |
| irsend.sendPanasonic(irData.address, irData.value); | |
| break; | |
| case RC5: | |
| irsend.sendRC5(irData.value, 12); | |
| break; | |
| case RC6: | |
| irsend.sendRC6(irData.value, 20); | |
| break; | |
| case JVC: | |
| irsend.sendJVC(irData.value, 8, false); | |
| break; | |
| case SAMSUNG: | |
| irsend.sendSAMSUNG(irData.value, 20); | |
| break; | |
| case SHARP: | |
| irsend.sendSharp(irData.address, irData.value); | |
| break; | |
| case DENON: | |
| irsend.sendDenon(irData.value, 15); | |
| break; | |
| case LG: | |
| irsend.sendLG(irData.value, 32); | |
| break; | |
| default: | |
| Serial.println("Unknown IR protocol"); | |
| return; | |
| } | |
| irrecv.enableIRIn(); | |
| Serial.print("{\"action\":\"send_ir_data\", \"ir\":"); | |
| Serial.print(irData.value, HEX); | |
| Serial.println("}"); | |
| delay(100); | |
| } | |
| void ledNotifyState(State state) { | |
| uint8_t ledColor[nColors] = {0}; | |
| if (state & BUTTON_PRESSED) | |
| for (int i=0; i < nColors; i++) | |
| ledColor[i] |= modeColors[BUTTON_PRESSED][i]; | |
| if (state & IR_RECV) | |
| for (int i=0; i < nColors; i++) | |
| ledColor[i] |= modeColors[IR_RECV][i]; | |
| for (int i=0; i < nColors; i++) | |
| analogWrite(ledPins[i], ledColor[i]); | |
| } | |
| void loop(){ | |
| State state = NONE; | |
| decode_results irResults; | |
| ButtonState button = getPressedButton(); | |
| uint32_t irValue = getIrValue(&irResults); | |
| if (button.button != NO_BTN) { | |
| state |= BUTTON_PRESSED; | |
| } | |
| if (irValue != NO_IR) { | |
| state |= IR_RECV; | |
| if (button.button != NO_BTN) { | |
| storeNewIrButtonData(button.button, &irResults); | |
| } | |
| } else { | |
| // Press a button with a stored command for more than 2 seconds and hold the key to clone | |
| // on the other remote to overwrite the existing command | |
| if (button.button != NO_BTN && getButtonDelay(button.pressedTime) < longPressDelay) { | |
| sendIrCommand(button.button); | |
| } | |
| } | |
| ledNotifyState(state); | |
| delay(10); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment