Library for New Haven NHD_0420DZW OLED
Diff: NHD_0420DZW_OLED.cpp
- Revision:
- 0:91420dff6791
--- /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; +}