mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-23 12:51:24 +01:00
Lcd experimental (#46)
* LCD/OLED Implementation * OLED basic working 32 *132 display * LCD/OLED startup ok * Simplified setup * Missing freememory include * Format Width Allow right padding number width in String format * Intermediate scroll * Compile issues with no LCD * Clean buffers at startup * Support for format left padded numbers * Smarter Scrolling And forced start messages Free Ram in slot 2 * LCD tidying Neater setup block in .ino. Dropped unnecessary code No-scroll if display not full * Missing %E format support This is used in WifiInterface checkForOK * Wifi correction and memory guard
This commit is contained in:
parent
3f06fb08df
commit
0e3046e24f
@ -1,3 +1,21 @@
|
||||
/*
|
||||
* © 2020,Gregor Baues, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
#include "CommandDistributor.h"
|
||||
#include "WiThrottle.h"
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
* © 2020,Gregor Baues, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CommandDistributor_h
|
||||
#define CommandDistributor_h
|
||||
#include "DCCEXParser.h"
|
||||
|
@ -12,18 +12,6 @@
|
||||
#include "config.h"
|
||||
#include "DCCEX.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Enables an I2C 2x24 or 4x24 LCD Screen
|
||||
#if ENABLE_LCD
|
||||
bool lcdEnabled = false;
|
||||
#if defined(LIB_TYPE_PCF8574)
|
||||
LiquidCrystal_PCF8574 lcdDisplay(LCD_ADDRESS);
|
||||
#elif defined(LIB_TYPE_I2C)
|
||||
LiquidCrystal_I2C lcdDisplay = LiquidCrystal_I2C(LCD_ADDRESS, LCD_COLUMNS, LCD_LINES);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Create a serial command parser for the USB connection,
|
||||
// This supports JMRI or manual diagnostics and commands
|
||||
// to be issued from the USB serial console.
|
||||
@ -31,45 +19,22 @@ DCCEXParser serialParser;
|
||||
|
||||
void setup()
|
||||
{
|
||||
////////////////////////////////////////////
|
||||
//
|
||||
// More display stuff. Need to put this in a .h file and make
|
||||
// it a class
|
||||
#if ENABLE_LCD
|
||||
Wire.begin();
|
||||
// Check that we can find the LCD by its address before attempting to use it.
|
||||
Wire.beginTransmission(LCD_ADDRESS);
|
||||
if (Wire.endTransmission() == 0)
|
||||
{
|
||||
lcdEnabled = true;
|
||||
lcdDisplay.begin(LCD_COLUMNS, LCD_LINES);
|
||||
lcdDisplay.setBacklight(255);
|
||||
lcdDisplay.clear();
|
||||
lcdDisplay.setCursor(0, 0);
|
||||
lcdDisplay.print("DCC++ EX v");
|
||||
lcdDisplay.print(VERSION);
|
||||
lcdDisplay.setCursor(0, 1);
|
||||
#if COMM_INTERFACE >= 1
|
||||
lcdDisplay.print("IP: PENDING");
|
||||
#else
|
||||
lcdDisplay.print("SERIAL: READY");
|
||||
#endif
|
||||
#if LCD_LINES > 2
|
||||
lcdDisplay.setCursor(0, 3);
|
||||
lcdDisplay.print("TRACK POWER: OFF");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// The main sketch has responsibilities during setup()
|
||||
|
||||
// Responsibility 1: Start the usb connection for diagnostics
|
||||
// This is normally Serial but uses SerialUSB on a SAMD processor
|
||||
Serial.begin(115200);
|
||||
DIAG(F("DCC++ EX v%S"),F(VERSION));
|
||||
|
||||
CONDITIONAL_LCD_START {
|
||||
// This block is ignored if LCD not in use
|
||||
LCD(0,F("DCC++ EX v%S"),F(VERSION));
|
||||
LCD(1,F("Starting"));
|
||||
}
|
||||
|
||||
// Start the WiFi interface on a MEGA, Uno cannot currently handle WiFi
|
||||
|
||||
#ifdef WIFI_ON
|
||||
#if WIFI_ON
|
||||
WifiInterface::setup(WIFI_SERIAL_LINK_SPEED, F(WIFI_SSID), F(WIFI_PASSWORD), F(WIFI_HOSTNAME), IP_PORT);
|
||||
#endif // WIFI_ON
|
||||
|
||||
@ -83,7 +48,8 @@ void setup()
|
||||
// Optionally a Timer number (1..4) may be passed to DCC::begin to override the default Timer1 used for the
|
||||
// waveform generation. e.g. DCC::begin(STANDARD_MOTOR_SHIELD,2); to use timer 2
|
||||
|
||||
DCC::begin(MOTOR_SHIELD_TYPE);
|
||||
DCC::begin(MOTOR_SHIELD_TYPE);
|
||||
LCD(1,F("Ready"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
@ -101,7 +67,9 @@ void loop()
|
||||
#if WIFI_ON
|
||||
WifiInterface::loop();
|
||||
#endif
|
||||
|
||||
|
||||
LCDDisplay::loop(); // ignored if LCD not in use
|
||||
|
||||
// Optionally report any decrease in memory (will automatically trigger on first call)
|
||||
#if ENABLE_FREE_MEM_WARNING
|
||||
static int ramLowWatermark = 32767; // replaced on first loop
|
||||
@ -110,7 +78,7 @@ void loop()
|
||||
if (freeNow < ramLowWatermark)
|
||||
{
|
||||
ramLowWatermark = freeNow;
|
||||
DIAG(F("\nFree RAM=%d\n"), ramLowWatermark);
|
||||
LCD(2,F("Free RAM=%5db"), ramLowWatermark);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
11
DCC.h
11
DCC.h
@ -162,16 +162,5 @@ private:
|
||||
#error CANNOT COMPILE - DCC++ EX ONLY WORKS WITH AN ARDUINO UNO, NANO 328, OR ARDUINO MEGA 1280/2560
|
||||
#endif
|
||||
|
||||
#if ENABLE_LCD
|
||||
#include <Wire.h>
|
||||
#if defined(LIB_TYPE_PCF8574)
|
||||
#include <LiquidCrystal_PCF8574.h>
|
||||
extern LiquidCrystal_PCF8574 lcdDisplay;
|
||||
#elif defined(LIB_TYPE_I2C)
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
extern LiquidCrystal_I2C lcdDisplay;
|
||||
#endif
|
||||
extern bool lcdEnabled;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
3
DCCEX.h
3
DCCEX.h
@ -11,7 +11,8 @@
|
||||
#include "version.h"
|
||||
#include "WifiInterface.h"
|
||||
#include "EthernetInterface.h"
|
||||
|
||||
#include "LCD_Implementation.h"
|
||||
#include "freeMemory.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#endif
|
||||
|
1
DIAG.h
1
DIAG.h
@ -20,4 +20,5 @@
|
||||
#define DIAG_h
|
||||
#include "StringFormatter.h"
|
||||
#define DIAG StringFormatter::diag
|
||||
#define LCD StringFormatter::lcd
|
||||
#endif
|
||||
|
79
LCDDisplay.cpp
Normal file
79
LCDDisplay.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* © 2020, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// CAUTION: the device dependent parts of this class are created in the .ini using LCD_Implementation.h
|
||||
#include "LCDDisplay.h"
|
||||
|
||||
void LCDDisplay::clear() {
|
||||
clearNative();
|
||||
for (byte row=0;row<MAX_LCD_ROWS; row++) rowBuffer[row][0]='\0';
|
||||
topRow=-1; // loop2 will fill from row 0
|
||||
}
|
||||
|
||||
void LCDDisplay::setRow(byte line) {
|
||||
hotRow=line;
|
||||
hotCol=0;
|
||||
}
|
||||
|
||||
size_t LCDDisplay::write(uint8_t b) {
|
||||
if (hotRow>=MAX_LCD_ROWS || hotCol>=MAX_LCD_COLS) return -1;
|
||||
rowBuffer[hotRow][hotCol]=b;
|
||||
hotCol++;
|
||||
rowBuffer[hotRow][hotCol]=0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LCDDisplay::loop() {
|
||||
if (!lcdDisplay) return;
|
||||
lcdDisplay->loop2(false);
|
||||
}
|
||||
|
||||
LCDDisplay* LCDDisplay::loop2(bool force) {
|
||||
if ((!force) && (millis() - lastScrollTime)< LCD_SCROLL_TIME) return NULL;
|
||||
lastScrollTime=millis();
|
||||
clearNative();
|
||||
int rowFirst=nextFilledRow();
|
||||
if (rowFirst<0)return NULL; // No filled rows
|
||||
setRowNative(0);
|
||||
writeNative(rowBuffer[rowFirst]);
|
||||
for (int slot=1;slot<lcdRows;slot++) {
|
||||
int rowNext=nextFilledRow();
|
||||
if (rowNext==rowFirst){
|
||||
// we have wrapped around and not filled the screen
|
||||
topRow=-1; // start again at first row next time.
|
||||
break;
|
||||
}
|
||||
setRowNative(slot);
|
||||
writeNative(rowBuffer[rowNext]);
|
||||
}
|
||||
displayNative();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int LCDDisplay::nextFilledRow() {
|
||||
for (int rx=1;rx<=MAX_LCD_ROWS;rx++) {
|
||||
topRow++;
|
||||
topRow %= MAX_LCD_ROWS;
|
||||
if (rowBuffer[topRow][0]) return topRow;
|
||||
}
|
||||
return -1; // No slots filled
|
||||
}
|
||||
|
||||
|
||||
|
63
LCDDisplay.h
Normal file
63
LCDDisplay.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* © 2020, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LCDDisplay_h
|
||||
#define LCDDisplay_h
|
||||
#include <Arduino.h>
|
||||
|
||||
// This class is created in LCDisplay_Implementation.h
|
||||
|
||||
class LCDDisplay : public Print {
|
||||
|
||||
public:
|
||||
static const int MAX_LCD_ROWS=8;
|
||||
static const int MAX_LCD_COLS=16;
|
||||
static const long LCD_SCROLL_TIME=3000; // 3 seconds
|
||||
|
||||
static LCDDisplay* lcdDisplay;
|
||||
LCDDisplay();
|
||||
void interfake(int p1, int p2, int p3);
|
||||
|
||||
// Internally handled functions
|
||||
static void loop();
|
||||
LCDDisplay* loop2(bool force);
|
||||
void setRow(byte line);
|
||||
void clear();
|
||||
|
||||
virtual size_t write(uint8_t b);
|
||||
using Print::write;
|
||||
|
||||
private:
|
||||
int nextFilledRow();
|
||||
|
||||
// Relay functions to the live driver
|
||||
void clearNative();
|
||||
void displayNative();
|
||||
void setRowNative(byte line);
|
||||
void writeNative(char * b);
|
||||
|
||||
unsigned long lastScrollTime=0;
|
||||
int hotRow=0;
|
||||
int hotCol=0;
|
||||
int topRow=0;
|
||||
int lcdRows;
|
||||
void renderRow(byte row);
|
||||
char rowBuffer[MAX_LCD_ROWS][MAX_LCD_COLS+1];
|
||||
};
|
||||
|
||||
#endif
|
55
LCD_Implementation.h
Normal file
55
LCD_Implementation.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* © 2020, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// This implementation is designed to be #included ONLY ONCE in the .ino
|
||||
//
|
||||
// It will create a driver implemntation and a shim class implementation.
|
||||
// This means that other classes can reference the shim without knowing
|
||||
// which libraray is involved.
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config.h"
|
||||
#include <Wire.h>
|
||||
#include "LCDDisplay.h"
|
||||
|
||||
LCDDisplay * LCDDisplay::lcdDisplay=0;
|
||||
|
||||
// Implement the LCDDisplay shim class as a singleton.
|
||||
// Notice that the LCDDisplay class declaration (LCDDisplay.h) is independent of the library
|
||||
// but the implementation is compiled here with dependencies on LCDDriver which is
|
||||
// specific to the library in use.
|
||||
// Thats the workaround to the drivers not all implementing a common interface.
|
||||
|
||||
#if defined(OLED_DRIVER)
|
||||
#include "LCD_OLED.h"
|
||||
#define CONDITIONAL_LCD_START for (LCDDisplay * dummy=new LCDDisplay();dummy!=NULL; dummy=dummy->loop2(true))
|
||||
|
||||
|
||||
#elif defined(LCD_DRIVER)
|
||||
#include "LCD_LCD.h"
|
||||
#define CONDITIONAL_LCD_START for (LCDDisplay * dummy=new LCDDisplay();dummy!=NULL; dummy=dummy->loop2(true))
|
||||
|
||||
#else
|
||||
#include "LCD_NONE.h"
|
||||
#define CONDITIONAL_LCD_START if (false) /* NO LCD CONFIG */
|
||||
#endif
|
||||
|
||||
|
||||
|
37
LCD_LCD.h
Normal file
37
LCD_LCD.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* © 2020, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
LiquidCrystal_I2C LCDDriver(LCD_DRIVER); // set the LCD address, cols, rows
|
||||
// DEVICE SPECIFIC LCDDisplay Implementation for LCD_DRIVER
|
||||
LCDDisplay::LCDDisplay() {
|
||||
lcdDisplay=this;
|
||||
LCDDriver.init();
|
||||
LCDDriver.backlight();
|
||||
interfake(LCD_DRIVER);
|
||||
clear();
|
||||
}
|
||||
void LCDDisplay::interfake(int p1, int p2, int p3) {(void)p1; (void)p2; lcdRows=p3; }
|
||||
void LCDDisplay::clearNative() {LCDDriver.clear();}
|
||||
void LCDDisplay::setRowNative(byte row) {
|
||||
LCDDriver.setCursor(0, row);
|
||||
LCDDriver.print(F(" "));
|
||||
LCDDriver.setCursor(0, row);
|
||||
}
|
||||
void LCDDisplay::writeNative(char * b){ LCDDriver.print(b); }
|
||||
void LCDDisplay::displayNative() { LCDDriver.display(); }
|
27
LCD_NONE.h
Normal file
27
LCD_NONE.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* © 2020, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// dummy LCD shim to keep linker happy
|
||||
LCDDisplay::LCDDisplay() {}
|
||||
void LCDDisplay::interfake(int p1, int p2, int p3) {(void)p1; (void)p2; (void)p3;}
|
||||
void LCDDisplay::setRowNative(byte row) { (void)row;}
|
||||
void LCDDisplay::clearNative() {}
|
||||
void LCDDisplay::writeNative(char * b){ (void)b;} //
|
||||
void LCDDisplay::displayNative(){}
|
||||
|
57
LCD_OLED.h
Normal file
57
LCD_OLED.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* © 2020, Chris Harlow. All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// OLED Implementation of LCDDisplay class
|
||||
// Note: this file is optionally included by LCD_Implenentation.h
|
||||
// It is NOT a .cpp file to prevent it being compiled and demanding libraraies even when not needed.
|
||||
|
||||
#include <Adafruit_SSD1306.h>
|
||||
Adafruit_SSD1306 LCDDriver(OLED_DRIVER);
|
||||
|
||||
// DEVICE SPECIFIC LCDDisplay Implementation for OLED
|
||||
|
||||
LCDDisplay::LCDDisplay() {
|
||||
if(LCDDriver.begin(SSD1306_SWITCHCAPVCC, 0x3C) || LCDDriver.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
|
||||
DIAG(F("\nOLED display found"));
|
||||
delay(2000); // painful Adafruit splash pants!
|
||||
lcdDisplay=this;
|
||||
LCDDriver.setTextSize(1); // Normal 1:1 pixel scale
|
||||
LCDDriver.setTextColor(SSD1306_WHITE); // Draw white text
|
||||
interfake(OLED_DRIVER,0);
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
DIAG(F("\nOLED display not found\n"));
|
||||
}
|
||||
|
||||
void LCDDisplay::interfake(int p1, int p2, int p3) {(void)p1; lcdRows=p2/8; (void)p3;}
|
||||
|
||||
void LCDDisplay::clearNative() {LCDDriver.clearDisplay();}
|
||||
|
||||
void LCDDisplay::setRowNative(byte row) {
|
||||
// Positions text write to start of row 1..n and clears previous text
|
||||
int y=8*row;
|
||||
LCDDriver.fillRect(0, y, LCDDriver.width(), 8, SSD1306_BLACK);
|
||||
LCDDriver.setCursor(0, y);
|
||||
}
|
||||
|
||||
void LCDDisplay::writeNative(char * b){ LCDDriver.print(b); }
|
||||
|
||||
void LCDDisplay::displayNative() { LCDDriver.display(); }
|
||||
|
@ -31,6 +31,8 @@
|
||||
#define __FlashStringHelper char
|
||||
#endif
|
||||
|
||||
#include "LCDDisplay.h"
|
||||
|
||||
bool Diag::ACK=false;
|
||||
bool Diag::CMD=false;
|
||||
bool Diag::WIFI=false;
|
||||
@ -44,6 +46,14 @@ void StringFormatter::diag( const __FlashStringHelper* input...) {
|
||||
send2(diagSerial,input,args);
|
||||
}
|
||||
|
||||
void StringFormatter::lcd(byte row, const __FlashStringHelper* input...) {
|
||||
if (!LCDDisplay::lcdDisplay) return;
|
||||
LCDDisplay::lcdDisplay->setRow(row);
|
||||
va_list args;
|
||||
va_start(args, input);
|
||||
send2(LCDDisplay::lcdDisplay,input,args);
|
||||
}
|
||||
|
||||
void StringFormatter::send(Print * stream, const __FlashStringHelper* input...) {
|
||||
va_list args;
|
||||
va_start(args, input);
|
||||
@ -56,7 +66,6 @@ void StringFormatter::send(Print & stream, const __FlashStringHelper* input...)
|
||||
send2(&stream,input,args);
|
||||
}
|
||||
|
||||
|
||||
void StringFormatter::send2(Print * stream,const __FlashStringHelper* format, va_list args) {
|
||||
|
||||
// thanks to Jan Turoň https://arduino.stackexchange.com/questions/56517/formatting-strings-in-arduino-for-output
|
||||
@ -66,6 +75,13 @@ void StringFormatter::send2(Print * stream,const __FlashStringHelper* format, va
|
||||
char c=pgm_read_byte_near(flash+i);
|
||||
if (c=='\0') return;
|
||||
if(c!='%') { stream->print(c); continue; }
|
||||
|
||||
bool formatContinues=false;
|
||||
byte formatWidth=0;
|
||||
bool formatLeft=false;
|
||||
do {
|
||||
|
||||
formatContinues=false;
|
||||
i++;
|
||||
c=pgm_read_byte_near(flash+i);
|
||||
switch(c) {
|
||||
@ -73,14 +89,34 @@ void StringFormatter::send2(Print * stream,const __FlashStringHelper* format, va
|
||||
case 'c': stream->print((char) va_arg(args, int)); break;
|
||||
case 's': stream->print(va_arg(args, char*)); break;
|
||||
case 'e': printEscapes(stream,va_arg(args, char*)); break;
|
||||
case 'E': printEscapes(stream,(const __FlashStringHelper*)va_arg(args, char*)); break;
|
||||
case 'S': stream->print((const __FlashStringHelper*)va_arg(args, char*)); break;
|
||||
case 'd': stream->print(va_arg(args, int), DEC); break;
|
||||
case 'l': stream->print(va_arg(args, long), DEC); break;
|
||||
case 'd': printPadded(stream,va_arg(args, int), formatWidth, formatLeft); break;
|
||||
case 'l': printPadded(stream,va_arg(args, long), formatWidth, formatLeft); break;
|
||||
case 'b': stream->print(va_arg(args, int), BIN); break;
|
||||
case 'o': stream->print(va_arg(args, int), OCT); break;
|
||||
case 'x': stream->print(va_arg(args, int), HEX); break;
|
||||
case 'f': stream->print(va_arg(args, double), 2); break;
|
||||
//format width prefix
|
||||
case '-':
|
||||
formatLeft=true;
|
||||
formatContinues=true;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
formatWidth=formatWidth * 10 + (c-'0');
|
||||
formatContinues=true;
|
||||
break;
|
||||
}
|
||||
} while(formatContinues);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
@ -94,6 +130,17 @@ void StringFormatter::printEscapes(Print * stream,char * input) {
|
||||
}
|
||||
}
|
||||
|
||||
void StringFormatter::printEscapes(Print * stream, const __FlashStringHelper * input) {
|
||||
|
||||
if (!stream) return;
|
||||
char* flash=(char*)input;
|
||||
for(int i=0; ; ++i) {
|
||||
char c=pgm_read_byte_near(flash+i);
|
||||
printEscape(stream,c);
|
||||
if (c=='\0') return;
|
||||
}
|
||||
}
|
||||
|
||||
void StringFormatter::printEscape( char c) {
|
||||
printEscape(diagSerial,c);
|
||||
}
|
||||
@ -109,4 +156,27 @@ void StringFormatter::printEscape(Print * stream, char c) {
|
||||
default: stream->print(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StringFormatter::printPadded(Print* stream, long value, byte width, bool formatLeft) {
|
||||
if (width==0) {
|
||||
stream->print(value, DEC);
|
||||
return;
|
||||
}
|
||||
|
||||
int digits=(value <= 0)? 1: 0; // zero and negative need extra digot
|
||||
long v=value;
|
||||
while (v) {
|
||||
v /= 10;
|
||||
digits++;
|
||||
}
|
||||
|
||||
if (formatLeft) stream->print(value, DEC);
|
||||
while(digits<width) {
|
||||
stream->print(' ');
|
||||
digits++;
|
||||
}
|
||||
if (!formatLeft) stream->print(value, DEC);
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#define __FlashStringHelper char
|
||||
#endif
|
||||
|
||||
#include "LCDDisplay.h"
|
||||
class Diag {
|
||||
public:
|
||||
static bool ACK;
|
||||
@ -42,16 +43,19 @@ class StringFormatter
|
||||
static void send(Print & serial, const __FlashStringHelper* input...);
|
||||
|
||||
static void printEscapes(Print * serial,char * input);
|
||||
static void printEscapes(Print * serial,const __FlashStringHelper* input);
|
||||
static void printEscape(Print * serial, char c);
|
||||
|
||||
// DIAG support
|
||||
static Print * diagSerial;
|
||||
static void diag( const __FlashStringHelper* input...);
|
||||
static void lcd(byte row, const __FlashStringHelper* input...);
|
||||
static void printEscapes(char * input);
|
||||
static void printEscape( char c);
|
||||
|
||||
private:
|
||||
static void send2(Print * serial, const __FlashStringHelper* input,va_list args);
|
||||
static void printPadded(Print* stream, long value, byte width, bool formatLeft);
|
||||
|
||||
};
|
||||
#endif
|
||||
|
@ -103,7 +103,7 @@ void WiThrottle::parse(Print & stream, byte * cmdx) {
|
||||
|
||||
// we have to take a copy of the cmd buffer as the reply will get built into the cmdx
|
||||
byte local[150];
|
||||
for (byte i=0;i<sizeof(local);i++) {
|
||||
for (byte i=0;i<sizeof(local)-1;i++) {
|
||||
local[i]=cmdx[i];
|
||||
if (!cmdx[i]) break;
|
||||
}
|
||||
|
@ -179,7 +179,11 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
|
||||
break;
|
||||
|
||||
case GOT_CLIENT_ID3: // got "x C" before CLOSE or CONNECTED (which is ignored)
|
||||
if(ch=='L') clientStatus[runningClientId]=UNUSED;
|
||||
if(ch=='L') {
|
||||
// CLOSE
|
||||
clientStatus[runningClientId]=UNUSED;
|
||||
if (runningClientId==clientPendingCIPSEND) clientPendingCIPSEND=-1;
|
||||
}
|
||||
loopState=SKIPTOEND;
|
||||
break;
|
||||
|
||||
|
@ -70,37 +70,17 @@ The configuration file for DCC++ EX Command Station
|
||||
//
|
||||
// Note: This feature requires an I2C enabled LCD screen using a PCF8574 based chipset.
|
||||
// or one using a Hitachi HD44780.
|
||||
//
|
||||
// To enable, uncomment the line below and make sure only the correct LIB_TYPE line
|
||||
// is uncommented below to select the library used for your LCD backpack
|
||||
// OR an I2C Oled screen.
|
||||
// To enable, uncomment one of the lines below
|
||||
|
||||
//#define ENABLE_LCD
|
||||
|
||||
#ifdef ENABLE_LCD
|
||||
#define LIB_TYPE_PCF8574
|
||||
//#define LIB_TYPE_I2C
|
||||
// This defines the I2C address for the LCD device
|
||||
#define LCD_ADDRESS 0x27 //common defaults are 0x27 and 0x3F
|
||||
|
||||
// This defines the number of columns the LCD device has
|
||||
#define LCD_COLUMNS 16
|
||||
|
||||
// This defines the number of lines the LCD device has
|
||||
#define LCD_LINES 2
|
||||
#endif
|
||||
// define LCD_DRIVER for I2C LCD address 0x3f,16 cols, 2 rows
|
||||
// #define LCD_DRIVER 0x3F,16,2
|
||||
|
||||
//OR define OLED_DRIVER width,height in pixels (address auto detected)
|
||||
// This will not work on a UNO due to memory constraints
|
||||
// #define OLED_DRIVER 128,32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Enable custom command filtering
|
||||
#define ENABLE_CUSTOM_FILTER false
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Enable custom command filtering
|
||||
#define ENABLE_CUSTOM_CALLBACK false
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Enable custom command filtering
|
||||
// Enable warning as memory gets depleted
|
||||
#define ENABLE_FREE_MEM_WARNING false
|
||||
|
Loading…
Reference in New Issue
Block a user