TACHYON
[~
pri SWI2IR.fth ." Steering Wheel Interface to IR remote - 130111.2357 " ;
{
The Problem:
The new car stereo does not support the buttons on the Steering Wheel Interface (SWI) which uses different resistance values for each button. Of course I could just buy another stereo that might be more compatible but that's no fun.
The Solution:
Interface to the SWI with a Propeller and measure the resistance while converting these into code ranges which end up sending out the correct infrared remote control codes to the car stereo.The IR LED does not need to be facing the unit as there is sufficient energy and light bounce if it is simply mounted or recessed on the dashboard area pointing to the rear of the vehicle.
The Implementation:
- Hardware
Adapt one of my Propeller boards (EcoLCD PX) that was designed as an 5V LCD backpack with backlight and soft contrast control. Since the current drain is low just add a linear 5V regulator to operate from 12V. Seeing I have a boxload of old DB25 enclosures I used one of these and ended up trimming off the ears.
- Steering Wheel Interface
Use the RC "contrast" network to interface to the SWI and measure the RC time constant. To simplify software a 100K resistor is added in parallel with the SWI interface so that it will discharge and timeout during sampling plus the 100K and 0.1uf of network could be used to self-calibrate.
- Infrared Interface
The IR LED is connected to the NPN which normally drives the LCD backlight but I added a 100R resistor in series to limit the current. There is also an IR receiver (TSOP1128) that was used during development to read the IR codes from the stereo's remote control.
- Development
To make it easier for me during development I have added one of my serial Bluetooth modules so that I can just bury the interface into the back of the dash and test and program from my laptop or tablet. This is possible because Tachyon is preloaded onto the Propeller and new code can be downloaded and locked into EEPROM ready for turnkey (literally) operation. At anytime I can still talk to the system and make changes all over serial Bluetooth. In fact this can be done from a smartphone using Blueterm.
Result
Worked first time and my wife was very happy. I'm chuffed because it all came together nicely and it's another feather in the hat for Tachyon as a very useful and powerful development tool and language.
To Do
Add more functionality to the buttons with longer presses and context sensitive operations. Even put a mode in there that automatically dials home if mode is held for 3 seconds.
}
( *** INFRARED RECEPTION *** )
\ Not really required but easy enough to add and useful for sampling RC codes.
\ Use an IR receiver (TSOP1128) to sample codes using the -1 method
#P16 |< CONSTANT =rxinp
pub IRRX
BEGIN
=rxinp WAITPNE \ wait for low
=rxinp WAITPEQ \ wait for high
=rxinp WAITPNE \ wait for low
CNT@ =rxinp WAITPEQ CNT@ SWAP - \ synch period
0 BL FOR \ measure high skip low
2*
CNT@ =rxinp WAITPNE CNT@ SWAP - 3RD / 1 > 1 AND +
=rxinp WAITPEQ \ skip low, wait for high
NEXT
CR .LONG NIP
#200 ms
KEY? AND
UNTIL
;
{
CODES FROM CAROL'S CAR STEREO
8bit 32bit LABEL Patterns
$0F 817EF00F PWR/MUTE 1111 0000 0000 1111
$0C 817E30CF VOL UP 0011 0000 1100 1111
$13 817EC837 MODE/PAIR
$09 817E906F |<<
$0A 817E50AF SEL
$08 817E10EF >>|
$07 817EE01F END/BND
$0B 817ED02F VOL DN
$15 817EA857 CALL
$01 817E807F 1 1000 0000 0111 1111
$02 817E40BF 2 0100 0000 1011 1111
$03 817EC03F 3 1100 0000 0011 1111
$04 817E20DF 4 0010 0000 1101 1111
$05 817EA05F 5 1010 0000 0101 1111
$06 817E609F 6 0110 0000 1001 1111
$10 817E08F7 7 0000 1000 1111 0111
$11 817E8877 8 1000 1000 0111 0111
$12 817E48B7 9 0100 1000 1011 0111
$0D 817EB04F * 1011 0000 0100 1111
$0E 817E708F 0 0111 0000 1000 1111
$14 $817E28D7 #
817E = 1000 0001 0111 1110
Codes are sent in 8-bit groups lsb first followed by the complement byte
[FAMILY CODE] [COMPLEMENT] [CODE] [COMPLEMENT]
FAMILY CODE = $81
}
( *** INFRARED TRANSMISSION *** )
#P24 CONSTANT =irled
BYTE family \ IR family code byte
$81 family C!
pub IRLED ( units -- )
A =irled APIN #38 KHZ \ Generate a 38kHz carrier
#460 * us
MUTE \ mute or stop the carrier
;
pub IRTX8 ( byte -- )
8 FOR
DUP 1 AND IF #1530 ELSE #480 THEN us \ "high" period - a 1 is 3 times the length of a 0 high
1 IRLED \ the "low" pulse
2/
NEXT
DROP
;
\ Transmit the IR code byte as code + inverted
\ First transmit the preamble then the family code + invert and then the IR code + invert
pub IRTX ( code -- )
#20 IRLED \ HEADER PREAMBLE
#4200 us
1 IRLED \ "start" bit
family C@ DUP IRTX8 INVERT IRTX8
DUP IRTX8 INVERT IRTX8
;
\ Define some codes
: PHONE $15 IRTX ;
: PWR $0F IRTX ;
: VOLUP $0C IRTX ;
: VOLDN $0B IRTX ;
: MODE $13 IRTX ;
: ENDCALL
: BAND 7 IRTX ;
: >>| 8 IRTX ;
: |<< 9 IRTX ;
: DIRUP 6 IRTX ;
: DIRDN 5 IRTX ;
: SHF 4 IRTX ;
{ *** STEERING WHEEL INTERFACE ***
Measure the resistance of the steering wheel interface
Resistance is a maximum of 6K8 and open if no switches are pressed
RC time constant method is used to detect the resistance but to help there is
a 100K resistor added in parallel.
The resistance is referenced to ground and discharges the capacitor as this method offers good noise immunity.
PORT ------220R------|-------|-----> to SWI resistors
104C
|------------>
_|_
RESISTANCES FROM CAROL'S SWI
6800 VOL DN
4610 VOL UP
2116 MODE
1110 SEEK DN
0430 SEEK UP
}
#10 CONSTANT =scale
#P8 |< CONSTANT =swi
\ Convert the resistance to a workable value
pub SWI ( -- val )
=swi OUTSET \ charge the capacitor
#100 us \ for long enough (prototype is using a series 220R resistor)
=swi INPUTS \ now float the line
CNT@ =swi WAITPNE \ and wait for it to go low
CNT@ SWAP - \ calculate the time constant
=scale SHR \ justify
DUP #64 > IF DROP 0 THEN
;
\ Read the SWI until a stable reading is obtained.
pub SWI@ ( -- code )
0 BEGIN SWI SWAP OVER = UNTIL
;
\ Use this function to test the SWI buttons and codes
pub SWI?
BEGIN SWI@ ?DUP IF CR . #300 ms THEN KEY? AND UNTIL
;
\ The SWI buttons
$01 CONSTANT [SEEKUP]
$04 CONSTANT [SEEKDN]
$08 CONSTANT [MODE]
$18 CONSTANT [VOLUP]
$24 CONSTANT [VOLDN]
\ Maintain a variable for phone call state
BYTE phone
\ Simple function to allow a range of values but works through elimination from highest to lowest.
\ (really needs a CASE structure for these kinds of functions)
pub SWI:
DUP [VOLDN] => IF DROP VOLDN #100 ms EXIT THEN
DUP [VOLUP] => IF DROP VOLUP #100 ms EXIT THEN
DUP [MODE] => IF DROP phone C~~ PHONE #500 ms EXIT THEN
DUP [SEEKDN] => IF DROP phone C@ IF ENDCALL phone C~ ELSE |<< THEN #200 ms EXIT THEN
DUP [SEEKUP] => IF DROP >>| #200 ms EXIT THEN
DROP \ No button was pressed
;
pub MAIN
phone C~
BEGIN
SWI@ SWI: \ Read a button and execute
KEY? AND $1B = \ Allow stopping for debugging from the serial console (over Bluetooth)
UNTIL
;
AUTORUN MAIN
?BACKUP
]~
END