Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

JuneBug SIRC RX - Complete

Status
Not open for further replies.
Hi Futz,

I don't know how much has been changed to get it into the 16F but I would place a breakpoint after the RISE label.

The first time you hit this breakpoint "should" be after the first pulse, TMR0L "should" contain the time delay between the fall and rise of the pulse.

Does the 16F use a 16 bit TMR0? what is TMR0H doing?

I love the 18F, it is my first chip but perhaps I should have cut my teeth on the 16F's?

Anyway hope this helps.

Mark

p.s. shame we can't see the TTL that is coming out of your TSOP?
 
UTMonkey said:
I don't know how much has been changed to get it into the 16F
Quite a bit.

Does the 16F use a 16 bit TMR0? what is TMR0H doing?
It's 8 bit only, so TMR0 only.

I love the 18F, it is my first chip but perhaps I should have cut my teeth on the 16F's?
Try some. It's not like they're expensive or anything. You'll find the differences interesting. They're much more RISC than the 18F's. Takes more instructions to get the same work done. The 18F's are still RISC but edging a bit more toward CISC.
 
UTMonkey said:
p.s. shame we can't see the TTL that is coming out of your TSOP?
Next best thing! I put in a counter to count the number of pulses I was getting when I pressed a key on the remote. I got 39 pulses, so I made a 39 byte array and indexed into it to store the value of the 39 Time2's in a command. Here's what I get when I press the 1 key on the remote (all hex):

13 - 1c 04 04 05 05 05 05 - 09 04 04 05 04
13 - 1c 04 05 04 04 04 05 - 09 04 04 04 05
13 - 1c 05 04 05 04 05 04 - 09 04 05 05 05

I separated the sections the way I think SIRC is supposed to work - start/command/address. The $1c is what's killing the thing. Wonder what's going on there?

Pressing the 5 key gets me:

13 - 1c 04 09 04 04 04 04 - 09 04 04 04 04
13 - 1c 04 09 04 04 04 04 - 09 04 04 04 04
13 - 1c 04 09 04 04 04 04 - 09 04 04 04 04

Everything looks fine except for that $1c. I can't understand how my code could botch that one and yet get the rest right, since it uses the same code to get every pulse length...

EDIT: I wonder if it's somehow combining the start pulse length with the second pulse. That could maybe add up to $1c.
 
Last edited:
Well, that was entertaining. :D Here's UTMonkey's program ported to **broken link removed** 16F88. Could still use some cleaning up, but it works.

I didn't bother to do the LEDs properly. When waiting for a code LED1 is red and LED2 is green. When a code is received all LEDs are off. Press button 3 to reset.
Code:
	LIST p=16F88
	INCLUDE "p16f88.inc"
	__CONFIG _CONFIG1,_INTRC_IO & _WDT_OFF & _LVP_OFF & _MCLR_ON & _BODEN_OFF
	ERRORLEVEL 0, -302
	

btDone		equ	0x00
btStart		equ	0x01
btCommand	equ	0x02

	cblock	0x20
		dlen,Time2,BitCount,DeviceCode,CommandCode,IRStatus,Bit,ScratchCode
		w_temp,status_temp,pclath_temp,the_end
	endc		

	org	0x0000
	goto	Init

;*****
; ISR
	org	0x0008
ISR	movwf	w_temp
	swapf	STATUS,W
	clrf	STATUS
	movwf	status_temp
	movf	PCLATH,W
	movwf	pclath_temp
	clrf	PCLATH
	
	bcf	PORTA,0			;LEDs 1 & 2 off
	bcf	PORTA,6
	bcf	PORTA,7
	btfsc	IRStatus,btDone		;has a code already been read?
	goto	isr_done
	banksel	OPTION_REG		;bank 1
	btfsc	OPTION_REG,INTEDG	;check if falling or rising signal
	goto	Rise
	banksel	TMR0			;bank 0
	clrf	TMR0			;reset timer
	banksel	OPTION_REG		;bank 1
	movlw	b'01010111'		;Enable timer0, 256 prescaler, set RB0 rising edge
	movwf	OPTION_REG
	banksel	PORTA			;bank 0
	goto	isr_done
Rise
	banksel	TMR0			;bank 0
	movf	TMR0,W			;Put timer 0 value into storage
	movwf	Time2
	banksel	OPTION_REG		;bank 1
	bcf	OPTION_REG,INTEDG	;set for falling edge
	banksel PORTA			;bank 0
GetPulseWidth
	movlw	0x12			;Check for start pulse, should be between 0x12 and 0x14
	subwf	Time2,W
	btfss	STATUS,C		;Greater than 0x11?
	goto	CheckZero
	movlw	0x14
	subwf	Time2,W			;Less than 0x15?
	btfsc	STATUS,C
	goto	IRError			;Start Bit exceeds tolerance
