TDR feature

This commit is contained in:
cho45 2019-09-10 22:39:20 +09:00
parent 35dfd691a2
commit 889d675836
5 changed files with 168 additions and 2 deletions

78
fft.h Normal file
View file

@ -0,0 +1,78 @@
/*
* fft.h is Based on
* Free FFT and convolution (C)
*
* Copyright (c) 2019 Project Nayuki. (MIT License)
* https://www.nayuki.io/page/free-small-fft-in-multiple-languages
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#include <math.h>
#include <stdint.h>
static uint8_t reverse_bits(uint8_t x, int n) {
uint8_t result = 0;
for (int i = 0; i < n; i++, x >>= 1)
result = (result << 1) | (x & 1U);
return result;
}
/***
* dir = forward: 0, inverse: 1
*/
void fft(float array[][2], uint8_t n, uint8_t dir) {
int levels = 0; // Compute levels = floor(log2(n))
for (uint8_t temp = n; temp > 1U; temp >>= 1)
levels++;
uint8_t real = dir & 1;
uint8_t imag = ~real & 1;
for (uint8_t i = 0; i < n; i++) {
uint8_t j = reverse_bits(i, levels);
if (j > i) {
float temp = array[i][real];
array[i][real] = array[j][real];
array[j][real] = temp;
temp = array[i][imag];
array[i][imag] = array[j][imag];
array[j][imag] = temp;
}
}
// Cooley-Tukey decimation-in-time radix-2 FFT
for (uint8_t size = 2; size <= n; size *= 2) {
uint8_t halfsize = size / 2;
uint8_t tablestep = n / size;
for (uint8_t i = 0; i < n; i += size) {
for (uint8_t j = i, k = 0; j < i + halfsize; j++, k += tablestep) {
uint8_t l = j + halfsize;
float tpre = array[l][real] * cos(2 * M_PI * k / n) + array[l][imag] * sin(2 * M_PI * k / n);
float tpim = -array[l][real] * sin(2 * M_PI * k / n) + array[l][imag] * cos(2 * M_PI * k / n);
array[l][real] = array[j][real] - tpre;
array[l][imag] = array[j][imag] - tpim;
array[j][real] += tpre;
array[j][imag] += tpim;
}
}
if (size == n) // Prevent overflow in 'size *= 2'
break;
}
}

34
main.c
View file

