Initial commit of base code
This commit is contained in:
parent
21caa63178
commit
3b63f9703d
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"cmake.configureOnOpen": false
|
||||
}
|
39
include/README
Normal file
39
include/README
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
lib/README
Normal file
46
lib/README
Normal file
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
29
platformio.ini
Normal file
29
platformio.ini
Normal file
|
@ -0,0 +1,29 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
[platformio]
|
||||
default_envs = nodemcuv2
|
||||
|
||||
[env:huzzah]
|
||||
platform = https://github.com/platformio/platform-espressif8266.git
|
||||
board = huzzah
|
||||
framework = arduino
|
||||
lib_deps = tzapu/WiFiManager@^0.16.0
|
||||
upload_speed = 115200
|
||||
monitor_speed = 115200
|
||||
|
||||
[env:nodemcuv2]
|
||||
platform = https://github.com/platformio/platform-espressif8266.git
|
||||
board = nodemcuv2
|
||||
framework = arduino
|
||||
lib_deps = tzapu/WiFiManager@^0.16.0
|
||||
upload_speed = 115200
|
||||
monitor_speed = 115200
|
||||
upload_port = COM5
|
||||
monitor_port = COM5
|
543
src/main.cpp
Normal file
543
src/main.cpp
Normal file
|
@ -0,0 +1,543 @@
|
|||
#include <Arduino.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <DNSServer.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <WiFiManager.h>
|
||||
|
||||
// The GPIO pin numbers for the three colors. Make sure these match your wiring/schematic.
|
||||
#define GPIO_RED 13
|
||||
#define GPIO_GREEN 12
|
||||
#define GPIO_BLUE 15
|
||||
|
||||
// The target ID of this device on the network if ID_SWITCHED is false
|
||||
// Commands sent to target ID 0 (zero) will be executed by ALL targets
|
||||
#define TARGET_ID_FIXED 1
|
||||
|
||||
// If a 4-position dip switch is present and tied to 4 GPIO pins, set ID_SWITCHED to true and put the pin numbers in the ID_BIT_? settings
|
||||
#define ID_SWITCHED true
|
||||
#define ID_BIT_0 16
|
||||
#define ID_BIT_1 14
|
||||
#define ID_BIT_2 4
|
||||
#define ID_BIT_3 5
|
||||
|
||||
// Used to turn debug serial output on/off
|
||||
#define DEBUG false
|
||||
|
||||
// UDP Command values
|
||||
#define CMD_OFF 0x00
|
||||
#define CMD_SETLEVELS 0x01
|
||||
#define CMD_AUTOPATTERN 0x02
|
||||
#define CMD_AUTODISABLE 0x03
|
||||
|
||||
// Auto-cycler state conditions
|
||||
#define AUTO_DISABLED 0x00
|
||||
#define AUTO_ACTIVE 0x01
|
||||
|
||||
// Maximum analog output level
|
||||
#define MAX_ANALOG 1023
|
||||
|
||||
// ID Numbers for the UDP Packet filter
|
||||
#define PACKET_FILTER_1 4039196302
|
||||
#define PACKET_FILTER_2 3194769291
|
||||
|
||||
// Set up this reference so we can put the huge array definition at the end
|
||||
extern const uint16_t gamma10[];
|
||||
|
||||
// Variables for tracking blue LED blink state during initialization
|
||||
volatile bool blueInitState = false;
|
||||
volatile unsigned long blueToggleCount;
|
||||
|
||||
// Struct for storing color value sets
|
||||
// Colors are obvious. restDuration is how long to rest on this color.
|
||||
struct colorTriplet {
|
||||
short red;
|
||||
short green;
|
||||
short blue;
|
||||
unsigned long restDuration;
|
||||
|
||||
colorTriplet() {
|
||||
red = 0;
|
||||
green = 0;
|
||||
blue = 0;
|
||||
restDuration = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// This gets dynamically reset in setup() from the DIP switch or the #define at the top of the sketch so make sure this is set to 0 (zero)
|
||||
byte myTargetID = 0;
|
||||
|
||||
// Variables for keeping the state of automatic color switching
|
||||
byte autoMode = AUTO_DISABLED;
|
||||
bool autoActive = false;
|
||||
|
||||
// For storing automatic color values
|
||||
#define MAX_AUTO_COLORS 35
|
||||
unsigned int rampDuration;
|
||||
byte numAutoColors = 0;
|
||||
struct colorTriplet autoColors[MAX_AUTO_COLORS];
|
||||
byte autoColorTargetIndex = 0;
|
||||
short redStatic = 0;
|
||||
short greenStatic = 0;
|
||||
short blueStatic = 0;
|
||||
bool resting = false;
|
||||
|
||||
// Debugging crap
|
||||
String rampValues[200] = {""};
|
||||
int rampValuesIndex = 0;
|
||||
|
||||
// We're going to listen on port 6565
|
||||
WiFiUDP listener;
|
||||
|
||||
// Variables to track message IDs so we don't process duplicate messages
|
||||
unsigned int lastMessageID = 0;
|
||||
unsigned int curMessageID = 0;
|
||||
|
||||
// Reset function
|
||||
void(* resetFunc) (void) = 0;
|
||||
|
||||
void inline blueBlinkISR(void) {
|
||||
if ( blueToggleCount < 60 ) {
|
||||
blueInitState = !blueInitState;
|
||||
analogWrite(GPIO_BLUE, (blueInitState) ? MAX_ANALOG : 0);
|
||||
}
|
||||
blueToggleCount++;
|
||||
if ( DEBUG ) {
|
||||
Serial.print("Init State: bIS=");
|
||||
Serial.print(blueInitState);
|
||||
Serial.print(" bTC=");
|
||||
Serial.println(blueToggleCount);
|
||||
}
|
||||
if ( blueToggleCount > 600 ) {
|
||||
timer0_detachInterrupt();
|
||||
analogWrite(GPIO_BLUE, 0);
|
||||
ESP.restart();
|
||||
}
|
||||
timer0_write(ESP.getCycleCount() + 40000000);
|
||||
}
|
||||
|
||||
// Set up our initial states and WiFi
|
||||
void setup() {
|
||||
// Set the three color PWM pins to output
|
||||
pinMode(GPIO_RED, OUTPUT);
|
||||
pinMode(GPIO_GREEN, OUTPUT);
|
||||
pinMode(GPIO_BLUE, OUTPUT);
|
||||
|
||||
// If ID_SWITCHED is true then set myTargetID from the dip switch, otherwise set it from TARGET_ID_FIXED
|
||||
if ( ID_SWITCHED ) {
|
||||
pinMode(ID_BIT_0, INPUT_PULLUP);
|
||||
pinMode(ID_BIT_1, INPUT_PULLUP);
|
||||
pinMode(ID_BIT_2, INPUT_PULLUP);
|
||||
pinMode(ID_BIT_3, INPUT_PULLUP);
|
||||
bitWrite(myTargetID, 0, ((digitalRead(ID_BIT_0) == HIGH) ? 1 : 0));
|
||||
bitWrite(myTargetID, 1, ((digitalRead(ID_BIT_1) == HIGH) ? 1 : 0));
|
||||
bitWrite(myTargetID, 2, ((digitalRead(ID_BIT_2) == HIGH) ? 1 : 0));
|
||||
bitWrite(myTargetID, 3, ((digitalRead(ID_BIT_3) == HIGH) ? 1 : 0));
|
||||
//pinMode(ID_BIT_1, INPUT);
|
||||
} else {
|
||||
myTargetID = TARGET_ID_FIXED;
|
||||
}
|
||||
|
||||
// Start up the serial console output
|
||||
Serial.begin(115200);
|
||||
Serial.println("--- Serial Output Started ---");
|
||||
delay(10);
|
||||
|
||||
WiFiManager wifiManager;
|
||||
//wifiManager.resetSettings();
|
||||
noInterrupts();
|
||||
timer0_isr_init();
|
||||
timer0_attachInterrupt(blueBlinkISR);
|
||||
timer0_write(ESP.getCycleCount() + 1000);
|
||||
interrupts();
|
||||
wifiManager.autoConnect("JaJLEDController");
|
||||
|
||||
// Show our ID!
|
||||
Serial.println();
|
||||
Serial.print("My target ID: ");
|
||||
Serial.println(myTargetID);
|
||||
|
||||
// Turn off blue LED and disable interrupt
|
||||
timer0_detachInterrupt();
|
||||
analogWrite(GPIO_BLUE, 0);
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
// Start listening for packets on port 6565 (yes, this should probably be defined at the top)
|
||||
listener.begin(6565);
|
||||
}
|
||||
|
||||
bool processMessage() {
|
||||
struct colorTriplet colorBlank;
|
||||
byte command;
|
||||
uint32 messageTargetID = 0;
|
||||
|
||||
// Read in the packet data to buff (up to 1024 bytes which is way more than we would ever need)
|
||||
char buff[1024];
|
||||
listener.read(buff, 1024);
|
||||
listener.flush();
|
||||
|
||||
// Check for the Packet Filter ID values and skip packet if not matched
|
||||
unsigned int filter1, filter2;
|
||||
memcpy(&filter1, (char*)buff, 4);
|
||||
memcpy(&filter2, (char*)buff + 4, 4);
|
||||
if ( (filter1 != PACKET_FILTER_1) || (filter2 != PACKET_FILTER_2) ) {
|
||||
if ( DEBUG ) {
|
||||
Serial.println("Filter Fail: " + String(filter1) + ", " + String(filter2));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse out the messageID field
|
||||
memcpy(&curMessageID, (char*)buff + 8, 4);
|
||||
// If we've seen the message before, skip it, otherwise update lastMessageID
|
||||
if ( curMessageID == lastMessageID ) return false;
|
||||
lastMessageID = curMessageID;
|
||||
|
||||
// Parse out the command and target ID fields
|
||||
memcpy(&command, (char*)buff + 12, 1);
|
||||
|
||||
memcpy(&messageTargetID, (char*)buff + 13, 4);
|
||||
|
||||
// If this packet isn't destined for ID=0 (all targets) or ID=TARGET_ID (our ID) then stop processing
|
||||
if ( (myTargetID != 0 ) && (messageTargetID != 0) && (messageTargetID != myTargetID) ) {
|
||||
if ( DEBUG ) {
|
||||
Serial.println("Got packet for different ID! Mine=" + String(myTargetID) + " Target=" + String(messageTargetID));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( DEBUG ) Serial.println("Got UDP packet!");
|
||||
|
||||
// Clear out the global autoColors[] array
|
||||
memset(autoColors, 0, sizeof(autoColors));
|
||||
|
||||
// If we get a CMD_SETLEVELS then disable autoMode, set the new static values and ramp to that color
|
||||
if ( command == CMD_SETLEVELS ) {
|
||||
autoMode = AUTO_DISABLED;
|
||||
numAutoColors = 1;
|
||||
autoColorTargetIndex = 0;
|
||||
memcpy(&rampDuration, (char*)buff + 17, 4);
|
||||
memcpy(&autoColors[0].red, (char*)buff + 21, 1);
|
||||
memcpy(&autoColors[0].green, (char*)buff + 22, 1);
|
||||
memcpy(&autoColors[0].blue, (char*)buff + 23, 1);
|
||||
autoColors[0].red = map(autoColors[0].red, 0, 255, 0, 1023);
|
||||
autoColors[0].green = map(autoColors[0].green, 0, 255, 0, 1023);
|
||||
autoColors[0].blue = map(autoColors[0].blue, 0, 255, 0, 1023);
|
||||
redStatic = autoColors[0].red;
|
||||
greenStatic = autoColors[0].green;
|
||||
blueStatic = autoColors[0].blue;
|
||||
if ( DEBUG ) {
|
||||
String debugOutput = "Setting Levels: ";
|
||||
debugOutput += String(redStatic) + ", ";
|
||||
debugOutput += String(greenStatic) + ", ";
|
||||
debugOutput += String(blueStatic) + ", ";
|
||||
debugOutput += String(rampDuration);
|
||||
Serial.println(debugOutput);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we get a CMD_AUTOPATTERN then build up the autoColors array and set autoMode to AUTO_ACTIVE
|
||||
if ( command == CMD_AUTOPATTERN ) {
|
||||
String debugOutput = "";
|
||||
autoMode = AUTO_ACTIVE;
|
||||
autoColorTargetIndex = 0;
|
||||
memcpy(&rampDuration, (char*)buff + 17, 4);
|
||||
memcpy(&numAutoColors, (char*)buff + 21, 1);
|
||||
if ( numAutoColors > MAX_AUTO_COLORS ) numAutoColors = MAX_AUTO_COLORS;
|
||||
if ( DEBUG ) debugOutput += "New AutoPattern " + String(numAutoColors) + ": ";
|
||||
for ( int i=0; i<numAutoColors; i++ ) {
|
||||
memcpy(&autoColors[i].red, (char*)buff + 22 + (i*7), 1);
|
||||
memcpy(&autoColors[i].green, (char*)buff + 23 + (i*7), 1);
|
||||
memcpy(&autoColors[i].blue, (char*)buff + 24 + (i*7), 1);
|
||||
memcpy(&autoColors[i].restDuration, (char*)buff + 25 + (i*7), 4);
|
||||
autoColors[i].red = map(autoColors[i].red, 0, 255, 0, 1023);
|
||||
autoColors[i].green = map(autoColors[i].green, 0, 255, 0, 1023);
|
||||
autoColors[i].blue = map(autoColors[i].blue, 0, 255, 0, 1023);
|
||||
if ( DEBUG ) {
|
||||
debugOutput += String(i) + "=[";
|
||||
debugOutput += String(autoColors[i].red) + ", ";
|
||||
debugOutput += String(autoColors[i].green) + ", ";
|
||||
debugOutput += String(autoColors[i].blue) + ", ";
|
||||
debugOutput += String(autoColors[i].restDuration) + "], ";
|
||||
}
|
||||
}
|
||||
if ( DEBUG ) {
|
||||
debugOutput += "Ramp=" + String(rampDuration);
|
||||
Serial.println(debugOutput);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we get a CMD_AUTODISABLE then disable autoMode and ramp back to the last static color levels
|
||||
if ( command == CMD_AUTODISABLE ) {
|
||||
autoMode = AUTO_DISABLED;
|
||||
numAutoColors = 1;
|
||||
autoColorTargetIndex = 0;
|
||||
autoColors[0].red = redStatic;
|
||||
autoColors[0].green = greenStatic;
|
||||
autoColors[0].blue = blueStatic;
|
||||
rampDuration = 1000;
|
||||
if ( DEBUG ) {
|
||||
String debugOutput = "Resetting Levels to static: ";
|
||||
debugOutput += String(redStatic) + ", ";
|
||||
debugOutput += String(greenStatic) + ", ";
|
||||
debugOutput += String(blueStatic) + ", ";
|
||||
debugOutput += "Ramp=" + String(rampDuration);
|
||||
Serial.println(debugOutput);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we get a CMD_OFF then set the levels to zero and ensure autoMode is disabled
|
||||
// The rampDuration is set to the same value as the step value during ramping (yes, this should probably be a constant or a #define)
|
||||
if ( command == CMD_OFF ) {
|
||||
autoMode = AUTO_DISABLED;
|
||||
numAutoColors = 1;
|
||||
autoColorTargetIndex = 0;
|
||||
rampDuration = 10;
|
||||
autoColors[0].restDuration = 10000;
|
||||
redStatic = 0;
|
||||
greenStatic = 0;
|
||||
blueStatic = 0;
|
||||
if ( DEBUG ) Serial.println("Shutting off LEDs");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static short redTarget = 0, greenTarget = 0, blueTarget = 0;
|
||||
static short redInitial = 0, greenInitial = 0, blueInitial = 0;
|
||||
static short redPrevious = 0, greenPrevious = 0, bluePrevious = 0;
|
||||
static short redLevel = 0, greenLevel = 0, blueLevel = 0;
|
||||
static bool newColor = false;
|
||||
static unsigned long nextDIPSample = 0;
|
||||
unsigned long nowMillis = millis();
|
||||
static unsigned long nextRampMillis;
|
||||
static unsigned long rampStartMillis;
|
||||
static unsigned long restingEndMillis;
|
||||
static unsigned long reportMillis = 0;
|
||||
static unsigned long repCount = 0;
|
||||
nowMillis = millis();
|
||||
if ( nowMillis >= reportMillis ) {
|
||||
repCount++;
|
||||
//Serial.print("Still alive... ("); Serial.print(repCount); Serial.println(")");
|
||||
/*
|
||||
String debugOutput = "Current State: C=";
|
||||
debugOutput += String(redLevel) + "," + String(greenLevel) + "," + String(blueLevel) + " ";
|
||||
debugOutput += "T=" + String(redTarget) + "," + String(greenTarget) + "," + String(blueTarget) + " ";
|
||||
debugOutput += "Index=" + String(autoColorTargetIndex) + " Ramp=" + String(rampDuration);
|
||||
Serial.println(debugOutput);
|
||||
*/
|
||||
reportMillis = nowMillis + 1000;
|
||||
}
|
||||
|
||||
// Check to see if we have a new packet waiting and parse it out if we do
|
||||
int packetSize = listener.parsePacket();
|
||||
if ( packetSize ) {
|
||||
if ( processMessage() ) {
|
||||
// Always reset newColor and resting states when we get a new UDP color command
|
||||
newColor = true;
|
||||
resting = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( newColor ) {
|
||||
// Reset rampColors Debugging
|
||||
for ( int i=0; i<200; i++ ) { rampValues[i] = ""; };
|
||||
rampValuesIndex = 0;
|
||||
// If the incoming auto-color pattern (from a CMD_AUTOPATTERN) has a single all zero color,
|
||||
// and autoMode is AUTO_ACTIVE then generate colors randomly instead of from the pattern
|
||||
if ( (autoMode == AUTO_ACTIVE) && (numAutoColors == 1) && (autoColors[0].red == 0) && (autoColors[0].green == 0) && (autoColors[0].blue == 0) ) {
|
||||
//redTarget = pgm_read_word(&gamma10[random(0, MAX_ANALOG)]);
|
||||
//greenTarget = pgm_read_word(&gamma10[random(0, MAX_ANALOG)]);
|
||||
//blueTarget = pgm_read_word(&gamma10[random(0, MAX_ANALOG)]);
|
||||
redTarget = gamma10[random(0, MAX_ANALOG)];
|
||||
greenTarget = gamma10[random(0, MAX_ANALOG)];
|
||||
blueTarget = gamma10[random(0, MAX_ANALOG)];
|
||||
} else {
|
||||
//redTarget = pgm_read_word(&gamma10[autoColors[autoColorTargetIndex].red]);
|
||||
//greenTarget = pgm_read_word(&gamma10[autoColors[autoColorTargetIndex].green]);
|
||||
//blueTarget = pgm_read_word(&gamma10[autoColors[autoColorTargetIndex].blue]);
|
||||
redTarget = gamma10[autoColors[autoColorTargetIndex].red];
|
||||
greenTarget = gamma10[autoColors[autoColorTargetIndex].green];
|
||||
blueTarget = gamma10[autoColors[autoColorTargetIndex].blue];
|
||||
}
|
||||
redInitial = redLevel;
|
||||
greenInitial = greenLevel;
|
||||
blueInitial = blueLevel;
|
||||
newColor = false;
|
||||
rampStartMillis = nowMillis;
|
||||
nextRampMillis = rampStartMillis;
|
||||
if ( DEBUG ) {
|
||||
String debugOutput = "Switching to new color: C=";
|
||||
debugOutput += String(redInitial) + "," + String(greenInitial) + "," + String(blueInitial) + " ";
|
||||
debugOutput += "T=" + String(redTarget) + "," + String(greenTarget) + "," + String(blueTarget) + " ";
|
||||
debugOutput += "Index=" + String(autoColorTargetIndex) + " Ramp=" + String(rampDuration);
|
||||
Serial.println(debugOutput);
|
||||
}
|
||||
}
|
||||
|
||||
if ( (redLevel != redTarget) || (greenLevel != greenTarget) || (blueLevel != blueTarget) ) {
|
||||
// Calculate the current rampInterval (how many milliseconds between start of ramp and now)
|
||||
unsigned long rampInterval = nowMillis - rampStartMillis;
|
||||
|
||||
// If nowMillis wrapped around the max INT32 we will just go straight to the last iteration of the ramp
|
||||
if ( rampInterval > rampDuration ) rampInterval = rampDuration;
|
||||
|
||||
// If we aren't at the target values yet, map the current number of milliseconds
|
||||
// into the ramp (rampInterval) to the (color)Initial -> (color)Target values
|
||||
if ( redLevel != redTarget ) {
|
||||
redLevel = map(rampInterval, 0, rampDuration, redInitial, redTarget);
|
||||
if ( abs(redTarget - redLevel) == 1 ) redLevel = redTarget;
|
||||
}
|
||||
if ( greenLevel != greenTarget ) {
|
||||
greenLevel = map(rampInterval, 0, rampDuration, greenInitial, greenTarget);
|
||||
if ( abs(greenTarget - greenLevel) == 1 ) greenLevel = greenTarget;
|
||||
}
|
||||
if ( blueLevel != blueTarget ) {
|
||||
blueLevel = map(rampInterval, 0, rampDuration, blueInitial, blueTarget);
|
||||
if ( abs(blueTarget - blueLevel) == 1 ) blueLevel = blueTarget;
|
||||
}
|
||||
if ( (nowMillis >= nextRampMillis) || ((redLevel == redTarget) && (greenLevel == greenTarget) && (blueLevel == blueTarget)) ) {
|
||||
if ( redLevel != redPrevious ) {
|
||||
analogWrite(GPIO_RED, redLevel);
|
||||
redPrevious = redLevel;
|
||||
}
|
||||
if ( greenLevel != greenPrevious ) {
|
||||
analogWrite(GPIO_GREEN, greenLevel);
|
||||
greenPrevious = greenLevel;
|
||||
}
|
||||
if ( blueLevel != bluePrevious ) {
|
||||
analogWrite(GPIO_BLUE, blueLevel);
|
||||
bluePrevious = blueLevel;
|
||||
}
|
||||
//rampValues[rampValuesIndex] = (String)"(" + (nowMillis - nextRampMillis) + "," + rampValuesIndex + ")" + "(" + redLevel + "," + greenLevel + "," + blueLevel + "),";
|
||||
//rampValuesIndex++;
|
||||
nextRampMillis = nowMillis + 15;
|
||||
}
|
||||
// If all the colors are at their targets and we aren't resting, then start resting
|
||||
} else if ( !resting ) {
|
||||
resting = true;
|
||||
restingEndMillis = nowMillis + autoColors[autoColorTargetIndex].restDuration;
|
||||
if ( DEBUG ) {
|
||||
String debugOutput = "Now resting for: ";
|
||||
debugOutput += String(autoColors[autoColorTargetIndex].restDuration) + " on ";
|
||||
debugOutput += String(autoColorTargetIndex);
|
||||
Serial.println(debugOutput);
|
||||
//Serial.print("rampValues=[");
|
||||
//for ( int i=0; i<rampValuesIndex; i++ ) Serial.print(rampValues[i]);
|
||||
//Serial.println("]");
|
||||
}
|
||||
// If we are resting and the restingEndMillis passes then it is time to ramp to
|
||||
// the next color IF AND ONLY IF we are in a pattern (i.e. don't keep ramping if we're on a static color)
|
||||
} else if ( (nowMillis >= restingEndMillis) && (autoMode == AUTO_ACTIVE) ) {
|
||||
if ( DEBUG ) { Serial.print("Done resting on index=" + String(autoColorTargetIndex)); }
|
||||
resting = false;
|
||||
newColor = true;
|
||||
autoColorTargetIndex = (autoColorTargetIndex < (numAutoColors - 1)) ? autoColorTargetIndex + 1 : 0;
|
||||
}
|
||||
|
||||
// If the DIP switches change, go ahead and adjust myTargetID accordingly. Saves having to restart.
|
||||
// In order to save clock cycles this is only done every 10 seconds.
|
||||
if ( ID_SWITCHED && (nowMillis >= nextDIPSample) ) {
|
||||
byte newVal = 0;
|
||||
bitWrite(newVal, 0, ((digitalRead(ID_BIT_0) == HIGH) ? 1 : 0));
|
||||
bitWrite(newVal, 1, ((digitalRead(ID_BIT_1) == HIGH) ? 1 : 0));
|
||||
bitWrite(newVal, 2, ((digitalRead(ID_BIT_2) == HIGH) ? 1 : 0));
|
||||
bitWrite(newVal, 3, ((digitalRead(ID_BIT_3) == HIGH) ? 1 : 0));
|
||||
if ( myTargetID != newVal ) {
|
||||
myTargetID = newVal;
|
||||
if ( DEBUG ) {
|
||||
Serial.println("BIT_0: " + String(digitalRead(ID_BIT_0)));
|
||||
Serial.println("BIT_1: " + String(digitalRead(ID_BIT_1)));
|
||||
Serial.println("BIT_2: " + String(digitalRead(ID_BIT_2)));
|
||||
Serial.println("BIT_3: " + String(digitalRead(ID_BIT_3)));
|
||||
Serial.println("New Target ID Detected: " + String(myTargetID));
|
||||
}
|
||||
}
|
||||
nextDIPSample = nowMillis + 10000; // Sample the DIP switches every 10 seconds
|
||||
}
|
||||
|
||||
yield();
|
||||
}
|
||||
|
||||
//const uint16_t PROGMEM gamma10[] {
|
||||
const uint16_t gamma10[] {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,
|
||||
5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,
|
||||
6,6,6,7,7,7,7,7,7,7,7,7,8,8,8,
|
||||
8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,
|
||||
10,10,10,10,10,11,11,11,11,11,11,12,12,12,12,
|
||||
12,12,12,13,13,13,13,13,13,14,14,14,14,14,15,
|
||||
15,15,15,15,15,16,16,16,16,16,17,17,17,17,17,
|
||||
18,18,18,18,18,19,19,19,19,20,20,20,20,20,21,
|
||||
21,21,21,22,22,22,22,23,23,23,23,24,24,24,24,
|
||||
25,25,25,25,26,26,26,26,27,27,27,27,28,28,28,
|
||||
29,29,29,29,30,30,30,31,31,31,31,32,32,32,33,
|
||||
33,33,34,34,34,35,35,35,35,36,36,36,37,37,37,
|
||||
38,38,38,39,39,40,40,40,41,41,41,42,42,42,43,
|
||||
43,43,44,44,45,45,45,46,46,46,47,47,48,48,48,
|
||||
49,49,50,50,50,51,51,52,52,52,53,53,54,54,55,
|
||||
55,55,56,56,57,57,58,58,58,59,59,60,60,61,61,
|
||||
62,62,63,63,63,64,64,65,65,66,66,67,67,68,68,
|
||||
69,69,70,70,71,71,72,72,73,73,74,74,75,75,76,
|
||||
76,77,77,78,79,79,80,80,81,81,82,82,83,83,84,
|
||||
85,85,86,86,87,87,88,89,89,90,90,91,92,92,93,
|
||||
93,94,95,95,96,96,97,98,98,99,99,100,101,101,102,
|
||||
103,103,104,105,105,106,106,107,108,108,109,110,110,111,112,
|
||||
112,113,114,115,115,116,117,117,118,119,119,120,121,122,122,
|
||||
123,124,124,125,126,127,127,128,129,130,130,131,132,132,133,
|
||||
134,135,136,136,137,138,139,139,140,141,142,143,143,144,145,
|
||||
146,146,147,148,149,150,151,151,152,153,154,155,155,156,157,
|
||||
158,159,160,161,161,162,163,164,165,166,167,167,168,169,170,
|
||||
171,172,173,174,175,175,176,177,178,179,180,181,182,183,184,
|
||||
185,186,186,187,188,189,190,191,192,193,194,195,196,197,198,
|
||||
199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,
|
||||
214,215,216,217,218,219,220,221,222,223,224,225,226,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,241,242,243,244,245,
|
||||
246,247,248,249,251,252,253,254,255,256,257,259,260,261,262,
|
||||
263,264,266,267,268,269,270,272,273,274,275,276,278,279,280,
|
||||
281,282,284,285,286,287,289,290,291,292,294,295,296,297,299,
|
||||
300,301,302,304,305,306,308,309,310,311,313,314,315,317,318,
|
||||
319,321,322,323,325,326,327,329,330,331,333,334,336,337,338,
|
||||
340,341,342,344,345,347,348,349,351,352,354,355,356,358,359,
|
||||
361,362,364,365,366,368,369,371,372,374,375,377,378,380,381,
|
||||
383,384,386,387,389,390,392,393,395,396,398,399,401,402,404,
|
||||
405,407,408,410,412,413,415,416,418,419,421,423,424,426,427,
|
||||
429,431,432,434,435,437,439,440,442,444,445,447,448,450,452,
|
||||
453,455,457,458,460,462,463,465,467,468,470,472,474,475,477,
|
||||
479,480,482,484,486,487,489,491,493,494,496,498,500,501,503,
|
||||
505,507,509,510,512,514,516,518,519,521,523,525,527,528,530,
|
||||
532,534,536,538,539,541,543,545,547,549,551,553,554,556,558,
|
||||
560,562,564,566,568,570,572,574,575,577,579,581,583,585,587,
|
||||
589,591,593,595,597,599,601,603,605,607,609,611,613,615,617,
|
||||
619,621,623,625,627,629,631,633,635,637,640,642,644,646,648,
|
||||
650,652,654,656,658,660,663,665,667,669,671,673,675,678,680,
|
||||
682,684,686,688,690,693,695,697,699,701,704,706,708,710,712,
|
||||
715,717,719,721,724,726,728,730,733,735,737,739,742,744,746,
|
||||
749,751,753,755,758,760,762,765,767,769,772,774,776,779,781,
|
||||
783,786,788,790,793,795,798,800,802,805,807,810,812,814,817,
|
||||
819,822,824,827,829,831,834,836,839,841,844,846,849,851,854,
|
||||
856,859,861,864,866,869,871,874,876,879,881,884,887,889,892,
|
||||
894,897,899,902,905,907,910,912,915,918,920,923,925,928,931,
|
||||
933,936,939,941,944,947,949,952,955,957,960,963,965,968,971,
|
||||
973,976,979,982,984,987,990,992,995,998,1001,1004,1006,1009,1012,
|
||||
1015,1017,1020,1023 };
|
11
test/README
Normal file
11
test/README
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
Loading…
Reference in New Issue
Block a user