;************************************************************************** ;* RACAL RA1792 DISPAY DRIVER FOR 16*2 DISPLAYS * ;************************************************************************** ;************************************************************************** ;* (C)Display Code DAVID SCHOFIELD, Capture Code MIKE STIRLING 2009 * ;* All rights reserved * ;************************************************************************** ;* Hardw. Rev: 2 Softw. Rev: 6.03 * ;* OSC.......: HS 20MHz Max. POWER.....: 5V DC * ;************************************************************************** ;############################################################################################################ ;# Hardware Configured As Follows # ;# 2x 16x2 displays with control lines on PORTA, running in 4 BIT mode. LCD Data on PORTB 0 - 4. # ;# Both displays connected in parallel on PORTB except for the control lines on PORTA # ;# Racal receiver ADDRESS bus on PORTC 0 - 4 # ;# Racal receiver DATA bus on PORTD 0 - 7 # ;# Number display strobe connected to PSP INT pin 9 PORT E1. E2 Pin 10 GND. E0 pulled up via 4k7 # ;############################################################################################################ org 0x0000 goto main org 0x0004 goto interrupt LIST NOLIST ;========================================================================== ; ; Verify Processor ; ;========================================================================== IFNDEF __16F877A MESSG "Processor-header file mismatch. Verify selected processor." ENDIF ;========================================================================== ; ; Register Definitions ; ;========================================================================== W EQU H'0000' F EQU H'0001' ;----- Register Files------------------------------------------------------ INDF EQU H'0000' PCL EQU H'0002' STATUS EQU H'0003' FSR EQU H'0004' PORTA EQU H'0005' PORTB EQU H'0006' PORTC EQU H'0007' PORTD EQU H'0008' PORTE EQU H'0009' PCLATH EQU H'000A' INTCON EQU H'000B' PIR1 EQU H'000C' TRISA EQU H'0085' TRISB EQU H'0086' TRISC EQU H'0087' TRISD EQU H'0088' TRISE EQU H'0089' PIE1 EQU H'008C' PSPMODE EQU H'0004' CMCON EQU H'009C' ADCON1 EQU H'009F' ;----- PIE1 Bits ---------------------------------------------------------- PSPIE EQU H'0007' ;----- INTCON Bits -------------------------------------------------------- GIE EQU H'0007' PEIE EQU H'0006' ;----- PIR1 Bits ---------------------------------------------------------- PSPIF EQU H'0007' ;----- STATUS Bits -------------------------------------------------------- RP1 EQU H'0006' RP0 EQU H'0005' Z EQU H'0002' C EQU H'0000' ;-------Configuration Bits------------------- _CP_OFF EQU H'3FFF' _LVP_OFF EQU H'3F7F' _BODEN_ON EQU H'3FFF' _PWRTE_ON EQU H'3FF7' _WDT_OFF EQU H'3FFB' _HS_OSC EQU H'3FFE' LIST __CONFIG _BODEN_ON & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _HS_OSC ERRORLEVEL 0, -302 ;suppress bank selection messages ;----- CUSTOM Bits -------------------------------------------------------- status_save EQU 0x20 ;used to store the status reg value during interrupt w_save EQU 0x22 ;used to store the w reg during interrupt routine digitbase EQU 0x30 ;These files store the current state of the display digits digit0 EQU 0x30 ;when the PSP interupt is activated. These are thw raw HEX digit1 EQU 0x31 ;values read straight from the Racal DATA bus PORTD digit2 EQU 0x32 digit3 EQU 0x33 digit4 EQU 0x34 digit5 EQU 0x35 digit6 EQU 0x36 digit7 EQU 0x37 digit8 EQU 0x38 digit9 EQU 0x39 digita EQU 0x3a digitb EQU 0x3b digitc EQU 0x3c digitd EQU 0x3d digite EQU 0x3e digitf EQU 0x3f LCD_CTRL Equ PORTA ;define PORTA as LCD control LCD_DATA Equ PORTB ;define PORTB as LCD data RACAL_NDA Equ PORTC ;define PORTC as Racal Number Display Address RACAL_DATA Equ PORTD ;define PORTD as Racal Display DATA LCD_RS Equ 0x01 ;LCD handshake lines RS line on PORTA 1 LCD_E1 Equ 0x02 ;display enable 1 on PORTA 2 LCD_E2 Equ 0x03 ;display enable 2 on PORTA 3 cblock 0x40 ;start of general purpose registers count ;used in looping routines count1 ;used in delay routine counta ;used in delay routine countb ;used in delay routine templcd ;temp store for 4 bit mode lcdaddress ;bit 0 set = LCD2, bit 0 clear = LCD1 hold ;file used in hex to ASCII convesion endc ;############################################################ ; End of Equates, setup ports and interupts # ;############################################################ main BCF STATUS,RP0 ;DISSABLE A TO D and comparitors ON F877A BCF STATUS,RP1 CLRF PORTA BSF STATUS,RP0 MOVLW 0X06 MOVWF ADCON1 MOVLW 0XCF MOVWF TRISA movlw 0x07 movwf CMCON ;turn comparators off SetPorts bsf STATUS,RP0 ;select bank 1 movlw 0x00 movwf TRISA ;set PORTA as output movwf TRISB ;set PORTB as output movlw 0x0F movwf TRISC ;set PORTC 0 - 3 as inputs these are the NDA (number display address) bits movlw 0xFF ;refered to in the RA1792 manual as N0 - N3 movwf TRISD ;set PORTD as inputs this is the RA1792 DATA Bus movlw (1 << PSPMODE) | (1 << 2) | (1 << 1) | (1 << 0) ;set PORTD to PSP mode movwf TRISE bsf PIE1,PSPIE ;enable parallel slave port interupt bcf STATUS,RP0 ;select bank 0 movlw (1 << GIE) | (1 << PEIE) movwf INTCON ;################################################## ;# MAIN PROGRAM START # ;################################################## clrf count ;clear all ports so we start at a known point clrf LCD_CTRL clrf LCD_DATA clrf RACAL_NDA clrf RACAL_DATA clrf PORTE call Delay100 ;wait for LCD to settle call LCD_Init ;setup LCD call LCD_Line1 call frqu_header ;start off with display 1 showing "Frequency Chan" on line 1 call LCD_Line1 call bw_header ;start off with display 2 showing "Bandwidth BFO" on line 1 main_loop call LCD1 call LCD_Cmd call LCD_Line2 ;get display data from digit xx files, convert to ASCII and output to LCD movfw digit8 call hex_ascii call LCD_Char movfw digit7 call hex_ascii call LCD_Char ; movlw 0x2e ;To place a . after the Mhz include these lines ; call LCD_Char movfw digit6 call hex_ascii call LCD_Char movfw digit5 call hex_ascii call LCD_Char movfw digit4 call hex_ascii call LCD_Char movlw 0x2e ;Place a . on the display after the Khz point call LCD_Char movfw digit3 call hex_ascii call LCD_Char movfw digit2 call hex_ascii call LCD_Char movfw digit1 call hex_ascii call LCD_Char Chan_dis movlw 0x20 ;Place a space between freq and chan data call LCD_Char movfw digita ;Output Channel data call hex_ascii call LCD_Char movfw digit9 call hex_ascii call LCD_Char BW_dis call LCD2 ;output Bandwidth data call LCD_Line2 ;Place a space betfore the BFO frequency movlw 0x20 call LCD_Char movfw digit0 call hex_ascii call LCD_Char movlw 0x2e ;Place a . to seperate the two digits call LCD_Char movfw digitf call hex_ascii call LCD_Char movlw 0x4b ;Khz notation after Bandwidth 4B 68 7A is hex for Khz call LCD_Char movlw 0x68 call LCD_Char movlw 0x7a call LCD_Char spaces movlw 0x20 ;Place 2 spaces between bandwidth and BFO call LCD_Char movlw 0x20 call LCD_Char BFO_dis movfw digite ;output BFO ofset data call hex_ascii call LCD_Char movlw 0x2e ;Place a . to seperate the two digits call LCD_Char movfw digitd call hex_ascii call LCD_Char movfw digitc call hex_ascii call LCD_Char movlw 0x4b ;Khz notation after BFO 4B 68 7A is hex for Khz call LCD_Char movlw 0x68 call LCD_Char movlw 0x7a call LCD_Char goto main_loop ;endless loop ; ##################################################################### ; # Main Program Ends. Subroutines and text tables start # ; ##################################################################### frequency addwf PCL, f retlw 'F' retlw 'r' retlw 'e' retlw 'q' retlw 'u' retlw 'e' retlw 'n' retlw 'c' retlw 'y' retlw ' ' RETLW 'C' RETLW 'h' RETLW 'a' RETLW 'n' retlw 0x00 bandwidth addwf PCL, f retlw 'B' retlw 'a' retlw 'n' retlw 'd' retlw 'w' retlw 'i' retlw 'd' retlw 't' retlw 'h' retlw ' ' retlw ' ' retlw 'B' retlw 'F' retlw '0' retlw 0x00 ; ######################################################################################################## ; # Title subroutines. These are used to display static info on line 1 of displays 1 & 2 # ; ######################################################################################################## frqu_header clrf count ;set counter register to zero freq_title call LCD1 ;display this message on display 1 line 1 movf count, w ;put counter value in W call frequency ;get a character from the text table xorlw 0x00 ;is it a zero? btfsc STATUS, Z goto to_main call LCD_Char incf count, f goto freq_title to_main retlw 0x00 bw_header clrf count ;set counter register to zero bw_title call LCD2 ;display this message on display 2 line 1 movf count, w ;put counter value in W call bandwidth ;get a character from the text table xorlw 0x00 ;is it a zero? btfsc STATUS, Z goto to_main2 call LCD_Char incf count, f goto bw_title to_main2 retlw 0x00 ; ############################################# ; # LCD routines # ; ############################################# LCD1 movlw 0x00 ;set display to 1. lcdaddress is read by pulse_e movwf lcdaddress retlw 0x00 LCD2 movlw 0x01 ;set display to 2. lcdaddress is read by pulse_e movwf lcdaddress retlw 0x00 ; ######################################################################################################## ; # Initialise the displays done twice to enable different setup on each display if needed # ; ######################################################################################################## LCD_Init call LCD1 ;initialise display no 1 movlw 0x20 ;Set 4 bit mode call LCD_Cmd movlw 0x28 ;Set display shift call LCD_Cmd movlw 0x06 ;Set display character mode call LCD_Cmd movlw 0x0c ;Set display on/off and cursor command call LCD_Cmd call LCD_Clr ;clear display call LCD2 ;initialise display no 2 movlw 0x20 ;Set 4 bit mode call LCD_Cmd movlw 0x28 ;Set display shift call LCD_Cmd movlw 0x06 ;Set display character mode call LCD_Cmd movlw 0x0c ;Set display on/off and cursor command call LCD_Cmd call LCD_Clr ;clear display retlw 0x00 ; ##################################### ; # command output routine # ; ##################################### LCD_Cmd movwf templcd swapf templcd, w ;send upper nibble andlw 0x0f ;clear upper 4 bits of W movwf LCD_DATA bcf LCD_CTRL, LCD_RS ;RS line to 0 call Pulse_e ;Pulse the E line high movf templcd, w ;send lower nibble andlw 0x0f ;clear upper 4 bits of W movwf LCD_DATA bcf LCD_CTRL, LCD_RS ;RS line to 0 call Pulse_e ;Pulse the E line high call Delay10 retlw 0x00 ; ##################################### ; # character output routine # ; ##################################### LCD_Char movwf templcd swapf templcd, w ;send upper nibble andlw 0x0f ;clear upper 4 bits of W movwf LCD_DATA bsf LCD_CTRL, LCD_RS ;RS line to 1 call Pulse_e ;Pulse the E line high movf templcd, w ;send lower nibble andlw 0x0f ;clear upper 4 bits of W movwf LCD_DATA bsf LCD_CTRL, LCD_RS ;RS line to 1 call Pulse_e ;Pulse the E line high call Delay1 retlw 0x00 ; ############################################################################# ; # LCD Cursor CTRL Routines. Not all used but left in for final setup # ; ############################################################################# LCD_Line1 movlw 0x80 ;move to 1st row, first column call LCD_Cmd retlw 0x00 LCD_Line2 movlw 0xc0 ;move to 2nd row, first column call LCD_Cmd retlw 0x00 LCD_Line1W addlw 0x80 ;move to 1st row, column W call LCD_Cmd retlw 0x00 LCD_Line2W addlw 0xc0 ;move to 2nd row, column W call LCD_Cmd retlw 0x00 LCD_CurOn movlw 0x0d ;Set display on/off and cursor command call LCD_Cmd retlw 0x00 LCD_CurOff movlw 0x0c ;Set display on/off and cursor command call LCD_Cmd retlw 0x00 LCD_Clr movlw 0x01 ;Clear display call LCD_Cmd retlw 0x00 ; ##################################### ; # HEX to ASCII conversion # ; ##################################### hex_ascii andlw 0x0f ;mask off bottom four bits movwf hold ;store copy of hex digit sublw 0x09 ;subtract w from 1 less than 0x0a btfss STATUS,C ;carry flag set if w < 0x0a goto add37 goto add30 add37 movf hold,w ;get hex digit addlw 0x37 return ;continue with ascii in w add30 movf hold,w ;get hex digit addlw 0x30 return ;continue with ascii in w ; ################################# ; # Delay routines. # ; ################################# Delay100 movlw d'100' ;delay 100mS goto d0 Delay50 movlw d'50' ;delay 50mS goto d0 Delay20 movlw d'20' ;delay 20mS goto d0 Delay10 movlw d'10' ;delay 10mS goto d0 Delay5 movlw d'05' ;delay 5mS goto d0 Delay1 movlw 0x01 ;delay 1.000 ms (4 MHz clock) d0 movwf count1 d1 movlw 0xC7 ;delay 1mS movwf counta movlw 0x01 movwf countb Delay_0 decfsz counta, f goto $+2 decfsz countb, f goto Delay_0 decfsz count1 ,f goto d1 retlw 0x00 ; ############################################################# ; # Pulse routines for the E line of displays 1 & 2 # ; ############################################################# Pulse_e btfss lcdaddress, 0 ;check if data is on display 1 or 2 call Pulse1 ;if it's on display 1 call Pulse1 btfss lcdaddress, 0 ;make sure we return without calling Pulse2 retlw 0x00 call Pulse2 ;if it's on display2 call Pulse2 retlw 0x00 Pulse1 bsf LCD_CTRL, LCD_E1 ;toggle the E line of display 1 nop bcf LCD_CTRL, LCD_E1 nop retlw 0x00 Pulse2 bsf LCD_CTRL, LCD_E2 ;toggle the E line of display 2 nop bcf LCD_CTRL, LCD_E2 nop retlw 0x00 ;######################################################################################################## ;# Interupt service routine triggered by -ve going pulse on PSP Interupt pin PORTE 1 # ;######################################################################################################## interrupt movwf w_save ;A write has occurred to the parallel slave port swapf STATUS,w ;save existing state of the status and program counter regs clrf STATUS movwf status_save movf PORTC,w ;least significant nibble is address andlw 0x0f addlw digitbase movwf FSR ;setup indirect addressing movf PORTD,w ;get segment data from port D movwf INDF ;save to indirectly addressed file register bcf PIR1,PSPIF ;clear interupt flag swapf status_save,w ;Restore STATUS reg and return from interrupt movwf STATUS swapf w_save,f swapf w_save,w retfie end