Fixed effects and ws2812 controller fw
Final push to this fork unless other critical errors are found.
This commit is contained in:
parent
9d84283e01
commit
48cb1018e9
@ -1,79 +1,131 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <ArduinoOTA.h>
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
//#include <WebSocketsServer.h>
|
|
||||||
//#include <Hash.h>
|
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
#include <NeoPixelBus.h>
|
|
||||||
|
|
||||||
// Set to the number of LEDs in your LED strip
|
#define FASTLED_ESP8266_DMA // better control for ESP8266 will output or RX pin requires fork https://github.com/coryking/FastLED
|
||||||
#define NUM_LEDS 242
|
#include "FastLED.h"
|
||||||
// Maximum number of packets to hold in the buffer. Don't change this.
|
|
||||||
#define BUFFER_LEN 726
|
|
||||||
// Toggles FPS output (1 = print FPS over serial, 0 = disable output)
|
|
||||||
#define PRINT_FPS 1
|
|
||||||
|
|
||||||
//NeoPixelBus settings
|
/************ Network Information (CHANGE THESE FOR YOUR SETUP) ************************/
|
||||||
const uint8_t PixelPin = 3; // make sure to set this to the correct pin, ignored for Esp8266(set to 3 by default for DMA)
|
const char* ssid = "WIFI_SSID";
|
||||||
|
const char* password = "WIFI_PASSWORD";
|
||||||
|
|
||||||
// Wifi and socket settings
|
const char* sensor_name = "TEST_SENSOR_HOSTNAME";
|
||||||
const char* ssid = "YOUR_WIFI_SSID";
|
const char* ota_password = "OTA_PASSWORD";
|
||||||
const char* password = "YOUR_WIFI_PASSWORD";
|
|
||||||
unsigned int localPort = 7778;
|
|
||||||
byte packetBuffer[BUFFER_LEN];
|
|
||||||
RgbColor ledDataBuffer[NUM_LEDS];
|
|
||||||
|
|
||||||
// LED strip
|
const bool static_ip = true;
|
||||||
NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> ledstrip(NUM_LEDS, PixelPin);
|
IPAddress ip(192, 168, 1, 112);
|
||||||
|
IPAddress gateway(192, 168, 1, 1);
|
||||||
WiFiUDP port;
|
|
||||||
|
|
||||||
// Network information
|
|
||||||
// IP must match the IP in config.py
|
|
||||||
IPAddress ip(192, 168, 137, 200);
|
|
||||||
// Set gateway to your router's gateway
|
|
||||||
IPAddress gateway(192, 168, 137, 1);
|
|
||||||
IPAddress subnet(255, 255, 255, 0);
|
IPAddress subnet(255, 255, 255, 0);
|
||||||
|
|
||||||
|
const int udp_port = 7778;
|
||||||
|
|
||||||
|
/*********************************** FastLED Defintions ********************************/
|
||||||
|
#define NUM_LEDS 250
|
||||||
|
#define DATA_PIN 5
|
||||||
|
//#define CLOCK_PIN 2
|
||||||
|
#define CHIPSET WS2812B
|
||||||
|
#define COLOR_ORDER GRB
|
||||||
|
|
||||||
|
/*********************************** Globals *******************************************/
|
||||||
|
WiFiUDP port;
|
||||||
|
CRGB leds[NUM_LEDS];
|
||||||
|
|
||||||
|
/********************************** Start Setup ****************************************/
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
//WiFi.config(ip, gateway, subnet);
|
|
||||||
|
// Setup FastLED
|
||||||
|
#ifdef CLOCK_PIN
|
||||||
|
FastLED.addLeds<CHIPSET, DATA_PIN, CLOCK_PIN, COLOR_ORDER>(leds, NUM_LEDS);
|
||||||
|
#else
|
||||||
|
FastLED.addLeds<CHIPSET, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Setup the wifi connection
|
||||||
|
setup_wifi();
|
||||||
|
|
||||||
|
// Setup OTA firmware updates
|
||||||
|
setup_ota();
|
||||||
|
|
||||||
|
// Initialize the UDP port
|
||||||
|
port.begin(udp_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_wifi() {
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.print("Connecting to ");
|
||||||
|
Serial.print(ssid);
|
||||||
|
|
||||||
|
if (static_ip) {
|
||||||
|
WiFi.config(ip, gateway, subnet);
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFi.hostname(sensor_name);
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
WiFi.begin(ssid, password);
|
WiFi.begin(ssid, password);
|
||||||
Serial.println("");
|
|
||||||
// Connect to wifi and print the IP address over serial
|
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
delay(500);
|
delay(500);
|
||||||
Serial.print(".");
|
Serial.print(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("");
|
Serial.println("");
|
||||||
Serial.print("Connected to ");
|
Serial.println("WiFi connected!");
|
||||||
Serial.println(ssid);
|
|
||||||
Serial.print("IP address: ");
|
Serial.print("IP address: ");
|
||||||
Serial.println(WiFi.localIP());
|
Serial.println(WiFi.localIP());
|
||||||
port.begin(localPort);
|
|
||||||
ledstrip.Begin();//Begin output
|
|
||||||
ledstrip.Show();//Clear the strip for use
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t N = 0;
|
void setup_ota() {
|
||||||
#if PRINT_FPS
|
ArduinoOTA.setHostname(sensor_name);
|
||||||
uint16_t fpsCounter = 0;
|
ArduinoOTA.setPassword(ota_password);
|
||||||
uint32_t secondTimer = 0;
|
|
||||||
#endif
|
ArduinoOTA.onStart([]() {
|
||||||
|
Serial.println("Starting");
|
||||||
|
});
|
||||||
|
ArduinoOTA.onEnd([]() {
|
||||||
|
Serial.println("\nEnd");
|
||||||
|
});
|
||||||
|
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||||
|
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||||
|
});
|
||||||
|
ArduinoOTA.onError([](ota_error_t error) {
|
||||||
|
Serial.printf("Error[%u]: ", error);
|
||||||
|
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
||||||
|
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
||||||
|
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
||||||
|
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
||||||
|
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
||||||
|
});
|
||||||
|
ArduinoOTA.begin();
|
||||||
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// Read data over socket
|
|
||||||
int packetSize = port.parsePacket();
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
// If packets have been received, interpret the command
|
delay(1);
|
||||||
if (packetSize) {
|
Serial.print("WIFI Disconnected. Attempting reconnection.");
|
||||||
int len = port.read(packetBuffer, BUFFER_LEN);
|
setup_wifi();
|
||||||
for(int i = 0; i < len; i+=4) {
|
return;
|
||||||
packetBuffer[len] = 0;
|
|
||||||
N = packetBuffer[i];
|
|
||||||
RgbColor pixel((uint8_t)packetBuffer[i+1], (uint8_t)packetBuffer[i+2], (uint8_t)packetBuffer[i+3]);
|
|
||||||
ledstrip.SetPixelColor(N, pixel);
|
|
||||||
}
|
}
|
||||||
ledstrip.Show();
|
|
||||||
Serial.print("/");
|
ArduinoOTA.handle();
|
||||||
|
|
||||||
|
// TODO: Hookup either a more elaborate protocol, or a secondary
|
||||||
|
// communication channel (i.e. mqtt) for functional control. This
|
||||||
|
// will also give the ability to have some non-reative effects to
|
||||||
|
// be driven completely locally making them less glitchy.
|
||||||
|
|
||||||
|
// Handle UDP data
|
||||||
|
int packetSize = port.parsePacket();
|
||||||
|
if (packetSize == sizeof(leds)) {
|
||||||
|
port.read((char*)leds, sizeof(leds));
|
||||||
|
FastLED.show();
|
||||||
|
} else if (packetSize) {
|
||||||
|
Serial.printf("Invalid packet size: %u (expected %u)\n", packetSize, sizeof(leds));
|
||||||
|
port.flush();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ settings = { # All settings
|
|||||||
'MAX_FREQUENCY': 18000, # Frequencies above this value will be removed during audio processing
|
'MAX_FREQUENCY': 18000, # Frequencies above this value will be removed during audio processing
|
||||||
'MAX_BRIGHTNESS': 250, # Frequencies above this value will be removed during audio processing
|
'MAX_BRIGHTNESS': 250, # Frequencies above this value will be removed during audio processing
|
||||||
'N_ROLLING_HISTORY': 4, # Number of past audio frames to include in the rolling window
|
'N_ROLLING_HISTORY': 4, # Number of past audio frames to include in the rolling window
|
||||||
'MIN_VOLUME_THRESHOLD': 0.01 # No music visualization displayed if recorded audio volume below threshold
|
'MIN_VOLUME_THRESHOLD': 0.001 # No music visualization displayed if recorded audio volume below threshold
|
||||||
#'LOGARITHMIC_SCALING': True, # Scale frequencies logarithmically to match perceived pitch of human ear
|
#'LOGARITHMIC_SCALING': True, # Scale frequencies logarithmically to match perceived pitch of human ear
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ settings = { # All settings
|
|||||||
|
|
||||||
# All devices and their respective settings. Indexed by name, call each one what you want.
|
# All devices and their respective settings. Indexed by name, call each one what you want.
|
||||||
"devices":{"Desk Strip":{
|
"devices":{"Desk Strip":{
|
||||||
"configuration":{"TYPE": "esp8266", # Device type (see below for all supported boards)
|
"configuration":{"TYPE": "ESP8266", # Device type (see below for all supported boards)
|
||||||
# Required configuration for device. See below for all required keys per device
|
# Required configuration for device. See below for all required keys per device
|
||||||
"AUTO_DETECT": True, # Set this true if you're using windows hotspot to connect (see below for more info)
|
"AUTO_DETECT": True, # Set this true if you're using windows hotspot to connect (see below for more info)
|
||||||
"MAC_ADDR": "2c-3a-e8-2f-2c-9f", # MAC address of the ESP8266. Only used if AUTO_DETECT is True
|
"MAC_ADDR": "2c-3a-e8-2f-2c-9f", # MAC address of the ESP8266. Only used if AUTO_DETECT is True
|
||||||
@ -42,7 +42,7 @@ settings = { # All settings
|
|||||||
# Other configuration
|
# Other configuration
|
||||||
"N_PIXELS": 58, # Number of pixels in the LED strip (must match ESP8266 firmware)
|
"N_PIXELS": 58, # Number of pixels in the LED strip (must match ESP8266 firmware)
|
||||||
"N_FFT_BINS": 24, # Number of frequency bins to use when transforming audio to frequency domain
|
"N_FFT_BINS": 24, # Number of frequency bins to use when transforming audio to frequency domain
|
||||||
"current_effect": "Single" # Currently selected effect for this board, used as default when program launches
|
"current_effect": "Energy" # Currently selected effect for this board, used as default when program launches
|
||||||
},
|
},
|
||||||
|
|
||||||
# Configurable options for this board's effects go in this dictionary.
|
# Configurable options for this board's effects go in this dictionary.
|
||||||
@ -67,7 +67,10 @@ settings = { # All settings
|
|||||||
"reverse_roll": False, # Reverse movement of gradient roll
|
"reverse_roll": False, # Reverse movement of gradient roll
|
||||||
"blur": 3.0, # Amount of blur to apply
|
"blur": 3.0, # Amount of blur to apply
|
||||||
"flip_lr":False}, # Flip output left-right
|
"flip_lr":False}, # Flip output left-right
|
||||||
"Scroll": {"decay": 0.995, # How quickly the colour fades away as it moves
|
"Scroll": {"lows_color": "Red", # Colour of low frequencies
|
||||||
|
"mids_color": "Green", # Colour of mid frequencies
|
||||||
|
"high_color": "Blue", # Colour of high frequencies
|
||||||
|
"decay": 0.995, # How quickly the colour fades away as it moves
|
||||||
"speed": 1, # Speed of scroll
|
"speed": 1, # Speed of scroll
|
||||||
"r_multiplier": 1.0, # How much red
|
"r_multiplier": 1.0, # How much red
|
||||||
"g_multiplier": 1.0, # How much green
|
"g_multiplier": 1.0, # How much green
|
||||||
@ -101,7 +104,7 @@ settings = { # All settings
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Main Strip":{
|
"Main Strip":{
|
||||||
"configuration":{"TYPE": "esp8266", # Device type (see below for all supported boards)
|
"configuration":{"TYPE": "ESP8266", # Device type (see below for all supported boards)
|
||||||
# Required configuration for device. See below for all required keys per device
|
# Required configuration for device. See below for all required keys per device
|
||||||
"AUTO_DETECT": True, # Set this true if you're using windows hotspot to connect (see below for more info)
|
"AUTO_DETECT": True, # Set this true if you're using windows hotspot to connect (see below for more info)
|
||||||
"MAC_ADDR": "5c-cf-7f-f0-8c-f3", # MAC address of the ESP8266. Only used if AUTO_DETECT is True
|
"MAC_ADDR": "5c-cf-7f-f0-8c-f3", # MAC address of the ESP8266. Only used if AUTO_DETECT is True
|
||||||
@ -136,7 +139,10 @@ settings = { # All settings
|
|||||||
"reverse_roll": False, # Reverse movement of gradient roll
|
"reverse_roll": False, # Reverse movement of gradient roll
|
||||||
"blur": 3.0, # Amount of blur to apply
|
"blur": 3.0, # Amount of blur to apply
|
||||||
"flip_lr":False}, # Flip output left-right
|
"flip_lr":False}, # Flip output left-right
|
||||||
"Scroll": {"decay": 0.995, # How quickly the colour fades away as it moves
|
"Scroll": {"lows_color": "Red", # Colour of low frequencies
|
||||||
|
"mids_color": "Green", # Colour of mid frequencies
|
||||||
|
"high_color": "Blue", # Colour of high frequencies
|
||||||
|
"decay": 0.995, # How quickly the colour fades away as it moves
|
||||||
"speed": 1, # Speed of scroll
|
"speed": 1, # Speed of scroll
|
||||||
"r_multiplier": 1.0, # How much red
|
"r_multiplier": 1.0, # How much red
|
||||||
"g_multiplier": 1.0, # How much green
|
"g_multiplier": 1.0, # How much green
|
||||||
@ -190,11 +196,56 @@ settings = { # All settings
|
|||||||
"Sunset" : ["Red", "Orange", "Yellow"],
|
"Sunset" : ["Red", "Orange", "Yellow"],
|
||||||
"Ocean" : ["Green", "Light blue", "Blue"],
|
"Ocean" : ["Green", "Light blue", "Blue"],
|
||||||
"Jungle" : ["Green", "Red", "Orange"],
|
"Jungle" : ["Green", "Red", "Orange"],
|
||||||
"Sunny" : ["Yellow", "Light blue", "Orange", "Blue"]
|
"Sunny" : ["Yellow", "Light blue", "Orange", "Blue"],
|
||||||
|
"Fruity" : ["Orange", "Blue"],
|
||||||
|
"Peach" : ["Orange", "Pink"],
|
||||||
|
"Rust" : ["Orange", "Red"]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
device_req_config = {"Stripless" : None, # duh
|
||||||
|
"BlinkStick" : None,
|
||||||
|
"DotStar" : None,
|
||||||
|
"ESP8266" : {"AUTO_DETECT": ["Auto Detect",
|
||||||
|
"Automatically detect device on network using MAC address",
|
||||||
|
"checkbox",
|
||||||
|
True],
|
||||||
|
"MAC_ADDR" : ["Mac Address",
|
||||||
|
"Hardware address of device, used for auto-detection",
|
||||||
|
"textbox",
|
||||||
|
"aa-bb-cc-dd-ee-ff"],
|
||||||
|
"UDP_IP" : ["IP Address",
|
||||||
|
"IP address of device, used if auto-detection isn't active",
|
||||||
|
"textbox",
|
||||||
|
"xxx.xxx.xxx.xxx"],
|
||||||
|
"UDP_PORT" : ["Port",
|
||||||
|
"Port used to communicate with device",
|
||||||
|
"textbox",
|
||||||
|
"7778"]},
|
||||||
|
"RaspberryPi" : {"LED_PIN" : ["LED Pin",
|
||||||
|
"GPIO pin connected to the LED strip RaspberryPi (must support PWM)",
|
||||||
|
"textbox",
|
||||||
|
"10"],
|
||||||
|
"LED_FREQ_HZ": ["LED Frequency",
|
||||||
|
"LED signal frequency in Hz",
|
||||||
|
"textbox",
|
||||||
|
"800000"],
|
||||||
|
"LED_DMA" : ["DMA Channel",
|
||||||
|
"DMA channel used for generating PWM signal",
|
||||||
|
"textbox",
|
||||||
|
"5"],
|
||||||
|
"LED_INVERT" : ["Invert LEDs",
|
||||||
|
"Set True if using an inverting logic level converter",
|
||||||
|
"checkbox",
|
||||||
|
True]},
|
||||||
|
"Fadecandy" : {"SERVER" : ["Server Address",
|
||||||
|
"Address of Fadecandy server",
|
||||||
|
"textbox",
|
||||||
|
"localhost:7890"]}
|
||||||
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
~~ NOTES ~~
|
~~ NOTES ~~
|
||||||
|
|
||||||
@ -215,45 +266,45 @@ be loaded. Basically it works as you would expect it to.
|
|||||||
|
|
||||||
Device used to control LED strip.
|
Device used to control LED strip.
|
||||||
|
|
||||||
'esp8266' means that you are using an ESP8266 module to control the LED strip
|
'ESP8266' means that you are using an ESP8266 module to control the LED strip
|
||||||
and commands will be sent to the ESP8266 over WiFi. You can have as many of
|
and commands will be sent to the ESP8266 over WiFi. You can have as many of
|
||||||
these as your computer is able to handle.
|
these as your computer is able to handle.
|
||||||
|
|
||||||
'pi' means that you are using a Raspberry Pi as a standalone unit to process
|
'RaspberryPi' means that you are using a Raspberry Pi as a standalone unit to process
|
||||||
audio input and control the LED strip directly.
|
audio input and control the LED strip directly.
|
||||||
|
|
||||||
'blinkstick' means that a BlinkstickPro is connected to this PC which will be used
|
'BlinkStick' means that a BlinkstickPro is connected to this PC which will be used
|
||||||
to control the leds connected to it.
|
to control the leds connected to it.
|
||||||
|
|
||||||
'fadecandy' means that a fadecandy server is running on your computer and is connected
|
'Fadecandy' means that a Fadecandy server is running on your computer and is connected
|
||||||
via usb to a fadecandy board connected to LEDs
|
via usb to a Fadecandy board connected to LEDs
|
||||||
|
|
||||||
'dotstar' creates an APA102-based output device. LMK if you have any success
|
'DotStar' creates an APA102-based output device. LMK if you have any success
|
||||||
getting this to work becuase i have no clue if it will.
|
getting this to work becuase i have no clue if it will.
|
||||||
|
|
||||||
'stripless' means that the program will run without sending data to a strip.
|
'Stripless' means that the program will run without sending data to a strip.
|
||||||
Useful for development etc, but doesn't look half as good ;)
|
Useful for development etc, but doesn't look half as good ;)
|
||||||
|
|
||||||
[REQUIRED CONFIGURATION KEYS]
|
[REQUIRED CONFIGURATION KEYS]
|
||||||
|
|
||||||
===== 'esp8266'
|
===== 'ESP8266'
|
||||||
"AUTO_DETECT" # Set this true if you're using windows hotspot to connect (see below for more info)
|
"AUTO_DETECT" # Set this true if you're using windows hotspot to connect (see below for more info)
|
||||||
"MAC_ADDR" # MAC address of the ESP8266. Only used if AUTO_DETECT is True
|
"MAC_ADDR" # MAC address of the ESP8266. Only used if AUTO_DETECT is True
|
||||||
"UDP_IP" # IP address of the ESP8266. Must match IP in ws2812_controller.ino
|
"UDP_IP" # IP address of the ESP8266. Must match IP in ws2812_controller.ino
|
||||||
"UDP_PORT" # Port number used for socket communication between Python and ESP8266
|
"UDP_PORT" # Port number used for socket communication between Python and ESP8266
|
||||||
===== 'pi'
|
===== 'RaspberryPi'
|
||||||
"LED_PIN" # GPIO pin connected to the LED strip pixels (must support PWM)
|
"LED_PIN" # GPIO pin connected to the LED strip pixels (must support PWM)
|
||||||
"LED_FREQ_HZ" # LED signal frequency in Hz (usually 800kHz)
|
"LED_FREQ_HZ" # LED signal frequency in Hz (usually 800kHz)
|
||||||
"LED_DMA" # DMA channel used for generating PWM signal (try 5)
|
"LED_DMA" # DMA channel used for generating PWM signal (try 5)
|
||||||
"BRIGHTNESS" # Brightness of LED strip between 0 and 255
|
"BRIGHTNESS" # Brightness of LED strip between 0 and 255
|
||||||
"LED_INVERT" # Set True if using an inverting logic level converter
|
"LED_INVERT" # Set True if using an inverting logic level converter
|
||||||
===== 'blinkstick'
|
===== 'BlinkStick'
|
||||||
No required configuration keys
|
No required configuration keys
|
||||||
===== 'fadecandy'
|
===== 'Fadecandy'
|
||||||
"SERVER" # Address of fadecandy server. (usually 'localhost:7890')
|
"SERVER" # Address of Fadecandy server. (usually 'localhost:7890')
|
||||||
===== 'dotstar'
|
===== 'DotStar'
|
||||||
No required configuration keys
|
No required configuration keys
|
||||||
===== 'stripless'
|
===== 'Stripless'
|
||||||
No required configuration keys (heh)
|
No required configuration keys (heh)
|
||||||
|
|
||||||
[AUTO_DETECT]
|
[AUTO_DETECT]
|
||||||
@ -293,19 +344,19 @@ There is no point using more bins than there are pixels on the LED strip.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
for board in settings["devices"]:
|
for board in settings["devices"]:
|
||||||
if settings["devices"][board]["configuration"]["TYPE"] == 'esp8266':
|
if settings["devices"][board]["configuration"]["TYPE"] == 'ESP8266':
|
||||||
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = False
|
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = False
|
||||||
# Set to False because the firmware handles gamma correction + dither
|
# Set to False because the firmware handles gamma correction + dither
|
||||||
elif settings["devices"][board]["configuration"]["TYPE"] == 'pi':
|
elif settings["devices"][board]["configuration"]["TYPE"] == 'RaspberryPi':
|
||||||
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = True
|
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = True
|
||||||
# Set to True because Raspberry Pi doesn't use hardware dithering
|
# Set to True because Raspberry Pi doesn't use hardware dithering
|
||||||
elif settings["devices"][board]["configuration"]["TYPE"] == 'blinkstick':
|
elif settings["devices"][board]["configuration"]["TYPE"] == 'BlinkStick':
|
||||||
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = True
|
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = True
|
||||||
elif settings["devices"][board]["configuration"]["TYPE"] == 'dotstar':
|
elif settings["devices"][board]["configuration"]["TYPE"] == 'DotStar':
|
||||||
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = False
|
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = False
|
||||||
elif settings["devices"][board]["configuration"]["TYPE"] == 'fadecandy':
|
elif settings["devices"][board]["configuration"]["TYPE"] == 'Fadecandy':
|
||||||
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = False
|
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = False
|
||||||
elif settings["devices"][board]["configuration"]["TYPE"] == 'stripless':
|
elif settings["devices"][board]["configuration"]["TYPE"] == 'Stripless':
|
||||||
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = False
|
settings["devices"][board]["configuration"]["SOFTWARE_GAMMA_CORRECTION"] = False
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid device selected. Device {} not known.".format(settings["devices"][board]["configuration"]["TYPE"]))
|
raise ValueError("Invalid device selected. Device {} not known.".format(settings["devices"][board]["configuration"]["TYPE"]))
|
||||||
|
6
python/lib/settings.ini
Normal file
6
python/lib/settings.ini
Normal file
File diff suppressed because one or more lines are too long
372
python/main.py
372
python/main.py
@ -47,7 +47,8 @@ class Visualizer():
|
|||||||
self.beat_count = 0
|
self.beat_count = 0
|
||||||
self.freq_channels = [deque(maxlen=self.freq_channel_history) for i in range(config.settings["devices"][self.board]["configuration"]["N_FFT_BINS"])]
|
self.freq_channels = [deque(maxlen=self.freq_channel_history) for i in range(config.settings["devices"][self.board]["configuration"]["N_FFT_BINS"])]
|
||||||
self.prev_output = np.array([[0 for i in range(config.settings["devices"][self.board]["configuration"]["N_PIXELS"])] for i in range(3)])
|
self.prev_output = np.array([[0 for i in range(config.settings["devices"][self.board]["configuration"]["N_PIXELS"])] for i in range(3)])
|
||||||
self.prev_spectrum = [0 for i in range(config.settings["devices"][self.board]["configuration"]["N_PIXELS"]//2)]
|
self.output = np.array([[0 for i in range(config.settings["devices"][self.board]["configuration"]["N_PIXELS"])] for i in range(3)])
|
||||||
|
self.prev_spectrum = np.array([config.settings["devices"][self.board]["configuration"]["N_PIXELS"] // 2])
|
||||||
self.current_freq_detects = {"beat":False,
|
self.current_freq_detects = {"beat":False,
|
||||||
"low":False,
|
"low":False,
|
||||||
"mid":False,
|
"mid":False,
|
||||||
@ -118,12 +119,12 @@ class Visualizer():
|
|||||||
["reverse_grad", "Reverse Gradient", "checkbox"],
|
["reverse_grad", "Reverse Gradient", "checkbox"],
|
||||||
["reverse_roll", "Reverse Roll", "checkbox"],
|
["reverse_roll", "Reverse Roll", "checkbox"],
|
||||||
["flip_lr", "Flip LR", "checkbox"]],
|
["flip_lr", "Flip LR", "checkbox"]],
|
||||||
"Scroll":[["blur", "Blur", "float_slider", (0.05,4.0,0.05)],
|
"Scroll":[["lows_color", "Lows Color", "dropdown", config.settings["colors"]],
|
||||||
|
["mids_color", "Mids Color", "dropdown", config.settings["colors"]],
|
||||||
|
["high_color", "Highs Color", "dropdown", config.settings["colors"]],
|
||||||
|
["blur", "Blur", "float_slider", (0.05,4.0,0.05)],
|
||||||
["decay", "Decay", "float_slider", (0.97,1.0,0.0005)],
|
["decay", "Decay", "float_slider", (0.97,1.0,0.0005)],
|
||||||
["speed", "Speed", "slider", (1,5,1)],
|
["speed", "Speed", "slider", (1,5,1)]],
|
||||||
["r_multiplier", "Red", "float_slider", (0.05,1.0,0.05)],
|
|
||||||
["g_multiplier", "Green", "float_slider", (0.05,1.0,0.05)],
|
|
||||||
["b_multiplier", "Blue", "float_slider", (0.05,1.0,0.05)]],
|
|
||||||
"Power":[["color_mode", "Color Mode", "dropdown", config.settings["gradients"]],
|
"Power":[["color_mode", "Color Mode", "dropdown", config.settings["gradients"]],
|
||||||
["s_color", "Spark Color ", "dropdown", config.settings["colors"]],
|
["s_color", "Spark Color ", "dropdown", config.settings["colors"]],
|
||||||
["s_count", "Spark Amount", "slider", (0,config.settings["devices"][self.board]["configuration"]["N_PIXELS"]//6,1)],
|
["s_count", "Spark Amount", "slider", (0,config.settings["devices"][self.board]["configuration"]["N_PIXELS"]//6,1)],
|
||||||
@ -149,8 +150,9 @@ class Visualizer():
|
|||||||
["g", "Green value", "slider", (0,255,1)],
|
["g", "Green value", "slider", (0,255,1)],
|
||||||
["b", "Blue value", "slider", (0,255,1)]]
|
["b", "Blue value", "slider", (0,255,1)]]
|
||||||
}
|
}
|
||||||
# Setup for latency timer
|
# Setup for fps counter
|
||||||
self.latency_deque = deque(maxlen=1000)
|
self.frame_counter = 0
|
||||||
|
self.start_time = time.time()
|
||||||
# Setup for "Wave" (don't change these)
|
# Setup for "Wave" (don't change these)
|
||||||
self.wave_wipe_count = 0
|
self.wave_wipe_count = 0
|
||||||
# Setup for "Power" (don't change these)
|
# Setup for "Power" (don't change these)
|
||||||
@ -270,17 +272,23 @@ class Visualizer():
|
|||||||
def get_vis(self, y, audio_input):
|
def get_vis(self, y, audio_input):
|
||||||
self.update_freq_channels(y)
|
self.update_freq_channels(y)
|
||||||
self.detect_freqs()
|
self.detect_freqs()
|
||||||
time1 = time.time()
|
|
||||||
if config.settings["devices"][self.board]["configuration"]["current_effect"] in self.non_reactive_effects:
|
if config.settings["devices"][self.board]["configuration"]["current_effect"] in self.non_reactive_effects:
|
||||||
self.prev_output = self.effects[config.settings["devices"][self.board]["configuration"]["current_effect"]]()
|
self.prev_output = self.effects[config.settings["devices"][self.board]["configuration"]["current_effect"]]()
|
||||||
elif audio_input:
|
elif audio_input:
|
||||||
self.prev_output = self.effects[config.settings["devices"][self.board]["configuration"]["current_effect"]](y)
|
self.prev_output = self.effects[config.settings["devices"][self.board]["configuration"]["current_effect"]](y)
|
||||||
else:
|
else:
|
||||||
self.prev_output = np.multiply(self.prev_output, 0.95)
|
self.prev_output = np.multiply(self.prev_output, 0.95)
|
||||||
time2 = time.time()
|
self.frame_counter += 1
|
||||||
self.latency_deque.append(1000*(time2-time1))
|
elapsed = time.time() - self.start_time
|
||||||
|
if elapsed >= 1.0:
|
||||||
|
self.start_time = time.time()
|
||||||
|
fps = self.frame_counter//elapsed
|
||||||
|
latency = elapsed/self.frame_counter
|
||||||
|
self.frame_counter = 0
|
||||||
|
|
||||||
if config.settings["configuration"]["USE_GUI"]:
|
if config.settings["configuration"]["USE_GUI"]:
|
||||||
gui.label_latency.setText("{} ms Processing Latency ".format(int(sum(self.latency_deque)/len(self.latency_deque))))
|
gui.label_latency.setText("{:0.3f} ms Processing Latency ".format(latency))
|
||||||
|
gui.label_fps.setText('{:.0f} / {:.0f} FPS '.format(fps, config.settings["configuration"]["FPS"]))
|
||||||
return self.prev_output
|
return self.prev_output
|
||||||
|
|
||||||
def _split_equal(self, value, parts):
|
def _split_equal(self, value, parts):
|
||||||
@ -315,54 +323,76 @@ class Visualizer():
|
|||||||
|
|
||||||
def visualize_scroll(self, y):
|
def visualize_scroll(self, y):
|
||||||
"""Effect that originates in the center and scrolls outwards"""
|
"""Effect that originates in the center and scrolls outwards"""
|
||||||
global p
|
|
||||||
y = y**4.0
|
y = y**4.0
|
||||||
signal_processers[self.board].gain.update(y)
|
# signal_processers[self.board].gain.update(y)
|
||||||
y /= signal_processers[self.board].gain.value
|
# y /= signal_processers[self.board].gain.value
|
||||||
y *= 255.0
|
# y *= 255.0
|
||||||
r = int(np.max(y[:len(y) // 3])*config.settings["devices"][self.board]["effect_opts"]["Scroll"]["r_multiplier"])
|
n_pixels = config.settings["devices"][self.board]["configuration"]["N_PIXELS"]
|
||||||
g = int(np.max(y[len(y) // 3: 2 * len(y) // 3])*config.settings["devices"][self.board]["effect_opts"]["Scroll"]["g_multiplier"])
|
y = np.copy(interpolate(y, n_pixels // 2))
|
||||||
b = int(np.max(y[2 * len(y) // 3:])*config.settings["devices"][self.board]["effect_opts"]["Scroll"]["b_multiplier"])
|
signal_processers[self.board].common_mode.update(y)
|
||||||
|
diff = y - self.prev_spectrum
|
||||||
|
self.prev_spectrum = np.copy(y)
|
||||||
|
# split spectrum up
|
||||||
|
# r = signal_processers[self.board].r_filt.update(y - signal_processers[self.board].common_mode.value)
|
||||||
|
# g = np.abs(diff)
|
||||||
|
# b = signal_processers[self.board].b_filt.update(np.copy(y))
|
||||||
|
y = np.clip(y, 0, 1)
|
||||||
|
lows = y[:len(y) // 6]
|
||||||
|
mids = y[len(y) // 6: 2 * len(y) // 5]
|
||||||
|
high = y[2 * len(y) // 5:]
|
||||||
|
# max values
|
||||||
|
lows_max = np.max(lows)#*config.settings["devices"][self.board]["effect_opts"]["Scroll"]["lows_multiplier"])
|
||||||
|
mids_max = float(np.max(mids))#*config.settings["devices"][self.board]["effect_opts"]["Scroll"]["mids_multiplier"])
|
||||||
|
high_max = float(np.max(high))#*config.settings["devices"][self.board]["effect_opts"]["Scroll"]["high_multiplier"])
|
||||||
|
# indexes of max values
|
||||||
|
# map to colour gradient
|
||||||
|
lows_val = (np.array(config.settings["colors"][config.settings["devices"][self.board]["effect_opts"]["Scroll"]["lows_color"]]) * lows_max).astype(int)
|
||||||
|
mids_val = (np.array(config.settings["colors"][config.settings["devices"][self.board]["effect_opts"]["Scroll"]["mids_color"]]) * mids_max).astype(int)
|
||||||
|
high_val = (np.array(config.settings["colors"][config.settings["devices"][self.board]["effect_opts"]["Scroll"]["high_color"]]) * high_max).astype(int)
|
||||||
# Scrolling effect window
|
# Scrolling effect window
|
||||||
speed = config.settings["devices"][self.board]["effect_opts"]["Scroll"]["speed"]
|
speed = config.settings["devices"][self.board]["effect_opts"]["Scroll"]["speed"]
|
||||||
p[:, speed:] = p[:, :-speed]
|
self.output[:, speed:] = self.output[:, :-speed]
|
||||||
p *= config.settings["devices"][self.board]["effect_opts"]["Scroll"]["decay"]
|
self.output = (self.output * config.settings["devices"][self.board]["effect_opts"]["Scroll"]["decay"]).astype(int)
|
||||||
p = gaussian_filter1d(p, sigma=config.settings["devices"][self.board]["effect_opts"]["Scroll"]["blur"])
|
self.output = gaussian_filter1d(self.output, sigma=config.settings["devices"][self.board]["effect_opts"]["Scroll"]["blur"])
|
||||||
# Create new color originating at the center
|
# Create new color originating at the center
|
||||||
p[0, :speed] = r
|
self.output[0, :speed] = lows_val[0] + mids_val[0] + high_val[0]
|
||||||
p[1, :speed] = g
|
self.output[1, :speed] = lows_val[1] + mids_val[1] + high_val[1]
|
||||||
p[2, :speed] = b
|
self.output[2, :speed] = lows_val[2] + mids_val[2] + high_val[2]
|
||||||
# Update the LED strip
|
# Update the LED strip
|
||||||
return np.concatenate((p[:, ::-1], p), axis=1)
|
#return np.concatenate((self.prev_spectrum[:, ::-speed], self.prev_spectrum), axis=1)
|
||||||
|
return self.output
|
||||||
|
|
||||||
def visualize_energy(self, y):
|
def visualize_energy(self, y):
|
||||||
"""Effect that expands from the center with increasing sound energy"""
|
"""Effect that expands from the center with increasing sound energy"""
|
||||||
global p
|
|
||||||
y = np.copy(y)
|
y = np.copy(y)
|
||||||
signal_processers[self.board].gain.update(y)
|
signal_processers[self.board].gain.update(y)
|
||||||
y /= signal_processers[self.board].gain.value
|
y /= signal_processers[self.board].gain.value
|
||||||
scale = config.settings["devices"][self.board]["effect_opts"]["Energy"]["scale"]
|
scale = config.settings["devices"][self.board]["effect_opts"]["Energy"]["scale"]
|
||||||
# Scale by the width of the LED strip
|
# Scale by the width of the LED strip
|
||||||
y *= float((config.settings["devices"][self.board]["configuration"]["N_PIXELS"] * scale) - 1)
|
y *= float((config.settings["devices"][self.board]["configuration"]["N_PIXELS"] * scale) - 1)
|
||||||
|
y = np.copy(interpolate(y, config.settings["devices"][self.board]["configuration"]["N_PIXELS"] // 2))
|
||||||
# Map color channels according to energy in the different freq bands
|
# Map color channels according to energy in the different freq bands
|
||||||
r = int(np.mean(y[:len(y) // 3]**scale)*config.settings["devices"][self.board]["effect_opts"]["Energy"]["r_multiplier"])
|
#y = np.copy(interpolate(y, config.settings["devices"][self.board]["configuration"]["N_PIXELS"] // 2))
|
||||||
g = int(np.mean(y[len(y) // 3: 2 * len(y) // 3]**scale)*config.settings["devices"][self.board]["effect_opts"]["Energy"]["g_multiplier"])
|
diff = y - self.prev_spectrum
|
||||||
b = int(np.mean(y[2 * len(y) // 3:]**scale)*config.settings["devices"][self.board]["effect_opts"]["Energy"]["b_multiplier"])
|
self.prev_spectrum = np.copy(y)
|
||||||
|
spectrum = np.copy(self.prev_spectrum)
|
||||||
|
spectrum = np.array([j for i in zip(spectrum,spectrum) for j in i])
|
||||||
|
# Color channel mappings
|
||||||
|
r = int(np.mean(spectrum[:len(spectrum) // 3]**scale)*config.settings["devices"][self.board]["effect_opts"]["Energy"]["r_multiplier"])
|
||||||
|
g = int(np.mean(spectrum[len(spectrum) // 3: 2 * len(spectrum) // 3]**scale)*config.settings["devices"][self.board]["effect_opts"]["Energy"]["g_multiplier"])
|
||||||
|
b = int(np.mean(spectrum[2 * len(spectrum) // 3:]**scale)*config.settings["devices"][self.board]["effect_opts"]["Energy"]["b_multiplier"])
|
||||||
# Assign color to different frequency regions
|
# Assign color to different frequency regions
|
||||||
p[0, :r] = 255.0
|
self.output[0, :r] = 255
|
||||||
p[0, r:] = 0.0
|
self.output[0, r:] = 0
|
||||||
p[1, :g] = 255.0
|
self.output[1, :g] = 255
|
||||||
p[1, g:] = 0.0
|
self.output[1, g:] = 0
|
||||||
p[2, :b] = 255.0
|
self.output[2, :b] = 255
|
||||||
p[2, b:] = 0.0
|
self.output[2, b:] = 0
|
||||||
signal_processers[self.board].p_filt.update(p)
|
|
||||||
p = np.round(signal_processers[self.board].p_filt.value)
|
|
||||||
# Apply blur to smooth the edges
|
# Apply blur to smooth the edges
|
||||||
p[0, :] = gaussian_filter1d(p[0, :], sigma=config.settings["devices"][self.board]["effect_opts"]["Energy"]["blur"])
|
self.output[0, :] = gaussian_filter1d(self.output[0, :], sigma=config.settings["devices"][self.board]["effect_opts"]["Energy"]["blur"])
|
||||||
p[1, :] = gaussian_filter1d(p[1, :], sigma=config.settings["devices"][self.board]["effect_opts"]["Energy"]["blur"])
|
self.output[1, :] = gaussian_filter1d(self.output[1, :], sigma=config.settings["devices"][self.board]["effect_opts"]["Energy"]["blur"])
|
||||||
p[2, :] = gaussian_filter1d(p[2, :], sigma=config.settings["devices"][self.board]["effect_opts"]["Energy"]["blur"])
|
self.output[2, :] = gaussian_filter1d(self.output[2, :], sigma=config.settings["devices"][self.board]["effect_opts"]["Energy"]["blur"])
|
||||||
# Set the new pixel value
|
return self.output
|
||||||
return np.concatenate((p[:, ::-1], p), axis=1)
|
|
||||||
|
|
||||||
def visualize_wavelength(self, y):
|
def visualize_wavelength(self, y):
|
||||||
y = np.copy(interpolate(y, config.settings["devices"][self.board]["configuration"]["N_PIXELS"] // 2))
|
y = np.copy(interpolate(y, config.settings["devices"][self.board]["configuration"]["N_PIXELS"] // 2))
|
||||||
@ -371,7 +401,7 @@ class Visualizer():
|
|||||||
self.prev_spectrum = np.copy(y)
|
self.prev_spectrum = np.copy(y)
|
||||||
# Color channel mappings
|
# Color channel mappings
|
||||||
r = signal_processers[self.board].r_filt.update(y - signal_processers[self.board].common_mode.value)
|
r = signal_processers[self.board].r_filt.update(y - signal_processers[self.board].common_mode.value)
|
||||||
#g = np.abs(diff)
|
g = np.abs(diff)
|
||||||
b = signal_processers[self.board].b_filt.update(np.copy(y))
|
b = signal_processers[self.board].b_filt.update(np.copy(y))
|
||||||
r = np.array([j for i in zip(r,r) for j in i])
|
r = np.array([j for i in zip(r,r) for j in i])
|
||||||
output = np.array([self.multicolor_modes[config.settings["devices"][self.board]["effect_opts"]["Wavelength"]["color_mode"]][0][
|
output = np.array([self.multicolor_modes[config.settings["devices"][self.board]["effect_opts"]["Wavelength"]["color_mode"]][0][
|
||||||
@ -399,7 +429,6 @@ class Visualizer():
|
|||||||
|
|
||||||
def visualize_spectrum(self, y):
|
def visualize_spectrum(self, y):
|
||||||
"""Effect that maps the Mel filterbank frequencies onto the LED strip"""
|
"""Effect that maps the Mel filterbank frequencies onto the LED strip"""
|
||||||
global p
|
|
||||||
#print(len(y))
|
#print(len(y))
|
||||||
#print(y)
|
#print(y)
|
||||||
y = np.copy(interpolate(y, config.settings["devices"][self.board]["configuration"]["N_PIXELS"] // 2))
|
y = np.copy(interpolate(y, config.settings["devices"][self.board]["configuration"]["N_PIXELS"] // 2))
|
||||||
@ -541,7 +570,7 @@ class Visualizer():
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
def visualize_pulse(self, y):
|
def visualize_pulse(self, y):
|
||||||
"""fckin dope ass visuals that's what"""
|
"""dope ass visuals that's what"""
|
||||||
config.settings["devices"][self.board]["effect_opts"]["Pulse"]["bar_color"]
|
config.settings["devices"][self.board]["effect_opts"]["Pulse"]["bar_color"]
|
||||||
config.settings["devices"][self.board]["effect_opts"]["Pulse"]["bar_speed"]
|
config.settings["devices"][self.board]["effect_opts"]["Pulse"]["bar_speed"]
|
||||||
config.settings["devices"][self.board]["effect_opts"]["Pulse"]["bar_length"]
|
config.settings["devices"][self.board]["effect_opts"]["Pulse"]["bar_length"]
|
||||||
@ -602,7 +631,7 @@ class GUI(QMainWindow):
|
|||||||
self.updateUIVisibleItems()
|
self.updateUIVisibleItems()
|
||||||
|
|
||||||
def initMainWindow(self):
|
def initMainWindow(self):
|
||||||
# ==================================== Set up window and wrapping layout
|
# Set up window and wrapping layout
|
||||||
self.setWindowTitle("Visualization")
|
self.setWindowTitle("Visualization")
|
||||||
# Initial window size/pos last saved if available
|
# Initial window size/pos last saved if available
|
||||||
settings.beginGroup("MainWindow")
|
settings.beginGroup("MainWindow")
|
||||||
@ -613,19 +642,22 @@ class GUI(QMainWindow):
|
|||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
self.main_wrapper = QVBoxLayout()
|
self.main_wrapper = QVBoxLayout()
|
||||||
|
|
||||||
# ======================================================= Set up toolbar
|
# Set up toolbar
|
||||||
#toolbar_guiDialogue.setShortcut('Ctrl+H')
|
#toolbar_guiDialogue.setShortcut('Ctrl+H')
|
||||||
|
toolbar_deviceDialogue = QAction('LED Strip Manager', self)
|
||||||
|
toolbar_deviceDialogue.triggered.connect(self.deviceDialogue)
|
||||||
toolbar_guiDialogue = QAction('GUI Properties', self)
|
toolbar_guiDialogue = QAction('GUI Properties', self)
|
||||||
toolbar_guiDialogue.triggered.connect(self.guiDialogue)
|
toolbar_guiDialogue.triggered.connect(self.guiDialogue)
|
||||||
#toolbar_configDialogue = QAction('GUI Properties', self)
|
toolbar_saveDialogue = QAction('Save Settings', self)
|
||||||
#toolbar_configDialogue.triggered.connect(self.configDialogue)
|
toolbar_saveDialogue.triggered.connect(self.saveDialogue)
|
||||||
|
|
||||||
self.toolbar = self.addToolBar('top_toolbar')
|
self.toolbar = self.addToolBar('top_toolbar')
|
||||||
self.toolbar.setObjectName('top_toolbar')
|
self.toolbar.setObjectName('top_toolbar')
|
||||||
self.toolbar.addAction(toolbar_guiDialogue)
|
self.toolbar.addAction(toolbar_guiDialogue)
|
||||||
# self.toolbar.addAction(toolbar_configDialogue)
|
self.toolbar.addAction(toolbar_saveDialogue)
|
||||||
|
self.toolbar.addAction(toolbar_deviceDialogue)
|
||||||
|
|
||||||
# ========================================== Set up FPS and error labels
|
# Set up FPS and error labels
|
||||||
self.statusbar = QStatusBar()
|
self.statusbar = QStatusBar()
|
||||||
self.setStatusBar(self.statusbar)
|
self.setStatusBar(self.statusbar)
|
||||||
self.label_error = QLabel("")
|
self.label_error = QLabel("")
|
||||||
@ -637,8 +669,8 @@ class GUI(QMainWindow):
|
|||||||
self.statusbar.addPermanentWidget(self.label_latency)
|
self.statusbar.addPermanentWidget(self.label_latency)
|
||||||
self.statusbar.addPermanentWidget(self.label_fps)
|
self.statusbar.addPermanentWidget(self.label_fps)
|
||||||
|
|
||||||
# ==================================================== Set up board tabs
|
# Set up board tabs
|
||||||
self.label_boards = QLabel("Boards")
|
self.label_boards = QLabel("LED Strips")
|
||||||
self.boardsTabWidget = QTabWidget()
|
self.boardsTabWidget = QTabWidget()
|
||||||
# Dynamically set up boards tabs
|
# Dynamically set up boards tabs
|
||||||
self.board_tabs = {} # contains all the tabs for each board
|
self.board_tabs = {} # contains all the tabs for each board
|
||||||
@ -648,9 +680,9 @@ class GUI(QMainWindow):
|
|||||||
self.addBoard(board)
|
self.addBoard(board)
|
||||||
self.main_wrapper.addWidget(self.label_boards)
|
self.main_wrapper.addWidget(self.label_boards)
|
||||||
self.main_wrapper.addWidget(self.boardsTabWidget)
|
self.main_wrapper.addWidget(self.boardsTabWidget)
|
||||||
self.setLayout(self.main_wrapper)
|
#self.setLayout(self.main_wrapper)
|
||||||
|
|
||||||
# =========================================== Set wrapper as main widget
|
# Set wrapper as main widget
|
||||||
self.setCentralWidget(QWidget(self))
|
self.setCentralWidget(QWidget(self))
|
||||||
self.centralWidget().setLayout(self.main_wrapper)
|
self.centralWidget().setLayout(self.main_wrapper)
|
||||||
self.show()
|
self.show()
|
||||||
@ -686,10 +718,185 @@ class GUI(QMainWindow):
|
|||||||
event.ignore()
|
event.ignore()
|
||||||
|
|
||||||
def updateUIVisibleItems(self):
|
def updateUIVisibleItems(self):
|
||||||
|
#print("-UPDATE-")
|
||||||
for section in self.gui_widgets:
|
for section in self.gui_widgets:
|
||||||
for widget in self.gui_widgets[section]:
|
for widget in self.gui_widgets[section]:
|
||||||
|
#print(widget.isVisible(), " ", config.settings["GUI_opts"][section])
|
||||||
widget.setVisible(config.settings["GUI_opts"][section])
|
widget.setVisible(config.settings["GUI_opts"][section])
|
||||||
|
|
||||||
|
def deviceDialogue(self):
|
||||||
|
def show_hide_addBoard_interface():
|
||||||
|
current_device = device_type_cbox.currentText()
|
||||||
|
for device in config.device_req_config:
|
||||||
|
for req_config_setting in widgets[device]:
|
||||||
|
if req_config_setting is not "no_config":
|
||||||
|
for widget in widgets[device][req_config_setting]:
|
||||||
|
widget.setVisible(device == current_device)
|
||||||
|
else:
|
||||||
|
# doesn't make sense i know i know
|
||||||
|
widgets[device][req_config_setting].setVisible(device == current_device)
|
||||||
|
|
||||||
|
def validate_input():
|
||||||
|
import re
|
||||||
|
current_device = device_type_cbox.currentText()
|
||||||
|
tests = []
|
||||||
|
print("testing")
|
||||||
|
if current_device == "ESP8266":
|
||||||
|
for req_config_setting in config.device_req_config[current_device]:
|
||||||
|
test = widgets[current_device][req_config_setting][1].text()
|
||||||
|
if req_config_setting == "MAC_ADDR":
|
||||||
|
# Validate MAC
|
||||||
|
tests.append(True if re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", test.lower()) else False)
|
||||||
|
elif req_config_setting == "UDP_IP":
|
||||||
|
# Validate IP
|
||||||
|
try:
|
||||||
|
pieces = test.split('.')
|
||||||
|
if len(pieces) != 4: return False
|
||||||
|
tests.append(all(0<=int(self.prev_output)<256 for self.prev_output in pieces))
|
||||||
|
except:
|
||||||
|
tests.append(False)
|
||||||
|
elif req_config_setting == "UDP_PORT":
|
||||||
|
# Validate port
|
||||||
|
print(test)
|
||||||
|
try:
|
||||||
|
int(test)
|
||||||
|
if test > 0:
|
||||||
|
test.append(True)
|
||||||
|
except:
|
||||||
|
tests.append(False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pass
|
||||||
|
|
||||||
|
|
||||||
|
# Validate port
|
||||||
|
elif current_device == "RaspberryPi":
|
||||||
|
pass
|
||||||
|
# Validate LED Pin
|
||||||
|
# Validate LED Freq
|
||||||
|
# Validate LED DMA
|
||||||
|
elif current_device == "Fadecandy":
|
||||||
|
pass
|
||||||
|
# Validate server
|
||||||
|
elif not config.req_config_setting[current_device]:
|
||||||
|
pass
|
||||||
|
print(tests)
|
||||||
|
|
||||||
|
# def lineEdit(labelText, defaultText):
|
||||||
|
# wrapper = QWidget()
|
||||||
|
# hLayout = QHBoxLayout()
|
||||||
|
# wrapper.setLayout(hLayout)
|
||||||
|
# label = QLabel(labelText)
|
||||||
|
# lEdit = QLineEdit()
|
||||||
|
# lEdit.setPlaceholderText(defaultText)
|
||||||
|
# hLayout.addWidget(label)
|
||||||
|
# hLayout.addWidget(lEdit)
|
||||||
|
# return wrapper
|
||||||
|
|
||||||
|
# Set up window and layout
|
||||||
|
self.device_dialogue = QDialog(None, Qt.WindowSystemMenuHint | Qt.WindowCloseButtonHint)
|
||||||
|
self.device_dialogue.setWindowTitle("LED Strip Manager")
|
||||||
|
self.device_dialogue.setWindowModality(Qt.ApplicationModal)
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
self.device_dialogue.setLayout(layout)
|
||||||
|
|
||||||
|
# Set up tab layouts
|
||||||
|
tabs = QTabWidget()
|
||||||
|
layout.addWidget(tabs)
|
||||||
|
addDeviceTab = QWidget()
|
||||||
|
remDeviceTab = QWidget()
|
||||||
|
addDeviceTabLayout = QVBoxLayout()
|
||||||
|
remDeviceTabLayout = QVBoxLayout()
|
||||||
|
addDeviceTabButtonLayout = QGridLayout()
|
||||||
|
remDeviceTabButtonLayout = QGridLayout()
|
||||||
|
addDeviceTab.setLayout(addDeviceTabLayout)
|
||||||
|
remDeviceTab.setLayout(remDeviceTabLayout)
|
||||||
|
tabs.addTab(addDeviceTab, "Add Device")
|
||||||
|
tabs.addTab(remDeviceTab, "Remove Device")
|
||||||
|
|
||||||
|
# Set up "Add Device" tab
|
||||||
|
device_type_cbox = QComboBox()
|
||||||
|
device_type_cbox.addItems(config.device_req_config.keys())
|
||||||
|
device_type_cbox.currentIndexChanged.connect(show_hide_addBoard_interface)
|
||||||
|
addDeviceTabLayout.addWidget(device_type_cbox)
|
||||||
|
|
||||||
|
# Set up "Add Device" widgets
|
||||||
|
widgets = {}
|
||||||
|
addDeviceTabLayout.addLayout(addDeviceTabButtonLayout)
|
||||||
|
remDeviceTabLayout.addLayout(remDeviceTabButtonLayout)
|
||||||
|
# if the new board has required config
|
||||||
|
for device in config.device_req_config:
|
||||||
|
# Make the widgets
|
||||||
|
widgets[device] = {}
|
||||||
|
if config.device_req_config[device]:
|
||||||
|
for req_config_setting in config.device_req_config[device]:
|
||||||
|
label = config.device_req_config[device][req_config_setting][0]
|
||||||
|
guide = config.device_req_config[device][req_config_setting][1]
|
||||||
|
wType = config.device_req_config[device][req_config_setting][2]
|
||||||
|
deflt = config.device_req_config[device][req_config_setting][3]
|
||||||
|
wLabel = QLabel(label)
|
||||||
|
#wGuide = QLabel(guide)
|
||||||
|
if wType == "textbox":
|
||||||
|
wEdit = QLineEdit()
|
||||||
|
wEdit.setPlaceholderText(deflt)
|
||||||
|
wEdit.textChanged.connect(validate_input)
|
||||||
|
elif wType == "checkbox":
|
||||||
|
wEdit = QCheckBox()
|
||||||
|
wEdit.setCheckState(Qt.Checked if deflt else Qt.Unchecked)
|
||||||
|
widgets[device][req_config_setting] = [wLabel, wEdit]
|
||||||
|
# Add widgets to layout
|
||||||
|
i = 0
|
||||||
|
for req_config in widgets[device]:
|
||||||
|
addDeviceTabButtonLayout.addWidget(widgets[device][req_config][0], i, 0)
|
||||||
|
addDeviceTabButtonLayout.addWidget(widgets[device][req_config][1], i, 1)
|
||||||
|
#addDeviceTabButtonLayout.addWidget(widget_set[2], i+1, 0, 1, 2)
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
no_setup = QLabel("Device requires no additional setup here! :)")
|
||||||
|
widgets[device]["no_config"] = no_setup
|
||||||
|
addDeviceTabButtonLayout.addWidget(no_setup, 0, 0)
|
||||||
|
|
||||||
|
# Show appropriate widgets
|
||||||
|
show_hide_addBoard_interface()
|
||||||
|
|
||||||
|
# self.gui_vis_checkboxes = {}
|
||||||
|
# for section in self.gui_widgets:
|
||||||
|
# self.gui_vis_checkboxes[section] = QCheckBox(section)
|
||||||
|
# self.gui_vis_checkboxes[section].setCheckState(
|
||||||
|
# Qt.Checked if config.settings["GUI_opts"][section] else Qt.Unchecked)
|
||||||
|
# self.gui_vis_checkboxes[section].stateChanged.connect(update_visibilty_dict)
|
||||||
|
# addDeviceTabLayout.addWidget(self.gui_vis_checkboxes[section])
|
||||||
|
self.add_device_button = QPushButton("Add Device")
|
||||||
|
addDeviceTabLayout.addWidget(self.add_device_button)
|
||||||
|
|
||||||
|
# Set up "Remove Device" tab
|
||||||
|
|
||||||
|
# Set up ok/cancel buttons
|
||||||
|
self.buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
|
||||||
|
self.buttons.accepted.connect(self.device_dialogue.accept)
|
||||||
|
self.buttons.rejected.connect(self.device_dialogue.reject)
|
||||||
|
layout.addWidget(self.buttons)
|
||||||
|
|
||||||
|
self.device_dialogue.show()
|
||||||
|
|
||||||
|
def saveDialogue(self):
|
||||||
|
# Save window state
|
||||||
|
settings.beginGroup("MainWindow")
|
||||||
|
settings.setValue("geometry", self.saveGeometry())
|
||||||
|
settings.setValue('state', self.saveState())
|
||||||
|
settings.endGroup()
|
||||||
|
# save all settings
|
||||||
|
settings.setValue("settings_dict", config.settings)
|
||||||
|
# save and close
|
||||||
|
settings.sync()
|
||||||
|
# Confirmation message
|
||||||
|
self.conf_dialogue = QMessageBox()
|
||||||
|
self.conf_dialogue.setText("Settings saved.\nSettings are also automatically saved when program closes.")
|
||||||
|
self.conf_dialogue.show()
|
||||||
|
|
||||||
def guiDialogue(self):
|
def guiDialogue(self):
|
||||||
def update_visibilty_dict():
|
def update_visibilty_dict():
|
||||||
for checkbox in self.gui_vis_checkboxes:
|
for checkbox in self.gui_vis_checkboxes:
|
||||||
@ -697,32 +904,7 @@ class GUI(QMainWindow):
|
|||||||
self.updateUIVisibleItems()
|
self.updateUIVisibleItems()
|
||||||
|
|
||||||
self.gui_dialogue = QDialog(None, Qt.WindowSystemMenuHint | Qt.WindowCloseButtonHint)
|
self.gui_dialogue = QDialog(None, Qt.WindowSystemMenuHint | Qt.WindowCloseButtonHint)
|
||||||
self.gui_dialogue.setWindowTitle("GUI Properties")
|
self.gui_dialogue.setWindowTitle("Show/hide Interface Sections")
|
||||||
self.gui_dialogue.setWindowModality(Qt.ApplicationModal)
|
|
||||||
layout = QGridLayout()
|
|
||||||
self.gui_dialogue.setLayout(layout)
|
|
||||||
# OK button
|
|
||||||
self.buttons = QDialogButtonBox(QDialogButtonBox.Ok, Qt.Horizontal, self)
|
|
||||||
self.buttons.accepted.connect(self.gui_dialogue.accept)
|
|
||||||
|
|
||||||
self.gui_vis_checkboxes = {}
|
|
||||||
for section in self.gui_widgets:
|
|
||||||
self.gui_vis_checkboxes[section] = QCheckBox(section)
|
|
||||||
self.gui_vis_checkboxes[section].setCheckState(
|
|
||||||
Qt.Checked if config.settings["GUI_opts"][section] else Qt.Unchecked)
|
|
||||||
self.gui_vis_checkboxes[section].stateChanged.connect(update_visibilty_dict)
|
|
||||||
layout.addWidget(self.gui_vis_checkboxes[section])
|
|
||||||
layout.addWidget(self.buttons)
|
|
||||||
self.gui_dialogue.show()
|
|
||||||
|
|
||||||
def configDialogue(self):
|
|
||||||
def update_visibilty_dict():
|
|
||||||
for checkbox in self.gui_vis_checkboxes:
|
|
||||||
config.settings["GUI_opts"][checkbox] = self.gui_vis_checkboxes[checkbox].isChecked()
|
|
||||||
self.updateUIVisibleItems()
|
|
||||||
|
|
||||||
self.gui_dialogue = QDialog(None, Qt.WindowSystemMenuHint | Qt.WindowCloseButtonHint)
|
|
||||||
self.gui_dialogue.setWindowTitle("GUI Properties")
|
|
||||||
self.gui_dialogue.setWindowModality(Qt.ApplicationModal)
|
self.gui_dialogue.setWindowModality(Qt.ApplicationModal)
|
||||||
layout = QGridLayout()
|
layout = QGridLayout()
|
||||||
self.gui_dialogue.setLayout(layout)
|
self.gui_dialogue.setLayout(layout)
|
||||||
@ -742,10 +924,10 @@ class GUI(QMainWindow):
|
|||||||
|
|
||||||
def initBoardUI(self, board):
|
def initBoardUI(self, board):
|
||||||
self.board = board
|
self.board = board
|
||||||
# =============================================== Set up wrapping layout
|
# Set up wrapping layout
|
||||||
self.board_tabs_widgets[board]["wrapper"] = QVBoxLayout()
|
self.board_tabs_widgets[board]["wrapper"] = QVBoxLayout()
|
||||||
|
|
||||||
# ================================================== Set up graph layout
|
# Set up graph layout
|
||||||
self.board_tabs_widgets[board]["graph_view"] = pg.GraphicsView()
|
self.board_tabs_widgets[board]["graph_view"] = pg.GraphicsView()
|
||||||
graph_layout = pg.GraphicsLayout(border=(100,100,100))
|
graph_layout = pg.GraphicsLayout(border=(100,100,100))
|
||||||
self.board_tabs_widgets[board]["graph_view"].setCentralItem(graph_layout)
|
self.board_tabs_widgets[board]["graph_view"].setCentralItem(graph_layout)
|
||||||
@ -780,7 +962,7 @@ class GUI(QMainWindow):
|
|||||||
led_plot.addItem(self.board_tabs_widgets[board]["g_curve"])
|
led_plot.addItem(self.board_tabs_widgets[board]["g_curve"])
|
||||||
led_plot.addItem(self.board_tabs_widgets[board]["b_curve"])
|
led_plot.addItem(self.board_tabs_widgets[board]["b_curve"])
|
||||||
|
|
||||||
# ================================================= Set up button layout
|
# Set up button layout
|
||||||
self.board_tabs_widgets[board]["label_reactive"] = QLabel("Audio Reactive Effects")
|
self.board_tabs_widgets[board]["label_reactive"] = QLabel("Audio Reactive Effects")
|
||||||
self.board_tabs_widgets[board]["label_non_reactive"] = QLabel("Non Reactive Effects")
|
self.board_tabs_widgets[board]["label_non_reactive"] = QLabel("Non Reactive Effects")
|
||||||
self.board_tabs_widgets[board]["reactive_button_grid_wrap"] = QWidget()
|
self.board_tabs_widgets[board]["reactive_button_grid_wrap"] = QWidget()
|
||||||
@ -824,7 +1006,7 @@ class GUI(QMainWindow):
|
|||||||
k = 0
|
k = 0
|
||||||
l += 1
|
l += 1
|
||||||
|
|
||||||
# ============================================== Set up frequency slider
|
# Set up frequency slider
|
||||||
# Frequency range label
|
# Frequency range label
|
||||||
self.board_tabs_widgets[board]["label_slider"] = QLabel("Frequency Range")
|
self.board_tabs_widgets[board]["label_slider"] = QLabel("Frequency Range")
|
||||||
# Frequency slider
|
# Frequency slider
|
||||||
@ -868,7 +1050,7 @@ class GUI(QMainWindow):
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# ============================================ Set up option tabs layout
|
# Set up option tabs layout
|
||||||
self.board_tabs_widgets[board]["label_options"] = QLabel("Effect Options")
|
self.board_tabs_widgets[board]["label_options"] = QLabel("Effect Options")
|
||||||
self.board_tabs_widgets[board]["opts_tabs"] = QTabWidget()
|
self.board_tabs_widgets[board]["opts_tabs"] = QTabWidget()
|
||||||
# Dynamically set up tabs
|
# Dynamically set up tabs
|
||||||
@ -944,7 +1126,7 @@ class GUI(QMainWindow):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================= Add layouts into self.board_tabs_widgets[board]["wrapper"]
|
# Add layouts into self.board_tabs_widgets[board]["wrapper"]
|
||||||
self.board_tabs_widgets[board]["wrapper"].addWidget(self.board_tabs_widgets[board]["graph_view"])
|
self.board_tabs_widgets[board]["wrapper"].addWidget(self.board_tabs_widgets[board]["graph_view"])
|
||||||
self.board_tabs_widgets[board]["wrapper"].addWidget(self.board_tabs_widgets[board]["label_reactive"])
|
self.board_tabs_widgets[board]["wrapper"].addWidget(self.board_tabs_widgets[board]["label_reactive"])
|
||||||
self.board_tabs_widgets[board]["wrapper"].addWidget(self.board_tabs_widgets[board]["reactive_button_grid_wrap"])
|
self.board_tabs_widgets[board]["wrapper"].addWidget(self.board_tabs_widgets[board]["reactive_button_grid_wrap"])
|
||||||
@ -1174,8 +1356,6 @@ def microphone_update(audio_samples):
|
|||||||
gui.label_error.setText("")
|
gui.label_error.setText("")
|
||||||
else:
|
else:
|
||||||
gui.label_error.setText("No audio input. Volume below threshold.")
|
gui.label_error.setText("No audio input. Volume below threshold.")
|
||||||
# Update fps counter
|
|
||||||
gui.label_fps.setText('{:.0f} / {:.0f} FPS'.format(fps, config.settings["configuration"]["FPS"]))
|
|
||||||
app.processEvents()
|
app.processEvents()
|
||||||
|
|
||||||
# Left in just in case prople dont use the gui
|
# Left in just in case prople dont use the gui
|
||||||
@ -1194,27 +1374,27 @@ visualizers = {}
|
|||||||
boards = {}
|
boards = {}
|
||||||
for board in config.settings["devices"]:
|
for board in config.settings["devices"]:
|
||||||
visualizers[board] = Visualizer(board)
|
visualizers[board] = Visualizer(board)
|
||||||
if config.settings["devices"][board]["configuration"]["TYPE"] == 'esp8266':
|
if config.settings["devices"][board]["configuration"]["TYPE"] == 'ESP8266':
|
||||||
boards[board] = devices.ESP8266(
|
boards[board] = devices.ESP8266(
|
||||||
auto_detect=config.settings["devices"][board]["configuration"]["AUTO_DETECT"],
|
auto_detect=config.settings["devices"][board]["configuration"]["AUTO_DETECT"],
|
||||||
mac_addr=config.settings["devices"][board]["configuration"]["MAC_ADDR"],
|
mac_addr=config.settings["devices"][board]["configuration"]["MAC_ADDR"],
|
||||||
ip=config.settings["devices"][board]["configuration"]["UDP_IP"],
|
ip=config.settings["devices"][board]["configuration"]["UDP_IP"],
|
||||||
port=config.settings["devices"][board]["configuration"]["UDP_PORT"])
|
port=config.settings["devices"][board]["configuration"]["UDP_PORT"])
|
||||||
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'pi':
|
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'RaspberryPi':
|
||||||
boards[board] = devices.RaspberryPi(
|
boards[board] = devices.RaspberryPi(
|
||||||
n_pixels=config.settings["devices"][board]["configuration"]["N_PIXELS"],
|
n_pixels=config.settings["devices"][board]["configuration"]["N_PIXELS"],
|
||||||
pin=config.settings["devices"][board]["configuration"]["LED_PIN"],
|
pin=config.settings["devices"][board]["configuration"]["LED_PIN"],
|
||||||
invert_logic=config.settings["devices"][board]["configuration"]["LED_INVERT"],
|
invert_logic=config.settings["devices"][board]["configuration"]["LED_INVERT"],
|
||||||
freq=config.settings["devices"][board]["configuration"]["LED_FREQ_HZ"],
|
freq=config.settings["devices"][board]["configuration"]["LED_FREQ_HZ"],
|
||||||
dma=config.settings["devices"][board]["configuration"]["LED_DMA"])
|
dma=config.settings["devices"][board]["configuration"]["LED_DMA"])
|
||||||
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'fadecandy':
|
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'Fadecandy':
|
||||||
boards[board] = devices.FadeCandy(
|
boards[board] = devices.FadeCandy(
|
||||||
server=config.settings["devices"][board]["configuration"]["SERVER"])
|
server=config.settings["devices"][board]["configuration"]["SERVER"])
|
||||||
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'blinkstick':
|
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'BlinkStick':
|
||||||
boards[board] = devices.BlinkStick()
|
boards[board] = devices.BlinkStick()
|
||||||
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'dotstar':
|
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'DotStar':
|
||||||
boards[board] = devices.DotStar()
|
boards[board] = devices.DotStar()
|
||||||
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'stripless':
|
elif config.settings["devices"][board]["configuration"]["TYPE"] == 'Stripless':
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Initialise DSP
|
# Initialise DSP
|
||||||
|
Loading…
Reference in New Issue
Block a user