TS-8100-4500 LCD

From embeddedTS Manuals
Revision as of 13:07, 17 June 2013 by Mark (talk | contribs)
(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:

./lcd 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 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;
}