LIST P=16F84, F=INHX8M ; ERRORLEVEL 2 __CONFIG _CP_OFF & _WDT_OFF & _XT_OSC ;***************************************************************************** ; ; ; Program 1216xx.ASM ; Date 2000/9/30 ; Author Charlos Potma ; ; Program to control a Philips type FI1216 or 816 TV tuner as part of a ; weather satellite reveiver system. These tuners are controlled ; using an I2C interace. ; Tuner can be cycled through 8 preset frequencies using a pushbutton ; switch. Another pushbutton switch alternates mode between HRTP and PDUS. ; A Philips PCF8574P I2C IC is used as 8 bit I/O to read the pushbuttons ; and to show the selected frequency number on a number of LED's. The latter ; is used for debugging purposes. ; A one-line 16-character LCD is used to show frequency number, frequency, ; HRTP or PDUS mode. (HRTP or PDUS mode determines the IF frequency ; when using the tuner as part of a Meteosat receiving system) ; The last character displayed is a "P" after a new ; frequency is sent to the tuner, and a "L" after the tuner status byte ; shows a PLL lock. The LCD is controlled using three control lines on ; PORTA and the upper 4 pins of PORTB. ; PORTA pin number three is low in HRTP and high in PDUS mode. This pin ; can be used to switch a relay (in the IF circuit) in the receiver. ; Using Peer Ouwehands' LCD routines ; Using Towanda Malone's I2C routines ;***************************************************************************** ;***************************************************************************** ; Fosc = 4MHz ; Cycle_time = 1/Fosc / 4 ; = 1/(4*10^6) / 4 ; = 1uSec ;***************************************************************************** include ;***************************************************************************** ; 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 ; Address of first location in upper LCD line LCD_LINE1 EQU 0x040 ; Address of first location in lower LCD line LCD_LAST EQU 0x047 ; Address of last character on lower LCD line ; LCD control bits 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 ; LCD Data bits, LCD on high nibble 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 (LSB) ; I2C control bits, I2C on lower two bits SCL EQU 1 ; I2C SCL line SDA EQU 0 ; I2C SDA line ; Buttons on I2C 8574 input FINC EQU 6 ; Increment frequency button RXTG EQU 7 ; RXmode toggle button ; RXMODE output pin RXMPORT EQU PORTA ; RXmode output pin port and RXMPNR EQU 3 ; number ; RXMODE bit number RXMB EQU 0 ; RXmode bit number ; I2C addresses ADR8574W EQU 0x40 ; Write ddress of 8574 8-bit i/o ; with a0,a1,a2 (pin 1,2,3) grounded ADR8574R EQU 0x41 ; Read ddress of 8574 8-bit i/o ; with a0,a1,a2 (pin 1,2,3) grounded ADR1216W EQU 0xC0 ; Write address of 816/1216 tuner with pin 15 ; grounded ADR1216R EQU 0xC1 ; Read address of 816/1216 tuner with pin 15 ; grounded ; 1216 control CRTLB1216 EQU 0x8E ; 816/1216 control byte:128+8+4+2 PORTB1216 EQU 0xA0 ; 816/1216 port byte: 128+32 (low band) LOCKBYTE EQU 0x4C ; Status byte when locked should be 76 decimal DECAD EQU 0X30 ; Decimal to ASCII 0-9 : ADD 0X30 ;***************************************************************************** ; Equates, registers ;***************************************************************************** ; 0x00C is FIRST location in RAM LCD_TEMP EQU 0x00C ; LCD subroutines internal use COUNT EQU 0x00D ; A counter DELAY equ 0x00E ; Used in DELAYxxx routines X_DELAY equ 0x00F ; Used in X_DELAYxxx routines WTEMP equ 0x010 ; Temp for W CTEMP equ 0x011 ; Temp char holder FREQNUM equ 0x012 ; Frequency setting number RXMODE equ 0x013 ; Receive mode: 0=HRTP, 1=PDUS FREQ0 equ 0x014 ; Frequency string FREQ1 equ 0x015 FREQ2 equ 0x016 FREQ3 equ 0x017 BYTE0HRTP equ 0x018 ; programming byte for HRTP mode BYTE1HRTP equ 0x019 BYTE0PDUS equ 0x01A ; programming byte for PDUS mode BYTE1PDUS equ 0x01B ; I2C stuff DIRS EQU 0x01C ; identifies input bits on 8574 O_8574 EQU 0x01D ; byte to be output on 8574 I_8574 EQU 0x01E ; input from 8574 O_BYTE EQU 0x01F ; byte sent on I2C bus I_BYTE EQU 0x020 ; byte received on I2C bus _N EQU 0x021 ; index LOOP1 EQU 0x022 ; timing LOOP2 EQU 0x023 ; timing ; !!! 0x04F is LAST location in RAM (16F84) ;***************************************************************************** ; Program start ;***************************************************************************** ORG RESET_V ; RESET vector location RESET GOTO START ;***************************************************************************** ; This is the interrupt routine. We should NEVER get here ;***************************************************************************** ORG ISR_V ; Interrupt vector location INTERRUPT BCF STATUS, RP0 ; Select bank 0 GOTO INTERRUPT ;***************************************************************************** ; 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 output should output Low. CLRF PORTB BSF STATUS, RP0 ; Select bank 1 MOVLW B'11110000' ; RA2-0 outputs, RA3 output, ; RA4 input MOVWF TRISA MOVLW B'00000011' ; RB7-2 outputs, RB1, RB0 input MOVWF TRISB ;BSF OPTION_REG, NOT_RBPU ; Disable PORTB pull-ups ;BSF OPTION_REG, T0SE ; Transition on RA4/T0CKL pin ;BSF OPTION_REG, PS2 ; ;BSF OPTION_REG, PS1 ; Prescaler 1:256 ;BSF OPTION_REG, PS0 ; MOVLW B'10100111' MOVWF OPTION_REG BCF STATUS, RP0 ; Select bank 0 CALL LCDINIT ; Initialize LCDisplay BSF RXMODE, RXMB ; RXMODE=1 : PDUS BCF RXMPORT, RXMPNR ; Clear RXmode output pin CLRF FREQNUM ; FREQ set to number 0 CALL INIT8574 ;***************************************************************************** CALL VERSION ; Display s/w version CALL SECWAIT CALL SECWAIT LOOP CALL GETFREQ ; Get frequency and tuner data from EEPROM CALL RXMOUT ; Set RXmode output pin CALL FREQTOLCD ; Frequency and mode to LCD CALL SECWAIT CALL PROGTUNER ; Program tuner CALL TUNERSTATUS ; Tuner locked? CALL STSTOI2C ; Freq.number to led's on 8574 output CALL SCANBUTTONS ; Wait for buttons to be pressed GOTO LOOP ;***************************************************************************** ; Program ends here. ; Routines follow. ;***************************************************************************** ;***************************************************************************** ; Test status of 1216 tuner ;***************************************************************************** TUNERSTATUS CALL DELAY_SHORT READLOCK CALL I2CSTART MOVLW ADR1216R ; I2C read ddress of tuner MOVWF O_BYTE CALL OUT_BYTE ; Output address byte CALL ACK CALL IN_BYTE ; Read tuner status byte CALL NACK CALL STOP MOVLW LOCKBYTE SUBWF I_BYTE, W BTFSS STATUS, Z GOTO READLOCK MOVLW LCD_LAST CALL LCDSDDA ; Position cursor MOVLW 'L' CALL LCDPUTCHAR RETURN ;***************************************************************************** ; Program 1216 tuner ;***************************************************************************** PROGTUNER CALL I2CSTART ; I2C start MOVLW ADR1216W ; I2C Write address of tuner MOVWF O_BYTE CALL OUT_BYTE ; Output address byte CALL ACK ; followed by an ack BTFSS RXMODE, RXMB ; Rxmode bit = 0 = HRTP GOTO SNDHRTP ; otherwise PDUS MOVF BYTE0PDUS, W ; send PDUS byte 0 MOVWF O_BYTE CALL OUT_BYTE CALL ACK ; followed by an ack MOVF BYTE1PDUS, W ; send PDUS byte 1 MOVWF O_BYTE CALL OUT_BYTE CALL ACK ; followed by an ack GOTO SNDLAST SNDHRTP MOVF BYTE0HRTP, W ; send HRTP byte 0 MOVWF O_BYTE CALL OUT_BYTE CALL ACK ; followed by a nack MOVF BYTE1HRTP, W ; send HRTP byte 1 MOVWF O_BYTE CALL OUT_BYTE CALL ACK ; followed by an ack SNDLAST MOVLW CRTLB1216 ; send 1216 control byte MOVWF O_BYTE CALL OUT_BYTE CALL ACK ; followed by an ack MOVLW PORTB1216 ; send 1216 port byte MOVWF O_BYTE CALL OUT_BYTE CALL STOP ; followed by a last stop RETURN ;***************************************************************************** ; Initialise 8574 I2C 8-bits i/o chip ;***************************************************************************** INIT8574 MOVLW 0xC0 ; bit 6,7 of 8574 is input MOVWF DIRS MOVLW 0xFF ; all outputs to one (led's off) MOVWF O_8574 CALL OUT_8574 RETURN ;***************************************************************************** ; Set RXmode output pin ;***************************************************************************** RXMOUT BTFSS RXMODE, RXMB ; If RXmode bit is set, GOTO RXMBOFF ; RXMPNR output high BSF RXMPORT, RXMPNR ; otherwise low RETURN RXMBOFF BCF RXMPORT, RXMPNR RETURN ;***************************************************************************** ; Wait for buttons to be pressed on 8574 inputs ;***************************************************************************** SCANBUTTONS CALL IN_8574 BTFSC I_8574, FINC ; input FINC is frequency number increment GOTO READSWA READSWFOFF MOVLW d'80' CALL X_DELAY500 ; 80 * 0.5mS = 40mS debounce time CALL IN_8574 BTFSS I_8574, FINC GOTO READSWFOFF INCF FREQNUM, 1 ; Next frequency number BTFSS FREQNUM, 2 ; Test bit 2, if one, roll over (four freq.'s) RETURN ; freqnum back to 0 CLRF FREQNUM RETURN READSWA BTFSC I_8574, RXTG ; input RXTG is rxmode toggle GOTO SCANBUTTONS READSWROFF MOVLW d'80' CALL X_DELAY500 ; 80 * 0.5mS = 40mS debounce time CALL IN_8574 BTFSS I_8574, RXTG GOTO READSWROFF BTFSC RXMODE, RXMB ; Test RXmode, is set (PDUS), reset GOTO RXCL BSF RXMODE, RXMB ; to HRTP, is reset (HRTP) set to RETURN RXCL BCF RXMODE, RXMB ; PDUS RETURN ;***************************************************************************** ; Status to I2C output ;***************************************************************************** STSTOI2C COMF FREQNUM, W MOVWF O_8574 ; freq.number Led's on DECF O_8574, 1 ; M0 is shown as one led on etc. CALL OUT_8574 CALL DELAY_LONG MOVLW 0xFF ; Led's off MOVWF O_8574 CALL OUT_8574 CALL DELAY_LONG RETURN ;***************************************************************************** ; Get frequency from EEPROM ;***************************************************************************** GETFREQ MOVF FREQNUM, W ; Frequency number to W MOVWF EEADR ; to eeadr BCF STATUS, C ; Clear carry (otherwise set carry gets ; left shifted into eeadr) RLF EEADR, 1 ; shift 3 bits left = mult by 8 RLF EEADR, 1 ; because frequency data is stored in RLF EEADR, 1 ; 8 byte block (4 freq.string, 2 tuner ; bytes each for HRTP and PDUS mode) CALL REEPROM ; Read frequency and other params from MOVWF FREQ0 ; eeprom INCF EEADR, 1 ; Increment eeprom address CALL REEPROM MOVWF FREQ1 ; Read frequency INCF EEADR, 1 ; Increment eeprom address CALL REEPROM INCF EEADR, 1 ; Increment eeprom address MOVWF FREQ2 CALL REEPROM MOVWF FREQ3 INCF EEADR, 1 ; Increment eeprom address CALL REEPROM ; Read HRTP programming bytes MOVWF BYTE0HRTP ; for this frequency INCF EEADR, 1 ; Increment eeprom address CALL REEPROM MOVWF BYTE1HRTP INCF EEADR, 1 ; Increment eeprom address CALL REEPROM ; Read PDUS programming bytes MOVWF BYTE0PDUS ; for this frequency INCF EEADR, 1 ; Increment eeprom address CALL REEPROM MOVWF BYTE1PDUS RETURN ;***************************************************************************** ; Read contents of EEADR in W ;***************************************************************************** REEPROM BSF STATUS,RP0 ;bank 1 BSF EECON1,RD ;eeprom read BCF STATUS,RP0 ;bank 0 MOVF EEDATA, W RETURN ;***************************************************************************** ; Frequency and mode to LCD ;***************************************************************************** FREQTOLCD MOVLW LCD_LINE0 CALL LCDSDDA ; Position cursor leftmost on first line MOVLW 'M' ; print memory location CALL LCDPUTCHAR MOVF FREQNUM, W ADDLW DECAD ; Add facor to get ascii code CALL LCDPUTCHAR MOVLW ' ' CALL LCDPUTCHAR MOVF FREQ0, W ; print frequency CALL LCDPUTCHAR MOVF FREQ1, W CALL LCDPUTCHAR MOVF FREQ2, W CALL LCDPUTCHAR MOVLW '.' CALL LCDPUTCHAR MOVF FREQ3, W CALL LCDPUTCHAR MOVLW LCD_LINE1 CALL LCDSDDA ; Position cursor leftmost on second line MOVLW ' ' CALL LCDPUTCHAR BTFSS RXMODE, RXMB ; Rxmode bit = 0 = HRTP GOTO HRTP ; otherwise PDUS MOVLW 'P' CALL LCDPUTCHAR MOVLW 'D' CALL LCDPUTCHAR MOVLW 'U' CALL LCDPUTCHAR MOVLW 'S' CALL LCDPUTCHAR GOTO PLAST HRTP MOVLW 'H' CALL LCDPUTCHAR MOVLW 'R' CALL LCDPUTCHAR MOVLW 'T' CALL LCDPUTCHAR MOVLW 'P' CALL LCDPUTCHAR PLAST MOVLW ' ' CALL LCDPUTCHAR MOVLW ' ' CALL LCDPUTCHAR MOVLW 'P' CALL LCDPUTCHAR RETURN ;***************************************************************************** ; Display version number... ;***************************************************************************** VERSION MOVLW LCD_LINE0 CALL LCDSDDA ; Position cursor leftmost on first line MOVLW '8' CALL LCDPUTCHAR MOVLW '1' CALL LCDPUTCHAR MOVLW '6' CALL LCDPUTCHAR MOVLW ' ' CALL LCDPUTCHAR MOVLW 'c' CALL LCDPUTCHAR MOVLW 't' CALL LCDPUTCHAR MOVLW "l" CALL LCDPUTCHAR MOVLW ' ' CALL LCDPUTCHAR MOVLW LCD_LINE1 CALL LCDSDDA ; Position cursor leftmost on second line MOVLW 'P' CALL LCDPUTCHAR MOVLW 'A' CALL LCDPUTCHAR MOVLW '3' CALL LCDPUTCHAR MOVLW 'C' CALL LCDPUTCHAR MOVLW 'K' CALL LCDPUTCHAR MOVLW 'R' CALL LCDPUTCHAR CALL SECWAIT CALL SECWAIT MOVLW 0X001 ; CLR DISP CALL LCDPUTCMD MOVLW 'V' CALL LCDPUTCHAR MOVLW '1' CALL LCDPUTCHAR MOVLW '.' CALL LCDPUTCHAR MOVLW '1' CALL LCDPUTCHAR RETURN ;***************************************************************************** ; LCD Module Subroutines ;***************************************************************************** ; ;============================================================================= ; LCDINIT ; Initilize LC-Display Module ; Should be modified to your needs (i.e. display type, cursor on/off, etc.) ; OK ;============================================================================= LCDINIT ; Busy-flag is not yet valid CLRF LCD_CTRL ; ALL PORT output should output Low. MOVLW d'30' ; power-up delay CALL X_DELAY500 ; 30 * 0.5mS = 15mS MOVLW B'00110000' ; 8-bit-interface, 1-line MOVWF LCD_DATA CALL LCD_ENABLE MOVLW d'30' CALL X_DELAY500 ; 30 * 0.5mS = 15mS CALL LCD_ENABLE ; LCD_DATA again to LCD MOVLW d'30' CALL X_DELAY500 ; 30 * 0.5mS = 15mS MOVLW B'00100000' ; 4-bit-interface MOVWF LCD_DATA CALL LCD_ENABLE MOVLW d'30' CALL X_DELAY500 ; 30 * 0.5mS = 15mS ; Busy Flag should be valid from here ; and we can use LCDroutines MOVLW B'00101000' ; 4-bit-interface, HIGH NIBBLE, 2-line CALL LCDPUTCMD MOVLW 0x008 ; disp.off, curs.off, no-blink CALL LCDPUTCMD MOVLW 0X00F ; DISP ON, C, B CALL LCDPUTCMD MOVLW 0X001 ; CLR DISP CALL LCDPUTCMD MOVLW 0X006 ; ENTRY INC CALL LCDPUTCMD RETURN ;============================================================================= ; LCD_ENABLE ; Pulses LCD enable pin ; OK ;============================================================================= 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 ; OK ;============================================================================= 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 0x0F0 ; Mask out low nibble MOVWF WTEMP BSF LCD_CTRL, LCD_E ; LCD E-line High SWAPF LCD_DATA, W ; Read lower nibble DDRam address BCF LCD_CTRL, LCD_E ; LCD E-line Low ANDLW 0x00F ; Mask out upper nibble IORWF WTEMP ; Combine nibbles BTFSC WTEMP, 7 ; Check busy flag, high=busy GOTO LCDBUSY LCDNOTBUSY BCF LCD_CTRL, LCD_RW BSF STATUS, RP0 ; Select Register page 1 ;MOVLW 0x000 ; !!!!!!!!!!!!!!!!!!!!! MOVLW B'00000011' ; RB7-2 outputs, RB1, RB0 input MOVWF LCD_DATA_TRIS ; Set PORTB for output BCF STATUS, RP0 ; Select Register page 0 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 ; OK ;============================================================================= LCDSDDA IORLW 0x080 ; Function set CALL LCDPUTCMD RETURN ;============================================================================= ; LCDPUTCHAR ; Sends character to LCD ; Required character must be in W ; OK ;============================================================================= 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 MOVF LCD_TEMP, W ANDLW 0xF0 ; Get upper nibble MOVWF CTEMP ; Save nibble MOVF LCD_DATA, W ; Save contents of LCD_DATA ANDLW 0x0F IORWF CTEMP, W ; Affect only upper nibble of LCD_DATA MOVWF LCD_DATA ; Send data to LCD CALL LCD_ENABLE SWAPF LCD_TEMP, W ANDLW 0xF0 ; Get lower nibble MOVWF CTEMP ; Save nibble MOVF LCD_DATA, W ; Save contents of LCD_DATA ANDLW 0x0F IORWF CTEMP, W ; Affect only upper nibble of LCD_DATA MOVWF LCD_DATA CALL LCD_ENABLE RETURN ;============================================================================= ; LCDPUTCMD ; Sends command to LCD ; Required command must be in W ; OK ;============================================================================= 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 MOVF LCD_TEMP, W ANDLW 0xF0 ; Get upper nibble MOVWF CTEMP ; Save nibble MOVF LCD_DATA, W ; Save contents of LCD_DATA ANDLW 0x0F IORWF CTEMP, W ; Affect only upper nibble of LCD_DATA MOVWF LCD_DATA ; Send data to LCD CALL LCD_ENABLE SWAPF LCD_TEMP, W ANDLW 0xF0 ; Get lower nibble MOVWF CTEMP ; Save nibble MOVF LCD_DATA, W ; Save contents of LCD_DATA ANDLW 0x0F IORWF CTEMP, W ; Affect only upper nibble of LCD_DATA MOVWF LCD_DATA ; Send data to LCD CALL LCD_ENABLE 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 ;***************************************************************************** SECWAIT MOVLW D'50' ; 100 times 15 = 1500 msec MOVWF COUNT SECLOOP MOVLW 0x01E ; 15 msec CALL X_DELAY500 DECFSZ COUNT, F GOTO SECLOOP SECLOOPEND RETURN ;***************************************************************************** ;***************************************************************************** ; I2C routines ;***************************************************************************** IN_8574: ; reads inputs on specified 8574. returns result in I_8574 CALL I2CSTART ;BCF STATUS, C ; clear carry ;RLF DEVICE_ADR, W ; left shift DEVICE_ADR, result to W I;ORLW 41H MOVLW ADR8574R MOVWF O_BYTE ; output 0100AAA1 for read CALL OUT_BYTE ; 210 CALL NACK CALL IN_BYTE ; fetch the byte on i2c bus CALL NACK CALL STOP MOVF I_BYTE, W MOVWF I_8574 ; return result in I_8574 RETURN OUT_8574: ; outputs O_8574 on addressed 8574 CALL I2CSTART ;BCF STATUS, C ; clear carry ;RLF DEVICE_ADR, W ; left shift DEVICE_ADR, result to W ;IORLW 40H MOVLW ADR8574W MOVWF O_BYTE ; output 0100AAA0 for write CALL OUT_BYTE ; 210 CALL NACK MOVF O_8574, W IORWF DIRS, W MOVWF O_BYTE ; output O_8574 | dirs CALL OUT_BYTE CALL NACK CALL STOP RETURN ; The following routines are low level I2C routines applicable to most ; interfaces with I2C devices. IN_BYTE ; read byte on i2c bus CLRF I_BYTE MOVLW .8 MOVWF _N ; set index to 8 CALL HIGH_SDA ; be sure SDA is configured as input ;CALL DELAY_SHORT ;!!!!! IN_BIT CALL HIGH_SCL ; clock high ;CALL DELAY_SHORT ;!!!!! BTFSS PORTB, SDA ; test SDA bit GOTO IN_ZERO GOTO IN_ONE IN_ZERO BCF STATUS, C ; clear any carry RLF I_BYTE, F ; i_byte = i_byte << 1 | 0 GOTO CONT_IN IN_ONE BCF STATUS, C ; clear any carry RLF I_BYTE, F INCF I_BYTE, F ; i_byte = (i_byte << 1) | 1 GOTO CONT_IN CONT_IN CALL LOW_SCL ; bring clock low ;CALL DELAY_SHORT ;!!!!! DECFSZ _N, F ; decrement index GOTO IN_BIT RETURN ;;;;;; OUT_BYTE: ; send o_byte on I2C bus MOVLW .8 MOVWF _N OUT_BIT: BCF STATUS,C ; clear carry RLF O_BYTE, F ; left shift, most sig bit is now in carry BTFSS STATUS, C ; if one, send a one GOTO OUT_ZERO GOTO OUT_ONE OUT_ZERO: CALL LOW_SDA ; SDA at zero CALL CLOCK_PULSE CALL HIGH_SDA GOTO OUT_CONT OUT_ONE: CALL HIGH_SDA ; SDA at logic one CALL CLOCK_PULSE GOTO OUT_CONT OUT_CONT: DECFSZ _N, F ; decrement index GOTO OUT_BIT RETURN ;;;;;; NACK: ; bring SDA high and clock CALL HIGH_SDA CALL CLOCK_PULSE RETURN ACK: CALL LOW_SDA CALL CLOCK_PULSE RETURN I2CSTART: CALL LOW_SCL CALL HIGH_SDA CALL HIGH_SCL CALL LOW_SDA ; bring SDA low while SCL is high CALL LOW_SCL RETURN STOP: CALL LOW_SCL CALL LOW_SDA CALL HIGH_SCL CALL HIGH_SDA ; bring SDA high while SCL is high CALL LOW_SCL RETURN CLOCK_PULSE: ; SCL momentarily to logic one CALL HIGH_SCL CALL LOW_SCL RETURN HIGH_SDA: ; high impedance by making SDA an input BSF STATUS, RP0 ; bank 1 BSF TRISB, SDA ; make SDA pin an input BCF STATUS, RP0 ; back to bank 0 CALL DELAY_SHORT RETURN LOW_SDA: BCF PORTB, SDA BSF STATUS, RP0 ; bank 1 BCF TRISB, SDA ; make SDA pin an output BCF STATUS, RP0 ; back to bank 0 CALL DELAY_SHORT RETURN HIGH_SCL: BSF STATUS, RP0 ; bank 1 BSF TRISB, SCL ; make SCL pin an input BCF STATUS, RP0 ; back to bank 0 CALL DELAY_SHORT RETURN LOW_SCL: BCF PORTB, SCL BSF STATUS, RP0 ; bank 1 BCF TRISB, SCL ; make SCL pin an output BCF STATUS, RP0 ; back to bank 0 CALL DELAY_SHORT RETURN DELAY_SHORT: ; provides nominal 25 usec delay MOVLW .5 MOVWF LOOP2 DELAY_SHORT_1: NOP DECFSZ LOOP2, F GOTO DELAY_SHORT_1 RETURN DELAY_LONG: ; provide 250 ms delay MOVLW .250 MOVWF LOOP1 OUTTER: MOVLW .110 ; close to 1.0 msec delay when set to .110 MOVWF LOOP2 INNER: NOP NOP NOP NOP NOP NOP DECFSZ LOOP2, F ; decrement and leave result in LOOP2 ; skip next statement if zero GOTO INNER DECFSZ LOOP1, F GOTO OUTTER RETURN ;***************************************************************************** ;Routines end here. ;***************************************************************************** ;***************************************************************************** ;Eeprom contents follows. ;***************************************************************************** ; eeprom contents: a maximum of eight frequency settings can be stored, ; each setting consisting of a 4-character ; frequency string (example: 137.5 MHZ), ; two tuner programming bytes for HRTP and ; two tuner programming bytes for PDUS mode ; ; eeprom is pre-filled with four frequency settings. ; ; Programming bytes have been calculated assuming ; fstep=62.5 kHz (4Mhz xtal in 1216) org 0x2100 data 0x31 ; location 00 ;setting 0: 134 MHz data 0x33 data 0x34 data 0x30 data 0x0A ; dec. 10 data 0xAB ; dec. 171 data 0x0A ; dec. 10 data 0xCE ; dec. 206 data 0x31 ; location 08 ;setting 0: 137.5 MHz data 0x33 data 0x37 data 0x35 data 0x0A ; dec. 10 data 0xE3 ; dec. 227 data 0x0B ; dec. 11 data 0x06 ; dec. 6 data 0x31 ; location 16 ;setting 1: 141 MHz data 0x34 data 0x31 data 0x30 data 0x0B ; dec. 11 data 0x1B ; dec. 27 data 0x0B ; dec. 11 data 0x3E ; dec. 62 data 0x31 ; location 24 ;setting 4: 150 MHz data 0x35 data 0x30 data 0x30 data 0x0B ; dec. 11 data 0xAB ; dec. 171 data 0x0B ; dec. 11 data 0xCE ; dec. 206 ;***************************************************************************** ;End of eeprom contents ;***************************************************************************** END