StartBit				;We have a Start Bit
	btfsc	IRStatus,btStart	;Check if already set (ERROR)
	goto	IRError
	bsf	IRStatus,btStart	;Flag IRStatus 
	movlw	0x07
	movwf	BitCount
	goto	isr_done

CheckZero
	movlw	0x04			;Check for zero pulse. Should be between 0x4 and 0x6
	subwf	Time2,W
	btfss	STATUS,C		;Greater than 0x3?
	goto	IRError
	movlw	0x06
	subwf	Time2,W
	btfsc	STATUS,C		;Less than 0x7?
	goto	CheckOne
ZeroBit	btfss	IRStatus,btStart	;Check if we have previously had Start Bit
	goto	IRError
	clrf	Bit
	call	ProcessBit
	goto	isr_done

CheckOne
	movlw	0x09			;Check for One Pulse. Should be between 0x9 and 0xB
	subwf	Time2,W
	btfss	STATUS,C		;Greater than 0x8?
	goto	IRError
	movlw	0x0b
	subwf	Time2,W			;Less than 0xC
	btfsc	STATUS,C
	goto	IRError
OneBit	btfss	IRStatus,btStart	;Check if we have previously had Start Bit
	goto	IRError
	movlw	0x01
	movwf	Bit
	call	ProcessBit
	goto	isr_done

IRError	clrf	IRStatus		;clear variables
	clrf	DeviceCode
	clrf	CommandCode
	clrf	ScratchCode
	banksel	OPTION_REG		;bank 1
	bcf	OPTION_REG,INTEDG	;Interrupt on falling edge

isr_done	
	banksel	PORTA			;bank 0
	clrf	PORTA
	movf	pclath_temp,W
	movwf	PCLATH
	swapf	status_temp,W
	movwf	STATUS
	swapf	w_temp,F
	swapf	w_temp,W
	bcf	INTCON,INT0IF
	retfie
; End ISR
;********

Init
	banksel	OSCCON			;bank 1
	movlw	0x7d			;Set Internal 8MHz
	movwf	OSCCON
	bcf	ANSEL,0			;Set RA0 as digital
	movlw	b'00111110'	
	movwf	TRISA
	bsf	TRISB,0			;Make RB0 Input
	bsf	TRISB,4			;Make RB4 Input
	banksel	PORTA			;bank 0
	bcf	PORTA,0
	bcf	PORTA,6
	bcf	PORTA,7
;clear variables from Time2 to the_end
	movlw	Time2			;point FSR to variables
	movwf	FSR
	movlw	the_end-Time2		;set counter = # of vars to clear
	movwf	dlen			;use dlen as counter
zero	clrf	INDF			;clear a variable
	incf	FSR,F			;increment the pointer
	decfsz	dlen,F			;finished?
	goto	zero			;no, go again
InitISR
	banksel	OPTION_REG		;bank 1
	movlw	b'00000111'		;enable weak pullups on PORTB - Interrupt on falling edge
	movwf	OPTION_REG
	movlw	b'10010000'		;Enable INT0 interrupt, Clear INT0 flag
	movwf	INTCON			;Disable peripheral interrupts, enable global interrupt
	banksel	PORTA			;bank 0
	
Main	bsf	PORTA,0			;Light LED 1
	bcf	PORTA,6
	bsf	PORTA,7
	btfss	IRStatus,btDone
	goto	Main
	bsf	PORTA,0			;Light LED 2
	bcf	PORTA,6
	bcf	PORTA,7
WaitForRB2
	btfsc	PORTB,4
	goto	WaitForRB2
	clrf	IRStatus		;clear variables
	clrf	DeviceCode
	clrf	CommandCode
	clrf	ScratchCode
	goto	Main

ProcessBit
	btfss	Bit,0			;Check if bit set
	goto	WriteZero
WriteOne
	bsf	ScratchCode,0x07
	goto	RotateRight
WriteZero
	bcf	ScratchCode,0x07
RotateRight
	rrf	ScratchCode,F
	btfss	STATUS,C
	goto	rr1
	bsf	ScratchCode,7
	goto	rrdone
rr1	bcf	ScratchCode,7
rrdone	decfsz	BitCount,F
	return

WhichCode
	btfss	IRStatus,btCommand
	goto	CommandCodeDone
DeviceCodeDone
	rrf	ScratchCode,F		;a couple of more rotations
	btfss	STATUS,C
	goto	zero1
	bsf	ScratchCode,7
	goto	done1
zero1	bcf	ScratchCode,7
done1	rrf	ScratchCode,F
	btfss	STATUS,C
	goto	zero2
	bsf	ScratchCode,7
	goto	done2
zero2	bcf	ScratchCode,7
done2	movf	ScratchCode,W
	movwf	DeviceCode
	bsf	IRStatus,btDone
	return

CommandCodeDone
	movf	ScratchCode,W
	movwf	CommandCode
	bsf	IRStatus,btCommand
	movlw	0x5
	movwf	BitCount
	clrf	ScratchCode
	return

	end
 
