; ; MIOS Custom LCD Driver Example for character LCDs ; ; NOTE: this is just a template for LCDs which are different to ; HD44780 (that is natively supported by MIOS -> LCD type #0) ; Note also that this driver only supports a single CLCD ; and no free definable enable (E) line ; ; ========================================================================== ; ; Copyright (C) 2003 Thorsten Klose (tk@midibox.org) ; Licensed for personal non-commercial use only. ; All other rights reserved. ; ; ========================================================================== ;; -------------------------------------------------------------------------- ;; Following system variables are given by MIOS and can be directly ;; accessed by the driver. The addresses are defined in mios.h and ;; should not be changed ;; ;; MIOS_GLCD_BUFFER a 8 byte buffer for data transfers ;; MIOS_LCD_OPTION1 contains the first LCD option given by MIOS_LCD_TypeSet ;; MIOS_LCD_OPTION2 contains the second LCD option given by MIOS_LCD_TypeSet ;; MIOS_LCD_CURSOR_POS the current cursor pos of characters (GLCD: multiplied by width) ;; MIOS_GLCD_GCURSOR_X for GLCDs: the current X position of graphical cursor ;; MIOS_GLCD_GCURSOR_Y for GLCDs: the current Y position of graphical cursor ;; MIOS_GLCD_FONT_WIDTH for GLCDs: the fontwidth given by MIOS_GLCD_FontInit ;; MIOS_GLCD_FONT_HEIGHT for GLCDs: the fontheight given by MIOS_GLCD_FontInit ;; MIOS_GLCD_FONT_X0 for GLCDs: the first byte within a char entry ;; MIOS_GLCD_FONT_OFFSET for GLCDs: the byte offset between the characters ;; MIOS_GLCD_FONT_PTRL for GLCDs: pointer to the character table, low-byte ;; MIOS_GLCD_FONT_PTRH for GLCDs: pointer to the character table, high-byte ;; MIOS_LCD_TIMEOUT0 can be used for timeout loops ;; MIOS_LCD_TIMEOUT1 can be used for timeout loops ;; MIOS_GLCD_TMP1 can be used as temporary buffer ;; MIOS_GLCD_TMP2 can be used as temporary buffer ;; MIOS_GLCD_TMP3 can be used as temporary buffer ;; MIOS_GLCD_TMP4 can be used as temporary buffer ;; MIOS_LCD_Y0_OFFSET Y0 offset of LCD ;; MIOS_LCD_Y1_OFFSET Y1 offset of LCD ;; MIOS_LCD_Y2_OFFSET Y2 offset of LCD ;; MIOS_LCD_Y3_OFFSET Y3 offset of LCD ;; MIOS_LCD_CURSOR_POS_REAL unmapped cursor position which has been set with MIOS_LCD_CursorSet ;; ;; Note: the addresses are located in an upper bank and therefore have to ;; be accessed with the BANKED flag. Also the BSR has to be justified ;; before using the registers ;; Example: ;; SET_BSR MIOS_LCD_OPTION1 ; sets BSR to the bank where MIOS_LCD_* ;; ; has been located. You don't need to ;; ; change the BSR for the other LCD registers ;; movf MIOS_LCD_OPTION1, W, BANKED ; get LCD option #1 ;; ;; Important: to allow a proper interaction with MIOS applications, you are ;; only allowed to modify MIOS_PARAMETER[123], the mutliplication registers ;; and FSR1. You are not allowed to change TMP[1-5] or FSR0 ;; if you need some temporary registers, use the given addresses above or ;; locate them to addresses which are not used by the application ;; -------------------------------------------------------------------------- ;; Pins of LC-Display USER_LCD_LAT_D EQU LATB ; Pin B.7-0 USER_LCD_PORT_D EQU PORTB USER_LCD_TRIS_D EQU TRISB USER_LCD_LAT_RW EQU LATD USER_LCD_PIN_RW EQU 6 ; Pin D.6 USER_LCD_LAT_RS EQU LATD USER_LCD_PIN_RS EQU 5 ; Pin D.5 USER_LCD_LAT_E EQU LATD ; Pin D.7 USER_LCD_PIN_E EQU 7 ;; new names for CLCD registers USER_LCD_STATUS EQU MIOS_GLCD_TMP1 USER_LCD_SC_CTR EQU MIOS_GLCD_TMP3 #define USER_LCD_STATUS_LCD0_DISABLED 0 ; bit0: if set, first LCD disabled #define USER_LCD_STATUS_LCD1_DISABLED 1 ; bit1: if set, second LCD disabled -- not provided by this driver! #define USER_LCD_STATUS_CUR_DISABLED 2 ; bit2: if set, currently selected LCD disabled #define USER_LCD_STATUS_CUR_LCD 3 ; bit3: if cleared: current LCD is first LCD, else second LCD ;; -------------------------------------------------------------------------- ;; This function is called by MIOS when the custom LCD should be initialized ;; In: MIOS_LCD_OPTION1 - contains the first LCD option given by MIOS_LCD_TypeSet ;; MIOS_LCD_OPTION2 - contains the second LCD option given by MIOS_LCD_TypeSet ;; Out: - ;; -------------------------------------------------------------------------- USER_LCD_Init ;; notify that no graphical LCD is connected bcf MIOS_BOX_CFG0, MIOS_BOX_CFG0_USE_GLCD movlw 0xf9 ; set only TRISE[2:1] as output andwf TRISE, F ; (Initialization of Ports: done in Init_Ports) SET_BSR MIOS_LCD_TIMEOUT1 clrf USER_LCD_STATUS, BANKED movlw 100 ; 100 ms delay call MIOS_Delay bcf USER_LCD_LAT_RW, USER_LCD_PIN_RW ; LCD_WRITE bcf USER_LCD_LAT_RS, USER_LCD_PIN_RS ; USER_LCD_PIN_RS_0 ;; initialize LCD movlw 0x38 movwf USER_LCD_LAT_D rcall USER_LCD_Strobe_Set rcall USER_LCD_Strobe_Clr movlw 50 ; 50 ms delay call MIOS_Delay rcall USER_LCD_Strobe_Set rcall USER_LCD_Strobe_Clr movlw 50 ; 50 ms delay call MIOS_Delay rcall USER_LCD_Strobe_Set rcall USER_LCD_Strobe_Clr movlw 0x08 ; Display Off rcall USER_LCD_Cmd movlw 0x0c ; Display On rcall USER_LCD_Cmd movlw 0x06 ; Entry Mode rcall USER_LCD_Cmd movlw 0x01 ; Clear Display call USER_LCD_Cmd bcf MIOS_LCD_TIMEOUT1, 7, BANKED ; everything ok, make sure that LCD_TIMEOUT, bit 7 is cleared movlw 0x38 ; without these lines the LCD will not work rcall USER_LCD_Cmd ; correctly after a second USER_LCD_Init movlw 0x0c rcall USER_LCD_Cmd movlw 0x00 ; set cursor to zero pos rgoto USER_LCD_CursorSet ;; -------------------------------------------------------------------------- ;; FUNCTION: USER_LCD_Data ;; DESCRIPTION: sends a data value to the LCD display.
;; On CLCDs: branch directly to USER_LCD_PrintChar
;; On GLCDs: ignore this function! ;; IN: data which should be sent ;; OUT: - ;; -------------------------------------------------------------------------- USER_LCD_Data ;; store byte in data latch movwf USER_LCD_LAT_D ;; store bits 3:2 into port E bits 2:1 rrncf WREG, 0, 0 ;; shift right movwf LATE ;; store in port E latch rlncf WREG, 0, 0 ;; shift left, leave WREG as it was! ;; wait until display unbusy rcall USER_LCD_WaitUnbusy ;; exit if current LCD not available due to timeout BIFSET USER_LCD_STATUS, USER_LCD_STATUS_CUR_DISABLED, BANKED, return ;; select data register bsf USER_LCD_LAT_RS, USER_LCD_PIN_RS ;; activate write bcf USER_LCD_LAT_RW, USER_LCD_PIN_RW ;; strobe and exit rcall USER_LCD_Strobe_Set rgoto USER_LCD_Strobe_Clr ;; -------------------------------------------------------------------------- ;; FUNCTION: USER_LCD_Cmd ;; DESCRIPTION: sends a command to the LCD display.
;; On CLCDs: use this function to decode the HD44780 commands if required
;; On GLCDs: ignore this function! ;; IN: command which should be sent ;; OUT: - ;; -------------------------------------------------------------------------- USER_LCD_Cmd ;; store byte in data latch movwf USER_LCD_LAT_D ;; store bits 3:2 into port E bits 2:1 rrncf WREG, 0, 0 ;; shift right movwf LATE ;; store in port E latch rlncf WREG, 0, 0 ;; shift left, leave WREG as it was! ;; wait until display unbusy rcall USER_LCD_WaitUnbusy ;; exit if current LCD not available due to timeout BIFSET USER_LCD_STATUS, USER_LCD_STATUS_CUR_DISABLED, BANKED, return ;; select command register bcf USER_LCD_LAT_RS, USER_LCD_PIN_RS ;; activate write bcf USER_LCD_LAT_RW, USER_LCD_PIN_RW ;; strobe and exit rcall USER_LCD_Strobe_Set rgoto USER_LCD_Strobe_Clr ;; -------------------------------------------------------------------------- ;; This function is NOT called by MIOS, but only used by the custom driver ;; to wait until the LCD is unbusy ;; In: - ;; Out: - ;; -------------------------------------------------------------------------- USER_LCD_WaitUnbusy ;; exit if current LCD not available due to timeout BIFSET USER_LCD_STATUS, USER_LCD_STATUS_CUR_DISABLED, BANKED, return ;; turn off output drivers movlw 0xf3 ; set all except TRISB[3:2] as input iorwf USER_LCD_TRIS_D, F movlw 0x06 ; set only TRISE[2:1] as input iorwf TRISE, F ;; select command register bcf USER_LCD_LAT_RS, USER_LCD_PIN_RS ;; poll busy bit clrf MIOS_LCD_TIMEOUT0, BANKED clrf MIOS_LCD_TIMEOUT1, BANKED bsf USER_LCD_LAT_RW, USER_LCD_PIN_RW ; LCD_READ USER_LCD_WaitUnbusy_Loop rcall USER_LCD_Strobe_Clr incf MIOS_LCD_TIMEOUT0, F, BANKED skpnz incf MIOS_LCD_TIMEOUT1, F, BANKED bz USER_LCD_WaitUnbusy_Disable ; leave loop when LCD_TIMEOUT = 0xff. Up to now bit 7 is set and the LCD ; busy routine will never be called again rcall USER_LCD_Strobe_Set IFSET USER_LCD_PORT_D, 7, rgoto USER_LCD_WaitUnbusy_Loop rcall USER_LCD_Strobe_Clr USER_LCD_WaitUnbusy_End ;; turn on output drivers again movlw 0x0c ; set all except TRISB[3:2] as output andwf USER_LCD_TRIS_D, F movlw 0xf9 ; set only TRISE[2:1] as output andwf TRISE, F return USER_LCD_WaitUnbusy_Disable ;; disable currently selected LCD btfss USER_LCD_STATUS, USER_LCD_STATUS_CUR_LCD, BANKED bsf USER_LCD_STATUS, USER_LCD_STATUS_LCD0_DISABLED, BANKED btfsc USER_LCD_STATUS, USER_LCD_STATUS_CUR_LCD, BANKED bsf USER_LCD_STATUS, USER_LCD_STATUS_LCD1_DISABLED, BANKED rgoto USER_LCD_WaitUnbusy_End ;; -------------------------------------------------------------------------- ;; This function is NOT called by MIOS, but only used by the custom driver ;; to set the strobe line to logic-1 ;; In: - ;; Out: - ;; -------------------------------------------------------------------------- USER_LCD_Strobe_Set ;; (code for variable E output removed) bsf USER_LCD_LAT_E, USER_LCD_PIN_E nop nop nop nop nop return ;; -------------------------------------------------------------------------- ;; This function is NOT called by MIOS, but only used by the custom driver ;; to set the strobe line to logic-0 ;; In: - ;; Out: - ;; -------------------------------------------------------------------------- USER_LCD_Strobe_Clr ;; (code for variable E output removed) nop nop nop nop nop bcf USER_LCD_LAT_E, USER_LCD_PIN_E return ;; -------------------------------------------------------------------------- ;; This function is called by MIOS when the custom LCD should be cleared ;; In: MIOS_LCD_OPTION1 - contains the first LCD option given by MIOS_LCD_TypeSet ;; MIOS_LCD_OPTION2 - contains the second LCD option given by MIOS_LCD_TypeSet ;; Out: - ;; -------------------------------------------------------------------------- USER_LCD_Clear movlw 0x01 call USER_LCD_Cmd BIFSET MIOS_LCD_Y2_OFFSET, 7, BANKED, rgoto USER_LCD_Clear2 BIFSET MIOS_LCD_Y3_OFFSET, 7, BANKED, rgoto USER_LCD_Clear2 return USER_LCD_Clear2 bsf MIOS_LCD_CURSOR_POS, 7, BANKED movlw 0x01 call USER_LCD_Cmd bcf MIOS_LCD_CURSOR_POS, 7, BANKED return ;; -------------------------------------------------------------------------- ;; This function is called by MIOS when the cursor should be changed ;; In: MIOS_LCD_OPTION1 - contains the first LCD option given by MIOS_LCD_TypeSet ;; MIOS_LCD_OPTION2 - contains the second LCD option given by MIOS_LCD_TypeSet ;; MIOS_GLCD_CURSOR_X - horizontal cursor position (for GLCDs) ;; MIOS_GLCD_CURSOR_Y - vertical cursor position (for GLCDs) ;; MIOS_LCD_CURSOR_POS - character cursor position (for CLCDs) ;; Out: - ;; -------------------------------------------------------------------------- USER_LCD_CursorSet SET_BSR MIOS_LCD_CURSOR_POS movf MIOS_LCD_CURSOR_POS, W, BANKED iorlw 0x80 rgoto USER_LCD_Cmd ;; -------------------------------------------------------------------------- ;; This function is called by MIOS when a character should be print ;; In: WREG - character ;; all other MIOS_*LCD_* registers ;; Out: GLCDs should justify the X/Y cursor position ;; -------------------------------------------------------------------------- USER_LCD_PrintChar rgoto USER_LCD_Data ;; -------------------------------------------------------------------------- ;; FUNCTION: USER_LCD_SpecialCharInit ;; DESCRIPTION: see MIOS_CLCD_SpecialCharInit ;; IN: number of special character (0-7) in WREG ;; pointer to special char pattern in TBLPTR (consists of 8 ;; entries for every character-line) ;; OUT: TBLPTR has to be set to next table entry (TBLPTR+=8) ;; -------------------------------------------------------------------------- USER_LCD_SpecialCharInit ;; transfer special character to display swapf WREG, F rrf WREG, W andlw 0x38 iorlw 0x40 rcall USER_LCD_Cmd SET_BSR USER_LCD_SC_CTR clrf USER_LCD_SC_CTR, BANKED USER_LCD_SpecialCharInitLoop tblrd*+ movf TABLAT, W rcall USER_LCD_Data incf USER_LCD_SC_CTR, F, BANKED BIFCLR USER_LCD_SC_CTR, 3, BANKED, rgoto USER_LCD_SpecialCharInitLoop goto USER_LCD_CursorSet