diff --git a/avr/lcd.asm b/avr/lcd.asm index 35e8f97..0347f1a 100644 --- a/avr/lcd.asm +++ b/avr/lcd.asm @@ -1,5 +1,9 @@ - - +; *************************************************************************** +; LCD module +; (c) 2023 Martin Preuss +; +; 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 @@ -20,16 +24,13 @@ ; *************************************************************************** ; defines -.equ LCD_CONTROLBYTE_DC_MASK = 0x40 -.equ LCD_CONTROLBYTE_CO_MASK = 0x80 - .equ LCD_TWI_ADDRESS = 0x3c .equ LCD_WIDTH = 128 .equ LCD_HEIGHT = 64 .equ LCD_PAGE_COUNT = 8 -.equ LCD_MULTIPLE = 2 + .equ LCD_CMD_MODE = 0x00 .equ LCD_DATA_MODE = 0x40 @@ -53,10 +54,16 @@ lcdDataEnd: -LCD_Init: - sbi DDRA, PORTA2 ; debug - sbi PORTA, PORTA2 ; debug (off) +; --------------------------------------------------------------------------- +; LCD_Init +; +; IN: +; - nothing +; OUT: +; - CFLAG: set if okay, clear on error +; USED: +LCD_Init: ldi zl, LOW(lcdInitCommandsBegin) ldi zh, HIGH(lcdInitCommandsBegin) ldi r16, 8 @@ -71,92 +78,50 @@ LCD_Init: ldi r16, 0 rcall LCD_Fill - ldi r18, 0 + ldi r18, 20 ldi r19, 0 rcall LCD_SetCursor - ldi zl, LOW(lcdHelloMsg1) - ldi zh, HIGH(lcdHelloMsg1) + ldi zl, LOW(lcdHelloMsg) + ldi zh, HIGH(lcdHelloMsg) rcall LCD_PrintFromFlash - ldi r18, 0 - ldi r19, 2 - rcall LCD_SetCursor - - ldi zl, LOW(lcdHelloMsg2) - ldi zh, HIGH(lcdHelloMsg2) - rcall LCD_PrintFromFlash - - ldi r18, 0 - ldi r19, 4 - rcall LCD_SetCursor - - ldi zl, LOW(lcdHelloMsg3) - ldi zh, HIGH(lcdHelloMsg3) - rcall LCD_PrintFromFlash - - ldi r18, 10 - ldi r19, 5 - rcall LCD_SetCursor - - ldi zl, LOW(lcdHelloMsg4) - ldi zh, HIGH(lcdHelloMsg4) - rcall LCD_PrintFromFlash - - sec ret +; --------------------------------------------------------------------------- +; LCD_Fini +; +; IN: +; - nothing +; OUT: +; - CFLAG: set if okay, clear on error +; USED: -; - R16: number of bytes to send -; - Z=pointer to data -lcdWriteCommandsFromFlash: - rcall twiStart - lsl zl - rol zh - mov r20, r16 ; number of bytes - ldi r16, (LCD_TWI_ADDRESS*2) - rcall twiSendByte - brcc lcdWriteCommandsFromFlash_error - tst r16 - brne lcdWriteCommandsFromFlash_error - -lcdWriteCommandsFromFlash_loop: - lpm r16, z+ - rcall twiSendByte - brcc lcdWriteCommandsFromFlash_error - tst r16 - brne lcdWriteCommandsFromFlash_error - dec r20 - brne lcdWriteCommandsFromFlash_loop - rcall twiStop - sbi DDRA, PORTA2 ; debug - cbi PORTA, PORTA2 ; debug (on) +LCD_Fini: sec ret -lcdWriteCommandsFromFlash_error: - rcall twiStop - clc - ret - ; --------------------------------------------------------------------------- ; LCD_SetCursor ; -; Set cursor. +; 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 ; ; IN: ; - R18: X ; - R19: Y ; OUT: -; - nothing +; - CFLAG: set if okay, cleared otherwise ; REGS: r1, r2, r16 (R16, R17, R18, R22) LCD_SetCursor: + in r15, SREG + cli mov r1, r18 mov r2, r19 rcall twiStart ; (R22) @@ -184,17 +149,31 @@ LCD_SetCursor: brcc LCD_SetCursor_error rcall twiStop ; (R22) + out SREG, r15 sec ret LCD_SetCursor_error: rcall twiStop ; (R22) + out SREG, r15 clc ret +; --------------------------------------------------------------------------- +; LCD_Fill +; +; Fill display RAM with the given value. +; +; IN: ; - R16: data to write +; OUT: +; - CFLAG: set if okay, cleared otherwise +; REGS: r15, r16, r18, r19, r20, r21 (r17, r22) + LCD_Fill: + in r15, SREG + cli mov r20, r16 ldi r21, 0 ; Y @@ -206,10 +185,10 @@ LCD_Fill_loopY: rcall twiStart ldi r16, (LCD_TWI_ADDRESS*2) - rcall twiSendByteExpectAck ; (R16, R17, R18, R22) + rcall twiSendByteExpectAck ; (R16, R17, R18, R22) brcc LCD_Fill_error ldi r16, LCD_DATA_MODE - rcall twiSendByteExpectAck ; (R16, R17, R18, R22) + rcall twiSendByteExpectAck ; (R16, R17, R18, R22) brcc LCD_Fill_error ldi r19, 0 @@ -225,14 +204,17 @@ LCD_Fill_loopX: inc r21 cpi r21, LCD_PAGE_COUNT brcs LCD_Fill_loopY + out SREG, r15 sec ret LCD_Fill_error: rcall twiStop + out SREG, r15 clc ret + ; --------------------------------------------------------------------------- ; LCD_PrintFromFlash ; @@ -242,8 +224,11 @@ LCD_Fill_error: ; - Z: position of string to print ; OUT: ; - CFLAG: set if okay, cleared otherwise -; REGS: +; REGS: r15, r16, Z (R17, R18, R22) + LCD_PrintFromFlash: + in r15, SREG + cli lsl zl rol zh rcall twiStart @@ -267,11 +252,13 @@ LCD_PrintFromFlash_loop: rjmp LCD_PrintFromFlash_loop LCD_PrintFromFlash_end: rcall twiStop + out SREG, r15 sec ret LCD_PrintFromFlash_error: rcall twiStop + out SREG, r15 clc ret @@ -285,8 +272,11 @@ LCD_PrintFromFlash_error: ; IN: ; - R16: char ; OUT: -; REGS: r16, r17, Z +; REGS: r15, r16, r17, Z + LCD_PrintChar: + in r15, SREG + cli rcall twiStart ldi r16, (LCD_TWI_ADDRESS*2) rcall twiSendByteExpectAck ; (R16, R17, R18, R22) @@ -298,10 +288,207 @@ LCD_PrintChar: rcall lcdPrintOneChar brcc LCD_PrintChar_error rcall twiStop + out SREG, r15 sec ret - LCD_PrintChar_error: + rcall twiStop + out SREG, r15 + clc + ret + + + +; --------------------------------------------------------------------------- +; LCD_PrintHexByte +; +; Convert a give byte into HEX and write it to the current position. +; +; IN: +; - R16: byte to convert to hex +; OUT: +; REGS: r15, r16, r17, Z + +LCD_PrintHexByte: + in r15, SREG + 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_DATA_MODE + rcall twiSendByteExpectAck ; (R16, R17, R18, R22) + brcc LCD_PrintHexByte_error + mov r16, r20 + rcall lcdPrintHexByte + brcc LCD_PrintHexByte_error + rcall twiStop + out SREG, r15 + sec + ret +LCD_PrintHexByte_error: + rcall twiStop + out SREG, r15 + clc + ret + + + +; --------------------------------------------------------------------------- +; LCD_PrintHexWord +; +; Convert a give word into HEX and write it to the current position. +; +; IN: +; - r18: low byte of the word +; - r19: high byte of the word +; OUT: +; - CFLAG: set if okay, cleared otherwise +; REGS: r15, r16, r17, Z + +LCD_PrintHexWord: + in r15, SREG + cli + push r18 + push r19 + rcall twiStart + ldi r16, (LCD_TWI_ADDRESS*2) + rcall twiSendByteExpectAck ; (R16, R17, R18, R22) + brcc LCD_PrintHexWord_error + ldi r16, LCD_DATA_MODE + rcall twiSendByteExpectAck ; (R16, R17, R18, R22) + brcc LCD_PrintHexWord_error + pop r19 + pop r18 + + rcall lcdPrintHexWord + brcc LCD_PrintHexWord_error + rcall twiStop + out SREG, r15 + sec + ret +LCD_PrintHexWord_error: + rcall twiStop + pop r19 + pop r18 + out SREG, r15 + clc + ret + + + +; --------------------------------------------------------------------------- +; lcdPrintHexWord +; +; Convert a give word into HEX and write it to the current position. +; +; IN: +; - r18: low byte of the word +; - r19: high byte of the word +; OUT: +; - CFLAG: set if okay, cleared otherwise + +lcdPrintHexWord: + mov r16, r19 + push r18 + rcall lcdPrintHexByte + pop r18 + brcc lcdPrintHexWord_error + mov r16, r18 + rcall lcdPrintHexByte + brcc lcdPrintHexWord_error + sec + ret +lcdPrintHexWord_error: + clc + ret + + + +; --------------------------------------------------------------------------- +; lcdPrintHexByte +; +; Convert a give byte into HEX and write it to the current position. +; +; IN: +; - R16: byte to convert to hex +; OUT: +; - CFLAG: set if okay, cleared otherwise +; REGS: r16, r20 (r16, r17) + +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 + + + +; --------------------------------------------------------------------------- +; lcdNibbleToAscii +; +; Convert a nibble to an ASCII char. +; IN: +; - R16: byte (in bits 0-3) +; OUT: +; - R16: ASCII representation of that nibble (e.g. '0' for 0) +; REGS: 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 + + + +; --------------------------------------------------------------------------- +; lcdWriteCommandsFromFlash +; +; IN: +; - R16: number of bytes to send +; - Z=pointer to data +; OUT: +; - CFLAG: set if okay, cleared otherwise + +; REGS: 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 + +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 @@ -316,10 +503,10 @@ LCD_PrintChar_error: ; IN: ; - R16: char ; OUT: -; REGS: r16, r17, Z +; REGS: r16, r19, Z (R17, R18, R22) lcdPrintOneChar: - rcall lcdGetCharMatrix + rcall lcdGetCharMatrix ; (r16, r17, Z) ldi r16, 0 ; spacing between chars rcall twiSendByteExpectAck ; (R16, R17, R18, R22) brcc lcdPrintOneChar_error @@ -348,6 +535,7 @@ lcdPrintOneChar_error: ; OUT: ; - Z: pos of character matrix (ready for LPM) ; REGS: r16, r17, Z + lcdGetCharMatrix: cpi r16, 95+32 brcc lcdGetCharMatrix_l1 @@ -378,17 +566,12 @@ lcdGetCharMatrix_l2: lcdInitCommandsBegin: ; 28 bytes .db LCD_CMD_MODE, 0xa8, ((LCD_PAGE_COUNT*8)-1), 0x8d, 0x14, 0xaf, 0xa1, 0xc8 lcdInitCommandsEnd: - .db 0xae, 0x00, 0x10, 0x40, 0x81, 0xcf, 0xa1, 0xc8 - .db 0xa6, 0xa8, 0x3f, 0xd3, 0x00, 0xd5, 0x80, 0xd9 - .db 0xf1, 0xda, 0x12, 0xdb, 0x40, 0x20, 0x02, 0x8d - .db 0x14, 0xa4, 0xa6, 0xaf -lcdHelloMsg1: .db "ILD :-)", 0 -;lcdHelloMsg2: .db "1234567890ABCDEFGH", 0, 0 -lcdHelloMsg2: .db "ICH LIEBE DICH!", 0 -lcdHelloMsg3: .db "abcdefghijklmnopqr", 0, 0 -lcdHelloMsg4: .db "abcde", 0 +lcdHelloMsg: .db "AqHOME 2023", 0 + +; font taken from Tiny4kOLED (https://github.com/datacute/Tiny4kOLED/tree/master/src) by Stephen Denne (MIT license), +; original by Neven Boyanov lcdFont6x8: .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; 0 .db 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 ; ! 1