Last edited:
UTMonkey said:
This is great, is it me or does it does the code look a lot smaller?
It's you. :D The code is bigger.

16F's have no BTG or MOVFF or CPFSGT/CPFSLT or RRNCF/RLNCF (have to move the carry yourself).

18F will automatically save and restore registers for you on an ISR call, as long as you use RETFIE FAST to return. You have to do it all yourself on 16F.

I even got rid of your clear_variables subroutine, adding yet another 4 or 5 lines to my version.

There are a bunch of extra bank select lines in 16F code too.

On the other hand my cblock is much more compact. Mine is 4 lines. Yours is 10.

My code has a bit less vertical whitespace.
 
Last edited:
I've put some code on my website for a Sony SIRC IR decoder for the 16F88 which can decode 12, 15 and 20 bit codes.

I've tested it with a four different Sony remotes, including the one for my surround sound AV amp which generates 12, 15 and 20 bit codes.

It is beta code but it seems to be working reliably now so I thought I'd put it up here for anyone whose interested in having a play + find any bugs:p

http://picprojects.org.uk/projects/sirc/

Pete
 
I had a play today with Swordfish and managed to get it reading a Sony Remote. It will send the device and command codes via RS232 to the PicKit USART tool.

Code:
{
*****************************************************************************
*  Name    : IR_Demo.BAS                                                    *
*  Author  : Mike Webb                                                      *
*  Notice  : Copyright (c) 2008 None                                        *
*          : No Rights Reserved                                             *
*  Date    : 4/03/2008                                                      *
*  Version : 1.0                                                            *
*  Notes   : Will decode a Sony remote and send the device and command      *
*          : over RS232. Will also light LED if 1-6 are pressed.            *
*****************************************************************************
}
Device = 18F1320
Clock = 8               // 8MHz clock
Config OSC = INTIO2, WDT = OFF, LVP = OFF

Include "18F1320.bas"
Include "Junebug.bas"
Include "USART.bas"
Include "Convert.bas"
Include "IR.bas"

Dim Command As Byte
Dim DeviceCode As Byte

OSCCON = $70            // 8 MHz clock
SetBaudrate(br9600)
While true
    ReadIR(Command,DeviceCode)    
    LED(Command+1)
    USART.Write("Device = ",DecToStr(DeviceCode),"  Command = ",DecToStr(Command),13,10)
    DelayMS (100)
Wend
End

And the module,

Code:
{
*****************************************************************************
*  Name    : IR.BAS                                                         *
*  Author  : Mike Webb.                                                     *
*  Notice  : Copyright (c) 2008 None                                        *
*          : No  Rights Reserved                                            *
*  Date    : 4/03/2008                                                      *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}

Module IR

Function GetPulse()As Byte
    GetPulse=0
    While(PORTB.0=1)
    Wend
    While(PORTB.0=0)
        DelayUS (100)
        GetPulse=GetPulse+1
    Wend
End Function

Public Sub ReadIR(ByRef pCMD As Byte,ByRef pDEV As Byte)
Dim I As Byte
Dim Pulse As Byte
Dim Error As Boolean
ADCON1.4 = 1                //ensure Portb.0 is digital
TRISB.0=1                   //and is input
    Repeat
        error=false
        pCMD=0
        pDEV=0
        Repeat
            Pulse=GetPulse()
        Until pulse>20              //wait for start pulse > 2.0mS
        For I=0 To 6                //get 7 bit command code
            pCMD=pCMD>>1
            Pulse=GetPulse()        //get pulse length
            If Pulse > 15 Then      //if greater than 15 is error
                error=true
            ElseIf pulse > 9 Then   //if between 10 and 15 is a 1 bit
                //pCMD.6=1
                pCMD=pCMD Or $40
            ElseIf pulse < 4 Then   //if less than 4 is error
                error=true
            EndIf
        Next    
        For I=0 To 4                //get 5 bit device code
            pDEV=pDEV>>1
            Pulse=GetPulse()        //as above
            If Pulse > 15 Then
                error=true
            ElseIf pulse > 9 Then
                //pDEV.4 = 1
                pDEV=pDEV Or $10
            ElseIf pulse < 4 Then
                error=true
            EndIf
        Next    
    Until error=false
End Sub

The Junebug module is on Bill's site. Switches 1,2,3,4 & 6 have to be on.

Mike.
 
Last edited:
UTMonkey said:
BASIC looks pretty cool! what are it's downsides?
The same as any compiled language, it will not be as optimized as asm. After saying that, Swordfish seems to be very well written and appears to produce good fast code. The best bit, it's free. Well, it's free as long as you don't use more than 256 bytes of ram. So far I have not exceeded that limit except when I tried to use floating point. Why not download it and give it a try.

Mike.
I can't believe I just said that.:eek:
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top