diff --git a/main.c b/main.c index 505f412..ae9e8b1 100644 --- a/main.c +++ b/main.c @@ -54,9 +54,9 @@ typedef void (*vna_shellcmd_t)(int argc, char *argv[]); static void command_name(int argc, char *argv[]) // Shell command line buffer, args, nargs, and function ptr -static char shell_line[VNA_SHELL_MAX_LENGTH]; -static char *shell_args[VNA_SHELL_MAX_ARGUMENTS + 1]; -static uint16_t shell_nargs; +char shell_line[VNA_SHELL_MAX_LENGTH]; +char *shell_args[VNA_SHELL_MAX_ARGUMENTS + 1]; +uint16_t shell_nargs; static volatile vna_shellcmd_t shell_function = 0; //#define ENABLED_DUMP @@ -124,6 +124,9 @@ void clear_backup(void) { *f++ = 0; } +#ifdef __USE_SD_CARD__ +systime_t last_auto_save = 0; +#endif #ifdef TINYSA4 static THD_WORKING_AREA(waThread1, 1224); @@ -194,6 +197,16 @@ static THD_FUNCTION(Thread1, arg) #endif { completed = sweep(true); +#ifdef __USE_SD_CARD__ + if (setting.trigger_auto_save && (last_auto_save == 0 || chVTGetSystemTimeX() - last_auto_save > S2ST(30)) ) { // once every 30 seconds max + uint16_t old_mode = config._mode; + config._mode |= _MODE_AUTO_FILENAME; + save_csv(1+(2<<0)); // frequencies + trace 1 + last_auto_save = chVTGetSystemTimeX(); + config._mode = old_mode; + } +#endif + if (sweep_once_count>1) { sweep_once_count--; } else @@ -388,6 +401,8 @@ static int get_str_index(const char *v, const char *list) return -1; } + + VNA_SHELL_FUNCTION(cmd_pause) { (void)argc; @@ -421,6 +436,33 @@ VNA_SHELL_FUNCTION(cmd_resume) resume_sweep(); } +VNA_SHELL_FUNCTION(cmd_wait) +{ + (void)argc; + (void)argv; + if (argc == 1 && argv[0][0] == '?') { + usage_printf("wait {seconds}\r\n"); + return; + } + break_execute = false; + drawMessageBox("Info", "Waiting", 0) ; + if (argc == 1) { + uint32_t t = my_atoi(argv[0]); + while (t > 0 && !break_execute) { + chThdSleepMilliseconds(1000); + t -= 1; + } + } else { + pause_sweep(); + resume_once(1) ; + while (!is_paused() && !break_execute) { + chThdSleepMilliseconds(100); + } + } + redraw_request|= REDRAW_AREA|REDRAW_FREQUENCY; + draw_all(true); +} + VNA_SHELL_FUNCTION(cmd_repeat) { (void)argc; @@ -1144,7 +1186,7 @@ config_t config = { }; -const int to_calibrate[5] = {8,9,10,11,12}; +const int to_calibrate[6] = {9,10,11,12,13,14}; //properties_t current_props; //properties_t *active_props = ¤t_props; @@ -2278,6 +2320,7 @@ static const VNAShellCommand commands[] = {"touchtest" , cmd_touchtest , CMD_WAIT_MUTEX}, {"pause" , cmd_pause , CMD_WAIT_MUTEX | CMD_RUN_IN_LOAD}, {"resume" , cmd_resume , CMD_WAIT_MUTEX | CMD_RUN_IN_LOAD}, + {"wait" , cmd_wait , CMD_RUN_IN_LOAD}, // This lets the sweep continue {"repeat" , cmd_repeat , CMD_RUN_IN_LOAD}, {"status" , cmd_status , CMD_RUN_IN_LOAD}, {"caloutput" , cmd_caloutput , CMD_RUN_IN_LOAD}, @@ -2585,7 +2628,7 @@ int parse_line(char *line, char* args[], int max_cnt) { return nargs; } -static const VNAShellCommand *VNAShell_parceLine(char *line){ +const VNAShellCommand *VNAShell_parceLine(char *line){ // Parse and execute line shell_nargs = parse_line(line, shell_args, ARRAY_COUNT(shell_args)); if (shell_nargs > ARRAY_COUNT(shell_args)) { @@ -2627,7 +2670,7 @@ static int VNAShell_readLine(char *line, int max_size) } // Others (skip) or too long - skip if (c < ' ' || j >= max_size - 1) continue; - streamPut(shell_stream, c); // Echo + if (shell_stream) streamPut(shell_stream, c); // Echo line[j++] = (char)c; } return 0; diff --git a/nanovna.h b/nanovna.h index 61899fe..544b69b 100644 --- a/nanovna.h +++ b/nanovna.h @@ -422,7 +422,7 @@ void set_auto_reflevel(bool); int is_paused(void); float set_actual_power(float); void set_actual_correction_value(int current_curve,int current_curve_index, float local_actual_level); -extern const int to_calibrate[5]; +extern const int to_calibrate[6]; void SetGenerate(int); void set_RBW(uint32_t rbw_x10); #ifdef __VBW__ @@ -575,6 +575,7 @@ extern uint16_t _grid_y; #define GRIDY _grid_y extern uint16_t graph_bottom; #ifdef TINYSA4 +#define SUPER_WATERFALL 90 #define BIG_WATERFALL 180 #define SMALL_WATERFALL 240 #define BIG_NUMBER_SPACE BIG_WATERFALL @@ -1224,6 +1225,9 @@ typedef struct setting uint8_t trigger_direction; // enum #ifdef __BEEP__ uint8_t trigger_beep; +#endif +#ifdef TINYSA4 + uint8_t trigger_auto_save; #endif uint8_t step_delay_mode; // enum uint8_t waterfall; // enum @@ -1329,6 +1333,7 @@ typedef struct setting int32_t exp_aver; bool increased_R; bool mixer_output; + uint32_t interval; #endif int64_t test_argument; // used for tests uint32_t checksum; // must be last and at 4 byte boundary @@ -1349,7 +1354,7 @@ enum { S_OFF=0, S_ON=1, S_AUTO_OFF=2, S_AUTO_ON=3 }; enum { SD_NORMAL, SD_PRECISE, SD_FAST, SD_NOISE_SOURCE, SD_MANUAL }; -enum {W_OFF, W_SMALL, W_BIG}; +enum {W_OFF, W_SMALL, W_BIG, W_SUPER}; #ifdef __FAST_SWEEP__ #define MINIMUM_SWEEP_TIME 1800U // Minimum sweep time on zero span in uS @@ -1573,6 +1578,7 @@ extern int si5351_available; #define OP_CONSOLE 0x04 //#define OP_FREQCHANGE 0x04 extern volatile uint8_t operation_requested; +extern volatile uint8_t break_execute; // lever_mode enum lever_mode { @@ -1705,6 +1711,8 @@ void SD_PowerOff(void); #endif void testLog(void); // debug log void sd_card_load_config(char *filename); +extern systime_t last_auto_save; +void save_csv(uint8_t mask); #endif /* @@ -1816,7 +1824,7 @@ enum { #define MEASUREMENT_TEXT "OFF","HARM","OIP3","PN","SNR","PASS","LIN","AM","FM","THD","CP","NF T","NF S","NF V","NF A", "DECONF" enum { - T_AUTO, T_NORMAL, T_SINGLE, T_DONE, T_UP, T_DOWN, T_MODE, T_PRE, T_POST, T_MID, T_BEEP, + T_AUTO, T_NORMAL, T_SINGLE, T_DONE, T_UP, T_DOWN, T_MODE, T_PRE, T_POST, T_MID, T_BEEP, T_AUTO_SAVE, }; //!!! Warning can show not correct results on CH_CFG_ST_FREQUENCY not round by 1000 or > 1000000UL diff --git a/plot.c b/plot.c index 97dae45..9e23deb 100644 --- a/plot.c +++ b/plot.c @@ -2257,6 +2257,9 @@ set_level_meter_or_waterfall(void) || setting.level_meter #endif ) graph_bottom = SMALL_WATERFALL; +#ifdef TINYSA4 + else if (setting.waterfall == W_SUPER) graph_bottom = SUPER_WATERFALL; +#endif else graph_bottom = NO_WATERFALL; _grid_y = graph_bottom / NGRIDY; area_height = AREA_HEIGHT_NORMAL; diff --git a/sa_core.c b/sa_core.c index 7d655d5..dfa2ea7 100644 --- a/sa_core.c +++ b/sa_core.c @@ -6338,8 +6338,9 @@ static volatile int test_wait = false; static float test_value; #ifdef TINYSA4 -static freq_t direct_test_freq = 0; +static freq_t direct_test_freq = 900000000; void determine_direct_test_freq(void) { + return; int old_ultra = config.ultra; config.ultra = true; float max_level = -150; @@ -6789,7 +6790,9 @@ common_silent: case TP_30MHZ_LNA: #endif case TP_30MHZ: +#ifdef TINYSA4 simple: +#endif set_mode(M_LOW); #ifdef TINYSA4 maxFreq = 9900000000ULL; // needed to measure the LPF rejection @@ -7920,13 +7923,13 @@ void calibrate(void) set_sweep_frequency(ST_CENTER, direct_test_freq); test_path = 4; // Direct path at 900MHz force_signal_path = true; - config.direct_level_offset -= 1.0; + // config.direct_level_offset -= 1.0; break; case CS_DIRECT_LNA: set_sweep_frequency(ST_CENTER, direct_test_freq); test_path = 5; // Direct lna path at 900MHz force_signal_path = true; - config.direct_lna_level_offset += 1.0; +// config.direct_lna_level_offset += 1.0; break; case CS_HARMONIC: test_path = 6; // harmonic path @@ -7942,11 +7945,13 @@ void calibrate(void) set_sweep_frequency(ST_CENTER, config.correction_frequency[1][to_calibrate[current_correction_calibration]]); test_path = 0; force_signal_path = true; + set_refer_output(2); break; case CS_CORRECTION_LNA: set_sweep_frequency(ST_CENTER, config.correction_frequency[1][to_calibrate[current_correction_calibration]]); test_path = 1; force_signal_path = true; + set_refer_output(2); break; #endif } @@ -8031,10 +8036,10 @@ low_level: else if (calibration_stage == CS_DIRECT_REF) direct_level = marker_to_value(0); else if (calibration_stage == CS_DIRECT){ - config.direct_level_offset += 1.0; +// config.direct_level_offset += 1.0; offset = set_actual_power(direct_level); } else if (calibration_stage == CS_DIRECT_LNA){ - config.direct_lna_level_offset -= 1.0; +// config.direct_lna_level_offset -= 1.0; offset = set_actual_power(direct_level); } else diff --git a/si4468.c b/si4468.c index 0a8b13d..d931fd6 100644 --- a/si4468.c +++ b/si4468.c @@ -1859,7 +1859,7 @@ static uint16_t buf_end = 0; static bool buf_read = false; static char Si446x_readRSSI(void){ - char rssi; + uint8_t rssi; #ifdef __USE_FRR_FOR_RSSI__ #if 0 // Restart RX, not needed as modem stays in RX mode SI4463_WAIT_CTS; // Wait for CTS @@ -1909,6 +1909,8 @@ static char Si446x_readRSSI(void){ data[0] = SI446X_CMD_GET_MODEM_STATUS; SI4463_do_api(data, 1, data, 3); rssi = data[2]; + if (rssi > 197) + rssi -= 1; #endif return rssi; } diff --git a/ui.c b/ui.c index 954be7f..91eace0 100644 --- a/ui.c +++ b/ui.c @@ -70,6 +70,7 @@ static uint16_t menu_button_height = MENU_BUTTON_HEIGHT_N(MENU_BUTTON_MIN); #endif volatile uint8_t operation_requested = OP_NONE; +volatile uint8_t break_execute = false; int8_t previous_marker = MARKER_INVALID; @@ -161,9 +162,9 @@ static void menu_move_back(bool leave_ui); static void draw_button(uint16_t x, uint16_t y, uint16_t w, uint16_t h, ui_button_t *b); //static const menuitem_t menu_marker_type[]; -#ifdef __USE_SD_CARD__ -static void save_csv(uint8_t mask); -#endif +//#ifdef __USE_SD_CARD__ +//svoid save_csv(uint8_t mask); +//#endif bool isFullScreenMode(void) { #ifdef __SD_FILE_BROWSER__ @@ -1390,6 +1391,7 @@ enum { #ifdef __USE_RTC__ KM_RTC_DATE, KM_RTC_TIME, + KM_INTERVAL, #endif #endif KM_CODE, @@ -1479,6 +1481,7 @@ static const struct { #ifdef __USE_RTC__ [KM_RTC_DATE] = {keypads_positive , "SET DATE\n YYMMDD"}, // Date [KM_RTC_TIME] = {keypads_positive , "SET TIME\n HHMMSS"}, // Time +[KM_INTERVAL] = {keypads_positive , "SET INTERVAL\n HHMMSS"}, // Interval #endif #endif [KM_CODE] = {keypads_positive , "CODE"}, // KM_CODE @@ -3363,7 +3366,12 @@ static UI_FUNCTION_ADV_CALLBACK(menu_waterfall_acb){ } else #endif { - setting.waterfall++; if (setting.waterfall>W_BIG)setting.waterfall = W_OFF; +#ifdef TINYSA4 +#define BIGGEST W_SUPER +#else +#define BIGGEST W_BIG +#endif + setting.waterfall++; if (setting.waterfall>BIGGEST)setting.waterfall = W_OFF; if (setting.waterfall != W_OFF) setting.level_meter = false; set_level_meter_or_waterfall(); @@ -3717,6 +3725,10 @@ static UI_FUNCTION_ADV_CALLBACK(menu_trigger_acb) #ifdef __BEEP__ else if (data == T_BEEP) b->icon = setting.trigger_beep ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; +#endif +#ifdef TINYSA4 + else if (data == T_AUTO_SAVE) + b->icon = setting.trigger_auto_save ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK; #endif else b->icon = setting.trigger == data ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP; @@ -3730,6 +3742,11 @@ static UI_FUNCTION_ADV_CALLBACK(menu_trigger_acb) #ifdef __BEEP__ } else if (data == T_BEEP) { setting.trigger_beep = !setting.trigger_beep; +#endif +#ifdef TINYSA4 + } else if (data == T_AUTO_SAVE) { + setting.trigger_auto_save = !setting.trigger_auto_save; + last_auto_save = 0; #endif } else if (data == T_UP || data == T_DOWN) { if (setting.trigger_direction == T_UP) @@ -5133,6 +5150,7 @@ static const menuitem_t menu_trigger[] = { #ifdef __BEEP__ { MT_ADV_CALLBACK, T_BEEP, "BEEP", menu_trigger_acb}, #endif + { MT_ADV_CALLBACK, T_AUTO_SAVE, "AUTO SAVE", menu_trigger_acb}, { MT_NONE, 0, NULL, menu_back} // next-> menu_back }; @@ -5184,8 +5202,9 @@ static const menuitem_t menu_storage[] = { { MT_CALLBACK, FMT_BMP_FILE, "SAVE\nCAPTURE", menu_sdcard_cb}, { MT_CALLBACK, FMT_PRS_FILE, "SAVE\nSETTINGS", menu_sdcard_cb}, { MT_CALLBACK, FMT_CFG_FILE, "SAVE\nCONFIG", menu_sdcard_cb}, - { MT_ADV_CALLBACK, 0, "MHz\nCSV", menu_mhz_csv_acb }, + { MT_ADV_CALLBACK, 0, "MHz\nCSV", menu_mhz_csv_acb }, { MT_CALLBACK, FMT_CSV_FILE, "SAVE\nTRACES", menu_save_traces_cb}, + { MT_KEYPAD, KM_INTERVAL, "INTERVAL\n\b%s", NULL }, { MT_NONE, 0, NULL, menu_back} // next-> menu_back }; #endif @@ -5527,13 +5546,22 @@ static void fetch_numeric_target(uint8_t mode) break; #endif #ifdef __USE_RTC__ + case KM_INTERVAL: + { + uint32_t interv = setting.interval; + plot_printf(uistat.text, sizeof uistat.text, "%02d:%02d:%02d", + interv / (60*60), + (interv / 60) % 60, + interv % 60); + } + break; case KM_RTC_TIME: { uint32_t tr = rtc_get_tr_bin(); // TR read first plot_printf(uistat.text, sizeof uistat.text, "%02d:%02d:%02d", - RTC_TR_HOUR(dr), - RTC_TR_MIN(dr), - RTC_TR_SEC(dr)); + RTC_TR_HOUR(tr), + RTC_TR_MIN(tr), + RTC_TR_SEC(tr)); } break; case KM_RTC_DATE: @@ -5804,6 +5832,15 @@ set_numeric_value(void) break; #endif #ifdef __USE_RTC__ + case KM_INTERVAL: + { + int i=0; + for (; i < 6 && kp_buf[i]!=0; i++) kp_buf[i]-= '0'; + for (; i < 6 ; i++) kp_buf[i] = 0; + setting.interval = (60*60)*(kp_buf[0]*10+kp_buf[1]) + 60*(kp_buf[2]*10+kp_buf[3]) + (kp_buf[4]*10+kp_buf[5]); +// set_autosave(); + } + break; case KM_RTC_DATE: case KM_RTC_TIME: { @@ -7809,7 +7846,7 @@ static void sa_save_file(uint8_t format) { ui_mode_normal(); } -static void save_csv(uint8_t mask) { +void save_csv(uint8_t mask) { file_mask = mask; menu_sdcard_cb(0, FMT_CSV_FILE); } @@ -7960,11 +7997,42 @@ void ui_process_touch(void) } } + + static uint16_t previous_button_state = 0; +#ifdef TINYSA4 +uint64_t time_since_start = 0; +uint64_t interval_stop_time = 0; + +systime_t old_ticks; +void set_interval_stop_time(void) +{ + if (setting.interval == 0) { + interval_stop_time = 0; + } else { + interval_stop_time = time_since_start + CH_CFG_ST_FREQUENCY * (uint64_t)setting.interval; + } +} +#endif + + void ui_process(void) { +#ifdef TINYSA4 + systime_t ticks = chVTGetSystemTimeX(); + if (ticks < old_ticks) + time_since_start += 0x100000000; + old_ticks = ticks; + time_since_start = (time_since_start & 0xffffffff00000000) | ticks; + + if (interval_stop_time != 0 && interval_stop_time < time_since_start) { + set_interval_stop_time(); + } + +#endif + int button_state = READ_PORT() & BUTTON_MASK; if (ui_mode == UI_NORMAL && current_menu_is_form()) { // Force into menu mode selection = -1; // hide keyboard mode selection @@ -7991,8 +8059,10 @@ static void extcb1(EXTDriver *extp, expchannel_t channel) if (channel == 12) SD_PowerOff(); #endif - if (channel < 9) + if (channel < 9) { operation_requested|=OP_LEVER; + break_execute = true; + } // cur_button = READ_PORT() & BUTTON_MASK; } diff --git a/vna_browser.c b/vna_browser.c index b675997..49a2eb7 100644 --- a/vna_browser.c +++ b/vna_browser.c @@ -104,7 +104,8 @@ repeat: // Delete file if in delete mode if (sel_mode) {f_unlink(fno.fname); return;} - +run_file: + {} const char *error = NULL; bool leave_show = true; UINT size; @@ -242,17 +243,31 @@ static char cmd_buffer[256+128]; char *buf_8 = cmd_buffer; // (char *)spi_buffer; // must be greater then buffer_size + line_size char *line = buf_8 + buffer_size; uint16_t j = 0, i; + break_execute = false; while (f_read(fs_file, buf_8, buffer_size, &size) == FR_OK && size > 0) { for (i = 0; i < size; i++) { + if (break_execute) goto done; uint8_t c = buf_8[i]; if (c == '\r') { // New line (Enter) line[j] = 0; j = 0; + if (line[0] == 'r' && line[1] == 'u' && line[2] == 'n') { + j = 4; + while (line[j] == ' ' || line[j] == '"') + j++; + i = 0; + while (line[j] != '"' && line[j] != 0) + fno.fname[i++] = line[j++]; + fno.fname[i] = 0; + f_close(fs_file); + goto run_file; + } shell_executeCMDLine(line); } else if (c < 0x20) continue; // Others (skip) else if (j < line_size) line[j++] = (char)c; // Store } } + done: break; } /*