Added new mode: Scheduler -- clock based switching of lights
This commit is contained in:
		| @@ -1,28 +1,39 @@ | ||||
| let addColor = ffi('void addColor(char *,int,int,int)'); | ||||
| 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, int)'); | ||||
| let LEDStateEngine_start = ffi('void startLEDStateEngine(void)'); | ||||
| let LEDStateEngine_pause = ffi('void pauseLEDStateEngine(void)'); | ||||
| let LEDStateEngine_getMinTickTime = ffi('double LEDStateEngine_getMinTickTime(void)'); | ||||
| let LEDStateEngine_getMaxTickTime = ffi('double LEDStateEngine_getMaxTickTime(void)'); | ||||
|  | ||||
| let LEDState_getRed = ffi('int LEDState_getLedRed(int)'); | ||||
| let LEDState_getGreen = ffi('int LEDState_getLedGreen(int)'); | ||||
| let LEDState_getBlue = ffi('int LEDState_getLedBlue(int)'); | ||||
| let LEDState_getColorName = ffi('char * LEDState_getLedColorName(int)'); | ||||
| let LEDState_getNextTick = ffi('int LEDState_getNextTick(int)'); | ||||
| let LEDState_getCurrentTick = ffi('int LEDState_getCurrentTick(int)'); | ||||
|  | ||||
| let LEDDefinition_addByName = ffi('void LEDDefinition_addByName(char *, char *, char *, char *)'); | ||||
| let LEDDefinition_getLevel = ffi('char *LEDDefinition_getLevel(int)'); | ||||
| let LEDDefinition_getRoom = ffi('char *LEDDefinition_getRoom(int)'); | ||||
| let LEDDefinition_getId = ffi('char *LEDDefinition_getId(int)'); | ||||
| let LEDDefinition_getOnColorRed = ffi('int LEDDefinition_getOnColorRed(int)'); | ||||
| 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 LEDStateEngine_getMinTickTime = ffi('double LEDStateEngine_getMinTickTime(void)'); | ||||
| let LEDStateEngine_getMaxTickTime = ffi('double LEDStateEngine_getMaxTickTime(void)'); | ||||
| let LEDStateEngine_getBrightness = ffi('int LEDStateEngine_getBrightness(void)'); | ||||
| let LEDStateEngine_setBrightness = ffi('void LEDStateEngine_setBrightness(int)'); | ||||
| let NeoPixel_getBrightness = ffi('int NeoPixel_getBrightness(void)'); | ||||
| let NeoPixel_setBrightness = ffi('void NeoPixel_setBrightness(int)'); | ||||
|  | ||||
| let LEDScheduler_init = ffi('void LEDScheduler_init(int, int, int)'); | ||||
| let LEDScheduler_run = ffi('void LEDScheduler_run(void)'); | ||||
| let LEDScheduler_pause = ffi('void LEDScheduler_pause(void)'); | ||||
| let LEDScheduler_addItem = ffi('void LEDScheduler_addItem(int, int, int, char *, char *)'); | ||||
| let LEDScheduler_setWatch = ffi('void LEDScheduler_setWatch(int, int, int)'); | ||||
|   | ||||
| @@ -1,6 +1,12 @@ | ||||
| [ | ||||
| 	{"name": "off", "red": 0, "green": 0, "blue": 0}, | ||||
| 	{"name": "candle", "red": 30, "green": 15, "blue": 4}, | ||||
| 	{"name": "25w", "red": 35, "green": 15, "blue": 6}, | ||||
| 	{"name": "40w", "red": 50, "green": 25, "blue": 10}, | ||||
| 	{"name": "60w", "red": 70, "green": 45, "blue": 20}, | ||||
| 	{"name": "75w", "red": 80, "green": 70, "blue": 30}, | ||||
| 	{"name": "100w", "red": 100, "green": 85, "blue": 50}, | ||||
| 	{"name": "neon", "red": 100, "green": 95, "blue": 70}, | ||||
| 	{"name": "red", "red": 50, "green": 5, "blue": 5}, | ||||
| 	{"name": "green", "red": 5, "green": 50, "blue": 5}, | ||||
| 	{"name": "blue", "red": 5, "green": 5, "blue": 80}, | ||||
|   | ||||
							
								
								
									
										26
									
								
								fs/demoschedule.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								fs/demoschedule.cfg
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| { | ||||
|   "comment": "7-LED development board", | ||||
|   "lampmapping": [ | ||||
|     "lamp-1", "lamp-2", "lamp-3", "lamp-4", "lamp-5", "lamp-6", "lamp-7" | ||||
|   ], | ||||
|   "mrclock": "N-RE", | ||||
|   "clock_starttime": {"h": 2, "m": 0}, | ||||
|   "clock_speed": 1, | ||||
|   "schedule": [ | ||||
|     {"time": {"h": 2, "m": 30}, "lamp": "lamp-1", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 31}, "lamp": "lamp-2", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 32}, "lamp": "lamp-3", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 45}, "lamp": "lamp-3", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 46}, "lamp": "lamp-2", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 47}, "lamp": "lamp-1", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 2}, "lamp": "lamp-1", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 4}, "lamp": "lamp-2", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 4}, "lamp": "lamp-3", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 18}, "lamp": "lamp-3", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 28}, "lamp": "lamp-1", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 29}, "lamp": "lamp-4", "color": "40w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 30}, "lamp": "lamp-5", "color": "40w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 31}, "lamp": "lamp-6", "color": "40w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 32}, "lamp": "lamp-7", "color": "60w", "mode": "OnOff"} | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										94
									
								
								fs/init.js
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								fs/init.js
									
									
									
									
									
								
							| @@ -61,6 +61,8 @@ let configNumLeds = Cfg.get('led.count'); | ||||
