diff --git a/dsp_lib.h b/dsp_lib.h index 066b1a4..8962636 100644 --- a/dsp_lib.h +++ b/dsp_lib.h @@ -19,6 +19,9 @@ class DDS { phase += ftw; // wraps on overflow return sin(phase*2.0*M_PI/(double)PHASE_MAX); } + phase_t get_phase() { + return phase; + } }; template @@ -60,4 +63,7 @@ class Lockin { phase -= ftw; // wraps on underflow return lpf.update(rotated); } + phase_t get_phase() { + return phase; + } }; diff --git a/sndlock.cpp b/sndlock.cpp index a6576f1..518b140 100644 --- a/sndlock.cpp +++ b/sndlock.cpp @@ -23,17 +23,26 @@ #define SND_BUFLEN 4096 static std::atomic shutdown_threads; + static std::atomic frequency[SND_PCHAN]; static std::atomic amplitude[SND_PCHAN]; #define HIST_DEPTH 512 +static std::atomic peak; +static std::atomic clipped; +static std::atomic in_wave_trigger; +static std::mutex in_wave_mutex; +static float in_wave[HIST_DEPTH]; + static std::atomic lpf_bandwidth[SND_PCHAN]; static std::mutex li_hist_mutex; static std::atomic li_hist_pause[SND_PCHAN]; static float li_hist_mag[SND_PCHAN][HIST_DEPTH]; static float li_hist_phase[SND_PCHAN][HIST_DEPTH]; +enum class InWaveState { delay, wait_trigger, capturing }; + static void dsp_thread() { struct sio_hdl *hdl; @@ -78,6 +87,14 @@ static void dsp_thread() FIFO ftw_fifo[SND_PCHAN]; + int clipped_count = 0; + double peak_running = 0.0; + int peak_count = 0; + phase_t last_trig_phase = 0; + InWaveState in_wave_state = InWaveState::delay; + int in_wave_count = 0; + float in_wave_buf[HIST_DEPTH]; + Lockin<4> lockin[SND_PCHAN]; for(int i=0;i lockin_out = lockin[i].update(sample); + for(int i=0;i 0.99*pow(2.0, SND_BITS-1)) + // display the clipped indicator for about one second + clipped_count = SND_RATE; + } + if(clipped_count > 0) { + clipped_count--; + clipped = true; + } else + clipped = false; - if(!li_hist_pause[i]) { - li_count[i]++; - if(li_count[i] == 200) { - li_count[i] = 0; + double sample_abs = std::abs(sample); + if(sample_abs > peak_running) + peak_running = sample_abs; + peak_count++; + if(peak_count == SND_RATE/10) { + peak_count = 0; + peak = peak_running/(pow(2.0, SND_BITS-1)*SND_RCHAN); + peak_running = 0.0; + } + + phase_t trig_phase = lockin[in_wave_trigger].get_phase(); + bool trigger = trig_phase > last_trig_phase; + last_trig_phase = trig_phase; + switch(in_wave_state) { + case InWaveState::delay: + in_wave_count++; + if(in_wave_count == SND_RATE/10) + in_wave_state = InWaveState::wait_trigger; + break; + case InWaveState::wait_trigger: + if(trigger) { + in_wave_count = 0; + in_wave_state = InWaveState::capturing; + } + break; + case InWaveState::capturing: + in_wave_buf[in_wave_count++] = sample/(pow(2.0, SND_BITS-1)*SND_RCHAN); + if(in_wave_count == HIST_DEPTH) { + { + std::lock_guard guard(in_wave_mutex); + std::memcpy(in_wave, in_wave_buf, sizeof(in_wave)); + } + in_wave_count = 0; + in_wave_state = InWaveState::delay; + } + break; + } + + for(int j=0;j lockin_out = lockin[j].update(sample); + + if(!li_hist_pause[j]) { + li_count[j]++; + if(li_count[j] == 200) { + li_count[j] = 0; std::lock_guard guard(li_hist_mutex); - std::memmove(&li_hist_mag[i][0], &li_hist_mag[i][1], (HIST_DEPTH-1)*sizeof(float)); - li_hist_mag[i][HIST_DEPTH-1] = std::abs(lockin_out); - std::memmove(&li_hist_phase[i][0], &li_hist_phase[i][1], (HIST_DEPTH-1)*sizeof(float)); - li_hist_phase[i][HIST_DEPTH-1] = std::arg(lockin_out); + std::memmove(&li_hist_mag[j][0], &li_hist_mag[j][1], (HIST_DEPTH-1)*sizeof(float)); + li_hist_mag[j][HIST_DEPTH-1] = std::abs(lockin_out); + std::memmove(&li_hist_phase[j][0], &li_hist_phase[j][1], (HIST_DEPTH-1)*sizeof(float)); + li_hist_phase[j][HIST_DEPTH-1] = std::arg(lockin_out); } } } + } } if(sio_eof(hdl)) { @@ -243,6 +310,31 @@ int main(int argc, char* argv[]) amplitude[i] = amplitude_l; } } + if(ImGui::CollapsingHeader("Input monitor")) { + ImGui::AlignTextToFramePadding(); + ImGui::Text("level:"); + ImGui::SameLine(); + ImGui::ProgressBar((float)peak, ImVec2(30.0f*ImGui::GetFontSize(), 0.0f)); + if(clipped) { + ImGui::SameLine(); + ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "clipped!"); + } + ImGui::AlignTextToFramePadding(); + ImGui::Text("trigger:"); + ImGui::SameLine(); + int in_wave_trigger_l = in_wave_trigger; + char str[64]; + for(int i=0;i guard(in_wave_mutex); + ImGui::PlotLines("waveform", in_wave, HIST_DEPTH, 0, 0, -1.0f, 1.0f, ImVec2(0.0f, 200.0f)); + } + } if(ImGui::CollapsingHeader("Demodulation", ImGuiTreeNodeFlags_DefaultOpen)) { for(int i=0;i