IR Remote Control Rx and Tx for Philips RC-5 Protocol.


Author Message
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 3407
Posted: 12:55am 11 Oct 2024      

This months edition of Silicon Chip has an article that includes a description of IR protocols. From that I see that my RC-6 Rx and Tx Subs aren't quite right. The start sequence includes a Bit that I missed.

Here is an updated version.
Not having anything to test it on is a bit of a problem so any feedback from anyone that does have RC-6 equipment would be welcome.
' "IR Philips RC-6 Mode 0 Rx & Tx.bas"
'Option explicit
Dim integer RxPin=MM.Info(pinno GP0), TxPin=MM.Info(pinno GP1) ' set GPxx for IR Rx & Tx
Dim Integer N = 48 ' expected maximum number of transitions, plus a few

Dim integer m, b(N), c(N\2), dev, key, r(N*2), Tend, Toggle, Type'Type = RC6 Mode or Field
Dim Float T
'SetPin RxPin, off 'for RP2350 if all pins have been set to DIN Pullup at start-up.
SetPin RxPin, intl, IR_RC6_Rx 'wait for IR activity to pull IRpin low
'SetPin TxPin, off 'for RP2350 if all pins have been set to DIN Pullup at start-up.
SetPin TxPin, DOUT

Print " To send commands un-comment the lines near the end of the program then:-"
Print " Toggle toggles between 0 and 1 on each Key press to distinguish from auto-repeat"
Print " Device = device code, 0 to 255"
Print " Key = Key code, 0 to 255." : Print
Print " Press a key on the IR remote control to record the RC-6 code" : Print

Sub IR_RC6_Rx
 SetPin RxPin, off : SetPin RxPin, Din :m=1 :b(0)=0 :T=Timer
 Do While (Pin(RxPin)=0) And (Timer-T<300) :Loop 'skip lead-in pulse
 Do While (Pin(RxPin)=1) And (Timer-T<300) :Loop
 Do While m<(N-1) And (Timer-T<300)  'get pulses/pauses & convert to Manchester bits
  Do While (Pin(RxPin)=0) And (Timer-T<300) :Loop
  If (Timer-T)>5 Then Exit Do
  b(m)=1
  If m=10 Or m=11 Then Inc T,0.444 'toggle is 444uS longer than normal pulse
  If (Timer-T)>0.66 Then : Inc m : b(m)=1 : EndIf
  T=Timer :Inc m
  Do While (Pin(RxPin)=1) And (Timer-T<300):Loop
  If (Timer-T)>1.9 Then Exit Do
  b(m)=0
  If m=10 Or m=11 Then Inc T,0.444 'toggle is 444uS longer than normal pause
  If (Timer-T)>.66 Then : Inc m :b(m)=0 : EndIf
  T=Timer :Inc m
 Loop

 SetPin RxPin, off 'disable interrupt while processing
 If b(6)+b(7)+b(8)+b(9)=0 Then GoTo no.data
'  Print :Print "IR BitStream - b() ":Math V_Print b()

 m=2
 Do While m<(N) 'convert pairs of Manchester half-bits to ordinary bits (oposite of RC-5)
  If (b(m)=0)And(b(m+1)=1) Then c(m\2-1)=0 '01 = 0
  If (b(m)=1)And(b(m+1)=0) Then c(m\2-1)=1 '10 = 1
   Inc m, 2
 Loop

'  Print "c()=bits  ";:Math V_print c()
 Type = c(1)*4+c(2)*2+c(3) : toggle=c(4) : dev=0 : key=0

 'Toggle toggles on each key press to distinguish autorepeat from double press
 For m=5 To 12 : Inc dev,dev + c(m) : Next 'assemble Device code
 For m=13 To 20 : Inc key,key + c(m) : Next 'assemble Key code

 Print "Received:- Type";type;"  Toggle";toggle;"  Dev";dev;"  Key";key :Print

'un-comment the following lines to re-transmit the received code to verify operation
'  Pause 3000 : Print "re-sendimg above codes, with Type = 0"
'  IR_RC6_Tx toggle, dev, key 'resend the received code after 3S
'  Pause 83
'  IR_RC6_Tx toggle, dev, key 'resend the received code after 3S
'  toggle=Not toggle

 no.data:
 T=0
 Math set 0, b()
 Math set 0, c()
 Pause 400 'block repeat codes
 SetPin RxPin, intl, IR_RC6_Rx 're-enable interrupt for next key

