From 94e5dce0459846d2aee15d5b6f648f03b8a41d03 Mon Sep 17 00:00:00 2001 From: Dirk Jahnke Date: Thu, 7 Dec 2017 10:33:14 +0100 Subject: [PATCH] Refactoring completed: NeoPixel implementation in C instead of js --- fs/init.js | 157 +++++++++++++++++++++++++++----------------- mos.yml | 4 +- src/LEDDefinition.c | 39 ++++++----- src/LEDDefinition.h | 6 +- src/LEDState.c | 26 ++++++-- src/LEDState.h | 3 +- src/NeoPixel.c | 81 +++++++++++++++-------- src/NeoPixel.h | 15 +++++ src/main.c | 22 ++++--- 9 files changed, 228 insertions(+), 125 deletions(-) create mode 100644 src/NeoPixel.h diff --git a/fs/init.js b/fs/init.js index 7943b06..fc9350c 100644 --- a/fs/init.js +++ b/fs/init.js @@ -60,10 +60,10 @@ Net.setStatusEventHandler(function(ev, arg) { // Initialize LED controller let addColor = ffi('void addColor(char *,int,int,int)'); -let addLedDefinition = ffi('void addLedDefinition(char *, char *, char *, char *)'); +let LEDDefinition_addByName = ffi('void LEDDefinition_addByName(char *, char *, char *, char *)'); let addAnimationStep = ffi('void addAnimationStep(int, char *, int)'); let LEDMode_on=1, LEDMode_off=2, LEDMode_blink=3, LEDMode_tv=4, LEDMode_fire=5; -let LEDStateEngine_init = ffi('void LEDStateEngine_init(int)'); +let LEDStateEngine_init = ffi('void LEDStateEngine_init(int, int)'); let LEDStateEngine_start = ffi('void startLEDStateEngine(void)'); let LEDStateEngine_pause = ffi('void pauseLEDStateEngine(void)'); let LEDState_getRed = ffi('int LEDState_getLedRed(int)'); @@ -80,11 +80,14 @@ let LEDDefinition_getOnColorGreen = ffi('int LEDDefinition_getOnColorGreen(int)' let LEDDefinition_getOnColorBlue = ffi('int LEDDefinition_getOnColorBlue(int)'); let getTicks = ffi('int getTicks(void)'); let printColor = ffi('void printColor(char *)'); +let NeoPixel_show = ffi('void NeoPixel_show(void)'); +let NeoPixel_clear = ffi('void NeoPixel_clear(void)'); +let NeoPixel_set = ffi('void NeoPixel_set(int,int,int,int)'); let pin = Cfg.get('led.pin'); -let numPixels = Cfg.get('led.count'); +let configNumLeds = Cfg.get('led.count'); let colorOrder = NeoPixel.GRB; -let strip = NeoPixel.create(pin, numPixels, colorOrder); +//let strip = NeoPixel.create(pin, configNumLeds, colorOrder); let colorFile = Cfg.get('led.colorFile'); let animationFile = Cfg.get('led.animationFile'); let lampsFile = Cfg.get('led.lampsFile'); @@ -92,53 +95,54 @@ let useDefaults = Cfg.get('led.useDefaults'); let updateCycle = Cfg.get('led.updateCycle'); let tickDuration = Cfg.get('led.tickDuration'); let brightnessAdjustment = Cfg.get('led.brightness'); -let numberOfLeds = 0; // from config files, count led definition entries +let numberOfLeds = configNumLeds, numberOfLedDefs = 0; // from config files, count led definition entries /* Create test pattern */ -function createLedTestPattern() { +function showLedTestPattern() { let i; let switchMod; - for (i=0; i 5) print("WRONG -- should never reach this in switch statement!"); } - strip.show(); + //strip.show(); + NeoPixel_show(); } function allLedOn() { let i; - for (i=0; i configNumLeds) { + print('WARNING: LED definition file contains more LEDs (', numberOfLedDefs, ') than configured in system-config (', configNumLeds, ')'); + } json = null; // ledDef = null; // NO! Do not do this, as the strings are still referenced! - +} + +function loadAnimDefs() { // Load Animation Definitions let json = File.read(animationFile); let animation = []; @@ -188,42 +200,65 @@ if (useDefaults) { addAnimationStep(animation[i].led, animation[i].mode, animation[i].ticks); } json = null; - - // Initialize LED State Engine - LEDStateEngine_init(numberOfLeds); -} -print('***** End of initialization', getInfo()); -print('_______________________________________________________'); -print('LedPin:', pin); -print('NumLEDs:', numberOfLeds); -print('Ticks:', getTicks()); -print('Tick duration:', tickDuration, 'ms'); -print('LED Update Cycle:', updateCycle, 'ms'); -print('Brightness:', brightnessAdjustment, '%'); -print('LED', 'Color', 'R', 'G', 'B', 'Tick', 'Level', 'Room', 'Id'); -print('---', '-----', '---', '---', '-----', '---', '-----', '----', '--'); -for (i=0; ired, c->green, c->blue); +} + void LEDDefinition_init(int numberOfLeds, bool loadDefaultData) { // initialize numberOfLEDDefinitions = 0; if (loadDefaultData) { do { - LEDDefinition_add("EG", "Wohnzimmer", "EG-WoZi", 200,200,200); - LEDDefinition_add("EG", "Bad", "EG-Bad", 130,130,130); - LEDDefinition_add("EG", "Schlafzimmer", "EG-Schlafen", 150,150,130); - LEDDefinition_add("EG", "Buero 0.1", "EG-Buero-1", 150,130,130); - LEDDefinition_add("EG", "Buero 0.2", "EG-Buero-2", 150,200,200); - LEDDefinition_add("EG", "Flur", "EG-Flur-1", 100,100,100); - LEDDefinition_add("EG", "Flur", "EG-Flur-2", 140,100,100); - LEDDefinition_add("OG1", "Buero 1.1", "OG1-WoZi", 200,200,200); - LEDDefinition_add("OG1", "Bad OG1", "OG1-Bad", 130,130,130); - LEDDefinition_add("OG1", "Buero 1.2", "OG1-Schlafen", 150,150,130); - LEDDefinition_add("OG1", "Buero 1.3", "OG1Buero-1", 150,150,130); - LEDDefinition_add("OG1", "Buero 1.4", "OG1-Buero-2", 150,200,200); - LEDDefinition_add("OG1", "Flur", "OG1-Flur-1", 100,100,100); - LEDDefinition_add("OG1", "Flur", "OG1-Flur-2", 140,100,100); + LEDDefinition_add("EG", "Wohnzimmer", "EG-WoZi", "demo", 200,200,200); + LEDDefinition_add("EG", "Bad", "EG-Bad", "demo", 130,130,130); + LEDDefinition_add("EG", "Schlafzimmer", "EG-Schlafen", "demo", 150,150,130); + LEDDefinition_add("EG", "Buero 0.1", "EG-Buero-1", "demo", 150,130,130); + LEDDefinition_add("EG", "Buero 0.2", "EG-Buero-2", "demo", 150,200,200); + LEDDefinition_add("EG", "Flur", "EG-Flur-1", "demo", 100,100,100); + LEDDefinition_add("EG", "Flur", "EG-Flur-2", "demo", 140,100,100); + LEDDefinition_add("OG1", "Buero 1.1", "OG1-WoZi", "demo", 200,200,200); + LEDDefinition_add("OG1", "Bad OG1", "OG1-Bad", "demo", 130,130,130); + LEDDefinition_add("OG1", "Buero 1.2", "OG1-Schlafen", "demo", 150,150,130); + LEDDefinition_add("OG1", "Buero 1.3", "OG1Buero-1", "demo", 150,150,130); + LEDDefinition_add("OG1", "Buero 1.4", "OG1-Buero-2", "demo", 150,200,200); + LEDDefinition_add("OG1", "Flur", "OG1-Flur-1", "demo", 100,100,100); + LEDDefinition_add("OG1", "Flur", "OG1-Flur-2", "demo", 140,100,100); } while(numberOfLEDDefinitions < numberOfLeds); } } @@ -121,4 +126,4 @@ int LEDDefinition_getOnColorGreen(int ledNum) { int LEDDefinition_getOnColorBlue(int ledNum) { ledNum = verifyLedDefinitionNum(ledNum); return ledDefinition[ledNum].onColor.blue; -} \ No newline at end of file +} diff --git a/src/LEDDefinition.h b/src/LEDDefinition.h index b8be85e..3589f0c 100644 --- a/src/LEDDefinition.h +++ b/src/LEDDefinition.h @@ -7,7 +7,6 @@ #include "fw/src/mgos.h" #include "mjs.h" #include "mongoose/mongoose.h" -#include "common/cs_dbg.h" #define MAX_LEDS 50 @@ -36,7 +35,8 @@ extern LEDDefinition ledDefinition[MAX_LEDS]; extern LEDDefinition *LEDDefinition_get(int ledNum); extern void LEDDefinition_init(int numberOfLeds, bool loadDefaultData); -extern void LEDDefinition_add(char *level, char *room, char *id, uint8_t red, uint8_t green, uint8_t blue); +extern void LEDDefinition_add(char *level, char *room, char *id, char *onColorName, uint8_t red, uint8_t green, uint8_t blue); +extern void LEDDefinition_addByName(char *level, char *room, char *id, char *onColorName); extern char *LEDDefinition_getLevel(int ledNum); extern char *LEDDefinition_getRoom(int ledNum); extern char *LEDDefinition_getId(int ledNum); @@ -44,4 +44,4 @@ extern int LEDDefinition_getOnColorRed(int ledNum); extern int LEDDefinition_getOnColorGreen(int ledNum); extern int LEDDefinition_getOnColorBlue(int ledNum); -#endif \ No newline at end of file +#endif diff --git a/src/LEDState.c b/src/LEDState.c index e91e695..f1569fc 100644 --- a/src/LEDState.c +++ b/src/LEDState.c @@ -1,9 +1,11 @@ /* LEDState.c */ +#include "mgos_sys_config.h" + #include "LEDDefinition.h" #include "LEDState.h" #include "AnimationConfig.h" - +#include "NeoPixel.h" static LEDStateEngine theLEDStateEngine; static int ticks = 0; @@ -15,13 +17,16 @@ void LEDStateEngine_setNumberOfLeds(int numberOfLeds) { LOG(LL_ERROR, ("Invalid number of LEDs %d", numberOfLeds)); numberOfLeds = MAX_LEDS; } + NeoPixel_release(); + NeoPixel_create(theLEDStateEngine.pin, numberOfLeds, NeoPixel_colorOrder_RGB); theLEDStateEngine.numberOfLeds = numberOfLeds; - LOG(LL_INFO, ("LEDStateEngine initialized: numLEDs=%d, MAX_LEDS=%d", numberOfLeds, MAX_LEDS)); + LOG(LL_INFO, ("LEDStateEngine initialized: numLEDs=%d, MAX_LEDS=%d, pin=%d", numberOfLeds, MAX_LEDS, theLEDStateEngine.pin)); } -void LEDStateEngine_init(int numberOfLeds) { - LEDStateEngine_setNumberOfLeds(numberOfLeds); +void LEDStateEngine_init(int ledPin, int numberOfLeds) { theLEDStateEngine.comment = ""; + theLEDStateEngine.pin = ledPin; + LEDStateEngine_setNumberOfLeds(numberOfLeds); for (int i=0; iindex, + adjustBrightness(state->currentColor.red), adjustBrightness(state->currentColor.green), adjustBrightness(state->currentColor.blue)); } void LEDState_tick(int ledNum) { @@ -65,6 +82,7 @@ void LEDState_tick(int ledNum) { state->currentColor = dimmedRedColor; break; } + updateLedDisplay(state); } // do animations, if necessary } diff --git a/src/LEDState.h b/src/LEDState.h index 209075f..790d5eb 100644 --- a/src/LEDState.h +++ b/src/LEDState.h @@ -23,6 +23,7 @@ typedef struct LEDState_t { } LEDState; typedef struct LEDStateEngine_t { + uint8_t pin; uint8_t numberOfLeds; LEDState ledState[MAX_LEDS]; char *comment; @@ -31,7 +32,7 @@ typedef struct LEDStateEngine_t { extern int getTicks(void); /* LEDStateEngine */ -extern void LEDStateEngine_init(int numberOfLeds); +extern void LEDStateEngine_init(int ledPin, int numberOfLeds); extern void LEDStateEngine_addComment(char *comment); extern LEDState *LEDStateEngine_getLedState(int n); diff --git a/src/NeoPixel.c b/src/NeoPixel.c index 9b29980..bfe6bed 100644 --- a/src/NeoPixel.c +++ b/src/NeoPixel.c @@ -1,18 +1,26 @@ +#include "common/platform.h" +#include "common/cs_dbg.h" #include "mgos_bitbang.h" #include "mgos_gpio.h" #include "mgos_system.h" +#include "NeoPixel.h" -enum NeoPixel_ColorOrder { - RGB = 0, - GRB = 1, - BGR = 2, -}; +static int NeoPixel_pin = 0; +static int NeoPixel_numPixels = 0; +static uint8_t *NeoPixel_leds = NULL; // pointer to allocated memory +static enum NeoPixel_ColorOrder NeoPixel_colorOrder = NeoPixel_colorOrder_RGB; -#define MAX_LEDS 100 -static uint8_t NeoPixel_pin = 0; -static uint8_t NeoPixel_numPixels = 0; -static uint8_t NeoPixel_leds[3 * MAX_LEDS]; -static NeoPixel_ColorOrder NeoPixel_colorOrder = RGB; +// ## **`NeoPixel_clear()`** +// Clear in-memory values of the pixels. +void NeoPixel_clear() { + if (NeoPixel_leds == NULL) { + LOG(LL_ERROR, ("NeoPixel data space not allocated")); + return; + } + for (int i=0; i= NeoPixel_numPixels) { + LOG(LL_ERROR, ("Invalid pixel number %d", pixel)); + return; + } + + if (NeoPixel_colorOrder == NeoPixel_colorOrder_RGB) { v0 = red; v1 = green; v2 = blue; - } else if (NeoPixel_colorOrder == GRB) { + } else if (NeoPixel_colorOrder == NeoPixel_colorOrder_GRB) { v0 = green; v1 = red; v2 = blue; - } else if (NeoPixel_colorOrder == BGR) { + } else if (NeoPixel_colorOrder == NeoPixel_colorOrder_BGR) { v0 = blue; v1 = green; v2 = red; } else return; - NeoPixel_leds[pixel] = v0; - NeoPixel_leds[pixel+1] = v1; - NeoPixel_leds[pixel+2] = v2; + NeoPixel_leds[3*pixel] = v0; + NeoPixel_leds[3*pixel+1] = v1; + NeoPixel_leds[3*pixel+2] = v2; } // ## **`NeoPixel_show()`** // Output values of the pixels. void NeoPixel_show() { + if (NeoPixel_leds == NULL) { + LOG(LL_ERROR, ("NeoPixel data space not allocated")); + return; + } + // GPIO.write(this.pin, 0); - mgos_gpio_write(pin, false); + mgos_gpio_write(NeoPixel_pin, false); // Sys.usleep(60); mgos_usleep(60); // BitBang.write(this.pin, BitBang.DELAY_100NSEC, 3, 8, 8, 6, this.data, this.len); - mgos_bitbang_write_bits(NeoPixel_pin, DELAY_100NSEC, 3, 8, 8, 6, NeoPixel_leds, NeoPixel_numPixels); + mgos_bitbang_write_bits(NeoPixel_pin, MGOS_DELAY_100NSEC, 3, 8, 8, 6, NeoPixel_leds, 3 * NeoPixel_numPixels); // GPIO.write(this.pin, 0); - mgos_gpio_write(pin, false); + mgos_gpio_write(NeoPixel_pin, false); // Sys.usleep(60); mgos_usleep(60); // GPIO.write(this.pin, 1); - mgos_gpio_write(pin, true); + mgos_gpio_write(NeoPixel_pin, true); } diff --git a/src/NeoPixel.h b/src/NeoPixel.h new file mode 100644 index 0000000..31e44b6 --- /dev/null +++ b/src/NeoPixel.h @@ -0,0 +1,15 @@ +#ifndef NeoPixel_h_loaded +#define NeoPixel_h_loaded + +enum NeoPixel_ColorOrder { + NeoPixel_colorOrder_RGB = 0, + NeoPixel_colorOrder_GRB = 1, + NeoPixel_colorOrder_BGR = 2 +}; + +extern void NeoPixel_release(); +extern void NeoPixel_create(uint8_t pin, uint8_t numPixels, enum NeoPixel_ColorOrder order); +extern void NeoPixel_set(int pixel, int red, int green, int blue); +extern void NeoPixel_show(); + +#endif diff --git a/src/main.c b/src/main.c index 02bf182..2094084 100644 --- a/src/main.c +++ b/src/main.c @@ -13,6 +13,7 @@ #include "LEDDefinition.h" #include "AnimationConfig.h" #include "LEDState.h" +#include "NeoPixel.h" #if CS_PLATFORM == CS_P_ESP8266 #define LED_GPIO 2 /* On ESP-12E there is a blue LED connected to GPIO2 */ @@ -36,24 +37,30 @@ int get_led_gpio_pin(void) { LEDStateEngine ledStateEngine; static bool stateEngineRunning = false; +static bool pausedReported = false; static void stateEngineTickTimer() { if (stateEngineRunning) { // LOG(LL_INFO, ("digg")); LEDStateEngine_tick(); + pausedReported = false; } else { - LOG(LL_INFO, ("--paused--")); + if (!pausedReported) { + LOG(LL_INFO, ("--paused--")); + pausedReported = true; + } } } static void delayed_boot() { LOG(LL_INFO, ("*** Start timer for LED state engine ticks")); - mgos_set_timer(mgos_sys_config_get_led_tickDuration(), true, stateEngineTickTimer, NULL); // every 0.1 second call timer_cb + mgos_set_timer(mgos_sys_config_get_led_tickDuration(), true, stateEngineTickTimer, NULL); } enum mgos_app_init_result mgos_app_init(void) { int numberOfLeds = mgos_sys_config_get_led_count(); bool loadDefaultData = mgos_sys_config_get_led_useDefaults(); + int ledPin = mgos_sys_config_get_led_pin(); LOG(LL_DEBUG, ("LEDColor_init(loadDefaultData=%s)", loadDefaultData ? "true" : "false")); mgos_msleep(50); @@ -67,13 +74,13 @@ enum mgos_app_init_result mgos_app_init(void) { if (loadDefaultData) { LOG(LL_DEBUG, ("LEDStateEngine_init(numberOfLeds=%d)", numberOfLeds)); mgos_msleep(50); - LEDStateEngine_init(numberOfLeds); + LEDStateEngine_init(ledPin, numberOfLeds); // stateEngineRunning = true; } else { LOG(LL_INFO, ("LEDStateEngine needs to be initialized, not started yet as LEDDefinition not loaded so far")); } - - mgos_set_timer(5000, false, delayed_boot, NULL); // after 5 seconds boot the functions + + mgos_set_timer(1000, false, delayed_boot, NULL); return MGOS_APP_INIT_SUCCESS; } @@ -86,10 +93,7 @@ void printColor(char *name) { void addColor(char *name, int red, int green, int blue) { LEDColor_add(name, red, green, blue); } -void addLedDefinition(char *level, char *room, char *id, char *onColorName) { - LEDColor *c = LEDColor_get(onColorName); - LEDDefinition_add(level, room, id, c->red, c->green, c->blue); -} + void addAnimationStep(int ledIndex, char *ledMode, int duration) { LEDMode m = LEDMode_off; if (strcmp(ledMode, "on") == 0 || strcmp(ledMode, "LEDMode_on") == 0) {