aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/HAL/LPC1768/u8g
diff options
context:
space:
mode:
Diffstat (limited to 'Marlin/src/HAL/LPC1768/u8g')
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.cpp123
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.h28
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/LCD_defines.h49
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/LCD_delay.h43
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/LCD_pin_routines.c110
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/LCD_pin_routines.h37
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp129
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp198
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp138
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp147
-rw-r--r--Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp209
11 files changed, 1211 insertions, 0 deletions
diff --git a/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.cpp b/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.cpp
new file mode 100644
index 0000000..a48a820
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.cpp
@@ -0,0 +1,123 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+// adapted from I2C/master/master.c example
+// https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
+
+#ifdef TARGET_LPC1768
+
+#include "../include/i2c_util.h"
+#include "../../../core/millis_t.h"
+
+extern int millis();
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+// These two routines are exact copies of the lpc17xx_i2c.c routines. Couldn't link to
+// to the lpc17xx_i2c.c routines so had to copy them into this file & rename them.
+
+static uint32_t _I2C_Start(LPC_I2C_TypeDef *I2Cx) {
+ // Reset STA, STO, SI
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC|I2C_I2CONCLR_STOC|I2C_I2CONCLR_STAC;
+
+ // Enter to Master Transmitter mode
+ I2Cx->I2CONSET = I2C_I2CONSET_STA;
+
+ // Wait for complete
+ while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI));
+ I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
+ return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
+}
+
+static void _I2C_Stop (LPC_I2C_TypeDef *I2Cx) {
+ /* Make sure start bit is not active */
+ if (I2Cx->I2CONSET & I2C_I2CONSET_STA)
+ I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
+
+ I2Cx->I2CONSET = I2C_I2CONSET_STO|I2C_I2CONSET_AA;
+ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+#define I2CDEV_S_ADDR 0x78 // from SSD1306 //actual address is 0x3C - shift left 1 with LSB set to 0 to indicate write
+
+#define BUFFER_SIZE 0x1 // only do single byte transfers with LCDs
+
+I2C_M_SETUP_Type transferMCfg;
+
+#define I2C_status (LPC_I2C1->I2STAT & I2C_STAT_CODE_BITMASK)
+
+// Send slave address and write bit
+uint8_t u8g_i2c_start(const uint8_t sla) {
+ // Sometimes TX data ACK or NAK status is returned. That mean the start state didn't
+ // happen which means only the value of the slave address was send. Keep looping until
+ // the slave address and write bit are actually sent.
+ do{
+ _I2C_Stop(I2CDEV_M); // output stop state on I2C bus
+ _I2C_Start(I2CDEV_M); // output start state on I2C bus
+ while ((I2C_status != I2C_I2STAT_M_TX_START)
+ && (I2C_status != I2C_I2STAT_M_TX_RESTART)
+ && (I2C_status != I2C_I2STAT_M_TX_DAT_ACK)
+ && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK)); //wait for start to be asserted
+
+ LPC_I2C1->I2CONCLR = I2C_I2CONCLR_STAC; // clear start state before tansmitting slave address
+ LPC_I2C1->I2DAT = I2CDEV_S_ADDR & I2C_I2DAT_BITMASK; // transmit slave address & write bit
+ LPC_I2C1->I2CONSET = I2C_I2CONSET_AA;
+ LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC;
+ while ((I2C_status != I2C_I2STAT_M_TX_SLAW_ACK)
+ && (I2C_status != I2C_I2STAT_M_TX_SLAW_NACK)
+ && (I2C_status != I2C_I2STAT_M_TX_DAT_ACK)
+ && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK)); //wait for slaw to finish
+ }while ( (I2C_status == I2C_I2STAT_M_TX_DAT_ACK) || (I2C_status == I2C_I2STAT_M_TX_DAT_NACK));
+ return 1;
+}
+
+void u8g_i2c_init(const uint8_t clock_option) {
+ configure_i2c(clock_option);
+ u8g_i2c_start(0); // Send slave address and write bit
+}
+
+uint8_t u8g_i2c_send_byte(uint8_t data) {
+ #define I2C_TIMEOUT 3
+ LPC_I2C1->I2DAT = data & I2C_I2DAT_BITMASK; // transmit data
+ LPC_I2C1->I2CONSET = I2C_I2CONSET_AA;
+ LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC;
+ const millis_t timeout = millis() + I2C_TIMEOUT;
+ while ((I2C_status != I2C_I2STAT_M_TX_DAT_ACK) && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK) && PENDING(millis(), timeout)); // wait for xmit to finish
+ // had hangs with SH1106 so added time out - have seen temporary screen corruption when this happens
+ return 1;
+}
+
+void u8g_i2c_stop() {
+}
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.h b/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.h
new file mode 100644
index 0000000..2d976c9
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.h
@@ -0,0 +1,28 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+void u8g_i2c_init(const uint8_t clock_options);
+//uint8_t u8g_i2c_wait(uint8_t mask, uint8_t pos);
+uint8_t u8g_i2c_start(uint8_t sla);
+uint8_t u8g_i2c_send_byte(uint8_t data);
+void u8g_i2c_stop();
diff --git a/Marlin/src/HAL/LPC1768/u8g/LCD_defines.h b/Marlin/src/HAL/LPC1768/u8g/LCD_defines.h
new file mode 100644
index 0000000..d226003
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/LCD_defines.h
@@ -0,0 +1,49 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+/**
+ * LPC1768 LCD-specific defines
+ */
+
+// The following are optional depending on the platform.
+
+// definitions of HAL specific com and device drivers.
+uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
+
+
+// connect U8g com generic com names to the desired driver
+#define U8G_COM_HW_SPI u8g_com_HAL_LPC1768_hw_spi_fn // use LPC1768 specific hardware SPI routine
+#define U8G_COM_SW_SPI u8g_com_HAL_LPC1768_sw_spi_fn // use LPC1768 specific software SPI routine
+#define U8G_COM_ST7920_HW_SPI u8g_com_HAL_LPC1768_ST7920_hw_spi_fn
+#define U8G_COM_ST7920_SW_SPI u8g_com_HAL_LPC1768_ST7920_sw_spi_fn
+#define U8G_COM_SSD_I2C u8g_com_HAL_LPC1768_ssd_hw_i2c_fn
+
+// let these default for now
+#define U8G_COM_PARALLEL u8g_com_null_fn
+#define U8G_COM_T6963 u8g_com_null_fn
+#define U8G_COM_FAST_PARALLEL u8g_com_null_fn
+#define U8G_COM_UC_I2C u8g_com_null_fn
diff --git a/Marlin/src/HAL/LPC1768/u8g/LCD_delay.h b/Marlin/src/HAL/LPC1768/u8g/LCD_delay.h
new file mode 100644
index 0000000..0b9e2b4
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/LCD_delay.h
@@ -0,0 +1,43 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+/**
+ * LCD delay routines - used by all the drivers.
+ *
+ * These are based on the LPC1768 routines.
+ *
+ * Couldn't just call exact copies because the overhead
+ * results in a one microsecond delay taking about 4µS.
+ */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+void U8g_delay(int msec);
+void u8g_MicroDelay();
+void u8g_10MicroDelay();
+
+#ifdef __cplusplus
+ }
+#endif
diff --git a/Marlin/src/HAL/LPC1768/u8g/LCD_pin_routines.c b/Marlin/src/HAL/LPC1768/u8g/LCD_pin_routines.c
new file mode 100644
index 0000000..466fc80
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/LCD_pin_routines.c
@@ -0,0 +1,110 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Low level pin manipulation routines - used by all the drivers.
+ *
+ * These are based on the LPC1768 pinMode, digitalRead & digitalWrite routines.
+ *
+ * Couldn't just call exact copies because the overhead killed the LCD update speed
+ * With an intermediate level the softspi was running in the 10-20kHz range which
+ * resulted in using about about 25% of the CPU's time.
+ */
+
+#ifdef TARGET_LPC1768
+
+#include <LPC17xx.h>
+#include <lpc17xx_pinsel.h>
+#include "../../../core/macros.h"
+//#include <pinmapping.h>
+
+#define LPC_PORT_OFFSET (0x0020)
+#define LPC_PIN(pin) (1UL << pin)
+#define LPC_GPIO(port) ((volatile LPC_GPIO_TypeDef *)(LPC_GPIO0_BASE + LPC_PORT_OFFSET * port))
+
+#define INPUT 0
+#define OUTPUT 1
+#define INPUT_PULLUP 2
+
+uint8_t LPC1768_PIN_PORT(const uint8_t pin);
+uint8_t LPC1768_PIN_PIN(const uint8_t pin);
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// I/O functions
+// As defined by Arduino INPUT(0x0), OUTPUT(0x1), INPUT_PULLUP(0x2)
+void pinMode_LCD(uint8_t pin, uint8_t mode) {
+ #define LPC1768_PIN_PORT(pin) ((uint8_t)((pin >> 5) & 0b111))
+ #define LPC1768_PIN_PIN(pin) ((uint8_t)(pin & 0b11111))
+ PINSEL_CFG_Type config = { LPC1768_PIN_PORT(pin),
+ LPC1768_PIN_PIN(pin),
+ PINSEL_FUNC_0,
+ PINSEL_PINMODE_TRISTATE,
+ PINSEL_PINMODE_NORMAL };
+ switch (mode) {
+ case INPUT:
+ LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(pin));
+ PINSEL_ConfigPin(&config);
+ break;
+ case OUTPUT:
+ LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR |= LPC_PIN(LPC1768_PIN_PIN(pin));
+ PINSEL_ConfigPin(&config);
+ break;
+ case INPUT_PULLUP:
+ LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(pin));
+ config.Pinmode = PINSEL_PINMODE_PULLUP;
+ PINSEL_ConfigPin(&config);
+ break;
+ default: break;
+ }
+}
+
+void u8g_SetPinOutput(uint8_t internal_pin_number) {
+ pinMode_LCD(internal_pin_number, 1); // OUTPUT
+}
+
+void u8g_SetPinInput(uint8_t internal_pin_number) {
+ pinMode_LCD(internal_pin_number, 0); // INPUT
+}
+
+void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status) {
+ #define LPC1768_PIN_PORT(pin) ((uint8_t)((pin >> 5) & 0b111))
+ #define LPC1768_PIN_PIN(pin) ((uint8_t)(pin & 0b11111))
+ if (pin_status)
+ LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOSET = LPC_PIN(LPC1768_PIN_PIN(pin));
+ else
+ LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOCLR = LPC_PIN(LPC1768_PIN_PIN(pin));
+}
+
+uint8_t u8g_GetPinLevel(uint8_t pin) {
+ #define LPC1768_PIN_PORT(pin) ((uint8_t)((pin >> 5) & 0b111))
+ #define LPC1768_PIN_PIN(pin) ((uint8_t)(pin & 0b11111))
+ return (uint32_t)LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOPIN & LPC_PIN(LPC1768_PIN_PIN(pin)) ? 1 : 0;
+}
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/u8g/LCD_pin_routines.h b/Marlin/src/HAL/LPC1768/u8g/LCD_pin_routines.h
new file mode 100644
index 0000000..d60d93d
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/LCD_pin_routines.h
@@ -0,0 +1,37 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+/**
+ * Low level pin manipulation routines - used by all the drivers.
+ *
+ * These are based on the LPC1768 pinMode, digitalRead & digitalWrite routines.
+ *
+ * Couldn't just call exact copies because the overhead killed the LCD update speed
+ * With an intermediate level the softspi was running in the 10-20kHz range which
+ * resulted in using about about 25% of the CPU's time.
+ */
+
+void u8g_SetPinOutput(uint8_t internal_pin_number);
+void u8g_SetPinInput(uint8_t internal_pin_number);
+void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status);
+uint8_t u8g_GetPinLevel(uint8_t pin);
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
new file mode 100644
index 0000000..b1eea13
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_hw_spi.cpp
@@ -0,0 +1,129 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Based on u8g_com_msp430_hw_spi.c
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2011, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TARGET_LPC1768
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if HAS_MARLINUI_U8GLIB
+
+#include <U8glib.h>
+#include "../../shared/HAL_SPI.h"
+
+#ifndef LCD_SPI_SPEED
+ #ifdef SD_SPI_SPEED
+ #define LCD_SPI_SPEED SD_SPI_SPEED // Assume SPI speed shared with SD
+ #else
+ #define LCD_SPI_SPEED SPI_FULL_SPEED // Use full speed if SD speed is not supplied
+ #endif
+#endif
+
+uint8_t u8g_com_HAL_LPC1768_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_INIT:
+ u8g_SetPILevel(u8g, U8G_PI_CS, 1);
+ u8g_SetPILevel(u8g, U8G_PI_A0, 1);
+ u8g_SetPILevel(u8g, U8G_PI_RESET, 1);
+ u8g_SetPIOutput(u8g, U8G_PI_CS);
+ u8g_SetPIOutput(u8g, U8G_PI_A0);
+ u8g_SetPIOutput(u8g, U8G_PI_RESET);
+ u8g_Delay(5);
+ spiBegin();
+ spiInit(LCD_SPI_SPEED);
+ break;
+
+ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
+ u8g_SetPILevel(u8g, U8G_PI_A0, arg_val);
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ u8g_SetPILevel(u8g, U8G_PI_CS, (arg_val ? 0 : 1));
+ break;
+
+ case U8G_COM_MSG_RESET:
+ u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ spiSend((uint8_t)arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ spiSend(*ptr++);
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ spiSend(*ptr++);
+ arg_val--;
+ }
+ }
+ break;
+ }
+ return 1;
+}
+
+#endif // HAS_MARLINUI_U8GLIB
+
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp
new file mode 100644
index 0000000..6f7efba
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_ssd_hw_i2c.cpp
@@ -0,0 +1,198 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Based on u8g_com_arduino_ssd_i2c.c
+ *
+ * COM interface for Arduino (AND ATmega) and the SSDxxxx chip (SOLOMON) variant
+ * I2C protocol
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2011, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Special pin usage:
+ * U8G_PI_I2C_OPTION additional options
+ * U8G_PI_A0_STATE used to store the last value of the command/data register selection
+ * U8G_PI_SET_A0 1: Signal request to update I2C device with new A0_STATE, 0: Do nothing, A0_STATE matches I2C device
+ * U8G_PI_SCL clock line (NOT USED)
+ * U8G_PI_SDA data line (NOT USED)
+ *
+ * U8G_PI_RESET reset line (currently disabled, see below)
+ *
+ * Protocol:
+ * SLA, Cmd/Data Selection, Arguments
+ * The command/data register is selected by a special instruction byte, which is sent after SLA
+ *
+ * The continue bit is always 0 so that a (re)start is equired for the change from cmd to/data mode
+ */
+
+#ifdef TARGET_LPC1768
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if HAS_MARLINUI_U8GLIB
+
+#include <U8glib.h>
+
+#define I2C_SLA (0x3C*2)
+//#define I2C_CMD_MODE 0x080
+#define I2C_CMD_MODE 0x000
+#define I2C_DATA_MODE 0x040
+
+uint8_t u8g_com_ssd_I2C_start_sequence(u8g_t *u8g) {
+ /* are we requested to set the a0 state? */
+ if (u8g->pin_list[U8G_PI_SET_A0] == 0) return 1;
+
+ /* setup bus, might be a repeated start */
+ if (u8g_i2c_start(I2C_SLA) == 0) return 0;
+ if (u8g->pin_list[U8G_PI_A0_STATE] == 0) {
+ if (u8g_i2c_send_byte(I2C_CMD_MODE) == 0) return 0;
+ }
+ else if (u8g_i2c_send_byte(I2C_DATA_MODE) == 0)
+ return 0;
+
+ u8g->pin_list[U8G_PI_SET_A0] = 0;
+ return 1;
+}
+
+uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_INIT:
+ //u8g_com_arduino_digital_write(u8g, U8G_PI_SCL, HIGH);
+ //u8g_com_arduino_digital_write(u8g, U8G_PI_SDA, HIGH);
+ //u8g->pin_list[U8G_PI_A0_STATE] = 0; /* initial RS state: unknown mode */
+
+ u8g_i2c_init(u8g->pin_list[U8G_PI_I2C_OPTION]);
+ u8g_com_ssd_I2C_start_sequence(u8g);
+ break;
+
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_RESET:
+ /* Currently disabled, but it could be enable. Previous restrictions have been removed */
+ /* u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); */
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ u8g->pin_list[U8G_PI_A0_STATE] = 0;
+ u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again, also forces start condition */
+ if (arg_val == 0 ) {
+ /* disable chip, send stop condition */
+ u8g_i2c_stop();
+ }
+ else {
+ /* enable, do nothing: any byte writing will trigger the i2c start */
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ //u8g->pin_list[U8G_PI_SET_A0] = 1;
+ if (u8g_com_ssd_I2C_start_sequence(u8g) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+
+ if (u8g_i2c_send_byte(arg_val) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+ // u8g_i2c_stop();
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ //u8g->pin_list[U8G_PI_SET_A0] = 1;
+ if (u8g_com_ssd_I2C_start_sequence(u8g) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+
+ uint8_t *ptr = (uint8_t *)arg_ptr;
+ while (arg_val > 0) {
+ if (u8g_i2c_send_byte(*ptr++) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+ arg_val--;
+ }
+ }
+ // u8g_i2c_stop();
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ //u8g->pin_list[U8G_PI_SET_A0] = 1;
+ if (u8g_com_ssd_I2C_start_sequence(u8g) == 0) {
+ u8g_i2c_stop();
+ return 0;
+ }
+
+ uint8_t *ptr = (uint8_t *)arg_ptr;
+ while (arg_val > 0) {
+ if (u8g_i2c_send_byte(u8g_pgm_read(ptr)) == 0)
+ return 0;
+ ptr++;
+ arg_val--;
+ }
+ }
+ // u8g_i2c_stop();
+ break;
+
+ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
+ u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
+ u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again */
+ break;
+
+ } // switch
+ return 1;
+}
+
+#endif // HAS_MARLINUI_U8GLIB
+
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
new file mode 100644
index 0000000..592e27f
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_hw_spi.cpp
@@ -0,0 +1,138 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Based on u8g_com_LPC1768_st7920_hw_spi.c
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2011, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TARGET_LPC1768
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if HAS_MARLINUI_U8GLIB
+
+#include <U8glib.h>
+#include "../../shared/HAL_SPI.h"
+#include "../../shared/Delay.h"
+
+void spiBegin();
+void spiInit(uint8_t spiRate);
+void spiSend(uint8_t b);
+void spiSend(const uint8_t* buf, size_t n);
+
+static uint8_t rs_last_state = 255;
+
+static void u8g_com_LPC1768_st7920_write_byte_hw_spi(uint8_t rs, uint8_t val) {
+
+ if (rs != rs_last_state) { // Time to send a command/data byte
+ rs_last_state = rs;
+ spiSend(rs ? 0x0FA : 0x0F8); // Send data or command
+ DELAY_US(40); // Give the controller some time: 20 is bad, 30 is OK, 40 is safe
+ }
+
+ spiSend(val & 0xF0);
+ spiSend(val << 4);
+}
+
+uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_INIT:
+ u8g_SetPILevel(u8g, U8G_PI_CS, 0);
+ u8g_SetPIOutput(u8g, U8G_PI_CS);
+ u8g_Delay(5);
+ spiBegin();
+ spiInit(SPI_EIGHTH_SPEED); // ST7920 max speed is about 1.1 MHz
+ u8g->pin_list[U8G_PI_A0_STATE] = 0; // initial RS state: command mode
+ break;
+
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_RESET:
+ u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
+ break;
+
+ case U8G_COM_MSG_ADDRESS: // Define cmd (arg_val = 0) or data mode (arg_val = 1)
+ u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ u8g_SetPILevel(u8g, U8G_PI_CS, arg_val); // Note: the ST7920 has an active high chip-select
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ u8g_com_LPC1768_st7920_write_byte_hw_spi(u8g->pin_list[U8G_PI_A0_STATE], arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ u8g_com_LPC1768_st7920_write_byte_hw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ u8g_com_LPC1768_st7920_write_byte_hw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+ }
+ return 1;
+}
+
+#endif // HAS_MARLINUI_U8GLIB
+
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
new file mode 100644
index 0000000..61211d9
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_st7920_sw_spi.cpp
@@ -0,0 +1,147 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Based on u8g_com_st7920_hw_spi.c
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2011, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TARGET_LPC1768
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if ENABLED(U8GLIB_ST7920)
+
+#include <U8glib.h>
+#include <SoftwareSPI.h>
+#include "../../shared/Delay.h"
+#include "../../shared/HAL_SPI.h"
+
+#ifndef LCD_SPI_SPEED
+ #define LCD_SPI_SPEED SPI_EIGHTH_SPEED // About 1 MHz
+#endif
+
+static pin_t SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL;
+static uint8_t SPI_speed = 0;
+
+static void u8g_com_LPC1768_st7920_write_byte_sw_spi(uint8_t rs, uint8_t val) {
+ static uint8_t rs_last_state = 255;
+ if (rs != rs_last_state) {
+ // Transfer Data (FA) or Command (F8)
+ swSpiTransfer(rs ? 0x0FA : 0x0F8, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
+ rs_last_state = rs;
+ DELAY_US(40); // Give the controller time to process the data: 20 is bad, 30 is OK, 40 is safe
+ }
+ swSpiTransfer(val & 0x0F0, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
+ swSpiTransfer(val << 4, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
+}
+
+uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_INIT:
+ SCK_pin_ST7920_HAL = u8g->pin_list[U8G_PI_SCK];
+ MOSI_pin_ST7920_HAL_HAL = u8g->pin_list[U8G_PI_MOSI];
+
+ u8g_SetPIOutput(u8g, U8G_PI_CS);
+ u8g_SetPIOutput(u8g, U8G_PI_SCK);
+ u8g_SetPIOutput(u8g, U8G_PI_MOSI);
+ u8g_Delay(5);
+
+ SPI_speed = swSpiInit(LCD_SPI_SPEED, SCK_pin_ST7920_HAL, MOSI_pin_ST7920_HAL_HAL);
+
+ u8g_SetPILevel(u8g, U8G_PI_CS, 0);
+ u8g_SetPILevel(u8g, U8G_PI_SCK, 0);
+ u8g_SetPILevel(u8g, U8G_PI_MOSI, 0);
+
+ u8g->pin_list[U8G_PI_A0_STATE] = 0; /* initial RS state: command mode */
+ break;
+
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_RESET:
+ if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
+ break;
+
+ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
+ u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_CS]) u8g_SetPILevel(u8g, U8G_PI_CS, arg_val); //note: the st7920 has an active high chip select
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ u8g_com_LPC1768_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ u8g_com_LPC1768_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ u8g_com_LPC1768_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+ }
+ return 1;
+}
+
+#endif // U8GLIB_ST7920
+#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
new file mode 100644
index 0000000..7f38ec5
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/u8g/u8g_com_HAL_LPC1768_sw_spi.cpp
@@ -0,0 +1,209 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * Based on u8g_com_std_sw_spi.c
+ *
+ * Universal 8bit Graphics Library
+ *
+ * Copyright (c) 2015, olikraus@gmail.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TARGET_LPC1768
+
+#include "../../../inc/MarlinConfigPre.h"
+
+#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920)
+
+#include <SoftwareSPI.h>
+#include "../../shared/HAL_SPI.h"
+
+#ifndef LCD_SPI_SPEED
+ #define LCD_SPI_SPEED SPI_QUARTER_SPEED // About 2 MHz
+#endif
+
+#include <Arduino.h>
+#include <algorithm>
+#include <LPC17xx.h>
+#include <gpio.h>
+
+#include <U8glib.h>
+
+uint8_t swSpiTransfer_mode_0(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin ) {
+
+ LOOP_L_N(i, 8) {
+ if (spi_speed == 0) {
+ LPC176x::gpio_set(mosi_pin, !!(b & 0x80));
+ LPC176x::gpio_set(sck_pin, HIGH);
+ b <<= 1;
+ if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
+ LPC176x::gpio_set(sck_pin, LOW);
+ }
+ else {
+ const uint8_t state = (b & 0x80) ? HIGH : LOW;
+ LOOP_L_N(j, spi_speed)
+ LPC176x::gpio_set(mosi_pin, state);
+
+ LOOP_L_N(j, spi_speed + (miso_pin >= 0 ? 0 : 1))
+ LPC176x::gpio_set(sck_pin, HIGH);
+
+ b <<= 1;
+ if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
+
+ LOOP_L_N(j, spi_speed)
+ LPC176x::gpio_set(sck_pin, LOW);
+ }
+ }
+
+ return b;
+}
+
+uint8_t swSpiTransfer_mode_3(uint8_t b, const uint8_t spi_speed, const pin_t sck_pin, const pin_t miso_pin, const pin_t mosi_pin ) {
+
+ LOOP_L_N(i, 8) {
+ const uint8_t state = (b & 0x80) ? HIGH : LOW;
+ if (spi_speed == 0) {
+ LPC176x::gpio_set(sck_pin, LOW);
+ LPC176x::gpio_set(mosi_pin, state);
+ LPC176x::gpio_set(mosi_pin, state); // need some setup time
+ LPC176x::gpio_set(sck_pin, HIGH);
+ }
+ else {
+ LOOP_L_N(j, spi_speed + (miso_pin >= 0 ? 0 : 1))
+ LPC176x::gpio_set(sck_pin, LOW);
+
+ LOOP_L_N(j, spi_speed)
+ LPC176x::gpio_set(mosi_pin, state);
+
+ LOOP_L_N(j, spi_speed)
+ LPC176x::gpio_set(sck_pin, HIGH);
+ }
+ b <<= 1;
+ if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
+ }
+
+ return b;
+}
+
+static uint8_t SPI_speed = 0;
+
+static void u8g_sw_spi_HAL_LPC1768_shift_out(uint8_t dataPin, uint8_t clockPin, uint8_t val) {
+ #if EITHER(FYSETC_MINI_12864, MKS_MINI_12864)
+ swSpiTransfer_mode_3(val, SPI_speed, clockPin, -1, dataPin);
+ #else
+ swSpiTransfer_mode_0(val, SPI_speed, clockPin, -1, dataPin);
+ #endif
+}
+
+uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ switch (msg) {
+ case U8G_COM_MSG_INIT:
+ u8g_SetPIOutput(u8g, U8G_PI_SCK);
+ u8g_SetPIOutput(u8g, U8G_PI_MOSI);
+ u8g_SetPIOutput(u8g, U8G_PI_CS);
+ u8g_SetPIOutput(u8g, U8G_PI_A0);
+ if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPIOutput(u8g, U8G_PI_RESET);
+ SPI_speed = swSpiInit(LCD_SPI_SPEED, u8g->pin_list[U8G_PI_SCK], u8g->pin_list[U8G_PI_MOSI]);
+ u8g_SetPILevel(u8g, U8G_PI_SCK, 0);
+ u8g_SetPILevel(u8g, U8G_PI_MOSI, 0);
+ break;
+
+ case U8G_COM_MSG_STOP:
+ break;
+
+ case U8G_COM_MSG_RESET:
+ if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT:
+ #if EITHER(FYSETC_MINI_12864, MKS_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0
+ if (arg_val) { // SCK idle state needs to be set to the proper idle state before
+ // the next chip select goes active
+ u8g_SetPILevel(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active
+ u8g_SetPILevel(u8g, U8G_PI_CS, LOW);
+ }
+ else {
+ u8g_SetPILevel(u8g, U8G_PI_CS, HIGH);
+ u8g_SetPILevel(u8g, U8G_PI_SCK, 0); // Set SCK to mode 0 idle state after CS goes inactive
+ }
+ #else
+ u8g_SetPILevel(u8g, U8G_PI_CS, !arg_val);
+ #endif
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ u8g_sw_spi_HAL_LPC1768_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ: {
+ uint8_t *ptr = (uint8_t *)arg_ptr;
+ while (arg_val > 0) {
+ u8g_sw_spi_HAL_LPC1768_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], *ptr++);
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ_P: {
+ uint8_t *ptr = (uint8_t *)arg_ptr;
+ while (arg_val > 0) {
+ u8g_sw_spi_HAL_LPC1768_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], u8g_pgm_read(ptr));
+ ptr++;
+ arg_val--;
+ }
+ }
+ break;
+
+ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
+ u8g_SetPILevel(u8g, U8G_PI_A0, arg_val);
+ break;
+ }
+ return 1;
+}
+
+#endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920
+#endif // TARGET_LPC1768