Add clock run/reset
This commit is contained in:
@ -107,6 +107,28 @@ void loop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clock Run
|
||||||
|
if (app.cv_run == 1 || app.cv_run == 2) {
|
||||||
|
auto &cv = app.cv_run == 1 ? gravity.cv1 : gravity.cv2;
|
||||||
|
int val = cv.Read();
|
||||||
|
if (val > AnalogInput::GATE_THRESHOLD && gravity.clock.IsPaused()) {
|
||||||
|
gravity.clock.Start();
|
||||||
|
app.refresh_screen = true;
|
||||||
|
} else if (val < AnalogInput::GATE_THRESHOLD && !gravity.clock.IsPaused()) {
|
||||||
|
gravity.clock.Stop();
|
||||||
|
ResetOutputs();
|
||||||
|
app.refresh_screen = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clock Reset
|
||||||
|
if ((app.cv_reset == 1 &&
|
||||||
|
gravity.cv1.IsRisingEdge(AnalogInput::GATE_THRESHOLD)) ||
|
||||||
|
(app.cv_reset == 2 &&
|
||||||
|
gravity.cv2.IsRisingEdge(AnalogInput::GATE_THRESHOLD))) {
|
||||||
|
gravity.clock.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
// Check for dirty state eligible to be saved.
|
// Check for dirty state eligible to be saved.
|
||||||
stateManager.update(app);
|
stateManager.update(app);
|
||||||
|
|
||||||
@ -285,6 +307,14 @@ void editMainParameter(int val) {
|
|||||||
gravity.clock.SetTempo(gravity.clock.Tempo() + val);
|
gravity.clock.SetTempo(gravity.clock.Tempo() + val);
|
||||||
app.tempo = gravity.clock.Tempo();
|
app.tempo = gravity.clock.Tempo();
|
||||||
break;
|
break;
|
||||||
|
case PARAM_MAIN_RUN:
|
||||||
|
updateSelection(app.selected_sub_param, val, 3);
|
||||||
|
app.cv_run = app.selected_sub_param;
|
||||||
|
break;
|
||||||
|
case PARAM_MAIN_RESET:
|
||||||
|
updateSelection(app.selected_sub_param, val, 3);
|
||||||
|
app.cv_reset = app.selected_sub_param;
|
||||||
|
break;
|
||||||
case PARAM_MAIN_SOURCE: {
|
case PARAM_MAIN_SOURCE: {
|
||||||
byte source = static_cast<int>(app.selected_source);
|
byte source = static_cast<int>(app.selected_source);
|
||||||
updateSelection(source, val, Clock::SOURCE_LAST);
|
updateSelection(source, val, Clock::SOURCE_LAST);
|
||||||
@ -301,6 +331,7 @@ void editMainParameter(int val) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// These changes are applied upon encoder button press.
|
||||||
case PARAM_MAIN_ENCODER_DIR:
|
case PARAM_MAIN_ENCODER_DIR:
|
||||||
updateSelection(app.selected_sub_param, val, 2);
|
updateSelection(app.selected_sub_param, val, 2);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -27,6 +27,8 @@ struct AppState {
|
|||||||
byte selected_save_slot = 0; // The currently active save slot.
|
byte selected_save_slot = 0; // The currently active save slot.
|
||||||
Clock::Source selected_source = Clock::SOURCE_INTERNAL;
|
Clock::Source selected_source = Clock::SOURCE_INTERNAL;
|
||||||
Clock::Pulse selected_pulse = Clock::PULSE_PPQN_24;
|
Clock::Pulse selected_pulse = Clock::PULSE_PPQN_24;
|
||||||
|
byte cv_run = 0;
|
||||||
|
byte cv_reset = 0;
|
||||||
bool editing_param = false;
|
bool editing_param = false;
|
||||||
bool encoder_reversed = false;
|
bool encoder_reversed = false;
|
||||||
bool refresh_screen = true;
|
bool refresh_screen = true;
|
||||||
|
|||||||
@ -127,6 +127,8 @@ constexpr uint8_t CHANNEL_BOX_HEIGHT = 14;
|
|||||||
// Menu items for editing global parameters.
|
// Menu items for editing global parameters.
|
||||||
enum ParamsMainPage : uint8_t {
|
enum ParamsMainPage : uint8_t {
|
||||||
PARAM_MAIN_TEMPO,
|
PARAM_MAIN_TEMPO,
|
||||||
|
PARAM_MAIN_RUN,
|
||||||
|
PARAM_MAIN_RESET,
|
||||||
PARAM_MAIN_SOURCE,
|
PARAM_MAIN_SOURCE,
|
||||||
PARAM_MAIN_PULSE,
|
PARAM_MAIN_PULSE,
|
||||||
PARAM_MAIN_ENCODER_DIR,
|
PARAM_MAIN_ENCODER_DIR,
|
||||||
@ -253,6 +255,34 @@ void DisplayMainPage() {
|
|||||||
}
|
}
|
||||||
subText = F("BPM");
|
subText = F("BPM");
|
||||||
break;
|
break;
|
||||||
|
case PARAM_MAIN_RUN:
|
||||||
|
mainText = F("RUN");
|
||||||
|
switch (app.cv_run) {
|
||||||
|
case 0:
|
||||||
|
subText = F("NONE");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
subText = F("CV1 GATE");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
subText = F("CV2 GATE");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PARAM_MAIN_RESET:
|
||||||
|
mainText = F("RST");
|
||||||
|
switch (app.cv_reset) {
|
||||||
|
case 0:
|
||||||
|
subText = F("NONE");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
subText = F("CV1 TRIG");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
subText = F("CV2 TRIG");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PARAM_MAIN_SOURCE:
|
case PARAM_MAIN_SOURCE:
|
||||||
mainText = F("EXT");
|
mainText = F("EXT");
|
||||||
switch (app.selected_source) {
|
switch (app.selected_source) {
|
||||||
@ -339,8 +369,9 @@ void DisplayMainPage() {
|
|||||||
|
|
||||||
// Draw Main Page menu items
|
// Draw Main Page menu items
|
||||||
String menu_items[PARAM_MAIN_LAST] = {
|
String menu_items[PARAM_MAIN_LAST] = {
|
||||||
F("TEMPO"), F("SOURCE"), F("PULSE OUT"), F("ENCODER DIR"),
|
F("TEMPO"), F("CLK RUN"), F("CLK RESET"), F("SOURCE"),
|
||||||
F("SAVE"), F("LOAD"), F("RESET"), F("ERASE")};
|
F("PULSE OUT"), F("ENCODER DIR"), F("SAVE"), F("LOAD"),
|
||||||
|
F("RESET"), F("ERASE")};
|
||||||
drawMenuItems(menu_items, PARAM_MAIN_LAST);
|
drawMenuItems(menu_items, PARAM_MAIN_LAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
// Define the constants for the current firmware.
|
// Define the constants for the current firmware.
|
||||||
const char StateManager::SKETCH_NAME[] = "ALT EUCLIDEAN";
|
const char StateManager::SKETCH_NAME[] = "ALT EUCLIDEAN";
|
||||||
const char StateManager::SEMANTIC_VERSION[] =
|
const char StateManager::SEMANTIC_VERSION[] =
|
||||||
"V2.0.0BETA2"; // NOTE: This should match the version in the
|
"V2.0.0BETA3"; // NOTE: This should match the version in the
|
||||||
// library.properties file.
|
// library.properties file.
|
||||||
|
|
||||||
// Number of available save slots.
|
// Number of available save slots.
|
||||||
@ -94,6 +94,8 @@ void StateManager::reset(AppState &app) {
|
|||||||
app.selected_channel = default_app.selected_channel;
|
app.selected_channel = default_app.selected_channel;
|
||||||
app.selected_source = default_app.selected_source;
|
app.selected_source = default_app.selected_source;
|
||||||
app.selected_pulse = default_app.selected_pulse;
|
app.selected_pulse = default_app.selected_pulse;
|
||||||
|
app.cv_run = default_app.cv_run;
|
||||||
|
app.cv_reset = default_app.cv_reset;
|
||||||
|
|
||||||
for (int i = 0; i < Gravity::OUTPUT_COUNT; i++) {
|
for (int i = 0; i < Gravity::OUTPUT_COUNT; i++) {
|
||||||
app.channel[i].Init();
|
app.channel[i].Init();
|
||||||
@ -148,6 +150,8 @@ void StateManager::_saveState(const AppState &app, byte slot_index) {
|
|||||||
save_data.selected_channel = app.selected_channel;
|
save_data.selected_channel = app.selected_channel;
|
||||||
save_data.selected_source = static_cast<byte>(app.selected_source);
|
save_data.selected_source = static_cast<byte>(app.selected_source);
|
||||||
save_data.selected_pulse = static_cast<byte>(app.selected_pulse);
|
save_data.selected_pulse = static_cast<byte>(app.selected_pulse);
|
||||||
|
save_data.cv_run = app.cv_run;
|
||||||
|
save_data.cv_reset = app.cv_reset;
|
||||||
|
|
||||||
// TODO: break this out into a separate function. Save State should be
|
// TODO: break this out into a separate function. Save State should be
|
||||||
// broken out into global / per-channel save methods. When saving via
|
// broken out into global / per-channel save methods. When saving via
|
||||||
@ -184,6 +188,8 @@ void StateManager::_loadState(AppState &app, byte slot_index) {
|
|||||||
app.selected_channel = load_data.selected_channel;
|
app.selected_channel = load_data.selected_channel;
|
||||||
app.selected_source = static_cast<Clock::Source>(load_data.selected_source);
|
app.selected_source = static_cast<Clock::Source>(load_data.selected_source);
|
||||||
app.selected_pulse = static_cast<Clock::Pulse>(load_data.selected_pulse);
|
app.selected_pulse = static_cast<Clock::Pulse>(load_data.selected_pulse);
|
||||||
|
app.cv_run = load_data.cv_run;
|
||||||
|
app.cv_reset = load_data.cv_reset;
|
||||||
|
|
||||||
for (int i = 0; i < Gravity::OUTPUT_COUNT; i++) {
|
for (int i = 0; i < Gravity::OUTPUT_COUNT; i++) {
|
||||||
auto &ch = app.channel[i];
|
auto &ch = app.channel[i];
|
||||||
|
|||||||
@ -72,6 +72,8 @@ public:
|
|||||||
byte selected_channel;
|
byte selected_channel;
|
||||||
byte selected_source;
|
byte selected_source;
|
||||||
byte selected_pulse;
|
byte selected_pulse;
|
||||||
|
byte cv_run;
|
||||||
|
byte cv_reset;
|
||||||
ChannelState channel_data[Gravity::OUTPUT_COUNT];
|
ChannelState channel_data[Gravity::OUTPUT_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -107,6 +107,28 @@ void loop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clock Run
|
||||||
|
if (app.cv_run == 1 || app.cv_run == 2) {
|
||||||
|
auto &cv = app.cv_run == 1 ? gravity.cv1 : gravity.cv2;
|
||||||
|
int val = cv.Read();
|
||||||
|
if (val > AnalogInput::GATE_THRESHOLD && gravity.clock.IsPaused()) {
|
||||||
|
gravity.clock.Start();
|
||||||
|
app.refresh_screen = true;
|
||||||
|
} else if (val < AnalogInput::GATE_THRESHOLD && !gravity.clock.IsPaused()) {
|
||||||
|
gravity.clock.Stop();
|
||||||
|
ResetOutputs();
|
||||||
|
app.refresh_screen = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clock Reset
|
||||||
|
if ((app.cv_reset == 1 &&
|
||||||
|
gravity.cv1.IsRisingEdge(AnalogInput::GATE_THRESHOLD)) ||
|
||||||
|
(app.cv_reset == 2 &&
|
||||||
|
gravity.cv2.IsRisingEdge(AnalogInput::GATE_THRESHOLD))) {
|
||||||
|
gravity.clock.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
// Check for dirty state eligible to be saved.
|
// Check for dirty state eligible to be saved.
|
||||||
stateManager.update(app);
|
stateManager.update(app);
|
||||||
|
|
||||||
@ -285,6 +307,14 @@ void editMainParameter(int val) {
|
|||||||
gravity.clock.SetTempo(gravity.clock.Tempo() + val);
|
gravity.clock.SetTempo(gravity.clock.Tempo() + val);
|
||||||
app.tempo = gravity.clock.Tempo();
|
app.tempo = gravity.clock.Tempo();
|
||||||
break;
|
break;
|
||||||
|
case PARAM_MAIN_RUN:
|
||||||
|
updateSelection(app.selected_sub_param, val, 3);
|
||||||
|
app.cv_run = app.selected_sub_param;
|
||||||
|
break;
|
||||||
|
case PARAM_MAIN_RESET:
|
||||||
|
updateSelection(app.selected_sub_param, val, 3);
|
||||||
|
app.cv_reset = app.selected_sub_param;
|
||||||
|
break;
|
||||||
case PARAM_MAIN_SOURCE: {
|
case PARAM_MAIN_SOURCE: {
|
||||||
byte source = static_cast<int>(app.selected_source);
|
byte source = static_cast<int>(app.selected_source);
|
||||||
updateSelection(source, val, Clock::SOURCE_LAST);
|
updateSelection(source, val, Clock::SOURCE_LAST);
|
||||||
@ -301,6 +331,7 @@ void editMainParameter(int val) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// These changes are applied upon encoder button press.
|
||||||
case PARAM_MAIN_ENCODER_DIR:
|
case PARAM_MAIN_ENCODER_DIR:
|
||||||
updateSelection(app.selected_sub_param, val, 2);
|
updateSelection(app.selected_sub_param, val, 2);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -25,6 +25,8 @@ struct AppState {
|
|||||||
byte selected_channel = 0; // 0=tempo, 1-6=output channel
|
byte selected_channel = 0; // 0=tempo, 1-6=output channel
|
||||||
byte selected_swing = 0;
|
byte selected_swing = 0;
|
||||||
byte selected_save_slot = 0; // The currently active save slot.
|
byte selected_save_slot = 0; // The currently active save slot.
|
||||||
|
byte cv_run = 0;
|
||||||
|
byte cv_reset = 0;
|
||||||
Clock::Source selected_source = Clock::SOURCE_INTERNAL;
|
Clock::Source selected_source = Clock::SOURCE_INTERNAL;
|
||||||
Clock::Pulse selected_pulse = Clock::PULSE_PPQN_24;
|
Clock::Pulse selected_pulse = Clock::PULSE_PPQN_24;
|
||||||
bool editing_param = false;
|
bool editing_param = false;
|
||||||
|
|||||||
@ -128,6 +128,8 @@ constexpr uint8_t CHANNEL_BOX_HEIGHT = 14;
|
|||||||
enum ParamsMainPage : uint8_t {
|
enum ParamsMainPage : uint8_t {
|
||||||
PARAM_MAIN_TEMPO,
|
PARAM_MAIN_TEMPO,
|
||||||
PARAM_MAIN_SOURCE,
|
PARAM_MAIN_SOURCE,
|
||||||
|
PARAM_MAIN_RUN,
|
||||||
|
PARAM_MAIN_RESET,
|
||||||
PARAM_MAIN_PULSE,
|
PARAM_MAIN_PULSE,
|
||||||
PARAM_MAIN_ENCODER_DIR,
|
PARAM_MAIN_ENCODER_DIR,
|
||||||
PARAM_MAIN_SAVE_DATA,
|
PARAM_MAIN_SAVE_DATA,
|
||||||
@ -296,6 +298,34 @@ void DisplayMainPage() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PARAM_MAIN_RUN:
|
||||||
|
mainText = F("RUN");
|
||||||
|
switch (app.cv_run) {
|
||||||
|
case 0:
|
||||||
|
subText = F("NONE");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
subText = F("CV 1");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
subText = F("CV 2");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PARAM_MAIN_RESET:
|
||||||
|
mainText = F("RST");
|
||||||
|
switch (app.cv_reset) {
|
||||||
|
case 0:
|
||||||
|
subText = F("NONE");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
subText = F("CV 1");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
subText = F("CV 2");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PARAM_MAIN_PULSE:
|
case PARAM_MAIN_PULSE:
|
||||||
mainText = F("OUT");
|
mainText = F("OUT");
|
||||||
switch (app.selected_pulse) {
|
switch (app.selected_pulse) {
|
||||||
@ -358,8 +388,9 @@ void DisplayMainPage() {
|
|||||||
|
|
||||||
// Draw Main Page menu items
|
// Draw Main Page menu items
|
||||||
String menu_items[PARAM_MAIN_LAST] = {
|
String menu_items[PARAM_MAIN_LAST] = {
|
||||||
F("TEMPO"), F("SOURCE"), F("PULSE OUT"), F("ENCODER DIR"),
|
F("TEMPO"), F("SOURCE"), F("CLK RUN"),
|
||||||
F("SAVE"), F("LOAD"), F("RESET"), F("ERASE")};
|
F("CLK RESET"), F("PULSE OUT"), F("ENCODER DIR"),
|
||||||
|
F("SAVE"), F("LOAD"), F("ERASE")};
|
||||||
drawMenuItems(menu_items, PARAM_MAIN_LAST);
|
drawMenuItems(menu_items, PARAM_MAIN_LAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
// Define the constants for the current firmware.
|
// Define the constants for the current firmware.
|
||||||
const char StateManager::SKETCH_NAME[] = "ALT GRAVITY";
|
const char StateManager::SKETCH_NAME[] = "ALT GRAVITY";
|
||||||
const char StateManager::SEMANTIC_VERSION[] =
|
const char StateManager::SEMANTIC_VERSION[] =
|
||||||
"V2.0.0BETA2"; // NOTE: This should match the version in the
|
"V2.0.0BETA4"; // NOTE: This should match the version in the
|
||||||
// library.properties file.
|
// library.properties file.
|
||||||
|
|
||||||
// Number of available save slots.
|
// Number of available save slots.
|
||||||
@ -94,6 +94,8 @@ void StateManager::reset(AppState &app) {
|
|||||||
app.selected_channel = default_app.selected_channel;
|
app.selected_channel = default_app.selected_channel;
|
||||||
app.selected_source = default_app.selected_source;
|
app.selected_source = default_app.selected_source;
|
||||||
app.selected_pulse = default_app.selected_pulse;
|
app.selected_pulse = default_app.selected_pulse;
|
||||||
|
app.cv_run = default_app.cv_run;
|
||||||
|
app.cv_reset = default_app.cv_reset;
|
||||||
|
|
||||||
for (int i = 0; i < Gravity::OUTPUT_COUNT; i++) {
|
for (int i = 0; i < Gravity::OUTPUT_COUNT; i++) {
|
||||||
app.channel[i].Init();
|
app.channel[i].Init();
|
||||||
@ -148,6 +150,8 @@ void StateManager::_saveState(const AppState &app, byte slot_index) {
|
|||||||
save_data.selected_channel = app.selected_channel;
|
save_data.selected_channel = app.selected_channel;
|
||||||
save_data.selected_source = static_cast<byte>(app.selected_source);
|
save_data.selected_source = static_cast<byte>(app.selected_source);
|
||||||
save_data.selected_pulse = static_cast<byte>(app.selected_pulse);
|
save_data.selected_pulse = static_cast<byte>(app.selected_pulse);
|
||||||
|
save_data.cv_run = app.cv_run;
|
||||||
|
save_data.cv_reset = app.cv_reset;
|
||||||
|
|
||||||
// TODO: break this out into a separate function. Save State should be
|
// TODO: break this out into a separate function. Save State should be
|
||||||
// broken out into global / per-channel save methods. When saving via
|
// broken out into global / per-channel save methods. When saving via
|
||||||
@ -185,6 +189,8 @@ void StateManager::_loadState(AppState &app, byte slot_index) {
|
|||||||
app.selected_channel = load_data.selected_channel;
|
app.selected_channel = load_data.selected_channel;
|
||||||
app.selected_source = static_cast<Clock::Source>(load_data.selected_source);
|
app.selected_source = static_cast<Clock::Source>(load_data.selected_source);
|
||||||
app.selected_pulse = static_cast<Clock::Pulse>(load_data.selected_pulse);
|
app.selected_pulse = static_cast<Clock::Pulse>(load_data.selected_pulse);
|
||||||
|
app.cv_run = load_data.cv_run;
|
||||||
|
app.cv_reset = load_data.cv_reset;
|
||||||
|
|
||||||
for (int i = 0; i < Gravity::OUTPUT_COUNT; i++) {
|
for (int i = 0; i < Gravity::OUTPUT_COUNT; i++) {
|
||||||
auto &ch = app.channel[i];
|
auto &ch = app.channel[i];
|
||||||
|
|||||||
@ -73,6 +73,8 @@ public:
|
|||||||
byte selected_channel;
|
byte selected_channel;
|
||||||
byte selected_source;
|
byte selected_source;
|
||||||
byte selected_pulse;
|
byte selected_pulse;
|
||||||
|
byte cv_run;
|
||||||
|
byte cv_reset;
|
||||||
ChannelState channel_data[Gravity::OUTPUT_COUNT];
|
ChannelState channel_data[Gravity::OUTPUT_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,8 @@ const int CALIBRATED_HIGH = 512;
|
|||||||
|
|
||||||
class AnalogInput {
|
class AnalogInput {
|
||||||
public:
|
public:
|
||||||
|
static const int GATE_THRESHOLD = 0;
|
||||||
|
|
||||||
AnalogInput() {}
|
AnalogInput() {}
|
||||||
~AnalogInput() {}
|
~AnalogInput() {}
|
||||||
|
|
||||||
@ -41,7 +43,8 @@ class AnalogInput {
|
|||||||
int raw = analogRead(pin_);
|
int raw = analogRead(pin_);
|
||||||
read_ = map(raw, 0, MAX_INPUT, low_, high_);
|
read_ = map(raw, 0, MAX_INPUT, low_, high_);
|
||||||
read_ = constrain(read_ - offset_, -512, 512);
|
read_ = constrain(read_ - offset_, -512, 512);
|
||||||
if (inverted_) read_ = -read_;
|
if (inverted_)
|
||||||
|
read_ = -read_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set calibration values.
|
// Set calibration values.
|
||||||
@ -74,6 +77,19 @@ class AnalogInput {
|
|||||||
*/
|
*/
|
||||||
inline float Voltage() { return ((read_ / 512.0) * 5.0); }
|
inline float Voltage() { return ((read_ / 512.0) * 5.0); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for a rising edge transition across a threshold.
|
||||||
|
*
|
||||||
|
* @param threshold The value that the input must cross.
|
||||||
|
* @return True if the value just crossed the threshold from below, false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
inline bool IsRisingEdge(int16_t threshold) const {
|
||||||
|
bool was_high = old_read_ > threshold;
|
||||||
|
bool is_high = read_ > threshold;
|
||||||
|
return is_high && !was_high;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t pin_;
|
uint8_t pin_;
|
||||||
int16_t read_;
|
int16_t read_;
|
||||||
|
|||||||
@ -43,8 +43,10 @@ class DigitalOutput {
|
|||||||
* @param state Arduino digital HIGH or LOW values.
|
* @param state Arduino digital HIGH or LOW values.
|
||||||
*/
|
*/
|
||||||
inline void Update(uint8_t state) {
|
inline void Update(uint8_t state) {
|
||||||
if (state == HIGH) High(); // Rising
|
if (state == HIGH)
|
||||||
if (state == LOW) Low(); // Falling
|
High(); // Rising
|
||||||
|
if (state == LOW)
|
||||||
|
Low(); // Falling
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the cv output HIGH to about 5v.
|
// Sets the cv output HIGH to about 5v.
|
||||||
@ -65,7 +67,8 @@ class DigitalOutput {
|
|||||||
* Return a bool representing the on/off state of the output.
|
* Return a bool representing the on/off state of the output.
|
||||||
*/
|
*/
|
||||||
inline void Process() {
|
inline void Process() {
|
||||||
// If trigger is HIGH and the trigger duration time has elapsed, set the output low.
|
// If trigger is HIGH and the trigger duration time has elapsed, set the
|
||||||
|
// output low.
|
||||||
if (on_ && (millis() - last_triggered_) >= trigger_duration_) {
|
if (on_ && (millis() - last_triggered_) >= trigger_duration_) {
|
||||||
update(LOW);
|
update(LOW);
|
||||||
}
|
}
|
||||||
@ -82,7 +85,6 @@ class DigitalOutput {
|
|||||||
unsigned long last_triggered_;
|
unsigned long last_triggered_;
|
||||||
uint8_t trigger_duration_;
|
uint8_t trigger_duration_;
|
||||||
uint8_t cv_pin_;
|
uint8_t cv_pin_;
|
||||||
uint8_t led_pin_;
|
|
||||||
bool on_;
|
bool on_;
|
||||||
|
|
||||||
void update(uint8_t state) {
|
void update(uint8_t state) {
|
||||||
|
|||||||
Reference in New Issue
Block a user