Mercurial > public > hwos_code
diff src/tft.asm @ 0:11d4fc797f74
init
author | heinrichsweikamp |
---|---|
date | Wed, 24 Apr 2013 19:22:45 +0200 |
parents | |
children | eb72c8865f47 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tft.asm Wed Apr 24 19:22:45 2013 +0200 @@ -0,0 +1,1071 @@ +;============================================================================= +; +; File tft.asm +; +; Managing the TFT screen +; +; Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved. +;============================================================================= +; HISTORY +; 2011-05-24 : [jDG] Cleanups from initial Matthias code. + +#include "ostc3.inc" +#include "wait.inc" +#include "varargs.inc" +#include "external_flash.inc" +#include "tft_outputs.inc" +#include "eeprom_rs232.inc" + +;============================================================================= +; TFT_frame needs to backup coordinates. + CBLOCK tmp + save_top + save_height + save_left + save_width + ds_line ; Current line (0..239). + ds_column ; Current columnx2 (0..159) + ds_pixel:2 ; Current pixel color. + ds_count ; Repetition count. + ENDC + +;============================================================================= +; Basic bit-level macros + +RD_H macro + bsf tft_rd,0 + endm + +RD_L macro + bcf tft_rd,0 + endm + +RS_H macro + bsf tft_rs,0 + endm + +RS_L macro + bcf tft_rs,0 + endm + +NCS_H macro + bsf tft_cs,0 + endm + +NCS_L macro + bcf tft_cs,0 + endm + +WR_H macro + bsf tft_nwr,0 + endm + +WR_L macro + bcf tft_nwr,0 + endm + +;============================================================================= +; Byte-leve macros +; +Index_out macro low_b + movlw low_b + rcall TFT_CmdWrite + endm + +Parameter_out macro high_b, low_b + movlw high_b + movwf PORTA ; Upper + movlw low_b + rcall TFT_DataWrite + endm + + +basic CODE + + +;============================================================================= +; TFT_write_flash_image +; +; Inputs: FSR2 = EEPROM address / 256 +; win_left, win_top : imagte CENTER position +; Outputs: win_height, win_width. +; image copyed on screen. +; Trashed: PROD, hi, lo +; + global TFT_write_flash_image +TFT_write_flash_image: + ; Get back the full 24bit EEPROM address + clrf ext_flash_address+0 + movff FSR2L,ext_flash_address+1 + movf FSR2H,W + iorlw 0x30 + movwf ext_flash_address+2 + + ; Read header: width and height + global TFT_write_flash_image_addr +TFT_write_flash_image_addr: + call ext_flash_read_block_start + movff SSP2BUF,win_width+0 + movwf SSP2BUF ; Write to buffer to initiate new read + btfss SSP2STAT, BF ; Next byte ready ? + bra $-2 ; NO: wait... + movff SSP2BUF,win_width+1 + movwf SSP2BUF ; Write to buffer to initiate new read + btfss SSP2STAT, BF ; Next byte ready ? + bra $-2 ; NO: wait... + movff SSP2BUF,win_height + movwf SSP2BUF ; Write to buffer to initiate new read + btfss SSP2STAT, BF ; Next byte ready ? + bra $-2 ; NO: wait... + movff SSP2BUF,WREG ; drop 4th byte. + movwf SSP2BUF ; Write to buffer to initiate new read + btfss SSP2STAT, BF ; Next byte ready ? + bra $-2 ; NO: wait... + + ; Sanity check on header to avoid badly uploaded images. + iorwf WREG ; Check height < 256 + bnz TFT_write_flash_image_failed + movf win_width+1,W ; Check width < 512 + andlw 0xFE + bnz TFT_write_flash_image_failed + + ; Center image on win_top, win_left values + bcf STATUS,C ; Clear carry + rrcf win_height,W ; And get height/2 + subwf win_top,F ; top -= height/2 + rrcf win_width+1,W ; Get 9th bit into carry + rrcf win_width+0,W ; Get width/2 (in 0..320 range) + bcf STATUS,C + rrcf WREG,W ; Get width/2 in 0..160 range + subwf win_leftx2,F ; left -= width/2 + + rcall TFT_box_write ; Inputs : win_top, win_leftx2, win_height, win_width(in 1..320 range) + + ; Compute number of pixels to move (result on 17 bits !) + clrf TBLPTRU + movf win_width+0,W + mulwf win_height ; Result in PRODL:H + movf win_width+1,W + bz TFT_write_flash_image_1 ; width > 8bits ? + movf win_height,W ; YES: add extra + addwf PRODH,F + rlcf TBLPTRU ; And carry into upper register. +TFT_write_flash_image_1: + incf PRODH,F ; Pre-condition nested loops + incf TBLPTRU,F + + ; Write pixels + Index_out 0x22 ; Frame Memory Data Write start + RS_H ; Data + +TFT_write_flash_image_loop: + btfss SSP2STAT, BF ; Buffer full? + bra $-2 ; NO: wait... + movff SSP2BUF,PORTH ; Read lo + movwf SSP2BUF ; Write to buffer to initiate new read + + btfss SSP2STAT, BF ; Buffer full? + bra $-2 ; NO: wait... + movff SSP2BUF,PORTA ; And read hi + movwf SSP2BUF ; Write to buffer to initiate new read + WR_L + WR_H ; Write 1 Pixel + + decfsz PRODL,F + bra TFT_write_flash_image_loop + decfsz PRODH,F + bra TFT_write_flash_image_loop + decfsz TBLPTRU,F + bra TFT_write_flash_image_loop + + btfss SSP2STAT, BF ; Buffer full? + bra $-2 ; No, wait + movf SSP2BUF,W ; Read dummy byte + + bsf flash_ncs ; CS=1 + movlw 0x00 ; NOP, to stop window mode + bra TFT_CmdWrite ; This routine "returns" + + ;---- Draw a 4x4 red square in place of missing images... +TFT_write_flash_image_failed: + movlw -1 + addwf win_leftx2,F + movlw -2 + addwf win_top,F + movlw 2 + movwf win_width+0 + clrf win_width+1 + movlw 4 + movwf win_height + movlw color_red + rcall TFT_set_color + goto TFT_box + +;============================================================================= +; + + global TFT_CmdWrite +TFT_CmdWrite: + RS_L ; Command + clrf PORTA ; Upper + movwf PORTH ; Lower + WR_L + WR_H ; Tick + return; + + global TFT_DataWrite +TFT_DataWrite: + RS_H ; Data + movwf PORTH ; Lower + WR_L + WR_H ; Tick + return + +;============================================================================= +; + global TFT_ClearScreen +TFT_ClearScreen: + Index_out 0x50 ; Window Horizontal Start Address + Parameter_out 0x00, 0x00 ; 0-239 + Index_out 0x51 ; Window Horizontal End Address + Parameter_out 0x00, 0xEF ; 0-239 + Index_out 0x52 ; Window Vertical Start Address + Parameter_out 0x00, 0x00 ; 0-319 + Index_out 0x53 ; Window Vertical End Address + Parameter_out 0x01, 0x3F ; 0-319 + Index_out 0x20 ; Frame Memory Horizontal Address + Parameter_out 0x00, 0x00 ; 0-239 + Index_out 0x21 ; Frame Memory Vertical Address + Parameter_out 0x01, 0x3F ; 0-319 + + Index_out 0x22 ; Frame Memory Data Write start + + RD_H ; Not Read + RS_H ; Data + NCS_L ; Not CS + clrf PORTA ; Data Upper + clrf PORTH ; Data Lower + + movlw d'10' + movwf tft_temp3 +TFT_ClearScreen2: + movlw d'30' + movwf tft_temp2 +TFT_ClearScreen3: + clrf tft_temp1 ; 30*10*256=76800 Pixels -> Clear complete 240*320 +TFT_ClearScreen4: + WR_L + WR_H ; Tick + decfsz tft_temp1,F + bra TFT_ClearScreen4 + decfsz tft_temp2,F + bra TFT_ClearScreen3 + decfsz tft_temp3,F + bra TFT_ClearScreen2 + return + +;============================================================================= +; + global TFT_DisplayOff +TFT_DisplayOff: + clrf CCPR1L ; PWM OFF + clrf PORTA + clrf PORTH + RD_L ; LOW + nop + RS_L ; LOW + bcf tft_nwr + nop + bcf tft_cs + nop + bcf tft_nreset + WAITMS d'1' + bsf tft_power ; inverted... + bcf lightsen_power ; power-down light sensor + return + +; ----------------------------- +; TFT boot +; ----------------------------- + global TFT_boot +TFT_boot: + clrf PORTA + clrf PORTH + RD_L ; LOW + bcf tft_nwr + nop + bcf tft_cs + nop + bcf tft_nreset + WAITMS d'1' + bcf tft_power ; inverted... + WAITMS d'1' + + RD_H ; Keep high + WR_H ; + NCS_L ; Not CS + + WAITMS d'2' + bsf tft_nreset + WAITMS d'150' + bsf lightsen_power ; Supply power to light sensor + +; Data Transfer Synchronization + Parameter_out 0x00, 0x00 + Parameter_out 0x00, 0x00 + +; Init through config table... + 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 + + Index_out 0x22 +; WAITMS d'81' ; 46 + call TFT_ClearScreen + Index_out 0x07 + Parameter_out 0x01, 0x00 + return + + +display0_config_table: + ; Reg, Dat0, Dat1 or 0xFF,0x00,0x00 for end + db 0xA4,0x00,0x01,0xFF,.002,0x00 + db 0x09,0x00,0x01,0x92,0x04,0x00 + db 0x93,0x04,0x02,0x94,0x00,0x02 + db 0x07,0x00,0x00,0x10,0x04,0x30 + db 0x11,0x02,0x37,0x12,0x11,0x8D + db 0x13,0x11,0x00,0x01,0x01,0x00 + db 0x02,0x02,0x00,0x03,0x50,0x20 + db 0x0A,0x00,0x08,0x0D,0x00,0x00 + db 0x0E,0x00,0x30,0xFF,.151,0x00 + db 0x12,0x11,0xBD,0x20,0x00,0x00 + db 0x21,0x00,0x00,0x30,0x06,0x02 + db 0x31,0x56,0x0D,0x32,0x05,0x07 + db 0x33,0x06,0x09,0x34,0x00,0x00 + db 0x35,0x09,0x06,0x36,0x57,0x05 + db 0x37,0x0D,0x06,0x38,0x02,0x06 + db 0x39,0x00,0x00,0xFF,0x00,0x00 + +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 + TBLRD*+ ; Dummy read (Third byte of delay command) + bra display0_init_loop ; Loop + +display0_config_write: ; With command in WREG + movf TABLAT,W + rcall TFT_CmdWrite ; Write command + TBLRD*+ ; Get config0 + movff TABLAT,PORTA + TBLRD*+ ; Get config1 + movf TABLAT,W + rcall TFT_DataWrite ; Write config + bra display0_init_loop ; Loop + + +;============================================================================= +; Smooth lighting-up of the display: +; +; Trashes: WREG, PRODL +; Typical usage: +; clrf CCPR1L ; Backlight off +; [draw splash screen] +; call TFT_DisplayFadeIn +; + global TFT_Display_FadeIn +TFT_Display_FadeIn: + movlw CCP1CON_VALUE ; See ostc3.inc + movwf CCP1CON + bsf tft_is_dimming ; TFT is dimming, ignore ambient sensor! + clrf CCPR1L ; Backlight off - to be sure + movff max_CCPR1L,PRODL +TFT_Display_FadeIn_0: + incf CCPR1L,F ; Duty cycle + WAITMS d'2' + decfsz PRODL,F + bra TFT_Display_FadeIn_0 + bcf tft_is_dimming ; dimming done. + return + +;============================================================================= +; Smooth lighting-off of the display: +; Trashes: WREG, PRODL + global TFT_Display_FadeOut +TFT_Display_FadeOut: + movff max_CCPR1L,PRODL + bsf tft_is_dimming ; TFT is dimming, ignore ambient sensor! +TFT_Display_FadeOut_0: + movff PRODL,CCPR1L ; Duty cycle + WAITMS d'1' + decfsz PRODL,F + bra TFT_Display_FadeOut_0 + clrf CCPR1L + return + +;============================================================================= + +start_common: + VARARGS_BEGIN + VARARGS_GET8 win_leftx2 + VARARGS_GET8 win_top + VARARGS_END + return + +;============================================================================= + + global box_std_block, box_black_block, box_color_block + +box_std_block: ; Use white color + setf WREG + bra box_common +box_black_block: ; Use black color + clrf WREG +box_common: +box_color_block: + rcall TFT_set_color + VARARGS_BEGIN + VARARGS_GET8 win_top + VARARGS_GET8 win_height + VARARGS_GET8 win_leftx2 + VARARGS_GET8 win_width + VARARGS_END + bra TFT_box + +;----------------------------------------------------------------------------- + + global box_frame_std, box_frame_common, box_frame_color, box_frame_color16 + +box_frame_std: + setf WREG + rcall TFT_set_color + +box_frame_common: + VARARGS_BEGIN + VARARGS_GET8 win_top + VARARGS_GET8 win_height + VARARGS_GET8 win_leftx2 + VARARGS_GET8 win_width + VARARGS_END + bra TFT_frame + +box_frame_color: + rcall TFT_set_color +box_frame_color16: + bra box_frame_common + +;============================================================================= +; Init for half_pixel_write +; Set column register on TFT device, and current color. +; Inputs: win_leftx2 +; Outputs: win_color:2 +; Trashed: WREG, PROD + global init_pixel_write +init_pixel_write: + movff win_leftx2,WREG + mullw 2 + rcall pixel_write_col320 ; Start Address Vertical (.0 - .319) + setf WREG + bra TFT_set_color + +;----------------------------------------------------------------------------- +; Writes two half-pixels at position (win_top,win_leftx2) +; Inputs: win_leftx2, win_top, win_color:2 +; Trashed: WREG, PROD + global pixel_write +pixel_write: + movff win_leftx2,WREG + mullw 2 ; win_leftx2 x 2 -> PRODH:PRODL + 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 + + global pixel_write_col320 +pixel_write_col320: + Index_out 0x21 ; Frame Memory Vertical Address + bra TFT_DataWrite_PROD + +;----------------------------------------------------------------------------- +; Writes one half-pixel at position (win_top,win_leftx2). +; Inputs: win_leftx2, win_top, win_color:2 +; Trashed: WREG, PROD + global half_pixel_write +half_pixel_write: + movff win_top,WREG ; d'0' ... d'239' + ; Variant with Y position in WREG. +half_pixel_write_1: + sublw .239 ; 239-Y --> Y + + mullw 1 ; Copy row to PRODH:L + Index_out 0x20 ; Frame Memory Horizontal Address + rcall TFT_DataWrite_PROD + + Index_out 0x22 ; Frame Memory Data Write start + RS_H ; Data + movff win_color1,PORTA ; Upper + movff win_color2,PORTH ; Lower + WR_L + WR_H ; Tick + 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 + global half_vertical_line +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 a horizontal line of half-pixel at position (win_top,win_leftx2,win_width). +; Inputs: win_leftx2, win_top, win_width, win_color:2 +; Trashed: WREG, PROD, TABLAT, TBLPTRL + global half_horizontal_line +half_horizontal_line: + clrf TABLAT ; Loop index. + +half_horizontal_line_loop: + movff win_leftx2,WREG ; Init X position. + mullw 2 + rcall pixel_write_col320 ; Start Address Vertical (.0 - .319) + movff win_width,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_horizontal_line_loop + + +;----------------------------------------------------------------------------- +; TFT Data Cmd via W +; + global TFT_DataWrite_PROD +TFT_DataWrite_PROD: +; RD_H ; Keep high + RS_H ; Data + movff PRODH,PORTA ; Move high byte to PORTA + movff PRODL,PORTH ; Move low byte to PORTH + WR_L + WR_H ; Tick + return + +TFT_DataRead_PROD: + Index_out 0x22 ; Frame Memory Data Read start + setf TRISA ; PortA as input. + setf TRISH ; PortH as input. + RS_H ; Data + WR_H ; Not write + RD_L ; Read! + nop + nop + nop + RD_H ; Tick + nop + RD_L ; Read! + nop + nop + nop + movff PORTA,PRODH + movff PORTH,PRODL + RD_H ; Tick + nop + clrf TRISA ; PortA as output + clrf TRISH ; PortH as output + return + + + +;============================================================================= +; Output TFT Window Address commands. +; Inputs : win_top, win_leftx2, win_height, win_width. +; Output : PortA/PortH commands. +; Trashed: PROD +; + global TFT_box_write +TFT_box_write: + movff win_leftx2,WREG ; Compute left = 2*leftx2 --> PROD + mullw 2 + + ;---- Normal horizontal window --------------------------------------- + ; Output 0x35 left, + ; 0x36 right == left + width - 1. + + Index_out 0x52 ; Window Vertical Start Address + rcall TFT_DataWrite_PROD ; Output left + Index_out 0x21 ; Frame Memory Vertical Address + rcall TFT_DataWrite_PROD ; Output left + + movff win_width+0,WREG ; right = left + width - 1 + addwf PRODL,F + movff win_width+1,WREG + addwfc PRODH,F + decf PRODL,F ; decrement result + btfss STATUS,C + decf PRODH,F + + Index_out 0x53 ; Window Vertical End Address + rcall TFT_DataWrite_PROD + + ;---- Flipped vertical window ---------------------------------------- + ; Output 0x37 flipped(bottom) = 239-bottom = 240 - top - height + ; flipped(top) = 239-top +TFT_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. + + Index_out 0x50 ; Window Horizontal Start Address + clrf PORTA ; Upper + movf PRODH,W + rcall TFT_DataWrite ; Lower (and tick) + + Index_out 0x51 ; Window Horizontal End Address + clrf PORTA ; Upper + movf PRODL,W + rcall TFT_DataWrite ; Lower (and tick) + + Index_out 0x20 ; Frame Memory Horizontal Address + clrf PORTA ; Upper + movf PRODL,W + rcall TFT_DataWrite ; Lower (and tick) + return + + +;============================================================================= +; TFT_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 + global TFT_frame +TFT_frame: + movff win_top,save_top ; Backup everything. + movff win_height,save_height + movff win_leftx2,save_left + movff win_width,save_width + + ;---- TOP line ----------------------------------------------------------- + movlw 1 ; row ~ height=1 + movff WREG,win_height + rcall TFT_box + + ;---- BOTTOM line -------------------------------------------------------- + movff save_top,PRODL ; Get back top, + movff save_height,WREG ; and height + addwf PRODL,W ; top+height + decf WREG ; top+height-1 + movff WREG,win_top ; top+height-1 --> top + rcall TFT_box + + ;---- LEFT column -------------------------------------------------------- + movff save_top,win_top ; Restore top/height. + movff save_height,win_height + movlw 1 ; column ~ width=1 + movff WREG,win_width + rcall TFT_box + + ;---- RIGHT column ------------------------------------------------------- + movff save_left,WREG + movff save_width,PRODL + addwf PRODL,W + decf WREG + movff WREG,win_leftx2 + rcall TFT_box + + ;---- Restore everything ------------------------------------------------- + movff save_left,win_leftx2 + movff save_width,win_width + return + +;============================================================================= +; TFT_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 TFT_box + +TFT_box: + ;---- Define Window ------------------------------------------------------ + movf win_width,W + bcf STATUS,C + rlcf WREG + movwf win_width+0 + movlw 0 + rlcf WREG + movwf win_width+1 + rcall TFT_box_write + + rrcf win_width+1,W ; width /= 2 + rrcf win_width+0,W + movwf win_width + + ;---- Fill Window -------------------------------------------------------- + Index_out 0x22 ; Frame Memory Data Write start + + clrf PRODH ; Column counter. + RS_H ; Data + +TFT_box2: ; Loop height times + movff win_height,PRODL + +TFT_box3: ; loop width times + movff win_color1,PORTA ; Upper + movff win_color2,PORTH ; Lower + WR_L + WR_H ; Tick + + movff win_color1,PORTA ; Upper + movff win_color2,PORTH ; Lower + WR_L + WR_H ; Tick + + decfsz PRODL,F ; row loop finished ? + bra TFT_box3 ; No: continue. + + incf PRODH,F ; column count ++ + + movff win_bargraph,WREG ; current column == bargraph ? + cpfseq PRODH + bra TFT_box4 ; No: just loop. + + clrf WREG ; Yes: switch to black + movff WREG,win_color1 + movff WREG,win_color2 +TFT_box4: + + movff win_width+0,WREG ; compare ? + xorwf PRODH,W + bnz TFT_box2 ; Loop not finished. + + movlw 0x00 ; NOP, to stop window mode + rcall TFT_CmdWrite + + setf WREG ; Reset bargraph mode... + movff WREG,win_bargraph + + return + +;============================================================================= +;Converts 8Bit RGB b'RRRGGGBB' into 16Bit RGB b'RRRRRGGGGGGBBBBB' + global TFT_set_color + +TFT_set_color: + movwf tft_temp1 ; Get 8Bit RGB b'RRRGGGBB' + movwf tft_temp2 ; Copy + + ; Mask Bit 7,6,5,4,3,2 + movlw b'00000011' + andwf tft_temp2,F + + movlw b'00000000' + dcfsnz tft_temp2,F + movlw b'01010000' + dcfsnz tft_temp2,F + movlw b'10100000' + dcfsnz tft_temp2,F + movlw b'11111000' + movwf tft_temp3 ; Blue done. + + movff tft_temp1, tft_temp2 ; Copy + ; Mask Bit 7,6,5,1,0 + movlw b'00011100' + andwf tft_temp2,F + rrncf tft_temp2,F + rrncf tft_temp2,F + + movlw b'00000000' + dcfsnz tft_temp2,F + movlw b'00000100' + dcfsnz tft_temp2,F + movlw b'00001000' + dcfsnz tft_temp2,F + movlw b'00001100' + dcfsnz tft_temp2,F + movlw b'00010000' + dcfsnz tft_temp2,F + movlw b'00010100' + dcfsnz tft_temp2,F + movlw b'00100000' + dcfsnz tft_temp2,F + movlw b'00111111' + movwf tft_temp4 + + rrcf tft_temp4,F + rrcf tft_temp3,F + + rrcf tft_temp4,F + rrcf tft_temp3,F + + rrcf tft_temp4,F + rrcf tft_temp3,F ; tft_temp3 (b'GGGBBBBB') done. + + movff tft_temp1, tft_temp2 ; Copy + clrf tft_temp1 + + rrcf tft_temp4,F + rrcf tft_temp1,F + + rrcf tft_temp4,F + rrcf tft_temp1,F + + rrcf tft_temp4,F + rrcf tft_temp1,F ; Green done. + + ; Mask Bit 4,3,2,1,0 + movlw b'11100000' + andwf tft_temp2,F + + rrncf tft_temp2,F + rrncf tft_temp2,F + rrncf tft_temp2,F + rrncf tft_temp2,F + rrncf tft_temp2,F + + movlw b'00000000' + dcfsnz tft_temp2,F + movlw b'00000100' + dcfsnz tft_temp2,F + movlw b'00001000' + dcfsnz tft_temp2,F + movlw b'00001100' + dcfsnz tft_temp2,F + movlw b'00010000' + dcfsnz tft_temp2,F + movlw b'00010100' + dcfsnz tft_temp2,F + movlw b'00100000' + dcfsnz tft_temp2,F + movlw b'00111111' + movwf tft_temp4 + + rrcf tft_temp4,F + rrcf tft_temp1,F + + rrcf tft_temp4,F + rrcf tft_temp1,F + + rrcf tft_temp4,F + rrcf tft_temp1,F + + rrcf tft_temp4,F + rrcf tft_temp1,F + + rrcf tft_temp4,F + rrcf tft_temp1,F ; Red done. + + movff tft_temp1,win_color1 + movff tft_temp3,win_color2 ; Set Bank0 Color registers... + return + +;============================================================================= +; Dump screen contents to the UART + + global TFT_dump_screen +TFT_dump_screen: + bsf no_sensor_int + movlw 'l' + movwf TXREG ; Send command echo. + call rs232_wait_tx ; wait for UART + ;---- Send DISPLAY box command for the full screen window ------------------- + Index_out 0x50 ; Window Horizontal Start Address + Parameter_out 0x00, 0x00 ; 0-239 + Index_out 0x51 ; Window Horizontal End Address + Parameter_out 0x00, 0xEF ; 0-239 + Index_out 0x52 ; Window Vertical Start Address + Parameter_out 0x00, 0x00 ; 0-319 + Index_out 0x53 ; Window Vertical End Address + Parameter_out 0x01, 0x3F ; 0-319 + + clrf ds_column + rcall dump_screen_pixel_reset +dump_screen_1: + btg LEDr ; LED activity toggle + ; Dump even column + movlw .240 ; 240 lines, once. + movwf ds_line +dump_screen_2: + Index_out 0x20 ; Frame Memory Horizontal Address + movff ds_line,WREG ; d'0' ... d'239' + mullw 1 ; Copy row to PRODH:L + rcall TFT_DataWrite_PROD + + movff ds_column,WREG ; Init X position. + mullw 2 + rcall pixel_write_col320 ; Start Address Vertical (.0 - .319) + + rcall TFT_DataRead_PROD ; read pixel + rcall dump_screen_pixel + + decfsz ds_line,F + bra dump_screen_2 + rcall dump_screen_pixel_flush + + ; Dump odd column + movlw .240 ; 240 lines, twice. + movwf ds_line +dump_screen_3: + Index_out 0x20 ; Frame Memory Horizontal Address + movff ds_line,WREG ; d'0' ... d'239' + mullw 1 ; Copy row to PRODH:L + rcall TFT_DataWrite_PROD + + movff ds_column,WREG ; Init X position. + mullw 2 + movlw .1 + addwf PRODL,F + movlw 0 + addwfc PRODH,F ; +1 + rcall pixel_write_col320 ; Start Address Vertical (.0 - .319) + + rcall TFT_DataRead_PROD ; read pixel + rcall dump_screen_pixel + + decfsz ds_line,F + bra dump_screen_3 + rcall dump_screen_pixel_flush + + incf ds_column,F + movlw .160 + cpfseq ds_column + bra dump_screen_1 + + bcf no_sensor_int + clrf RCREG1 ; Clear receive buffer + bcf RCSTA1,CREN ; Clear receiver status + bsf RCSTA1,CREN + bsf enable_screen_dumps ; =1: Ignore vin_usb, wait for "l" command (Screen dump) + return + + +;============================================================================= +; Pixel compression +; +; Input: PRODH:L = pixel. +; Output: Compressed stream on output. +; Compressed format: +; 0ccccccc : BLACK pixel, repeated ccccccc+1 times (1..128). +; 11cccccc : WHITE pixel, repeated cccccc+1 times (1..64). +; 10cccccc HIGH LOW : color pixel (H:L) repeated ccccc+1 times (1..64). +; +dump_screen_pixel: + movf PRODH,W ; Compare pixel-high + xorwf ds_pixel+1,W + bnz dump_screen_pixel_1 ; Different -> dump. + + movf PRODL,W ; Compare pixel-low + xorwf ds_pixel+0,W + bnz dump_screen_pixel_1 ; Different -> dump. + + incf ds_count,F ; Same color: just increment. + return + +dump_screen_pixel_1: ; Send (pixel,count) tuple + movf ds_count,W ; Is count zero ? + bz dump_screen_pixel_2 ; Yes: skip sending. + + movf ds_pixel+1,W ; This is a BLACK pixel ? + iorwf ds_pixel+0,W + bz dump_screen_pix_black ; YES. + + movf ds_pixel+1,W ; This is a white pixel ? + andwf ds_pixel+0,W + incf WREG + bz dump_screen_pix_white ; YES. + + ; No: write the pixel itself... + movlw .64 ; Max color pixel on a single byte. + cpfsgt ds_count ; Skip if count > 64 + movf ds_count,W ; W <- min(64,count) + subwf ds_count,F ; ds_count <- ds_count-W + decf WREG ; Save as 0..63 + iorlw b'10000000' ; MARK as a color pixel. + + movwf TXREG + call rs232_wait_tx ; wait for UART + movff ds_pixel+1,TXREG + call rs232_wait_tx ; wait for UART + movff ds_pixel+0,TXREG + call rs232_wait_tx ; wait for UART + bra dump_screen_pixel_1 + +dump_screen_pixel_2: + movff PRODH,ds_pixel+1 ; Save new pixel color + movff PRODL,ds_pixel+0 + movlw 1 + movwf ds_count ; And set count=1. + return + +dump_screen_pix_black: + movlw .128 ; Max black pixel on a single byte. + cpfsgt ds_count ; Skip if count > 128 + movf ds_count,W ; W <- min(128,count) + subwf ds_count,F ; ds_count <- ds_count-W + decf WREG ; Save as 0..127 +dump_screen_pix_3: + movwf TXREG + call rs232_wait_tx + bra dump_screen_pixel_1 ; More to dump ? + +dump_screen_pix_white: + movlw .64 ; Max white pixel on a single byte. + cpfsgt ds_count ; Skip if count > 64 + movf ds_count,W ; W <- min(64,count) + subwf ds_count,F ; ds_count <- ds_count-W + decf WREG ; Save as 0..63 + iorlw b'11000000' ; MARK as a compressed white. + bra dump_screen_pix_3 + +dump_screen_pixel_flush: + clrf PRODH + clrf PRODL + rcall dump_screen_pixel_1 ; Send it +dump_screen_pixel_reset: + clrf ds_count ; But clear count. + return + + end \ No newline at end of file