Subversion Repositories HomeAutomation

Rev

Rev 1415 | Rev 1468 | 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. #ifndef IR_TX_ACTIVE_LOW
  35. #define IR_TX_ACTIVE_LOW    0
  36. #endif
  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. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  66. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  67.  
  68.  
  69. /*-----------------------------------------------------------------------------
  70.  * Interrupt Handlers
  71.  *---------------------------------------------------------------------------*/
  72.  
  73. ISR(IR_COMPARE_VECTOR)
  74. {
  75.     if ((bufIndex&1) == 1) {        /* if odd, ir-pause */
  76.         IR_OUTP_LOW();
  77.     } else {
  78.         IR_OUTP_HIGH();
  79.     }
  80.    
  81.     //The following three lines is just to allow a start signal to be zero.
  82. /*  bufIndex++;
  83.     while (txbuf[bufIndex] == 0){
  84.         bufIndex++;
  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__) || defined(__AVR_ATmega328P__)
  181.     TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00);
  182.     TCCR0B = (0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02);
  183.     #endif
  184.    
  185. #if IR_TX_ACTIVE_LOW==1
  186.     /* when pwm is disconnected from port (during low) the port should output 5V */
  187.     IR_T_PORT |= (1<<IR_T_BIT);
  188. #else
  189.     /* when pwm is disconnected from port (during low) the port should output 0V */
  190.     IR_T_PORT &= ~(1<<IR_T_BIT);
  191. #endif
  192. }
  193.  
  194. void IrTransceiver_Receive_Start(uint16_t *buffer)
  195. {
  196.      /* Setup buffer and arm the edge detection. */
  197.     rxbuf = buffer;
  198.     rxlen = 0;
  199.     data_received = 0;
  200.     store = 0;
  201. #if (IR_RX_ACTIVE_LOW == 1)
  202.     IR_CAPTURE_FALLING();
  203.     detect_edge = 0;
  204. #else
  205.     IR_CAPTURE_RISING();
  206.     detect_edge = 1;
  207. #endif
  208.     IR_UNMASK_CAPTURE();
  209. }
  210.  
  211. uint8_t IrTransceiver_Receive_Poll(uint8_t *len)
  212. {
  213.     *len = rxlen;
  214.     if (data_received)
  215.     {
  216.         return IR_OK;
  217.     }
  218.     else if (rxlen > 0)
  219.     {
  220.         return IR_NOT_FINISHED;
  221.     } else {
  222.         return IR_NO_DATA;
  223.     }
  224. }
  225.  
  226. uint8_t IrTransceiver_Transmit_Poll(void) {
  227.     if (data_transmitted == 0) {
  228.         return IR_NOT_FINISHED;
  229.     } else {
  230.         return IR_OK;
  231.     }
  232. }
  233.  
  234. uint8_t IrTransceiver_Transmit(uint16_t *buffer, uint8_t length, uint8_t modfreq)
  235. {
  236.     data_transmitted = 0;
  237.    
  238.     if (length == 0) return IR_NO_DATA;
  239.  
  240.     txbuf = buffer;
  241.     txlen = length;
  242.     bufIndex = 1;
  243.    
  244.     IR_MODULATION_REG = modfreq;
  245.    
  246.     IR_COMPARE_REG = IR_COUNT_REG + txbuf[0];
  247.    
  248.     IR_OUTP_HIGH();
  249.    
  250.     IR_UNMASK_COMPARE();
  251.    
  252.     //while (!data_transmitted);
  253.    
  254.     return IR_OK;
  255. }
  256.