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
main.cpp@2:674e2dd56e7d, 2015-11-20 (annotated)
- Committer:
- andrewcrussell
- Date:
- Fri Nov 20 14:36:14 2015 +0000
- Revision:
- 2:674e2dd56e7d
- Parent:
- 1:bb881a434906
- Child:
- 3:f0cd7c22ca94
Updated 20th Nov
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewcrussell | 1:bb881a434906 | 1 | /****************************** RC5 Decoder and Preamp Controller V1.0 *************************/ |
andrewcrussell | 1:bb881a434906 | 2 | /* AndrewR written in 2015 */ |
andrewcrussell | 0:83d4a20e7bc7 | 3 | /* This RC5 decoder works by reading in the RC5 stream from one of the serial port lines */ |
andrewcrussell | 0:83d4a20e7bc7 | 4 | /* and saving the incoming stream into an array called stream, after which it is decoded and */ |
andrewcrussell | 1:bb881a434906 | 5 | /* the command executed. A Marantz RC-68PM IR R/C was used to develop this program - it */ |
andrewcrussell | 0:83d4a20e7bc7 | 6 | /* should work with any controller complying with the Philips RC5 standard. */ |
andrewcrussell | 1:bb881a434906 | 7 | /* See the rc5codes.h header for the codes used. */ |
andrewcrussell | 0:83d4a20e7bc7 | 8 | |
andrewcrussell | 0:83d4a20e7bc7 | 9 | /* The following audio preamplifier facilities are catered for:- */ |
andrewcrussell | 0:83d4a20e7bc7 | 10 | /* 1. Manual volume control adjustment via ALPS RK27 motorized potentiometer */ |
andrewcrussell | 0:83d4a20e7bc7 | 11 | /* 2. Input select via rotary encoder */ |
andrewcrussell | 0:83d4a20e7bc7 | 12 | /* 3. Output mute via push button actuation */ |
andrewcrussell | 0:83d4a20e7bc7 | 13 | /* 4. Record loop via push button actuation */ |
andrewcrussell | 0:83d4a20e7bc7 | 14 | /* 5. Power ON output to drive the /standby input of a system power supply */ |
andrewcrussell | 0:83d4a20e7bc7 | 15 | /* Facilities 1,2,3 and 5 are supported by an RC5 compliant remote control for preamplifiers */ |
andrewcrussell | 1:bb881a434906 | 16 | /* The program can be used with either the LPC11U24 or the LPC1114 - just use the appropriate */ |
andrewcrussell | 1:bb881a434906 | 17 | /* Pindfefxxxx.h file */ |
andrewcrussell | 0:83d4a20e7bc7 | 18 | |
andrewcrussell | 0:83d4a20e7bc7 | 19 | #include "mbed.h" |
andrewcrussell | 1:bb881a434906 | 20 | #include "rc5codes.h" // Philips RC5 code definitions |
andrewcrussell | 0:83d4a20e7bc7 | 21 | #include "Pindef1114.h" // all microcontroller I/O pin assignments defined here |
andrewcrussell | 0:83d4a20e7bc7 | 22 | |
andrewcrussell | 0:83d4a20e7bc7 | 23 | #define TRUE 1 |
andrewcrussell | 0:83d4a20e7bc7 | 24 | #define FALSE 0 |
andrewcrussell | 0:83d4a20e7bc7 | 25 | #define HIGH 1 |
andrewcrussell | 0:83d4a20e7bc7 | 26 | #define LOW 0 |
andrewcrussell | 0:83d4a20e7bc7 | 27 | #define rc5_bitcount 14 // number of RC5 bits |
andrewcrussell | 0:83d4a20e7bc7 | 28 | #define tick 444 // quarter bit time in us |
andrewcrussell | 0:83d4a20e7bc7 | 29 | #define tock 1778 // one bit time in us |
andrewcrussell | 0:83d4a20e7bc7 | 30 | #define VUP_timeout 10 // defines max number of R/C cycles before the vol ctrl mtr drive stops |
andrewcrussell | 0:83d4a20e7bc7 | 31 | #define VDWN_timeout 10 // as above but for volume decrease. Needed to ensure the motor is not burnt out |
andrewcrussell | 0:83d4a20e7bc7 | 32 | |
andrewcrussell | 0:83d4a20e7bc7 | 33 | //#define PHONO_IN 1 // these are the input assignments - not used in V1.0 of the |
andrewcrussell | 0:83d4a20e7bc7 | 34 | //#define CD_IN 2 // controller since the input select is just stepped |
andrewcrussell | 0:83d4a20e7bc7 | 35 | //#define TUN_IN 4 // through from PHONO_IN to REC_IN and back again |
andrewcrussell | 0:83d4a20e7bc7 | 36 | //#define AUX1_IN 8 |
andrewcrussell | 0:83d4a20e7bc7 | 37 | //#define MSERV_IN 16 |
andrewcrussell | 0:83d4a20e7bc7 | 38 | //define REC_IN 32 |
andrewcrussell | 0:83d4a20e7bc7 | 39 | |
andrewcrussell | 0:83d4a20e7bc7 | 40 | int startbit; |
andrewcrussell | 2:674e2dd56e7d | 41 | int toggle; // this is the 3rd bit position in the input stream and checks for |
andrewcrussell | 2:674e2dd56e7d | 42 | // subsequent button depresses from the r/control |
andrewcrussell | 2:674e2dd56e7d | 43 | int toggle1; // temorary storage in the volume UP and volume DOWN functions |
andrewcrussell | 2:674e2dd56e7d | 44 | int toggle2; // temprary storage of the PB in the mute function |
andrewcrussell | 0:83d4a20e7bc7 | 45 | int standby; |
andrewcrussell | 0:83d4a20e7bc7 | 46 | int address; |
andrewcrussell | 0:83d4a20e7bc7 | 47 | int command; |
andrewcrussell | 0:83d4a20e7bc7 | 48 | |
andrewcrussell | 0:83d4a20e7bc7 | 49 | int FLAG1; // this is used in the remote control input processing |
andrewcrussell | 0:83d4a20e7bc7 | 50 | int FLAG2; // this is used in the select input processing |
andrewcrussell | 0:83d4a20e7bc7 | 51 | int FLAG3; // this is for the mute pushbutton |
andrewcrussell | 0:83d4a20e7bc7 | 52 | int FLAG4; // this is for the standby pushbutton |
andrewcrussell | 0:83d4a20e7bc7 | 53 | int FLAG5; // this is the recloop flag |
andrewcrussell | 0:83d4a20e7bc7 | 54 | int RCFLAG = FALSE; // used to determine if the select command came via R/C |
andrewcrussell | 0:83d4a20e7bc7 | 55 | int standbyflag; // used to save the standby condition |
andrewcrussell | 0:83d4a20e7bc7 | 56 | |
andrewcrussell | 0:83d4a20e7bc7 | 57 | int relay; |
andrewcrussell | 0:83d4a20e7bc7 | 58 | int key_press = 1; // keeps track of key presses |
andrewcrussell | 0:83d4a20e7bc7 | 59 | int toggle_press = 1; //stores value of toggle for key_press routine |
andrewcrussell | 0:83d4a20e7bc7 | 60 | |
andrewcrussell | 0:83d4a20e7bc7 | 61 | // delcarations below are all for the input select proceses |
andrewcrussell | 0:83d4a20e7bc7 | 62 | int select = 0; |
andrewcrussell | 0:83d4a20e7bc7 | 63 | int select_save = 1; // we save the status of select drive here. Initial value is 1 |
andrewcrussell | 0:83d4a20e7bc7 | 64 | int select_rot = 1; // rotary encoder pulse counter |
andrewcrussell | 0:83d4a20e7bc7 | 65 | |
andrewcrussell | 2:674e2dd56e7d | 66 | //int loop_counter = 0; // debug loop counter |
andrewcrussell | 2:674e2dd56e7d | 67 | |
andrewcrussell | 0:83d4a20e7bc7 | 68 | // declare function prototypes here |
andrewcrussell | 0:83d4a20e7bc7 | 69 | void select_out (void); |
andrewcrussell | 0:83d4a20e7bc7 | 70 | void rc5isr(void); |
andrewcrussell | 0:83d4a20e7bc7 | 71 | void mute_isr(void); |
andrewcrussell | 0:83d4a20e7bc7 | 72 | void recloop_isr(void); |
andrewcrussell | 0:83d4a20e7bc7 | 73 | void select_isr(void); |
andrewcrussell | 0:83d4a20e7bc7 | 74 | void standby_out(void); |
andrewcrussell | 0:83d4a20e7bc7 | 75 | |
andrewcrussell | 0:83d4a20e7bc7 | 76 | /****************************** volume increase ***********************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 77 | void vol_up (void) |
andrewcrussell | 0:83d4a20e7bc7 | 78 | { |
andrewcrussell | 0:83d4a20e7bc7 | 79 | if ((standbyflag == TRUE) && (key_press < VUP_timeout)) { |
andrewcrussell | 0:83d4a20e7bc7 | 80 | |
andrewcrussell | 0:83d4a20e7bc7 | 81 | FWD1 = HIGH; |
andrewcrussell | 0:83d4a20e7bc7 | 82 | // FWD2 = HIGH; |
andrewcrussell | 0:83d4a20e7bc7 | 83 | wait(.1); //drive the motors for a short while |
andrewcrussell | 0:83d4a20e7bc7 | 84 | FWD1 = LOW; |
andrewcrussell | 0:83d4a20e7bc7 | 85 | // FWD2 = LOW; |
andrewcrussell | 0:83d4a20e7bc7 | 86 | } |
andrewcrussell | 0:83d4a20e7bc7 | 87 | if (toggle1 != toggle) { |
andrewcrussell | 0:83d4a20e7bc7 | 88 | key_press = 0; // user released the button, so reset counter |
andrewcrussell | 0:83d4a20e7bc7 | 89 | } else if (toggle1 == toggle) { |
andrewcrussell | 0:83d4a20e7bc7 | 90 | key_press++; // button remained depressed, so increment counter |
andrewcrussell | 0:83d4a20e7bc7 | 91 | } |
andrewcrussell | 0:83d4a20e7bc7 | 92 | toggle1 = toggle; |
andrewcrussell | 0:83d4a20e7bc7 | 93 | wait_ms(1); |
andrewcrussell | 0:83d4a20e7bc7 | 94 | } |
andrewcrussell | 0:83d4a20e7bc7 | 95 | |
andrewcrussell | 0:83d4a20e7bc7 | 96 | /******************************* volume decrease **********************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 97 | void vol_dwn (void) |
andrewcrussell | 0:83d4a20e7bc7 | 98 | { |
andrewcrussell | 0:83d4a20e7bc7 | 99 | if ((standbyflag == TRUE) && (key_press < VDWN_timeout)) { |
andrewcrussell | 0:83d4a20e7bc7 | 100 | |
andrewcrussell | 0:83d4a20e7bc7 | 101 | REV1 = HIGH; |
andrewcrussell | 0:83d4a20e7bc7 | 102 | // REV2 = HIGH; |
andrewcrussell | 0:83d4a20e7bc7 | 103 | wait(.1); //drive the motors for a short while |
andrewcrussell | 0:83d4a20e7bc7 | 104 | REV1 = LOW; |
andrewcrussell | 0:83d4a20e7bc7 | 105 | // REV2 = LOW; |
andrewcrussell | 0:83d4a20e7bc7 | 106 | } |
andrewcrussell | 0:83d4a20e7bc7 | 107 | if (toggle1 != toggle) { |
andrewcrussell | 0:83d4a20e7bc7 | 108 | key_press = 0; // user released the button, so reset counter |
andrewcrussell | 0:83d4a20e7bc7 | 109 | } else if (toggle1 == toggle) { |
andrewcrussell | 0:83d4a20e7bc7 | 110 | key_press++; // button remained depressed, so increment counter |
andrewcrussell | 0:83d4a20e7bc7 | 111 | } |
andrewcrussell | 0:83d4a20e7bc7 | 112 | toggle1 = toggle; |
andrewcrussell | 0:83d4a20e7bc7 | 113 | wait_ms(1); |
andrewcrussell | 0:83d4a20e7bc7 | 114 | } |
andrewcrussell | 0:83d4a20e7bc7 | 115 | /********************************** stdby_isr *************************************/ |
andrewcrussell | 2:674e2dd56e7d | 116 | void stdby_isr(void) |
andrewcrussell | 0:83d4a20e7bc7 | 117 | { |
andrewcrussell | 0:83d4a20e7bc7 | 118 | FLAG4 = TRUE; |
andrewcrussell | 0:83d4a20e7bc7 | 119 | } |
andrewcrussell | 0:83d4a20e7bc7 | 120 | |
andrewcrussell | 0:83d4a20e7bc7 | 121 | /*********************************** standby **************************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 122 | /* this will require supporting hardware functionality to power down the */ |
andrewcrussell | 0:83d4a20e7bc7 | 123 | /* analog board, LED's etc. Best option here is to use regulators with a */ |
andrewcrussell | 1:bb881a434906 | 124 | /* shutdown option. for now, all the LED's are just turned off. */ |
andrewcrussell | 0:83d4a20e7bc7 | 125 | |
andrewcrussell | 0:83d4a20e7bc7 | 126 | void standby_out(void) // both p/button and R/C come in here |
andrewcrussell | 0:83d4a20e7bc7 | 127 | { |
andrewcrussell | 0:83d4a20e7bc7 | 128 | stdby_int.fall(NULL); // on first power up cycle NO interuppts are accepted |
andrewcrussell | 1:bb881a434906 | 129 | // and neither any while this function is executed in any case |
andrewcrussell | 0:83d4a20e7bc7 | 130 | wait_ms(20); // a very simple debounce |
andrewcrussell | 0:83d4a20e7bc7 | 131 | do { // that waits for the depressed button to be released |
andrewcrussell | 0:83d4a20e7bc7 | 132 | (1); |
andrewcrussell | 0:83d4a20e7bc7 | 133 | } while (stdby !=1); |
andrewcrussell | 0:83d4a20e7bc7 | 134 | |
andrewcrussell | 0:83d4a20e7bc7 | 135 | if (standbyflag == TRUE) { // was ON so we will turn it OFF |
andrewcrussell | 0:83d4a20e7bc7 | 136 | // turn off all interrupts except the standby and rc5int |
andrewcrussell | 0:83d4a20e7bc7 | 137 | select_int.fall(NULL); |
andrewcrussell | 0:83d4a20e7bc7 | 138 | mute_int.fall(NULL); |
andrewcrussell | 0:83d4a20e7bc7 | 139 | recloop_int.fall(NULL); |
andrewcrussell | 1:bb881a434906 | 140 | muteind = LOW; |
andrewcrussell | 0:83d4a20e7bc7 | 141 | muteout = LOW; |
andrewcrussell | 2:674e2dd56e7d | 142 | recloop_out = HIGH; // make sure the recloop is OFF [its active HIGH] |
andrewcrussell | 0:83d4a20e7bc7 | 143 | select_save = select_drv; // save the status of select_drv |
andrewcrussell | 0:83d4a20e7bc7 | 144 | select_drv = 0; // turn all input select realys OFF |
andrewcrussell | 1:bb881a434906 | 145 | //power_ind = LOW; // this is the regulator shutdown control. HIGH = ON |
andrewcrussell | 0:83d4a20e7bc7 | 146 | wait(1); |
andrewcrussell | 2:674e2dd56e7d | 147 | muteind = HIGH; |
andrewcrussell | 0:83d4a20e7bc7 | 148 | standbyflag = FALSE; // set it up for the next power cycle |
andrewcrussell | 0:83d4a20e7bc7 | 149 | |
andrewcrussell | 2:674e2dd56e7d | 150 | |
andrewcrussell | 2:674e2dd56e7d | 151 | |
andrewcrussell | 0:83d4a20e7bc7 | 152 | } else if (standbyflag == FALSE) { // was OFF so we will turn it ON |
andrewcrussell | 2:674e2dd56e7d | 153 | //printf("Going thru power up\n\r"); |
andrewcrussell | 1:bb881a434906 | 154 | //power_ind = HIGH; |
andrewcrussell | 1:bb881a434906 | 155 | muteind = LOW; |
andrewcrussell | 0:83d4a20e7bc7 | 156 | rc5int.rise(&rc5isr); // trigger int on rising edge - go service it at rc5dat |
andrewcrussell | 0:83d4a20e7bc7 | 157 | select_int.fall(&select_isr); // input from rotary encoder or input select |
andrewcrussell | 0:83d4a20e7bc7 | 158 | mute_int.fall(&mute_isr); |
andrewcrussell | 0:83d4a20e7bc7 | 159 | recloop_int.fall(&recloop_isr); |
andrewcrussell | 0:83d4a20e7bc7 | 160 | wait(2); |
andrewcrussell | 0:83d4a20e7bc7 | 161 | select_drv = select_save; // recall the input select setting |
andrewcrussell | 1:bb881a434906 | 162 | wait(2); |
andrewcrussell | 2:674e2dd56e7d | 163 | muteind = HIGH; // let things settle a bit |
andrewcrussell | 0:83d4a20e7bc7 | 164 | muteout = HIGH; |
andrewcrussell | 0:83d4a20e7bc7 | 165 | standbyflag = TRUE; |
andrewcrussell | 2:674e2dd56e7d | 166 | //printf("Finished powering up in standby_out\n\r"); |
andrewcrussell | 0:83d4a20e7bc7 | 167 | } |
andrewcrussell | 0:83d4a20e7bc7 | 168 | wait_ms(5); |
andrewcrussell | 2:674e2dd56e7d | 169 | stdby_int.fall(&stdby_isr); // re-enable the standby interrupt |
andrewcrussell | 2:674e2dd56e7d | 170 | //printf("exiting standby_out handler now\n\r"); |
andrewcrussell | 2:674e2dd56e7d | 171 | |
andrewcrussell | 0:83d4a20e7bc7 | 172 | } |
andrewcrussell | 0:83d4a20e7bc7 | 173 | |
andrewcrussell | 0:83d4a20e7bc7 | 174 | /********************************** record loop isr *******************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 175 | |
andrewcrussell | 0:83d4a20e7bc7 | 176 | void recloop_isr(void) |
andrewcrussell | 0:83d4a20e7bc7 | 177 | { |
andrewcrussell | 0:83d4a20e7bc7 | 178 | FLAG5 = TRUE; |
andrewcrussell | 0:83d4a20e7bc7 | 179 | } |
andrewcrussell | 0:83d4a20e7bc7 | 180 | /************************** recloop - just a simple toggle ************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 181 | void recloop() |
andrewcrussell | 0:83d4a20e7bc7 | 182 | { |
andrewcrussell | 0:83d4a20e7bc7 | 183 | recloop_int.fall(NULL); // to prevent re-entrance when coming here from the R/C |
andrewcrussell | 0:83d4a20e7bc7 | 184 | wait_ms(20); // simple debounce for when mute is via the f/p p/b switch |
andrewcrussell | 0:83d4a20e7bc7 | 185 | do { |
andrewcrussell | 0:83d4a20e7bc7 | 186 | (1); // wait here until the button is released |
andrewcrussell | 0:83d4a20e7bc7 | 187 | } while (recloop_in!=1); |
andrewcrussell | 0:83d4a20e7bc7 | 188 | recloop_out = !recloop_out; |
andrewcrussell | 0:83d4a20e7bc7 | 189 | wait_ms(20); |
andrewcrussell | 0:83d4a20e7bc7 | 190 | recloop_int.fall(&recloop_isr); |
andrewcrussell | 0:83d4a20e7bc7 | 191 | } |
andrewcrussell | 0:83d4a20e7bc7 | 192 | |
andrewcrussell | 0:83d4a20e7bc7 | 193 | /************************************ mute_isr ************************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 194 | |
andrewcrussell | 0:83d4a20e7bc7 | 195 | void mute_isr(void) |
andrewcrussell | 0:83d4a20e7bc7 | 196 | { |
andrewcrussell | 0:83d4a20e7bc7 | 197 | FLAG3 = TRUE; |
andrewcrussell | 0:83d4a20e7bc7 | 198 | toggle2 = !toggle2; // so the p/button input is recognized in mute_out() |
andrewcrussell | 2:674e2dd56e7d | 199 | |
andrewcrussell | 0:83d4a20e7bc7 | 200 | } |
andrewcrussell | 0:83d4a20e7bc7 | 201 | /*************************** mute - just a simple toggle **************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 202 | void mute_out() |
andrewcrussell | 0:83d4a20e7bc7 | 203 | { |
andrewcrussell | 0:83d4a20e7bc7 | 204 | mute_int.fall(NULL); // to prevent re-entance when coming here from the R/C |
andrewcrussell | 0:83d4a20e7bc7 | 205 | if ((standbyflag == TRUE) && (toggle != toggle2)) { // only toggle mute if the preamp is ON |
andrewcrussell | 0:83d4a20e7bc7 | 206 | wait_ms(20); //simple debounce for when mute is via the f/p p/b switch |
andrewcrussell | 0:83d4a20e7bc7 | 207 | do { |
andrewcrussell | 0:83d4a20e7bc7 | 208 | (1); //wait here until the button is released |
andrewcrussell | 2:674e2dd56e7d | 209 | } while (mute != 1); |
andrewcrussell | 2:674e2dd56e7d | 210 | muteout = !muteout; // flip the mute relay |
andrewcrussell | 2:674e2dd56e7d | 211 | muteind = !muteout; // Turn the indicator LED ON - it inverted compared to muteout |
andrewcrussell | 0:83d4a20e7bc7 | 212 | wait_ms(20); |
andrewcrussell | 0:83d4a20e7bc7 | 213 | |
andrewcrussell | 0:83d4a20e7bc7 | 214 | } |
andrewcrussell | 0:83d4a20e7bc7 | 215 | toggle2 = toggle; |
andrewcrussell | 2:674e2dd56e7d | 216 | //toggle = toggle2; |
andrewcrussell | 0:83d4a20e7bc7 | 217 | mute_int.fall(&mute_isr); |
andrewcrussell | 0:83d4a20e7bc7 | 218 | } |
andrewcrussell | 0:83d4a20e7bc7 | 219 | |
andrewcrussell | 0:83d4a20e7bc7 | 220 | /************************************ rc5isr **************************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 221 | /* Interrupt triggered by a rising edge on p21 of the cont which is R/C data in */ |
andrewcrussell | 0:83d4a20e7bc7 | 222 | |
andrewcrussell | 0:83d4a20e7bc7 | 223 | void rc5isr(void) |
andrewcrussell | 0:83d4a20e7bc7 | 224 | { |
andrewcrussell | 0:83d4a20e7bc7 | 225 | FLAG1 = TRUE; |
andrewcrussell | 0:83d4a20e7bc7 | 226 | } |
andrewcrussell | 0:83d4a20e7bc7 | 227 | /***************** save rc5 bit stream from remote controller *********************/ |
andrewcrussell | 0:83d4a20e7bc7 | 228 | /* This function reads the input data on pin rc5dat at 1778us ('tock')intervals */ |
andrewcrussell | 0:83d4a20e7bc7 | 229 | /* and saves the data into an array stream[i]. */ |
andrewcrussell | 0:83d4a20e7bc7 | 230 | /* This function only looks at the second half of the bit position, since if that */ |
andrewcrussell | 0:83d4a20e7bc7 | 231 | /* is a 1 then it is assumed the first half of the bit position is a zero. Note */ |
andrewcrussell | 0:83d4a20e7bc7 | 232 | /* that in Manchester encoding, you cannot (should not) have both the 0 half-bit */ |
andrewcrussell | 0:83d4a20e7bc7 | 233 | /* position and the 1 half-bit position both HIGH or LOW in the same bit time - */ |
andrewcrussell | 0:83d4a20e7bc7 | 234 | /* a simplification exploited in this function. */ |
andrewcrussell | 0:83d4a20e7bc7 | 235 | |
andrewcrussell | 0:83d4a20e7bc7 | 236 | void save_stream(void) |
andrewcrussell | 0:83d4a20e7bc7 | 237 | { |
andrewcrussell | 0:83d4a20e7bc7 | 238 | bool stream[15];// the array is initialized each time its used and is local only |
andrewcrussell | 0:83d4a20e7bc7 | 239 | int bitloop; // number of bit positions |
andrewcrussell | 0:83d4a20e7bc7 | 240 | int i = 0; // counter |
andrewcrussell | 0:83d4a20e7bc7 | 241 | int k = 0; // temp storage |
andrewcrussell | 0:83d4a20e7bc7 | 242 | startbit = 0; |
andrewcrussell | 0:83d4a20e7bc7 | 243 | address = 0; |
andrewcrussell | 0:83d4a20e7bc7 | 244 | command = 0; |
andrewcrussell | 0:83d4a20e7bc7 | 245 | toggle = 0; |
andrewcrussell | 0:83d4a20e7bc7 | 246 | wait_us(tick); // locate read point in middle of 1st half bit time of the 1st start bit |
andrewcrussell | 0:83d4a20e7bc7 | 247 | for (bitloop = 0; bitloop <15; bitloop++) { |
andrewcrussell | 0:83d4a20e7bc7 | 248 | stream[bitloop] = rc5dat; //read the data and save it to array position [i] |
andrewcrussell | 0:83d4a20e7bc7 | 249 | wait_us(tock); //wait here until ready to read the next bit in |
andrewcrussell | 0:83d4a20e7bc7 | 250 | |
andrewcrussell | 0:83d4a20e7bc7 | 251 | // now have 14 bits loaded into stream[i] |
andrewcrussell | 0:83d4a20e7bc7 | 252 | } |
andrewcrussell | 0:83d4a20e7bc7 | 253 | /* now put data in the array into the start, toggle, address and command variables - array counts from stream[0] */ |
andrewcrussell | 0:83d4a20e7bc7 | 254 | |
andrewcrussell | 0:83d4a20e7bc7 | 255 | for (i=0; i<2; i++) { // first 2 bit positions are start bits = 3; will use this later for basic error checking |
andrewcrussell | 0:83d4a20e7bc7 | 256 | k = stream[i]; |
andrewcrussell | 0:83d4a20e7bc7 | 257 | startbit = (startbit << 1); |
andrewcrussell | 0:83d4a20e7bc7 | 258 | startbit = startbit|k; |
andrewcrussell | 0:83d4a20e7bc7 | 259 | } |
andrewcrussell | 0:83d4a20e7bc7 | 260 | |
andrewcrussell | 0:83d4a20e7bc7 | 261 | toggle = stream[2]; // 3rd bit position is the toggle bit - 1 bit |
andrewcrussell | 0:83d4a20e7bc7 | 262 | |
andrewcrussell | 0:83d4a20e7bc7 | 263 | for (i = 3; i <8; i++) { // bit positions 3 to 7 are the address (or 'system') - 5 bit positions in total |
andrewcrussell | 0:83d4a20e7bc7 | 264 | k = stream[i]; |
andrewcrussell | 0:83d4a20e7bc7 | 265 | address = (address << 1); |
andrewcrussell | 0:83d4a20e7bc7 | 266 | address = address|k; |
andrewcrussell | 0:83d4a20e7bc7 | 267 | } |
andrewcrussell | 0:83d4a20e7bc7 | 268 | |
andrewcrussell | 0:83d4a20e7bc7 | 269 | for (i = 8; i <14; i++) { // bit positions 8 to 13 are the command - 6 bit positions |
andrewcrussell | 0:83d4a20e7bc7 | 270 | k = stream[i]; |
andrewcrussell | 0:83d4a20e7bc7 | 271 | command = (command << 1); |
andrewcrussell | 0:83d4a20e7bc7 | 272 | command = command|k; |
andrewcrussell | 0:83d4a20e7bc7 | 273 | } |
andrewcrussell | 0:83d4a20e7bc7 | 274 | |
andrewcrussell | 0:83d4a20e7bc7 | 275 | } |
andrewcrussell | 0:83d4a20e7bc7 | 276 | /********************************* process_stream() *******************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 277 | /* handles commands coming in from the remote controller only */ |
andrewcrussell | 0:83d4a20e7bc7 | 278 | |
andrewcrussell | 0:83d4a20e7bc7 | 279 | void process_stream (void) |
andrewcrussell | 0:83d4a20e7bc7 | 280 | { |
andrewcrussell | 0:83d4a20e7bc7 | 281 | if ((address == PREAMP) && (startbit == 3)) { |
andrewcrussell | 0:83d4a20e7bc7 | 282 | // basic error checking - must be preamp + startbit ok to get executed otherwise skip completly |
andrewcrussell | 0:83d4a20e7bc7 | 283 | switch (command) { |
andrewcrussell | 0:83d4a20e7bc7 | 284 | |
andrewcrussell | 0:83d4a20e7bc7 | 285 | case VUP: |
andrewcrussell | 0:83d4a20e7bc7 | 286 | vol_up(); |
andrewcrussell | 0:83d4a20e7bc7 | 287 | break; |
andrewcrussell | 0:83d4a20e7bc7 | 288 | |
andrewcrussell | 0:83d4a20e7bc7 | 289 | case VDOWN: |
andrewcrussell | 0:83d4a20e7bc7 | 290 | vol_dwn(); |
andrewcrussell | 0:83d4a20e7bc7 | 291 | break; |
andrewcrussell | 0:83d4a20e7bc7 | 292 | |
andrewcrussell | 0:83d4a20e7bc7 | 293 | case MUTE: |
andrewcrussell | 0:83d4a20e7bc7 | 294 | mute_out(); |
andrewcrussell | 0:83d4a20e7bc7 | 295 | break; |
andrewcrussell | 0:83d4a20e7bc7 | 296 | |
andrewcrussell | 0:83d4a20e7bc7 | 297 | case SELECT_R: |
andrewcrussell | 0:83d4a20e7bc7 | 298 | select_out(); |
andrewcrussell | 0:83d4a20e7bc7 | 299 | break; |
andrewcrussell | 0:83d4a20e7bc7 | 300 | |
andrewcrussell | 0:83d4a20e7bc7 | 301 | case STANDBY: |
andrewcrussell | 0:83d4a20e7bc7 | 302 | standby_out(); |
andrewcrussell | 0:83d4a20e7bc7 | 303 | break; |
andrewcrussell | 0:83d4a20e7bc7 | 304 | } |
andrewcrussell | 0:83d4a20e7bc7 | 305 | } |
andrewcrussell | 0:83d4a20e7bc7 | 306 | } |
andrewcrussell | 0:83d4a20e7bc7 | 307 | /*********************************** select_isr ***********************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 308 | |
andrewcrussell | 0:83d4a20e7bc7 | 309 | void select_isr(void) |
andrewcrussell | 0:83d4a20e7bc7 | 310 | { |
andrewcrussell | 0:83d4a20e7bc7 | 311 | FLAG2 = TRUE; |
andrewcrussell | 0:83d4a20e7bc7 | 312 | } |
andrewcrussell | 0:83d4a20e7bc7 | 313 | |
andrewcrussell | 0:83d4a20e7bc7 | 314 | /********************************* select_process *********************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 315 | /* used for selecting the input source. This function is used by both the */ |
andrewcrussell | 0:83d4a20e7bc7 | 316 | /* rotary encoder and the remote control */ |
andrewcrussell | 0:83d4a20e7bc7 | 317 | |
andrewcrussell | 0:83d4a20e7bc7 | 318 | void select_process(void) |
andrewcrussell | 0:83d4a20e7bc7 | 319 | { |
andrewcrussell | 0:83d4a20e7bc7 | 320 | if (RCFLAG == FALSE) { // if used R/C skip to select below |
andrewcrussell | 0:83d4a20e7bc7 | 321 | wait_ms(5); // debounce |
andrewcrussell | 0:83d4a20e7bc7 | 322 | select = 0; // flush select |
andrewcrussell | 0:83d4a20e7bc7 | 323 | |
andrewcrussell | 0:83d4a20e7bc7 | 324 | select = (select | sela) <<1; // read the two port lines associated with the select rotary encoder |
andrewcrussell | 0:83d4a20e7bc7 | 325 | select = (select | selb); |
andrewcrussell | 0:83d4a20e7bc7 | 326 | } |
andrewcrussell | 0:83d4a20e7bc7 | 327 | |
andrewcrussell | 0:83d4a20e7bc7 | 328 | switch (select) { |
andrewcrussell | 0:83d4a20e7bc7 | 329 | case 1: // select encoder is being rotated CW |
andrewcrussell | 0:83d4a20e7bc7 | 330 | select_rot <<= 1; |
andrewcrussell | 0:83d4a20e7bc7 | 331 | if (select_rot > 32) { |
andrewcrussell | 0:83d4a20e7bc7 | 332 | select_rot = 1; |
andrewcrussell | 0:83d4a20e7bc7 | 333 | } |
andrewcrussell | 0:83d4a20e7bc7 | 334 | break; |
andrewcrussell | 0:83d4a20e7bc7 | 335 | |
andrewcrussell | 0:83d4a20e7bc7 | 336 | case 0: |
andrewcrussell | 0:83d4a20e7bc7 | 337 | select_rot >>= 1; // encoder is being rotated CCW |
andrewcrussell | 0:83d4a20e7bc7 | 338 | if (select_rot < 1) { |
andrewcrussell | 0:83d4a20e7bc7 | 339 | select_rot = 32; |
andrewcrussell | 0:83d4a20e7bc7 | 340 | } |
andrewcrussell | 0:83d4a20e7bc7 | 341 | break; |
andrewcrussell | 0:83d4a20e7bc7 | 342 | |
andrewcrussell | 0:83d4a20e7bc7 | 343 | case 2: |
andrewcrussell | 0:83d4a20e7bc7 | 344 | {} break; // indeterminate fall through values - ignore |
andrewcrussell | 0:83d4a20e7bc7 | 345 | case 3: |
andrewcrussell | 0:83d4a20e7bc7 | 346 | {} break; |
andrewcrussell | 0:83d4a20e7bc7 | 347 | } |
andrewcrussell | 1:bb881a434906 | 348 | |
andrewcrussell | 0:83d4a20e7bc7 | 349 | select_drv = select_rot; // write the value out to the bus |
andrewcrussell | 0:83d4a20e7bc7 | 350 | } |
andrewcrussell | 0:83d4a20e7bc7 | 351 | |
andrewcrussell | 0:83d4a20e7bc7 | 352 | |
andrewcrussell | 0:83d4a20e7bc7 | 353 | /********************* input select from remote controller only *******************/ |
andrewcrussell | 0:83d4a20e7bc7 | 354 | void select_out (void) |
andrewcrussell | 0:83d4a20e7bc7 | 355 | { |
andrewcrussell | 0:83d4a20e7bc7 | 356 | if (toggle != toggle1) { // if the R/C button is held down, skip the increment |
andrewcrussell | 0:83d4a20e7bc7 | 357 | RCFLAG = TRUE; // this indicates command came in through the remote |
andrewcrussell | 0:83d4a20e7bc7 | 358 | select = 1; |
andrewcrussell | 0:83d4a20e7bc7 | 359 | select_process(); |
andrewcrussell | 0:83d4a20e7bc7 | 360 | RCFLAG = FALSE; |
andrewcrussell | 0:83d4a20e7bc7 | 361 | } |
andrewcrussell | 0:83d4a20e7bc7 | 362 | toggle1 = toggle; |
andrewcrussell | 0:83d4a20e7bc7 | 363 | } |
andrewcrussell | 0:83d4a20e7bc7 | 364 | /************************************ main() ***************************************/ |
andrewcrussell | 0:83d4a20e7bc7 | 365 | int main(void) |
andrewcrussell | 0:83d4a20e7bc7 | 366 | { |
andrewcrussell | 2:674e2dd56e7d | 367 | __disable_irq(); // just to make sure we can set up correctly without problems |
andrewcrussell | 1:bb881a434906 | 368 | |
andrewcrussell | 2:674e2dd56e7d | 369 | mute_int.mode(PullUp); // pin 11 on LPC1114 |
andrewcrussell | 2:674e2dd56e7d | 370 | rc5dat.mode(PullUp); // pin 15 |
andrewcrussell | 2:674e2dd56e7d | 371 | sela.mode(PullUp); // pin 28 |
andrewcrussell | 2:674e2dd56e7d | 372 | selb.mode(PullUp); // pin 27 |
andrewcrussell | 2:674e2dd56e7d | 373 | stdby.mode(PullUp); // pin 26 |
andrewcrussell | 2:674e2dd56e7d | 374 | recloop_in.mode(PullUp); // pin 15 |
andrewcrussell | 2:674e2dd56e7d | 375 | //TXD.mode(PullUp); // pin 16 |
andrewcrussell | 2:674e2dd56e7d | 376 | |
andrewcrussell | 2:674e2dd56e7d | 377 | |
andrewcrussell | 2:674e2dd56e7d | 378 | //muteind = LOW; |
andrewcrussell | 0:83d4a20e7bc7 | 379 | muteout = LOW; // mute the output while we go through power-up sequence |
andrewcrussell | 2:674e2dd56e7d | 380 | recloop_out = HIGH; // make sure initial recloop condition is delected - this is open drain O/PO |
andrewcrussell | 1:bb881a434906 | 381 | //power_ind = LOW; // power control; HIGH = power up |
andrewcrussell | 2:674e2dd56e7d | 382 | //wait(.2); |
andrewcrussell | 2:674e2dd56e7d | 383 | //Serial pc(USBTX, USBRX); // for debuging only - comment out on production |
andrewcrussell | 0:83d4a20e7bc7 | 384 | FLAG1 = FALSE; |
andrewcrussell | 0:83d4a20e7bc7 | 385 | FLAG2 = FALSE; |
andrewcrussell | 2:674e2dd56e7d | 386 | FWD1=0; //make sure the volume control motor is OFF |
andrewcrussell | 0:83d4a20e7bc7 | 387 | REV1=0; |
andrewcrussell | 2:674e2dd56e7d | 388 | |
andrewcrussell | 0:83d4a20e7bc7 | 389 | |
andrewcrussell | 0:83d4a20e7bc7 | 390 | // set up the ISR's we will be using |
andrewcrussell | 0:83d4a20e7bc7 | 391 | rc5int.rise(&rc5isr); // trigger int on rising edge - go service it at rc5dat |
andrewcrussell | 0:83d4a20e7bc7 | 392 | select_int.fall(&select_isr); // input from rotary encoder or input select |
andrewcrussell | 0:83d4a20e7bc7 | 393 | mute_int.fall(&mute_isr); // mute push button interrupt |
andrewcrussell | 0:83d4a20e7bc7 | 394 | recloop_int.fall(&recloop_isr); // record loop push button interrupt |
andrewcrussell | 0:83d4a20e7bc7 | 395 | stdby_int.fall(&stdby_isr); // the system power/standby switch |
andrewcrussell | 0:83d4a20e7bc7 | 396 | |
andrewcrussell | 0:83d4a20e7bc7 | 397 | //now disable them, leaving only the stand by p/button and rc5int interrupts active |
andrewcrussell | 0:83d4a20e7bc7 | 398 | select_int.fall(NULL); |
andrewcrussell | 0:83d4a20e7bc7 | 399 | mute_int.fall(NULL); |
andrewcrussell | 0:83d4a20e7bc7 | 400 | recloop_int.fall(NULL); |
andrewcrussell | 0:83d4a20e7bc7 | 401 | |
andrewcrussell | 2:674e2dd56e7d | 402 | //printf("disable ISR\n"); |
andrewcrussell | 1:bb881a434906 | 403 | |
andrewcrussell | 1:bb881a434906 | 404 | standbyflag = TRUE; // preamp will be set-up first time for OFF |
andrewcrussell | 0:83d4a20e7bc7 | 405 | standby_out(); // go through standby_out for initial set-up |
andrewcrussell | 1:bb881a434906 | 406 | select_save = 2; // CD will be selected when power is first turned on |
andrewcrussell | 2:674e2dd56e7d | 407 | //muteind = HIGH; |
andrewcrussell | 0:83d4a20e7bc7 | 408 | __enable_irq(); |
andrewcrussell | 0:83d4a20e7bc7 | 409 | |
andrewcrussell | 1:bb881a434906 | 410 | |
andrewcrussell | 0:83d4a20e7bc7 | 411 | // all ready and in standby from this point forward |
andrewcrussell | 0:83d4a20e7bc7 | 412 | |
andrewcrussell | 0:83d4a20e7bc7 | 413 | LOOP: // this is the main operating loop |
andrewcrussell | 2:674e2dd56e7d | 414 | |
andrewcrussell | 2:674e2dd56e7d | 415 | |
andrewcrussell | 2:674e2dd56e7d | 416 | //printf("WFI . . . . %i\n\r", loop_counter); |
andrewcrussell | 0:83d4a20e7bc7 | 417 | __WFI(); // wait here until interrupt |
andrewcrussell | 0:83d4a20e7bc7 | 418 | |
andrewcrussell | 0:83d4a20e7bc7 | 419 | if (FLAG1 == TRUE) { // FLAG1 indicates remote control was used |
andrewcrussell | 0:83d4a20e7bc7 | 420 | __disable_irq(); |
andrewcrussell | 0:83d4a20e7bc7 | 421 | save_stream(); |
andrewcrussell | 0:83d4a20e7bc7 | 422 | if (startbit == 3) { |
andrewcrussell | 0:83d4a20e7bc7 | 423 | process_stream(); |
andrewcrussell | 0:83d4a20e7bc7 | 424 | } |
andrewcrussell | 0:83d4a20e7bc7 | 425 | FLAG1 = FALSE; |
andrewcrussell | 0:83d4a20e7bc7 | 426 | __enable_irq(); |
andrewcrussell | 0:83d4a20e7bc7 | 427 | } |
andrewcrussell | 0:83d4a20e7bc7 | 428 | |
andrewcrussell | 0:83d4a20e7bc7 | 429 | if (FLAG2 == TRUE) { |
andrewcrussell | 0:83d4a20e7bc7 | 430 | __disable_irq(); |
andrewcrussell | 0:83d4a20e7bc7 | 431 | select_process(); //select process |
andrewcrussell | 0:83d4a20e7bc7 | 432 | FLAG2 = FALSE; |
andrewcrussell | 0:83d4a20e7bc7 | 433 | __enable_irq(); |
andrewcrussell | 0:83d4a20e7bc7 | 434 | } |
andrewcrussell | 0:83d4a20e7bc7 | 435 | |
andrewcrussell | 0:83d4a20e7bc7 | 436 | if (FLAG3 == TRUE) { |
andrewcrussell | 0:83d4a20e7bc7 | 437 | __disable_irq(); |
andrewcrussell | 0:83d4a20e7bc7 | 438 | mute_out(); //mute |
andrewcrussell | 0:83d4a20e7bc7 | 439 | FLAG3 = FALSE; |
andrewcrussell | 0:83d4a20e7bc7 | 440 | __enable_irq(); |
andrewcrussell | 0:83d4a20e7bc7 | 441 | } |
andrewcrussell | 2:674e2dd56e7d | 442 | //printf("B4stdby\n\r"); |
andrewcrussell | 0:83d4a20e7bc7 | 443 | if (FLAG4 == TRUE) { |
andrewcrussell | 0:83d4a20e7bc7 | 444 | __disable_irq(); |
andrewcrussell | 1:bb881a434906 | 445 | standby_out(); |
andrewcrussell | 2:674e2dd56e7d | 446 | FLAG4 = FALSE; |
andrewcrussell | 2:674e2dd56e7d | 447 | __enable_irq(); // standby |
andrewcrussell | 2:674e2dd56e7d | 448 | |
andrewcrussell | 2:674e2dd56e7d | 449 | // printf("back from isr\n\r"); |
andrewcrussell | 2:674e2dd56e7d | 450 | //__enable_irq(); |
andrewcrussell | 2:674e2dd56e7d | 451 | //printf("re-enable isr straight after back from standby\n\r"); |
andrewcrussell | 0:83d4a20e7bc7 | 452 | } |
andrewcrussell | 1:bb881a434906 | 453 | //printf("finished with STBY\n"); |
andrewcrussell | 0:83d4a20e7bc7 | 454 | if (FLAG5 == TRUE) { |
andrewcrussell | 0:83d4a20e7bc7 | 455 | __disable_irq(); |
andrewcrussell | 0:83d4a20e7bc7 | 456 | recloop(); //recloop |
andrewcrussell | 0:83d4a20e7bc7 | 457 | FLAG5 = FALSE; |
andrewcrussell | 0:83d4a20e7bc7 | 458 | __enable_irq(); |
andrewcrussell | 0:83d4a20e7bc7 | 459 | } |
andrewcrussell | 0:83d4a20e7bc7 | 460 | |
andrewcrussell | 2:674e2dd56e7d | 461 | wait_us(5); |
andrewcrussell | 2:674e2dd56e7d | 462 | //printf("loop to WFI\n\r"); |
andrewcrussell | 2:674e2dd56e7d | 463 | // loop_counter++; |
andrewcrussell | 0:83d4a20e7bc7 | 464 | goto LOOP; |
andrewcrussell | 0:83d4a20e7bc7 | 465 | |
andrewcrussell | 0:83d4a20e7bc7 | 466 | } |
andrewcrussell | 0:83d4a20e7bc7 | 467 | |
andrewcrussell | 0:83d4a20e7bc7 | 468 | |
andrewcrussell | 0:83d4a20e7bc7 | 469 | |
andrewcrussell | 2:674e2dd56e7d | 470 |