An RC5 decoder and preamp controller. Written on the LPC11U24, Ported to LPC1114 and now 100% stable (January 2016)

Dependents:   AppleRemoteController_copy_Production_Version AppleRemoteController_Reference_Only

Revision:
4:d900d90588d0
Parent:
3:f0cd7c22ca94
Child:
9:c9fb1f8e2ab8
--- a/main.cpp	Tue Jul 26 16:24:40 2022 +0000
+++ b/main.cpp	Mon Nov 07 10:42:42 2022 +0000
@@ -1,17 +1,15 @@
-/****************************** 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        */
+/****************************** Apple TV Remote Decoder  and Preamp Controller V1.0 *************************/
+/*                                  Andrew C. Russell (c) 2022                                  */
+/* This decoder works by reading in the Apple TV Remote IR data 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 IR 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.                                                */
+/* the command executed. .                                                */
 
 /* 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                      */
+/* 3. Output mute via remote controller only                                                    */
+/* 4. Power ON output to drive the /standby input of a system power supply                      */
+/* 5.Trigger output to power up an amplifier or other system components                         */
 /* Facilities 1,2,3 and 5 are supported by an RC5 compliant remote control for preamplifiers    */
 /* The controller pin definitions are set in Pindef1114.h file.                                 */
 
@@ -20,8 +18,21 @@
 // for the standby output to drive a power amplifier. Pin 8 on J2 (Controller board)
 
 #include "mbed.h"
-#include "rc5codes.h"      // RC code definitions - in this case for Apple TV Remote
-#include "Pindef1114.h"    // all microcontroller I/O pin assignments defined here    
+//#include "rc5codes.h"      // RC code definitions - in this case for Apple TV Remote
+#include "Pindef1114.h"    // all microcontroller I/O pin assignments defined here
+
+/************************************* Apple TV Remote control codes ****************************/
+#define STANDBY 378      // toggle  power ON and OFF
+#define MUTE 442         // toggle output signal on and off
+#define VUP 464
+#define VDOWN 432
+#define SELECT_R 480      // rotates input through inputs - must depress and then release each time
+#define SELECT_L 272      // rotates input through inputs - must depress and then release each time
+#define PREAMP 479          // this is the system code identifying an Apple Remote
+
+
+
+/*******************************************************************************************/
 
 #define TRUE 1
 #define FALSE 0
@@ -45,8 +56,8 @@
 int toggle;                 // this is the 3rd bit position in the input stream and checks for
 // subsequent button depresses from the r/control
 int toggle1;                // temorary storage in the volume UP and volume DOWN functions
-int toggle2;                // temprary storage of the PB in the mute function
-int toggle3;                // temp storage for the r/control tone in-out function
+//int toggle2;                // temprary storage of the PB in the mute function
+//int toggle3;                // temp storage for the r/control tone in-out function
 int standby;
 int command = 0;
 int vendor_id = 0;
@@ -58,18 +69,18 @@
 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 FLAG5;                  // this is the recloop flag
 int RCFLAG = FALSE;         // used to determine if the select command came via R/C
 int REPEATFLAG;             // repaet command flag used for volume control
 int FLAGVOLUP;
 int FLAGVOLDWN;
-int FLAG7 = FALSE;          // thyis flag is set to TRUE if recloop is active
+//int FLAG7 = FALSE;          // this flag is set to TRUE if recloop is active
 int standbyflag;            // used to save the standby condition
 int RECLOOP1 = 16;          // this is the bus address 1 before the Recorder
-int RECLOOP2 = 32;          // this is the bus address for the Recorder input
+int RECLOOP2 = 32;          // this is the bus address for the Recorder input - last input
 // and is used in the recloop service routine
 int muteflag = FALSE;        // use to control mute and mute indicatoe independently
-int recloop_status = 32;    // this is the initial value. This variable is used
+int recloop_status = 0;    // this is the initial value. This variable is used
 // in the select_out routine to indicate when the
 // input select should wrap around dependent upon
 // whether the record loop has been activated.
@@ -87,7 +98,7 @@
 void rc5isr(void);          // RC5 ISR for remote control
 void mute_isr(void);
 void mute_sel(void);        //mutes select relays for a few ms during select
-void recloop_isr(void);
+//void recloop_isr(void);
 void standby_out(void);
 
 /****************************** volume increase ***********************************/
