A basic basic basic driver for 2x16 HD44780 based displays using the four wire interface.

Dependents:   lcdLibraryTest generado_final

Files at this revision

API Documentation at this revision

Comitter:
mattegan
Date:
Fri Nov 08 07:03:35 2013 +0000
Commit message:
[ADMIN] initial commit - everything should be working

Changed in this revision

lcd.cpp Show annotated file Show diff for this revision Revisions of this file
lcd.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lcd.cpp	Fri Nov 08 07:03:35 2013 +0000
@@ -0,0 +1,215 @@
+#include "lcd.h"
+
+//Public Methods
+//////////////////////////////////////////////////////////////////////////////////////////
+
+lcd::lcd(PinName _rs, PinName _rw, PinName _e, PinName _db4, PinName _db5, PinName _db6, PinName _db7):
+    registerSelect(_rs), readWrite(_rw), enable(_e), dataBus(_db4, _db5, _db6, _db7) {
+   
+    currentMode = klcdReadMode;
+    setMode(klcdWriteMode);
+     
+    //wait for more than 15ms after Vcc rises to 4.5v
+    wait_ms(20);
+    
+    //function set (interface is 8 bits long)
+    writeNibble(klcdInstructionRegister, 0x3);
+    
+    //wait for more than 4.1ms
+    wait_ms(4.5);
+    
+    //function set(interface is 8 bits long)
+    writeNibble(klcdInstructionRegister, 0x3);
+    
+    //wait for more than 100us
+    wait_us(150);
+    
+    //function set (interface is 8 bits long)
+    writeNibble(klcdInstructionRegister, 0x3);
+    wait_us(90);
+    
+    //function set (interface is 4 bits long)
+    writeNibble(klcdInstructionRegister, 0x2);
+    wait_us(90);
+        
+    //function set (interface is 4 bits long) set display lines and character font
+    //      2 lines, 5x8 character font (1 0 0 0)
+    writeByte(klcdInstructionRegister, 0x28, false);
+    wait_us(90);
+      
+    //display off
+    writeByte(klcdInstructionRegister, 0x08, false);
+    wait_us(90);
+        
+    //display clear
+    writeByte(klcdInstructionRegister, 0x01, false);
+    wait_ms(2.0);
+       
+    //entry mode set
+    writeByte(klcdInstructionRegister, 0x0C, false);   
+    wait_us(90);
+   
+    //clear display, and turn on
+    writeByte(klcdInstructionRegister, 0x01);
+    writeByte(klcdInstructionRegister, 0x0C);
+    
+    //turn shifting off
+    writeByte(klcdInstructionRegister, 0x04);
+    
+    row = 0;
+    column = 0;
+    
+}
+
+void lcd::clear() {
+    //clear screen -> 0 0 (0 0 0 0 0 0 0 1)
+    writeByte(klcdInstructionRegister, 0x01);
+    locate(0, 0);
+}
+
+void lcd::locate(int _row, int _column) {
+    row = _row;
+    column = _column;
+}
+
+void lcd::locateCharacter(int _row, int _column, int _char) {
+    //set DDRAM address -> 0 0 (1 a a a a a a a)
+    //write DDRAM -> 1 0 (d d d d d d d d);
+    writeByte(klcdInstructionRegister, 0x80 + (_row * 0x40) + _column);
+    writeByte(klcdDataRegister, _char);
+}
+
+void lcd::defineCharacter(int _char, int _charData[8]) {
+    if(_char < 0 || _char > 7) return;
+    //write CGRAM address 0 0 (0 1 a a a a a a)
+    //  first three bits are character (0-7)
+    //  second three bits are the row in the character
+    writeByte(klcdInstructionRegister, 0x40 + (_char << 3));
+    for(int row = 0; row < 8; row++) {
+        //write CGRAM data 1 0 (d d d d d d d d)
+        writeByte(klcdDataRegister, _charData[row]);
+    }
+}
+
+//Protected Methods
+//////////////////////////////////////////////////////////////////////////////////////////
+void lcd::setMode(int _mode) {
+    //since changing the databus mode takes time only do it
+    //  if we're not in the mode already, this might be
+    //  fuzzy science (read, not actually accurate), but it
+    //  can't hurt
+    if(_mode != currentMode) {
+        readWrite = _mode;
+        currentMode = _mode;
+        switch(_mode) {
+            case klcdWriteMode: {
+                dataBus.output();
+                break;
+            }
+            case klcdReadMode: {
+                dataBus.input();
+                break;
+            }
+        }
+    }
+}
+
+void lcd::waitUntilNotBusy() {
+    setMode(klcdReadMode);
+    registerSelect = klcdInstructionRegister;
+    wait_us(5);
+    enable = klcdEnableHigh;
+    wait_us(0.5);
+    while(dataBus.read() >> 3) {};
+    enable = klcdEnableLow;
+    wait_us(0.6);
+    readNibble(klcdInstructionRegister);
+    return;
+}
+
+void lcd::writeByte(int _reg, int _byte, bool _wait) {
+    //write the most significant four bytes first
+    writeNibble(_reg, _byte >> 4);
+    writeNibble(_reg, _byte);
+    if(_wait) {
+        waitUntilNotBusy();
+    }
+}
+
+//this is useless at the moment, not sure how I want to structure
+//  reading bytes with the four wire interface, as one read is
+//  technically reading the busy flag and internal address counter,
+//  another is actually reading bytes from CGRAM or DDRAM (which isn't
+//  all that useful actually)
+int lcd::readNibble(int _reg) {
+    setMode(klcdReadMode);
+    registerSelect = _reg;
+    
+    //wait more than 60ns for address set up, then bring enable high
+    wait_us(0.1);
+    enable = klcdEnableHigh;
+    //wait for the enable pulse width to elapse (450ns), by which time the data
+    //  should be present on the bus, then bring enable low, and wait
+    //  till the end of the enable cycle
+    wait_us(0.5);
+    int nibble = dataBus.read();
+    enable = klcdEnableLow;
+    wait_us(0.6);
+    return nibble;
+}
+
+//write a four bit nibble onto the bus with correct delays
+void lcd::writeNibble(int _reg, int _nibble) {
+    setMode(klcdWriteMode);
+    registerSelect = _reg;
+    
+    dataBus = _nibble;
+    //wait for more than 60ns for address set up, then bring enable high
+    wait_us(0.1);
+    enable = klcdEnableHigh;
+    //wait for more than 450ns for enable pulse width, then bring enable low
+    wait_us(0.5);
+    enable = klcdEnableLow;
+    //wait for more than 550ns for the completion of the enable cycle
+    wait_us(0.6);
+}
+
+
+//Stream Implementation
+//////////////////////////////////////////////////////////////////////////////////////
+int lcd::_putc(int _char) {
+    if(_char == '\n') {
+        column = 0;
+        row = (++row % 2);
+    } else {
+        locateCharacter(row, column, _char);
+        column++;
+    }    
+    return _char;
+}
+
+//not respoinding to getc (yet, this would require reading out of the 
+// DDRAM of the display, or caching
+int lcd::_getc() {
+    return -1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lcd.h	Fri Nov 08 07:03:35 2013 +0000
@@ -0,0 +1,54 @@
+#ifndef LCD
+#define LCD
+
+#include "mbed.h"
+
+#define klcdWriteMode           0
+#define klcdReadMode            1
+#define klcdInstructionRegister 0
+#define klcdDataRegister        1
+#define klcdEnableHigh          1
+#define klcdEnableLow           0
+
+class lcd : public Stream{
+    public:
+        //uses the four bit interface with a read/write pin in order to read the busy flag
+        lcd(PinName _rs, PinName _rw, PinName _e, PinName _db4, PinName _db5, PinName _db6, PinName _db7);
+        
+        //clear the screen
+        void clear();
+        
+        //move to a location on the screen, the next printf or putc call
+        //  will locate the character at the location
+        void locate(int _row, int _column);
+        
+        //place a character at a location
+        void locateCharacter(int _row, int _column, int _char);
+        
+        //define a character with a 8 element array of 5 bit wide pixel
+        //  definitions, from top to bottom
+        void defineCharacter(int _char, int _charData[8]);
+        
+    protected:
+        void setMode(int _mode);
+        void waitUntilNotBusy();
+        int readByte(int _reg);
+        void writeByte(int _reg, int _byte, bool _wait = true);
+        int readNibble(int _reg);
+        void writeNibble(int _reg, int _nibble);
+        
+        //stream implementation
+        virtual int _putc(int _value);
+        virtual int _getc();
+        
+        BusInOut dataBus;
+        DigitalOut registerSelect;
+        DigitalOut readWrite;
+        DigitalOut enable;
+               
+        int currentMode;
+        int column;
+        int row;
+};
+
+#endif
\ No newline at end of file