HD44780 compatible 16x2 character LCD driver with HC595 shiftregister

Dependents:   mbed_3pinLCD

Files at this revision

API Documentation at this revision

Comitter:
k4zuki
Date:
Fri Jun 20 01:07:06 2014 +0000
Commit message:
porting from arduino library

Changed in this revision

ShiftOut.h Show annotated file Show diff for this revision Revisions of this file
TriPinLcd.cpp Show annotated file Show diff for this revision Revisions of this file
TriPinLcd.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ShiftOut.h	Fri Jun 20 01:07:06 2014 +0000
@@ -0,0 +1,43 @@
+#ifndef SHIFTOUT_H
+#define SHIFTOUT_H
+
+#include <mbed.h>
+
+class ShiftOut
+{
+
+public :
+
+    ShiftOut(PinName data, PinName clk, PinName latch, int8_t registerCount = 8) {
+        dataout = new DigitalOut(data);
+        clkout = new DigitalOut(clk);
+        latchout = new DigitalOut(latch);
+        this->registerCount = registerCount;
+    }
+
+    ~ShiftOut() {
+        delete clkout;
+        delete dataout;
+        delete latchout;
+    }
+
+    void write(int8_t data) {
+        *latchout = 0;
+        for(int i = registerCount - 1; i >=  0; i--) {
+            *clkout = 0;
+            wait_us(0.01);
+            *dataout = (data & (1 << i)) != 0; // 1 or 0
+            *clkout = 1;
+            wait_us(0.01);
+        }
+        *latchout = 1;
+    }
+
+private :
+    DigitalOut *clkout;
+    DigitalOut *dataout;
+    DigitalOut *latchout;
+    int8_t registerCount;
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TriPinLcd.cpp	Fri Jun 20 01:07:06 2014 +0000
@@ -0,0 +1,269 @@
+
+#include "mbed.h"
+#include "TriPinLcd.h"
+
+TriPinLcd::TriPinLcd(PinName data, PinName clock, PinName latch): _lcd(data,clock,latch,8)
+{
+
+    _displayfunction = LCD_3WIERMODE | LCD_1LINE | LCD_5x8DOTS;
+
+    begin(16, 1);
+    setCursor(0,0);
+
+}
+/*
+    TriPinLcd(PinName data, PinName clock, PinName latch);
+
+    void init();
+
+    void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
+    void clear();
+    void home();
+
+    void noDisplay();
+    void display();
+    void noBlink();
+    void blink();
+    void noCursor();
+    void cursor();
+    void scrollDisplayLeft();
+    void scrollDisplayRight();
+    void leftToRight();
+    void rightToLeft();
+    void autoscroll();
+    void noAutoscroll();
+
+    void createChar(uint8_t, uint8_t[]);
+    void setCursor(uint8_t, uint8_t);
+
+    virtual int _putc(int value);
+    virtual int _getc();
+
+*/
+
+void TriPinLcd::begin(uint8_t cols, uint8_t lines, uint8_t dotsize)
+{
+    if (lines > 1) {
+        _displayfunction |= LCD_2LINE;
+    }
+    _numlines = lines;
+    _currline = 0;
+
+    // for some 1 line displays you can select a 10 pixel high font
+    if ((dotsize != 0) && (lines == 1)) {
+        _displayfunction |= LCD_5x10DOTS;
+    }
+
+    // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
+    // according to datasheet, we need at least 40ms after power rises above 2.7V
+    // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
+    wait_us(40000);
+
+    //put the LCD into 4 bit or 8 bit mode
+    if (! (_displayfunction & LCD_8BITMODE)) {
+        // this is according to the hitachi HD44780 datasheet
+        // figure 24, pg 46
+
+        // we start in 8bit mode, try to set 4 bit mode
+        _write4bits(0x03);
+        wait_us(4500); // wait min 4.1ms
+
+        // second try
+        _write4bits(0x03);
+        wait_us(4500); // wait min 4.1ms
+
+        // third go!
+        _write4bits(0x03);
+        wait_us(150);
+
+        // finally, set to 4-bit interface
+        _write4bits(0x02);
+    }
+    _command(LCD_FUNCTIONSET | _displayfunction);
+
+    // turn the display on with no cursor or blinking default
+    _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
+    display();
+
+    // clear it off
+    clear();
+
+    // Initialize to default text direction (for romance languages)
+    _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
+    // set the entry mode
+    _command(LCD_ENTRYMODESET | _displaymode);
+    wait_us(150);
+}
+
+// ********** high level commands, for the user!
+void TriPinLcd::clear()
+{
+    _command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero
+    wait_ms(30);  // this command takes a long time!
+}
+
+void TriPinLcd::home()
+{
+    _command(LCD_RETURNHOME);  // set cursor position to zero
+    wait_ms(30);  // this command takes a long time!
+}
+
+void TriPinLcd::setCursor(uint8_t col, uint8_t row)
+{
+    int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+    if ( row >= _numlines ) {
+        row = _numlines-1;    // we count rows starting w/0
+    }
+
+    _command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
+}
+
+// Turn the display on/off (quickly)
+void TriPinLcd::noDisplay()
+{
+    _displaycontrol &= ~LCD_DISPLAYON;
+    _command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+void TriPinLcd::display()
+{
+    _displaycontrol |= LCD_DISPLAYON;
+    _command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// Turns the underline cursor on/off
+void TriPinLcd::noCursor()
+{
+    _displaycontrol &= ~LCD_CURSORON;
+    _command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+void TriPinLcd::cursor()
+{
+    _displaycontrol |= LCD_CURSORON;
+    _command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// Turn on and off the blinking cursor
+void TriPinLcd::noBlink()
+{
+    _displaycontrol &= ~LCD_BLINKON;
+    _command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+void TriPinLcd::blink()
+{
+    _displaycontrol |= LCD_BLINKON;
+    _command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// These commands scroll the display without changing the RAM
+void TriPinLcd::scrollDisplayLeft(void)
+{
+    _command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
+}
+void TriPinLcd::scrollDisplayRight(void)
+{
+    _command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
+}
+
+// This is for text that flows Left to Right
+void TriPinLcd::leftToRight(void)
+{
+    _displaymode |= LCD_ENTRYLEFT;
+    _command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This is for text that flows Right to Left
+void TriPinLcd::rightToLeft(void)
+{
+    _displaymode &= ~LCD_ENTRYLEFT;
+    _command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This will 'right justify' text from the cursor
+void TriPinLcd::autoscroll(void)
+{
+    _displaymode |= LCD_ENTRYSHIFTINCREMENT;
+    _command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This will 'left justify' text from the cursor
+void TriPinLcd::noAutoscroll(void)
+{
+    _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
+    _command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// Allows us to fill the first 8 CGRAM locations
+// with custom characters
+void TriPinLcd::createChar(uint8_t location, uint8_t charmap[])
+{
+    location &= 0x07; // we only have 8 locations 0-7
+    _command(LCD_SETCGRAMADDR | (location << 3));
+    for (int i=0; i<8; i++) {
+        _write(charmap[i]);
+    }
+}
+
+// *********** mid level commands, for sending data/cmds
+
+inline void TriPinLcd::_command(uint8_t value)
+{
+    _send(value, CMND_BYTE);
+}
+
+inline void TriPinLcd::_write(uint8_t value)
+{
+    _send(value, DATA_BYTE);
+}
+
+int TriPinLcd::_putc(int value)
+{
+    _send(value, DATA_BYTE);
+    wait_us(1000);
+    return value;
+}
+
+int TriPinLcd::_getc()
+{
+    return -1;
+}
+
+
+void TriPinLcd::_send(uint8_t value, uint8_t mode)
+{
+
+    int data = value & 0xf0; //send the 4 MSbits (from 8)
+
+    data |= (mode << SHIFT_RS); // set DI mode
+    data &= ~SHIFT_EN; // set Enable LOW
+    _lcd.write(data);
+    data |= SHIFT_EN; // Set Enable HIGH
+    _lcd.write(data);
+    data &= ~SHIFT_EN; // set Enable LOW
+    _lcd.write(data);
+
+    data = value << 4; // send the 4 LSbits (from 8)
+
+    data |= (mode << SHIFT_RS); // set DI mode
+    data &= ~SHIFT_EN; // set Enable LOW
+    _lcd.write(data);
+    data |= SHIFT_EN; // Set Enable HIGH
+    _lcd.write(data);
+    data &= ~SHIFT_EN; // set Enable LOW
+    _lcd.write(data);
+
+}
+
+void TriPinLcd::_write4bits(uint8_t value)
+{
+    int data=0; //= value & 0x0f;
+
+    data = value << 4; //send the first 4 databits (from 8)
+
+    data &= ~SHIFT_EN; // set Enable LOW
+    _lcd.write(data);
+    data |= SHIFT_EN; // Set Enable HIGH
+    _lcd.write(data);
+    data &= ~SHIFT_EN; // set Enable LOW
+    _lcd.write(data);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TriPinLcd.h	Fri Jun 20 01:07:06 2014 +0000
@@ -0,0 +1,190 @@
+/** this is for HD44780 compatible 16x2 charachter LCD with HC595 by bitbanging
+* by Kazuki Yamamoto, or _K4ZUKI_
+*/
+
+#ifndef __TRIPINLCD_H__
+#define __TRIPINLCD_H__
+
+#include <inttypes.h>
+#include "mbed.h"
+#include "ShiftOut.h"
+
+// commands
+#define LCD_CLEARDISPLAY 0x01
+#define LCD_RETURNHOME 0x02
+#define LCD_ENTRYMODESET 0x04
+#define LCD_DISPLAYCONTROL 0x08
+#define LCD_CURSORSHIFT 0x10
+#define LCD_FUNCTIONSET 0x20
+#define LCD_SETCGRAMADDR 0x40
+#define LCD_SETDDRAMADDR 0x80
+
+// flags for display entry mode
+#define LCD_ENTRYRIGHT 0x00
+#define LCD_ENTRYLEFT 0x02
+#define LCD_ENTRYSHIFTINCREMENT 0x01
+#define LCD_ENTRYSHIFTDECREMENT 0x00
+
+// flags for display on/off control
+#define LCD_DISPLAYON 0x04
+#define LCD_DISPLAYOFF 0x00
+#define LCD_CURSORON 0x02
+#define LCD_CURSOROFF 0x00
+#define LCD_BLINKON 0x01
+#define LCD_BLINKOFF 0x00
+
+// flags for display/cursor shift
+#define LCD_DISPLAYMOVE 0x08
+#define LCD_CURSORMOVE 0x00
+#define LCD_MOVERIGHT 0x04
+#define LCD_MOVELEFT 0x00
+
+// flags for function set
+#define LCD_3WIERMODE 0x20
+#define LCD_8BITMODE 0x10
+#define LCD_4BITMODE 0x00
+#define LCD_2LINE 0x08
+#define LCD_1LINE 0x00
+#define LCD_5x10DOTS 0x04
+#define LCD_5x8DOTS 0x00
+
+//#define SHIFT_RS (0x02) //B00000010
+#define SHIFT_RS (0x01) //B00000010
+#define SHIFT_EN (0x08) //B00001000
+
+#define DATA_BYTE (1)
+#define CMND_BYTE (0)
+
+/** tripinLcd
+ * mbed library for HD44780 compatible charachter LCD with HC595 by bitbanging
+ *
+ * Example:
+ * @code
+#include "mbed.h"
+#include "TriPinLcd.h"
+
+Timer t;
+TriPinLcd lcd(p5,p7,p6);//clk = p7, data = p5, latch = p6
+
+int main()
+{
+
+    lcd.begin(16, 2);
+    lcd.noBlink();
+
+    lcd.printf("LCD3WIRE mbed");
+    t.start();
+    while(1) {
+        lcd.setCursor(0, 1);
+//        lcd.printf("%.0f", t.read());
+        lcd.printf("%d", t.read_us());
+    }
+}
+
+ * @endcode
+ */
+
+class TriPinLcd : public Stream
+{
+
+public:
+    /** Constructor
+    * @param data data input
+    * @param clock clock input
+    * @param latch latches HC595 and sends data to LCD
+    */
+    TriPinLcd(PinName data, PinName clock, PinName latch);
+
+    void begin(uint8_t cols, uint8_t rows, uint8_t dotsize = LCD_5x8DOTS);
+    
+    /**
+    clears display, set cursor position to zero
+    */
+    void clear();
+    
+    /**
+    set cursor position to zero
+    */
+    void home();
+    /**
+     Turn the display off
+    */
+    void noDisplay();
+    /**
+     Turn the display on
+    */
+    void display();
+    /**
+    Turns off the blinking cursor
+    */
+    void noBlink();
+    /**
+    Turns on the blinking cursor
+    */
+    void blink();
+    /**
+    Turns the underline cursor off
+    */
+    void noCursor();
+    /**
+    Turns the underline cursor on
+    */
+    void cursor();
+    /**
+    scroll the display to left without changing the RAM
+    */
+    void scrollDisplayLeft();
+    /**
+    scroll the display to right without changing the RAM
+    */
+    void scrollDisplayRight();
+    /**
+    This is for text that flows Left to Right
+    */
+    void leftToRight();
+    /**
+    This is for text that flows Right to Left
+    */
+    void rightToLeft();
+    /**
+    This will 'right justify' text from the cursor
+    */
+    void autoscroll();
+    /**
+    This will 'left justify' text from the cursor
+    */
+    void noAutoscroll();
+
+    /**
+    Allows us to fill the first 8 CGRAM locations
+    with custom characters
+    */
+    void createChar(uint8_t, uint8_t[]);
+    /**
+    set cursor position to (x=col,y=row); (0,0) is left-top
+    @param col X position
+    @param row Y position
+    */
+    void setCursor(uint8_t, uint8_t);
+
+
+private:
+    ShiftOut::ShiftOut _lcd;
+    void _write(uint8_t);
+    void _command(uint8_t);
+
+    virtual int _putc(int value);
+    virtual int _getc();
+
+    void _send(uint8_t, uint8_t);
+    void _write4bits(uint8_t);
+
+    uint8_t _displayfunction;
+    uint8_t _displaycontrol;
+    uint8_t _displaymode;
+
+    uint8_t _numlines,_currline;
+
+};
+
+#endif
\ No newline at end of file