@@ -151,40 +162,40 @@
     if (standbyflag == TRUE) {      // was ON so now turn it OFF
         stby_pa = LOW;
         wait_ms(500); // make sure the power amp is OFF
-        muteind = LOW;
+//        muteind = LOW;
         wait_ms(1000);               // make sure the power amp output goes OFF
         muteout = LOW;              // now mute the preamp
         // turn off all interrupts except the standby and rc5int
         select_int.fall(NULL);
-        mute_int.fall(NULL);
-        recloop_int.fall(NULL);
-        recloop_out = LOW;          // make sure the recloop is OFF [its active HIGH]
-        recloop_status = RECLOOP2;  // reset the select so on subsequent power up it does
+//        mute_int.fall(NULL);
+//        recloop_int.fall(NULL);
+//        recloop_out = LOW;          // make sure the recloop is OFF [its active HIGH]
+//        recloop_status = RECLOOP2;  // reset the select so on subsequent power up it does
         //not skip recorder input
         select_save = select_drv;   // save the status of select_drv
         wait(.2);
         select_drv = 0;             // all input select relays are OFF
         wait(3);
         standbyflag = FALSE;
-        muteind = HIGH;
+//        muteind = HIGH;
     }
 
 
     else if (standbyflag == FALSE) {// was OFF so we will turn it ON
 
-        muteind = LOW;              // turn the mute indicator ON
+        muteLED = LOW;              // turn the mute indicator ON
         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);
+//        mute_int.fall(&mute_isr);
+//        recloop_int.fall(&recloop_isr);
 //        tone_pb.fall(tone_isr);
-        recloop_out = LOW;          // make sure the recloop is OFF [its active HIGH]
+//        recloop_out = LOW;          // make sure the recloop is OFF [its active HIGH]
         wait_ms(100);
         select_drv = select_save;   // recall the input select setting and write to output
         wait(2);                    // let things settle a bit
         muteout = HIGH;             // enable output
         muteflag = TRUE;
-        muteind = HIGH;             // turn the mute indicator OFF
+        muteLED = HIGH;             // turn the mute indicator OFF
         standbyflag = TRUE;
         stby_pa = HIGH;             // now power up the amplifier
     }
@@ -196,77 +207,92 @@
 
 /********************************** record loop isr *******************************/
 
-void recloop_isr(void)
-{
-    FLAG5 = TRUE;
-}
+//void recloop_isr(void)
+//{
+//    FLAG5 = TRUE;
+//}
 /********************************** recloop  ***********************************/
-void recloop()
-{
-
-    if (select_drv != RECLOOP2) {           // if its anything other than recloop we can activate the recloop relay
-        recloop_int.fall(NULL);             // to prevent re-entrance when coming here from the R/C
-        wait_ms(DEBOUNCE);                  // simple debounce for when mute is via the f/p p/b switch
-
-        do {
-            continue;                       // wait here until the button is released
-        } while (recloop_in != 1);
-
-        if (recloop_rly == HIGH) {          // the recloop relay was activated
-            recloop_rly = LOW;              // so turn it off
-            recloop_out = LOW;
-            FLAG7 = 0;
-        }
-
-        else if (recloop_rly == LOW) {      // it was OFF so activate it
-            recloop_rly = HIGH;
-            recloop_out = HIGH;
-            FLAG7 = 32;
-        }
-
-        wait_ms(DEBOUNCE);
-
-    }
-
-    recloop_int.fall(&recloop_isr);
-
-}
+//void recloop()
+//{
+//
+//    if (select_drv != RECLOOP2) {           // if its anything other than recloop we can activate the recloop relay
+//        recloop_int.fall(NULL);             // to prevent re-entrance when coming here from the R/C
+//        wait_ms(DEBOUNCE);                  // simple debounce for when mute is via the f/p p/b switch
+//
+//        do {
+//            continue;                       // wait here until the button is released
+//        } while (recloop_in != 1);
+//
+//        if (recloop_rly == HIGH) {          // the recloop relay was activated
+//            recloop_rly = LOW;              // so turn it off
+//            recloop_out = LOW;
+//            FLAG7 = 0;
+//        }
+//
+//        else if (recloop_rly == LOW) {      // it was OFF so activate it
+//            recloop_rly = HIGH;
+//            recloop_out = HIGH;
+//            FLAG7 = 32;
+//        }
+//
+//        wait_ms(DEBOUNCE);
+//
+//    }
+//
+//    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()
+//void mute_isr(void)
+//{
+//    FLAG3 = TRUE;
+//    toggle2 = !toggle2;         // so the p/button input is recognized in mute_out()
 
