TS-8100-4500 LCD
From embeddedTS Manuals
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:
./lcd Technologic Systems
Will write this to the screen:
/* LCD 2x24 character example code
*
* To compile, copy to the board and run:
* gcc lcd.c sbus.c -o lcd */
#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include "sbus.h"
void lcd_init(void);
void lcd_wait(void);
void lcd_command(unsigned int cmd);
void lcd_writechars(unsigned char *dat);
// These are nanosecond delays
#define SETUP 800
#define PULSE 1600
#define HOLD 800
void lcd_init(void) {
uint16_t out;
// Data lines to inputs, control lines to outputs
sbuslock();
winpoke16(0xa, 0x700);
out = winpeek16(0x6);
// Set LCD_EN and LCD_RS low
out &= ~(0x600);
// Set LCD_WR high
out |= 0x100;
winpoke16(0x6, out);
sbusunlock();
usleep(15000);
lcd_command(0x38); // two rows, 5x7, 8 bit
usleep(4100);
lcd_command(0x38); // two rows, 5x7, 8 bit
usleep(100);
lcd_command(0x38); // two rows, 5x7, 8 bit
lcd_command(0x6); // cursor increment mode
lcd_wait();
lcd_command(0x1); // clear display
lcd_wait();
lcd_command(0xc); // display on, blink off, cursor off
lcd_wait();
lcd_command(0x2); // return home
}
void lcd_wait(void) {
uint16_t ddr, out, in;
int i, dat, tries = 0;
struct timespec dly;
dly.tv_sec = 0;
sbuslock();
winpoke16(0xa, winpeek16(0xa) & 0xff00);
out = winpeek16(0x6);
sbusunlock();
do {
// step 1, apply RS & WR
out |= 0x100; // de-assert WR
out &= ~0x200; // de-assert RS
sbuslock();
winpoke16(0x6, out);
sbusunlock();
// step 2, wait
dly.tv_nsec = SETUP;
nanosleep(&dly, NULL);
// step 3, assert EN
out |= 0x400;
sbuslock();
winpoke16(0x6, out);
sbusunlock();
// step 4, wait
dly.tv_nsec = PULSE;
nanosleep(&dly, NULL);
// step 5, de-assert EN, read result
sbuslock();
in = winpeek16(0xe) & 0xff;
out &= ~0x400; // de-assert EN
winpoke16(0x6, out);
sbusunlock();
// step 6, wait
dly.tv_nsec = HOLD;
nanosleep(&dly, NULL);
} while (in & 0x80 && tries++ < 1000);
}
void lcd_command(unsigned int cmd) {
int i;
uint16_t out;
struct timespec dly;
dly.tv_sec = 0;
// Set port A to outputs
sbuslock();
winpoke16(0xa, winpeek16(0xa) | 0x00ff);
out = winpeek16(0x6);
// step 1, apply RS & WR, send data
out &= 0xff00;
out |= (cmd & 0xff);
out &= ~(0x300); // de-assert RS, assert WR
winpoke16(0x6, out);
sbusunlock();
// step 2, wait
dly.tv_nsec = SETUP;
nanosleep(&dly, NULL);
// step 3, assert EN
out |= 0x400;
sbuslock();
winpoke16(0x6, out);
sbusunlock();
// step 4, wait
dly.tv_nsec = PULSE;
nanosleep(&dly, NULL);
// step 5, de-assert EN
out &= ~0x400;
sbuslock();
winpoke16(0x6, out);
sbusunlock();
// step 6, wait
dly.tv_nsec = HOLD;
nanosleep(&dly, NULL);
}
void lcd_writechars(unsigned char *dat) {
int i;
uint16_t out;
struct timespec dly;
dly.tv_sec = 0;
sbuslock();
out = winpeek16(0x6);
sbusunlock();
do {
lcd_wait();
// set data lines to outputs
sbuslock();
winpoke16(0xa, winpeek16(0xa) | 0x00ff);
// step 1, apply RS & WR, send data
out &= 0xff00;
out |= *dat++;
out |= 0x200; // assert RS
out &= ~0x100; // assert WR
winpoke16(0x6, out);
sbusunlock();
// step 2
dly.tv_nsec = SETUP;
nanosleep(&dly, NULL);
// step 3, assert EN
out |= 0x400;
sbuslock();
winpoke16(0x6, out);
sbusunlock();
// step 4, wait 800 nS
dly.tv_nsec = PULSE;
nanosleep(&dly, NULL);
// step 5, de-assert EN
out &= ~0x400;
sbuslock();
winpoke16(0x6, out);
sbusunlock();
// step 6, wait
dly.tv_nsec = HOLD;
nanosleep(&dly, NULL);
} while(*dat);
}
/* 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;
sbuslock();
winpoke16(0x20000, 0x181);
sbusunlock();
lcd_init();
if (argc == 2) {
lcd_writechars(argv[1]);
}
if (argc > 2) {
lcd_writechars(argv[1]);
lcd_wait();
lcd_command(0xa8); // set DDRAM addr to second row
lcd_writechars(argv[2]);
}
if (argc >= 2) return 0;
while(!feof(stdin)) {
unsigned char buf[512];
lcd_wait();
if (i) {
// XXX: this seek addr may be different for different
// LCD sizes! -JO
lcd_command(0xa8); // set DDRAM addr to second row
} else {
lcd_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;
lcd_writechars(buf);
}
}
return 0;
}