diff --git a/daisy/scope/osclsk.cpp b/daisy/scope/osclsk.cpp index dc585b8..1616842 100644 --- a/daisy/scope/osclsk.cpp +++ b/daisy/scope/osclsk.cpp @@ -80,8 +80,6 @@ osclsk_scope::prep(void) case osc_state::READY: return (0); case osc_state::RENDER_DONE: - block_fill = 0; - block_fill_nsamp = 0; st = osc_state::READY; return (0); @@ -95,11 +93,7 @@ osclsk_scope::trig(void) { switch (st) { case osc_state::READY: - trig_lkb_idx = 0; - trig_lkb_idx_nsamp = 0; - trig_num = 0; - trig_state = osc_trig_state::READY; st = osc_state::TRIGGER; @@ -162,11 +156,23 @@ osclsk_scope::sample(const float *sig, size_t num) } } - if (block_fill >= OSCLSK_BLOCK_LEN) + if (block_fill >= OSCLSK_BLOCK_LEN) { st = osc_state::SAMPLE_DONE; + /* use the leftover samples to sample the trig lookback + * data buffer. we reset the nsamp for the current + * lookback buffer index to get a clean slate */ + trig_lkb_idx_nsamp = 0; + trig_lkb_num = 0; + sample_trigger(&sig[i], num - i); + } + break; case osc_state::TRIGGER: + case osc_state::SAMPLE_DONE: + case osc_state::RENDER: + case osc_state::RENDER_DONE: + case osc_state::READY: sample_trigger(sig, num); break; default: @@ -174,13 +180,18 @@ osclsk_scope::sample(const float *sig, size_t num) } } - bool osclsk_scope::is_triggering(float sample) { switch (trig_mode) { case osc_trig_mode::RISING_EDGE: return (sample > trig_margin); + case osc_trig_mode::FALLING_EDGE: + return (sample < -trig_margin); + case osc_trig_mode::ABS_THRESHOLD: + return (std::abs(sample) > trig_margin); + case osc_trig_mode::INSTANT: + return (true); default: return (false); } @@ -191,10 +202,11 @@ osclsk_scope::trig_lkb_wr_block(void) { size_t lkb_i, n; - lkb_i = trig_lkb_idx > trig_lkb_amount ? - trig_lkb_idx - trig_lkb_amount : - OSCLSK_TRIG_LOOKBACK + trig_lkb_idx - trig_lkb_amount; + lkb_i = trig_lkb_idx >= trig_lkb_amount ? + trig_lkb_idx - (trig_lkb_amount) : + OSCLSK_TRIG_LOOKBACK + trig_lkb_idx - (trig_lkb_amount); + block_fill = 0; for (n = 0; n < trig_lkb_amount; n++) { block_y_max[block_fill] = trig_lkb_y_max[lkb_i]; block_y_min[block_fill] = trig_lkb_y_min[lkb_i]; @@ -216,7 +228,7 @@ osclsk_scope::sample_trigger(const float *sig, size_t num) { size_t i; - AC_PRECOND(st == osc_state::TRIGGER); + AC_PRECOND(st != osc_state::INIT && st != osc_state::SAMPLE); /* sample data in lookback buffers */ for (i = 0; i < num; i++) { @@ -238,38 +250,62 @@ osclsk_scope::sample_trigger(const float *sig, size_t num) trig_lkb_idx_nsamp = 0; } + trig_lkb_num = std::min(trig_lkb_num + 1, + OSCLSK_TRIG_LOOKBACK); + trig_lkb_idx = trig_lkb_idx & (OSCLSK_TRIG_LOOKBACK - 1); } - /* do triggering checks */ + + /* only do triggering checks in TRIGGER state and out lookback buffer is + * full enough */ + if (st != osc_state::TRIGGER || trig_lkb_num < trig_lkb_amount) + return; + + /* trigger needs to be in NO_TRIG before TRIG state for e.g. + * RISING_EDGE trigger mode */ for (i = 0; i < num; i++) { switch (trig_state) { case osc_trig_state::READY: - if (! is_triggering(sig[i])) { - trig_state = osc_trig_state::NO_TRIG; + switch (trig_mode) { + case osc_trig_mode::RISING_EDGE: + case osc_trig_mode::FALLING_EDGE: + case osc_trig_mode::ABS_THRESHOLD: + if (! is_triggering(sig[i])) { + trig_state = osc_trig_state::NO_TRIG; + } + break; + case osc_trig_mode::INSTANT: + trig_state = osc_trig_state::TRIGGERED; + break; } break; case osc_trig_state::NO_TRIG: if (is_triggering(sig[i])) { - trig_num = 0; + trig_num++; trig_state = osc_trig_state::TRIG; } break; case osc_trig_state::TRIG: if (is_triggering(sig[i])) { - if (++trig_num >= trig_num_req) { - trig_state = - osc_trig_state::TRIGGERED; - } + trig_num++; } else { trig_state = osc_trig_state::NO_TRIG; + trig_num = 0; } break; default: break; } + if (trig_num >= trig_num_req) { + trig_state = + osc_trig_state::TRIGGERED; + } + + if (trig_state == osc_trig_state::TRIGGERED) + break; } /* transfer lookback to actual block if triggered */ @@ -336,11 +372,11 @@ osclsk_scope::render_block(void) } for (render_idx = 0; render_idx < OSCLSK_BLOCK_LEN; render_idx++) { - screen_px_y_max[render_idx] = 1u + (uint16_t)( - OSCLSK_Y_MAX_PX * (.5f + block_y_max[render_idx]) + screen_px_y_max[render_idx] = (uint16_t)( + OSCLSK_Y_MAX_PX/2 * (1 - block_y_max[render_idx]) ); - screen_px_y_min[render_idx] = (uint16_t)( - OSCLSK_Y_MAX_PX * (.5f + block_y_min[render_idx]) + screen_px_y_min[render_idx] = 1u + (uint16_t)( + OSCLSK_Y_MAX_PX/2 * (1 - block_y_min[render_idx]) ); } @@ -359,9 +395,10 @@ osclsk_scope::render_block(void) case osc_state::RENDER: for (; render_idx < OSCLSK_BLOCK_LEN; render_idx++) { res = tft.async_hline_row_bg_fill(async_id, &bg, &fg, - screen_px_y_min[render_idx], - screen_px_y_max[render_idx], + screen_px_y_max[render_idx], // inverted + screen_px_y_min[render_idx], // inverted render_idx); + AC_ASSERT(res >= 0); if (res < 0) return (-1); if (res > 0) diff --git a/daisy/scope/osclsk.hpp b/daisy/scope/osclsk.hpp index 1814d28..8db91ce 100644 --- a/daisy/scope/osclsk.hpp +++ b/daisy/scope/osclsk.hpp @@ -15,7 +15,7 @@ using namespace daisy; #define OSCLSK_RATE_DIV 32 #define OSCLSK_BLOCK_LEN OSCLSK_SCREEN_XSZ -#define OSCLSK_TRIG_LOOKBACK 0x100 +#define OSCLSK_TRIG_LOOKBACK 0x100u #define OSCLSK_TFT_CMD_BUF_NSPLIT 4 @@ -40,6 +40,7 @@ struct osclsk_scope { RISING_EDGE, FALLING_EDGE, ABS_THRESHOLD, + INSTANT }; enum class osc_trig_state { @@ -61,6 +62,7 @@ struct osclsk_scope { float trig_lkb_y_min[OSCLSK_TRIG_LOOKBACK]; size_t trig_lkb_idx; int trig_lkb_idx_nsamp; + size_t trig_lkb_num; size_t trig_lkb_amount; float trig_margin; @@ -85,10 +87,10 @@ struct osclsk_scope { block_fill(0), block_fill_nsamp(0), trig_lkb_idx(0), trig_lkb_idx_nsamp(0), trig_lkb_amount(2), - trig_margin(.05f), trig_num(0), + trig_margin(.01f), trig_num(0), trig_num_req(2), trig_state(osc_trig_state::INIT), - trig_mode(osc_trig_mode::RISING_EDGE), + trig_mode(osc_trig_mode::INSTANT), render_idx(0) {}; int init(uint8_t *dma_buf, size_t dma_sz); diff --git a/daisy/scope/scope.cpp b/daisy/scope/scope.cpp index ec55604..d3a985a 100644 --- a/daisy/scope/scope.cpp +++ b/daisy/scope/scope.cpp @@ -163,13 +163,6 @@ main(void) while (true) { - read = scope_in.readable(); - read = (read <= sizeof(s)/sizeof(*s)) ? read : - sizeof(s)/sizeof(*s); - - scope_in.ImmediateRead(s, read); - - scope.sample(s, read); switch (scope.state()) { case osclsk_scope::osc_state::SAMPLE_DONE: @@ -188,6 +181,13 @@ main(void) break; } + read = scope_in.readable(); + read = (read <= sizeof(s)/sizeof(*s)) ? read : + sizeof(s)/sizeof(*s); + scope_in.ImmediateRead(s, read); + scope.sample(s, read); + + // if (--load_tick == 0) { // load_tick = LOAD_METER_TICKS; // // get the current load (smoothed value and peak values)