aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/feature/leds
diff options
context:
space:
mode:
Diffstat (limited to 'Marlin/src/feature/leds')
-rw-r--r--Marlin/src/feature/leds/blinkm.cpp46
-rw-r--r--Marlin/src/feature/leds/blinkm.h31
-rw-r--r--Marlin/src/feature/leds/leds.cpp200
-rw-r--r--Marlin/src/feature/leds/leds.h253
-rw-r--r--Marlin/src/feature/leds/neopixel.cpp172
-rw-r--r--Marlin/src/feature/leds/neopixel.h182
-rw-r--r--Marlin/src/feature/leds/pca9533.cpp127
-rw-r--r--Marlin/src/feature/leds/pca9533.h59
-rw-r--r--Marlin/src/feature/leds/pca9632.cpp164
-rw-r--r--Marlin/src/feature/leds/pca9632.h37
-rw-r--r--Marlin/src/feature/leds/printer_event_leds.cpp82
-rw-r--r--Marlin/src/feature/leds/printer_event_leds.h87
-rw-r--r--Marlin/src/feature/leds/tempstat.cpp55
-rw-r--r--Marlin/src/feature/leds/tempstat.h28
14 files changed, 1523 insertions, 0 deletions
diff --git a/Marlin/src/feature/leds/blinkm.cpp b/Marlin/src/feature/leds/blinkm.cpp
new file mode 100644
index 0000000..868eb4b
--- /dev/null
+++ b/Marlin/src/feature/leds/blinkm.cpp
@@ -0,0 +1,46 @@
+/**
+ * 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/>.
+ *
+ */
+
+/**
+ * blinkm.cpp - Control a BlinkM over i2c
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(BLINKM)
+
+#include "blinkm.h"
+#include "leds.h"
+#include <Wire.h>
+
+void blinkm_set_led_color(const LEDColor &color) {
+ Wire.begin();
+ Wire.beginTransmission(I2C_ADDRESS(0x09));
+ Wire.write('o'); //to disable ongoing script, only needs to be used once
+ Wire.write('n');
+ Wire.write(color.r);
+ Wire.write(color.g);
+ Wire.write(color.b);
+ Wire.endTransmission();
+}
+
+#endif // BLINKM
diff --git a/Marlin/src/feature/leds/blinkm.h b/Marlin/src/feature/leds/blinkm.h
new file mode 100644
index 0000000..29a9e78
--- /dev/null
+++ b/Marlin/src/feature/leds/blinkm.h
@@ -0,0 +1,31 @@
+/**
+ * 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
+
+/**
+ * blinkm.h - Control a BlinkM over i2c
+ */
+
+struct LEDColor;
+typedef LEDColor LEDColor;
+
+void blinkm_set_led_color(const LEDColor &color);
diff --git a/Marlin/src/feature/leds/leds.cpp b/Marlin/src/feature/leds/leds.cpp
new file mode 100644
index 0000000..ef9099f
--- /dev/null
+++ b/Marlin/src/feature/leds/leds.cpp
@@ -0,0 +1,200 @@
+/**
+ * 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/>.
+ *
+ */
+
+/**
+ * leds.cpp - Marlin RGB LED general support
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if HAS_COLOR_LEDS
+
+#include "leds.h"
+
+#if ENABLED(BLINKM)
+ #include "blinkm.h"
+#endif
+
+#if ENABLED(PCA9632)
+ #include "pca9632.h"
+#endif
+
+#if ENABLED(PCA9533)
+ #include "pca9533.h"
+#endif
+
+#if ENABLED(LED_COLOR_PRESETS)
+ const LEDColor LEDLights::defaultLEDColor = MakeLEDColor(
+ LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE,
+ LED_USER_PRESET_WHITE, LED_USER_PRESET_BRIGHTNESS
+ );
+#endif
+
+#if EITHER(LED_CONTROL_MENU, PRINTER_EVENT_LEDS)
+ LEDColor LEDLights::color;
+ bool LEDLights::lights_on;
+#endif
+
+LEDLights leds;
+
+void LEDLights::setup() {
+ #if EITHER(RGB_LED, RGBW_LED)
+ if (PWM_PIN(RGB_LED_R_PIN)) SET_PWM(RGB_LED_R_PIN); else SET_OUTPUT(RGB_LED_R_PIN);
+ if (PWM_PIN(RGB_LED_G_PIN)) SET_PWM(RGB_LED_G_PIN); else SET_OUTPUT(RGB_LED_G_PIN);
+ if (PWM_PIN(RGB_LED_B_PIN)) SET_PWM(RGB_LED_B_PIN); else SET_OUTPUT(RGB_LED_B_PIN);
+ #if ENABLED(RGBW_LED)
+ if (PWM_PIN(RGB_LED_W_PIN)) SET_PWM(RGB_LED_W_PIN); else SET_OUTPUT(RGB_LED_W_PIN);
+ #endif
+ #endif
+ TERN_(NEOPIXEL_LED, neo.init());
+ TERN_(PCA9533, PCA9533_init());
+ TERN_(LED_USER_PRESET_STARTUP, set_default());
+}
+
+void LEDLights::set_color(const LEDColor &incol
+ #if ENABLED(NEOPIXEL_LED)
+ , bool isSequence/*=false*/
+ #endif
+) {
+
+ #if ENABLED(NEOPIXEL_LED)
+
+ const uint32_t neocolor = LEDColorWhite() == incol
+ ? neo.Color(NEO_WHITE)
+ : neo.Color(incol.r, incol.g, incol.b, incol.w);
+ static uint16_t nextLed = 0;
+
+ #ifdef NEOPIXEL_BKGD_LED_INDEX
+ if (NEOPIXEL_BKGD_LED_INDEX == nextLed) {
+ if (++nextLed >= neo.pixels()) nextLed = 0;
+ return;
+ }
+ #endif
+
+ neo.set_brightness(incol.i);
+
+ if (isSequence) {
+ neo.set_pixel_color(nextLed, neocolor);
+ neo.show();
+ if (++nextLed >= neo.pixels()) nextLed = 0;
+ return;
+ }
+
+ neo.set_color(neocolor);
+
+ #endif
+
+ #if ENABLED(BLINKM)
+
+ // This variant uses i2c to send the RGB components to the device.
+ blinkm_set_led_color(incol);
+
+ #endif
+
+ #if EITHER(RGB_LED, RGBW_LED)
+
+ // This variant uses 3-4 separate pins for the RGB(W) components.
+ // If the pins can do PWM then their intensity will be set.
+ #define UPDATE_RGBW(C,c) do { \
+ if (PWM_PIN(RGB_LED_##C##_PIN)) \
+ analogWrite(pin_t(RGB_LED_##C##_PIN), incol.c); \
+ else \
+ WRITE(RGB_LED_##C##_PIN, incol.c ? HIGH : LOW); \
+ }while(0)
+ UPDATE_RGBW(R,r); UPDATE_RGBW(G,g); UPDATE_RGBW(B,b);
+ #if ENABLED(RGBW_LED)
+ UPDATE_RGBW(W,w);
+ #endif
+
+ #endif
+
+ // Update I2C LED driver
+ TERN_(PCA9632, PCA9632_set_led_color(incol));
+ TERN_(PCA9533, PCA9533_set_rgb(incol.r, incol.g, incol.b));
+
+ #if EITHER(LED_CONTROL_MENU, PRINTER_EVENT_LEDS)
+ // Don't update the color when OFF
+ lights_on = !incol.is_off();
+ if (lights_on) color = incol;
+ #endif
+}
+
+#if ENABLED(LED_CONTROL_MENU)
+ void LEDLights::toggle() { if (lights_on) set_off(); else update(); }
+#endif
+
+#ifdef LED_BACKLIGHT_TIMEOUT
+
+ millis_t LEDLights::led_off_time; // = 0
+
+ void LEDLights::update_timeout(const bool power_on) {
+ const millis_t ms = millis();
+ if (power_on)
+ reset_timeout(ms);
+ else if (ELAPSED(ms, led_off_time))
+ set_off();
+ }
+
+#endif
+
+#if ENABLED(NEOPIXEL2_SEPARATE)
+
+ #if ENABLED(NEO2_COLOR_PRESETS)
+ const LEDColor LEDLights2::defaultLEDColor = MakeLEDColor(
+ NEO2_USER_PRESET_RED, NEO2_USER_PRESET_GREEN, NEO2_USER_PRESET_BLUE,
+ NEO2_USER_PRESET_WHITE, NEO2_USER_PRESET_BRIGHTNESS
+ );
+ #endif
+
+ #if ENABLED(LED_CONTROL_MENU)
+ LEDColor LEDLights2::color;
+ bool LEDLights2::lights_on;
+ #endif
+
+ LEDLights2 leds2;
+
+ void LEDLights2::setup() {
+ neo2.init();
+ TERN_(NEO2_USER_PRESET_STARTUP, set_default());
+ }
+
+ void LEDLights2::set_color(const LEDColor &incol) {
+ const uint32_t neocolor = LEDColorWhite() == incol
+ ? neo2.Color(NEO2_WHITE)
+ : neo2.Color(incol.r, incol.g, incol.b, incol.w);
+ neo2.set_brightness(incol.i);
+ neo2.set_color(neocolor);
+
+ #if ENABLED(LED_CONTROL_MENU)
+ // Don't update the color when OFF
+ lights_on = !incol.is_off();
+ if (lights_on) color = incol;
+ #endif
+ }
+
+ #if ENABLED(LED_CONTROL_MENU)
+ void LEDLights2::toggle() { if (lights_on) set_off(); else update(); }
+ #endif
+
+#endif // NEOPIXEL2_SEPARATE
+
+#endif // HAS_COLOR_LEDS
diff --git a/Marlin/src/feature/leds/leds.h b/Marlin/src/feature/leds/leds.h
new file mode 100644
index 0000000..57b21d5
--- /dev/null
+++ b/Marlin/src/feature/leds/leds.h
@@ -0,0 +1,253 @@
+/**
+ * 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
+
+/**
+ * leds.h - Marlin general RGB LED support
+ */
+
+#include "../../inc/MarlinConfigPre.h"
+
+#include <string.h>
+
+#if ENABLED(NEOPIXEL_LED)
+ #include "neopixel.h"
+#endif
+
+// A white component can be passed
+#if ANY(RGBW_LED, NEOPIXEL_LED, PCA9632_RGBW)
+ #define HAS_WHITE_LED 1
+#endif
+
+/**
+ * LEDcolor type for use with leds.set_color
+ */
+typedef struct LEDColor {
+ uint8_t r, g, b
+ #if HAS_WHITE_LED
+ , w
+ #if ENABLED(NEOPIXEL_LED)
+ , i
+ #endif
+ #endif
+ ;
+
+ LEDColor() : r(255), g(255), b(255)
+ #if HAS_WHITE_LED
+ , w(255)
+ #if ENABLED(NEOPIXEL_LED)
+ , i(NEOPIXEL_BRIGHTNESS)
+ #endif
+ #endif
+ {}
+
+ LEDColor(uint8_t r, uint8_t g, uint8_t b
+ #if HAS_WHITE_LED
+ , uint8_t w=0
+ #if ENABLED(NEOPIXEL_LED)
+ , uint8_t i=NEOPIXEL_BRIGHTNESS
+ #endif
+ #endif
+ ) : r(r), g(g), b(b)
+ #if HAS_WHITE_LED
+ , w(w)
+ #if ENABLED(NEOPIXEL_LED)
+ , i(i)
+ #endif
+ #endif
+ {}
+
+ LEDColor(const uint8_t (&rgbw)[4]) : r(rgbw[0]), g(rgbw[1]), b(rgbw[2])
+ #if HAS_WHITE_LED
+ , w(rgbw[3])
+ #if ENABLED(NEOPIXEL_LED)
+ , i(NEOPIXEL_BRIGHTNESS)
+ #endif
+ #endif
+ {}
+
+ LEDColor& operator=(const uint8_t (&rgbw)[4]) {
+ r = rgbw[0]; g = rgbw[1]; b = rgbw[2];
+ TERN_(HAS_WHITE_LED, w = rgbw[3]);
+ return *this;
+ }
+
+ LEDColor& operator=(const LEDColor &right) {
+ if (this != &right) memcpy(this, &right, sizeof(LEDColor));
+ return *this;
+ }
+
+ bool operator==(const LEDColor &right) {
+ if (this == &right) return true;
+ return 0 == memcmp(this, &right, sizeof(LEDColor));
+ }
+
+ bool operator!=(const LEDColor &right) { return !operator==(right); }
+
+ bool is_off() const {
+ return 3 > r + g + b + TERN0(HAS_WHITE_LED, w);
+ }
+} LEDColor;
+
+/**
+ * Color helpers and presets
+ */
+#if HAS_WHITE_LED
+ #if ENABLED(NEOPIXEL_LED)
+ #define MakeLEDColor(R,G,B,W,I) LEDColor(R, G, B, W, I)
+ #else
+ #define MakeLEDColor(R,G,B,W,I) LEDColor(R, G, B, W)
+ #endif
+#else
+ #define MakeLEDColor(R,G,B,W,I) LEDColor(R, G, B)
+#endif
+
+#define LEDColorOff() LEDColor( 0, 0, 0)
+#define LEDColorRed() LEDColor(255, 0, 0)
+#if ENABLED(LED_COLORS_REDUCE_GREEN)
+ #define LEDColorOrange() LEDColor(255, 25, 0)
+ #define LEDColorYellow() LEDColor(255, 75, 0)
+#else
+ #define LEDColorOrange() LEDColor(255, 80, 0)
+ #define LEDColorYellow() LEDColor(255, 255, 0)
+#endif
+#define LEDColorGreen() LEDColor( 0, 255, 0)
+#define LEDColorBlue() LEDColor( 0, 0, 255)
+#define LEDColorIndigo() LEDColor( 0, 255, 255)
+#define LEDColorViolet() LEDColor(255, 0, 255)
+#if HAS_WHITE_LED && DISABLED(RGB_LED)
+ #define LEDColorWhite() LEDColor( 0, 0, 0, 255)
+#else
+ #define LEDColorWhite() LEDColor(255, 255, 255)
+#endif
+
+class LEDLights {
+public:
+ LEDLights() {} // ctor
+
+ static void setup(); // init()
+
+ static void set_color(const LEDColor &color
+ #if ENABLED(NEOPIXEL_LED)
+ , bool isSequence=false
+ #endif
+ );
+
+ static inline void set_color(uint8_t r, uint8_t g, uint8_t b
+ #if HAS_WHITE_LED
+ , uint8_t w=0
+ #endif
+ #if ENABLED(NEOPIXEL_LED)
+ , uint8_t i=NEOPIXEL_BRIGHTNESS
+ , bool isSequence=false
+ #endif
+ ) {
+ set_color(MakeLEDColor(r, g, b, w, i)
+ #if ENABLED(NEOPIXEL_LED)
+ , isSequence
+ #endif
+ );
+ }
+
+ static inline void set_off() { set_color(LEDColorOff()); }
+ static inline void set_green() { set_color(LEDColorGreen()); }
+ static inline void set_white() { set_color(LEDColorWhite()); }
+
+ #if ENABLED(LED_COLOR_PRESETS)
+ static const LEDColor defaultLEDColor;
+ static inline void set_default() { set_color(defaultLEDColor); }
+ static inline void set_red() { set_color(LEDColorRed()); }
+ static inline void set_orange() { set_color(LEDColorOrange()); }
+ static inline void set_yellow() { set_color(LEDColorYellow()); }
+ static inline void set_blue() { set_color(LEDColorBlue()); }
+ static inline void set_indigo() { set_color(LEDColorIndigo()); }
+ static inline void set_violet() { set_color(LEDColorViolet()); }
+ #endif
+
+ #if ENABLED(PRINTER_EVENT_LEDS)
+ static inline LEDColor get_color() { return lights_on ? color : LEDColorOff(); }
+ #endif
+
+ #if EITHER(LED_CONTROL_MENU, PRINTER_EVENT_LEDS)
+ static LEDColor color; // last non-off color
+ static bool lights_on; // the last set color was "on"
+ #endif
+
+ #if ENABLED(LED_CONTROL_MENU)
+ static void toggle(); // swap "off" with color
+ static inline void update() { set_color(color); }
+ #endif
+
+ #ifdef LED_BACKLIGHT_TIMEOUT
+ private:
+ static millis_t led_off_time;
+ public:
+ static inline void reset_timeout(const millis_t &ms) {
+ led_off_time = ms + LED_BACKLIGHT_TIMEOUT;
+ if (!lights_on) set_default();
+ }
+ static void update_timeout(const bool power_on);
+ #endif
+};
+
+extern LEDLights leds;
+
+#if ENABLED(NEOPIXEL2_SEPARATE)
+
+ class LEDLights2 {
+ public:
+ LEDLights2() {}
+
+ static void setup(); // init()
+
+ static void set_color(const LEDColor &color);
+
+ inline void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0, uint8_t i=NEOPIXEL2_BRIGHTNESS) {
+ set_color(MakeLEDColor(r, g, b, w, i));
+ }
+
+ static inline void set_off() { set_color(LEDColorOff()); }
+ static inline void set_green() { set_color(LEDColorGreen()); }
+ static inline void set_white() { set_color(LEDColorWhite()); }
+
+ #if ENABLED(NEO2_COLOR_PRESETS)
+ static const LEDColor defaultLEDColor;
+ static inline void set_default() { set_color(defaultLEDColor); }
+ static inline void set_red() { set_color(LEDColorRed()); }
+ static inline void set_orange() { set_color(LEDColorOrange()); }
+ static inline void set_yellow() { set_color(LEDColorYellow()); }
+ static inline void set_blue() { set_color(LEDColorBlue()); }
+ static inline void set_indigo() { set_color(LEDColorIndigo()); }
+ static inline void set_violet() { set_color(LEDColorViolet()); }
+ #endif
+
+ #if ENABLED(NEOPIXEL2_SEPARATE)
+ static LEDColor color; // last non-off color
+ static bool lights_on; // the last set color was "on"
+ static void toggle(); // swap "off" with color
+ static inline void update() { set_color(color); }
+ #endif
+ };
+
+ extern LEDLights2 leds2;
+
+#endif // NEOPIXEL2_SEPARATE
diff --git a/Marlin/src/feature/leds/neopixel.cpp b/Marlin/src/feature/leds/neopixel.cpp
new file mode 100644
index 0000000..27bbeb3
--- /dev/null
+++ b/Marlin/src/feature/leds/neopixel.cpp
@@ -0,0 +1,172 @@
+/**
+ * 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/>.
+ *
+ */
+
+/**
+ * Marlin RGB LED general support
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(NEOPIXEL_LED)
+
+#include "neopixel.h"
+
+#if EITHER(NEOPIXEL_STARTUP_TEST, NEOPIXEL2_STARTUP_TEST)
+ #include "../../core/utility.h"
+#endif
+
+Marlin_NeoPixel neo;
+int8_t Marlin_NeoPixel::neoindex;
+
+Adafruit_NeoPixel Marlin_NeoPixel::adaneo1(NEOPIXEL_PIXELS, NEOPIXEL_PIN, NEOPIXEL_TYPE + NEO_KHZ800)
+ #if CONJOINED_NEOPIXEL
+ , Marlin_NeoPixel::adaneo2(NEOPIXEL_PIXELS, NEOPIXEL2_PIN, NEOPIXEL2_TYPE + NEO_KHZ800)
+ #endif
+;
+
+#ifdef NEOPIXEL_BKGD_LED_INDEX
+
+ void Marlin_NeoPixel::set_color_background() {
+ uint8_t background_color[4] = NEOPIXEL_BKGD_COLOR;
+ set_pixel_color(NEOPIXEL_BKGD_LED_INDEX, adaneo1.Color(background_color[0], background_color[1], background_color[2], background_color[3]));
+ }
+
+#endif
+
+void Marlin_NeoPixel::set_color(const uint32_t color) {
+ if (neoindex >= 0) {
+ set_pixel_color(neoindex, color);
+ neoindex = -1;
+ }
+ else {
+ for (uint16_t i = 0; i < pixels(); ++i) {
+ #ifdef NEOPIXEL_BKGD_LED_INDEX
+ if (i == NEOPIXEL_BKGD_LED_INDEX && color != 0x000000) {
+ set_color_background();
+ continue;
+ }
+ #endif
+ set_pixel_color(i, color);
+ }
+ }
+ show();
+}
+
+void Marlin_NeoPixel::set_color_startup(const uint32_t color) {
+ for (uint16_t i = 0; i < pixels(); ++i)
+ set_pixel_color(i, color);
+ show();
+}
+
+void Marlin_NeoPixel::init() {
+ neoindex = -1; // -1 .. NEOPIXEL_PIXELS-1 range
+ set_brightness(NEOPIXEL_BRIGHTNESS); // 0 .. 255 range
+ begin();
+ show(); // initialize to all off
+
+ #if ENABLED(NEOPIXEL_STARTUP_TEST)
+ set_color_startup(adaneo1.Color(255, 0, 0, 0)); // red
+ safe_delay(500);
+ set_color_startup(adaneo1.Color(0, 255, 0, 0)); // green
+ safe_delay(500);
+ set_color_startup(adaneo1.Color(0, 0, 255, 0)); // blue
+ safe_delay(500);
+ #endif
+
+ #ifdef NEOPIXEL_BKGD_LED_INDEX
+ set_color_background();
+ #endif
+
+ #if ENABLED(LED_USER_PRESET_STARTUP)
+ set_color(adaneo1.Color(LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE, LED_USER_PRESET_WHITE));
+ #else
+ set_color(adaneo1.Color(0, 0, 0, 0));
+ #endif
+}
+
+#if 0
+bool Marlin_NeoPixel::set_led_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t w, const uint8_t p) {
+ const uint32_t color = adaneo1.Color(r, g, b, w);
+ set_brightness(p);
+ #if DISABLED(NEOPIXEL_IS_SEQUENTIAL)
+ set_color(color);
+ return false;
+ #else
+ static uint16_t nextLed = 0;
+ set_pixel_color(nextLed, color);
+ show();
+ if (++nextLed >= pixels()) nextLed = 0;
+ return true;
+ #endif
+}
+#endif
+
+#if ENABLED(NEOPIXEL2_SEPARATE)
+
+ Marlin_NeoPixel2 neo2;
+
+ int8_t Marlin_NeoPixel2::neoindex;
+ Adafruit_NeoPixel Marlin_NeoPixel2::adaneo(NEOPIXEL2_PIXELS, NEOPIXEL2_PIN, NEOPIXEL2_TYPE);
+
+ void Marlin_NeoPixel2::set_color(const uint32_t color) {
+ if (neoindex >= 0) {
+ set_pixel_color(neoindex, color);
+ neoindex = -1;
+ }
+ else {
+ for (uint16_t i = 0; i < pixels(); ++i)
+ set_pixel_color(i, color);
+ }
+ show();
+ }
+
+ void Marlin_NeoPixel2::set_color_startup(const uint32_t color) {
+ for (uint16_t i = 0; i < pixels(); ++i)
+ set_pixel_color(i, color);
+ show();
+ }
+
+ void Marlin_NeoPixel2::init() {
+ neoindex = -1; // -1 .. NEOPIXEL2_PIXELS-1 range
+ set_brightness(NEOPIXEL2_BRIGHTNESS); // 0 .. 255 range
+ begin();
+ show(); // initialize to all off
+
+ #if ENABLED(NEOPIXEL2_STARTUP_TEST)
+ set_color_startup(adaneo.Color(255, 0, 0, 0)); // red
+ safe_delay(500);
+ set_color_startup(adaneo.Color(0, 255, 0, 0)); // green
+ safe_delay(500);
+ set_color_startup(adaneo.Color(0, 0, 255, 0)); // blue
+ safe_delay(500);
+ #endif
+
+ #if ENABLED(NEO2_USER_PRESET_STARTUP)
+ set_color(adaneo.Color(NEO2_USER_PRESET_RED, NEO2_USER_PRESET_GREEN, NEO2_USER_PRESET_BLUE, NEO2_USER_PRESET_WHITE));
+ #else
+ set_color(adaneo.Color(0, 0, 0, 0));
+ #endif
+ }
+
+#endif // NEOPIXEL2_SEPARATE
+
+#endif // NEOPIXEL_LED
diff --git a/Marlin/src/feature/leds/neopixel.h b/Marlin/src/feature/leds/neopixel.h
new file mode 100644
index 0000000..acf2e7f
--- /dev/null
+++ b/Marlin/src/feature/leds/neopixel.h
@@ -0,0 +1,182 @@
+/**
+ * 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
+
+/**
+ * NeoPixel support
+ */
+
+// ------------------------
+// Includes
+// ------------------------
+
+#include "../../inc/MarlinConfig.h"
+
+#include <Adafruit_NeoPixel.h>
+#include <stdint.h>
+
+// ------------------------
+// Defines
+// ------------------------
+
+#if defined(NEOPIXEL2_TYPE) && NEOPIXEL2_TYPE != NEOPIXEL_TYPE && DISABLED(NEOPIXEL2_SEPARATE)
+ #define MULTIPLE_NEOPIXEL_TYPES 1
+#endif
+
+#if EITHER(MULTIPLE_NEOPIXEL_TYPES, NEOPIXEL2_INSERIES)
+ #define CONJOINED_NEOPIXEL 1
+#endif
+
+#if NEOPIXEL_TYPE == NEO_RGB || NEOPIXEL_TYPE == NEO_RBG || NEOPIXEL_TYPE == NEO_GRB || NEOPIXEL_TYPE == NEO_GBR || NEOPIXEL_TYPE == NEO_BRG || NEOPIXEL_TYPE == NEO_BGR
+ #define NEOPIXEL_IS_RGB 1
+#else
+ #define NEOPIXEL_IS_RGBW 1
+#endif
+
+#if NEOPIXEL_IS_RGB
+ #define NEO_WHITE 255, 255, 255, 0
+#else
+ #define NEO_WHITE 0, 0, 0, 255
+#endif
+
+// ------------------------
+// Function prototypes
+// ------------------------
+
+class Marlin_NeoPixel {
+private:
+ static Adafruit_NeoPixel adaneo1
+ #if CONJOINED_NEOPIXEL
+ , adaneo2
+ #endif
+ ;
+
+public:
+ static int8_t neoindex;
+
+ static void init();
+ static void set_color_startup(const uint32_t c);
+
+ static void set_color(const uint32_t c);
+
+ #ifdef NEOPIXEL_BKGD_LED_INDEX
+ static void set_color_background();
+ #endif
+
+ static inline void begin() {
+ adaneo1.begin();
+ TERN_(CONJOINED_NEOPIXEL, adaneo2.begin());
+ }
+
+ static inline void set_pixel_color(const uint16_t n, const uint32_t c) {
+ #if ENABLED(NEOPIXEL2_INSERIES)
+ if (n >= NEOPIXEL_PIXELS) adaneo2.setPixelColor(n - (NEOPIXEL_PIXELS), c);
+ else adaneo1.setPixelColor(n, c);
+ #else
+ adaneo1.setPixelColor(n, c);
+ #if MULTIPLE_NEOPIXEL_TYPES
+ adaneo2.setPixelColor(n, c);
+ #endif
+ #endif
+ }
+
+ static inline void set_brightness(const uint8_t b) {
+ adaneo1.setBrightness(b);
+ TERN_(CONJOINED_NEOPIXEL, adaneo2.setBrightness(b));
+ }
+
+ static inline void show() {
+ // Some platforms cannot maintain PWM output when NeoPixel disables interrupts for long durations.
+ TERN_(HAS_PAUSE_SERVO_OUTPUT, PAUSE_SERVO_OUTPUT());
+ adaneo1.show();
+ #if PIN_EXISTS(NEOPIXEL2)
+ #if CONJOINED_NEOPIXEL
+ adaneo2.show();
+ #else
+ IF_DISABLED(NEOPIXEL2_SEPARATE, adaneo1.setPin(NEOPIXEL2_PIN));
+ adaneo1.show();
+ adaneo1.setPin(NEOPIXEL_PIN);
+ #endif
+ #endif
+ TERN_(HAS_PAUSE_SERVO_OUTPUT, RESUME_SERVO_OUTPUT());
+ }
+
+ #if 0
+ bool set_led_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t w, const uint8_t p);
+ #endif
+
+ // Accessors
+ static inline uint16_t pixels() { TERN(NEOPIXEL2_INSERIES, return adaneo1.numPixels() * 2, return adaneo1.numPixels()); }
+ static inline uint8_t brightness() { return adaneo1.getBrightness(); }
+ static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
+ return adaneo1.Color(r, g, b, w);
+ }
+};
+
+extern Marlin_NeoPixel neo;
+
+// Neo pixel channel 2
+#if ENABLED(NEOPIXEL2_SEPARATE)
+
+ #if NEOPIXEL2_TYPE == NEO_RGB || NEOPIXEL2_TYPE == NEO_RBG || NEOPIXEL2_TYPE == NEO_GRB || NEOPIXEL2_TYPE == NEO_GBR || NEOPIXEL2_TYPE == NEO_BRG || NEOPIXEL2_TYPE == NEO_BGR
+ #define NEOPIXEL2_IS_RGB 1
+ #else
+ #define NEOPIXEL2_IS_RGBW 1
+ #endif
+
+ #if NEOPIXEL2_IS_RGB
+ #define NEO2_WHITE 255, 255, 255, 0
+ #else
+ #define NEO2_WHITE 0, 0, 0, 255
+ #endif
+
+ class Marlin_NeoPixel2 {
+ private:
+ static Adafruit_NeoPixel adaneo;
+
+ public:
+ static int8_t neoindex;
+
+ static void init();
+ static void set_color_startup(const uint32_t c);
+
+ static void set_color(const uint32_t c);
+
+ static inline void begin() { adaneo.begin(); }
+ static inline void set_pixel_color(const uint16_t n, const uint32_t c) { adaneo.setPixelColor(n, c); }
+ static inline void set_brightness(const uint8_t b) { adaneo.setBrightness(b); }
+ static inline void show() {
+ adaneo.show();
+ adaneo.setPin(NEOPIXEL2_PIN);
+ }
+
+ // Accessors
+ static inline uint16_t pixels() { return adaneo.numPixels();}
+ static inline uint8_t brightness() { return adaneo.getBrightness(); }
+ static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
+ return adaneo.Color(r, g, b, w);
+ }
+ };
+
+ extern Marlin_NeoPixel2 neo2;
+
+#endif // NEOPIXEL2_SEPARATE
diff --git a/Marlin/src/feature/leds/pca9533.cpp b/Marlin/src/feature/leds/pca9533.cpp
new file mode 100644
index 0000000..0fd4d66
--- /dev/null
+++ b/Marlin/src/feature/leds/pca9533.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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/>.
+ *
+ */
+
+/**
+ * PCA9533 LED controller driver (MightyBoard, FlashForge Creator Pro, etc.)
+ * by @grauerfuchs - 1 Apr 2020
+ */
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(PCA9533)
+
+#include "pca9533.h"
+#include <Wire.h>
+
+void PCA9533_init() {
+ Wire.begin();
+ PCA9533_reset();
+}
+
+static void PCA9533_writeAllRegisters(uint8_t psc0, uint8_t pwm0, uint8_t psc1, uint8_t pwm1, uint8_t ls0){
+ uint8_t data[6] = { PCA9533_REG_PSC0 | PCA9533_REGM_AI, psc0, pwm0, psc1, pwm1, ls0 };
+ Wire.beginTransmission(PCA9533_Addr >> 1);
+ Wire.write(data, 6);
+ Wire.endTransmission();
+ delayMicroseconds(1);
+}
+
+static void PCA9533_writeRegister(uint8_t reg, uint8_t val){
+ uint8_t data[2] = { reg, val };
+ Wire.beginTransmission(PCA9533_Addr >> 1);
+ Wire.write(data, 2);
+ Wire.endTransmission();
+ delayMicroseconds(1);
+}
+
+// Reset (clear) all registers
+void PCA9533_reset() {
+ PCA9533_writeAllRegisters(0, 0, 0, 0, 0);
+}
+
+// Turn all LEDs off
+void PCA9533_setOff() {
+ PCA9533_writeRegister(PCA9533_REG_SEL, 0);
+}
+
+void PCA9533_set_rgb(uint8_t red, uint8_t green, uint8_t blue) {
+ uint8_t r_pwm0 = 0; // Register data - PWM value
+ uint8_t r_pwm1 = 0; // Register data - PWM value
+
+ uint8_t op_g = 0, op_r = 0, op_b = 0; // Opcodes - Green, Red, Blue
+
+ // Light theory! GREEN takes priority because
+ // it's the most visible to the human eye.
+ if (green == 0) op_g = PCA9533_LED_OP_OFF;
+ else if (green == 255) op_g = PCA9533_LED_OP_ON;
+ else { r_pwm0 = green; op_g = PCA9533_LED_OP_PWM0; }
+
+ // RED
+ if (red == 0) op_r = PCA9533_LED_OP_OFF;
+ else if (red == 255) op_r = PCA9533_LED_OP_ON;
+ else if (r_pwm0 == 0 || r_pwm0 == red) {
+ r_pwm0 = red; op_r = PCA9533_LED_OP_PWM0;
+ }
+ else {
+ r_pwm1 = red; op_r = PCA9533_LED_OP_PWM1;
+ }
+
+ // BLUE
+ if (blue == 0) op_b = PCA9533_LED_OP_OFF;
+ else if (blue == 255) op_b = PCA9533_LED_OP_ON;
+ else if (r_pwm0 == 0 || r_pwm0 == blue) {
+ r_pwm0 = blue; op_b = PCA9533_LED_OP_PWM0;
+ }
+ else if (r_pwm1 == 0 || r_pwm1 == blue) {
+ r_pwm1 = blue; op_b = PCA9533_LED_OP_PWM1;
+ }
+ else {
+ /**
+ * Conflict. 3 values are requested but only 2 channels exist.
+ * G is on channel 0 and R is on channel 1, so work from there.
+ * Find the closest match, average the values, then use the free channel.
+ */
+ uint8_t dgb = ABS(green - blue),
+ dgr = ABS(green - red),
+ dbr = ABS(blue - red);
+ if (dgb < dgr && dgb < dbr) { // Mix with G on channel 0.
+ op_b = PCA9533_LED_OP_PWM0;
+ r_pwm0 = uint8_t(((uint16_t)green + (uint16_t)blue) / 2);
+ }
+ else if (dbr <= dgr && dbr <= dgb) { // Mix with R on channel 1.
+ op_b = PCA9533_LED_OP_PWM1;
+ r_pwm1 = uint8_t(((uint16_t)red + (uint16_t)blue) / 2);
+ }
+ else { // Mix R+G on 0 and put B on 1.
+ op_r = PCA9533_LED_OP_PWM0;
+ r_pwm0 = uint8_t(((uint16_t)green + (uint16_t)red) / 2);
+ op_b = PCA9533_LED_OP_PWM1;
+ r_pwm1 = blue;
+ }
+ }
+
+ // Write the changes to the hardware
+ PCA9533_writeAllRegisters(0, r_pwm0, 0, r_pwm1,
+ (op_g << PCA9533_LED_OFS_GRN) | (op_r << PCA9533_LED_OFS_RED) | (op_b << PCA9533_LED_OFS_BLU)
+ );
+}
+
+#endif // PCA9533
diff --git a/Marlin/src/feature/leds/pca9533.h b/Marlin/src/feature/leds/pca9533.h
new file mode 100644
index 0000000..431058c
--- /dev/null
+++ b/Marlin/src/feature/leds/pca9533.h
@@ -0,0 +1,59 @@
+/*
+ * 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
+
+/*
+ * Driver for the PCA9533 LED controller found on the MightyBoard
+ * used by FlashForge Creator Pro, MakerBot, etc.
+ * Written 2020 APR 01 by grauerfuchs
+ */
+#include <Arduino.h>
+
+#define ENABLE_I2C_PULLUPS
+
+// Chip address (for Wire)
+#define PCA9533_Addr 0xC4
+
+// Control registers
+#define PCA9533_REG_READ 0x00
+#define PCA9533_REG_PSC0 0x01
+#define PCA9533_REG_PWM0 0x02
+#define PCA9533_REG_PSC1 0x03
+#define PCA9533_REG_PWM1 0x04
+#define PCA9533_REG_SEL 0x05
+#define PCA9533_REGM_AI 0x10
+
+// LED selector operation
+#define PCA9533_LED_OP_OFF 0B00
+#define PCA9533_LED_OP_ON 0B01
+#define PCA9533_LED_OP_PWM0 0B10
+#define PCA9533_LED_OP_PWM1 0B11
+
+// Select register bit offsets for LED colors
+#define PCA9533_LED_OFS_RED 0
+#define PCA9533_LED_OFS_GRN 2
+#define PCA9533_LED_OFS_BLU 4
+
+void PCA9533_init();
+void PCA9533_reset();
+void PCA9533_set_rgb(uint8_t red, uint8_t green, uint8_t blue);
+void PCA9533_setOff();
diff --git a/Marlin/src/feature/leds/pca9632.cpp b/Marlin/src/feature/leds/pca9632.cpp
new file mode 100644
index 0000000..bb30e0b
--- /dev/null
+++ b/Marlin/src/feature/leds/pca9632.cpp
@@ -0,0 +1,164 @@
+/**
+ * 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/>.
+ *
+ */
+
+/**
+ * Driver for the Philips PCA9632 LED driver.
+ * Written by Robert Mendon Feb 2017.
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(PCA9632)
+
+#include "pca9632.h"
+#include "leds.h"
+#include <Wire.h>
+
+#define PCA9632_MODE1_VALUE 0b00000001 //(ALLCALL)
+#define PCA9632_MODE2_VALUE 0b00010101 //(DIMMING, INVERT, CHANGE ON STOP,TOTEM)
+#define PCA9632_LEDOUT_VALUE 0b00101010
+
+/* Register addresses */
+#define PCA9632_MODE1 0x00
+#define PCA9632_MODE2 0x01
+#define PCA9632_PWM0 0x02
+#define PCA9632_PWM1 0x03
+#define PCA9632_PWM2 0x04
+#define PCA9632_PWM3 0x05
+#define PCA9632_GRPPWM 0x06
+#define PCA9632_GRPFREQ 0x07
+#define PCA9632_LEDOUT 0x08
+#define PCA9632_SUBADR1 0x09
+#define PCA9632_SUBADR2 0x0A
+#define PCA9632_SUBADR3 0x0B
+#define PCA9632_ALLCALLADDR 0x0C
+
+#define PCA9632_NO_AUTOINC 0x00
+#define PCA9632_AUTO_ALL 0x80
+#define PCA9632_AUTO_IND 0xA0
+#define PCA9632_AUTOGLO 0xC0
+#define PCA9632_AUTOGI 0xE0
+
+// Red=LED0 Green=LED1 Blue=LED2 White=LED3
+#ifndef PCA9632_RED
+ #define PCA9632_RED 0x00
+#endif
+#ifndef PCA9632_GRN
+ #define PCA9632_GRN 0x02
+#endif
+#ifndef PCA9632_BLU
+ #define PCA9632_BLU 0x04
+#endif
+#if HAS_WHITE_LED && !defined(PCA9632_WHT)
+ #define PCA9632_WHT 0x06
+#endif
+
+// If any of the color indexes are greater than 0x04 they can't use auto increment
+#if !defined(PCA9632_NO_AUTO_INC) && (PCA9632_RED > 0x04 || PCA9632_GRN > 0x04 || PCA9632_BLU > 0x04 || PCA9632_WHT > 0x04)
+ #define PCA9632_NO_AUTO_INC
+#endif
+
+#define LED_OFF 0x00
+#define LED_ON 0x01
+#define LED_PWM 0x02
+
+#define PCA9632_ADDRESS 0b01100000
+
+byte PCA_init = 0;
+
+static void PCA9632_WriteRegister(const byte addr, const byte regadd, const byte value) {
+ Wire.beginTransmission(I2C_ADDRESS(addr));
+ Wire.write(regadd);
+ Wire.write(value);
+ Wire.endTransmission();
+}
+
+static void PCA9632_WriteAllRegisters(const byte addr, const byte regadd, const byte vr, const byte vg, const byte vb
+ #if ENABLED(PCA9632_RGBW)
+ , const byte vw
+ #endif
+) {
+ #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_GRN >> 1)] = vg;
+ data[1 + (PCA9632_BLU >> 1)] = 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_GRN >> 1), vg);
+ PCA9632_WriteRegister(addr, regadd + (PCA9632_BLU >> 1), vb);
+ #if ENABLED(PCA9632_RGBW)
+ PCA9632_WriteRegister(addr, regadd + (PCA9632_WHT >> 1), vw);
+ #endif
+ #endif
+}
+
+#if 0
+ static byte PCA9632_ReadRegister(const byte addr, const byte regadd) {
+ Wire.beginTransmission(I2C_ADDRESS(addr));
+ Wire.write(regadd);
+ const byte value = Wire.read();
+ Wire.endTransmission();
+ return value;
+ }
+#endif
+
+void PCA9632_set_led_color(const LEDColor &color) {
+ Wire.begin();
+ if (!PCA_init) {
+ PCA_init = 1;
+ PCA9632_WriteRegister(PCA9632_ADDRESS,PCA9632_MODE1, PCA9632_MODE1_VALUE);
+ PCA9632_WriteRegister(PCA9632_ADDRESS,PCA9632_MODE2, PCA9632_MODE2_VALUE);
+ }
+
+ const byte LEDOUT = (color.r ? LED_PWM << PCA9632_RED : 0)
+ | (color.g ? LED_PWM << PCA9632_GRN : 0)
+ | (color.b ? LED_PWM << PCA9632_BLU : 0)
+ #if ENABLED(PCA9632_RGBW)
+ | (color.w ? LED_PWM << PCA9632_WHT : 0)
+ #endif
+ ;
+
+ PCA9632_WriteAllRegisters(PCA9632_ADDRESS,PCA9632_PWM0, color.r, color.g, color.b
+ #if ENABLED(PCA9632_RGBW)
+ , color.w
+ #endif
+ );
+ PCA9632_WriteRegister(PCA9632_ADDRESS,PCA9632_LEDOUT, LEDOUT);
+}
+
+#if ENABLED(PCA9632_BUZZER)
+
+ void PCA9632_buzz(const long, const uint16_t) {
+ uint8_t data[] = PCA9632_BUZZER_DATA;
+ Wire.beginTransmission(I2C_ADDRESS(PCA9632_ADDRESS));
+ Wire.write(data, sizeof(data));
+ Wire.endTransmission();
+ }
+
+#endif // PCA9632_BUZZER
+
+#endif // PCA9632
diff --git a/Marlin/src/feature/leds/pca9632.h b/Marlin/src/feature/leds/pca9632.h
new file mode 100644
index 0000000..fb59a8c
--- /dev/null
+++ b/Marlin/src/feature/leds/pca9632.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
+
+/**
+ * Driver for the Philips PCA9632 LED driver.
+ * Written by Robert Mendon Feb 2017.
+ */
+
+struct LEDColor;
+typedef LEDColor LEDColor;
+
+void PCA9632_set_led_color(const LEDColor &color);
+
+#if ENABLED(PCA9632_BUZZER)
+ #include <stdint.h>
+ void PCA9632_buzz(const long, const uint16_t);
+#endif
diff --git a/Marlin/src/feature/leds/printer_event_leds.cpp b/Marlin/src/feature/leds/printer_event_leds.cpp
new file mode 100644
index 0000000..3a6b91a
--- /dev/null
+++ b/Marlin/src/feature/leds/printer_event_leds.cpp
@@ -0,0 +1,82 @@
+/**
+ * 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/>.
+ *
+ */
+
+/**
+ * feature/leds/printer_event_leds.cpp - LED color changing based on printer status
+ */
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if ENABLED(PRINTER_EVENT_LEDS)
+
+#include "printer_event_leds.h"
+
+PrinterEventLEDs printerEventLEDs;
+
+#if HAS_LEDS_OFF_FLAG
+ bool PrinterEventLEDs::leds_off_after_print; // = false
+#endif
+
+#if HAS_TEMP_HOTEND || HAS_HEATED_BED
+
+ uint8_t PrinterEventLEDs::old_intensity = 0;
+
+ inline uint8_t pel_intensity(const float &start, const float &current, const float &target) {
+ if (uint16_t(start) == uint16_t(target)) return 255;
+ return (uint8_t)map(constrain(current, start, target), start, target, 0.f, 255.f);
+ }
+
+ inline void pel_set_rgb(const uint8_t r, const uint8_t g, const uint8_t b) {
+ leds.set_color(
+ MakeLEDColor(r, g, b, 0, neo.brightness())
+ #if ENABLED(NEOPIXEL_IS_SEQUENTIAL)
+ , true
+ #endif
+ );
+ }
+
+#endif
+
+#if HAS_TEMP_HOTEND
+
+ void PrinterEventLEDs::onHotendHeating(const float &start, const float &current, const float &target) {
+ const uint8_t blue = pel_intensity(start, current, target);
+ if (blue != old_intensity) {
+ old_intensity = blue;
+ pel_set_rgb(255, 0, 255 - blue);
+ }
+ }
+
+#endif
+
+#if HAS_HEATED_BED
+
+ void PrinterEventLEDs::onBedHeating(const float &start, const float &current, const float &target) {
+ const uint8_t red = pel_intensity(start, current, target);
+ if (red != old_intensity) {
+ old_intensity = red;
+ pel_set_rgb(red, 0, 255);
+ }
+ }
+#endif
+
+#endif // PRINTER_EVENT_LEDS
diff --git a/Marlin/src/feature/leds/printer_event_leds.h b/Marlin/src/feature/leds/printer_event_leds.h
new file mode 100644
index 0000000..86ec292
--- /dev/null
+++ b/Marlin/src/feature/leds/printer_event_leds.h
@@ -0,0 +1,87 @@
+/**
+ * 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
+
+/**
+ * feature/leds/printer_event_leds.h - LED color changing based on printer status
+ */
+
+#include "leds.h"
+#include "../../inc/MarlinConfig.h"
+
+class PrinterEventLEDs {
+private:
+ static uint8_t old_intensity;
+
+ #if HAS_LEDS_OFF_FLAG
+ static bool leds_off_after_print;
+ #endif
+
+ static inline void set_done() {
+ #if ENABLED(LED_COLOR_PRESETS)
+ leds.set_default();
+ #else
+ leds.set_off();
+ #endif
+ }
+
+public:
+ #if HAS_TEMP_HOTEND
+ static inline LEDColor onHotendHeatingStart() { old_intensity = 0; return leds.get_color(); }
+ static void onHotendHeating(const float &start, const float &current, const float &target);
+ #endif
+
+ #if HAS_HEATED_BED
+ static inline LEDColor onBedHeatingStart() { old_intensity = 127; return leds.get_color(); }
+ static void onBedHeating(const float &start, const float &current, const float &target);
+ #endif
+
+ #if HAS_TEMP_HOTEND || HAS_HEATED_BED
+ static inline void onHeatingDone() { leds.set_white(); }
+ static inline void onPidTuningDone(LEDColor c) { leds.set_color(c); }
+ #endif
+
+ #if ENABLED(SDSUPPORT)
+
+ static inline void onPrintCompleted() {
+ leds.set_green();
+ #if HAS_LEDS_OFF_FLAG
+ leds_off_after_print = true;
+ #else
+ safe_delay(2000);
+ set_done();
+ #endif
+ }
+
+ static inline void onResumeAfterWait() {
+ #if HAS_LEDS_OFF_FLAG
+ if (leds_off_after_print) {
+ set_done();
+ leds_off_after_print = false;
+ }
+ #endif
+ }
+
+ #endif // SDSUPPORT
+};
+
+extern PrinterEventLEDs printerEventLEDs;
diff --git a/Marlin/src/feature/leds/tempstat.cpp b/Marlin/src/feature/leds/tempstat.cpp
new file mode 100644
index 0000000..880258f
--- /dev/null
+++ b/Marlin/src/feature/leds/tempstat.cpp
@@ -0,0 +1,55 @@
+/**
+ * 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/>.
+ *
+ */
+
+/**
+ * Marlin RGB LED general support
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(TEMP_STAT_LEDS)
+
+#include "tempstat.h"
+#include "../../module/temperature.h"
+
+void handle_status_leds() {
+ static int8_t old_red = -1; // Invalid value to force LED initialization
+ static millis_t next_status_led_update_ms = 0;
+ if (ELAPSED(millis(), next_status_led_update_ms)) {
+ next_status_led_update_ms += 500; // Update every 0.5s
+ float max_temp = TERN0(HAS_HEATED_BED, _MAX(thermalManager.degTargetBed(), thermalManager.degBed()));
+ HOTEND_LOOP()
+ max_temp = _MAX(max_temp, thermalManager.degHotend(e), thermalManager.degTargetHotend(e));
+ const int8_t new_red = (max_temp > 55.0) ? HIGH : (max_temp < 54.0 || old_red < 0) ? LOW : old_red;
+ if (new_red != old_red) {
+ old_red = new_red;
+ #if PIN_EXISTS(STAT_LED_RED)
+ WRITE(STAT_LED_RED_PIN, new_red);
+ #endif
+ #if PIN_EXISTS(STAT_LED_BLUE)
+ WRITE(STAT_LED_BLUE_PIN, !new_red);
+ #endif
+ }
+ }
+}
+
+#endif // TEMP_STAT_LEDS
diff --git a/Marlin/src/feature/leds/tempstat.h b/Marlin/src/feature/leds/tempstat.h
new file mode 100644
index 0000000..a8b919b
--- /dev/null
+++ b/Marlin/src/feature/leds/tempstat.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
+
+/**
+ * Marlin general RGB LED support
+ */
+
+void handle_status_leds();