Code:
;------------------------------------------------------ ; Breshenham's line draw for KS0108 based 128x64 LCDs ; (C) Peter Onion 2005 ; Use at your own risk ! ;------------------------------------------------------ Processor 16F877 Radix DEC EXPAND include "p16f877.inc" brWleF macro F,dst subwf F,W skpz skpc goto $+2 ; YUK! goto dst endm #define CNTLPORT PORTB #define CNTLTRIS TRISB #define DATAPORT PORTD #define DATATRIS TRISD ;; For 20Mhz use 12. Can be reduced at lower clock speeds ;; For 12.288Mhz use 5 Select on test ! #define DELAY 12 ;; Definitions for bits in CNTLPORT #define CSABIT 0 #define CSBBIT 1 #define DIBIT 2 #define RWBIT 3 #define EBIT 4 #define RESETBIT 5 ;; Definitions for bits in the control word #define INCX 0 #define INCY 1 #define DECY 2 #define SETCS 3 #define SETPAGE 4 #define FLUSH 5 #define DONE 6 #define SAVE 7 ;; Macros for bit twiddling on the control interface WSTROBE MACRO movlw 12 movwf scratch3 decfsz scratch3,F goto $-1 bsf CNTLPORT,EBIT ; Rising edge IF 0 movlw 1 movwf scratch3 decfsz scratch3,F goto $-1 ENDIF bcf CNTLPORT,EBIT ; Falling edge ; strobes data ENDM RSTROBE MACRO movlw 12 movwf scratch3 decfsz scratch3,F goto $-1 bsf CNTLPORT,EBIT ; Rising edge If 0 movlw 1 movwf scratch3 decfsz scratch3,F goto $-1 ENDIF movf DATAPORT,W bcf CNTLPORT,EBIT ; Falling edge ENDM SETELOW MACRO bcf CNTLPORT,EBIT ENDM SETW MACRO bcf CNTLPORT,RWBIT ENDM SETR MACRO bsf CNTLPORT,RWBIT ENDM SETD MACRO bsf CNTLPORT,DIBIT ENDM SETI MACRO bcf CNTLPORT,DIBIT ENDM RESETH MACRO bsf CNTLPORT,RESETBIT ENDM RESETL MACRO bcf CNTLPORT,RESETBIT ENDM SELA MACRO bcf CNTLPORT,CSABIT bsf CNTLPORT,CSBBIT ENDM SELB MACRO bsf CNTLPORT,CSABIT bcf CNTLPORT,CSBBIT ENDM SELBOTH MACRO bcf CNTLPORT,CSABIT bcf CNTLPORT,CSBBIT ENDM SELNONE MACRO bsf CNTLPORT,CSABIT bsf CNTLPORT,CSBBIT ENDM DATA1 UDATA x1 res 1 ; Start ppint y1 res 1 x2 res 1 ; End point y2 res 1 dx res 1 dy res 1 control res 1 length res 1 dec res 1 d res 1 aa res 1 bb res 1 temp res 1 cachestart res 1 currentbyte res 1 cachelength res 1 count res 1 pageNo res 1 AA res 1 BB res 1 xpos res 1 ypos res 1 ctlCode res 1 ; bits temp1 res 1 pixelbit res 1 ;; delay res 1 ;; A cache that hold one "page" of pixels CacheRam UDATA cache res 64 ;; Scratch registers in shared bank. DO not assume they ;; are preserved by any subroutines. extern scratch1,scratch2,scratch3,scratch4 GLOBAL x1,y1,x2,y2 line CODE ;; Clear the LCD clearLCD: clrf scratch1 ; set page number to zero banksel CNTLPORT SELBOTH ; Write to both halves together SETW clrloop: SETI movf scratch1,W addlw 0xB8 ; set page number movwf DATAPORT WSTROBE movlw 0x40 ; set X address to 0 movwf DATAPORT WSTROBE movlw 64 movwf scratch2 ; counter SETW SETD movlw 0x0 ; clear to OFF movwf DATAPORT clrloop1: WSTROBE decfsz scratch2,F goto clrloop1 incf scratch1,F ; loop until page == 8 btfss scratch1,3 goto clrloop SETI SELNONE return ;; Write used part of cache back to the LCD flushcache: BANKSEL CNTLPORT BANKISEL cache ; set up for indirect cahce access movlw cache movwf FSR banksel cachelength movf cachelength,W movwf scratch1 ; hold the counter banksel CNTLPORT SETI SETW BANKSEL DATATRIS ; reset portd to output movlw 0x00 movwf DATATRIS banksel cachestart movlw 0x40 ; set y address to first used addwf cachestart,W ; byte in the cache banksel DATAPORT movwf DATAPORT WSTROBE SETD ; data SETW ; write flushloop: movlw DELAY movwf scratch2 decfsz scratch2,F goto $-1 movf INDF,W ; read from the cache bsf CNTLPORT,EBIT ; Rising edge movwf DATAPORT bcf CNTLPORT,EBIT ; Falling edge ; strobes data incf FSR,F decfsz scratch1,F goto flushloop return linedraw: banksel ctlCode clrf ctlCode clrf control comf y1,F ; Make y = 0 the bottom rather comf y2,F ; than the top movf x1,W ; check moving left to right subwf x2,W ; and workout dx skpnc goto ld1 sublw 0 movwf temp movf x1,W ; swap end points so left to right movwf temp1 movf x2,W movwf x1 movf temp1,W movwf x2 movf y1,W movwf temp1 movf y2,W movwf y1 movf temp1,W movwf y2 movf temp,W ld1 movwf dx ; dx = |x1 - x2| movf y1,W subwf y2,W skpnc goto ld2 sublw 0 bsf ctlCode,0 ; Going Up or Down ld2 movwf dy ; dy = |y1 - y2| movf dy,W ; test if steep or shallow line subwf dx,W skpnc goto ld3 movf dx,W ; swap to make shallow movwf temp movf dy,W movwf dx movf temp,W movwf dy bsf ctlCode,1 ; set "steep flag" ld3 clrf dec bcf STATUS,C rrf dx,W ; W = dx >> 1 rlf dec,F ; dec = dx & 1 subwf dy,W ; W = dy - (dx >> 1) movwf d ; d = W movf dx,W subwf dy,W movwf AA ; A = dy -dx movf dy,W movwf BB ; B = dy movf AA,W subwf dec,F ; dec -= A subwf d,F ; d -= A movf dx,W sublw 0 movwf AA ; A = -dx movf x1,W ; set up for looping movwf xpos movf y1,W movwf ypos movf dx,W movwf length clrf control ; set the inital actions to take bsf control,SETCS ; setup the Chip Selects bsf control,SETPAGE ; set the page number bsf control,SAVE ; movf ypos,W ; Set correct bit in pixelbit andlw 0x7 ; for the y position addlw 0x1 movwf temp clrf pixelbit bsf STATUS,C setyloop: rlf pixelbit,F decfsz temp,F goto setyloop ;; loop back here if step over to right hand side setcs: banksel control btfss control,SETCS goto pageSet bcf control,SETCS btfsc xpos,6 ; set correct Chip select goto setcs1 banksel CNTLPORT SELA goto pageSet setcs1: banksel CNTLPORT SELB pageSet:banksel control btfss control,SETPAGE goto initcache movf ypos,W ; set y page address in controler movwf pageNo rrf pageNo,F rrf pageNo,F rrf pageNo,F movlw 0x7 andwf pageNo,F movf pageNo,W addlw 0xB8 banksel DATAPORT movwf DATAPORT SETI SETW WSTROBE initcache: bankisel cache banksel cachelength clrf cachelength ; initialise the cache movlw cache movwf FSR movf xpos,W andlw 0x3F movwf cachestart movlw 0x40 ; set x address addwf cachestart,W banksel DATAPORT movwf DATAPORT WSTROBE clrf DATAPORT ; prepare to read from controler BANKSEL DATATRIS movlw 0xFF movwf DATATRIS BANKSEL DATAPORT SETD ; data SETR ; read RSTROBE ; Dummy read readbyte: banksel control btfss control,SAVE goto dontread banksel DATAPORT RSTROBE ; read the byte banksel currentbyte movwf currentbyte dontread: movf pixelbit,W ; set the bit iorwf currentbyte,F btfsc control,DONE ; test end flag goto alldone clrf control ; reset all the flags ;; DANGER DANGER..... Check for page boundry !! here: banksel ctlCode movlw high $ movwf PCLATH ; page movf ctlCode,W andlw 0x7 addwf PCL,F goto code0 goto code1 goto code2 goto code3 code0: movf d,W brWleF dec,code01 movf AA,W addwf d,F bsf control,INCY code01: movf BB,W addwf d,F bsf control,INCX goto common code1: movf d,W brWleF dec,code11 movf AA,W addwf d,F bsf control,DECY code11: movf BB,W addwf d,F bsf control,INCX goto common code2: movf d,W brWleF dec,code21 movf AA,W addwf d,F bsf control,INCX code21: movf BB,W addwf d,F bsf control,INCY goto common code3: movf d,W brWleF dec,code31 movf AA,W addwf d,F bsf control,INCX code31: movf BB,W addwf d,F bsf control,DECY goto common common: decf length,F skpnz bsf control,DONE btfss control,INCX ; did we move to the right ? goto checkINCY bsf control,SAVE movf xpos,W ; increment X incf xpos,F xorwf xpos,W movwf temp1 btfss temp1,6 ; test for left-to-right change goto checkINCY bsf control,FLUSH ; set flush bsf control,SETCS ; set setCS bsf control,SETPAGE checkINCY: btfss control,INCY ; did we move down ? goto checkDECY incf ypos,F bcf STATUS,C rlf pixelbit,F ; move bit btfss STATUS,C ; if carry set, we ned to move to next bank goto checksave rlf pixelbit,F bsf control,SETPAGE bsf control,SAVE bsf control,FLUSH goto checksave checkDECY: btfss control,DECY ; did we move up ? goto checksave decf ypos,F bcf STATUS,C rrf pixelbit,F btfss STATUS,C goto checksave rrf pixelbit,F bsf control,SETPAGE bsf control,SAVE bsf control,FLUSH goto checksave checksave: ; do we need to save byte to cache ? btfss control,SAVE goto checkflush movf currentbyte,W ; write byte to cache movwf INDF incf FSR,F incf cachelength,F checkflush: ; do we need to flush the cache ? btfss control,FLUSH goto readbyte call flushcache goto setcs alldone: ; write endpoint and flush cache movf currentbyte,W movwf INDF incf FSR,F incf cachelength,F call flushcache return initGRLCD: banksel DATATRIS clrf DATATRIS clrf CNTLTRIS banksel DATAPORT RESETL ; 5 XX0XXXXX SELBOTH ; 0 1 XX0XXX00 SETELOW ; 4 XX00XX00 SETI ; 2 XX00X000 SETW ; 3 XX000000 RESETH ; XX100000 movlw 0x3F ; Display ON movwf DATAPORT movlw 9 movwf scratch1 decfsz scratch1,F goto $-1 WSTROBE movlw 0x40 ; set x address to 0 movwf DATAPORT WSTROBE movlw 0xBF ; set page to 0 movwf DATAPORT WSTROBE movlw 0xC0 ; set display start line to 0 movwf DATAPORT WSTROBE return GLOBAL linedraw,initGRLCD,clearLCD END