LCDproc development and user support list

Text archives Help


[Lcdproc] New HD44780 sub driver


Chronological Thread 
  • From: vince AT kyllikki.org (Vincent Sanders)
  • Subject: [Lcdproc] New HD44780 sub driver
  • Date: Fri Jul 4 01:37:02 2003

Greetings

Attached is a new sub driver for the onboard 8bit LCD module port on
Simtec's EB2410ITX board
(http://www.simtec.co.uk/products/EB2410ITX/). The port supports two
selects E1 and E2 has current limited contrast and backlight controls
which are software configurable (even PWM controlable!)

The attached diff is against the 0.4.4 CVS snapshot as of a couple of
days ago the driver supports standard module i/o and backlight
control. There is provision for acess to the keypad(keypad? there are
8 rows by 6 colums thats 48 keys!) GPIO lines but I have not
implemented this yet.

There are some special notes!

This driver relies upon mmaping /dev/mem this works fine on this ARM
board but may raise issues on other architectures - maybe it should
only be built on ARM targets?

Because this driver uses mmaped areas it must be able to munmap these
areas and cleanly close itself if possible which leads onto...

I have extended the sub driver functions to include a close function,
this is called when the main driver close() is called and may be
overiden by the driver just like the sendata or backlight functions.

Comments apreciated, placing in the CVS even more so ;-)

--
Regards Vincent
http://www.kyllikki.org/
diff -ubrN lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780-bast.c
lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780-bast.c
--- lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780-bast.c
1970-01-01 01:00:00.000000000 +0100
+++ lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780-bast.c
2003-07-04 01:39:27.000000000 +0100
@@ -0,0 +1,335 @@
+/*
+ * 8-bit driver module for Hitachi HD44780 based LCD displays.
+ * The LCD is operated in it's 8 bit-mode and is attched to the onboard port
+ * of the bast board (http://www.simtec.co.uk/products/EB2410ITX/)
+ *
+ * Copyright (C) 2003, Vincent Sanders
<vince AT simtec.co.uk>
+ *
+ * The board allows for direct access to an 8bit LCD module using memory
areas
+ * to select command and data ports, read and write, the areas are duplicated
+ * once for E1 and once for E2. The bast board also allows for backlight
+ * control both on and off but also using PWM for variable brightnes.
+ *
+ * Wiring on the board is intended so most HD44780 type display modules can
be
+ * connected with a simple ribbon cable, refer to the web site for port
pinouts
+ * and example wiring for several modules.
+ *
+ * Based on the code in the ext8bit driver
+ *
+ * This file is released under the GNU General Public License. Refer to the
+ * COPYING file distributed with this package.
+ */
+
+#include "hd44780-bast.h"
+#include "hd44780.h"
+#include "lpt-port.h"
+
+#include "port.h"
+#include "lcd_sem.h"
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+// Generally, any function that accesses the LCD control lines needs to be
+// implemented separately for each HW design. This is typically (but not
+// restricted to):
+// HD44780_senddata
+// HD44780_readkeypad
+
+void bast_HD44780_senddata (unsigned char displayID, unsigned char flags,
unsigned char ch);
+void bast_HD44780_backlight (unsigned char state);
+unsigned char bast_HD44780_readkeypad (unsigned int YData);
+void bast_HD44780_close();
+
+static char backlight_bit = 0;
+static int stuckinputs;
+
+static int semid;
+
+volatile unsigned char *bast_lcd_e1_wdata;
+volatile unsigned char *bast_lcd_e1_wcmd;
+volatile unsigned char *bast_lcd_e1_rcmd;
+
+volatile unsigned char *bast_lcd_e2_wdata;
+volatile unsigned char *bast_lcd_e2_wcmd;
+volatile unsigned char *bast_lcd_e2_rcmd;
+
+volatile unsigned char *bast_cpld4;
+
+volatile unsigned long *bast_cpu_gpio;
+
+int bastfd;
+
+#define MAPSIZE (4*1024)
+
+#define BAST_LCD_E1_WCMD (0x08000000)
+#define BAST_LCD_E1_RCMD (0x08800000)
+#define BAST_LCD_E1_WDATA (0x09000000)
+#define BAST_LCD_E1_RDATA (0x09800000)
+
+#define BAST_LCD_E2_WCMD (0x0A000000)
+#define BAST_LCD_E2_RCMD (0x0A800000)
+#define BAST_LCD_E2_WDATA (0x0B000000)
+#define BAST_LCD_E2_RDATA (0x0B800000)
+
+#define BAST_CS1 (0x8 << 24)
+#define BAST_LCD_CPLD4 (BAST_CS1 + (0xe << 23))
+
+#define BAST_CPU_GPIO (0x56000000)
+
+volatile unsigned char *
+bast_map_area(unsigned long area)
+{
+ void *data = mmap(NULL, MAPSIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
bastfd, area);
+
+ if (data == (void *)-1)
+ {
+ perror("mmap");
+ return NULL;
+ }
+ return (volatile unsigned char *)data;
+}
+
+void
+bast_munmap()
+{
+ if(bast_lcd_e1_wdata)
+ munmap(bast_lcd_e1_wdata, MAPSIZE);
+ if(bast_lcd_e1_wcmd)
+ munmap(bast_lcd_e1_wcmd, MAPSIZE);
+ if(bast_lcd_e1_rcmd)
+ munmap(bast_lcd_e1_rcmd, MAPSIZE);
+ if(bast_lcd_e1_wdata)
+ munmap(bast_lcd_e2_wdata, MAPSIZE);
+ if(bast_lcd_e1_wcmd)
+ munmap(bast_lcd_e2_wcmd, MAPSIZE);
+ if(bast_lcd_e1_rcmd)
+ munmap(bast_lcd_e2_rcmd, MAPSIZE);
+ if(bast_cpld4)
+ munmap(bast_cpld4, MAPSIZE);
+ if(bast_cpu_gpio)
+ munmap(bast_cpu_gpio, MAPSIZE);
+}
+
+int
+bast_mmap()
+{
+ bast_lcd_e1_wdata = bast_map_area(BAST_LCD_E1_WDATA);
+ if( bast_lcd_e1_wdata == NULL)
+ return 1;
+
+ bast_lcd_e1_wcmd = bast_map_area(BAST_LCD_E1_WCMD);
+ if( bast_lcd_e1_wcmd == NULL)
+ return 2;
+
+ bast_lcd_e1_rcmd = bast_map_area(BAST_LCD_E1_RCMD);
+ if( bast_lcd_e1_rcmd == NULL)
+ return 3;
+
+ bast_lcd_e2_wdata = bast_map_area(BAST_LCD_E2_WDATA);
+ if( bast_lcd_e2_wdata == NULL)
+ return 4;
+
+ bast_lcd_e2_wcmd = bast_map_area(BAST_LCD_E2_WCMD);
+ if( bast_lcd_e2_wcmd == NULL)
+ return 5;
+
+ bast_lcd_e2_rcmd = bast_map_area(BAST_LCD_E2_RCMD);
+ if( bast_lcd_e2_rcmd == NULL)
+ return 6;
+
+ bast_cpld4 = bast_map_area(BAST_LCD_CPLD4);
+ if( bast_cpld4 == NULL )
+ return 7;
+
+ bast_cpu_gpio = bast_map_area(BAST_CPU_GPIO);
+ if( bast_cpu_gpio == NULL )
+ return 8;
+
+ return 0;
+}
+
+
+
+/* write byte to port, the double write is correct, the first starts the
+ * write cycle the second finishes it, this is so the onboard logic doesnt
have
+ * to do extended wait states */
+void
+bast_lcd_write(volatile unsigned char * reg,unsigned char val)
+{
+ *reg=val;
+ hd44780_functions->uPause (1);
+ *reg=val;
+}
+
+unsigned char
+bast_lcd_read(volatile unsigned char * reg)
+{
+ unsigned char tmp;
+ tmp = *reg;
+ hd44780_functions->uPause (1);
+ return *reg;
+}
+
+
+/* check the lcd busy command register and wait until its cleared */
+static int
+bast_busy_wait(volatile unsigned char * reg)
+{
+ int count = 0x8000;
+ unsigned long tmp;
+
+ while (count-- > 0) {
+ hd44780_functions->uPause (10);
+
+ tmp=bast_lcd_read(reg);
+
+ if ((tmp & (1<<7)) == 0)
+ {
+ return (tmp & 0x7f);
+ }
+ }
+ return -1;
+}
+
+void
+bast_backlight_init()
+{
+ bast_cpu_gpio[4] = ((bast_cpu_gpio[4] & (~3)) | 1);/* configure GPIOB0
as output */
+}
+
+
+// initialise the driver
+int
+hd_init_bast (HD44780_functions * hd44780_functions, lcd_logical_driver *
driver, char *args, unsigned int port)
+{
+ semid = sem_get ();
+
+ /* get fd for /dev/mem */
+ bastfd = open("/dev/mem", O_RDWR | O_SYNC);
+
+ if (bastfd < 0) {
+ perror("open(/dev/mem)");
+ return 1;
+ }
+
+ /* get mmaped areas */
+ if (bast_mmap())
+ {
+ bast_munmap();/* remove any mappings that suceeded */
+ return 2;
+ }
+
+ bast_backlight_init();
+
+
+ /* all areas sucessfuly mapped - setup functions */
+ hd44780_functions->senddata = bast_HD44780_senddata;
+ hd44780_functions->backlight = bast_HD44780_backlight;
+ hd44780_functions->readkeypad = bast_HD44780_readkeypad;
+ hd44780_functions->close = bast_HD44780_close;
+
+ // setup the lcd in 8 bit mode
+ hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
+ hd44780_functions->uPause (4100);
+ hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT);
+ hd44780_functions->uPause (100);
+ hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_8BIT | TWOLINE |
SMALLCHAR);
+ hd44780_functions->uPause (40);
+
+ common_init ();
+
+ if (have_keypad) {
+ // Remember which input lines are stuck
+ stuckinputs = bast_HD44780_readkeypad (0);
+ }
+ return 0;
+}
+
+
+
+/* frees all resources claimed by driver */
+void
+bast_HD44780_close()
+{
+ bast_munmap();
+
+ close(bastfd);
+}
+
+// bast_HD44780_senddata
+void
+bast_HD44780_senddata (unsigned char displayID, unsigned char flags,
unsigned char ch)
+{
+ sem_wait (semid);
+
+ /* printf("bast_HD44780_senddata: displayID %d\n",displayID);*/
+
+ switch(displayID)
+ {
+
+ case 0:/*all enables */
+ bast_busy_wait(bast_lcd_e1_rcmd);/* wait for module to be ready */
+ bast_busy_wait(bast_lcd_e2_rcmd);/* wait for module to be ready */
+ if (flags == RS_DATA)
+ {
+ bast_lcd_write(bast_lcd_e1_wdata,ch);
+ bast_lcd_write(bast_lcd_e2_wdata,ch);
+ }
+ else
+ {
+ bast_lcd_write(bast_lcd_e1_wcmd,ch);
+ bast_lcd_write(bast_lcd_e2_wdata,ch);
+ }
+ break;
+
+ case 1:
+ bast_busy_wait(bast_lcd_e2_rcmd);/* wait for module to be ready */
+ if (flags == RS_DATA)
+ bast_lcd_write(bast_lcd_e1_wdata,ch);
+ else
+ bast_lcd_write(bast_lcd_e1_wcmd,ch);
+ break;
+
+ case 2:
+ bast_busy_wait(bast_lcd_e2_rcmd);/* wait for module to be ready */
+ if (flags == RS_DATA)
+ bast_lcd_write(bast_lcd_e2_wdata,ch);
+ else
+ bast_lcd_write(bast_lcd_e2_wcmd,ch);
+ break;
+
+ default:
+ /* this is an error as the bast port only supports e1 and e2 */
+ break;
+ }
+
+ sem_signal (semid);
+}
+
+void bast_HD44780_backlight (unsigned char state)
+{
+ if(state)
+ bast_cpu_gpio[5] = (bast_cpu_gpio[5] | 1); /* turn backlight on */
+ else
+ bast_cpu_gpio[5] = (bast_cpu_gpio[5] & (~1)); /* turn backlight off */
+}
+
+
+/* the keypad is on the GPIO registers */
+unsigned char bast_HD44780_readkeypad (unsigned int YData)
+{
+ unsigned char readval;
+
+ sem_wait (semid);
+ /* TODO: add gpio kb reading here */
+ /* GPIOF0-7 are rows GPIOE 5- 10 are colums */
+ sem_signal (semid);
+
+ return 0;
+}
diff -ubrN lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780-bast.h
lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780-bast.h
--- lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780-bast.h
1970-01-01 01:00:00.000000000 +0100
+++ lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780-bast.h
2003-07-02 00:08:04.000000000 +0100
@@ -0,0 +1,10 @@
+#ifndef HD_BAST_H
+#define HD_BAST_H
+
+#include "lcd.h" /* for
lcd_logical_driver */
+#include "hd44780-low.h" /* for HD44780_functions */
+
+// initialise this particular driver
+int hd_init_bast (HD44780_functions * hd44780_functions, lcd_logical_driver
* driver, char *args, unsigned int port);
+
+#endif
diff -ubrN lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780-drivers.h
lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780-drivers.h
--- lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780-drivers.h
2003-01-05 08:05:01.000000000 +0000
+++ lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780-drivers.h
2003-07-02 00:11:05.000000000 +0100
@@ -20,9 +20,10 @@
#include "hd44780-picanlcd.h"
#include "hd44780-usblcd.h"
#include "hd44780-anslcd.h"
+#include "hd44780-bast.h"
// add new connection type header files here

