/************************************************************************/ /* */ /* RC5 Remote Receiver */ /* */ /* Author: Niels Nikolaisen */ /* niels@nikolaisens.de */ /************************************************************************/ //#include //#include //#include //#include #define uchar unsigned char #define uint unsigned int #define xRC5_IN PINE // Port E - PIN 7 = DIGITAL7 - DI7 ist IR-Eingang #define xRC5 PE7 // IR input low active #define XTAL 16e6 // 16 MHz Prozessor-Takt // Der RC-5-Code ist folgendermaßen aufgebaut: // // |1|C6|T|A4|A3|A2|A1|A0|C5|C4|C3|C2|C1|C0| // // Am Anfang kommt IMMER eine "1" // A0 bis A4 sind die Geräteadresse (TV1, TV2, usw.) // C0 bis C6 ist der eigentlich RC-5-Befehl // T ist das Toggle-Bit, das bei jedem Tastendruck geändert wird. // Damit kann das mehrfache Drücken einer Taste ermittelt werden. // // Beispiele für das Impulsbild des RC-5-Signals vom IR-Sensor am Eingangs-Pin xRC5: // -_-_-_ = 1-1-1 usw. // -__--_ = 1-0-1 usw. // Die Bitfolge wird während des Messvorgangs in 28 Werten im PULSE_ARRAY[] gespeichert. // Kurze H- oder L-Phasen bekommen je eine "1" oder eine "0". // Lange H- oder L-Phasen bekommen je 2 x "1" bzw. 2 x "0". // Aus der empfangenen RC-5-Bitfolge 111 00001 011001 wird dann im PULSE_ARRAY = 101010 0101010110 011010010110 // Es dürfen somit niemals 3 Nullen oder Einsen nacheinander im PULSE_ARRAY stehen! Das muss geprüft werden! // // Zu Beginn des 14-Bit-RC-5-Codes kommt immer eine 1 = H-L-Übergang (im Standard festgelegt). // Diese 1 wird aber als "9+0" statt "1+0" abgespeichert, um später auf Gültigkeit der Bitfolge testen zu können. // Nach dem kompletten "Einsammeln" aller 28 Stückchen im PULSE_ARRAY[] wird dieses also auf Gültigkeit geprüft: // Ist der erste Speicherwert eine "9"? // Wenn ja, dann werden in jedem weiteren Durchlauf in der Schleife (14 Bit = 14 Durchläufe) jeweils zwei nacheinander liegende // Werte (also eigentlich Flankenimpulse) folgendermaßen interpretiert: // 1-0 = "1" (HIGH) bzw. 0-1 = "0" (LOW) // // Ausgabe des RC-5-Codes als 14-Bit-Wert mit 2 führenden Nullen in uint rc5_data #define RC5TIME 1.778e-3 // 1.778msec #define PULSE_MIN1 4 // 4 * 128 us = kurzer H- oder L-Puls minimal #define PULSE_MIN2 8 // 8 * 128 us = kurzer H- oder L-Puls maximal #define PULSE_MAX1 12 // Doppelte Pulslänge bei Wechsel von 0 auf 1 oder umgekehrt #define PULSE_MAX2 16 #define LOW 0b00000000 #define HIGH 0b00000001 #define PULSE_ARRAY_MAX_VALUE 28 // 14 Bit mal 2 Zustände "1" oder "0" volatile uint rc5_data=0; // store result volatile uint rc5_channel=0; // RC-5-Kanal der Fernbedienung (TV1 =0, TV2=1, AUX=2 usw...) // Damit können mehrere Roboter unabhängig gesteuert werden volatile int array_counter=0; volatile int PULSE_ARRAY[PULSE_ARRAY_MAX_VALUE]; uint rc5_highpulscounter; // zählt die Anzahl der Timer-Interrupts nach der L-H-Flanke uint rc5_lowpulscounter; // zählt die Anzahl der Timer-Interrupts nach der L-H-Flanke uint8_t rc5_state_old; //alter Pegelwert an xRC5 (IR-IN-Portpin) void Init_RC5() { rc5_highpulscounter = 0; rc5_lowpulscounter = 0; // Timer 2 ist 8-Bit-Timer TCCR2 = 0b00000010; // Prescaler = 8 (aber nur bei ATMega128!) TIMSK |= (1< ohne die anderen Bits zu verändern sei(); //enable all interrupts for(int i=0; i>6); // Rechtsverschiebung - 6 Stellen rc5_channel_tmp &=0b00011111; // Maskierung RC5-Channel (die letzten 5 Bit) rc5_tmp &=0b00111111; // Maskierung RC5-Command (die letzten 6 Bit) if(fehler==0 && rc5_data!=rc5_tmp){ rc5_channel=rc5_channel_tmp; rc5_data=rc5_tmp; } } //alle 128 us Interrupt SIGNAL (SIG_OVERFLOW2) { uint8_t rc5_state_new; rc5_state_new=xRC5_IN; // Übernahme und Zwischenspeichern des aktuellen Pegels vom IR-IN-PORT rc5_state_new >>=xRC5; // Rechtsverschiebung des Portpins rc5_state_new &= 0b00000001; // Obere 7 Bits NULL setzen // Im Array if(rc5_state_old==HIGH && rc5_state_new==LOW) // H-L-Flanke { if(rc5_highpulscounter>=PULSE_MAX2){ array_counter=0; // Es war vorher lange HIGH - also muss es nun die erste H-L-Flanke des RC-Signals sein PULSE_ARRAY[array_counter]=9; // Erstes halbes Bit ist immer HIGH, daher muss zu Beginn eigentlich eine "1" stehen // Aber als Prüfziffer und Anfangskenner wird hier eine "9" geschrieben! array_counter++; } if(rc5_highpulscounter>=PULSE_MIN1 && rc5_highpulscounter<=PULSE_MIN2){ PULSE_ARRAY[array_counter]=1; // einfache HIGH-Lücke - 1 x "1" schreiben array_counter++; if(array_counter==PULSE_ARRAY_MAX_VALUE-1){ PULSE_ARRAY[array_counter]=0; // Ende der Bitfolge nach H-L-Übergang: Ein LOW = "0" wird geschrieben array_counter=0; // Es geht danach wieder von vorne los! rc5_convert(); } } if(rc5_highpulscounter>=PULSE_MAX1 && rc5_highpulscounter<=PULSE_MAX2){ PULSE_ARRAY[array_counter]=1; // doppelte HIGH-Lücke array_counter++; PULSE_ARRAY[array_counter]=1; // 2 x "1" schreiben array_counter++; if(array_counter==PULSE_ARRAY_MAX_VALUE-1){ PULSE_ARRAY[array_counter]=0; // Ende der Bitfolge nach H-L-Übergang: Ein LOW = "0" wird geschrieben array_counter=0; // Es geht danach wieder von vorne los! rc5_convert(); } } rc5_lowpulscounter++; rc5_highpulscounter=0; //Zurücksetzen } if(rc5_state_old==LOW && rc5_state_new==HIGH) // L-H-Flanke { if(rc5_lowpulscounter>=PULSE_MIN1 && rc5_lowpulscounter<=PULSE_MIN2){ PULSE_ARRAY[array_counter]=0; // einfache LOW-Lücke - 1 x "0" schreiben array_counter++; if(array_counter==PULSE_ARRAY_MAX_VALUE-1){ PULSE_ARRAY[array_counter]=1; // Ende der Bitfolge - ein HIGH = "1" wird geschrieben array_counter=0; // Es geht danach wieder von vorne los! rc5_convert(); } } if(rc5_lowpulscounter>=PULSE_MAX1 && rc5_lowpulscounter<=PULSE_MAX2){ PULSE_ARRAY[array_counter]=0; // doppelte LOW-Lücke array_counter++; PULSE_ARRAY[array_counter]=0; // 2 x "0" schreiben array_counter++; if(array_counter==PULSE_ARRAY_MAX_VALUE-1){ PULSE_ARRAY[array_counter]=1; // Ende der Bitfolge - ein HIGH = "1" wird geschrieben array_counter=0; // Es geht danach wieder von vorne los! rc5_convert(); } } rc5_highpulscounter++; rc5_lowpulscounter=0; //Zurücksetzen } if(rc5_state_old==HIGH && rc5_state_new==HIGH){ rc5_highpulscounter++; } if(rc5_state_old==LOW && rc5_state_new==LOW){ rc5_lowpulscounter++; } rc5_state_old=rc5_state_new; // Neuen Pegelwert abspeichern }