Andrew Russell / Mbed OS RC5_AndrewR

Dependents:   AppleRemoteController_copy_Production_Version AppleRemoteController_Reference_Only

Files at this revision

API Documentation at this revision

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

Pindef1114.h Show annotated file Show diff for this revision Revisions of this file
Pindef11U24.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
rc5codes.h Show annotated file Show diff for this revision Revisions of this file
--- /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
+
+
+
+
+
+
+
+