diff --git a/CHANGELOG.md b/CHANGELOG.md index 489e99d2..8138ab4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ - **FIX**: support all line ending types for USB load - **FIX**: fix `STATE` not accounting for `DEVICE.FLIP` - **FIX**: fix MIDI IN ops channel number being off by 1 +- **FIX**: improve `TR.P` accuracy +- **FIX**: fix `KILL` not stopping TR pulses in progress ## v4.0.0 diff --git a/docs/whats_new.md b/docs/whats_new.md index 05c4b005..61bb7d4b 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -20,6 +20,8 @@ - **FIX**: support all line ending types for USB load - **FIX**: fix `STATE` not accounting for `DEVICE.FLIP` - **FIX**: fix MIDI IN ops channel number being off by 1 +- **FIX**: improve `TR.P` accuracy +- **FIX**: fix `KILL` not stopping TR pulses in progress ## v4.0.0 diff --git a/module/main.c b/module/main.c index 4f264358..7e01b6ff 100644 --- a/module/main.c +++ b/module/main.c @@ -133,6 +133,7 @@ static softTimer_t monomePollTimer = {.next = NULL, .prev = NULL }; static softTimer_t monomeRefreshTimer = {.next = NULL, .prev = NULL }; static softTimer_t gridFaderTimer = {.next = NULL, .prev = NULL }; static softTimer_t midiScriptTimer = {.next = NULL, .prev = NULL }; +static softTimer_t trPulseTimer[TR_COUNT]; //////////////////////////////////////////////////////////////////////////////// @@ -150,6 +151,7 @@ static void monome_poll_timer_callback(void* obj); static void monome_refresh_timer_callback(void* obj); static void grid_fader_timer_callback(void* obj); static void midiScriptTimer_callback(void* obj); +static void trPulseTimer_callback(void* obj); // event handler prototypes static void handler_None(int32_t data); @@ -1046,6 +1048,36 @@ void tele_tr(uint8_t i, int16_t v) { gpio_set_pin_low(pin); } +void tele_tr_pulse(uint8_t i, int16_t time) { + if (i >= TR_COUNT) return; + timer_remove(&trPulseTimer[i]); + timer_add(&trPulseTimer[i], time, &trPulseTimer_callback, + (void*)(int32_t)i); +} + +void tele_tr_pulse_clear(uint8_t i) { + if (i >= TR_COUNT) return; + timer_remove(&trPulseTimer[i]); +} + +void tele_tr_pulse_time(uint8_t i, int16_t time) { + if (i >= TR_COUNT) return; + + u32 time_spent = trPulseTimer[i].ticks - trPulseTimer[i].ticksRemain; + timer_set(&trPulseTimer[i], time); + if (time_spent >= time) { timer_manual(&trPulseTimer[i]); } + else { + trPulseTimer[i].ticksRemain = time - time_spent; + } +} + +void trPulseTimer_callback(void* obj) { + int i = (int)obj; + if (i >= TR_COUNT) return; + timer_remove(&trPulseTimer[i]); + tele_tr_pulse_end(&scene_state, i); +} + void tele_cv(uint8_t i, int16_t v, uint8_t s) { int16_t t = v + aout[i].off; if (t < 0) @@ -1237,6 +1269,11 @@ int main(void) { aout[2].slew = 1; aout[3].slew = 1; + for (uint8_t i = 0; i < TR_COUNT; i++) { + trPulseTimer[i].next = NULL; + trPulseTimer[i].prev = NULL; + } + init_live_mode(); set_mode(M_LIVE); diff --git a/simulator/tt.c b/simulator/tt.c index 52706e7b..b3a436a4 100644 --- a/simulator/tt.c +++ b/simulator/tt.c @@ -30,6 +30,21 @@ void tele_tr(uint8_t i, int16_t v) { printf("\n"); } +void tele_tr_pulse(uint8_t i, int16_t time) { + printf("TR PULSE i:%" PRIu8 " time:%" PRId16, i, time); + printf("\n"); +} + +void tele_tr_pulse_clear(uint8_t i) { + printf("TR PULSE CLEAR i:%" PRIu8, i); + printf("\n"); +} + +void tele_tr_pulse_time(uint8_t i, int16_t time) { + printf("TR PULSE TIME i:%" PRIu8 " time:%" PRId16, i, time); + printf("\n"); +} + void tele_cv(uint8_t i, int16_t v, uint8_t s) { printf("CV i:%" PRIu8 " v:%" PRId16 " s:%" PRIu8, i, v, s); printf("\n"); diff --git a/src/ops/hardware.c b/src/ops/hardware.c index 5607d167..38af4dc2 100644 --- a/src/ops/hardware.c +++ b/src/ops/hardware.c @@ -409,6 +409,7 @@ static void op_TR_TIME_set(const void *NOTUSED(data), scene_state_t *ss, return; else if (a < 4) { ss->variables.tr_time[a] = b; + tele_tr_pulse_time(a, b); } else if (a < 20) { uint8_t d[] = { II_ANSIBLE_TR_TIME, a & 0x3, b >> 8, b & 0xff }; @@ -447,8 +448,8 @@ static void op_TR_PULSE_get(const void *NOTUSED(data), scene_state_t *ss, int16_t time = ss->variables.tr_time[a]; // pulse time if (time <= 0) return; // if time <= 0 don't do anything ss->variables.tr[a] = ss->variables.tr_pol[a]; - ss->tr_pulse_timer[a] = time; // set time tele_tr(a, ss->variables.tr[a]); + tele_tr_pulse(a, time); } else if (a < 20) { uint8_t d[] = { II_ANSIBLE_TR_PULSE, a & 0x3 }; diff --git a/src/ops/init.c b/src/ops/init.c index 574bf659..8dbb1219 100644 --- a/src/ops/init.c +++ b/src/ops/init.c @@ -144,7 +144,7 @@ static void op_INIT_TR_get(const void *NOTUSED(data), scene_state_t *ss, ss->variables.tr[v] = 0; ss->variables.tr_pol[v] = 1; ss->variables.tr_time[v] = 100; - ss->tr_pulse_timer[v] = 0; + tele_tr_pulse_clear(v); tele_tr(v, 0); } } @@ -156,7 +156,7 @@ static void op_INIT_TR_ALL_get(const void *NOTUSED(data), scene_state_t *ss, ss->variables.tr[i] = 0; ss->variables.tr_pol[i] = 1; ss->variables.tr_time[i] = 100; - ss->tr_pulse_timer[i] = 0; + tele_tr_pulse_clear(i); tele_tr(i, 0); } } diff --git a/src/state.c b/src/state.c index 0f8931a6..751c3068 100644 --- a/src/state.c +++ b/src/state.c @@ -17,7 +17,6 @@ void ss_init(scene_state_t *ss) { ss_rand_init(ss); ss_midi_init(ss); ss->delay.count = 0; - for (size_t i = 0; i < TR_COUNT; i++) { ss->tr_pulse_timer[i] = 0; } for (size_t i = 0; i < NB_NBX_SCALES; i++) { ss->variables.n_scale_bits[i] = bit_reverse(0b101011010101, 12); ss->variables.n_scale_root[i] = 0; diff --git a/src/state.h b/src/state.h index 3ae57521..e2435cc7 100644 --- a/src/state.h +++ b/src/state.h @@ -261,7 +261,6 @@ typedef struct { scene_pattern_t patterns[PATTERN_COUNT]; scene_delay_t delay; scene_stack_op_t stack_op; - int16_t tr_pulse_timer[TR_COUNT]; scene_script_t scripts[TOTAL_SCRIPT_COUNT]; scene_turtle_t turtle; bool every_last; diff --git a/src/teletype.c b/src/teletype.c index 6a9d4a63..07b79547 100644 --- a/src/teletype.c +++ b/src/teletype.c @@ -18,7 +18,10 @@ bool processing_delays = false; // DELAY //////////////////////////////////////////////////////// void clear_delays(scene_state_t *ss) { - for (int16_t i = 0; i < TR_COUNT; i++) { ss->tr_pulse_timer[i] = 0; } + for (int16_t i = 0; i < TR_COUNT; i++) { + tele_tr_pulse_clear(i); + tele_tr_pulse_end(ss, i); + } for (int16_t i = 0; i < DELAY_SIZE; i++) { ss->delay.time[i] = 0; } @@ -344,25 +347,11 @@ void tele_tick(scene_state_t *ss, uint8_t time) { } } } +} - // process tr pulses - for (int16_t i = 0; i < TR_COUNT; i++) { - if (ss->tr_pulse_timer[i]) { - // prevent tr_pulse_timer from being greater than tr_time - int16_t tr_time = ss->variables.tr_time[i]; - if (tr_time < 0) tr_time = 0; - if (ss->tr_pulse_timer[i] > tr_time) - ss->tr_pulse_timer[i] = tr_time; - - ss->tr_pulse_timer[i] -= time; - - if (ss->tr_pulse_timer[i] <= 0) { - ss->tr_pulse_timer[i] = 0; - ss->variables.tr[i] = ss->variables.tr_pol[i] == 0; - tele_tr(i, ss->variables.tr[i]); - } - } - } +void tele_tr_pulse_end(scene_state_t *ss, uint8_t i) { + ss->variables.tr[i] = ss->variables.tr_pol[i] == 0; + tele_tr(i, ss->variables.tr[i]); } ///////////////////////////////////////////////////////////////// diff --git a/src/teletype.h b/src/teletype.h index 3e0c6970..97ecf8e1 100644 --- a/src/teletype.h +++ b/src/teletype.h @@ -47,6 +47,8 @@ void tele_tick(scene_state_t *ss, uint8_t); void clear_delays(scene_state_t *ss); +void tele_tr_pulse_end(scene_state_t *ss, uint8_t i); + const char *tele_error(error_t); #endif diff --git a/src/teletype_io.h b/src/teletype_io.h index b1dffe0d..006eaf93 100644 --- a/src/teletype_io.h +++ b/src/teletype_io.h @@ -23,6 +23,9 @@ extern void tele_metro_updated(void); extern void tele_metro_reset(void); extern void tele_tr(uint8_t i, int16_t v); +extern void tele_tr_pulse(uint8_t i, int16_t time); +extern void tele_tr_pulse_clear(uint8_t i); +extern void tele_tr_pulse_time(uint8_t i, int16_t time); extern void tele_cv(uint8_t i, int16_t v, uint8_t s); extern void tele_cv_slew(uint8_t i, int16_t v); diff --git a/tests/main.c b/tests/main.c index d83d3661..b2970667 100644 --- a/tests/main.c +++ b/tests/main.c @@ -17,6 +17,9 @@ uint32_t tele_get_ticks() { void tele_metro_updated() {} void tele_metro_reset() {} void tele_tr(uint8_t i, int16_t v) {} +void tele_tr_pulse(uint8_t i, int16_t time) {} +void tele_tr_pulse_clear(uint8_t i) {} +void tele_tr_pulse_time(uint8_t i, int16_t time) {} void tele_cv(uint8_t i, int16_t v, uint8_t s) {} void tele_cv_slew(uint8_t i, int16_t v) {} void tele_update_adc(uint8_t force) {}