Library for New Haven NHD_0420DZW OLED
Revision 0:91420dff6791, committed 2016-10-26
- Comitter:
- JackB
- Date:
- Wed Oct 26 12:19:43 2016 +0000
- Commit message:
- Library for New Haven NHD_0420DZW OLED
Changed in this revision
NHD_0420DZW_OLED.cpp | Show annotated file Show diff for this revision Revisions of this file |
NHD_0420DZW_OLED.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 91420dff6791 NHD_0420DZW_OLED.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NHD_0420DZW_OLED.cpp Wed Oct 26 12:19:43 2016 +0000 @@ -0,0 +1,308 @@ +/** +* @file NHD_0420DZW_OLED.cpp +* @brief This C++ file contains the functions to interface the New Haven +* NHD_0420DZW display using a 4-wire software spi bus bus. +* 10-bit SPI operation, ie spi.format(10, 3), does not work with Nucleo-F746ZG, +* it remains 8-bit, so unfortunately I had to do bit banging +* @author Jack Berkhout +* +* @date 2016-10-21 +*/ +#include "NHD_0420DZW_OLED.h" +#include "mbed.h" + +NHD_0420DZW_OLED::NHD_0420DZW_OLED(PinName sdi, PinName sdo, PinName scl, PinName csb, const char *name) : + Stream(name), _lcd_sdi(sdi), _lcd_sdo(sdo), _lcd_scl(scl), _lcd_csb(csb) +// TextDisplay(name), _lcd_sdi(sdi), _lcd_sdo(sdo), _lcd_scl(scl), _lcd_csb(csb) +{ + _lcd_csb = 1; + _lcd_scl = 1; + _lcd_sdi = 0; + + // --- claim --- + _row = 0; + _column = 0; + if (name == NULL) { + _path = NULL; + } else { + _path = new char[strlen(name) + 2]; + sprintf(_path, "/%s", name); + } + // ------------- + + init(); +} + +void NHD_0420DZW_OLED::init(void) +{ + writeCommand(LCD_FUNCTION_SET); + writeCommand(LCD_DISPLAY_OFF); + writeCommand(LCD_CLEAR_DISPLAY); + writeCommand(LCD_CURSOR_INCR); + writeCommand(LCD_RETURN_HOME); + writeCommand(LCD_DISPLAY_ON); + + // custom characters + // In the character generator RAM, the user can rewrite character patterns + // For 5x8 dots, eight character patterns can be written + // Store custom chars in LCD's CGRAM + writeCommand(LCD_CGRAM(1)); + char CharacterBytes[] = CHARACTERBYTES; + for (unsigned char Index = 0; Index < sizeof(CharacterBytes); Index++) { + writeData(CharacterBytes[Index]); + } +} + +void NHD_0420DZW_OLED::cls(void) +{ + writeCommand(LCD_CLEAR_DISPLAY); // Clear display +} + +void NHD_0420DZW_OLED::cursorHome(void) +{ + writeCommand(LCD_RETURN_HOME); // Clear display +} + +void NHD_0420DZW_OLED::writeCharacter(int column, int row, int c) +{ + locate(column, row); + writeData(c); +} + +void NHD_0420DZW_OLED::writeCharacter(char c) +{ + writeData((int)c); +} + +void NHD_0420DZW_OLED::writeString(char *charString) +{ + uint8_t length = strlen(charString); + for (uint8_t i = 0; i < length; i++) { + writeCharacter(charString[i]); + } +} + +void NHD_0420DZW_OLED::writeString(int row, char *charString) +{ + locate(0, row); + writeString(charString); +} + +void NHD_0420DZW_OLED::writeString(int column, int row, char *charString) +{ + locate(column, row); + writeString(charString); +} + +void NHD_0420DZW_OLED::clearLine(int row) +{ + int length = LCD_NUMBER_OF_CHARACTERS; + locate(0, row); + while(length--) { + writeCharacter(' '); + } + locate(0, row); +} + +void NHD_0420DZW_OLED::clearRegion(int column, int row, int length) +{ + locate(column, row); + while(length--) { + writeCharacter(' '); + } + locate(column, row); +} + +void NHD_0420DZW_OLED::locate(int column, int row) +{ + if ((column > LCD_NUMBER_OF_CHARACTERS) || (row > LCD_NUMBER_OF_LINES)) + { + return; + } + else + { + switch (row) { + case 0: + writeCommand(LCD_LINE_1 + column); /* command - position cursor at 0x00 (0x80 + 0x00 ) */ + break; + case 1: + writeCommand(LCD_LINE_2 + column); /* command - position cursor at 0x40 (0x80 + 0x00 ) */ + break; + case 2: + writeCommand(LCD_LINE_3 + column); /* command - position cursor at 0x40 (0x80 + 0x00 ) */ + break; + case 3: + writeCommand(LCD_LINE_4 + column); /* command - position cursor at 0x40 (0x80 + 0x00 ) */ + break; + default: + writeCommand(LCD_LINE_1 + column); /* command - position cursor at 0x00 (0x80 + 0x00 ) */ + break; + } + } +} + +void NHD_0420DZW_OLED::drawBar(int column, int row, int Value, int Max) +{ + int Count = 0; + int Characters = Max / 5; + if (Value > Max) + Value = Max; + locate(column, row); + // Print the characters + while (Count < Characters) + { + if ((Value >= 6) && (Value <= Max)) + writeData('\6'); // ***** + else + if ((Value == 0) || (Value > Max)) + writeData('\1'); // ..... + else + writeData(Value+1); // ***.. + Value -= 5; + Count++; + } +} + +void NHD_0420DZW_OLED::writeCommand(int data) +{ + waitBusy(); + writeSerial(LCD_COMMAND, LCD_WRITE, data); +} + +void NHD_0420DZW_OLED::writeData(int data) +{ +// waitBusy(); + writeSerial(LCD_DATA, LCD_WRITE, data); +} + +int NHD_0420DZW_OLED::readAddress(void) +{ + writeSerial(LCD_COMMAND, LCD_READ, 0x00); // Dummy read + return (serialData(LCD_COMMAND, LCD_READ, 0x00, 0x00) >> 3) & 0x7F; +} + +void NHD_0420DZW_OLED::waitBusy(void) +{ + while (readBusyFlag()); +} + +int NHD_0420DZW_OLED::readBusyFlag(void) +{ + return (serialInstruction(LCD_COMMAND, LCD_READ, 0x00, 0x00) >> 10); +} + +void NHD_0420DZW_OLED::writeSerial(int rs, int rw, int data) +{ + // CSB ---|_________________________________________|---- + // SCL -----|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|------ + // SDI .....|RS0|RW0|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |.... + // SDO .............|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |.... + // RS=1: Data + // RS=0: Command <--- + // RW=1: Read + // RW=0: Write <--- + if (rs > 0) { + data |= LCD_RS_BIT_MASK; + } + if (rw > 0) { + data |= LCD_Rw_BIT_MASK; + } + + selectSerial(true); + clockSerial(data, 10); + selectSerial(false); +} + +int NHD_0420DZW_OLED::serialInstruction(int rs, int rw, int data1, int data2) +{ + // CSB ---|_________________________________________________________________________________|---- + // SCL -----|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|------ + // SDI .....|RS0|RW1|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |RS |RW |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |.... + // SDO .............|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |D7 |D6 |.... + // RS=1: Data + // RS=0: Command <--- + // RW=1: Read <--- + // RW=0: Write + // Read Bussy Flag & Address BF AC6 AC5 AC4 AC3 AC2 AC1 AC0 + if (rs > 0) { + data1 |= LCD_RS_BIT_MASK; + data2 |= LCD_RS_BIT_MASK; + } + if (rw > 0) { + data1 |= LCD_Rw_BIT_MASK; + data2 |= LCD_Rw_BIT_MASK; + } + + selectSerial(true); + clockSerial(data1, 10); + int data = clockSerial(data2, 10); + selectSerial(false); + return data; +} + +int NHD_0420DZW_OLED::serialData(int rs, int rw, int data1, int data2) +{ + // CSB ---|_________________________________________________________________________________|---- + // SCL -----|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|------ + // SDI .....|RS1|RW1|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |RS |RW |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |.... + // SDO .............|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |D7 |D6 |.... + // RS=1: Data <--- + // RS=0: Command + // RW=1: Read <--- + // RW=0: Write + // Read data from CGRAM or DDRAM + if (rs > 0) { + data1 |= LCD_RS_BIT_MASK; + } + if (rw > 0) { + data1 |= LCD_Rw_BIT_MASK; + } + + selectSerial(true); + clockSerial(data1, 10); + int data = clockSerial(data2, 8); + selectSerial(false); + return data; +} + +int NHD_0420DZW_OLED::clockSerial(int dataOut, int bits) +{ + int dataIn = 0; + for (int bit = bits; bit > 0; bit--) { + _lcd_scl = 0; + if ((dataOut & (1 << (bit-1))) == 0) { + _lcd_sdi = 0; + } else { + _lcd_sdi = 1; + } +// wait_us(LCD_CLOCK_PULSE_LENGTH); + _lcd_scl = 1; + dataIn |= _lcd_sdo; + dataIn <<= 1; +// wait_us(LCD_CLOCK_PULSE_LENGTH); + } + return dataIn; +} + +void NHD_0420DZW_OLED::selectSerial(bool select) +{ + if (select) + _lcd_csb = 0; + else + _lcd_csb = 1; +// wait_us(LCD_CLOCK_PULSE_LENGTH); +} + +bool NHD_0420DZW_OLED::claim (FILE *stream) { + if ( _path == NULL) { + fprintf(stderr, "claim requires a name to be given in the instantioator of the TextDisplay instance!\r\n"); + return false; + } + if (freopen(_path, "w", stream) == NULL) { + // Failed, should not happen + return false; + } + // make sure we use line buffering + setvbuf(stdout, NULL, _IOLBF, LCD_NUMBER_OF_CHARACTERS); + return true; +}
diff -r 000000000000 -r 91420dff6791 NHD_0420DZW_OLED.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NHD_0420DZW_OLED.h Wed Oct 26 12:19:43 2016 +0000 @@ -0,0 +1,139 @@ +#ifndef _NHD_0420DZW_OLED_H_ +#define _NHD_0420DZW_OLED_H_ + +/** +* @file NHD_0420DZW_OLED.h +* @brief this header file will contain the definitions to interface the New Haven +* NHD-0420DZW-AY5 display using a 4-wire software spi bus bus. +* @author Jack Berkhout +* +* @date 2016-10-21 +*/ + +/** +* Class for the New Haven NHD-0420DZW-AY5 SPI LCD 4x20 +* @author Jack Berkhout +* @date 2016-10-21 +*/ + +#include "mbed.h" +//#include "TextDisplay.h" + +#define LCD_COMMAND 0 +#define LCD_DATA 1 +#define LCD_WRITE 0 +#define LCD_READ 1 + +#define LCD_CLEAR_DISPLAY 0x01 +#define LCD_RETURN_HOME 0x02 +#define LCD_CURSOR_INCR 0x06 +#define LCD_DISPLAY_OFF 0x08 +#define LCD_DISPLAY_ON 0x0C +#define LCD_FUNCTION_SET 0x38 +#define LCD_BUSSY_FLAG 0x80 +#define LCD_NUMBER_OF_CHARACTERS 20 +#define LCD_NUMBER_OF_LINES 4 + +#define LCD_LINE_1 0x80 +#define LCD_LINE_2 0xC0 +#define LCD_LINE_3 0x94 +#define LCD_LINE_4 0xD4 + +#define LCD_CLOCK_PULSE_LENGTH 1 +#define LCD_RS_BIT_MASK 0x0200 +#define LCD_Rw_BIT_MASK 0x0100 + +/* set CGRAM addr */ +#define LCD_CGRAM(n) (0x40 + ((n) << 3)) +// *.... 16 +// **... 24 +// ***.. 28 +// ****. 30 +// ***** 31 +// *..*. 18 +// *..*. 18 +// .***. 14 + +//#define CHARACTERBYTES { \ +// 0, 0, 0, 0, 0, 0, 0, 0, \ +// 16, 16, 16, 16, 16, 16, 16, 16, \ +// 24, 24, 24, 24, 24, 24, 24, 24, \ +// 28, 28, 28, 28, 28, 28, 28, 28, \ +// 30, 30, 30, 30, 30, 30, 30, 30, \ +// 31, 31, 31, 31, 31, 31, 31, 31, \ +// 1, 1, 1, 1, 1, 1, 1, 1 \ +//} + +#define CHARACTERBYTES { \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 16, 16, 0, 0, 0, \ + 0, 0, 0, 24, 24, 0, 0, 0, \ + 0, 0, 0, 28, 28, 0, 0, 0, \ + 0, 0, 0, 30, 30, 0, 0, 0, \ + 0, 0, 0, 31, 31, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0 \ +} + +//class NHD_0420DZW_OLED { +class NHD_0420DZW_OLED : public Stream { +public: + /** + * @brief Create a new Class to interface to an NH-0216K3Z-NSW-BBW 2x16 Character LCD from New Haven + **/ + NHD_0420DZW_OLED(PinName mosi, PinName miso, PinName sck, PinName cs, const char *name); + + void init(void); + + void cls(void); + void cursorHome(void); + + void writeCharacter(int column, int row, int c); + void writeCharacter(char character); + void writeString(char *charString); + void writeString(int y, char *charString); + void writeString(int x, int y, char *charString); + void clearLine(int y); + void clearRegion(int x, int y, int length); + void locate(int X, int Y); + void drawBar(int X, int Y, int Value, int Max); + + virtual bool claim (FILE *stream); + +private: + DigitalOut _lcd_csb; + DigitalOut _lcd_scl; + DigitalOut _lcd_sdi; + DigitalIn _lcd_sdo; + + void writeCommand(int data); + void writeData(int data); + int readAddress(void); + void waitBusy(void); + int readBusyFlag(void); + void writeSerial(int rs, int rw, int data); + int serialInstruction(int rs, int rw, int data1, int data2); + int serialData(int rs, int rw, int data1, int data2); + int clockSerial(int dataOut, int bits); + void selectSerial(bool select); + +// https://developer.mbed.org/users/4180_1/notebook/how-to-get-printf-to-work-in-a-new-display-driver-/ +//and add this to the end of the class +protected: + //used by printf - supply a new _putc virtual function for the new device + virtual int _putc(int c) { + writeData(c); //your new LCD put to print an ASCII character on LCD + return 0; + }; +//assuming no reads from LCD + virtual int _getc() { + return -1; + } + + // character location + uint16_t _column; + uint16_t _row; + char *_path; + +}; +#endif \ No newline at end of file