/***************************************************************** METP0000_lib Arduino library Structure based on standard Arduino LiquidCrystal.h library Some code is based on code developed and maintanied by MCUdude https://github.com/MCUdude/KTMS1201 Based on Tronixstruff's work tronixstuff.com/2013/03/11/arduino-and-ktm-s1201-lcd-modules (Jeff Albertson, Robert W. Mech, John Boxall) Also incorporating font/code ideas from all over Conversion to supporting METP0000 module by Tony Wills 2018-11-24 v 1.00 initial version 2018-11-27 v 1.30 print.h version based on LiquidCrystal.h *****************************************************************/ #include "METP0000_lib.h" #include #include #include #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif // Constructor with busy pin METP0000::METP0000(uint8_t NSCK, uint8_t SI, uint8_t BUSY, uint8_t CS) { init(NSCK, SI, BUSY, CS); } // Constructor without busy pin METP0000::METP0000(uint8_t NSCK, uint8_t SI, uint8_t CS) { init(NSCK, SI, 255, CS); } void METP0000::init(uint8_t NSCK, uint8_t SI, uint8_t BUSY, uint8_t CS) { // Store parameters _SCK = NSCK; // data clock _SI = SI; // serial data _BUSY = BUSY; // LCD busy _CS = CS; // LCD select // Set inputs and outputs pinMode(_SCK, OUTPUT); pinMode(_SI, OUTPUT); if (_BUSY != 255) pinMode(_BUSY, INPUT); pinMode(_CS, OUTPUT); } void METP0000::begin(uint8_t cols, uint8_t rows, uint8_t charsize) //parameters just to maintain compatibility { digitalWrite(_SCK,LOW); digitalWrite(_SI, LOW); digitalWrite(_CS, LOW); // deselect LCD // Setup command mode. See header for more info command(_Mode); // initialise LCD bias, timing etc command(_Sync); // delay screen update to sync with frame rate delay(2); command(_NoFlash); // disable blinking delay(2); command(_DispOn); // turn on display delay(1); command(_NoDecode); // not using character decoders as custom wired command(_ClearDsp); // clear LCD, home cursor delay(2); } /********** high level commands, for the user! */ void METP0000::clear(uint8_t start, uint8_t stop) { // Clear the whole LCD if(start == 0 && stop >= 5) { command(_ClearDsp); delay(2); setCursor(0); } else { // clear a section uint8_t currentCursorPos = _cursorPos; // store the current cursor position setCursor(start); String blankSpace = ""; // Fill string with spaces for(uint8_t i = 0; i < (stop - start + 1); i++) blankSpace += ' '; print(blankSpace); setCursor(currentCursorPos); } } void METP0000::home() { setCursor(0); } void METP0000::setCursor(uint8_t cursorPos, uint8_t row) // row is ignore, only here for compatibility { // Store cursor position if(cursorPos > 5) _cursorPos = 5; else _cursorPos = cursorPos; } // Turn the display on/off (quickly) void METP0000::noDisplay() { command(_DispOff); } void METP0000::display() { command(_DispOn); } // Turns the underline cursor on/off void METP0000::noCursor() { // _displaycontrol &= ~LCD_CURSORON; // command(LCD_DISPLAYCONTROL | _displaycontrol); } void METP0000::cursor() { // _displaycontrol |= LCD_CURSORON; // command(LCD_DISPLAYCONTROL | _displaycontrol); } // Turn on and off the blinking cursor void METP0000::noBlink() { // _displaycontrol &= ~LCD_BLINKON; // command(LCD_DISPLAYCONTROL | _displaycontrol); } void METP0000::blink() { // _displaycontrol |= LCD_BLINKON; // command(LCD_DISPLAYCONTROL | _displaycontrol); } // These commands scroll the display without changing the RAM void METP0000::scrollDisplayLeft(void) { // command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); } void METP0000::scrollDisplayRight(void) { // command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); } // This is for text that flows Left to Right void METP0000::leftToRight(void) { // _displaymode |= LCD_ENTRYLEFT; // command(LCD_ENTRYMODESET | _displaymode); } // This is for text that flows Right to Left void METP0000::rightToLeft(void) { // _displaymode &= ~LCD_ENTRYLEFT; // command(LCD_ENTRYMODESET | _displaymode); } // This will 'right justify' text from the cursor void METP0000::autoscroll(void) { // _displaymode |= LCD_ENTRYSHIFTINCREMENT; // command(LCD_ENTRYMODESET | _displaymode); } // This will 'left justify' text from the cursor void METP0000::noAutoscroll(void) { // _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; // command(LCD_ENTRYMODESET | _displaymode); } // Allows us to fill the first 8 CGRAM locations // with custom characters void METP0000::createChar(uint8_t location, uint8_t charmap[]) { // location &= 0x7; // we only have 8 locations 0-7 // command(LCD_SETCGRAMADDR | (location << 3)); // for (int i=0; i<8; i++) { // write(charmap[i]); // } } void METP0000::flash(bool speed) { // Flash fast if(speed == true) command(_FFlash); // Flash slow else command(_SFlash); } void METP0000::noFlash() { command(_NoFlash); } void METP0000::setFlash() { digitalWrite(_CS, HIGH); // select LCD wait(); // wait for the LCD to finish // Enable all segments for flashing for (int i=0; i<32; i++) { send(_WFlshMem + 0x07); wait(); // wait for the LCD to finish } digitalWrite(_CS, LOW); // deselect LCD to display data } void METP0000::unSetFlash() { command(_ClearFlsh); } void METP0000::setSegment(uint16_t seg) { int chr; chr = seg >> 12; uint8_t currentCursorPos = _cursorPos; // store the current cursor position digitalWrite(_CS, HIGH); // select LCD wait(); // wait for the LCD to finish send(_LoadPtr+chr*3); send(_OrDspMem + ((seg >> 8) & 0x007)); wait(); send(_OrDspMem + ((seg >> 4) & 0x007)); wait(); send(_OrDspMem + ((seg >> 0) & 0x007)); wait(); digitalWrite(_CS, LOW); // deselect LCD to display data wait(); setCursor(currentCursorPos); } void METP0000::clearSegment(uint16_t seg) { int chr; chr = seg >> 12; uint8_t currentCursorPos = _cursorPos; // store the current cursor position digitalWrite(_CS, HIGH); // select LCD wait(); // wait for the LCD to finish send(_LoadPtr+chr*3); send(_AndDspMem + ((~seg >> 8) & 0x007)); wait(); send(_AndDspMem + ((~seg >> 4) & 0x007)); wait(); send(_AndDspMem + ((~seg >> 0) & 0x007)); wait(); digitalWrite(_CS, LOW); // deselect LCD to display data wait(); setCursor(currentCursorPos); } /*********** mid level commands, for sending data/cmds */ void METP0000::command(uint8_t cmd) { digitalWrite(_CS, HIGH); // select LCD wait(); // wait for the LCD to finish send(cmd); wait(); // wait for the LCD to finish digitalWrite(_CS, LOW); // deselect LCD to display data } size_t METP0000::write(uint8_t character) { digitalWrite(_CS, HIGH); // select LCD wait(); // wait for the LCD to finish send(_LoadPtr+_cursorPos*3); // position cursor writeChar(sevenSegHex[(uint8_t)character-32]); // write 12bit character digitalWrite(_CS, LOW); //deselect LCD to display data setCursor(_cursorPos+1); return 1; // assume success } /************ low level data pushing commands **********/ void METP0000::send(uint8_t character) { for(uint8_t i = 0; i < 8; i++) { digitalWrite(_SI, !(character & (1 << (7-i)))); digitalWrite(_SCK,HIGH); waitClk(); digitalWrite(_SCK, LOW); waitClk(); } wait(); } // Write a nine-bit character (in a sixteen bit word) using load-immediate commands void METP0000::writeChar(uint16_t _dta) { wait(); send(_WriteMem + ((_dta >> 8) & 0x007)); wait(); send(_WriteMem + ((_dta >> 4) & 0x007)); wait(); send(_WriteMem + ((_dta >> 0) & 0x007)); wait(); } void METP0000::wait() { if(_BUSY == 255) delay(busyDelay); else while(digitalRead(_BUSY) == 0); } void METP0000::waitClk() { delayMicroseconds(15); }