Files
aqhomecontrol/avr/modules/lcd2/ili9341/main.asm

721 lines
15 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 character
ldi r16, 65
rcall ili9341_WriteCharacterX2At
sec
ret
; @end
; ---------------------------------------------------------------------------
; @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 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:
rcall ili9341BeginSpi ; (R16, R17)
push r8 ; W
push r9
push r10
push r11
ldi r16, 1
sub r8, r16 ; X1=X+W-1
sbc r9, r16
add r9, r16
add r8, r4
adc r9, r5
sub r10, r16 ; Y1=Y+H-1
sbc r11, r16
add r11, r16
add r10, r6
adc r11, r7
rcall ili9341SetAddressWindow ; (R16)
pop r11
pop r10
pop r9
pop r8
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
ILI9341_FillRect_loopH:
mov r24, r8 ; W low
mov r25, r9 ; W high
ILI9341_FillRect_loopW:
rcall ili9341Send16BitData ; send r19:r18
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
rcall ili9341EndSpi
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341SetAddressWindow
;
; @param r5:r4 X0
; @param r7:r6 Y0
; @param r9:r8 X1
; @param r11:r10 Y1
; @clobbers R16
ili9341SetAddressWindow:
; send column address
ldi r16, ILI9341_CMD_CASET
rcall ili9341SendCommand
; X0
mov r16, r5
rcall ili9341SendData
mov r16, r4
rcall ili9341SendData
; X1
mov r16, r9
rcall ili9341SendData
mov r16, r8
rcall ili9341SendData
; send row address
ldi r16, ILI9341_CMD_PASET
rcall ili9341SendCommand
; Y0
mov r16, r7
rcall ili9341SendData
mov r16, r6
rcall ili9341SendData
; Y1
mov r16, r11
rcall ili9341SendData
mov r16, r10
rcall ili9341SendData
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341_WriteCharacterX1At
; @param R16 character to write
; @param r5:r4 X
; @param r7:r6 Y
; @param r1:r0 background color
; @param r3:r2 foreground color
; @param Z pointer to font
; @param X pointer to RAM to store data to
; @return r5:r4 new X (advanced by character width)
; @clobbers r16, r17, r18, r19, r24, r25, x, z
ili9341_WriteCharacterX1At:
push xl
push xh
rcall ili9341WriteCharacterFromFont8x8x1 ; (r17, r24, r25, x, z)
pop xh
pop xl
ldi r17, 7
; calc X1
mov r8, r4
mov r9, r5
add r8, r17
adc r9, r17
sub r9, r17
; calc Y1
mov r10, r6
mov r11, r7
add r10, r17
adc r11, r17
sub r11, r17
rcall ili9341BeginSpi ; (r16, r17)
rcall ili9341SetAddressWindow ; (R16)
ldi r16, 8 ; increment X pos for next char
add r4, r16
adc r5, r16
sub r5, r16
ldi r16, ILI9341_CMD_RAMWR ; start writing ro RAM
rcall ili9341SendCommand
ldi r17, 64 ; 8x8
ili9341_WriteCharacterX1At_loop:
ld r18, X+
ld r19, X+
rcall ili9341Send16BitData
dec r17
brne ili9341_WriteCharacterX1At_loop
rcall ili9341EndSpi
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341_WriteCharacterX2At
; @param R16 character to write
; @param r5:r4 X
; @param r7:r6 Y
; @param r1:r0 background color
; @param r3:r2 foreground color
; @param Z pointer to font
; @param X pointer to RAM to store data to
; @clobbers r16, r17, r18, r19, r24, r25, x, z
ili9341_WriteCharacterX2At:
push xl
push xh
rcall ili9341WriteCharacterFromFont8x8x2 ; (r17, r24, r25, x, z)
pop xh
pop xl
ldi r17, 15
; calc X1
mov r8, r4
mov r9, r5
add r8, r17
adc r9, r17
sub r9, r17
; calc Y1
mov r10, r6
mov r11, r7
add r10, r17
adc r11, r17
sub r11, r17
rcall ili9341BeginSpi ; (r16, r17)
rcall ili9341SetAddressWindow ; (R16)
ldi r16, 16 ; increment X pos for next char
add r4, r16
adc r5, r16
sub r5, r16
ldi r16, ILI9341_CMD_RAMWR ; start writing ro RAM
rcall ili9341SendCommand
ldi r17, 0 ; 256 bytes
ili9341_WriteCharacterX2At_loop:
ld r18, X+
ld r19, X+
rcall ili9341Send16BitData
dec r17
brne ili9341_WriteCharacterX2At_loop
rcall ili9341EndSpi
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341WriteCharacterFromFont8x8x1
; @param R16 character to write
; @param R1:R0 background color
; @param R3:R2 foreground color
; @param Z pointer to font
; @param X pointer to RAM to store data to
; @clobbers r17, r24, r25, x, z
ili9341WriteCharacterFromFont8x8x1:
rcall ili9341GetCharPosInFont8x8 ; (r17, r24, r25, z)
ldi r25, 8 ; 8 bytes
ili9341WriteCharacterFromFont8x8x1_loop1:
ldi r24, 8 ; 8 bits
lpm r17, Z+
ili9341WriteCharacterFromFont8x8x1_loop2:
lsr r17
brcs ili9341WriteCharacterFromFont8x8x1_writeForeground
st X+, r0
st X+, r1
rjmp ili9341WriteCharacterFromFont8x8x1_loop2end
ili9341WriteCharacterFromFont8x8x1_writeForeground:
st X+, r2
st X+, r3
ili9341WriteCharacterFromFont8x8x1_loop2end:
dec r24
brne ili9341WriteCharacterFromFont8x8x1_loop2
dec r25
brne ili9341WriteCharacterFromFont8x8x1_loop1
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341WriteCharacterFromFont8x8x2
; @param R16 character to write
; @param R1:R0 background color
; @param R3:R2 foreground color
; @param Z pointer to font
; @param X pointer to RAM to store data to
; @clobbers r17, r22, r23, r24, r25, x, z
ili9341WriteCharacterFromFont8x8x2:
rcall ili9341GetCharPosInFont8x8 ; (r17, r24, r25, z)
ldi r25, 8 ; 8 bytes
ili9341WriteCharacterFromFont8x8x2_loop1:
ldi r24, 8 ; 8 bits
lpm r17, Z+
ili9341WriteCharacterFromFont8x8x2_loop2:
lsr r17
brcs ili9341WriteCharacterFromFont8x8x2_writeForeground
mov r22, r0
mov r23, r1
rjmp ili9341WriteCharacterFromFont8x8x2_loop2end
ili9341WriteCharacterFromFont8x8x2_writeForeground:
mov r22, r2
mov r23, r3
ili9341WriteCharacterFromFont8x8x2_loop2end:
st X+, r22
st X+, r23
st X+, r22
st X+, r23
adiw xh:xl, 28 ; move to next row (8*4)-4
st X+, r22
st X+, r23
st X+, r22
st X+, r23
sbiw xh:xl, 32 ; move back to previous row
dec r24
brne ili9341WriteCharacterFromFont8x8x2_loop2
adiw xh:xl, 32 ; skip next line (we already wrote it)
dec r25
brne ili9341WriteCharacterFromFont8x8x2_loop1
ret
; @end
; ---------------------------------------------------------------------------
; @routine ili9341GetCharPosInFont8x8
; @param R16 character to write
; @param Z pointer to font
; @return Z pointer to begin of char data
; @clobbers r17, r24, r25, z
ili9341GetCharPosInFont8x8:
mov r24, r16
lpm r17, Z+ ; first char num
sub r24, r17
brcc ili9341GetCharPosInFont8x8_firstValueOkay
adiw zh:zl, 1 ; use first char
ret
ili9341GetCharPosInFont8x8_firstValueOkay:
lpm r17, Z+
cp r24, r17
brcs ili9341WriteCharacterFromFont8x8_gotPos
ret
ili9341WriteCharacterFromFont8x8_gotPos:
clr r25
lsl r24 ; R16x8
rol r25
lsl r24
rol r25
lsl r24
rol r25
add zl, r24
adc zh, r25
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"