Subversion Repositories HomeAutomation

Rev

Rev 1435 | Rev 1972 | 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. #if IR_RX_ENABLE==1
  23. uint16_t *rxbuf;
  24. uint8_t rxlen;
  25. #endif
  26. #if IR_TX_ENABLE==1
  27. uint16_t *txbuf;
  28. uint8_t txlen;
  29. #endif
  30.  
  31. #if IR_TX_ENABLE==1
  32. static uint8_t bufIndex;                            //selects the pulse width in buffer to send
  33. #endif
  34. volatile uint8_t data_received;
  35. volatile uint8_t data_transmitted;
  36. uint8_t detect_edge;
  37. uint8_t store;
  38.  
  39. /*-----------------------------------------------------------------------------
  40.  * Prerequisites
  41.  *---------------------------------------------------------------------------*/
  42. #ifndef IR_RX_ACTIVE_LOW
  43. #define IR_RX_ACTIVE_LOW    1
  44. #endif
  45.  
  46. #ifndef IR_TX_ACTIVE_LOW
  47. #define IR_TX_ACTIVE_LOW    0
  48. #endif
  49.  
  50. #ifndef IR_TX_ENABLE
  51. #define IR_TX_ENABLE    0
  52. #endif
  53.  
  54. #ifndef IR_RX_ENABLE
  55. #define IR_RX_ENABLE    0
  56. #endif
  57.  
  58.  
  59. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
  60. #define TIMSK1  TIMSK
  61. #define TIFR1   TIFR
  62. #define ICIE1   TICIE1
  63. #endif
  64.  
  65. #define IR_COMPARE_VECTOR       TIMER1_COMPB_vect
  66. #define IR_TIMEOUT_VECTOR       TIMER1_COMPA_vect
  67. #define IR_CAPTURE_VECTOR       TIMER1_CAPT_vect
  68. #define IR_TIMEOUT_REG          OCR1A
  69. #define IR_COMPARE_REG          OCR1B
  70. #define IR_CAPTURE_REG          ICR1
  71. #define IR_COUNT_REG            TCNT1
  72. #define IR_MODULATION_REG       OCR0A
  73. #define IR_TIMER_INIT()         TCCR1A = 0; \
  74.                                 TCCR1B = (1<<ICNC1)|(2<<CS10);
  75. #define IR_MASK_COMPARE()       TIMSK1 &= ~(1<<OCIE1B);
  76. #define IR_UNMASK_COMPARE()     TIFR1 = (1<<OCF1B); TIMSK1 |= (1<<OCIE1B);
  77. #define IR_MASK_TIMEOUT()       TIMSK1 &= ~(1<<OCIE1A);
  78. #define IR_UNMASK_TIMEOUT()     TIFR1 = (1<<OCF1A); TIMSK1 |= (1<<OCIE1A);
  79. #define IR_MASK_CAPTURE()       TIMSK1 &= ~(1<<ICIE1);
  80. #define IR_UNMASK_CAPTURE()     TIFR1 = (1<<ICF1); TIMSK1 |= (1<<ICIE1);
  81. #define IR_CAPTURE_FALLING()    TCCR1B &= ~(1<<ICES1); \
  82.                                 TIFR1 = (1<<ICF1);
  83. #define IR_CAPTURE_RISING()     TCCR1B |= (1<<ICES1); \
  84.                                 TIFR1 = (1<<ICF1);
  85.  
  86. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  87. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  88.  
  89.  
  90. /*-----------------------------------------------------------------------------
  91.  * Interrupt Handlers
  92.  *---------------------------------------------------------------------------*/
  93.  
  94. #if IR_TX_ENABLE==1
  95. ISR(IR_COMPARE_VECTOR)
  96. {
  97.     if ((bufIndex&1) == 1) {        /* if odd, ir-pause */
  98.         IR_OUTP_LOW();
  99.     } else {
  100.         IR_OUTP_HIGH();
  101.     }
  102.    
  103.     //The following three lines is just to allow a start signal to be zero.
  104. /*  bufIndex++;
  105.     while (txbuf[bufIndex] == 0){
  106.         bufIndex++;
  107.     }*/
  108.    
  109.     if (bufIndex < txlen)
  110.     {      
  111.         IR_COMPARE_REG += txbuf[bufIndex++];       
  112.         //IR_COMPARE_REG += *(txbuf + bufIndex++);     
  113.     }
  114.     else
  115.     {
  116.         IR_MASK_COMPARE();
  117.         data_transmitted = 1;
  118.     }
  119. }
  120. #endif
  121.  
  122. #if IR_RX_ENABLE==1
  123. ISR(IR_TIMEOUT_VECTOR)
  124. {
  125.     if (rxlen)
  126.     {
  127.         /* Disable interrupts until the application has taken action on the
  128.          * current data and reenabled reception. */
  129.         IR_MASK_CAPTURE();
  130.         IR_MASK_TIMEOUT();
  131.         /* Notify the application that a pulse train has been received. */
  132.         data_received = 1;
  133.     }
  134.     store = 0;
  135. }
  136. #endif
  137.  
  138. #if IR_RX_ENABLE==1
  139. ISR(IR_CAPTURE_VECTOR)
  140. {
  141.     static uint16_t prev_time;
  142.     uint16_t pulsewidth;
  143.  
  144.     /* Read the measured transition time from the capture register. */
  145.     uint16_t time = IR_CAPTURE_REG;
  146.    
  147.     /* Toggle the edge detection. */
  148.     if (detect_edge == 0)
  149.     {
  150.         IR_CAPTURE_RISING();
  151.         detect_edge = 1;
  152.     }
  153.     else
  154.     {
  155.         IR_CAPTURE_FALLING();
  156.         detect_edge = 0;
  157.     }
  158.    
  159.     /* Subtract the current measurement from the previous to get the pulse
  160.      * width. */
  161.     pulsewidth = time - prev_time;
  162.     prev_time = time;
  163.    
  164.     /* Set the timeout. */
  165.     IR_TIMEOUT_REG = time + IR_MAX_PULSE_WIDTH;
  166.    
  167.     if (store)
  168.     {
  169.         /* Store the measurement. */
  170.         rxbuf[rxlen++] = pulsewidth;
  171.         //*(rxbuf+rxlen++) = pulsewidth;
  172.         /* Disable future measurements if we've filled the buffer. */
  173.         //TODO: Report overflow to application
  174.         if (rxlen == MAX_NR_TIMES)
  175.         {
  176.             IR_MASK_CAPTURE();
  177.         }
  178.     }
  179.     else
  180.     {
  181.         /* The first edge of the pulse train has been detected. Enable the
  182.          * storage of the following pulsewidths. */
  183.         store = 1;
  184.         /* Enable timeout interrupt for detection of the end of the pulse
  185.          * train. */
  186.         IR_UNMASK_TIMEOUT();
  187.     }
  188. }
  189. #endif
  190.  
  191.  
  192. /*-----------------------------------------------------------------------------
  193.  * Public Functions
  194.  *---------------------------------------------------------------------------*/
  195.  
  196. void IrTransceiver_Init(void)
  197. {
  198.     IR_TIMER_INIT();
  199. #if IR_RX_ENABLE==1
  200.     /* Set up receiver */
  201.     IR_TIMEOUT_REG = IR_MAX_PULSE_WIDTH;
  202.     IR_R_DDR &= ~(1<<IR_R_BIT);
  203.     //DDRC |= (1<<PC5);
  204. #endif
  205.    
  206. #if IR_TX_ENABLE==1
  207.     /* Set up transmitter */
  208.     IR_T_DDR |= (1<<IR_T_BIT);
  209.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  210.     TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00);
  211.     TCCR0B = (0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02);
  212.     #endif
  213.    
  214. #if IR_TX_ACTIVE_LOW==1
  215.     /* when pwm is disconnected from port (during low) the port should output 5V */
  216.     IR_T_PORT |= (1<<IR_T_BIT);
  217. #else
  218.     /* when pwm is disconnected from port (during low) the port should output 0V */
  219.     IR_T_PORT &= ~(1<<IR_T_BIT);
  220. #endif
  221.  
  222. #endif
  223. }
  224.  
  225. void IrTransceiver_Receive_Start(uint16_t *buffer)
  226. {
  227. #if IR_RX_ENABLE==1
  228.      /* Setup buffer and arm the edge detection. */
  229.     rxbuf = buffer;
  230.     rxlen = 0;
  231.     data_received = 0;
  232.     store = 0;
  233. #if (IR_RX_ACTIVE_LOW == 1)
  234.     IR_CAPTURE_FALLING();
  235.     detect_edge = 0;
  236. #else
  237.     IR_CAPTURE_RISING();
  238.     detect_edge = 1;
  239. #endif
  240.     IR_UNMASK_CAPTURE();
  241. #endif
  242. }
  243.  
  244. uint8_t IrTransceiver_Receive_Poll(uint8_t *len)
  245. {
  246. #if IR_RX_ENABLE==1
  247.     *len = rxlen;
  248.     if (data_received)
  249.     {
  250.         return IR_OK;
  251.     }
  252.     else if (rxlen > 0)
  253.     {
  254.         return IR_NOT_FINISHED;
  255.     } else {
  256.         return IR_NO_DATA;
  257.     }
  258. #else
  259.     return 0;
  260. #endif
  261. }
  262.  
  263. uint8_t IrTransceiver_Transmit_Poll(void) {
  264. #if IR_TX_ENABLE==1
  265.     if (data_transmitted == 0) {
  266.         return IR_NOT_FINISHED;
  267.     } else {
  268.         return IR_OK;
  269.     }
  270. #else
  271.     return 0;
  272. #endif
  273. }
  274.  
  275. uint8_t IrTransceiver_Transmit(uint16_t *buffer, uint8_t length, uint8_t modfreq)
  276. {
  277. #if IR_TX_ENABLE==1
  278.     data_transmitted = 0;
  279.    
  280.     if (length == 0) return IR_NO_DATA;
  281.  
  282.     txbuf = buffer;
  283.     txlen = length;
  284.     bufIndex = 1;
  285.    
  286.     IR_MODULATION_REG = modfreq;
  287.    
  288.     IR_COMPARE_REG = IR_COUNT_REG + txbuf[0];
  289.    
  290.     IR_OUTP_HIGH();
  291.    
  292.     IR_UNMASK_COMPARE();
  293.    
  294.     //while (!data_transmitted);
  295.    
  296.     return IR_OK;
  297. #else
  298.     return 0;
  299. #endif
  300. }
  301.