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