Test of LCD code

Dependencies:   mbed

lcd_i2c.cpp

Committer:
garyr
Date:
2014-05-30
Revision:
0:a4d44dfd2f03

File content as of revision 0:a4d44dfd2f03:

#include "mbed.h"
#include "lcd_i2c.h"
/*
    LCD (Optrex DCM16230, DCM20261, etc.)  via I2C using a PCF8574

                                  Frequency (clks/sec)                    Frequency
    Transfer rate = ------------------------------------------------ = ---------------- (characters/sec)
                9 clks/write * 3 writes/nibble * 2 nibbles/character      54
*/
I2C i2c(p9, p10);           // (sda, scl)
Serial pc2(USBTX, USBRX);    // tx, rx

// PCF8574 output bits     Px
#define     RS      BIT1
#define     RW      BIT2
#define     E       BIT3
#define     DB4     BIT4
#define     DB5     BIT5
#define     DB6     BIT6
#define     DB7     BIT7

char update[NUPDATE];
char cw, address;

int updateDisplay(char *str, int nchars)
{
char w, ch, *p;
int n, k, rc;

    if (nchars > 20)
        return 1;
    n = 0;
    p = update;
    for (k = 0; k < nchars; k++)
    {
        // write most significant nibble
        ch = *str++;
        w = (ch & 0xf0) | cw;
        *p++ = w;
        *p++ = w | E;
        *p++ = w;

        // write least significant nibble
        w = (ch << 4) | cw;
        *p++ = w;
        *p++ = w | E;
        *p++ = w;
        n += 6;
    }
    rc = i2c.write(address, update, n);  // rc == 0 ==> ACK
    return rc;
}

int write4Bits(char data)
{
char w;
int rc;

    w = (data & 0xf0) | cw;     // grab the left nibble
    update[0] = w;
    update[1] = w | E;
    update[2] = w & ~ E;
    rc = i2c.write(address, update, 3);
    return rc;
}

int initLcd(int i2cAddress, int frequency)
{
typedef struct {
    char    cmd;
    char    numNibbles;
    char    delayMs;
    //char  testBF;
} INIT;
static const INIT initData[] = {
    {3, 1, 5},
    {3, 1, 1},
    {3, 1, 1},
    {2, 1, 1},      // Function set: 4-bit interface
    {0x28, 2, 2},   // Function set: 2 lines, 5x7
    {0x08, 2, 2},   // Display off
    {0x01, 2, 16},  // Clear display
    {0x06, 2, 2},   // Entry mode set: No increment, shift cursor
    {0x0e, 2, 2}};  // Display on: cursor on, blink off
#define NINITD (sizeof(initData)/sizeof(initData[0]))
INIT *p;
int k, rc;
    // Initialization must start at least 16 ms after power up.
    i2c.frequency(frequency);
    address = i2cAddress;
    cw = 0;
    p = (INIT *)initData;
    for (k = 0; k < NINITD; k++)
    {
        //p = (INIT *)&initData[k];
        if (p->numNibbles == 1)
            rc = write4Bits(p->cmd << 4);
        else
        {
            rc = write4Bits(p->cmd);        // output the most significant nibble
            wait_us(10);                    // this will need to be adjusted when printf stmts are removed
            rc |= write4Bits(p->cmd << 4);  // output the least significant nibble
        }
        if (rc)
            break;
        wait_ms(p->delayMs);
        p++;
    }
    return rc;
}

int lcdWriteMsg(char *msg)
{   // msg must be a null-terminated string
char rc;
    cw |= RS;       // data
    cw &= ~RW;      // write
    rc = updateDisplay(msg, strlen(msg));
    return rc;
}

int lcdWriteCmd(char cmd, int delayMs)
{
int rc;
    cw &= ~RS;      // command
    rc = write4Bits(cmd);
    wait_us(10);
    rc |= write4Bits(cmd << 4);
    if (delayMs)
        wait_ms(delayMs);
    return rc;
}

int lcdPositionCursor(char row, char col)
{
// Code may not be correct for displays larger than 20 x 2
int x, rc;
    x = 0x80 | ((row & 1)<<6) | (col & 0xf);
    rc = lcdWriteCmd(x, 1);
    return rc;
}

int lcdClearDisplay(void)
{
    return lcdWriteCmd(1, 16);
}