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:
Mon Nov 14 13:03:43 2022 +0000
Revision:
6:6aedba64f314
Parent:
5:9525755f7457
Child:
7:ea2799ec389d
22 nov main

Who changed what in which revision?

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