NoPaste

rc5.c

von Chosen

SNIPPET_TEXT:
  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include "rc5.h"
  4.  
  5. #ifndef RC5_INT
  6. #define RC5_INT      RC5_INT0
  7. #endif  /* RC5_INT */
  8.  
  9. #ifndef RC5_PRESCALE
  10. #define RC5_PRESCALE 64         //bei 1Mhz
  11. #endif  /* RC5_PRESCALE */
  12.  
  13. /* ******************************************************************************** */
  14.  
  15. rc5_t rc5;
  16.  
  17. /* ******************************************************************************** */
  18. #define F_CPU   1000000
  19. #ifndef F_CPU
  20. #error Please define F_CPU
  21. #endif /* !F_CPU */
  22.  
  23. #define LED_PORT        PORTC
  24. #define LED1            1
  25. #define LED_DDR         DDRC
  26.  
  27. /* µs for a whole bit of RC5 (first & second part) */
  28. #define RC5_BIT_US   (64*27)
  29.  
  30. #define RC5_TICKS \
  31.         ((uint8_t) ((uint32_t) (F_CPU / 1000 * RC5_BIT_US / 1000 / RC5_PRESCALE)))
  32.        
  33. #define RC5_DELTA \
  34.         (RC5_TICKS / 6)
  35.        
  36. typedef union
  37. {
  38.         uint16_t w;
  39.         uint8_t  b[2];
  40. } code_t;
  41.  
  42. static code_t code; //siehe README
  43. static uint8_t rc5_addr;
  44.  
  45. /* Number of Bits received so far */
  46. /* Number of Interrupts occured so far */
  47. static uint8_t nbits;
  48. static uint8_t nint;
  49.  
  50. /* ******************************************************************************** */
  51.        
  52. void rc5_init (uint8_t addr)
  53. {
  54.         nint  = 0;
  55.         nbits = 0;
  56.         rc5.flip = -1;
  57.        
  58.         rc5_addr = addr;
  59.        
  60. /* Bedingte Kompilierung je nachdem welcher inerrupt eingang benutzt wird */
  61. #if (RC5_PRESCALE==1024)
  62.         TCCR0 = (1 << CS02) | (1 << CS00);
  63. #elif   (RC5_PRESCALE==256)
  64.         TCCR0 = (1 << CS02);
  65. #elif   (RC5_PRESCALE==64)
  66.         TCCR0 = (1 << CS01) | (1 << CS00);
  67. #else
  68. #error This RC5_PRESCALE is not supported
  69. #endif /* RC5_PRESCALE */
  70.        
  71.         /* INTx on falling edge */
  72.         /* clear pending INTx */
  73.         /* enable INTx interrupt */
  74. //#if (RC5_INT == RC5_INT0)              
  75.         MCUCR = (MCUCR | (1 << ISC01)) & ~ (1 << ISC00);
  76.         GIFR = (1 << INTF0);
  77.         GICR |= (1 << INT0);
  78.  
  79. }
  80.  
  81. /* ******************************************************************************** */
  82.  
  83. //vorher: SIGNAL (SIG_OVERFLOW0)
  84. ISR (TIMER0_OVF_vect)
  85. {
  86.         /*Timer/Counter0 Overflow Interrupt Enable. bit wird gelöscht also deaktiviert, da wir in der overflowroutine sind wollen wir nicht erneut da rein springen */
  87.         TIMSK &= ~(1 << TOIE0);
  88.        
  89.         uint8_t _nbits = nbits;
  90.         code_t _code = code;
  91.        
  92.         if (26 == _nbits) //wenn 26 bits empfangen wurden
  93.         {
  94.                 _nbits++;
  95.                 _code.w <<= 1;
  96.         }
  97.        
  98.         if (27 == _nbits  //wenn 27 Bits empfangen wurden
  99.                 && _code.b[1] >= 0x30 /* kommt nach der Startsequenz+flip bit daten?*/
  100.                 && 0 > rc5.flip) //wenn rc5.flip kleiner als 0, also rc5.flip = -1    RC5-Empfang aktiv, wartet auf nächste Übertragung
  101.         {
  102.                 uint8_t _rc5_code;
  103.                 uint8_t _rc5_addr;
  104.                 /* we do the bit manipulation stuff by hand, because of code size */
  105.                 _rc5_code = _code.b[0] & 0x3f; /* 0b00111111 : #0..#5 ist der payload der sequenz*/
  106.                 _code.w <<= 2;
  107.                 _rc5_addr = _code.b[1] & 0x1f; /* 0b00011111 : #6..#10 die adressbits*/
  108.  
  109.                 if (rc5_addr & 0x80
  110.                         || rc5_addr == _rc5_addr)
  111.                 {
  112.                         rc5.code = _rc5_code;
  113.                         rc5.addr = _rc5_addr;
  114.                         signed char flip = 0; //rc5.flip = 0    Code empfangen, RC5-Empfang inaktiv
  115.  
  116.                         if (_code.b[1] & 0x20) /* 0b00100000 : #11 */
  117.                                 flip = 1;
  118.                         rc5.flip = flip;
  119.                 }
  120.         }
  121.  
  122.         nint = 0;
  123.         nbits = 0;
  124.  
  125.         /* INTx on falling edge */
  126.         /* clear pending INTx */
  127.         /* enable INTx interrupt */
  128.         MCUCR = (MCUCR | (1 << ISC01)) & ~ (1 << ISC00);
  129.         GIFR = (1 << INTF0);
  130.         GICR |= (1 << INT0);
  131.  
  132. }
  133.  
  134. /* ******************************************************************************** */
  135.  
  136. ISR (INT0_vect)
  137. {
  138.         code_t _code = code;
  139.         uint8_t _nint = nint;
  140.        
  141.         uint8_t tcnt0 = TCNT0; //Timer/Counter 0 Zählregister
  142.         TCNT0 = 0;
  143.        
  144.  
  145.         if (0 == _nint) //wenn noch keine Interrupts gezählt wurden (also sie noch nicht aktiviert wurden)
  146.         {
  147.                 /* INTx on both edges  setzt erstmal in mcucr das 0. bit also angenommen mcucr sieht so aus 11001000 macht er dann erst 11001001 und verknüpft das ergebnis dann und mit 00000010 invertiert also11111101  das ergibt dann wieder 11001001 geht also sicher dass zum schluss auf jeden fall 01 steht, was bedeutet das jede änderung an INT0 zu einem Interrupt führt*/
  148. //MCU General Control Register konfiguriert externe inerruptbehandlung hier wird INT0 genommen
  149. //if (RC5_INT == RC5_INT0)              
  150.                 MCUCR = (MCUCR | (1 << ISC00)) & ~ (1 << ISC01);
  151.  
  152.        
  153. //Timer Interrupt Flag Register        
  154.                 TIFR = (1 << TOV0); //TOV0 Timer/Counter 0 Überlauf aufgetreten 1 resettet den interrupt
  155. //Timer Interrupt Maskenregister
  156.                 TIMSK |= (1 << TOIE0); // TOIE0 Timer/Counter 0 Überlauf-Interrupt 0: Kein Int bei Überlauf 1: Int bei Überlauf TOIE0: Timer/Counter0 Overflow Interrupt Enable aktiviert den interrupt
  157.                 _code.w = 0;
  158.         }
  159.         else //wenn interrupts schon eingeschaltet wurden
  160.         {
  161.                 /* Number of bits of the just elapsed period  anzahl der bits der bisher verstrichenen periode*/
  162.                 uint8_t n = 1;
  163.          
  164.                 /* Bits received so far */
  165.                 uint8_t _nbits = nbits;
  166.        
  167.                 /* is TCNT0 close to RC5_TICKS or RC5_TICKS/2 ? */
  168.                 if (tcnt0 > RC5_TICKS + RC5_DELTA)
  169.                         goto invalid;
  170.                 else if (tcnt0 < RC5_TICKS/2 - RC5_DELTA)
  171.                         goto invalid;
  172.                 else if (tcnt0 > RC5_TICKS - RC5_DELTA)
  173.                         n = 2;
  174.                 else if (tcnt0 > RC5_TICKS/2 + RC5_DELTA)
  175.                         goto invalid;
  176.                
  177.                 /* store the just received 1 or 2 bits */
  178.                 do
  179.                 {
  180.                         _nbits++;
  181.                         if (_nbits & 1)
  182.                         {
  183.                                 _code.w <<= 1;
  184.                                 _code.b[0] |= _nint & 1;
  185.                         }
  186.                 }
  187.                 while (--n); //wenn --n=1 ist oder größer wird wiederholt wenn n=1 also --1=0 bricht die schelife ab
  188.                
  189.                 if (0)  //ist nie null daher nur kontainer für invalid <-- vermutung
  190.                 {
  191.                         invalid: //ungültiges empfangenes bit (sequenz zu lange/kurz)
  192.                        
  193.                         /* disable INTx, run into Overflow0 */
  194. //if (RC5_INT == RC5_INT0)              
  195.                         GICR &= ~(1 << INT0); //General Interrupt Control Register
  196.  
  197.  
  198.                         _nbits = 0;     //keine (brauchbaren) bits wurden empfangen
  199.                 }
  200.                
  201.                 nbits = _nbits;
  202.         }
  203.  
  204.         code = _code;
  205.         nint = 1+_nint;
  206. }
  207.  
  208.  
  209. int main(void)
  210. {
  211. LED_PORT = 0xFF;
  212. LED_DDR = 0xFF;
  213. /* der ensprechende INT-Port muss INPUT sein */
  214.         /* RC5 initialisieren, alle Adressen zulassen */
  215.         rc5_init (RC5_ALL);
  216.  
  217.         /* Interrupts zulassen */
  218.         sei();
  219.  
  220. while(1){
  221.  
  222.          if (-1 == rc5.flip)
  223.    {
  224.      //LED_PORT ^= 1<<LED1;
  225.    }
  226.    else
  227.    {
  228.       /* Ja, dann rc5.code merken und evtl. rc5.addr */
  229.       /* falls man die braucht und nicht sowieso schon kennt */
  230.       uint8_t code = rc5.code;
  231.       uint8_t addr = rc5.addr;
  232.       /* und auf naechstes Zeichen warten */
  233.       rc5.flip = -1;
  234.         if(code&1){
  235.                 LED_PORT &= ~(1<<LED1);
  236.         }
  237.       /* code (evtl. addr) auswerten */
  238.    }
  239. }
  240. }

Quellcode

Hier kannst du den Code kopieren und ihn in deinen bevorzugten Editor einfügen. PASTEBIN_DOWNLOAD_SNIPPET_EXPLAIN