📄 asuro 013, remote controlled by rc5.c
字号:
/*
================================================================================
Program : Asuro controlled by IR remote control
Release date : 2004-09-16
Author : Henk van Winkoop
Build : 037, 2004-09-16, V2.1
Build : 038, 2005-02-01, V2.2, comments enlarged/added
================================================================================
Asuro is remotly controlled by infrared signals according the RC5 standard.
Use keys: Vol-, Vol+, Prg-, Prg+ and Standby for driving left/right/forward/reverse/stop.
Remember:
If Asuro is driving, both engines will draw relatively much current from the batteries.
The battery voltage will drop significantly.
The Asuro IR-receiver chip is very sensitive to low voltage.
So with not fully charged batteries, Asuro may not respond to remote control signals when driving!
An RC5 signal is 14 bits width.
2 startbits, a toggle bit, 5 address bits, 6 command bits
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| S1 | S2 | TG | A4 | A3 | A2 | A1 | A0 | C5 | C4 | C3 | C2 | C1 | C0 |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
A low bit starts with a high level, going low halfway bittime.
| |
+---+ |
| | |
| +---+
| |
A high bit starts with a low level, going high halfway bittime.
| |
| +---+
| | |
+---+ |
| |
Each RC5-bit duration is 1778us.
Asuro contains a 3-pin IR(Infra Red)-signal receive chip.
This chip demodulates any received 36KHz infrared signal and outputs a clean digital code.
If Asuro is beamed with an RC5 remote control, this chip will output a clean RC5 digital code.
The Asuro IR-chip output is directly connected to the ATMEGA8 (microcontroller) RXD pin.
Normally, the first bit of a RC5 signal received by the ATMEGA8 RXD pin should generate an interrupt.
This interrupt then would start a internal ATMEGA8 timer for analysing the next received RC5 bits.
The ATMEGA8 RXD pin however can not simply generate an interrupt.
It only generates an interrupt if a valid serial CHARACTER (complete valid character, not signal)
is received on the RXD-pin.
Probably the Asuro was not intended to be used for IR-control.
So we need to use a little trick.
The UART generates an interrupt when a valid complete character is received.
The UART detects a valid character if a low-going startbit is detected and if after a certain time
(depending on the baudrate) a valid high-level (stopbit) is detected.
Now we use the low-going edge in the first RC5-startbit (S1) as the UART startbit detection.
If we set the UART to 4800baud and if we set the expected/received character to have 5 bits,
then the UART will expect a high-level stopbit in the middle of the high part of our second
RC5-startbit (S2)
|-------------------RC5-code-as-is-generated-by-Asuro-IR-receive-chip-------------------|
|---startbit1---|---startbit2---|---togglebit---|---address4----|--//---|---command0----|
|----low-bit----|----low-bit----|-low/high-bit--|-low/high-bit--|--//---|-low/high-bit--|
|-----1778us----|-----1778us----|-----1778us----|-----1778us----|--//---|-----1778us----|
|--------------------------------14*1778=24892us----------------------------------------|
+-------+ +-------+ +-------+-------+-------+-------+--//---+-------+-------+
S1(h)| S1(l)| S2(h)| S2(l)| TG | TG | A4 | A4 | | C0 | C0 |
+-------+ +-------+-------+-------+-------+-------+--//---+-------+-------+
|-------------| expected character-length by UART when UART is set to 4800baud/5bits per character
->| |<- startbit
->| |<- expected stopbit
0 0 0 1 1 <- received 5-bits data, not important/not used
--------+ +-+-+-+-+-+-+-------------
|S|1|2|3|4|5|S
+-+-+-+-+-+-+|
|
|<- halfway stopbit an interrupt is generated by the UART (detecting valid received character)
|
+-------+ +----|--+ +-------+-------+-------+-------+--//---+-------+-------+
S1(h)| S1(l)| S2(h)| S2(l)| TG | TG | A4 | A4 | | C0 | C0 |
+-------+ +-------+-------+-------+-------+-------+--//---+-------+-------+
So it is NOT possible to generate an interrupt in the first RC5-startbit S1 as was first
intended but it IS possible to generate an interrupt in the SECOND RC5-startbit S2.
Because each RC5 code always contains 2 startbits, this is no problem.
In stead of using 4800baud/5bit we could also have used 9600baud/8bit to let the stopbit occur in the
high part of the RC5-S2 signal.
Now we can start the internal ATMEGA8 timer0 to detect the level of the remaining RC5 bits.
|<- here an interrupt is generated by the UART
|
+-------+ +----|--+ +-------+-------+-------+-------+--//---+-------+-------+
S1(h)| S1(l)| S2(h)| S2(l)| TG | TG | A4 | A4 | | C0 | C0 |
+-------+ +-------+-------+-------+-------+-------+--//---+-------+-------+
After the first interrupt, timer/counter0 is used to measure the delay to the next bits.
As the first timer/counter0 interval (A1-B2) differs from the remaining timer/counter0 intervals (B2-B14), a
different timer/counter0 timervalue is used.
|---startbit1---|---startbit2---|---togglebit---|---address4----|--//---|---command0----|
|----low-bit----|----low-bit----|-low/high-bit--|-low/high-bit--|--//---|-low/high-bit--|
|-----1778us----|
|---------2223us--------|
|<- here an interrupt is generated by the UART
|
+-------+ +----|--+ +-------+-------+-------+-------+--//---+-------+-------+
S1(h)| S1(l)| S2(h)| S2(l)| TG | TG | A4 | A4 | | C0 | C0 |
+-------+ +-------+-------+-------+-------+-------+--//---+-------+-------+
--|---------------|---------------|-----------------------|---- needed timer0 interrupts
---1--- timer0 interrupts counter (dummy, predefined)
---2---------------3---------------4----------------------14---- timer0 interrupts counter (updated)
--------+ +-+-+-+-+-+-+-------------
|S|1|2|3|4|5|S
+-+-+-+-+-+-+
|-----1778us----| (length of one single RC5 bit)
|---1352us---| (208us (=1/4800baud) * 6,5 (1 startbit + 5 databits + 0,5 stopbit))
|--| 426us ((A) distance between 4800baud-stopbit/interrupt and RC5-S2 going low)
|---| 445us ((B) = 1778/4 = length of a quarter of one RC5-bit)
|------| 871us (= (A) + (B) = 426 + 445 = distance between interrupt and half of low half of RC5-S2
So each time a UART interrupt is generated, timer0 is used to delay the running program for 871us so it will be
exactly in the middle of the low part of RC5-startbit S2.
Then for each remaining RC5 bit, timer0 will be used to find the middle of each second-half of each bit .
Timer0 prescaler output /256 is selected. So timer0 clock frequency is 8MHz / 256 = 31250Hz = 32us period.
Timer0 is 8-bits wide, so timer0 continuously counts up from 0 to 255 and then resets to 0 again.
Timer0 generates an interrupt (if enabled) on each 255 to 0 transition.
To make timer0 delay (first time) 871us, divide it by timer0 clockcycle duration of 32us makes 871/32 = 27 clockcycles.
To make timer0 delay 27 (0x1B) clockcycles, set it's initial value to 0xFF minus 0x1B = 0xE4.
So it will take 27*32 = 864us (closest to 871us) after a UART interrupt when the first timer0 interrupt will occur.
|------| 871us (= (A) + (B) = 426 + 445 (871/32=27=0x1B => 0xFF-0x1B=0xE4)
The USART takes 3 samples in the middle of each bit. Also in the expected stopbit.
If valid, an interrupt will be generated immediately after detecting a valid stopbit,
so almost halfway the stopbit, which is approximately halfway the RC5-S2 bit.
The RXD interrupt handler will then disable itself and init timer/counter0 and enable timer/counter0 interrupt.
When timer/counter0 interrupt handler has detected 1 dummy (RC5-S2) plus 12 real bits, it will disable it's own interrupt.
Remember: each bit value is checked in the second half part of each bit, because the second half part represents the
real bit value. But, because a '1' bit in real world is represented by a low voltage level, (due to IR-chip characteristics)
the bit-value detected must be inverted to represent the real received infrared value.(???)
Some IR signal info:
Infrared signal carrier frequency = 36KHz
Infrared signal carrier bit duration = 1/36000 = 27,78us
Each data bit takes 64 carrier bits. so...
- data bit frequency = 36000/64 = 562,5Hz
- data bit size = 64*27,78us = 1778us
########## NO NEED TO READ, JUST FOR MY OWN THOUGHTS ##########
TTTTTTTTTT
1234567890
+-+ +-+ +-+
| | | | | |
+-+ +-+ +-+ +-//
+-+ +-+-+ +-//
| | | | |
+-+ +-+ +-+
+---+---+---+---
S1 S2 TG
To detect first startbit, be sure that a stopbit is detected at positin 6.
Set baudrate to 9600, one bit is 104us,
Low level from 1st startbit is at t=890us.
stopbit (bit 8 from 0-7) is from 832us to 936us
4800baud and 5 bits
bit time
1 = 0 - 207 ns
2 = 208 - 415 ns
3 = 416 - 623 ns
4 = 624 - 831 ns
5 = 832 - 1039 ns
S = 1040 - 1247 stopbit is well inside low part T6 (T6=890ns-1780ns)
Using baudrate 4800 with 5-bits dataframe will find valid stopbit inside T6.
If a valid frame is detected then a '1' bit is assumed to be received.
If a frame error is detected then a '1' bit followed by a '0' bit is assumed to be received.
This will make the expected 4800baud stopbit detection occur in the high part of the second startbit S2.
A startbit is detected when S1 is going low. The expected stopbit must be in the high part of S2.
If the bitrate is set, for instance, to 9600baud (104us) then using 8-bits with 1 startbit and 1 stopbit,
will expect a stopbit at (1+8+0.5) * 104 = 9.5 * 104 = 988us after S1 going low, is in high part of S2.
So this bitrate will also work fine.
The bitrate must be choosen that way, so that the expected stopbit will occur in the high part of S2.
########## END OF NO NEED TO READ, JUST FOR MY OWN THOUGHTS ##########
*/
#include "asuro.h"
#include "hvwdefines.h"
//remote control key codes
#define REMOTE_KEY_STD_BY 12
#define REMOTE_KEY_VOL_UP 16
#define REMOTE_KEY_VOL_DW 17
#define REMOTE_KEY_PRG_UP 32
#define REMOTE_KEY_PRG_DW 33
#define REMOTE_KEY_0 0
#define ASURO_FORWARD REMOTE_KEY_PRG_UP
#define ASURO_REVERSE REMOTE_KEY_PRG_DW
#define ASURO_TURN_LEFT REMOTE_KEY_VOL_UP
#define ASURO_TURN_RIGHT REMOTE_KEY_VOL_DW
#define ASURO_STOP REMOTE_KEY_0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -