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