@ -23,6 +23,7 @@
#include "usbcfg.h"
#include "si5351.h"
#include "nanovna.h"
#include "fft.h"
#include <chprintf.h>
#include <shell.h>
@ -36,6 +37,7 @@
static void apply_error_term(void);
static void apply_error_term_at(int i);
static void cal_interpolate(int s);
static void transform_domain(void);
void sweep(void);
@ -54,6 +56,8 @@ int8_t redraw_requested = FALSE;
int8_t stop_the_world = FALSE;
int16_t vbat = 0;
uint8_t domain = DOMAIN_TIME;
uint8_t tdrfunc = TDR_IMPULSE;
static THD_WORKING_AREA(waThread1, 640);
static THD_FUNCTION(Thread1, arg)
{
@ -82,6 +86,7 @@ static THD_FUNCTION(Thread1, arg)
draw_battery_status();
}
transform_domain();
/* calculate trace coordinates */
plot_into_index(measured);
/* plot trace as raster */
@ -107,6 +112,35 @@ toggle_sweep(void)
sweep_enabled = !sweep_enabled;
}
static
void
transform_domain(void)
{
if (domain != DOMAIN_TIME) return; // nothing to do for freq domain
// use spi_buffer as temporary buffer
// and calculate ifft for time domain
float* tmp = (float*)spi_buffer;
for (int ch = 0; ch < 2; ch++) {
for (int i = 0; i < 128; i++) {
tmp[i*2+0] = 0.0;
tmp[i*2+1] = 0.0;
}
memcpy(spi_buffer, measured[ch], sizeof(measured[0]));
fft((float(*)[2])tmp, 128, 1);
memcpy(measured[ch], spi_buffer, sizeof(measured[0]));
for (int i = 0; i < 101; i++) {
measured[ch][i][0] /= 128.0;
measured[ch][i][1] /= 128.0;
}
if (tdrfunc == TDR_STEP) {
for (int i = 1; i < 101; i++) {
measured[ch][i][0] += measured[ch][i-1][0];
measured[ch][i][1] += measured[ch][i-1][1];
}
}
}
}
static void cmd_pause(BaseSequentialStream *chp, int argc, char *argv[])
{
(void)chp;

View file

@ -22,8 +22,20 @@
/*
* main.c
*/
extern float measured[2][101][2];
enum {
DOMAIN_FREQ, DOMAIN_TIME
};
enum {
TDR_IMPULSE, TDR_STEP
};
extern uint8_t domain;
extern uint8_t tdrfunc;
#define CAL_LOAD 0
#define CAL_OPEN 1
#define CAL_SHORT 2

11
plot.c
View file

@ -1367,8 +1367,15 @@ cell_draw_marker_info(int m, int n, int w, int h)
chsnprintf(buf, sizeof buf, "%d:", active_marker + 1);
cell_drawstring_5x7(w, h, buf, xpos, ypos, 0xffff);
xpos += 16;
frequency_string(buf, sizeof buf, frequencies[idx]);
cell_drawstring_5x7(w, h, buf, xpos, ypos, 0xffff);
if (domain == DOMAIN_FREQ) {
frequency_string(buf, sizeof buf, frequencies[idx]);
cell_drawstring_5x7(w, h, buf, xpos, ypos, 0xffff);
} else {
#define SPEED_OF_LIGHT 299792458
float distance = ((float)idx * (float)SPEED_OF_LIGHT) / ( (float)(frequencies[1] - frequencies[0]) * 128.0 * 2.0);
chsnprintf(buf, sizeof buf, "%f m", distance);
cell_drawstring_5x7(w, h, buf, xpos, ypos, 0xffff);
}
// draw marker delta
if (previous_marker >= 0 && active_marker != previous_marker && markers[previous_marker].enabled) {

35
ui.c
View file

@ -664,6 +664,24 @@ menu_channel_cb(int item)
ui_mode_normal();
}
static void
menu_tdr_cb(int item)
{
switch (item) {
case 0:
domain = (domain == DOMAIN_FREQ) ? DOMAIN_TIME : DOMAIN_FREQ;
break;
case 1:
tdrfunc = TDR_IMPULSE;
break;
case 2:
tdrfunc = TDR_STEP;
break;
}
ui_mode_normal();
}
static void
choose_active_marker(void)
{
@ -874,11 +892,20 @@ const menuitem_t menu_channel[] = {
{ MT_NONE, NULL, NULL } // sentinel
};
const menuitem_t menu_tdr[] = {
{ MT_CALLBACK, "TDR MODE", menu_tdr_cb },
{ MT_CALLBACK, "IMPULSE", menu_tdr_cb },
{ MT_CALLBACK, "STEP", menu_tdr_cb },
{ MT_CANCEL, S_LARROW" BACK", NULL },
{ MT_NONE, NULL, NULL } // sentinel
};
const menuitem_t menu_display[] = {
{ MT_SUBMENU, "TRACE", menu_trace },
{ MT_SUBMENU, "FORMAT", menu_format },
{ MT_SUBMENU, "SCALE", menu_scale },
{ MT_SUBMENU, "CHANNEL", menu_channel },
{ MT_SUBMENU, "TDR", menu_tdr },
{ MT_CANCEL, S_LARROW" BACK", NULL },
{ MT_NONE, NULL, NULL } // sentinel
};
@ -1235,6 +1262,14 @@ menu_item_modify_attribute(const menuitem_t *menu, int item,
*bg = 0x0000;
*fg = 0xffff;
}
} else if (menu == menu_tdr) {
if ((item == 0 && domain == DOMAIN_TIME)
|| (item == 1 && tdrfunc == TDR_IMPULSE)
|| (item == 2 && tdrfunc == TDR_STEP)
) {
*bg = 0x0000;
*fg = 0xffff;
}
}
}