Strawberry Linux LCD module interface

Dependents:   LCDExample

LCD.cpp

Committer:
yamaguch
Date:
2011-12-22
Revision:
0:b3def1d4f466

File content as of revision 0:b3def1d4f466:

#include "LCD.h"
#include "mbed.h"

#define I2C_ADDR 0x7C

#define COLUMNS 16
#define ROWS 2

#define COMMAND 0x00
#define DATA 0x40

// Clear Display
#define CLEAR_DISPLAY 0x01

// Return Home
#define RETURN_HOME 0x02

// Display ON/OFF
#define DISPLAY_ON_OFF_CONTROL 0x08
#define DISPLAY_ON 1 << 2
#define CURSOR_ON 1 << 1
#define CURSOR_POSITION_ON 1 << 0

// Function set
#define FUNCTION_SET 0x20
#define DL 1 << 4 // 8 bit interface
#define N 1 << 3 // 2 lines
#define DH 1 << 2 // double height
#define IS 1 << 0 // instruction table select

// Instruction Table 0 (IS = 0)
#define CURSOR_OR_DISPLAY_SHIFT = 0x10;
#define SC 1 << 3 // select screen (DISPLAY)
#define RL 1 << 2 // moving to the right

// Instruction Table 1 (when IS = 1)
#define INTERNAL_OSC_FREQUENCY 0x10
#define BS 1 << 3 // 1/4 bias
#define FR_MASK 7 // adjust internal OSC freq
#define SET_ICON_ADDRESS 0x40
#define AC_MASK 7 // set ICON addr in address counter
#define POWER_ICON_CONTRAST_CONTROL 0x50
#define ION 1 << 3 // Icon On
#define BON 1 << 2 // Booster On
#define CONTRAST_MASK1 3 // contrast (higher bits)
#define FOLLOWER_CONTROL 0x60
#define FON 1 << 3 // Follower On
#define RAB_MASK 7 // Rab
#define CONTRAST_SET 0x70
#define CONTRAST_MASK0 15 // contrast (lower bits)

// Set DDRAM Address
#define SET_DDRAM_ADDRESS 0x80

Serial pc(USBTX, USBRX);
LCD::LCD(PinName sdaPin, PinName sclPin, PinName resetPin, PinName backlightPin, int contrast, bool cursor, bool blink)
        : _reset(resetPin), backlight(backlightPin), i2c(sdaPin, sclPin), contrast(contrast), cursor(cursor), blink(blink) {
    resetEnabled = resetPin != NC;
    backlightEnabled = backlightPin != NC;
    reset();
}

void LCD::reset() {
    wait(0.015);
    if (resetEnabled)
        _reset = 0;
    wait(0.01);
    if (resetEnabled)
        _reset = 1;
    wait(0.05);

    writeCommand(FUNCTION_SET | DL | N | (IS & 0));
    writeCommand(FUNCTION_SET | DL | N | (IS & 1));
    writeCommand(INTERNAL_OSC_FREQUENCY | BS | (FR_MASK & 0));
    writeCommand(CONTRAST_SET | (CONTRAST_MASK0 & contrast));
    writeCommand(POWER_ICON_CONTRAST_CONTROL | ION | BON | (CONTRAST_MASK1 & contrast >> 4));
    //writeCommand(FOLLOWER_CONTROL | FON | (RAB_MASK & 2));
    writeCommand(FOLLOWER_CONTROL | FON | (RAB_MASK & 4));
    wait(0.3);

    writeCommand(DISPLAY_ON_OFF_CONTROL | DISPLAY_ON | (cursor ? CURSOR_ON : 0) | (blink ? CURSOR_POSITION_ON : 0));
    wait(0.002);
    cls();
}

void LCD::display(int column, int row, int c) {
    writeCommand(column + 0x40 * row + 0x80);
    writeData(c);
    if (row == 1) row2[column] = c;
}

void LCD::cls() {
    for (int i = 0; i < 16; i++) {
        writeCommand(FUNCTION_SET | DL | N | (IS & 1));
        writeCommand(SET_ICON_ADDRESS | i);
        //writeCommand(0x39);
        //writeCommand(0x40 + i);
        writeData(0);
    }

    writeCommand(CLEAR_DISPLAY);
    wait(0.00164f);
    locate(0, 0);
}

void LCD::locate(int column, int row) {
    this->column = column;
    this->row = row;
}

int LCD::_putc(int value) {
    if (row >= ROWS) {
        scrollDown();
        row = 1;
    }
    if (value == '\n')
        column = COLUMNS;
    else
        display(column, row, value);

    if (++column >= COLUMNS) {
        column = 0;
        row++;
    }

    return value;
}

int LCD::_getc() {
    return -1;
}

void LCD::scrollDown() {
    writeCommand(SET_DDRAM_ADDRESS | 0x00);
    writeData(row2, sizeof(row2));
    memset(row2, ' ', sizeof(row2));
    writeCommand(SET_DDRAM_ADDRESS | 0x40);
    writeData(row2, sizeof(row2));
}

void LCD::writeCommand(int command) {
    char buf[] = {COMMAND, command};
    i2c.write(I2C_ADDR, buf, sizeof(buf));
}

void LCD::writeData(int data) {
    char buf[] = {DATA, data};
    i2c.write(I2C_ADDR, buf, sizeof(buf));
}

void LCD::writeData(char data[], int length) {
    char buf[length + 1];
    buf[0] = DATA;
    memcpy(&buf[1], data, length);
    i2c.write(I2C_ADDR, buf, sizeof(buf));
}

void LCD::showIcon(Icon icon) {
    switch (icon) {
        case ALL:
            for (int i = 0; i < 16; i++) {
                writeCommand(FUNCTION_SET | DL | N | (IS & 1));
                writeCommand(SET_ICON_ADDRESS | i);
                writeData(0x1F);
            }
            break;
        default:
            writeCommand(FUNCTION_SET | DL | N | (IS & 1));
            writeCommand(SET_ICON_ADDRESS | (icon >> 8));
            writeData(icon & 0xFF);
    }
}

void LCD::hideIcon(Icon icon) {
    switch (icon) {
        case ALL:
            for (int i = 0; i < 16; i++) {
                writeCommand(FUNCTION_SET | DL | N | (IS & 1));
                writeCommand(SET_ICON_ADDRESS | i);
                writeData(0);
            }
            break;
        default:
            writeCommand(FUNCTION_SET | DL | N | (IS & 1));
            writeCommand(SET_ICON_ADDRESS | (icon >> 8));
            writeData(0);
    }
}

void LCD::setBacklight(bool on) {
    if (backlightEnabled)
        backlight = on;
}