// Title: RC5 IR Receive Program
// Author: Brian Hoskins
// Version: 0.1
// Date 01 March 2008
#include <pic.h>
unsigned char Timer = 0x00;
unsigned char Address = 0x00;
unsigned char Command = 0x00;
bit Sync = 0;
void display_data (void)
{
PORTB = Address; // Display Address Data on PortB
PORTC = Command; // Display Command Data on PortC
TMR0 = 0x00;
while (TMR0 != Timer) // Do nothing for a millisecond or so. This ensures that the comms line has returned
{ // high before going back to main (), otherwise main will think there is a new
} // incoming datastream (data_validate should throw that out anyway though)
}
void process_data (void)
// Collect Address Data
{
char i;
for (i = 6; i>0; i--)
{
{
while (RA0 != Sync) // Wait for RA0 to equal sync, then we are at sync point
{
}
TMR0 = 0x00; // Reset TMR0 then wait for it to equal Timer
while (TMR0 != Timer) // Do nothing until TMR0 == Timer
{
}
Address |= RA0; // Set bottom bit of Address to RA0. (using logical OR)
Address = Address << 1; // Shift Left Address
Sync = !RA0; // Set Sync to complement of RA0
}
}
Address = Address >> 1; // Address Shift correction
// Collect Command Data
for (i = 6; i>0; i--)
{
{
while (RA0 != Sync) // Wait for RA0 to equal sync, then we are at sync point
{
}
TMR0 = 0x00; // Reset TMR0 then wait for it to equal Timer
while (TMR0 != Timer) // Do nothing until TMR0 == Timer
{
}
Command |= RA0; // Set bottom bit of Command to RA0. (using logical OR)
Command = Command << 1; // Shift Left Command
Sync = !RA0; // Set Sync to complement of RA0
}
}
Command = Command >> 1; // Command Shift correction
display_data () ; // Display that data.
}
void data_validate (void)
// The purpose of this function is as follows;
// When this function is called it means PortA bit 0 has gone low, which indicates that there may be some incoming
// data. TMR0 is reset so that timing of the incoming data pulse is started. The function then waits for PortA bit0
// to return high again. The TMR0 value is then stored in Timer, and this value is tested to ensure that it falls within
// 20% of the 889uS duration of an RC5 communication pulse. If it is within spec, the processing function is called
// so that the data can be further processed. If it is ouside of the limits, the function returns to main(). The value
// of Timer is used as the timing for sampling of the data stream in process_data ().
// AUTHOR NOTE: What if RA0 never returns high? Program will get stuck. Function should timeout once TMR0 reaches
// a certain value (although if it never returns high there is a fault condition anyway)
{
TMR0 = 0x00; // Reset Timer to 0
while (RA0 == 0) // Wait for PortA bit 0 to return high
{
}
Timer = TMR0; // Store Timer value
if (Timer > 0x6F && Timer <0x9D) // Check Pulse duration was within 20% of that stated in RC5 protocol
{
Timer = Timer + (Timer/2); // After sync the process_data function must sample RA0 after 1.5 pulse durations. This will
// cause a sample to be taken in the middle of the required data pulse (which allows for a
// timing error either side
process_data () ;
}
}
void setup_hardware (void)
{
TRISC = 0x00; // Set all of Port C for output
TRISB = 0x00 ; // Set all of Port B for output
TRISA = 0x01 ; // Set bit 0 of Port A for input, the rest for output
OPTION = 0b10000100; // Set Option Reg for /32 Timer clocked on internal instructions
GIE = 0; // Disable all interrupts
ADCON1 = 0b00000111; // Disable A/D (otherwise you can't use RA0 for digital I/O)
}
void main (void)
{
setup_hardware () ; // Setup I/O ports and Registers etc
while (1)
{
while (RA0 == 1) // Do nothing while PortA bit 0 is high (wait for IR signal)
{ // AUTHOR NOTE: This would be better as an interrupt
}
data_validate () ;
}
}