Skip to content

Instantly share code, notes, and snippets.

@mcejp
Created April 14, 2020 12:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mcejp/cbd817f96201bd960fbfdb2f96f522ac to your computer and use it in GitHub Desktop.
Save mcejp/cbd817f96201bd960fbfdb2f96f522ac to your computer and use it in GitHub Desktop.
ILI9163C routines for AVR
/*
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