Files
aqhomecontrol/avr/modules/lcd2/ili9341/main.asm
2025-05-22 01:19:04 +02:00

755 lines
16 KiB
NASM

; ***************************************************************************
; copyright : (C) 2025 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
; generally we use the following parameters here:
; @param r1:r0 background color
; @param r3:r2 foreground color
; @param r5:r4 X0
; @param r7:r6 Y0
; @param r9:r8 X1/W
; @param r11:r10 Y1/H
; ***************************************************************************
; data
.dseg
ILI9341_buffer: .byte 128
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine ILI9341_Init @global
ILI9341_Init:
rcall ILI9341IoInit
rcall ILI9341_Reset
rcall ILI9341_LeaveSleepMode
ldi r16, 0xff
rcall ILI9341_SetBacklight
ldi r16, 0xff
mov r3, r16
ldi r16, 0xff
mov r2, r16
rcall ili9341Test5
; 0bRRRRRGGGGGGBBBBB
ldi r16, 0b11111000 ; red
mov r3, r16
ldi r16, 0b00000000 ; red
mov r2, r16
rcall ili9341Test2
; 0bRRRRRGGGGGGBBBBB
ldi r16, 0b00000000
mov r3, r16
ldi r16, 0b00011111 ; blue
mov r2, r16
rcall ili9341Test3
; 0bRRRRRGGGGGGBBBBB
ldi r16, 0b00000111 ; green
mov r3, r16
ldi r16, 0b11100000 ; green
mov r2, r16
rcall ili9341Test4
; set foreground color
ldi r16, 0b11100000 ; green
mov r2, r16
ldi r16, 0b00000111 ; green
mov r3, r16
; set background color
ldi r16, 0b11111111 ; white
mov r0, r16
mov r1, r16
; set Xpos
ldi r16, LOW(100)
mov r4, r16
ldi r16, HIGH(100)
mov r5, r16
; setYpos
ldi r16, LOW(150)
mov r6, r16
ldi r16, HIGH(150)
mov r7, r16
; set font pos
ldi zl, LOW(font8x8*2)
ldi zh, HIGH(font8x8*2)
; set buffer pos
; ldi xl, LOW(ILI9341_buffer)
; ldi xh, HIGH(ILI9341_buffer)
ldi xl, LOW(0x260)
ldi xh, HIGH(0x260)
; set foreground color
ldi r16, 0b00000000 ; black
mov r2, r16
mov r3, r16
; set character
ldi r16, 'A'
rcall ili9341PrintChar
ldi r16, 'Q'
rcall ili9341PrintChar
ldi r16, 'H'
rcall ili9341PrintChar
ldi r16, 'O'
rcall ili9341PrintChar
ldi r16, 'M'
rcall ili9341PrintChar
ldi r16, 'E'
rcall ili9341PrintChar
sec
ret
; @end
ili9341PrintChar:
push zl
push zh
rcall ili9341_WriteCharacterX4At
pop zh
pop zl
ret
; ---------------------------------------------------------------------------
; @routine ILI9341_Fini @global
ILI9341_Fini:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341_SendCommands
;
; @clobbers r16
; Z=byte pointer to command list (as for LPM)
ili9341SendCommands:
rcall ili9341BeginSpi
ili9341SendCommands_loop1:
lpm r16, Z+ ; read command
lpm r18, Z+ ; read number of args
cpi r18, 0xff ; end?
breq ili9341SendCommands_end
rcall ili9341SendCommand
mov r19, r18
andi r19, 1 ; if 1: need to skip filler byte
tst r18
breq ili9341SendCommands_loop1 ; no args, next command
ili9341SendCommands_loop2:
lpm r16, Z+
rcall ili9341SendData ; (R16)
dec r18
brne ili9341SendCommands_loop2
add zl, r19 ; possibly skip filler byte
adc zh, r19
sub zh, r19
rjmp ili9341SendCommands_loop1
ili9341SendCommands_end:
rcall ili9341EndSpi ; (R16)
ret
; @end
; ---------------------------------------------------------------------------
; @routine ILI9341_Reset @global
; @clobbers (R22)
ILI9341_Reset:
cbi ILI9341_RESET_OUTPUT, ILI9341_RESET_PIN
ldi r16, 100
rcall Utils_WaitForMilliSecs
sbi ILI9341_RESET_OUTPUT, ILI9341_RESET_PIN
ldi r16, 50
rcall Utils_WaitForMilliSecs
ldi zl, LOW(ili9341InitCommands*2)
ldi zh, HIGH(ili9341InitCommands*2)
rcall ili9341SendCommands
ldi r16, 120
rcall Utils_WaitForMilliSecs
rcall ili9341BeginSpi
ldi r16, 0x29
rcall ili9341SendCommand
rcall ili9341EndSpi
ldi r16, 120
rcall Utils_WaitForMilliSecs
ret
; @end
; ---------------------------------------------------------------------------
; @routine ILI9341_SetBacklight @global
;
; @param r16 0=off, on otherwise
; @clobbers r16, r17
ILI9341_SetBacklight:
tst r16
brne ILI9341_SetBacklight_on
cbi ILI9341_LED_OUTPUT, ILI9341_LED_PIN
ret
ILI9341_SetBacklight_on:
sbi ILI9341_LED_OUTPUT, ILI9341_LED_PIN
push r16
rcall ili9341BeginSpi
ldi r16, ILI9341_CMD_WRITECTLDISPLAY
rcall ili9341SendCommand
; ldi r16, 0b00100100
ldi r16, 0x24
rcall ili9341SendData
ldi r16, ILI9341_CMD_SETDSPBRIGHTNESS
rcall ili9341SendCommand
pop r16
rcall ili9341SendData
ldi r16, 0xbe
rcall ili9341SendCommand
ldi r16, 0x0f
rcall ili9341SendData
rcall ili9341EndSpi
ret
; @end
ILI9341_LeaveSleepMode:
rcall ili9341BeginSpi
ldi r16, 0x11 ; sleep out
rcall ili9341SendCommand
rcall ili9341EndSpi
ldi r16, 5
rcall Utils_WaitForMilliSecs
ret
; @end
; ---------------------------------------------------------------------------
; @routine ILI9341_FillScreen
;
; @param r17:r16 color
ILI9341_FillScreen:
; TODO
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341SetAddressWindow
;
; @param r5:r4 X0
; @param r7:r6 Y0
; @param r9:r8 W
; @param r11:r10 H
; @clobbers R16, r20, r21
ili9341SetAddressWindow:
; calc XEnd (=X+W-1)
mov r20, r8
mov r21, r9
add r20, r4
adc r21, r5
subi r20, 1
sbci r21, 0
; send column address
ldi r16, ILI9341_CMD_CASET
rcall ili9341SendCommand
; X0
mov r16, r5
rcall ili9341SendData
mov r16, r4
rcall ili9341SendData
; X1
mov r16, r21
rcall ili9341SendData
mov r16, r20
rcall ili9341SendData
; calc YEnd (=Y+H-1)
mov r20, r10
mov r21, r11
add r20, r6
adc r21, r7
subi r20, 1
sbci r21, 0
; send row address
ldi r16, ILI9341_CMD_PASET
rcall ili9341SendCommand
; Y0
mov r16, r7
rcall ili9341SendData
mov r16, r6
rcall ili9341SendData
; Y1
mov r16, r21
rcall ili9341SendData
mov r16, r20
rcall ili9341SendData
ret
; @end
; ---------------------------------------------------------------------------
; @routine ILI9341_FillRect
; @param r3:r2 color
; @param r5:r4 X0
; @param r7:r6 Y0
; @param r9:r8 X1/W
; @param r11:r10 Y1/H
ILI9341_FillRect:
push r15
in r15, SREG
cli
rcall ili9341BeginSpi ; (R16, R17)
rcall ili9341SetAddressWindow ; (R16, r20, r21)
mov r18, r2 ; color
mov r19, r3
mov r22, r10 ; H low
mov r23, r11 ; H high
ldi r16, ILI9341_CMD_RAMWR ; start writing ro RAM
rcall ili9341SendCommand
cbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS low
sbi ILI9341_DC_OUTPUT, ILI9341_DC_PIN ; D high (DATA)
ILI9341_FillRect_loopH:
mov r24, r8 ; W low
mov r25, r9 ; W high
ILI9341_FillRect_loopW:
mov r16, r19
rcall SPIHW_MasterTransfer
mov r16, r18
rcall SPIHW_MasterTransfer
sbiw r25:r24, 1
brne ILI9341_FillRect_loopW
mov r24, r22 ; H low
mov r25, r23 ; H high
sbiw r25:r24, 1 ; dec
mov r22, r24 ; save in r23:r22
mov r23, r25
brne ILI9341_FillRect_loopH
sbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS high
rcall ili9341EndSpi
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341BitBlit
; @param r5:r4 X (dest)
; @param r7:r6 Y (dest)
; @param r9:r8 W
; @param r11:r10 H
; @param X source data pointer (RAM)
; @clobbers r16, r22, r23, r24, r25, X (r17, r20, r21)
ili9341BitBlit:
push r15
in r15, SREG
cli
rcall ili9341BeginSpi ; (r16, r17)
rcall ili9341SetAddressWindow ; (R16, R20, R21)
ldi r16, ILI9341_CMD_RAMWR ; start writing ro RAM
rcall ili9341SendCommand
mov r22, r10
mov r23, r11
cbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS low
sbi ILI9341_DC_OUTPUT, ILI9341_DC_PIN ; D high (DATA)
ili9341BitBlit_loopH:
mov r24, r8
mov r25, r9
ili9341BitBlit_loopW:
ld r18, X+
ld r19, X+
mov r16, r19
rcall SPIHW_MasterTransfer ; (R16)
mov r16, r18
rcall SPIHW_MasterTransfer ; (R16)
sbiw r25:r24, 1
brne ili9341BitBlit_loopW
mov r24, r22
mov r25, r23
sbiw r25:r24, 1
mov r22, r24
mov r23, r25
brne ili9341BitBlit_loopH
sbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS high
rcall ili9341EndSpi ; (R16)
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341BitBlitStretch2
; @param r5:r4 X (dest)
; @param r7:r6 Y (dest)
; @param r9:r8 W
; @param r11:r10 H
; @param X source data pointer (RAM)
; @clobbers r16, r22, r23, r24, r25, X (r17, r18, r19, r20, r21)
ili9341BitBlitStretch2:
push r15
in r15, SREG
cli
push r8
push r9
push r10
push r11
; width
lsl r8 ; x2
rol r9
; height
lsl r10 ; x2
rol r11
rcall ili9341BeginSpi ; (r16, r17)
rcall ili9341SetAddressWindow ; (R16, R20, R21)
pop r11
pop r10
pop r9
pop r8
ldi r16, ILI9341_CMD_RAMWR ; start writing ro RAM
rcall ili9341SendCommand
mov r22, r10
mov r23, r11
cbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS low
sbi ILI9341_DC_OUTPUT, ILI9341_DC_PIN ; D high (DATA)
ldi r17, 2
ili9341BitBlitStretch2_loopH:
mov r20, xl ; preserve for next run
mov r21, xh
rcall ili9341BitBlitStretchNWriteLine ; (r16, r17, r18, r19, r24, r25, X)
mov xl, r20
mov xh, r21
rcall ili9341BitBlitStretchNWriteLine ; (r16, r17, r18, r19, r24, r25, X)
mov r24, r22
mov r25, r23
sbiw r25:r24, 1
mov r22, r24
mov r23, r25
brne ili9341BitBlitStretch2_loopH
sbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS high
rcall ili9341EndSpi ; (R16)
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341BitBlitStretch4
; @param r5:r4 X (dest)
; @param r7:r6 Y (dest)
; @param r9:r8 W
; @param r11:r10 H
; @param X source data pointer (RAM)
; @clobbers r16, r22, r23, r24, r25, X (r17, r20, r21)
ili9341BitBlitStretch4:
push r15
in r15, SREG
cli
push r8
push r9
push r10
push r11
; width
lsl r8 ; x2
rol r9
lsl r8 ; x4
rol r9
; height
lsl r10 ; x2
rol r11
lsl r10 ; x4
rol r11
rcall ili9341BeginSpi ; (r16, r17)
rcall ili9341SetAddressWindow ; (R16, R20, R21)
pop r11
pop r10
pop r9
pop r8
ldi r16, ILI9341_CMD_RAMWR ; start writing ro RAM
rcall ili9341SendCommand
mov r22, r10
mov r23, r11
ldi r17, 4
cbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS low
sbi ILI9341_DC_OUTPUT, ILI9341_DC_PIN ; D high (DATA)
ili9341BitBlitStretch4_loopH:
mov r20, xl ; preserve for next run
mov r21, xh
rcall ili9341BitBlitStretchNWriteLine ; (r16, r17, r18, r19, r24, r25, X)
mov xl, r20
mov xh, r21
rcall ili9341BitBlitStretchNWriteLine ; (r16, r17, r18, r19, r24, r25, X)
mov xl, r20
mov xh, r21
rcall ili9341BitBlitStretchNWriteLine ; (r16, r17, r18, r19, r24, r25, X)
mov xl, r20
mov xh, r21
rcall ili9341BitBlitStretchNWriteLine ; (r16, r17, r18, r19, r24, r25, X)
mov r24, r22
mov r25, r23
sbiw r25:r24, 1
mov r22, r24
mov r23, r25
brne ili9341BitBlitStretch4_loopH
sbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS high
rcall ili9341EndSpi ; (R16)
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341BitBlitStretchNWriteLine
; @param r9:r8 width
; @param r17 repeat factor
; @param X source position of line
; @clobbers r16, r17, r18, r19, r24, r25, X
ili9341BitBlitStretchNWriteLine:
mov r24, r8
mov r25, r9
ili9341BitBlitStretchNWriteLine_loop1:
ld r18, X+
ld r19, X+
push r17
ili9341BitBlitStretchNWriteLine_loop2:
mov r16, r19
rcall SPIHW_MasterTransfer ; (R16)
mov r16, r18
rcall SPIHW_MasterTransfer ; (R16)
dec r17
brne ili9341BitBlitStretchNWriteLine_loop2
pop r17
sbiw r25:r24, 1
brne ili9341BitBlitStretchNWriteLine_loop1
ret
; @end
ili9341Test1:
rcall ili9341BeginSpi
ldi r16, 0x04
cbi ILI9341_DC_OUTPUT, ILI9341_DC_PIN ; D low (send command)
rcall SPIHW_MasterTransfer ; (R16)
sbi ILI9341_DC_OUTPUT, ILI9341_DC_PIN ; D high (send data)
clr r16
; read byte 1
rcall SPIHW_MasterTransfer ; (R16)
; read byte 2
rcall SPIHW_MasterTransfer ; (R16)
; read byte 3
rcall SPIHW_MasterTransfer ; (R16)
; read byte 4
rcall SPIHW_MasterTransfer ; (R16)
rcall ili9341EndSpi ; (R16)
ret
; @param %0 X
; @param %1 Y
; @param %2 W
; @param %3 H
.macro M_ILI9341_FILL_RECT
ldi r16, LOW(@0) ; X0
mov r4, r16
ldi r16, HIGH(@0)
mov r5, r16
ldi r16, LOW(@1) ; Y0
mov r6, r16
ldi r16, HIGH(@1)
mov r7, r16
ldi r16, LOW(@2) ; W
mov r8, r16
ldi r16, HIGH(@2)
mov r9, r16
ldi r16, LOW(@3) ; H
mov r10, r16
ldi r16, HIGH(@3)
mov r11, r16
rcall ILI9341_FillRect
.endmacro
ili9341Test2:
M_ILI9341_FILL_RECT 10, 20, 70, 100
ret
ili9341Test3:
M_ILI9341_FILL_RECT 90, 40, 70, 100
ret
ili9341Test4:
M_ILI9341_FILL_RECT 40, 30, 70, 100
ret
ili9341Test5:
M_ILI9341_FILL_RECT 0, 0, 319, 239
ret
ili9341InitCommands:
; display off
.db 0x28, 0
; PowerCtlA
.db 0xcb, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, 0x00
; PowerCtlB
.db 0xcf, 3, 0x00, 0xC1, 0x30, 0x00
; DriverTimingCtlA
.db 0xe8, 3, 0x85, 0x00, 0x78, 0x00
; DriverTimingCtlB
.db 0xea, 2, 0x00, 0x00
; _PowerSeqCtl
.db 0xed, 4, 0x64, 0x03, 0x12, 0x81
; PumpRatioCtl
.db 0xf7, 1, 0x20, 0x00
; PowerCtl1
.db 0xc0, 1, 0x23, 0x00 ; lookup!
; PowerCtl2
.db 0xc1, 1, 0x10, 0x00 ; lookup!
; VomCtl1
.db 0xc5, 2, 0x3e, 0x28 ; lookup!
; VomCtl2
.db 0xc7, 1, 0x86, 0x00 ; lookup!
; ColMod
.db 0x3A, 1, 0x55, 0x00 ; DPI=16bits/pixel, DBI=16bits/pixel
; FrameRateCtl
.db 0xb1, 2, 0x00, ILI9341_FRAMERATE_79_HZ
; DspFnCtl
.db 0xb6, 3, 0x08, 0x82, 0x27, 0x00
; GammaCurve
.db 0x26, 1, 0x01, 0x00
; PosGamma
.db 0xe0, 15
.db 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1
.db 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, 0x00
; NegGamma
.db 0xe1, 15
.db 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1
.db 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, 0x00
; memory access control (use ILI9341_MADCTL_MV to flip X/Y)
; MMMMBM
; YXVLGH00
.db 0x36, 1, 0b11101000, 0x00
; normal mode on
; .db 0x13, 0
; end
.db 0xff, 0xff
helloWorld: .db "Hello World", 0
.include "modules/lcd2/ili9341/font1.asm"