2020-12-01 19:40:58 -05:00
|
|
|
/*
|
|
|
|
strobe_esp32.cpp
|
|
|
|
|
|
|
|
Part of WiFlash_esp32
|
|
|
|
|
|
|
|
Copyright (c) 2020 Kevin Matz (kevin.matz@gmail.com)
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <Arduino.h>
|
2020-12-07 08:45:40 -05:00
|
|
|
#include <AsyncUDP.h>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <iterator>
|
2020-12-01 19:40:58 -05:00
|
|
|
#include "strobe_esp32.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
calculate period from DMX value
|
|
|
|
*/
|
|
|
|
uint32_t hz_to_micros(uint8_t dmx) {
|
|
|
|
if (dmx == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// ( millis / ( percent * scalor ) + offset ) * micros
|
|
|
|
return (1000 / (((dmx / 255.0) * 24.5) + 0.5)) * 1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
calculate duration from DMX value
|
|
|
|
*/
|
|
|
|
uint32_t dr_to_micros(uint8_t dmx) {
|
|
|
|
// (( percent * scalor) + offset) * micros
|
|
|
|
return (((dmx / 255.0) * .5 ) + .01 ) * 1000 * 1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Constructor
|
|
|
|
*/
|
2020-12-06 11:07:30 -05:00
|
|
|
Strobe::Strobe(uint16_t address) {
|
2020-12-07 08:45:40 -05:00
|
|
|
address_ = address;
|
2020-12-01 19:40:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
call durring setup()
|
|
|
|
*/
|
|
|
|
bool Strobe::begin(uint8_t pin, uint8_t pwm) {
|
2020-12-04 09:44:58 -05:00
|
|
|
bool success = true;
|
2020-12-01 19:40:58 -05:00
|
|
|
// set state
|
2020-12-07 08:45:40 -05:00
|
|
|
pwm_ = pwm;
|
|
|
|
state_ = STROBE_INACTIVE;
|
2020-12-01 19:40:58 -05:00
|
|
|
|
|
|
|
// configure hardware
|
2020-12-07 08:45:40 -05:00
|
|
|
ledcAttachPin(pin, pwm_); // Attach GPIO to PWM timer
|
|
|
|
ledcSetup(pwm_, 2400, 15); // 2.4KHz PWM, 15 bit resolutio
|
|
|
|
ledcWrite(pwm_, 0); // LED to 0%
|
2020-12-01 19:40:58 -05:00
|
|
|
|
2020-12-04 11:34:26 -05:00
|
|
|
// start update task
|
|
|
|
xTaskCreate(this->update, // function name
|
|
|
|
"StrobeUpdateThread", // task name
|
|
|
|
2048, // stack size (bytes)
|
|
|
|
this, // parameter to pass
|
|
|
|
1, // task priority
|
|
|
|
NULL); // task handle
|
2020-12-04 14:57:57 -05:00
|
|
|
|
2020-12-01 19:40:58 -05:00
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2020-12-04 11:34:26 -05:00
|
|
|
void Strobe::update(void * param) {
|
2020-12-04 14:57:57 -05:00
|
|
|
Strobe *tThis = (Strobe *) param;
|
2020-12-06 17:21:27 -05:00
|
|
|
uint32_t last_time = 0;
|
2020-12-04 11:34:26 -05:00
|
|
|
for (;;) {
|
|
|
|
// intensity changes start/stop the cycle
|
2020-12-07 08:45:40 -05:00
|
|
|
uint16_t intensity = tThis->profile_.intensity << 8 |
|
|
|
|
tThis->profile_.intensity >> 8;
|
|
|
|
if (intensity == 0) {
|
2020-12-04 11:34:26 -05:00
|
|
|
// intensity off breaks the cycle
|
2020-12-07 08:45:40 -05:00
|
|
|
tThis->state_ = STROBE_INACTIVE;
|
2020-12-04 11:34:26 -05:00
|
|
|
} else {
|
2020-12-07 08:45:40 -05:00
|
|
|
if (tThis->state_ == STROBE_INACTIVE) {
|
2020-12-04 11:34:26 -05:00
|
|
|
// going active
|
2020-12-07 08:45:40 -05:00
|
|
|
tThis->state_ = STROBE_ACTIVE_ON;
|
2020-12-04 11:34:26 -05:00
|
|
|
}
|
2020-12-01 19:40:58 -05:00
|
|
|
}
|
|
|
|
|
2020-12-04 11:34:26 -05:00
|
|
|
// time based cycle changes
|
2020-12-07 08:45:40 -05:00
|
|
|
if (tThis->state_ == STROBE_ACTIVE_ON ||
|
|
|
|
tThis->state_ == STROBE_ACTIVE_OFF) {
|
|
|
|
uint32_t now, elapsed, period, dur;
|
2020-12-04 11:34:26 -05:00
|
|
|
now = micros();
|
2020-12-06 17:21:27 -05:00
|
|
|
elapsed = now - last_time;
|
2020-12-07 08:45:40 -05:00
|
|
|
period = hz_to_micros(tThis->profile_.rate);
|
|
|
|
dur = dr_to_micros(tThis->profile_.duration);
|
2020-12-04 11:34:26 -05:00
|
|
|
|
|
|
|
if (elapsed > period || // hz period completed
|
2020-12-06 17:21:27 -05:00
|
|
|
now < last_time) { // micros() wraps 32 bits every ~70 min.
|
2020-12-04 11:34:26 -05:00
|
|
|
// cycle restarts
|
2020-12-07 08:45:40 -05:00
|
|
|
tThis->state_ = STROBE_ACTIVE_ON;
|
2020-12-06 17:21:27 -05:00
|
|
|
last_time = now;
|
2020-12-07 08:45:40 -05:00
|
|
|
} else if (elapsed > dur) { // durration period completed
|
2020-12-04 11:34:26 -05:00
|
|
|
// cycle enters dark phase
|
2020-12-07 08:45:40 -05:00
|
|
|
tThis->state_ = STROBE_ACTIVE_OFF;
|
2020-12-04 11:34:26 -05:00
|
|
|
}
|
2020-12-01 19:40:58 -05:00
|
|
|
}
|
|
|
|
|
2020-12-04 11:34:26 -05:00
|
|
|
// set LED output
|
2020-12-07 08:45:40 -05:00
|
|
|
if (tThis->state_ == STROBE_ACTIVE_ON) {
|
|
|
|
tThis->setLevel(intensity);
|
2020-12-04 11:34:26 -05:00
|
|
|
} else {
|
|
|
|
tThis->setLevel(0);
|
|
|
|
}
|
2020-12-01 19:40:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Write a 15bit level to PWM
|
|
|
|
*/
|
|
|
|
void Strobe::setLevel(uint16_t level) {
|
2020-12-07 08:45:40 -05:00
|
|
|
ledcWrite(pwm_, ((level >> 1) & 0xffff)); // write at 15 bit PWM
|
2020-12-01 19:40:58 -05:00
|
|
|
}
|
|
|
|
|
2020-12-07 08:45:40 -05:00
|
|
|
void Strobe::recvData(Universe * univ) {
|
|
|
|
if ( sizeof(profile_.dmx) + address_ > sizeof(univ->data()->data)) {
|
|
|
|
// address is higher than allowable
|
|
|
|
Serial.println("Bad Address");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
std::copy(univ->data()->data + address_,
|
|
|
|
univ->data()->data + address_ + sizeof(profile_.dmx),
|
|
|
|
std::begin(profile_.dmx));
|
2020-12-01 19:40:58 -05:00
|
|
|
}
|