This shows you the differences between two versions of the page.
— |
pic18f4685_8bit_lcd_driver [2007/04/10 00:06] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | <file> | ||
+ | ; | ||
+ | ; 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.<BR> | ||
+ | ;; On CLCDs: branch directly to USER_LCD_PrintChar<BR> | ||
+ | ;; 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.<BR> | ||
+ | ;; On CLCDs: use this function to decode the HD44780 commands if required<BR> | ||
+ | ;; 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 | ||
+ | </file> |