PDA

View Full Version : Infrared Remote Receiver



Art
- 27th June 2016, 14:56
Hi Guys :)
After a search for infrared, the only successful code I found links to a broken 404 page,
so I’ll upload code shortly.

https://www.youtube.com/watch?v=MwJgcBFQmQk

It’s the long way round, but doing better at the moment would customise it very strongly to Sony pulse coded remotes.
Also reading into a buffer first will be great for trying a new remote.
I didn’t use any existing information out there about Sony remotes, or a scope.. only the pic code!

Since the video I’ve got continuous button presses working well (such as seeking an audio CD track),
and also replaced the Sony IR receiver with a stock 40kHz receiver module which works the same if not better.

On the downside, all of the code is blocking, so the program won’t do anything else simultaneously without some effort.
Cheers, Art.

Art
- 9th October 2016, 05:22
Hi Guys,
This code is for 16f628A @ 10 MHz to become an IR receiver for the Commodore CDTV remote.
Commodore had a lot of these manufactured before a new model CDTV that never happened,
and so plenty of new old stock is available from eBay.

http://img.photobucket.com/albums/v186/ArtArt/CDTV_Overlay_zpsewk4bpsn.png

The overlayed buttons in this image are mapped to pic IO pins, and they will be held low
for as long as the buttons are pressed.
Additionally, the CD player buttons can be read as well.
Some combinations entered on the keypad can also be used to configure the receiver.
For example, a certain keypad code (revealed in the source) will make the keypad
a DTMF keypad, and another will mute the beeps for CD track skip.

No schematic is available, but the IO pin definitions are given at the end of the code/

If anyone builds it, it’s probably a good idea to watch this series of videos starting with this one:
https://www.youtube.com/watch?v=MwJgcBFQmQk
In the second part, I changed from the Sony remote, to the CDTV remote pictured here.
Cheers, Art.

Art
- 9th October 2016, 05:23
Here is the source:


