; *************************************************************************** ; 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. * ; *************************************************************************** #ifndef AQH_AVR_ILI9341_MAIN_ASM #define AQH_AVR_ILI9341_MAIN_ASM ; 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 ; @param r13:r12 source data width in bytes (for bit blit, i.e. byte offset from ; one source data line to the next) ; *************************************************************************** ; data .dseg ;ILI9341_buffer: .byte 128 ; *************************************************************************** ; code .cseg ; --------------------------------------------------------------------------- ; @routine ILI9341_Init @global ILI9341_Init: rcall ILI9341IoInit rcall ILI9341_Reset rcall ILI9341_LeaveSleepMode ldi r16, 0x20 rcall Display_SetBacklight 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 ; (R16, R17) 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 ; display on rcall ili9341SendCommand rcall ili9341EndSpi ldi r16, 120 rcall Utils_WaitForMilliSecs ret ; @end ; --------------------------------------------------------------------------- ; @routine Display_SetBacklight @global ; ; @param r16 0=off, on otherwise ; @clobbers r16, r17 Display_SetBacklight: tst r16 brne Display_SetBacklight_on cbi ILI9341_LED_OUTPUT, ILI9341_LED_PIN ret Display_SetBacklight_on: sbi ILI9341_LED_OUTPUT, ILI9341_LED_PIN ret ; DEBUG push r16 rcall ili9341BeginSpi ldi r16, ILI9341_CMD_WRITECTLDISPLAY rcall ili9341SendCommand ; BCTRL=1, DD=1, BL=1 (or: 0x24 reported to work) ldi r16, (1<<5) | (1<<3) | (1<<2) 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, 120 rcall Utils_WaitForMilliSecs rcall ili9341BeginSpi ldi r16, 0x38 ; idle mode off rcall ili9341SendCommand rcall ili9341EndSpi rcall ili9341BeginSpi ldi r16, 0x13 ; normal mode on rcall ili9341SendCommand rcall ili9341EndSpi ret ; @end ili9341InitCommands: #if 1 ; 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 #else .db 0xef, 3, 0x03, 0x80, 0x02, 0x00 .db 0xcf, 3, 0x00, 0xc1, 0x30, 0x00 .db 0xed, 4, 0x64, 0x03, 0x12, 0x81 .db 0xe8, 3, 0x85, 0x00, 0x78, 0x00 .db 0xcb, 5, 0x39, 0x2c, 0x00, 0x34, 0x02, 0x00 .db 0xf7, 1, 0x20, 0x00 .db 0xea, 2, 0x00, 0x00 .db 0xc0, 1, 0x23, 0x00 .db 0xc1, 1, 0x10, 0x00 .db 0xc5, 2, 0x3e, 0x28 ; .db 0xc7, 1, 0x86, 0x00 .db 0xc7, 1, 0xb7, 0x00 .db 0x36, 1, 0b11101000, 0x00 .db 0x3a, 1, 0x55, 0x00 .db 0xb1, 2, 0x00, ILI9341_FRAMERATE_100_HZ .db 0xb6, 3, 0x08, 0x82, 0x27, 0x00 .db 0xf2, 1, 0x00, 0x00 .db 0x26, 1, 0x01, 0x00 .db 0xe0, 15, 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1 .db 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00, 0x00 .db 0xe1, 15, 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1 .db 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f, 0x00 ; end .db 0xff, 0xff #endif ; AQH_AVR_ILI9341_MAIN_ASM