Created
September 5, 2016 18:17
-
-
Save hughpyle/d4013d27f9b426fca082088b99b7288f to your computer and use it in GitHub Desktop.
Teensy remote control for MiniDSP 2x4 HD
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
#include <ir_Lego_PF_BitStreamEncoder.h> | |
#include <IRremote.h> | |
#include <IRremoteInt.h> | |
/* This is a special-purpose infrared "remote control" to control vokume and channel selecion for the MiniDSP */ | |
/* Hardware: Teensy 3.x, two rotary hex encoders (I used 25LB22-H), and a generic IR LED */ | |
int UP = 1; | |
int DOWN = -1; | |
int NONE = 0; | |
bool stopped = 1; | |
int oldDirection = NONE; | |
int oldVolume = 0; | |
int oldPreset = 0; | |
IRsend irsend; | |
/* Pins */ | |
/* Note: correct the IR LED to output pin 5 (Teensy 3) or 10 (Teensy 2) */ | |
const int SRC_PIN_0 = 0; | |
const int SRC_PIN_1 = 1; | |
const int SRC_PIN_2 = 2; | |
const int SRC_PIN_3 = 3; | |
const int VOL_PIN_0 = 21; | |
const int VOL_PIN_1 = 20; | |
const int VOL_PIN_2 = 19; | |
const int VOL_PIN_3 = 18; | |
/* Some actual preset codes. Or you could use random values instead. | |
These are from hk3370 at http://www.righto.com/2009/11/controlling-your-stereo-over-web-with.html | |
*/ | |
const uint32_t NEC_SOURCE_0 = 0x010e43bc; | |
const uint32_t NEC_SOURCE_1 = 0x010e23dc; | |
const uint32_t NEC_SOURCE_2 = 0x010e41be; | |
const uint32_t NEC_SOURCE_3 = 0x010e817e; | |
const uint32_t NEC_VOL_UP = 0x010ee31c; | |
const uint32_t NEC_VOL_DOWN = 0x010e13ec; | |
uint32_t PRESETS[] = {NEC_SOURCE_0, NEC_SOURCE_1, NEC_SOURCE_2, NEC_SOURCE_3}; | |
void setup() { | |
/* nothing */ | |
Serial.begin(9600); | |
pinMode(SRC_PIN_0, INPUT_PULLUP); | |
pinMode(SRC_PIN_1, INPUT_PULLUP); | |
pinMode(SRC_PIN_2, INPUT_PULLUP); | |
pinMode(SRC_PIN_3, INPUT_PULLUP); | |
pinMode(VOL_PIN_0, INPUT_PULLUP); | |
pinMode(VOL_PIN_1, INPUT_PULLUP); | |
pinMode(VOL_PIN_2, INPUT_PULLUP); | |
pinMode(VOL_PIN_3, INPUT_PULLUP); | |
} | |
/* Get the raw value from the volume input. Counter value 0 to 16. */ | |
int getVolumeSetting() { | |
int vol = 0; | |
vol = (vol << 1) | digitalRead(VOL_PIN_0); | |
vol = (vol << 1) | digitalRead(VOL_PIN_1); | |
vol = (vol << 1) | digitalRead(VOL_PIN_2); | |
vol = (vol << 1) | digitalRead(VOL_PIN_3); | |
return vol; | |
} | |
/* Get the raw value from the sources input. Counter value 0 to 16. */ | |
int getSourceSetting() { | |
int pre = 0; | |
pre = (pre << 1) | digitalRead(SRC_PIN_0); | |
pre = (pre << 1) | digitalRead(SRC_PIN_1); | |
pre = (pre << 1) | digitalRead(SRC_PIN_2); | |
pre = (pre << 1) | digitalRead(SRC_PIN_3); | |
return pre; | |
} | |
void loop() { | |
doStuff(); | |
delay(100); | |
} | |
void doStuff() { | |
int v = getVolumeSetting(); | |
int p = getSourceSetting(); | |
/* If nothing has changed, there's nothing to do */ | |
if( v==oldVolume && p==oldPreset ) { | |
stopped = true; | |
return; | |
} | |
/* If the preset has changed: handle it */ | |
if( p != oldPreset ) { | |
Serial.print("Source has changed to "); | |
Serial.println(p, DEC); | |
sendPreset(p); | |
stopped = false; | |
return; | |
} | |
if( v != oldVolume ) { | |
Serial.print("Volume has changed to "); | |
Serial.println(v, DEC); | |
sendVolume(v); | |
stopped = false; | |
return; | |
} | |
} | |
void sendPreset(int p) { | |
/* The preset 'p' is from 0x0 to 0xF | |
* But it really only controls three inputs, so send (p % 3) | |
*/ | |
/* Send the code for the selected preset. */ | |
irsend.sendNEC(PRESETS[p % 0x03], 32); | |
/* Send twice. Helps with 'learn mode' but also for more reliability. */ | |
delay(100); | |
irsend.sendNEC(PRESETS[p % 0x03], 32); | |
oldPreset = p; | |
/* Reset the direction memory for the volume spinner */ | |
oldDirection = NONE; | |
} | |
void sendVolume(int v) { | |
/* Determine whether the volume went up or down. */ | |
int direction = NONE; | |
if( v > oldVolume ) { | |
if( v-oldVolume >= 7 ) { | |
direction = DOWN; | |
} else { | |
direction = UP; | |
} | |
} else { | |
if( oldVolume-v >= 7 ) { | |
direction = UP; | |
} else { | |
direction = DOWN; | |
} | |
} | |
/* Did the volume change, in the same direction, twice in a row? | |
* If so, we're "spinning the wheel". | |
* Don't send "up" or "down", instead send "repeat". | |
*/ | |
/* | |
if(direction == oldDirection && !stopped) { | |
Serial.println("repeat"); | |
sendNECRepeat(); | |
} else | |
*/ | |
/* Send multiple volume steps at once, the control is too fine otherwise */ | |
if(direction == UP) { | |
Serial.println("up"); | |
irsend.sendNEC(NEC_VOL_UP, 32); | |
delay(100); | |
irsend.sendNEC(NEC_VOL_UP, 32); | |
delay(100); | |
irsend.sendNEC(NEC_VOL_UP, 32); | |
} else if(direction == DOWN) { | |
Serial.println("down"); | |
irsend.sendNEC(NEC_VOL_DOWN, 32); | |
delay(100); | |
irsend.sendNEC(NEC_VOL_DOWN, 32); | |
delay(100); | |
irsend.sendNEC(NEC_VOL_DOWN, 32); | |
} | |
oldDirection = direction; | |
oldVolume = v; | |
} | |
void sendNECRepeat() { | |
/* https://github.com/z3t0/Arduino-IRremote/issues/28 */ | |
unsigned int buf[3]; | |
buf[0] = 9000; // Mark 9ms | |
buf[1] = 2250; // Space 2.25ms | |
buf[2] = 560; // Burst | |
irsend.sendRaw(buf, 3, 38); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment