Naiv som man är så fixade jag fram ett program som avkodar RC5-protokollet, men efter lite mätningar med skåpet så visar det sig att den använder inte alls RC5 utan något "hemmaknåpat" protokoll. Istället för att skicka samma kommando om och om igen så skickar den kommandot först, sedan skickar den ett kortare paket a'la "fortfarande intryckt".
Eftersom det är IR så har jag aktivt låg på ingången.
Preamblen eller vad jag ska kalla det har jag avkodat till:
X (9ms) Y
-----_______-----_- ....
Där Y varierar beroende på om den är en ny knapptryckning eller inte, är Y halva X så är den ett nytt kommando, är Y en fjärdedels X så är knappen fortfarande intryckt.
Är det ett nytt kommando så kommer det 32bitar data där de första 16 är samma för alla kommandon, de efterföljande 8 är olika för de olika knapparna och de sista 8 är deras komplement.
Bitarna skickas sedan som olika långt intervall mellan pulserna, där jag har definierat en etta som kort intervall och en norra som långt. ett kort intervall är X/8 och ett långt är X/4.
ex.
0 1 1 0 1
----_--_-_-_--_-_------
För att avgöra allt detta så använder jag interrupt och en timer, när jag får ett interrupt så lagrar jag timervärdet och nollar det.
För att kolla vad som händer sparar jag undan några värden och skriver ut dessa på en LCD, när jag felsöker så går det inte riktigt som jag vill, när jag får rätt värden på X vägrar den räkna vidare, men får jag fel värde (1/20 på X) så funkar det oftast.
Jag har suttit ett tag och pillat med detta man kan inte komma fram till vad som är fel, är det någon som kanske kan se något?
Kod: Markera allt
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#define IDLE 0
#define NEW 1
#define MODE 2
#define RECIEVE 3
#define DONE 4
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include "lcd_lib.h"
volatile int STATE = IDLE;
volatile int lenght = 0;
volatile int recieved = 0;
volatile int header = 0;
volatile char data1 = 0;
volatile char data2 = 0;
volatile int temp, first, second = 0;
volatile int ref, ref1, ref2, ref3 = 0;
// - - - - Main Loop - - - - //
int main (void) {
init_lcd();
init_ir();
delay_ms(10);
lcd_clear();
sei();
lcd_puts("ELLU WoRLD");
delay_ms(2000);
//lcd_clear();
while(1){
asm volatile("nop");
}
}
void init_ir()
{
//Enable pin-change interrupt
PCICR |= _BV(PCIE1);
PCMSK1 |= _BV(PCINT13);
//Start timer
//TCCR1B |= _BV(CS11) | _BV(CS10);
//Init buffer
}
ISR(PCINT1_vect)
{
//PORTD = 0b11111111;
temp = TCNT1;
TCNT1 = 0;
//New input
if((STATE == IDLE) && !(PINC & _BV(PC5))) {
TCCR1B |= _BV(CS11) | _BV(CS10);
TCNT1 = 0;
STATE = NEW;
return;
}
if((STATE == NEW) && (PINC & _BV(PC5))){
lenght = temp;
STATE = MODE;
return;
}
//New command or button still pushed.
if((STATE == MODE) && !(PINC & _BV(PC5))){
ref = (lenght>>3) + (lenght>>2);
ref1 = (lenght>>4);
ref2 = (lenght>>3) + (lenght>>4);
ref3 = (lenght>>2) + (lenght>>4);
if((temp > ref) && (temp < (ref + ref3))){//New command
first = temp;
STATE = RECIEVE;
recieved = 0;
header = 0;
data1 = 0;
data2 = 0;
return;
}
else if(temp < ref){ // Still pushed
STATE = DONE;
//data2 = 0b00000000;
return;
}
else{ //Ellol
STATE = IDLE;
TCCR1B &= ~(_BV(CS11) | _BV(CS10));
return;
}
}
//Recieve Data
if((STATE == RECIEVE) && !(PINC & _BV(PC5))){
if((temp > ref1) && (temp < ref2)){ // Is '1'
if(recieved < 16){
header |= _BV(recieved);
}
else if(recieved < 24){
data1 |= _BV(recieved-16);
}
else if(recieved < 32){
data2 |= _BV(recieved-24);
}
else{
STATE = DONE;
}
recieved++;
}
else if((temp > ref2) && (temp < ref3)){// Is '0'
if(recieved < 16){
//header[recieved] = 0;
}
else if(recieved < 24){
//data1[(recieved-8)] = 0;
}
else if(recieved < 32){
//data2[(recieved-16)] = 0;
}
else{
STATE = DONE;
}
recieved++;
}
else{ //Fel
STATE = IDLE;
TCCR1B &= ~(_BV(CS11) | _BV(CS10));
//data2 = 0b11111111;
}
return;
}
//Print data
if((STATE == DONE) && (PINC & _BV(PC5))){
//data2 &= 0b00001111; //Mask irrelevant bits
lcd_clear();
lcd_dec(data2);
lcd_puts("-");
lcd_dec(lenght);
lcd_puts("-");
lcd_dec(ref);
lcd_puts("-");
lcd_dec(first);
lcd_jumptosec();
//lcd_puts("-");
lcd_dec(ref1);
lcd_puts("-");
lcd_dec(ref2);
lcd_puts("-");
lcd_dec(ref3);
lcd_puts("-");
lcd_dec(recieved);
//PORTD = data2;
STATE = IDLE;
TCCR1B &= ~(_BV(CS11) | _BV(CS10));
return;
}
}