diff --git a/nanovna.h b/nanovna.h index f6a08be..54a3144 100644 --- a/nanovna.h +++ b/nanovna.h @@ -213,6 +213,7 @@ extern uint8_t signal_is_AM; extern const int reffer_freq[]; extern uint32_t minFreq; extern uint32_t maxFreq; +extern uint32_t lpf_switch; int level_is_calibrated(void); void reset_settings(int); void update_min_max_freq(void); @@ -826,6 +827,7 @@ typedef struct setting int32_t slider_span; int extra_lna; int ultra; + int R; uint32_t checksum; // must be last }setting_t; @@ -1137,6 +1139,8 @@ extern void ADF4351_mux(int R); extern void ADF4351_force_refresh(void); extern void ADF4351_CP(int p); extern void ADF4351_modulo(int m); +extern void ADF4351_csr(int c); +extern void ADF4351_fastlock(int c); extern int SI4463_R; extern volatile int64_t ADF4350_modulo; extern void SI446x_set_AGC_LNA(uint8_t v); diff --git a/sa_core.c b/sa_core.c index 3330f2b..e284f11 100644 --- a/sa_core.c +++ b/sa_core.c @@ -21,7 +21,7 @@ #include "stdlib.h" #pragma GCC push_options -#pragma GCC optimize ("Os") +#pragma GCC optimize ("Og") //#define __DEBUG_AGC__ If set the AGC value will be shown in the stored trace and FAST_SWEEP rmmode will be disabled @@ -40,6 +40,7 @@ uint16_t actual_rbw_x10 = 0; uint16_t vbwSteps = 1; uint32_t minFreq = 0; uint32_t maxFreq = 520000000; +uint32_t lpf_switch = 600000000; static unsigned long old_freq[5] = { 0, 0, 0, 0,0}; static unsigned long real_old_freq[5] = { 0, 0, 0, 0,0}; @@ -73,7 +74,7 @@ void update_min_max_freq(void) maxFreq = HIGH_MAX_FREQ_MHZ * 1000000; break; case M_GENHIGH: -//#define __HIGH_OUT_ADF4351__ +#define __HIGH_OUT_ADF4351__ #ifdef __HIGH_OUT_ADF4351__ minFreq = 135000000; maxFreq = 4290000000U; @@ -136,6 +137,7 @@ void reset_settings(int m) setting.level = -15.0; setting.trigger_level = -150.0; setting.linearity_step = 0; +// setting.R = 0; // Automatic setting of R trace[TRACE_STORED].enabled = false; trace[TRACE_TEMP].enabled = false; // setting.refer = -1; // do not reset reffer when switching modes @@ -451,8 +453,11 @@ void set_IF2(int f) void set_R(int f) { - ADF4351_R_counter(f % 10); - ADF4351_spur_mode(f/10); + setting.R = f; + ADF4351_R_counter(f % 1000); + ADF4351_spur_mode(f/1000); + ADF4351_force_refresh(); + old_freq[ADF4351_LO] = 0; dirty = true; } @@ -460,7 +465,9 @@ void set_modulo(uint32_t f) { ADF4351_modulo(f); ADF4351_force_refresh(); + old_freq[ADF4351_LO] = 0; ADF4351_set_frequency(0, real_old_freq[ADF4351_LO]); + dirty = true; } #endif @@ -1080,7 +1087,7 @@ void calculate_step_delay(void) else { SI4432_step_delay = 15000; SI4432_offset_delay =5000; } #endif if (setting.step_delay_mode == SD_PRECISE) // In precise mode wait twice as long for RSSI to stabalize - SI4432_step_delay *= 2; + SI4432_step_delay += (SI4432_step_delay>>2) ; if (setting.fast_speedup >0) SI4432_offset_delay = SI4432_step_delay / setting.fast_speedup; } @@ -1313,7 +1320,7 @@ void set_freq(int V, unsigned long freq) // translate the requested frequency if (freq) { real_old_freq[V] = ADF4351_set_frequency(V-ADF4351_LO,freq); } - } else if (V==ADF4351_LO2){ + } else if (V==ADF4351_LO2) { real_old_freq[V] = ADF4351_set_frequency(V-ADF4351_LO, freq); } else if (V==SI4463_RX) { if (setting.step_delay_mode == SD_FAST) { // If in extra fast scanning mode and NOT SI4432_RX !!!!!! @@ -1581,7 +1588,7 @@ void update_rbw(void) // calculate the actual_rbw and the vbwSteps (# temp_actual_rbw_x10 = setting.vbw_x10; #endif } else - temp_actual_rbw_x10 = 2*setting.vbw_x10; // rbw is twice the frequency step to ensure no gaps in coverage + temp_actual_rbw_x10 = setting.vbw_x10; // rbw is NOT twice the frequency step to ensure no gaps in coverage } #ifdef __SI4432__ if (temp_actual_rbw_x10 < 26) @@ -1607,8 +1614,8 @@ void update_rbw(void) // calculate the actual_rbw and the vbwSteps (# // actual_rbw_x10 = 3000; // if spur suppression reduce max rbw to fit within BPF #endif actual_rbw_x10 = set_rbw(actual_rbw_x10); // see what rbw the SI4432 can realize - if (setting.frequency_step > 0 && MODE_INPUT(setting.mode)) { // When doing frequency scanning in input mode - vbwSteps = ((int)(2 * (setting.vbw_x10 + (actual_rbw_x10/2)) / actual_rbw_x10)); // calculate # steps in between each frequency step due to rbw being less than frequency step + if (setting.vbw_x10 > actual_rbw_x10 && setting.frequency_step > 0 && MODE_INPUT(setting.mode)) { // When doing frequency scanning in input mode + vbwSteps = (setting.vbw_x10 / actual_rbw_x10 ) + 1; //((int)(2 * (setting.vbw_x10 + (actual_rbw_x10/8)) / actual_rbw_x10)); // calculate # steps in between each frequency step due to rbw being less than frequency step if (setting.step_delay_mode==SD_PRECISE) // if in Precise scanning vbwSteps *= 2; // use twice as many steps if (vbwSteps < 1) // at least one step @@ -1727,8 +1734,10 @@ static const unsigned int spur_alternate_IF = DEFAULT_SPUR_IF; // if the static const int spur_table[] = // Frequencies to avoid { 117716000, + 487500000, + 650700000, 746083000, -// 1956000000, + // 1956000000, #if 0 // 580000, // 433.8 MHz table // 880000, //? @@ -2005,7 +2014,7 @@ modulation_again: } // -------------- set ultra --------------------------------- if (setting.mode == M_LOW && config.ultra) { - if ((S_IS_AUTO(setting.ultra)&& f > 850000000U) || S_STATE(setting.ultra) ) { + if ((S_IS_AUTO(setting.ultra)&& f > lpf_switch) || S_STATE(setting.ultra) ) { enable_ultra(true); } else enable_ultra(false); @@ -2020,13 +2029,16 @@ modulation_again: do { uint32_t lf = f; if (vbwSteps > 1) { // Calculate sub steps - int offs_div10 = (t - (vbwSteps >> 1)) * 500 / 10; // steps of half the rbw + int offs_div10 = (t - (vbwSteps >> 1)) * 100; // steps of x10 * settings. if ((vbwSteps & 1) == 0) // Uneven steps, center - offs_div10+= 250 / 10; // Even, shift half step - int offs = offs_div10 * actual_rbw_x10; - if (setting.step_delay_mode == SD_PRECISE) - offs>>=1; // steps of a quarter rbw - lf += offs; + offs_div10+= 50; // Even, shift half step + int offs = (offs_div10 * (int32_t)setting.vbw_x10 )/ vbwSteps; + // if (setting.step_delay_mode == SD_PRECISE) + // offs>>=1; // steps of a quarter rbw + // if (lf > -offs) // No negative frequencies + lf += offs; + if (lf > 4000000000U) + lf = 0; } // -------------- Calculate the IF ----------------------------- @@ -2064,7 +2076,7 @@ modulation_again: } #ifdef __SI4468__ if (S_IS_AUTO(setting.spur_removal)) { - if (lf >= local_IF) { + if (lf >= lpf_switch) { setting.spur_removal= S_AUTO_ON; } else { setting.spur_removal= S_AUTO_OFF; @@ -2147,14 +2159,27 @@ modulation_again: local_IF = config.frequency_IF2; } -#if 0 - if (lf < 500000000 && 0) { - uint32_t tf = ((lf + actual_rbw_x10*200) / 26000000) * 26000000; - if (tf >= lf && tf < lf + actual_rbw_x10*200) - ADF4351_R_counter(6); - else - ADF4351_R_counter(1); +#if 1 +#define TCXO 30000000 +#define TXCO_DIV3 10000000 + + if (setting.R == 0) { + if (lf < 850000000 && lf >= TCXO) { + uint32_t tf = ((lf + actual_rbw_x10*100) / TCXO) * TCXO; + if (tf + actual_rbw_x10*100 >= lf && tf < lf + actual_rbw_x10*100) { +// ADF4351_R_counter(8); no impact + } else { + uint32_t tf = ((lf + actual_rbw_x10*100) / TXCO_DIV3) * TXCO_DIV3; + if (tf + actual_rbw_x10*100 >= lf && tf < lf + actual_rbw_x10*100) + ADF4351_R_counter(4); + else + ADF4351_R_counter(3); + } + } else + ADF4351_R_counter(3); } + else + ADF4351_R_counter(setting.R); #endif #if 0 uint32_t target_f; diff --git a/si4432.c b/si4432.c index afeca98..4740858 100644 --- a/si4432.c +++ b/si4432.c @@ -976,9 +976,9 @@ float Simulated_SI4432_RSSI(uint32_t i, int s) #define CS_ADF0_LOW palClearLine(LINE_LO_SEL) #define CS_ADF1_LOW palClearLine(LINE_LO_SEL) -//uint32_t registers[6] = {0x320000, 0x8008011, 0x4E42, 0x4B3,0x8C803C , 0x580005} ; //25 MHz ref +//uint32_t t_R[6] = {0x320000, 0x8008011, 0x4E42, 0x4B3,0x8C803C , 0x580005} ; //25 MHz ref #ifdef TINYSA4_PROTO -uint32_t registers[6] = {0xA00000, 0x8000011, 0x4042, 0x4B3,0xDC003C , 0x580005} ; //10 MHz ref +uint32_t registers[6] = {0xC80000, 0x8008011, 0x1800C642, 0x48963,0xA5003C , 0x580005} ; //10 MHz ref #else uint32_t registers[6] = {0xA00000, 0x8000011, 0x4E42, 0x4B3,0xDC003C , 0x580005} ; //10 MHz ref #endif @@ -996,24 +996,25 @@ int ADF4351_frequency_changed = false; #define DEBUGLN(X) #ifdef TINYSA4_PROTO -#define XTAL 30.0 +#define XTAL 30000000 #else -#define XTAL 26.0 +#define XTAL 26000000 #endif -double RFout, //Output freq in MHz - PFDRFout[6] = {XTAL,XTAL,XTAL,10.0,10.0,10.0}, //Reference freq in MHz - Chrystal[6] = {XTAL,XTAL,XTAL,10.0,10.0,10.0}, - FRACF; // Temp +//double RFout; //Output freq in MHz +uint64_t PFDRFout_x100[6] = {XTAL*100,XTAL*100,XTAL*100,10000000,10000000,10000000}; //Reference freq in MHz +uint64_t Chrystal[6] = {XTAL,XTAL,XTAL,10000000,10000000,10000000}; +//double FRACF; // Temp volatile int64_t INTA, // Temp - ADF4350_modulo = 260, + ADF4350_modulo = 64, MOD, target_freq, FRAC; //Temp uint8_t OutputDivider; // Temp uint8_t lock=2; //Not used +static int old_R = 0; // Lock = A4 @@ -1035,12 +1036,15 @@ void ADF4351_Setup(void) ADF4351_R_counter(1); - ADF4351_CP(1); + ADF4351_CP(0); + + ADF4351_fastlock(1); // Fastlock enabled + ADF4351_csr(1); //Cycle slip enabled ADF4351_set_frequency(0,200000000); - ADF4351_mux(2); // No led - // ADF4351_mux(6); // Show lock on led +// ADF4351_mux(2); // No led + ADF4351_mux(6); // Show lock on led // ADF4351_set_frequency(1,150000000,0); // ADF4351_Set(0); @@ -1140,7 +1144,6 @@ void ADF4351_spur_mode(int S) void ADF4351_R_counter(int R) { -static int old_R; if (R == old_R) return; old_R = R; @@ -1157,7 +1160,7 @@ static int old_R; bitClear (registers[2], 25); // Reference doubler } for (int channel=0; channel < 6; channel++) { - PFDRFout[channel] = Chrystal[channel] * (dbl?2:1) / R; + PFDRFout_x100[channel] = (100*Chrystal[channel] * (dbl?2:1)) / R; } registers[2] &= ~ (((unsigned long)0x3FF) << 14); registers[2] |= (((unsigned long)R) << 14); @@ -1171,6 +1174,20 @@ void ADF4351_mux(int R) ADF4351_Set(0); } +void ADF4351_csr(int c) +{ + registers[3] &= ~ (((unsigned long)0x1) << 18); + registers[3] |= (((unsigned long)c & (unsigned long)0x01) << 18); + ADF4351_Set(0); +} + +void ADF4351_fastlock(int c) +{ + registers[3] &= ~ (((unsigned long)0x3) << 15); + registers[3] |= (((unsigned long)c & (unsigned long)0x03) << 15); + ADF4351_Set(0); +} + void ADF4351_CP(int p) { registers[2] &= ~ (((unsigned long)0xF) << 9); @@ -1236,10 +1253,10 @@ uint64_t ADF4351_prep_frequency(int channel, uint64_t freq) // freq / 10Hz bitWrite (registers[4], 20, 0); } - volatile uint64_t PFDR = (int) (PFDRFout[channel]*1000000); - INTA = (((uint64_t)freq) * OutputDivider) / PFDR; + volatile uint64_t PFDR_x100 = PFDRFout_x100[channel]; + INTA = (((uint64_t)freq) * OutputDivider*100) / PFDR_x100; MOD = ADF4350_modulo; - FRAC = ((((uint64_t)freq) * OutputDivider) - INTA * PFDR + (PFDR / MOD / 2)) * (uint64_t) MOD /PFDR; + FRAC = ((((uint64_t)freq) * OutputDivider*100) - INTA * PFDR_x100 + (PFDR_x100 / MOD / 2)) * (uint64_t) MOD /PFDR_x100; if (FRAC >= MOD) { FRAC -= MOD; INTA++; @@ -1260,21 +1277,24 @@ uint64_t ADF4351_prep_frequency(int channel, uint64_t freq) // freq / 10Hz MOD=2; } #endif - uint64_t actual_freq = PFDR *(INTA * MOD +FRAC)/OutputDivider / MOD; - volatile int max_delta = 1000000 * PFDRFout[channel]/OutputDivider/MOD; + uint64_t actual_freq = PFDR_x100 *(INTA * MOD +FRAC)/OutputDivider / MOD/100; +#if 0 + volatile int max_delta = PFDRFout_x100[channel]/OutputDivider/MOD/100; if (actual_freq < freq - max_delta || actual_freq > freq + max_delta ){ while(1) my_microsecond_delay(10); } max_delta = freq - actual_freq; - if (max_delta > 100000 || max_delta < -100000 || freq == 0) { + if (max_delta > 200000 || max_delta < -200000 || freq == 0) { while(1) my_microsecond_delay(10); } +#endif if (FRAC >= MOD ){ while(1) my_microsecond_delay(10); } + registers[0] = 0; registers[0] = INTA << 15; // OK FRAC = FRAC << 3; @@ -1914,7 +1934,7 @@ int16_t Si446x_RSSI(void) 0xFF }; if (SI4432_step_delay && (ADF4351_frequency_changed || SI4463_frequency_changed)) { - my_microsecond_delay(SI4432_step_delay); + my_microsecond_delay(SI4432_step_delay * ((setting.R == 0 && old_R > 5 ) ? 8 : 1)); ADF4351_frequency_changed = false; SI4463_frequency_changed = false; } else if (SI4432_offset_delay && SI4463_offset_changed) { @@ -1922,7 +1942,7 @@ int16_t Si446x_RSSI(void) ADF4351_frequency_changed = false; SI4463_offset_changed = false; } -#define SAMPLE_COUNT 3 +#define SAMPLE_COUNT 1 int j = SAMPLE_COUNT; //setting.repeat; int RSSI_RAW_ARRAY[3]; do{ diff --git a/ui_sa.c b/ui_sa.c index b8cc625..fa322e4 100644 --- a/ui_sa.c +++ b/ui_sa.c @@ -412,7 +412,8 @@ enum { KM_COR_AM,KM_COR_WFM, KM_COR_NFM, #endif KM_ATTACK, - KM_IF2, + KM_IF2, + KM_LPF, KM_NONE // always at enum end }; @@ -456,7 +457,7 @@ static const struct { {keypads_positive , "MODULO"}, // KM_MOD {keypads_positive , "CP"}, // KM_CP {keypads_positive , "ATTACK"}, // KM_ATTACK - + {keypads_freq , "LPF"}, // KM_LPF }; #if 0 // Not used ui_slider_t ui_sliders [] = @@ -1373,7 +1374,7 @@ static UI_FUNCTION_ADV_CALLBACK(menu_outputmode_acb) } #ifdef TINYSA4 -static const uint16_t points_setting[] = {51, 101, 201, 450}; +static const uint16_t points_setting[] = {51, 101, 201, 290, 450}; #else static const uint16_t points_setting[] = {51, 101, 145, 290}; #endif @@ -1549,11 +1550,16 @@ static const menuitem_t menu_lowoutputmode[] = { static const menuitem_t menu_highoutputmode[] = { { MT_FORM | MT_ADV_CALLBACK, 0, "HIGH OUTPUT %s", menu_outputmode_acb}, + { MT_FORM | MT_SUBMENU, 255, S_RARROW" Settings", menu_settings3}, { MT_FORM | MT_KEYPAD, KM_CENTER, center_text, "240MHz..960MHz"}, { MT_FORM | MT_ADV_CALLBACK, 0, "LEVEL: %+ddBm", menu_sdrive_acb}, +#if 0 { MT_FORM | MT_ADV_CALLBACK, 0, "MOD: %s", menu_smodulation_acb}, { MT_FORM | MT_KEYPAD, KM_SPAN, "SPAN: %s", NULL}, { MT_FORM | MT_KEYPAD, KM_SWEEP_TIME,"SWEEP TIME: %s", "0..600 seconds"}, +#else + { MT_FORM | MT_ADV_CALLBACK, 0, "%s", menu_sweep_acb}, +#endif { MT_FORM | MT_KEYPAD, KM_OFFSET, "EXTERNAL AMP: %s", "-100..+100"}, { MT_FORM | MT_CANCEL, 0, "MODE", NULL }, { MT_FORM | MT_NONE, 0, NULL, NULL } // sentinel @@ -1755,6 +1761,7 @@ static const menuitem_t menu_sweep_points[] = { { MT_ADV_CALLBACK, 1, "%3d point", menu_points_acb }, { MT_ADV_CALLBACK, 2, "%3d point", menu_points_acb }, { MT_ADV_CALLBACK, 3, "%3d point", menu_points_acb }, + { MT_ADV_CALLBACK, 4, "%3d point", menu_points_acb }, { MT_CANCEL, 0, S_LARROW" BACK", NULL }, { MT_NONE, 0, NULL, NULL } // sentinel }; @@ -1775,6 +1782,7 @@ static const menuitem_t menu_settings3[] = { { MT_KEYPAD, KM_10MHZ, "CORRECT\nFREQUENCY", "Enter actual lMHz frequency"}, { MT_KEYPAD, KM_GRIDLINES, "MINIMUM\nGRIDLINES", "Enter minimum horizontal grid divisions"}, + { MT_KEYPAD, KM_LPF, "LPF", "Enter LPF max freq"}, #if 0 // only used during development { MT_KEYPAD, KM_COR_AM, "COR\nAM", "Enter AM modulation correction"}, { MT_KEYPAD, KM_COR_WFM, "COR\nWFM", "Enter WFM modulation correction"}, @@ -2169,6 +2177,10 @@ static void fetch_numeric_target(void) plot_printf(uistat.text, sizeof uistat.text, "%5d", ((int32_t)uistat.value)); break; #endif + case KM_LPF: + uistat.value = lpf_switch; + plot_printf(uistat.text, sizeof uistat.text, "%3.6fMHz", uistat.value / 1000000.0); + break; case KM_NOISE: uistat.value = setting.noise; plot_printf(uistat.text, sizeof uistat.text, "%3d", ((int32_t)uistat.value)); @@ -2301,6 +2313,9 @@ set_numeric_value(void) set_attack(uistat.value); break; #endif + case KM_LPF: + lpf_switch = uistat.value; + break; case KM_NOISE: set_noise(uistat.value); break; @@ -2561,7 +2576,10 @@ redraw_cal_status: // Spur #ifdef __SPUR__ if (setting.spur_removal) { - ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + if (S_IS_AUTO(setting.spur_removal)) + color = LCD_FG_COLOR; + else + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); ili9341_drawstring("Spur:", x, y); y += YSTEP; if (S_IS_AUTO(setting.spur_removal)) @@ -2647,7 +2665,13 @@ redraw_cal_status: y += YSTEP + YSTEP/2 ; #endif - // Cal output + if (setting.extra_lna){ + ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); + y = add_quick_menu("LNA:ON", x, y, (menuitem_t *)menu_level); + y += YSTEP; + } + + // Cal output if (setting.refer >= 0) { ili9341_set_foreground(LCD_BRIGHT_COLOR_GREEN); ili9341_drawstring("Ref:", x, y);