diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 089917c14..839d51e93 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -284,17 +284,8 @@ #include "Max7219_Debug_LEDs.h" #endif -#if ENABLED(NEOPIXEL_LED) - #include -#endif - -#if ENABLED(BLINKM) - #include "blinkm.h" - #include "Wire.h" -#endif - -#if ENABLED(PCA9632) - #include "pca9632.h" +#if HAS_COLOR_LEDS + #include "leds.h" #endif #if HAS_SERVOS @@ -331,32 +322,6 @@ void gcode_G26(); #endif -#if ENABLED(LED_CONTROL_MENU) - #if ENABLED(LED_COLOR_PRESETS) - uint8_t led_intensity_red = LED_USER_PRESET_RED, - led_intensity_green = LED_USER_PRESET_GREEN, - led_intensity_blue = LED_USER_PRESET_BLUE - #if ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED) - , led_intensity_white = LED_USER_PRESET_WHITE - #endif - #if ENABLED(NEOPIXEL_LED) - , led_intensity = NEOPIXEL_BRIGHTNESS - #endif - ; - #else - uint8_t led_intensity_red = 255, - led_intensity_green = 255, - led_intensity_blue = 255 - #if ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED) - , led_intensity_white = 0 - #endif - #if ENABLED(NEOPIXEL_LED) - , led_intensity = NEOPIXEL_BRIGHTNESS - #endif - ; - #endif -#endif - #if ENABLED(SDSUPPORT) CardReader card; #endif @@ -381,20 +346,6 @@ || isnan(ubl.z_values[0][0])) #endif -#if ENABLED(NEOPIXEL_LED) - #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 NEO_WHITE 255, 255, 255 - #else - #define NEO_WHITE 0, 0, 0, 255 - #endif -#endif - -#if ENABLED(RGB_LED) || ENABLED(BLINKM) || ENABLED(PCA9632) - #define LED_WHITE 255, 255, 255 -#elif ENABLED(RGBW_LED) - #define LED_WHITE 0, 0, 0, 255 -#endif - #if ENABLED(CNC_COORDINATE_SYSTEMS) int8_t active_coordinate_system = -1; // machine space float coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ]; @@ -1039,124 +990,6 @@ void servo_init() { #endif -#if HAS_COLOR_LEDS - - #if ENABLED(NEOPIXEL_LED) - - Adafruit_NeoPixel pixels(NEOPIXEL_PIXELS, NEOPIXEL_PIN, NEOPIXEL_TYPE + NEO_KHZ800); - - void set_neopixel_color(const uint32_t color) { - for (uint16_t i = 0; i < pixels.numPixels(); ++i) - pixels.setPixelColor(i, color); - pixels.show(); - } - - void setup_neopixel() { - pixels.setBrightness(NEOPIXEL_BRIGHTNESS); // 0 - 255 range - pixels.begin(); - pixels.show(); // initialize to all off - - #if ENABLED(NEOPIXEL_STARTUP_TEST) - safe_delay(1000); - set_neopixel_color(pixels.Color(255, 0, 0, 0)); // red - safe_delay(1000); - set_neopixel_color(pixels.Color(0, 255, 0, 0)); // green - safe_delay(1000); - set_neopixel_color(pixels.Color(0, 0, 255, 0)); // blue - safe_delay(1000); - #endif - set_neopixel_color(pixels.Color(NEO_WHITE)); // white - } - - #endif // NEOPIXEL_LED - - void set_led_color( - const uint8_t r, const uint8_t g, const uint8_t b - #if ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED) - , const uint8_t w = 0 - #if ENABLED(NEOPIXEL_LED) - , const uint8_t p = NEOPIXEL_BRIGHTNESS - , bool isSequence = false - #endif - #endif - ) { - - #if ENABLED(NEOPIXEL_LED) - - const uint32_t color = pixels.Color(r, g, b, w); - static uint16_t nextLed = 0; - - pixels.setBrightness(p); - if (!isSequence) - set_neopixel_color(color); - else { - pixels.setPixelColor(nextLed, color); - pixels.show(); - if (++nextLed >= pixels.numPixels()) nextLed = 0; - return; - } - - #endif - - #if ENABLED(BLINKM) - - // This variant uses i2c to send the RGB components to the device. - SendColors(r, g, b); - - #endif - - #if ENABLED(RGB_LED) || ENABLED(RGBW_LED) - - // This variant uses 3 separate pins for the RGB components. - // If the pins can do PWM then their intensity will be set. - WRITE(RGB_LED_R_PIN, r ? HIGH : LOW); - WRITE(RGB_LED_G_PIN, g ? HIGH : LOW); - WRITE(RGB_LED_B_PIN, b ? HIGH : LOW); - analogWrite(RGB_LED_R_PIN, r); - analogWrite(RGB_LED_G_PIN, g); - analogWrite(RGB_LED_B_PIN, b); - - #if ENABLED(RGBW_LED) - WRITE(RGB_LED_W_PIN, w ? HIGH : LOW); - analogWrite(RGB_LED_W_PIN, w); - #endif - - #endif - - #if ENABLED(PCA9632) - // Update I2C LED driver - PCA9632_SetColor(r, g, b); - #endif - - #if ENABLED(LED_CONTROL_MENU) - if ((r + g + b - #if ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED) - + w - #endif - ) >= 3) { - led_intensity_red = r; - led_intensity_green = g; - led_intensity_blue = b; - #if ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED) - led_intensity_white = w; - #endif - #if ENABLED(NEOPIXEL_LED) - led_intensity = p; - #endif - } - #endif - } - - void set_led_white() { - #if ENABLED(NEOPIXEL_LED) - set_neopixel_color(pixels.Color(NEO_WHITE)); - #else - set_led_color(LED_WHITE); - #endif - } - -#endif // HAS_COLOR_LEDS - void gcode_line_error(const char* err, bool doFlush = true) { SERIAL_ERROR_START(); serialprintPGM(err); @@ -1342,13 +1175,13 @@ inline void get_serial_commands() { SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED); #if ENABLED(PRINTER_EVENT_LEDS) LCD_MESSAGEPGM(MSG_INFO_COMPLETED_PRINTS); - set_led_color(0, 255, 0); // Green + leds.set_green(); #if HAS_RESUME_CONTINUE enqueue_and_echo_commands_P(PSTR("M0")); // end of the queue! #else safe_delay(1000); #endif - set_led_color(0, 0, 0); // OFF + leds.set_off(); #endif card.checkautostart(true); } @@ -8039,14 +7872,11 @@ inline void gcode_M109() { const uint8_t blue = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 255, 0); if (blue != old_blue) { old_blue = blue; - set_led_color(255, 0, blue - #if ENABLED(NEOPIXEL_LED) - , 0 - , pixels.getBrightness() + leds.set_color( + MakeLEDColor(255, 0, blue, 0, pixels.getBrightness()) #if ENABLED(NEOPIXEL_IS_SEQUENTIAL) , true #endif - #endif ); } } @@ -8083,12 +7913,7 @@ inline void gcode_M109() { if (wait_for_heatup) { LCD_MESSAGEPGM(MSG_HEATING_COMPLETE); #if ENABLED(PRINTER_EVENT_LEDS) - #if ENABLED(RGB_LED) || ENABLED(BLINKM) || ENABLED(PCA9632) || ENABLED(RGBW_LED) - set_led_color(LED_WHITE); - #endif - #if ENABLED(NEOPIXEL_LED) - set_neopixel_color(pixels.Color(NEO_WHITE)); - #endif + leds.set_white(); #endif } @@ -8184,12 +8009,10 @@ inline void gcode_M109() { const uint8_t red = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 0, 255); if (red != old_red) { old_red = red; - set_led_color(red, 0, 255 - #if ENABLED(NEOPIXEL_LED) - , 0, pixels.getBrightness() - #if ENABLED(NEOPIXEL_IS_SEQUENTIAL) - , true - #endif + leds.set_color( + MakeLEDColor(red, 0, 255, 0, pixels.getBrightness()) + #if ENABLED(NEOPIXEL_IS_SEQUENTIAL) + , true #endif ); } @@ -8866,17 +8689,13 @@ inline void gcode_M121() { endstops.enable_globally(false); } * M150 P ; Set LED full brightness */ inline void gcode_M150() { - set_led_color( + leds.set_color(MakeLEDColor( parser.seen('R') ? (parser.has_value() ? parser.value_byte() : 255) : 0, parser.seen('U') ? (parser.has_value() ? parser.value_byte() : 255) : 0, - parser.seen('B') ? (parser.has_value() ? parser.value_byte() : 255) : 0 - #if ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED) - , parser.seen('W') ? (parser.has_value() ? parser.value_byte() : 255) : 0 - #if ENABLED(NEOPIXEL_LED) - , parser.seen('P') ? (parser.has_value() ? parser.value_byte() : 255) : pixels.getBrightness() - #endif - #endif - ); + parser.seen('B') ? (parser.has_value() ? parser.value_byte() : 255) : 0, + parser.seen('W') ? (parser.has_value() ? parser.value_byte() : 255) : 0, + parser.seen('P') ? (parser.has_value() ? parser.value_byte() : 255) : pixels.getBrightness() + )); } #endif // HAS_COLOR_LEDS @@ -14034,9 +13853,8 @@ void setup() { OUT_WRITE(STAT_LED_BLUE_PIN, LOW); // turn it off #endif - #if ENABLED(NEOPIXEL_LED) - SET_OUTPUT(NEOPIXEL_PIN); - setup_neopixel(); + #if HAS_COLOR_LEDS + leds.setup(); #endif #if ENABLED(RGB_LED) || ENABLED(RGBW_LED) diff --git a/Marlin/blinkm.cpp b/Marlin/blinkm.cpp index 1caf0a071..7eba6c0d9 100644 --- a/Marlin/blinkm.cpp +++ b/Marlin/blinkm.cpp @@ -21,26 +21,26 @@ */ /** - * blinkm.cpp - Library for controlling a BlinkM over i2c - * Created by Tim Koster, August 21 2013. + * blinkm.cpp - Control a BlinkM over i2c */ -#include "Marlin.h" +#include "MarlinConfig.h" #if ENABLED(BLINKM) #include "blinkm.h" +#include "leds.h" +#include -void SendColors(byte red, byte grn, byte blu) { +void blinkm_set_led_color(const LEDColor &color) { Wire.begin(); Wire.beginTransmission(0x09); Wire.write('o'); //to disable ongoing script, only needs to be used once Wire.write('n'); - Wire.write(red); - Wire.write(grn); - Wire.write(blu); + Wire.write(color.r); + Wire.write(color.g); + Wire.write(color.b); Wire.endTransmission(); } #endif // BLINKM - diff --git a/Marlin/blinkm.h b/Marlin/blinkm.h index ed2ad79bb..20e84d9a9 100644 --- a/Marlin/blinkm.h +++ b/Marlin/blinkm.h @@ -21,11 +21,15 @@ */ /** - * blinkm.h - Library for controlling a BlinkM over i2c - * Created by Tim Koster, August 21 2013. + * blinkm.h - Control a BlinkM over i2c */ -#include "Arduino.h" -#include "Wire.h" +#ifndef _BLINKM_H_ +#define _BLINKM_H_ -void SendColors(byte red, byte grn, byte blu); +struct LEDColor; +typedef LEDColor LEDColor; + +void blinkm_set_led_color(const LEDColor &color); + +#endif // _BLINKM_H_ diff --git a/Marlin/language_en.h b/Marlin/language_en.h index d2d93dc59..a4cd4ef97 100644 --- a/Marlin/language_en.h +++ b/Marlin/language_en.h @@ -361,63 +361,65 @@ #ifndef MSG_UBL_STEP_BY_STEP_MENU #define MSG_UBL_STEP_BY_STEP_MENU _UxGT("Step-By-Step UBL") #endif + #ifndef MSG_LED_CONTROL #define MSG_LED_CONTROL _UxGT("LED Control") #endif +#ifndef MSG_LEDS_ON + #define MSG_LEDS_ON _UxGT("Lights On") +#endif #ifndef MSG_LEDS_OFF - #define MSG_LEDS_OFF _UxGT("Turn Off Lights") + #define MSG_LEDS_OFF _UxGT("Lights Off") #endif -#ifndef MSG_LED_ON - #define MSG_LED_ON _UxGT("Turn on ") +#ifndef MSG_LED_PRESETS + #define MSG_LED_PRESETS _UxGT("Light Presets") #endif -#ifndef MSG_RED - #define MSG_RED _UxGT("Red ") +#ifndef MSG_SET_LEDS_RED + #define MSG_SET_LEDS_RED _UxGT("Lights Red") #endif -#ifndef MSG_ORANGE - #define MSG_ORANGE _UxGT("Orange ") +#ifndef MSG_SET_LEDS_ORANGE + #define MSG_SET_LEDS_ORANGE _UxGT("Lights Orange") #endif -#ifndef MSG_YELLOW - #define MSG_YELLOW _UxGT("Yellow ") +#ifndef MSG_SET_LEDS_YELLOW + #define MSG_SET_LEDS_YELLOW _UxGT("Lights Yellow") #endif -#ifndef MSG_GREEN - #define MSG_GREEN _UxGT("Green ") +#ifndef MSG_SET_LEDS_GREEN + #define MSG_SET_LEDS_GREEN _UxGT("Lights Green") #endif -#ifndef MSG_BLUE - #define MSG_BLUE _UxGT("Blue ") +#ifndef MSG_SET_LEDS_BLUE + #define MSG_SET_LEDS_BLUE _UxGT("Lights Blue") #endif -#ifndef MSG_PURPLE - #define MSG_PURPLE _UxGT("Purple ") +#ifndef MSG_SET_LEDS_INDIGO + #define MSG_SET_LEDS_INDIGO _UxGT("Lights Indigo") #endif -#ifndef MSG_WHITE - #define MSG_WHITE _UxGT("White ") +#ifndef MSG_SET_LEDS_VIOLET + #define MSG_SET_LEDS_VIOLET _UxGT("Lights Violet") #endif -#ifndef MSG_CUSTOM - #define MSG_CUSTOM _UxGT("Custom ") +#ifndef MSG_SET_LEDS_WHITE + #define MSG_SET_LEDS_WHITE _UxGT("Lights White") #endif -#ifndef MSG_LED_PRESET - #define MSG_LED_PRESET _UxGT("Preset ") +#ifndef MSG_SET_LEDS_DEFAULT + #define MSG_SET_LEDS_DEFAULT _UxGT("Lights Default") #endif -#ifndef MSG_LED_DEFAULT - #define MSG_LED_DEFAULT _UxGT("Default ") +#ifndef MSG_CUSTOM_LEDS + #define MSG_CUSTOM_LEDS _UxGT("Custom Lights") #endif -#ifndef MSG_LIGHTS - #define MSG_LIGHTS _UxGT("Lights ") +#ifndef MSG_INTENSITY_R + #define MSG_INTENSITY_R _UxGT("Red Intensity") #endif -#ifndef MSG_COLOR - #define MSG_COLOR _UxGT("Color") +#ifndef MSG_INTENSITY_G + #define MSG_INTENSITY_G _UxGT("Green Intensity") #endif -#ifndef MSG_LED_INTENSITY - #define MSG_LED_INTENSITY _UxGT("Intensity ") +#ifndef MSG_INTENSITY_B + #define MSG_INTENSITY_B _UxGT("Blue Intensity") #endif -#ifndef MSG_LED_CUSTOM - #define MSG_LED_CUSTOM _UxGT("Custom LED") +#ifndef MSG_INTENSITY_W + #define MSG_INTENSITY_W _UxGT("White Intensity") #endif -#ifndef MSG_LED_SAVE - #define MSG_LED_SAVE _UxGT("Save ") -#endif -#ifndef MSG_LED_LOAD - #define MSG_LED_LOAD _UxGT("Load ") +#ifndef MSG_LED_BRIGHTNESS + #define MSG_LED_BRIGHTNESS _UxGT("Brightness") #endif + #ifndef MSG_MOVING #define MSG_MOVING _UxGT("Moving...") #endif diff --git a/Marlin/leds.cpp b/Marlin/leds.cpp new file mode 100644 index 000000000..df798acf8 --- /dev/null +++ b/Marlin/leds.cpp @@ -0,0 +1,140 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 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 . + * + */ + +/** + * leds.cpp - Marlin RGB LED general support + */ + +#include "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(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 ENABLED(LED_CONTROL_MENU) + LEDColor LEDLights::color; + bool LEDLights::lights_on; +#endif + +LEDLights leds; + +void LEDLights::setup() { + #if ENABLED(NEOPIXEL_LED) + setup_neopixel(); + #endif + #if ENABLED(LED_USER_PRESET_STARTUP) + set_default(); + #endif +} + +void LEDLights::set_color(const LEDColor &incol + #if ENABLED(NEOPIXEL_LED) + , bool isSequence/*=false*/ + #endif +) { + + #if ENABLED(NEOPIXEL_LED) + + const uint32_t neocolor = pixels.Color(incol.r, incol.g, incol.b, incol.w); + static uint16_t nextLed = 0; + + pixels.setBrightness(incol.i); + if (!isSequence) + set_neopixel_color(neocolor); + else { + pixels.setPixelColor(nextLed, neocolor); + pixels.show(); + if (++nextLed >= pixels.numPixels()) nextLed = 0; + return; + } + + #endif + + #if ENABLED(BLINKM) + + // This variant uses i2c to send the RGB components to the device. + blinkm_set_led_color(incol); + + #endif + + #if ENABLED(RGB_LED) || ENABLED(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. + WRITE(RGB_LED_R_PIN, incol.r ? HIGH : LOW); + WRITE(RGB_LED_G_PIN, incol.g ? HIGH : LOW); + WRITE(RGB_LED_B_PIN, incol.b ? HIGH : LOW); + analogWrite(RGB_LED_R_PIN, incol.r); + analogWrite(RGB_LED_G_PIN, incol.g); + analogWrite(RGB_LED_B_PIN, incol.b); + + #if ENABLED(RGBW_LED) + WRITE(RGB_LED_W_PIN, incol.w ? HIGH : LOW); + analogWrite(RGB_LED_W_PIN, incol.w); + #endif + + #endif + + #if ENABLED(PCA9632) + // Update I2C LED driver + pca9632_set_led_color(incol); + #endif + + #if ENABLED(LED_CONTROL_MENU) + // Don't update the color when OFF + lights_on = !incol.is_off(); + if (lights_on) color = incol; + #endif +} + +void LEDLights::set_white() { + #if ENABLED(RGB_LED) || ENABLED(RGBW_LED) || ENABLED(BLINKM) || ENABLED(PCA9632) + set_color(LEDColorWhite()); + #endif + #if ENABLED(NEOPIXEL_LED) + set_neopixel_color(pixels.Color(NEO_WHITE)); + #endif +} + +#if ENABLED(LED_CONTROL_MENU) + void LEDLights::toggle() { if (lights_on) set_off(); else update(); } +#endif + +#endif // HAS_COLOR_LEDS diff --git a/Marlin/leds.h b/Marlin/leds.h new file mode 100644 index 000000000..a0cf28b84 --- /dev/null +++ b/Marlin/leds.h @@ -0,0 +1,169 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 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 . + * + */ + +/** + * leds.h - Marlin general RGB LED support + */ + +#ifndef __LEDS_H__ +#define __LEDS_H__ + +#include "MarlinConfig.h" + +#if ENABLED(NEOPIXEL_LED) + #include "neopixel.h" +#endif + +#define HAS_WHITE_LED (ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED)) + +/** + * 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& 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 + #if HAS_WHITE_LED + + w + #endif + ; + } +} LEDColor; + +/** + * Color helpers and presets + */ +#if HAS_WHITE_LED + #define LEDColorWhite() LEDColor(0, 0, 0, 255) + #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) + #define LEDColorWhite() LEDColor(255, 255, 255) +#endif +#define LEDColorOff() LEDColor( 0, 0, 0) +#define LEDColorRed() LEDColor(255, 0, 0) +#define LEDColorOrange() LEDColor(255, 80, 0) +#define LEDColorYellow() LEDColor(255, 255, 0) +#define LEDColorGreen() LEDColor( 0, 255, 0) +#define LEDColorBlue() LEDColor( 0, 0, 255) +#define LEDColorIndigo() LEDColor( 0, 255, 255) +#define LEDColorViolet() LEDColor(255, 0, 255) + +class LEDLights { +public: + LEDLights() {} // ctor + + static void setup(); // init() + + static void set_color(const LEDColor &color + #if ENABLED(NEOPIXEL_LED) + , bool isSequence=false + #endif + ); + + FORCE_INLINE void set_color(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 + #if ENABLED(NEOPIXEL_LED) + , bool isSequence=false + #endif + ) { + set_color(MakeLEDColor(r, g, b, w, i) + #if ENABLED(NEOPIXEL_LED) + , isSequence + #endif + ); + } + + static void set_white(); + FORCE_INLINE static void set_off() { set_color(LEDColorOff()); } + FORCE_INLINE static void set_green() { set_color(LEDColorGreen()); } + + #if ENABLED(LED_COLOR_PRESETS) + static const LEDColor defaultLEDColor; + FORCE_INLINE static void set_default() { set_color(defaultLEDColor); } + FORCE_INLINE static void set_red() { set_color(LEDColorRed()); } + FORCE_INLINE static void set_orange() { set_color(LEDColorOrange()); } + FORCE_INLINE static void set_yellow() { set_color(LEDColorYellow()); } + FORCE_INLINE static void set_blue() { set_color(LEDColorBlue()); } + FORCE_INLINE static void set_indigo() { set_color(LEDColorIndigo()); } + FORCE_INLINE static void set_violet() { set_color(LEDColorViolet()); } + #endif + + #if ENABLED(LED_CONTROL_MENU) + static LEDColor color; // last non-off color + static bool lights_on; // the last set color was "on" + static void toggle(); // swap "off" with color + FORCE_INLINE static void update() { set_color(color); } + #endif +}; + +extern LEDLights leds; + +#endif // __LEDS_H__ diff --git a/Marlin/neopixel.cpp b/Marlin/neopixel.cpp new file mode 100644 index 000000000..8d8a5445e --- /dev/null +++ b/Marlin/neopixel.cpp @@ -0,0 +1,60 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 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 . + * + */ + +/** + * neopixel.cpp + */ + +#include "MarlinConfig.h" + +#if ENABLED(NEOPIXEL_LED) + +#include "neopixel.h" + +Adafruit_NeoPixel pixels(NEOPIXEL_PIXELS, NEOPIXEL_PIN, NEOPIXEL_TYPE + NEO_KHZ800); + +void set_neopixel_color(const uint32_t color) { + for (uint16_t i = 0; i < pixels.numPixels(); ++i) + pixels.setPixelColor(i, color); + pixels.show(); +} + +void setup_neopixel() { + SET_OUTPUT(NEOPIXEL_PIN); + pixels.setBrightness(NEOPIXEL_BRIGHTNESS); // 0 - 255 range + pixels.begin(); + pixels.show(); // initialize to all off + + #if ENABLED(NEOPIXEL_STARTUP_TEST) + safe_delay(1000); + set_neopixel_color(pixels.Color(255, 0, 0, 0)); // red + safe_delay(1000); + set_neopixel_color(pixels.Color(0, 255, 0, 0)); // green + safe_delay(1000); + set_neopixel_color(pixels.Color(0, 0, 255, 0)); // blue + safe_delay(1000); + #endif + set_neopixel_color(pixels.Color(NEO_WHITE)); // white +} + +#endif // NEOPIXEL_LED + diff --git a/Marlin/neopixel.h b/Marlin/neopixel.h new file mode 100644 index 000000000..b7ed45c82 --- /dev/null +++ b/Marlin/neopixel.h @@ -0,0 +1,44 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 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 . + * + */ + +/** + * neopixel.h + */ + +#include "MarlinConfig.h" + +#define NEOPIXEL_IS_RGB (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_RGBW !NEOPIXEL_IS_RGB + +#if NEOPIXEL_IS_RGB + #define NEO_WHITE 255, 255, 255, 0 +#else + #define NEO_WHITE 0, 0, 0, 255 +#endif + +#include +#include + +void setup_neopixel(); +void set_neopixel_color(const uint32_t color); + +extern Adafruit_NeoPixel pixels; diff --git a/Marlin/pca9632.cpp b/Marlin/pca9632.cpp index 37f7bd7df..2b4ee7f40 100644 --- a/Marlin/pca9632.cpp +++ b/Marlin/pca9632.cpp @@ -20,7 +20,7 @@ * */ -/* +/** * Driver for the Philips PCA9632 LED driver. * Written by Robert Mendon Feb 2017. */ @@ -30,12 +30,13 @@ #if ENABLED(PCA9632) #include "pca9632.h" +#include "leds.h" +#include #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 @@ -98,7 +99,7 @@ static void PCA9632_WriteAllRegisters(const byte addr, const byte regadd, const } #endif -void PCA9632_SetColor(const byte r, const byte g, const byte b) { +void pca9632_set_led_color(const LEDColor &color) { if (!PCA_init) { PCA_init = 1; Wire.begin(); @@ -106,11 +107,11 @@ void PCA9632_SetColor(const byte r, const byte g, const byte b) { PCA9632_WriteRegister(PCA9632_ADDRESS,PCA9632_MODE2, PCA9632_MODE2_VALUE); } - const byte LEDOUT = (r ? LED_PWM << PCA9632_RED : 0) - | (g ? LED_PWM << PCA9632_GRN : 0) - | (b ? LED_PWM << PCA9632_BLU : 0); + const byte LEDOUT = (color.r ? LED_PWM << PCA9632_RED : 0) + | (color.g ? LED_PWM << PCA9632_GRN : 0) + | (color.b ? LED_PWM << PCA9632_BLU : 0); - PCA9632_WriteAllRegisters(PCA9632_ADDRESS,PCA9632_PWM0, r, g, b); + PCA9632_WriteAllRegisters(PCA9632_ADDRESS,PCA9632_PWM0, color.r, color.g, color.b); PCA9632_WriteRegister(PCA9632_ADDRESS,PCA9632_LEDOUT, LEDOUT); } diff --git a/Marlin/pca9632.h b/Marlin/pca9632.h index b8c78f065..4d98267be 100644 --- a/Marlin/pca9632.h +++ b/Marlin/pca9632.h @@ -20,7 +20,7 @@ * */ -/* +/** * Driver for the Philips PCA9632 LED driver. * Written by Robert Mendon Feb 2017. */ @@ -28,9 +28,9 @@ #ifndef __PCA9632_H__ #define __PCA9632_H__ -#include "Arduino.h" -#include "Wire.h" +struct LEDColor; +typedef LEDColor LEDColor; -void PCA9632_SetColor(const byte r, const byte g, const byte b); +void pca9632_set_led_color(const LEDColor &color); #endif // __PCA9632_H__ diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 5c41dcdcc..76348b41d 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -185,20 +185,8 @@ uint16_t max_display_update_time = 0; #endif // LCD_INFO_MENU #if ENABLED(LED_CONTROL_MENU) - extern void set_led_color( - const uint8_t r, const uint8_t g, const uint8_t b - #if ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED) - , const uint8_t w = 0 - #if ENABLED(NEOPIXEL_LED) - , const uint8_t p = NEOPIXEL_BRIGHTNESS - , bool isSequence = false - #endif - #endif - ); - - extern void set_led_white(); + #include "leds.h" void lcd_led_menu(); - void lcd_led_custom_menu(); #endif #if ENABLED(ADVANCED_PAUSE_FEATURE) @@ -1031,7 +1019,7 @@ void kill_screen(const char* lcd_msg) { #endif #if ENABLED(LED_CONTROL_MENU) - MENU_ITEM(submenu, "LED Control", lcd_led_menu); + MENU_ITEM(submenu, MSG_LED_CONTROL, lcd_led_menu); #endif END_MENU(); @@ -3971,105 +3959,37 @@ void kill_screen(const char* lcd_msg) { #if ENABLED(LED_CONTROL_MENU) - bool led_restore_color = - #if ENABLED(LED_USER_PRESET_STARTUP) - false; - #else - true; - #endif + #if ENABLED(LED_COLOR_PRESETS) - extern uint8_t led_intensity_red, - led_intensity_green, - led_intensity_blue - #if ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED) - , led_intensity_white - #endif - #if ENABLED(NEOPIXEL_LED) - , led_intensity - #endif - ; - - void update_leds() { - if (led_restore_color) { - #if ENABLED(LED_COLOR_PRESETS) - led_intensity_red = LED_USER_PRESET_RED; - led_intensity_green = LED_USER_PRESET_GREEN; - led_intensity_blue = LED_USER_PRESET_BLUE; - #if ENABLED(RGBW_LED) - led_intensity_white = LED_USER_PRESET_WHITE; - #endif - #if ENABLED(NEOPIXEL_LED) - led_intensity = LED_USER_PRESET_INTENSITY; - #endif - #else - led_intensity_red = 255; - led_intensity_green = 255; - led_intensity_blue = 255; - #if ENABLED(RGBW_LED) - led_intensity_white = 0; - #endif - #if ENABLED(NEOPIXEL_LED) - led_intensity = LED_USER_PRESET_INTENSITY; - #endif + void lcd_led_presets_menu() { + START_MENU(); + #if LCD_HEIGHT > 2 + STATIC_ITEM(MSG_LED_PRESETS, true, true); #endif - led_restore_color = false; + MENU_BACK(MSG_LED_CONTROL); + MENU_ITEM(function, MSG_SET_LEDS_WHITE, leds.set_white); + MENU_ITEM(function, MSG_SET_LEDS_RED, leds.set_red); + MENU_ITEM(function, MSG_SET_LEDS_ORANGE, leds.set_orange); + MENU_ITEM(function, MSG_SET_LEDS_YELLOW,leds.set_yellow); + MENU_ITEM(function, MSG_SET_LEDS_GREEN, leds.set_green); + MENU_ITEM(function, MSG_SET_LEDS_BLUE, leds.set_blue); + MENU_ITEM(function, MSG_SET_LEDS_INDIGO, leds.set_indigo); + MENU_ITEM(function, MSG_SET_LEDS_VIOLET, leds.set_violet); + END_MENU(); } - - set_led_color(led_intensity_red, led_intensity_green, led_intensity_blue - #if ENABLED(RGBW_LED) - , led_intensity_white - #endif - #if ENABLED(NEOPIXEL_LED) - , 0, led_intensity - #endif - ); - led_restore_color = false; - } - - void led_restore_default() { - led_restore_color = true; - update_leds(); - } - - void set_leds_off() { - set_led_color(0, 0, 0 - #if ENABLED(RGBW) || ENABLED(NEOPIXEL_LED) - , 0 - #endif - ); - } - - void lcd_led_red() { set_led_color(255, 0, 0); } - void lcd_led_orange() { set_led_color(150, 60, 0); } - void lcd_led_yellow() { set_led_color(255, 255, 0); } - void lcd_led_green() { set_led_color(0, 255, 0); } - void lcd_led_blue() { set_led_color(0, 0, 255); } - void lcd_led_purple() { set_led_color(255, 0, 255); } - - void lcd_led_presets_menu() { - START_MENU(); - MENU_BACK(MSG_LED_CONTROL); - MENU_ITEM(function, MSG_LED_ON MSG_RED MSG_LIGHTS, lcd_led_red); - MENU_ITEM(function, MSG_LED_ON MSG_ORANGE MSG_LIGHTS, lcd_led_orange); - MENU_ITEM(function, MSG_LED_ON MSG_YELLOW MSG_LIGHTS,lcd_led_yellow); - MENU_ITEM(function, MSG_LED_ON MSG_GREEN MSG_LIGHTS, lcd_led_green); - MENU_ITEM(function, MSG_LED_ON MSG_BLUE MSG_LIGHTS, lcd_led_blue); - MENU_ITEM(function, MSG_LED_ON MSG_PURPLE MSG_LIGHTS, lcd_led_purple); - MENU_ITEM(function, MSG_LED_ON MSG_WHITE MSG_LIGHTS, set_led_white); - END_MENU(); - } + #endif // LED_COLOR_PRESETS void lcd_led_custom_menu() { START_MENU(); MENU_BACK(MSG_LED_CONTROL); - MENU_ITEM_EDIT_CALLBACK(int8, MSG_RED MSG_LED_INTENSITY, &led_intensity_red, 0, 255, update_leds, true); - MENU_ITEM_EDIT_CALLBACK(int8, MSG_GREEN MSG_LED_INTENSITY, &led_intensity_green, 0, 255, update_leds, true); - MENU_ITEM_EDIT_CALLBACK(int8, MSG_BLUE MSG_LED_INTENSITY, &led_intensity_blue, 0, 255, update_leds, true); + MENU_ITEM_EDIT_CALLBACK(int8, MSG_INTENSITY_R, &leds.color.r, 0, 255, leds.update, true); + MENU_ITEM_EDIT_CALLBACK(int8, MSG_INTENSITY_G, &leds.color.g, 0, 255, leds.update, true); + MENU_ITEM_EDIT_CALLBACK(int8, MSG_INTENSITY_B, &leds.color.b, 0, 255, leds.update, true); #if ENABLED(RGBW_LED) || ENABLED(NEOPIXEL_LED) - MENU_ITEM_EDIT_CALLBACK(int8, MSG_WHITE MSG_LED_INTENSITY, &led_intensity_white, 0, 255, update_leds, true); - #endif - #if ENABLED(NEOPIXEL_LED) - MENU_ITEM_EDIT_CALLBACK(int8, MSG_LED_INTENSITY, &led_intensity, 0, 255, update_leds, true); + MENU_ITEM_EDIT_CALLBACK(int8, MSG_INTENSITY_W, &leds.color.w, 0, 255, leds.update, true); + #if ENABLED(NEOPIXEL_LED) + MENU_ITEM_EDIT_CALLBACK(int8, MSG_LED_BRIGHTNESS, &leds.color.i, 0, 255, leds.update, true); + #endif #endif END_MENU(); } @@ -4077,13 +3997,15 @@ void kill_screen(const char* lcd_msg) { void lcd_led_menu() { START_MENU(); MENU_BACK(MSG_MAIN); - MENU_ITEM(function, MSG_LIGHTS MSG_OFF, set_leds_off); // works - MENU_ITEM(function, MSG_LIGHTS MSG_ON, update_leds); // works - MENU_ITEM(function, MSG_LED_LOAD MSG_LED_DEFAULT MSG_COLOR, led_restore_default); // works + if (leds.lights_on) + MENU_ITEM(function, MSG_LEDS_OFF, leds.toggle); + else + MENU_ITEM(function, MSG_LEDS_ON, leds.toggle); + MENU_ITEM(function, MSG_SET_LEDS_DEFAULT, leds.set_default); #if ENABLED(LED_COLOR_PRESETS) - MENU_ITEM(submenu, MSG_LED_PRESET MSG_LIGHTS, lcd_led_presets_menu); + MENU_ITEM(submenu, MSG_LED_PRESETS, lcd_led_presets_menu); #endif - MENU_ITEM(submenu, MSG_CUSTOM MSG_LIGHTS, lcd_led_custom_menu); + MENU_ITEM(submenu, MSG_CUSTOM_LEDS, lcd_led_custom_menu); END_MENU(); }