phil99
 Guru
 Joined: 11/02/2018 Location: AustraliaPosts: 3191 |
| Posted: 11:50am 30 Aug 2024 |
|
|
|
Here is a MMBasic version of the NECsend Subroutine that supports 8 and 16 bit Device Codes, with or without bit order reversal*** and the Samsung32 variant. Tested on Picomite and ArmMiteF4.
***The MMBasic IR reading command outputs codes with MSB first and 16 bit Device Code so this is the default setting but the NEC specifies LSB first. This can be selected with an extra parameter if you have codes intended for that format.
Usage: Call "NECsend DeviceCode, KeyCode [, Variant]"
If using the Sub in an existing program that can't have a separate Variant parameter the parameter can instead be bit shifted up 16 and added to the DeviceCode.
eg Inc DeviceCode, (Variant << 16) Then Call "NECsend DeviceCode, KeyCode
Variant: 0 standard NEC 16 bit DeviceCode, MSB first (default) 1 Samsung32 2 standard NEC 8 bit DeviceCode, MSB first 3 standard NEC 16 bit DeviceCode, LSB first 4 standard NEC 8 bit DeviceCode, LSB first
' "NECsend with option for Samsung32 variant.bas" 'Dim Integer IRpin=MM.Info(pinno GP0) 'for Picomite - set your output pin Dim Integer IRpin=MM.Info(pinno PA0) 'for ArmMiteF4 - set your output pin Dim Integer dev, key, V 'for standard NEC V = 0, or omit. V = 1 for Samsung32 'for 8 bit NEC Dev code V = 2 'for 16 bit, LSB first NEC Dev code V = 3 'for 8 bit, LSB first NEC Dev code V = 4
'Alternatively those variants can instead be denoted by adding them to Dev above bit 16 'eg. for S32 (V=1) Device 5 Dev = &H10005 = 65541 Do 'Your program here. Input "Enter Device, Key, Variant (NEC=0, S32=1) codes "; dev, key, V NECsend IRpin, dev, key, V Loop
Sub NECsend IRpin As integer, Dev As integer, Key As integer, V As integer Local Integer word, d(1390), m, n = 1 Local Float T Pin(IRpin) = 0 Math set 13, d() 'fill array. 13=1000/(38*2) uS - duration of a half cycle @ 38kHz 'Math set 14, d() 'to overcome F4 timing error use this instead of line above
If V = 0 Then V = (Dev >> 16) ' if V missing or 0 then look for V in Dev above bit 16 Dev = Dev AND &Hffff
If V = 1 Then dev = ((Dev AND 255) * &H0202020202 AND &H010884422010) MOD 1023 'ensure 8 bits only & key = ((Key AND 255) * &H0202020202 AND &H010884422010) MOD 1023 ' reverse bit order word = (dev<<24) + (dev<<16) + (key<<8) + 255-key 'assemble 32 bits BitBang bitstream IRpin, 330, d() 'send 4.5ms start 38kHz Else
If (V=2) OR (V=4) Then dev = (Dev << 8) + 255-Dev 'convert 8 bit address to 16 if required If (V=3) OR (V=4) Then key = ((Key AND 255) * &H0202020202 AND &H010884422010) MOD 1023 ' reverse Key bit order, 8 bit dev16 = (((dev AND 255) * &H0202020202 AND &H010884422010) MOD 1023) << 8 ' reverse Dev bit order, low byte dev = dev16 + ((dev >> 8) * &H0202020202 AND &H010884422010) MOD 1023 'now reverse high byte & swap bytes EndIf word = (dev<<16) + (key<<8) + 255-key ':Print Bin$(word,32) 'assemble 32 bits '16 bit address only BitBang bitstream IRpin, 620, d() 'send 9ms start 38kHz EndIf
T = Timer' :Print t For m = 42 To 1386 Step 42 'load data after start sequence, step 42 = 21 cycle IR pulse d(m) = (((word>>(32-n)) AND 1)*2 + 1) * 560 'convert bits to duration (short = 0, long = 1) Inc n ':Print d(m); 'step to next data bit Next
Do : Loop Until Timer > T+4.3 ':Print Timer-T 'less than 4.5 due processing time, adjust for CPU speed BitBang bitstream IRpin, 1386, d() 'send the data
'Pin(IRpin) = 0 End Sub
'Samsung32 specification:- 'coding: Pulse Distance (same as NEC, fixed length pulses, long pause=1 short=0) 'Frame: 1 start + 32 Coding + 1 Stop bit (same as NEC) 'Data: 8 bit address + 8 bit address + 8 bit command + inverted 8 bit command - all bytes LSB first ' (old NEC 8bit address similar but 2nd copy inverted. Most NEC use 16bit address) 'Start Bit: 4500uS pulse 4500uS pause (NEC Start Bit: 9000uS pulse 4500uS pause) 'Data: 0 bit = 550uS pulse + 550uS pause, 1 bit = 550uS pulse + 1650uS pause ' (close enough to NEC - 562.5uS, difference = 1/2 cycle & 38kHz) 'Stop Bit 550uS pulse (almost same as NEC - 562.5uS) 'Repetition after 47mS End The current F4 BitBang Bitstream command has a small timing error, however for most devices it is close enough. If some don't work changing: Math set 13, d() to Math set 14, d() should fix it.
The MMBasic IR command reads Sony and standard NEC codes but not the Samsung32 variant. So here is a IR code reader for the Samsung32 variant. Tested on a PicoMite. Samsung32 has a 4.5mS start pulse instead of 9mS and has an 8 bit device code repeated without inverting. Bit timings are multiples of 550uS instead of 562.5uS but I found 560uS works for both.
' "Samsung32 IR code receiver.bas" ' tested on PicoMite v5.09.00 126MHz to 400MHz Dim Integer Dev, Key, IRpin=MM.Info(pinno GP6) ' set your pin SetPin IRpin, INTL, IR_Rx_Samsung32 Print Print "Dev", "Key"
Do : Loop
Sub IR_Rx_Samsung32 SetPin IRpin, off :SetPin IRpin, DIN 'stop interrupt and prepare to get data Local float T=Timer, T1, Tmax=300, Z=T+Tmax Local Integer n, m
Do :Loop Until Pin(IRpin)Or(Timer>Z),:Do While Pin(IRpin)And(Timer<Z):Loop :T1=Timer-T 'wait for start sequence to complete then get time, falling edge to falling edge For n=0 To 31 T=Timer :Do :Loop Until Pin(IRpin):Do While Pin(IRpin):Loop :T1=Timer-T
If T1>1.4 And T1<2.4 Then 'measure bits, add to word, LSB first into MSB and shifting down m=(m>>1) + &H80000000 'add 1 Else m=m>>1 'add 0 EndIf Next
SetPin IRpin, off ' Print :Print Bin$(m,32), "Bit order reversed so MSB is on the left" :Print
' Print Bin$(m And &Hff,8), Bin$(m>>16 And &Hff,8) 'show assembled bytes 1 & 3 (m is in reverse order) ' Print Bin$(m>>8 And &Hff,8), Bin$(255-(m>>24) And &Hff,8) 'show assembled bytes 2 & inverted 4 'error check. compare byte 1 and byte 2 If ((m And 255) = ((m>>8) And 255)) And (((m>>16) And 255) = (255-((m>>24) And 255))) Then dev = m And &Hff 'get device code key = m >> 16 And &Hff 'get key code Print Dev, Key Else dev=-1 :key=-1 EndIf
Pause 300 'prevent re-triggering, Samsung remote always sends code twice SetPin IRpin, INTL, IR_Rx_Samsung32 'prepare for next input
End Sub
'Samsung32 specification:- 'coding: Pulse Distance 'Frame: 1 start + 32 Coding + 1 Stop bits 'Data: 8 bit address + 8 bit address + 8 bit command + inverted 8 bit command all LSB first 'Start Bit: 4500uS pulse 4500uS pause 'Data: 0 bit = 550uS pulse + 550uS pause, 1 bit = 550uS pulse + 1650uS pause 'Stop Bit 550uS pulse 'Repetition after 47mS 'on the remote control I have a button press always sends the code at least twice Edited 2024-08-30 22:00 by phil99
Footnote added 2024-08-31 11:18 by phil99 First Bug - MM.INFO(Pinno xx) is different on F4 to Pico. It gives the first pin of the Port, not the individual pin number. By blind luck the pin I used was the first pin of that port so it worked.
For the F4 define IRpin this way:- ' "NECsend with option for Samsung32 variant.bas" 'Dim Integer IRpin = MM.Info(pinno GP0) 'for Picomite - set your output pin Dim Integer IRpin = 23 '= PA0 for ArmMiteF4 - set your output pin |