Contiki 2.6
|
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 "contiki.h" 00077 #include "dev/ir.h" 00078 00079 #include "dev/leds.h" 00080 #include "dev/beep.h" 00081 #include "isr_compat.h" 00082 00083 PROCESS(ir_process, "IR receiver"); 00084 process_event_t ir_event_received; 00085 /*---------------------------------------------------------------------------*/ 00086 #define SIR1 (P1OUT |= 0x01) ///< MACRO: Puts IR sending diode high. 00087 #define SIR0 (P1OUT &= 0xFE) ///< MACRO: Puts IR sending diode low. 00088 #define BIT75 3282 ///< 3 quarters of a bit after start, 3282 cyc @ 2,4576Mhz = 1335us. 00089 #define BIT50 2188 ///< Half of bit length, 2188 cyc @ 2,4576Mhz = 890 us. 00090 00091 /*---------------------------------------------------------------------------*/ 00092 /* Sends a logical one via IR, method is timed for the 2.4576Mhz SMCLK!!! 00093 */ 00094 static volatile void 00095 send1bit(void) 00096 { 00097 volatile int i; 00098 for(i = 0; i < 34; ++i) { 00099 SIR1; SIR1; SIR1; SIR1; 00100 SIR0; SIR0; SIR0; SIR0; 00101 SIR0; SIR0; SIR0; SIR0; 00102 SIR0; 00103 } 00104 } 00105 /*---------------------------------------------------------------------------*/ 00106 /* Sends a logical 0 via IR, method is timed for the 2.4576Mhz SMCLK!!! 00107 */ 00108 static volatile void 00109 send0bit(void) 00110 { 00111 volatile int i; 00112 for(i = 0; i < 34; ++i) { 00113 SIR0; SIR0; SIR0; SIR0; 00114 SIR0; SIR0; SIR0; SIR0; 00115 SIR0; SIR0; SIR0; SIR0; 00116 SIR0; 00117 } 00118 } 00119 /*---------------------------------------------------------------------------*/ 00120 /* Sends the lower 12 bits of data via IR, turns interrupt off while 00121 it's sending. 00122 */ 00123 void 00124 ir_send(unsigned short data) 00125 { 00126 volatile unsigned short mask = 0x2000; 00127 data |= 0xF000; 00128 00129 dint(); 00130 while(mask != 0){ 00131 if(!(mask & data)){ 00132 send1bit(); 00133 send0bit(); 00134 } else { 00135 send0bit(); 00136 send1bit(); 00137 } 00138 mask /= 2; 00139 } 00140 eint(); 00141 } 00142 /*---------------------------------------------------------------------------*/ 00143 /* Testroutine which repetedly sends two commands. 00144 */ 00145 /*void 00146 ir_test_send(void) 00147 { 00148 volatile unsigned int i; 00149 send12bits(0xF010); 00150 for(i=0; i<0xFFFF; i++) nop(); 00151 send12bits(0xF011); 00152 for(i=0; i<0xFFFF; i++) nop(); 00153 }*/ 00154 /*---------------------------------------------------------------------------*/ 00155 00156 00157 static void setErrorBit(void); 00158 static void clearErrorBit(void); 00159 static void setDataAvailableBit(void); 00160 static void clearDataAvailableBit(void); 00161 00162 00163 /// \name Internal variables. 00164 //@{ 00165 static unsigned int ir_pos; ///< current position in frame 00166 static unsigned int recvdata; ///< here a received packet is saved 00167 static unsigned int recvdatabuffer; ///< temporary buffer for receiving 00168 static unsigned char ir_temp; ///< saves the first half of the manchester bit 00169 //@} 00170 00171 /// \name Public functions. 00172 /// If ::recir_dataAvailable()==1 use the get* functions. 00173 //@{ 00174 unsigned char recir_getCode(void){ return (recvdata & 0x003F); } 00175 unsigned char recir_getAddress(void){ return ((recvdata & 0x07C0) >> 6); } 00176 unsigned char recir_getToggle(void){ return ((recvdata & 0x0800) >> 11); } 00177 unsigned char recir_getError(void){ return ((recvdata & 0x2000) >> 13); } 00178 00179 uint16_t 00180 ir_data(void) 00181 { 00182 return recvdata; 00183 } 00184 00185 uint8_t 00186 ir_poll(void) 00187 { 00188 if(recvdata & 0x1000) { 00189 clearDataAvailableBit(); 00190 return 1; 00191 } else { 00192 return 0; 00193 } 00194 } 00195 00196 00197 ///\name Internal functions. 00198 //@{ 00199 static void setErrorBit(void){ recvdata |= 0x2000; } 00200 static void clearErrorBit(void) { recvdata &= 0xDFFF; } 00201 static void setDataAvailableBit(void){ recvdata |= 0x1000; } 00202 static void clearDataAvailableBit(void){ recvdata &= 0xEFFF; } 00203 00204 00205 /// Timer B0 interrupt service routine 00206 ISR(TIMERB1, Timer_B1) { 00207 00208 /*P2OUT = (P2OUT & 0xf7) | (8 - (P2OUT & 0x08));*/ 00209 00210 if(ir_pos <= 25) { 00211 if(ir_pos % 2) { // odd position 00212 if(ir_temp && !(P1IN & 0x04)) { // 1 - 0 --> write 1 00213 recvdatabuffer +=1; 00214 recvdatabuffer = recvdatabuffer << 1; 00215 } else if(!ir_temp && (P1IN & 0x04)) { // 0 - 1 --> write 0 00216 recvdatabuffer = recvdatabuffer << 1; 00217 } else { 00218 setErrorBit(); 00219 if(P1IN & 0x04) { 00220 recvdatabuffer += 1; 00221 } 00222 recvdatabuffer = recvdatabuffer << 1; 00223 } 00224 } else { // even position 00225 ir_temp = P1IN & 0x04; 00226 } 00227 } 00228 00229 if(ir_pos == 25) { // end reached 00230 recvdatabuffer = recvdatabuffer >> 1; 00231 00232 if(!recir_getError() && ( (recvdatabuffer & 0x0FFF) != (recvdata & 0x0FFF) ) ){ 00233 recvdata = recvdatabuffer; 00234 setDataAvailableBit(); 00235 } else { 00236 _NOP(); 00237 } 00238 } 00239 00240 if(ir_pos==27) { 00241 TBCCTL1 &= ~CCIE; 00242 00243 //GREENOFF; 00244 // temporary debug output 00245 //sendRS232Address(recvdatabuffer); 00246 //if(recir_getError()) sendRS232('E'); 00247 //sendRS232String("\r\n"); 00248 if(!recir_getError()) beep_beep(20); 00249 00250 // reenable interrupt for falling edge 00251 P1IFG &= ~(0x04); 00252 P1IE |= 0x04; // enable interrupt for recir RC5 00253 leds_off(LEDS_RED); 00254 } 00255 00256 ir_pos++; 00257 TBCCR1 += BIT50; // set new interrupt 00258 00259 TBCCTL1 &= ~CCIFG; 00260 } 00261 00262 00263 /** \brief IR Interrupt routine 00264 ** 00265 ** For the falling edge (start of RC5 packet)( mid of first start bit ), IRReceiver is on P12 00266 ** real interrupt routine, which calls this, is in sensors.c */ 00267 void 00268 ir_irq(void) 00269 { 00270 if(P1IN & 0x04) return; // high again, just a peak 00271 00272 ir_pos = 0; 00273 recvdatabuffer = 0; 00274 clearErrorBit(); 00275 00276 // the first timer interrupt will occur in the mid of the first half of the second start bit 00277 TBCCR1 = TBR + BIT75; // set first TBCCR1 IRQ to 75% of RC5 bitlength 00278 TBCCTL1 &= ~CCIFG; // clear previous compare flag 00279 TBCCTL1 |= CCIE; // CCR0 interrupt enabled, interrupt occurs when timer equals CCR0 00280 00281 P1IE &= ~0x04; // disable interrupt for P12 ( ReceiveIR ) 00282 leds_on(LEDS_RED); 00283 //GREENON; 00284 } 00285 00286 //@} 00287 /*---------------------------------------------------------------------*/ 00288 PROCESS_THREAD(ir_process, ev, data) 00289 { 00290 PROCESS_BEGIN(); 00291 00292 // init TIMERB ccr0 to run continouslycreate the 5 ms interval 00293 // ccr1 is used for ir receiving (RC5) 00294 TBCTL = TBSSEL1 + TBCLR; // select SMCLK (2.4576MHz), clear TBR 00295 TBCTL |= MC1; // Start Timer_A in continuous mode 00296 00297 00298 P1IES |= 0x04; // Important for IR-RC5 receive to detect the first FALLING edge 00299 00300 ir_event_received = process_alloc_event(); 00301 00302 while(1) { 00303 PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_POLL); 00304 00305 if(ir_poll() == IR_DATA) { 00306 unsigned short irdata; 00307 irdata = ir_data() & 0x7ff; 00308 process_post(PROCESS_BROADCAST, ir_event_received, (process_data_t)irdata); 00309 } 00310 00311 } 00312 00313 PROCESS_END(); 00314 } 00315 /*---------------------------------------------------------------------*/