-enum connectionType { HD_4bit, HD_8bit, HD_serialLpt, HD_winamp,
HD_picanlcd,HD_usblcd,HD_anslcd,
+enum connectionType { HD_4bit, HD_8bit, HD_serialLpt, HD_winamp,
HD_picanlcd,HD_usblcd,HD_anslcd,HD_bast,
// add new connection types here
HD_unknown
};
@@ -49,6 +50,7 @@
{ HD_picanlcd, "picanlcd", hd_init_picanlcd, ""},
{ HD_usblcd, "usblcd", hd_init_usblcd, ""},
{ HD_anslcd, "anslcd", hd_init_anslcd, ""},
+ { HD_bast, "bast", hd_init_bast, ""},
// add new connection types and their string specifier here
// default, end of structure element (do not delete)
{ HD_unknown, "", NULL, ""}
diff -ubrN lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780-low.h
lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780-low.h
--- lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780-low.h
2002-12-28 08:05:08.000000000 +0000
+++ lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780-low.h
2003-07-03 16:15:25.000000000 +0100
@@ -39,6 +39,8 @@
// - override scankeypad.
unsigned char (*scankeypad) ();

+ //A subdriver may need to free resources on close
+ void (*close) ();

} HD44780_functions; /* for want of a better
name :-) */

