diff code_part1/OSTC_code_asm_part1/display_lowlevel.asm @ 681:6e456a6398e0

Hardware4 support
author heinrichsweikamp
date Fri, 25 Jan 2013 18:00:49 +0100
parents
children 99b3fb0ab4c7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code_part1/OSTC_code_asm_part1/display_lowlevel.asm	Fri Jan 25 18:00:49 2013 +0100
@@ -0,0 +1,1377 @@
+; OSTC - diving computer code
+; Copyright (C) 2009 HeinrichsWeikamp GbR
+
+;    This program is free software: you can redistribute it and/or modify
+;    it under the terms of the GNU General Public License as published by
+;    the Free Software Foundation, either version 3 of the License, or
+;    (at your option) any later version.
+
+;    This program is distributed in the hope that it will be useful,
+;    but WITHOUT ANY WARRANTY; without even the implied warranty of
+;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;    GNU General Public License for more details.
+
+;    You should have received a copy of the GNU General Public License
+;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+; written by: Matthias Heinrichs, info@heinrichsweikamp.com
+; written: 090801
+; History:
+; 2009-08-30: [MH] last updated.
+; 2011-01-07: [jDG] Added flip_screen option
+; known bugs: pixel-write (loogbok curves) not done yet...
+; ToDo:
+
+WIN_FONT 	macro	win_font_input
+			movlw	win_font_input
+			movff	WREG,win_font
+			endm
+			
+WIN_TOP 	macro 	win_top_input
+			movlw	win_top_input
+			movff	WREG,win_top
+			endm
+			
+WIN_LEFT 	macro 	win_left_input
+			movlw	win_left_input
+			movff	WREG,win_leftx2
+			endm
+			
+WIN_INVERT	macro 	win_invert_input
+			movlw	win_invert_input
+			movff	WREG,win_invert
+			endm
+
+WIN_COLOR	macro 	win_color_input
+			movlw	win_color_input
+			call	DISP_set_color
+			endm
+
+;=============================================================================
+
+word_processor:						; word_processor:
+    clrf	POSTINC2				; Required, to mark end of string.
+    call	aa_wordprocessor
+    movlb	b'00000001'				; Back to Rambank1
+    return
+
+;=============================================================================
+; Macro to provides our own interface code.
+;
+PIXEL_WRITE macro   colRegister, rowRegister
+        movff   colRegister,win_leftx2
+        movff   rowRegister,win_top
+        call    pixel_write
+        endm
+
+INIT_PIXEL_WROTE macro colRegister
+        movff   colRegister,win_leftx2
+        call    init_pixel_write
+        endm
+
+HALF_PIXEL_WRITE macro rowRegister
+        movff   rowRegister,win_top
+        call    half_pixel_write
+        endm
+
+;-----------------------------------------------------------------------------
+; Init for half_pixel_write
+; Set column register on DISPLAY device, and current color.
+; Inputs: win_leftx2
+; Outputs: win_color:2
+; Trashed: WREG, PROD
+init_pixel_write:
+        movff   win_leftx2,WREG
+        mullw   2
+        rcall   pixel_write_col320      ; Start Address Vertical (.0 - .319)
+        goto    DISP_standard_color
+    
+;-----------------------------------------------------------------------------
+; Writes two half-pixels at position (win_top,win_leftx2)
+; Inputs: win_leftx2, win_top, win_color:2
+; Trashed: WREG, PROD
+pixel_write:
+        movff   win_leftx2,WREG
+        mullw   2
+        rcall   pixel_write_col320      ; Start Address Vertical (.0 - .319)
+        rcall   half_pixel_write        ; Write this half-one.
+
+        movff   win_leftx2,WREG         ; Address of next one
+        mullw   2
+        infsnz  PRODL                   ; +1
+        incf    PRODH
+    	rcall   pixel_write_col320
+    	bra     half_pixel_write        ; Note: Cmd 0x20 is mandatory, because
+    	                                ; of the autoincrement going vertical
+
+        ;---- Do the 16bit 319-X-->X, if needed, and send to DISPLAY ------------
+pixel_write_col320:
+        movff   win_flags,WREG          ; BEWARE: bank0 bit-test
+        btfss   WREG,0                  ; 180° rotation ?
+        bra     pixel_write_noflip_H
+
+        movf    PRODL,W                 ; 16bits 319 - PROD --> PROD
+        sublw   LOW(.319)               ; 319-W --> W
+        movwf   PRODL
+        movf    PRODH,W
+        btfss   STATUS,C                ; Borrow = /CARRY
+        incf    WREG
+        sublw   HIGH(.319)
+        movwf   PRODH
+
+pixel_write_noflip_H:
+    	movlw	0x21				    ; Start Address Vertical (.0 - .319)
+    	rcall	DISP_CmdWrite
+    	bra     DISP_DataWrite_PROD   
+
+;-----------------------------------------------------------------------------
+; Writes a vertical line of half-pixel at position (win_top,win_leftx2,win_height).
+; Inputs: win_leftx2, win_top, win_height, win_color:2
+; Trashed: WREG, PROD, TABLAT, TBLPTRL
+half_vertical_line:
+        clrf    TABLAT                  ; Loop index.
+
+half_vertical_line_loop:
+        movff   win_leftx2,WREG         ; Init X position.
+        mullw   2
+        movf    TABLAT,W                ; Get loop index
+        andlw   1                       ; Just low bit
+        xorwf   PRODL,F                 ; And use it to jitter current X position
+        rcall   pixel_write_col320      ; Start Address Vertical (.0 - .319)
+
+        movff   win_height,WREG         ; Index reached height (Bank0 read) ?
+        xorwf   TABLAT,W
+        btfsc   STATUS,Z                ; Equals ?
+        return                          ; Yes: done.
+        movff   win_top,WREG            ; Y = top + index (Bank0 read)
+        addwf   TABLAT,W
+        rcall   half_pixel_write_1
+        incf    TABLAT,F                ; index++
+        bra     half_vertical_line_loop
+
+;-----------------------------------------------------------------------------
+; Writes one half-pixel at position (win_top,win_leftx2).
+; Inputs: win_leftx2, win_top, win_color:2
+; Trashed: WREG, PROD
+half_pixel_write:
+    	movff  	win_top,WREG            ; d'0' ... d'239'
+
+; Variant with Y position in WREG.
+half_pixel_write_1:
+        movff   win_flags,PRODL         ; BEWARE: bank0 bit-test
+    	btfsc   PRODL,0                 ; 180° rotation ?
+    	sublw   .239                    ; 239-Y --> Y
+
+    	mullw   1                       ; Copy row to PRODH:L
+    	movlw	0x20			        ; Horizontal Address START:END
+    	rcall	DISP_CmdWrite
+    	rcall   DISP_DataWrite_PROD
+    
+    	movlw	0x22					; Start Writing Data to GRAM
+    	rcall	DISP_CmdWrite
+    	bsf		DISPLAY_rs					; Data!
+    	movff	win_color1, PORTD
+    	bcf		DISPLAY_rw
+    	bsf		DISPLAY_rw					; Upper
+    	movff	win_color2, PORTD
+    	bcf		DISPLAY_rw
+    	bsf		DISPLAY_rw					; Lower
+        movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+        btfss   WREG,1
+        return                          ; No, Done.
+    	movff	win_color3, PORTD
+    	bcf		DISPLAY_rw
+    	bsf		DISPLAY_rw					; Lower
+    	return
+
+; -----------------------------
+; DISP Display Off
+; -----------------------------
+DISP_DisplayOff:
+	clrf	PORTD
+	bcf		DISPLAY_hv
+	bcf		DISPLAY_vdd
+	bcf		DISPLAY_cs
+	bcf		DISPLAY_e_nwr	
+	bcf		DISPLAY_rw
+	bcf		DISPLAY_nreset
+	return
+
+;=============================================================================
+; Fast macros to write to DISPLAY display.
+; Adding a call/return adds 3 words and a pipeline flush, hence make it
+; nearly twice slower...
+;
+; Input	 : commande as macro parameter.
+; Output : NONE
+; Trash  : WREG
+;
+AA_CMD_WRITE macro cmd
+		movlw	cmd
+		rcall   DISP_CmdWrite			; slow but saves a lot of bytes in flash
+		endm
+;
+; Input	 : data as macro parameter.
+; Output : NONE
+; Trash  : WREG
+;
+AA_DATA_WRITE macro data
+        movlw   data
+        rcall   DISP_DataWrite
+        endm
+;
+; Input	 : PRODH:L as 16bits data.
+; Output : NONE
+; Trash  : NONE
+;
+AA_DATA_WRITE_PROD	macro
+        rcall   DISP_DataWrite_PROD	; slow but saves a lot of bytes in flash
+		endm
+
+;=============================================================================
+; Output DISPLAY Window Address commands.
+; Inputs : win_top, win_leftx2, win_height, aa_width.
+; Output : PortD commands.
+; Trashed: PROD
+;
+DISP_box_write:
+        movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+        btfsc   WREG,1                  ; Display1?
+        bra     DISP_box_write_display1 ; Yes
+
+		movff	win_leftx2,WREG         ; Compute left = 2*leftx2 --> PROD
+		mullw	2
+
+        movff   win_flags,WREG          ; BEWARE: bank0 bit-test
+    	btfsc   WREG,0                  ; 180° rotation ?
+    	bra     DISP_box_flip_H         ; YES: 
+
+        ;---- Normal horizontal window ---------------------------------------
+        ; Output 0x35 left,
+        ;        0x36 right ==  left + width - 1.
+		AA_CMD_WRITE	0x35		    ; this is the left border
+		AA_DATA_WRITE_PROD              ; Output left
+		AA_CMD_WRITE	0x21            ; Also the horizontal first pix coord.
+		AA_DATA_WRITE_PROD
+		
+		movf	aa_width+0,W,ACCESS	    ; right = left + width - 1
+		addwf	PRODL,F
+		movf	aa_width+1,W,ACCESS
+		addwfc	PRODH,F
+		decf	PRODL,F,A			    ; decrement result
+		btfss   STATUS,C
+		decf	PRODH,F,A
+
+		AA_CMD_WRITE	0x36		    ; Write and the right border
+		AA_DATA_WRITE_PROD
+
+		bra     DISP_box_noflip_H
+
+        ;---- Flipped horizontal window --------------------------------------
+DISP_box_flip_H:
+        ; Output 0x36 flipped(left)  = 319-left
+        ;        0x35 flipped(right) = 319-right = 320 - left - width
+        movf    PRODL,W                 ; 16bits 319 - PROD --> PROD
+        sublw   LOW(.319)               ; 319-W --> W
+        movwf   PRODL
+        movf    PRODH,W
+        btfss   STATUS,C                ; Borrow = /CARRY
+        incf    WREG
+        sublw   HIGH(.319)
+        movwf   PRODH
+		AA_CMD_WRITE	0x36		    ; this is the left border
+		AA_DATA_WRITE_PROD              ; Output left
+		AA_CMD_WRITE	0x21
+		AA_DATA_WRITE_PROD
+
+        movf    aa_width+0,W            ; 16bits PROD - width --> PROD
+        subwf   PRODL,F                 ; PRODL - WREG --> PRODL
+        movf    aa_width+1,W
+        subwfb  PRODH,F
+        infsnz  PRODL                   ; PROD+1 --> PROD
+        incf    PRODH
+		AA_CMD_WRITE	0x35		    ; this is the left border
+		AA_DATA_WRITE_PROD              ; Output left
+
+DISP_box_noflip_H:
+        movff   win_flags,WREG          ; BEWARE: bank0 bit-test
+    	btfsc   WREG,0                  ; 180° rotation ?
+    	bra     DISP_box_flip_V
+
+        ;---- Normal vertical window -----------------------------------------
+        ; Output 0x37 (top) (bottom)
+		movff	win_top,PRODH           ; top --> PRODH (first byte)
+		movff   win_height,WREG
+		addwf   PRODH,W
+		decf	WREG
+		movwf	PRODL                   ; top+height-1 --> PRODL (second byte)
+
+		AA_CMD_WRITE	0x37
+		AA_DATA_WRITE_PROD
+
+        movff   PRODH,PRODL
+        clrf    PRODH                   ; Start pixel V coord == top.
+		AA_CMD_WRITE	0x20
+		AA_DATA_WRITE_PROD
+
+		return
+
+        ;---- Flipped vertical window ----------------------------------------
+        ; Output 0x37 flipped(bottom) = 239-bottom = 240 - top - height
+        ;             flipped(top)    = 239-top
+DISP_box_flip_V:
+		movff   win_top,PRODL
+		movff   win_height,WREG
+		addwf   PRODL,W
+		sublw   .240                    ; 240 - top - height
+		movwf   PRODH                   ; First byte
+
+		movf	PRODL,W
+		sublw   .239                    ; 249-top
+		movwf   PRODL                   ; --> second byte.
+
+		AA_CMD_WRITE	0x37
+		AA_DATA_WRITE_PROD
+
+        clrf    PRODH                   ; Start pixel V coord.
+		AA_CMD_WRITE	0x20
+		AA_DATA_WRITE_PROD
+
+		return
+
+DISP_box_write_display1:
+    	movff	win_leftx2,WREG         ; Compute left = 2*leftx2 --> PROD
+		mullw	2
+
+        movlw	0x06
+        rcall	DISP_CmdWrite
+        movf    PRODH,W
+        rcall	DISP_DataWrite
+        movlw	0x07
+        rcall	DISP_CmdWrite
+        movf    PRODL,W
+        rcall	DISP_DataWrite
+
+		movf	aa_width+0,W,ACCESS	    ; right = left + width - 1
+		addwf	PRODL,F
+		movf	aa_width+1,W,ACCESS
+		addwfc	PRODH,F
+		decf	PRODL,F,A			    ; decrement result
+		btfss   STATUS,C
+		decf	PRODH,F,A
+
+        movlw	0x08
+        rcall	DISP_CmdWrite
+        movf    PRODH,W
+        rcall	DISP_DataWrite
+        movlw	0x09
+        rcall	DISP_CmdWrite
+        movf    PRODL,W
+        rcall	DISP_DataWrite
+
+        ;---- Normal vertical window -----------------------------------------
+        ; Output 0x37 (top) (bottom)
+		movff	win_top,PRODH           ; top --> PRODH (first byte)
+		movff   win_height,WREG
+		addwf   PRODH,W
+		decf	WREG
+		movwf	PRODL                   ; top+height-1 --> PRODL (second byte)
+
+        movlw	0x02
+        rcall	DISP_CmdWrite
+        movlw   0x00
+        rcall	DISP_DataWrite
+        movlw	0x03
+        rcall	DISP_CmdWrite
+        movf    PRODH,W
+        rcall	DISP_DataWrite
+
+
+        movlw	0x04
+        rcall	DISP_CmdWrite
+        movlw   0x00
+        rcall	DISP_DataWrite
+        movlw	0x05
+        rcall	DISP_CmdWrite
+        movf    PRODL,W
+        rcall	DISP_DataWrite
+		return
+
+;=============================================================================
+; DISP_frame : draw a frame around current box with current color.
+; Inputs:  win_top, win_leftx2, win_height, win_width, win_color1, win_color2
+; Outputs: (none)
+; Trashed: WREG, PROD, aa_start:2, aa_end:2, win_leftx2, win_width:1
+    global  DISP_frame
+DISP_frame:
+    movff   win_top,aa_start+0          ; Backup everything.
+    movff   win_height,aa_start+1
+    movff   win_leftx2,aa_end+0
+    movff   win_width,aa_end+1
+
+    ;---- TOP line -----------------------------------------------------------
+    movlw   1                           ; row ~ height=1
+    movff   WREG,win_height
+    rcall   DISP_box
+
+    ;---- BOTTOM line --------------------------------------------------------
+    movff   aa_start+0,PRODL             ; Get back top,
+    movff   aa_start+1,WREG              ; and height
+    addwf   PRODL,W                      ; top+height
+    decf    WREG                         ; top+height-1
+    movff   WREG,win_top                 ; top+height-1 --> top
+    rcall   DISP_box                        
+
+    ;---- LEFT column --------------------------------------------------------
+    movff   aa_start+0,win_top              ; Restore top/height.
+    movff   aa_start+1,win_height
+    movlw   1                               ; column ~ width=1
+    movff   WREG,win_width
+    rcall   DISP_box
+
+    ;---- RIGHT column -------------------------------------------------------
+    movff   aa_end+0,WREG
+    movff   aa_end+1,PRODL
+    addwf   PRODL,W
+    decf    WREG
+    movff   WREG,win_leftx2
+    bra     DISP_box
+
+;=============================================================================
+; DISP_box : fills current box with current color.
+; Inputs:  win_top, win_leftx2, win_height, win_width, win_color1, win_color2
+; Outputs: (none)
+; Trashed: WREG, PROD
+
+    global  DISP_box
+DISP_box:
+    ;---- Define Window ------------------------------------------------------
+	movff	win_width,WREG
+	bcf     STATUS,C
+	rlcf    WREG
+	movwf   aa_width+0
+	movlw   0
+	rlcf    WREG
+	movwf   aa_width+1
+	rcall   DISP_box_write
+
+    ;---- Fill Window --------------------------------------------------------
+	movlw	0x22                        ; Start Writing Data to GRAM
+	rcall	DISP_CmdWrite
+
+	clrf	PRODH                       ; Column counter.
+	bsf		DISPLAY_rs                     ; Data!
+
+DISP_box2:                              ; Loop height times
+	movff	win_height,PRODL
+    
+DISP_box3:                              ; loop width times
+	movff	win_color1,PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw                     ; Upper
+	movff	win_color2,PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw                     ; Lower
+    movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+    btfss   WREG,1                  ; Display1?
+    bra     DISP_box3a                  ; No
+    movff	win_color3,PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw                     ; Lower
+
+DISP_box3a:
+	movff	win_color1,PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw                     ; Upper
+	movff	win_color2,PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw                     ; Lower
+    movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+    btfss   WREG,1                  ; Display1?
+    bra     DISP_box3b                  ; No
+    movff	win_color3,PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw                     ; Lower
+
+DISP_box3b:
+	decfsz	PRODL,F                     ; row loop finished ?
+	bra		DISP_box3                   ; No: continue.
+
+    incf    PRODH,F                     ; column count ++
+
+    movff   win_bargraph,WREG           ; current column == bargraph ?
+    cpfseq  PRODH
+    bra     DISP_box4                   ; No: just loop.
+
+    clrf    WREG                        ; Yes: switch to black
+    movff   WREG,win_color1
+    movff   WREG,win_color2
+    movff   WREG,win_color3             ; Yes.
+DISP_box4:
+    movff   win_width,WREG
+    cpfseq  PRODH
+    bra     DISP_box2
+
+	setf    WREG                        ; Reset bargraph mode...
+	movff   WREG,win_bargraph
+
+    movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+    btfsc   WREG,1                  ; Display1?
+    return                              ; Yes, done.
+
+	movlw	0x00                        ; NOP, to stop window mode
+	bra     DISP_CmdWrite               ; Returns....
+
+;=============================================================================
+; DISP_ClearScreen: An optimized version of PLEX_box, for full screen black.
+; Trashed: WREG, PROD
+
+    global  DISP_ClearScreen
+DISP_ClearScreen:
+    movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+    btfsc   WREG,1                  ; Display1?
+    bra     DISP_ClearScreen_display1; Yes
+
+	movlw	0x35				; VerticalStartAddress HIGH:LOW
+	rcall	DISP_CmdWrite
+	mullw   0
+	rcall	DISP_DataWrite_PROD
+
+	movlw	0x36				; VerticalEndAddress HIGH:LOW
+	rcall	DISP_CmdWrite
+	movlw	0x01
+	rcall	DISP_DataWrite		
+	movlw	0x3F
+	rcall	DISP_DataWrite		
+
+	movlw	0x37				; HorizontalAddress START:END
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite		
+	movlw	0xEF
+	rcall	DISP_DataWrite		
+
+	movlw	0x20				; Start Address Horizontal (.0 - .239)
+	rcall	DISP_CmdWrite
+	rcall	DISP_DataWrite_PROD
+
+	movlw	0x21				; Start Address Vertical (.0 - .319)
+	rcall	DISP_CmdWrite
+	rcall	DISP_DataWrite_PROD
+
+	movlw	0x22                ; Start Writing Data to GRAM
+	rcall	DISP_CmdWrite
+
+	; See Page 101 of DISPLAY Driver IC Datasheet how to handle rs/rw clocks
+	bsf		DISPLAY_rs             ; Data!
+
+	movlw	.160
+	movwf	PRODH
+DISP_ClearScreen2:
+	movlw	.240
+	movwf	PRODL
+DISP_ClearScreen3:
+
+	clrf	PORTD               ; Need to generate trace here too.
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; Upper
+
+    clrf	PORTD               ; Need to generate trace here too.
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; Lower
+
+	clrf	PORTD               ; Need to generate trace here too.
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; Upper
+
+    clrf	PORTD               ; Need to generate trace here too.
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; Lower
+
+	decfsz	PRODL,F
+	bra		DISP_ClearScreen3
+	decfsz	PRODH,F
+	bra		DISP_ClearScreen2
+
+	movlw	0x00					; NOP, to stop Address Update Counter
+	bra     DISP_CmdWrite
+
+DISP_ClearScreen_display1:
+    ; Column Address start
+	movlw	0x02
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x03
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+
+; Column Address end
+	movlw	0x04
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x05
+	rcall	DISP_CmdWrite
+	movlw	0xEF
+	rcall	DISP_DataWrite
+
+; Row address start
+	movlw	0x06
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x07
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+
+; Row address end
+	movlw	0x08
+	rcall	DISP_CmdWrite
+	movlw	0x01
+	rcall	DISP_DataWrite
+	movlw	0x09
+	rcall	DISP_CmdWrite
+	movlw	0x3F
+	rcall	DISP_DataWrite
+
+	movlw	0x22                ; Start Writing Data to GRAM
+	rcall	DISP_CmdWrite
+
+	bsf		DISPLAY_rs             ; Data!
+
+	movlw	.160
+	movwf	PRODH
+DISP_ClearScreen2_display1:
+	movlw	.240
+	movwf	PRODL
+	clrf	PORTD               ; Need to generate trace here too.
+DISP_ClearScreen3_display1:
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; Upper
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; High
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; Lower
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; Upper
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; High
+    bcf		DISPLAY_rw
+	bsf		DISPLAY_rw             ; Lower
+	decfsz	PRODL,F
+	bra		DISP_ClearScreen3_display1
+	decfsz	PRODH,F
+	bra		DISP_ClearScreen2_display1
+    return
+
+
+; -----------------------------
+; DISP Write Cmd via W
+; -----------------------------
+DISP_CmdWrite:
+	bcf		DISPLAY_rs					; Command!
+	movwf	PORTD					; Move Data to PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw
+	return
+
+; -----------------------------
+; DISP Write Display Data via W
+; -----------------------------
+DISP_DataWrite:
+	bsf		DISPLAY_rs					; Data!
+	movwf	PORTD					; Move Data to PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw
+	return
+
+; -----------------------------
+; DISP Data Cmd via W
+; -----------------------------
+DISP_DataWrite_PROD:
+	bsf		DISPLAY_rs					; Data!
+	movff	PRODH,PORTD				; Move high byte to PORTD (DISPLAY is bigendian)
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw
+	movff	PRODL,PORTD				; Move low byte to PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw
+    movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+    btfss   WREG,1                  ; Display1?
+    return                          ; No, done.
+    movff   win_color3,PORTD        ; Move low byte to PORTD
+	bcf		DISPLAY_rw
+	bsf		DISPLAY_rw
+	return
+
+
+; -----------------------------
+; DISP Read data into WREG
+; -----------------------------
+; NOTE: you should "setf TRISD" before calling this function,
+;       to make PortD an input port...
+DISP_DataRead:
+	bsf		DISPLAY_rs					; Data register.
+	bcf		DISPLAY_e_nwr              ; Read enable.
+	nop
+	nop
+	nop
+	nop
+	movf	PORTD,W				    ; Read byte.
+	bsf		DISPLAY_e_nwr              ; release bus.
+	return
+
+; -----------------------------
+; DISP boot
+; -----------------------------
+DISPLAY_boot:
+    movlw   LOW     0x17FDC
+    movwf   TBLPTRL
+    movlw   HIGH    0x17FDC
+    movwf   TBLPTRH
+    movlw   UPPER   0x17FDC
+    movwf   TBLPTRU
+    TBLRD*
+    movlw   0x01
+    cpfseq  TABLAT      ; Display1?
+    bra     display0_init ; No, Display0
+
+    banksel win_flags
+    bsf     win_flags,0
+    bsf     win_flags,1
+    banksel flag1
+    bcf     DISPLAY_hv     ; Backlight off
+    nop
+	bcf		DISPLAY_vdd
+    WAITMS	d'10'
+	bsf		DISPLAY_vdd
+    WAITMS	d'100'
+	bsf		DISPLAY_rw
+	nop
+	bcf		DISPLAY_cs
+	nop
+	bsf		DISPLAY_nreset
+	WAITMS	d'1'
+	bcf		DISPLAY_nreset
+	WAIT10US	d'2'
+	bsf		DISPLAY_nreset
+	WAITMS	d'120'
+    bsf		DISPLAY_e_nwr              ; release bus.
+    rcall   display1_init           ; Init sequence
+	rcall	DISP_ClearScreen
+	WAITMS	d'60'
+	bsf		DISPLAY_hv     ; Backlight on
+	return
+
+display1_init:
+    movlw   LOW     display1_config_table
+    movwf   TBLPTRL
+    movlw   HIGH    display1_config_table
+    movwf   TBLPTRH
+    movlw   UPPER   display1_config_table
+    movwf   TBLPTRU
+display_init_loop:
+    TBLRD*+
+    movlw   0xFF
+    cpfseq  TABLAT
+    bra     display_config_write    ; Write Config pair to Display
+    ; Delay ms or quit (return)
+    TBLRD*+
+    tstfsz  TABLAT                  ; End of config?
+    bra     $+4                     ; No
+    return                          ; Done.
+    movf    TABLAT,W
+    call    WAITMSX                 ; Wait WREG milliseconds
+    bra     display_init_loop       ; Loop
+
+display_config_write:               ; With command in WREG
+    movf    TABLAT,W
+    rcall	DISP_CmdWrite           ; Write command
+    TBLRD*+                         ; Get config
+    movf    TABLAT,W
+	rcall	DISP_DataWrite          ; Write config
+    bra     display_init_loop       ; Loop
+
+
+display1_config_table:
+    ; Reg, Dat or 0xFF, Delay or 0xFF, 0x00 (End)
+    db  0x96,0x01
+    db  0x19,0x87
+    db  0xFF,.10
+    db  0x26,0x80
+    db  0x1B,0x0C
+    db  0x43,0x00
+    db  0x20,0x00
+    db  0x1F,0x07
+    db  0x44,0x7F
+    db  0x45,0x14
+    db  0x1D,0x05
+    db  0x1E,0x00
+    db  0x1C,0x04
+    db  0x1B,0x14
+    db  0xFF,.40
+    db  0x43,0x80
+    db  0x42,0x08
+    db  0x23,0x95
+    db  0x24,0x95
+    db  0x25,0xFF
+    db  0x21,0x10
+    db  0x2B,0x00
+    db  0x95,0x01
+    db  0x1A,0x00
+    db  0x93,0x0F
+    db  0x70,0x66
+    db  0x18,0x01
+    db  0x46,0x86
+    db  0x47,0x60
+    db  0x48,0x01
+    db  0x49,0x67
+    db  0x4A,0x46
+    db  0x4B,0x13
+    db  0x4C,0x01
+    db  0x4D,0x67
+    db  0x4E,0x00
+    db  0x4F,0x13
+    db  0x50,0x02
+    db  0x51,0x00
+    db  0x38,0x00
+    db  0x39,0x00
+    db  0x27,0x02
+    db  0x28,0x03
+    db  0x29,0x08
+    db  0x2A,0x08
+    db  0x2C,0x08
+    db  0x2D,0x08
+    db  0x35,0x09
+    db  0x36,0x09
+    db  0x91,0x14
+    db  0x37,0x00
+    db  0x01,0x06
+    db  0x3A,0xA1
+    db  0x3B,0xA1
+    db  0x3C,0xA1
+    db  0x3D,0x00
+    db  0x3E,0x2D
+    db  0x40,0x03
+    db  0x41,0xCC
+    db  0x0A,0x00
+    db  0x0B,0x00
+    db  0x0C,0x01
+    db  0x0D,0x3F
+    db  0x0E,0x00
+    db  0x0F,0x00
+    db  0x10,0x01
+    db  0x11,0x40
+    db  0x12,0x00
+    db  0x13,0x00
+    db  0x14,0x00
+    db  0x15,0x00
+    db  0x02,0x00
+    db  0x03,0x00
+    db  0x04,0x00
+    db  0x05,0xEF
+    db  0x06,0x00
+    db  0x07,0x00
+    db  0x08,0x01
+    db  0x09,0x3F
+    db  0x16,0x88
+    db  0x72,0x00
+    db  0x22,0x60
+    db  0x94,0x0A
+    db  0x90,0x7F
+    db  0x26,0x84
+    db  0xFF,.40
+    db  0x26,0xA4
+    db  0x26,0xAC
+    db  0xFF,.40
+    db  0x26,0xBC
+    db  0x96,0x00
+    db  0xFF,0x00   ; End of table pair
+
+
+display0_init:          ; Display0
+    banksel win_flags
+    bcf     win_flags,1
+    banksel flag1
+	bcf		DISPLAY_hv
+	WAITMS	d'32'
+	bsf		DISPLAY_vdd
+	nop
+	bcf		DISPLAY_cs
+	nop
+	bsf		DISPLAY_nreset
+;	WAITMS	d'10'			; Quick wake-up
+	WAITMS	d'250'			; Standard wake-up
+	bsf		DISPLAY_e_nwr	
+	nop
+	bcf		DISPLAY_nreset
+	WAIT10US	d'2'
+	bsf		DISPLAY_nreset
+	WAITMS	d'10'
+
+	movlw	0x24				; 80-System 8-Bit Mode
+	rcall	DISP_CmdWrite
+
+	movlw	0x02				; RGB Interface Control (S6E63D6 Datasheet page 42)
+	rcall	DISP_CmdWrite
+	movlw	0x00				; X X X X X X X RM
+	rcall	DISP_DataWrite
+	movlw	0x00				; DM X RIM1 RIM0 VSPL HSPL EPL DPL
+	rcall	DISP_DataWrite		; System Interface: RIM is ignored, Internal Clock
+
+	movlw	0x03				; Entry Mode (S6E63D6 Datasheet page 46)
+	rcall	DISP_CmdWrite
+	movlw	0x00				; CLS MDT1 MDT0 	BGR 	X  	X  	X  	SS  65k Color
+	rcall	DISP_DataWrite
+
+	; Change direction for block-writes of pixels
+    lfsr    FSR0,win_flags
+	btfss   INDF0,0             ; BANK-SAFE bit test.
+	movlw	b'00110000'			; [normal]  X  	X 	 I/D1 	I/D0 	X  	X  	X 	AM
+	btfsc   INDF0,0
+    movlw   b'00000000'         ; [flipped] X  	X 	 I/D1 	I/D0 	X  	X  	X 	AM
+	rcall	DISP_DataWrite
+
+	movlw	0x18
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x28
+	rcall	DISP_DataWrite
+
+	movlw	0xF8
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x0F
+	rcall	DISP_DataWrite
+
+	movlw	0xF9
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x0F
+	rcall	DISP_DataWrite
+
+	movlw	0x10
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+
+; Now Gamma settings...
+	rcall	DISP_brightness_full
+	;rcall	DISP_brightness_low
+; End Gamma Settings
+
+	rcall	DISP_ClearScreen
+
+	bsf		DISPLAY_hv
+	WAITMS	d'32'
+	bsf		DISPLAY_hv
+	WAITMS	d'32'
+	bsf		DISPLAY_hv
+
+	movlw	0x05
+	rcall	DISP_CmdWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x01
+	rcall	DISP_DataWrite			; Display ON
+	return
+
+
+DISP_brightness_full: ; Choose between Eco and High...
+	btfsc	DISPLAY_brightness_high		; DISPLAY brightness (=0: Eco, =1: High)
+	bra		DISP_brightness_full_high
+; Mid
+    bsf     PORTB,7
+    bcf     PORTB,6
+
+    movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+    btfsc   WREG,1                  ; Display1?
+    return                          ; Yes, done.
+
+	movlw	0x70
+	rcall	DISP_CmdWrite
+	movlw	0x1B
+	rcall	DISP_DataWrite
+	movlw	0x80
+	rcall	DISP_DataWrite
+	movlw	0x71
+	rcall	DISP_CmdWrite
+	movlw	0x1F
+	rcall	DISP_DataWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x72
+	rcall	DISP_CmdWrite
+	movlw	0x22
+	rcall	DISP_DataWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+
+	movlw	0x73
+	rcall	DISP_CmdWrite
+	movlw	0x17
+	rcall	DISP_DataWrite
+	movlw	0x11
+	rcall	DISP_DataWrite
+	movlw	0x74
+	rcall	DISP_CmdWrite
+	movlw	0x1A
+	rcall	DISP_DataWrite
+	movlw	0x0E
+	rcall	DISP_DataWrite
+
+	movlw	0x75
+	rcall	DISP_CmdWrite
+	movlw	0x1D
+	rcall	DISP_DataWrite
+	movlw	0x15
+	rcall	DISP_DataWrite
+	movlw	0x76
+	rcall	DISP_CmdWrite
+	movlw	0x18
+	rcall	DISP_DataWrite
+	movlw	0x11
+	rcall	DISP_DataWrite
+
+	movlw	0x77
+	rcall	DISP_CmdWrite
+	movlw	0x1E
+	rcall	DISP_DataWrite
+	movlw	0x18
+	rcall	DISP_DataWrite
+	movlw	0x78
+	rcall	DISP_CmdWrite
+	movlw	0x1D
+	rcall	DISP_DataWrite
+	movlw	0x11
+	rcall	DISP_DataWrite
+	return
+
+DISP_brightness_full_high:
+; Full
+    bsf     PORTB,7
+    bsf     PORTB,6
+
+    movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+    btfsc   WREG,1                  ; Display1?
+    return                          ; Yes, done.
+
+	movlw	0x70
+	rcall	DISP_CmdWrite
+	movlw	0x1F
+	rcall	DISP_DataWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x71
+	rcall	DISP_CmdWrite
+	movlw	0x23
+	rcall	DISP_DataWrite
+	movlw	0x80
+	rcall	DISP_DataWrite
+	movlw	0x72
+	rcall	DISP_CmdWrite
+	movlw	0x2A
+	rcall	DISP_DataWrite
+	movlw	0x80
+	rcall	DISP_DataWrite
+
+	movlw	0x73
+	rcall	DISP_CmdWrite
+	movlw	0x15
+	rcall	DISP_DataWrite
+	movlw	0x11
+	rcall	DISP_DataWrite
+	movlw	0x74
+	rcall	DISP_CmdWrite
+	movlw	0x1C
+	rcall	DISP_DataWrite
+	movlw	0x11
+	rcall	DISP_DataWrite
+
+	movlw	0x75
+	rcall	DISP_CmdWrite
+	movlw	0x1B
+	rcall	DISP_DataWrite
+	movlw	0x15
+	rcall	DISP_DataWrite
+	movlw	0x76
+	rcall	DISP_CmdWrite
+	movlw	0x1A
+	rcall	DISP_DataWrite
+	movlw	0x15
+	rcall	DISP_DataWrite
+
+	movlw	0x77
+	rcall	DISP_CmdWrite
+	movlw	0x1C
+	rcall	DISP_DataWrite
+	movlw	0x18
+	rcall	DISP_DataWrite
+	movlw	0x78
+	rcall	DISP_CmdWrite
+	movlw	0x21
+	rcall	DISP_DataWrite
+	movlw	0x15
+	rcall	DISP_DataWrite
+	return
+
+
+DISP_brightness_low:
+;Low
+    bcf     PORTB,7
+    bcf     PORTB,6
+    movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+    btfsc   WREG,1                  ; Display1?
+    return                          ; Yes, done.
+
+	movlw	0x70
+	rcall	DISP_CmdWrite
+	movlw	0x14
+	rcall	DISP_DataWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x71
+	rcall	DISP_CmdWrite
+	movlw	0x17
+	rcall	DISP_DataWrite
+	movlw	0x00
+	rcall	DISP_DataWrite
+	movlw	0x72
+	rcall	DISP_CmdWrite
+	movlw	0x15
+	rcall	DISP_DataWrite
+	movlw	0x80
+	rcall	DISP_DataWrite
+
+	movlw	0x73
+	rcall	DISP_CmdWrite
+	movlw	0x15
+	rcall	DISP_DataWrite
+	movlw	0x11
+	rcall	DISP_DataWrite
+	movlw	0x74
+	rcall	DISP_CmdWrite
+	movlw	0x14
+	rcall	DISP_DataWrite
+	movlw	0x0B
+	rcall	DISP_DataWrite
+
+	movlw	0x75
+	rcall	DISP_CmdWrite
+	movlw	0x1B
+	rcall	DISP_DataWrite
+	movlw	0x15
+	rcall	DISP_DataWrite
+	movlw	0x76
+	rcall	DISP_CmdWrite
+	movlw	0x13
+	rcall	DISP_DataWrite
+	movlw	0x0E
+	rcall	DISP_DataWrite
+
+	movlw	0x77
+	rcall	DISP_CmdWrite
+	movlw	0x1C
+	rcall	DISP_DataWrite
+	movlw	0x18
+	rcall	DISP_DataWrite
+	movlw	0x78
+	rcall	DISP_CmdWrite
+	movlw	0x15
+	rcall	DISP_DataWrite
+	movlw	0x0E
+	rcall	DISP_DataWrite
+	
+	return
+
+DISP_set_color:;Converts 8Bit RGB b'RRRGGGBB' into 16Bit RGB b'RRRRRGGG GGGBBBBB'
+	movwf	DISPLAY1_temp				; Get 8Bit RGB b'RRRGGGBB'
+	movwf	DISPLAY2_temp				; Copy
+
+    movff   win_flags,WREG          ; Display1? win_flags is in bank0...
+    btfsc   WREG,1                  ; Display1?
+    bra     DISP_set_color_display1 ; Yes
+
+    ; Display0
+	; Mask Bit 7,6,5,4,3,2
+	movlw	b'00000011'
+	andwf	DISPLAY2_temp,F
+
+	movlw	b'00000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'01010000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'10100000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'11111000'
+	movwf	DISPLAY3_temp				; Blue done.
+
+	movff	DISPLAY1_temp,	DISPLAY2_temp	; Copy
+	; Mask Bit 7,6,5,1,0
+	movlw	b'00011100'
+	andwf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+
+	movlw	b'00000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00000100'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00001000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00001100'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00010000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00010100'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00100000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00111111'
+	movwf	DISPLAY4_temp			
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY3_temp,F
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY3_temp,F
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY3_temp,F		; DISPLAY3_temp (b'GGGBBBBB') done.
+
+	movff	DISPLAY1_temp,	DISPLAY2_temp	; Copy
+	clrf	DISPLAY1_temp
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY1_temp,F
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY1_temp,F
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY1_temp,F		; Green done.
+
+	; Mask Bit 4,3,2,1,0
+	movlw	b'11100000'
+	andwf	DISPLAY2_temp,F
+
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+
+	movlw	b'00000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00000100'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00001000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00001100'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00010000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00010100'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00100000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00111111'
+	movwf	DISPLAY4_temp			
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY1_temp,F
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY1_temp,F	
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY1_temp,F
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY1_temp,F
+
+	rrcf	DISPLAY4_temp,F
+	rrcf	DISPLAY1_temp,F		; Red done.
+
+	movff	DISPLAY1_temp,win_color1
+	movff	DISPLAY3_temp,win_color2	; Set Bank0 Color registers...
+	return
+
+DISP_set_color_display1:
+	; Mask Bit 7,6,5,4,3,2
+	movlw	b'00000011'
+	andwf	DISPLAY2_temp,F
+
+	movlw	b'00000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'01010000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'10100000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'11111000'
+;	movwf	DISPLAY3_temp				; Blue done.
+    movff   WREG,win_color3              ; B
+
+	movff	DISPLAY1_temp,	DISPLAY2_temp	; Copy
+	; Mask Bit 7,6,5,1,0
+	movlw	b'00011100'
+	andwf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+
+	movlw	b'00000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00010000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00100000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00110000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'01000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'01010000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'10000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'11111100'
+;	movwf	DISPLAY4_temp
+    movff   WREG,win_color2              ; G
+
+	movff	DISPLAY1_temp,	DISPLAY2_temp	; Copy
+	; Mask Bit 4,3,2,1,0
+	movlw	b'11100000'
+	andwf	DISPLAY2_temp,F
+
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+	rrncf	DISPLAY2_temp,F
+
+	movlw	b'00000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00010000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00100000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'00110000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'01000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'01010000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'10000000'
+	dcfsnz	DISPLAY2_temp,F
+	movlw	b'11111100'
+;	movwf	DISPLAY4_temp
+    movff   WREG,win_color1              ; R
+	return