Subversion Repositories HomeAutomation

Rev

Rev 613 | Rev 1415 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * IR receiver and transmitter driver.
  3.  *
  4.  * @date    2006-12-10
  5.  *
  6.  * @author  Anders Runeson, Andreas Fritiofson
  7.  *  
  8.  */
  9.  
  10. /*-----------------------------------------------------------------------------
  11.  * Includes
  12.  *---------------------------------------------------------------------------*/
  13. #include <config.h>
  14. #include <drivers/ir/transceiver/irtransceiver.h>
  15. #include <drivers/ir/protocols.h>
  16. #include <avr/io.h>
  17. #include <avr/interrupt.h>
  18.  
  19. /*-----------------------------------------------------------------------------
  20.  * Globals
  21.  *---------------------------------------------------------------------------*/
  22. uint16_t *rxbuf, *txbuf;
  23. uint8_t rxlen, txlen;
  24.  
  25. static uint8_t bufIndex;                            //selects the pulse width in buffer to send
  26. volatile uint8_t data_received;
  27. volatile uint8_t data_transmitted;
  28. uint8_t detect_edge;
  29. uint8_t store;
  30.  
  31. /*-----------------------------------------------------------------------------
  32.  * Prerequisites
  33.  *---------------------------------------------------------------------------*/
  34. #define IR_RX_ACTIVE_LOW    1
  35. #define IR_TX_ACTIVE_LOW    0       //Only 0 is implemented
  36.  
  37.  
  38. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
  39. #define TIMSK1  TIMSK
  40. #define TIFR1   TIFR
  41. #define ICIE1   TICIE1
  42. #endif
  43.  
  44. #define IR_COMPARE_VECTOR       TIMER1_COMPB_vect
  45. #define IR_TIMEOUT_VECTOR       TIMER1_COMPA_vect
  46. #define IR_CAPTURE_VECTOR       TIMER1_CAPT_vect
  47. #define IR_TIMEOUT_REG          OCR1A
  48. #define IR_COMPARE_REG          OCR1B
  49. #define IR_CAPTURE_REG          ICR1
  50. #define IR_COUNT_REG            TCNT1
  51. #define IR_MODULATION_REG       OCR0A
  52. #define IR_TIMER_INIT()         TCCR1A = 0; \
  53.                                 TCCR1B = (1<<ICNC1)|(2<<CS10);
  54. #define IR_MASK_COMPARE()       TIMSK1 &= ~(1<<OCIE1B);
  55. #define IR_UNMASK_COMPARE()     TIFR1 = (1<<OCF1B); TIMSK1 |= (1<<OCIE1B);
  56. #define IR_MASK_TIMEOUT()       TIMSK1 &= ~(1<<OCIE1A);
  57. #define IR_UNMASK_TIMEOUT()     TIFR1 = (1<<OCF1A); TIMSK1 |= (1<<OCIE1A);
  58. #define IR_MASK_CAPTURE()       TIMSK1 &= ~(1<<ICIE1);
  59. #define IR_UNMASK_CAPTURE()     TIFR1 = (1<<ICF1); TIMSK1 |= (1<<ICIE1);
  60. #define IR_CAPTURE_FALLING()    TCCR1B &= ~(1<<ICES1); \
  61.                                 TIFR1 = (1<<ICF1);
  62. #define IR_CAPTURE_RISING()     TCCR1B |= (1<<ICES1); \
  63.                                 TIFR1 = (1<<ICF1);
  64.  
  65. //TODO: if active low is 0 then make port 5V at "LOW"
  66. #if IR_TX_ACTIVE_LOW==1
  67. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  68. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  69. #else
  70. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  71. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  72. #endif
  73.  
  74.  
  75. /*-----------------------------------------------------------------------------
  76.  * Interrupt Handlers
  77.  *---------------------------------------------------------------------------*/
  78.  
  79. ISR(IR_COMPARE_VECTOR)
  80. {
  81.     if ((bufIndex&1) == 1) {        /* if odd, ir-pause */
  82.         IR_OUTP_LOW();
  83.     } else {
  84.         IR_OUTP_HIGH();
  85.     }
  86.    
  87.     if (bufIndex < txlen)
  88.     {
  89.         IR_COMPARE_REG += txbuf[bufIndex++];       
  90.         //IR_COMPARE_REG += *(txbuf + bufIndex++);     
  91.     }
  92.     else
  93.     {
  94.         IR_MASK_COMPARE();
  95.         data_transmitted = 1;
  96.     }
  97. }
  98.  
  99. ISR(IR_TIMEOUT_VECTOR)
  100. {
  101.     if (rxlen)
  102.     {
  103.         /* Disable interrupts until the application has taken action on the
  104.          * current data and reenabled reception. */
  105.         IR_MASK_CAPTURE();
  106.         IR_MASK_TIMEOUT();
  107.         /* Notify the application that a pulse train has been received. */
  108.         data_received = 1;
  109.     }
  110.     store = 0;
  111. }
  112.  
  113. ISR(IR_CAPTURE_VECTOR)
  114. {
  115.     static uint16_t prev_time;
  116.     uint16_t pulsewidth;
  117.  
  118.     /* Read the measured transition time from the capture register. */
  119.     uint16_t time = IR_CAPTURE_REG;
  120.    
  121.     /* Toggle the edge detection. */
  122.     if (detect_edge == 0)
  123.     {
  124.         IR_CAPTURE_RISING();
  125.         detect_edge = 1;
  126.     }
  127.     else
  128.     {
  129.         IR_CAPTURE_FALLING();
  130.         detect_edge = 0;
  131.     }
  132.    
  133.     /* Subtract the current measurement from the previous to get the pulse
  134.      * width. */
  135.     pulsewidth = time - prev_time;
  136.     prev_time = time;
  137.    
  138.     /* Set the timeout. */
  139.     IR_TIMEOUT_REG = time + IR_MAX_PULSE_WIDTH;
  140.    
  141.     if (store)
  142.     {
  143.         /* Store the measurement. */
  144.         rxbuf[rxlen++] = pulsewidth;
  145.         //*(rxbuf+rxlen++) = pulsewidth;
  146.         /* Disable future measurements if we've filled the buffer. */
  147.         //TODO: Report overflow to application
  148.         if (rxlen == MAX_NR_TIMES)
  149.         {
  150.             IR_MASK_CAPTURE();
  151.         }
  152.     }
  153.     else
  154.     {
  155.         /* The first edge of the pulse train has been detected. Enable the
  156.          * storage of the following pulsewidths. */
  157.         store = 1;
  158.         /* Enable timeout interrupt for detection of the end of the pulse
  159.          * train. */
  160.         IR_UNMASK_TIMEOUT();
  161.     }
  162. }
  163.  
  164.  
  165.  
  166. /*-----------------------------------------------------------------------------
  167.  * Public Functions
  168.  *---------------------------------------------------------------------------*/
  169.  
  170. void IrTransceiver_Init(void)
  171. {
  172.     /* Set up receiver */
  173.     IR_TIMER_INIT();
  174.     IR_TIMEOUT_REG = IR_MAX_PULSE_WIDTH;
  175.     IR_R_DDR &= ~(1<<IR_R_BIT);
  176.     //DDRC |= (1<<PC5);
  177.    
  178.     /* Set up transmitter */
  179.     IR_T_DDR |= (1<<IR_T_BIT);
  180.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
  181.     TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00);
  182.     TCCR0B = (0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02);
  183.     #endif
  184.  
  185. }
  186.  
  187. void IrTransceiver_Receive_Start(uint16_t *buffer)
  188. {
  189.      /* Setup buffer and arm the edge detection. */
  190.     rxbuf = buffer;
  191.     rxlen = 0;
  192.     data_received = 0;
  193.     store = 0;
  194. #if (IR_RX_ACTIVE_LOW == 1)
  195.     IR_CAPTURE_FALLING();
  196.     detect_edge = 0;
  197. #else
  198.     IR_CAPTURE_RISING();
  199.     detect_edge = 1;
  200. #endif
  201.     IR_UNMASK_CAPTURE();
  202. }
  203.  
  204. uint8_t IrTransceiver_Receive_Poll(uint8_t *len)
  205. {
  206.     *len = rxlen;
  207.     if (data_received)
  208.     {
  209.         return IR_OK;
  210.     }
  211.     else if (rxlen > 0)
  212.     {
  213.         return IR_NOT_FINISHED;
  214.     } else {
  215.         return IR_NO_DATA;
  216.     }
  217. }
  218.  
  219. uint8_t IrTransceiver_Transmit_Poll(void) {
  220.     if (data_transmitted == 0) {
  221.         return IR_NOT_FINISHED;
  222.     } else {
  223.         return IR_OK;
  224.     }
  225. }
  226.  
  227. uint8_t IrTransceiver_Transmit(uint16_t *buffer, uint8_t length, uint8_t modfreq)
  228. {
  229.     data_transmitted = 0;
  230.    
  231.     if (length == 0) return IR_NO_DATA;
  232.  
  233.     txbuf = buffer;
  234.     txlen = length;
  235.     bufIndex = 1;
  236.    
  237.     IR_MODULATION_REG = modfreq;
  238.    
  239.     IR_COMPARE_REG = IR_COUNT_REG + txbuf[0];
  240.    
  241.     IR_OUTP_HIGH();
  242.    
  243.     IR_UNMASK_COMPARE();
  244.    
  245.     //while (!data_transmitted);
  246.    
  247.     return IR_OK;
  248. }
  249.