From 80de5c2e24056d38e49c4aeff4f84a299165d933 Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 17 Mar 2020 17:20:43 +0100 Subject: Debugging signal capture subsystem --- controller/fw/src/adc.c | 2 + controller/fw/src/con_usart.h | 3 +- controller/fw/src/main.c | 19 +++- controller/fw/src/serial.c | 29 +++++ controller/fw/src/serial.h | 2 + lab-windows/scratch.ipynb | 251 +++++++++++++++++++++++++++++++++++++++++- 6 files changed, 300 insertions(+), 6 deletions(-) diff --git a/controller/fw/src/adc.c b/controller/fw/src/adc.c index 81f5ac1..027fd11 100644 --- a/controller/fw/src/adc.c +++ b/controller/fw/src/adc.c @@ -6,6 +6,7 @@ #include "adc.h" #include "sr_global.h" +static unsigned int adc_overruns = 0; uint16_t adc_fft_buf[2][FMEAS_FFT_LEN]; volatile int adc_fft_buf_ready_idx = -1; @@ -93,6 +94,7 @@ void DMA2_Stream0_IRQHandler(void) { GPIOA->BSRR = 1<<11<<16; /* clear all flags */ adc_dma->LIFCR = isr<BSRR = 1<<11; - adc_fft_buf_ready_idx = !adc_fft_buf_ready_idx; /* DEBUG */ - memcpy(adc_fft_buf[!adc_fft_buf_ready_idx], adc_fft_buf[adc_fft_buf_ready_idx] + FMEAS_FFT_LEN/2, sizeof(adc_fft_buf[0][0]) * FMEAS_FFT_LEN/2); + //adc_fft_buf_ready_idx = !adc_fft_buf_ready_idx; /* DEBUG */ + //DEBUG: + //memcpy(adc_fft_buf[!adc_fft_buf_ready_idx], adc_fft_buf[adc_fft_buf_ready_idx] + FMEAS_FFT_LEN/2, sizeof(adc_fft_buf[0][0]) * FMEAS_FFT_LEN/2); + + for (int i=0; i<168*1000*2; i++) + asm volatile ("nop"); + /* BEGIN DEBUG */ + con_printf_blocking("\r\n%06d: ", freq_sample_ts); + int old_idx = adc_fft_buf_ready_idx; + for (int i=0; iBSRR = 1<<11<<16; + continue; + /* END DEBUG */ GPIOA->BSRR = 1<<11; float out; diff --git a/controller/fw/src/serial.c b/controller/fw/src/serial.c index 71e1868..2d09f80 100644 --- a/controller/fw/src/serial.c +++ b/controller/fw/src/serial.c @@ -11,6 +11,8 @@ static void usart_schedule_dma(volatile struct usart_desc *us); static void usart_dma_reset(volatile struct usart_desc *us); static void usart_putc_nonblocking_tpf(void *us, char c); +static void usart_wait_chunk_free(volatile struct usart_desc *us); +static void usart_putc_blocking_tpf(void *us, char c); void usart_dma_reset(volatile struct usart_desc *us) { us->tx_buf.xfr_start = -1; @@ -117,10 +119,24 @@ int usart_putc_nonblocking(volatile struct usart_desc *us, char c) { return 0; } +int usart_putc_blocking(volatile struct usart_desc *us, char c) { + volatile struct dma_tx_buf *buf = &us->tx_buf; + + while (buf->wr_pos == buf->xfr_start) + ; + + buf->data[buf->wr_pos] = c; + buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->data); + return 0; +} + void usart_putc_nonblocking_tpf(void *us, char c) { usart_putc_nonblocking((struct usart_desc *)us, c); } +void usart_putc_blocking_tpf(void *us, char c) { + usart_putc_blocking((struct usart_desc *)us, c); +} int usart_send_chunk_nonblocking(volatile struct usart_desc *us, const char *chunk, size_t chunk_len) { for (size_t i=0; itx_buf.chunk_end[us->tx_buf.wr_idx] != -1) + ; +} + int usart_flush(volatile struct usart_desc *us) { /* Find a free slot for this chunk */ if (us->tx_buf.chunk_end[us->tx_buf.wr_idx] != -1) { @@ -151,3 +172,11 @@ int usart_printf(volatile struct usart_desc *us, char *fmt, ...) { return usart_flush(us); } +int usart_printf_blocking(volatile struct usart_desc *us, char *fmt, ...) { + va_list va; + va_start(va, fmt); + tfp_format((void *)us, usart_putc_blocking_tpf, fmt, va); + usart_wait_chunk_free(us); + return usart_flush(us); +} + diff --git a/controller/fw/src/serial.h b/controller/fw/src/serial.h index 02f6f5d..bad4374 100644 --- a/controller/fw/src/serial.h +++ b/controller/fw/src/serial.h @@ -74,9 +74,11 @@ struct usart_desc { void usart_dma_init(volatile struct usart_desc *us, unsigned int baudrate); int usart_send_chunk_nonblocking(volatile struct usart_desc *us, const char *chunk, size_t chunk_len); int usart_putc_nonblocking(volatile struct usart_desc *us, char c); +int usart_putc_blocking(volatile struct usart_desc *us, char c); void usart_dma_stream_irq(volatile struct usart_desc *us); int usart_flush(volatile struct usart_desc *us); int usart_printf(volatile struct usart_desc *us, char *fmt, ...); +int usart_printf_blocking(volatile struct usart_desc *us, char *fmt, ...); #endif // __SERIAL_H__ diff --git a/lab-windows/scratch.ipynb b/lab-windows/scratch.ipynb index 93a11fe..da795fd 100644 --- a/lab-windows/scratch.ipynb +++ b/lab-windows/scratch.ipynb @@ -2,12 +2,14 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import json\n", "import csv\n", + "import re\n", + "import math\n", "\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", @@ -18,13 +20,258 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "%matplotlib widget" ] }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [], + "source": [ + "def read_freq_log(fn):\n", + " with open(fn) as f:\n", + " def parse_freq(f):\n", + " try:\n", + " return float(f)\n", + " except:\n", + " return 0\n", + " freqs = np.trim_zeros(np.array([ parse_freq(line.split()[1]) for line in f.readlines() if re.match('\\d+: .*', line) ]))\n", + " return freqs[np.nonzero(freqs)]" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + ":1: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).\n", + " fig, axs = plt.subplots(2, 2, figsize=(15, 9))\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c040d7b8285a4444abc23ec0ef8c0d45", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(2, 2, figsize=(15, 9))\n", + "ax1, ax2, ax3, ax4 = axs.flatten()\n", + "\n", + "freqs_mod, freqs_clean, freqs_clean_gnd = read_freq_log('/mnt/c/Users/jaseg/shared/dsss_test.log'), read_freq_log('/mnt/c/Users/jaseg/shared/dsss_test_50hz_clean.log'), read_freq_log('/mnt/c/Users/jaseg/shared/dsss_test_50hz_clean_gndtest.log')\n", + "\n", + "ax1.plot(freqs_mod)\n", + "ax1.grid()\n", + "\n", + "ax2.plot(freqs_clean)\n", + "ax2.grid()\n", + "\n", + "ax4.plot(freqs_clean_gnd)\n", + "ax4.grid()\n", + "\n", + "w = 512\n", + "\n", + "ax3.psd(freqs_mod[:80000], w, 100/128 * 10)\n", + "ax3.psd(freqs_clean[:80000], w, 100/128 * 10)\n", + "ax3.psd(freqs_clean_gnd[:80000], w, 100/128 * 10)\n", + "None" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def read_raw_log(fn):\n", + " with open(fn) as f:\n", + " vals = np.array([ int(x, 16) for line in f for x in line.partition(':')[2].split() ])\n", + " return vals" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f5f37f4970ae4d0fb5677c55045c6ebf", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(2, 2, figsize=(15, 9))\n", + "ax1, ax2, ax3, ax4 = axs.flatten()\n", + "\n", + "raw_50hz, raw_silence = read_raw_log('/mnt/c/Users/jaseg/shared/rawlog_50hz_clean.log'), read_raw_log('/mnt/c/Users/jaseg/shared/rawlog_silence_clean3.log')\n", + "\n", + "ax1.plot(raw_50hz)\n", + "ax1.grid()\n", + "#for x in range(0, len(raw_50hz), 128):\n", + "# ax1.axvline(x, color='red', alpha=0.3)\n", + "\n", + "ax2.plot(raw_silence)\n", + "ax2.grid()\n", + "#for x in range(0, len(raw_silence), 128):\n", + "# ax2.axvline(x, color='red', alpha=0.3)\n", + "\n", + "w = 16384\n", + "\n", + "ax3.psd(raw_50hz, w, 1e3)\n", + "\n", + "ax4.psd(raw_silence, w, 1e3)\n", + "None" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "eba72dea09bc45ff9de68cb22b352fb3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(figsize=(12, 6))\n", + "\n", + "raw_silence = read_raw_log('/mnt/c/Users/jaseg/shared/rawlog_silence_clean.log')\n", + "raw_silence2 = read_raw_log('/mnt/c/Users/jaseg/shared/rawlog_silence_clean3.log')\n", + "\n", + "raw_silence = raw_silence.reshape([-1, 128])\n", + "le_mean = raw_silence.mean(axis=0)\n", + "ax.plot(le_mean - np.mean(le_mean))\n", + "\n", + "raw_silence2 = raw_silence2.reshape([-1, 128])\n", + "le_mean2 = raw_silence2.mean(axis=0)\n", + "ax.plot(le_mean2 - np.mean(le_mean2))\n", + "ax.grid()" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + ":1: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).\n", + " fig, axs = plt.subplots(2, 2, figsize=(15, 9))\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d9143b226974466aaec05a70592ac69e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(2, 2, figsize=(15, 9))\n", + "ax1, ax2, ax3, ax4 = axs.flatten()\n", + "\n", + "raw_d, raw_e = read_raw_log('/mnt/c/Users/jaseg/shared/rawlog_test_d.log'), read_raw_log('/mnt/c/Users/jaseg/shared/rawlog_test_e.log')\n", + "\n", + "ax1.plot(raw_d)\n", + "ax1.grid()\n", + "\n", + "ax2.plot(raw_e)\n", + "ax2.grid()\n", + "\n", + "w = 16384\n", + "\n", + "ax3.psd(raw_d, w, 1e3)\n", + "ax4.psd(raw_e, w, 1e3)\n", + "#ax3.psd(raw_silence, w, 1e3)\n", + "None" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + ":1: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).\n", + " fig, ax = plt.subplots(figsize=(9, 5))\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "48b1d8b994594af79c3dca2bf9a6fb41", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(figsize=(9, 5))\n", + "\n", + "raw_c = read_raw_log('/mnt/c/Users/jaseg/shared/rawlog_test_c.log')\n", + "\n", + "ax.plot(raw_c[1000:2000])\n", + "ax.grid()" + ] + }, { "cell_type": "code", "execution_count": 25, -- cgit