Created
April 14, 2020 12:56
-
-
Save mcejp/cbd817f96201bd960fbfdb2f96f522ac to your computer and use it in GitHub Desktop.
ILI9163C routines for AVR
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This is free and unencumbered software released into the public domain. | |
Anyone is free to copy, modify, publish, use, compile, sell, or | |
distribute this software, either in source code form or as a compiled | |
binary, for any purpose, commercial or non-commercial, and by any | |
means. | |
Originally published on http://0xfffe.blogspot.com/2015/11/to-lcd-or-not-to-lcd-fighting-ili9163.html | |
*/ | |
#include <avr/io.h> | |
#include "lcd.h" | |
#define SLPOUT 0x11 | |
#define INVOFF 0x20 | |
#define INVON 0x21 | |
#define DISPON 0x29 | |
#define CASET 0x2A | |
#define PASET 0x2B | |
#define RAMWR 0x2C | |
#define VSCRDEF 0x33 | |
#define MADCTL 0x36 | |
#define VSCRSADD 0x37 | |
#define COLMOD 0x3A | |
#define LCD_BEGIN_DRAW ldi r24, RAMWR $\ | |
call LCD_Cmd $\ | |
sbi _SFR_IO_ADDR(LCD_PORT), DCX_PIN | |
// TODO: use r0 for temp more often | |
.section .text.LCD_Init,"ax",@progbits | |
.global LCD_Init | |
// r24 = x, r22 = y, r20 = c, r18:19 = text color, r16:17 = bg color | |
LCD_Init: | |
cbi _SFR_IO_ADDR(LCD_PORT), RESET_PIN | |
ldi r24, 1 | |
call DelayMillis | |
sbi _SFR_IO_ADDR(LCD_PORT), RESET_PIN | |
ldi r24, 120 | |
call DelayMillis | |
ldi r24, SLPOUT | |
call LCD_Cmd | |
ldi r24, 120 | |
call DelayMillis | |
ldi r24, DISPON | |
call LCD_Cmd | |
ldi r24, 1 | |
call DelayMillis | |
// Set 16-bit color | |
ldi r24, COLMOD | |
call LCD_Cmd | |
sbi _SFR_IO_ADDR(LCD_PORT), DCX_PIN | |
ldi r24, 0x05 | |
call SPI_transmit | |
// Set up MADCTL - flip X, flip Y, BGR color order | |
ldi r24, MADCTL | |
call LCD_Cmd | |
sbi _SFR_IO_ADDR(LCD_PORT), DCX_PIN | |
//ldi r24, 0xC8 | |
ldi r24, 0x08 | |
call SPI_transmit | |
//call LCD_ClearPattern | |
ret | |
.section .text.LCD_Cmd,"ax",@progbits | |
.global LCD_Cmd | |
LCD_Cmd: | |
cbi _SFR_IO_ADDR(LCD_PORT), DCX_PIN | |
// fall-through to SPI_transmit | |
.section .text.SPI_transmit,"ax",@progbits | |
.global SPI_transmit | |
SPI_transmit: | |
out _SFR_IO_ADDR(SPDR), r24 | |
0: | |
in r0, _SFR_IO_ADDR(SPSR) | |
sbrs r0, SPIF | |
rjmp 0b | |
ret | |
.section .text.SPI_Transmit16,"ax",@progbits | |
.global SPI_Transmit16 | |
SPI_Transmit16: | |
out _SFR_IO_ADDR(SPDR), r25 | |
0: | |
in r0, _SFR_IO_ADDR(SPSR) | |
sbrs r0, SPIF | |
rjmp 0b | |
out _SFR_IO_ADDR(SPDR), r24 | |
0: | |
in r0, _SFR_IO_ADDR(SPSR) | |
sbrs r0, SPIF | |
rjmp 0b | |
ret | |
/*.section .text.LCD_SetColumnAddress,"ax",@progbits | |
.global LCD_SetColumnAddress | |
// r24 = xs, r22 = xe | |
LCD_SetColumnAddress: | |
mov r18, r24 | |
ldi r24, CASET | |
1: call LCD_Cmd | |
sbi _SFR_IO_ADDR(LCD_PORT), DCX_PIN | |
clr r24 | |
call SPI_transmit | |
mov r24, r18 | |
call SPI_transmit | |
clr r24 | |
call SPI_transmit | |
mov r24, r22 | |
call SPI_transmit | |
ret | |
.section .text.LCD_SetRowAddress,"ax",@progbits | |
.global LCD_SetRowAddress | |
// r24 = ys, r22 = ye | |
LCD_SetRowAddress: | |
mov r18, r24 | |
ldi r24, PASET | |
rjmp 1b*/ | |
.section .text.LCD_SetWindow,"ax",@progbits | |
.global LCD_SetWindow | |
// r24 = xs, r22 = xe, r20 = ys, r18 = ye | |
LCD_SetWindow: | |
mov r25, r24 | |
ldi r24, CASET | |
call LCD_Cmd | |
sbi _SFR_IO_ADDR(LCD_PORT), DCX_PIN | |
mov r24, r25 | |
clr r25 | |
call SPI_Transmit16 | |
mov r24, r22 | |
call SPI_Transmit16 | |
ldi r24, PASET | |
call LCD_Cmd | |
sbi _SFR_IO_ADDR(LCD_PORT), DCX_PIN | |
mov r24, r20 | |
call SPI_Transmit16 | |
mov r24, r18 | |
call SPI_Transmit16 | |
ret | |
.section .text.LCD_SetScrollArea,"ax",@progbits | |
.global LCD_SetScrollArea | |
// r24 = top fixed height, r22 = scroll area height, r20 = bottom fixed height | |
LCD_SetScrollArea: | |
mov r25, r24 | |
ldi r24, VSCRDEF | |
call LCD_Cmd | |
sbi _SFR_IO_ADDR(LCD_PORT), DCX_PIN | |
mov r24, r25 | |
clr r25 | |
call SPI_Transmit16 | |
mov r24, r22 | |
clr r25 | |
call SPI_Transmit16 | |
mov r24, r20 | |
clr r25 | |
call SPI_Transmit16 | |
ret | |
.section .text.LCD_Clear,"ax",@progbits | |
.global LCD_Clear | |
// r24:25 = color | |
LCD_Clear: | |
mov r30, r24 | |
mov r31, r25 | |
// LCD_SetWindow(r24: xs, r22: xe, r20: ys, r18: ye) | |
ldi r24, 0 | |
ldi r22, LCD_WIDTH | |
ldi r20, Y_OFFSET | |
ldi r18, Y_OFFSET + LCD_HEIGHT | |
call LCD_SetWindow | |
LCD_BEGIN_DRAW | |
mov r24, r30 | |
mov r25, r31 | |
ldi r22, LCD_HEIGHT | |
0: ldi r23, LCD_WIDTH | |
1: call SPI_Transmit16 | |
dec r23 | |
brne 1b | |
dec r22 | |
brne 0b | |
ret | |
.section .text.LCD_DrawChar,"ax",@progbits | |
.global LCD_DrawChar | |
// r24 = x, r22 = y, r20 = c, r18:19 = text color, r16:17 = bg color | |
LCD_DrawChar: | |
push r20 | |
mov r26, r18 | |
cpi r22, LCD_HEIGHT | |
brlo 0f | |
subi r22, LCD_HEIGHT | |
0: | |
// LCD_SetWindow(r24: x, r22: x + 7, r20: Y_OFFSET + y, r18: Y_OFFSET + y + 7) | |
ldi r20, Y_OFFSET | |
add r20, r22 | |
ldi r18, 7 | |
add r18, r20 | |
ldi r22, 7 | |
add r22, r24 | |
call LCD_SetWindow | |
LCD_BEGIN_DRAW | |
// z = &CHAR_ROM[c] | |
pop r30 | |
ldi r31, hi8(CHAR_ROM) | |
// init loop counter (y) | |
ldi r25, FONT_HEIGHT | |
0: // r23 = CHAR_ROM[y * 128 + c] | |
lpm r23, z | |
subi r30, -128 | |
sbci r31, 0xff | |
// init loop counter (x) | |
ldi r22, FONT_WIDTH | |
1: sbrc r23, 0 | |
rjmp 2f | |
// TODO: inline SPI_transmit | |
// not set | |
mov r24, r17 | |
call SPI_transmit | |
mov r24, r16 | |
call SPI_transmit | |
rjmp 3f | |
2: // set | |
mov r24, r19 | |
call SPI_transmit | |
mov r24, r26 | |
call SPI_transmit | |
3: lsr r23 | |
dec r22 | |
brne 1b | |
dec r25 | |
brne 0b | |
ret | |
.section .text.LCD_Scroll,"ax",@progbits | |
.global LCD_Scroll | |
// r24 = y | |
LCD_Scroll: | |
mov r25, r24 | |
ldi r24, VSCRSADD | |
call LCD_Cmd | |
sbi _SFR_IO_ADDR(LCD_PORT), DCX_PIN | |
mov r24, r25 | |
clr r25 | |
rjmp SPI_Transmit16 | |
.section .text.DelayMillis,"ax",@progbits | |
// r24 = millis | |
DelayMillis: | |
// assuming 16 MHz | |
// 1ms = 16000 cycles = 4000 loops @ 4clk/loop | |
0: ldi r26, lo8(4000) | |
ldi r27, hi8(4000) | |
1: sbiw r26, 1 | |
brne 1b | |
dec r24 | |
brne 0b | |
ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment