diff options
author | reinelt <> | 2003-09-29 06:58:37 +0000 |
---|---|---|
committer | reinelt <> | 2003-09-29 06:58:37 +0000 |
commit | 74bcb3f0eca15fffeb63fbdbc8102c4fc9d686be (patch) | |
tree | 219b2b249576d73ba2eedd6a10804e8faaf3ab60 /MilfordInstruments.c | |
parent | 0023926a82ccc300f2fdbc01c91244cc3180d261 (diff) | |
download | lcd4linux-74bcb3f0eca15fffeb63fbdbc8102c4fc9d686be.tar.gz |
[lcd4linux @ 2003-09-29 06:58:36 by reinelt]
new driver for Milford Instruments MI420 by Andy Baxter
Diffstat (limited to 'MilfordInstruments.c')
-rw-r--r-- | MilfordInstruments.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/MilfordInstruments.c b/MilfordInstruments.c new file mode 100644 index 0000000..564c6c1 --- /dev/null +++ b/MilfordInstruments.c @@ -0,0 +1,332 @@ +/* $Id: MilfordInstruments.c,v 1.1 2003/09/29 06:58:36 reinelt Exp $ + * + * driver for Milford Instruments serial display modules + * + * Written 2003 by Andy Baxter <andy@earthsong.free-online.co.uk> + * + * based on the MatrixOrbital driver by M. Reinelt + * + * 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, 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. + * + * + * $Log: MilfordInstruments.c,v $ + * Revision 1.1 2003/09/29 06:58:36 reinelt + * new driver for Milford Instruments MI420 by Andy Baxter + * + */ + +/* + * + * exported fuctions: + * + * struct LCD MilfordInstruments[] + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <termios.h> +#include <fcntl.h> + +#include "debug.h" +#include "cfg.h" +#include "lock.h" +#include "display.h" +#include "bar.h" +#include "icon.h" + +#define XRES 5 +#define YRES 8 +#define CHARS 8 + +static LCD Lcd; +static char *Port=NULL; +static speed_t Speed; +static int Device=-1; +static int Icons; + +static char *FrameBuffer1=NULL; +static char *FrameBuffer2=NULL; + + +static int MI_open (void) +{ + int fd; + pid_t pid; + struct termios portset; + + if ((pid=lock_port(Port))!=0) { + if (pid==-1) + error ("MilfordInstruments: port %s could not be locked", Port); + else + error ("MilfordInstruments: port %s is locked by process %d", Port, pid); + return -1; + } + fd = open(Port, O_RDWR | O_NOCTTY | O_NDELAY); + if (fd==-1) { + error ("MilfordInstruments: open(%s) failed: %s", Port, strerror(errno)); + unlock_port(Port); + return -1; + } + if (tcgetattr(fd, &portset)==-1) { + error ("MilfordInstruments: tcgetattr(%s) failed: %s", Port, strerror(errno)); + unlock_port(Port); + return -1; + } + cfmakeraw(&portset); + cfsetospeed(&portset, Speed); + if (tcsetattr(fd, TCSANOW, &portset)==-1) { + error ("MilfordInstruments: tcsetattr(%s) failed: %s", Port, strerror(errno)); + unlock_port(Port); + return -1; + } + return fd; +} + + +static void MI_write (char *string, int len) +{ + if (Device==-1) return; + if (write (Device, string, len)==-1) { + if (errno==EAGAIN) { + usleep(1000); + if (write (Device, string, len)>=0) return; + } + error ("MilfordInstruments: write(%s) failed: %s", Port, strerror(errno)); + } +} + + +static void MI_define_char (int ascii, char *buffer) +{ + char cmd[3]="\376x"; + if (ascii<8) { + cmd[2]=(char)(64+ascii*8); + MI_write (cmd, 3); + MI_write (buffer, 8); + } +} + + +static int MI_clear (int full) +{ + memset (FrameBuffer1, ' ', Lcd.rows*Lcd.cols*sizeof(char)); + + icon_clear(); + bar_clear(); + + if (full) { + memset (FrameBuffer2, ' ', Lcd.rows*Lcd.cols*sizeof(char)); + MI_write ("\376\001", 2); // clear screen + } + return 0; +} + + +static int MI_init (LCD *Self) +{ + char *port; + int speed; + + Lcd=*Self; + + // Init the framebuffers + FrameBuffer1 = (char*)malloc(Lcd.cols*Lcd.rows*sizeof(char)); + FrameBuffer2 = (char*)malloc(Lcd.cols*Lcd.rows*sizeof(char)); + if (FrameBuffer1==NULL || FrameBuffer2==NULL) { + error ("MilfordInstruments: framebuffer could not be allocated: malloc() failed"); + return -1; + } + + if (Port) { + free (Port); + Port=NULL; + } + + port=cfg_get ("Port",NULL); + if (port==NULL || *port=='\0') { + error ("MilfordInstruments: no 'Port' entry in %s", cfg_source()); + return -1; + } + Port=strdup(port); + + if (cfg_number("Speed", 19200, 1200,19200, &speed)<0) return -1; + switch (speed) { + case 2400: + Speed=B2400; + break; + case 9600: + Speed=B9600; + break; + default: + error ("MilfordInstruments: unsupported speed '%d' in %s", speed, cfg_source()); + return -1; + } + + debug ("using port %s at %d baud", Port, speed); + + Device=MI_open(); + if (Device==-1) return -1; + + if (cfg_number("Icons", 0, 0, CHARS, &Icons)<0) return -1; + if (Icons>0) { + debug ("reserving %d of %d user-defined characters for icons", Icons, CHARS); + icon_init(Lcd.rows, Lcd.cols, XRES, YRES, CHARS, Icons, MI_define_char); + Self->icons=Icons; + Lcd.icons=Icons; + } + + bar_init(Lcd.rows, Lcd.cols, XRES, YRES, CHARS-Icons); + bar_add_segment( 0, 0,255, 32); // ASCII 32 = blank + bar_add_segment(255,255,255,255); // ASCII 255 = block + + MI_clear(1); + + MI_write ("\376\014", 2); // cursor off + + return 0; +} + + +void MI_goto (int row, int col) +{ + char cmd[2]="\376x"; + char ddbase=0; + switch (row) { + case 0: + ddbase=128; + break; + case 1: + ddbase=192; + break; + case 2: + ddbase=148; + break; + case 3: + ddbase=212; + break; + } + cmd[1]=(char)(ddbase+col); + MI_write(cmd,2); +} + + +int MI_put (int row, int col, char *text) +{ + char *p=FrameBuffer1+row*Lcd.cols+col; + char *t=text; + + while (*t && col++<=Lcd.cols) { + *p++=*t++; + } + return 0; +} + + +int MI_bar (int type, int row, int col, int max, int len1, int len2) +{ + return bar_draw (type, row, col, max, len1, len2); +} + + +int MI_icon (int num, int seq, int row, int col) +{ + return icon_draw (num, seq, row, col); +} + + +static int MI_flush (void) +{ + int row, col, pos1, pos2; + int c, equal; + + bar_process(MI_define_char); + + for (row=0; row<Lcd.rows; row++) { + for (col=0; col<Lcd.cols; col++) { + c=bar_peek(row, col); + if (c==-1) c=icon_peek(row, col); + if (c!=-1) { + FrameBuffer1[row*Lcd.cols+col]=(char)c; + } + } + for (col=0; col<Lcd.cols; col++) { + if (FrameBuffer1[row*Lcd.cols+col]==FrameBuffer2[row*Lcd.cols+col]) continue; + MI_goto (row, col); + for (pos1=col++, pos2=pos1, equal=0; col<Lcd.cols; col++) { + if (FrameBuffer1[row*Lcd.cols+col]==FrameBuffer2[row*Lcd.cols+col]) { + // If we find just one equal byte, we don't break, because this + // would require a goto, which takes one byte, too. + if (++equal>5) break; + } else { + pos2=col; + equal=0; + } + } + MI_write (FrameBuffer1+row*Lcd.cols+pos1, pos2-pos1+1); + } + } + + memcpy (FrameBuffer2, FrameBuffer1, Lcd.rows*Lcd.cols*sizeof(char)); + + return 0; +} + + +int MI_quit (void) +{ + info("MilfordInstruments: shutting down."); + + debug ("closing port %s", Port); + close (Device); + unlock_port(Port); + + if (FrameBuffer1) { + free(FrameBuffer1); + FrameBuffer1=NULL; + } + + if (FrameBuffer2) { + free(FrameBuffer2); + FrameBuffer2=NULL; + } + + return (0); +} + + +LCD MilfordInstruments[] = { + { name: "MI420", + rows: 4, + cols: 20, + xres: XRES, + yres: YRES, + bars: BAR_L | BAR_R | BAR_U | BAR_D | BAR_H2, + icons: 0, + gpos: 0, + init: MI_init, + clear: MI_clear, + put: MI_put, + bar: MI_bar, + icon: MI_icon, + gpo: NULL, + flush: MI_flush, + quit: MI_quit + }, + { NULL } +}; |