; *************************************************************************** ; 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"