Displaytronic (Xiamen Zettler)'s I2C text LCD driver

Dependents:   IsuProject_LPC1768 robottt

ACM1602.cpp

Committer:
kayekss
Date:
2014-03-19
Revision:
0:f81621685b23

File content as of revision 0:f81621685b23:

// ==================================================== Mar 19 2014, kayeks ==
// ACM1602.cpp
// ===========================================================================
// Displaytronic (Xiamen Zettler)'s I2C text LCD driver

#include <stdlib.h>
#include "mbed.h"
#include "ACM1602.h"

/** Constructor of class ACM1602. */
ACM1602::ACM1602(PinName sda, PinName scl, uint8_t address)
:
    i2c(sda, scl)
{
    i2c.frequency(100000);
    this->address = address & 0xfe;
}

/** Initialize LCD. */
void ACM1602::init() {
    cls();
    command(0x38);  // 8-bit mode, double-line
    command(0x0c);  // Display on, cursor off
    command(0x06);  // Enable DDRAM address increment
}

/** Clear display and reset DDRAM address. */
void ACM1602::cls() {
    command(0x01);
    wait(0.01);
    memset(lineBuffer[0], ' ', 16);
    memset(lineBuffer[1], ' ', 16);
    this->col = 0;
    this->row = 0;
}

/** Locate the cursor position. */
void ACM1602::locate(int col, int row) {
    if (col < 0 || col > 15 || row < 0 || row > 1) {
        return;
    }
    command(0x80 | (row << 6) | col);
    this->col = col;
    this->row = row;
}

/** Implementation of putc from Stream class. */
int ACM1602::_putc(int c) {
    switch (c) {
    case '\r':
        this->col = 0;
        locate(this->col, this->row);
        break;
    case '\n':
        if (this->row == 1) {
            shiftUp();
        } else {
            locate(this->col, ++this->row);
        }
        break;
    default:
        if (this->col > 15) {
            shiftUp();
            this->col = 0;
            this->row = 1;
            locate(this->col, this->row);
        }
        data(c);
        lineBuffer[this->row][this->col] = c;
        this->col++;
        break;
    }
    return 0;
}

/** Implementation of getc from Stream class. */
int ACM1602::_getc() {
    return EOF;
}

/** Shift up the lower line for scroll. */
void ACM1602::shiftUp() {
    memcpy(lineBuffer[0], lineBuffer[1], 16);
    memset(lineBuffer[1], ' ', 16);
    
    locate(0, 0);
    for (uint8_t i = 0; i < 16; i++) {
        data(lineBuffer[0][i]);
    }
    locate(0, 1);
    for (uint8_t i = 0; i < 16; i++) {
        data(' ');
    }
    locate(0, 1);
}

/** Send a command byte to LCD. */
void ACM1602::command(uint8_t b) {
    wait_us(25); i2c.start();
    wait_us(25); i2c.write(this->address);
    wait_us(25); i2c.write(0x00);
    wait_us(25); i2c.write(b);
    wait_us(25); i2c.stop();
    wait_us(40);
}

/** Send a data byte to LCD. */
void ACM1602::data(uint8_t b) {
    wait_us(25); i2c.start();
    wait_us(25); i2c.write(this->address);
    wait_us(25); i2c.write(0x80);
    wait_us(25); i2c.write(b);
    wait_us(25); i2c.stop();
    wait_us(40);
}