jp main ; Startup vector: DO NOT MOVE! Must be the first instruction ; Tests TM404A, on ports 2 and 3 IO_2: EQU 0x40 IO_3: EQU 0x60 LCD_TOP_INSTR_REG: EQU IO_2 LCD_TOP_DATA_REG: EQU IO_2 + 1 LCD_BOTTOM_INSTR_REG: EQU IO_3 LCD_BOTTOM_DATA_REG: EQU IO_3 + 1 ; Inits the lcd display LCD4004_init: ; --- Init first controller --- ; The following are documented as in the datasheet: RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ; Function set: 0 0 0 0 1 DL N F 0 0 (DL: 8-bit/4-bit, N: number of display lines 2/1, F: Font type 11dots/8dots) ; 0000111000 (8 bit, 2 lines) ld a,0x38 out (LCD_TOP_INSTR_REG),a call LCD4004_wait_busy_clear ; Display ON/OFF Control: 0 0 0 0 0 0 1 D C B (D: display on/off, C: cursor on/off, B: blinking cursor on/off) ; 0000001111 (display on, blinking cursor) ld a,0x0F out (LCD_TOP_INSTR_REG),a call LCD4004_wait_busy_clear ; Clear display ; 0000000001 ld a,0x01 out (LCD_TOP_INSTR_REG),a call LCD4004_wait_busy_clear ; --- Init second controller --- ; The following are documented as in the datasheet: RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ; Function set: 0 0 0 0 1 DL N F 0 0 (DL: 8-bit/4-bit, N: number of display lines 2/1, F: Font type 11dots/8dots) ; 0000111000 (8 bit, 2 lines) ld a,0x38 out (LCD_BOTTOM_INSTR_REG),a call LCD4004_wait_busy_clear ; Display ON/OFF Control: 0 0 0 0 0 0 1 D C B (D: display on/off, C: cursor on/off, B: blinking cursor on/off) ; 0000001111 (display on, blinking cursor) ld a,0x0F out (LCD_BOTTOM_INSTR_REG),a call LCD4004_wait_busy_clear ; Clear display ; 0000000001 ld a,0x01 out (LCD_BOTTOM_INSTR_REG),a call LCD4004_wait_busy_clear ret ; Prints string ; @param BC Pointer to a null-terminated string first character LCD4004_TOP_print: ld a, (bc) ; bc is the pointer to passed string's first char cp 0 ; compare A content with 0 (subtract 0 from value and set zero flag Z if result is 0) ret z ; if prev compare is true (Z flag set), string is finished, return out (LCD_TOP_DATA_REG),a ; output char call LCD4004_wait_busy_clear ; wait for the lcd to execute (busy signal check) inc bc ; increment bc to move to next char jp LCD4004_TOP_print ; Prints string ; @param BC Pointer to a null-terminated string first character LCD4004_BOTTOM_print: ld a, (bc) ; bc is the pointer to passed string's first char cp 0 ; compare A content with 0 (subtract 0 from value and set zero flag Z if result is 0) ret z ; if prev compare is true (Z flag set), string is finished, return out (LCD_BOTTOM_DATA_REG),a ; output char call LCD4004_wait_busy_clear ; wait for the lcd to execute (busy signal check) inc bc ; increment bc to move to next char jp LCD4004_BOTTOM_print ; Waits for the busy flag to be clear, indicating the LCD controllers to have finished their work LCD4004_wait_busy_clear: ret in a, (LCD_TOP_INSTR_REG) ; reads the status rla ; busy flag is DB7, so we shift it into carry to check it jp c, LCD4004_wait_busy_clear ; if carry is set, lcd is busy in a, (LCD_BOTTOM_INSTR_REG) ; reads the status rla ; busy flag is DB7, so we shift it into carry to check it jp c, LCD4004_wait_busy_clear ; if carry is set, lcd is busy ret ; --- TEST CODE --- main: TEST_STR_80: DB "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam augue tortor sed.",0 ; null terminated string TEST_STR_85: DB "2Lorem ipsum dolor sit amet, consectetur adipiscing elit praesent pellentesque nisi.",0 ; null terminated string ; Init display call LCD4004_init ; Write string on first 2 lines ld bc, TEST_STR_80 call LCD4004_TOP_print ; Write long string on last 2 lines (to see how it wraps) ld bc, TEST_STR_85 call LCD4004_BOTTOM_print halt