Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cproject6
-rw-r--r--.settings/org.eclipse.core.resources.prefs4
-rw-r--r--src/Display/Display.cpp55
-rw-r--r--src/Display/Display.h8
-rw-r--r--src/Display/Lcd/Fonts/LcdFont.h24
-rw-r--r--src/Display/Lcd/Fonts/glcd11x14.cpp (renamed from src/Display/ST7920/glcd11x14.cpp)4
-rw-r--r--src/Display/Lcd/Fonts/glcd7x11.cpp (renamed from src/Display/ST7920/glcd7x11.cpp)3
-rw-r--r--src/Display/Lcd/Lcd.cpp (renamed from src/Display/ST7920/lcd7920.cpp)254
-rw-r--r--src/Display/Lcd/Lcd.h (renamed from src/Display/ST7920/lcd7920.h)61
-rw-r--r--src/Display/Lcd/ST7567/Lcd7567.cpp56
-rw-r--r--src/Display/Lcd/ST7567/Lcd7567.h38
-rw-r--r--src/Display/Lcd/ST7920/Lcd7920.cpp144
-rw-r--r--src/Display/Lcd/ST7920/Lcd7920.h36
-rw-r--r--src/Display/Menu.cpp31
-rw-r--r--src/Display/Menu.h4
-rw-r--r--src/Display/MenuItem.cpp32
-rw-r--r--src/Display/MenuItem.h40
-rw-r--r--src/GCodes/GCodeBuffer/BinaryParser.cpp18
-rw-r--r--src/GCodes/GCodeBuffer/BinaryParser.h1
-rw-r--r--src/GCodes/GCodeBuffer/GCodeBuffer.cpp50
-rw-r--r--src/GCodes/GCodeBuffer/StringParser.cpp15
-rw-r--r--src/RepRapFirmware.h7
22 files changed, 553 insertions, 338 deletions
diff --git a/.cproject b/.cproject
index 724c19d3..1bb23ab0 100644
--- a/.cproject
+++ b/.cproject
@@ -1438,7 +1438,7 @@
</toolChain>
</folderInfo>
<sourceEntries>
- <entry excluding="src/SAME70xpld|src/Duet3_V03|src/Duet|src/Hardware/SAME70|src/DuetNG|src/Networking/W5500Ethernet|src/Alligator|src/Pccb|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Networking/LwipEthernet/Lwip/doc|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Duet3_V05|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/DuetM|src/RADDS" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+ <entry excluding="src/SAME70xpld|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Duet3_V03|src/Duet|src/Duet3_V05|src/Hardware/SAME70|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Alligator|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/Pccb|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/RADDS|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
@@ -1583,7 +1583,7 @@
</toolChain>
</folderInfo>
<sourceEntries>
- <entry excluding="src/SAME70xpld|src/Duet3_V03|src/Duet|src/Hardware/SAME70|src/DuetNG|src/Networking/W5500Ethernet|src/Alligator|src/Pccb|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Networking/LwipEthernet/Lwip/doc|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Duet3_V05|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/DuetM|src/RADDS" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+ <entry excluding="src/SAME70xpld|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Duet3_V03|src/Duet|src/Duet3_V05|src/Hardware/SAME70|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Alligator|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/Pccb|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/RADDS|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
@@ -1727,7 +1727,7 @@
</toolChain>
</folderInfo>
<sourceEntries>
- <entry excluding="src/SAME70xpld|src/Duet3_V03|src/Duet|src/Hardware/SAME70|src/DuetNG|src/Networking/W5500Ethernet|src/Alligator|src/Pccb|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/Networking/LwipEthernet/Lwip/doc|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Duet3_V05|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/DuetM|src/RADDS" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+ <entry excluding="src/SAME70xpld|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Networking/LwipEthernet/Lwip/src/apps/smtp|src/Duet3_V03|src/Duet|src/Duet3_V05|src/Hardware/SAME70|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Alligator|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/altcp_tls|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Networking/LwipEthernet/Lwip/src/apps/http|src/Duet3_V06|src/Pccb|src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/RADDS|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
index 6ebe5254..52a88ec0 100644
--- a/.settings/org.eclipse.core.resources.prefs
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,4 @@
eclipse.preferences.version=1
-encoding//src/Display/ST7920/glcd11x14.cpp=UTF-8
-encoding//src/Display/ST7920/glcd7x11.cpp=UTF-8
+encoding//src/Display/Lcd/Fonts/glcd11x14.cpp=UTF-8
+encoding//src/Display/Lcd/Fonts/glcd7x11.cpp=UTF-8
encoding//src/Movement/StepperDrivers/TMC51xx.cpp=UTF-8
diff --git a/src/Display/Display.cpp b/src/Display/Display.cpp
index 2b7a1350..3e80de22 100644
--- a/src/Display/Display.cpp
+++ b/src/Display/Display.cpp
@@ -9,6 +9,8 @@
#if SUPPORT_12864_LCD
+#include "Lcd/ST7920/Lcd7920.h"
+#include "Lcd/ST7567/Lcd7567.h"
#include "GCodes/GCodes.h"
#include "GCodes/GCodeBuffer/GCodeBuffer.h"
#include "Hardware/IoPorts.h"
@@ -144,38 +146,45 @@ void Display::ErrorBeep() noexcept
Beep(500, 1000);
}
-GCodeResult Display::Configure(GCodeBuffer& gb, const StringRef& reply) noexcept
+void Display::InitDisplay(GCodeBuffer& gb, Lcd *newLcd, bool defaultCsPolarity) THROWS(GCodeException)
+{
+ newLcd->Init(LcdCSPin, LcdA0Pin, defaultCsPolarity, (gb.Seen('F')) ? gb.GetUIValue() : LcdSpiClockFrequency);
+ IoPort::SetPinMode(LcdBeepPin, OUTPUT_PWM_LOW);
+ newLcd->SetFont(SmallFontNumber);
+ IoPort::SetPinMode(LcdBeepPin, OUTPUT_PWM_LOW);
+ newLcd->SetFont(SmallFontNumber);
+
+ if (encoder == nullptr)
+ {
+ encoder = new RotaryEncoder(EncoderPinA, EncoderPinB, EncoderPinSw);
+ encoder->Init(DefaultPulsesPerClick);
+ }
+ menu = new Menu(*newLcd);
+ menu->Load("main");
+ lcd = newLcd;
+}
+
+GCodeResult Display::Configure(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException)
{
bool seen = false;
if (gb.Seen('P'))
{
+ Lcd *tempLcd = nullptr;
+ std::swap(lcd, tempLcd);
+ delete tempLcd;
+ delete menu;
+ menu = nullptr;
+
seen = true;
- const unsigned int displayType = gb.GetUIValue();
- switch (displayType)
+ switch (gb.GetUIValue())
{
case 1: // 12864 display, ST7920 controller
- case 2: // 12864 display, ST7567 controller
- if (lcd == nullptr)
- {
- lcd = new Lcd7920(fonts, ARRAY_SIZE(fonts));
- }
- lcd->Init(displayType - 1, LcdCSPin, LcdA0Pin, (gb.Seen('F')) ? gb.GetUIValue() : LcdSpiClockFrequency);
- IoPort::SetPinMode(LcdBeepPin, OUTPUT_PWM_LOW);
- lcd->SetFont(SmallFontNumber);
- IoPort::SetPinMode(LcdBeepPin, OUTPUT_PWM_LOW);
- lcd->SetFont(SmallFontNumber);
+ InitDisplay(gb, new Lcd7920(fonts, ARRAY_SIZE(fonts)), true);
+ break;
- if (encoder == nullptr)
- {
- encoder = new RotaryEncoder(EncoderPinA, EncoderPinB, EncoderPinSw);
- encoder->Init(DefaultPulsesPerClick);
- }
- if (menu == nullptr)
- {
- menu = new Menu(*lcd);
- }
- menu->Load("main");
+ case 2: // 12864 display, ST7567 controller
+ InitDisplay(gb, new Lcd7567(fonts, ARRAY_SIZE(fonts)), false);
break;
default:
diff --git a/src/Display/Display.h b/src/Display/Display.h
index 1fe5a0d1..c15a255d 100644
--- a/src/Display/Display.h
+++ b/src/Display/Display.h
@@ -13,7 +13,7 @@
#if SUPPORT_12864_LCD
#include "RotaryEncoder.h"
-#include "ST7920/lcd7920.h"
+#include "Lcd/Lcd.h"
#include "Menu.h"
#include "GCodes/GCodeResult.h"
@@ -23,7 +23,7 @@ public:
Display() noexcept;
void Init() noexcept { }
- GCodeResult Configure(GCodeBuffer& gb, const StringRef& reply) noexcept;
+ GCodeResult Configure(GCodeBuffer& gb, const StringRef& reply);
void Spin() noexcept;
void Exit() noexcept;
void Beep(unsigned int frequency, unsigned int milliseconds) noexcept;
@@ -33,7 +33,9 @@ public:
void UpdatingFirmware() noexcept;
private:
- Lcd7920 *lcd;
+ void InitDisplay(GCodeBuffer& gb, Lcd *newLcd, bool defaultCsPolarity);
+
+ Lcd *lcd;
Menu *menu;
RotaryEncoder *encoder;
uint32_t whenBeepStarted;
diff --git a/src/Display/Lcd/Fonts/LcdFont.h b/src/Display/Lcd/Fonts/LcdFont.h
new file mode 100644
index 00000000..a102426e
--- /dev/null
+++ b/src/Display/Lcd/Fonts/LcdFont.h
@@ -0,0 +1,24 @@
+/*
+ * LcdFont.h
+ *
+ * Created on: 15 Jul 2020
+ * Author: David
+ */
+
+#ifndef SRC_DISPLAY_LCD_FONTS_LCDFONT_H_
+#define SRC_DISPLAY_LCD_FONTS_LCDFONT_H_
+
+#include <cstdint>
+
+// Struct for describing a font table, always held in PROGMEM
+struct LcdFont
+{
+ const uint8_t *ptr; // pointer to font table
+ uint16_t startCharacter; // Unicode code point of the first character in the font
+ uint16_t endCharacter; // Unicode code point of the last character in the font
+ uint8_t height; // row height in pixels - only this number of pixels will be fetched and drawn - maximum 16 in this version of the software
+ uint8_t width; // max character width in pixels (the font table contains this number of bytes or words per character, plus 1 for the active width)
+ uint8_t numSpaces; // number of space columns between characters before kerning
+};
+
+#endif /* SRC_DISPLAY_LCD_FONTS_LCDFONT_H_ */
diff --git a/src/Display/ST7920/glcd11x14.cpp b/src/Display/Lcd/Fonts/glcd11x14.cpp
index 18e1d9fa..4f7e9235 100644
--- a/src/Display/ST7920/glcd11x14.cpp
+++ b/src/Display/Lcd/Fonts/glcd11x14.cpp
@@ -5,10 +5,12 @@
* Author: David
*/
-#include "lcd7920.h"
+#include "RepRapFirmware.h"
#if SUPPORT_12864_LCD
+#include "LcdFont.h"
+
//Font Generated by MikroElektronika GLCD Font Creator 1.2.0.0
//MikroElektronika 2011
//http://www.mikroe.com
diff --git a/src/Display/ST7920/glcd7x11.cpp b/src/Display/Lcd/Fonts/glcd7x11.cpp
index cd7e5c1e..368353e0 100644
--- a/src/Display/ST7920/glcd7x11.cpp
+++ b/src/Display/Lcd/Fonts/glcd7x11.cpp
@@ -5,10 +5,11 @@
* Author: David
*/
-#include "lcd7920.h"
+#include "RepRapFirmware.h"
#if SUPPORT_12864_LCD
+#include "LcdFont.h"
//Font Generated by MikroElektronika GLCD Font Creator 1.2.0.0
//MikroElektronika 2011
diff --git a/src/Display/ST7920/lcd7920.cpp b/src/Display/Lcd/Lcd.cpp
index 3f914fb8..c6cb2aa8 100644
--- a/src/Display/ST7920/lcd7920.cpp
+++ b/src/Display/Lcd/Lcd.cpp
@@ -1,7 +1,7 @@
// Driver for 128x64 graphical LCD with ST7920 controller
// D Crocker, Escher Technologies Ltd.
-#include "lcd7920.h"
+#include "Lcd.h"
#if SUPPORT_12864_LCD
@@ -10,88 +10,42 @@
// The LCD SPI clock frequency is now defined in the Pins.h file for the configuration being built
-// LCD basic instructions. These all take 72us to execute except LcdDisplayClear, which takes 1.6ms
-constexpr uint8_t LcdDisplayClear = 0x01;
-constexpr uint8_t LcdHome = 0x02;
-constexpr uint8_t LcdEntryModeSet = 0x06; // move cursor right and increment address when writing data
-constexpr uint8_t LcdDisplayOff = 0x08;
-constexpr uint8_t LcdDisplayOn = 0x0C; // add 0x02 for cursor on and/or 0x01 for cursor blink on
-constexpr uint8_t LcdFunctionSetBasicAlpha = 0x20;
-constexpr uint8_t LcdFunctionSetBasicGraphic = 0x22;
-constexpr uint8_t LcdFunctionSetExtendedAlpha = 0x24;
-constexpr uint8_t LcdFunctionSetExtendedGraphic = 0x26;
-constexpr uint8_t LcdSetDdramAddress = 0x80; // add the address we want to set
-
-// LCD extended instructions
-constexpr uint8_t LcdSetGdramAddress = 0x80;
-
-constexpr unsigned int LcdCommandDelayMicros = 72 - 8; // 72us required, less 7us time to send the command @ 2.0MHz
-constexpr unsigned int LcdDataDelayMicros = 4; // delay between sending data bytes
-constexpr unsigned int LcdDisplayClearDelayMillis = 3; // 1.6ms should be enough
-
-inline void Lcd7920::CommandDelay() noexcept
+Lcd::Lcd(PixelNumber nr, PixelNumber nc, const LcdFont * const fnts[], size_t nFonts) noexcept
+ : fonts(fnts), numFonts(nFonts),
+ device(SharedSpiDevice::GetMainSharedSpiDevice(), LcdSpiClockFrequency, SpiMode::mode0, NoPin, true),
+ numRows(nr), numCols(nc)
{
- delayMicroseconds(LcdCommandDelayMicros);
+ imageSize = nr * ((nc + 7)/8);
+ image = new uint8_t[imageSize];
}
-inline void Lcd7920::DataDelay() noexcept
-{
- delayMicroseconds(LcdDataDelayMicros);
-}
-
-Lcd7920::Lcd7920(const LcdFont * const fnts[], size_t nFonts) noexcept
- : fonts(fnts), numFonts(nFonts), device(SharedSpiDevice::GetMainSharedSpiDevice(), LcdSpiClockFrequency, SpiMode::mode0, NoPin, true)
+Lcd::~Lcd()
{
+ delete image;
}
// Initialise. cControllerType is 1 for ST7567 controller, 0 for ST7920. a0Pin is only used by the ST7567.
-void Lcd7920::Init(uint8_t p_controllerType, Pin csPin, Pin p_a0Pin, uint32_t freq) noexcept
+void Lcd::Init(Pin csPin, Pin p_a0Pin, bool csPolarity, uint32_t freq) noexcept
{
- controllerType = p_controllerType;
a0Pin = p_a0Pin;
- if (p_controllerType == 1)
- {
- pinMode(p_a0Pin, OUTPUT_HIGH);
- }
device.SetClockFrequency(freq);
device.SetCsPin(csPin);
- device.SetCsPolarity(controllerType == 0); // active high chip select for ST7920, active low for ST7567
+ device.SetCsPolarity(csPolarity); // normally active high chip select for ST7920, active low for ST7567
#ifdef __LPC17xx__
device.sspChannel = LcdSpiChannel;
#endif
numContinuationBytesLeft = 0;
textInverted = false;
- startRow = NumRows;
- startCol = NumCols;
+ startRow = numRows;
+ startCol = numCols;
endRow = endCol = nextFlushRow = 0;
- device.Select();
- delayMicroseconds(1);
- sendLcdCommand(LcdFunctionSetBasicAlpha);
- delay(2);
- sendLcdCommand(LcdFunctionSetBasicAlpha);
- CommandDelay();
- sendLcdCommand(LcdEntryModeSet);
- CommandDelay();
- sendLcdCommand(LcdDisplayClear); // need this on some displays to ensure that the alpha RAM is clear (M3D Kanji problem)
- delay(LcdDisplayClearDelayMillis);
- sendLcdCommand(LcdFunctionSetExtendedGraphic);
- CommandDelay();
- device.Deselect();
-
- Clear();
- FlushAll();
-
- device.Select();
- delayMicroseconds(1);
- sendLcdCommand(LcdDisplayOn);
- CommandDelay();
- device.Deselect();
+ HardwareInit();
currentFontNumber = 0;
}
-void Lcd7920::SetFont(size_t newFont) noexcept
+void Lcd::SetFont(size_t newFont) noexcept
{
if (newFont < numFonts)
{
@@ -100,13 +54,13 @@ void Lcd7920::SetFont(size_t newFont) noexcept
}
// Get the current font height
-PixelNumber Lcd7920::GetFontHeight() const noexcept
+PixelNumber Lcd::GetFontHeight() const noexcept
{
return fonts[currentFontNumber]->height;
}
// Get the height of a specified font
-PixelNumber Lcd7920::GetFontHeight(size_t fontNumber) const noexcept
+PixelNumber Lcd::GetFontHeight(size_t fontNumber) const noexcept
{
if (fontNumber >= numFonts)
{
@@ -117,7 +71,7 @@ PixelNumber Lcd7920::GetFontHeight(size_t fontNumber) const noexcept
// Flag a pixel as dirty. The r and c parameters must be no greater than NumRows-1 and NumCols-1 respectively.
// Only one pixel in each 16-bit word needs to be flagged dirty for the whole word to get refreshed.
-void Lcd7920::SetDirty(PixelNumber r, PixelNumber c) noexcept
+void Lcd::SetDirty(PixelNumber r, PixelNumber c) noexcept
{
// if (r >= NumRows) { debugPrintf("r=%u\n", r); return; }
// if (c >= NumCols) { debugPrintf("c=%u\n", c); return; }
@@ -130,7 +84,7 @@ void Lcd7920::SetDirty(PixelNumber r, PixelNumber c) noexcept
// Write a UTF8 byte.
// If textYpos is off the end of the display, then don't write anything, just update textXpos and lastCharColData
-size_t Lcd7920::write(uint8_t c) noexcept
+size_t Lcd::write(uint8_t c) noexcept
{
if (numContinuationBytesLeft == 0)
{
@@ -194,7 +148,7 @@ size_t Lcd7920::write(uint8_t c) noexcept
}
}
-size_t Lcd7920::writeNative(uint16_t ch) noexcept
+size_t Lcd::writeNative(uint16_t ch) noexcept
{
const LcdFont * const currentFont = fonts[currentFontNumber];
if (ch == '\n')
@@ -213,13 +167,13 @@ size_t Lcd7920::writeNative(uint16_t ch) noexcept
uint8_t ySize = currentFont->height;
const uint8_t bytesPerColumn = (ySize + 7)/8;
- if (row >= NumRows)
+ if (row >= numRows)
{
ySize = 0; // we still execute the code, so that the caller can tell how many columns the text will occupy by writing it off-screen
}
- else if (row + ySize > NumRows)
+ else if (row + ySize > numRows)
{
- ySize = NumRows - row;
+ ySize = numRows - row;
}
const uint8_t bytesPerChar = (bytesPerColumn * currentFont->width) + 1;
@@ -253,8 +207,8 @@ size_t Lcd7920::writeNative(uint16_t ch) noexcept
if (ySize != 0)
{
const uint8_t mask = 0x80 >> (column & 7);
- uint8_t *p = image + ((row * (NumCols/8)) + (column/8));
- for (uint8_t i = 0; i < ySize && p < (image + sizeof(image)); ++i)
+ uint8_t *p = image + ((row * (numCols/8)) + (column/8));
+ for (uint8_t i = 0; i < ySize && p < (image + imageSize); ++i)
{
const uint8_t oldVal = *p;
const uint8_t newVal = (textInverted) ? oldVal | mask : oldVal & ~mask;
@@ -263,7 +217,7 @@ size_t Lcd7920::writeNative(uint16_t ch) noexcept
*p = newVal;
SetDirty(row + i, column);
}
- p += (NumCols/8);
+ p += (numCols/8);
}
}
++column;
@@ -282,7 +236,7 @@ size_t Lcd7920::writeNative(uint16_t ch) noexcept
{
const uint8_t mask1 = 0x80 >> (column & 7);
const uint8_t mask2 = ~mask1;
- uint8_t *p = image + ((row * (NumCols/8)) + (column/8));
+ uint8_t *p = image + ((row * (numCols/8)) + (column/8));
const uint16_t setPixelVal = (textInverted) ? 0 : 1;
for (uint8_t i = 0; i < ySize; ++i)
{
@@ -294,7 +248,7 @@ size_t Lcd7920::writeNative(uint16_t ch) noexcept
SetDirty(row + i, column);
}
colData >>= 1;
- p += (NumCols/8);
+ p += (numCols/8);
}
}
--nCols;
@@ -307,26 +261,26 @@ size_t Lcd7920::writeNative(uint16_t ch) noexcept
}
// Write a space
-void Lcd7920::WriteSpaces(PixelNumber numPixels) noexcept
+void Lcd::WriteSpaces(PixelNumber numPixels) noexcept
{
const LcdFont * const currentFont = fonts[currentFontNumber];
uint8_t ySize = currentFont->height;
- if (row >= NumRows)
+ if (row >= numRows)
{
ySize = 0; // we still execute the code, so that the caller can tell how many columns the text will occupy by writing it off-screen
}
- else if (row + ySize > NumRows)
+ else if (row + ySize > numRows)
{
- ySize = NumRows - row;
+ ySize = numRows - row;
}
- while (numPixels != 0 && column < NumCols)
+ while (numPixels != 0 && column < numCols)
{
if (ySize != 0)
{
const uint8_t mask = 0x80 >> (column & 7);
- uint8_t *p = image + ((row * (NumCols/8)) + (column/8));
- for (uint8_t i = 0; i < ySize && p < (image + sizeof(image)); ++i)
+ uint8_t *p = image + ((row * (numCols/8)) + (column/8));
+ for (uint8_t i = 0; i < ySize && p < (image + imageSize); ++i)
{
const uint8_t oldVal = *p;
const uint8_t newVal = (textInverted) ? oldVal | mask : oldVal & ~mask;
@@ -335,7 +289,7 @@ void Lcd7920::WriteSpaces(PixelNumber numPixels) noexcept
*p = newVal;
SetDirty(row + i, column);
}
- p += (NumCols/8);
+ p += (numCols/8);
}
}
--numPixels;
@@ -347,24 +301,24 @@ void Lcd7920::WriteSpaces(PixelNumber numPixels) noexcept
}
// Set the left margin. This is where the cursor goes to when we print newline.
-void Lcd7920::SetLeftMargin(PixelNumber c) noexcept
+void Lcd::SetLeftMargin(PixelNumber c) noexcept
{
- leftMargin = min<uint8_t>(c, NumCols);
+ leftMargin = min<PixelNumber>(c, numCols);
}
// Set the right margin. In graphics mode, anything written will be truncated at the right margin. Defaults to the right hand edge of the display.
-void Lcd7920::SetRightMargin(PixelNumber r) noexcept
+void Lcd::SetRightMargin(PixelNumber r) noexcept
{
- rightMargin = min<uint8_t>(r, NumCols);
+ rightMargin = min<PixelNumber>(r, numCols);
}
// Clear a rectangle from the current position to the right margin. The height of the rectangle is the height of the current font.
-void Lcd7920::ClearToMargin() noexcept
+void Lcd::ClearToMargin() noexcept
{
const uint8_t fontHeight = fonts[currentFontNumber]->height;
while (column < rightMargin)
{
- uint8_t *p = image + ((row * (NumCols/8)) + (column/8));
+ uint8_t *p = image + ((row * (numCols/8)) + (column/8));
uint8_t mask = 0xFF >> (column & 7);
PixelNumber nextColumn;
if ((column & (~7)) < (rightMargin & (~7)))
@@ -377,7 +331,7 @@ void Lcd7920::ClearToMargin() noexcept
nextColumn = rightMargin;;
}
- for (uint8_t i = 0; i < fontHeight && p < (image + sizeof(image)); ++i)
+ for (uint8_t i = 0; i < fontHeight && p < (image + imageSize); ++i)
{
const uint8_t oldVal = *p;
const uint8_t newVal = (textInverted) ? oldVal | mask : oldVal & ~mask;
@@ -386,14 +340,14 @@ void Lcd7920::ClearToMargin() noexcept
*p = newVal;
SetDirty(row + i, column); // we refresh 16-bit words, so setting 1 pixel dirty in byte will suffice
}
- p += (NumCols/8);
+ p += (numCols/8);
}
column = nextColumn;
}
}
// Select normal or inverted text
-void Lcd7920::TextInvert(bool b) noexcept
+void Lcd::TextInvert(bool b) noexcept
{
if (b != textInverted)
{
@@ -406,10 +360,10 @@ void Lcd7920::TextInvert(bool b) noexcept
}
// Clear a rectangular block of pixels starting at rows, scol ending just before erow, ecol
-void Lcd7920::Clear(PixelNumber sRow, PixelNumber sCol, PixelNumber eRow, PixelNumber eCol) noexcept
+void Lcd::Clear(PixelNumber sRow, PixelNumber sCol, PixelNumber eRow, PixelNumber eCol) noexcept
{
- if (eCol > NumCols) { eCol = NumCols; }
- if (eRow > NumRows) { eRow = NumRows; }
+ if (eCol > numCols) { eCol = numCols; }
+ if (eRow > numRows) { eRow = numRows; }
if (sCol < eCol && sRow < eRow)
{
uint8_t sMask = ~(0xFF >> (sCol & 7)); // mask of bits we want to keep in the first byte of each row that we modify
@@ -420,8 +374,8 @@ void Lcd7920::Clear(PixelNumber sRow, PixelNumber sCol, PixelNumber eRow, PixelN
}
for (PixelNumber row = sRow; row < eRow; ++row)
{
- uint8_t * p = image + ((row * (NumCols/8)) + (sCol/8));
- uint8_t * const endp = image + ((row * (NumCols/8)) + (eCol/8));
+ uint8_t * p = image + ((row * (numCols/8)) + (sCol/8));
+ uint8_t * const endp = image + ((row * (numCols/8)) + (eCol/8));
*p &= sMask;
if (p != endp)
{
@@ -450,7 +404,7 @@ void Lcd7920::Clear(PixelNumber sRow, PixelNumber sCol, PixelNumber eRow, PixelN
}
// Draw a line using the Bresenham Algorithm (thanks Wikipedia)
-void Lcd7920::Line(PixelNumber y0, PixelNumber x0, PixelNumber y1, PixelNumber x1, PixelMode mode) noexcept
+void Lcd::Line(PixelNumber y0, PixelNumber x0, PixelNumber y1, PixelNumber x1, PixelMode mode) noexcept
{
int dx = (x1 >= x0) ? x1 - x0 : x0 - x1;
int dy = (y1 >= y0) ? y1 - y0 : y0 - y1;
@@ -480,7 +434,7 @@ void Lcd7920::Line(PixelNumber y0, PixelNumber x0, PixelNumber y1, PixelNumber x
}
// Draw a circle using the Bresenham Algorithm (thanks Wikipedia)
-void Lcd7920::Circle(PixelNumber x0, PixelNumber y0, PixelNumber radius, PixelMode mode) noexcept
+void Lcd::Circle(PixelNumber x0, PixelNumber y0, PixelNumber radius, PixelMode mode) noexcept
{
int f = 1 - (int)radius;
int ddF_x = 1;
@@ -519,13 +473,13 @@ void Lcd7920::Circle(PixelNumber x0, PixelNumber y0, PixelNumber radius, PixelMo
}
// Draw a bitmap. x0 and numCols must be divisible by 8.
-void Lcd7920::Bitmap(PixelNumber x0, PixelNumber y0, PixelNumber width, PixelNumber height, const uint8_t data[]) noexcept
+void Lcd::Bitmap(PixelNumber x0, PixelNumber y0, PixelNumber width, PixelNumber height, const uint8_t data[]) noexcept
{
- for (PixelNumber r = 0; r < height && r + y0 < NumRows; ++r)
+ for (PixelNumber r = 0; r < height && r + y0 < numRows; ++r)
{
- uint8_t *p = image + (((r + y0) * (NumCols/8)) + (x0/8));
+ uint8_t *p = image + (((r + y0) * (numCols/8)) + (x0/8));
uint16_t bitMapOffset = r * (width/8);
- for (PixelNumber c = 0; c < (width/8) && c + (x0/8) < NumCols/8; ++c)
+ for (PixelNumber c = 0; c < (width/8) && c + (x0/8) < numCols/8; ++c)
{
*p++ = data[bitMapOffset++];
}
@@ -539,7 +493,7 @@ void Lcd7920::Bitmap(PixelNumber x0, PixelNumber y0, PixelNumber width, PixelNum
}
// Draw a single bitmap row. 'left' and 'width' do not need to be divisible by 8.
-void Lcd7920::BitmapRow(PixelNumber top, PixelNumber left, PixelNumber width, const uint8_t data[], bool invert) noexcept
+void Lcd::BitmapRow(PixelNumber top, PixelNumber left, PixelNumber width, const uint8_t data[], bool invert) noexcept
{
if (width != 0) // avoid possible arithmetic underflow
{
@@ -547,7 +501,7 @@ void Lcd7920::BitmapRow(PixelNumber top, PixelNumber left, PixelNumber width, co
uint8_t firstColIndex = left/8; // column index of the first byte to write
const uint8_t lastColIndex = (left + width - 1)/8; // column index of the last byte to write
const unsigned int firstDataShift = left % 8; // number of bits in the first byte that we leave alone
- uint8_t *p = image + (top * NumCols/8) + firstColIndex;
+ uint8_t *p = image + (top * numCols/8) + firstColIndex;
// Do all bytes except the last one
uint8_t accumulator = *p & (0xFF << (8 - firstDataShift)); // prime the accumulator
@@ -581,7 +535,7 @@ void Lcd7920::BitmapRow(PixelNumber top, PixelNumber left, PixelNumber width, co
}
// Flush all of the dirty part of the image to the lcd. Only called during startup and shutdown.
-void Lcd7920::FlushAll() noexcept
+void Lcd::FlushAll() noexcept
{
while (FlushSome())
{
@@ -589,59 +543,8 @@ void Lcd7920::FlushAll() noexcept
}
}
-// Flush some of the dirty part of the image to the LCD, returning true if there is more to do
-bool Lcd7920::FlushSome() noexcept
-{
- // See if there is anything to flush
- if (endCol > startCol && endRow > startRow)
- {
- // Decide which row to flush next
- if (nextFlushRow < startRow || nextFlushRow >= endRow)
- {
- nextFlushRow = startRow; // start from the beginning
- }
-
- if (nextFlushRow == startRow) // if we are starting form the beginning
- {
- ++startRow; // flag this row as flushed because it will be soon
- }
-
- // Flush that row
- {
- uint8_t startColNum = startCol/16;
- const uint8_t endColNum = (endCol + 15)/16;
-// debugPrintf("flush %u %u %u\n", nextFlushRow, startColNum, endColNum);
-
- device.Select();
- delayMicroseconds(1);
-
- setGraphicsAddress(nextFlushRow, startColNum);
- uint8_t *ptr = image + (((NumCols/8) * nextFlushRow) + (2 * startColNum));
- while (startColNum < endColNum)
- {
- sendLcdData(*ptr++);
- sendLcdData(*ptr++);
- ++startColNum;
- DataDelay();
- }
- device.Deselect();
- }
-
- if (startRow != endRow)
- {
- ++nextFlushRow;
- return true;
- }
-
- startRow = NumRows;
- startCol = NumCols;
- endCol = endRow = nextFlushRow = 0;
- }
- return false;
-}
-
// Set the cursor position
-void Lcd7920::SetCursor(PixelNumber r, PixelNumber c) noexcept
+void Lcd::SetCursor(PixelNumber r, PixelNumber c) noexcept
{
row = r;
column = c;
@@ -649,11 +552,11 @@ void Lcd7920::SetCursor(PixelNumber r, PixelNumber c) noexcept
justSetCursor = true;
}
-void Lcd7920::SetPixel(PixelNumber y, PixelNumber x, PixelMode mode) noexcept
+void Lcd::SetPixel(PixelNumber y, PixelNumber x, PixelMode mode) noexcept
{
- if (y < NumRows && x < rightMargin)
+ if (y < numRows && x < rightMargin)
{
- uint8_t * const p = image + ((y * (NumCols/8)) + (x/8));
+ uint8_t * const p = image + ((y * (numCols/8)) + (x/8));
const uint8_t mask = 0x80u >> (x%8);
const uint8_t oldVal = *p;
uint8_t newVal;
@@ -681,41 +584,16 @@ void Lcd7920::SetPixel(PixelNumber y, PixelNumber x, PixelMode mode) noexcept
}
}
-bool Lcd7920::ReadPixel(PixelNumber x, PixelNumber y) const noexcept
+bool Lcd::ReadPixel(PixelNumber x, PixelNumber y) const noexcept
{
- if (y < NumRows && x < NumCols)
+ if (y < numRows && x < numCols)
{
- const uint8_t * const p = image + ((y * (NumCols/8)) + (x/8));
+ const uint8_t * const p = image + ((y * (numCols/8)) + (x/8));
return (*p & (0x80u >> (x%8))) != 0;
}
return false;
}
-// Set the address to write to. The column address is in 16-bit words, so it ranges from 0 to 7.
-void Lcd7920::setGraphicsAddress(unsigned int r, unsigned int c) noexcept
-{
- sendLcdCommand(LcdSetGdramAddress | (r & 31));
- //commandDelay(); // don't seem to need this one
- sendLcdCommand(LcdSetGdramAddress | c | ((r & 32) >> 2));
- CommandDelay(); // we definitely need this one
-}
-
-// Send a command or data to the lcd. The SPI mutex is already owned
-void Lcd7920::sendLcd(uint8_t byteToSend, bool isData) noexcept
-{
- if (controllerType == 1) // if ST7567
- {
- digitalWrite(a0Pin, isData);
- uint8_t data[1] = { byteToSend };
- device.TransceivePacket(data, nullptr, 1);
- }
- else // ST7960
- {
- uint8_t data[3] = { (isData) ? (uint8_t)0xFA : (uint8_t)0xF8, (uint8_t)(byteToSend & 0xF0), (uint8_t)(byteToSend << 4) };
- device.TransceivePacket(data, nullptr, 3);
- }
-}
-
#endif
// End
diff --git a/src/Display/ST7920/lcd7920.h b/src/Display/Lcd/Lcd.h
index ba0d5164..c4e62af0 100644
--- a/src/Display/ST7920/lcd7920.h
+++ b/src/Display/Lcd/Lcd.h
@@ -1,11 +1,12 @@
-#ifndef LCD7920_H
-#define LCD7920_H
+#ifndef SRC_DISPLAY_LCD_LCD_H
+#define SRC_DISPLAY_LCD_LCD_H
#include "RepRapFirmware.h"
#if SUPPORT_12864_LCD
#include <Print.h>
+#include "Fonts/LcdFont.h"
#include <Hardware/SharedSpi/SharedSpiClient.h>
// Enumeration for specifying drawing modes
@@ -16,38 +17,27 @@ enum class PixelMode : uint8_t
PixelFlip = 2 // invert the pixel(s)
};
-// Struct for describing a font table, always held in PROGMEM
-struct LcdFont
-{
- const uint8_t *ptr; // pointer to font table
- uint16_t startCharacter; // Unicode code point of the first character in the font
- uint16_t endCharacter; // Unicode code point of the last character in the font
- uint8_t height; // row height in pixels - only this number of pixels will be fetched and drawn - maximum 16 in this version of the software
- uint8_t width; // max character width in pixels (the font table contains this number of bytes or words per character, plus 1 for the active width)
- uint8_t numSpaces; // number of space columns between characters before kerning
-};
-
typedef uint8_t PixelNumber;
-const PixelNumber NumRows = 64, NumCols = 128;
// Class for driving 128x64 graphical LCD fitted with ST7920 controller
// This drives the GLCD in serial mode so that it needs just 2 pins.
// Derive the LCD class from the Print class so that we can print stuff to it in alpha mode
-class Lcd7920 : public Print
+class Lcd : public Print
{
public:
// Construct a GLCD driver.
- Lcd7920(const LcdFont * const fnts[], size_t nFonts) noexcept;
+ Lcd(PixelNumber nr, PixelNumber nc, const LcdFont * const fnts[], size_t nFonts) noexcept;
+ virtual ~Lcd();
// Initialize the display
- void Init(uint8_t p_controllerType, Pin csPin, Pin p_a0Pin, uint32_t freq) noexcept;
+ void Init(Pin csPin, Pin p_a0Pin, bool csPolarity, uint32_t freq) noexcept;
// Select the font to use for subsequent calls to write() in graphics mode
void SetFont(size_t newFont) noexcept;
- constexpr PixelNumber GetNumRows() const noexcept { return NumRows; }
- constexpr PixelNumber GetNumCols() const noexcept { return NumCols; }
+ const PixelNumber GetNumRows() const noexcept { return numRows; }
+ const PixelNumber GetNumCols() const noexcept { return numCols; }
// Write a single character in the current font. Called by the 'print' functions.
// c = character to write
@@ -69,8 +59,14 @@ public:
// Select normal or inverted text (only works in graphics mode)
void TextInvert(bool b) noexcept;
- // Clear the display and select non-inverted text.
- void Clear(PixelNumber top = 0, PixelNumber left = 0, PixelNumber bottom = NumRows, PixelNumber right = NumCols) noexcept;
+ // Clear part of the display and select non-inverted text.
+ void Clear(PixelNumber top, PixelNumber left, PixelNumber bottom, PixelNumber right) noexcept;
+
+ // Clear the whole display and select non-inverted text.
+ void Clear() noexcept
+ {
+ Clear(0, 0, numRows, numCols);
+ }
// Set the cursor position
// r = row, the number of pixels from the top of the display to the top of the character.
@@ -96,7 +92,7 @@ public:
void FlushAll() noexcept;
// Flush just some data, returning true if this needs to be called again
- bool FlushSome() noexcept;
+ virtual bool FlushSome() noexcept = 0;
// Set, clear or invert a pixel
// x = x-coordinate of the pixel, measured from left hand edge of the display
@@ -138,36 +134,35 @@ public:
// data = bitmap image, must be ((width + 7)/8) bytes long
void BitmapRow(PixelNumber top, PixelNumber left, PixelNumber width, const uint8_t data[], bool invert) noexcept;
-private:
+protected:
const LcdFont * const *fonts;
const size_t numFonts;
size_t currentFontNumber; // index of the current font
uint32_t charVal;
+ size_t imageSize;
+ uint8_t *image; // image buffer
SharedSpiClient device;
uint16_t lastCharColData; // data for the last non-space column, used for kerning
- uint8_t controllerType;
+ const PixelNumber numRows, numCols;
Pin a0Pin;
uint8_t numContinuationBytesLeft;
PixelNumber row, column;
PixelNumber startRow, startCol, endRow, endCol; // coordinates of the dirty rectangle
PixelNumber nextFlushRow; // which row we need to flush next
PixelNumber leftMargin, rightMargin;
- uint8_t image[(NumRows * NumCols)/8]; // image buffer, 1K in size
bool textInverted;
bool justSetCursor;
- void sendLcdCommand(uint8_t command) noexcept { sendLcd(command, false); }
- void sendLcdData(uint8_t data) noexcept { sendLcd(data, true); }
- void sendLcd(uint8_t byteToSend, bool isData) noexcept;
-
- void CommandDelay() noexcept;
- void DataDelay() noexcept;
+ virtual void HardwareInit() noexcept = 0;
+ virtual void CommandDelay() noexcept = 0;
+ virtual void DataDelay() noexcept = 0;
+ virtual void SendLcdCommand(uint8_t byteToSend) noexcept = 0;
+ virtual void SendLcdData(uint8_t byteToSend) noexcept = 0;
- void setGraphicsAddress(unsigned int r, unsigned int c) noexcept;
size_t writeNative(uint16_t c) noexcept; // write a decoded character
void SetDirty(PixelNumber r, PixelNumber c) noexcept;
};
#endif
-#endif
+#endif // SRC_DISPLAY_LCD_LCD_H
diff --git a/src/Display/Lcd/ST7567/Lcd7567.cpp b/src/Display/Lcd/ST7567/Lcd7567.cpp
new file mode 100644
index 00000000..af8085cd
--- /dev/null
+++ b/src/Display/Lcd/ST7567/Lcd7567.cpp
@@ -0,0 +1,56 @@
+/*
+ * Lcd7567.cpp
+ *
+ * Created on: 15 Jul 2020
+ * Author: David
+ */
+
+#include "Lcd7567.h"
+
+#if SUPPORT_12864_LCD
+
+Lcd7567::Lcd7567(const LcdFont * const fnts[], size_t nFonts) noexcept
+ : Lcd(128, 64, fnts, nFonts)
+{
+}
+
+// Flush just some data, returning true if this needs to be called again
+bool Lcd7567::FlushSome() noexcept
+{
+ //TODO
+ return true;
+}
+
+void Lcd7567::HardwareInit() noexcept
+{
+ pinMode(a0Pin, OUTPUT_HIGH);
+ //TODO
+}
+
+void Lcd7567::CommandDelay() noexcept
+{
+ //TODO
+}
+
+void Lcd7567::DataDelay() noexcept
+{
+ //TODO
+}
+
+void Lcd7567::SendLcdCommand(uint8_t byteToSend) noexcept
+{
+ digitalWrite(a0Pin, false);
+ uint8_t data[1] = { byteToSend };
+ device.TransceivePacket(data, nullptr, 1);
+}
+
+void Lcd7567::SendLcdData(uint8_t byteToSend) noexcept
+{
+ digitalWrite(a0Pin, true);
+ uint8_t data[1] = { byteToSend };
+ device.TransceivePacket(data, nullptr, 1);
+}
+
+#endif
+
+// End
diff --git a/src/Display/Lcd/ST7567/Lcd7567.h b/src/Display/Lcd/ST7567/Lcd7567.h
new file mode 100644
index 00000000..a5532d72
--- /dev/null
+++ b/src/Display/Lcd/ST7567/Lcd7567.h
@@ -0,0 +1,38 @@
+/*
+ * Lcd7567.h
+ *
+ * Created on: 15 Jul 2020
+ * Author: David
+ */
+
+#ifndef SRC_DISPLAY_LCD_ST7567_LCD7567_H_
+#define SRC_DISPLAY_LCD_ST7567_LCD7567_H_
+
+#include "RepRapFirmware.h"
+
+#if SUPPORT_12864_LCD
+
+#include <Display/Lcd/Lcd.h>
+
+class Lcd7567 : public Lcd
+{
+public:
+ // Construct a GLCD driver.
+ Lcd7567(const LcdFont * const fnts[], size_t nFonts) noexcept;
+
+ // Flush just some data, returning true if this needs to be called again
+ bool FlushSome() noexcept override;
+
+protected:
+ void HardwareInit() noexcept override;
+ void CommandDelay() noexcept override;
+ void DataDelay() noexcept override;
+ void SendLcdCommand(uint8_t byteToSend) noexcept override;
+ void SendLcdData(uint8_t byteToSend) noexcept override;
+
+private:
+};
+
+#endif
+
+#endif /* SRC_DISPLAY_LCD_ST7567_LCD7567_H_ */
diff --git a/src/Display/Lcd/ST7920/Lcd7920.cpp b/src/Display/Lcd/ST7920/Lcd7920.cpp
new file mode 100644
index 00000000..a2054739
--- /dev/null
+++ b/src/Display/Lcd/ST7920/Lcd7920.cpp
@@ -0,0 +1,144 @@
+// Driver for 128x64 graphical LCD with ST7920 controller
+// D Crocker, Escher Technologies Ltd.
+
+#include "Lcd7920.h"
+
+#if SUPPORT_12864_LCD
+
+#include "Pins.h"
+
+// LCD basic instructions. These all take 72us to execute except LcdDisplayClear, which takes 1.6ms
+constexpr uint8_t LcdDisplayClear = 0x01;
+constexpr uint8_t LcdHome = 0x02;
+constexpr uint8_t LcdEntryModeSet = 0x06; // move cursor right and increment address when writing data
+constexpr uint8_t LcdDisplayOff = 0x08;
+constexpr uint8_t LcdDisplayOn = 0x0C; // add 0x02 for cursor on and/or 0x01 for cursor blink on
+constexpr uint8_t LcdFunctionSetBasicAlpha = 0x20;
+constexpr uint8_t LcdFunctionSetBasicGraphic = 0x22;
+constexpr uint8_t LcdFunctionSetExtendedAlpha = 0x24;
+constexpr uint8_t LcdFunctionSetExtendedGraphic = 0x26;
+constexpr uint8_t LcdSetDdramAddress = 0x80; // add the address we want to set
+
+// LCD extended instructions
+constexpr uint8_t LcdSetGdramAddress = 0x80;
+
+constexpr unsigned int LcdCommandDelayMicros = 72 - 8; // 72us required, less 7us time to send the command @ 2.0MHz
+constexpr unsigned int LcdDataDelayMicros = 4; // delay between sending data bytes
+constexpr unsigned int LcdDisplayClearDelayMillis = 3; // 1.6ms should be enough
+
+Lcd7920::Lcd7920(const LcdFont * const fnts[], size_t nFonts) noexcept
+ : Lcd(64, 128, fnts, nFonts)
+{
+}
+
+void Lcd7920::HardwareInit() noexcept
+{
+ device.Select();
+ delayMicroseconds(1);
+ SendLcdCommand(LcdFunctionSetBasicAlpha);
+ delay(2);
+ SendLcdCommand(LcdFunctionSetBasicAlpha);
+ CommandDelay();
+ SendLcdCommand(LcdEntryModeSet);
+ CommandDelay();
+ SendLcdCommand(LcdDisplayClear); // need this on some displays to ensure that the alpha RAM is clear (M3D Kanji problem)
+ delay(LcdDisplayClearDelayMillis);
+ SendLcdCommand(LcdFunctionSetExtendedGraphic);
+ CommandDelay();
+ device.Deselect();
+
+ Clear();
+ FlushAll();
+
+ device.Select();
+ delayMicroseconds(1);
+ SendLcdCommand(LcdDisplayOn);
+ CommandDelay();
+ device.Deselect();
+}
+
+void Lcd7920::CommandDelay() noexcept
+{
+ delayMicroseconds(LcdCommandDelayMicros);
+}
+
+void Lcd7920::DataDelay() noexcept
+{
+ delayMicroseconds(LcdDataDelayMicros);
+}
+
+// Flush some of the dirty part of the image to the LCD, returning true if there is more to do
+bool Lcd7920::FlushSome() noexcept
+{
+ // See if there is anything to flush
+ if (endCol > startCol && endRow > startRow)
+ {
+ // Decide which row to flush next
+ if (nextFlushRow < startRow || nextFlushRow >= endRow)
+ {
+ nextFlushRow = startRow; // start from the beginning
+ }
+
+ if (nextFlushRow == startRow) // if we are starting form the beginning
+ {
+ ++startRow; // flag this row as flushed because it will be soon
+ }
+
+ // Flush that row
+ {
+ uint8_t startColNum = startCol/16;
+ const uint8_t endColNum = (endCol + 15)/16;
+// debugPrintf("flush %u %u %u\n", nextFlushRow, startColNum, endColNum);
+
+ device.Select();
+ delayMicroseconds(1);
+
+ SetGraphicsAddress(nextFlushRow, startColNum);
+ uint8_t *ptr = image + (((numCols/8) * nextFlushRow) + (2 * startColNum));
+ while (startColNum < endColNum)
+ {
+ SendLcdData(*ptr++);
+ SendLcdData(*ptr++);
+ ++startColNum;
+ DataDelay();
+ }
+ device.Deselect();
+ }
+
+ if (startRow != endRow)
+ {
+ ++nextFlushRow;
+ return true;
+ }
+
+ startRow = numRows;
+ startCol = numCols;
+ endCol = endRow = nextFlushRow = 0;
+ }
+ return false;
+}
+
+// Set the address to write to. The column address is in 16-bit words, so it ranges from 0 to 7.
+void Lcd7920::SetGraphicsAddress(unsigned int r, unsigned int c) noexcept
+{
+ SendLcdCommand(LcdSetGdramAddress | (r & 31));
+ //commandDelay(); // don't seem to need this one
+ SendLcdCommand(LcdSetGdramAddress | c | ((r & 32) >> 2));
+ CommandDelay(); // we definitely need this one
+}
+
+void Lcd7920::SendLcdCommand(uint8_t byteToSend) noexcept
+{
+ uint8_t data[3] = { (uint8_t)0xF8, (uint8_t)(byteToSend & 0xF0), (uint8_t)(byteToSend << 4) };
+ device.TransceivePacket(data, nullptr, 3);
+}
+
+void Lcd7920::SendLcdData(uint8_t byteToSend) noexcept
+{
+ uint8_t data[3] = { (uint8_t)0xFA, (uint8_t)(byteToSend & 0xF0), (uint8_t)(byteToSend << 4) };
+ device.TransceivePacket(data, nullptr, 3);
+}
+
+#endif
+
+// End
diff --git a/src/Display/Lcd/ST7920/Lcd7920.h b/src/Display/Lcd/ST7920/Lcd7920.h
new file mode 100644
index 00000000..c1dbf480
--- /dev/null
+++ b/src/Display/Lcd/ST7920/Lcd7920.h
@@ -0,0 +1,36 @@
+#ifndef LCD7920_H
+#define LCD7920_H
+
+#include "RepRapFirmware.h"
+
+#if SUPPORT_12864_LCD
+
+#include <Display/Lcd/Lcd.h>
+
+// Class for driving 128x64 graphical LCD fitted with ST7920 controller
+// This drives the GLCD in serial mode so that it needs just 2 pins.
+
+// Derive the LCD class from the Print class so that we can print stuff to it in alpha mode
+class Lcd7920 : public Lcd
+{
+public:
+ // Construct a GLCD driver.
+ Lcd7920(const LcdFont * const fnts[], size_t nFonts) noexcept;
+
+ // Flush just some data, returning true if this needs to be called again
+ bool FlushSome() noexcept override;
+
+protected:
+ void HardwareInit() noexcept override;
+ void CommandDelay() noexcept override;
+ void DataDelay() noexcept override;
+ void SendLcdCommand(uint8_t byteToSend) noexcept override;
+ void SendLcdData(uint8_t byteToSend) noexcept override;
+
+private:
+ void SetGraphicsAddress(unsigned int r, unsigned int c) noexcept;
+};
+
+#endif
+
+#endif
diff --git a/src/Display/Menu.cpp b/src/Display/Menu.cpp
index 6a707800..0787355e 100644
--- a/src/Display/Menu.cpp
+++ b/src/Display/Menu.cpp
@@ -69,7 +69,7 @@
#if SUPPORT_12864_LCD
-#include "ST7920/lcd7920.h"
+#include "Lcd/Lcd.h"
#include "RepRap.h"
#include "Platform.h"
#include "Display/Display.h"
@@ -81,7 +81,7 @@
const uint32_t InactivityTimeout = 20000; // inactivity timeout
const uint32_t ErrorTimeout = 6000; // how long we display an error message for
-Menu::Menu(Lcd7920& refLcd) noexcept
+Menu::Menu(Lcd& refLcd) noexcept
: lcd(refLcd),
timeoutValue(0), lastActionTime(0),
selectableItems(nullptr), unSelectableItems(nullptr), highlightedItem(nullptr), numNestedMenus(0),
@@ -110,7 +110,7 @@ void Menu::LoadFixedMenu() noexcept
lcd.Clear();
// Instead of Reload():
- lcd.SetRightMargin(NumCols - currentMargin);
+ lcd.SetRightMargin(lcd.GetNumCols() - currentMargin);
ResetCache();
@@ -149,12 +149,13 @@ void Menu::DisplayMessageBox(const MessageBox& mbox) noexcept
const PixelNumber sideMargin = 4;
// Draw and a box and clear the interior
- lcd.SetRightMargin(NumCols);
- lcd.Line(topBottomMargin, sideMargin, topBottomMargin, NumCols - sideMargin - 1, PixelMode::PixelSet);
- lcd.Line(topBottomMargin, NumCols - sideMargin - 1, NumRows - topBottomMargin - 1, NumCols - sideMargin - 1, PixelMode::PixelSet);
- lcd.Line(NumRows - topBottomMargin - 1, sideMargin, NumRows - topBottomMargin - 1, NumCols - sideMargin - 1, PixelMode::PixelSet);
- lcd.Line(topBottomMargin, sideMargin, NumRows - topBottomMargin - 1, sideMargin, PixelMode::PixelSet);
- lcd.Clear(topBottomMargin + 1, sideMargin + 1, NumRows - topBottomMargin - 1, NumCols - sideMargin - 1);
+ const PixelNumber nr = lcd.GetNumRows(), nc = lcd.GetNumCols();
+ lcd.SetRightMargin(nc);
+ lcd.Line(topBottomMargin, sideMargin, topBottomMargin, nc - sideMargin - 1, PixelMode::PixelSet);
+ lcd.Line(topBottomMargin, nc - sideMargin - 1, nr - topBottomMargin - 1, nc - sideMargin - 1, PixelMode::PixelSet);
+ lcd.Line(nr - topBottomMargin - 1, sideMargin, nr - topBottomMargin - 1, nc - sideMargin - 1, PixelMode::PixelSet);
+ lcd.Line(topBottomMargin, sideMargin, nr - topBottomMargin - 1, sideMargin, PixelMode::PixelSet);
+ lcd.Clear(topBottomMargin + 1, sideMargin + 1, nr - topBottomMargin - 1, nc - sideMargin - 1);
// We could draw the static text directly, but it is easier to use the existing classes
const uint8_t fontToUse = 0;
@@ -162,7 +163,7 @@ void Menu::DisplayMessageBox(const MessageBox& mbox) noexcept
const PixelNumber rowHeight = lcd.GetFontHeight(fontToUse) + 1;
const PixelNumber top = topBottomMargin + 1 + insideMargin;
const PixelNumber left = sideMargin + 1 + insideMargin;
- const PixelNumber right = NumCols - left;
+ const PixelNumber right = nc - left;
const PixelNumber availableWidth = right - left;
AddItem(new TextMenuItem(top, left, availableWidth, MenuItem::CentreAlign, fontToUse, MenuItem::AlwaysVisible, mbox.title.c_str()), false);
AddItem(new TextMenuItem(top + rowHeight, left, availableWidth, MenuItem::CentreAlign, fontToUse, MenuItem::AlwaysVisible, mbox.message.c_str()), false); // only 1 row for now
@@ -393,7 +394,7 @@ const char *Menu::ParseMenuLine(char * const commandWord) noexcept
const char * const actionString = AppendString(action);
const char *const dir = AppendString(dirpath);
const char *const acFileString = AppendString(fname);
- AddItem(new FilesMenuItem(row, 0, NumCols, fontNumber, xVis, actionString, dir, acFileString, nparam), true);
+ AddItem(new FilesMenuItem(row, 0, lcd.GetNumCols(), fontNumber, xVis, actionString, dir, acFileString, nparam), true);
row += nparam * lcd.GetFontHeight(fontNumber);
column = 0;
}
@@ -436,8 +437,8 @@ void Menu::Reload() noexcept
else
{
currentMargin = 0;
- const PixelNumber right = NumCols;
- const PixelNumber bottom = NumRows;
+ const PixelNumber right = lcd.GetNumCols();
+ const PixelNumber bottom = lcd.GetNumRows();
lcd.Clear(currentMargin, currentMargin, bottom, right);
// Draw the outline
@@ -452,7 +453,7 @@ void Menu::Reload() noexcept
ResetCache();
displayingErrorMessage = false;
- lcd.SetRightMargin(NumCols - currentMargin);
+ lcd.SetRightMargin(lcd.GetNumCols() - currentMargin);
const char * const fname = filenames[numNestedMenus - 1].c_str();
FileStore * const file = reprap.GetPlatform().OpenFile(MENU_DIR, fname, OpenMode::read);
if (file == nullptr)
@@ -698,7 +699,7 @@ void Menu::DrawAll() noexcept
}
// Now draw items
- const PixelNumber rightMargin = NumCols - currentMargin;
+ const PixelNumber rightMargin = lcd.GetNumCols() - currentMargin;
for (MenuItem *item = selectableItems; item != nullptr; item = item->GetNext())
{
item->Draw(lcd, rightMargin, (item == highlightedItem), rowOffset);
diff --git a/src/Display/Menu.h b/src/Display/Menu.h
index 27ae884b..02d64a1a 100644
--- a/src/Display/Menu.h
+++ b/src/Display/Menu.h
@@ -21,7 +21,7 @@ class MessageBox;
class Menu
{
public:
- Menu(Lcd7920& refLcd) noexcept;
+ Menu(Lcd& refLcd) noexcept;
void Load(const char* filename) noexcept; // load a menu file
void Pop() noexcept;
void EncoderAction(int action) noexcept;
@@ -63,7 +63,7 @@ private:
static const PixelNumber InnerMargin = 2; // how many pixels we keep clear inside the border
static const PixelNumber OuterMargin = 8 + InnerMargin; // how many pixels of the previous menu we leave on each side
- Lcd7920& lcd;
+ Lcd& lcd;
uint32_t timeoutValue; // how long to time out after 0 = no timeout
uint32_t lastActionTime;
diff --git a/src/Display/MenuItem.cpp b/src/Display/MenuItem.cpp
index 0fc25b9e..bfc9b9e2 100644
--- a/src/Display/MenuItem.cpp
+++ b/src/Display/MenuItem.cpp
@@ -40,7 +40,7 @@ MenuItem::MenuItem(PixelNumber r, PixelNumber c, PixelNumber w, Alignment a, Fon
}
// Print the item at the correct place with the correct alignment
-void MenuItem::PrintAligned(Lcd7920& lcd, PixelNumber tOffset, PixelNumber rightMargin) noexcept
+void MenuItem::PrintAligned(Lcd& lcd, PixelNumber tOffset, PixelNumber rightMargin) noexcept
{
PixelNumber colsToSkip = 0;
lcd.SetFont(fontNumber);
@@ -97,7 +97,7 @@ bool MenuItem::IsVisible() const noexcept
}
// Erase this item if it is drawn but should not be visible
-void MenuItem::EraseIfInvisible(Lcd7920& lcd, PixelNumber tOffset) noexcept
+void MenuItem::EraseIfInvisible(Lcd& lcd, PixelNumber tOffset) noexcept
{
if (drawn && !IsVisible())
{
@@ -111,12 +111,12 @@ TextMenuItem::TextMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, Alignmen
{
}
-void TextMenuItem::CorePrint(Lcd7920& lcd) noexcept
+void TextMenuItem::CorePrint(Lcd& lcd) noexcept
{
lcd.print(text);
}
-void TextMenuItem::Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
+void TextMenuItem::Draw(Lcd& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
{
// We ignore the 'highlight' parameter because text items are not selectable
if (IsVisible() && (!drawn || itemChanged))
@@ -127,7 +127,7 @@ void TextMenuItem::Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, P
}
}
-void TextMenuItem::UpdateWidthAndHeight(Lcd7920& lcd) noexcept
+void TextMenuItem::UpdateWidthAndHeight(Lcd& lcd) noexcept
{
if (width == 0)
{
@@ -154,14 +154,14 @@ ButtonMenuItem::ButtonMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, Font
{
}
-void ButtonMenuItem::CorePrint(Lcd7920& lcd) noexcept
+void ButtonMenuItem::CorePrint(Lcd& lcd) noexcept
{
lcd.WriteSpaces(1); // space at start in case highlighted
lcd.print(text);
lcd.WriteSpaces(1); // space at end to allow for highlighting
}
-void ButtonMenuItem::Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
+void ButtonMenuItem::Draw(Lcd& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
{
if (IsVisible() && (itemChanged || !drawn || highlight != highlighted) && column < lcd.GetNumCols())
{
@@ -172,7 +172,7 @@ void ButtonMenuItem::Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight,
}
}
-void ButtonMenuItem::UpdateWidthAndHeight(Lcd7920& lcd) noexcept
+void ButtonMenuItem::UpdateWidthAndHeight(Lcd& lcd) noexcept
{
if (width == 0)
{
@@ -237,7 +237,7 @@ ValueMenuItem::ValueMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, Alignm
{
}
-void ValueMenuItem::CorePrint(Lcd7920& lcd) noexcept
+void ValueMenuItem::CorePrint(Lcd& lcd) noexcept
{
if (adjustable)
{
@@ -312,7 +312,7 @@ void ValueMenuItem::CorePrint(Lcd7920& lcd) noexcept
}
}
-void ValueMenuItem::Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
+void ValueMenuItem::Draw(Lcd& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
{
if (IsVisible())
{
@@ -501,7 +501,7 @@ bool ValueMenuItem::Select(const StringRef& cmd) noexcept
return false;
}
-void ValueMenuItem::UpdateWidthAndHeight(Lcd7920& lcd) noexcept
+void ValueMenuItem::UpdateWidthAndHeight(Lcd& lcd) noexcept
{
// The width is always set for a ValueMenuItem so we just need to determine the height
if (height == 0)
@@ -768,7 +768,7 @@ unsigned int FilesMenuItem::uListingEntries() const noexcept
return bInSubdirectory() ? (1 + m_uHardItemsInDirectory) : m_uHardItemsInDirectory;
}
-void FilesMenuItem::Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
+void FilesMenuItem::Draw(Lcd& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
{
// The 'highlight' parameter is not used to highlight this item, but it is still used to tell whether this item is selected or not
if (!IsVisible())
@@ -831,7 +831,7 @@ void FilesMenuItem::Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight,
}
}
-void FilesMenuItem::ListFiles(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
+void FilesMenuItem::ListFiles(Lcd& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
{
lcd.SetFont(fontNumber);
lcd.SetRightMargin(rightMargin);
@@ -1079,7 +1079,7 @@ bool FilesMenuItem::Select(const StringRef& cmd) noexcept
return false;
}
-void FilesMenuItem::UpdateWidthAndHeight(Lcd7920& lcd) noexcept
+void FilesMenuItem::UpdateWidthAndHeight(Lcd& lcd) noexcept
{
// The width is always set for a FilesMenuItem so we just need to determine the height
if (height == 0)
@@ -1106,7 +1106,7 @@ ImageMenuItem::ImageMenuItem(PixelNumber r, PixelNumber c, Visibility vis, const
fileName.copy(pFileName);
}
-void ImageMenuItem::Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
+void ImageMenuItem::Draw(Lcd& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept
{
if (IsVisible() && (!drawn || itemChanged || highlight != highlighted))
{
@@ -1140,7 +1140,7 @@ void ImageMenuItem::Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight,
}
}
-void ImageMenuItem::UpdateWidthAndHeight(Lcd7920& lcd) noexcept
+void ImageMenuItem::UpdateWidthAndHeight(Lcd& lcd) noexcept
{
if (width == 0 || height == 0)
{
diff --git a/src/Display/MenuItem.h b/src/Display/MenuItem.h
index 02f72dc6..cdd754f3 100644
--- a/src/Display/MenuItem.h
+++ b/src/Display/MenuItem.h
@@ -13,7 +13,7 @@
#if SUPPORT_12864_LCD
#include "General/FreelistManager.h"
-#include "ST7920/lcd7920.h"
+#include "Lcd/Lcd.h"
#include "Storage/MassStorage.h"
// Menu item class hierarchy
@@ -28,7 +28,7 @@ public:
static constexpr Visibility AlwaysVisible = 0;
// Draw this element on the LCD respecting 'maxWidth' and 'highlight'
- virtual void Draw(Lcd7920& lcd, PixelNumber maxWidth, bool highlight, PixelNumber tOffset) noexcept = 0;
+ virtual void Draw(Lcd& lcd, PixelNumber maxWidth, bool highlight, PixelNumber tOffset) noexcept = 0;
// Select this element with a push of the encoder.
// If it returns nullptr false go into adjustment mode, if we can adjust the item.
@@ -50,7 +50,7 @@ public:
virtual bool Adjust(int clicks) noexcept { return true; }
// If the width was specified as zero, update it with the actual width. Also update the height.
- virtual void UpdateWidthAndHeight(Lcd7920& lcd) noexcept = 0;
+ virtual void UpdateWidthAndHeight(Lcd& lcd) noexcept = 0;
// DC: I don't know what this one is for, the person who wrote it didn't document it
virtual PixelNumber GetVisibilityRowOffset(PixelNumber tCurrentOffset, PixelNumber fontHeight) const noexcept { return 0; }
@@ -63,7 +63,7 @@ public:
bool IsVisible() const noexcept;
// Erase this item if it is drawn but should not be visible
- void EraseIfInvisible(Lcd7920& lcd, PixelNumber tOffset) noexcept;
+ void EraseIfInvisible(Lcd& lcd, PixelNumber tOffset) noexcept;
// Return the width of this item in pixels
PixelNumber GetWidth() const noexcept { return width; }
@@ -76,10 +76,10 @@ protected:
// Print the item starting at the current cursor position, which may be off screen. Used to find the width and also to really print the item.
// Overridden for items that support variable alignment
- virtual void CorePrint(Lcd7920& lcd) noexcept { }
+ virtual void CorePrint(Lcd& lcd) noexcept { }
// Print the item at the correct place with the correct alignment
- void PrintAligned(Lcd7920& lcd, PixelNumber tOffset, PixelNumber rightMargin) noexcept;
+ void PrintAligned(Lcd& lcd, PixelNumber tOffset, PixelNumber rightMargin) noexcept;
const PixelNumber row, column;
PixelNumber width, height;
@@ -102,11 +102,11 @@ public:
void operator delete(void* p) noexcept { FreelistManager::Release<TextMenuItem>(p); }
TextMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, Alignment a, FontNumber fn, Visibility vis, const char *t) noexcept;
- void Draw(Lcd7920& lcd, PixelNumber maxWidth, bool highlight, PixelNumber tOffset) noexcept override;
- void UpdateWidthAndHeight(Lcd7920& lcd) noexcept override;
+ void Draw(Lcd& lcd, PixelNumber maxWidth, bool highlight, PixelNumber tOffset) noexcept override;
+ void UpdateWidthAndHeight(Lcd& lcd) noexcept override;
protected:
- void CorePrint(Lcd7920& lcd) noexcept override;
+ void CorePrint(Lcd& lcd) noexcept override;
private:
const char *text;
@@ -119,14 +119,14 @@ public:
void operator delete(void* p) noexcept { FreelistManager::Release<ButtonMenuItem>(p); }
ButtonMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, FontNumber fn, Visibility vis, const char *t, const char *cmd, const char *acFile) noexcept;
- void Draw(Lcd7920& lcd, PixelNumber maxWidth, bool highlight, PixelNumber tOffset) noexcept override;
- void UpdateWidthAndHeight(Lcd7920& lcd) noexcept override;
+ void Draw(Lcd& lcd, PixelNumber maxWidth, bool highlight, PixelNumber tOffset) noexcept override;
+ void UpdateWidthAndHeight(Lcd& lcd) noexcept override;
bool Select(const StringRef& cmd) noexcept override;
PixelNumber GetVisibilityRowOffset(PixelNumber tCurrentOffset, PixelNumber fontHeight) const noexcept override;
protected:
- void CorePrint(Lcd7920& lcd) noexcept override;
+ void CorePrint(Lcd& lcd) noexcept override;
private:
const char *text;
@@ -141,18 +141,18 @@ public:
void operator delete(void* p) noexcept { FreelistManager::Release<ValueMenuItem>(p); }
ValueMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, Alignment a, FontNumber fn, Visibility vis, bool adj, unsigned int v, unsigned int d) noexcept;
- void Draw(Lcd7920& lcd, PixelNumber maxWidth, bool highlight, PixelNumber tOffset) noexcept override;
+ void Draw(Lcd& lcd, PixelNumber maxWidth, bool highlight, PixelNumber tOffset) noexcept override;
bool Select(const StringRef& cmd) noexcept override;
bool CanAdjust() const noexcept override { return true; }
bool Adjust(int clicks) noexcept override;
- void UpdateWidthAndHeight(Lcd7920& lcd) noexcept override;
+ void UpdateWidthAndHeight(Lcd& lcd) noexcept override;
PixelNumber GetVisibilityRowOffset(PixelNumber tCurrentOffset, PixelNumber fontHeight) const noexcept override;
unsigned int GetReferencedToolNumber() const noexcept;
protected:
- void CorePrint(Lcd7920& lcd) noexcept override;
+ void CorePrint(Lcd& lcd) noexcept override;
private:
enum class AdjustMode : uint8_t { displaying, adjusting, liveAdjusting };
@@ -188,11 +188,11 @@ public:
void operator delete(void* p) noexcept { FreelistManager::Release<FilesMenuItem>(p); }
FilesMenuItem(PixelNumber r, PixelNumber c, PixelNumber w, FontNumber fn, Visibility vis, const char *cmd, const char *dir, const char *acFile, unsigned int nf) noexcept;
- void Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept override;
+ void Draw(Lcd& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept override;
void Enter(bool bForwardDirection) noexcept override;
int Advance(int nCounts) noexcept override;
bool Select(const StringRef& cmd) noexcept override;
- void UpdateWidthAndHeight(Lcd7920& lcd) noexcept override;
+ void UpdateWidthAndHeight(Lcd& lcd) noexcept override;
PixelNumber GetVisibilityRowOffset(PixelNumber tCurrentOffset, PixelNumber fontHeight) const noexcept override;
@@ -202,7 +202,7 @@ protected:
void vResetViewState() noexcept;
private:
- void ListFiles(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept;
+ void ListFiles(Lcd& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept;
uint8_t GetDirectoryNesting() const noexcept;
const unsigned int numDisplayLines;
@@ -236,8 +236,8 @@ public:
ImageMenuItem(PixelNumber r, PixelNumber c, Visibility vis, const char *pFileName) noexcept;
- void Draw(Lcd7920& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept override;
- void UpdateWidthAndHeight(Lcd7920& lcd) noexcept override;
+ void Draw(Lcd& lcd, PixelNumber rightMargin, bool highlight, PixelNumber tOffset) noexcept override;
+ void UpdateWidthAndHeight(Lcd& lcd) noexcept override;
private:
String<MaxFilenameLength> fileName;
diff --git a/src/GCodes/GCodeBuffer/BinaryParser.cpp b/src/GCodes/GCodeBuffer/BinaryParser.cpp
index f6423ae2..980f2e6f 100644
--- a/src/GCodes/GCodeBuffer/BinaryParser.cpp
+++ b/src/GCodes/GCodeBuffer/BinaryParser.cpp
@@ -219,6 +219,18 @@ uint32_t BinaryParser::GetUIValue() THROWS(GCodeException)
return value;
}
+void BinaryParser::SetDriverIdFromBinary(DriverId& did, uint32_t val) THROWS(GCodeException)
+{
+#if SUPPORT_CAN_EXPANSION
+ did.SetFromBinary(val);
+#else
+ if (did.SetFromBinary(val))
+ {
+ throw ConstructParseException("Board address of driver must be 0");
+ }
+#endif
+}
+
// Get a driver ID
DriverId BinaryParser::GetDriverId() THROWS(GCodeException)
{
@@ -233,7 +245,7 @@ DriverId BinaryParser::GetDriverId() THROWS(GCodeException)
case DataType::Int:
case DataType::UInt:
case DataType::DriverId:
- value.SetFromBinary(seenParameter->uintValue);
+ SetDriverIdFromBinary(value, seenParameter->uintValue);
break;
default:
@@ -462,7 +474,7 @@ void BinaryParser::GetDriverIdArray(DriverId arr[], size_t& length) THROWS(GCode
case DataType::Int:
case DataType::UInt:
case DataType::DriverId:
- arr[0].SetFromBinary(seenParameter->uintValue);
+ SetDriverIdFromBinary(arr[0], seenParameter->uintValue);
length = 1;
break;
@@ -472,7 +484,7 @@ void BinaryParser::GetDriverIdArray(DriverId arr[], size_t& length) THROWS(GCode
CheckArrayLength(length);
for (int i = 0; i < seenParameter->intValue; i++)
{
- arr[i].SetFromBinary(reinterpret_cast<const uint32_t*>(seenParameterValue)[i]);
+ SetDriverIdFromBinary(arr[i], reinterpret_cast<const uint32_t*>(seenParameterValue)[i]);
}
length = seenParameter->intValue;
break;
diff --git a/src/GCodes/GCodeBuffer/BinaryParser.h b/src/GCodes/GCodeBuffer/BinaryParser.h
index 3320fb28..897a5c7a 100644
--- a/src/GCodes/GCodeBuffer/BinaryParser.h
+++ b/src/GCodes/GCodeBuffer/BinaryParser.h
@@ -64,6 +64,7 @@ private:
GCodeBuffer& gb;
void CheckArrayLength(size_t maxLength) THROWS(GCodeException);
+ void SetDriverIdFromBinary(DriverId& did, uint32_t val) THROWS(GCodeException);
GCodeException ConstructParseException(const char *str) const noexcept;
GCodeException ConstructParseException(const char *str, const char *param) const noexcept;
GCodeException ConstructParseException(const char *str, uint32_t param) const noexcept;
diff --git a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp
index e6d4de9e..c1bf3e8d 100644
--- a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp
+++ b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp
@@ -302,7 +302,7 @@ bool GCodeBuffer::Seen(char c) noexcept
}
// Test for character present, throw error if not
-void GCodeBuffer::MustSee(char c)
+void GCodeBuffer::MustSee(char c) THROWS(GCodeException)
{
if (!Seen(c))
{
@@ -311,19 +311,19 @@ void GCodeBuffer::MustSee(char c)
}
// Get a float after a key letter
-float GCodeBuffer::GetFValue()
+float GCodeBuffer::GetFValue() THROWS(GCodeException)
{
return PARSER_OPERATION(GetFValue());
}
// Get a distance or coordinate and convert it from inches to mm if necessary
-float GCodeBuffer::GetDistance()
+float GCodeBuffer::GetDistance() THROWS(GCodeException)
{
return ConvertDistance(GetFValue());
}
// Get an integer after a key letter
-int32_t GCodeBuffer::GetIValue()
+int32_t GCodeBuffer::GetIValue() THROWS(GCodeException)
{
return PARSER_OPERATION(GetIValue());
}
@@ -345,7 +345,7 @@ int32_t GCodeBuffer::GetLimitedIValue(char c, int32_t minValue, int32_t maxValue
}
// Get an unsigned integer value
-uint32_t GCodeBuffer::GetUIValue()
+uint32_t GCodeBuffer::GetUIValue() THROWS(GCodeException)
{
return PARSER_OPERATION(GetUIValue());
}
@@ -363,54 +363,54 @@ uint32_t GCodeBuffer::GetLimitedUIValue(char c, uint32_t maxValuePlusOne) THROWS
}
// Get an IP address quad after a key letter
-void GCodeBuffer::GetIPAddress(IPAddress& returnedIp)
+void GCodeBuffer::GetIPAddress(IPAddress& returnedIp) THROWS(GCodeException)
{
PARSER_OPERATION(GetIPAddress(returnedIp));
}
// Get a MAC address sextet after a key letter
-void GCodeBuffer::GetMacAddress(MacAddress& mac)
+void GCodeBuffer::GetMacAddress(MacAddress& mac) THROWS(GCodeException)
{
PARSER_OPERATION(GetMacAddress(mac));
}
// Get a string with no preceding key letter
-void GCodeBuffer::GetUnprecedentedString(const StringRef& str, bool allowEmpty)
+void GCodeBuffer::GetUnprecedentedString(const StringRef& str, bool allowEmpty) THROWS(GCodeException)
{
PARSER_OPERATION(GetUnprecedentedString(str, allowEmpty));
}
// Get and copy a quoted string
-void GCodeBuffer::GetQuotedString(const StringRef& str)
+void GCodeBuffer::GetQuotedString(const StringRef& str) THROWS(GCodeException)
{
PARSER_OPERATION(GetQuotedString(str));
}
// Get and copy a string which may or may not be quoted
-void GCodeBuffer::GetPossiblyQuotedString(const StringRef& str)
+void GCodeBuffer::GetPossiblyQuotedString(const StringRef& str) THROWS(GCodeException)
{
PARSER_OPERATION(GetPossiblyQuotedString(str));
}
-void GCodeBuffer::GetReducedString(const StringRef& str)
+void GCodeBuffer::GetReducedString(const StringRef& str) THROWS(GCodeException)
{
PARSER_OPERATION(GetReducedString(str));
}
// Get a colon-separated list of floats after a key letter
-void GCodeBuffer::GetFloatArray(float arr[], size_t& length, bool doPad)
+void GCodeBuffer::GetFloatArray(float arr[], size_t& length, bool doPad) THROWS(GCodeException)
{
PARSER_OPERATION(GetFloatArray(arr, length, doPad));
}
// Get a :-separated list of ints after a key letter
-void GCodeBuffer::GetIntArray(int32_t arr[], size_t& length, bool doPad)
+void GCodeBuffer::GetIntArray(int32_t arr[], size_t& length, bool doPad) THROWS(GCodeException)
{
PARSER_OPERATION(GetIntArray(arr, length, doPad));
}
// Get a :-separated list of unsigned ints after a key letter
-void GCodeBuffer::GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad)
+void GCodeBuffer::GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad) THROWS(GCodeException)
{
PARSER_OPERATION(GetUnsignedArray(arr, length, doPad));
}
@@ -422,7 +422,7 @@ void GCodeBuffer::GetDriverIdArray(DriverId arr[], size_t& length)
}
// If the specified parameter character is found, fetch 'value' and set 'seen'. Otherwise leave val and seen alone.
-bool GCodeBuffer::TryGetFValue(char c, float& val, bool& seen)
+bool GCodeBuffer::TryGetFValue(char c, float& val, bool& seen) THROWS(GCodeException)
{
const bool ret = Seen(c);
if (ret)
@@ -434,7 +434,7 @@ bool GCodeBuffer::TryGetFValue(char c, float& val, bool& seen)
}
// If the specified parameter character is found, fetch 'value' and set 'seen'. Otherwise leave val and seen alone.
-bool GCodeBuffer::TryGetIValue(char c, int32_t& val, bool& seen)
+bool GCodeBuffer::TryGetIValue(char c, int32_t& val, bool& seen) THROWS(GCodeException)
{
const bool ret = Seen(c);
if (ret)
@@ -464,7 +464,7 @@ bool GCodeBuffer::TryGetLimitedIValue(char c, int32_t& val, bool& seen, int32_t
}
// If the specified parameter character is found, fetch 'value' and set 'seen'. Otherwise leave val and seen alone.
-bool GCodeBuffer::TryGetUIValue(char c, uint32_t& val, bool& seen)
+bool GCodeBuffer::TryGetUIValue(char c, uint32_t& val, bool& seen) THROWS(GCodeException)
{
const bool ret = Seen(c);
if (ret)
@@ -487,7 +487,7 @@ bool GCodeBuffer::TryGetLimitedUIValue(char c, uint32_t& val, bool& seen, uint32
}
// If the specified parameter character is found, fetch 'value' as a Boolean and set 'seen'. Otherwise leave val and seen alone.
-bool GCodeBuffer::TryGetBValue(char c, bool& val, bool& seen)
+bool GCodeBuffer::TryGetBValue(char c, bool& val, bool& seen) THROWS(GCodeException)
{
const bool ret = Seen(c);
if (ret)
@@ -501,7 +501,7 @@ bool GCodeBuffer::TryGetBValue(char c, bool& val, bool& seen)
// Try to get an int array exactly 'numVals' long after parameter letter 'c'.
// If the wrong number of values is provided, generate an error message and return true.
// Else set 'seen' if we saw the letter and value, and return false.
-bool GCodeBuffer::TryGetUIArray(char c, size_t numVals, uint32_t vals[], const StringRef& reply, bool& seen, bool doPad)
+bool GCodeBuffer::TryGetUIArray(char c, size_t numVals, uint32_t vals[], const StringRef& reply, bool& seen, bool doPad) THROWS(GCodeException)
{
if (Seen(c))
{
@@ -523,7 +523,7 @@ bool GCodeBuffer::TryGetUIArray(char c, size_t numVals, uint32_t vals[], const S
// Try to get a float array exactly 'numVals' long after parameter letter 'c'.
// If the wrong number of values is provided, generate an error message and return true.
// Else set 'seen' if we saw the letter and value, and return false.
-bool GCodeBuffer::TryGetFloatArray(char c, size_t numVals, float vals[], const StringRef& reply, bool& seen, bool doPad)
+bool GCodeBuffer::TryGetFloatArray(char c, size_t numVals, float vals[], const StringRef& reply, bool& seen, bool doPad) THROWS(GCodeException)
{
if (Seen(c))
{
@@ -544,7 +544,7 @@ bool GCodeBuffer::TryGetFloatArray(char c, size_t numVals, float vals[], const S
// Try to get a quoted string after parameter letter.
// If we found it then set 'seen' true and return true, else leave 'seen' alone and return false
-bool GCodeBuffer::TryGetQuotedString(char c, const StringRef& str, bool& seen)
+bool GCodeBuffer::TryGetQuotedString(char c, const StringRef& str, bool& seen) THROWS(GCodeException)
{
if (Seen(c))
{
@@ -557,7 +557,7 @@ bool GCodeBuffer::TryGetQuotedString(char c, const StringRef& str, bool& seen)
// Try to get a string, which may be quoted, after parameter letter.
// If we found it then set 'seen' true and return true, else leave 'seen' alone and return false
-bool GCodeBuffer::TryGetPossiblyQuotedString(char c, const StringRef& str, bool& seen)
+bool GCodeBuffer::TryGetPossiblyQuotedString(char c, const StringRef& str, bool& seen) THROWS(GCodeException)
{
if (Seen(c))
{
@@ -569,13 +569,13 @@ bool GCodeBuffer::TryGetPossiblyQuotedString(char c, const StringRef& str, bool&
}
// Get a PWM frequency
-PwmFrequency GCodeBuffer::GetPwmFrequency()
+PwmFrequency GCodeBuffer::GetPwmFrequency() THROWS(GCodeException)
{
return (PwmFrequency)constrain<uint32_t>(GetUIValue(), 1, 65535);
}
// Get a PWM value. If may be in the old style 0..255 in which case convert it to be in the range 0.0..1.0
-float GCodeBuffer::GetPwmValue()
+float GCodeBuffer::GetPwmValue() THROWS(GCodeException)
{
float v = GetFValue();
if (v > 1.0)
@@ -586,7 +586,7 @@ float GCodeBuffer::GetPwmValue()
}
// Get a driver ID
-DriverId GCodeBuffer::GetDriverId()
+DriverId GCodeBuffer::GetDriverId() THROWS(GCodeException)
{
return PARSER_OPERATION(GetDriverId());
}
diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp
index c058b2c5..2d375b25 100644
--- a/src/GCodes/GCodeBuffer/StringParser.cpp
+++ b/src/GCodes/GCodeBuffer/StringParser.cpp
@@ -1656,7 +1656,20 @@ DriverId StringParser::ReadDriverIdValue() THROWS(GCodeException)
result.boardAddress = 0;
}
#else
- result.localDriver = v1;
+ // We now allow driver names of the form "0.x" on boards without CAN expansion
+ if (gb.buffer[readPointer] == '.')
+ {
+ if (v1 != 0)
+ {
+ throw ConstructParseException("Board address of driver must be 0");
+ }
+ ++readPointer;
+ result.localDriver = ReadUIValue();
+ }
+ else
+ {
+ result.localDriver = v1;
+ }
#endif
return result;
}
diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h
index b44a2825..a52fb204 100644
--- a/src/RepRapFirmware.h
+++ b/src/RepRapFirmware.h
@@ -186,9 +186,12 @@ struct DriverId
#else
- void SetFromBinary(uint32_t val) noexcept
+ // Set the driver ID from the binary value, returning true if there was a nonzero board number so that the caller knows the address is not valid
+ bool SetFromBinary(uint32_t val) noexcept
{
- localDriver = (uint8_t)val;
+ localDriver = val & 0x000000FF;
+ const uint32_t brdNum = val >> 16;
+ return (brdNum != 0);
}
void SetLocal(unsigned int driver) noexcept