diff -ubrN lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780.c
lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780.c
--- lcdproc-CVS-stable-0-4-4-20030701/server/drivers/hd44780.c 2003-01-05
08:05:01.000000000 +0000
+++ lcdproc-CVS-stable-0-4-4-20030701-bast/server/drivers/hd44780.c
2003-07-03 16:21:34.000000000 +0100
@@ -153,6 +153,7 @@
void HD44780_draw_frame (char *dat);
char HD44780_getkey ();

+void HD44780_close_driver ();
void HD44780_position (int x, int y);
unsigned char HD44780_scankeypad();
static int parse_span_list (int *spanListArray[], int *spLsize, int
*dispOffsets[], int *dOffsize, int *dispSizeArray[], char *spanlist);
@@ -303,6 +304,7 @@

hd44780_functions->scankeypad = HD44780_scankeypad;

+ hd44780_functions->close = HD44780_close_driver;

if (connectionMapping[connectiontype_index].init_fn
(hd44780_functions, driver, args, port) < 0)
return -1;
@@ -357,10 +359,17 @@
//
void HD44780_close()
{
+ hd44780_functions->close();
+
free( HD44780->framebuf );
free( lcd_contents );
}

+void HD44780_close_driver()
+{
+ /* dummy close for sub drivers */
+}
+
/////////////////////////////////////////////////////////////////
// Set position (not part of API)
//

Attachment: pgpjvxnM_9Utn.pgp
Description: PGP signature




Archive powered by MHonArc 2.6.18.

Top of page