-}
+//}
 /************************************** mute  ************************************/
 void mute_out()
 {
-    mute_int.fall(NULL);        // to prevent re-entance when coming here from the R/C
-    wait_ms(DEBOUNCE);          //simple debounce for when mute is via the f/p p/b switch
-    do {
-        continue;               //wait here until the button is released
-    } while (mute != 1);
+    muteout = !muteout;
 
-    if (muteflag == FALSE) {    // mute was inactive so it will now get activated
-        muteout = TRUE;
-        muteind = HIGH;
-        muteflag = TRUE;        // indicate its been activated
+    if (muteout == HIGH) {
+        muteLED = LOW;
+    }
+
+    else if (muteout == LOW) {
+        muteLED = HIGH;
     }
 
-    else if (muteflag == TRUE) {   //it was active, so it must be deactivated here
-        muteout = FALSE;
-        muteind = LOW;
-        muteflag = FALSE;
-    }
-
-    wait_ms(800);               // make sure relay state is settled
-
-    mute_int.fall(&mute_isr);
+    wait_ms(100);
 }
 
+
+
+//    mute_int.fall(NULL);        // to prevent re-entance when coming here from the R/C
+//    wait_ms(DEBOUNCE);          //simple debounce for when mute is via the f/p p/b switch
+//    do {
+//        continue;               //wait here until the button is released
+//    } while (mute != 1);
+//
+//    if (muteflag == FALSE) {    // mute was inactive so it will now get activated
+//        muteout = TRUE;
+//        muteind = HIGH;
+//        muteflag = TRUE;        // indicate its been activated
+//    }
+//
+//    else if (muteflag == TRUE) {   //it was active, so it must be deactivated here
+//        muteout = FALSE;
+//        muteind = LOW;
+//        muteflag = FALSE;
+//    }
+//
+//    wait_ms(800);               // make sure relay state is settled
+//
+//    mute_int.fall(&mute_isr);
+//}
+//
 /************************************ rc5isr **************************************/
-/* Interrupt triggered by a rising edge on p21 which is R/C data in               */
+/* Interrupt triggered by a rising edge on p18 which is R/C data in               */
 
 void rc5isr(void)
 {
@@ -279,14 +305,14 @@
 /* This function reads the input data on pin rc5dat at 1120us ('tock')intervals   */
 /* and saves the data into an array stream[i].                                    */
 
-void save_stream(void)
-{
+void save_stream(void) {
+
     if (RCFLAG == TRUE) {
-        wait_us(13500); // this is the AGC header - ignore
-    }
+        wait_us(13500); // this is the IR AGC header - wait until passed
+   //}
 
-    bool stream[32];// the array is initialized each time it is used and is local only
-    int bitloop;    // number of bit positions
+    bool stream[63];// the array is initialized each time it is used and is local only
+    int bitloop = 0;    // number of bit positions - local
     int i = 0;      // counter
     int k = 0;      // temp storage
     vendor_id = 0;
@@ -296,20 +322,21 @@
     stop_bit = 0; //must always return a 1 to be valid, so reset it
     wait_us(tick);   // locate read point in middle of 1st half bit time of the 1st start bit
 
-    for (bitloop = 0; bitloop <32; bitloop ++) {
+    for (bitloop = 0; bitloop <64; bitloop ++) {
 
         stream[bitloop] = rc5dat;  //read the data and save it to array position [i]
-        //stby_pa = !stby_pa; // for debugging - monitor stby_pa on pin 25
+ //       bitstreamsync = !bitstreamsync; // the recovered IR bitstream is output on p14 for debug
         if (rc5dat == HIGH) {
-            wait_us(tock);
+            wait_us(tock); // wait for start of next bit time
         }
-
-        wait_us(tock); //wait here until ready to read the next bit in
-    }     // now have 31 bits loaded into stream[i]
+   
+    wait_us(tock); //wait here until ready to read the next bit in
+   
+   }     // now have 32 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<11; i++) {   // first 11 bit positions are vendor ID - always 043f for Apple; use for error checking later
+    for (i=0; i<11; i++) {   // first 11 bit positions are vendor ID
 
         k = stream[i];      // k will hold the vendor ID
         vendor_id = (vendor_id << 1);
@@ -334,13 +361,16 @@
         k = stream[i];
         command = (command << 1);
         command = command|k;
+        printf("\n here \r ");
     }
+    
     stop_bit = stream[31];
-   
 
     printf("\n vendor_id = %d pair_command = %d address = %d command = %d  stop_bit = %d \r", vendor_id, pair_command, address, command, stop_bit);
 }
 
+}
+
 /********************************* process_stream() *******************************/
 /* handles commands coming in from the remote controller only                     */
 
@@ -399,11 +429,11 @@
 
 /****************************** mute inter select*********************************/
 
-void mute_sel(void)
-{
-    select_drv = 0;
-    wait_ms(2);
-}
+//void mute_sel(void)
+//{
+//    select_drv = 0;
+//    wait_ms(2);
+//}
 
 /********************************* select_process *********************************/
 /* Used for selecting the input source.  This function is used by the             */
@@ -444,7 +474,7 @@
         }
     }
 