'
'
' -----------------------------------------------------
' Amiga CD32 Controller & CDTV IR Receiver Interface V3
' -----------------------------------------------------
' Copyright Brek Martin 2016.
' -----------------------------------------------------
'
DEFINE OSC 10 ' 10 MHz high speed oscillator
DEFINE NO_CLRWDT ' watchdog is cleared manually
'
keycode var byte[7] ' combination keycode buffer
decodedir var byte[3] '
decodedira var decodedir[0] ' decoded command sentence
decodedirb var decodedir[1] '
decodedirc var decodedir[2] '
irworda var word ' 12 bit ir command
irwordb var word ' 12 bit inverted ir command
rotcnt var word ' loop counter
releasecnt var word '
repeatdel var word '
repeatlen var word '
rawdelay var byte '
headerlen var byte '
ircount var byte ' pulse length counter
irbitcnt var byte ' ir bit counter
irbuff var byte ' byte buffer
leadcnt var byte ' header length counter
sndval var byte ' sound frequency
mousejoy var byte ' mouse or joy mode value
qualifyir var bit ' useless but left for timing
gotpulse var bit ' ir signal edge detect flag
irbit var bit ' ir bit status buffer
keyrot var bit ' rotate key code flag
dualtone var bit ' dtmf keypad flag
debugwrite var byte ' debug mode flag
cdkey var byte ' cd player button beep value
mute var byte ' mute setting
dual var byte ' dtmf keypad setting
sndbuff var byte '
sndspd var byte ' intro sound speed
sndsine var byte ' pseudo sine
'
goto startup ' do program startup
'
main:
@ clrwdt '
if qualifyir = 0 then ' look for initial ir burst * only here for timing now
if porta.5 = 0 then ' look for ir header
leadcnt = leadcnt + 1 ' count time for header length
else '
leadcnt = 0 ' reset time for header length
if releasecnt != 0 then ' release contunuous button presses
releasecnt = releasecnt - 1 ' decrement button cancel delay
if releasecnt = 1 then ' trigger button cancel
portb = %11111111 ' set all cd32 controller pins high and led off
porta = %1111 ' set all cd32 controller pins high
endif '
endif '
endif '
'
if leadcnt > headerlen then ' qualify initial ir burst duration
burst: ' allow initial ir burst to finish
if porta.5 = 0 then ' wait here until ir header is finished
goto burst '
endif '
'
pauseus repeatlen '
if porta.5 = 0 then ' repeat code detected
goto checkcont ' skip decoding of ir data for repeat code
endif '
'
gotpulse = 0 ' decode pulse coded ir signal
irbitcnt = 0 '
ircount = 0 '
'
for rotcnt = 0 to 407 ' sample ir data into buffer
'
for irbuff = 0 to 11 ' waste 58 instructions
next irbuff ' delay replacement for previous bitwise rotation routine
irbit = porta.5 ' sample ir port
'
if irbit = 1 then ' look for edge of pulse
irbitcnt = irbitcnt + 1 '
gotpulse = 1 '
endif '
'
if irbit = 0 then ' shift in decoded bit
if gotpulse = 1 then '
@ rlf _decodedir+2 ,F ;
@ rlf _decodedir+1 ,F ;
@ rlf _decodedir+0 ,F ;
@ bcf _decodedir+2 ,0 ; clear msb
irbuff = decodedir[2] '
if irbitcnt < 11 then '
irbuff.bit0 = 0 '
else '
irbuff.bit0 = 1 '
endif '
decodedir[2] = irbuff '
'
if irbitcnt > 0 then '
irbitcnt = 0 '
ircount = ircount + 1 ' increment the ir bit count
endif '
endif '
gotpulse = 0 ' reset flag to look for next ir pulse
endif '
'
if ircount > 24 then ' limit number of decoded bits
rotcnt = 407 ' cause loop termination
endif '
'
pauseus rawdelay ' raw pulse sample delay
next rotcnt '
'
' copy the 12 bit decoded data to a pair of word variables
' the second copy is the same command with inverted bits
' the four unused bits in both commands are leading zeros
'
irworda = irworda << 4 '
for rotcnt = 0 to 11 '
irworda = irworda << 1 '
irworda.bit0 = decodedira.bit7 '
@ rlf _decodedir+2 ,F ;
@ rlf _decodedir+1 ,F ;
@ rlf _decodedir+0 ,F ;
@ bcf _decodedir+2 ,0 ; clear msb
next rotcnt '
irwordb = irwordb << 4 '
for rotcnt = 0 to 11 '
irwordb = irwordb << 1 '
irwordb.bit0 = decodedira.bit7 '
@ rlf _decodedir+2 ,F ;
@ rlf _decodedir+1 ,F ;
@ rlf _decodedir+0 ,F ;
@ bcf _decodedir+2 ,0 ; clear msb
next rotcnt '
'
irwordb = irwordb^%111111111111 ' invert copy to compare
if irworda != irwordb then ' potentially do somethng for invalid command
goto main ' disqualified command data packet
endif '
'
portb.3 = 0 ' turn blue led on
'
checkcont:
'
' lookup tables translate all joypad related commands
' from decoded ir commands to both port values
'
if irworda.byte1 = mousejoy then ' qualify joypad or mouse mode related command
if irworda.byte0 < 193 then ' check for in lookup table range
'
lookup irworda.byte0,[_ ' convert decoded command lsb to portb value
$F7,$F7,$F7,$F7,$77,$F7,$F7,$F7,$B7,$F7,_ ' 00-09 *** 192 - 0xC0 is the highest for fire a + b
$F7,$F7,$F7,$F7,$F7,$F7,$D7,$F7,$F7,$F7,_ ' 10-19
$57,$F7,$F7,$F7,$97,$F7,$F7,$F7,$F7,$F7,_ ' 20-29
$F7,$F7,$E7,$F7,$F7,$F7,$67,$F7,$F7,$F7,_ ' 30-39
$A7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,_ ' 40-49
$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,_ ' 50-59
$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$77,$F7,_ ' 60-69
$F7,$F7,$B7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,_ ' 70-79
$D7,$F7,$F7,$F7,$57,$F7,$F7,$F7,$97,$F7,_ ' 80-89
$F7,$F7,$F7,$F7,$F7,$F7,$E7,$F7,$F7,$F7,_ ' 90-99
$67,$F7,$F7,$F7,$A7,$F7,$F7,$F7,$F7,$F7,_ ' 100-109
$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,_ ' 110-119
$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F5,$F7,_ ' 120-129
$F7,$F7,$75,$F7,$F7,$F7,$B5,$F7,$F7,$F7,_ ' 130-139
$F7,$F7,$F7,$F7,$D5,$F7,$F7,$F7,$55,$F7,_ ' 140-149
$F7,$F7,$95,$F7,$F7,$F7,$F7,$F7,$F7,$F7,_ ' 150-159
$E5,$F7,$F7,$F7,$65,$F7,$F7,$F7,$A5,$F7,_ ' 160-169
$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,_ ' 170-179
$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,$F7,_ ' 180-189
$F7,$F7,$F5_ ' 190-192
],portb ' destination is portb
'
lookup irworda.byte0,[_ ' convert decoded command lsb to porta value
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 00-09
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 10-19
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 20-29
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 30-39
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 40-49
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 50-59
$0F,$0F,$0F,$0F,$0E,$0F,$0F,$0F,$0E,$0F,_ ' 60-69
$0F,$0F,$0E,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 70-79
$0E,$0F,$0F,$0F,$0E,$0F,$0F,$0F,$0E,$0F,_ ' 80-89
$0F,$0F,$0F,$0F,$0F,$0F,$0E,$0F,$0F,$0F,_ ' 90-99
$0E,$0F,$0F,$0F,$0E,$0F,$0F,$0F,$0F,$0F,_ ' 100-109
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 110-119
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 120-129
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 130-139
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 140-149
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 150-159
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 160-169
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 170-179
$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,_ ' 180-189
$0F,$0F,$0E_ ' 190-192
],porta ' destination is porta
'
releasecnt = repeatdel ' set the repeat cancel delay
goto donecheckcont ' skip further checking
else '
goto donecheck ' out of range of lookup tables
endif '
endif '
'
'
if irworda.byte1 = $00 then ' qualify keypad related command
if irworda.byte0 = %00110101 then ' enter
portb = %11110011 '
releasecnt = repeatdel '
goto donecheckcont '
endif '
'
if irworda.byte0 = %00110001 then ' escape
portb = %11110110 '
releasecnt = repeatdel '
goto donecheckcont '
endif '
'
'
cdkey = 0 ' clear cd player button beep value
'
if irworda.byte0 = %00001010 then ' play
porta = %1011 '
if releasecnt = 0 then '
cdkey = 120 '
endif '
releasecnt = repeatdel '
goto donecheckcontcd '
endif '
'
if irworda.byte0 = %00101010 then ' stop
porta = %1110 '
if releasecnt = 0 then '
cdkey = 90 '
endif '
releasecnt = repeatdel '
goto donecheckcontcd '
endif '
'
if irworda.byte0 = %00011010 then ' skip forward
porta = %1101 '
if releasecnt = 0 then '
cdkey = 115 '
endif '
releasecnt = repeatdel '
goto donecheckcontcd '
endif '
'
if irworda.byte0 = %00110010 then ' skip reverse
porta = %0111 '
if releasecnt = 0 then '
cdkey = 115 '
endif '
releasecnt = repeatdel '
goto donecheckcontcd '
endif '
'
'
keyrot = 0 ' clear key rotation flag
'
if irworda.byte0 = %00111001 then ' 0
if releasecnt = 0 then '
keycode[0] = $30 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00000001 then ' 1
if releasecnt = 0 then '
keycode[0] = $31 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00100001 then ' 2
if releasecnt = 0 then '
keycode[0] = $32 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00010001 then ' 3
if releasecnt = 0 then '
keycode[0] = $33 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00001001 then ' 4
if releasecnt = 0 then '
keycode[0] = $34 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00101001 then ' 5
if releasecnt = 0 then '
keycode[0] = $35 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00011001 then ' 6
if releasecnt = 0 then '
keycode[0] = $36 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00000101 then ' 7
if releasecnt = 0 then '
keycode[0] = $37 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00100101 then ' 8
if releasecnt = 0 then '
keycode[0] = $38 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00010101 then ' 9
if releasecnt = 0 then '
keycode[0] = $39 '
keyrot = 1 '
endif '
endif '
'
if irworda.byte0 = %00100010 then ' genlock
if releasecnt = 0 then '
keycode[0] = $3B ' hash key for dtmf mode
keyrot = 1 '
endif '
endif '
'
' cd/tv - %00000010 power - %00010010
' >>vol>> - %00000110 <<vol<< - %00111010
'
if keyrot = 1 then ' rotate key code buffer
'
if dualtone = 1 then '
DTMFOUT porta.4,400,10,[keycode[0]-$30] '
else '
SOUND porta.4,[110,1] '
endif '
'
if keycode[0] = $3B then ' check for genlock button
if keycode[6] = $31 then ' 1
if keycode[5] = $33 then ' 3
if keycode[4] = $33 then ' 3
if keycode[3] = $37 then ' 7
'
'
if keycode[2] = $31 then ' 1
if keycode[1] = $36 then ' 6
if debugwrite = 0 then '
debugwrite = $AA '
else '
debugwrite = 0 '
endif '
write 10,debugwrite '
goto codefunction '
endif '
endif '
'
'
if keycode[2] = $30 then ' 0
'
if keycode[1] = $30 then ' 0
sndval = sndval + 2 ' increment intro frequency value
write 0,sndval '
goto codefunction '
endif '
'
if keycode[1] = $31 then ' 1
if dual = 0 then ' toggle dtmf setting
write 8,1 '
else '
write 8,0 '
endif '
goto codefunction '
endif '
'
if keycode[1] = $32 then ' 2
if mute = 0 then ' toggle mute setting
write 7,1 '
else '
write 7,0 '
endif '
goto codefunction '
endif '
'
if keycode[1] = $33 then ' 3
goto codefunction '
endif '
'
if keycode[1] = $34 then ' 4
SOUND porta.4,[120,16] ' sound for correct keypad code
mousejoy = $00 ' cdtv mouse mode
endif '
'
if keycode[1] = $36 then ' 6
write 0,$F9 ' reset default intro value
goto codefunction '
endif '
'
if keycode[1] = $39 then ' 9
repeatdel = repeatdel + 10 ' increment repeat delay
goto setrepeat '
endif '
'
if keycode[1] = $38 then ' 8
repeatdel = repeatdel - 10 ' decrement repeat delay
goto setrepeat '
endif '
'
if keycode[1] = $37 then ' 7
repeatdel = 1820 ' set default repeat delay
setrepeat: '
write 3,repeatdel.byte1 '
write 4,repeatdel.byte0 '
goto codefunction '
endif '
'
endif '
endif '
endif '
endif '
endif '
else ' else not genlock button
keycode[6] = keycode [5] '
keycode[5] = keycode [4] '
keycode[4] = keycode [3] '
keycode[3] = keycode [2] '
keycode[2] = keycode [1] '
keycode[1] = keycode [0] '
endif '
endif ' not genlock button
'
releasecnt = repeatdel '
goto donecheckcont '
endif '
'
donecheck: ' invalid or unknown ir code
porta = %1111 ' set all cd32 controller pins high
portb = $FF ' and turn off blue led
if mute = 0 then '
SOUND porta.4,[90,1] ' buzz for invalid or unknown command
endif '
'
'********************************************
' sound the 12 bit command out of speaker
'********************************************
if debugwrite != 0 then '
irwordb = irworda '
for rotcnt = 0 to 11 '
@ clrwdt ;
if irwordb.bit11 = 0 then '
cdkey = 90 '
else '
cdkey = 120 '
endif '
SOUND porta.4,[cdkey,2] '
pause 900 '
irwordb = irwordb << 1 '
next rotcnt '
endif '
'********************************************
'
donecheckcontcd: ' cd player buttons sound
if cdkey != 0 then '
if mute != 0 then '
cdkey = 0 '
endif '
SOUND porta.4,[cdkey,1] '
endif '
donecheckcont: '
leadcnt = 0 ' reset the header counter
endif '
endif '
goto main ' cycle program
'
codefunction:
SOUND porta.4,[120,16] ' sound for correct keypad code
wdtresetl: '
goto wdtresetl ' cause watchdog timer reset
'
startup:
CMCON = $07 ' set ports as digital
trisa = %100000 '
porta = %1111 '
trisb = %00000000 '
portb = %11110111 ' set all cd32 controller pins high
pause 100 ' delay
portb = %11111111 ' turn blue led off this time
'
leadcnt = 0 ' reset variables
qualifyir = 0 '
decodedira = 0 '
decodedirb = 0 '
decodedirc = 0 '
releasecnt = 0 ' *** try 2?
irworda = 0 '
irwordb = 0 '
irbit = 0 '
dualtone = 0 ' set dtmf initially off
sndsine = 0 ' set intitial sine
mousejoy = $08 ' set joypad mode default
'
'
'repeatlen = 2400 ' repeat ir pulse delay (program setting) *** 2400
'repeatdel = 1820 ' repeat cancel delay (program setting) *** 1820
'headerlen = 150 ' header pulse length (program setting) *** 150
'rawdelay = 36 ' raw ir signal sample delay (program setting) *** 36
'sndval = 120 ' sound frequency for intro (program setting) *** 120
'mute = 0 ' mute sound from speaker (program setting) *** 0
'dual = 0 ' dtmf keypad (program setting) *** 0
'sndspd = 1 ' intro sound speed (program setting) *** 1
'debugwrite = 0 ' sound out invalid ir codes (program setting) *** 0
'
' defaults 1820 msb 1820 lsb 2400 msb 2400 lsb
DATA $F9,36,150,%00000111,%00011100,%00001001,%01100000 ,0,0,1,0
'
read 0,sndval ' read program settings from on-chip eeprom
read 1,rawdelay '
read 2,headerlen '
read 3,repeatdel.byte1 '
read 4,repeatdel.byte0 '
read 5,repeatlen.byte1 '
read 6,repeatlen.byte0 '
read 7,mute '
read 8,dual '
read 9,sndspd '
read 10,debugwrite '
'
if dual != 0 then '
dualtone = 1 '
endif '
'
if mute = 0 then ' if sound not muted
sndbuff = $FF '
sloop: '
sndbuff = sndbuff + sndval '
SOUND porta.4,[sndbuff,sndspd+sndsine] ' output sound
@ clrwdt ;
sndsine = sndbuff.bit3 '
IF sndbuff != 0 THEN sloop '
endif '
porta = %1111 '
goto main '
'
'
'RA0 = 0 - cd32 control port
'RA1 = 0
'RA2 = 0
'RA3 = 0
'RA4 = 0 - piezo speaker port
'RA5 = 1 - infrared receiver input
'RB0 = 0 - cd32 controller yellow button
'RB1 = 0 - cd32 controller red button
'RB2 = 0 - cd32 controller green button
'RB3 = 0 - led indicator
'RB4 = 0 - joypad up
'RB5 = 0 - joypad down
'RB6 = 0 - joypad left
'RB7 = 0 - joypad right
'
'
'



Cheers, Art.

Ioannis
- 14th October 2016, 16:29
I am not particularly interesting in IR, but had a look at your code and found it very interesting the mix of asm and basic at rotating variables.

Thanks for posting. Nice work!

Ioannis

Art
- 10th November 2016, 13:37
Hi Ioannis :) Thanks, I should have also mentioned it’s no good for writing another program into it. It’s blocking and event driven.
Meant as a stand alone receiver where it’s output ports reflect the state of the buttons on the joypad (even when held down).
So really intended for use with a program on another chip altogether, and saves touching this code again.