Files
aqhomecontrol/avr/modules/lcd/main.asm
2026-03-16 22:43:32 +01:00

921 lines
24 KiB
NASM

; ***************************************************************************
; copyright : (C) 2023 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. *
; ***************************************************************************
; Some code in this module is based on C-code in Tiny4kOLED (https://github.com/datacute/Tiny4kOLED/tree/master/src)
; by Stephen Denne (MIT license), rewritten in AVR assembler
;
; - page 0 is top line, page 7 ist bottom line
; - column 0 is the leftmost colum, column 127 is the rightmost column
; - a page has a height of 8 (->8 bits)
; - when writing a byte to a position (e.g. page 0, column 0)
; - writing to chip RAM is done in columns
;
; text_xpos=(xpos*8), meaning max 16 chars per text line
;
; Page 0: col 0 col 1 ... col 127
; Row 0(LSB) 0/0 1/0 ... 127/0
; Row 1 0/1 1/1 ... 127/1
; Row 2 0/2 1/2 ... 127/2
; Row 3 0/3 1/3 ... 127/3
; ...
; Row 7(MSB) 0/7 1/7 ... 127/7
; and so one
; ***************************************************************************
; defines
.equ LCD_WIDTH = 128
.equ LCD_HEIGHT = 64
.equ LCD_PAGE_COUNT = 8
.equ LCD_MODE_MULTICMD = 0x00
.equ LCD_MODE_SINGLECMD = 0x80
.equ LCD_MODE_DATA = 0x40
.equ LCD_MODE_SINGLEDATA = 0xc0
; ***************************************************************************
; data
.dseg
lcdDataBegin:
lcdDataEnd:
; ***************************************************************************
; code
.cseg
LCD_BEGIN:
; ---------------------------------------------------------------------------
; @routine LCD_Init @global
;
; @return CFLAG set if okay, cleared on error
LCD_Init:
ldi zl, LOW(lcdInitCommandsBegin)
ldi zh, HIGH(lcdInitCommandsBegin)
ldi r16, 28
rcall lcdWriteCommandsFromFlash
ldi r16, 0
rcall LCD_Fill
; set cursor to next line here, sometimes this doesn't work correctly
; when called later. TODO: find out what goes wrong here...
ldi r18, 0
ldi r19, 0
rcall LCD_SetCursor
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine LCD_Fini @global
;
LCD_Fini:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine LCD_Sleep @global
;
; @return nothing
; @param r16 1=sleep, 0=awake
; @clobbers r15, r16, r19 (R17, R18, R22)
;
LCD_Sleep:
ldi r16, 0xae ; set sleep
tst r19
brne LCD_Sleep_send
ldi r16, 0xaf ; set wake
LCD_Sleep_send:
rjmp lcdOneByteCommand
; @end
; ---------------------------------------------------------------------------
; @routine LCD_SetContrast @global
;
; @return nothing
; @param r16 1=sleep, 0=awake
; @clobbers r15, r16, r19 (R17, R18, R22)
;
LCD_SetContrast:
ldi r20, 0x81
mov r21, r16
rjmp lcdTwoByteCommand
; @end
; ---------------------------------------------------------------------------
; @routine lcdOneByteCommand
; Send a one byte command
;
; @return CFLAG set if okay, cleared on error
; @param r20 first byte of command
; @clobbers r15, r16, r19 (R17, R18, R22)
lcdOneByteCommand:
in r15, SREG
push r15
cli
rcall lcdBeginMultiCommand ; (r16, R17, R18, R22)
brcc lcdOneByteCommand_error
mov r16, r20
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc lcdOneByteCommand_error
rcall twiStop ; (R22)
pop r15
out SREG, r15
sec
ret
lcdOneByteCommand_error:
rjmp lcdTwiStopPopR15ClcRet ; (R22)
; @end
; ---------------------------------------------------------------------------
; @routine lcdTwoByteCommand
; Send a two byte command
;
; @return CFLAG set if okay, cleared on error
; @param r20 first byte of command
; @param r21 second byte of command
; @clobbers r15, r16, r19 (R17, R18, R22)
;
lcdTwoByteCommand:
in r15, SREG
push r15
cli
rcall lcdBeginMultiCommand ; (r16, R17, R18, R22)
brcc lcdTwoByteCommand_error
mov r16, r20
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc lcdTwoByteCommand_error
mov r16, r21
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc lcdTwoByteCommand_error
rcall twiStop ; (R22)
pop r15
out SREG, r15
sec
ret
lcdTwoByteCommand_error:
rjmp lcdTwiStopPopR15ClcRet ; (R22)
; @end
; ---------------------------------------------------------------------------
; @routine lcdBeginMultiCommand
;
; Set TWI start condition, send address and LCD_MODE_MULTICMD
;
; @return CFLAG set if okay, cleared on error
; @clobbers r16, (R17, R18, R22)
lcdBeginMultiCommand:
rcall twiStart ; (R22)
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc lcdTwoByteCommand_error
ldi r16, LCD_MODE_MULTICMD
rjmp twiSendByteExpectAck ; (R16, R17, R18, R22)
; @end
lcdTwiStopPopR15ClcRet:
rcall twiStop ; (R22)
pop r15
out SREG, r15
clc
ret
; ---------------------------------------------------------------------------
; @routine LCD_SetCursor @global
;
; Set cursor. X is specified in pixels, Y is specified in character rows (8 pixels).
; Left upper corner is 0/0 (x/y), right lower corner is 127/7
;
; @return CFLAG set if okay, cleared on error
; @param R18 X
; @param R19 Y
; @clobbers r1, r2, r15, r16 (R16, R17, R18, R22)
LCD_SetCursor:
in r15, SREG
push r15
cli
mov r1, r18
mov r2, r19
rcall twiStart ; (R22)
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
ldi r16, LCD_MODE_MULTICMD
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
mov r16, r2 ; Y
andi r16, 0x07
ori r16, 0xb0 ; set page start address for page addressing mode
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
ldi r16, 0x21 ; set column start
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
mov r16, r1 ; X
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
ldi r16, LCD_WIDTH-1
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
rcall twiStop ; (R22)
pop r15
out SREG, r15
sec
ret
LCD_SetCursor_error:
rjmp lcdTwiStopPopR15ClcRet ; (R22)
; @end
; ---------------------------------------------------------------------------
; @routine LCD_Fill @global
;
; Fill display RAM with the given value.
;
; @return CFLAG set if okay, cleared on error
; @param R16 data to write
; @clobbers r15, r16, r18, r19, r20, r21 (r17, r22)
LCD_Fill:
in r15, SREG
push r15
cli
mov r20, r16
ldi r21, 0 ; Y
LCD_Fill_loopY:
clr r18
mov r19, r21
rcall LCD_SetCursor
brcc LCD_Fill_error
rcall twiStart
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_Fill_error
ldi r16, LCD_MODE_DATA
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_Fill_error
ldi r19, LCD_WIDTH ; count backwards to save one instruction
LCD_Fill_loopX:
mov r16, r20
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
rcall twiSendByte
brcc LCD_Fill_error
dec r19
brne LCD_Fill_loopX
rcall twiStop
inc r21
cpi r21, LCD_PAGE_COUNT
brcs LCD_Fill_loopY
pop r15
out SREG, r15
sec
ret
LCD_Fill_error:
rjmp lcdTwiStopPopR15ClcRet ; (R22)
; @end
; ---------------------------------------------------------------------------
; @routine LCD_PrintFromFlash @global
;
; Print a string from flash at the current position.
;
; @return CFLAG set if okay, cleared on error
; @param Z position of string to print
; @clobbers r15, r16, Z (R17, R18, R22)
LCD_PrintFromFlash:
in r15, SREG
push r15
cli
lsl zl
rol zh
rcall twiStart
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintFromFlash_error
ldi r16, LCD_MODE_DATA
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintFromFlash_error
LCD_PrintFromFlash_loop:
lpm r16, z+
tst r16
breq LCD_PrintFromFlash_end
push zh
push zl
rcall lcdPrintOneChar
pop zl
pop zh
brcc LCD_PrintFromFlash_error
rjmp LCD_PrintFromFlash_loop
LCD_PrintFromFlash_end:
rcall twiStop
pop r15
out SREG, r15
sec
ret
LCD_PrintFromFlash_error:
rjmp lcdTwiStopPopR15ClcRet ; (R22)
; @end
; ---------------------------------------------------------------------------
; @routine LCD_PrintChar @global
;
; Print a character at the current position.
;
; @return CFLAG set if okay, cleared on error
; @param R16 char
; @clobbers r15, r16, r17, Z
LCD_PrintChar:
in r15, SREG
push r15
cli
rcall twiStart
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintChar_error
ldi r16, LCD_MODE_DATA
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintChar_error
rcall lcdPrintOneChar
brcc LCD_PrintChar_error
rcall twiStop
pop r15
out SREG, r15
sec
ret
LCD_PrintChar_error:
rjmp lcdTwiStopPopR15ClcRet ; (R22)
; @end
; ---------------------------------------------------------------------------
; @routine LCD_PrintHexByte @global
;
; Convert a given byte into HEX and write it to the current position.
;
; @return CFLAG set if okay, cleared on error
; @param R16 byte to convert to hex
; @clobbers r15, r16, r17, r20, Z
LCD_PrintHexByte:
in r15, SREG
push r15
cli
mov r20, r16
rcall twiStart
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintHexByte_error
ldi r16, LCD_MODE_DATA
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintHexByte_error
mov r16, r20
rcall lcdPrintHexByte
brcc LCD_PrintHexByte_error
rcall twiStop
pop r15
out SREG, r15
sec
ret
LCD_PrintHexByte_error:
rjmp lcdTwiStopPopR15ClcRet ; (R22)
; @end
; ---------------------------------------------------------------------------
; @routine LCD_PrintHexWord @global
;
; Convert a give word into HEX and write it to the current position.
;
; @return CFLAG set if okay, cleared on error
; @param r18 low byte of the word
; @param r19 high byte of the word
; @clobbers r15, r16, r17, r22, Z
LCD_PrintHexWord:
in r15, SREG
push r15
cli
push r18
push r19
rcall twiStart
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintHexWord_errorPop
ldi r16, LCD_MODE_DATA
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintHexWord_errorPop
pop r19
pop r18
rcall lcdPrintHexWord
brcc LCD_PrintHexWord_errorNoPop
rcall twiStop
pop r15
out SREG, r15
sec
ret
LCD_PrintHexWord_errorPop:
rcall twiStop
pop r19
pop r18
LCD_PrintHexWord_errorNoPop:
pop r15
out SREG, r15
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine lcdPrintHexWord
;
; Convert a given word into HEX and write it to the current position.
;
; @return CFLAG set if okay, cleared on error
; @param r18 low byte of the word
; @param r19 high byte of the word
; @clobbers r16, (r17, r20, Z)
lcdPrintHexWord:
mov r16, r19
push r18
rcall lcdPrintHexByte ; (r16, r17, r20, Z)
pop r18
brcc lcdPrintHexWord_error
mov r16, r18
rcall lcdPrintHexByte ; (r16, r17, r20, Z)
brcc lcdPrintHexWord_error
sec
ret
lcdPrintHexWord_error:
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine lcdPrintHexByte
;
; Convert a give byte into HEX and write it to the current position.
;
; @return CFLAG set if okay, cleared on error
; @param R16 byte to convert to hex
; @clobbers r16, r20 (r16, r17, Z)
lcdPrintHexByte:
mov r20, r16
swap r16
rcall lcdNibbleToAscii ; write high nibble (r16, r17)
rcall lcdPrintOneChar ; (r16, r17, Z)
brcc lcdPrintHexByte_error
mov r16, r20
rcall lcdNibbleToAscii ; write low nibble
rcall lcdPrintOneChar
brcc lcdPrintHexByte_error
sec
ret
lcdPrintHexByte_error:
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine lcdNibbleToAscii
;
; Convert a nibble to an ASCII char.
; @return R16 ASCII representation of that nibble (e.g. '0' for 0)
; @param R16 byte (in bits 0-3)
; @clobbers r16, r17
lcdNibbleToAscii:
andi r16, 0xf
cpi r16, 10
brcs lcdNibbleToAscii_l1
ldi r17, 7
add r16, r17
lcdNibbleToAscii_l1:
ldi r17, '0'
add r16, r17
ret
; @end
; ---------------------------------------------------------------------------
; @routine lcdWriteCommandsFromFlash
;
; @return CFLAG set if okay, cleared on error
; @param R16 number of bytes to send
; @param Z pointer to data
; @clobbers r16, r20, Z (r17, r18, r22)
lcdWriteCommandsFromFlash:
rcall twiStart
lsl zl
rol zh
mov r20, r16 ; number of bytes
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc lcdWriteCommandsFromFlash_error
ldi r16,LCD_MODE_MULTICMD
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc lcdWriteCommandsFromFlash_error
lcdWriteCommandsFromFlash_loop:
lpm r16, z+
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc lcdWriteCommandsFromFlash_error
dec r20
brne lcdWriteCommandsFromFlash_loop
rcall twiStop ; (R22)
sec
ret
lcdWriteCommandsFromFlash_error:
rcall twiStop
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine lcdPrintOneChar
;
; Print a character at the current position.
;
; @param R16 char
; @clobbers r16, r19, Z (R17, R18, R22)
lcdPrintOneChar:
rcall lcdGetCharMatrix ; (r16, r17, Z)
ldi r16, 0 ; spacing between chars
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc lcdPrintOneChar_error
ldi r19, 6
lcdPrintOneChar_loop:
lpm r16, z+
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc lcdPrintOneChar_error
dec r19
brne lcdPrintOneChar_loop
sec
ret
lcdPrintOneChar_error:
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine lcdGetCharMatrix
;
; Get pointer to matrix of given char.
;
; @return Z pos of character matrix (ready for LPM)
; @param R16 char to lookup
; @clobbers r16, r17, Z
lcdGetCharMatrix:
#ifdef LCD_MINIMAL_FONT
rcall lcdUpcase
cpi r16, 65+32
brcc lcdGetCharMatrix_l1
cpi r16, 32
brcc lcdGetCharMatrix_l2
lcdGetCharMatrix_l1:
ldi r16, 32
lcdGetCharMatrix_l2:
ldi r17, 32
sub r16, r17
mov zl, r16
clr zh
clr r17
lsl zl ; *2
rol zh
add zl, r16 ; *3
adc zh, r17
lsl zl ; *6
rol zh
ldi r16, LOW(lcdFont6x8Minimal*2)
ldi r17, HIGH(lcdFont6x8Minimal*2)
add zl, r16
adc zh, r17
ret
#else
cpi r16, 95+32
brcc lcdGetCharMatrix_l1
cpi r16, 32
brcc lcdGetCharMatrix_l2
lcdGetCharMatrix_l1:
ldi r16, 32
lcdGetCharMatrix_l2:
ldi r17, 32
sub r16, r17
mov zl, r16
clr zh
clr r17
lsl zl ; *2
rol zh
add zl, r16 ; *3
adc zh, r17
lsl zl ; *6
rol zh
ldi r16, LOW(lcdFont6x8*2)
ldi r17, HIGH(lcdFont6x8*2)
add zl, r16
adc zh, r17
ret
#endif
; @end
#ifdef LCD_MINIMAL_FONT
; ---------------------------------------------------------------------------
; @routine Uppercase the given character if it is lower case.
;
; @return R16 char
; @param R16 char
; @clobbers r16, r17
lcdUpcase:
cpi r16, 'a'
brcs lcdUpcase_done
cpi r16, 'z'+1
brcc lcdUpcase_done
ldi r17, 32
sub r16, r17
lcdUpcase_done:
ret
#endif
; @end
lcdInitCommandsBegin: ; 28 bytes
.db 0xae, 0x20, 0x00, 0xb0, 0xc8, 0x00, 0x10, 0x40
.db 0x81, 0x3f, 0xa1, 0xa6, 0xa8, LCD_HEIGHT-1, 0xa4, 0xd3
.db 0x00, 0xd5, 0xf0, 0xd9, 0x22, 0xda, 0x12, 0xdb
.db 0x20, 0x8d, 0x14, 0xaf
lcdInitCommandsEnd:
; font taken from Tiny4kOLED (https://github.com/datacute/Tiny4kOLED/tree/master/src) by Stephen Denne (MIT license),
; original by Neven Boyanov
#ifdef LCD_MINIMAL_FONT
lcdFont6x8Minimal:
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; 0
.db 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 ; ! 1
.db 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 ; " 2
.db 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 ; # 3
.db 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 ; $ 4
.db 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 ; % 5
.db 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 ; & 6
.db 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 ; ' 7
.db 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 ; ( 8
.db 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 ; ) 9
.db 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 ; * 10
.db 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 ; + 11
.db 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 ; , 12
.db 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 ; - 13
.db 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 ; . 14
.db 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 ; / 15
.db 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E ; 0 16
.db 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 ; 1 17
.db 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 ; 2 18
.db 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 ; 3 19
.db 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 ; 4 20
.db 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 ; 5 21
.db 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 ; 6 22
.db 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 ; 7 23
.db 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 ; 8 24
.db 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E ; 9 25
.db 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 ; : 26
.db 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 ; ; 27
.db 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 ; < 28
.db 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 ; = 29
.db 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 ; > 30
.db 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 ; ? 31
.db 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E ; @ 32
.db 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C ; A 33
.db 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 ; B 34
.db 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 ; C 35
.db 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C ; D 36
.db 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 ; E 37
.db 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 ; F 38
.db 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A ; G 39
.db 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F ; H 40
.db 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 ; I 41
.db 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 ; J 42
.db 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 ; K 43
.db 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 ; L 44
.db 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F ; M 45
.db 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F ; N 46
.db 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E ; O 47
.db 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 ; P 48
.db 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E ; Q 49
.db 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 ; R 50
.db 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 ; S 51
.db 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 ; T 52
.db 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F ; U 53
.db 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F ; V 54
.db 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F ; W 55
.db 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 ; X 56
.db 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 ; Y 57
.db 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 ; Z 58
.db 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 ; [ 59
.db 0x00, 0x02, 0x04, 0x08, 0x10, 0x20 ; \ 60
.db 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 ; ] 61
.db 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 ; ^ 62
.db 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 ; _ 63
.db 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 ; ' 64
#else
lcdFont6x8:
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; 0
.db 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 ; ! 1
.db 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 ; " 2
.db 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 ; # 3
.db 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 ; $ 4
.db 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 ; % 5
.db 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 ; & 6
.db 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 ; ' 7
.db 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 ; ( 8
.db 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 ; ) 9
.db 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 ; * 10
.db 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 ; + 11
.db 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 ; , 12
.db 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 ; - 13
.db 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 ; . 14
.db 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 ; / 15
.db 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E ; 0 16
.db 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 ; 1 17
.db 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 ; 2 18
.db 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 ; 3 19
.db 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 ; 4 20
.db 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 ; 5 21
.db 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 ; 6 22
.db 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 ; 7 23
.db 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 ; 8 24
.db 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E ; 9 25
.db 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 ; : 26
.db 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 ; ; 27
.db 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 ; < 28
.db 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 ; = 29
.db 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 ; > 30
.db 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 ; ? 31
.db 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E ; @ 32
.db 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C ; A 33
.db 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 ; B 34
.db 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 ; C 35
.db 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C ; D 36
.db 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 ; E 37
.db 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 ; F 38
.db 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A ; G 39
.db 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F ; H 40
.db 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 ; I 41
.db 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 ; J 42
.db 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 ; K 43
.db 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 ; L 44
.db 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F ; M 45
.db 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F ; N 46
.db 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E ; O 47
.db 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 ; P 48
.db 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E ; Q 49
.db 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 ; R 50
.db 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 ; S 51
.db 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 ; T 52
.db 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F ; U 53
.db 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F ; V 54
.db 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F ; W 55
.db 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 ; X 56
.db 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 ; Y 57
.db 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 ; Z 58
.db 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 ; [ 59
.db 0x00, 0x02, 0x04, 0x08, 0x10, 0x20 ; \ 60
.db 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 ; ] 61
.db 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 ; ^ 62
.db 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 ; _ 63
.db 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 ; ' 64
.db 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 ; a 65
.db 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 ; b 66
.db 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 ; c 67
.db 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F ; d 68
.db 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 ; e 69
.db 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 ; f 70
.db 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C ; g 71
.db 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 ; h 72
.db 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 ; i 73
.db 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 ; j 74
.db 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 ; k 75
.db 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 ; l 76
.db 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 ; m 77
.db 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 ; n 78
.db 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 ; o 79
.db 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 ; p 80
.db 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC ; q 81
.db 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 ; r 82
.db 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 ; s 83
.db 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 ; t 84
.db 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C ; u 85
.db 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C ; v 86
.db 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C ; w 87
.db 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 ; x 88
.db 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C ; y 89
.db 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 ; z 90
.db 0x00, 0x08, 0x36, 0x41, 0x41, 0x00 ; { 91
.db 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00 ; | 92
.db 0x00, 0x00, 0x41, 0x41, 0x36, 0x08 ; } 93
.db 0x00, 0x08, 0x04, 0x08, 0x10, 0x08 ; ~ 94
#endif
LCD_END:
.equ MODULE_SIZE_LCD = LCD_END-LCD_BEGIN