/*
A simple RC5 decoder
the demodulator diode is connected to P3.2 (INT0)
and T0 is used to recieve the RC5 bits
The reload values are based on a 12 MHZ XTAL
and on a programmable remote control (EasyTip1 code 718)
This remote control uses a slightly differnd timming
so for standart timming the reload values have to be adjusted
I wrote this because I had to emulate a SAA3049
which is discontinued
more infos and some asm code at:
http://www.ustr.net/infrared/infrared1.shtml
*/
#include "AT892051.h"
#define UINT8 unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long
#define INT8 signed char
#define INT16 signed int
#define INT32 signed long
#define HighB(value) ((value >> 8) & 0xFF)
#define LowB(value) (value & 0xFF)
#define RELOAD -440 // Timming for EasyTip1 Code718
#define FIRST_RELOAD -870 // and XTAL = 12 MHZ
#define _TOGGLE 0x80 // Toggle Bit
#define _START2 0x40
#define _START1 0x20
typedef struct _BYTE
{
UINT8 b3; /*msb */
UINT8 b2;
UINT8 b1;
UINT8 b0; /*lsb */
}BYTES;
typedef union _LONGINT
{
UINT32 l;
BYTES b;
}LONGUNION;
// global vars
bit bRC5valid; // 1 after RC5 code was recieved
UINT8 command; // command and subaddress
UINT8 subaddress;
UINT8 slopecount; // counter for RC5 slopes
LONGUNION shiftreg; // shiftregister for raw RC5 data
//****************************************************************
// Interrrupt for reciever diode
// this IRQ starts the meassurement Timer
//****************************************************************
void RC5StartIrq(void) interrupt IE0_VECTOR
{
EX0=0; // disable the IRQ
slopecount=27; // we need 27 slopes
TH0=HighB(RELOAD); // first reload
TL0=LowB(RELOAD);
TR0=1; // start messurement Timer
TF0=0;
ET0=1; // Timer0 Irq
}
// **************************************************************
// Timerinterrupt,
// after 27 slopes the shiftreg contains the RC5 value
// und bRC5Valid goes to 1
// **************************************************************
void TimingIrq(void) interrupt TF0_VECTOR using 1
{
bit bLevel;
bLevel= P3_2; // read level
while (slopecount) // max 27 slopes
{
TR0=0; // T0 stopp
TH0=HighB(FIRST_RELOAD); // new reload value
TL0=LowB (FIRST_RELOAD);
TR0=1; // T0 start
if (bLevel) // add the level to the shift value
{
shiftreg.b.b0=shiftreg.b.b0 | 1;
}
shiftreg.l = shiftreg.l << 1;
slopecount--;
return;
}
TR0=0; // T0 stop
ET0=0; // Timer Irq off
bRC5valid=1; //
}
//*******************************************************
// decodes the recieved value
// and sets command and subbaddress
// returns 1 if no error occures
// else 0
//*******************************************************
bit DecodeRC5Code(void)
{
UINT8 i;
UINT8 b;
command=0;
subaddress=0;
shiftreg.l = shiftreg.l >> 1;
for (i=0; i < 6 ; i ++) // first 6 Bit command
{
b=shiftreg.b.b0 & 0x03;
if (b==0x02)
command = command | 0x40;
else if (b==0x01)
command = command & ~0x40;
else return 0;
command = command >> 1;
shiftreg.l = shiftreg.l >> 2;
}
for (i=0;i < 5;i++) // then 5 Bit subaddress
{
b=shiftreg.b.b0 & 0x03;
if (b ==0x02)
subaddress = subaddress | 0x20;
else if (b==0x01)
subaddress = subaddress & ~0x20;
else return 0;
subaddress = subaddress >> 1;
shiftreg.l = shiftreg.l >> 2;
}
b=shiftreg.b.b0 & 0x03;
if (b==0x02) // Toggle Bit
command = command | _TOGGLE;
else if (b==0x01)
command = command & ~_TOGGLE;
else return 0;
shiftreg.l = shiftreg.l >> 2;
b=shiftreg.b.b0 & 0x03; // Startbit 2
if (b==0x02)
command = command & ~_START2; // inverted to command
else if (b==0x01) // for extented RC5 (7 Bit Commands)
command = command | _START2;
else return 0;
shiftreg.l = shiftreg.l >> 2;
b=shiftreg.b.b0 & 0x03; // Startbit 1
if (b==0x02)
subaddress = subaddress | _START1;
else if (b==0x01)
subaddress = subaddress & ~_START1;
else return 0;
return 1; // return valid
}
//*******************************************************
// ext.Int0 in slope mode
//*******************************************************
void InitEx0Irq(void)
{
EX0=1;
IT0=1;
IE0=0;
}
//*******************************************************
// both timer in 16 Bit mode
// T0 is vor RC5 bittime
//*******************************************************
void InitTimer(void)
{
TMOD = 0x11;
}
void main(void)
{
InitTimer();
InitEx0Irq(); // ReciverInterupt
shiftreg.l=0x02; // startvalue
EA=1;
while (1)
{
if (bRC5valid) // if we got a code
{
bRC5valid=0;
if (DecodeRC5Code()) // then test the shiftreg
{
// here command + subaddress
// has a valid RC5 code
}
shiftreg.l=0x02; // restart the reciever
IE0=0;
EX0=1;
}
}
}