It's written in ASM..
#include <p16f877.inc>
errorlevel -203, -205 ,-207
;**************************************************************************************
;** THIS DEFINITIONS CAN BE CHANGED BY USER
;**
;** REMEMBER THAT KS0108_data and its associated TRIS register SHOULD BE A COMPLETE 8 BIT
;** PORT
;** REGISTER ASSOCIATED WHITH E, RW, RS SHALL HAVE THEIR TRIS DEFINITION
;**
;**
;**
;**
;**************************************************************************************
#define KS0108_data PORTD ; LCD data bits (port wired to D0-D7) - in this case port D
#define KS0108_tris TRISD ; LCD data direction - Thisi is TRISS register associated to KS0108_data port
#define KS0108_E PORTC, 6 ; LCD E clock (pin wired to E line)
#define KS0108_RW PORTC, 5 ; LCD read/write line (pin wired to RW line)
#define KS0108_RS PORTC, 4 ; LCD register select line (pin wired to RS line)
#define KS0108_E_DIR TRISC, 6 ; E line associated TRIS bit
#define KS0108_RW_DIR TRISC, 5 ; RW line associated TRIS bit
#define KS0108_RS_DIR TRISC, 4 ; RS line associated TRIS bit
#define KS0108_CS1 PORTB,0 ; CS1 line (pin wired to CS1 line)
#define KS0108_CS2 PORTB,1 ; CS2 line (pin wired to CS2 line)
#define KS0108_CS1_DIR TRISB,0 ; CS1 line associated TRIS bit
#define KS0108_CS2_DIR TRISB,1 ; CS2 line associated TRIS bit
#define MCUCLK Nop4 ; delay time for data settiling: select Nop4 for CPUCLK > = 20 MHZ else select Nop0
udata
KS0108_out res 1 ;var to put in data to be displayed
KS0108_X res 1 ; X pos to turn on pixel
KS0108_Y res 1 ; Y POS TO TURN ON PIXEL
KS0108_COL res 1 ; RAW
KS0108_RAW res 1 ; COL
KS0108_busyflag res 1 ; status flags (local)
KS0108_IN res 1 ; data input from KS0108
temp res 1
temp1 res 1
x res 1
y res 1
timer res 1
;******************** global vars to create library
global KS0108_out ;data to send to KS0108
global KS0108_X ;X pixel pos (0 o 127)
global KS0108_Y ;Y pixel pos (0 to 63)
global KS0108_COL ; Coloumn (o to 7)
global KS0108_RAW ;raw (0 to 127) - chip select done by program
global KS0108_IN ; data read from KS0108
;****************** reset vector
org 0x0000
goto main
org 0x0004
code
retfie
; **************** program example
main
call KS0108init ; inits display
;***** fills display whith byte pattern from 255 to 1
movlw 0xff
movwf KS0108_out ; puts value 0xff in KS0108_out (var used to put data on
main1
call KS0108fill
decfsz KS0108_out,F
goto main1
;traces a line from (127,63) to (1,0)
movlw .127
movwf KS0108_X
traceline
movf KS0108_X,W
rrf KS0108_X,W
bcf STATUS,C
movwf KS0108_Y
call KS0108_pixon
decfsz KS0108_X,F
goto traceline
main2
goto main2 ; infinite loop
;**************************** end program example
;****************** DRIVER SUBROUTINES
;****************** init ports and values
KS0108init
banksel KS0108_tris ; sets ports TRIS registers
bcf KS0108_E_DIR
bcf KS0108_RW_DIR
bcf KS0108_RS_DIR
bcf KS0108_CS1_DIR
bcf KS0108_CS2_DIR
clrf KS0108_tris
banksel KS0108_data ; reset to 0 all ports values
bcf KS0108_E
bcf KS0108_RW
bcf KS0108_RS
bcf KS0108_CS1
bcf KS0108_CS2
clrf KS0108_data
;********************* selects and initailizes chip 1
bsf KS0108_CS1
bcf KS0108_CS2
movlw 0x3f ; 0xef is init command
call KS0108commandW ; KS0108commandw is a part of KS0108command instruction and doesn't need data to be
;stored in KS0108_out, but uses data in W register
; it's used by internal driver routines
movlw 0xc0 ;0xc0 sets start display line to 0
call KS0108commandW
;******************** selects and initailizes chip2 (as for chip 1)
bcf KS0108_CS1
bsf KS0108_CS2
movlw 0x3f
call KS0108commandW
movlw 0xc0
call KS0108commandW
bcf KS0108_CS1
bcf KS0108_CS2
;******************** clears GLCD (fill whith 0x00)
movlw 0x00
movwf KS0108_out ; KS0108_out is var used to output data bytes to glcd, now it's set to 0
call KS0108fill ; executes "fill" instruction
return
; KS0108fill routine ***************** fill GLCD whith data stored in KS0108_out
KS0108fill
BSF KS0108_CS1
BCF KS0108_CS2
fill_1 ;here starts loop 1 that will be repeated one time per chip
MOVLW 0x08 ; init raw loop from 8 to 1 note thata x and y are internal and not global vars
MOVWF y
fill_2
decf y,W ;as i'm countig from 8 to 1, but I need selecr raws from 7 to 0, I decrement y and ;put it in w
ADDLW 0xB8 ; to select a raw, command is 0xb8 + raw number
CALL KS0108commandW ; sends command to select raw
MOVLW 0x40 ;command to selects a coloumn is 0x40 + coloumn number, I start from 0
CALL KS0108commandW ; send command to select coloumn
MOVWF x
fill_3
movf KS0108_out ,W
CALL KS0108writeW ;displays on selected raw, coloumn data stored in KS0108_out
;decrements and goes on displaying data ( I don't need to select coloumns every time
;as KS0108 auto increments coloumn number every write operation)
DECFSZ x,F ; repeats fill_3 64 times ( from 0 to 63)
GOTO fill_3
DECFSZ y,F ; repeats fill_2 8 tines (for coloumns from 7 to 0)
GOTO fill_2
BTFSS KS0108_CS1 ;if chip 2 is selected (chip 1 cleared) ends
GOTO fillend
MOVLW 0xC0 ;0xC0 is "home command"
CALL KS0108commandW
BCF KS0108_CS1 ;else selects chip 2
BSF KS0108_CS2
GOTO fill_1 ;repeats loop
fillend
MOVLW 0xC0
CALL KS0108commandW
BCF KS0108_CS1
BCF KS0108_CS1
RETURN
global KS0108fill
;****************** Write command to KS0108
KS0108command
movf KS0108_out,W
KS0108commandW ; procedure using data in WREG
bcf KS0108_RS ;clears RS line
bcf KS0108_RW ;clears RW line
bsf KS0108_E ;Enable high to lock command lines status
movwf KS0108_data ;data on D0-D7
call MCUCLK ; wait KS0108 data settiling time
bcf KS0108_E ; Enable low
nop ; 1 cycle settiling time
call KS0108_ready ; check busy flag ( if clock is less than 12 MHz it shall be omitted)
return
global KS0108command
;***************** write data to KS0108 (for comments wiew KS0108command )
KS0108write
movf KS0108_out,W
KS0108writeW
bsf KS0108_RS
bcf KS0108_RW
bsf KS0108_E
movwf KS0108_data
call MCUCLK
bcf KS0108_E
bcf KS0108_RS
call KS0108_ready
return
global KS0108write
;****************** read data from KS0108 and put it in KS0108_IN
KS0108_read ; read from display routine
bsf KS0108_RS ; RS and RW lines must be ""HIGH"
bsf KS0108_RW
bsf KS0108_E ; Enable high to lock command lines
call MCUCLK ; waits .....
bcf KS0108_E ;Enable line low
call KS0108_ready ; waits display to be ready
bsf KS0108_RW ;Read command shall be repeated 2 times as 1st time KS0108 puts data on latch and
;2nd time puts them on D0-D7 (1st time read is a "dummy" read)
bsf KS0108_RS
bsf KS0108_E
banksel KS0108_tris ; make D0-D7 port an input
movlw 0xff
movwf KS0108_tris
banksel KS0108_data
movf KS0108_data,W ; reads data
movwf KS0108_IN ; puts data on KS0108_IN
banksel KS0108_tris
clrf KS0108_tris
banksel KS0108_data
bcf KS0108_E
bcf KS0108_RW
bcf KS0108_RW
call KS0108_ready ; check busy flag ( if clock is less than 12 MHz it could be omitted)
return
global KS0108_read
;************ check KS0108 busy flag ( checks if GLCD is ready)
; note that KS0108 will ALWAYS answer to this command, also if it's doing something else
;***************************** MORE COMMENTS NEXT TIME.....
KS0108_ready
movwf temp1
clrf KS0108_data
readyflag1
bcf KS0108_RS
bsf KS0108_RW
bsf KS0108_E
bsf STATUS,RP0
movlw 0xff
movwf KS0108_tris
bcf STATUS,RP0
movf KS0108_data
movwf KS0108_busyflag
bsf STATUS,RP0
clrf KS0108_data
bcf STATUS,RP0
call Nop4
bcf KS0108_E
btfss KS0108_busyflag,7
goto readyflag1
bcf KS0108_RW
movf temp1
return
; wait cycle (quite stupid way, but timigs are perfect)
Nop20
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
Nop8
nop
nop
nop
nop
Nop4
nop
nop
nop
nop
Nop0
return
;************** turn on a pixel x = KS0108_X y= KS0108_Y
KS0108_pixon
call KS0108_pos ; selects raw, coloumn
call KS0108_read ;reads data already displayed
movf KS0108_Y,W
andlw 0x07
call pixtable
iorwf KS0108_IN
call KS0108_posX
movf KS0108_IN,W
call KS0108writeW
return
global KS0108_pixon
;************** turn off a pixel x = KS0108_X y= KS0108_Y
KS0108_pixoff
call KS0108_pos
call KS0108_read
movf KS0108_Y,W
andlw 0x07
call pixtable
movwf temp
negf temp,W
andwf KS0108_IN,W
call KS0108_posX
movf KS0108_IN,W
call KS0108writeW
return
global KS0108_pixoff
; ********** reads KS0108_X and KS0108_Y and selects right chip, raw, coloumn
KS0108_pos
btfss KS0108_X,6
goto KS0108_pos1
bcf KS0108_CS1
bsf KS0108_CS2
goto KS0108_pos2
KS0108_pos1
bsf KS0108_CS1
bcf KS0108_CS2
KS0108_pos2
movf KS0108_Y,W
movwf temp
rrf temp,F
bcf STATUS,C
rrf temp,F
bcf STATUS,C
rrf temp,W
iorlw 0xb8
call KS0108commandW
KS0108_posX
movf KS0108_X,W
iorlw 0x40
call KS0108commandW
return
; ********** reads KS0108_RAW and KS0108_COL and selects chip, raw, coloumn
KS0108_pos
btfss KS0108_COL,6
goto KS0108_pos1
bcf KS0108_CS1
bsf KS0108_CS2
goto KS0108_pos2
KS0108_pos1
bsf KS0108_CS1
bcf KS0108_CS2
KS0108_pos2
movf KS0108_RAW,W
iorlw 0xb8
call KS0108commandW
movf KS0108_COL,W
iorlw 0x40
call KS0108commandW
return
;******************** part of pixon... selects pixel on byte
pixtable
addwf PCL,F ;add offset to pc to
retlw 0x01
retlw 0x02
retlw 0x04
retlw 0x08
retlw 0x10
retlw 0x20
retlw 0x40
retlw 0x80
end
I can't grab the code for some reason...
Can you post it instead?
Ian
;Config register bits (all PIC TOOLKIT MK2 defaults except for oscillator)
; CP1 CP0 DBG NIL WRT CPD LVP BOR CP1 CP0 POR WDT OS1 OS0
; 1 1 1 1 1 1 0 0 1 1 0 0 1 0
;N.B. Logic 1/0 do NOT necessarily mean that the function is On/Off
;respectively - refer to PIC '87 data sheet.
#DEFINE PAGE0 BCF $03,5 ;STATUS bit 5
#DEFINE PAGE1 BSF $03,5 ;STATUS bit 5
#DEFINE BLOCK0 BCF $03,7 ;STATUS bit 7
#DEFINE BLOCK1 BSF $03,7 ;STATUS bit 7
;BLOCK0 used for indirect addressing to BANKS 0 & 1, clearing IRP bit
;BLOCK1 used for indirect addressing to BANKS 2 & 3, setting IRP bit
INDF: .EQU $00 ;page 0, 1, 2, 3
OPTION: .EQU $01 ;page 1, 3
PCL: .EQU $02 ;page 0, 1, 2, 3
STATUS: .EQU $03 ;page 0, 1, 2, 3
FSR: .EQU $04 ;page 0, 1, 2, 3
PORTA: .EQU $05 ;page 0
TRISA: .EQU $05 ;page 1
PORTB: .EQU $06 ;page 0, 2
TRISB: .EQU $06 ;page 1, 3
PORTC: .EQU $07 ;page 0
TRISC: .EQU $07 ;page 1
PORTD: .EQU $08 ;page 0
TRISD: .EQU $08 ;page 1
PORTE: .EQU $09 ;page 0
TRISE: .EQU $09 ;page 1
INTCON: .EQU $0B ;page 0, 1, 2, 3
ADRESH: .EQU $1E ;page 0
ADRESL: .EQU $1E ;page 1
ADCON0: .EQU $1F ;page 0
ADCON1: .EQU $1F ;page 1
;*** VARIABLES ONLY ACCESSABLE THROUGH BLOCK 0, PAGE 0 *******
ADC0: .EQU $20 ; ADC storage set, extends to $5F (64 samples)
TIMOUT0: .EQU $60 ; sync time-out counter LSB
TIMOUT1: .EQU $61 ; sync time-out counter MSB
FOSC: .EQU $62 ; ADC sampling rate value
FRQCNT1: .EQU $63 ; freq counter LSB
FRQCNT2: .EQU $64 ; freq counter MSB
STORE: .EQU $65 ; general store used in freq counter
STORE1: .EQU $66 ; general store used in freq counter
STORE2: .EQU $67 ; general store used in freq counter
MARK1: .EQU $68 ; hi-lo flag for freq counter
MARK2: .EQU $69 ; hi-lo flag for freq counter
MIN: .EQU $6A ; min val store for volts calc
MAX: .EQU $6B ; max val store for volts calc
ADCTEMP: .EQU $6C ; temp val used during data config for LCD
SWITCH: .EQU $6D ; switch status flags
spare6E: .EQU $6E ; spare
spare6F: .EQU $6F ; spare
;******** VARIABLES ACCESSED THROUGH ALL PAGES & BLOCKS ********
LOOPA: .EQU $70 ; waveform byte sample counter
LOOPB: .EQU $71 ; general loop used in SETUP
LOOPC: .EQU $72 ; general loop used in SETUP
LOOPD: .EQU $73 ; column counter
LOOPE: .EQU $74 ; sample/line counter
ADCADR: .EQU $75 ; ADC block address
CLKCNT: .EQU $76 ; counter for PAUSE val
ADRLSB: .EQU $77 ; LCD low address
ADRMSB: .EQU $78 ; LCD high address
ATTRIB: .EQU $79 ; temp store used in LCD output routines
TEMPA: .EQU $7A ; temp store used in LCD output routines
COLUMN: .EQU $7B ; column length holder
PEAKLO: .EQU $7C ; waveform sample min for graph
PEAKHI: .EQU $7D ; waveform sample max for graph
LOBIT: .EQU $7E ; rotating bit for 8-bit column
spare7F: .EQU $7F ; spare
;******* variables in BLOCK 0, PAGE 1 ********
ADC1: .EQU $A0 ; ADC storage set for 2nd SET of 64 samples
; extends to $EF
;******* variables in BLOCK 2, PAGE 2 ********
MEM0: .EQU $20 ; start of memory for 64 screen line samples
; extends to $5F
;******* variables in BLOCK 2, PAGE 3 ********
COUNTER1: .EQU $20 ;counter used in decimalisation
COUNTER2: .EQU $21 ;counter used in decimalisation
COUNT0: .EQU $22 ;holds bin val to be decimalised LSB
COUNT1: .EQU $23 ;holds bin val to be decimalised NSB
COUNT2: .EQU $24 ;holds bin val to be decimalised MSB
DIGIT1: .EQU $25 ;decimalised digit 1
DIGIT2: .EQU $26 ;decimalised digit 2
DIGIT3: .EQU $27 ;decimalised digit 3
DIGIT4: .EQU $28 ;decimalised digit 4
DIGIT5: .EQU $29 ;decimalised digit 5
DIGIT6: .EQU $2A ;decimalised digit 6
DIGIT7: .EQU $2B ;decimalised digit 7
DIGIT8: .EQU $2C ;decimalised digit 8
;******* FIXED VALUES FOR COMMANDS *********
TXHOME: .EQU $40 ; text home address command
TXAREA: .EQU $41 ; text area (columns) address command
GRHOME: .EQU $42 ; graphics home address command
GRAREA: .EQU $43 ; graphic area (columns) address command
AWRON: .EQU $B0 ; autowrite on command
AWROFF: .EQU $B2 ; autowrite off command
OFFSET: .EQU $22 ; offset command
ADPSET: .EQU $24 ; address set command
PEEK: .EQU $E0 ; screen peek command
CSRPOS: .EQU $21 ; set cursor position command
;******* BIT VALUES ******
W: .EQU 0 ; working reg
F: .EQU 1 ; file reg
Z: .EQU 2 ; ZERO status
C: .EQU 0 ; CARRY status
DC: .EQU 1 ; DIGIT CARRY status
RP0: .EQU 5 ; STATUS BLOCK0 (BANKS0/1) reg
RP1: .EQU 6 ; STATUS BLOCK1 (BANKS2/3) reg
GIE: .EQU 7 ; INTCON reg
GO: .EQU 2 ; ADCON0 reg
FS: .EQU %00000000 ; FS mode set by bit 5: 1 = 6x8, 0 = 8x8
; 8x8 needed for EPE demos
;..........
; .ORG 0
; goto 5
; nop
; nop
; nop
.ORG $0004 ; Interrupt vector address
GOTO GIEOFF ; Jump to interrupt routine on interrupt
.ORG $0005 ; Start of program memory
GIEOFF: BCF INTCON,GIE ; turn off global interrupts
BTFSC INTCON,GIE
goto GIEOFF
goto START
FREQVAL: movf FOSC,W
addwf PCL,F ;table for freq factor routing
goto GETFREQ0
goto GETFREQ1
goto GETFREQ2
TABLE1: ADDWF PCL,F
retlw 'G'
retlw '-'
retlw 'S'
retlw 'C'
retlw 'O'
retlw 'P'
retlw 'E'
retlw ' '
retlw ' '
retlw ' '
retlw 'R'
retlw 'A'
retlw 'T'
retlw 'E'
retlw ' '
retlw ' '
retlw 'V'
retlw 'p'
retlw '-'
retlw 'p'
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw ' '
retlw 'H'
retlw 'z'
;**************
START: bcf STATUS,RP0
bcf STATUS,RP1
BLOCK0
clrf PORTA
clrf PORTB
movlw %00001111 ; FS low, RST low, CD CE RD WR high
movwf PORTC
clrf PORTD
clrf PORTE
PAGE1
movlw 255
movwf TRISA ; PORTA as input
movwf TRISB ; PORTB as input
movlw FS
movwf TRISC ; PORTC as output GRAPHIC LCD control/FS
clrf TRISD ; PORTD as output GRAPHIC LCD D0-D7
clrf TRISE ; PORTE as output
movlw %00000110 ; pull-up Rs on (bit 7 lo), timer 1/25 sec
movwf OPTION ; (for 3.2768MHz xtal)
movlw %00000100 ; set LHS justify, RA0, RA1, RA3 as analog inputs
movwf ADCON1 ; with RA, RE digital, ref to +VE and 0V
PAGE0
movlw %00011111 ; FS low, RST CD CE RD WR high
movwf PORTC
movlw %00000001 ; set AD on, Fosc/2
movwf ADCON0
call PAUSIT ; 1/5th sec pause
movlw 16
movwf COLUMN ; set column length
call SETUP
movlw %10011100 ; text on, graphic on, cursor & blink off
call SENDCMD ; send command
WORDS: clrf ADRMSB ; SHOW TEXT
movlw 0 ; set column
call LINE0 ; set cell number for line stated
movlw 16 ; character quantity
movwf LOOPC ;
clrf LOOPB ; clear table loop counter
call SHWTXT ;
clrf ADRMSB
movlw 3 ; set column
call LINE7 ; set cell number for line stated
movlw 13 ; character quantity
movwf LOOPC ;
call SHWTXT ;
call GETRATE
movlw %10000000
movwf SWITCH
;............................
MAIN: bsf ADCON0,GO ; start data conversion
btfsc PORTB,1 ; is sync needed?
goto SAMPLE1 ; no
clrf TIMOUT0 ; yes, clear timeout counters
clrf TIMOUT1
;.........get sync
WAITS1: btfsc ADCON0,GO
goto WAITS1
movf ADRESH,W ;get ADC val
; comf ADRESH,W ;get & invert ADC val
bsf ADCON0,GO ;start data conversion for next sample
decfsz TIMOUT0,F
decfsz TIMOUT1,F
goto WAITS1A
goto SAMPLE1
WAITS1A: addlw 114
btfss STATUS,C
goto WAITS1
WAITS2: btfsc ADCON0,GO
goto WAITS2
movlw 120
subwf ADRESH,W ;sub 120 from ADC val
bsf ADCON0,GO ;start data conversion for next sample
decfsz TIMOUT0,F
decfsz TIMOUT1,F
goto WAITS2A
goto SAMPLE1
WAITS2A: btfsc STATUS,C
goto WAITS2
WAITS3: btfsc ADCON0,GO
goto WAITS3
; movf ADRESH,W ;get ADC val
comf ADRESH,W ;get & invert ADC val
bsf ADCON0,GO ;start data conversion for next sample
decfsz TIMOUT0,F
decfsz TIMOUT1,F
goto WAITS3A
goto SAMPLE1
WAITS3A: addlw 128
btfss STATUS,C
goto WAITS3
;....... get 2 consecutive 64-byte data blocks from ADC
SAMPLE1: movlw ADC0 ;set store address at ADC0 BLOCK0
movwf FSR
movlw 64
movwf LOOPE
WAITAD0: btfsc ADCON0,GO
goto WAITAD0
; movf ADRESH,W ;get ADC val
comf ADRESH,W ;get & invert ADC val
bsf ADCON0,GO ;start data conversion for next sample
movwf INDF ;put it out to mem
incf FSR,F ;inc store address
decfsz LOOPE,F
goto WAITAD0
movlw ADC1 ;set store address at ADC1 BLOCK0
movwf FSR
bsf LOOPE,6
WAITAD1: btfsc ADCON0,GO
goto WAITAD1
; movf ADRESH,W ; get ADC val
comf ADRESH,W ;get & invert ADC val
bsf ADCON0,GO ;start data conversion for next sample
movwf INDF ;put it out to mem
incf FSR,F ;inc store address
decfsz LOOPE,F
goto WAITAD1
clrf LOOPA
clrf LOOPD
;...........
movlw ADC0 ; config & send data ADC0 BLOCK 0 to screen
movwf ADCADR ; samples need limiting to value of 63 max
movwf FSR
rrf INDF,W ; divide by 2
movwf ADCTEMP
rrf ADCTEMP,W ; divide by 2 again and clear bits 6&7
andlw %00111111
movwf PEAKLO ; move into PEAKLO (setting screen start val)
BLK0: movlw %10000000 ; indicates which bit of column is affected
movwf LOBIT
call SCOPE1 ; config & send to LCD
incf LOOPD,F ; inc to next column
btfss LOOPD,3 ; has column 8 been reached?
goto BLK0 ; no
movlw ADC1 ; config & send data ADC1 BLOCK 0 to screen
movwf ADCADR
BLK1: movlw %10000000 ; indicates which bit of column is affected
movwf LOBIT
call SCOPE1 ; config & send to LCD
incf LOOPD,F ; inc to next column
btfss LOOPD,4 ; has column 16 been reached?
goto BLK1 ; no
btfsc SWITCH,7 ; is text off?
call FREQVAL ; no, show freq & volts
call TESTIT ; get switches status
goto MAIN ; start again at screen left
;********** START OF SCOPE SUB-ROUTINES ***************
SCOPE1: movf LOOPA,W ; copy ADC loop val into PEAKHI
addwf ADCADR,W
movwf FSR ;
rrf INDF,W ; divide by 2
movwf ADCTEMP
rrf ADCTEMP,W ; divide by 2 again and clear bits 6&7
andlw %00111111
movwf ADCTEMP ; store for later use
movwf PEAKHI ; and move into PEAKHI
subwf PEAKLO,W ; is PEAKHI > PEAKLO ? (subtract hi from lo)
btfss STATUS,C ; is there a borrow?
goto SCOPE2 ; yes
movf PEAKLO,W ; no, so swap lo & hi
movwf PEAKHI
movf ADCTEMP,W
movwf PEAKLO
SCOPE2: call SETMEM ; config LCD memory store
movf ADCTEMP,W ; store current val into PEAKLO
movwf PEAKLO
incf LOOPA,F ; inc wavform counter
bcf LOOPA,6 ; limit to 64 max
bcf STATUS,C
rrf LOBIT,F ; shift right bitting setting val
btfss STATUS,C ; is CARRY set? (stating all 8 bits of col done)
goto SCOPE1 ; no
call SHOWMEM ; display results on screen
return
;************ config LCD memory store
SETMEM: BLOCK1
movlw MEM0 ; set address for 1st affected LCD store memory
addwf PEAKLO,W
movwf FSR ;
movf PEAKLO,W ; set loop to val of PEAKLO
movwf LOOPE
movf LOBIT,W
iorwf INDF,F ; (MEM0) set new bit
SCOPE3: movf LOOPE,W ; is loop = peakhi?
xorwf PEAKHI,W
btfsc STATUS,Z
goto SCOPE4
movf LOBIT,W ; no
iorwf INDF,F ; (MEM0) set new bit
incf LOOPE,F
btfsc LOOPE,6
goto SCOPE4
incf FSR,F
goto SCOPE3
SCOPE4: BLOCK0
return
;************ send 8-bit column to screen
SHOWMEM: movlw MEM0
addlw 63
movwf FSR
movlw 64
movwf LOOPE ; set loop val (number of lines)
movlw 2 ; set graphic base address ($02xx)
movwf ADRMSB
movf LOOPD,W ; set column
movwf ADRLSB
SCOPE5: call SCREENADR ; set screen write address
movlw AWRON ; AUTO WRITE ON
call SENDCMD ; send command
call CHECK3 ; read status for DA0/DA1 = 3
BLOCK1
movf INDF,W ; get value, clear store
clrf INDF ;,F 03feb06
BLOCK0
decf FSR,F
call OUTDATA ;
movlw AWROFF ; AUTO WRITE OFF
call SENDCMD ; send command
decf LOOPE,F
btfsc STATUS,Z
return
movf COLUMN,W ; set for next line
addwf ADRLSB,F
btfsc STATUS,0 ; add CARRY (if any) to MSB
incf ADRMSB,F
goto SCOPE5 ; repeat until done
;.......Frequency & Volts get & display
;Prototype values (LSB/MSB) set with freq gen at 4000Hz, counter at 4000Hz
;Fosc=0 ...70/85 Approx best max - Gen at 17007Hz counter showed 16984Hz
;Fosc=1 ...110/77 Approx best max - Gen at 17007Hz counter showed 16998Hz
;Fosc=2 ...128/24 Approx best max - Gen at 5827Hz counter showed 5812Hz
GETFREQ0: movlw 70 ;freq factor lsb ... for Fosc=0 ...70/85
movwf STORE ;sample counter lsb
movlw 85 ;freq factor msb
movwf STORE1 ;sample counter msb
goto GF0
GETFREQ1: movlw 110 ;freq factor lsb ... for Fosc=1 ...110/77
movwf STORE ;sample counter lsb
movlw 77 ;freq factor msb
movwf STORE1 ;sample counter msb
goto GF0
GETFREQ2: movlw 128 ;freq factor lsb ... for Fosc=2 ...128/24
movwf STORE ;sample counter lsb
movlw 24 ;freq factor msb
movwf STORE1 ;sample counter msb
GF0: bsf ADCON0,GO ;start data conversion for next sample
clrf FRQCNT1 ;freq counter lsb
clrf FRQCNT2 ;freq counter msb
GF1: btfsc ADCON0,GO
goto GF1
; movf ADRESH,W ;get ADC val
comf ADRESH,W ;get & invert ADC val
movwf STORE2
bsf ADCON0,GO ;start data conversion for next sample
CHKPOS: movlw 120 ;is ADC >136
addwf STORE2,W
btfss STATUS,C
goto CPOS1
bsf MARK2,0
goto CHKNEG
CPOS1: bcf MARK2,7 ;dummy action to maintain timing
CHKNEG: movlw 136
addwf STORE2,W
btfsc STATUS,C
goto CNEG1
bcf MARK2,0
goto MARKIT
CNEG1: bcf MARK2,7 ;dummy action to maintain timing
MARKIT: movf MARK2,W ;compare MARK1 & 2, add result (1 or 0) to count
xorwf MARK1,W
addwf FRQCNT1,F
movf STATUS,W
andlw 1
addwf FRQCNT2,F
GF4: movf MARK2,W
movwf MARK1
decfsz STORE,F ;dec counter
goto GF1
decfsz STORE1,F ;dec counter
goto GF1
GETVOLTS: movlw ADC0
movwf FSR
movlw 255
movwf MIN
clrf MAX
BLOCK0
call GV1
movlw ADC1
movwf FSR
call GV1
goto GV5
;...........
GV1: movlw 64
movwf LOOPE
GV2: movf INDF,W ;is ADC < MIN ? (sub ADC from MIN)
subwf MIN,W
btfss STATUS,C ;is there a borrow
goto GV3 ;yes
movf INDF,W
movwf MIN
GV3: movf MAX,W ;is ADC > MAX ? (sub MAX from ADC)
subwf INDF,W
btfss STATUS,C ;is there a borrow
goto GV4 ;no
movf INDF,W
movwf MAX
GV4: incf FSR,F
decfsz LOOPE,F
goto GV2
return
GV5: movf MIN,W ; sub MIN from MAX
subwf MAX,W
PAGE1 ; decimalisation variables held in BANK3
bsf STATUS,RP1
movwf COUNT0 ; move MAX-MIN val into COUNT0
clrf COUNT2
clrf COUNT1
bcf STATUS,C
rlf COUNT0,F ; multiply by 2
rlf COUNT1,F
call DECIMAL
bcf STATUS,RP1
PAGE0
SHOWVOLTS:
clrf ADRMSB
movlw 0 ; set column
call LINE7 ; set line
call SCREENADR ; set screen write address
movlw AWRON ; AUTO WRITE ON
call SENDCMD ; send command
movlw DIGIT3 ; ,W 03feb06
iorlw %10000000
movwf FSR
BLOCK1
movf INDF,W ; decimal values held in BLOCK1
BLOCK0
iorlw 16
call AUTOWRITE ; auto write and increment
movlw '.'
addlw 224
call AUTOWRITE ; auto write and increment
decf FSR,F
BLOCK1
movf INDF,W ; decimal values held in BLOCK1
BLOCK0
iorlw 16
call AUTOWRITE ; auto write and increment
movlw AWROFF ; AUTO WRITE OFF
call SENDCMD ; send command
SHOWFREQ: movf FRQCNT1,W ; BANK0 get freq val LSB
PAGE1
bsf STATUS,RP1
movwf COUNT0 ; BANK3
bcf STATUS,RP1
PAGE0
movf FRQCNT2,W ; BANK0 get freq val MSB
PAGE1
bsf STATUS,RP1
movwf COUNT1 ; BANK3
clrf COUNT2 ; BANK3
call DECIMAL ; BANK3
bcf STATUS,RP1
PAGE0
clrf ADRMSB
movlw 9 ; set column
call LINE7 ; set line
call SCREENADR ; set screen write address
movlw AWRON ; AUTO WRITE ON
call SENDCMD ; send command
movlw DIGIT5 ; ,W 03feb06
iorlw %10000000
movwf FSR
movlw 5
movwf LOOPE
SD1: BLOCK1
movf INDF,W ; decimal values held in BLOCK1
BLOCK0
call AUTOWRITE ; auto write and increment
decf FSR,F
decfsz LOOPE,F
goto SD1
movlw AWROFF ; AUTO WRITE OFF
call SENDCMD ; send command
return
;............. Modified BIN-DEC ROUTINE from Peter Hemsley 07JUN00
; converts 24-bit binary (3 bytes) to decimal
DECIMAL: ;decimalise binary number ALL VALS IN BANK3
;on entry COUNT0-2 holds number to be decimalised
;answer goes into DIGIT1-8
BLOCK1
call BINDEC
call BLANK0 ;blank leading zeros
BLOCK0
return
BINDEC: call CLRDIG ;reset DIGITs
movlw 24 ;24 bits to do
movwf COUNTER1
goto SHIFT1
ADJBCD movlw DIGIT1
iorlw %10000000
movwf FSR ;pointer to digits
movlw 7 ;7 digits to do (Digit 8 never >4)
movwf COUNTER2 ;if Digit > 4 then digit = digit + 3
movlw 3 ;check for Digit > 4 by adding 3 to it
ADJLOOP: addwf INDF,F ;and test bit 3 of result
btfss INDF,3 ;is it greater than 7?
subwf INDF,F ;restore to original
incf FSR,F ;next digit
decfsz COUNTER2,F
goto ADJLOOP
SHIFT1: call SLCNT ;shift MSB into Carry
SLDEC: movlw DIGIT1 ;shift Carry and Digits 1 bit left
iorlw %10000000
movwf FSR ;pointer to digits
movlw 8 ;8 Digits to do
movwf COUNTER2
SLDLOOP: ;after RLF if bit 4 is set then shift 1
rlf INDF,F ;into LSB of next Digit else shift 0
btfsc INDF,4 ;test for BCD carry
bsf STATUS,C ;set Carry for next Digit (cleared by RLF)
bcf INDF,4 ;clear BCD overflow (if any)
incf FSR,F ;next Digit
decfsz COUNTER2,F
goto SLDLOOP
decfsz COUNTER1,F ;next bit
goto ADJBCD
return
SLCNT: rlf COUNT0,F ;LSB
rlf COUNT1,F ;shift left count 0-2
rlf COUNT2,F ;MSB
return
CLRDIG: clrf DIGIT1 ;lsd
clrf DIGIT2
clrf DIGIT3
clrf DIGIT4
clrf DIGIT5
clrf DIGIT6
clrf DIGIT7
clrf DIGIT8 ;msd
return
BLANK0: movlw 8 ; blank leading zeros
movwf LOOPA
movlw DIGIT8
iorlw %10000000
movwf FSR
BLANK1: movf INDF,W
btfss STATUS,Z
goto BLANK2
movlw ' '
addlw 224
movwf INDF
decf FSR,F
decfsz LOOPA,F
goto BLANK1
movlw 16
iorwf DIGIT1,F
return
BLANK2: movlw 16
iorwf INDF,F
decf FSR,F
decfsz LOOPA,F
goto BLANK2
return
;..........
TESTIT: btfss PORTB,0 ; test bit 0 of Port B, is it high?
goto TSTPRV ; no, it's = 0 so go to TSTPRV
bcf SWITCH,0 ; clear bit 0 of SWITCH
btfss PORTB,2 ; test bit 2 of Port B, is it high?
goto TSTPRV2 ; no, it's = 0 so go to TSTPRV
bcf SWITCH,2 ; clear bit 2 of SWITCH
return ; return
TSTPRV: btfsc SWITCH,0 ; test bit 0 of SWITCH, is it clear?
return ; no, it's = 1 so return
movlw %01000000 ; yes, it's = 0 so inc ADCON0 rate count
addwf ADCON0,F ;
movf ADCON0,W ; get COUNT
andlw %11000000
xorlw %11000000
btfss STATUS,Z
goto TP2
bcf ADCON0,6
bcf ADCON0,7
TP2: bsf SWITCH,0 ; set bit 0 of SWITCH
GETRATE: swapf ADCON0,W ; set ADC sampling rate
andlw %00001100
movwf FOSC
bcf STATUS,C
rrf FOSC,F
rrf FOSC,F
clrf ADRMSB
movlw 15 ; set column
call LINE0 ; set line
movf FOSC,W
addlw 16
call ONEWRITE
return
TSTPRV2: btfsc SWITCH,2 ; test bit 2 of SWITCH, is it clear?
return ; no, it's = 1 so return
movlw 128 ; set toggle flag for text on/off
addwf SWITCH,F
movlw %10011000 ; text off, graphic on, cursor & blink off
btfsc SWITCH,7
movlw %10011100 ; text on, graphic on, cursor & blink off
call SENDCMD ; send command
bsf SWITCH,2 ; set bit 2 of SWITCH
return
;********** START OF LCD SUB-ROUTINES ***************
ONEWRITE: ; ** WRITE SINGLE BYTE **
movwf ATTRIB ; temp store val brought in on W
call SCREENADR ; set screen write address - vals preset at call
movlw AWRON ; AUTO WRITE ON
call SENDCMD ; send command
call CHECK3 ; read status for DA0/DA1 = 3
movf ATTRIB,W
call OUTDATA ;
movlw AWROFF ; AUTO WRITE OFF
call SENDCMD ; send command
return
;............
AUTOWRITE: ; ** AUTO WRITE ROUTINE **
movwf TEMPA ; temp store value brought in on W
call CHECK8 ; read status for DA3 = 8
movf TEMPA,W ; WRITE DATA
call OUTDATA ;
return ;
;..............
CMDADR: ; ** SET ADDRESS FOR COMMAND SENDING **
call CHECK3 ; read status for DA0/DA1 = 3
movf ADRLSB,W ; WRITE DATA D1
call OUTDATA ;
call CHECK3 ; read status for DA0/DA1 = 3
movf ADRMSB,W ; WRITE DATA D2
call OUTDATA ;
return ;
;.........
SCREENADR: ; ** SET ADDRESS FOR WRITE/READ TO/FROM SCREEN
call CHECK3 ; read status for DA0/DA1 = 3
movf ADRLSB,W ; WRITE ADDRESS LSB
call OUTDATA ;
call CHECK3 ; read status for DA0/DA1 = 3
movf ADRMSB,W ; WRITE ADDRESS MSB
call OUTDATA ;
movlw ADPSET ; SET ADDRESS POINTER
call SENDCMD ; send command
return ;
;.............
TEXTHOME: ; ** SET TEXT HOME ADDRESS **
clrf ADRMSB ; TEXT HOME ADDRESS $0000
clrf ADRLSB ;
call CMDADR ; send command address
movlw TXHOME ;
call SENDCMD ; send command
return
;...........
GRAPHHOME: ; ** SET GRAPHIC HOME ADDRESS **
movlw $02 ; GRAPHIC HOME ADDRESS $0200
movwf ADRMSB
clrf ADRLSB
call CMDADR ; send command address
movlw GRHOME ;
call SENDCMD ; send command
return
;...........
TEXTAREA: ; ** SET TEXT AREA **
clrf ADRMSB ;
movf COLUMN,W ; columns length
movwf ADRLSB ;
call CMDADR ; send command address
movlw TXAREA ; text area command
call SENDCMD ; send command
return
;...........
GRAPHAREA: ; ** SET GRAPHIC AREA **
clrf ADRMSB ;
movf COLUMN,W ; columns length
movwf ADRLSB ;
call CMDADR ; send command address
movlw GRAREA ; graphic area command
call SENDCMD ; send command
return
;...........
SETMODE: ; ** SET MODE **
movlw %10000000 ; (OR mode, Internal CG mode)
call SENDCMD ; send command
return
;...........
SETDISPLAY: ; ** DISPLAY MODE **
movlw %10011100 ; text on, graphic on, cursor & blink off
call SENDCMD ; send command
return
;...........
CLRTXT ; ** CLEAR TEXT AREA ($0000) **
clrf ADRMSB ; clear all text screen lines, length as set
clrf ADRLSB ;
call SCREENADR ; set screen write address
movlw AWRON ; AUTO WRITE ON
call SENDCMD ; send command
movlw 8 ; number of lines
movwf LOOPC
CLR2: movf COLUMN,W ; column length
movwf LOOPB ;
CLR3: movlw 0 ; write 0
call AUTOWRITE ; auto write and increment
decfsz LOOPB,F ;
goto CLR3 ;
decfsz LOOPC,F ;
goto CLR2 ;
movlw AWROFF ; AUTO WRITE OFF
call SENDCMD ; send command
return
;............
CLRGRAPH: ; ** CLEAR GRAPH AREA ($0200) **
movlw $02
movwf ADRMSB ;
clrf ADRLSB ;
call SCREENADR ; set screen write address
movlw AWRON ; AUTO WRITE ON
call SENDCMD ; send command
movlw 64 ; number of lines
movwf LOOPC
CLRG2: movf COLUMN,W ; column length
movwf LOOPB ;
CLRG3: movlw 0 ; write 0
call AUTOWRITE ; auto write and increment
decfsz LOOPB,F ;
goto CLRG3 ;
decfsz LOOPC,F ;
goto CLRG2 ;
movlw AWROFF ; AUTO RESET OFF
call SENDCMD ; send command
return
;............
CHECK3: PAGE1 ; STATUS CHECK for DA0/DA1 = 3
movlw 255 ;
movwf TRISD ; set PORTD as inputs
PAGE0 ; RST CD CE RD WR
movlw %00011001 ; 1 1 0 0 1
movwf PORTC ; set CE, RD low
nop
CK3: btfss PORTD,0 ; PORTD bit 0 set?
goto CK3 ; no
CK3A: btfss PORTD,1 ; PORTD bit 1 set?
goto CK3A ; no RST CD CE RD WR
movlw %00011111 ; 1 1 1 1 1
movwf PORTC ; set controls
nop
PAGE1 ;
clrf TRISD ; set PORTD as outputs
PAGE0 ;
return
;............
CHECK8: PAGE1 ; STATUS CHECK for DA3 = 8
bsf PORTD,3 ; set PORTD bit 3 as input
PAGE0 ; RST CD CE RD WR
movlw %00011001 ; 1 1 0 0 1
movwf PORTC ; set CE, RD low
nop
CK8: btfss PORTD,3 ; is PORTD,3 high?
goto CK8 ; no RST CD CE RD WR
movlw %00011111 ; 1 1 1 1 1
movwf PORTC ; set controls
nop
PAGE1 ;
bcf TRISD,3 ; set PORTD bit 3 as output
PAGE0 ;
return
;........
OUTDATA: ; ** SEND DATA ROUTINE **
movwf TEMPA ; temp store val brought in on W
; RST CD CE RD WR
movlw %00010111 ; 1 0 1 1 1
movwf PORTC ; set CD low
movf TEMPA,W ; get stored data
movwf PORTD ; send data
nop ; RST CD CE RD WR
movlw %00010010 ; 1 0 0 1 0
movwf PORTC ; set CD, CE, WR low
nop ; RST CD CE RD WR
movlw %00010111 ; 1 0 1 1 1
movwf PORTC ; set CE, WR high
nop ; RST CD CE RD WR
movlw %00011111 ; 1 1 1 1 1
movwf PORTC ; set CD high
return
;..........
SENDCMD: ; ** COMMAND WRITE ROUTINE **
movwf TEMPA ; temp store val brought in on W
call CHECK3 ; read status for DA0/DA1 = 3
movf TEMPA,W ; WRITE COMMAND
movwf PORTD ; send stored data
nop ; RST CD CE RD WR
movlw %00011010 ; 1 1 0 1 0
movwf PORTC ; set CE, WR low
nop ; RST CD CE RD WR
movlw %00011111 ; 1 1 1 1 1
movwf PORTC ; set all high
return
;...........
SHWTXT: ; ** SHOW TEXT HELD IN TABLE **
call SCREENADR ; set screen write address - vals preset at call
movlw AWRON ; SET AUTO WRITE ON
call SENDCMD ; send command
SHTXT1: movf LOOPB,W ; LOOPB val specified by calling routine
call TABLE1 ; get table data and convert to graphic LCD val
addlw 224 ; +224 is same as -32 for conversion from ASCII
call AUTOWRITE ; auto write and increment
incf LOOPB,F ;
decfsz LOOPC,F ; LOOPC val specified by calling routine
goto SHTXT1 ;
movlw AWROFF ; AUTO WRITE OFF
call SENDCMD ; send command
return
;............. sets line addresses for text screen
LINE7: addlw 112 ; COLUMN set for 16 cells per line during SETUP
LINE0: movwf ADRLSB ;
return ; ADRMSB is set/cleared before routine called
;..............
PAUSIT: movlw 5 ; pause routine, 1/5th sec
movwf CLKCNT
clrf INTCON
PAUSE: btfss INTCON,2
goto PAUSE
BCF INTCON,2
decfsz CLKCNT,F
goto PAUSE
return
;................
SETUP: ; RST CD CE RD WR GENERAL SETUP
movlw %00011111 ; 1 1 1 1 1
movwf PORTC ; set controls high (off)
call TEXTHOME ; SET TEXT HOME ADDRESS
call GRAPHHOME ; SET GRAPHIC HOME ADDRESS
call TEXTAREA ; SET TEXT AREA
call GRAPHAREA ; SET GRAPHIC AREA
call SETMODE ; SET MODE (INT/EXT/AND-OR-XOR etc)
call SETDISPLAY ; DISPLAY MODE (text, graph on/off etc)
call CLRTXT ; clear text screen
call CLRGRAPH ; clear graph screen
return
.END
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?