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

Committer:
andrewcrussell
Date:
Tue Jul 26 16:24:40 2022 +0000
Revision:
3:f0cd7c22ca94
Parent:
2:674e2dd56e7d
Child:
4:d900d90588d0
Child:
5:9525755f7457
Apple Remote

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewcrussell 1:bb881a434906 1 /****************************** RC5 Decoder and Preamp Controller V1.0 *************************/
andrewcrussell 3:f0cd7c22ca94 2 /* Andrew C. Russell (c) 2015 */
andrewcrussell 0:83d4a20e7bc7 3 /* This RC5 decoder works by reading in the RC5 stream from one of the serial port lines */
andrewcrussell 0:83d4a20e7bc7 4 /* and saving the incoming stream into an array called stream, after which it is decoded and */
andrewcrussell 1:bb881a434906 5 /* the command executed. A Marantz RC-68PM IR R/C was used to develop this program - it */
andrewcrussell 0:83d4a20e7bc7 6 /* should work with any controller complying with the Philips RC5 standard. */
andrewcrussell 1:bb881a434906 7 /* See the rc5codes.h header for the codes used. */
andrewcrussell 0:83d4a20e7bc7 8
andrewcrussell 0:83d4a20e7bc7 9 /* The following audio preamplifier facilities are catered for:- */
andrewcrussell 0:83d4a20e7bc7 10 /* 1. Manual volume control adjustment via ALPS RK27 motorized potentiometer */
andrewcrussell 0:83d4a20e7bc7 11 /* 2. Input select via rotary encoder */
andrewcrussell 0:83d4a20e7bc7 12 /* 3. Output mute via push button actuation */
andrewcrussell 0:83d4a20e7bc7 13 /* 4. Record loop via push button actuation */
andrewcrussell 0:83d4a20e7bc7 14 /* 5. Power ON output to drive the /standby input of a system power supply */
andrewcrussell 0:83d4a20e7bc7 15 /* Facilities 1,2,3 and 5 are supported by an RC5 compliant remote control for preamplifiers */
andrewcrussell 3:f0cd7c22ca94 16 /* The controller pin definitions are set in Pindef1114.h file. */
andrewcrussell 3:f0cd7c22ca94 17
andrewcrussell 3:f0cd7c22ca94 18
andrewcrussell 3:f0cd7c22ca94 19 // UPDATE 26 July 2018: tone functionality removed. The associated pin (dp25) has been sequestrated
andrewcrussell 3:f0cd7c22ca94 20 // for the standby output to drive a power amplifier. Pin 8 on J2 (Controller board)
andrewcrussell 0:83d4a20e7bc7 21
andrewcrussell 0:83d4a20e7bc7 22 #include "mbed.h"
andrewcrussell 3:f0cd7c22ca94 23 #include "rc5codes.h" // RC code definitions - in this case for Apple TV Remote
andrewcrussell 0:83d4a20e7bc7 24 #include "Pindef1114.h" // all microcontroller I/O pin assignments defined here
andrewcrussell 0:83d4a20e7bc7 25
andrewcrussell 0:83d4a20e7bc7 26 #define TRUE 1
andrewcrussell 0:83d4a20e7bc7 27 #define FALSE 0
andrewcrussell 0:83d4a20e7bc7 28 #define HIGH 1
andrewcrussell 0:83d4a20e7bc7 29 #define LOW 0
andrewcrussell 3:f0cd7c22ca94 30 #define tick 280 // quarter bit time in us
andrewcrussell 3:f0cd7c22ca94 31 #define tock 1120 // one bit time in us
andrewcrussell 3:f0cd7c22ca94 32 #define VUP_timeout 45 // defines max number of R/C cycles before the vol ctrl mtr drive stops
andrewcrussell 3:f0cd7c22ca94 33 #define VDWN_timeout 45 // as above but for volume decrease
andrewcrussell 3:f0cd7c22ca94 34 // Needed to ensure the motor is not burnt out
andrewcrussell 3:f0cd7c22ca94 35 #define DEBOUNCE 20 // this is the switch debounce time
andrewcrussell 0:83d4a20e7bc7 36
andrewcrussell 3:f0cd7c22ca94 37 // PHONO_ 1 // these are the input assignments written out
andrewcrussell 3:f0cd7c22ca94 38 // CD 2 // on select_out - see thePindef1114.h file for details
andrewcrussell 3:f0cd7c22ca94 39 // TUN 4
andrewcrussell 3:f0cd7c22ca94 40 // MSERV 8
andrewcrussell 3:f0cd7c22ca94 41 // AUX 16
andrewcrussell 3:f0cd7c22ca94 42 // RECORDER 32
andrewcrussell 0:83d4a20e7bc7 43
andrewcrussell 0:83d4a20e7bc7 44 int startbit;
andrewcrussell 3:f0cd7c22ca94 45 int toggle; // this is the 3rd bit position in the input stream and checks for
andrewcrussell 3:f0cd7c22ca94 46 // subsequent button depresses from the r/control
andrewcrussell 2:674e2dd56e7d 47 int toggle1; // temorary storage in the volume UP and volume DOWN functions
andrewcrussell 2:674e2dd56e7d 48 int toggle2; // temprary storage of the PB in the mute function
andrewcrussell 3:f0cd7c22ca94 49 int toggle3; // temp storage for the r/control tone in-out function
andrewcrussell 0:83d4a20e7bc7 50 int standby;
andrewcrussell 3:f0cd7c22ca94 51 int command = 0;
andrewcrussell 3:f0cd7c22ca94 52 int vendor_id = 0;
andrewcrussell 3:f0cd7c22ca94 53 int pair_command = 0;
andrewcrussell 3:f0cd7c22ca94 54 int address = 0;
andrewcrussell 3:f0cd7c22ca94 55 int stop_bit = 0;
andrewcrussell 0:83d4a20e7bc7 56
andrewcrussell 0:83d4a20e7bc7 57 int FLAG1; // this is used in the remote control input processing
andrewcrussell 0:83d4a20e7bc7 58 int FLAG2; // this is used in the select input processing
andrewcrussell 0:83d4a20e7bc7 59 int FLAG3; // this is for the mute pushbutton
andrewcrussell 0:83d4a20e7bc7 60 int FLAG4; // this is for the standby pushbutton
andrewcrussell 0:83d4a20e7bc7 61 int FLAG5; // this is the recloop flag
andrewcrussell 0:83d4a20e7bc7 62 int RCFLAG = FALSE; // used to determine if the select command came via R/C
andrewcrussell 3:f0cd7c22ca94 63 int REPEATFLAG; // repaet command flag used for volume control
andrewcrussell 3:f0cd7c22ca94 64 int FLAGVOLUP;
andrewcrussell 3:f0cd7c22ca94 65 int FLAGVOLDWN;
andrewcrussell 3:f0cd7c22ca94 66 int FLAG7 = FALSE; // thyis flag is set to TRUE if recloop is active
andrewcrussell 0:83d4a20e7bc7 67 int standbyflag; // used to save the standby condition
andrewcrussell 3:f0cd7c22ca94 68 int RECLOOP1 = 16; // this is the bus address 1 before the Recorder
andrewcrussell 3:f0cd7c22ca94 69 int RECLOOP2 = 32; // this is the bus address for the Recorder input
andrewcrussell 3:f0cd7c22ca94 70 // and is used in the recloop service routine
andrewcrussell 3:f0cd7c22ca94 71 int muteflag = FALSE; // use to control mute and mute indicatoe independently
andrewcrussell 3:f0cd7c22ca94 72 int recloop_status = 32; // this is the initial value. This variable is used
andrewcrussell 3:f0cd7c22ca94 73 // in the select_out routine to indicate when the
andrewcrussell 3:f0cd7c22ca94 74 // input select should wrap around dependent upon
andrewcrussell 3:f0cd7c22ca94 75 // whether the record loop has been activated.
andrewcrussell 0:83d4a20e7bc7 76 int relay;
andrewcrussell 0:83d4a20e7bc7 77 int key_press = 1; // keeps track of key presses
andrewcrussell 0:83d4a20e7bc7 78
andrewcrussell 0:83d4a20e7bc7 79 // delcarations below are all for the input select proceses
andrewcrussell 0:83d4a20e7bc7 80 int select = 0;
andrewcrussell 3:f0cd7c22ca94 81 int select_save = 2; // we save the status of select drive here. Initial setting is for CD
andrewcrussell 3:f0cd7c22ca94 82 int select_rot; // rotary encoder pulse counter
andrewcrussell 2:674e2dd56e7d 83
andrewcrussell 0:83d4a20e7bc7 84 // declare function prototypes here
andrewcrussell 3:f0cd7c22ca94 85 void select_out (void); // writes selected input out to the select_drv bus
andrewcrussell 3:f0cd7c22ca94 86 void select_isr(void);
andrewcrussell 3:f0cd7c22ca94 87 void rc5isr(void); // RC5 ISR for remote control
andrewcrussell 0:83d4a20e7bc7 88 void mute_isr(void);
andrewcrussell 3:f0cd7c22ca94 89 void mute_sel(void); //mutes select relays for a few ms during select
andrewcrussell 0:83d4a20e7bc7 90 void recloop_isr(void);
andrewcrussell 0:83d4a20e7bc7 91 void standby_out(void);
andrewcrussell 0:83d4a20e7bc7 92
andrewcrussell 0:83d4a20e7bc7 93 /****************************** volume increase ***********************************/
andrewcrussell 0:83d4a20e7bc7 94 void vol_up (void)
andrewcrussell 0:83d4a20e7bc7 95 {
andrewcrussell 0:83d4a20e7bc7 96 if ((standbyflag == TRUE) && (key_press < VUP_timeout)) {
andrewcrussell 0:83d4a20e7bc7 97
andrewcrussell 0:83d4a20e7bc7 98 FWD1 = HIGH;
andrewcrussell 0:83d4a20e7bc7 99 wait(.1); //drive the motors for a short while
andrewcrussell 0:83d4a20e7bc7 100 FWD1 = LOW;
andrewcrussell 3:f0cd7c22ca94 101
andrewcrussell 3:f0cd7c22ca94 102 }
andrewcrussell 3:f0cd7c22ca94 103 if (toggle1 != toggle) {
andrewcrussell 3:f0cd7c22ca94 104 key_press = 0; // user released the button, so reset counter
andrewcrussell 3:f0cd7c22ca94 105 } else if (toggle1 == toggle) {
andrewcrussell 3:f0cd7c22ca94 106 key_press++; // button remained depressed, so increment counter
andrewcrussell 3:f0cd7c22ca94 107 }
andrewcrussell 3:f0cd7c22ca94 108 toggle1 = toggle;
andrewcrussell 3:f0cd7c22ca94 109 // wait_ms(1);
andrewcrussell 3:f0cd7c22ca94 110 }
andrewcrussell 3:f0cd7c22ca94 111
andrewcrussell 3:f0cd7c22ca94 112 /******************************* volume decrease **********************************/
andrewcrussell 3:f0cd7c22ca94 113 void vol_dwn (void)
andrewcrussell 3:f0cd7c22ca94 114 {
andrewcrussell 3:f0cd7c22ca94 115 if ((standbyflag == TRUE) && (key_press < VDWN_timeout)) {
andrewcrussell 3:f0cd7c22ca94 116
andrewcrussell 3:f0cd7c22ca94 117 REV1 = HIGH;
andrewcrussell 3:f0cd7c22ca94 118 wait(.1); //drive the motors for a short while
andrewcrussell 3:f0cd7c22ca94 119 REV1 = LOW;
andrewcrussell 0:83d4a20e7bc7 120 }
andrewcrussell 0:83d4a20e7bc7 121 if (toggle1 != toggle) {
andrewcrussell 0:83d4a20e7bc7 122 key_press = 0; // user released the button, so reset counter
andrewcrussell 0:83d4a20e7bc7 123 } else if (toggle1 == toggle) {
andrewcrussell 0:83d4a20e7bc7 124 key_press++; // button remained depressed, so increment counter
andrewcrussell 0:83d4a20e7bc7 125 }
andrewcrussell 0:83d4a20e7bc7 126 toggle1 = toggle;
andrewcrussell 0:83d4a20e7bc7 127 wait_ms(1);
andrewcrussell 0:83d4a20e7bc7 128 }
andrewcrussell 0:83d4a20e7bc7 129
andrewcrussell 0:83d4a20e7bc7 130 /********************************** stdby_isr *************************************/
andrewcrussell 2:674e2dd56e7d 131 void stdby_isr(void)
andrewcrussell 0:83d4a20e7bc7 132 {
andrewcrussell 0:83d4a20e7bc7 133 FLAG4 = TRUE;
andrewcrussell 0:83d4a20e7bc7 134 }
andrewcrussell 0:83d4a20e7bc7 135
andrewcrussell 0:83d4a20e7bc7 136 /*********************************** standby **************************************/
andrewcrussell 0:83d4a20e7bc7 137 /* this will require supporting hardware functionality to power down the */
andrewcrussell 0:83d4a20e7bc7 138 /* analog board, LED's etc. Best option here is to use regulators with a */
andrewcrussell 3:f0cd7c22ca94 139 /* shutdown option. for now, all the LED's are just turned off */
andrewcrussell 3:f0cd7c22ca94 140 /* and input relays and mute relayes disabled. */
andrewcrussell 0:83d4a20e7bc7 141
andrewcrussell 0:83d4a20e7bc7 142 void standby_out(void) // both p/button and R/C come in here
andrewcrussell 0:83d4a20e7bc7 143 {
andrewcrussell 3:f0cd7c22ca94 144 __disable_irq();
andrewcrussell 3:f0cd7c22ca94 145 stdby_int.fall(NULL); // on first power up cycle NO interrupts are accepted
andrewcrussell 3:f0cd7c22ca94 146 wait_ms(DEBOUNCE); // a very simple debounce
andrewcrussell 0:83d4a20e7bc7 147 do { // that waits for the depressed button to be released
andrewcrussell 3:f0cd7c22ca94 148 continue; //(1);
andrewcrussell 3:f0cd7c22ca94 149 } while (stdby != 1);
andrewcrussell 0:83d4a20e7bc7 150
andrewcrussell 3:f0cd7c22ca94 151 if (standbyflag == TRUE) { // was ON so now turn it OFF
andrewcrussell 3:f0cd7c22ca94 152 stby_pa = LOW;
andrewcrussell 3:f0cd7c22ca94 153 wait_ms(500); // make sure the power amp is OFF
andrewcrussell 3:f0cd7c22ca94 154 muteind = LOW;
andrewcrussell 3:f0cd7c22ca94 155 wait_ms(1000); // make sure the power amp output goes OFF
andrewcrussell 3:f0cd7c22ca94 156 muteout = LOW; // now mute the preamp
andrewcrussell 0:83d4a20e7bc7 157 // turn off all interrupts except the standby and rc5int
andrewcrussell 0:83d4a20e7bc7 158 select_int.fall(NULL);
andrewcrussell 0:83d4a20e7bc7 159 mute_int.fall(NULL);
andrewcrussell 0:83d4a20e7bc7 160 recloop_int.fall(NULL);
andrewcrussell 3:f0cd7c22ca94 161 recloop_out = LOW; // make sure the recloop is OFF [its active HIGH]
andrewcrussell 3:f0cd7c22ca94 162 recloop_status = RECLOOP2; // reset the select so on subsequent power up it does
andrewcrussell 3:f0cd7c22ca94 163 //not skip recorder input
andrewcrussell 3:f0cd7c22ca94 164 select_save = select_drv; // save the status of select_drv
andrewcrussell 3:f0cd7c22ca94 165 wait(.2);
andrewcrussell 3:f0cd7c22ca94 166 select_drv = 0; // all input select relays are OFF
andrewcrussell 3:f0cd7c22ca94 167 wait(3);
andrewcrussell 3:f0cd7c22ca94 168 standbyflag = FALSE;
andrewcrussell 2:674e2dd56e7d 169 muteind = HIGH;
andrewcrussell 3:f0cd7c22ca94 170 }
andrewcrussell 0:83d4a20e7bc7 171
andrewcrussell 2:674e2dd56e7d 172
andrewcrussell 3:f0cd7c22ca94 173 else if (standbyflag == FALSE) {// was OFF so we will turn it ON
andrewcrussell 2:674e2dd56e7d 174
andrewcrussell 3:f0cd7c22ca94 175 muteind = LOW; // turn the mute indicator ON
andrewcrussell 3:f0cd7c22ca94 176 rc5int.rise(&rc5isr); // trigger int on rising edge - go service it at rc5dat
andrewcrussell 0:83d4a20e7bc7 177 select_int.fall(&select_isr); // input from rotary encoder or input select
andrewcrussell 0:83d4a20e7bc7 178 mute_int.fall(&mute_isr);
andrewcrussell 0:83d4a20e7bc7 179 recloop_int.fall(&recloop_isr);
andrewcrussell 3:f0cd7c22ca94 180 // tone_pb.fall(tone_isr);
andrewcrussell 3:f0cd7c22ca94 181 recloop_out = LOW; // make sure the recloop is OFF [its active HIGH]
andrewcrussell 3:f0cd7c22ca94 182 wait_ms(100);
andrewcrussell 3:f0cd7c22ca94 183 select_drv = select_save; // recall the input select setting and write to output
andrewcrussell 3:f0cd7c22ca94 184 wait(2); // let things settle a bit
andrewcrussell 3:f0cd7c22ca94 185 muteout = HIGH; // enable output
andrewcrussell 3:f0cd7c22ca94 186 muteflag = TRUE;
andrewcrussell 3:f0cd7c22ca94 187 muteind = HIGH; // turn the mute indicator OFF
andrewcrussell 0:83d4a20e7bc7 188 standbyflag = TRUE;
andrewcrussell 3:f0cd7c22ca94 189 stby_pa = HIGH; // now power up the amplifier
andrewcrussell 0:83d4a20e7bc7 190 }
andrewcrussell 3:f0cd7c22ca94 191 wait_ms(500); // let things settle a bit
andrewcrussell 3:f0cd7c22ca94 192 __enable_irq();
andrewcrussell 3:f0cd7c22ca94 193 stdby_int.fall(&stdby_isr); // re-enable the standby interrupt
andrewcrussell 3:f0cd7c22ca94 194
andrewcrussell 0:83d4a20e7bc7 195 }
andrewcrussell 0:83d4a20e7bc7 196
andrewcrussell 0:83d4a20e7bc7 197 /********************************** record loop isr *******************************/
andrewcrussell 0:83d4a20e7bc7 198
andrewcrussell 0:83d4a20e7bc7 199 void recloop_isr(void)
andrewcrussell 0:83d4a20e7bc7 200 {
andrewcrussell 0:83d4a20e7bc7 201 FLAG5 = TRUE;
andrewcrussell 0:83d4a20e7bc7 202 }
andrewcrussell 3:f0cd7c22ca94 203 /********************************** recloop ***********************************/
andrewcrussell 0:83d4a20e7bc7 204 void recloop()
andrewcrussell 0:83d4a20e7bc7 205 {
andrewcrussell 3:f0cd7c22ca94 206
andrewcrussell 3:f0cd7c22ca94 207 if (select_drv != RECLOOP2) { // if its anything other than recloop we can activate the recloop relay
andrewcrussell 3:f0cd7c22ca94 208 recloop_int.fall(NULL); // to prevent re-entrance when coming here from the R/C
andrewcrussell 3:f0cd7c22ca94 209 wait_ms(DEBOUNCE); // simple debounce for when mute is via the f/p p/b switch
andrewcrussell 3:f0cd7c22ca94 210
andrewcrussell 3:f0cd7c22ca94 211 do {
andrewcrussell 3:f0cd7c22ca94 212 continue; // wait here until the button is released
andrewcrussell 3:f0cd7c22ca94 213 } while (recloop_in != 1);
andrewcrussell 3:f0cd7c22ca94 214
andrewcrussell 3:f0cd7c22ca94 215 if (recloop_rly == HIGH) { // the recloop relay was activated
andrewcrussell 3:f0cd7c22ca94 216 recloop_rly = LOW; // so turn it off
andrewcrussell 3:f0cd7c22ca94 217 recloop_out = LOW;
andrewcrussell 3:f0cd7c22ca94 218 FLAG7 = 0;
andrewcrussell 3:f0cd7c22ca94 219 }
andrewcrussell 3:f0cd7c22ca94 220
andrewcrussell 3:f0cd7c22ca94 221 else if (recloop_rly == LOW) { // it was OFF so activate it
andrewcrussell 3:f0cd7c22ca94 222 recloop_rly = HIGH;
andrewcrussell 3:f0cd7c22ca94 223 recloop_out = HIGH;
andrewcrussell 3:f0cd7c22ca94 224 FLAG7 = 32;
andrewcrussell 3:f0cd7c22ca94 225 }
andrewcrussell 3:f0cd7c22ca94 226
andrewcrussell 3:f0cd7c22ca94 227 wait_ms(DEBOUNCE);
andrewcrussell 3:f0cd7c22ca94 228
andrewcrussell 3:f0cd7c22ca94 229 }
andrewcrussell 3:f0cd7c22ca94 230
andrewcrussell 0:83d4a20e7bc7 231 recloop_int.fall(&recloop_isr);
andrewcrussell 3:f0cd7c22ca94 232
andrewcrussell 0:83d4a20e7bc7 233 }
andrewcrussell 0:83d4a20e7bc7 234 /************************************ mute_isr ************************************/
andrewcrussell 0:83d4a20e7bc7 235
andrewcrussell 0:83d4a20e7bc7 236 void mute_isr(void)
andrewcrussell 0:83d4a20e7bc7 237 {
andrewcrussell 0:83d4a20e7bc7 238 FLAG3 = TRUE;
andrewcrussell 3:f0cd7c22ca94 239 toggle2 = !toggle2; // so the p/button input is recognized in mute_out()
andrewcrussell 3:f0cd7c22ca94 240
andrewcrussell 0:83d4a20e7bc7 241 }
andrewcrussell 3:f0cd7c22ca94 242 /************************************** mute ************************************/
andrewcrussell 0:83d4a20e7bc7 243 void mute_out()
andrewcrussell 0:83d4a20e7bc7 244 {
andrewcrussell 3:f0cd7c22ca94 245 mute_int.fall(NULL); // to prevent re-entance when coming here from the R/C
andrewcrussell 3:f0cd7c22ca94 246 wait_ms(DEBOUNCE); //simple debounce for when mute is via the f/p p/b switch
andrewcrussell 3:f0cd7c22ca94 247 do {
andrewcrussell 3:f0cd7c22ca94 248 continue; //wait here until the button is released
andrewcrussell 3:f0cd7c22ca94 249 } while (mute != 1);
andrewcrussell 0:83d4a20e7bc7 250
andrewcrussell 3:f0cd7c22ca94 251 if (muteflag == FALSE) { // mute was inactive so it will now get activated
andrewcrussell 3:f0cd7c22ca94 252 muteout = TRUE;
andrewcrussell 3:f0cd7c22ca94 253 muteind = HIGH;
andrewcrussell 3:f0cd7c22ca94 254 muteflag = TRUE; // indicate its been activated
andrewcrussell 0:83d4a20e7bc7 255 }
andrewcrussell 3:f0cd7c22ca94 256
andrewcrussell 3:f0cd7c22ca94 257 else if (muteflag == TRUE) { //it was active, so it must be deactivated here
andrewcrussell 3:f0cd7c22ca94 258 muteout = FALSE;
andrewcrussell 3:f0cd7c22ca94 259 muteind = LOW;
andrewcrussell 3:f0cd7c22ca94 260 muteflag = FALSE;
andrewcrussell 3:f0cd7c22ca94 261 }
andrewcrussell 3:f0cd7c22ca94 262
andrewcrussell 3:f0cd7c22ca94 263 wait_ms(800); // make sure relay state is settled
andrewcrussell 3:f0cd7c22ca94 264
andrewcrussell 0:83d4a20e7bc7 265 mute_int.fall(&mute_isr);
andrewcrussell 0:83d4a20e7bc7 266 }
andrewcrussell 0:83d4a20e7bc7 267
andrewcrussell 0:83d4a20e7bc7 268 /************************************ rc5isr **************************************/
andrewcrussell 3:f0cd7c22ca94 269 /* Interrupt triggered by a rising edge on p21 which is R/C data in */
andrewcrussell 0:83d4a20e7bc7 270
andrewcrussell 0:83d4a20e7bc7 271 void rc5isr(void)
andrewcrussell 0:83d4a20e7bc7 272 {
andrewcrussell 0:83d4a20e7bc7 273 FLAG1 = TRUE;
andrewcrussell 3:f0cd7c22ca94 274 RCFLAG = TRUE;
andrewcrussell 3:f0cd7c22ca94 275 REPEATFLAG = TRUE;
andrewcrussell 0:83d4a20e7bc7 276 }
andrewcrussell 3:f0cd7c22ca94 277
andrewcrussell 3:f0cd7c22ca94 278 /******************* save bit stream from remote controller ***********************/
andrewcrussell 3:f0cd7c22ca94 279 /* This function reads the input data on pin rc5dat at 1120us ('tock')intervals */
andrewcrussell 0:83d4a20e7bc7 280 /* and saves the data into an array stream[i]. */
andrewcrussell 0:83d4a20e7bc7 281
andrewcrussell 0:83d4a20e7bc7 282 void save_stream(void)
andrewcrussell 0:83d4a20e7bc7 283 {
andrewcrussell 3:f0cd7c22ca94 284 if (RCFLAG == TRUE) {
andrewcrussell 3:f0cd7c22ca94 285 wait_us(13500); // this is the AGC header - ignore
andrewcrussell 3:f0cd7c22ca94 286 }
andrewcrussell 3:f0cd7c22ca94 287
andrewcrussell 3:f0cd7c22ca94 288 bool stream[32];// the array is initialized each time it is used and is local only
andrewcrussell 0:83d4a20e7bc7 289 int bitloop; // number of bit positions
andrewcrussell 0:83d4a20e7bc7 290 int i = 0; // counter
andrewcrussell 0:83d4a20e7bc7 291 int k = 0; // temp storage
andrewcrussell 3:f0cd7c22ca94 292 vendor_id = 0;
andrewcrussell 3:f0cd7c22ca94 293 pair_command = 0;
andrewcrussell 0:83d4a20e7bc7 294 address = 0;
andrewcrussell 0:83d4a20e7bc7 295 command = 0;
andrewcrussell 3:f0cd7c22ca94 296 stop_bit = 0; //must always return a 1 to be valid, so reset it
andrewcrussell 3:f0cd7c22ca94 297 wait_us(tick); // locate read point in middle of 1st half bit time of the 1st start bit
andrewcrussell 3:f0cd7c22ca94 298
andrewcrussell 3:f0cd7c22ca94 299 for (bitloop = 0; bitloop <32; bitloop ++) {
andrewcrussell 3:f0cd7c22ca94 300
andrewcrussell 0:83d4a20e7bc7 301 stream[bitloop] = rc5dat; //read the data and save it to array position [i]
andrewcrussell 3:f0cd7c22ca94 302 //stby_pa = !stby_pa; // for debugging - monitor stby_pa on pin 25
andrewcrussell 3:f0cd7c22ca94 303 if (rc5dat == HIGH) {
andrewcrussell 3:f0cd7c22ca94 304 wait_us(tock);
andrewcrussell 3:f0cd7c22ca94 305 }
andrewcrussell 3:f0cd7c22ca94 306
andrewcrussell 0:83d4a20e7bc7 307 wait_us(tock); //wait here until ready to read the next bit in
andrewcrussell 3:f0cd7c22ca94 308 } // now have 31 bits loaded into stream[i]
andrewcrussell 3:f0cd7c22ca94 309
andrewcrussell 0:83d4a20e7bc7 310 /* now put data in the array into the start, toggle, address and command variables - array counts from stream[0] */
andrewcrussell 0:83d4a20e7bc7 311
andrewcrussell 3:f0cd7c22ca94 312 for (i=0; i<11; i++) { // first 11 bit positions are vendor ID - always 043f for Apple; use for error checking later
andrewcrussell 3:f0cd7c22ca94 313
andrewcrussell 3:f0cd7c22ca94 314 k = stream[i]; // k will hold the vendor ID
andrewcrussell 3:f0cd7c22ca94 315 vendor_id = (vendor_id << 1);
andrewcrussell 3:f0cd7c22ca94 316 vendor_id = vendor_id|k;
andrewcrussell 3:f0cd7c22ca94 317
andrewcrussell 0:83d4a20e7bc7 318 }
andrewcrussell 0:83d4a20e7bc7 319
andrewcrussell 3:f0cd7c22ca94 320 for (i = 11; i <16; i++) { // command or pair
andrewcrussell 3:f0cd7c22ca94 321 k = stream[i];
andrewcrussell 3:f0cd7c22ca94 322 pair_command = (pair_command << 1);
andrewcrussell 3:f0cd7c22ca94 323 pair_command = pair_command|k;
andrewcrussell 3:f0cd7c22ca94 324 }
andrewcrussell 0:83d4a20e7bc7 325
andrewcrussell 3:f0cd7c22ca94 326 for (i = 16; i <25; i++) { // device pairing address
andrewcrussell 0:83d4a20e7bc7 327 k = stream[i];
andrewcrussell 0:83d4a20e7bc7 328 address = (address << 1);
andrewcrussell 0:83d4a20e7bc7 329 address = address|k;
andrewcrussell 0:83d4a20e7bc7 330 }
andrewcrussell 0:83d4a20e7bc7 331
andrewcrussell 3:f0cd7c22ca94 332
andrewcrussell 3:f0cd7c22ca94 333 for (i = 25; i <31; i++) { // bit positions 25 to 30 are the command - 7 bit positions
andrewcrussell 0:83d4a20e7bc7 334 k = stream[i];
andrewcrussell 0:83d4a20e7bc7 335 command = (command << 1);
andrewcrussell 0:83d4a20e7bc7 336 command = command|k;
andrewcrussell 0:83d4a20e7bc7 337 }
andrewcrussell 3:f0cd7c22ca94 338 stop_bit = stream[31];
andrewcrussell 3:f0cd7c22ca94 339
andrewcrussell 0:83d4a20e7bc7 340
andrewcrussell 3:f0cd7c22ca94 341 printf("\n vendor_id = %d pair_command = %d address = %d command = %d stop_bit = %d \r", vendor_id, pair_command, address, command, stop_bit);
andrewcrussell 0:83d4a20e7bc7 342 }
andrewcrussell 3:f0cd7c22ca94 343
andrewcrussell 0:83d4a20e7bc7 344 /********************************* process_stream() *******************************/
andrewcrussell 0:83d4a20e7bc7 345 /* handles commands coming in from the remote controller only */
andrewcrussell 0:83d4a20e7bc7 346
andrewcrussell 0:83d4a20e7bc7 347 void process_stream (void)
andrewcrussell 0:83d4a20e7bc7 348 {
andrewcrussell 3:f0cd7c22ca94 349 if ((RCFLAG == TRUE) && ((vendor_id == 479) || (vendor_id == 2047))) {
andrewcrussell 0:83d4a20e7bc7 350 // basic error checking - must be preamp + startbit ok to get executed otherwise skip completly
andrewcrussell 3:f0cd7c22ca94 351 switch (address) {
andrewcrussell 0:83d4a20e7bc7 352
andrewcrussell 0:83d4a20e7bc7 353 case VUP:
andrewcrussell 0:83d4a20e7bc7 354 vol_up();
andrewcrussell 3:f0cd7c22ca94 355 FLAGVOLUP = TRUE;
andrewcrussell 0:83d4a20e7bc7 356 break;
andrewcrussell 0:83d4a20e7bc7 357
andrewcrussell 0:83d4a20e7bc7 358 case VDOWN:
andrewcrussell 0:83d4a20e7bc7 359 vol_dwn();
andrewcrussell 3:f0cd7c22ca94 360 FLAGVOLDWN = TRUE;
andrewcrussell 0:83d4a20e7bc7 361 break;
andrewcrussell 0:83d4a20e7bc7 362
andrewcrussell 0:83d4a20e7bc7 363 case MUTE:
andrewcrussell 0:83d4a20e7bc7 364 mute_out();
andrewcrussell 0:83d4a20e7bc7 365 break;
andrewcrussell 0:83d4a20e7bc7 366
andrewcrussell 0:83d4a20e7bc7 367 case SELECT_R:
andrewcrussell 0:83d4a20e7bc7 368 select_out();
andrewcrussell 0:83d4a20e7bc7 369 break;
andrewcrussell 0:83d4a20e7bc7 370
andrewcrussell 3:f0cd7c22ca94 371 case SELECT_L:
andrewcrussell 3:f0cd7c22ca94 372 select_out();
andrewcrussell 3:f0cd7c22ca94 373 break;
andrewcrussell 3:f0cd7c22ca94 374
andrewcrussell 0:83d4a20e7bc7 375 case STANDBY:
andrewcrussell 0:83d4a20e7bc7 376 standby_out();
andrewcrussell 0:83d4a20e7bc7 377 break;
andrewcrussell 3:f0cd7c22ca94 378
andrewcrussell 0:83d4a20e7bc7 379 }
andrewcrussell 3:f0cd7c22ca94 380
andrewcrussell 3:f0cd7c22ca94 381 if ((FLAGVOLUP == TRUE) && (vendor_id == 2047)) {
andrewcrussell 3:f0cd7c22ca94 382 vol_up();
andrewcrussell 3:f0cd7c22ca94 383 }
andrewcrussell 3:f0cd7c22ca94 384
andrewcrussell 3:f0cd7c22ca94 385 if ((FLAGVOLDWN == TRUE) && (vendor_id ==2047)) {
andrewcrussell 3:f0cd7c22ca94 386 vol_dwn();
andrewcrussell 3:f0cd7c22ca94 387 }
andrewcrussell 3:f0cd7c22ca94 388
andrewcrussell 0:83d4a20e7bc7 389 }
andrewcrussell 3:f0cd7c22ca94 390 RCFLAG = FALSE;
andrewcrussell 3:f0cd7c22ca94 391
andrewcrussell 0:83d4a20e7bc7 392 }
andrewcrussell 0:83d4a20e7bc7 393 /*********************************** select_isr ***********************************/
andrewcrussell 0:83d4a20e7bc7 394
andrewcrussell 0:83d4a20e7bc7 395 void select_isr(void)
andrewcrussell 0:83d4a20e7bc7 396 {
andrewcrussell 0:83d4a20e7bc7 397 FLAG2 = TRUE;
andrewcrussell 0:83d4a20e7bc7 398 }
andrewcrussell 0:83d4a20e7bc7 399
andrewcrussell 3:f0cd7c22ca94 400 /****************************** mute inter select*********************************/
andrewcrussell 3:f0cd7c22ca94 401
andrewcrussell 3:f0cd7c22ca94 402 void mute_sel(void)
andrewcrussell 3:f0cd7c22ca94 403 {
andrewcrussell 3:f0cd7c22ca94 404 select_drv = 0;
andrewcrussell 3:f0cd7c22ca94 405 wait_ms(2);
andrewcrussell 3:f0cd7c22ca94 406 }
andrewcrussell 3:f0cd7c22ca94 407
andrewcrussell 0:83d4a20e7bc7 408 /********************************* select_process *********************************/
andrewcrussell 3:f0cd7c22ca94 409 /* Used for selecting the input source. This function is used by the */
andrewcrussell 3:f0cd7c22ca94 410 /* rotary encoder only */
andrewcrussell 0:83d4a20e7bc7 411
andrewcrussell 0:83d4a20e7bc7 412 void select_process(void)
andrewcrussell 0:83d4a20e7bc7 413 {
andrewcrussell 3:f0cd7c22ca94 414
andrewcrussell 3:f0cd7c22ca94 415 if (RCFLAG == FALSE) { // if used R/C skip completely - extra safety check
andrewcrussell 3:f0cd7c22ca94 416 wait_ms(5); // debounce - very short for the rotary encoder
andrewcrussell 0:83d4a20e7bc7 417 select = 0; // flush select
andrewcrussell 0:83d4a20e7bc7 418
andrewcrussell 0:83d4a20e7bc7 419 select = (select | sela) <<1; // read the two port lines associated with the select rotary encoder
andrewcrussell 0:83d4a20e7bc7 420 select = (select | selb);
andrewcrussell 3:f0cd7c22ca94 421
andrewcrussell 3:f0cd7c22ca94 422
andrewcrussell 3:f0cd7c22ca94 423 switch (select) {
andrewcrussell 3:f0cd7c22ca94 424 case 1: // select encoder is being rotated CW so increment select_rot
andrewcrussell 3:f0cd7c22ca94 425 select_rot <<= 1;
andrewcrussell 3:f0cd7c22ca94 426 if (select_rot > recloop_status ) {
andrewcrussell 3:f0cd7c22ca94 427 select_rot = 1; // wrap around to 1
andrewcrussell 3:f0cd7c22ca94 428 }
andrewcrussell 3:f0cd7c22ca94 429
andrewcrussell 3:f0cd7c22ca94 430 break;
andrewcrussell 3:f0cd7c22ca94 431
andrewcrussell 3:f0cd7c22ca94 432 case 0:
andrewcrussell 3:f0cd7c22ca94 433 select_rot >>= 1; // encoder is being rotated CCW so decrement select_rot
andrewcrussell 3:f0cd7c22ca94 434 if (select_rot < 1) {
andrewcrussell 3:f0cd7c22ca94 435 select_rot = recloop_status; //wrap around to 32
andrewcrussell 3:f0cd7c22ca94 436 }
andrewcrussell 3:f0cd7c22ca94 437
andrewcrussell 3:f0cd7c22ca94 438 break;
andrewcrussell 3:f0cd7c22ca94 439
andrewcrussell 3:f0cd7c22ca94 440 case 2:
andrewcrussell 3:f0cd7c22ca94 441 break; // indeterminate fall through values - ignore
andrewcrussell 3:f0cd7c22ca94 442 case 3:
andrewcrussell 3:f0cd7c22ca94 443 break; // and do not change the output
andrewcrussell 3:f0cd7c22ca94 444 }
andrewcrussell 0:83d4a20e7bc7 445 }
andrewcrussell 0:83d4a20e7bc7 446
andrewcrussell 3:f0cd7c22ca94 447 select_rot = (select_rot | FLAG7);
andrewcrussell 3:f0cd7c22ca94 448 select_drv = select_rot; // write the value out to the bus
andrewcrussell 0:83d4a20e7bc7 449
andrewcrussell 3:f0cd7c22ca94 450 // printf("\n RCFLAG %d \r", RCFLAG);
andrewcrussell 0:83d4a20e7bc7 451 }
andrewcrussell 0:83d4a20e7bc7 452
andrewcrussell 0:83d4a20e7bc7 453
andrewcrussell 3:f0cd7c22ca94 454
andrewcrussell 3:f0cd7c22ca94 455
andrewcrussell 3:f0cd7c22ca94 456 /********************************* select_out *********************************/
andrewcrussell 3:f0cd7c22ca94 457 // this is only used by the IR remote
andrewcrussell 3:f0cd7c22ca94 458
andrewcrussell 0:83d4a20e7bc7 459 void select_out (void)
andrewcrussell 0:83d4a20e7bc7 460 {
andrewcrussell 3:f0cd7c22ca94 461
andrewcrussell 3:f0cd7c22ca94 462 if (address == SELECT_L) {
andrewcrussell 3:f0cd7c22ca94 463 select_rot >>= 1;
andrewcrussell 3:f0cd7c22ca94 464 if (select_rot <1) {
andrewcrussell 3:f0cd7c22ca94 465 select_rot = 32;
andrewcrussell 3:f0cd7c22ca94 466 }
andrewcrussell 0:83d4a20e7bc7 467 }
andrewcrussell 3:f0cd7c22ca94 468
andrewcrussell 3:f0cd7c22ca94 469
andrewcrussell 3:f0cd7c22ca94 470 if (address == SELECT_R) {
andrewcrussell 3:f0cd7c22ca94 471 select_rot <<= 1;
andrewcrussell 3:f0cd7c22ca94 472 if (select_rot >32) {
andrewcrussell 3:f0cd7c22ca94 473 select_rot = 1;
andrewcrussell 3:f0cd7c22ca94 474 }
andrewcrussell 3:f0cd7c22ca94 475
andrewcrussell 3:f0cd7c22ca94 476 }
andrewcrussell 3:f0cd7c22ca94 477
andrewcrussell 3:f0cd7c22ca94 478 select_drv = (select_rot | FLAG7); //write the selection out to the bus.
andrewcrussell 3:f0cd7c22ca94 479
andrewcrussell 3:f0cd7c22ca94 480 // printf("\n select_rot = %d select_drv = %d\r", select_rot, select_drv);
andrewcrussell 3:f0cd7c22ca94 481
andrewcrussell 0:83d4a20e7bc7 482 }
andrewcrussell 3:f0cd7c22ca94 483
andrewcrussell 0:83d4a20e7bc7 484 /************************************ main() ***************************************/
andrewcrussell 0:83d4a20e7bc7 485 int main(void)
andrewcrussell 0:83d4a20e7bc7 486 {
andrewcrussell 3:f0cd7c22ca94 487 Serial pc(USBTX, USBRX);
andrewcrussell 3:f0cd7c22ca94 488 __disable_irq(); // just to make sure we can set up correctly without problems
andrewcrussell 3:f0cd7c22ca94 489 stby_pa = LOW; // make sure the power aamp is OFF
andrewcrussell 3:f0cd7c22ca94 490 stby_pa = LOW; // make sure the power amp is OFF via the trigger output
andrewcrussell 3:f0cd7c22ca94 491 muteout = LOW; //make sure the outputis muted from the get go
andrewcrussell 3:f0cd7c22ca94 492 muteind = LOW; //mute LED must be ON - power up preamble
andrewcrussell 3:f0cd7c22ca94 493 select_drv = 0;
andrewcrussell 3:f0cd7c22ca94 494 recloop_out = LOW; // make sure the recloop LED is OFF [its active HIGH]
andrewcrussell 3:f0cd7c22ca94 495 recloop_rly = LOW; // make sure the recloop relay is OFF
andrewcrussell 3:f0cd7c22ca94 496
andrewcrussell 3:f0cd7c22ca94 497 mute_int.mode(PullUp); // set up all the pin states per Pindef1114.h
andrewcrussell 3:f0cd7c22ca94 498 rc5dat.mode(PullUp); // pin 17
andrewcrussell 3:f0cd7c22ca94 499 sela.mode(PullUp); // pin 28
andrewcrussell 3:f0cd7c22ca94 500 selb.mode(PullUp); // pin 27
andrewcrussell 3:f0cd7c22ca94 501 stdby.mode(PullUp); // pin 26
andrewcrussell 3:f0cd7c22ca94 502 recloop_in.mode(PullUp); // pin 14
andrewcrussell 3:f0cd7c22ca94 503
andrewcrussell 3:f0cd7c22ca94 504 wait(.2);
andrewcrussell 0:83d4a20e7bc7 505 FLAG1 = FALSE;
andrewcrussell 0:83d4a20e7bc7 506 FLAG2 = FALSE;
andrewcrussell 3:f0cd7c22ca94 507 FLAG5 = FALSE; // this is the recloop flag
andrewcrussell 3:f0cd7c22ca94 508 FWD1=0; //make sure the volume control motor is OFF
andrewcrussell 0:83d4a20e7bc7 509 REV1=0;
andrewcrussell 0:83d4a20e7bc7 510
andrewcrussell 3:f0cd7c22ca94 511 // set up the ISR's that will be used
andrewcrussell 3:f0cd7c22ca94 512 rc5int.fall(&rc5isr); // trigger int on rising edge - go service it at rc5dat
andrewcrussell 0:83d4a20e7bc7 513 select_int.fall(&select_isr); // input from rotary encoder or input select
andrewcrussell 0:83d4a20e7bc7 514 mute_int.fall(&mute_isr); // mute push button interrupt
andrewcrussell 0:83d4a20e7bc7 515 recloop_int.fall(&recloop_isr); // record loop push button interrupt
andrewcrussell 0:83d4a20e7bc7 516 stdby_int.fall(&stdby_isr); // the system power/standby switch
andrewcrussell 0:83d4a20e7bc7 517
andrewcrussell 0:83d4a20e7bc7 518 //now disable them, leaving only the stand by p/button and rc5int interrupts active
andrewcrussell 0:83d4a20e7bc7 519 select_int.fall(NULL);
andrewcrussell 0:83d4a20e7bc7 520 mute_int.fall(NULL);
andrewcrussell 0:83d4a20e7bc7 521 recloop_int.fall(NULL);
andrewcrussell 0:83d4a20e7bc7 522
andrewcrussell 1:bb881a434906 523 standbyflag = TRUE; // preamp will be set-up first time for OFF
andrewcrussell 3:f0cd7c22ca94 524 standby_out(); // set system up
andrewcrussell 3:f0cd7c22ca94 525 standbyflag = FALSE;
andrewcrussell 3:f0cd7c22ca94 526 select_save = 2;
andrewcrussell 3:f0cd7c22ca94 527 select_rot = select_save; // CD will be selected when power is first turned on
andrewcrussell 3:f0cd7c22ca94 528 wait(3);
andrewcrussell 3:f0cd7c22ca94 529 muteind = HIGH;
andrewcrussell 0:83d4a20e7bc7 530 __enable_irq();
andrewcrussell 0:83d4a20e7bc7 531
andrewcrussell 3:f0cd7c22ca94 532 // all ready and in standby from this point forward
andrewcrussell 1:bb881a434906 533
andrewcrussell 3:f0cd7c22ca94 534 // note: if printf is used for debug, the record indicate LED will remain ON after printing
andrewcrussell 3:f0cd7c22ca94 535 // the first message
andrewcrussell 0:83d4a20e7bc7 536
andrewcrussell 0:83d4a20e7bc7 537 LOOP: // this is the main operating loop
andrewcrussell 2:674e2dd56e7d 538
andrewcrussell 0:83d4a20e7bc7 539 __WFI(); // wait here until interrupt
andrewcrussell 0:83d4a20e7bc7 540
andrewcrussell 0:83d4a20e7bc7 541 if (FLAG1 == TRUE) { // FLAG1 indicates remote control was used
andrewcrussell 0:83d4a20e7bc7 542 save_stream();
andrewcrussell 3:f0cd7c22ca94 543 process_stream();
andrewcrussell 3:f0cd7c22ca94 544
andrewcrussell 0:83d4a20e7bc7 545 FLAG1 = FALSE;
andrewcrussell 0:83d4a20e7bc7 546 }
andrewcrussell 0:83d4a20e7bc7 547
andrewcrussell 0:83d4a20e7bc7 548 if (FLAG2 == TRUE) {
andrewcrussell 0:83d4a20e7bc7 549 select_process(); //select process
andrewcrussell 0:83d4a20e7bc7 550 FLAG2 = FALSE;
andrewcrussell 0:83d4a20e7bc7 551 }
andrewcrussell 0:83d4a20e7bc7 552
andrewcrussell 0:83d4a20e7bc7 553 if (FLAG3 == TRUE) {
andrewcrussell 0:83d4a20e7bc7 554 mute_out(); //mute
andrewcrussell 0:83d4a20e7bc7 555 FLAG3 = FALSE;
andrewcrussell 0:83d4a20e7bc7 556 }
andrewcrussell 3:f0cd7c22ca94 557
andrewcrussell 3:f0cd7c22ca94 558 if (FLAG4 == TRUE) { // standby ON/OFF
andrewcrussell 3:f0cd7c22ca94 559 standby_out();
andrewcrussell 3:f0cd7c22ca94 560 FLAG4 = FALSE;
andrewcrussell 0:83d4a20e7bc7 561 }
andrewcrussell 3:f0cd7c22ca94 562
andrewcrussell 0:83d4a20e7bc7 563 if (FLAG5 == TRUE) {
andrewcrussell 0:83d4a20e7bc7 564 recloop(); //recloop
andrewcrussell 0:83d4a20e7bc7 565 FLAG5 = FALSE;
andrewcrussell 0:83d4a20e7bc7 566 }
andrewcrussell 0:83d4a20e7bc7 567
andrewcrussell 3:f0cd7c22ca94 568 //printf("\r Command = %d Address = %d \n",command, address);
andrewcrussell 3:f0cd7c22ca94 569
andrewcrussell 0:83d4a20e7bc7 570 goto LOOP;
andrewcrussell 0:83d4a20e7bc7 571
andrewcrussell 0:83d4a20e7bc7 572 }
andrewcrussell 0:83d4a20e7bc7 573
andrewcrussell 0:83d4a20e7bc7 574
andrewcrussell 0:83d4a20e7bc7 575
andrewcrussell 2:674e2dd56e7d 576