Andrew R
/
Apple_Mbed_Studio
Apple Mbed Studio ready 15 Nov 2022
main.cpp@0:3110d82c59ff, 22 months ago (annotated)
- 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?
User | Revision | Line number | New 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 |