-    select_rot = (select_rot | FLAG7);
+//   select_rot = (select_rot | FLAG7);
     select_drv = select_rot;   // write the value out to the bus
 
     // printf("\n RCFLAG %d \r", RCFLAG);
@@ -475,9 +505,11 @@
 
     }
 
-    select_drv = (select_rot | FLAG7);   //write the selection out to the bus.
+    select_drv = select_rot;
 
-// printf("\n select_rot = %d     select_drv = %d\r", select_rot, select_drv);
+//    select_drv = (select_rot | FLAG7);   //write the selection out to the bus.
+
+    printf("\n select_rot = %d     \r", select_rot);
 
 }
 
@@ -486,53 +518,51 @@
 {
     Serial pc(USBTX, USBRX);
     __disable_irq();            // just to make sure we can set up correctly without problems
-    stby_pa = LOW;              // make sure the power aamp is OFF
     stby_pa = LOW;              // make sure the power amp is OFF via the trigger output
     muteout = LOW;              //make sure the outputis muted from the get go
-    muteind  = LOW;             //mute LED must be ON - power up preamble
-    select_drv = 0;
-    recloop_out = LOW;          // make sure the recloop LED is OFF [its active HIGH]
-    recloop_rly = LOW;          // make sure the recloop relay is OFF
+//    muteind  = HIGH;             //mute LED must be ON - power up preamble
+    select_drv = 0;             // no input relays must be on
+ //   bitstreamsync = LOW;        // this is the IR bitsteeam output on pin 14 for debug
+    //  recloop_out = LOW;          // make sure the recloop LED is OFF [its active HIGH]
+    //  recloop_rly = LOW;          // make sure the recloop relay is OFF
 
-    mute_int.mode(PullUp);      // set up all the pin states per Pindef1114.h
+//    mute_int.mode(PullUp);      // set up all the pin states per Pindef1114.h
     rc5dat.mode(PullUp);        // pin 17
     sela.mode(PullUp);          // pin 28
     selb.mode(PullUp);          // pin 27
     stdby.mode(PullUp);         // pin 26
-    recloop_in.mode(PullUp);    // pin 14
+    //  recloop_in.mode(PullUp);    // pin 14
 
     wait(.2);
     FLAG1 = FALSE;
     FLAG2 = FALSE;
-    FLAG5 = FALSE;              // this is the recloop flag
+//    FLAG5 = FALSE;              // this is the recloop flag
     FWD1=0;                     //make sure the volume control motor is OFF
     REV1=0;
 
     // set up the ISR's that will be used
-    rc5int.fall(&rc5isr);               // trigger int on rising edge - go service it at rc5dat
+    rc5int.fall(&rc5isr);               // trigger int on falling 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
+//    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 - on sel rotenc
 
     //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);
+//    mute_int.fall(NULL);
+//    recloop_int.fall(NULL);
 
     standbyflag = TRUE;                 // preamp will be set-up first time for OFF
     standby_out();                      // set system up
     standbyflag = FALSE;
-    select_save = 2;
+    select_save = 2;                    // CD always slected on initital power up
     select_rot = select_save;          // CD will be selected when power is first turned on
     wait(3);
-    muteind = HIGH;
+//    muteind = LOW;
     __enable_irq();
 
 // all ready and in standby from this point forward
 
-// note: if printf is used for debug, the record indicate LED will remain ON after printing
-// the first message
 
 LOOP:                                   // this is the main operating loop
 
@@ -560,10 +590,10 @@
         FLAG4 = FALSE;
     }
 
-    if (FLAG5 == TRUE) {
-        recloop();                      //recloop
-        FLAG5 = FALSE;
-    }
+//    if (FLAG5 == TRUE) {
+//        recloop();                      //recloop
+//        FLAG5 = FALSE;
+//    }
 
     //printf("\r Command = %d     Address = %d      \n",command, address);