Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: AppleRemoteController_copy_Production_Version AppleRemoteController_Reference_Only
Revision 0:83d4a20e7bc7, committed 2015-06-16
- Comitter:
- andrewcrussell
- Date:
- Tue Jun 16 11:22:55 2015 +0000
- Child:
- 1:bb881a434906
- Commit message:
- RC5 Decoder with various outputs and inputs to control a preamp
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pindef1114.h Tue Jun 16 11:22:55 2015 +0000 @@ -0,0 +1,35 @@ +/************************************ Pinfef1114.h *******************************/ + +DigitalOut FWD1(dp15); // the are the motor 'H' bridge drive signals +DigitalOut REV1(dp16); // when the volume controll motor is not being driven +//DigitalOut REV1(p11); // they are all OFF +//DigitalOut REV2(p13); + +DigitalOut muteout(dp17); // drives the mute relay via a mosfet or transistor +InterruptIn mute_int(dp6); // mute p/button interrupt +DigitalIn mute(dp6); // mute input from associated pushbutton + +InterruptIn rc5int(dp1); // this is the R/C interrupt triggered by the IRx data out +DigitalIn rc5dat(dp1); // data is read in from here - its coming from the IRx data out + +InterruptIn select_int(dp28); // select rotary encoder interrupt - we use the 'A' O/P to generate the interrupt +DigitalIn sela(dp28); // select input rotary enc input A +DigitalIn selb(dp27); // select input rotary enc input B + +DigitalIn stdby(dp26); // standby function p/button input +InterruptIn stdby_int(dp26); // standby p/button interrupt in + +InterruptIn recloop_int(dp5); //record loop interrupt +DigitalIn recloop_in(dp5); // record loop p/button input +DigitalOut recloop_out(dp18); // drives record loop relay via mosfet or transistor + +DigitalOut power_ind(dp25); // this pin drives the standby controller - LOW = OFF; use regulators with standby inpu + +BusOut select_drv(dp9, dp10, dp11, dp13, dp14); //these are the select relay drivers +// note that we do not explicitly define the input select output ports because we just move the active +// output port bit around in a continuos loop with each depress of the select button. Drive the associated +// input relays via a mosfet or transistor + +// DigitalOut myled(LED1); // for test purposes only - on the mbed module - comment out when not used +// DigitalOut myled2(LED2); +// DigitalOut sync(p29); //this is a sync pin that is toggled during IR read - used for debug only \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pindef11U24.h Tue Jun 16 11:22:55 2015 +0000 @@ -0,0 +1,35 @@ +/************************************ Pinfef11U24.h *******************************/ + +DigitalOut FWD1(p12); // the are the motor 'H' bridge drive signals +DigitalOut REV1(p11); // when the volume controll motor is not being driven +//DigitalOut REV1(p11); // they are all OFF +//DigitalOut REV2(p13); + +DigitalOut muteout(p30); // drives the mute relay via a mosfet or transistor +InterruptIn mute_int(p26); // mute p/button interrupt +DigitalIn mute(p26); // mute input from associated pushbutton + +InterruptIn rc5int(p24); // this is the R/C interrupt triggered by the IRx data out +DigitalIn rc5dat(p24); // data is read in from here - its coming from the IRx data out + +InterruptIn select_int(p5); // select rotary encoder interrupt - we use the 'A' O/P to generate the interrupt +DigitalIn sela(p5); // select input rotary enc input A +DigitalIn selb(p6); // select input rotary enc input B + +DigitalIn stdby(p21); // standby function p/button input +InterruptIn stdby_int(p21); // standby p/button interrupt in + +InterruptIn recloop_int(p23); //record loop interrupt +DigitalIn recloop_in(p23); // record loop p/button input +DigitalOut recloop_out(p22); // drives record loop relay via mosfet or transistor + +DigitalOut power_ind(p33); // this pin drives the standby controller - LOW = OFF; use regulators with standby inpu + +BusOut select_drv(p15, p16, p17, p18, p19, p20); //these are the select relay drivers +// note that we do not explicitly define the input select output ports because we just move the active +// output port bit around in a continuos loop with each depress of the select button. Drive the associated +// input relays via a mosfet or transistor + +// DigitalOut myled(LED1); // for test purposes only - on the mbed module - comment out when not used +// DigitalOut myled2(LED2); +// DigitalOut sync(p29); //this is a sync pin that is toggled during IR read - used for debug only \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Tue Jun 16 11:22:55 2015 +0000
@@ -0,0 +1,431 @@
+/* **************************** RC5 Decoder and Preamp Controller V1.0 *************************/
+/* Andrew C. Russell (c) 2015 */
+/* This RC5 decoder works by reading in the RC5 stream from one of the serial port lines */
+/* and saving the incoming stream into an array called stream, after which it is decoded and */
+/* the command executed. A Marantz RC-68PM R/C was used to develop this program - it */
+/* should work with any controller complying with the Philips RC5 standard. */
+/* See the rc5codes.h header for the codes used. Note the address is 16 which is for a preamp. */
+
+/* The following audio preamplifier facilities are catered for:- */
+/* 1. Manual volume control adjustment via ALPS RK27 motorized potentiometer */
+/* 2. Input select via rotary encoder */
+/* 3. Output mute via push button actuation */
+/* 4. Record loop via push button actuation */
+/* 5. Power ON output to drive the /standby input of a system power supply */
+/* Facilities 1,2,3 and 5 are supported by an RC5 compliant remote control for preamplifiers */
+
+#include "mbed.h"
+#include "rc5codes.h" // Philips RC5 code definitions
+#include "Pindef1114.h" // all microcontroller I/O pin assignments defined here
+
+#define TRUE 1
+#define FALSE 0
+#define HIGH 1
+#define LOW 0
+#define rc5_bitcount 14 // number of RC5 bits
+#define tick 444 // quarter bit time in us
+#define tock 1778 // one bit time in us
+#define VUP_timeout 10 // defines max number of R/C cycles before the vol ctrl mtr drive stops
+#define VDWN_timeout 10 // as above but for volume decrease. Needed to ensure the motor is not burnt out
+
+//#define PHONO_IN 1 // these are the input assignments - not used in V1.0 of the
+//#define CD_IN 2 // controller since the input select is just stepped
+//#define TUN_IN 4 // through from PHONO_IN to REC_IN and back again
+//#define AUX1_IN 8
+//#define MSERV_IN 16
+//define REC_IN 32
+
+int startbit;
+int toggle;
+int toggle1;
+int toggle2;
+int standby;
+int address;
+int command;
+
+int FLAG1; // this is used in the remote control input processing
+int FLAG2; // this is used in the select input processing
+int FLAG3; // this is for the mute pushbutton
+int FLAG4; // this is for the standby pushbutton
+int FLAG5; // this is the recloop flag
+int RCFLAG = FALSE; // used to determine if the select command came via R/C
+int standbyflag; // used to save the standby condition
+
+int relay;
+int key_press = 1; // keeps track of key presses
+int toggle_press = 1; //stores value of toggle for key_press routine
+
+// delcarations below are all for the input select proceses
+int select = 0;
+int select_save = 1; // we save the status of select drive here. Initial value is 1
+int select_rot = 1; // rotary encoder pulse counter
+
+// declare function prototypes here
+void select_out (void);
+void rc5isr(void);
+void mute_isr(void);
+void recloop_isr(void);
+void select_isr(void);
+void standby_out(void);
+
+/****************************** volume increase ***********************************/
+void vol_up (void)
+{
+ if ((standbyflag == TRUE) && (key_press < VUP_timeout)) {
+
+ FWD1 = HIGH;
+ // FWD2 = HIGH;
+ wait(.1); //drive the motors for a short while
+ FWD1 = LOW;
+ // FWD2 = LOW;
+ }
+ if (toggle1 != toggle) {
+ key_press = 0; // user released the button, so reset counter
+ } else if (toggle1 == toggle) {
+ key_press++; // button remained depressed, so increment counter
+ }
+ toggle1 = toggle;
+ wait_ms(1);
+}
+
+/******************************* volume decrease **********************************/
+void vol_dwn (void)
+{
+ if ((standbyflag == TRUE) && (key_press < VDWN_timeout)) {
+
+ REV1 = HIGH;
+ // REV2 = HIGH;
+ wait(.1); //drive the motors for a short while
+ REV1 = LOW;
+ // REV2 = LOW;
+ }
+ if (toggle1 != toggle) {
+ key_press = 0; // user released the button, so reset counter
+ } else if (toggle1 == toggle) {
+ key_press++; // button remained depressed, so increment counter
+ }
+ toggle1 = toggle;
+ wait_ms(1);
+}
+/********************************** stdby_isr *************************************/
+void stdby_isr (void)
+{
+ FLAG4 = TRUE;
+}
+
+/*********************************** standby **************************************/
+/* this will require supporting hardware functionality to power down the */
+/* analog board, LED's etc. Best option here is to use regulators with a */
+/* shutdown option */
+
+void standby_out(void) // both p/button and R/C come in here
+{
+ stdby_int.fall(NULL); // on first power up cycle NO interuppts are accepted
+ // and neither any while this function is executed in any case
+ wait_ms(20); // a very simple debounce
+ do { // that waits for the depressed button to be released
+ (1);
+ } while (stdby !=1);
+
+ if (standbyflag == TRUE) { // was ON so we will turn it OFF
+ // turn off all interrupts except the standby and rc5int
+ select_int.fall(NULL);
+ mute_int.fall(NULL);
+ recloop_int.fall(NULL);
+ muteout = LOW;
+ wait(1);
+ recloop_out = LOW;
+ select_save = select_drv; // save the status of select_drv
+ select_drv = 0; // turn all input select realys OFF
+ wait(1);
+ power_ind = LOW; // this is the regulator shutdown control. HIGH = ON
+ standbyflag = FALSE; // set it up for the next power cycle
+
+ } else if (standbyflag == FALSE) { // was OFF so we will turn it ON
+ power_ind = HIGH;
+ rc5int.rise(&rc5isr); // trigger int on rising edge - go service it at rc5dat
+ select_int.fall(&select_isr); // input from rotary encoder or input select
+ mute_int.fall(&mute_isr);
+ recloop_int.fall(&recloop_isr);
+ wait(2);
+ select_drv = select_save; // recall the input select setting
+ wait(2); // let things settle a bit
+ muteout = HIGH;
+ standbyflag = TRUE;
+
+ }
+ wait_ms(5);
+ stdby_int.fall(&stdby_isr); // re-enable the standby interrupt
+}
+
+/********************************** record loop isr *******************************/
+
+void recloop_isr(void)
+{
+ FLAG5 = TRUE;
+}
+/************************** recloop - just a simple toggle ************************/
+void recloop()
+{
+ recloop_int.fall(NULL); // to prevent re-entrance when coming here from the R/C
+ wait_ms(20); // simple debounce for when mute is via the f/p p/b switch
+ do {
+ (1); // wait here until the button is released
+ } while (recloop_in!=1);
+ recloop_out = !recloop_out;
+ wait_ms(20);
+ recloop_int.fall(&recloop_isr);
+}
+
+/************************************ mute_isr ************************************/
+
+void mute_isr(void)
+{
+ FLAG3 = TRUE;
+ toggle2 = !toggle2; // so the p/button input is recognized in mute_out()
+}
+/*************************** mute - just a simple toggle **************************/
+void mute_out()
+{
+ mute_int.fall(NULL); // to prevent re-entance when coming here from the R/C
+ if ((standbyflag == TRUE) && (toggle != toggle2)) { // only toggle mute if the preamp is ON
+ wait_ms(20); //simple debounce for when mute is via the f/p p/b switch
+ do {
+ (1); //wait here until the button is released
+ } while (mute != 1);
+ muteout = !muteout;
+ wait_ms(20);
+
+ }
+ toggle2 = toggle;
+ mute_int.fall(&mute_isr);
+}
+
+/************************************ rc5isr **************************************/
+/* Interrupt triggered by a rising edge on p21 of the cont which is R/C data in */
+
+void rc5isr(void)
+{
+ FLAG1 = TRUE;
+}
+/***************** save rc5 bit stream from remote controller *********************/
+/* This function reads the input data on pin rc5dat at 1778us ('tock')intervals */
+/* and saves the data into an array stream[i]. */
+/* This function only looks at the second half of the bit position, since if that */
+/* is a 1 then it is assumed the first half of the bit position is a zero. Note */
+/* that in Manchester encoding, you cannot (should not) have both the 0 half-bit */
+/* position and the 1 half-bit position both HIGH or LOW in the same bit time - */
+/* a simplification exploited in this function. */
+
+void save_stream(void)
+{
+ bool stream[15];// the array is initialized each time its used and is local only
+ int bitloop; // number of bit positions
+ int i = 0; // counter
+ int k = 0; // temp storage
+ startbit = 0;
+ address = 0;
+ command = 0;
+ toggle = 0;
+ wait_us(tick); // locate read point in middle of 1st half bit time of the 1st start bit
+ for (bitloop = 0; bitloop <15; bitloop++) {
+ stream[bitloop] = rc5dat; //read the data and save it to array position [i]
+ wait_us(tock); //wait here until ready to read the next bit in
+
+ // now have 14 bits loaded into stream[i]
+ }
+ /* now put data in the array into the start, toggle, address and command variables - array counts from stream[0] */
+
+ for (i=0; i<2; i++) { // first 2 bit positions are start bits = 3; will use this later for basic error checking
+ k = stream[i];
+ startbit = (startbit << 1);
+ startbit = startbit|k;
+ }
+
+ toggle = stream[2]; // 3rd bit position is the toggle bit - 1 bit
+
+ for (i = 3; i <8; i++) { // bit positions 3 to 7 are the address (or 'system') - 5 bit positions in total
+ k = stream[i];
+ address = (address << 1);
+ address = address|k;
+ }
+
+ for (i = 8; i <14; i++) { // bit positions 8 to 13 are the command - 6 bit positions
+ k = stream[i];
+ command = (command << 1);
+ command = command|k;
+ }
+
+}
+/********************************* process_stream() *******************************/
+/* handles commands coming in from the remote controller only */
+
+void process_stream (void)
+{
+ if ((address == PREAMP) && (startbit == 3)) {
+// basic error checking - must be preamp + startbit ok to get executed otherwise skip completly
+ switch (command) {
+
+ case VUP:
+ vol_up();
+ break;
+
+ case VDOWN:
+ vol_dwn();
+ break;
+
+ case MUTE:
+ mute_out();
+ break;
+
+ case SELECT_R:
+ select_out();
+ break;
+
+ case STANDBY:
+ standby_out();
+ break;
+ }
+ }
+}
+/*********************************** select_isr ***********************************/
+
+void select_isr(void)
+{
+ FLAG2 = TRUE;
+}
+
+/********************************* select_process *********************************/
+/* used for selecting the input source. This function is used by both the */
+/* rotary encoder and the remote control */
+
+void select_process(void)
+{
+ if (RCFLAG == FALSE) { // if used R/C skip to select below
+ wait_ms(5); // debounce
+ select = 0; // flush select
+
+ select = (select | sela) <<1; // read the two port lines associated with the select rotary encoder
+ select = (select | selb);
+ }
+
+ switch (select) {
+ case 1: // select encoder is being rotated CW
+ select_rot <<= 1;
+ if (select_rot > 32) {
+ select_rot = 1;
+ }
+ break;
+
+ case 0:
+ select_rot >>= 1; // encoder is being rotated CCW
+ if (select_rot < 1) {
+ select_rot = 32;
+ }
+ break;
+
+ case 2:
+ {} break; // indeterminate fall through values - ignore
+ case 3:
+ {} break;
+ }
+ select_drv = select_rot; // write the value out to the bus
+}
+
+
+/********************* input select from remote controller only *******************/
+void select_out (void)
+{
+ if (toggle != toggle1) { // if the R/C button is held down, skip the increment
+ RCFLAG = TRUE; // this indicates command came in through the remote
+ select = 1;
+ select_process();
+ RCFLAG = FALSE;
+ }
+ toggle1 = toggle;
+}
+/************************************ main() ***************************************/
+int main(void)
+{
+ __disable_irq(); // just to make sure we can set up correctly without problems
+ muteout = LOW; // mute the output while we go through power-up sequence
+ recloop_out = LOW; // make sure initial recloop condition is delected
+ power_ind = LOW; // power control; HIGH = power up
+ wait(.2);
+ Serial pc(USBTX, USBRX); // for debuging only - comment out on production
+ FLAG1 = FALSE;
+ FLAG2 = FALSE;
+ FWD1=0;
+ // FWD2=0;
+ REV1=0;
+ // REV2=0; //make sure the volume control motor is OFF
+
+ // set up the ISR's we will be using
+ rc5int.rise(&rc5isr); // trigger int on rising edge - go service it at rc5dat
+ select_int.fall(&select_isr); // input from rotary encoder or input select
+ mute_int.fall(&mute_isr); // mute push button interrupt
+ recloop_int.fall(&recloop_isr); // record loop push button interrupt
+ stdby_int.fall(&stdby_isr); // the system power/standby switch
+
+ //now disable them, leaving only the stand by p/button and rc5int interrupts active
+ select_int.fall(NULL);
+ mute_int.fall(NULL);
+ recloop_int.fall(NULL);
+
+ standbyflag = HIGH; // preamp will be set-up first time for OFF
+ standby_out(); // go through standby_out for initial set-up
+ select_save = 1; // phono will be selected when power is first turned on
+ __enable_irq();
+
+ // all ready and in standby from this point forward
+
+LOOP: // this is the main operating loop
+
+ __WFI(); // wait here until interrupt
+
+ if (FLAG1 == TRUE) { // FLAG1 indicates remote control was used
+ __disable_irq();
+ save_stream();
+ if (startbit == 3) {
+ process_stream();
+ }
+ FLAG1 = FALSE;
+ __enable_irq();
+ }
+
+ if (FLAG2 == TRUE) {
+ __disable_irq();
+ select_process(); //select process
+ FLAG2 = FALSE;
+ __enable_irq();
+ }
+
+ if (FLAG3 == TRUE) {
+ __disable_irq();
+ mute_out(); //mute
+ FLAG3 = FALSE;
+ __enable_irq();
+ }
+
+ if (FLAG4 == TRUE) {
+ __disable_irq();
+ standby_out(); // standby
+ FLAG4 = FALSE;
+ __enable_irq();
+ }
+
+ if (FLAG5 == TRUE) {
+ __disable_irq();
+ recloop(); //recloop
+ FLAG5 = FALSE;
+ __enable_irq();
+ }
+
+ wait_us(5);
+
+ goto LOOP;
+
+}
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Tue Jun 16 11:22:55 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/487b796308b0 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rc5codes.h Tue Jun 16 11:22:55 2015 +0000 @@ -0,0 +1,81 @@ +/********************************* RC5 control codes ******************************/ +// The Philips RC5 coce consists of 14 bits delivered in bi-phase Manchester encoding from +// an IR LED on the remote. This is picked up by a detector (e.g. a Vishay TSOP3741) which +// outputs the demodulated bit stream as follows:- +// First 2 bits are start bits - allow the detector AGC to stabilize and trigger decoding process +// Third bit is the toggle bit - it remains at the same logic level as long as a key is depressed +// and will change to the alternate state when the key is un/re-depressed or when a different +// key is depressed +// Bits 4~8 are the address bits and determine which piece of equipment is being controlled +// Bits 9~14 are the command bits +// As long as a key is depressed, the 14 bits will be sent by the remote controller in sequential +// blocks with a 120ms delay between subsequent block transmissions +// See http://en.wikipedia.org/wiki/RC-5 for the codes + +// 0-9 NUMERIC KEYS 0 - 9 - not used in this implementation + +// unused commands and addresses have been commented out - simply un-comment them to use them +// but note that if you do this, you will have to decode them, otherwise they will just fall through +// and be ignored by the decoder. Only the ones un-commented out below are active in V1.0 +// note you will also need to write the associated command processor functions + +#define STANDBY 12 // toggle power ON and OFF +#define MUTE 13 // toggle output signal on and off +// #define 14 PRESETS +#define VUP 16 +#define VDOWN 17 +// #define 18 BRIGHTNESS + +// #define 19 BRIGHTNESS - +// #define 20 COLOR SATURATION + +// #define 21 COLOR SATURATION - +// #define BASSUP 22 +// #define BASSDOWN 23 +// #define TREBLEUP 24 +// #define TREBLEDWN 25 +// #define BALRIGHT 26 +// #define BALLEFT 27 +// #define PAUSE 48 +// #define 50 FAST REVERSE +// #define 52 FAST FORWARD- +// #define PLAY 53 +// #define STOP 54 +// #define 55 RECORD +#define SELECT_R 3 // rotates input through inputs - must depress and then release each time + +/* RC5 address */ +// #define 0 TV SET 1 +// #define 1 TV SET 2 +// #define 2 VIDEOTEXT +// #define 3 EXPANSION FOR TV 1 AND 2 +// #define 4 LASER VIDEO PLAYER +// #define 5 VIDEO RECORDER 1 (VCR 1) +// #define 6 VIDEO RECORDER 2 (VCR 2) +// #define 7 RESERVED +// #define 8 SAT 1 +// #define 9 EXPANSION FOR VCR 1 OR 2 +// #define 10 SAT 2 +// #define 11 RESERVED +// #define 12 CD VIDEO +// #define 13 RESERVED +// #define 14 CD PHOTO +// #define RESERVED +#define PREAMP 16 +// #define RECEIVER 17 +// #define 18 TAPE / CASSETE RECORDER +// #define PRE2 19 +// #define CD 20 +// #define AUDIO_RACK 21 +// #define 22 AUDIO SAT RECEIVER +// #define 23 DCC RECORDER +// #define 24 RESERVED +// #define 25 RESERVED +// #define 26 WRITABLE CD +// #define 26-31 RESERVED0 TV SET 1 + + + + + + + +