TS-8100-4200 LCD

From embeddedTS Manuals
Revision as of 10:02, 14 June 2013 by Mark (talk | contribs) (Created page with "This example project allows you to pipe in data separated by newlines, or you can call the application with arguments to draw the two lines. For example: <source lang=bash> ....")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This example project allows you to pipe in data separated by newlines, or you can call the application with arguments to draw the two lines. For example:

./lcdmesg Technologic Systems

Will write this to the screen:

LCD LED example.jpg
/* LCD 2x24 character example code
 *
 * To compile, copy to the board and run:
 * 	gcc lcdmesg.c -o lcdmesg  */

#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>

#define FPGABASE 0x30000000
#define SYSCON (0x0a /sizeof(unsigned short))
#define ODR (0x406 /sizeof(unsigned short))
#define DDR (0x40A /sizeof(unsigned short))
#define IDR (0x40E /sizeof(unsigned short))

#define MUXBUS 0x20

#define LCD_WR 0x100
#define LCD_RS 0x200
#define LCD_EN 0x400

#define LCD_PWR 0x1000

// These delay values are calibrated for the TS-4200
#define SETUP	200
#define PULSE	400
#define HOLD	200

#define COUNTDOWN(x)	asm volatile ( \
  "1:\n"\
  "subs %1, %1, #1;\n"\
  "bne 1b;\n"\
  : "=r" ((x)) : "r" ((x)) \
);

volatile unsigned short *syscon, *odr, *ddr, *idr;

void command(unsigned int);
void writechars(unsigned char *);
unsigned int lcdwait(void);
void lcdinit(void);

/* This program takes lines from stdin and prints them to the
 * 2 line LCD connected to the TS-8100/TS-8160 LCD header.  e.g
 *
 *    echo "hello world" | lcdmesg
 * 
 * It may need to be tweaked for different size displays
 */

int main(int argc, char **argv) {
	int i = 0;

	lcdinit();
	if (argc == 2) {
		writechars(argv[1]);
	}
	if (argc > 2) {
		writechars(argv[1]);
		lcdwait();
		command(0xa8); // set DDRAM addr to second row
		writechars(argv[2]);
	}
	if (argc >= 2) return 0;

	while(!feof(stdin)) {
		unsigned char buf[512];

		lcdwait();
		if (i) {
			// XXX: this seek addr may be different for different
			// LCD sizes!  -JO
			command(0xa8); // set DDRAM addr to second row
		} else {
			command(0x2); // return home
		}
		i = i ^ 0x1;
		if (fgets(buf, sizeof(buf), stdin) != NULL) {
			unsigned int len;
			buf[0x27] = 0;
			len = strlen(buf);
			if (buf[len - 1] == '\n') buf[len - 1] = 0;
			writechars(buf);
		}
	}
	return 0;
}

void lcdinit(void) {
	int fd = open("/dev/mem", O_RDWR|O_SYNC);

	syscon = (unsigned short *)mmap(0, getpagesize(), 
	  PROT_READ|PROT_WRITE, MAP_SHARED, fd, FPGABASE);

	
	odr = &syscon[ODR];
	ddr = &syscon[DDR];
	idr = &syscon[IDR];
	syscon = &syscon[SYSCON];

	*syscon = *syscon | 0x1000;
	
	*ddr = *ddr & 0xFF00; // data lines to inputs
	*ddr = *ddr | LCD_WR | LCD_RS | LCD_EN; // control lines to outputs
	*odr &= ~(LCD_EN | LCD_RS);
	*odr |= LCD_WR;

	usleep(15000);
	command(0x38); // two rows, 5x7, 8 bit
	usleep(4100);
	command(0x38); // two rows, 5x7, 8 bit
	usleep(100);
	command(0x38); // two rows, 5x7, 8 bit
	command(0x6); // cursor increment mode
	lcdwait();
	command(0x1); // clear display
	lcdwait();
	command(0xc); // display on, blink off, cursor off
	lcdwait();
	command(0x2); // return home
}

unsigned int lcdwait(void) {
	int i, dat, tries = 0;
	unsigned short ctrl;

	*ddr &= 0xff00; // data lines to inputs
	ctrl = *odr;
	
	do {
		// step 1, apply RS & WR
		ctrl |= LCD_WR; // de-assert WR
		ctrl &= ~LCD_RS; // de-assert RS
		*odr = ctrl;

		// step 2, wait
		i = SETUP;
		COUNTDOWN(i);

		// step 3, assert EN
		ctrl |= LCD_EN;
		*odr = ctrl;

		// step 4, wait
		i = PULSE;
		COUNTDOWN(i);

		// step 5, de-assert EN, read result
		dat = *idr & 0xff;
		ctrl &= ~LCD_EN; // de-assert EN
		*odr = ctrl;

		// step 6, wait
		i = HOLD;
		COUNTDOWN(i);
	} while (dat & 0x80 && tries++ < 1000);
	return dat;
}

void command(unsigned int cmd) {
	int i;
	unsigned short ctrl;

	*ddr = *ddr | 0x00ff; // set port A to outputs
	ctrl = *odr;
	
	// step 1, apply RS & WR, send data

	ctrl = ctrl & 0xFF00;
	ctrl = ctrl | (cmd & 0xFF);
	ctrl &= ~(LCD_RS | LCD_WR); // de-assert RS, assert WR
	*odr = ctrl;


	// step 2, wait
	i = SETUP;
	COUNTDOWN(i);

	// step 3, assert EN
	ctrl = ctrl | LCD_EN;
	*odr = ctrl;

	// step 4, wait
	i = PULSE;
	COUNTDOWN(i);

	// step 5, de-assert EN	
	ctrl = ctrl & ~LCD_EN; // de-assert EN
	*odr = ctrl;

	// step 6, wait 
	i = HOLD;
	COUNTDOWN(i);
}

void writechars(unsigned char *dat) {
	int i;
	unsigned short ctrl = *odr;

	do {
		lcdwait();

		*ddr = *ddr | 0x00FF; // set data lines to outputs

		// step 1, apply RS & WR, send data

		ctrl = ctrl & 0xFF00;
		ctrl = ctrl | *dat++;
		ctrl = ctrl | LCD_RS; // assert RS
		ctrl = ctrl & ~LCD_WR; // assert WR
		*odr = ctrl;

		// step 2
		i = SETUP;
		COUNTDOWN(i);

		// step 3, assert EN
		ctrl = ctrl | LCD_EN;
		*odr = ctrl;

		// step 4, wait 800 nS
		i = PULSE;
		COUNTDOWN(i);

		// step 5, de-assert EN	
		ctrl = ctrl & ~LCD_EN; // de-assert EN
		*odr = ctrl;

		// step 6, wait
		i = HOLD;
		COUNTDOWN(i);
	} while(*dat);
}