End Sub

Sub IR_RC6_Tx(toggle, dev, key) As integer
 toggle=toggle And 1 : dev=dev And 255 : key=key And 255 'only uses Field=0
 Local integer ord(16), bs(900), m=0, n
 Math set 14, bs() 'load BitStream array with 36kHz half cycles (14uS)
 'assemble ordinary bit array
 m=0 : For n=15 To 8 Step -1 : ord(n) = (key >> m) And 1 : Inc m :Next
 m=0 : For n=7 To 0 Step -1 : ord(n) = (dev >> m) And 1 : Inc m :Next

 'Print "ord()  ";:Math V_print ord()
 'fixed 3 bit Field / Mode number = 0 for consumer electronics
 'convert ordinary bits to pairs of Manchester half-bits and load into BitStream array -
 'merging adjacent high or low pairs of half-bits into long highs or long lows,
 ' without causing inversions in the BitStream

 'half cycle at 36kHz = 14uS = 32 half cycles per short pulse, 65 per long pulse
  bs(193)=889 : bs(225)=889 : bs(257)=444 : bs(289)=444
   ' Leader pulse + Start bit=1 + Mode=0 3 bits
 If toggle=0 Then bs(321)=889 'long pause - long pulse for toggle bit
 If toggle=1 Then bs(387)=889 'short pulse+long pulse - long pause
 m=387
 If toggle=0 And ord(0)=0 Then bs(m)=444
 If toggle=1 And ord(0)=1 Then bs(m)=889
 If toggle=1 And ord(0)=0 Then bs(m)=1333
 If toggle=0 And ord(0)=1 Then bs(m+32)=444
 Inc m,32

 For n=0 To 15
  If ord(n)=ord(n+1) Then bs(m)=444
  If ord(n)=1 And ord(n+1)=0 Then bs(m)=889
  If ord(n)=0 And ord(n+1)=1 Then bs(m+32)=444
  Inc m,32
 Next

'  BitBang BitStream TxPin, 900, bs() 'for ARMMiteF4
 Device BitStream TxPin, 900, bs() 'for PicoMite
 Pin(TxPin) = 0 'ensure correct polarity for next run
 Pause 5
 Device BitStream TxPin, 900, bs() 'for PicoMite
 Pin(TxPin) = 0 'ensure correct polarity for next run
'  Print : Math V_print bs() :Print

End Sub

dev = 128 : key = 0
Do 'un-comment the next line to send data
'  Input "Enter RC-6 Data:- toggle, Device, Key "; toggle,dev,key
 IR_RC6_Tx toggle,dev,key
 Print "Sent:- toggle";toggle,"dev";dev,"key";key
 Inc key
 Pause 2000
 IR_RC6_Tx toggle,dev,key
 Print "Sent:- toggle";toggle,"dev";dev,"key";key
 Inc dev
 Pause 2000
 toggle = Not toggle

Loop
End

Edited 2024-10-11 11:45 by phil99

Footnote added 2024-10-12 21:48 by phil99
Noticed some redundant variables and commands left over from development.

in this line near the start:
Dim integer m, b(N), c(N\2), dev, key, r(N*2), Tend, Toggle, Type'Type = RC6 Mode or Field
delete:
r(N*2), Tend,

And near the end of Sub IR_RC6_Rx remove:
Math set 0, b()
Math set 0, c()


Footnote added 2024-10-13 16:38 by phil99
Red Face Time!

Math set 0, b()

does serve a purpose. As the number of transitions for a fixed number of bits can vary in Manchester encoded data, there can be a left-over bit or two in b() from the previous IR input.
This can result in the last bit of the Key code being a 0 instead of 1.

However you don't need to set the whole array to 0. Replacing Math set 0, b() with b(43)=0 is all that is needed to fix it.

Footnote added 2024-10-13 22:16 by phil99
Bought a universal remote control and programmed it for a Philips RC-6 TV and Sub IR_RC6_Rx outputs the correct codes for all the buttons!
When those codes are fed into Sub IR_RC6_Tx the Rx Sub repeats them so it all works.