Scrolling text #DATETIME bugfix.
Cosmetic changes.
This commit is contained in:
parent
cf54115077
commit
f3364e1327
@ -144,7 +144,8 @@ float fftAdd(int from, int to) {
|
||||
}
|
||||
|
||||
// FFT main code
|
||||
void FFTcode(void * parameter) {
|
||||
void FFTcode(void * parameter)
|
||||
{
|
||||
DEBUGSR_PRINT("FFT running on core: "); DEBUGSR_PRINTLN(xPortGetCoreID());
|
||||
#ifdef MAJORPEAK_SUPPRESS_NOISE
|
||||
static double xtemp[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
@ -367,17 +368,16 @@ class AudioReactive : public Usermod {
|
||||
int8_t mclkPin = MLCK_PIN;
|
||||
#endif
|
||||
|
||||
#define UDP_SYNC_HEADER "00001"
|
||||
struct audioSyncPacket {
|
||||
char header[6];
|
||||
char header[6];
|
||||
uint8_t myVals[32]; // 32 Bytes
|
||||
int sampleAgc; // 04 Bytes
|
||||
int sample; // 04 Bytes
|
||||
float sampleAvg; // 04 Bytes
|
||||
bool samplePeak; // 01 Bytes
|
||||
int sampleAgc; // 04 Bytes
|
||||
int sample; // 04 Bytes
|
||||
float sampleAvg; // 04 Bytes
|
||||
bool samplePeak; // 01 Bytes
|
||||
uint8_t fftResult[16]; // 16 Bytes
|
||||
double FFT_Magnitude; // 08 Bytes
|
||||
double FFT_MajorPeak; // 08 Bytes
|
||||
double FFT_Magnitude; // 08 Bytes
|
||||
double FFT_MajorPeak; // 08 Bytes
|
||||
};
|
||||
|
||||
WiFiUDP fftUdp;
|
||||
@ -416,20 +416,21 @@ class AudioReactive : public Usermod {
|
||||
bool agcEffect = false;
|
||||
int last_soundAgc = -1;
|
||||
float control_integrated = 0.0f; // "integrator control" = accumulated error
|
||||
unsigned long last_update_time = 0;
|
||||
unsigned long last_kick_time = 0;
|
||||
uint8_t last_user_inputLevel = 0;
|
||||
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
static const char _name[];
|
||||
static const char _enabled[];
|
||||
static const char _analogmic[];
|
||||
static const char _digitalmic[];
|
||||
static const char UDP_SYNC_HEADER[];
|
||||
|
||||
|
||||
// private methods
|
||||
bool isValidUdpSyncVersion(const char *header) {
|
||||
return strncmp(header, UDP_SYNC_HEADER, 6) == 0;
|
||||
}
|
||||
|
||||
|
||||
void logAudio() {
|
||||
void logAudio()
|
||||
{
|
||||
#ifdef MIC_LOGGER
|
||||
//Serial.print("micData:"); Serial.print(micData); Serial.print("\t");
|
||||
//Serial.print("micDataSm:"); Serial.print(micDataSm); Serial.print("\t");
|
||||
@ -522,7 +523,8 @@ class AudioReactive : public Usermod {
|
||||
* a) normal zone - very slow adjustment
|
||||
* b) emergency zome (<10% or >90%) - very fast adjustment
|
||||
*/
|
||||
void agcAvg() {
|
||||
void agcAvg()
|
||||
{
|
||||
const int AGC_preset = (soundAgc > 0)? (soundAgc-1): 0; // make sure the _compiler_ knows this value will not change while we are inside the function
|
||||
|
||||
float lastMultAgc = multAgc; // last muliplier used
|
||||
@ -605,9 +607,8 @@ class AudioReactive : public Usermod {
|
||||
} // agcAvg()
|
||||
|
||||
|
||||
void getSample() {
|
||||
static long peakTime;
|
||||
|
||||
void getSample()
|
||||
{
|
||||
const int AGC_preset = (soundAgc > 0)? (soundAgc-1): 0; // make sure the _compiler_ knows this value will not change while we are inside the function
|
||||
|
||||
#ifdef WLED_DISABLE_SOUND
|
||||
@ -677,24 +678,24 @@ class AudioReactive : public Usermod {
|
||||
if (userVar1 == 0) samplePeak = 0;
|
||||
// Poor man's beat detection by seeing if sample > Average + some value.
|
||||
// Serial.print(binNum); Serial.print("\t"); Serial.print(fftBin[binNum]); Serial.print("\t"); Serial.print(fftAvg[binNum/16]); Serial.print("\t"); Serial.print(maxVol); Serial.print("\t"); Serial.println(samplePeak);
|
||||
if ((fftBin[binNum] > maxVol) && (millis() > (peakTime + 100))) { // This goe through ALL of the 255 bins
|
||||
// if (sample > (sampleAvg + maxVol) && millis() > (peakTime + 200)) {
|
||||
if ((fftBin[binNum] > maxVol) && (millis() > (timeOfPeak + 100))) { // This goe through ALL of the 255 bins
|
||||
// if (sample > (sampleAvg + maxVol) && millis() > (timeOfPeak + 200)) {
|
||||
// Then we got a peak, else we don't. The peak has to time out on its own in order to support UDP sound sync.
|
||||
samplePeak = 1;
|
||||
timeOfPeak = millis();
|
||||
samplePeak = 1;
|
||||
timeOfPeak = millis();
|
||||
udpSamplePeak = 1;
|
||||
userVar1 = samplePeak;
|
||||
peakTime=millis();
|
||||
userVar1 = samplePeak;
|
||||
}
|
||||
} // getSample()
|
||||
|
||||
|
||||
void transmitAudioData() {
|
||||
void transmitAudioData()
|
||||
{
|
||||
if (!udpSyncConnected) return;
|
||||
//DEBUGSR_PRINTLN("Transmitting UDP Mic Packet");
|
||||
|
||||
audioSyncPacket transmitData;
|
||||
strncpy(transmitData.header, UDP_SYNC_HEADER, 6);
|
||||
strncpy_P(transmitData.header, PSTR(UDP_SYNC_HEADER), 6);
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
transmitData.myVals[i] = myVals[i];
|
||||
@ -720,7 +721,13 @@ class AudioReactive : public Usermod {
|
||||
} // transmitAudioData()
|
||||
|
||||
|
||||
void receiveAudioData() {
|
||||
bool isValidUdpSyncVersion(const char *header) {
|
||||
return strncmp_P(header, PSTR(UDP_SYNC_HEADER), 6) == 0;
|
||||
}
|
||||
|
||||
|
||||
void receiveAudioData()
|
||||
{
|
||||
if (!udpSyncConnected) return;
|
||||
//DEBUGSR_PRINTLN("Checking for UDP Microphone Packet");
|
||||
|
||||
@ -764,8 +771,8 @@ class AudioReactive : public Usermod {
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
* It is called *AFTER* readFromConfig()
|
||||
*/
|
||||
void setup() {
|
||||
|
||||
void setup()
|
||||
{
|
||||
if (!initDone) {
|
||||
// usermod exchangeable data
|
||||
// we will assign all usermod exportable data here as pointers to original variables or arrays and allocate memory for pointers
|
||||
@ -859,6 +866,7 @@ class AudioReactive : public Usermod {
|
||||
}
|
||||
delay(250); // give mictophone enough time to initialise
|
||||
|
||||
if (!audioSource) enabled = false; // audio failed to initialise
|
||||
if (enabled) onUpdateBegin(false); // create FFT task
|
||||
|
||||
initDone = true;
|
||||
@ -869,7 +877,8 @@ class AudioReactive : public Usermod {
|
||||
* connected() is called every time the WiFi is (re)connected
|
||||
* Use it to initialize network interfaces
|
||||
*/
|
||||
void connected() {
|
||||
void connected()
|
||||
{
|
||||
if (audioSyncPort > 0 || (audioSyncEnabled & 0x03)) {
|
||||
#ifndef ESP8266
|
||||
udpSyncConnected = fftUdp.beginMulticast(IPAddress(239, 0, 0, 1), audioSyncPort);
|
||||
@ -890,7 +899,10 @@ class AudioReactive : public Usermod {
|
||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
if (!enabled || strip.isUpdating()) return;
|
||||
|
||||
if (!(audioSyncEnabled & 0x02)) { // Only run the sampling code IF we're not in Receive mode
|
||||
if (soundAgc > AGC_NUM_PRESETS) soundAgc = 0; // make sure that AGC preset is valid (to avoid array bounds violation)
|
||||
getSample(); // Sample the microphone
|
||||
@ -918,9 +930,6 @@ class AudioReactive : public Usermod {
|
||||
|
||||
// update inputLevel Slider based on current AGC gain
|
||||
if ((soundAgc>0) && agcEffect) {
|
||||
static unsigned long last_update_time = 0;
|
||||
static unsigned long last_kick_time = 0;
|
||||
static int last_user_inputLevel = 0;
|
||||
unsigned long now_time = millis();
|
||||
|
||||
// "user kick" feature - if user has moved the slider by at least 32 units, we "kick" AGC gain by 30% (up or down)
|
||||
@ -938,9 +947,9 @@ class AudioReactive : public Usermod {
|
||||
new_user_inputLevel = MIN(MAX(new_user_inputLevel, 0),255);
|
||||
|
||||
// update user interfaces - restrict frequency to avoid flooding UI's with small changes
|
||||
if ( ( ((now_time - last_update_time > 3500) && (abs(new_user_inputLevel - inputLevel) > 2)) // small change - every 3.5 sec (max)
|
||||
||((now_time - last_update_time > 2200) && (abs(new_user_inputLevel - inputLevel) > 15)) // medium change
|
||||
||((now_time - last_update_time > 1200) && (abs(new_user_inputLevel - inputLevel) > 31)) )) // BIG change - every second
|
||||
if ( (((now_time - last_update_time > 3500) && (abs(new_user_inputLevel - inputLevel) > 2)) // small change - every 3.5 sec (max)
|
||||
|| ((now_time - last_update_time > 2200) && (abs(new_user_inputLevel - inputLevel) > 15)) // medium change
|
||||
|| ((now_time - last_update_time > 1200) && (abs(new_user_inputLevel - inputLevel) > 31))) ) // BIG change - every second
|
||||
{
|
||||
inputLevel = new_user_inputLevel; // change of least 3 units -> update user variable
|
||||
updateInterfaces(CALL_MODE_WS_SEND); // is this the correct way to notify UIs ? Yes says blazoncek
|
||||
@ -970,14 +979,16 @@ class AudioReactive : public Usermod {
|
||||
}
|
||||
|
||||
|
||||
bool getUMData(um_data_t **data) {
|
||||
bool getUMData(um_data_t **data)
|
||||
{
|
||||
if (!data || !enabled) return false; // no pointer provided by caller or not enabled -> exit
|
||||
*data = um_data;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void onUpdateBegin(bool init) {
|
||||
void onUpdateBegin(bool init)
|
||||
{
|
||||
if (init) vTaskDelete(FFT_Task); // update is about to begin, remove task to prevent crash
|
||||
else { // update has failed or create task requested
|
||||
// Define the FFT Task and lock it to core 0
|
||||
@ -998,19 +1009,30 @@ class AudioReactive : public Usermod {
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
/*
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
int reading = 20;
|
||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray lightArr = user.createNestedArray("Light"); //name
|
||||
lightArr.add(reading); //value
|
||||
lightArr.add(" lux"); //unit
|
||||
String uiDomString = F("<button class=\"btn\" onclick=\"requestJson({");
|
||||
uiDomString += FPSTR(_name);
|
||||
uiDomString += F(":{");
|
||||
uiDomString += FPSTR(_enabled);
|
||||
if (enabled) {
|
||||
uiDomString += F(":false}});\">");
|
||||
} else {
|
||||
uiDomString += F(":true}});\">");
|
||||
}
|
||||
uiDomString += F("Audio <i class=\"icons\"></i>");
|
||||
uiDomString += F("</button>");
|
||||
|
||||
JsonArray infoArr = user.createNestedArray(uiDomString);
|
||||
if (enabled) {
|
||||
infoArr.add(FPSTR(_enabled));
|
||||
} else {
|
||||
infoArr.add(F("disabled"));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
@ -1029,13 +1051,18 @@ class AudioReactive : public Usermod {
|
||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
*/
|
||||
/*
|
||||
void readFromJsonState(JsonObject& root)
|
||||
{
|
||||
userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
if (!initDone) return; // prevent crash on boot applyPreset()
|
||||
bool prevEnabled = enabled;
|
||||
JsonObject usermod = root[FPSTR(_name)];
|
||||
if (!usermod.isNull()) {
|
||||
if (usermod[FPSTR(_enabled)].is<bool>()) {
|
||||
enabled = usermod[FPSTR(_enabled)].as<bool>();
|
||||
if (prevEnabled != enabled) onUpdateBegin(!enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
@ -1076,7 +1103,7 @@ class AudioReactive : public Usermod {
|
||||
void addToConfig(JsonObject& root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||
top[F("enabled")] = enabled;
|
||||
top[FPSTR(_enabled)] = enabled;
|
||||
|
||||
JsonObject amic = top.createNestedObject(FPSTR(_analogmic));
|
||||
amic["pin"] = audioPin;
|
||||
@ -1125,7 +1152,7 @@ class AudioReactive : public Usermod {
|
||||
bool configComplete = !top.isNull();
|
||||
|
||||
bool prevEnabled = enabled;
|
||||
configComplete &= getJsonValue(top[F("enabled")], enabled);
|
||||
configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled);
|
||||
if (initDone && prevEnabled != enabled) {
|
||||
onUpdateBegin(!enabled); // create or remove FFT task
|
||||
}
|
||||
@ -1156,7 +1183,8 @@ class AudioReactive : public Usermod {
|
||||
}
|
||||
|
||||
|
||||
void appendConfigData() {
|
||||
void appendConfigData()
|
||||
{
|
||||
oappend(SET_F("dd=addDropdown('AudioReactive','digitalmic:type');"));
|
||||
oappend(SET_F("addOption(dd,'Generic Analog',0);"));
|
||||
oappend(SET_F("addOption(dd,'Generic I2S',1);"));
|
||||
@ -1201,5 +1229,7 @@ class AudioReactive : public Usermod {
|
||||
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
const char AudioReactive::_name[] PROGMEM = "AudioReactive";
|
||||
const char AudioReactive::_enabled[] PROGMEM = "enabled";
|
||||
const char AudioReactive::_analogmic[] PROGMEM = "analogmic";
|
||||
const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic";
|
||||
const char AudioReactive::UDP_SYNC_HEADER[] PROGMEM = "00001";
|
||||
|
@ -5872,17 +5872,17 @@ uint16_t WS2812FX::mode_2Dscrollingtext(void) {
|
||||
const char *text = PSTR("Use segment name"); // fallback if empty segment name
|
||||
if (SEGMENT.name && strlen(SEGMENT.name)) text = SEGMENT.name;
|
||||
|
||||
char lineBuffer[17];
|
||||
if (!strstr_P(text, PSTR("#DATETIME"))) {
|
||||
char lineBuffer[17], sec[3];
|
||||
if (strstr_P(text, PSTR("#DATETIME"))) {
|
||||
byte AmPmHour = hour(localTime);
|
||||
boolean isitAM = true;
|
||||
if (useAMPM) {
|
||||
if (AmPmHour > 11) { AmPmHour -= 12; isitAM = false; }
|
||||
if (AmPmHour == 0) { AmPmHour = 12; }
|
||||
}
|
||||
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(month(localTime)), day(localTime));
|
||||
if (useAMPM) sprintf_P(lineBuffer,PSTR("%2d:%02d %s"), AmPmHour, minute(localTime), (isitAM ? "AM" : "PM"));
|
||||
else sprintf_P(lineBuffer,PSTR("%2d:%02d:%02d"), AmPmHour, minute(localTime), second(localTime));
|
||||
if (useAMPM) sprintf_P(sec, PSTR(" %2s"), (isitAM ? "AM" : "PM"));
|
||||
else sprintf_P(sec, PSTR(":%02d"), second(localTime));
|
||||
sprintf_P(lineBuffer,PSTR("%s %2d %2d:%02d%s"), monthShortStr(month(localTime)), day(localTime), AmPmHour, minute(localTime), sec);
|
||||
text = lineBuffer;
|
||||
}
|
||||
const int numberOfLetters = strlen(text);
|
||||
|
Loading…
Reference in New Issue
Block a user