| let colorFile = Cfg.get('led.colorFile'); | ||||
| let animationFile = Cfg.get('led.animationFile'); | ||||
| let lampsFile = Cfg.get('led.lampsFile'); | ||||
| let scheduleFile = Cfg.get('led.scheduleFile'); | ||||
| let dynamicMode = Cfg.get('led.mode'); | ||||
| let useDefaults = Cfg.get('led.useDefaults'); | ||||
| let tickDuration = Cfg.get('led.tickDuration'); | ||||
| let numberOfLeds = configNumLeds, numberOfLedDefs = 0; // from config files, count led definition entries | ||||
| @@ -155,6 +157,41 @@ function loadAnimDefs() { | ||||
|   json = null; | ||||
| } | ||||
|  | ||||
| function loadScheduleDefs() { | ||||
|   // Load Animation Definitions | ||||
|   let json = File.read(scheduleFile); | ||||
|   let scheduleDef = []; | ||||
|   print('scheduleFile =', json); | ||||
|   if (json === '') { | ||||
|     print('ERROR: Schedule definition file does not exist!'); | ||||
|   } else { | ||||
|     scheduleDef = JSON.parse(json); | ||||
|   } | ||||
|   LEDScheduler_init(scheduleDef.schedule.length, numberOfLeds, pin); | ||||
|   LEDScheduler_setWatch(2, 0, 1); // time 02:00, clock speed = 1 real time second per model minute | ||||
|   let ledMapping = scheduleDef.lampmapping; | ||||
|   let mapLed = function (name) { | ||||
|     for (let i=0; i<ledMapping.length; ++i) { | ||||
|       if (ledMapping[i] === name) return i; | ||||
|     } | ||||
|     print("**** ERROR in schedule definition file: no lamp mapping found for lamp", name); | ||||
|     return 0; | ||||
|   }; | ||||
|  | ||||
|   for (i=0; i<scheduleDef.schedule.length; ++i) { | ||||
|     print('- addScheduleItem', scheduleDef.schedule[i].time.h, ":", scheduleDef.schedule[i].time.m, "/", | ||||
|       scheduleDef.schedule[i].lamp, "=", mapLed(scheduleDef.schedule[i].lamp), "/", | ||||
|       scheduleDef.schedule[i].mode, "/", | ||||
|       scheduleDef.schedule[i].color); | ||||
|     LEDScheduler_addItem(scheduleDef.schedule[i].time.h, scheduleDef.schedule[i].time.m, | ||||
|       mapLed(scheduleDef.schedule[i].lamp), | ||||
|       scheduleDef.schedule[i].mode, | ||||
|       scheduleDef.schedule[i].color); | ||||
|   } | ||||
|   json = null; | ||||
| } | ||||
|  | ||||
|  | ||||
| function initialize() { | ||||
|   print('***** Start initialization', getInfo()); | ||||
|   let i; | ||||
| @@ -165,10 +202,30 @@ function initialize() { | ||||
|     startLEDStateEngine(); | ||||
|   } else { | ||||
|     loadColorDefs(); | ||||
|     loadLedDefs(); | ||||
|     loadAnimDefs(); | ||||
|     // Initialize LED State Engine | ||||
|     LEDStateEngine_init(pin, numberOfLeds); | ||||
|     if (dynamicMode === "animation") { | ||||
|       loadLedDefs(); | ||||
|       loadAnimDefs(); | ||||
|       // Initialize LED State Engine | ||||
|       LEDStateEngine_init(pin, numberOfLeds); | ||||
|       print('LED', 'Color', 'R', 'G', 'B', 'Tick', 'Level', 'Room', 'Id'); | ||||
|       print('---', '-----', '---', '---', '-----', '---', '-----', '----', '--'); | ||||
|       for (i=0; i<numberOfLeds; ++i) { | ||||
|         // print(i, LEDState_getRed(i), LEDState_getGreen(i), LEDState_getBlue(i), LEDState_getCurrentTick(i), LEDDefinition_getLevel(i), LEDDefinition_getRoom(i), LEDDefinition_getId(i)) | ||||
|         print(i, LEDState_getColorName(i), | ||||
|           LEDDefinition_getOnColorRed(i), | ||||
|           LEDDefinition_getOnColorGreen(i), | ||||
|           LEDDefinition_getOnColorBlue(i), | ||||
|           LEDState_getCurrentTick(i), | ||||
|           LEDDefinition_getLevel(i), | ||||
|           LEDDefinition_getRoom(i), | ||||
|           LEDDefinition_getId(i)); | ||||
|       } | ||||
|     } else if (dynamicMode === "schedule") { | ||||
|       loadScheduleDefs(); | ||||
|     } else { | ||||
|       print("**** ERROR: Unknown dynamic mode", dynamicMode); | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
|   allLedOff(); | ||||
|   print('***** End of initialization', getInfo()); | ||||
| @@ -177,20 +234,7 @@ function initialize() { | ||||
|   print('NumLEDs:', numberOfLeds); | ||||
|   print('Ticks:', getTicks()); | ||||
|   print('Tick duration:', tickDuration, 'ms'); | ||||
|   print('Brightness:', LEDStateEngine_getBrightness(), '%'); | ||||
|   print('LED', 'Color', 'R', 'G', 'B', 'Tick', 'Level', 'Room', 'Id'); | ||||
|   print('---', '-----', '---', '---', '-----', '---', '-----', '----', '--'); | ||||
|   for (i=0; i<numberOfLeds; ++i) { | ||||
|     // print(i, LEDState_getRed(i), LEDState_getGreen(i), LEDState_getBlue(i), LEDState_getCurrentTick(i), LEDDefinition_getLevel(i), LEDDefinition_getRoom(i), LEDDefinition_getId(i)) | ||||
|     print(i, LEDState_getColorName(i), | ||||
|       LEDDefinition_getOnColorRed(i), | ||||
|       LEDDefinition_getOnColorGreen(i), | ||||
|       LEDDefinition_getOnColorBlue(i), | ||||
|       LEDState_getCurrentTick(i), | ||||
|       LEDDefinition_getLevel(i), | ||||
|       LEDDefinition_getRoom(i), | ||||
|       LEDDefinition_getId(i)); | ||||
|   } | ||||
|   print('Brightness:', NeoPixel_getBrightness(), '%'); | ||||
| } | ||||
|  | ||||
| Timer.set(300, false, function() { | ||||
| @@ -200,8 +244,14 @@ Timer.set(300, false, function() { | ||||
|   allLedOff(); | ||||
|   print('***** LED test pattern', getInfo()); | ||||
|   showLedTestPattern(); | ||||
|   print('***** Start LED state engine and LED-update timer', getInfo()); | ||||
|   LEDStateEngine_start(); | ||||
|   if (dynamicMode === "animation") { | ||||
|     print('***** Start LED state engine and LED-update timer', getInfo()); | ||||
|     LEDStateEngine_start(); | ||||
|   } else if (dynamicMode === "schedule") { | ||||
|     print('***** Start schedule based animation', getInfo()); | ||||
|     NeoPixel_clear(); | ||||
|     LEDScheduler_run(); | ||||
|   } | ||||
|   Timer.set(30000, true, function() { | ||||
|     print("Timer: minTickTime =", LEDStateEngine_getMinTickTime(), | ||||
|         "ms, maxTickTime =", LEDStateEngine_getMaxTickTime(), "ms"); | ||||
| @@ -215,7 +265,7 @@ RPC.addHandler('led.setBrightness', function(args) { | ||||
|   // print(args); | ||||
|   if (args !== undefined && args.level !== undefined) { | ||||
|     if (args.level > 0 && args.level <= 100) { | ||||
|       LEDStateEngine_setBrightness(args.level); | ||||
|       NeoPixel_setBrightness(args.level); | ||||
|       return { result: 'ok' }; | ||||
|     } else { | ||||
|       return { error: 'Brightness level must be in the range 1..100' }; | ||||
| @@ -226,7 +276,7 @@ RPC.addHandler('led.setBrightness', function(args) { | ||||
| }, "{level: %d}"); | ||||
| print('     led.getBrightness'); | ||||
| RPC.addHandler('led.getBrightness', function(args) { | ||||
|   let brightness = LEDStateEngine_getBrightness(); | ||||
|   let brightness = NeoPixel_getBrightness(); | ||||
|   return { result: 'ok', brightness: brightness }; | ||||
| }, null); | ||||
| print('     led.pause'); | ||||
|   | ||||
							
								
								
									
										30
									
								
								fs/schedule.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								fs/schedule.cfg
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| { | ||||
|   "comment": "Company office building with facility manager appartement", | ||||
|   "lampmapping": [ | ||||
|     "eg-1.1", "eg-1.2", "eg-3.1", "eg-4", "eg-5", "eg-8", "eg-7, "eg-6", "eg-3.2", "eg-2.2", "eg-2.1", | ||||
|     "og-1.1", "og-1.2", "og-3.1", "og-4", "og-5", "og-8", "og-7, "og-6", "og-3.2", "og-2.2", "og-2.1", | ||||
|     "dg-1", "dg-2", "dg-3", "dg-4", "dg-5", "dg-6", "dg-7", "dg-8" | ||||
|   ], | ||||
|   "mrclock": "N-RE", | ||||
|   "clock_starttime": {"h": 2, "m": 0}, | ||||
|   "clock_speed": 1, | ||||
|   "schedule": [ | ||||
|     {"time": {"h": 2, "m": 30}, "lamp": "dg-5", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 31}, "lamp": "dg-8", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 32}, "lamp": "dg-7", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 45}, "lamp": "dg-7", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 46}, "lamp": "dg-8", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 2, "m": 47}, "lamp": "dg-5", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 2}, "lamp": "dg-5", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 4}, "lamp": "dg-8", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 4}, "lamp": "dg-7", "color": "25w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 18}, "lamp": "dg-7", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 28}, "lamp": "dg-5", "color": "off", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 29}, "lamp": "dg-3", "color": "40w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 30}, "lamp": "og-3.2", "color": "40w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 30}, "lamp": "eg-3.2", "color": "40w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 30}, "lamp": "eg-4", "color": "60w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 45}, "lamp": "eg-3.1", "color": "40w", "mode": "OnOff"}, | ||||
|     {"time": {"h": 4, "m": 47}, "lamp": "eg-1.1", "color": "60w", "mode": "OnOff"} | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										2
									
								
								mos.yml
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								mos.yml
									
									
									
									
									
								
							| @@ -39,6 +39,8 @@ config_schema: | ||||
|   - ["led.colorFile", "s", "colors.cfg", {title: "File name containing color definitions"}] | ||||
|   - ["led.lampsFile", "s", "lamps.cfg", {title: "File name containing lamp definitions"}] | ||||
|   - ["led.animationFile", "s", "animations.cfg", {title: "File name containing animation definitions"}] | ||||
|   - ["led.mode", "s", "schedule", {title: "Mode = animation (use lampsFile + animationFile) | schedule (use scheduleFile)"}] | ||||
|   - ["led.scheduleFile", "s", "demoschedule.cfg", {title: "File name containing schedule definitions"}] | ||||
| build_vars: | ||||
|   MGOS_ENABLE_ONEWIRE: 1 | ||||
| cflags: [] | ||||
|   | ||||
| @@ -9,7 +9,6 @@ | ||||
|  | ||||
| static LEDStateEngine theLEDStateEngine; | ||||
| static int ticks = 0; | ||||
| static int brightness = 50; | ||||
|  | ||||
| int getTicks(void) { return ticks; } | ||||
|  | ||||
| @@ -27,7 +26,6 @@ void LEDStateEngine_setNumberOfLeds(int numberOfLeds) { | ||||
| void LEDStateEngine_init(int ledPin, int numberOfLeds) { | ||||
| 	theLEDStateEngine.comment = ""; | ||||
| 	theLEDStateEngine.pin = ledPin; | ||||
| 	brightness = mgos_sys_config_get_led_brightness(); | ||||
| 	LEDStateEngine_setNumberOfLeds(numberOfLeds); | ||||
| 	for (int i=0; i<numberOfLeds; ++i) { | ||||
| 		LEDState_init(i, LEDDefinition_get(i)); | ||||
| @@ -61,24 +59,11 @@ void LEDStateEngine_tick() { | ||||
| double LEDStateEngine_getMinTickTime() { return 1000 * minTickTime; } | ||||
| double LEDStateEngine_getMaxTickTime() { return 1000 * maxTickTime; } | ||||
|  | ||||
| static uint8_t adjustBrightness(uint8_t value) { | ||||
| 	return (value * brightness)/100; | ||||
| } | ||||
|  | ||||
| int LEDStateEngine_getBrightness() { return brightness; } | ||||
| void LEDStateEngine_setBrightness(int newBrightness) { | ||||
| 	if (newBrightness > 0 && newBrightness <= 100) { | ||||
| 			brightness = newBrightness; | ||||
| 	} else { | ||||
| 		LOG(LL_ERROR, ("invalid brightness value %d", newBrightness)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void updateLedDisplay(LEDState *state) { | ||||
| 	NeoPixel_set(state->index, | ||||
| 		adjustBrightness(state->currentColor.red), | ||||
| 		adjustBrightness(state->currentColor.green), | ||||
| 		adjustBrightness(state->currentColor.blue)); | ||||
| 		state->currentColor.red, | ||||
| 		state->currentColor.green, | ||||
| 		state->currentColor.blue); | ||||
| } | ||||
|  | ||||
| void LEDState_tick(int ledNum) { | ||||
|   | ||||
| @@ -3,12 +3,28 @@ | ||||
| #include "mgos_bitbang.h" | ||||
| #include "mgos_gpio.h" | ||||
| #include "mgos_system.h" | ||||
| #include "mgos_sys_config.h" | ||||
| #include "NeoPixel.h" | ||||
|  | ||||
| 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; | ||||
| static enum NeoPixel_ColorOrder NeoPixel_colorOrder = NeoPixel_colorOrder_GRB; | ||||
| static int brightness = 50; | ||||
|  | ||||
| static uint8_t adjustBrightness(uint8_t value) { | ||||
| 	return (value * brightness)/100; | ||||
| } | ||||
|  | ||||
| int NeoPixel_getBrightness() { return brightness; } | ||||
| void NeoPixel_setBrightness(int newBrightness) { | ||||
| 	if (newBrightness > 0 && newBrightness <= 100) { | ||||
| 			brightness = newBrightness; | ||||
| 	} else { | ||||
| 		LOG(LL_ERROR, ("invalid brightness value %d", newBrightness)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| // ## **`NeoPixel_clear()`** | ||||
| // Clear in-memory values of the pixels. | ||||
| @@ -44,7 +60,8 @@ void NeoPixel_create(uint8_t pin, uint8_t numPixels, enum NeoPixel_ColorOrder or | ||||
|   mgos_gpio_set_mode(pin, MGOS_GPIO_MODE_OUTPUT); | ||||
|   // GPIO.write(pin, 0);  // Keep in reset. | ||||
|   mgos_gpio_write(pin, false); | ||||
|   LOG(LL_INFO, ("pin=%d, numPixels=%d, colorOrder=%d", pin, numPixels, order)); | ||||
|   brightness = mgos_sys_config_get_led_brightness(); | ||||
|   LOG(LL_INFO, ("pin=%d, numPixels=%d, colorOrder=%d, brightness=%d", pin, numPixels, order, brightness)); | ||||
|   NeoPixel_clear(); | ||||
| } | ||||
|  | ||||
| @@ -78,9 +95,9 @@ void NeoPixel_set(int pixel, int red, int green, int blue) { | ||||
|   } else if (NeoPixel_colorOrder == NeoPixel_colorOrder_BGR) { | ||||
|     v0 = blue; v1 = green; v2 = red; | ||||
|   } else return; | ||||
|   NeoPixel_leds[3*pixel] = v0; | ||||
|   NeoPixel_leds[3*pixel+1] = v1; | ||||
|   NeoPixel_leds[3*pixel+2] = v2; | ||||
|   NeoPixel_leds[3*pixel] = adjustBrightness(v0); | ||||
|   NeoPixel_leds[3*pixel+1] = adjustBrightness(v1); | ||||
|   NeoPixel_leds[3*pixel+2] = adjustBrightness(v2); | ||||
| } | ||||
|  | ||||
| // ## **`NeoPixel_show()`** | ||||
|   | ||||
| @@ -11,5 +11,7 @@ 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(); | ||||
| extern int NeoPixel_getBrightness(); | ||||
| extern void NeoPixel_setBrightness(int newBrightness); | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										105
									
								
								src/Scheduler.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/Scheduler.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| #include "Scheduler.h" | ||||
| #include "LEDDefinition.h" | ||||
| #include "NeoPixel.h" | ||||
| #include "mgos_timers.h" | ||||
|  | ||||
| enum ScheduleItemMode { | ||||
|   ScheduleItemMode_OnOff, | ||||
|   ScheduleItemMode_NeonOn, | ||||
|   ScheduleItemMode_tv_bw, | ||||
|   ScheduleItemMode_tv_color | ||||
| }; | ||||
|  | ||||
| static enum ScheduleItemMode modeFromName(char *name) { | ||||
|   if (strcmp(name, "OnOff") == 0) return ScheduleItemMode_OnOff; | ||||
|   if (strcmp(name, "NeonOn") == 0) return ScheduleItemMode_NeonOn; | ||||
|   if (strcmp(name, "TV_BW") == 0) return ScheduleItemMode_tv_bw; | ||||
|   if (strcmp(name, "TV_Color") == 0) return ScheduleItemMode_tv_color; | ||||
|   LOG(LL_ERROR, ("Invalid mode name: %s", name)); | ||||
|   return ScheduleItemMode_OnOff; | ||||
| } | ||||
|  | ||||
| typedef struct Schedule_t { | ||||
|   uint8_t h; | ||||
|   uint8_t m; | ||||
|   uint8_t led; | ||||
|   enum ScheduleItemMode mode; | ||||
|   LEDColor *color; | ||||
| } Schedule; | ||||
| static Schedule *schedule = NULL; | ||||
| static int numScheduleItems = 0; | ||||
| static int loadedScheduleItems = 0; | ||||
| static int numberOfLeds = 0; | ||||
| static int currentHour = 0; | ||||
| static int currentMinute = 0; | ||||
| static int clockSpeed = 1; // # seconds for every real time minute | ||||
| static bool clockRunning = false; | ||||
| static mgos_timer_id clockTimer = 0; | ||||
|  | ||||
| static void executeScheduleItem(Schedule *s) { | ||||
|   LOG(LL_INFO, ("%d:%d LED #%d / mode=%d / color=%s", s->h, s->m, s->led, s->mode, s->color->name)); | ||||
|   if (s->mode == ScheduleItemMode_OnOff) { | ||||
|     NeoPixel_set(s->led, s->color->red, s->color->green, s->color->blue); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void LEDScheduler_timerTick() { | ||||
|   bool ledsNeedUpdate = false; | ||||
|  | ||||
|   if (clockRunning) { | ||||
|     currentMinute++; | ||||
|     if (currentMinute >= 60) { | ||||
|       currentMinute = 0; | ||||
|       currentHour++; | ||||
|       if (currentHour >= 24) { | ||||
|         currentHour = 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   for (int i=0; i<loadedScheduleItems; ++i) { | ||||
|     if (schedule[i].h == currentHour && schedule[i].m == currentMinute) { | ||||
|       // ACTION! | ||||
|       executeScheduleItem(&schedule[i]); | ||||
|       ledsNeedUpdate = true; | ||||
|     } | ||||
|   } | ||||
|   if (ledsNeedUpdate) { | ||||
|     NeoPixel_show(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void LEDScheduler_init(int setNumScheduleItems, int setNumberOfLeds, int ledPin) { | ||||
|   if (schedule != NULL) free(schedule); | ||||
|   numScheduleItems = setNumScheduleItems; | ||||
|   loadedScheduleItems = 0; | ||||
|   numberOfLeds = setNumberOfLeds; | ||||
|   schedule = malloc(numScheduleItems * sizeof(Schedule)); | ||||
|   NeoPixel_release(); | ||||
|   NeoPixel_create(ledPin, numberOfLeds, NeoPixel_colorOrder_GRB); | ||||
|   clockRunning = false; | ||||
|   clockTimer = mgos_set_timer(1000, true, LEDScheduler_timerTick, NULL); | ||||
| } | ||||
|  | ||||
| void LEDScheduler_addItem(int h, int m, int led, char *mode, char *colorName) { | ||||
|   if (loadedScheduleItems >= numScheduleItems) { | ||||
|     LOG(LL_ERROR, ("Cannot load schedule item as storage is already full, %d:%d LED #%d", h, m, led)); | ||||
|     return; | ||||
|   } | ||||
|   schedule[loadedScheduleItems].h = h; | ||||
|   schedule[loadedScheduleItems].m = m; | ||||
|   schedule[loadedScheduleItems].led = led; | ||||
|   schedule[loadedScheduleItems].mode = modeFromName(mode); | ||||
|   schedule[loadedScheduleItems].color = LEDColor_get(colorName);; | ||||
|   schedule[loadedScheduleItems].h = h; | ||||
|   ++loadedScheduleItems; | ||||
| } | ||||
|  | ||||
| void LEDScheduler_run() { clockRunning = true; } | ||||
| void LEDScheduler_pause() { clockRunning = false; } | ||||
|  | ||||
| void LEDScheduler_setWatch(int h, int m, int speed) { | ||||
|   currentHour = h; | ||||
|   currentMinute = m; | ||||
|   clockSpeed = speed; | ||||
|   LOG(LL_INFO, ("set time %d:%d and speed to %d real-time seconds for a model minute", h, m, speed)); | ||||
| } | ||||
							
								
								
									
										5
									
								
								src/Scheduler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/Scheduler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| extern void LEDScheduler_init(int, int, int); | ||||
| extern void LEDScheduler_run(); | ||||
| extern void LEDScheduler_pause(); | ||||
| extern void LEDScheduler_addItem(int h, int m, int led, char *mode, char *colorName); | ||||
| extern void LEDScheduler_setWatch(int h, int m, int speed); | ||||
| @@ -52,6 +52,7 @@ static void stateEngineTickTimer() { | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| 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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user