Subversion Repositories HomeAutomation

Rev

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/irtransceiverMulti.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. uint8_t gPinB;
  39. uint8_t gPinC;
  40. uint8_t gPinD;
  41.  
  42.  
  43. /*-----------------------------------------------------------------------------
  44.  * Prerequisites
  45.  *---------------------------------------------------------------------------*/
  46. #ifndef IR_RX_ACTIVE_LOW
  47. #define IR_RX_ACTIVE_LOW    1
  48. #endif
  49.  
  50. #ifndef IR_TX_ACTIVE_LOW
  51. #define IR_TX_ACTIVE_LOW    0
  52. #endif
  53.  
  54. #ifndef IR_TX_ENABLE
  55. #define IR_TX_ENABLE    0
  56. #endif
  57.  
  58. #ifndef IR_RX_ENABLE
  59. #define IR_RX_ENABLE    0
  60. #endif
  61.  
  62.  
  63. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
  64. #define TIMSK1  TIMSK
  65. #define TIFR1   TIFR
  66. #define ICIE1   TICIE1
  67. #endif
  68.  
  69. #define IR_COMPARE_VECTOR       TIMER1_COMPB_vect
  70. #define IR_TIMEOUT_VECTOR       TIMER1_COMPA_vect
  71. #define IR_CAPTURE_VECTOR       TIMER1_CAPT_vect
  72. #define IR_TIMEOUT_REG          OCR1A
  73. #define IR_COMPARE_REG          OCR1B
  74. #define IR_CAPTURE_REG          ICR1
  75. #define IR_COUNT_REG            TCNT1
  76. #define IR_MODULATION_REG       OCR0A
  77. /*#define IR_TIMER_INIT()           TCCR1A = 0; \
  78.                                 TCCR1B = (1<<ICNC1)|(2<<CS10);
  79.                                 */
  80. #define IR_TIMER_INIT()         TCCR1A = 0; \
  81.                                 TCCR1B = (2<<CS10);
  82. #define IR_MASK_COMPARE()       TIMSK1 &= ~(1<<OCIE1B);
  83. #define IR_UNMASK_COMPARE()     TIFR1 = (1<<OCF1B); TIMSK1 |= (1<<OCIE1B);
  84. #define IR_MASK_TIMEOUT()       TIMSK1 &= ~(1<<OCIE1A);
  85. #define IR_UNMASK_TIMEOUT()     TIFR1 = (1<<OCF1A); TIMSK1 |= (1<<OCIE1A);
  86. #define IR_MASK_CAPTURE()       TIMSK1 &= ~(1<<ICIE1);
  87. #define IR_UNMASK_CAPTURE()     TIFR1 = (1<<ICF1); TIMSK1 |= (1<<ICIE1);
  88. #define IR_CAPTURE_FALLING()    TCCR1B &= ~(1<<ICES1); \
  89.                                 TIFR1 = (1<<ICF1);
  90. #define IR_CAPTURE_RISING()     TCCR1B |= (1<<ICES1); \
  91.                                 TIFR1 = (1<<ICF1);
  92.  
  93. #define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
  94. #define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
  95.  
  96.  
  97. /*-----------------------------------------------------------------------------
  98.  * Interrupt Handlers
  99.  *---------------------------------------------------------------------------*/
  100.  
  101.  
  102. /*
  103. timer 1 has two comprare registers and compare ISRs, one is used below for "timeout" on receive and the other is used here for transmitter
  104. //TODO: how to handle more than one transmitter on one compare interrupt, spara en array med tider och nån enableflagga för varje kanal
  105. */
  106.  
  107. #if IR_TX_ENABLE==1
  108. ISR(IR_COMPARE_VECTOR)
  109. {
  110.     if ((bufIndex&1) == 1) {        /* if odd, ir-pause */
  111.         IR_OUTP_LOW();
  112.     } else {
  113.         IR_OUTP_HIGH();
  114.     }
  115.    
  116.     //The following three lines is just to allow a start signal to be zero.
  117. /*  bufIndex++;
  118.     while (txbuf[bufIndex] == 0){
  119.         bufIndex++;
  120.     }*/
  121.    
  122.     if (bufIndex < txlen)
  123.     {      
  124.         IR_COMPARE_REG += txbuf[bufIndex++];       
  125.         //IR_COMPARE_REG += *(txbuf + bufIndex++);     
  126.     }
  127.     else
  128.     {
  129.         IR_MASK_COMPARE();
  130.         data_transmitted = 1;
  131.     }
  132. }
  133. #endif
  134.  
  135. #if IR_RX_ENABLE==1
  136. //TODO: hur hantera detta i multi receiver
  137. //TODO: ha en array med tider och nån enableflagga för varje kanal
  138. //TODO: mot slutet av ISRen laddas nästa tid in...
  139. ISR(IR_TIMEOUT_VECTOR)
  140. {
  141.     if (rxlen)
  142.     {
  143.         /* Disable interrupts until the application has taken action on the
  144.          * current data and reenabled reception. */
  145. //      IR_MASK_CAPTURE();
  146. //      IR_MASK_TIMEOUT();
  147.         PCMSK0 &= ~(1<<IR_TRANS_CH0_MASK);
  148.  
  149.         /* Notify the application that a pulse train has been received. */
  150.         data_received = 1;
  151.     }
  152.     store = 0;
  153. }
  154. #endif
  155.  
  156. #if IR_RX_ENABLE==1
  157.  
  158. //ISR(IR_CAPTURE_VECTOR)
  159. //TODO: skriv denna för multi receiver
  160. ISR(PCINT0_vect) {
  161. //  uint8_t p;
  162.     uint8_t rPinB=PINB;
  163.     uint8_t rPinC=PINC;
  164.     uint8_t rPinD=PIND;
  165.    
  166.     /* check if channel 0 pin was changed */
  167.     if ((rPinB ^ gPinB)&(1<<IR_TRANS_CH0_MASK))
  168.     {
  169.         IrTransceiver_Store(0);
  170.     }
  171.    
  172.     gPinB=rPinB;
  173.     gPinC=rPinC;
  174.     gPinD=rPinD;
  175. } /* ISR(PCINT0_vect) */
  176. #endif
  177.  
  178.  
  179. /*-----------------------------------------------------------------------------
  180.  * Private Functions
  181.  *---------------------------------------------------------------------------*/
  182.  
  183. #if IR_RX_ENABLE==1
  184. void IrTransceiver_Store(uint8_t channel)
  185. {
  186.     static uint16_t prev_time;
  187.     uint16_t pulsewidth;
  188.  
  189.     /* Read the measured transition time from the capture register. */
  190.     //uint16_t time = IR_CAPTURE_REG;
  191.     /* Read the timer counter register to get the current "time". */
  192.     uint16_t time = IR_COUNT_REG;
  193.    
  194.     /* Toggle the edge detection. */
  195. //  if (detect_edge == 0)
  196. //  {
  197. //      IR_CAPTURE_RISING();
  198. //      detect_edge = 1;
  199. //  }
  200. //  else
  201. //  {
  202. //      IR_CAPTURE_FALLING();
  203. //      detect_edge = 0;
  204. //  }
  205.    
  206.     /* Subtract the current measurement from the previous to get the pulse
  207.      * width. */
  208.     pulsewidth = time - prev_time;
  209.     prev_time = time;
  210.    
  211.     /* Set the timeout. */
  212.     IR_TIMEOUT_REG = time + IR_MAX_PULSE_WIDTH;
  213.    
  214.     if (store)
  215.     {
  216.         /* Store the measurement. */
  217.         rxbuf[rxlen++] = pulsewidth;
  218.         //*(rxbuf+rxlen++) = pulsewidth;
  219.         /* Disable future measurements if we've filled the buffer. */
  220.         //TODO: What to do in multi recevier?
  221.         //TODO: Report overflow to application
  222.         if (rxlen == MAX_NR_TIMES)
  223.         {
  224.             //IR_MASK_CAPTURE();
  225.         }
  226.     }
  227.     else
  228.     {
  229.         /* The first edge of the pulse train has been detected. Enable the
  230.          * storage of the following pulsewidths. */
  231.         store = 1;
  232.         /* Enable timeout interrupt for detection of the end of the pulse
  233.          * train. */
  234.         IR_UNMASK_TIMEOUT();
  235.     }
  236. }
  237. #endif
  238.  
  239.  
  240. /*-----------------------------------------------------------------------------
  241.  * Public Functions
  242.  *---------------------------------------------------------------------------*/
  243.  
  244. /* call this function like this:
  245.     IrTransceiver_Init_TX_Channel(0, buffer, callback, GPIO_D6);
  246.     buffer is a memory location
  247.     callback is a function to call when a receive/transmitt is complete
  248.     also call with IO port to use
  249.    
  250.     function to deactivate channel may later be needed
  251. */
  252. /*
  253. void IrTransceiver_Init_TX_Channel(uint8_t channel, uint16_t *buffer, irCallback_t callback, volatile uint8_t* port, volatile uint8_t* pin, volatile uint8_t* ddr,uint8_t nr, uint8_t pcint)
  254. {
  255.    
  256. }
  257.  
  258. void IrTransceiver_Init_RX_Channel(uint8_t channel, uint16_t *buffer, irCallback_t callback, volatile uint8_t* port, volatile uint8_t* pin, volatile uint8_t* ddr,uint8_t nr, uint8_t pcint)
  259. {
  260.    
  261. }
  262. */
  263.  
  264. void IrTransceiver_Init(void)
  265. {
  266.     IR_TIMER_INIT();
  267.    
  268. #if IR_RX_ENABLE==1
  269.     /* Set up receiver */
  270.     //IR_TIMEOUT_REG = IR_MAX_PULSE_WIDTH;
  271.     IR_R_DDR &= ~(1<<IR_R_BIT);
  272.     //DDRC |= (1<<PC5);
  273. #endif
  274.    
  275. #if IR_TX_ENABLE==1
  276.     /* Set up transmitter */
  277.     IR_T_DDR |= (1<<IR_T_BIT);
  278.     #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
  279.     TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00);
  280.     TCCR0B = (0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02);
  281.     #endif
  282.    
  283. #if IR_TX_ACTIVE_LOW==1
  284.     /* when pwm is disconnected from port (during low) the port should output 5V */
  285.     IR_T_PORT |= (1<<IR_T_BIT);
  286. #else
  287.     /* when pwm is disconnected from port (during low) the port should output 0V */
  288.     IR_T_PORT &= ~(1<<IR_T_BIT);
  289. #endif
  290.  
  291. #endif
  292.  
  293. }
  294.  
  295. void IrTransceiver_Receive_Start(uint16_t *buffer)
  296. {
  297. #if IR_RX_ENABLE==1
  298.      /* Setup buffer and arm the edge detection. */
  299.     rxbuf = buffer;
  300.     rxlen = 0;
  301.     data_received = 0;
  302.     store = 0;
  303. #if (IR_RX_ACTIVE_LOW == 1)
  304.     //IR_CAPTURE_FALLING();
  305.     //detect_edge = 0;
  306. #else
  307.     //IR_CAPTURE_RISING();
  308.     //detect_edge = 1;
  309. #endif
  310.     //IR_UNMASK_CAPTURE();
  311.  
  312.     gPinB=PINB;
  313.     gPinC=PINC;
  314.     gPinD=PIND;
  315.     PCIFR=(1<<PCIF0|1<<PCIF1|1<<PCIF2); /* clear any pending interrupt before enabling interrupts */
  316. //  PCICR|=(1<<PCIE0|1<<PCIE1|1<<PCIE2);    /* enable interrupt for PCINT0-2 */
  317.     PCICR|=(1<<PCIE0);  /* enable interrupt for PCINT0 */
  318.     PCMSK0 |= (1<<IR_TRANS_CH0_MASK);
  319. //  PCMSK1 |= (1<<pcints[pcint_id].pcintBit%8);
  320. //  PCMSK2 |= (1<<pcints[pcint_id].pcintBit%8);
  321. #endif
  322.  
  323. }
  324.  
  325. uint8_t IrTransceiver_Receive_Poll(uint8_t *len)
  326. {
  327. #if IR_RX_ENABLE==1
  328.     *len = rxlen;
  329.     if (data_received)
  330.     {
  331.         return IR_OK;
  332.     }
  333.     else if (rxlen > 0)
  334.     {
  335.         return IR_NOT_FINISHED;
  336.     } else {
  337.         return IR_NO_DATA;
  338.     }
  339. #else
  340.     return 0;
  341. #endif
  342. }
  343.  
  344. uint8_t IrTransceiver_Transmit_Poll(void) {
  345. #if IR_TX_ENABLE==1
  346.     if (data_transmitted == 0) {
  347.         return IR_NOT_FINISHED;
  348.     } else {
  349.         return IR_OK;
  350.     }
  351. #else
  352.     return 0;
  353. #endif
  354. }
  355.  
  356. uint8_t IrTransceiver_Transmit(uint16_t *buffer, uint8_t length, uint8_t modfreq)
  357. {
  358. #if IR_TX_ENABLE==1
  359.     data_transmitted = 0;
  360.    
  361.     if (length == 0) return IR_NO_DATA;
  362.  
  363.     txbuf = buffer;
  364.     txlen = length;
  365.     bufIndex = 1;
  366.    
  367.     IR_MODULATION_REG = modfreq;
  368.    
  369.     IR_COMPARE_REG = IR_COUNT_REG + txbuf[0];
  370.    
  371.     IR_OUTP_HIGH();
  372.    
  373.     IR_UNMASK_COMPARE();
  374.    
  375.     //while (!data_transmitted);
  376.    
  377.     return IR_OK;
  378. #else
  379.     return 0;
  380. #endif
  381. }
  382.