An RC5 decoder and preamp controller. Written on the LPC11U24, Ported to LPC1114 and now 100% stable (January 2016)

Dependents:   AppleRemoteController_copy_Production_Version AppleRemoteController_Reference_Only

Committer:
andrewcrussell
Date:
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?

UserRevisionLine numberNew 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