; *************************************************************************** ; 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, 65 rcall ili9341_WriteCharacterX4At 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 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, 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 ; --------------------------------------------------------------------------- ; @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: ; render character push xl push xh rcall ili9341WriteCharacterFromFont8x8 ; (r17, r24, r25, x, z) pop xh pop xl ; set width and height ldi r16, 8 mov r8, r16 clr r9 mov r10, r16 clr r11 rjmp ili9341BitBlit ; @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 ; @return r5:r4 new X (advanced by character width) ; @clobbers r16, r17, r18, r19, r24, r25, x, z ili9341_WriteCharacterX2At: ; render character push xl push xh rcall ili9341WriteCharacterFromFont8x8 ; (r17, r24, r25, x, z) pop xh pop xl ; set width and height ldi r16, 8 mov r8, r16 clr r9 mov r10, r8 clr r11 rjmp ili9341BitBlitStretch2 ; @end ; --------------------------------------------------------------------------- ; @routine ili9341_WriteCharacterX4At ; @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_WriteCharacterX4At: ; render character push xl push xh rcall ili9341WriteCharacterFromFont8x8 ; (r17, r24, r25, x, z) pop xh pop xl ; set width and height ldi r16, 8 mov r8, r16 clr r9 mov r10, r8 clr r11 rjmp ili9341BitBlitStretch4 ; @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"