Subversion Repositories HomeAutomation

Rev

Blame | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * IR receiver driver.
  3.  *
  4.  * @date    2006-12-10
  5.  *
  6.  * @author  Anders Runeson
  7.  *  
  8.  */
  9.  
  10. /*-----------------------------------------------------------------------------
  11.  * Includes
  12.  *---------------------------------------------------------------------------*/
  13. #include "irreceiver.h"
  14. #include <avr/io.h>
  15.  
  16.  
  17. /*-----------------------------------------------------------------------------
  18.  * Prerequisites
  19.  *---------------------------------------------------------------------------*/
  20.  
  21.  
  22. /*-----------------------------------------------------------------------------
  23.  * Public Functions
  24.  *---------------------------------------------------------------------------*/
  25.  
  26. void initTimer(void) {
  27.     //sätt upp timer
  28.     #if defined(__AVR_ATmega8__)
  29.     TCCR1B = (0<<CS11) | (1<<CS10); // prescaler: 1
  30.     TIFR  |= (1<<TOV1);             // clear overflow flag.
  31.     TCNT1 = 0;
  32.     #endif
  33.     #if defined(__AVR_ATmega88__)
  34.     TCCR1B = (0<<CS11) | (1<<CS10); // prescaler: 1
  35.     TIFR1  |= (1<<TOV1);            // clear overflow flag.
  36.     TCNT1 = 0;
  37.     #endif
  38. }
  39.  
  40. int isTimerOvfl(void) {
  41.     #if defined(__AVR_ATmega8__)
  42.     if (TIFR  & (1<<TOV1)) return 1;
  43.     #endif
  44.     #if defined(__AVR_ATmega88__)
  45.     if (TIFR1  & (1<<TOV1)) return 1;
  46.     #endif
  47.  
  48.     return 0;
  49. }
  50.  
  51. uint16_t getTimerVal(void) {
  52.     #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
  53.     return TCNT1;
  54.     #endif
  55. }
  56.  
  57. void setTimerVal(uint16_t value) {
  58.     #if defined(__AVR_ATmega8__)
  59.     TCNT1 = value;
  60.     TIFR |= (1<<TOV1);  // clear overflow flag.
  61.     #endif
  62.     #if defined(__AVR_ATmega88__)
  63.     TCNT1 = value;
  64.     TIFR1 |= (1<<TOV1);  // clear overflow flag.
  65.     #endif
  66. }
  67.  
  68. /**
  69.  * Receive RC5 data
  70.  *
  71.  * @param address
  72.  *      Pointer to store the address of the received data
  73.  * @param command
  74.  *      Pointer to store the command of the received data
  75.  */
  76. int receiveRC5(uint8_t *address, uint8_t *command) {
  77.     //printf("startbit of RC5!\n");
  78.     uint8_t i;
  79.     //read second startbit, togglebit and the 5 addressbits
  80.     for (i=0; i<7; i++) {
  81.         //set up a quarter of a bit period time
  82.         setTimerVal(0xFFFF-(IR_RC5_BIT/4));
  83.         //and wait for time to elapse
  84.         while(!isTimerOvfl());
  85.         //reset timer ovfl flag
  86.         setTimerVal(0);
  87.         if (IRPIN & (1<<IRBIT)) {
  88.             //save a one
  89.             *address |= (1<<(6-i));
  90.             //wait for negative slope, while checking timer overflow
  91.             while ((IRPIN & (1<<IRBIT))) {
  92.                 //om timeout (om timer-ovflow-flaggan sätt)
  93.                 if (isTimerOvfl() == 1) return IR_TIME_OVFL;
  94.             }
  95.         } else {
  96.             //save a zero
  97.            
  98.             //wait for positiv slope
  99.             while (!(IRPIN & (1<<IRBIT))) {
  100.                 //om timeout (om timer-ovflow-flaggan sätt)
  101.                 if (isTimerOvfl() == 1) return IR_TIME_OVFL;
  102.             }
  103.         }
  104.         //set up a half a bit period time
  105.         setTimerVal(0xFFFF-(IR_RC5_BIT/2));
  106.         //and wait for time to elapse
  107.         while(!isTimerOvfl());
  108.     }
  109.    
  110.     //read 5 command bits
  111.     for (i=0; i<6; i++) {
  112.         //set up a quarter of a bit period time
  113.         setTimerVal(0xFFFF-(IR_RC5_BIT/4));
  114.         //and wait for time to elapse
  115.         while(!isTimerOvfl());
  116.         //reset timer ovfl flag
  117.         setTimerVal(0);
  118.         if (IRPIN & (1<<IRBIT)) {
  119.             //save a one
  120.             *command |= (1<<(5-i));
  121.             //wait for negative slope, while checking timer overflow
  122.             while ((IRPIN & (1<<IRBIT))) {
  123.                 //om timeout (om timer-ovflow-flaggan sätt).
  124.                 if (isTimerOvfl() == 1) return IR_TIME_OVFL;
  125.             }
  126.         } else {
  127.             //save a zero
  128.            
  129.             //wait for positiv slope
  130.             while (!(IRPIN & (1<<IRBIT))) {
  131.                 //om timeout (om timer-ovflow-flaggan sätt)
  132.                 if (isTimerOvfl() == 1) return IR_TIME_OVFL;
  133.             }
  134.         }
  135.         //set up a half a bit period time
  136.         setTimerVal(0xFFFF-(IR_RC5_BIT/2));
  137.         //and wait for time to elapse
  138.         while(!isTimerOvfl());
  139.     }
  140.    
  141.     //wait for positiv slope to ensure that ir sequence is over
  142.     setTimerVal(0);
  143.     while (!(IRPIN & (1<<IRBIT))) {
  144.         //om timeout (om timer-ovflow-flaggan sätt)
  145.         if (isTimerOvfl() == 1) return IR_TIME_OVFL;
  146.     }
  147.    
  148.     //support RC5-extended by putting the inversion of startbit 2 as the 7th commandbit
  149.     *command |= (~(*address) & 0x40);
  150.     *address &= 0x1f;
  151.     //printf("address %i\n", *address);
  152.     //printf("command %i\n", *command);
  153.    
  154.     return IR_OK;
  155. }
  156.  
  157. /**
  158.  * Checks if ir-receiver is outputting data, if so then receive it
  159.  *
  160.  * @param proto
  161.  *      Pointer to store the protocol of the received data
  162.  * @param address
  163.  *      Pointer to store the address of the received data
  164.  * @param command
  165.  *      Pointer to store the command of the received data
  166.  * @return
  167.  *      IR_OK if data received successfully, one of several errormessages if not
  168.  */
  169. int checkIr(uint8_t *proto, uint8_t *address, uint8_t *command) {
  170.     if (IRPIN & (1<<IRBIT)) return IR_NO_DATA;      //om irmodulen ger en etta så återgå
  171.    
  172.     //nu lägger irmodulen ut en nolla, "startbiten" alltså
  173.    
  174.     uint16_t timerVal;
  175.    
  176.     *address = 0;
  177.     *command = 0;
  178.    
  179.     //Läs in längden på startbiten
  180.     initTimer();
  181.     while (!(IRPIN & (1<<IRBIT))) {     //vänta på att irmodulen lägger ut en etta
  182.         //om timeout (om timer-ovflow-flaggan sätt)
  183.         if (isTimerOvfl() == 1) return IR_TIME_OVFL;
  184.     }
  185.     timerVal = getTimerVal();
  186.    
  187.     /*
  188.      * Anropa olika funktioner beroende på längden
  189.      * för vissa protokoll behöver längden på första biten skickas med till funktionen?
  190.      * t.ex. sharp?
  191.      * */
  192.    
  193.     if ((timerVal < IR_RC5_ST_BIT+500) && (timerVal > IR_RC5_ST_BIT-500)) {
  194.         *proto = IR_PROTO_RC5;
  195.         return receiveRC5(&*address, &*command);
  196.     } //else if ...
  197.    
  198.    
  199.     return IR_NO_PROTOCOL;
  200. }
  201.