IRIN with a Samsung remote

pjrebordao

Senior Member
I would like to use a Samsung remote in a project. I'm assuming that Samsung uses the NEC protocol, but I'm not sure...

Has anyone implemented a routine (similar to IRIN) to read NEC codes ? On a 08M2 ?
Code doesn't need to run in background as program can wait for any command to be received.

Thanks
 

PhilHornby

Senior Member
See: (2) Background Infrared Receiver for 32-bit Codes | PICAXE Forum

or my rather less sophisticated offering (which was for debugging purposes - so would need some more work) :-

Code:
#picaxe 08m2
#terminal 38400
#no_data
#no_end

Symbol Debug_Pin        = C.4                ;20uS pulse sent to sync oscilloscope - if req'd
symbol Data_Pin         = C.3                  ;Infrared input from TSOP decoder

                                ;NOTE: The output from the 'TSOP' range of
                                ;IR detectors is inverted:-
                                ;LOW = Carrier burst detected
                                ;HIGH = Space
;
;
;
symbol PULSE_1_SPACE    = 1200     ;(1.5mS)    ;a "0" bit is (theoretically) 0.562ms burst and 0.562ms space 
                                          ;a "1" bit is 0.562ms burst and 1.687ms space
symbol AGC_Pulse_Length = 7100     ;(8.875mS)    ;leading pulse burst is 9mS and 4.5ms space
symbol AGC_Pulse_Length_Max = 7300    ;(9.125mS)    ;upper limit



; 28 - 63 spare

symbol BitStore = 64                    ;Space for 64 bytes in here (32 word values)

    setfreq M32

    sertxd ("NEC Protocol Analyser",cr,lf)

