Recently there's been a thread about controlling a bank of satellite receivers using a common remote control, but as the OP was never even able to confirm if it used RF remotes, IR, or either, it came to nothing.
However, this reminded me of when I did the same thing years ago, using assembler, based on my tutorial IR routines.
Ian Rogers very kindly converted my tutorials to C, and provides a link to them in his signature - but (as I recall) he'd never had a Sony remote or TV to try them with - although possibly they may have worked, as he uses the commercial (expensive) XC8 compiler which is considerably more optimised, and faster.
However, when I tried the free version of XC8 a number of years ago, they wouldn't work, as the timing was FAR too slow, where as the original assembler version allowed accuracy to 1uS even with a 4MHz clock. So following the recent thread, I thought I'd make a 'proper' effort to produce a version that works with the free version of XC8 - and so far I've got it working really well. For anyone who's interested?, I'm using the SMT timer on modern PIC's (the 16F18857 in this instance) to handle receiving the incoming IR data stream.
Now the issue for transmission was still timing - as you need 600uS, 1200uS and 2400uS series of 40KHz pulses.
One of my favourite simple timing routines is:
Which gives a simple variable millisecond delay function, which works perfectly, as the millisecond resolution is enough to 'lose' the XC8 overheads. So I simply wrote a similar routine for uS.
Utter disaster - the huge overheads made it completely unusable - I did measure them, and it was BAD!!
My solution was to use a timer to do it, and while it works, I'm still less than impressed at the overhead Free XC8 imposes.
The timer is configured to count every uS, and the routine simply waits for the overflow flag.
The function works fine, but it has a 7uS overhead - and this is running with a 32MHz clock - the routine below toggles an I/O pin, feeding my scope, and producing a 100uS square wave.
I used this to trim my timing values, by subtracting 7 from each value, as in this example:
So if you're using the free version of XC8 (or perhaps even the paid for version?), keep an eye open for timing overheads.
Before anyone asks, I used another timer and PWM module to generate the 40KHz (or 38KHz, or 36KHz) pulses, and gate them ON and OFF by setting the PWM to 50% or 0%.
Here's an example of my current debug output, when pressing ON/OFF on a Sony TV remote (actually the TV ON/OFF button on a Sony DVD remote).
However, this reminded me of when I did the same thing years ago, using assembler, based on my tutorial IR routines.
Ian Rogers very kindly converted my tutorials to C, and provides a link to them in his signature - but (as I recall) he'd never had a Sony remote or TV to try them with - although possibly they may have worked, as he uses the commercial (expensive) XC8 compiler which is considerably more optimised, and faster.
However, when I tried the free version of XC8 a number of years ago, they wouldn't work, as the timing was FAR too slow, where as the original assembler version allowed accuracy to 1uS even with a 4MHz clock. So following the recent thread, I thought I'd make a 'proper' effort to produce a version that works with the free version of XC8 - and so far I've got it working really well. For anyone who's interested?, I'm using the SMT timer on modern PIC's (the 16F18857 in this instance) to handle receiving the incoming IR data stream.
Now the issue for transmission was still timing - as you need 600uS, 1200uS and 2400uS series of 40KHz pulses.
One of my favourite simple timing routines is:
C:
void delayMs(int x)
{
while(x--)
__delay_ms(1);
}
Which gives a simple variable millisecond delay function, which works perfectly, as the millisecond resolution is enough to 'lose' the XC8 overheads. So I simply wrote a similar routine for uS.
C:
void delayUs(int x)
{
while(x--)
__delay_us(1);
}
Utter disaster - the huge overheads made it completely unusable - I did measure them, and it was BAD!!
My solution was to use a timer to do it, and while it works, I'm still less than impressed at the overhead Free XC8 imposes.
C:
void Timer1_us(unsigned int timeval)
{
// Clearing IF flag.
PIR4bits.TMR1IF = 0;
TMR1_WriteTimer(65535-timeval);
while(PIR4bits.TMR1IF == 0){}; // wait for timer interrupt flag
T1CONbits.TMR1ON = 0; // disable timer
}
The timer is configured to count every uS, and the routine simply waits for the overflow flag.
The function works fine, but it has a 7uS overhead - and this is running with a 32MHz clock - the routine below toggles an I/O pin, feeding my scope, and producing a 100uS square wave.
C:
#define TOGGLE_LED LATBbits.LATB7=~LATBbits.LATB7
while(1)
{
Timer1_us(93);
TOGGLE_LED;
}
I used this to trim my timing values, by subtracting 7 from each value, as in this example:
C:
// send start bit
ir_mark(SONY_HDR_MARK-7);
ir_space(SONY_HDR_SPACE-7); // -7us to allow for timer setup time
So if you're using the free version of XC8 (or perhaps even the paid for version?), keep an eye open for timing overheads.
Before anyone asks, I used another timer and PWM module to generate the 40KHz (or 38KHz, or 36KHz) pulses, and gate them ON and OFF by setting the PWM to 50% or 0%.
Here's an example of my current debug output, when pressing ON/OFF on a Sony TV remote (actually the TV ON/OFF button on a Sony DVD remote).
Code:
******************
PulseNum = 13
******************
Start bit:
Pulse Width 0 = 2508 - Space Width 0 = 508
Command code:
Pulse Width 1 = 1283 - Space Width 1 = 509
Pulse Width 2 = 685 - Space Width 2 = 509
Pulse Width 3 = 1283 - Space Width 3 = 509
Pulse Width 4 = 686 - Space Width 4 = 509
Pulse Width 5 = 1283 - Space Width 5 = 508
Pulse Width 6 = 686 - Space Width 6 = 509
Pulse Width 7 = 686 - Space Width 7 = 509
Device code:
Pulse Width 8 = 1284 - Space Width 8 = 508
Pulse Width 9 = 686 - Space Width 9 = 509
Pulse Width 10 = 686 - Space Width 10 = 509
Pulse Width 11 = 685 - Space Width 11 = 509
Pulse Width 12 = 686 - Space Width 12 = 0
DataValue Hex = 0x095 - Command Hex = 0x015 - Device Hex = 0x01
TV On/Off pressed
Last edited: