00001 00002 00003 00004 /* The software in this file is based on code from FU Berlin. */ 00005 00006 /* 00007 Copyright 2003/2004, Freie Universitaet Berlin. All rights reserved. 00008 00009 These sources were developed at the Freie Universität Berlin, Computer 00010 Systems and Telematics group. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are 00014 met: 00015 00016 - Redistributions of source code must retain the above copyright 00017 notice, this list of conditions and the following disclaimer. 00018 00019 - Redistributions in binary form must reproduce the above copyright 00020 notice, this list of conditions and the following disclaimer in the 00021 documentation and/or other materials provided with the distribution. 00022 00023 - Neither the name of Freie Universitaet Berlin (FUB) nor the names of its 00024 contributors may be used to endorse or promote products derived from 00025 this software without specific prior written permission. 00026 00027 This software is provided by FUB and the contributors on an "as is" 00028 basis, without any representations or warranties of any kind, express 00029 or implied including, but not limited to, representations or 00030 warranties of non-infringement, merchantability or fitness for a 00031 particular purpose. In no event shall FUB or contributors be liable 00032 for any direct, indirect, incidental, special, exemplary, or 00033 consequential damages (including, but not limited to, procurement of 00034 substitute goods or services; loss of use, data, or profits; or 00035 business interruption) however caused and on any theory of liability, 00036 whether in contract, strict liability, or tort (including negligence 00037 or otherwise) arising in any way out of the use of this software, even 00038 if advised of the possibility of such damage. 00039 00040 This implementation was developed by the CST group at the FUB. 00041 Contributors: Thomas Pietsch, Bjoern Lichtblau 00042 00043 */ 00044 00045 /* \file recir.c 00046 ** \ingroup Firmware 00047 ** \brief Receiving RC5 via IR Receiving Diode. 00048 ** 00049 ** \code 00050 ** RC5: 1780 us bitlength (manchester encoded, so half bitlength of 890 us is important) 00051 ** Transferred packet (2 start + toggle bit + 5 address bits + 6 comand bits)): 00052 ** | S | S | T | A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | C0 | 00053 ** irdata format: | ? | ? | error | newData | T | A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | C0 | 00054 ** \endcode 00055 ** 00056 ** <img src="../pics/rc5.jpg"> 00057 ** See detailed description at <a href="http://users.pandora.be/davshomepage/rc5.htm">http://users.pandora.be/davshomepage/rc5.htm</a> 00058 ** 00059 ** Some common addresses and commands: 00060 ** \code 00061 ** Address: Device: Command: 00062 ** 0 TV1 0...9 Numbers 0...9 (channel select) 00063 ** 1 TV2 12 Standby 00064 ** 5 VCR1 16 Master Volume + 00065 ** 6 VCR2 17 Master Volume - 00066 ** 17 Tuner 18 Brightness + 00067 ** 18 Audio Tape 19 Brightness - 00068 ** 20 CD Player 50 Fast rewind 00069 ** 52 Fast run forward 00070 ** 53 Play 00071 ** 54 Stop 00072 ** 55 Recording 00073 ** \endcode 00074 **/ 00075 00076 #include <io.h> 00077 #include <signal.h> 00078 00079 #include "dev/ir.h" 00080 00081 #include "dev/leds.h" 00082 #include "dev/beep.h" 00083 00084 PROCESS(ir_process, "IR receiver"); 00085 process_event_t ir_event_received; 00086 /*---------------------------------------------------------------------------*/ 00087 #define SIR1 (P1OUT |= 0x01) ///< MACRO: Puts IR sending diode high. 00088 #define SIR0 (P1OUT &= 0xFE) ///< MACRO: Puts IR sending diode low. 00089 #define BIT75 3282 ///< 3 quarters of a bit after start, 3282 cyc @ 2,4576Mhz = 1335us. 00090 #define BIT50 2188 ///< Half of bit length, 2188 cyc @ 2,4576Mhz = 890 us. 00091 00092 /*---------------------------------------------------------------------------*/ 00093 /* Sends a logical one via IR, method is timed for the 2.4576Mhz SMCLK!!! 00094 */ 00095 static volatile void 00096 send1bit(void) 00097 { 00098 volatile int i; 00099 for(i = 0; i < 34; ++i) { 00100 SIR1; SIR1; SIR1; SIR1; 00101 SIR0; SIR0; SIR0; SIR0; 00102 SIR0; SIR0; SIR0; SIR0; 00103 SIR0; 00104 } 00105 } 00106 /*---------------------------------------------------------------------------*/ 00107 /* Sends a logical 0 via IR, method is timed for the 2.4576Mhz SMCLK!!! 00108 */ 00109 static volatile void 00110 send0bit(void) 00111 { 00112 volatile int i; 00113 for(i = 0; i < 34; ++i) { 00114 SIR0; SIR0; SIR0; SIR0; 00115 SIR0; SIR0; SIR0; SIR0; 00116 SIR0; SIR0; SIR0; SIR0; 00117 SIR0; 00118 } 00119 } 00120 /*---------------------------------------------------------------------------*/ 00121 /* Sends the lower 12 bits of data via IR, turns interrupt off while 00122 it's sending. 00123 */ 00124 void 00125 ir_send(unsigned short data) 00126 { 00127 volatile unsigned short mask = 0x2000; 00128 data |= 0xF000; 00129 00130 dint(); 00131 while(mask != 0){ 00132 if(!(mask & data)){ 00133 send1bit(); 00134 send0bit(); 00135 } else { 00136 send0bit(); 00137 send1bit(); 00138 } 00139 mask /= 2; 00140 } 00141 eint(); 00142 } 00143 /*---------------------------------------------------------------------------*/ 00144 /* Testroutine which repetedly sends two commands. 00145 */ 00146 /*void 00147 ir_test_send(void) 00148 { 00149 volatile unsigned int i; 00150 send12bits(0xF010); 00151 for(i=0; i<0xFFFF; i++) nop(); 00152 send12bits(0xF011); 00153 for(i=0; i<0xFFFF; i++) nop(); 00154 }*/ 00155 /*---------------------------------------------------------------------------*/ 00156 00157 00158 static void setErrorBit(void); 00159 static void clearErrorBit(void); 00160 static void setDataAvailableBit(void); 00161 static void clearDataAvailableBit(void); 00162 00163 00164 /// \name Internal variables. 00165 //@{ 00166 static unsigned int ir_pos; ///< current position in frame 00167 static unsigned int recvdata; ///< here a received packet is saved 00168 static unsigned int recvdatabuffer; ///< temporary buffer for receiving 00169 static unsigned char ir_temp; ///< saves the first half of the manchester bit 00170 //@} 00171 00172 /// \name Public functions. 00173 /// If ::recir_dataAvailable()==1 use the get* functions. 00174 //@{ 00175 unsigned char recir_getCode(void){ return (recvdata & 0x003F); } 00176 unsigned char recir_getAddress(void){ return ((recvdata & 0x07C0) >> 6); } 00177 unsigned char recir_getToggle(void){ return ((recvdata & 0x0800) >> 11); } 00178 unsigned char recir_getError(void){ return ((recvdata & 0x2000) >> 13); } 00179 00180 u16_t 00181 ir_data(void) 00182 { 00183 return recvdata; 00184 } 00185 00186 u8_t 00187 ir_poll(void) 00188 { 00189 if(recvdata & 0x1000) { 00190 clearDataAvailableBit(); 00191 return 1; 00192 } else { 00193 return 0; 00194 } 00195 } 00196 00197 00198 ///\name Internal functions. 00199 //@{ 00200 static void setErrorBit(void){ recvdata |= 0x2000; } 00201 static void clearErrorBit(void) { recvdata &= 0xDFFF; } 00202 static void setDataAvailableBit(void){ recvdata |= 0x1000; } 00203 static void clearDataAvailableBit(void){ recvdata &= 0xEFFF; } 00204 00205 00206 /// Timer B0 interrupt service routine 00207 interrupt(TIMERB1_VECTOR) Timer_B1 (void) { 00208 00209 /*P2OUT = (P2OUT & 0xf7) | (8 - (P2OUT & 0x08));*/ 00210 00211 if(ir_pos <= 25) { 00212 if(ir_pos % 2) { // odd position 00213 if(ir_temp && !(P1IN & 0x04)) { // 1 - 0 --> write 1 00214 recvdatabuffer +=1; 00215 recvdatabuffer = recvdatabuffer << 1; 00216 } else if(!ir_temp && (P1IN & 0x04)) { // 0 - 1 --> write 0 00217 recvdatabuffer = recvdatabuffer << 1; 00218 } else { 00219 setErrorBit(); 00220 if(P1IN & 0x04) { 00221 recvdatabuffer += 1; 00222 } 00223 recvdatabuffer = recvdatabuffer << 1; 00224 } 00225 } else { // even position 00226 ir_temp = P1IN & 0x04; 00227 } 00228 } 00229 00230 if(ir_pos == 25) { // end reached 00231 recvdatabuffer = recvdatabuffer >> 1; 00232 00233 if(!recir_getError() && ( (recvdatabuffer & 0x0FFF) != (recvdata & 0x0FFF) ) ){ 00234 recvdata = recvdatabuffer; 00235 setDataAvailableBit(); 00236 } else { 00237 _NOP(); 00238 } 00239 } 00240 00241 if(ir_pos==27) { 00242 TBCCTL1 &= ~CCIE; 00243 00244 //GREENOFF; 00245 // temporary debug output 00246 //sendRS232Address(recvdatabuffer); 00247 //if(recir_getError()) sendRS232('E'); 00248 //sendRS232String("\r\n"); 00249 if(!recir_getError()) beep_beep(20); 00250 00251 // reenable interrupt for falling edge 00252 P1IFG &= ~(0x04); 00253 P1IE |= 0x04; // enable interrupt for recir RC5 00254 leds_off(LEDS_RED); 00255 } 00256 00257 ir_pos++; 00258 TBCCR1 += BIT50; // set new interrupt 00259 00260 TBCCTL1 &= ~CCIFG; 00261 } 00262 00263 00264 /** \brief IR Interrupt routine 00265 ** 00266 ** For the falling edge (start of RC5 packet)( mid of first start bit ), IRReceiver is on P12 00267 ** real interrupt routine, which calls this, is in sensors.c */ 00268 void 00269 ir_irq(void) 00270 { 00271 if(P1IN & 0x04) return; // high again, just a peak 00272 00273 ir_pos = 0; 00274 recvdatabuffer = 0; 00275 clearErrorBit(); 00276 00277 // the first timer interrupt will occur in the mid of the first half of the second start bit 00278 TBCCR1 = TBR + BIT75; // set first TBCCR1 IRQ to 75% of RC5 bitlength 00279 TBCCTL1 &= ~CCIFG; // clear previous compare flag 00280 TBCCTL1 |= CCIE; // CCR0 interrupt enabled, interrupt occurs when timer equals CCR0 00281 00282 P1IE &= ~0x04; // disable interrupt for P12 ( ReceiveIR ) 00283 leds_on(LEDS_RED); 00284 //GREENON; 00285 } 00286 00287 //@} 00288 /*---------------------------------------------------------------------*/ 00289 PROCESS_THREAD(ir_process, ev, data) 00290 { 00291 PROCESS_BEGIN(); 00292 00293 // init TIMERB ccr0 to run continouslycreate the 5 ms interval 00294 // ccr1 is used for ir receiving (RC5) 00295 TBCTL = TBSSEL1 + TBCLR; // select SMCLK (2.4576MHz), clear TBR 00296 TBCTL |= MC1; // Start Timer_A in continuous mode 00297 00298 00299 P1IES |= 0x04; // Important for IR-RC5 receive to detect the first FALLING edge 00300 00301 ir_event_received = process_alloc_event(); 00302 00303 while(1) { 00304 PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_POLL); 00305 00306 if(ir_poll() == IR_DATA) { 00307 unsigned short irdata; 00308 irdata = ir_data() & 0x7ff; 00309 process_post(PROCESS_BROADCAST, ir_event_received, (process_data_t)irdata); 00310 } 00311 00312 } 00313 00314 PROCESS_END(); 00315 } 00316 /*---------------------------------------------------------------------*/