Mercurial > public > mk2
view code_part1/OSTC_code_asm_part1/display_lowlevel.asm @ 813:c87b9f2fb2f6
wakeup from deep sleep mode automatically upon USB connect
author | heinrichsweikamp |
---|---|
date | Tue, 14 Apr 2015 14:50:11 +0200 |
parents | d79aa21ee54c |
children | 2a0e5d884fc3 |
line wrap: on
line source
; 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_WRITE 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 btfsc WREG,1 ; Display1 bra pixel_write_noflip_H_display1 ; Yes. 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 ; And return... pixel_write_noflip_H_display1: movlw 0x06 rcall DISP_CmdWrite movf PRODH,W rcall DISP_DataWrite movlw 0x07 rcall DISP_CmdWrite movf PRODL,W rcall DISP_DataWrite incf PRODL,F movlw .0 addwfc PRODH,F ;+1 movlw 0x08 rcall DISP_CmdWrite movf PRODH,W rcall DISP_DataWrite movlw 0x09 rcall DISP_CmdWrite movf PRODL,W bra DISP_DataWrite ; And return... ;----------------------------------------------------------------------------- ; 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 ; Display1? win_flags is in bank0... btfsc PRODL,1 bra half_pixel_write_1_display1 ; Yes. btfsc PRODL,0 ; 180° rotation ? sublw .239 ; 239-Y --> Y mullw 1 ; Copy row to PRODL (PRODH=0) 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 return ; Done. half_pixel_write_1_display1: mullw 1 ; Copy row to PRODL (PRODH=0) ; Row address start movlw 0x02 rcall DISP_CmdWrite movlw .0 rcall DISP_DataWrite movlw 0x03 rcall DISP_CmdWrite movf PRODL,W rcall DISP_DataWrite incf PRODL,F movlw 0x04 rcall DISP_CmdWrite movlw .0 rcall DISP_DataWrite movlw 0x05 rcall DISP_CmdWrite movf PRODL,W rcall DISP_DataWrite movlw 0x22 ; Start Writing Data to GRAM rcall DISP_CmdWrite bsf DISPLAY_rs ; Data! movff win_color4, PORTD bcf DISPLAY_rw bsf DISPLAY_rw ; Upper movff win_color5, PORTD bcf DISPLAY_rw bsf DISPLAY_rw ; High movff win_color6, PORTD bcf DISPLAY_rw bsf DISPLAY_rw ; Lower return ; ----------------------------- ; DISP Display Off ; ----------------------------- DISP_DisplayOff: rcall DISP_ClearScreen clrf PORTD bcf DISPLAY_hv bcf DISPLAY_vdd bcf DISPLAY_cs bcf DISPLAY_e_nwr bcf DISPLAY_rw bcf DISPLAY_rs 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 (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_flags,WREG ; Display1? win_flags is in bank0... btfsc WREG,1 ; Display1? bra DISP_box3aa ; Yes movff win_color1,PORTD bcf DISPLAY_rw bsf DISPLAY_rw ; Upper movff win_color2,PORTD bra DISP_box3a ; Done. DISP_box3aa: movff win_color4,PORTD bcf DISPLAY_rw bsf DISPLAY_rw ; Upper movff win_color5,PORTD bcf DISPLAY_rw bsf DISPLAY_rw ; Lower/High movff win_color6,PORTD DISP_box3a: bcf DISPLAY_rw bsf DISPLAY_rw ; Lower/High movff win_flags,WREG ; Display1? win_flags is in bank0... btfsc WREG,1 ; Display1? bra DISP_box3ab ; Yes movff win_color1,PORTD bcf DISPLAY_rw bsf DISPLAY_rw ; Upper movff win_color2,PORTD bra DISP_box3b DISP_box3ab: movff win_color4,PORTD bcf DISPLAY_rw bsf DISPLAY_rw ; Upper movff win_color5,PORTD bcf DISPLAY_rw bsf DISPLAY_rw ; High movff win_color6,PORTD DISP_box3b: bcf DISPLAY_rw bsf DISPLAY_rw ; Lower 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 movff WREG,win_color4 movff WREG,win_color5 movff WREG,win_color6 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! clrf PORTD movlw .160 movwf PRODH DISP_ClearScreen2: movlw .240 movwf PRODL DISP_ClearScreen3: bcf DISPLAY_rw bsf DISPLAY_rw ; Upper bcf DISPLAY_rw bsf DISPLAY_rw ; Lower bcf DISPLAY_rw bsf DISPLAY_rw ; Upper 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 ; And return... 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 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(est) 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: movff win_flags,WREG ; Display1? win_flags is in bank0... btfsc WREG,1 ; Display1? return ; Yes, done. 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 display1_init_loop: TBLRD*+ movlw 0xFF cpfseq TABLAT bra display1_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 display1_init_loop ; Loop display1_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 display1_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 btfsc DISPLAY_hv bra $-4 WAITMS d'32' bsf DISPLAY_vdd nop bcf DISPLAY_cs nop bsf DISPLAY_nreset 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 movlw b'00000000' ; [flipped] X X I/D1 I/D0 X X X AM btfss INDF0,0 ; BANK-SAFE bit test. movlw b'00110000' ; [normal] X X I/D1 I/D0 X X X AM rcall DISP_DataWrite movlw LOW display0_config_table movwf TBLPTRL movlw HIGH display0_config_table movwf TBLPTRH movlw UPPER display0_config_table movwf TBLPTRU rcall display0_init_loop rcall DISP_brightness_full ; Gamma settings... rcall DISP_ClearScreen bsf DISPLAY_hv ; OLED volatages on return display0_config_table: ; Reg, Dat0, Dat1 or 0xFF,0x00,0x00 for end db 0x18,0x00,0x28,0xF8,0x00,0x0F db 0xF9,0x00,0x0F,0x10,0x00,0x00 db 0x05,0x00,0x01,0xFF,0x00,0x00 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 nop bcf PORTB,6 movff win_flags,WREG ; Display1? win_flags is in bank0... btfsc WREG,1 ; Display1? return ; Yes, done. movlw LOW display0_gamma_high_table movwf TBLPTRL movlw HIGH display0_gamma_high_table movwf TBLPTRH movlw UPPER display0_gamma_high_table movwf TBLPTRU bra display0_init_loop ; And return... DISP_brightness_full_high: ; Full bsf PORTB,7 nop bsf PORTB,6 movff win_flags,WREG ; Display1? win_flags is in bank0... btfsc WREG,1 ; Display1? return ; Yes, done. movlw LOW display0_gamma_full_table movwf TBLPTRL movlw HIGH display0_gamma_full_table movwf TBLPTRH movlw UPPER display0_gamma_full_table movwf TBLPTRU bra display0_init_loop ; And return... DISP_brightness_low: ;Low bcf PORTB,7 nop bcf PORTB,6 movff win_flags,WREG ; Display1? win_flags is in bank0... btfsc WREG,1 ; Display1? return ; Yes, done. movlw LOW display0_gamma_low_table movwf TBLPTRL movlw HIGH display0_gamma_low_table movwf TBLPTRH movlw UPPER display0_gamma_low_table movwf TBLPTRU bra display0_init_loop ; And return... display0_init_loop: TBLRD*+ movlw 0xFF cpfseq TABLAT bra display0_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 display0_init_loop ; Loop display0_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 TBLRD*+ ; Get config movf TABLAT,W rcall DISP_DataWrite ; Write config bra display0_init_loop ; Loop display0_gamma_high_table: ; Reg, Dat0, Dat1 or 0xFF,0x00,0x00 for end db 0x70,0x1B,0x80,0x71,0x1F,0x00 db 0x72,0x22,0x00,0x73,0x17,0x11 db 0x74,0x1A,0x0E,0x75,0x1D,0x15 db 0x76,0x18,0x11,0x77,0x1E,0x18 db 0x78,0x1D,0x11,0xFF,0x00,0x00 display0_gamma_full_table: ; Reg, Dat0, Dat1 or 0xFF,0x00,0x00 for end db 0x70,0x1F,0x00,0x71,0x23,0x80 db 0x72,0x2A,0x80,0x73,0x15,0x11 db 0x74,0x1C,0x11,0x75,0x1B,0x15 db 0x76,0x1A,0x15,0x77,0x1C,0x18 db 0x78,0x21,0x15,0xFF,0x00,0x00 display0_gamma_low_table: ; Reg, Dat0, Dat1 or 0xFF,0x00,0x00 for end db 0x70,0x14,0x00,0x71,0x17,0x00 db 0x72,0x15,0x80,0x73,0x15,0x11 db 0x74,0x14,0x0B,0x75,0x1B,0x15 db 0x76,0x13,0x0E,0x77,0x1C,0x18 db 0x78,0x15,0x0E,0xFF,0x00,0x00 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 WREG,win_color6 ; Another (bank-safe) copy ; 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'00011000' dcfsnz DISPLAY2_temp,F movlw b'00011111' 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... movff win_flags,WREG ; Display1? win_flags is in bank0... btfss WREG,1 ; Display1? return ; No DISP_set_color_display1:;Converts 8Bit RGB b'RRRGGGBB' into 24Bit RGB b'00RRRRRR 00GGGGGG 00BBBBBB' movff win_color6,DISPLAY1_temp movff win_color6,DISPLAY2_temp ; 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' movff WREG,win_color6 ; 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' movff WREG,win_color5 ; G ; Mask Bit 4,3,2,1,0 movlw b'11100000' andwf DISPLAY1_temp,F rrncf DISPLAY1_temp,F rrncf DISPLAY1_temp,F rrncf DISPLAY1_temp,F rrncf DISPLAY1_temp,F rrncf DISPLAY1_temp,F movlw b'00000000' dcfsnz DISPLAY1_temp,F movlw b'00010000' dcfsnz DISPLAY1_temp,F movlw b'00100000' dcfsnz DISPLAY1_temp,F movlw b'00110000' dcfsnz DISPLAY1_temp,F movlw b'01000000' dcfsnz DISPLAY1_temp,F movlw b'01010000' dcfsnz DISPLAY1_temp,F movlw b'10000000' dcfsnz DISPLAY1_temp,F movlw b'11111100' movff WREG,win_color4 ; R return