rc5.c
von Chosen- SNIPPET_TEXT:
-
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include "rc5.h"
- #ifndef RC5_INT
- #define RC5_INT RC5_INT0
- #endif /* RC5_INT */
- #ifndef RC5_PRESCALE
- #define RC5_PRESCALE 64 //bei 1Mhz
- #endif /* RC5_PRESCALE */
- /* ******************************************************************************** */
- rc5_t rc5;
- /* ******************************************************************************** */
- #define F_CPU 1000000
- #ifndef F_CPU
- #error Please define F_CPU
- #endif /* !F_CPU */
- #define LED_PORT PORTC
- #define LED1 1
- #define LED_DDR DDRC
- /* µs for a whole bit of RC5 (first & second part) */
- #define RC5_BIT_US (64*27)
- #define RC5_TICKS \
- ((uint8_t) ((uint32_t) (F_CPU / 1000 * RC5_BIT_US / 1000 / RC5_PRESCALE)))
- #define RC5_DELTA \
- (RC5_TICKS / 6)
- typedef union
- {
- uint16_t w;
- uint8_t b[2];
- } code_t;
- static code_t code; //siehe README
- static uint8_t rc5_addr;
- /* Number of Bits received so far */
- /* Number of Interrupts occured so far */
- static uint8_t nbits;
- static uint8_t nint;
- /* ******************************************************************************** */
- void rc5_init (uint8_t addr)
- {
- nint = 0;
- nbits = 0;
- rc5.flip = -1;
- rc5_addr = addr;
- /* Bedingte Kompilierung je nachdem welcher inerrupt eingang benutzt wird */
- #if (RC5_PRESCALE==1024)
- TCCR0 = (1 << CS02) | (1 << CS00);
- #elif (RC5_PRESCALE==256)
- TCCR0 = (1 << CS02);
- #elif (RC5_PRESCALE==64)
- TCCR0 = (1 << CS01) | (1 << CS00);
- #else
- #error This RC5_PRESCALE is not supported
- #endif /* RC5_PRESCALE */
- /* INTx on falling edge */
- /* clear pending INTx */
- /* enable INTx interrupt */
- //#if (RC5_INT == RC5_INT0)
- MCUCR = (MCUCR | (1 << ISC01)) & ~ (1 << ISC00);
- GIFR = (1 << INTF0);
- GICR |= (1 << INT0);
- }
- /* ******************************************************************************** */
- //vorher: SIGNAL (SIG_OVERFLOW0)
- ISR (TIMER0_OVF_vect)
- {
- /*Timer/Counter0 Overflow Interrupt Enable. bit wird gelöscht also deaktiviert, da wir in der overflowroutine sind wollen wir nicht erneut da rein springen */
- TIMSK &= ~(1 << TOIE0);
- uint8_t _nbits = nbits;
- code_t _code = code;
- if (26 == _nbits) //wenn 26 bits empfangen wurden
- {
- _nbits++;
- _code.w <<= 1;
- }
- if (27 == _nbits //wenn 27 Bits empfangen wurden
- && _code.b[1] >= 0x30 /* kommt nach der Startsequenz+flip bit daten?*/
- && 0 > rc5.flip) //wenn rc5.flip kleiner als 0, also rc5.flip = -1 RC5-Empfang aktiv, wartet auf nächste Übertragung
- {
- uint8_t _rc5_code;
- uint8_t _rc5_addr;
- /* we do the bit manipulation stuff by hand, because of code size */
- _rc5_code = _code.b[0] & 0x3f; /* 0b00111111 : #0..#5 ist der payload der sequenz*/
- _code.w <<= 2;
- _rc5_addr = _code.b[1] & 0x1f; /* 0b00011111 : #6..#10 die adressbits*/
- if (rc5_addr & 0x80
- || rc5_addr == _rc5_addr)
- {
- rc5.code = _rc5_code;
- rc5.addr = _rc5_addr;
- signed char flip = 0; //rc5.flip = 0 Code empfangen, RC5-Empfang inaktiv
- if (_code.b[1] & 0x20) /* 0b00100000 : #11 */
- flip = 1;
- rc5.flip = flip;
- }
- }
- nint = 0;
- nbits = 0;
- /* INTx on falling edge */
- /* clear pending INTx */
- /* enable INTx interrupt */
- MCUCR = (MCUCR | (1 << ISC01)) & ~ (1 << ISC00);
- GIFR = (1 << INTF0);
- GICR |= (1 << INT0);
- }
- /* ******************************************************************************** */
- ISR (INT0_vect)
- {
- code_t _code = code;
- uint8_t _nint = nint;
- uint8_t tcnt0 = TCNT0; //Timer/Counter 0 Zählregister
- TCNT0 = 0;
- if (0 == _nint) //wenn noch keine Interrupts gezählt wurden (also sie noch nicht aktiviert wurden)
- {
- /* 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*/
- //MCU General Control Register konfiguriert externe inerruptbehandlung hier wird INT0 genommen
- //if (RC5_INT == RC5_INT0)
- MCUCR = (MCUCR | (1 << ISC00)) & ~ (1 << ISC01);
- //Timer Interrupt Flag Register
- TIFR = (1 << TOV0); //TOV0 Timer/Counter 0 Überlauf aufgetreten 1 resettet den interrupt
- //Timer Interrupt Maskenregister
- 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
- _code.w = 0;
- }
- else //wenn interrupts schon eingeschaltet wurden
- {
- /* Number of bits of the just elapsed period anzahl der bits der bisher verstrichenen periode*/
- uint8_t n = 1;
- /* Bits received so far */
- uint8_t _nbits = nbits;
- /* is TCNT0 close to RC5_TICKS or RC5_TICKS/2 ? */
- if (tcnt0 > RC5_TICKS + RC5_DELTA)
- goto invalid;
- else if (tcnt0 < RC5_TICKS/2 - RC5_DELTA)
- goto invalid;
- else if (tcnt0 > RC5_TICKS - RC5_DELTA)
- n = 2;
- else if (tcnt0 > RC5_TICKS/2 + RC5_DELTA)
- goto invalid;
- /* store the just received 1 or 2 bits */
- do
- {
- _nbits++;
- if (_nbits & 1)
- {
- _code.w <<= 1;
- _code.b[0] |= _nint & 1;
- }
- }
- while (--n); //wenn --n=1 ist oder größer wird wiederholt wenn n=1 also --1=0 bricht die schelife ab
- if (0) //ist nie null daher nur kontainer für invalid <-- vermutung
- {
- invalid: //ungültiges empfangenes bit (sequenz zu lange/kurz)
- /* disable INTx, run into Overflow0 */
- //if (RC5_INT == RC5_INT0)
- GICR &= ~(1 << INT0); //General Interrupt Control Register
- _nbits = 0; //keine (brauchbaren) bits wurden empfangen
- }
- nbits = _nbits;
- }
- code = _code;
- nint = 1+_nint;
- }
- int main(void)
- {
- LED_PORT = 0xFF;
- LED_DDR = 0xFF;
- /* der ensprechende INT-Port muss INPUT sein */
- /* RC5 initialisieren, alle Adressen zulassen */
- rc5_init (RC5_ALL);
- /* Interrupts zulassen */
- sei();
- while(1){
- if (-1 == rc5.flip)
- {
- //LED_PORT ^= 1<<LED1;
- }
- else
- {
- /* Ja, dann rc5.code merken und evtl. rc5.addr */
- /* falls man die braucht und nicht sowieso schon kennt */
- uint8_t code = rc5.code;
- uint8_t addr = rc5.addr;
- /* und auf naechstes Zeichen warten */
- rc5.flip = -1;
- if(code&1){
- LED_PORT &= ~(1<<LED1);
- }
- /* code (evtl. addr) auswerten */
- }
- }
- }
Quellcode
Hier kannst du den Code kopieren und ihn in deinen bevorzugten Editor einfügen. PASTEBIN_DOWNLOAD_SNIPPET_EXPLAIN