diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index a443d4b302..ca732790e7 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -3042,6 +3042,20 @@ // //#define FF_INTERFACEBOARD +// +// MightyBoard LCD and Interface +// +//#define MIGHTYBOARD_LCD +#if ENABLED(MIGHTYBOARD_LCD) + //#define MIGHTYBOARD_RUNTIME_DEBUG // Lightweight debug output for buttons and encoder + //#define MIGHTYBOARD_DISABLE_ENC_PULLUP // Enable if the encoder button doesn't work correctly + //#define MIGHTYBOARD_BUTTON_PULLUPS // Enable if other buttons don't work correctly + + // Enable to use LEFT/RIGHT for Back and Status Screen. + // Otherwise LEFT/RIGHT act like the encoder in menu navigation and value editing. + //#define MIGHTYBOARD_BACK_STATUS_BUTTONS +#endif // MIGHTYBOARD_LCD + // // TFT GLCD Panel with Marlin UI // Panel connected to main board by SPI or I2C interface. diff --git a/Marlin/src/HAL/AVR/pinsDebug.h b/Marlin/src/HAL/AVR/pinsDebug.h index c833964a29..ce801333a2 100644 --- a/Marlin/src/HAL/AVR/pinsDebug.h +++ b/Marlin/src/HAL/AVR/pinsDebug.h @@ -45,7 +45,7 @@ #define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS -#if MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14) +#if MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14, MIGHTYBOARD_REVG) #define AVR_ATmega2560_FAMILY_PLUS_70 1 #endif diff --git a/Marlin/src/HAL/AVR/pinsDebug_plus_70.h b/Marlin/src/HAL/AVR/pinsDebug_plus_70.h index 6565acd523..46fe45c1f8 100644 --- a/Marlin/src/HAL/AVR/pinsDebug_plus_70.h +++ b/Marlin/src/HAL/AVR/pinsDebug_plus_70.h @@ -25,7 +25,7 @@ * Structures for 2560 family boards that use more than 70 pins */ -#if MB(BQ_ZUM_MEGA_3D, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14) +#if MB(BQ_ZUM_MEGA_3D, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14, MIGHTYBOARD_REVG) #undef NUM_DIGITAL_PINS #define NUM_DIGITAL_PINS 85 #elif MB(MIGHTYBOARD_REVE) diff --git a/Marlin/src/core/boards.h b/Marlin/src/core/boards.h index 13d28a4a02..718bc8f7d5 100644 --- a/Marlin/src/core/boards.h +++ b/Marlin/src/core/boards.h @@ -187,6 +187,7 @@ #define BOARD_MALYAN_M180 1333 // Malyan M180 Mainboard Version 2 (no display function, direct G-code only) #define BOARD_PROTONEER_CNC_SHIELD_V3 1334 // Mega controller & Protoneer CNC Shield V3.00 #define BOARD_WEEDO_62A 1335 // WEEDO 62A board (TINA2, Monoprice Cadet, etc.) +#define BOARD_MIGHTYBOARD_REVG 1336 // Makerbot Mightyboard Revision G and H // // ATmega1281, ATmega2561 diff --git a/Marlin/src/feature/leds/pca9632.cpp b/Marlin/src/feature/leds/pca9632.cpp index d8fba380a4..29c00fc682 100644 --- a/Marlin/src/feature/leds/pca9632.cpp +++ b/Marlin/src/feature/leds/pca9632.cpp @@ -81,7 +81,11 @@ #define LED_ON 0x01 #define LED_PWM 0x02 -#define PCA9632_ADDRESS 0b01100000 +#ifndef PCA9632_ADDRESS + #define PCA9632_ADDRESS 0b01100000 + #warning "Using default PCA9632_ADDRESS for I2C (0b01100000)." +#endif +//static_assert(false, "Using PCA9632 I2C address=" STRINGIFY(PCA9632_ADDRESS)); byte PCA_init = 0; @@ -98,16 +102,16 @@ static void PCA9632_WriteAllRegisters(const byte addr, const byte regadd, const #if DISABLED(PCA9632_NO_AUTO_INC) uint8_t data[4]; data[0] = PCA9632_AUTO_IND | regadd; - data[1 + (PCA9632_RED >> 1)] = vr; + data[1 + (PCA9632_RED >> 1)] = TERN(PCA9632_SWAP_RB, vb, vr); data[1 + (PCA9632_GRN >> 1)] = vg; - data[1 + (PCA9632_BLU >> 1)] = vb; + data[1 + (PCA9632_BLU >> 1)] = TERN(PCA9632_SWAP_RB, vr, vb); Wire.beginTransmission(I2C_ADDRESS(addr)); Wire.write(data, sizeof(data)); Wire.endTransmission(); #else - PCA9632_WriteRegister(addr, regadd + (PCA9632_RED >> 1), vr); + PCA9632_WriteRegister(addr, regadd + (PCA9632_RED >> 1), TERN(PCA9632_SWAP_RB, vb, vr)); PCA9632_WriteRegister(addr, regadd + (PCA9632_GRN >> 1), vg); - PCA9632_WriteRegister(addr, regadd + (PCA9632_BLU >> 1), vb); + PCA9632_WriteRegister(addr, regadd + (PCA9632_BLU >> 1), TERN(PCA9632_SWAP_RB, vb, vr)); #if ENABLED(PCA9632_RGBW) PCA9632_WriteRegister(addr, regadd + (PCA9632_WHT >> 1), vw); #endif @@ -132,15 +136,20 @@ void PCA9632_set_led_color(const LED1Color_t &color) { PCA9632_WriteRegister(PCA9632_ADDRESS,PCA9632_MODE2, PCA9632_MODE2_VALUE); } - const byte LEDOUT = (color.r ? LED_PWM << PCA9632_RED : 0) + const byte LEDOUT = (TERN(PCA9632_SWAP_RB, color.b, color.r) ? LED_PWM << PCA9632_RED : 0) | (color.g ? LED_PWM << PCA9632_GRN : 0) - | (color.b ? LED_PWM << PCA9632_BLU : 0) + | (TERN(PCA9632_SWAP_RB, color.r, color.b) ? LED_PWM << PCA9632_BLU : 0) | (TERN0(PCA9632_RGBW, color.w ? LED_PWM << PCA9632_WHT : 0)); - PCA9632_WriteAllRegisters(PCA9632_ADDRESS,PCA9632_PWM0, color.r, color.g, color.b + PCA9632_WriteAllRegisters( + PCA9632_ADDRESS, PCA9632_PWM0, + TERN(PCA9632_SWAP_RB, color.b, color.r), + color.g, + TERN(PCA9632_SWAP_RB, color.r, color.b) OPTARG(PCA9632_RGBW, color.w) ); PCA9632_WriteRegister(PCA9632_ADDRESS,PCA9632_LEDOUT, LEDOUT); + } #if ENABLED(PCA9632_BUZZER) diff --git a/Marlin/src/inc/Conditionals-2-LCD.h b/Marlin/src/inc/Conditionals-2-LCD.h index 72bad45c89..ed9b9bc370 100644 --- a/Marlin/src/inc/Conditionals-2-LCD.h +++ b/Marlin/src/inc/Conditionals-2-LCD.h @@ -307,6 +307,12 @@ #define IS_RRD_SC 1 #define U8GLIB_SSD1309 +#elif ENABLED(MIGHTYBOARD_LCD) + + #define IS_ULTIPANEL 1 + #define LCD_WIDTH 20 + #define LCD_HEIGHT 4 + #endif // ST7920-based graphical displays @@ -922,6 +928,7 @@ + ENABLED(CARTESIO_UI) \ + ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) \ + ENABLED(FF_INTERFACEBOARD) \ + + ENABLED(MIGHTYBOARD_LCD) \ + ENABLED(FYSETC_242_OLED_12864) \ + ENABLED(G3D_PANEL) \ + ENABLED(LCD_FOR_MELZI) \ diff --git a/Marlin/src/lcd/HD44780/MightyboardLCDSerial.cpp b/Marlin/src/lcd/HD44780/MightyboardLCDSerial.cpp new file mode 100644 index 0000000000..6291689931 --- /dev/null +++ b/Marlin/src/lcd/HD44780/MightyboardLCDSerial.cpp @@ -0,0 +1,331 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2026 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 . + * + */ + +#include "MightyboardLCDSerial.h" + +#include "../../inc/MarlinConfigPre.h" +#include "../../core/serial.h" + +#if HAS_MARLINUI_HD44780 && ENABLED(MIGHTYBOARD_LCD) + +#include + +/** + * Constructor: store pin assignments + */ +MightyboardLCDSerial::MightyboardLCDSerial(uint8_t strobe, uint8_t data, uint8_t clk, uint8_t pwrPin) + : _strobe_pin(strobe), _data_pin(data), _clk_pin(clk), _pwr_pin(pwrPin), + _displayfunction(LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS), + _displaycontrol(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF), + _displaymode(LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT), + _xcursor(0), _ycursor(0) {} + +/** + * Initialize LCD display with 4-bit mode + * Follows HD44780 initialization sequence from datasheet + */ +void MightyboardLCDSerial::begin(uint8_t cols, uint8_t rows, uint8_t charsize) { + pinMode(_strobe_pin, OUTPUT); + pinMode(_data_pin, OUTPUT); + pinMode(_clk_pin, OUTPUT); + + // Power on LCD if power pin is defined + if (_pwr_pin != 255) { + pinMode(_pwr_pin, OUTPUT); + digitalWrite(_pwr_pin, LOW); // Power on (active low) + } + + _cols = cols; + _rows = rows; + + // Diagnostic output showing LCD configuration + #if ENABLED(MIGHTYBOARD_RUNTIME_DEBUG) + SERIAL_ECHOLNPGM("MightyboardLCDSerial::begin() - LCD Configuration:"); + SERIAL_ECHOLNPGM(" Dimensions: ", _cols, " x ", _rows); + #ifdef LCD_WIDTH + SERIAL_ECHOLNPGM(" Expected from config: ", LCD_WIDTH, " x ", LCD_HEIGHT); + #endif + SERIAL_ECHOPGM(" Charsize: "); + if (charsize == LCD_5x8DOTS) + SERIAL_ECHOLNPGM("5x8 dots"); + else if (charsize == LCD_5x10DOTS) + SERIAL_ECHOLNPGM("5x10 dots"); + else + SERIAL_ECHOLNPGM("unknown"); + #endif + + if (rows > 1) + _displayfunction |= LCD_2LINE; + else if (rows == 1 && charsize != LCD_5x8DOTS) + _displayfunction |= LCD_5x10DOTS; + + // Power-up delay as per HD44780 datasheet (> 40ms required) + delay(50); + + // Initialization sequence for 4-bit mode + // This is a simplified sequence that works reliably + sendCommand(0x33); // Initialize, 8-bit mode attempt 1 + sendCommand(0x32); // Set 4-bit mode + sendCommand(0x28); // Function Set: 4-bit, 2-line, 5x8 dots + sendCommand(0x0C); // Display ON, cursor OFF, blink OFF + sendCommand(0x06); // Entry Mode Set: increment, no shift + sendCommand(0x01); // Clear display + delay(5); +} + +/** + * Clear the display and return cursor to home + */ +void MightyboardLCDSerial::clear() { + sendCommand(LCD_CLEARDISPLAY); + delay(2); // Clear takes ~1.52ms +} + +/** + * Return cursor to home (0, 0) + */ +void MightyboardLCDSerial::home() { + sendCommand(LCD_RETURNHOME); + delay(2); + _xcursor = 0; + _ycursor = 0; +} + +/** + * Turn display off (keeps data in DDRAM) + */ +void MightyboardLCDSerial::noDisplay() { + _displaycontrol &= ~LCD_DISPLAYON; + sendCommand(LCD_DISPLAYCONTROL | _displaycontrol); +} + +/** + * Turn display on + */ +void MightyboardLCDSerial::display() { + _displaycontrol |= LCD_DISPLAYON; + sendCommand(LCD_DISPLAYCONTROL | _displaycontrol); +} + +/** + * Turn off the blinking cursor + */ +void MightyboardLCDSerial::noBlink() { + _displaycontrol &= ~LCD_BLINKON; + sendCommand(LCD_DISPLAYCONTROL | _displaycontrol); +} + +/** + * Turn on the blinking cursor + */ +void MightyboardLCDSerial::blink() { + _displaycontrol |= LCD_BLINKON; + sendCommand(LCD_DISPLAYCONTROL | _displaycontrol); +} + +/** + * Turn off the underline cursor + */ +void MightyboardLCDSerial::noCursor() { + _displaycontrol &= ~LCD_CURSORON; + sendCommand(LCD_DISPLAYCONTROL | _displaycontrol); +} + +/** + * Turn on the underline cursor + */ +void MightyboardLCDSerial::cursor() { + _displaycontrol |= LCD_CURSORON; + sendCommand(LCD_DISPLAYCONTROL | _displaycontrol); +} + +/** + * Scroll display contents left (cursor follows) + */ +void MightyboardLCDSerial::scrollDisplayLeft() { + sendCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); +} + +/** + * Scroll display contents right (cursor follows) + */ +void MightyboardLCDSerial::scrollDisplayRight() { + sendCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); +} + +/** + * Set text direction left-to-right + */ +void MightyboardLCDSerial::leftToRight() { + _displaymode |= LCD_ENTRYLEFT; + sendCommand(LCD_ENTRYMODESET | _displaymode); +} + +/** + * Set text direction right-to-left + */ +void MightyboardLCDSerial::rightToLeft() { + _displaymode &= ~LCD_ENTRYLEFT; + sendCommand(LCD_ENTRYMODESET | _displaymode); +} + +/** + * Enable autoscroll (characters printed shift display left) + */ +void MightyboardLCDSerial::autoscroll() { + _displaymode |= LCD_ENTRYSHIFTINCREMENT; + sendCommand(LCD_ENTRYMODESET | _displaymode); +} + +/** + * Disable autoscroll + */ +void MightyboardLCDSerial::noAutoscroll() { + _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; + sendCommand(LCD_ENTRYMODESET | _displaymode); +} + +/** + * Load a custom character into CGRAM + * @param location CGRAM address (0-7) + * @param charmap 8-byte array defining the character + */ +void MightyboardLCDSerial::createChar(uint8_t location, uint8_t charmap[]) { + location &= 0x7; // Only 8 locations available + sendCommand(LCD_SETCGRAMADDR | (location << 3)); + for (int8_t i = 0; i < 8; i++) sendData(charmap[i]); +} + +/** + * Set cursor position + * @param col Column (0 to cols-1) + * @param row Row (0 to rows-1) + */ +void MightyboardLCDSerial::setCursor(uint8_t col, uint8_t row) { + static const uint8_t row_offsets[] = {0x00, 0x40, 0x14, 0x54}; + if (row >= _rows) row = _rows - 1; + _xcursor = col; + _ycursor = row; + sendCommand(LCD_SETDDRAMADDR | (col + row_offsets[row])); +} + +/** + * Write a character to the LCD at current cursor position + * Automatically advances cursor and wraps to next line if needed + */ +size_t MightyboardLCDSerial::write(uint8_t value) { + sendData(value); + _xcursor++; + if (_xcursor >= _cols) { + _xcursor = 0; + _ycursor++; + if (_ycursor >= _rows) _ycursor = 0; + setCursor(_xcursor, _ycursor); + } + return 1; +} + +/** + * Send a raw command byte to LCD + */ +void MightyboardLCDSerial::command(uint8_t value) { + send(value, false); +} + +/** + * Low-level: send 8-bit value as two 4-bit nibbles + * @param value Byte to send + * @param mode false = command, true = data + */ +void MightyboardLCDSerial::send(uint8_t value, bool mode) { + write4bits(value >> 4, mode); + write4bits(value & 0x0F, mode); +} + +/** + * Send command (RS = 0) + */ +inline void MightyboardLCDSerial::sendCommand(uint8_t value) { + send(value, false); +} + +/** + * Send data (RS = 1) + */ +inline void MightyboardLCDSerial::sendData(uint8_t value) { + send(value, true); +} + +/** + * Write 4-bit nibble to display + * @param value Lower 4 bits are used + * @param dataMode false = command (RS=0), true = data (RS=1) + */ +void MightyboardLCDSerial::write4bits(uint8_t value, bool dataMode) { + // Shift data to upper 4 bits (D7-D4 in HD44780) + uint8_t bits = value << 4; + + // Set RS bit (bit 1) based on mode + // On Mightyboard: RS = 0b0010 + if (dataMode) bits |= 0b0010; // RS = 1 for data + + // Pulse enable to latch the nibble + pulseEnable(bits); +} + +/** + * Pulse the Enable line to latch data + * On Mightyboard hardware: Enable = bit 3 (0b01000) + * @param value Pre-set data bits (D7-D0 in shift register) + */ +void MightyboardLCDSerial::pulseEnable(uint8_t value) { + _delay_us(1); + value |= 0b00001000; // Set enable HIGH + writeSerial(value); + _delay_us(1); + value &= 0b11110111; // Set enable LOW + writeSerial(value); + _delay_us(50); // Wait for command execution +} + +/** + * Shift out 8 bits serially via shift register + * Sends MSB first (bit 7 down to bit 0) + * @param value Byte to shift out + */ +void MightyboardLCDSerial::writeSerial(uint8_t value) { + // Shift out each bit, MSB first + for (int8_t i = 7; i >= 0; i--) { + digitalWrite(_clk_pin, LOW); + bool data = (value >> i) & 0x01; + digitalWrite(_data_pin, data); + digitalWrite(_clk_pin, HIGH); + _delay_us(1); // Clock pulse width + } + + // Pulse strobe to latch data into display shift register + digitalWrite(_strobe_pin, HIGH); + _delay_us(1); + digitalWrite(_strobe_pin, LOW); +} + +#endif // HAS_MARLINUI_HD44780 && ENABLED(MIGHTYBOARD_LCD) diff --git a/Marlin/src/lcd/HD44780/MightyboardLCDSerial.h b/Marlin/src/lcd/HD44780/MightyboardLCDSerial.h new file mode 100644 index 0000000000..6e630196e9 --- /dev/null +++ b/Marlin/src/lcd/HD44780/MightyboardLCDSerial.h @@ -0,0 +1,142 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2026 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 . + * + */ +#pragma once + +/** + * MightyboardLCDSerial + * Optimized 3-wire shift-register LCD driver for Mightyboard OEM displays + * Provides HD44780 compatible interface with minimal CPU overhead + */ + +#include + +class MightyboardLCDSerial : public Print { +public: + /** + * Constructor: initialize pin assignments + * @param strobe Strobe/latch pin (LATCH_PIN / SR_STROBE_PIN) + * @param data Data pin (MOSI_PIN / SR_DATA_PIN) + * @param clk Clock pin (SCLK_PIN / SR_CLK_PIN) + * @param pwrPin Power control pin (LCD_PWR_PIN) + */ + MightyboardLCDSerial(uint8_t strobe, uint8_t data, uint8_t clk, uint8_t pwrPin = 255); + + /** + * Initialize display with given dimensions + * @param cols Number of columns (typically 20) + * @param rows Number of rows (typically 4) + */ + void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); + + // Basic display control + void clear(); + void home(); + void noDisplay(); + void display(); + void noBlink(); + void blink(); + void noCursor(); + void cursor(); + + // Cursor movement + void setCursor(uint8_t col, uint8_t row); + void scrollDisplayLeft(); + void scrollDisplayRight(); + void leftToRight(); + void rightToLeft(); + void autoscroll(); + void noAutoscroll(); + + // Custom characters + void createChar(uint8_t location, uint8_t charmap[]); + + // Text output + virtual size_t write(uint8_t value); + using Print::write; + + // Low-level command + void command(uint8_t value); + +private: + uint8_t _strobe_pin; + uint8_t _data_pin; + uint8_t _clk_pin; + uint8_t _pwr_pin; + + uint8_t _cols; + uint8_t _rows; + uint8_t _displayfunction; + uint8_t _displaycontrol; + uint8_t _displaymode; + + uint8_t _xcursor; + uint8_t _ycursor; + + // Low-level communication + void send(uint8_t value, bool mode); + void sendCommand(uint8_t value); + void sendData(uint8_t value); + void write4bits(uint8_t value, bool dataMode); + void pulseEnable(uint8_t value); + void writeSerial(uint8_t value); + + // HD44780 command constants + static const uint8_t LCD_CLEARDISPLAY = 0x01; + static const uint8_t LCD_RETURNHOME = 0x02; + static const uint8_t LCD_ENTRYMODESET = 0x04; + static const uint8_t LCD_DISPLAYCONTROL = 0x08; + static const uint8_t LCD_CURSORSHIFT = 0x10; + static const uint8_t LCD_FUNCTIONSET = 0x20; + static const uint8_t LCD_SETCGRAMADDR = 0x40; + static const uint8_t LCD_SETDDRAMADDR = 0x80; + + // Entry mode flags + static const uint8_t LCD_ENTRYRIGHT = 0x00; + static const uint8_t LCD_ENTRYLEFT = 0x02; + static const uint8_t LCD_ENTRYSHIFTINCREMENT = 0x01; + static const uint8_t LCD_ENTRYSHIFTDECREMENT = 0x00; + + // Display control flags + static const uint8_t LCD_DISPLAYON = 0x04; + static const uint8_t LCD_DISPLAYOFF = 0x00; + static const uint8_t LCD_CURSORON = 0x02; + static const uint8_t LCD_CURSOROFF = 0x00; + static const uint8_t LCD_BLINKON = 0x01; + static const uint8_t LCD_BLINKOFF = 0x00; + + // Display shift flags + static const uint8_t LCD_DISPLAYMOVE = 0x08; + static const uint8_t LCD_CURSORMOVE = 0x00; + static const uint8_t LCD_MOVERIGHT = 0x04; + static const uint8_t LCD_MOVELEFT = 0x00; + + // Function set flags + static const uint8_t LCD_8BITMODE = 0x10; + static const uint8_t LCD_4BITMODE = 0x00; + static const uint8_t LCD_2LINE = 0x08; + static const uint8_t LCD_1LINE = 0x00; + static const uint8_t LCD_5x10DOTS = 0x04; + static const uint8_t LCD_5x8DOTS = 0x00; +}; + +// Alias for compatibility with Marlin's LCD_CLASS macro +using MightyboardLCD = MightyboardLCDSerial; diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp index 60cb91dc79..65ce352a9e 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp @@ -89,6 +89,16 @@ #endif ); +#elif ENABLED(MIGHTYBOARD_LCD) + + // 3-wire shift-register LCD for Mightyboard + // Optimized in-tree implementation + #if PIN_EXISTS(LCD_PWR) + LCD_CLASS lcd(SR_STROBE_PIN, SR_DATA_PIN, SR_CLK_PIN, LCD_PWR_PIN); + #else + LCD_CLASS lcd(SR_STROBE_PIN, SR_DATA_PIN, SR_CLK_PIN); + #endif + #elif ENABLED(SR_LCD_3W_NL) // NewLiquidCrystal was not working diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.h b/Marlin/src/lcd/HD44780/marlinui_HD44780.h index 15f268f8d9..09050d2996 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.h +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.h @@ -89,6 +89,15 @@ #include #define LCD_CLASS LiquidCrystal_SR +#elif ENABLED(MIGHTYBOARD_LCD) + + // 3-wire shift-register LCD for Mightyboard + // Optimized in-tree implementation + // Pin mapping: SR_STROBE_PIN, SR_DATA_PIN, SR_CLK_PIN + + #include "MightyboardLCDSerial.h" + #define LCD_CLASS MightyboardLCDSerial + #elif ENABLED(SR_LCD_3W_NL) // NewLiquidCrystal didn't work, so this uses diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp index 3c30304ed8..9aef5cff60 100644 --- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp +++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp @@ -305,6 +305,10 @@ void MarlinUI::init_lcd() { did_init_u8g = true; } + #if PIN_EXISTS(LCD_PWR) + OUT_WRITE(LCD_PWR_PIN, LOW); + #endif + #if PIN_EXISTS(LCD_BACKLIGHT) OUT_WRITE(LCD_BACKLIGHT_PIN, DISABLED(DELAYED_BACKLIGHT_INIT)); // Illuminate after reset or right away #endif diff --git a/Marlin/src/lcd/marlinui.cpp b/Marlin/src/lcd/marlinui.cpp index f475b52efc..2cf04f68c0 100644 --- a/Marlin/src/lcd/marlinui.cpp +++ b/Marlin/src/lcd/marlinui.cpp @@ -69,6 +69,12 @@ MarlinUI ui; bool MarlinUI::wait_for_move; // = false #endif +#if ENABLED(MIGHTYBOARD_BACK_STATUS_BUTTONS) + // Flags set from interrupt context; handled in main loop + volatile bool MarlinUI::request_back = false, + MarlinUI::request_return_to_status = false; +#endif + constexpr uint8_t epps = ENCODER_PULSES_PER_STEP; #if HAS_STATUS_MESSAGE @@ -276,7 +282,11 @@ void MarlinUI::init() { SET_INPUT_PULLUP(BTN_EN2); #endif #if BUTTON_EXISTS(ENC) - SET_INPUT_PULLUP(BTN_ENC); + #if ENABLED(MIGHTYBOARD_DISABLE_ENC_PULLUP) + SET_INPUT(BTN_ENC); + #else + SET_INPUT_PULLUP(BTN_ENC); + #endif #endif #if BUTTON_EXISTS(ENC_EN) SET_INPUT_PULLUP(BTN_ENC_EN); @@ -285,18 +295,68 @@ void MarlinUI::init() { SET_INPUT_PULLUP(BTN_BACK); #endif #if BUTTON_EXISTS(UP) - SET_INPUT(BTN_UP); + #if ENABLED(MIGHTYBOARD_BUTTON_PULLUPS) + SET_INPUT_PULLUP(BTN_UP); + #else + SET_INPUT(BTN_UP); + #endif #endif #if BUTTON_EXISTS(DOWN) - SET_INPUT(BTN_DOWN); + #if ENABLED(MIGHTYBOARD_BUTTON_PULLUPS) + SET_INPUT_PULLUP(BTN_DOWN); + #else + SET_INPUT(BTN_DOWN); + #endif #endif #if BUTTON_EXISTS(LFT) - SET_INPUT(BTN_LEFT); + #if ENABLED(MIGHTYBOARD_BUTTON_PULLUPS) + SET_INPUT_PULLUP(BTN_LEFT); + #else + SET_INPUT(BTN_LEFT); + #endif #endif #if BUTTON_EXISTS(RT) - SET_INPUT(BTN_RIGHT); + #if ENABLED(MIGHTYBOARD_BUTTON_PULLUPS) + SET_INPUT_PULLUP(BTN_RIGHT); + #else + SET_INPUT(BTN_RIGHT); + #endif #endif + // Compile-time warnings to confirm whether this directional-button init block + // is compiled for the current board. These will appear in the compiler output + // only when ANY_BUTTON(UP, DOWN, LFT, RT) evaluates true for the current build. + //#if ENABLED(MIGHTYBOARD_RUNTIME_DEBUG) && ANY_BUTTON(UP, DOWN, LFT, RT) + // #warning "Marlin: Compiling directional button init (UP/DOWN/LEFT/RIGHT)" + //#endif + + // Optional runtime trace for MightyBoard UI/button flow. + // Enable by uncommenting `#define MIGHTYBOARD_RUNTIME_DEBUG` in the board pins file. + //#if ENABLED(MIGHTYBOARD_RUNTIME_DEBUG) + // SERIAL_ECHOLN("MarlinUI::init() - MIGHTYBOARD_RUNTIME_DEBUG active"); + // #if ENABLED(MIGHTYBOARD_BUTTON_PULLUPS) + // SERIAL_ECHOLN("MIGHTYBOARD_BUTTON_PULLUPS: ENABLED"); + // #else + // SERIAL_ECHOLN("MIGHTYBOARD_BUTTON_PULLUPS: DISABLED"); + // #endif + // SERIAL_ECHO_MSG("LCD dimensions: ", LCD_WIDTH, " x ", LCD_HEIGHT); + // SERIAL_ECHOLN(""); + // + //// Report encoder/click compile-time presence and pin numbers (if defined) + // #if BUTTON_EXISTS(ENC) + // SERIAL_ECHOLN("BUTTON_EXISTS(ENC): defined"); + // SERIAL_ECHO_MSG("BTN_ENC pin: ", BTN_ENC); + // SERIAL_ECHOLN(""); + // #else + // SERIAL_ECHOLN("BUTTON_EXISTS(ENC): NOT defined"); + // #endif + // + // #ifdef BTN_CLICK + // SERIAL_ECHO_MSG("BTN_CLICK pin: ", BTN_CLICK); + // SERIAL_ECHOLN(""); + // #endif + //#endif // MIGHTYBOARD_RUNTIME_DEBUG + #if HAS_SHIFT_ENCODER #if ENABLED(SR_LCD_2W_NL) // Non latching 2 wire shift register @@ -1031,6 +1091,19 @@ void MarlinUI::init() { else wait_for_unclick = false; } + #if ENABLED(MIGHTYBOARD_BACK_STATUS_BUTTONS) + // Handle requests set from interrupt context (ISR-safe) + if (request_back) { + request_back = false; + quick_feedback(); + goto_previous_screen(); + } + if (request_return_to_status) { + request_return_to_status = false; + quick_feedback(); + return_to_status(); + } + #endif if (LCD_BACK_CLICKED()) { quick_feedback(); @@ -1357,6 +1430,18 @@ void MarlinUI::init() { void MarlinUI::update_buttons() { const millis_t now = millis(); + //#if ENABLED(MIGHTYBOARD_RUNTIME_DEBUG) + // // Debug: print raw pin reads for encoder/click to diagnose BTN_ENC alias + // #if BUTTON_EXISTS(ENC) + // SERIAL_ECHO_MSG("DBG: READ(BTN_ENC) = ", READ(BTN_ENC)); + // SERIAL_ECHOLN(""); + // #endif + // #ifdef BTN_CLICK + // SERIAL_ECHO_MSG("DBG: READ(BTN_CLICK) = ", READ(BTN_CLICK)); + // SERIAL_ECHOLN(""); + // #endif + //#endif + #if HAS_MARLINUI_ENCODER const int8_t delta = get_encoder_delta(now); @@ -1389,17 +1474,29 @@ void MarlinUI::init() { if (BUTTON_PRESSED(UP)) { encoderDiff = pulses * (ENCODER_STEPS_PER_MENU_ITEM); next_button_update_ms = now + 300; + //#if ENABLED(MIGHTYBOARD_RUNTIME_DEBUG) + // SERIAL_ECHO_MSG("update_buttons(): UP -> encoderDiff=", encoderDiff); + // SERIAL_ECHOLN(""); + //#endif } else if (BUTTON_PRESSED(DOWN)) { encoderDiff = pulses * -(ENCODER_STEPS_PER_MENU_ITEM); next_button_update_ms = now + 300; } else if (BUTTON_PRESSED(LEFT)) { - encoderDiff = -pulses; + #if ENABLED(MIGHTYBOARD_BACK_STATUS_BUTTONS) + request_back = true; // ISR-safe: flag action run in the main loop + #else + encoderDiff = -pulses; + #endif next_button_update_ms = now + 300; } else if (BUTTON_PRESSED(RIGHT)) { - encoderDiff = pulses; + #if ENABLED(MIGHTYBOARD_BACK_STATUS_BUTTONS) + request_return_to_status = true; // ISR-safe: flag action run in the main loop + #else + encoderDiff = -pulses; + #endif next_button_update_ms = now + 300; } diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h index 15f355ccd0..65e0e6729f 100644 --- a/Marlin/src/lcd/marlinui.h +++ b/Marlin/src/lcd/marlinui.h @@ -836,6 +836,11 @@ public: static void update_buttons(); + #if ENABLED(MIGHTYBOARD_BACK_STATUS_BUTTONS) + // Requests set from interrupt context and handled in main loop + static volatile bool request_back, request_return_to_status; + #endif + #if ENABLED(ENCODER_NOISE_FILTER) /** * Some printers may have issues with EMI noise especially using a motherboard with 3.3V logic levels diff --git a/Marlin/src/libs/softspi.h b/Marlin/src/libs/softspi.h index f9408904e1..3b9775f3e9 100644 --- a/Marlin/src/libs/softspi.h +++ b/Marlin/src/libs/softspi.h @@ -207,7 +207,16 @@ {&DDRJ, &PINJ, &PORTJ, 5}, // J5 76 {&DDRJ, &PINJ, &PORTJ, 6}, // J6 77 {&DDRE, &PINE, &PORTE, 2}, // E2 78 - {&DDRE, &PINE, &PORTE, 6} // E6 79 + {&DDRE, &PINE, &PORTE, 6}, // E6 79 + + // pins MIGHTYBOARD_REVG.h + // TODO: Only include with a -D define in build + {&DDRE, &PINE, &PORTE, 7}, // E7 80 + {&DDRD, &PIND, &PORTD, 4}, // D4 81 + {&DDRD, &PIND, &PORTD, 5}, // D5 82 + {&DDRD, &PIND, &PORTD, 6}, // D6 83 + {&DDRH, &PINH, &PORTH, 2}, // H2 84 + {&DDRH, &PINH, &PORTH, 7} // H7 85 }; #elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__) \ diff --git a/Marlin/src/pins/mega/pins_MIGHTYBOARD_REVG.h b/Marlin/src/pins/mega/pins_MIGHTYBOARD_REVG.h new file mode 100644 index 0000000000..61c6340a02 --- /dev/null +++ b/Marlin/src/pins/mega/pins_MIGHTYBOARD_REVG.h @@ -0,0 +1,202 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2026 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 . + * + */ +#pragma once + +/** + * Mightyboard Rev.G and H pin assignments + * Schematic: not avalable (as rev G and H are not open source) + * Pins based on the work of https://github.com/Sgail7/Replicator-Revival-Project/ + * Pin number according to Mega extended mega2560ext: .\buildroot\share\PlatformIO\variants\MARLIN_MEGA_EXTENDED\pins_arduino.h + * Corrected pins based on Marlin\src\libs\softspi.h + * Use env:MightyBoard2560 or env:MightyBoard1280 in platformio.ini + */ + +#define ALLOW_MEGA1280 +#include "env_validate.h" + +#define BOARD_INFO_NAME "Mightyboard rev.G/H" +#define DEFAULT_MACHINE_NAME "MB Replicator" + +// +// Limit Switches: X and Y go to max, Z to min +// +#define X_STOP_PIN 30 // C7 +#define Y_STOP_PIN 31 // C6 +#define Z_STOP_PIN 32 // C5 + +// +// Steppers +// +#define X_STEP_PIN 83 // D6 +#define X_DIR_PIN 38 // D7 +#define X_ENABLE_PIN 81 // D4 + +#define Y_STEP_PIN 44 // L5 +#define Y_DIR_PIN 42 // L7 +#define Y_ENABLE_PIN 45 // L4 + +#define Z_STEP_PIN 48 // L1 +#define Z_DIR_PIN 47 // L2 +#define Z_ENABLE_PIN 49 // L0 + +#define E0_STEP_PIN 25 // A3 +#define E0_DIR_PIN 24 // A2 +#define E0_ENABLE_PIN 27 // A5 + +#define E1_STEP_PIN 22 // A0 +#define E1_DIR_PIN 15 // K7 +#define E1_ENABLE_PIN 23 // A1 + +/** + * I2C Digipots - MCP4018 + * Address 5E (2F << 1) + * Set from 0 - 127 with stop bit. + * (Ex. 3F << 1 | 1) + */ +#define DIGIPOTS_I2C_SCL 28 // A6 +#define DIGIPOTS_I2C_SDA_X 82 // D5 +#define DIGIPOTS_I2C_SDA_Y 43 // L6 +#define DIGIPOTS_I2C_SDA_Z 46 // L3 +#define DIGIPOTS_I2C_SDA_E0 26 // A4 +#define DIGIPOTS_I2C_SDA_E1 74 // J7 + +#ifndef DIGIPOT_I2C_ADDRESS_A + #define DIGIPOT_I2C_ADDRESS_A 0x2F // unshifted slave address (5E <- 2F << 1) +#endif +#define DIGIPOT_ENABLE_I2C_PULLUPS // MightyBoard doesn't have hardware I2C pin pull-ups. + +// Bed temp sensor pin +#define TEMP_BED_PIN 3 // F3 + +/** + * Temperature Sensors + * Uses ADS1118 as ADC converter to read the hotend temperature sensors + * SPI for ADS1118 ADC, Uses software SPI + */ +#define TEMP_0_CS_PIN 79 // E6 +#define TEMP_0_SCK_PIN 78 // E2 +#define TEMP_0_MISO_PIN 80 // E7 +#define TEMP_0_MOSI_PIN 84 // H2 + +#define TEMP_1_CS_PIN 2 // E4 +#define TEMP_1_SCK_PIN TEMP_0_SCK_PIN +#define TEMP_1_MISO_PIN TEMP_0_MISO_PIN +#define TEMP_1_MOSI_PIN TEMP_0_MOSI_PIN + +// +// FET Pin Mapping - FET A is closest to the input power connector +// + +#define MOSFET_A_PIN 3 // E5 +#define MOSFET_B_PIN 5 // E3 +#define MOSFET_C_PIN 8 // H5 +#define MOSFET_D_PIN 7 // H4 +#define MOSFET_E_PIN 2 // E4 +#define MOSFET_F_PIN 4 // G5 + +// +// Heaters / Fans (24V) +// + +#define HEATER_0_PIN MOSFET_A_PIN // E5 +#define HEATER_1_PIN MOSFET_B_PIN // E3 ?* +#define HEATER_BED_PIN MOSFET_C_PIN // H5 + +#ifndef E0_AUTO_FAN_PIN + #define E0_AUTO_FAN_PIN MOSFET_D_PIN +#elif !defined(FAN0_PIN) + #define FAN0_PIN MOSFET_D_PIN +#endif + +#ifndef E1_AUTO_FAN_PIN + #define E1_AUTO_FAN_PIN MOSFET_E_PIN +#elif !defined(FAN1_PIN) + #define FAN1_PIN MOSFET_E_PIN +#endif + +// +// LCD / Controller +// + +#if IS_RRD_FG_SC + + #define BEEPER_PIN 8 // H5, SD_WP + + #define BTN_EN2 75 // J4, UP + #define BTN_EN1 73 // J3, DOWN + + #define LCD_PINS_RS 33 // C4: LCD-STROBE + #define LCD_PINS_EN 72 // J2: LEFT + #define LCD_PINS_D4 35 // C2: LCD-CLK + #define LCD_PINS_D5 32 // C5: RLED + #define LCD_PINS_D6 34 // C3: LCD-DATA + #define LCD_PINS_D7 31 // C6: GLED + + // STOP button connected as KILL_PIN + #define KILL_PIN 14 // J1, RIGHT (not connected) + + // Onboard leds + #define STAT_LED_RED_PIN SERVO0_PIN // C1 (1280-EX1, DEBUG2) + #define STAT_LED_BLUE_PIN SERVO1_PIN // C0 (1280-EX2, DEBUG3) + +#elif HAS_WIRED_LCD + + // Replicator 2 and 2X uses a HD44780 SPI display, pins: mosi, sclk, miso (not used), missing: latch, click, power + + #define BEEPER_PIN 6 // H3 + + // Map the CLICK button to the encoder 'click' so Marlin treats it as SELECT + #ifndef BTN_ENC + #define BTN_ENC BTN_CENTER + #endif + + #define BTN_CENTER 39 // G2 + #define BTN_UP 76 // J5 + #define BTN_DOWN 75 // J4 + #define BTN_LEFT 77 // J6 + #define BTN_RIGHT 73 // J3 + + #define SR_DATA_PIN 37 // C0 + #define SR_CLK_PIN 36 // C1 + #define SR_STROBE_PIN 34 // C3 + #define SR_DETECT_PIN 33 // C4 + + #define LCD_PWR_PIN 29 // A7 + + #define BUTTON_LED_PIN 35 // C2 To be implemented... + + /** + * SD Card + * + * NOTE: With SD support enabled it is implicitly assumed + * that the following pins are connected: + * AVR | SD header + *---------|-------------- + * MISO | DATA_OUT + * MOSI | DATA_IN + * SCK | CLK + */ + //#define SD_WRITE_PIN 41 // Sailfish mighty two: G0(41) H5(D8) - + #define SD_DETECT_PIN 40 // Sailfish mighty two: G1(40) H6(D9) L0(D49) + #define SD_SS_PIN 53 // Sailfish mighty two: B0(53) + +#endif // HAS_WIRED_LCD diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h index 6c4894f20d..c2933eb5fb 100644 --- a/Marlin/src/pins/pins.h +++ b/Marlin/src/pins/pins.h @@ -317,6 +317,8 @@ #include "mega/pins_PROTONEER_CNC_SHIELD_V3.h" // ATmega2560 env:mega2560 #elif MB(WEEDO_62A) #include "mega/pins_WEEDO_62A.h" // ATmega2560 env:mega2560 +#elif MB(MIGHTYBOARD_REVG) + #include "mega/pins_MIGHTYBOARD_REVG.h" // ATmega2560, ATmega1280 env:MightyBoard2560 env:MightyBoard1280 env:mega2560ext // // ATmega1281, ATmega2561 diff --git a/Marlin/src/pins/pinsDebug_list.h b/Marlin/src/pins/pinsDebug_list.h index a6807f5c69..bb8d282a53 100644 --- a/Marlin/src/pins/pinsDebug_list.h +++ b/Marlin/src/pins/pinsDebug_list.h @@ -960,6 +960,9 @@ #if PIN_EXISTS(LCD_BACKLIGHT) REPORT_NAME_DIGITAL(__LINE__, LCD_BACKLIGHT_PIN) #endif +#if PIN_EXISTS(LCD_PWR) + REPORT_NAME_DIGITAL(__LINE__, LCD_PWR_PIN) +#endif #if PIN_EXISTS(DOGLCD_SCL) REPORT_NAME_DIGITAL(__LINE__, DOGLCD_SCL_PIN) #endif