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:
Tue Jun 16 11:22:55 2015 +0000
Revision:
0:83d4a20e7bc7
Child:
1:bb881a434906
RC5 Decoder with various outputs and inputs to control a preamp

Who changed what in which revision?

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