;********************************************************************** ; This file is a basic code template for assembly code generation * ; on the PICmicro PIC16F628. This file contains the basic code * ; building blocks to build upon. * ; * ; If interrupts are not used all code presented between the ORG * ; 0x004 directive and the label main can be removed. In addition * ; the variable assignments for 'w_temp' and 'status_temp' can * ; be removed. * ; * ; Refer to the MPASM User's Guide for additional information on * ; features of the assembler (Document DS33014). * ; * ; Refer to the respective PICmicro data sheet for additional * ; information on the instruction set. * ; * ; Template file assembled with MPLAB V4.00.00 and MPASM V2.20.12 * ; * ;********************************************************************** ; * ; Filename: irsony.asm * ; Date: 5-4-2006 * ; File Version: 1.0 * ; * ; Author: David De Vleeschauwer * ; Company: http://users.pandora.be/davshomepage * ; * ; * ;********************************************************************** ; * ; Files required: * ; * ; * ; * ;********************************************************************** ; * ; Notes: * ; * ; * ; * ; * ;********************************************************************** list p=16f628 ; list directive to define processor #include ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _XT_OSC & _MCLRE_ON & _LVP_OFF ; '__CONFIG' directive is used to embed configuration data within .asm file. ; The lables following the directive are located in the respective .inc file. ; See respective data sheet for additional information on configuration word. ;***** VARIABLE DEFINITIONS w_temp EQU 0x70 ; variable used for context saving status_temp EQU 0x71 ; variable used for context saving irerror EQU 0x72 ; variable used for possible errors while receiving irtimer EQU 0x73 ; variable to save the bitlenght time ircounter EQU 0x74 ; variable used as a counter for the bits ircmd EQU 0x75 ; variable wich hold the received command iradr EQU 0x76 ; variable wich hold the received address irtemp EQU 0x77 ; variable used for calc ircommand to outputs delay1 EQU 0x78 delay2 EQU 0X79 led EQU 0x01 ; variable to assign LED output ir EQU 0x00 ; variable to assign IR input ;********************************************************************** ORG 0x000 ; processor reset vector goto main ; go to beginning of program ORG 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf status_temp ; save off contents of STATUS register ; isr code can go here or be located as a call subroutine elsewhere movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt init CLRF PORTA ;Initialize PORTA by setting ;output data latches BSF PORTA,LED MOVLW 0X07 ;Turn comparators off and MOVWF CMCON ;enable pins for I/O ;functions BCF STATUS, RP1 BSF STATUS, RP0 ;Select Bank1 MOVLW b'11111101' ;Value used to initialize ;data direction MOVWF TRISA ;Set RA<1> as output MOVLW b'00000000' ;Value used to initialize ;data direction MOVWF TRISB ;Set Rb<7:0> as outputs BCF STATUS, RP0 ;Select bank 0 return ;return from subroutine read_sony BSF irerror,0 ;Set the errorbit (will be cleared later when receiving a good code) BCF INTCON,GIE ;Disable interupts temporary CLRWDT ;Clear the watchdog timer BSF STATUS,RP0 ;Select bank1 MOVLW b'10000101' ;Sets the prescaler and timer MOVWF OPTION_REG BCF STATUS,RP0 ;Select bank0 BTFSC PORTA,IR ;If it was just a short parasite on the ir line skip reading code with error. GOTO end_sony CLRF TMR0 ;Clear timer to measure startbit lenght sony_st1 BTFSS PORTA,IR ;Measure the startbit GOTO sony_st1 MOVF TMR0,0 ;move value of bitlength to irtimer MOVWF irtimer MOVLW d'32' ;If startbit lenght less then 2ms then end reading code with error. SUBWF irtimer,0 BTFSS STATUS,C GOTO end_sony MOVLW d'213' ;If startbit was longer then 2,6ms then end reading code with error. ADDWF irtimer,0 ;Because when not valid startbit ir code is not sony protocol BTFSC STATUS,C ;So startbit must be between 2ms and 2,6ms. GOTO end_sony MOVLW d'7' ;Set ir counter to receive 7 commandbits. MOVWF ircounter rd_sony_cmd CLRF TMR0 ;Measure the first part of the bitlength: If if is not between 300 and 900µs sony_prt1_c BTFSC PORTA,IR ;Then exit inmediatly the routine with an error GOTO sony_prt1_c MOVF TMR0,0 MOVWF IRTIMER MOVLW d'5' SUBWF irtimer,0 BTFSS STATUS,C GOTO end_sony MOVLW d'241' ADDWF irtimer,0 BTFSC STATUS,C GOTO end_sony CLRF TMR0 CLRWDT ;Clear the watchdog sony_prt2_c BTFSS PORTA,IR ;Measure part2 of the command bits and test if the length is between 300 and 1600µs GOTO sony_prt2_c ;If between these ranges test if second bitpart is shorter or longer than 900µs MOVF TMR0,0 MOVWF IRTIMER MOVLW d'5' SUBWF irtimer,0 BTFSS STATUS,C GOTO end_sony MOVLW d'230' ADDWF irtimer,0 BTFSC STATUS,C GOTO end_sony MOVLW d'241' ADDWF irtimer,0 BTFSC STATUS,C GOTO sony_its_1 sony_its_0 BCF STATUS,C ;if shorter than 900 µs the received bit is a zero RRF IRCMD,1 GOTO nxt_sony_cmd sony_its_1 BSF STATUS,C RRF IRCMD,1 nxt_sony_cmd DECFSZ ircounter,1 ;test if all command bits are processed if not receive next GOTO rd_sony_cmd ;if longer than 900µs the received bit is a one BCF STATUS,C RRF IRCMD,1 ;Rotate ircmd one position to become correct command MOVLW d'5' ;set ircounter to receive 5 address bits MOVWF IRCOUNTER rd_sony_adr CLRF TMR0 sony_prt1_a BTFSC PORTA,IR ;measure firtst bitlenght if shorter than 300 µs or longer than 900µs GOTO sony_prt1_a ;then exit inmediatly with error MOVF TMR0,0 MOVWF IRTIMER MOVLW d'5' SUBWF irtimer,0 BTFSS STATUS,C GOTO end_sony MOVLW d'241' ADDWF irtimer,0 BTFSC STATUS,C GOTO end_sony CLRF TMR0 CLRWDT ;clear watchdog timer sony_prt2_a BTFSS PORTA,IR GOTO sony_prt2_a ;measure second bitlenght if shorter than 300µs or longer than 1600µs MOVF TMR0,0 ;then exit with error MOVWF IRTIMER ;If between these ranges test if the bit is a one or zero (shorter or longer than 900µs) MOVLW d'5' SUBWF irtimer,0 BTFSS STATUS,C GOTO end_sony MOVLW d'230' ADDWF irtimer,0 BTFSC STATUS,C GOTO end_sony MOVLW d'241' ADDWF irtimer,0 BTFSC STATUS,C GOTO sony_its_1_a sony_its_0_a BCF STATUS,C ;if second bitpart was shorter than 900µs it's a zero RRF IRADR,1 GOTO nxt_sony_adr sony_its_1_a BSF STATUS,C ;if second bitpart was longer than 900µs it's a one RRF IRADR,1 nxt_sony_adr DECFSZ ircounter,1 ;Test if all bits are processed if not receive next GOTO rd_sony_adr BCF STATUS,C ;Rotate tree time the iradr to become the correct address RRF IRADR,1 BCF STATUS,C RRF IRADR,1 BCF STATUS,C RRF IRADR,1 CLRF irerror ;Because every bitlength was measured between correct limits no errors occured bcf portA,led end_sony BCF INTCON,T0IF ;Clear timer0 interrupt flag to avoid an interrupt BSF STATUS,RP0 MOVLW b'00000101' MOVWF OPTION_REG BCF STATUS,RP0 RETURN ir_to_outp movf ircmd,W ;Save ircmd in irtemp to prevent loosing the received code movwf irtemp sublw d'10' ;Check if ir command is higher or equal then 10 if so exit and do nothing btfss STATUS,C goto end_output movf irtemp,W ;Check if ir command is 9 (button 0) if so clear all outputs sublw d'9' btfss status,Z goto not_button0 clrf portB goto end_output not_button0 movf irtemp,W ;Check if ir command is 0 (button1) if so toggle bit 0 btfss status,Z goto not_button1 movlw b'00000001' xorwf PORTB,1 goto end_output not_button1 movf irtemp,W ;Check if ir command is 1 (button2) if so toggle bit 1 sublw d'1' btfss status,Z goto not_button2 movlw b'00000010' xorwf PORTB,1 goto end_output not_button2 movf irtemp,W ;Check if ir command is 2 (button3) if so toggle bit 2 sublw d'2' btfss status,Z goto not_button3 movlw b'00000100' xorwf PORTB,1 goto end_output not_button3 movf irtemp,W ;Check if ir command is 3 (button4) if so toggle bit 3 sublw d'3' btfss status,Z goto not_button4 movlw b'00001000' xorwf PORTB,1 goto end_output not_button4 movf irtemp,W ;Check if ir command is 4 (button5) if so toggle bit 4 sublw d'4' btfss status,Z goto not_button5 movlw b'00010000' xorwf PORTB,1 goto end_output not_button5 movf irtemp,W ;Check if ir command is 5 (button6) if so toggle bit 5 sublw d'5' btfss status,Z goto not_button6 movlw b'00100000' xorwf PORTB,1 goto end_output not_button6 movf irtemp,W ;Check if ir command is 6 (button7) if so toggle bit 6 sublw d'6' btfss status,Z goto not_button7 movlw b'01000000' xorwf PORTB,1 goto end_output not_button7 movf irtemp,W ;Check if ir command is 7 (button8) if so toggle bit 7 sublw d'7' btfss status,Z goto end_output movlw b'10000000' xorwf PORTB,1 goto end_output end_output return delayrout1 movlw d'255' movwf delay2 looping2 movlw d'255' movwf delay1 looping1 nop nop decfsz delay1,1 goto looping1 decfsz delay2,1 goto looping2 return main call init test call read_sony btfsc irerror,1 goto test movf iradr,0 sublw d'1' ;<--- Change this value into the value of the deviceaddress btfss status,Z ; Now its for address 1 goto test call ir_to_outp call delayrout1 goto test ; remaining code goes here END ; directive 'end of program'