Merge pull request #126 from DiSlord/master

Fix screen artifacts, change start/stop or center/span mode set, remove Mutex use
This commit is contained in:
TT 2020-03-21 09:22:06 +09:00 committed by GitHub
commit a4821604a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 893 additions and 821 deletions

13
adc.c
View file

@ -79,20 +79,23 @@ uint16_t adc_single_read(uint32_t chsel)
int16_t adc_vbat_read(void) int16_t adc_vbat_read(void)
{ {
// 13.9 Temperature sensor and internal reference voltage
// VREFINT_CAL calibrated on 3.3V, need get value in mV
#define ADC_FULL_SCALE 3300 #define ADC_FULL_SCALE 3300
#define VREFINT_CAL (*((uint16_t*)0x1FFFF7BA)) #define VREFINT_CAL (*((uint16_t*)0x1FFFF7BA))
adc_stop(); adc_stop();
float vbat = 0;
float vrefint = 0;
ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN; ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN;
// VREFINT == ADC_IN17 // VREFINT == ADC_IN17
vrefint = adc_single_read(ADC_CHSELR_CHSEL17); uint32_t vrefint = adc_single_read(ADC_CHSELR_CHSEL17);
// VBAT == ADC_IN18 // VBAT == ADC_IN18
// VBATEN enables resiter devider circuit. It consume vbat power. // VBATEN enables resiter devider circuit. It consume vbat power.
vbat = adc_single_read(ADC_CHSELR_CHSEL18); uint32_t vbat = adc_single_read(ADC_CHSELR_CHSEL18);
ADC->CCR &= ~(ADC_CCR_VREFEN | ADC_CCR_VBATEN); ADC->CCR &= ~(ADC_CCR_VREFEN | ADC_CCR_VBATEN);
touch_start_watchdog(); touch_start_watchdog();
uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * vbat * 2 / (vrefint * ((1<<12)-1))); // vbat_raw = (3300 * 2 * vbat / 4095) * (VREFINT_CAL / vrefint)
// uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * (float)vbat * 2 / (vrefint * ((1<<12)-1)));
// For speed divide not on 4095, divide on 4096, get little error, but no matter
uint16_t vbat_raw = ((ADC_FULL_SCALE * 2 * vbat)>>12) * VREFINT_CAL / vrefint;
if (vbat_raw < 100) { if (vbat_raw < 100) {
// maybe D2 is not installed // maybe D2 is not installed
return -1; return -1;

View file

@ -183,7 +183,7 @@
* *
* @note The default is @p TRUE. * @note The default is @p TRUE.
*/ */
#define CH_CFG_USE_MUTEXES TRUE #define CH_CFG_USE_MUTEXES FALSE
/** /**
* @brief Enables recursive behavior on mutexes. * @brief Enables recursive behavior on mutexes.

4
fft.h
View file

@ -68,8 +68,8 @@ static void fft256(float array[][2], const uint8_t dir) {
uint16_t j, k; uint16_t j, k;
for (j = i, k = 0; j < i + halfsize; j++, k += tablestep) { for (j = i, k = 0; j < i + halfsize; j++, k += tablestep) {
uint16_t l = j + halfsize; uint16_t l = j + halfsize;
float tpre = array[l][real] * cos(2 * M_PI * k / 256) + array[l][imag] * sin(2 * M_PI * k / 256); float tpre = array[l][real] * cos(2 * VNA_PI * k / 256) + array[l][imag] * sin(2 * VNA_PI * k / 256);
float tpim = -array[l][real] * sin(2 * M_PI * k / 256) + array[l][imag] * cos(2 * M_PI * k / 256); float tpim = -array[l][real] * sin(2 * VNA_PI * k / 256) + array[l][imag] * cos(2 * VNA_PI * k / 256);
array[l][real] = array[j][real] - tpre; array[l][real] = array[j][real] - tpre;
array[l][imag] = array[j][imag] - tpim; array[l][imag] = array[j][imag] - tpim;
array[j][real] += tpre; array[j][real] += tpre;

View file

@ -23,8 +23,8 @@
uint16_t spi_buffer[SPI_BUFFER_SIZE]; uint16_t spi_buffer[SPI_BUFFER_SIZE];
// Default foreground & background colors // Default foreground & background colors
uint16_t foreground_color=DEFAULT_FG_COLOR; uint16_t foreground_color=0;
uint16_t background_color=DEFAULT_BG_COLOR; uint16_t background_color=0;
// Display width and height definition // Display width and height definition
#define ILI9341_WIDTH 320 #define ILI9341_WIDTH 320
@ -425,6 +425,23 @@ void ili9341_fill(int x, int y, int w, int h, int color)
dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD); dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD);
dmaStreamFlush(w * h); dmaStreamFlush(w * h);
} }
void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette){
uint32_t xx = __REV16(x|((x+w-1)<<16));
uint32_t yy = __REV16(y|((y+h-1)<<16));
send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx);
send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy);
send_command(ILI9341_MEMORY_WRITE, 0, NULL);
uint8_t *buf = (uint8_t *)spi_buffer;
int32_t len = w * h;
while (len-- > 0){
uint16_t color = palette[*buf++];
while (SPI_TX_IS_NOT_EMPTY);
SPI_WRITE_16BIT(color);
}
}
// Copy spi_buffer to region // Copy spi_buffer to region
void ili9341_bulk(int x, int y, int w, int h) void ili9341_bulk(int x, int y, int w, int h)
{ {

363
main.c
View file

@ -51,34 +51,38 @@ static BaseSequentialStream *shell_stream = (BaseSequentialStream *)&SDU1;
typedef void (*vna_shellcmd_t)(int argc, char *argv[]); typedef void (*vna_shellcmd_t)(int argc, char *argv[]);
#define VNA_SHELL_FUNCTION(command_name) static void command_name(int argc, char *argv[]) #define VNA_SHELL_FUNCTION(command_name) static void command_name(int argc, char *argv[])
// Shell command line buffer // Shell command line buffer, args, nargs, and function ptr
static char shell_line[VNA_SHELL_MAX_LENGTH]; static char shell_line[VNA_SHELL_MAX_LENGTH];
static char *shell_args[VNA_SHELL_MAX_ARGUMENTS + 1];
static uint16_t shell_nargs;
static volatile vna_shellcmd_t shell_function = 0;
//#define ENABLED_DUMP //#define ENABLED_DUMP
// Allow get threads debug info
//#define ENABLE_THREADS_COMMAND //#define ENABLE_THREADS_COMMAND
// RTC time not used
//#define ENABLE_TIME_COMMAND //#define ENABLE_TIME_COMMAND
// Enable vbat_offset command, allow change battery voltage correction in config
#define ENABLE_VBAT_OFFSET_COMMAND #define ENABLE_VBAT_OFFSET_COMMAND
// Info about NanoVNA, need fore soft
#define ENABLE_INFO_COMMAND #define ENABLE_INFO_COMMAND
// Enable color command, allow change config color for traces, grid, menu
#define ENABLE_COLOR_COMMAND
static void apply_error_term_at(int i); static void apply_error_term_at(int i);
static void apply_edelay_at(int i); static void apply_edelay_at(int i);
static void cal_interpolate(int s); static void cal_interpolate(int s);
void update_frequencies(void); static void update_frequencies(void);
void set_frequencies(uint32_t start, uint32_t stop, uint16_t points); static void set_frequencies(uint32_t start, uint32_t stop, uint16_t points);
static bool sweep(bool break_on_operation); static bool sweep(bool break_on_operation);
static void transform_domain(void); static void transform_domain(void);
static MUTEX_DECL(mutex);
#define DRIVE_STRENGTH_AUTO (-1) #define DRIVE_STRENGTH_AUTO (-1)
#define FREQ_HARMONICS (config.harmonic_freq_threshold) #define FREQ_HARMONICS (config.harmonic_freq_threshold)
#define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS) #define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS)
// Obsolete, always use interpolate // Obsolete, always use interpolate
#define cal_auto_interpolate TRUE #define cal_auto_interpolate TRUE
static int32_t frequency_offset = 5000;
static uint32_t frequency = 10000000;
static int8_t drive_strength = DRIVE_STRENGTH_AUTO; static int8_t drive_strength = DRIVE_STRENGTH_AUTO;
int8_t sweep_mode = SWEEP_ENABLE; int8_t sweep_mode = SWEEP_ENABLE;
volatile uint8_t redraw_request = 0; // contains REDRAW_XXX flags volatile uint8_t redraw_request = 0; // contains REDRAW_XXX flags
@ -107,22 +111,25 @@ static THD_FUNCTION(Thread1, arg)
while (1) { while (1) {
bool completed = false; bool completed = false;
if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) { if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) {
chMtxLock(&mutex);
completed = sweep(true); completed = sweep(true);
sweep_mode&=~SWEEP_ONCE; sweep_mode&=~SWEEP_ONCE;
chMtxUnlock(&mutex);
} else { } else {
__WFI(); __WFI();
} }
// Run Shell command in sweep thread
chMtxLock(&mutex); if (shell_function){
shell_function(shell_nargs-1, &shell_args[1]);
shell_function = 0;
osalThreadSleepMilliseconds(10);
continue;
}
// Process UI inputs
ui_process(); ui_process();
// Process collected data, calculate trace coordinates and plot only if scan completed
if (sweep_mode&SWEEP_ENABLE) { if (sweep_mode&SWEEP_ENABLE && completed) {
// calculate trace coordinates and plot only if scan completed
if (completed) {
if ((domain_mode & DOMAIN_MODE) == DOMAIN_TIME) if ((domain_mode & DOMAIN_MODE) == DOMAIN_TIME)
transform_domain(); transform_domain();
// Prepare draw graphics, cache all lines, mark screen cells for redraw
plot_into_index(measured); plot_into_index(measured);
redraw_request |= REDRAW_CELLS|REDRAW_BATTERY; redraw_request |= REDRAW_CELLS|REDRAW_BATTERY;
@ -134,10 +141,8 @@ static THD_FUNCTION(Thread1, arg)
} }
} }
} }
}
// plot trace and other indications as raster // plot trace and other indications as raster
draw_all(completed); // flush markmap only if scan completed to prevent remaining traces draw_all(completed); // flush markmap only if scan completed to prevent remaining traces
chMtxUnlock(&mutex);
} }
} }
@ -325,7 +330,7 @@ static int
adjust_gain(uint32_t newfreq) adjust_gain(uint32_t newfreq)
{ {
int new_order = newfreq / FREQ_HARMONICS; int new_order = newfreq / FREQ_HARMONICS;
int old_order = frequency / FREQ_HARMONICS; int old_order = si5351_getFrequency() / FREQ_HARMONICS;
if (new_order != old_order) { if (new_order != old_order) {
tlv320aic3204_set_gain(gain_table[new_order], gain_table[new_order]); tlv320aic3204_set_gain(gain_table[new_order], gain_table[new_order]);
return DELAY_GAIN_CHANGE; return DELAY_GAIN_CHANGE;
@ -340,9 +345,7 @@ int set_frequency(uint32_t freq)
if (ds == DRIVE_STRENGTH_AUTO) { if (ds == DRIVE_STRENGTH_AUTO) {
ds = freq > FREQ_HARMONICS ? SI5351_CLK_DRIVE_STRENGTH_8MA : SI5351_CLK_DRIVE_STRENGTH_2MA; ds = freq > FREQ_HARMONICS ? SI5351_CLK_DRIVE_STRENGTH_8MA : SI5351_CLK_DRIVE_STRENGTH_2MA;
} }
delay += si5351_set_frequency_with_offset(freq, frequency_offset, ds); delay += si5351_set_frequency_with_offset(freq, ds);
frequency = freq;
return delay; return delay;
} }
@ -364,13 +367,30 @@ static int32_t my_atoi(const char *p){
} }
// Convert string to uint32 // Convert string to uint32
// 0x - for hex radix
// 0o - for oct radix
// 0b - for bin radix
// default dec radix
uint32_t my_atoui(const char *p) { uint32_t my_atoui(const char *p) {
uint32_t value = 0; uint32_t value = 0, radix = 10, c;
uint32_t c;
if (*p == '+') p++; if (*p == '+') p++;
while ((c = *p++ - '0') < 10) if (*p == '0') {
value = value * 10 + c; switch (p[1]) {
return value; case 'x': radix = 16; break;
case 'o': radix = 8; break;
case 'b': radix = 2; break;
default: goto calculate;
}
p+=2;
}
calculate:
while (1) {
c = *p++ - '0';
// c = to_upper(*p) - 'A' + 10
if (c >= 'A' - '0') c = (c&(~0x20)) - ('A' - '0') + 10;
if (c >= radix) return value;
value = value * radix + c;
}
} }
double double
@ -446,8 +466,7 @@ VNA_SHELL_FUNCTION(cmd_offset)
shell_printf("usage: offset {frequency offset(Hz)}\r\n"); shell_printf("usage: offset {frequency offset(Hz)}\r\n");
return; return;
} }
frequency_offset = my_atoui(argv[0]); si5351_set_frequency_offset(my_atoi(argv[0]));
set_frequency(frequency);
} }
VNA_SHELL_FUNCTION(cmd_freq) VNA_SHELL_FUNCTION(cmd_freq)
@ -471,7 +490,7 @@ VNA_SHELL_FUNCTION(cmd_power)
return; return;
} }
drive_strength = my_atoi(argv[0]); drive_strength = my_atoi(argv[0]);
set_frequency(frequency); // set_frequency(frequency);
} }
#ifdef ENABLE_TIME_COMMAND #ifdef ENABLE_TIME_COMMAND
@ -496,7 +515,7 @@ VNA_SHELL_FUNCTION(cmd_dac)
"current value: %d\r\n", config.dac_value); "current value: %d\r\n", config.dac_value);
return; return;
} }
value = my_atoi(argv[0]); value = my_atoui(argv[0]);
config.dac_value = value; config.dac_value = value;
dacPutChannelX(&DACD2, 0, value); dacPutChannelX(&DACD2, 0, value);
} }
@ -718,6 +737,7 @@ config_t config = {
.trace_color = { DEFAULT_TRACE_1_COLOR, DEFAULT_TRACE_2_COLOR, DEFAULT_TRACE_3_COLOR, DEFAULT_TRACE_4_COLOR }, .trace_color = { DEFAULT_TRACE_1_COLOR, DEFAULT_TRACE_2_COLOR, DEFAULT_TRACE_3_COLOR, DEFAULT_TRACE_4_COLOR },
// .touch_cal = { 693, 605, 124, 171 }, // 2.4 inch LCD panel // .touch_cal = { 693, 605, 124, 171 }, // 2.4 inch LCD panel
.touch_cal = { 338, 522, 153, 192 }, // 2.8 inch LCD panel .touch_cal = { 338, 522, 153, 192 }, // 2.8 inch LCD panel
.freq_mode = FREQ_MODE_START_STOP,
.harmonic_freq_threshold = 300000000, .harmonic_freq_threshold = 300000000,
.vbat_offset = 500 .vbat_offset = 500
}; };
@ -783,13 +803,12 @@ bool sweep(bool break_on_operation)
int i, delay; int i, delay;
// blink LED while scanning // blink LED while scanning
palClearPad(GPIOC, GPIOC_LED); palClearPad(GPIOC, GPIOC_LED);
// Power stabilization after LED off, also align timings // Power stabilization after LED off, also align timings on i == 0
// Also touch made some
DSP_START(1); DSP_WAIT_READY;
for (i = 0; i < sweep_points; i++) { // 5300 for (i = 0; i < sweep_points; i++) { // 5300
if (frequencies[i] == 0) break;
delay = set_frequency(frequencies[i]); // 700 delay = set_frequency(frequencies[i]); // 700
tlv320aic3204_select(0); // 60 CH0:REFLECT tlv320aic3204_select(0); // 60 CH0:REFLECT, reset and begin measure
DSP_START(delay); // 1900 DSP_START(delay+((i==0)?1:0)); // 1900
//================================================ //================================================
// Place some code thats need execute while delay // Place some code thats need execute while delay
//================================================ //================================================
@ -797,7 +816,7 @@ bool sweep(bool break_on_operation)
// calculate reflection coefficient // calculate reflection coefficient
(*sample_func)(measured[0][i]); // 60 (*sample_func)(measured[0][i]); // 60
tlv320aic3204_select(1); // 60 CH1:TRANSMISSION tlv320aic3204_select(1); // 60 CH1:TRANSMISSION, reset and begin measure
DSP_START(DELAY_CHANNEL_CHANGE); // 1700 DSP_START(DELAY_CHANNEL_CHANGE); // 1700
//================================================ //================================================
// Place some code thats need execute while delay // Place some code thats need execute while delay
@ -825,9 +844,9 @@ VNA_SHELL_FUNCTION(cmd_scan)
{ {
uint32_t start, stop; uint32_t start, stop;
int16_t points = sweep_points; int16_t points = sweep_points;
int i;
if (argc != 2 && argc != 3) { if (argc < 2 || argc > 4) {
shell_printf("usage: scan {start(Hz)} {stop(Hz)} [points]\r\n"); shell_printf("usage: scan {start(Hz)} {stop(Hz)} [points] [outmask]\r\n");
return; return;
} }
@ -837,26 +856,33 @@ VNA_SHELL_FUNCTION(cmd_scan)
shell_printf("frequency range is invalid\r\n"); shell_printf("frequency range is invalid\r\n");
return; return;
} }
if (argc == 3) { if (argc >= 3) {
points = my_atoi(argv[2]); points = my_atoi(argv[2]);
if (points <= 0 || points > sweep_points) { if (points <= 0 || points > POINTS_COUNT) {
shell_printf("sweep points exceeds range\r\n"); shell_printf("sweep points exceeds range "define_to_STR(POINTS_COUNT)"\r\n");
return; return;
} }
} }
pause_sweep();
chMtxLock(&mutex);
set_frequencies(start, stop, points); set_frequencies(start, stop, points);
if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY)) if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY))
cal_interpolate(lastsaveid); cal_interpolate(lastsaveid);
pause_sweep();
sweep_mode|= SWEEP_ONCE; sweep(false);
chMtxUnlock(&mutex); // Output data after if set (faster data recive)
if (argc == 4){
// wait finishing sweep uint16_t mask = my_atoui(argv[3]);
while (sweep_mode&SWEEP_ONCE) if (mask)
chThdSleepMilliseconds(10); for (i = 0; i < points; i++){
if (mask&1)
shell_printf("%u ", frequencies[i]);
if (mask&2)
shell_printf("%f %f ", measured[0][i][0], measured[0][i][1]);
if (mask&4)
shell_printf("%f %f ", measured[1][i][0], measured[1][i][1]);
shell_printf("\r\n");
}
}
} }
static void static void
@ -887,7 +913,7 @@ update_marker_index(void)
} }
} }
void static void
set_frequencies(uint32_t start, uint32_t stop, uint16_t points) set_frequencies(uint32_t start, uint32_t stop, uint16_t points)
{ {
uint32_t i; uint32_t i;
@ -905,21 +931,16 @@ set_frequencies(uint32_t start, uint32_t stop, uint16_t points)
} }
} }
// disable at out of sweep range // disable at out of sweep range
for (; i < sweep_points; i++) for (; i < POINTS_COUNT; i++)
frequencies[i] = 0; frequencies[i] = 0;
} }
void static void
update_frequencies(void) update_frequencies(void)
{ {
uint32_t start, stop; uint32_t start, stop;
if (frequency0 < frequency1) { start = get_sweep_frequency(ST_START);
start = frequency0; stop = get_sweep_frequency(ST_STOP);
stop = frequency1;
} else {
start = frequency1;
stop = frequency0;
}
set_frequencies(start, stop, sweep_points); set_frequencies(start, stop, sweep_points);
// operation_requested|= OP_FREQCHANGE; // operation_requested|= OP_FREQCHANGE;
@ -930,28 +951,6 @@ update_frequencies(void)
update_grid(); update_grid();
} }
static void
freq_mode_startstop(void)
{
if (frequency0 > frequency1) {
ensure_edit_config();
uint32_t f = frequency1;
frequency1 = frequency0;
frequency0 = f;
}
}
static void
freq_mode_centerspan(void)
{
if (frequency0 <= frequency1) {
ensure_edit_config();
uint32_t f = frequency1;
frequency1 = frequency0;
frequency0 = f;
}
}
void void
set_sweep_frequency(int type, uint32_t freq) set_sweep_frequency(int type, uint32_t freq)
{ {
@ -963,11 +962,11 @@ set_sweep_frequency(int type, uint32_t freq)
if (freq > STOP_MAX) if (freq > STOP_MAX)
freq = STOP_MAX; freq = STOP_MAX;
ensure_edit_config();
switch (type) { switch (type) {
case ST_START: case ST_START:
freq_mode_startstop(); config.freq_mode&=~FREQ_MODE_CENTER_SPAN;
if (frequency0 != freq) { if (frequency0 != freq) {
ensure_edit_config();
frequency0 = freq; frequency0 = freq;
// if start > stop then make start = stop // if start > stop then make start = stop
if (frequency1 < freq) if (frequency1 < freq)
@ -975,9 +974,8 @@ set_sweep_frequency(int type, uint32_t freq)
} }
break; break;
case ST_STOP: case ST_STOP:
freq_mode_startstop(); config.freq_mode&=~FREQ_MODE_CENTER_SPAN;
if (frequency1 != freq) { if (frequency1 != freq) {
ensure_edit_config();
frequency1 = freq; frequency1 = freq;
// if start > stop then make start = stop // if start > stop then make start = stop
if (frequency0 > freq) if (frequency0 > freq)
@ -985,25 +983,23 @@ set_sweep_frequency(int type, uint32_t freq)
} }
break; break;
case ST_CENTER: case ST_CENTER:
freq_mode_centerspan(); config.freq_mode|=FREQ_MODE_CENTER_SPAN;
uint32_t center = FREQ_CENTER(); uint32_t center = frequency0/2 + frequency1/2;
if (center != freq) { if (center != freq) {
uint32_t span = FREQ_SPAN(); uint32_t span = frequency1 - frequency0;
ensure_edit_config();
if (freq < START_MIN + span/2) { if (freq < START_MIN + span/2) {
span = (freq - START_MIN) * 2; span = (freq - START_MIN) * 2;
} }
if (freq > STOP_MAX - span/2) { if (freq > STOP_MAX - span/2) {
span = (STOP_MAX - freq) * 2; span = (STOP_MAX - freq) * 2;
} }
frequency0 = freq + span/2; frequency0 = freq - span/2;
frequency1 = freq - span/2; frequency1 = freq + span/2;
} }
break; break;
case ST_SPAN: case ST_SPAN:
freq_mode_centerspan(); config.freq_mode|=FREQ_MODE_CENTER_SPAN;
if (frequency0 - frequency1 != freq) { if (frequency1 - frequency0 != freq) {
ensure_edit_config();
uint32_t center = frequency0/2 + frequency1/2; uint32_t center = frequency0/2 + frequency1/2;
if (center < START_MIN + freq/2) { if (center < START_MIN + freq/2) {
center = START_MIN + freq/2; center = START_MIN + freq/2;
@ -1011,14 +1007,13 @@ set_sweep_frequency(int type, uint32_t freq)
if (center > STOP_MAX - freq/2) { if (center > STOP_MAX - freq/2) {
center = STOP_MAX - freq/2; center = STOP_MAX - freq/2;
} }
frequency1 = center - freq/2; frequency0 = center - freq/2;
frequency0 = center + freq/2; frequency1 = center + freq/2;
} }
break; break;
case ST_CW: case ST_CW:
freq_mode_centerspan(); config.freq_mode|=FREQ_MODE_CENTER_SPAN;
if (frequency0 != freq || frequency1 != freq) { if (frequency0 != freq || frequency1 != freq) {
ensure_edit_config();
frequency0 = freq; frequency0 = freq;
frequency1 = freq; frequency1 = freq;
} }
@ -1032,22 +1027,14 @@ set_sweep_frequency(int type, uint32_t freq)
uint32_t uint32_t
get_sweep_frequency(int type) get_sweep_frequency(int type)
{ {
if (frequency0 <= frequency1) { // Obsolete, ensure correct start/stop, start always must be < stop
if (frequency0>frequency1) {uint32_t t=frequency0; frequency0=frequency1; frequency1=t;}
switch (type) { switch (type) {
case ST_START: return frequency0; case ST_START: return frequency0;
case ST_STOP: return frequency1; case ST_STOP: return frequency1;
case ST_CENTER: return frequency0/2 + frequency1/2; case ST_CENTER: return frequency0/2 + frequency1/2;
case ST_SPAN: return frequency1 - frequency0; case ST_SPAN: return frequency1 - frequency0;
case ST_CW: return frequency0/2 + frequency1/2; case ST_CW: return frequency0;
}
} else {
switch (type) {
case ST_START: return frequency1;
case ST_STOP: return frequency0;
case ST_CENTER: return frequency0/2 + frequency1/2;
case ST_SPAN: return frequency0 - frequency1;
case ST_CW: return frequency0/2 + frequency1/2;
}
} }
return 0; return 0;
} }
@ -1055,7 +1042,7 @@ get_sweep_frequency(int type)
VNA_SHELL_FUNCTION(cmd_sweep) VNA_SHELL_FUNCTION(cmd_sweep)
{ {
if (argc == 0) { if (argc == 0) {
shell_printf("%d %d %d\r\n", frequency0, frequency1, sweep_points); shell_printf("%d %d %d\r\n", get_sweep_frequency(ST_START), get_sweep_frequency(ST_STOP), sweep_points);
return; return;
} else if (argc > 3) { } else if (argc > 3) {
goto usage; goto usage;
@ -1125,7 +1112,7 @@ adjust_ed(void)
// prepare 1/s11ao to avoid dividing complex // prepare 1/s11ao to avoid dividing complex
float c = 1000e-15; float c = 1000e-15;
float z0 = 50; float z0 = 50;
//float z = 2 * M_PI * frequencies[i] * c * z0; //float z = 2 * VNA_PI * frequencies[i] * c * z0;
float z = 0.02; float z = 0.02;
cal_data[ETERM_ED][i][0] += z; cal_data[ETERM_ED][i][0] += z;
} }
@ -1143,7 +1130,7 @@ eterm_calc_es(void)
float c = 50e-15; float c = 50e-15;
//float c = 1.707e-12; //float c = 1.707e-12;
float z0 = 50; float z0 = 50;
float z = 2 * M_PI * frequencies[i] * c * z0; float z = 2 * VNA_PI * frequencies[i] * c * z0;
float sq = 1 + z*z; float sq = 1 + z*z;
float s11aor = (1 - z*z) / sq; float s11aor = (1 - z*z) / sq;
float s11aoi = 2*z / sq; float s11aoi = 2*z / sq;
@ -1279,7 +1266,7 @@ static void apply_error_term_at(int i)
static void apply_edelay_at(int i) static void apply_edelay_at(int i)
{ {
float w = 2 * M_PI * electrical_delay * frequencies[i] * 1E-12; float w = 2 * VNA_PI * electrical_delay * frequencies[i] * 1E-12;
float s = sin(w); float s = sin(w);
float c = cos(w); float c = cos(w);
float real = measured[0][i][0]; float real = measured[0][i][0];
@ -1296,35 +1283,20 @@ void
cal_collect(int type) cal_collect(int type)
{ {
ensure_edit_config(); ensure_edit_config();
int dst, src;
switch (type) { switch (type) {
case CAL_LOAD: case CAL_LOAD: cal_status|= CALSTAT_LOAD; dst = CAL_LOAD; src = 0; break;
cal_status |= CALSTAT_LOAD; case CAL_OPEN: cal_status|= CALSTAT_OPEN; dst = CAL_OPEN; src = 0; cal_status&= ~(CALSTAT_ES|CALSTAT_APPLY); break;
memcpy(cal_data[CAL_LOAD], measured[0], sizeof measured[0]); case CAL_SHORT: cal_status|= CALSTAT_SHORT; dst = CAL_SHORT; src = 0; cal_status&= ~(CALSTAT_ER|CALSTAT_APPLY); break;
break; case CAL_THRU: cal_status|= CALSTAT_THRU; dst = CAL_THRU; src = 1; break;
case CAL_ISOLN: cal_status|= CALSTAT_ISOLN; dst = CAL_ISOLN; src = 1; break;
case CAL_OPEN: default:
cal_status |= CALSTAT_OPEN; return;
cal_status &= ~(CALSTAT_ES|CALSTAT_APPLY);
memcpy(cal_data[CAL_OPEN], measured[0], sizeof measured[0]);
break;
case CAL_SHORT:
cal_status |= CALSTAT_SHORT;
cal_status &= ~(CALSTAT_ER|CALSTAT_APPLY);
memcpy(cal_data[CAL_SHORT], measured[0], sizeof measured[0]);
break;
case CAL_THRU:
cal_status |= CALSTAT_THRU;
memcpy(cal_data[CAL_THRU], measured[1], sizeof measured[0]);
break;
case CAL_ISOLN:
cal_status |= CALSTAT_ISOLN;
memcpy(cal_data[CAL_ISOLN], measured[1], sizeof measured[0]);
break;
} }
// Run sweep for collect data
sweep(false);
// Copy calibration data
memcpy(cal_data[dst], measured[src], sizeof measured[0]);
redraw_request |= REDRAW_CAL_STATUS; redraw_request |= REDRAW_CAL_STATUS;
} }
@ -1389,8 +1361,8 @@ cal_interpolate(int s)
j = 0; j = 0;
for (; i < sweep_points; i++) { for (; i < sweep_points; i++) {
uint32_t f = frequencies[i]; uint32_t f = frequencies[i];
if (f == 0) goto interpolate_finish;
for (; j < sweep_points-1; j++) { for (; j < src->_sweep_points-1; j++) {
if (src->_frequencies[j] <= f && f < src->_frequencies[j+1]) { if (src->_frequencies[j] <= f && f < src->_frequencies[j+1]) {
// found f between freqs at j and j+1 // found f between freqs at j and j+1
float k1 = (float)(f - src->_frequencies[j]) float k1 = (float)(f - src->_frequencies[j])
@ -1410,7 +1382,7 @@ cal_interpolate(int s)
break; break;
} }
} }
if (j == sweep_points-1) if (j == src->_sweep_points-1)
break; break;
} }
@ -1418,11 +1390,11 @@ cal_interpolate(int s)
for (; i < sweep_points; i++) { for (; i < sweep_points; i++) {
// fill cal_data at tail of src // fill cal_data at tail of src
for (eterm = 0; eterm < 5; eterm++) { for (eterm = 0; eterm < 5; eterm++) {
cal_data[eterm][i][0] = src->_cal_data[eterm][sweep_points-1][0]; cal_data[eterm][i][0] = src->_cal_data[eterm][src->_sweep_points-1][0];
cal_data[eterm][i][1] = src->_cal_data[eterm][sweep_points-1][1]; cal_data[eterm][i][1] = src->_cal_data[eterm][src->_sweep_points-1][1];
} }
} }
interpolate_finish:
cal_status |= src->_cal_status | CALSTAT_APPLY | CALSTAT_INTERPOLATED; cal_status |= src->_cal_status | CALSTAT_APPLY | CALSTAT_INTERPOLATED;
redraw_request |= REDRAW_CAL_STATUS; redraw_request |= REDRAW_CAL_STATUS;
} }
@ -1707,7 +1679,7 @@ VNA_SHELL_FUNCTION(cmd_marker)
if (t < 0 || t >= MARKERS_MAX) if (t < 0 || t >= MARKERS_MAX)
goto usage; goto usage;
if (argc == 1) { if (argc == 1) {
shell_printf("%d %d %d\r\n", t+1, markers[t].index, frequency); shell_printf("%d %d %d\r\n", t+1, markers[t].index, markers[t].frequency);
active_marker = t; active_marker = t;
// select active marker // select active marker
markers[t].enabled = TRUE; markers[t].enabled = TRUE;
@ -1764,7 +1736,7 @@ VNA_SHELL_FUNCTION(cmd_frequencies)
(void)argv; (void)argv;
for (i = 0; i < sweep_points; i++) { for (i = 0; i < sweep_points; i++) {
if (frequencies[i] != 0) if (frequencies[i] != 0)
shell_printf("%d\r\n", frequencies[i]); shell_printf("%u\r\n", frequencies[i]);
} }
} }
@ -1933,7 +1905,6 @@ VNA_SHELL_FUNCTION(cmd_stat)
// shell_printf("awd: %d\r\n", awd_count); // shell_printf("awd: %d\r\n", awd_count);
} }
#ifndef VERSION #ifndef VERSION
#define VERSION "unknown" #define VERSION "unknown"
#endif #endif
@ -1976,6 +1947,55 @@ VNA_SHELL_FUNCTION(cmd_info)
} }
#endif #endif
#ifdef ENABLE_COLOR_COMMAND
VNA_SHELL_FUNCTION(cmd_color)
{
uint32_t color;
int i;
if (argc != 2) {
shell_printf("usage: color {id} {rgb24}\r\n");
for (i=-3; i < TRACES_MAX; i++) {
#if 0
switch(i){
case -3: color = config.grid_color; break;
case -2: color = config.menu_normal_color; break;
case -1: color = config.menu_active_color; break;
default: color = config.trace_color[i];break;
}
#else
// WARNING!!! Dirty hack for size, depend from config struct
color = config.trace_color[i];
#endif
color = ((color >> 3) & 0x001c00) |
((color >> 5) & 0x0000f8) |
((color << 16) & 0xf80000) |
((color << 13) & 0x00e000);
// color = (color>>8)|(color<<8);
// color = ((color<<8)&0xF80000)|((color<<5)&0x00FC00)|((color<<3)&0x0000F8);
shell_printf(" %d: 0x%06x\r\n", i, color);
}
return;
}
i = my_atoi(argv[0]);
if (i < -3 && i >= TRACES_MAX)
return;
color = RGBHEX(my_atoui(argv[1]));
#if 0
switch(i){
case -3: config.grid_color = color; break;
case -2: config.menu_normal_color = color; break;
case -1: config.menu_active_color = color; break;
default: config.trace_color[i] = color;break;
}
#else
// WARNING!!! Dirty hack for size, depend from config struct
config.trace_color[i] = color;
#endif
// Redraw all
redraw_request|= REDRAW_AREA;
}
#endif
#ifdef ENABLE_THREADS_COMMAND #ifdef ENABLE_THREADS_COMMAND
#if CH_CFG_USE_REGISTRY == FALSE #if CH_CFG_USE_REGISTRY == FALSE
#error "Threads Requite enabled CH_CFG_USE_REGISTRY in chconf.h" #error "Threads Requite enabled CH_CFG_USE_REGISTRY in chconf.h"
@ -2017,7 +2037,7 @@ typedef struct {
} VNAShellCommand; } VNAShellCommand;
#pragma pack(pop) #pragma pack(pop)
// Some commands can executed only if process thread not in main cycle // Some commands can executed only in sweep thread, not in main cycle
#define CMD_WAIT_MUTEX 1 #define CMD_WAIT_MUTEX 1
static const VNAShellCommand commands[] = static const VNAShellCommand commands[] =
{ {
@ -2042,7 +2062,7 @@ static const VNAShellCommand commands[] =
{"power" , cmd_power , 0}, {"power" , cmd_power , 0},
{"sample" , cmd_sample , 0}, {"sample" , cmd_sample , 0},
// {"gamma" , cmd_gamma , 0}, // {"gamma" , cmd_gamma , 0},
{"scan" , cmd_scan , 0}, // Wait mutex hardcoded in cmd, need wait one sweep manually {"scan" , cmd_scan , CMD_WAIT_MUTEX},
{"sweep" , cmd_sweep , 0}, {"sweep" , cmd_sweep , 0},
{"test" , cmd_test , 0}, {"test" , cmd_test , 0},
{"touchcal" , cmd_touchcal , CMD_WAIT_MUTEX}, {"touchcal" , cmd_touchcal , CMD_WAIT_MUTEX},
@ -2066,6 +2086,9 @@ static const VNAShellCommand commands[] =
#ifdef ENABLE_INFO_COMMAND #ifdef ENABLE_INFO_COMMAND
{"info" , cmd_info , 0}, {"info" , cmd_info , 0},
#endif #endif
#ifdef ENABLE_COLOR_COMMAND
{"color" , cmd_color , 0},
#endif
#ifdef ENABLE_THREADS_COMMAND #ifdef ENABLE_THREADS_COMMAND
{"threads" , cmd_threads , 0}, {"threads" , cmd_threads , 0},
#endif #endif
@ -2128,52 +2151,50 @@ static int VNAShell_readLine(char *line, int max_size){
return 0; return 0;
} }
// Macros for convert define value to string
#define STR1(x) #x
#define define_to_STR(x) STR1(x)
// //
// Parse and run command line // Parse and run command line
// //
static void VNAShell_executeLine(char *line){ static void VNAShell_executeLine(char *line){
// Parse and execute line // Parse and execute line
char *args[VNA_SHELL_MAX_ARGUMENTS + 1];
int n = 0;
char *lp = line, *ep; char *lp = line, *ep;
shell_nargs = 0;
while (*lp!=0){ while (*lp!=0){
// Skipping white space and tabs at string begin. // Skipping white space and tabs at string begin.
while (*lp==' ' || *lp=='\t') lp++; while (*lp==' ' || *lp=='\t') lp++;
// If an argument starts with a double quote then its delimiter is another quote, else delimiter is white space. // If an argument starts with a double quote then its delimiter is another quote, else delimiter is white space.
ep = (*lp == '"') ? strpbrk(++lp, "\"") : strpbrk( lp, " \t"); ep = (*lp == '"') ? strpbrk(++lp, "\"") : strpbrk( lp, " \t");
// Store in args string // Store in args string
args[n++]=lp; shell_args[shell_nargs++]=lp;
// Stop, end of input string // Stop, end of input string
if ((lp = ep) == NULL) if ((lp = ep) == NULL)
break; break;
// Argument limits check // Argument limits check
if (n > VNA_SHELL_MAX_ARGUMENTS) { if (shell_nargs > VNA_SHELL_MAX_ARGUMENTS) {
shell_printf("too many arguments, max "define_to_STR(VNA_SHELL_MAX_ARGUMENTS)""VNA_SHELL_NEWLINE_STR); shell_printf("too many arguments, max "define_to_STR(VNA_SHELL_MAX_ARGUMENTS)""VNA_SHELL_NEWLINE_STR);
return; return;
} }
// Set zero at the end of string and continue check // Set zero at the end of string and continue check
*lp++ = 0; *lp++ = 0;
} }
if (n == 0) if (shell_nargs == 0)
return; return;
// Execute line // Execute line
const VNAShellCommand *scp; const VNAShellCommand *scp;
for (scp = commands; scp->sc_name!=NULL;scp++) { for (scp = commands; scp->sc_name!=NULL;scp++) {
if (strcmp(scp->sc_name, args[0]) == 0) { if (strcmp(scp->sc_name, shell_args[0]) == 0) {
if (scp->flags&CMD_WAIT_MUTEX){ if (scp->flags&CMD_WAIT_MUTEX){
chMtxLock(&mutex); shell_function= scp->sc_function;
scp->sc_function(n-1, &args[1]); // Wait execute command in sweep thread
chMtxUnlock(&mutex); do{
osalThreadSleepMilliseconds(100);
} while(shell_function);
} }
else else
scp->sc_function(n-1, &args[1]); scp->sc_function(shell_nargs-1, &shell_args[1]);
return; return;
} }
} }
shell_printf("%s?"VNA_SHELL_NEWLINE_STR, args[0]); shell_printf("%s?"VNA_SHELL_NEWLINE_STR, shell_args[0]);
} }
#ifdef VNA_SHELL_THREAD #ifdef VNA_SHELL_THREAD
@ -2209,6 +2230,10 @@ static const I2CConfig i2ccfg = {
STM32_TIMINGR_PRESC(5U) | STM32_TIMINGR_PRESC(5U) |
STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) | STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) |
STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U), STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U),
// 600kHz @ SYSCLK 48MHz, manually get values, x1.5 I2C speed, but need calc timings
// STM32_TIMINGR_PRESC(3U) |
// STM32_TIMINGR_SCLDEL(2U) | STM32_TIMINGR_SDADEL(2U) |
// STM32_TIMINGR_SCLH(4U) | STM32_TIMINGR_SCLL(4U),
#else #else
#error "Need Define STM32_I2C1SW and set correct TIMINGR settings" #error "Need Define STM32_I2C1SW and set correct TIMINGR settings"
#endif #endif
@ -2232,8 +2257,6 @@ int main(void)
halInit(); halInit();
chSysInit(); chSysInit();
chMtxObjectInit(&mutex);
//palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN); //palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN);
//palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN); //palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN);
i2cStart(&I2CD1, &i2ccfg); i2cStart(&I2CD1, &i2ccfg);

View file

@ -25,8 +25,17 @@
/* /*
* main.c * main.c
*/ */
// Minimum frequency set
#define START_MIN 50000 #define START_MIN 50000
// Maximum frequency set
#define STOP_MAX 2700000000U #define STOP_MAX 2700000000U
// Frequency offset (sin_cos table in dsp.c generated for this offset, if change need create new table)
#define FREQUENCY_OFFSET 5000
// Speed of light const
#define SPEED_OF_LIGHT 299792458
// pi const
#define VNA_PI 3.14159265358979323846
#define POINTS_COUNT 101 #define POINTS_COUNT 101
extern float measured[2][POINTS_COUNT][2]; extern float measured[2][POINTS_COUNT][2];
@ -209,6 +218,10 @@ typedef struct trace {
float refpos; float refpos;
} trace_t; } trace_t;
#define FREQ_MODE_START_STOP 0x0
#define FREQ_MODE_CENTER_SPAN 0x1
#define FREQ_MODE_DOTTED_GRID 0x2
typedef struct config { typedef struct config {
int32_t magic; int32_t magic;
uint16_t dac_value; uint16_t dac_value;
@ -217,7 +230,7 @@ typedef struct config {
uint16_t menu_active_color; uint16_t menu_active_color;
uint16_t trace_color[TRACES_MAX]; uint16_t trace_color[TRACES_MAX];
int16_t touch_cal[4]; int16_t touch_cal[4];
int8_t reserved_1; int8_t freq_mode;
uint32_t harmonic_freq_threshold; uint32_t harmonic_freq_threshold;
uint16_t vbat_offset; uint16_t vbat_offset;
uint8_t _reserved[22]; uint8_t _reserved[22];
@ -226,8 +239,6 @@ typedef struct config {
extern config_t config; extern config_t config;
//extern trace_t trace[TRACES_MAX];
void set_trace_type(int t, int type); void set_trace_type(int t, int type);
void set_trace_channel(int t, int channel); void set_trace_channel(int t, int channel);
void set_trace_scale(int t, float scale); void set_trace_scale(int t, float scale);
@ -260,7 +271,7 @@ void redraw_frame(void);
//void redraw_all(void); //void redraw_all(void);
void request_to_draw_cells_behind_menu(void); void request_to_draw_cells_behind_menu(void);
void request_to_draw_cells_behind_numeric_input(void); void request_to_draw_cells_behind_numeric_input(void);
void redraw_marker(int marker, int update_info); void redraw_marker(int marker);
void plot_into_index(float measured[2][POINTS_COUNT][2]); void plot_into_index(float measured[2][POINTS_COUNT][2]);
void force_set_markmap(void); void force_set_markmap(void);
void draw_frequencies(void); void draw_frequencies(void);
@ -283,6 +294,7 @@ int marker_search_right(int from);
#define REDRAW_CAL_STATUS (1<<2) #define REDRAW_CAL_STATUS (1<<2)
#define REDRAW_MARKER (1<<3) #define REDRAW_MARKER (1<<3)
#define REDRAW_BATTERY (1<<4) #define REDRAW_BATTERY (1<<4)
#define REDRAW_AREA (1<<5)
extern volatile uint8_t redraw_request; extern volatile uint8_t redraw_request;
/* /*
@ -396,13 +408,9 @@ extern properties_t current_props;
#define velocity_factor current_props._velocity_factor #define velocity_factor current_props._velocity_factor
#define marker_smith_format current_props._marker_smith_format #define marker_smith_format current_props._marker_smith_format
#define FREQ_IS_STARTSTOP() (frequency0 < frequency1) #define FREQ_IS_STARTSTOP() (!(config.freq_mode&FREQ_MODE_CENTER_SPAN))
#define FREQ_IS_CENTERSPAN() (frequency0 > frequency1) #define FREQ_IS_CENTERSPAN() (config.freq_mode&FREQ_MODE_CENTER_SPAN)
#define FREQ_IS_CW() (frequency0 == frequency1) #define FREQ_IS_CW() (frequency0 == frequency1)
#define FREQ_START() (frequency0)
#define FREQ_STOP() (frequency1)
#define FREQ_CENTER() (frequency0/2 + frequency1/2)
#define FREQ_SPAN() (frequency0 - frequency1)
int caldata_save(int id); int caldata_save(int id);
int caldata_recall(int id); int caldata_recall(int id);
@ -482,4 +490,7 @@ int plot_printf(char *str, int, const char *fmt, ...);
// Speed profile definition // Speed profile definition
#define START_PROFILE systime_t time = chVTGetSystemTimeX(); #define START_PROFILE systime_t time = chVTGetSystemTimeX();
#define STOP_PROFILE {char string_buf[12];plot_printf(string_buf, sizeof string_buf, "T:%06d", chVTGetSystemTimeX() - time);ili9341_drawstringV(string_buf, 1, 60);} #define STOP_PROFILE {char string_buf[12];plot_printf(string_buf, sizeof string_buf, "T:%06d", chVTGetSystemTimeX() - time);ili9341_drawstringV(string_buf, 1, 60);}
// Macros for convert define value to string
#define STR1(x) #x
#define define_to_STR(x) STR1(x)
/*EOF*/ /*EOF*/

238
plot.c
View file

@ -8,13 +8,17 @@
static void cell_draw_marker_info(int x0, int y0); static void cell_draw_marker_info(int x0, int y0);
static void draw_battery_status(void); static void draw_battery_status(void);
int16_t grid_offset; static int16_t grid_offset;
int16_t grid_width; static int16_t grid_width;
int16_t area_width = AREA_WIDTH_NORMAL; int16_t area_width = AREA_WIDTH_NORMAL;
int16_t area_height = AREA_HEIGHT_NORMAL; int16_t area_height = AREA_HEIGHT_NORMAL;
// Depends from spi_buffer size, CELLWIDTH*CELLHEIGHT <= sizeof(spi_buffer) // Cell render use spi buffer
typedef uint16_t pixel;
pixel *cell_buffer = (pixel *)spi_buffer;
// Cell size
// Depends from spi_buffer size, CELLWIDTH*CELLHEIGHT*sizeof(pixel) <= sizeof(spi_buffer)
#define CELLWIDTH (64) #define CELLWIDTH (64)
#define CELLHEIGHT (32) #define CELLHEIGHT (32)
// Check buffer size // Check buffer size
@ -25,18 +29,27 @@ int16_t area_height = AREA_HEIGHT_NORMAL;
// indicate dirty cells (not redraw if cell data not changed) // indicate dirty cells (not redraw if cell data not changed)
#define MAX_MARKMAP_X ((320+CELLWIDTH-1)/CELLWIDTH) #define MAX_MARKMAP_X ((320+CELLWIDTH-1)/CELLWIDTH)
#define MAX_MARKMAP_Y ((240+CELLHEIGHT-1)/CELLHEIGHT) #define MAX_MARKMAP_Y ((240+CELLHEIGHT-1)/CELLHEIGHT)
uint16_t markmap[2][MAX_MARKMAP_Y]; // Define markmap mask size
uint16_t current_mappage = 0; #if MAX_MARKMAP_X <= 8
typedef uint8_t map_t;
#elif MAX_MARKMAP_X <= 16
typedef uint16_t map_t;
#elif MAX_MARKMAP_X <= 32
typedef uint32_t map_t;
#endif
map_t markmap[2][MAX_MARKMAP_Y];
uint8_t current_mappage = 0;
// Trace data cache, for faster redraw cells // Trace data cache, for faster redraw cells
// CELL_X[16:31] x position // CELL_X[16:31] x position
// CELL_Y[ 0:15] y position // CELL_Y[ 0:15] y position
static uint32_t trace_index[TRACES_MAX][POINTS_COUNT]; typedef uint32_t index_t;
static index_t trace_index[TRACES_MAX][POINTS_COUNT];
#define INDEX(x, y) ((((uint32_t)x)<<16)|(((uint32_t)y))) #define INDEX(x, y) ((((index_t)x)<<16)|(((index_t)y)))
#define CELL_X(i) (int)(((i)>>16)) #define CELL_X(i) (int)(((i)>>16))
#define CELL_Y(i) (int)(((i)&0xFFFF)) #define CELL_Y(i) (int)(((i)&0xFFFF))
//#define CELL_P(i, x, y) (((((x)&0x03e0UL)<<22) | (((y)&0x03e0UL)<<17)) == ((i)&0xffc00000UL))
//#define floatToInt(v) ((int)(v)) //#define floatToInt(v) ((int)(v))
static int static int
@ -412,7 +425,7 @@ logmag(const float *v)
static float static float
phase(const float *v) phase(const float *v)
{ {
return 2 * atan2f(v[1], v[0]) / M_PI * 90; return 2 * atan2f(v[1], v[0]) / VNA_PI * 90;
} }
/* /*
@ -425,9 +438,9 @@ groupdelay(const float *v, const float *w, float deltaf)
// atan(w)-atan(v) = atan((w-v)/(1+wv)) // atan(w)-atan(v) = atan((w-v)/(1+wv))
float r = w[0]*v[1] - w[1]*v[0]; float r = w[0]*v[1] - w[1]*v[0];
float i = w[0]*v[0] + w[1]*v[1]; float i = w[0]*v[0] + w[1]*v[1];
return atan2f(r, i) / (2 * M_PI * deltaf); return atan2f(r, i) / (2 * VNA_PI * deltaf);
#else #else
return (atan2f(w[0], w[1]) - atan2f(v[0], v[1])) / (2 * M_PI * deltaf); return (atan2f(w[0], w[1]) - atan2f(v[0], v[1])) / (2 * VNA_PI * deltaf);
#endif #endif
} }
@ -486,7 +499,7 @@ float
groupdelay_from_array(int i, float array[POINTS_COUNT][2]) groupdelay_from_array(int i, float array[POINTS_COUNT][2])
{ {
int bottom = (i == 0) ? 0 : i - 1; int bottom = (i == 0) ? 0 : i - 1;
int top = (i == POINTS_COUNT-1) ? POINTS_COUNT-1 : i + 1; int top = (i == sweep_points-1) ? sweep_points-1 : i + 1;
float deltaf = frequencies[top] - frequencies[bottom]; float deltaf = frequencies[top] - frequencies[bottom];
return groupdelay(array[bottom], array[top], deltaf); return groupdelay(array[bottom], array[top], deltaf);
} }
@ -507,7 +520,7 @@ gamma2reactance(const float v[2])
return 2*v[1] * d; return 2*v[1] * d;
} }
static uint32_t static index_t
trace_into_index(int t, int i, float array[POINTS_COUNT][2]) trace_into_index(int t, int i, float array[POINTS_COUNT][2])
{ {
int y, x; int y, x;
@ -592,11 +605,11 @@ format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency)
case MS_RLC: case MS_RLC:
if (zi < 0){// Capacity if (zi < 0){// Capacity
prefix = 'F'; prefix = 'F';
value = -1 / (2 * M_PI * frequency * zi); value = -1 / (2 * VNA_PI * frequency * zi);
} }
else { else {
prefix = 'H'; prefix = 'H';
value = zi / (2 * M_PI * frequency); value = zi / (2 * VNA_PI * frequency);
} }
plot_printf(buf, len, "%F"S_OHM" %F%c", zr, value, prefix); plot_printf(buf, len, "%F"S_OHM" %F%c", zr, value, prefix);
break; break;
@ -745,7 +758,6 @@ static float time_of_index(int idx) {
} }
static float distance_of_index(int idx) { static float distance_of_index(int idx) {
#define SPEED_OF_LIGHT 299792458
float distance = ((float)idx * (float)SPEED_OF_LIGHT) / ( (float)(frequencies[1] - frequencies[0]) * (float)FFT_SIZE * 2.0); float distance = ((float)idx * (float)SPEED_OF_LIGHT) / ( (float)(frequencies[1] - frequencies[0]) * (float)FFT_SIZE * 2.0);
return distance * velocity_factor; return distance * velocity_factor;
} }
@ -757,7 +769,7 @@ mark_map(int x, int y)
markmap[current_mappage][y] |= 1<<x; markmap[current_mappage][y] |= 1<<x;
} }
static void static inline void
swap_markmap(void) swap_markmap(void)
{ {
current_mappage^= 1; current_mappage^= 1;
@ -787,48 +799,31 @@ invalidateRect(int x0, int y0, int x1, int y1){
mark_map(x, y); mark_map(x, y);
} }
#define SWAP(x,y) {int t=x;x=y;y=t;}
static void static void
mark_cells_from_index(void) mark_cells_from_index(void)
{ {
int t; int t, i, j;
/* mark cells between each neighber points */ /* mark cells between each neighber points */
map_t *map = &markmap[current_mappage][0];
for (t = 0; t < TRACES_MAX; t++) { for (t = 0; t < TRACES_MAX; t++) {
if (!trace[t].enabled) if (!trace[t].enabled)
continue; continue;
int x0 = CELL_X(trace_index[t][0]); index_t *index = &trace_index[t][0];
int y0 = CELL_Y(trace_index[t][0]); int m0 = CELL_X(index[0]) / CELLWIDTH;
int m0 = x0 / CELLWIDTH; int n0 = CELL_Y(index[0]) / CELLHEIGHT;
int n0 = y0 / CELLHEIGHT; map[n0]|= 1<<m0;
int i;
mark_map(m0, n0);
for (i = 1; i < sweep_points; i++) { for (i = 1; i < sweep_points; i++) {
int x1 = CELL_X(trace_index[t][i]); int m1 = CELL_X(index[i]) / CELLWIDTH;
int y1 = CELL_Y(trace_index[t][i]); int n1 = CELL_Y(index[i]) / CELLHEIGHT;
int m1 = x1 / CELLWIDTH; if (m0 == m1 && n0 == n1)
int n1 = y1 / CELLHEIGHT; continue;
while (m0 != m1 || n0 != n1) { int x0 = m0; int x1 = m1; if (x0>x1) SWAP(x0, x1); m0=m1;
if (m0 == m1) { int y0 = n0; int y1 = n1; if (y0>y1) SWAP(y0, y1); n0=n1;
if (n0 < n1) n0++; else n0--; for (; y0<=y1; y0++)
} else if (n0 == n1) { for(j=x0; j<=x1; j++)
if (m0 < m1) m0++; else m0--; map[y0]|= 1<<j;
} else {
int x = ((m0 < m1) ? (m0 + 1) : m0) * CELLWIDTH;
int y = ((n0 < n1) ? (n0 + 1) : n0) * CELLHEIGHT;
int sgn = (n0 < n1) ? 1 : -1;
if (sgn*(y-y0)*(x1-x0) < sgn*(x-x0)*(y1-y0)) {
if (m0 < m1) m0++;
else m0--;
} else {
if (n0 < n1) n0++;
else n0--;
}
}
mark_map(m0, n0);
}
x0 = x1;
y0 = y1;
m0 = m1;
n0 = n1;
} }
} }
} }
@ -840,7 +835,6 @@ markmap_upperarea(void)
invalidateRect(0, 0, AREA_WIDTH_NORMAL, 31); invalidateRect(0, 0, AREA_WIDTH_NORMAL, 31);
} }
#define SWAP(x,y) {int t=x;x=y;y=t;}
// //
// in most cases _compute_outcode clip calculation not give render line speedup // in most cases _compute_outcode clip calculation not give render line speedup
// //
@ -860,7 +854,7 @@ cell_drawline(int x0, int y0, int x1, int y1, int c)
while (1){ while (1){
if (y0>=0 && y0<CELLHEIGHT && x0>=0 && x0<CELLWIDTH) if (y0>=0 && y0<CELLHEIGHT && x0>=0 && x0<CELLWIDTH)
spi_buffer[y0*CELLWIDTH+x0]|= c; cell_buffer[y0*CELLWIDTH+x0]|= c;
if (x0 == x1 && y0 == y1) if (x0 == x1 && y0 == y1)
return; return;
int e2 = err; int e2 = err;
@ -872,7 +866,7 @@ cell_drawline(int x0, int y0, int x1, int y1, int c)
// Give a little speedup then draw rectangular plot (50 systick on all calls, all render req 700 systick) // Give a little speedup then draw rectangular plot (50 systick on all calls, all render req 700 systick)
// Write more difficult algoritm for seach indexes not give speedup // Write more difficult algoritm for seach indexes not give speedup
static int static int
search_index_range_x(int x1, int x2, uint32_t index[POINTS_COUNT], int *i0, int *i1) search_index_range_x(int x1, int x2, index_t index[POINTS_COUNT], int *i0, int *i1)
{ {
int i, j; int i, j;
int head = 0; int head = 0;
@ -936,7 +930,7 @@ draw_refpos(int x, int y, int c)
uint8_t bits = reference_bitmap[j]; uint8_t bits = reference_bitmap[j];
while (bits){ while (bits){
if (x0 >= 0 && x0 < CELLWIDTH) if (x0 >= 0 && x0 < CELLWIDTH)
spi_buffer[y0*CELLWIDTH+x0] = (bits&0x80) ? c : DEFAULT_BG_COLOR; cell_buffer[y0*CELLWIDTH+x0] = (bits&0x80) ? c : DEFAULT_BG_COLOR;
x0++; x0++;
bits<<=1; bits<<=1;
} }
@ -1007,9 +1001,9 @@ draw_marker(int x, int y, int c, int ch)
force_color = true; force_color = true;
if (x0 >= 0 && x0 < CELLWIDTH && y0 >= 0 && y0 < CELLHEIGHT){ if (x0 >= 0 && x0 < CELLWIDTH && y0 >= 0 && y0 < CELLHEIGHT){
if (bits&0x80) if (bits&0x80)
spi_buffer[y0*CELLWIDTH+x0] = c; cell_buffer[y0*CELLWIDTH+x0] = c;
else if (force_color) else if (force_color)
spi_buffer[y0*CELLWIDTH+x0] = DEFAULT_BG_COLOR; cell_buffer[y0*CELLWIDTH+x0] = DEFAULT_BG_COLOR;
} }
x0++; x0++;
bits<<=1; bits<<=1;
@ -1026,7 +1020,7 @@ markmap_marker(int marker)
for (t = 0; t < TRACES_MAX; t++) { for (t = 0; t < TRACES_MAX; t++) {
if (!trace[t].enabled) if (!trace[t].enabled)
continue; continue;
uint32_t index = trace_index[t][markers[marker].index]; index_t index = trace_index[t][markers[marker].index];
int x = CELL_X(index) - X_MARKER_OFFSET; int x = CELL_X(index) - X_MARKER_OFFSET;
int y = CELL_Y(index) - Y_MARKER_OFFSET; int y = CELL_Y(index) - Y_MARKER_OFFSET;
invalidateRect(x, y, x+MARKER_WIDTH-1, y+MARKER_HEIGHT-1); invalidateRect(x, y, x+MARKER_WIDTH-1, y+MARKER_HEIGHT-1);
@ -1048,7 +1042,7 @@ markmap_all_markers(void)
void void
marker_position(int m, int t, int *x, int *y) marker_position(int m, int t, int *x, int *y)
{ {
uint32_t index = trace_index[t][markers[m].index]; index_t index = trace_index[t][markers[m].index];
*x = CELL_X(index); *x = CELL_X(index);
*y = CELL_Y(index); *y = CELL_Y(index);
} }
@ -1068,8 +1062,8 @@ marker_search(void)
return -1; return -1;
int value = CELL_Y(trace_index[uistat.current_trace][0]); int value = CELL_Y(trace_index[uistat.current_trace][0]);
for (i = 0; i < POINTS_COUNT; i++) { for (i = 0; i < sweep_points; i++) {
uint32_t index = trace_index[uistat.current_trace][i]; index_t index = trace_index[uistat.current_trace][i];
if ((*compare)(value, CELL_Y(index))) { if ((*compare)(value, CELL_Y(index))) {
value = CELL_Y(index); value = CELL_Y(index);
found = i; found = i;
@ -1096,14 +1090,14 @@ marker_search_left(int from)
int value = CELL_Y(trace_index[uistat.current_trace][from]); int value = CELL_Y(trace_index[uistat.current_trace][from]);
for (i = from - 1; i >= 0; i--) { for (i = from - 1; i >= 0; i--) {
uint32_t index = trace_index[uistat.current_trace][i]; index_t index = trace_index[uistat.current_trace][i];
if ((*compare)(value, CELL_Y(index))) if ((*compare)(value, CELL_Y(index)))
break; break;
value = CELL_Y(index); value = CELL_Y(index);
} }
for (; i >= 0; i--) { for (; i >= 0; i--) {
uint32_t index = trace_index[uistat.current_trace][i]; index_t index = trace_index[uistat.current_trace][i];
if ((*compare)(CELL_Y(index), value)) { if ((*compare)(CELL_Y(index), value)) {
break; break;
} }
@ -1123,15 +1117,15 @@ marker_search_right(int from)
return -1; return -1;
int value = CELL_Y(trace_index[uistat.current_trace][from]); int value = CELL_Y(trace_index[uistat.current_trace][from]);
for (i = from + 1; i < POINTS_COUNT; i++) { for (i = from + 1; i < sweep_points; i++) {
uint32_t index = trace_index[uistat.current_trace][i]; index_t index = trace_index[uistat.current_trace][i];
if ((*compare)(value, CELL_Y(index))) if ((*compare)(value, CELL_Y(index)))
break; break;
value = CELL_Y(index); value = CELL_Y(index);
} }
for (; i < POINTS_COUNT; i++) { for (; i < sweep_points; i++) {
uint32_t index = trace_index[uistat.current_trace][i]; index_t index = trace_index[uistat.current_trace][i];
if ((*compare)(CELL_Y(index), value)) { if ((*compare)(CELL_Y(index), value)) {
break; break;
} }
@ -1144,7 +1138,7 @@ marker_search_right(int from)
int int
search_nearest_index(int x, int y, int t) search_nearest_index(int x, int y, int t)
{ {
uint32_t *index = trace_index[t]; index_t *index = trace_index[t];
int min_i = -1; int min_i = -1;
int min_d = 1000; int min_d = 1000;
int i; int i;
@ -1161,7 +1155,6 @@ search_nearest_index(int x, int y, int t)
min_i = i; min_i = i;
} }
} }
return min_i; return min_i;
} }
@ -1173,8 +1166,9 @@ plot_into_index(float measured[2][POINTS_COUNT][2])
if (!trace[t].enabled) if (!trace[t].enabled)
continue; continue;
int ch = trace[t].channel; int ch = trace[t].channel;
index_t *index = trace_index[t];
for (i = 0; i < sweep_points; i++) for (i = 0; i < sweep_points; i++)
trace_index[t][i] = trace_into_index(t, i, measured[ch]); index[i] = trace_into_index(t, i, measured[ch]);
} }
#if 0 #if 0
for (t = 0; t < TRACES_MAX; t++) for (t = 0; t < TRACES_MAX; t++)
@ -1217,8 +1211,8 @@ draw_cell(int m, int n)
#error "CELLWIDTH % 8 should be == 0 for speed, or need rewrite cell cleanup" #error "CELLWIDTH % 8 should be == 0 for speed, or need rewrite cell cleanup"
#endif #endif
// Set DEFAULT_BG_COLOR for 8 pixels in one cycle // Set DEFAULT_BG_COLOR for 8 pixels in one cycle
int count = h*CELLWIDTH / 8; int count = h*CELLWIDTH / (16/sizeof(pixel));
uint32_t *p = (uint32_t *)spi_buffer; uint32_t *p = (uint32_t *)cell_buffer;
while (count--) { while (count--) {
p[0] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16); p[0] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16);
p[1] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16); p[1] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16);
@ -1241,14 +1235,14 @@ draw_cell(int m, int n)
for (x = 0; x < w; x++) { for (x = 0; x < w; x++) {
if (rectangular_grid_x(x+x0)){ if (rectangular_grid_x(x+x0)){
for (y = 0; y < h; y++) for (y = 0; y < h; y++)
spi_buffer[y * CELLWIDTH + x] = c; cell_buffer[y * CELLWIDTH + x] = c;
} }
} }
for (y = 0; y < h; y++) { for (y = 0; y < h; y++) {
if (rectangular_grid_y(y+y0)){ if (rectangular_grid_y(y+y0)){
for (x = 0; x < w; x++) for (x = 0; x < w; x++)
if (x+x0 >= CELLOFFSETX && x+x0 <= WIDTH+CELLOFFSETX) if (x+x0 >= CELLOFFSETX && x+x0 <= WIDTH+CELLOFFSETX)
spi_buffer[y * CELLWIDTH + x] = c; cell_buffer[y * CELLWIDTH + x] = c;
} }
} }
} }
@ -1257,14 +1251,14 @@ draw_cell(int m, int n)
for (y = 0; y < h; y++) for (y = 0; y < h; y++)
for (x = 0; x < w; x++) for (x = 0; x < w; x++)
if (smith_grid(x+x0, y+y0)) if (smith_grid(x+x0, y+y0))
spi_buffer[y * CELLWIDTH + x] = c; cell_buffer[y * CELLWIDTH + x] = c;
} }
// Polar greed line (800 system ticks for all screen calls) // Polar greed line (800 system ticks for all screen calls)
else if(trace_type&(1<<TRC_POLAR)){ else if(trace_type&(1<<TRC_POLAR)){
for (y = 0; y < h; y++) for (y = 0; y < h; y++)
for (x = 0; x < w; x++) for (x = 0; x < w; x++)
if (polar_grid(x+x0, y+y0)) if (polar_grid(x+x0, y+y0))
spi_buffer[y * CELLWIDTH + x] = c; cell_buffer[y * CELLWIDTH + x] = c;
} }
#if 0 #if 0
else if(trace_type&(1<<TRC_ADMIT)){ else if(trace_type&(1<<TRC_ADMIT)){
@ -1272,7 +1266,7 @@ draw_cell(int m, int n)
for (x = 0; x < w; x++) for (x = 0; x < w; x++)
if (smith_grid3(x+x0, y+y0) if (smith_grid3(x+x0, y+y0)
// smith_grid2(x+x0, y+y0, 0.5)) // smith_grid2(x+x0, y+y0, 0.5))
spi_buffer[y * CELLWIDTH + x] = c; cell_buffer[y * CELLWIDTH + x] = c;
} }
#endif #endif
#endif #endif
@ -1290,7 +1284,7 @@ draw_cell(int m, int n)
i1 = sweep_points-1; i1 = sweep_points-1;
else // draw rectangular plot (search index range in cell, save 50-70 system ticks for all screen calls) else // draw rectangular plot (search index range in cell, save 50-70 system ticks for all screen calls)
search_index_range_x(x0, x0+w, trace_index[t], &i0, &i1); search_index_range_x(x0, x0+w, trace_index[t], &i0, &i1);
uint32_t *index = trace_index[t]; index_t *index = trace_index[t];
for (i=i0; i < i1; i++) { for (i=i0; i < i1; i++) {
int x1 = CELL_X(index[i ]) - x0; int x1 = CELL_X(index[i ]) - x0;
int y1 = CELL_Y(index[i ]) - y0; int y1 = CELL_Y(index[i ]) - y0;
@ -1312,7 +1306,7 @@ draw_cell(int m, int n)
for (t = 0; t < TRACES_MAX; t++) { for (t = 0; t < TRACES_MAX; t++) {
if (!trace[t].enabled) if (!trace[t].enabled)
continue; continue;
uint32_t index = trace_index[t][markers[i].index]; index_t index = trace_index[t][markers[i].index];
int x = CELL_X(index) - x0 - X_MARKER_OFFSET; int x = CELL_X(index) - x0 - X_MARKER_OFFSET;
int y = CELL_Y(index) - y0 - Y_MARKER_OFFSET; int y = CELL_Y(index) - y0 - Y_MARKER_OFFSET;
// Check marker icon on cell // Check marker icon on cell
@ -1344,8 +1338,8 @@ draw_cell(int m, int n)
// Need right clip cell render (25 system ticks for all screen calls) // Need right clip cell render (25 system ticks for all screen calls)
#if 1 #if 1
if (w < CELLWIDTH){ if (w < CELLWIDTH){
uint16_t *src = spi_buffer+CELLWIDTH; pixel *src = cell_buffer+CELLWIDTH;
uint16_t *dst = spi_buffer+w; pixel *dst = cell_buffer+w;
for (y=h; --y; src+=CELLWIDTH-w) for (y=h; --y; src+=CELLWIDTH-w)
for(x=w;x--;) for(x=w;x--;)
*dst++=*src++; *dst++=*src++;
@ -1361,8 +1355,7 @@ draw_all_cells(bool flush_markmap){
// START_PROFILE // START_PROFILE
for (m = 0; m < (area_width+CELLWIDTH-1) / CELLWIDTH; m++) for (m = 0; m < (area_width+CELLWIDTH-1) / CELLWIDTH; m++)
for (n = 0; n < (area_height+CELLHEIGHT-1) / CELLHEIGHT; n++) { for (n = 0; n < (area_height+CELLHEIGHT-1) / CELLHEIGHT; n++) {
uint16_t bit = 1<<m; if ((markmap[0][n] | markmap[1][n]) & (1<<m)){
if ((markmap[0][n] & bit) || (markmap[1][n] & bit)){
draw_cell(m, n); draw_cell(m, n);
// ili9341_fill(m*CELLWIDTH+10, n*CELLHEIGHT, 2, 2, RGB565(255,0,0)); // ili9341_fill(m*CELLWIDTH+10, n*CELLHEIGHT, 2, 2, RGB565(255,0,0));
} }
@ -1381,9 +1374,11 @@ draw_all_cells(bool flush_markmap){
void void
draw_all(bool flush) draw_all(bool flush)
{ {
if (redraw_request & REDRAW_AREA)
force_set_markmap();
if (redraw_request & REDRAW_MARKER) if (redraw_request & REDRAW_MARKER)
markmap_upperarea(); markmap_upperarea();
if (redraw_request & (REDRAW_CELLS | REDRAW_MARKER)) if (redraw_request & (REDRAW_CELLS | REDRAW_MARKER | REDRAW_AREA))
draw_all_cells(flush); draw_all_cells(flush);
if (redraw_request & REDRAW_FREQUENCY) if (redraw_request & REDRAW_FREQUENCY)
draw_frequencies(); draw_frequencies();
@ -1394,8 +1389,11 @@ draw_all(bool flush)
redraw_request = 0; redraw_request = 0;
} }
//
// Call this function then need fast draw marker and marker info
// Used in ui.c for leveler move marker, drag marker and etc.
void void
redraw_marker(int marker, int update_info) redraw_marker(int marker)
{ {
if (marker < 0) if (marker < 0)
return; return;
@ -1403,10 +1401,11 @@ redraw_marker(int marker, int update_info)
markmap_marker(marker); markmap_marker(marker);
// mark cells on marker info // mark cells on marker info
if (update_info)
markmap_upperarea(); markmap_upperarea();
draw_all_cells(TRUE); draw_all_cells(TRUE);
// Force redraw all area after (disable artifacts after fast marker update area)
redraw_request|=REDRAW_AREA;
} }
void void
@ -1442,7 +1441,7 @@ cell_drawchar(uint8_t ch, int x, int y)
continue; continue;
for (r = 0; r < ch_size; r++) { for (r = 0; r < ch_size; r++) {
if ((x+r) >= 0 && (x+r) < CELLWIDTH && (0x80 & bits)) if ((x+r) >= 0 && (x+r) < CELLWIDTH && (0x80 & bits))
spi_buffer[(y+c)*CELLWIDTH + (x+r)] = foreground_color; cell_buffer[(y+c)*CELLWIDTH + (x+r)] = foreground_color;
bits <<= 1; bits <<= 1;
} }
} }
@ -1580,7 +1579,7 @@ cell_draw_marker_info(int x0, int y0)
cell_drawstring(S_SARROW, xpos, ypos); cell_drawstring(S_SARROW, xpos, ypos);
xpos += 5; xpos += 5;
float light_speed_ps = 299792458e-12; //(m/ps) float light_speed_ps = SPEED_OF_LIGHT*1e-12; //(m/ps)
plot_printf(buf, sizeof buf, "Edelay %Fs %Fm", electrical_delay * 1e-12, plot_printf(buf, sizeof buf, "Edelay %Fs %Fm", electrical_delay * 1e-12,
electrical_delay * light_speed_ps * velocity_factor); electrical_delay * light_speed_ps * velocity_factor);
cell_drawstring(buf, xpos, ypos); cell_drawstring(buf, xpos, ypos);
@ -1593,18 +1592,18 @@ draw_frequencies(void)
char buf1[32]; char buf1[32];
char buf2[32];buf2[0]=0; char buf2[32];buf2[0]=0;
if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) { if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) {
if (FREQ_IS_STARTSTOP()) { if (FREQ_IS_CW()){
plot_printf(buf1, sizeof(buf1), " START %qHz", frequency0); plot_printf(buf1, sizeof(buf1), " CW %qHz", get_sweep_frequency(ST_CW));
plot_printf(buf2, sizeof(buf2), " STOP %qHz", frequency1); } else if (FREQ_IS_STARTSTOP()) {
plot_printf(buf1, sizeof(buf1), " START %qHz", get_sweep_frequency(ST_START));
plot_printf(buf2, sizeof(buf2), " STOP %qHz", get_sweep_frequency(ST_STOP));
} else if (FREQ_IS_CENTERSPAN()) { } else if (FREQ_IS_CENTERSPAN()) {
plot_printf(buf1, sizeof(buf1), " CENTER %qHz", FREQ_CENTER()); plot_printf(buf1, sizeof(buf1), " CENTER %qHz", get_sweep_frequency(ST_CENTER));
plot_printf(buf2, sizeof(buf2), " SPAN %qHz", FREQ_SPAN()); plot_printf(buf2, sizeof(buf2), " SPAN %qHz", get_sweep_frequency(ST_SPAN));
} else {
plot_printf(buf1, sizeof(buf1), " CW %qHz", frequency0);
} }
} else { } else {
plot_printf(buf1, sizeof(buf1), " START 0s"); plot_printf(buf1, sizeof(buf1), " START 0s");
plot_printf(buf2, sizeof(buf2), "STOP %Fs (%Fm)", time_of_index(POINTS_COUNT-1), distance_of_index(POINTS_COUNT-1)); plot_printf(buf2, sizeof(buf2), "STOP %Fs (%Fm)", time_of_index(sweep_points-1), distance_of_index(sweep_points-1));
} }
setForegroundColor(DEFAULT_FG_COLOR); setForegroundColor(DEFAULT_FG_COLOR);
setBackgroundColor(DEFAULT_BG_COLOR); setBackgroundColor(DEFAULT_BG_COLOR);
@ -1622,41 +1621,28 @@ draw_cal_status(void)
{ {
int x = 0; int x = 0;
int y = 100; int y = 100;
#define YSTEP 8 char c[3];
setForegroundColor(DEFAULT_FG_COLOR); setForegroundColor(DEFAULT_FG_COLOR);
setBackgroundColor(DEFAULT_BG_COLOR); setBackgroundColor(DEFAULT_BG_COLOR);
ili9341_fill(0, y, 10, 6*YSTEP, DEFAULT_BG_COLOR); ili9341_fill(0, y, OFFSETX, 6*(FONT_GET_HEIGHT+1), DEFAULT_BG_COLOR);
if (cal_status & CALSTAT_APPLY) { if (cal_status & CALSTAT_APPLY) {
char c[3] = "C0"; c[0] = cal_status & CALSTAT_INTERPOLATED ? 'c' : 'C';
c[1] += lastsaveid; c[1] = active_props == &current_props ? '*' : '0' + lastsaveid;
if (cal_status & CALSTAT_INTERPOLATED) c[2] = 0;
c[0] = 'c';
else if (active_props == &current_props)
c[1] = '*';
ili9341_drawstring(c, x, y); ili9341_drawstring(c, x, y);
y += YSTEP; y +=FONT_GET_HEIGHT+1;
}
if (cal_status & CALSTAT_ED) {
ili9341_drawstring("D", x, y);
y += YSTEP;
}
if (cal_status & CALSTAT_ER) {
ili9341_drawstring("R", x, y);
y += YSTEP;
}
if (cal_status & CALSTAT_ES) {
ili9341_drawstring("S", x, y);
y += YSTEP;
}
if (cal_status & CALSTAT_ET) {
ili9341_drawstring("T", x, y);
y += YSTEP;
}
if (cal_status & CALSTAT_EX) {
ili9341_drawstring("X", x, y);
y += YSTEP;
} }
int i;
static const struct {char text, zero, mask;} calibration_text[]={
{'D', 0, CALSTAT_ED},
{'R', 0, CALSTAT_ER},
{'S', 0, CALSTAT_ES},
{'T', 0, CALSTAT_ET},
{'X', 0, CALSTAT_EX}
};
for (i = 0; i < 5; i++, y+=FONT_GET_HEIGHT+1)
if (cal_status & calibration_text[i].mask)
ili9341_drawstring(&calibration_text[i].text, x, y);
} }
// Draw battery level // Draw battery level

View file

@ -38,6 +38,25 @@
static uint8_t current_band = 0; static uint8_t current_band = 0;
static uint32_t current_freq = 0; static uint32_t current_freq = 0;
static int32_t current_offset = FREQUENCY_OFFSET;
// Minimum value is 2, freq change apply at next dsp measure, and need skip it
#define DELAY_NORMAL 2
// Delay for bands (depend set band 1 more fast (can change before next dsp buffer ready, need wait additional interval)
#define DELAY_BAND_1 3
#define DELAY_BAND_2 2
// Band changes need set delay after reset PLL
#define DELAY_BANDCHANGE_1 3
#define DELAY_BANDCHANGE_2 3
// Delay after set new PLL values, and send reset (on band 1 unstable if less then 900, on 4000-5000 no amplitude spike on change)
#define DELAY_RESET_PLL 5000
uint32_t si5351_getFrequency(void) {return current_freq;}
void si5351_set_frequency_offset(int32_t offset) {
current_offset = offset;
current_freq = 0; // reset freq, for
}
static void static void
si5351_bulk_write(const uint8_t *buf, int len) si5351_bulk_write(const uint8_t *buf, int len)
@ -46,13 +65,26 @@ si5351_bulk_write(const uint8_t *buf, int len)
(void)i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, buf, len, NULL, 0, 1000); (void)i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, buf, len, NULL, 0, 1000);
i2cReleaseBus(&I2CD1); i2cReleaseBus(&I2CD1);
} }
#if 0 #if 0
static void si5351_bulk_read(uint8_t reg, uint8_t* buf, int len) static bool si5351_bulk_read(uint8_t reg, uint8_t* buf, int len)
{ {
int addr = SI5351_I2C_ADDR>>1;
i2cAcquireBus(&I2CD1); i2cAcquireBus(&I2CD1);
msg_t mr = i2cMasterTransmitTimeout(&I2CD1, addr, &reg, 1, buf, len, 1000); msg_t mr = i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, &reg, 1, buf, len, 1000);
i2cReleaseBus(&I2CD1); i2cReleaseBus(&I2CD1);
return mr == MSG_OK;
}
static void si5351_wait_pll_lock(void)
{
uint8_t status;
int count = 100;
do{
status=0xFF;
si5351_bulk_read(0, &status, 1);
if ((status & 0x60) == 0) // PLLA and PLLB locked
return;
}while (--count);
} }
#endif #endif
@ -118,7 +150,7 @@ static void si5351_reset_pll(uint8_t mask)
{ {
// Writing a 1<<5 will reset PLLA, 1<<7 reset PLLB, this is a self clearing bits. // Writing a 1<<5 will reset PLLA, 1<<7 reset PLLB, this is a self clearing bits.
// !!! Need delay before reset PLL for apply PLL freq changes before // !!! Need delay before reset PLL for apply PLL freq changes before
chThdSleepMicroseconds(400); chThdSleepMicroseconds(DELAY_RESET_PLL);
si5351_write(SI5351_REG_177_PLL_RESET, mask | 0x0C); si5351_write(SI5351_REG_177_PLL_RESET, mask | 0x0C);
} }
@ -335,14 +367,6 @@ static inline uint8_t si5351_getBand(uint32_t freq){
return 3; return 3;
} }
// Minimum value is 2, freq change apply at next dsp measure, and need skip it
#define DELAY_NORMAL 2
// Additional delay for band 1 (remove unstable generation at begin)
#define DELAY_BAND_1 1
// Band changes need additional delay after reset PLL
#define DELAY_BANDCHANGE_1 2
#define DELAY_BANDCHANGE_2 2
/* /*
* Maximum supported frequency = FREQ_HARMONICS * 9U * Maximum supported frequency = FREQ_HARMONICS * 9U
* configure output as follows: * configure output as follows:
@ -351,16 +375,21 @@ static inline uint8_t si5351_getBand(uint32_t freq){
* CLK2: fixed 8MHz * CLK2: fixed 8MHz
*/ */
int int
si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength){ si5351_set_frequency_with_offset(uint32_t freq, uint8_t drive_strength){
uint8_t band; uint8_t band;
int delay = DELAY_NORMAL; int delay = DELAY_NORMAL;
if (freq == current_freq) if (freq == current_freq)
return delay; return delay;
uint32_t ofreq = freq + offset; else if (current_freq > freq) // Reset band on sweep begin (if set range 150-600, fix error then 600 MHz band 2 or 3 go back)
current_band = 0;
current_freq = freq;
uint32_t ofreq = freq + current_offset;
uint32_t mul = 1, omul = 1; uint32_t mul = 1, omul = 1;
uint32_t rdiv = SI5351_R_DIV_1; uint32_t rdiv = SI5351_R_DIV_1;
uint32_t fdiv; uint32_t fdiv;
current_freq = freq; // Fix possible incorrect input
drive_strength&=SI5351_CLK_DRIVE_STRENGTH_MASK;
if (freq >= config.harmonic_freq_threshold * 7U) { if (freq >= config.harmonic_freq_threshold * 7U) {
mul = 9; mul = 9;
omul = 11; omul = 11;
@ -383,7 +412,6 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng
freq<<= 3; freq<<= 3;
ofreq<<= 3; ofreq<<= 3;
} }
band = si5351_getBand(freq/mul); band = si5351_getBand(freq/mul);
switch (band) { switch (band) {
case 1: case 1:
@ -391,12 +419,13 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng
if (current_band != 1){ if (current_band != 1){
si5351_setupPLL(SI5351_REG_PLL_A, PLL_N, 0, 1); si5351_setupPLL(SI5351_REG_PLL_A, PLL_N, 0, 1);
si5351_set_frequency_fixedpll(2, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_A); si5351_set_frequency_fixedpll(2, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_A);
delay+=DELAY_BANDCHANGE_1; delay=DELAY_BANDCHANGE_1;
} }
else
delay=DELAY_BAND_1;
// Calculate and set CH0 and CH1 divider // Calculate and set CH0 and CH1 divider
si5351_set_frequency_fixedpll(0, (uint64_t)omul * XTALFREQ * PLL_N, ofreq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A); si5351_set_frequency_fixedpll(0, (uint64_t)omul * XTALFREQ * PLL_N, ofreq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A);
si5351_set_frequency_fixedpll(1, (uint64_t) mul * XTALFREQ * PLL_N, freq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A); si5351_set_frequency_fixedpll(1, (uint64_t) mul * XTALFREQ * PLL_N, freq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A);
delay+=DELAY_BAND_1;
break; break;
case 2:// fdiv = 6 case 2:// fdiv = 6
case 3:// fdiv = 4; case 3:// fdiv = 4;
@ -405,8 +434,10 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng
if (current_band != band){ if (current_band != band){
si5351_setupMultisynth(0, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength|SI5351_CLK_PLL_SELECT_A); si5351_setupMultisynth(0, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength|SI5351_CLK_PLL_SELECT_A);
si5351_setupMultisynth(1, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength|SI5351_CLK_PLL_SELECT_B); si5351_setupMultisynth(1, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength|SI5351_CLK_PLL_SELECT_B);
delay+=DELAY_BANDCHANGE_2; delay=DELAY_BANDCHANGE_2;
} }
else
delay=DELAY_BAND_2;
// Calculate and set CH0 and CH1 PLL freq // Calculate and set CH0 and CH1 PLL freq
si5351_setupPLL_freq(SI5351_REG_PLL_A, ofreq, fdiv, omul);// set PLLA freq = (ofreq/omul)*fdiv si5351_setupPLL_freq(SI5351_REG_PLL_A, ofreq, fdiv, omul);// set PLLA freq = (ofreq/omul)*fdiv
si5351_setupPLL_freq(SI5351_REG_PLL_B, freq, fdiv, mul);// set PLLB freq = ( freq/ mul)*fdiv si5351_setupPLL_freq(SI5351_REG_PLL_B, freq, fdiv, mul);// set PLLB freq = ( freq/ mul)*fdiv
@ -414,7 +445,6 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng
si5351_set_frequency_fixedpll(2, (uint64_t)freq*fdiv, CLK2_FREQUENCY*mul, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_B); si5351_set_frequency_fixedpll(2, (uint64_t)freq*fdiv, CLK2_FREQUENCY*mul, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_B);
break; break;
} }
if (current_band != band) { if (current_band != band) {
si5351_reset_pll(SI5351_PLL_RESET_A|SI5351_PLL_RESET_B); si5351_reset_pll(SI5351_PLL_RESET_A|SI5351_PLL_RESET_B);
current_band = band; current_band = band;

View file

@ -72,4 +72,8 @@ void si5351_init(void);
void si5351_disable_output(void); void si5351_disable_output(void);
void si5351_enable_output(void); void si5351_enable_output(void);
//void si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength); //void si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength);
int si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength);
void si5351_set_frequency_offset(int32_t offset);
int si5351_set_frequency_with_offset(uint32_t freq, uint8_t drive_strength);
uint32_t si5351_getFrequency(void);

38
ui.c
View file

@ -767,7 +767,7 @@ menu_marker_search_cb(int item, uint8_t data)
if (i != -1) if (i != -1)
markers[active_marker].index = i; markers[active_marker].index = i;
draw_menu(); draw_menu();
redraw_marker(active_marker, TRUE); redraw_marker(active_marker);
select_lever_mode(LM_SEARCH); select_lever_mode(LM_SEARCH);
} }
@ -776,7 +776,7 @@ menu_marker_smith_cb(int item, uint8_t data)
{ {
(void)item; (void)item;
marker_smith_format = data; marker_smith_format = data;
redraw_marker(active_marker, TRUE); redraw_marker(active_marker);
draw_menu(); draw_menu();
} }
@ -822,7 +822,7 @@ menu_marker_sel_cb(int item, uint8_t data)
} else if (item == 5) { /* marker delta */ } else if (item == 5) { /* marker delta */
uistat.marker_delta = !uistat.marker_delta; uistat.marker_delta = !uistat.marker_delta;
} }
redraw_marker(active_marker, TRUE); redraw_marker(active_marker);
draw_menu(); draw_menu();
} }
@ -1250,9 +1250,9 @@ draw_keypad(void)
static void static void
draw_numeric_area_frame(void) draw_numeric_area_frame(void)
{ {
ili9341_fill(0, 240-NUM_INPUT_HEIGHT, 320, NUM_INPUT_HEIGHT, DEFAULT_MENU_COLOR); ili9341_fill(0, 240-NUM_INPUT_HEIGHT, 320, NUM_INPUT_HEIGHT, config.menu_normal_color);
setForegroundColor(DEFAULT_MENU_TEXT_COLOR); setForegroundColor(DEFAULT_MENU_TEXT_COLOR);
setBackgroundColor(DEFAULT_MENU_COLOR); setBackgroundColor(config.menu_normal_color);
ili9341_drawstring(keypad_mode_label[keypad_mode], 10, 240-(FONT_GET_HEIGHT+NUM_INPUT_HEIGHT)/2); ili9341_drawstring(keypad_mode_label[keypad_mode], 10, 240-(FONT_GET_HEIGHT+NUM_INPUT_HEIGHT)/2);
//ili9341_drawfont(KP_KEYPAD, 300, 216); //ili9341_drawfont(KP_KEYPAD, 300, 216);
} }
@ -1267,7 +1267,7 @@ draw_numeric_input(const char *buf)
for (i = 0, x = 64; i < 10 && buf[i]; i++, xsim<<=1) { for (i = 0, x = 64; i < 10 && buf[i]; i++, xsim<<=1) {
uint16_t fg = DEFAULT_MENU_TEXT_COLOR; uint16_t fg = DEFAULT_MENU_TEXT_COLOR;
uint16_t bg = DEFAULT_MENU_COLOR; uint16_t bg = config.menu_normal_color;
int c = buf[i]; int c = buf[i];
if (c == '.') if (c == '.')
c = KP_PERIOD; c = KP_PERIOD;
@ -1294,7 +1294,7 @@ draw_numeric_input(const char *buf)
x += xsim&0x8000 ? NUM_FONT_GET_WIDTH+2+8 : NUM_FONT_GET_WIDTH+2; x += xsim&0x8000 ? NUM_FONT_GET_WIDTH+2+8 : NUM_FONT_GET_WIDTH+2;
} }
// erase last // erase last
ili9341_fill(x, 240-NUM_INPUT_HEIGHT+4, NUM_FONT_GET_WIDTH+2+8, NUM_FONT_GET_WIDTH+2+8, DEFAULT_MENU_COLOR); ili9341_fill(x, 240-NUM_INPUT_HEIGHT+4, NUM_FONT_GET_WIDTH+2+8, NUM_FONT_GET_WIDTH+2+8, config.menu_normal_color);
} }
static int static int
@ -1639,18 +1639,18 @@ lever_move_marker(int status)
if ((status & EVT_DOWN) && markers[active_marker].index > 0) { if ((status & EVT_DOWN) && markers[active_marker].index > 0) {
markers[active_marker].index--; markers[active_marker].index--;
markers[active_marker].frequency = frequencies[markers[active_marker].index]; markers[active_marker].frequency = frequencies[markers[active_marker].index];
redraw_marker(active_marker, FALSE); redraw_marker(active_marker);
} }
if ((status & EVT_UP) && markers[active_marker].index < 100) { if ((status & EVT_UP) && markers[active_marker].index < sweep_points-1) {
markers[active_marker].index++; markers[active_marker].index++;
markers[active_marker].frequency = frequencies[markers[active_marker].index]; markers[active_marker].frequency = frequencies[markers[active_marker].index];
redraw_marker(active_marker, FALSE); redraw_marker(active_marker);
} }
} }
status = btn_wait_release(); status = btn_wait_release();
} while (status != 0); } while (status != 0);
if (active_marker >= 0) if (active_marker >= 0)
redraw_marker(active_marker, TRUE); redraw_marker(active_marker);
} }
static void static void
@ -1664,7 +1664,7 @@ lever_search_marker(int status)
i = marker_search_right(markers[active_marker].index); i = marker_search_right(markers[active_marker].index);
if (i != -1) if (i != -1)
markers[active_marker].index = i; markers[active_marker].index = i;
redraw_marker(active_marker, TRUE); redraw_marker(active_marker);
} }
} }
@ -2067,7 +2067,7 @@ drag_marker(int t, int m)
if (index >= 0) { if (index >= 0) {
markers[m].index = index; markers[m].index = index;
markers[m].frequency = frequencies[index]; markers[m].frequency = frequencies[index];
redraw_marker(m, TRUE); redraw_marker(m);
} }
} while(touch_check()!=EVT_TOUCH_RELEASED); } while(touch_check()!=EVT_TOUCH_RELEASED);
} }
@ -2097,7 +2097,7 @@ touch_pickup_marker(void)
if (active_marker != m) { if (active_marker != m) {
previous_marker = active_marker; previous_marker = active_marker;
active_marker = m; active_marker = m;
redraw_marker(active_marker, TRUE); redraw_marker(active_marker);
} }
// select trace // select trace
uistat.current_trace = t; uistat.current_trace = t;
@ -2142,21 +2142,19 @@ void ui_process_touch(void)
if (status == EVT_TOUCH_PRESSED || status == EVT_TOUCH_DOWN) { if (status == EVT_TOUCH_PRESSED || status == EVT_TOUCH_DOWN) {
switch (ui_mode) { switch (ui_mode) {
case UI_NORMAL: case UI_NORMAL:
// Try drag marker
if (touch_pickup_marker()) if (touch_pickup_marker())
break; break;
// Try select lever mode (top and bottom screen)
if (touch_lever_mode_select()) { if (touch_lever_mode_select()) {
draw_all(FALSE);
touch_wait_release(); touch_wait_release();
break; break;
} }
// switch menu mode after release
touch_wait_release(); touch_wait_release();
selection = -1; // hide keyboard mode selection
// switch menu mode
selection = -1;
ui_mode_menu(); ui_mode_menu();
break; break;
case UI_MENU: case UI_MENU:
menu_apply_touch(); menu_apply_touch();
break; break;