Apple Mbed Studio ready 15 Nov 2022

Dependencies:   mbed

Committer:
andrewcrussell
Date:
Tue Nov 15 11:32:21 2022 +0000
Revision:
0:3110d82c59ff
Apple final build Nov 15 2022

Who changed what in which revision?

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