/* lcd.c Routines for sending data to a serial LCD * * Copyright (C) 1998 Mark Crosbie mcrosbie@best.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Provides the following functions: * * void lcd_putc(char c) send the byte c to the LCD * void lcd_clear(void) clears the LCD screen * void lcd_home(void) homes the LCD cursor * void lcd_puts() print a string **UNIMPLEMENTED** * void lcd_printhex(char c) prints byte c as a 2 digit hex character * void lcd_printdec(char c) prints byte c as a decimal digit string * void lcd_printbin(char c) prints byte c as a binary string * void lcd_scroll_left(char n) scrolls LCD screen left n positions * void lcd_scroll_right(char n) scrolls LCD screen right n positions * void lcd_goto(char row, char col) goto a position * * Constants used: * LCDPORT port on the PIC the LCD is connected to * LCDPIN what PIN the LCD serial input is connected to * * Libraries used: * delay_ms() from the delays.lib library. * */ /* Change these definitions if you move the LCD */ #define LCDPORT PORTA #define LCDPIN 1 #define LCDCMD 254 #define LCDCLS 1 #define LCDHOME 2 #define LCDLINE1BASE 128 #define LCDLINEINCR 64 #define LCDSCRLRIGHT 28 #define LCDSCRLLEFT 24 /* defined in delays.c */ extern void delay_ms(char); /* Print a single byte to the LCD screen * * Inverts the bits as the serial LCD expects inverse polarity. * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Arguments: character c: 0 <= c <= 255 * Return Value: none * * Uses Dwayne Reid's TXBYTE routine. Thanks Dwayne! * Also uses code from Peter H. Anderson */ void lcd_putc(char c) { char sertime; /* This code adapted from: * TXBYTE: send 1 byte @ 9600 baud: 1 RAM, 15 (16) ROM, 1043 cycles * Copyright (C) 1995 Dwayne Reid. May be freely used so long as this * copyright notice is retained. * * Other parts taken from code: * Copyright, Peter H. Anderson, Morgan State University, June 14, '97 * * This code must invert the sense of the bits because the Serial * LCD backpack expects it this way. This includes inverting the sense * of the START and STOP bits. */ clear_bit(LCDPORT, LCDPIN); /* set to stop bit */ sertime = 255; while(sertime-- != 0); /* let stop bit be set for a while */ /* now we loop through 9 bits and set the output line. After each bit, pause for 104uS. This represents 9600 baud */ asm movlw 9 ; 8 data + 1 start asm clrc ; start bit lcdtxloop: asm skpnc ; bit time = 104.167 uSec clear_bit(LCDPORT, LCDPIN); asm skpc set_bit(LCDPORT, LCDPIN); lcddloop: asm ; 95 clk cycle delay asm goto $+1 ; 2-cycle NOP in 1 instruction! asm addlw b'00010000' ; increment upper nibble asm skpc ; delay = 6n -1 (1 less when falls thru) /* A relative jump backwards */ asm goto $-3 ; goto lcddloop loop sixteen times asm addlw -1 ; dec w, valid z, c=1 if w=0 after decrement asm rrf param00_lcd_putc,F ; carry will be set - shifted in as stop bit asm skpz /* A relative jump back */ asm goto $-0xb ; goto lcdtxloop txloop is 104 clk cycles clear_bit(LCDPORT, LCDPIN); /* send stop bit */ delay_ms(10); /* a pacing delay of 10ms between characters */ } /* * clear the LCD screen * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Arguments: none * Return Value: none */ void lcd_clear(void) { lcd_putc(LCDCMD); lcd_putc(LCDCLS); } /* * Home the LCD cursor * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Arguments: none * Return Value: none */ void lcd_home(void) { lcd_putc(LCDCMD); lcd_putc(LCDHOME); } /* Print a string to the LCD screen * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Arguments: s: address of a string of bytes in DATA memory * string must be NULL terminated * Returns: number of bytes written (number of chars printed) */ char lcd_puts(char s) { } /* Print a value in decimal to the LCD screen * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Note: output is always 3 digits: 001 not 1, 025, not 25 * Arguments: x: value to print 0 <= x <= 255 * Returns: none */ void lcd_printdec(char x) { char count; /* how many hundreds? */ count=0; while(x > 99) { x = x - 100; count++; } lcd_putc('0' + count); /* how many tens? */ count=0; while(x > 9) { x = x - 10; count++; } lcd_putc('0' + count); /* and finally units */ lcd_putc('0' + x); } /* Print a value in hex to the LCD screen * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Arguments: x: value to print 0 <= x <= 255 * Returns: none */ void lcd_printhex(char x) { char nibble; /* extract high nibble */ nibble = x & 0xf0; /* swap the high and low nibbles */ asm swapf _nibble_lcd_printhex, f; if(nibble < 10) { lcd_putc('0' + nibble); } else { lcd_putc(nibble - 10 + 'A'); } /* do the same on the low nibble */ nibble = x & 0x0f; if(nibble < 10) { lcd_putc('0' + nibble); } else { lcd_putc(nibble - 10 + 'A'); } } /* Print a value to the LCD screen as binary * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Arguments: x: value to print 0 <= x <= 255 * Returns: none */ void lcd_printbin(char x) { char bits[] = {128, 64, 32, 16, 8, 4, 2, 1}; char i = 0; while(i < 8) { if(x & bits[i]) { lcd_putc('1'); } else { lcd_putc('0'); } i++; } } /* Move the cursor to the specified position * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Arguments: row: row on LCD: 0 <= row <= 1 * col: column on LCD: 0 <= col <= 16 * *** Remember: columns are indexed from the left starting at col 0. * If you print off the screen, it is not displayed, but is stored in * the LCD's RAM. Use the lcd_scroll_left and lcd_scroll_right commands * to access the data * * Returns: nothing */ void lcd_goto(char row, char col) { lcd_putc(LCDCMD); lcd_putc(LCDLINE1BASE + (LCDLINEINCR * row) + col); } /* Scroll the display N characters to the left * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Arguments: N: number of characters to scroll left. N > 0 * There is a 10ms delay between each scroll action * Returns: nothing */ void lcd_scroll_left(char n) { while(n) { lcd_putc(LCDCMD); lcd_putc(LCDSCRLLEFT); delay_ms(10); n--; } } /* Scroll the display N characters to the right * *** Assumes 9600 8N1 communication *** The constant LCDPIN defines which pin the LCD is on *** The constant LCDPORT defines which port the LCD in on * * Arguments: N: number of characters to scroll right. N > 0 * There is a 10ms delay between each scroll action * Returns: nothing */ void lcd_scroll_right(char n) { while(n) { lcd_putc(LCDCMD); lcd_putc(LCDSCRLRIGHT); delay_ms(10); n--; } }
[HOME] to Mark's page.
Created on Dec 6 1998 by
Mark Crosbie (mcrosbie@best.com) Last modified: Sun Dec 6 19:09:27 PST 1998