Podría hacer alguien el fabor de pasarme el siguiente fichero a HEX para introducirlo en un 16F84.
A mi me da errores cuando intento pasarlo con el Mpasmwin, y no se por que es. Mis conocimientos no llegan ya que soy novato.
Gracias de antemano.
;*****************************************************************************
;
; This program reads the Philips RC5 remote control codes from a
; handheld infrared remote control, and displays the decoded
; data words on an LCD.
;
; IMPORTANT NOTE: This code may be used for private purposes only.
; Anyone contemplating commercial use of this code should check
; with Philips Corporation for possible limitations and
; restrictions on the use of their RC5 remote control code format.
;
; The interface works with a Hitachi HD66702- or 44780-based LC-Display
; This is a 2 line * 20 characters display module.
;
; Program READRC5.ASM
; Last update SEPT. 15, 1996
; Author Brian Aase
; Thanks to Peer Ouwehand for the enhanced LCD driver routines and demo code.
;
;*****************************************************************************
;Mod info: This version assumes RA3 idling at high level so that Sharp
;IR pickup can be connected directly.
;
;*****************************************************************************
; Fosc = 4MHz
; Cycle_time = 1/Fosc / 4
; = 1/(4*10^6) / 4
; = 1uSec
;*****************************************************************************
LIST P=16C84
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
RADIX DEC
include <c:mplabp16c84.inc>
;*****************************************************************************
; Equates, I/O, vars
;*****************************************************************************
RESET_V EQU 0x0000 ; Address of RESET Vector
ISR_V EQU 0x0004 ; Address of Interrupt Vector
OSC_FREQ EQU D"4000000" ; Oscillator Frequency is 4 MHz
LCD_DATA EQU PORTB ; LCD data lines interface
LCD_DATA_TRIS EQU TRISB
LCD_CTRL EQU PORTA ; LCD control lines interface
LCD_LINE0 EQU 0x000
LCD_LINE1 EQU 0x040
LCD_LINE2 EQU 0x014
LCD_LINE3 EQU 0x054
; PORTA bits
DATA_IN EQU 3 ; Input data from IR pickup
LCD_E EQU 2 ; LCD Enable control line
LCD_RW EQU 1 ; LCD Read/Write control line
LCD_RS EQU 0 ; LCD Register-Select control line
; PORTB bits
DB7 EQU 7 ; LCD dataline 7 (MSB)
DB6 EQU 6 ; LCD dataline 6
DB5 EQU 5 ; LCD dataline 5
DB4 EQU 4 ; LCD dataline 4
DB3 EQU 3 ; LCD dataline 3
DB2 EQU 2 ; LCD dataline 2
DB1 EQU 1 ; LCD dataline 1
DB0 EQU 0 ; LCD dataline 0 (LSB)
; misc.
#DEFINE RAMstart 0x0C ; For 16C84
LCD_TEMP EQU RAMstart ; LCD subroutines internal use
COUNT EQU RAMstart+1 ; A counter, used multiple places
DELAY EQU RAMstart+2 ; Used in DELAYxxx routines
X_DELAY EQU RAMstart+3 ; Used in X_DELAYxxx routines
TOGGLE EQU RAMstart+4 ; The RC5 Toggle bit
SYSTEM EQU RAMstart+5 ; The RC5 System word
COMND EQU RAMstart+6 ; The RC5 Command word
MZDATA EQU RAMstart+7 ; The RC5 extra Data word
POINTER EQU RAMstart+8 ; Used in TABLE_MSG subroutine
ASCII_O EQU RAMstart+9 ; ASCII One"s digit to print
ASCII_T EQU RAMstart+10 ; ASCII Ten"s digit to print
ASCII_H EQU RAMstart+11 ; ASCII Hundred"s digit to print
BIT_COUNT EQU RAMstart+12 ; Counter for incoming bits
BYTE_COUNT EQU RAMstart+13 ; Counter for buffer bytes
TEMP EQU RAMstart+14 ; Used by PARSE to hold the 2-bit pattern
SERIAL_BUF EQU RAMstart+15 ; Buffer for incoming bitstream
SERIAL_2 EQU RAMstart+16
SERIAL_3 EQU RAMstart+17
SERIAL_4 EQU RAMstart+18
SERIAL_5 EQU RAMstart+19
SERIAL_6 EQU RAMstart+20
FIELD EQU RAMstart+21 ; Temporary storage for field bit
PARSE_FLAGS EQU RAMstart+22 ; DECODE returns its data in this
MZ_FLAG EQU RAMstart+23 ; Set if there is an extra data word
; in the bitstream
w EQU 0
f EQU 1
ONE EQU B"00000001" ; 2-bit incoming pattern matches
ZERO EQU B"00000010"
;*****************************************************************************
; Program start
;*****************************************************************************
ORG RESET_V ; RESET vector location
RESET GOTO START
;*****************************************************************************
; This is the Periperal Interrupt routine. Should NOT get here
;*****************************************************************************
ORG ISR_V ; Interrupt vector location
INTERRUPT BCF STATUS, RP0 ; Select bank 0
GOTO INTERRUPT
;=============================================================================
; Table message to display: kept right up front to avoid crossing 0xff boundary
;=============================================================================
TABLE_ST MOVWF PCL
MSG_T RETLW "T"
RETLW "O"
RETLW "G"
RETLW " "
RETLW "="
RETLW " "
RETLW 0x00
MSG_S RETLW "S"
RETLW "Y"
RETLW "S"
RETLW "T"
RETLW "E"
RETLW "M"
RETLW " "
RETLW "="
RETLW " "
RETLW 0x00
MSG_C RETLW "C"
RETLW "O"
RETLW "M"
RETLW "N"
RETLW "D"
RETLW " "
RETLW "="
RETLW " "
RETLW 0x00
MSG_D RETLW "D"
RETLW "A"
RETLW "T"
RETLW "A"
RETLW " "
RETLW "="
RETLW 0x00
MSG_Y RETLW "D" ; Place your debug messages here
RETLW "E"
RETLW "B"
RETLW "U"
RETLW "G"
RETLW " "
RETLW "M"
RETLW "E"
RETLW "S"
RETLW "S"
RETLW "A"
RETLW "G"
RETLW "E"
RETLW " "
RETLW "1"
RETLW 0x00
MSG_Z RETLW "M"
RETLW "E"
RETLW "S"
RETLW "S"
RETLW "A"
RETLW "G"
RETLW "E"
RETLW " "
RETLW "2"
TABLE_END RETLW 0X00
IF ( (TABLE_ST & 0x0FF) >= (TABLE_END & 0x0FF) )
MESSG "Warning - Message table "TABLE_ST" crosses page boundary"
ENDIF
;*****************************************************************************
; Initialize processor registers
;*****************************************************************************
START ; POWER_ON Reset (Beginning of program)
CLRF STATUS ; Do initialization, Select bank 0
CLRF INTCON ; Clear int-flags, Disable interrupts
CLRF PCLATH ; Keep in lower 2KByte
CLRF PORTA ; ALL PORT outputs should output Low.
CLRF PORTB
BSF STATUS, RP0 ; Select bank 1
MOVLW 0x0F8 ; RA2-0 outputs, RA5-3 inputs
MOVWF TRISA
MOVLW 0x000 ; RB7-0 outputs
MOVWF TRISB
MOVLW B"11010001" ; Option register setup:
; No RB Pullups
; TMR0 fed from internal clock
; Assign prescaler to TMR0
; use 1:4 prescaling ratio
MOVWF OPTION_REG
BCF STATUS, RP0 ; Select bank 0
CALL LCDINIT ; Initialize LCDisplay
;***************************************************************************
; Look at RA4 to invoke debug routine instead of regular program
;***************************************************************************
POLL_RA4 BTFSS PORTA,4
GOTO POLL_RA3 ; Start regular program if RA4 is low
MOVLW LCD_LINE0 ;
CALL LCDSDDA ; Set to first line
MOVLW MSG_Y ; Point to first message string
CALL TABLE_MSG ; Display it
MOVLW LCD_LINE1 ;
CALL LCDSDDA ; Set to second line
MOVLW MSG_Z ; Point to next message string
CALL TABLE_MSG ; Display it
DB_LOOP GOTO DB_LOOP ; Hang here forever
;***************************************************************************
; When power is applied, wait for data on RA3 before proceeding
; Remember the Sharp IR pickup has an active-low output
;***************************************************************************
POLL_RA3 BTFSC PORTA, DATA_IN ; The pickup module has inverse logic
GOTO POLL_RA3 ; High is idle, low is active
MOVLW D"147" ; Found data, load timer for 444 uS
; minus 11 overhead = 433 cycles
; 255-147=108 counts x 4 prescaled
MOVWF TMR0 ; Which creates a 1/4 bit wait
BCF INTCON,T0IF ; Clear timer overflow flag
BCF STATUS,C ; Initialize the carry flag
CALL READ ; Read the data stream
BTFSC STATUS,C ; Carry flag set means bogus data
GOTO POLL_RA3 ; Start over if bad datastream
CALL PARSE ; Parse the data
BTFSC STATUS,C ; Carry flag set means no success
GOTO POLL_RA3 ; Start over if bad parse
;*****************************************************************************
; Display the data we gathered
;
;*****************************************************************************
MOVLW LCD_LINE0 ; 0x00
CALL LCDSDDA ; Position cursor leftmost on first line
MOVLW MSG_T ; Point to Toggle message
CALL TABLE_MSG ; Display message
MOVF TOGGLE,w ; Load the toggle bit to display
MOVWF ASCII_O ; Send data to conversion routine
CALL HEX_TO_ASC ; Convert to ascii
MOVF ASCII_O,w ; Ones digit is in ascii_o
CALL LCDPUTCHAR ; Display toggle data
MOVLW LCD_LINE0 + 0x009 ; Position 9
CALL LCDSDDA ; Position cursor
MOVLW MSG_S ; Point to System message
CALL TABLE_MSG ; Display message
MOVF SYSTEM,w ; Load the system byte to display
MOVWF ASCII_O ; Send data to conversion routine
CALL HEX_TO_ASC ; Convert to ascii
MOVF ASCII_T,w ; Tens digit
CALL LCDPUTCHAR ; Display it
MOVF ASCII_O,w ; Ones digit
CALL LCDPUTCHAR ; Display it
MOVLW LCD_LINE1 ; 0x40
CALL LCDSDDA ; Set cursor leftmost on line 2
MOVLW MSG_C ; Point to Command message
CALL TABLE_MSG ; Display the message
MOVF COMND,w ; Load the command byte to display
MOVWF ASCII_O ; Send data to conversion routine
CALL HEX_TO_ASC ; Convert to ascii
MOVF ASCII_H,w ; Hundreds digit
CALL LCDPUTCHAR ; Display it
MOVF ASCII_T,w ; Tens digit
CALL LCDPUTCHAR ; Display it
MOVF ASCII_O,w ; Ones digit
CALL LCDPUTCHAR ; Display it
MOVLW LCD_LINE1 + 0x00C ; Position 12
CALL LCDSDDA ; Set cursor
MOVLW MSG_D ; Point to Data message
CALL TABLE_MSG ; Display the message
BTFSS MZ_FLAG,0 ; Is there a data word to display?
GOTO NO_DATA ; No
MOVF MZDATA,w ; Load the data byte to display
MOVWF ASCII_O ; Send data to conversion routine
CALL HEX_TO_ASC ; Convert to ascii
MOVF ASCII_T,w ; Tens digit
CALL LCDPUTCHAR ; Display it
MOVF ASCII_O,w ; Ones digit
CALL LCDPUTCHAR ; Display it
GOTO POLL_RA3 ; Wait for incoming again
NO_DATA MOVLW " " ; Print spaces instead of data value
CALL LCDPUTCHAR
MOVLW " "
CALL LCDPUTCHAR
GOTO POLL_RA3 ; Wait for incoming again
;*****************************************************************************
; Main program ends here
;
;*****************************************************************************
;*****************************************************************************
; Send a message using a table to output the message
;
;*****************************************************************************
TABLE_MSG
MOVWF POINTER ; Point to the first char. we want
LOOP_WR
MOVFW POINTER ; Renew the pointer
CALL TABLE_ST ; Initiate table lookup
XORLW 0x00 ; Is this the terminating char?
BTFSC STATUS,Z
GOTO END_WR
CALL LCDPUTCHAR ; Actually put the char on display
INCF POINTER,f ; Point to the next char
GOTO LOOP_WR ; Do next character
END_WR
RETURN
;*****************************************************************************
; LCD Module Subroutines
;*****************************************************************************
;
;=============================================================================
; LCDINIT
; Initilize LC-Display Module
; This code sets up the Optrex DMC50218 (2x20)
;=============================================================================
LCDINIT
; Busy-flag is not yet valid
CLRF LCD_CTRL ; ALL PORT output should output Low.
; power-up delay
MOVLW 0x01E
CALL X_DELAY500 ; 30 * 0.5mS = 15mS
; Busy Flag should be valid from here
MOVLW 0x038 ; 8-bit-interface, 2-lines
CALL LCDPUTCMD
MOVLW 0x000 ; disp.off, curs.off, no-blink
CALL LCDDMODE
CALL LCDCLEAR
MOVLW 0x004 ; disp.on, curs.off
CALL LCDDMODE
MOVLW 0x002 ; auto-inc (shift-cursor)
CALL LCDEMODE
RETURN
;=============================================================================
; LCD_ENABLE
; Pulses LCD enable pin
;=============================================================================
LCD_ENABLE
BSF LCD_CTRL, LCD_E ; LCD E-line High
BCF LCD_CTRL, LCD_E ; LCD E-line Low
RETURN
;=============================================================================
; LCDBUSY
; Returns when LCD busy-flag is inactive
;=============================================================================
LCDBUSY
BSF STATUS,RP0 ; Select Register page 1
MOVLW 0x0FF ; Set PORTB for input
MOVWF LCD_DATA_TRIS
BCF STATUS, RP0 ; Select Register page 0
BCF LCD_CTRL, LCD_RS; Set LCD for command mode
BSF LCD_CTRL, LCD_RW; Setup to read busy flag
BSF LCD_CTRL, LCD_E ; LCD E-line High
MOVF LCD_DATA, W ; Read busy flag + DDram address
BCF LCD_CTRL, LCD_E ; LCD E-line Low
ANDLW 0x80 ; Check Busy flag, High = Busy
BTFSS STATUS, Z
GOTO LCDBUSY
LCDNOTBUSY BCF LCD_CTRL, LCD_RW
BSF STATUS, RP0 ; Select Register page 1
MOVLW 0x000
MOVWF LCD_DATA_TRIS ; Set PORTB for output
BCF STATUS, RP0 ; Select Register page 0
RETURN
;=============================================================================
; LCDCLEAR
; Clears display and returns cursor to home position (upper-left corner).
;=============================================================================
LCDCLEAR
MOVLW 0x001
CALL LCDPUTCMD
RETURN
;=============================================================================
; LCDHOME
; Returns cursor to home position.
; Returns display to original position (when shifted).
;=============================================================================
LCDHOME
MOVLW 0x002
CALL LCDPUTCMD
RETURN
;=============================================================================
; LCDEMODE
; Sets entry mode of display.
; Required entry mode must be set in W
; b0 : 0 = no display shift 1 = display shift
; b1 : 0 = auto-decrement 1 = auto-increment
; b2-7 : don"t care
;=============================================================================
LCDEMODE
ANDLW 0x003 ; Strip upper bits
IORLW 0x004 ; Function set
CALL LCDPUTCMD
RETURN
;=============================================================================
; LCDDMODE
; Sets display control.
; Required display mode must be set in W
; b0 : 0 = cursor blink off 1 = cursor blink on
; b1 : 0 = cursor off 1 = cursor on
; b2 : 0 = display off 1 = display on (display data remains in DDRAM)
; b3-7 : don"t care
;=============================================================================
LCDDMODE
ANDLW 0x007 ; Strip upper bits
IORLW 0x008 ; Function set
CALL LCDPUTCMD
RETURN
;=============================================================================
; LCDSCGA
; Sets Character-Generator-RAM address. CGRAM is read/written after
; this setting.
; Required CGRAM address must be set in W
; b0-5 : required CGRAM address
; b6-7 : don"t care
;=============================================================================
LCDSCGA
ANDLW 0x03F ; Strip upper bits
IORLW 0x040 ; Function set
CALL LCDPUTCMD
RETURN
;=============================================================================
; LCDSDDA
; Sets the Display-Data-RAM address. DDRAM data is read/written after
; this setting.
; Required DDRAM address must be set in W
; b0-6 : required DDRAM address
; b7 : don"t care
;=============================================================================
LCDSDDA
IORLW 0x080 ; Function set
CALL LCDPUTCMD
RETURN
;=============================================================================
; LCDGADDR
; Returns address counter contents, used for both DDRAM and CGRAM.
; RAM address is returned in W
;=============================================================================
LCDGADDR
BSF STATUS,RP0 ; Select Register page 1
MOVLW 0x0FF ; Set PORTB for input
MOVWF LCD_DATA_TRIS
BCF STATUS, RP0 ; Select Register page 0
BCF LCD_CTRL, LCD_RS; Set LCD for command mode
BSF LCD_CTRL, LCD_RW; Setup to read busy flag
BSF LCD_CTRL, LCD_E ; LCD E-line High
MOVF LCD_DATA, W ; Read busy flag + RAM address
BCF LCD_CTRL, LCD_E ; LCD E-line Low
ANDLW 0x07F ; Strip upper bit
BCF LCD_CTRL, LCD_RW
BSF STATUS, RP0 ; Select Register page 1
MOVLW 0x000
MOVWF LCD_DATA_TRIS ; Set PORTB for output
BCF STATUS, RP0 ; Select Register page 0
RETURN
;=============================================================================
; LCDPUTCHAR
; Sends character to LCD
; Required character must be in W
;=============================================================================
LCDPUTCHAR
MOVWF LCD_TEMP ; Character to be sent is in W
CALL LCDBUSY ; Wait for LCD to be ready
BCF LCD_CTRL, LCD_RW; Set LCD in read mode
BSF LCD_CTRL, LCD_RS; Set LCD in data mode
BSF LCD_CTRL, LCD_E ; LCD E-line High
MOVF LCD_TEMP, W
MOVWF LCD_DATA ; Send data to LCD
BCF LCD_CTRL, LCD_E ; LCD E-line Low
RETURN
;=============================================================================
; LCDPUTCMD
; Sends command to LCD
; Required command must be in W
;=============================================================================
LCDPUTCMD
MOVWF LCD_TEMP ; Command to be sent is in W
CALL LCDBUSY ; Wait for LCD to be ready
BCF LCD_CTRL, LCD_RW; Set LCD in read mode
BCF LCD_CTRL, LCD_RS; Set LCD in command mode
BSF LCD_CTRL, LCD_E ; LCD E-line High
MOVF LCD_TEMP, W
MOVWF LCD_DATA ; Send data to LCD
BCF LCD_CTRL, LCD_E ; LCD E-line Low
RETURN
;*****************************************************************************
; Delay_time = ((DELAY_value * 3) + 4) * Cycle_time
; DELAY_value = (Delay_time - (4 * Cycle_time)) / (3 * Cycle_time)
;
; i.e. (@ 4MHz crystal)
; Delay_time = ((32 * 3) + 4) * 1uSec
; = 100uSec
; DELAY_value = (500uSec - 4) / 3
; = 165.33
; = 165
;*****************************************************************************
DELAY500 MOVLW D"165" ; +1 1 cycle
MOVWF DELAY ; +2 1 cycle
DELAY500_LOOP DECFSZ DELAY, F ; step 1 1 cycle
GOTO DELAY500_LOOP ; step 2 2 cycles
DELAY500_END RETURN ; +3 2 cycles
;
;
X_DELAY500 MOVWF X_DELAY ; +1 1 cycle
X_DELAY500_LOOP CALL DELAY500 ; step1 wait 500uSec
DECFSZ X_DELAY, F ; step2 1 cycle
GOTO X_DELAY500_LOOP ; step3 2 cycles
X_DELAY500_END RETURN ; +2 2 cycles
;===========================================================================
; HEX_TO_ASC .. Converts a hex digit to three ASCII characters
; Enter with the hex digit in ASCII_O
; Exit with Hundreds ascii digit in ASCII_H,
; Tens ascii digit in ASCII_T,
; and Ones ascii digit in ASCII_O.
; The incoming byte is not preserved.
;===========================================================================
HEX_TO_ASC MOVLW "0" ; Preload a zero into 10"s & 100"s
MOVWF ASCII_T
MOVWF ASCII_H
DO_100s MOVLW D"100"
SUBWF ASCII_O,w ; Subtract 100 to test size
BNC DO_10s ; It"s less than 100, so branch
MOVWF ASCII_O ; It was bigger, so decrement it
INCF ASCII_H,f ; Bump up the 100"s digit
GOTO DO_100s ; Loop again till < 100
DO_10s MOVLW D"10"
SUBWF ASCII_O,w ; Subtract 10 to test size
BNC ADJUST ; It"s less than 10, so branch
MOVWF ASCII_O ; It was bigger, so decrement it
INCF ASCII_T,f ; Bump up the 10"s digit
GOTO DO_10s ; Loop again till < 10
ADJUST MOVLW "0" ; The # in ASCII_O is now < 10
ADDWF ASCII_O,f ; Turn it into an ASCII character
BLANK_ZEROS MOVLW "0"
XORWF ASCII_H,w ; Is the 100"s char a 0?
BTFSS STATUS,Z
GOTO HEX_DONE ; No.
MOVLW " " ; Yes,
MOVWF ASCII_H ; So replace it with a space.
MOVLW "0"
XORWF ASCII_T,w ; Is the 10"s char a 0?
BTFSS STATUS,Z
GOTO HEX_DONE ; No.
MOVLW " " ; Yes,
MOVWF ASCII_T ; So replace it with a space
HEX_DONE RETURN
;****************************************************************************
;READ .. reads the incoming data stream and saves it into a 6-byte buffer
; Remember again that the IR pickup output is active low
;****************************************************************************
READ ; First, zero all storage
MOVLW SERIAL_BUF ; Start of RAM buffer
MOVWF FSR ; Load indirect register
RD_LOOP1 CLRF INDF ; Zero out the buffer
INCF FSR,f ; Increment to next byte
MOVLW SERIAL_BUF+6 ; Test for 6 bytes done
XORWF FSR,w
BTFSS STATUS,Z
GOTO RD_LOOP1 ; Loop till done
CLRF BIT_COUNT
CLRF BYTE_COUNT
MOVLW SERIAL_BUF ; Reset the indirect pointer back
MOVWF FSR ; to the start of the buffer space
RD_LOOP2 BTFSS INTCON, T0IF ; Wait till timer goes 444 Usec
GOTO RD_LOOP2
CALL RESTART_TMR0 ; Reset timer for 888 uSec
BTFSC PORTA,3 ; Check RA3 signal (i.e. debounce)
GOTO BAD_DATA ; If it"s high (logic 0), bail out
RD_LOOP3 BTFSS INTCON, T0IF ; Wait till timer goes 888 uSec
GOTO RD_LOOP3
CALL RESTART_TMR0 ; Restart 888 uSec timer
INCF BIT_COUNT,f
MOVLW D"43" ; See if we"ve done all 42 bits
XORWF BIT_COUNT,w
BTFSC STATUS,Z
GOTO RD_FINISH ; We"ve done all 42 bits
BSF STATUS,C ; Preset the carry bit
BTFSC PORTA,3 ; Test RA3
BCF STATUS,C ; Input bit is high (logic 0) so change carry
; Now the input bit is in the carry flag
RLF INDF,f ; Rotate it into the buffer
INCF BYTE_COUNT,f ;
BTFSC BYTE_COUNT,3 ; See if all 8 bits are filled
CALL NEXT_BYTE ; Yes, use next buffer byte
GOTO RD_LOOP3 ; Loop back & do the rest of the bits
RD_FINISH BCF STATUS,C ;
RLF INDF,f ; The last buffer byte has only 2
RLF INDF,f ; bits loaded.
RLF INDF,f ; So we shift them up to the top
RLF INDF,f ; the hard way.
RLF INDF,f
RLF INDF,f
BCF STATUS,C ; Clear carry to show a successful capture
RETURN
;****************************************************************************
;NEXT_BYTE .. Increment the FSR and clear the counter
;
;****************************************************************************
NEXT_BYTE INCF FSR,f
CLRF BYTE_COUNT
RETURN
;****************************************************************************
;RESTART_TMR0 .. Restart the timer with an 888 uSec delay
; and refresh the overflow flag.
; MPLAB stopwatch says there is a loop overhead of
; 14 cycles, thus we need it to run for 888-14=874 uSec
;****************************************************************************
RESTART_TMR0
BCF INTCON, T0IF ; Clear the overflow flag
MOVLW D"37" ; 255 - 37 = 218 x 4 = 872 uSec
MOVWF TMR0
RETURN
;****************************************************************************
;PARSE .. decodes the saved datastream into the various
; RC5 words and flags.
;****************************************************************************
PARSE
MOVLW SERIAL_BUF ; Put buffer start address into
MOVWF FSR ; the FSR
CLRF TEMP ; Initialize variables
CLRF BYTE_COUNT ;
CLRF MZ_FLAG ;
CLRF FIELD ;
CLRF TOGGLE ;
CLRF SYSTEM ;
CLRF COMND ;
CLRF MZDATA ;
; First one is the field bit
RLF INDF,f ; First bit into carry
RLF TEMP,f ; Put it into TEMP for decoding
RLF INDF,f ; Second bit
RLF TEMP,f ; ditto
INCF BYTE_COUNT,f ; Start keeping track of INDF bit position
CALL DECODE
BTFSC PARSE_FLAGS,2 ; Illegal pattern found
GOTO BAD_DATA
; Must have found a good bit
RRF PARSE_FLAGS,f ; Put field bit into Carry
RLF FIELD,f ; Move it into FIELD
CLRF TEMP ; Next one is the toggle bit
RLF INDF,f ; First bit into carry
RLF TEMP,f ; Put it into TEMP for decoding
RLF INDF,f ; Second bit
RLF TEMP,f ; ditto
INCF BYTE_COUNT,f ; keep track of INDF bit position
CALL DECODE
BTFSC PARSE_FLAGS,2 ; Illegal pattern found
GOTO BAD_DATA
; Must have found a good bit
RRF PARSE_FLAGS,f ; Put toggle bit into Carry
RLF TOGGLE,f ; Move it into TOGGLE
MOVLW 0x05 ; Next one is the system byte, 5 bits
MOVWF COUNT
SYS_1 CLRF TEMP
RLF INDF,f ; First bit into carry
RLF TEMP,f ; Put it into TEMP for decoding
RLF INDF,f ; Second bit
RLF TEMP,f ; ditto
INCF BYTE_COUNT,f ; keep track of INDF bit position
BTFSC BYTE_COUNT,2 ; (there are two rotates per count)
CALL NEXT_BYTE ; Go to next buffer byte when count=4
CALL DECODE
BTFSC PARSE_FLAGS,2 ; Illegal pattern found
GOTO BAD_DATA
; Must have found a good bit
RRF PARSE_FLAGS,f ; Put bit into Carry
RLF SYSTEM,f ; Move it into SYSTEM
DECFSZ COUNT,f ; Have we done all 5 bits?
GOTO SYS_1 ; No, not yet
; Here we test for the two spaces
; present in the extended data format.
; If they appear, we set a flag
; and skip over them to the command
; word.
MOVLW B"11000000" ; Mask for 2nd buffer byte
ANDWF SERIAL_2,w ; Are the 2 top bits zero?
BTFSS STATUS,Z ;
GOTO PHILIPS ; No space found
CALL NEXT_BYTE ; Skip over first space
RLF INDF,f ; Skip over second space
RLF INDF,f ;
INCF BYTE_COUNT,f
MOVLW 0x01
MOVWF MZ_FLAG ; Set the flag
PHILIPS MOVLW 0x06 ; Next one is the command byte, 6 bits
MOVWF COUNT
CMD_1 CLRF TEMP
RLF INDF,f ; First bit into carry
RLF TEMP,f ; Put it into TEMP for decoding
RLF INDF,f ; Second bit
RLF TEMP,f ; ditto
INCF BYTE_COUNT,f ; keep track of INDF bit position
BTFSC BYTE_COUNT,2 ; (there are two rotates per count)
CALL NEXT_BYTE ; Go to next buffer byte when count=4
CALL DECODE
BTFSC PARSE_FLAGS,2 ; Illegal pattern found
GOTO BAD_DATA
; Must have found a good bit
RRF PARSE_FLAGS,f ; Put bit into Carry
RLF COMND,f ; Move it into COMND
DECFSZ COUNT,f ; Have we done all 6 bits?
GOTO CMD_1 ; No, not yet
BTFSS FIELD,0 ; If field bit=0 then comnd=comnd+64
BSF COMND,6
BTFSC MZ_FLAG,0 ; Test for extra data word
GOTO MDAT_1 ; Parse extra data word
RETURN ; Finish here if Philips format
MDAT_1 MOVLW 0x06 ; Next one is the data byte, 6 bits
MOVWF COUNT
MDAT_2 CLRF TEMP
RLF INDF,f ; First bit into carry
RLF TEMP,f ; Put it into TEMP for decoding
RLF INDF,f ; Second bit
RLF TEMP,f ; ditto
INCF BYTE_COUNT,f ; keep track of INDF bit position
BTFSC BYTE_COUNT,2 ; (there are two rotates per count)
CALL NEXT_BYTE ; Go to next buffer byte when count=4
CALL DECODE
BTFSC PARSE_FLAGS,2 ; Illegal pattern found
GOTO BAD_DATA
; Must have found a good bit
RRF PARSE_FLAGS,f ; Put bit into Carry
RLF MZDATA,f ; Move it into MZDATA
DECFSZ COUNT,f ; Have we done all 6 bits?
GOTO MDAT_2 ; No, not yet
PARSE_DONE RETURN
;****************************************************************************
; DECODE .. enter with two-bit data in TEMP
; return with result code in PARSE_FLAGS, thus
; PARSE_FLAGS<0> = valid data, one or zero
; PARSE_FLAGS<1> = unused
; PARSE_FLAGS<2> = set if data is invalid
;****************************************************************************
DECODE
CLRF PARSE_FLAGS
MOVLW ONE
XORWF TEMP,w ; Compare to bit pattern "01"
BZ ONE_EXIT
MOVLW ZERO
XORWF TEMP,w ; compare to bit pattern "10"
BZ ZERO_EXIT
BAD_EXIT BSF PARSE_FLAGS,2 ; bit pattern neither 01 nor 10
RETURN
ONE_EXIT BSF PARSE_FLAGS,0 ; Return with valid data in LSB
ZERO_EXIT RETURN ; of the PARSE_FLAGS variable
;****************************************************************************
; BAD_DATA .. Exit if Read or Parse doesn"t like what it finds.
; The Carry flag is set as an error message.
;****************************************************************************
BAD_DATA
BSF STATUS,C ; Set the carry flag to show error
RETURN
;****************************************************************************
END ; End of program