Published using Google Docs
( SWI2IR.fth )
Updated automatically every 5 minutes

 ( STEERING WHEEL INTERFACE to INFRARED REMOTE CONTROL )

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