do
    gosub Get_Data
    if b0 <> $FF then
        sertxd(cr,lf,cr,lf,"Data Byte: 0x")
        gosub B0_TO_HEX
        sertxd(", (",#b0," decimal)",cr,lf)
    endif
loop


Get_Data:

    
    pulsin Data_Pin,0,W9                      ;Measure the low-going pulse. (TSOP o/p goes low, when it detects 38KHz carrier)
    if W9 < AGC_Pulse_Length or W9 > AGC_Pulse_Length_Max then
        if W9 <> 0 then                ;assuming it's not 'no pulse at all'
            sertxd(cr,lf,"Abort - pulse length: ",#W9)
        endif
        b0=$FF
        return
    endif
;
;    We are in the 4.5mS 'space', after the the initial 9mS carrier burst
;
    bptr = BitStore                    ;point at our storage location
    pulsout Debug_Pin,15                ;if required.
    ;
    ; Now we will be measuring the lengths of the high-going pulses. These are the gaps between 38KHz carrier detection
    ; and the length of these gaps signifies a "0" or a "1", depending on their length.
    ;
    for b2 = 1 to 32
        ;
        ; Measure the length of the next 32 bits and store their lengths (in 1.25uS units)
        ; in RAM. (The Picaxe isn't fast enough to analyse them on the fly.) Each Pulsin command
        ; has an 81.92uS timeout @ 32MHZ, so if we enter this loop 'under false pretences', we
        ; could be stuck here for 2.6S. Make sure AGC_Pulse_Length is set tight enough to prevent this.
        ;
        pulsin Data_Pin,1,W0 : @bptrinc = b0 : @bptrinc = b1 ; (uses 2 * 32 bytes)
    next b2

    pulsout Debug_Pin,15                ;if required
;
; Print data
;
    sertxd (cr,lf,cr,lf,"PACKET DECODE:-")
    bptr = BitStore                    ;Point at start of our store
    ;
    ; Print out the timings first
    ;
    
    ; W9 is the length of the input pulse - but needs to be multplied by 1.25 to get mS units.
    
    W10 = W9 / 4                    ;x = 1.25Y => x = (Y + 0.25Y)
    W10 = W10 + W9               
    sertxd(cr,lf,"Start pulse: ",#W10,"uS",cr,lf,cr,lf,"Timings:-",cr,lf)
 
    sertxd (cr,lf,"Address Byte:          ")
    gosub PrintTimingsFromBitStore
    sertxd (cr,lf,"Inverted Address Byte: ")
    gosub PrintTimingsFromBitStore
    sertxd (cr,lf,"Data Byte:             ")
    gosub PrintTimingsFromBitStore
    sertxd (cr,lf,"Inverted Data Byte:    ")
    gosub PrintTimingsFromBitStore
    sertxd (cr,lf,cr,lf,"Data interpretation:-",cr,lf)
    ;
    ; Now print the interpreted values these pulses represent
    ;
    bptr = BitStore                    ;Point at start of our store again
    
    gosub GetDataFromBitStore            ;Get the Address Byte
                                ;(Returns 'b0' and prints out its values in binary)
    b20 = b0                        ;save for comparison
    gosub GetDataFromBitStore            ;Get the Inverted Address Byte
    ;
    ; Check data validity
    ;
    b21 = b0 xor b20
    if b21 = $FF then
        sertxd (" (ok)")
    else
        sertxd (" *BAD!*")
        b0 = $FF
        return
    endif

    gosub GetDataFromBitStore            ;get the actual data byte
    b22 = b0                        ;save for comparison...

    gosub GetDataFromBitStore            ;...with the inverted byte
    ;
    ; Check data validity
    ;
    b21 = b0 xor b22
    if b21 = $FF then
        sertxd (" (ok)")
    else
        sertxd (" *BAD!*")            ;some remotes make use of BOTH bytes for actual data!
        b0 = $FF
        return
    endif

    b0 = b22                        ;Return the Data byte to caller
    b1 = b20                        ;and the controller address

    return


PrintTimingsFromBitStore:
    ;
    ; Print the timing values of the next eight pulses in the store
    ;
    for b1 = 1 to 8                    ;do for next 8 stored samples

        b2 = @bptrinc : b3 = @bptrinc     ;Get pair of bytes in W1
        ;
        ; Print the length of the pulse in uS (multiple by 1.25, as before)
        ;
        W2 = W1 / 4
        W2 = W2 + W1
        sertxd(#W2)
        ;
        ; Add a comma, unless it's the last one
        ;
        if b1 <> 8 then
            sertxd(",")
        endif
    next b1

    sertxd(" (uSecs)")
    return
    
    
GetDataFromBitStore:
    ;
    ; Interpret the next eight stored timings as a data byte; LSb first, so needs reversing.
    ;
    b4 = 0                        ;result
    for b1 = 1 to 8                    ;do for next 8 stored samples

        b0 = 0 : b2 = @bptrinc : b3 = @bptrinc : if W1 > PULSE_1_SPACE then : b0 = %10000000 endif
        b4 = b4 / 2                    ;shift previous answer 1 bit right
        b4 = b4 + b0                ;and add in the new 'bit'
    next b1

    b0 = b4                        ;return result
    sertxd(cr,lf,"RCV'D-> ","[",#bit0,"][",#bit1,"][",#bit2,"][",#bit3,"][",#bit4,"][",#bit5,"][",#bit6,"][",#bit7,"]")
    sertxd("  => ",#bit7,#bit6,#bit5,#bit4,#bit3,#bit2,#bit1,#bit0," <=") ; debug print of byte in binary

    return
    

;-----------bin to hex debug dump----------------
B0_TO_HEX:
        b1 = b0 / 16 + "0"
        gosub Nybble
        b1 = b0 & 15 + "0"
Nybble:
        if b1 > "9" then : b1 = b1 + 7    endif
        sertxd(b1)
        return
 

pjrebordao

Senior Member
Thanks for your nifty code ! But...
Tried with both a Sony and Samsung remotes and always get "Abort - pulse length" no matter what key pressed.

This is happening because the initial pulse length returned is always less than 7100 (around 400-600 usually). Any ideas ?
 

AllyCat

Senior Member
Hi,
I'm assuming that Samsung uses the NEC protocol, but I'm not sure...
Neither am I. ;) AFAIK there is a large number of IR protocols, in addition to NEC, Sony and Philips RC 5/6, etc...

However, this does "remind" me that I have a completed NEC receiver program waiting to be posted in the "Finished Projects" section, or I'd considered posting it in THIS RELATED THREAD.

If you think there's a reasonable chance that Samsung do use the NEC protocol (surely there's a link on the web?) , then I'll try to "expedite" my posting. As a taster/teaser here it is working in a 20M2 at 16 MHz, but it should run on any M2 because the 20M2 is the slowest of the M2s (at any given clock speed). The test traces include a standard PICaxe SERVO pulse stream, which is completely unaffected by the IR reception, but badly upset by the "echoed" SEROUT Diagnostics data!

NEC+Servo+.png

ADDED: Yes, a quick Google on the Internet HERE and HERE indicates that Samsung almost use the NEC protocol, but with a first "AGC" pulse of 4.5 ms instead of 9 ms. However, I didn't see if Samsung use NEC's weird "Repeat Code" method. So you may be able to get InglewoodPete's code to work, but I'll try to get my 16 MHz, M2, NEC code tidied up in a day or two.

Cheers, Alan.
 
Last edited:

PhilHornby

Senior Member
This is happening because the initial pulse length returned is always less than 7100 (around 400-600 usually). Any ideas ?
The most likely reason is that it's not NEC format. You probably need a bit more insight into what the IR receiver is actually 'seeing'.

(Assuming no access to a 'scope or Logic Analyser) a Sound Card/Audicity combo might do the trick.
Or even: http://www.delphiforfun.org/programs/oscilloscope.htm
 

pjrebordao

Senior Member
Hi,

Neither am I. ;) AFAIK there is a large number of IR protocols, in addition to NEC, Sony and Philips RC 5/6, etc...

However, this does "remind" me that I have a completed NEC receiver program waiting to be posted in the "Finished Projects" section, or I'd considered posting it in THIS RELATED THREAD.

If you think there's a reasonable chance that Samsung do use the NEC protocol (surely there's a link on the web?) , then I'll try to "expedite" my posting. As a taster/teaser here it is working in a 20M2 at 16 MHz, but it should run on any M2 because the 20M2 is the slowest of the M2s (at any given clock speed). The test traces include a standard PICaxe SERVO pulse stream, which is completely unaffected by the IR reception, but badly upset by the "echoed" SEROUT Diagnostics data!

View attachment 24612

Cheers, Alan.
If the information below is true, Samsung protocol seems to be a variation of NEC's with different start timing and a different layout of the 32 bit payload. If something works for NEC, it should be "easy" to make it work with SAM...

http://techiesms.blogspot.com/2016/01/ir-protocol-decoding-and-transmiting.html
 

pjrebordao

Senior Member
By changing the timing for the start pulse on Phil's code, now I can read a Samsung remote

Code:
symbol AGC_Pulse_Length = 3500     ;(8.875mS)    ;leading pulse burst is 9mS and 4.5ms space
symbol AGC_Pulse_Length_Max = 3700    ;(9.125mS)    ;upper limit
That's all it takes.

And I removed a validation as the address checking is different:

Code:
   ; b21 = b0 xor b20
   ; if b21 = $FF then
   ;     sertxd (" (ok)")
   ; else
   ;     sertxd (" *BAD!*")
   ;     b0 = $FF
   ;     return
   ; endif
Thanks Phil !!!
 

AllyCat

Senior Member
Hi,
Rich (BB code):
    for b2 = 1 to 32
        ; Measure the length of the next 32 bits and store their lengths (in 1.25uS units) in RAM.
        ; (The Picaxe isn't fast enough to analyse them on the fly.)  Each Pulsin command has an 81.92mS timeout
        ;  @ 32MHZ, so if we enter this loop 'under false pretences', we could be stuck here for 2.6S. 
        pulsin Data_Pin,1,W0 : @bptrinc = b0 : @bptrinc = b1        ; (uses 2 * 32 bytes)
    next b2

Actually the PICaxe can be fast enough to analyse the data On The Fly (even at 16 MHz), but it wasn't easy. :)

I'll try to post my version soon, perhaps including support for "Samsung". However, much of the internet data appears to date back to around 2011 and most of the links are now dead :( . One of the advantages of the PICaxe forum is that many of the links from 2011 do still work and the chips are still available. ;)

In particular, I haven't discovered if Samsung also use the (2.25 ms short header) "Repeat Code" method, nor if the (non-inverted) second Address Byte is intended to give another "error-detectable" 256 addresses, or a total of 65536 addresses (i.e. 16 bits) ?

The issues described in the code snippet above could be worked-around, if necessary. For example the @bptrinc = b0 is not strictly necessary (except for diagnostics) because b1 should always have different values for "0" and "1" data periods. Then there could be time for an IF W0 = 0 THEN GOTO timeout to be added, or the FOR loop changed to a simple DO : ... : LOOP UNTIL W0 = 0 which will terminate whenever the pulse stream ends. But that does slightly risk a "RAM Overflow" crash, at least with an 08M2.

Cheers, Alan.
 

inglewoodpete

Senior Member
A couple of points. Firstly, I have never owned a Samsung appliance, so I don't know which protocol they use. However, read on, below.

Of the appliances I have tested (apart from my now-defunct Sony TV), all used the 32-bit NEC protocol although each had unique timing for the leader on- and off-periods.

All I started out with when I was doing my early experiments was a sound-card oscilloscope - nothing too sophisticated, so you don't need much to determine what the Samsung protocol looks like.

Back in 2007-8, my first 32-bit decoder used an 08M, with its maximum clock speed of 8MHz and available program space of just 256 bytes. So, with some clever work, you can do miracles! That early (and successful) version did need some external hardware to separate the 0s and 1s. A cheap CD4092 schmitt trigger provided 3 inputs to the 08M, identifying the long start pulse; treating each of the 32 bit pulses as a clock input and the 3rd input was the differentiated 0 and 1 period indicator. I used it to control my PICAXE-based home theatre controller. It was smart enough to discriminate between several different IR remote controls (TV, DVD, VCR and later, PVR).
 
Top