mirror of
https://github.com/ttrftech/NanoVNA.git
synced 2025-12-06 03:31:59 +01:00
Big work around si5351 generator
Improve sweep speed about 60% Stop generation on pause sweep Remove all hack for si5351 Reduce code size Fix integer overflow on big freq values Additional Change I2C Others: move marker_tracking variable to ui config move some definition to correct place reduce tlv320aic3204 code size Speedup marker move from lever (BUTTON_REPEAT_TICKS = 625) Need test stability
This commit is contained in:
parent
f1cc60e99e
commit
b77e1d6680
75
main.c
75
main.c
|
|
@ -69,10 +69,6 @@ static void transform_domain(void);
|
||||||
|
|
||||||
static MUTEX_DECL(mutex);
|
static MUTEX_DECL(mutex);
|
||||||
|
|
||||||
#define DRIVE_STRENGTH_AUTO (-1)
|
|
||||||
#define FREQ_HARMONICS (config.harmonic_freq_threshold)
|
|
||||||
#define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS)
|
|
||||||
|
|
||||||
int32_t frequency_offset = 5000;
|
int32_t frequency_offset = 5000;
|
||||||
uint32_t frequency = 10000000;
|
uint32_t frequency = 10000000;
|
||||||
int8_t drive_strength = DRIVE_STRENGTH_AUTO;
|
int8_t drive_strength = DRIVE_STRENGTH_AUTO;
|
||||||
|
|
@ -101,6 +97,7 @@ static THD_FUNCTION(Thread1, arg)
|
||||||
sweep_once = FALSE;
|
sweep_once = FALSE;
|
||||||
chMtxUnlock(&mutex);
|
chMtxUnlock(&mutex);
|
||||||
} else {
|
} else {
|
||||||
|
si5351_disable_output();
|
||||||
__WFI();
|
__WFI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,7 +120,7 @@ static THD_FUNCTION(Thread1, arg)
|
||||||
plot_into_index(measured);
|
plot_into_index(measured);
|
||||||
redraw_request |= REDRAW_CELLS;
|
redraw_request |= REDRAW_CELLS;
|
||||||
|
|
||||||
if (marker_tracking) {
|
if (uistat.marker_tracking) {
|
||||||
int i = marker_search();
|
int i = marker_search();
|
||||||
if (i != -1 && active_marker != -1) {
|
if (i != -1 && active_marker != -1) {
|
||||||
markers[active_marker].index = i;
|
markers[active_marker].index = i;
|
||||||
|
|
@ -316,7 +313,7 @@ const int8_t gain_table[] = {
|
||||||
95 // 2400MHz ~
|
95 // 2400MHz ~
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DELAY_GAIN_CHANGE 10
|
#define DELAY_GAIN_CHANGE 2
|
||||||
|
|
||||||
static int
|
static int
|
||||||
adjust_gain(int newfreq)
|
adjust_gain(int newfreq)
|
||||||
|
|
@ -474,7 +471,7 @@ VNA_SHELL_FUNCTION(cmd_power)
|
||||||
|
|
||||||
#ifdef ENABLE_TIME_COMMAND
|
#ifdef ENABLE_TIME_COMMAND
|
||||||
#if HAL_USE_RTC == FALSE
|
#if HAL_USE_RTC == FALSE
|
||||||
#error "Error cmd_time require ENABLE_TIME_COMMAND = TRUE in halconf.h"
|
#error "Error cmd_time require define HAL_USE_RTC = TRUE in halconf.h"
|
||||||
#endif
|
#endif
|
||||||
VNA_SHELL_FUNCTION(cmd_time)
|
VNA_SHELL_FUNCTION(cmd_time)
|
||||||
{
|
{
|
||||||
|
|
@ -745,7 +742,8 @@ static const marker_t def_markers[MARKERS_MAX] = {
|
||||||
|
|
||||||
// Load propeties default settings
|
// Load propeties default settings
|
||||||
void loadDefaultProps(void){
|
void loadDefaultProps(void){
|
||||||
current_props.magic = CONFIG_MAGIC;
|
//Magic add on caldata_save
|
||||||
|
//current_props.magic = CONFIG_MAGIC;
|
||||||
current_props._frequency0 = 50000; // start = 50kHz
|
current_props._frequency0 = 50000; // start = 50kHz
|
||||||
current_props._frequency1 = 900000000; // end = 900MHz
|
current_props._frequency1 = 900000000; // end = 900MHz
|
||||||
current_props._sweep_points = POINTS_COUNT;
|
current_props._sweep_points = POINTS_COUNT;
|
||||||
|
|
@ -761,6 +759,8 @@ void loadDefaultProps(void){
|
||||||
current_props._active_marker = 0;
|
current_props._active_marker = 0;
|
||||||
current_props._domain_mode = 0;
|
current_props._domain_mode = 0;
|
||||||
current_props._marker_smith_format = MS_RLC;
|
current_props._marker_smith_format = MS_RLC;
|
||||||
|
//Checksum add on caldata_save
|
||||||
|
//current_props.checksum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -775,7 +775,7 @@ ensure_edit_config(void)
|
||||||
cal_status = 0;
|
cal_status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DELAY_CHANNEL_CHANGE 3
|
#define DELAY_CHANNEL_CHANGE 2
|
||||||
|
|
||||||
// main loop for measurement
|
// main loop for measurement
|
||||||
bool sweep(bool break_on_operation)
|
bool sweep(bool break_on_operation)
|
||||||
|
|
@ -783,11 +783,17 @@ bool sweep(bool break_on_operation)
|
||||||
int i;
|
int i;
|
||||||
// blink LED while scanning
|
// blink LED while scanning
|
||||||
palClearPad(GPIOC, GPIOC_LED);
|
palClearPad(GPIOC, GPIOC_LED);
|
||||||
|
systime_t time = chVTGetSystemTimeX();
|
||||||
|
systime_t sweep_t = 0;
|
||||||
|
si5351_enable_output();
|
||||||
|
// On CW set freq once, and run
|
||||||
for (i = 0; i < sweep_points; i++) { // 8365
|
for (i = 0; i < sweep_points; i++) { // 8365
|
||||||
|
sweep_t-= chVTGetSystemTimeX();
|
||||||
int delay = set_frequency(frequencies[i]); // 1560
|
int delay = set_frequency(frequencies[i]); // 1560
|
||||||
|
sweep_t+= chVTGetSystemTimeX();
|
||||||
tlv320aic3204_select(0); // 60 CH0:REFLECT
|
tlv320aic3204_select(0); // 60 CH0:REFLECT
|
||||||
|
|
||||||
wait_dsp(delay); // 3270
|
wait_dsp(delay+(i==0 ? 1 :0)); // 3270
|
||||||
// calculate reflection coefficient
|
// calculate reflection coefficient
|
||||||
(*sample_func)(measured[0][i]); // 60
|
(*sample_func)(measured[0][i]); // 60
|
||||||
|
|
||||||
|
|
@ -803,9 +809,11 @@ bool sweep(bool break_on_operation)
|
||||||
apply_edelay_at(i);
|
apply_edelay_at(i);
|
||||||
|
|
||||||
// back to toplevel to handle ui operation
|
// back to toplevel to handle ui operation
|
||||||
if (operation_requested && break_on_operation)
|
if (operation_requested && break_on_operation){
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
{char string_buf[18];plot_printf(string_buf, sizeof string_buf, "T:%06d:%06d", chVTGetSystemTimeX() - time, sweep_t);ili9341_drawstringV(string_buf, 1, 90);}
|
||||||
// blink LED while scanning
|
// blink LED while scanning
|
||||||
palSetPad(GPIOC, GPIOC_LED);
|
palSetPad(GPIOC, GPIOC_LED);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -912,7 +920,7 @@ update_frequencies(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_frequencies(start, stop, sweep_points);
|
set_frequencies(start, stop, sweep_points);
|
||||||
operation_requested = OP_FREQCHANGE;
|
// operation_requested|= OP_FREQCHANGE;
|
||||||
|
|
||||||
update_marker_index();
|
update_marker_index();
|
||||||
|
|
||||||
|
|
@ -1430,6 +1438,7 @@ VNA_SHELL_FUNCTION(cmd_cal)
|
||||||
shell_printf("\r\n");
|
shell_printf("\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
redraw_request|=REDRAW_CAL_STATUS;
|
||||||
// 0 1 2 3 4 5 6 7 8 9 10
|
// 0 1 2 3 4 5 6 7 8 9 10
|
||||||
static const char cmd_cal_list[] = "load|open|short|thru|isoln|done|on|off|reset|data|in";
|
static const char cmd_cal_list[] = "load|open|short|thru|isoln|done|on|off|reset|data|in";
|
||||||
switch (getStringIndex(argv[0], cmd_cal_list)){
|
switch (getStringIndex(argv[0], cmd_cal_list)){
|
||||||
|
|
@ -1439,9 +1448,9 @@ VNA_SHELL_FUNCTION(cmd_cal)
|
||||||
case 3:cal_collect(CAL_THRU ); return;
|
case 3:cal_collect(CAL_THRU ); return;
|
||||||
case 4:cal_collect(CAL_ISOLN); return;
|
case 4:cal_collect(CAL_ISOLN); return;
|
||||||
case 5:cal_done(); return;
|
case 5:cal_done(); return;
|
||||||
case 6:cal_status|= CALSTAT_APPLY;redraw_request|=REDRAW_CAL_STATUS; return;
|
case 6:cal_status|= CALSTAT_APPLY;return;
|
||||||
case 7:cal_status&=~CALSTAT_APPLY;redraw_request|=REDRAW_CAL_STATUS; return;
|
case 7:cal_status&=~CALSTAT_APPLY;return;
|
||||||
case 8:cal_status = 0; redraw_request|=REDRAW_CAL_STATUS; return;
|
case 8:cal_status = 0; return;
|
||||||
case 9:
|
case 9:
|
||||||
shell_printf("%f %f\r\n", cal_data[CAL_LOAD ][0][0], cal_data[CAL_LOAD ][0][1]);
|
shell_printf("%f %f\r\n", cal_data[CAL_LOAD ][0][0], cal_data[CAL_LOAD ][0][1]);
|
||||||
shell_printf("%f %f\r\n", cal_data[CAL_OPEN ][0][0], cal_data[CAL_OPEN ][0][1]);
|
shell_printf("%f %f\r\n", cal_data[CAL_OPEN ][0][0], cal_data[CAL_OPEN ][0][1]);
|
||||||
|
|
@ -1451,11 +1460,9 @@ VNA_SHELL_FUNCTION(cmd_cal)
|
||||||
return;
|
return;
|
||||||
case 10:
|
case 10:
|
||||||
cal_interpolate((argc > 1) ? my_atoi(argv[1]) : 0);
|
cal_interpolate((argc > 1) ? my_atoi(argv[1]) : 0);
|
||||||
redraw_request|=REDRAW_CAL_STATUS;
|
|
||||||
return;
|
return;
|
||||||
default:break;
|
default:break;
|
||||||
}
|
}
|
||||||
|
|
||||||
shell_printf("usage: cal [%s]\r\n", cmd_cal_list);
|
shell_printf("usage: cal [%s]\r\n", cmd_cal_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1687,14 +1694,13 @@ VNA_SHELL_FUNCTION(cmd_marker)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
redraw_request |= REDRAW_MARKER;
|
||||||
if (strcmp(argv[0], "off") == 0) {
|
if (strcmp(argv[0], "off") == 0) {
|
||||||
active_marker = -1;
|
active_marker = -1;
|
||||||
for (t = 0; t < MARKERS_MAX; t++)
|
for (t = 0; t < MARKERS_MAX; t++)
|
||||||
markers[t].enabled = FALSE;
|
markers[t].enabled = FALSE;
|
||||||
redraw_request |= REDRAW_MARKER;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = my_atoi(argv[0])-1;
|
t = my_atoi(argv[0])-1;
|
||||||
if (t < 0 || t >= MARKERS_MAX)
|
if (t < 0 || t >= MARKERS_MAX)
|
||||||
goto usage;
|
goto usage;
|
||||||
|
|
@ -1703,13 +1709,12 @@ VNA_SHELL_FUNCTION(cmd_marker)
|
||||||
active_marker = t;
|
active_marker = t;
|
||||||
// select active marker
|
// select active marker
|
||||||
markers[t].enabled = TRUE;
|
markers[t].enabled = TRUE;
|
||||||
redraw_request |= REDRAW_MARKER;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static const char cmd_marker_list[] = "on|off";
|
static const char cmd_marker_list[] = "on|off";
|
||||||
switch (getStringIndex(argv[1], cmd_marker_list)){
|
switch (getStringIndex(argv[1], cmd_marker_list)){
|
||||||
case 0: markers[t].enabled = TRUE; active_marker = t; redraw_request |= REDRAW_MARKER; return;
|
case 0: markers[t].enabled = TRUE; active_marker = t; return;
|
||||||
case 1: markers[t].enabled =FALSE; if (active_marker == t) active_marker = -1; redraw_request|=REDRAW_MARKER; return;
|
case 1: markers[t].enabled =FALSE; if (active_marker == t) active_marker = -1; return;
|
||||||
default:
|
default:
|
||||||
// select active marker and move to index
|
// select active marker and move to index
|
||||||
markers[t].enabled = TRUE;
|
markers[t].enabled = TRUE;
|
||||||
|
|
@ -1717,7 +1722,6 @@ VNA_SHELL_FUNCTION(cmd_marker)
|
||||||
markers[t].index = index;
|
markers[t].index = index;
|
||||||
markers[t].frequency = frequencies[index];
|
markers[t].frequency = frequencies[index];
|
||||||
active_marker = t;
|
active_marker = t;
|
||||||
redraw_request |= REDRAW_MARKER;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
usage:
|
usage:
|
||||||
|
|
@ -1923,8 +1927,8 @@ VNA_SHELL_FUNCTION(cmd_stat)
|
||||||
//shell_printf("interval cycle: %d\r\n", stat.interval_cycles);
|
//shell_printf("interval cycle: %d\r\n", stat.interval_cycles);
|
||||||
//shell_printf("busy cycle: %d\r\n", stat.busy_cycles);
|
//shell_printf("busy cycle: %d\r\n", stat.busy_cycles);
|
||||||
//shell_printf("load: %d\r\n", stat.busy_cycles * 100 / stat.interval_cycles);
|
//shell_printf("load: %d\r\n", stat.busy_cycles * 100 / stat.interval_cycles);
|
||||||
extern int awd_count;
|
// extern int awd_count;
|
||||||
shell_printf("awd: %d\r\n", awd_count);
|
// shell_printf("awd: %d\r\n", awd_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2160,10 +2164,25 @@ THD_FUNCTION(myshellThread, p) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// I2C clock bus setting: depend from STM32_I2C1SW in mcuconf.h
|
||||||
|
// STM32_I2C1SW = STM32_I2C1SW_HSI (HSI=8MHz)
|
||||||
|
// STM32_I2C1SW = STM32_I2C1SW_SYSCLK (SYSCLK = 48MHz)
|
||||||
static const I2CConfig i2ccfg = {
|
static const I2CConfig i2ccfg = {
|
||||||
0x00300506, //voodoo magic 400kHz @ HSI 8MHz
|
// TIMINGR register initialization. (use I2C timing configuration tool for STM32F3xx and STM32F0xx microcontrollers (AN4235))
|
||||||
0,
|
// 400kHz @ SYSCLK 48MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual)
|
||||||
0
|
// STM32_TIMINGR_PRESC(5U) |
|
||||||
|
// STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) |
|
||||||
|
// STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U),
|
||||||
|
// 400kHz @ HSI 8MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual)
|
||||||
|
STM32_TIMINGR_PRESC(0U) |
|
||||||
|
STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(1U) |
|
||||||
|
STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U),
|
||||||
|
// Old values voodoo magic 400kHz @ HSI 8MHz
|
||||||
|
// STM32_TIMINGR_PRESC(0U) |
|
||||||
|
// STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(0U) |
|
||||||
|
// STM32_TIMINGR_SCLH(5U) | STM32_TIMINGR_SCLL(6U),
|
||||||
|
0, // CR1 register initialization.
|
||||||
|
0 // CR2 register initialization.
|
||||||
};
|
};
|
||||||
|
|
||||||
static DACConfig dac1cfg1 = {
|
static DACConfig dac1cfg1 = {
|
||||||
|
|
|
||||||
56
nanovna.h
56
nanovna.h
|
|
@ -88,30 +88,6 @@ void loadDefaultProps(void);
|
||||||
|
|
||||||
extern int8_t sweep_enabled;
|
extern int8_t sweep_enabled;
|
||||||
|
|
||||||
/*
|
|
||||||
* flash.c
|
|
||||||
*/
|
|
||||||
#define SAVEAREA_MAX 5
|
|
||||||
// Begin addr 0x08018000
|
|
||||||
#define SAVE_CONFIG_AREA_SIZE 0x00008000
|
|
||||||
// config save area
|
|
||||||
#define SAVE_CONFIG_ADDR 0x08018000
|
|
||||||
// properties_t save area
|
|
||||||
#define SAVE_PROP_CONFIG_0_ADDR 0x08018800
|
|
||||||
#define SAVE_PROP_CONFIG_1_ADDR 0x0801a000
|
|
||||||
#define SAVE_PROP_CONFIG_2_ADDR 0x0801b800
|
|
||||||
#define SAVE_PROP_CONFIG_3_ADDR 0x0801d000
|
|
||||||
#define SAVE_PROP_CONFIG_4_ADDR 0x0801e800
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ui.c
|
|
||||||
*/
|
|
||||||
extern void ui_init(void);
|
|
||||||
extern void ui_process(void);
|
|
||||||
|
|
||||||
enum opreq { OP_NONE = 0, OP_LEVER, OP_TOUCH, OP_FREQCHANGE };
|
|
||||||
extern uint8_t operation_requested;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dsp.c
|
* dsp.c
|
||||||
*/
|
*/
|
||||||
|
|
@ -134,9 +110,6 @@ void calculate_gamma(float *gamma);
|
||||||
void fetch_amplitude(float *gamma);
|
void fetch_amplitude(float *gamma);
|
||||||
void fetch_amplitude_ref(float *gamma);
|
void fetch_amplitude_ref(float *gamma);
|
||||||
|
|
||||||
int si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tlv320aic3204.c
|
* tlv320aic3204.c
|
||||||
*/
|
*/
|
||||||
|
|
@ -250,6 +223,10 @@ typedef struct config {
|
||||||
|
|
||||||
extern config_t config;
|
extern config_t config;
|
||||||
|
|
||||||
|
#define DRIVE_STRENGTH_AUTO (-1)
|
||||||
|
#define FREQ_HARMONICS (config.harmonic_freq_threshold)
|
||||||
|
#define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS)
|
||||||
|
|
||||||
//extern trace_t trace[TRACES_MAX];
|
//extern trace_t trace[TRACES_MAX];
|
||||||
|
|
||||||
void set_trace_type(int t, int type);
|
void set_trace_type(int t, int type);
|
||||||
|
|
@ -366,6 +343,16 @@ void show_logo(void);
|
||||||
* flash.c
|
* flash.c
|
||||||
*/
|
*/
|
||||||
#define SAVEAREA_MAX 5
|
#define SAVEAREA_MAX 5
|
||||||
|
// Begin addr 0x08018000
|
||||||
|
#define SAVE_CONFIG_AREA_SIZE 0x00008000
|
||||||
|
// config save area
|
||||||
|
#define SAVE_CONFIG_ADDR 0x08018000
|
||||||
|
// properties_t save area
|
||||||
|
#define SAVE_PROP_CONFIG_0_ADDR 0x08018800
|
||||||
|
#define SAVE_PROP_CONFIG_1_ADDR 0x0801a000
|
||||||
|
#define SAVE_PROP_CONFIG_2_ADDR 0x0801b800
|
||||||
|
#define SAVE_PROP_CONFIG_3_ADDR 0x0801d000
|
||||||
|
#define SAVE_PROP_CONFIG_4_ADDR 0x0801e800
|
||||||
|
|
||||||
typedef struct properties {
|
typedef struct properties {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
|
|
@ -432,6 +419,15 @@ void clear_all_config_prop_data(void);
|
||||||
/*
|
/*
|
||||||
* ui.c
|
* ui.c
|
||||||
*/
|
*/
|
||||||
|
extern void ui_init(void);
|
||||||
|
extern void ui_process(void);
|
||||||
|
|
||||||
|
// Irq operation process set
|
||||||
|
#define OP_NONE 0x00
|
||||||
|
#define OP_LEVER 0x01
|
||||||
|
#define OP_TOUCH 0x02
|
||||||
|
//#define OP_FREQCHANGE 0x04
|
||||||
|
extern volatile uint8_t operation_requested;
|
||||||
|
|
||||||
// lever_mode
|
// lever_mode
|
||||||
enum lever_mode {
|
enum lever_mode {
|
||||||
|
|
@ -448,13 +444,13 @@ typedef struct uistat {
|
||||||
int8_t digit_mode;
|
int8_t digit_mode;
|
||||||
int8_t current_trace; /* 0..3 */
|
int8_t current_trace; /* 0..3 */
|
||||||
uint32_t value; // for editing at numeric input area
|
uint32_t value; // for editing at numeric input area
|
||||||
uint32_t previous_value;
|
// uint32_t previous_value;
|
||||||
uint8_t lever_mode;
|
uint8_t lever_mode;
|
||||||
bool marker_delta;
|
uint8_t marker_delta;
|
||||||
|
uint8_t marker_tracking;
|
||||||
} uistat_t;
|
} uistat_t;
|
||||||
|
|
||||||
extern uistat_t uistat;
|
extern uistat_t uistat;
|
||||||
|
|
||||||
void ui_init(void);
|
void ui_init(void);
|
||||||
void ui_show(void);
|
void ui_show(void);
|
||||||
void ui_hide(void);
|
void ui_hide(void);
|
||||||
|
|
|
||||||
1
plot.c
1
plot.c
|
|
@ -1056,7 +1056,6 @@ static int greater(int x, int y) { return x > y; }
|
||||||
static int lesser(int x, int y) { return x < y; }
|
static int lesser(int x, int y) { return x < y; }
|
||||||
|
|
||||||
static int (*compare)(int x, int y) = lesser;
|
static int (*compare)(int x, int y) = lesser;
|
||||||
int8_t marker_tracking = false;
|
|
||||||
|
|
||||||
int
|
int
|
||||||
marker_search(void)
|
marker_search(void)
|
||||||
|
|
|
||||||
353
si5351.c
353
si5351.c
|
|
@ -21,17 +21,18 @@
|
||||||
#include "nanovna.h"
|
#include "nanovna.h"
|
||||||
#include "si5351.h"
|
#include "si5351.h"
|
||||||
|
|
||||||
|
#define XTALFREQ 26000000L
|
||||||
|
// MCLK (processor clock, audio codec) frequency clock
|
||||||
|
#define CLK2_FREQUENCY 8000000L
|
||||||
|
|
||||||
|
// Fixed PLL mode multiplier
|
||||||
|
#define PLL_N 32
|
||||||
|
|
||||||
|
//
|
||||||
#define SI5351_I2C_ADDR (0x60<<1)
|
#define SI5351_I2C_ADDR (0x60<<1)
|
||||||
|
|
||||||
static void
|
static uint8_t current_band = 0;
|
||||||
si5351_write(uint8_t reg, uint8_t dat)
|
static uint32_t current_freq = 0;
|
||||||
{
|
|
||||||
int addr = SI5351_I2C_ADDR>>1;
|
|
||||||
uint8_t buf[] = { reg, dat };
|
|
||||||
i2cAcquireBus(&I2CD1);
|
|
||||||
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, 2, NULL, 0, 1000);
|
|
||||||
i2cReleaseBus(&I2CD1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
si5351_bulk_write(const uint8_t *buf, int len)
|
si5351_bulk_write(const uint8_t *buf, int len)
|
||||||
|
|
@ -41,6 +42,22 @@ si5351_bulk_write(const uint8_t *buf, int len)
|
||||||
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
|
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
|
||||||
i2cReleaseBus(&I2CD1);
|
i2cReleaseBus(&I2CD1);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
static void si5351_bulk_read(uint8_t reg, uint8_t* buf, int len)
|
||||||
|
{
|
||||||
|
int addr = SI5351_I2C_ADDR>>1;
|
||||||
|
i2cAcquireBus(&I2CD1);
|
||||||
|
msg_t mr = i2cMasterTransmitTimeout(&I2CD1, addr, ®, 1, buf, len, 1000);
|
||||||
|
i2cReleaseBus(&I2CD1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
si5351_write(uint8_t reg, uint8_t dat)
|
||||||
|
{
|
||||||
|
uint8_t buf[] = { reg, dat };
|
||||||
|
si5351_bulk_write(buf, 2);
|
||||||
|
}
|
||||||
|
|
||||||
// register addr, length, data, ...
|
// register addr, length, data, ...
|
||||||
const uint8_t si5351_configs[] = {
|
const uint8_t si5351_configs[] = {
|
||||||
|
|
@ -48,13 +65,14 @@ const uint8_t si5351_configs[] = {
|
||||||
4, SI5351_REG_16_CLK0_CONTROL, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN,
|
4, SI5351_REG_16_CLK0_CONTROL, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN,
|
||||||
2, SI5351_REG_183_CRYSTAL_LOAD, SI5351_CRYSTAL_LOAD_8PF,
|
2, SI5351_REG_183_CRYSTAL_LOAD, SI5351_CRYSTAL_LOAD_8PF,
|
||||||
// setup PLL (26MHz * 32 = 832MHz, 32/2-2=14)
|
// setup PLL (26MHz * 32 = 832MHz, 32/2-2=14)
|
||||||
9, SI5351_REG_26_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
|
// 9, SI5351_REG_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
|
||||||
|
// 9, SI5351_REG_PLL_B, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
|
||||||
// RESET PLL
|
// RESET PLL
|
||||||
2, SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B,
|
2, SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B | 0x0C, //
|
||||||
// setup multisynth (832MHz / 104 = 8MHz, 104/2-2=50)
|
// setup multisynth (832MHz / 104 = 8MHz, 104/2-2=50)
|
||||||
9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 1, /*P1*/0, 50, 0, /*P2|P3*/0, 0, 0,
|
// 9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 1, /*P1*/0, 50, 0, /*P2|P3*/0, 0, 0,
|
||||||
2, SI5351_REG_18_CLK2_CONTROL, SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE,
|
// 2, SI5351_REG_18_CLK2_CONTROL, SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE,
|
||||||
2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0,
|
// 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0,
|
||||||
0 // sentinel
|
0 // sentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -71,26 +89,46 @@ si5351_init(void)
|
||||||
|
|
||||||
static const uint8_t disable_output[] = {
|
static const uint8_t disable_output[] = {
|
||||||
SI5351_REG_16_CLK0_CONTROL,
|
SI5351_REG_16_CLK0_CONTROL,
|
||||||
SI5351_CLK_POWERDOWN,
|
SI5351_CLK_POWERDOWN, // CLK 0
|
||||||
SI5351_CLK_POWERDOWN,
|
SI5351_CLK_POWERDOWN, // CLK 1
|
||||||
SI5351_CLK_POWERDOWN
|
SI5351_CLK_POWERDOWN // CLK 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Get the appropriate starting point for the PLL registers */
|
||||||
|
static const uint8_t msreg_base[] = {
|
||||||
|
SI5351_REG_42_MULTISYNTH0,
|
||||||
|
SI5351_REG_50_MULTISYNTH1,
|
||||||
|
SI5351_REG_58_MULTISYNTH2,
|
||||||
|
};
|
||||||
|
static const uint8_t clkctrl[] = {
|
||||||
|
SI5351_REG_16_CLK0_CONTROL,
|
||||||
|
SI5351_REG_17_CLK1_CONTROL,
|
||||||
|
SI5351_REG_18_CLK2_CONTROL
|
||||||
|
};
|
||||||
|
|
||||||
|
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.
|
||||||
|
// !!! Need delay before reset PLL for apply PLL freq changes before
|
||||||
|
chThdSleepMicroseconds(200);
|
||||||
|
si5351_write(SI5351_REG_177_PLL_RESET, mask | 0x0C);
|
||||||
|
// chThdSleepMicroseconds(250);
|
||||||
|
}
|
||||||
|
|
||||||
void si5351_disable_output(void)
|
void si5351_disable_output(void)
|
||||||
{
|
{
|
||||||
|
// si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, (SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN));
|
||||||
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
|
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
|
||||||
si5351_bulk_write(disable_output, sizeof(disable_output));
|
si5351_bulk_write(disable_output, sizeof(disable_output));
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351_enable_output(void)
|
void si5351_enable_output(void)
|
||||||
{
|
{
|
||||||
|
si5351_reset_pll( SI5351_PLL_RESET_A | SI5351_PLL_RESET_B );
|
||||||
|
// si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN));
|
||||||
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0x00);
|
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0x00);
|
||||||
}
|
current_freq = 0;
|
||||||
|
current_band = 0;
|
||||||
static void si5351_reset_pll(void)
|
|
||||||
{
|
|
||||||
//si5351_write(SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B);
|
|
||||||
si5351_write(SI5351_REG_177_PLL_RESET, 0xAC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */
|
static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */
|
||||||
|
|
@ -98,11 +136,6 @@ static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */
|
||||||
uint32_t num,
|
uint32_t num,
|
||||||
uint32_t denom)
|
uint32_t denom)
|
||||||
{
|
{
|
||||||
/* Get the appropriate starting point for the PLL registers */
|
|
||||||
static const uint8_t pllreg_base[] = {
|
|
||||||
SI5351_REG_26_PLL_A,
|
|
||||||
SI5351_REG_34_PLL_B
|
|
||||||
};
|
|
||||||
uint32_t P1;
|
uint32_t P1;
|
||||||
uint32_t P2;
|
uint32_t P2;
|
||||||
uint32_t P3;
|
uint32_t P3;
|
||||||
|
|
@ -134,10 +167,17 @@ static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */
|
||||||
P2 = 128 * num - denom * ((128 * num) / denom);
|
P2 = 128 * num - denom * ((128 * num) / denom);
|
||||||
P3 = denom;
|
P3 = denom;
|
||||||
}
|
}
|
||||||
|
// Pll MSN(A|B) registers Datasheet
|
||||||
/* The datasheet is a nightmare of typos and inconsistencies here! */
|
// MSN_P3[15:8]
|
||||||
|
// MSN_P3[ 7:0]
|
||||||
|
// Reserved | MSN_P1[17:16]
|
||||||
|
// MSN_P1[15:8]
|
||||||
|
// MSN_P1[ 7:0]
|
||||||
|
// MSN_P3[19:16] | MSN_P2[19:16]
|
||||||
|
// MSN_P2[15:8]
|
||||||
|
// MSN_P2[ 7:0]
|
||||||
uint8_t reg[9];
|
uint8_t reg[9];
|
||||||
reg[0] = pllreg_base[pll];
|
reg[0] = pll;//reg_base[pll];
|
||||||
reg[1] = (P3 & 0x0000FF00) >> 8;
|
reg[1] = (P3 & 0x0000FF00) >> 8;
|
||||||
reg[2] = (P3 & 0x000000FF);
|
reg[2] = (P3 & 0x000000FF);
|
||||||
reg[3] = (P1 & 0x00030000) >> 16;
|
reg[3] = (P1 & 0x00030000) >> 16;
|
||||||
|
|
@ -149,8 +189,9 @@ static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */
|
||||||
si5351_bulk_write(reg, 9);
|
si5351_bulk_write(reg, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
si5351_setupMultisynth(uint8_t output,
|
si5351_setupMultisynth(uint8_t channel,
|
||||||
uint8_t pllSource,
|
uint8_t pllSource,
|
||||||
uint32_t div, // 4,6,8, 8+ ~ 900
|
uint32_t div, // 4,6,8, 8+ ~ 900
|
||||||
uint32_t num,
|
uint32_t num,
|
||||||
|
|
@ -158,17 +199,6 @@ si5351_setupMultisynth(uint8_t output,
|
||||||
uint32_t rdiv, // SI5351_R_DIV_1~128
|
uint32_t rdiv, // SI5351_R_DIV_1~128
|
||||||
uint8_t drive_strength)
|
uint8_t drive_strength)
|
||||||
{
|
{
|
||||||
/* Get the appropriate starting point for the PLL registers */
|
|
||||||
static const uint8_t msreg_base[] = {
|
|
||||||
SI5351_REG_42_MULTISYNTH0,
|
|
||||||
SI5351_REG_50_MULTISYNTH1,
|
|
||||||
SI5351_REG_58_MULTISYNTH2,
|
|
||||||
};
|
|
||||||
static const uint8_t clkctrl[] = {
|
|
||||||
SI5351_REG_16_CLK0_CONTROL,
|
|
||||||
SI5351_REG_17_CLK1_CONTROL,
|
|
||||||
SI5351_REG_18_CLK2_CONTROL
|
|
||||||
};
|
|
||||||
uint8_t dat;
|
uint8_t dat;
|
||||||
|
|
||||||
uint32_t P1;
|
uint32_t P1;
|
||||||
|
|
@ -204,7 +234,7 @@ si5351_setupMultisynth(uint8_t output,
|
||||||
|
|
||||||
/* Set the MSx config registers */
|
/* Set the MSx config registers */
|
||||||
uint8_t reg[9];
|
uint8_t reg[9];
|
||||||
reg[0] = msreg_base[output];
|
reg[0] = msreg_base[channel];
|
||||||
reg[1] = (P3 & 0x0000FF00) >> 8;
|
reg[1] = (P3 & 0x0000FF00) >> 8;
|
||||||
reg[2] = (P3 & 0x000000FF);
|
reg[2] = (P3 & 0x000000FF);
|
||||||
reg[3] = ((P1 & 0x00030000) >> 16) | div4 | rdiv;
|
reg[3] = ((P1 & 0x00030000) >> 16) | div4 | rdiv;
|
||||||
|
|
@ -217,86 +247,80 @@ si5351_setupMultisynth(uint8_t output,
|
||||||
|
|
||||||
/* Configure the clk control and enable the output */
|
/* Configure the clk control and enable the output */
|
||||||
dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N;
|
dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N;
|
||||||
if (pllSource == SI5351_PLL_B)
|
if (pllSource == SI5351_REG_PLL_B)
|
||||||
dat |= SI5351_CLK_PLL_SELECT_B;
|
dat |= SI5351_CLK_PLL_SELECT_B;
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
dat |= SI5351_CLK_INTEGER_MODE;
|
dat |= SI5351_CLK_INTEGER_MODE;
|
||||||
si5351_write(clkctrl[output], dat);
|
si5351_write(clkctrl[channel], dat);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define XTALFREQ 26000000L
|
|
||||||
#define PLL_N 32
|
|
||||||
#define PLLFREQ (XTALFREQ * PLL_N)
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
si5351_set_frequency_fixedpll(int channel, int pll, uint32_t pllfreq, uint32_t freq,
|
si5351_set_frequency_fixedpll(uint8_t channel, uint32_t pllSource, uint64_t pllfreq, uint32_t freq, uint32_t rdiv, uint8_t drive_strength)
|
||||||
int rdiv, uint8_t drive_strength, int mul)
|
|
||||||
{
|
{
|
||||||
int denom = freq;
|
uint32_t denom = freq;
|
||||||
int div = (pllfreq * mul) / denom; // range: 8 ~ 1800
|
uint32_t div = pllfreq / denom; // range: 8 ~ 1800
|
||||||
int num = (pllfreq * mul) - denom * div;
|
uint32_t num = pllfreq % denom;
|
||||||
|
|
||||||
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
|
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
|
||||||
int max_denominator = (1 << 20) - 1;
|
uint32_t max_denominator = (1 << 20) - 1;
|
||||||
if (denom > max_denominator) {
|
if (denom > max_denominator) {
|
||||||
int p0 = 0, q0 = 1, p1 = 1, q1 = 0;
|
uint32_t p0 = 0, q0 = 1, p1 = 1, q1 = 0;
|
||||||
while (denom != 0) {
|
while (denom != 0) {
|
||||||
int a = num / denom;
|
uint32_t a = num / denom;
|
||||||
int q2 = q0 + a*q1;
|
uint32_t b = num % denom;
|
||||||
|
uint32_t q2 = q0 + a*q1;
|
||||||
if (q2 > max_denominator)
|
if (q2 > max_denominator)
|
||||||
break;
|
break;
|
||||||
int p2 = p0 + a*p1;
|
uint32_t p2 = p0 + a*p1;
|
||||||
p0 = p1; q0 = q1; p1 = p2; q1 = q2;
|
p0 = p1;
|
||||||
int new_denom = num - a * denom;
|
q0 = q1;
|
||||||
num = denom; denom = new_denom;
|
p1 = p2;
|
||||||
|
q1 = q2;
|
||||||
|
num = denom; denom = b;
|
||||||
}
|
}
|
||||||
num = p1;
|
num = p1;
|
||||||
denom = q1;
|
denom = q1;
|
||||||
}
|
}
|
||||||
|
si5351_setupMultisynth(channel, pllSource, div, num, denom, rdiv, drive_strength);
|
||||||
si5351_setupMultisynth(channel, pll, div, num, denom, rdiv, drive_strength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void si5351_setupPLL_freq(uint32_t pll, uint32_t freq, uint32_t div, uint32_t mul){
|
||||||
si5351_set_frequency_fixeddiv(int channel, int pll, uint32_t freq, int div,
|
uint32_t denom = XTALFREQ * mul;
|
||||||
uint8_t drive_strength, int mul)
|
uint64_t pllfreq = (uint64_t)freq * div;
|
||||||
{
|
uint32_t multi = pllfreq / denom;
|
||||||
int denom = XTALFREQ * mul;
|
uint32_t num = pllfreq % denom;
|
||||||
int64_t pllfreq = (int64_t)freq * div;
|
|
||||||
int multi = pllfreq / denom;
|
|
||||||
int num = pllfreq - denom * multi;
|
|
||||||
|
|
||||||
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
|
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
|
||||||
int max_denominator = (1 << 20) - 1;
|
uint32_t max_denominator = (1 << 20) - 1;
|
||||||
if (denom > max_denominator) {
|
if (denom > max_denominator) {
|
||||||
int p0 = 0, q0 = 1, p1 = 1, q1 = 0;
|
uint32_t p0 = 0, q0 = 1, p1 = 1, q1 = 0;
|
||||||
while (denom != 0) {
|
while (denom != 0) {
|
||||||
int a = num / denom;
|
uint32_t a = num / denom;
|
||||||
int q2 = q0 + a*q1;
|
uint32_t b = num % denom;
|
||||||
if (q2 > max_denominator)
|
uint32_t q2 = q0 + a*q1;
|
||||||
break;
|
if (q2 > max_denominator)
|
||||||
int p2 = p0 + a*p1;
|
break;
|
||||||
p0 = p1; q0 = q1; p1 = p2; q1 = q2;
|
uint32_t p2 = p0 + a*p1;
|
||||||
int new_denom = num - a * denom;
|
p0 = p1; q0 = q1; p1 = p2; q1 = q2;
|
||||||
num = denom; denom = new_denom;
|
num = denom; denom = b;
|
||||||
}
|
|
||||||
num = p1;
|
|
||||||
denom = q1;
|
|
||||||
}
|
}
|
||||||
|
num = p1;
|
||||||
si5351_setupPLL(pll, multi, num, denom);
|
denom = q1;
|
||||||
si5351_setupMultisynth(channel, pll, div, 0, 1, SI5351_R_DIV_1, drive_strength);
|
}
|
||||||
|
si5351_setupPLL(pll, multi, num, denom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 1~100MHz fixed PLL 900MHz, fractional divider
|
|
||||||
* 100~150MHz fractional PLL 600-900MHz, fixed divider 6
|
|
||||||
* 150~200MHz fractional PLL 600-900MHz, fixed divider 4
|
|
||||||
*/
|
|
||||||
#if 0
|
#if 0
|
||||||
void
|
static void
|
||||||
si5351_set_frequency(int channel, int freq, uint8_t drive_strength)
|
si5351_set_frequency_fixeddiv(uint8_t channel, uint32_t pll, uint32_t freq, uint32_t div,
|
||||||
|
uint8_t drive_strength, uint32_t mul)
|
||||||
{
|
{
|
||||||
|
si5351_setupPLL_freq(pll, freq, div, mul);
|
||||||
|
si5351_setupMultisynth(channel, pll, div, 0, 1, SI5351_R_DIV_1, drive_strength);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength){
|
||||||
if (freq <= 100000000) {
|
if (freq <= 100000000) {
|
||||||
si5351_setupPLL(SI5351_PLL_B, 32, 0, 1);
|
si5351_setupPLL(SI5351_PLL_B, 32, 0, 1);
|
||||||
si5351_set_frequency_fixedpll(channel, SI5351_PLL_B, PLLFREQ, freq, SI5351_R_DIV_1, drive_strength, 1);
|
si5351_set_frequency_fixedpll(channel, SI5351_PLL_B, PLLFREQ, freq, SI5351_R_DIV_1, drive_strength, 1);
|
||||||
|
|
@ -308,11 +332,8 @@ si5351_set_frequency(int channel, int freq, uint8_t drive_strength)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int current_band = -1;
|
#define DELAY_NORMAL 2
|
||||||
|
#define DELAY_BANDCHANGE 2
|
||||||
#define DELAY_NORMAL 3
|
|
||||||
#define DELAY_BANDCHANGE 1
|
|
||||||
#define DELAY_LOWBAND 1
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* configure output as follows:
|
* configure output as follows:
|
||||||
|
|
@ -320,105 +341,89 @@ int current_band = -1;
|
||||||
* CLK1: frequency
|
* CLK1: frequency
|
||||||
* CLK2: fixed 8MHz
|
* CLK2: fixed 8MHz
|
||||||
*/
|
*/
|
||||||
#define CLK2_FREQUENCY 8000000L
|
|
||||||
int
|
int
|
||||||
si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength)
|
si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength)
|
||||||
{
|
{
|
||||||
int band;
|
uint8_t band;
|
||||||
int delay = DELAY_NORMAL;
|
int delay = DELAY_NORMAL;
|
||||||
|
if (freq == current_freq)
|
||||||
|
return delay;
|
||||||
uint32_t ofreq = freq + offset;
|
uint32_t ofreq = freq + 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;
|
||||||
if (freq >= config.harmonic_freq_threshold * 7U) {
|
uint32_t fdiv;
|
||||||
|
current_freq = freq;
|
||||||
|
if (freq >= FREQ_HARMONICS * 7U) {
|
||||||
mul = 9;
|
mul = 9;
|
||||||
omul = 11;
|
omul = 11;
|
||||||
} else if (freq >= config.harmonic_freq_threshold * 5U) {
|
} else if (freq >= FREQ_HARMONICS * 5U) {
|
||||||
mul = 7;
|
mul = 7;
|
||||||
omul = 9;
|
omul = 9;
|
||||||
} else if (freq >= config.harmonic_freq_threshold * 3U) {
|
} else if (freq >= FREQ_HARMONICS * 3U) {
|
||||||
mul = 5;
|
mul = 5;
|
||||||
omul = 7;
|
omul = 7;
|
||||||
} else if (freq >= config.harmonic_freq_threshold) {
|
} else if (freq >= FREQ_HARMONICS) {
|
||||||
mul = 3;
|
mul = 3;
|
||||||
omul = 5;
|
omul = 5;
|
||||||
}
|
}
|
||||||
if ((freq / mul) < 100000000U) {
|
else if (freq <= 500000U) {
|
||||||
band = 0;
|
|
||||||
} else if ((freq / mul) < 150000000U) {
|
|
||||||
band = 1;
|
|
||||||
} else {
|
|
||||||
band = 2;
|
|
||||||
}
|
|
||||||
if (freq <= 500000U) {
|
|
||||||
rdiv = SI5351_R_DIV_64;
|
rdiv = SI5351_R_DIV_64;
|
||||||
|
freq *= 64;
|
||||||
|
ofreq *= 64;
|
||||||
} else if (freq <= 4000000U) {
|
} else if (freq <= 4000000U) {
|
||||||
rdiv = SI5351_R_DIV_8;
|
rdiv = SI5351_R_DIV_8;
|
||||||
|
freq *= 8;
|
||||||
|
ofreq *= 8;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Band 0
|
||||||
|
* 1~100MHz fixed PLL = XTALFREQ * PLL_N, fractional divider
|
||||||
|
* Band 1
|
||||||
|
* 100~150MHz fractional PLL = 600- 900MHz, fixed divider 6
|
||||||
|
* Band 2
|
||||||
|
* 150~300MHz fractional PLL = 600-1200MHz, fixed divider 4
|
||||||
|
*/
|
||||||
|
if ((freq / mul) < 100000000U) {
|
||||||
|
band = 1;
|
||||||
|
} else if ((freq / mul) < 150000000U) {
|
||||||
|
band = 2;
|
||||||
|
fdiv = 6;
|
||||||
|
} else {
|
||||||
|
band = 3;
|
||||||
|
fdiv = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
if (current_band != band)
|
|
||||||
si5351_disable_output();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (band) {
|
switch (band) {
|
||||||
case 0:
|
|
||||||
// fractional divider mode. only PLL A is used.
|
|
||||||
if (current_band == 1 || current_band == 2)
|
|
||||||
si5351_setupPLL(SI5351_PLL_A, 32, 0, 1);
|
|
||||||
// Set PLL twice on changing from band 2
|
|
||||||
if (current_band == 2)
|
|
||||||
si5351_setupPLL(SI5351_PLL_A, 32, 0, 1);
|
|
||||||
|
|
||||||
if (rdiv == SI5351_R_DIV_8) {
|
|
||||||
freq *= 8;
|
|
||||||
ofreq *= 8;
|
|
||||||
} else if (rdiv == SI5351_R_DIV_64) {
|
|
||||||
freq *= 64;
|
|
||||||
ofreq *= 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
si5351_set_frequency_fixedpll(0, SI5351_PLL_A, PLLFREQ, ofreq,
|
|
||||||
rdiv, drive_strength, omul);
|
|
||||||
si5351_set_frequency_fixedpll(1, SI5351_PLL_A, PLLFREQ, freq,
|
|
||||||
rdiv, drive_strength, mul);
|
|
||||||
//if (current_band != 0)
|
|
||||||
si5351_set_frequency_fixedpll(2, SI5351_PLL_A, PLLFREQ, CLK2_FREQUENCY,
|
|
||||||
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
// Set PLL twice on changing from band 2
|
// Setup CH0 and CH1 constant PLL freq at band change, and set CH2 freq = CLK2_FREQUENCY
|
||||||
if (current_band == 2) {
|
if (current_band != 1){
|
||||||
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul);
|
si5351_setupPLL(SI5351_REG_PLL_A, PLL_N, 0, 1);
|
||||||
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul);
|
si5351_setupPLL(SI5351_REG_PLL_B, PLL_N, 0, 1);
|
||||||
|
si5351_set_frequency_fixedpll(2, SI5351_REG_PLL_B, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||||
}
|
}
|
||||||
|
// Calculate and set CH0 and CH1 divider
|
||||||
// div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1
|
si5351_set_frequency_fixedpll(0, SI5351_REG_PLL_A, XTALFREQ * PLL_N * omul, ofreq, rdiv, drive_strength);
|
||||||
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul);
|
si5351_set_frequency_fixedpll(1, SI5351_REG_PLL_A, XTALFREQ * PLL_N * mul, freq, rdiv, drive_strength);
|
||||||
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul);
|
|
||||||
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 6, CLK2_FREQUENCY,
|
|
||||||
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
// div by 4 mode. both PLL A and B are dedicated for CLK0, CLK1
|
case 3:
|
||||||
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 4, drive_strength, omul);
|
// Setup CH0 and CH1 constant fdiv divider at change
|
||||||
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 4, drive_strength, mul);
|
if (current_band != band){
|
||||||
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 4, CLK2_FREQUENCY,
|
si5351_setupMultisynth(0, SI5351_REG_PLL_A, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength);
|
||||||
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
|
si5351_setupMultisynth(1, SI5351_REG_PLL_B, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength);
|
||||||
|
}
|
||||||
|
// 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_B, freq, fdiv, mul);// set PLLB freq = ( freq/ mul)*fdiv
|
||||||
|
// Calculate CH2 freq = CLK2_FREQUENCY, depend from calculated before CH1 PLLB = (freq/mul)*fdiv
|
||||||
|
si5351_set_frequency_fixedpll(2, SI5351_REG_PLL_B, (freq/mul)*fdiv, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_band != band) {
|
if (current_band != band) {
|
||||||
si5351_reset_pll();
|
si5351_reset_pll(SI5351_PLL_RESET_A|SI5351_PLL_RESET_B);
|
||||||
#if 1
|
current_band = band;
|
||||||
si5351_enable_output();
|
delay+=DELAY_BANDCHANGE;
|
||||||
#endif
|
|
||||||
delay += DELAY_BANDCHANGE;
|
|
||||||
}
|
}
|
||||||
if (band == 0)
|
|
||||||
delay += DELAY_LOWBAND;
|
|
||||||
|
|
||||||
current_band = band;
|
|
||||||
return delay;
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
si5351.h
19
si5351.h
|
|
@ -17,8 +17,8 @@
|
||||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
#define SI5351_PLL_A 0
|
//#define SI5351_PLL_A 0
|
||||||
#define SI5351_PLL_B 1
|
//#define SI5351_PLL_B 1
|
||||||
|
|
||||||
#define SI5351_MULTISYNTH_DIV_4 4
|
#define SI5351_MULTISYNTH_DIV_4 4
|
||||||
#define SI5351_MULTISYNTH_DIV_6 6
|
#define SI5351_MULTISYNTH_DIV_6 6
|
||||||
|
|
@ -33,12 +33,16 @@
|
||||||
#define SI5351_R_DIV_128 (7<<4)
|
#define SI5351_R_DIV_128 (7<<4)
|
||||||
#define SI5351_DIVBY4 (3<<2)
|
#define SI5351_DIVBY4 (3<<2)
|
||||||
|
|
||||||
#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3
|
#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3
|
||||||
|
#define SI5351_CLK0_EN (1<<0)
|
||||||
|
#define SI5351_CLK1_EN (1<<2)
|
||||||
|
#define SI5351_CLK2_EN (1<<3)
|
||||||
|
|
||||||
#define SI5351_REG_16_CLK0_CONTROL 16
|
#define SI5351_REG_16_CLK0_CONTROL 16
|
||||||
#define SI5351_REG_17_CLK1_CONTROL 17
|
#define SI5351_REG_17_CLK1_CONTROL 17
|
||||||
#define SI5351_REG_18_CLK2_CONTROL 18
|
#define SI5351_REG_18_CLK2_CONTROL 18
|
||||||
#define SI5351_REG_26_PLL_A 26
|
#define SI5351_REG_PLL_A 26
|
||||||
#define SI5351_REG_34_PLL_B 34
|
#define SI5351_REG_PLL_B 34
|
||||||
#define SI5351_REG_42_MULTISYNTH0 42
|
#define SI5351_REG_42_MULTISYNTH0 42
|
||||||
#define SI5351_REG_50_MULTISYNTH1 50
|
#define SI5351_REG_50_MULTISYNTH1 50
|
||||||
#define SI5351_REG_58_MULTISYNTH2 58
|
#define SI5351_REG_58_MULTISYNTH2 58
|
||||||
|
|
@ -74,4 +78,7 @@
|
||||||
|
|
||||||
void si5351_init(void);
|
void si5351_init(void);
|
||||||
|
|
||||||
void si5351_set_frequency(int channel, int freq, uint8_t drive_strength);
|
void si5351_disable_output(void);
|
||||||
|
void si5351_enable_output(void);
|
||||||
|
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);
|
||||||
|
|
|
||||||
159
tlv320aic3204.c
159
tlv320aic3204.c
|
|
@ -25,74 +25,78 @@
|
||||||
|
|
||||||
#define wait_ms(ms) chThdSleepMilliseconds(ms)
|
#define wait_ms(ms) chThdSleepMilliseconds(ms)
|
||||||
|
|
||||||
static const uint8_t conf_data_pll[] = {
|
static const uint8_t conf_data[] = {
|
||||||
// len, ( reg, data ),
|
// reg, data,
|
||||||
2, 0x00, 0x00, /* Initialize to Page 0 */
|
// PLL clock config
|
||||||
2, 0x01, 0x01, /* Initialize the device through software reset */
|
0x00, 0x00, /* Initialize to Page 0 */
|
||||||
2, 0x04, 0x43, /* PLL Clock High, MCLK, PLL */
|
0x01, 0x01, /* Initialize the device through software reset */
|
||||||
|
0x04, 0x43, /* PLL Clock High, MCLK, PLL */
|
||||||
#ifdef REFCLK_8000KHZ
|
#ifdef REFCLK_8000KHZ
|
||||||
/* 8.000MHz*10.7520 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */
|
/* 8.000MHz*10.7520 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */
|
||||||
2, 0x05, 0x91, /* Power up PLL, P=1,R=1 */
|
0x05, 0x91, /* Power up PLL, P=1,R=1 */
|
||||||
2, 0x06, 0x0a, /* J=10 */
|
0x06, 0x0a, /* J=10 */
|
||||||
2, 0x07, 29, /* D=7520 = (29<<8) + 96 */
|
0x07, 29, /* D=7520 = (29<<8) + 96 */
|
||||||
2, 0x08, 96,
|
0x08, 96,
|
||||||
#endif
|
#endif
|
||||||
0 // sentinel
|
// Clock config, default fs=48kHz
|
||||||
|
0x0b, 0x82, /* Power up the NDAC divider with value 2 */
|
||||||
|
0x0c, 0x87, /* Power up the MDAC divider with value 7 */
|
||||||
|
0x0d, 0x00, /* Program the OSR of DAC to 128 */
|
||||||
|
0x0e, 0x80,
|
||||||
|
0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */
|
||||||
|
//0x3c, 25, /* Set the DAC Mode to PRB_P25 */
|
||||||
|
0x1b, 0x0c, /* Set the BCLK,WCLK as output */
|
||||||
|
0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */
|
||||||
|
0x25, 0xee, /* DAC power up */
|
||||||
|
|
||||||
|
0x12, 0x82, /* Power up the NADC divider with value 2 */
|
||||||
|
0x13, 0x87, /* Power up the MADC divider with value 7 */
|
||||||
|
0x14, 0x80, /* Program the OSR of ADC to 128 */
|
||||||
|
0x3d, 0x01, /* Select ADC PRB_R1 */
|
||||||
|
// Data routing
|
||||||
|
0x00, 0x01, /* Select Page 1 */
|
||||||
|
0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/
|
||||||
|
0x02, 0x01, /* Enable Master Analog Power Control */
|
||||||
|
0x7b, 0x01, /* Set the REF charging time to 40ms */
|
||||||
|
0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */
|
||||||
|
0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */
|
||||||
|
|
||||||
|
0x3d, 0x00, /* Select ADC PTM_R4 */
|
||||||
|
0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */
|
||||||
|
0x7b, 0x01, /* Set the REF charging time to 40ms */
|
||||||
|
0x34, 0x10, /* Route IN2L to LEFT_P with 10K */
|
||||||
|
0x36, 0x10, /* Route IN2R to LEFT_N with 10K */
|
||||||
|
//0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */
|
||||||
|
//0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */
|
||||||
|
//0x3b, 0x00, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */
|
||||||
|
//0x3c, 0x00, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */
|
||||||
};
|
};
|
||||||
|
|
||||||
// default fs=48kHz
|
static const uint8_t conf_data_unmute[] = {
|
||||||
static const uint8_t conf_data_clk[] = {
|
// reg, data,
|
||||||
2, 0x0b, 0x82, /* Power up the NDAC divider with value 2 */
|
0x00, 0x00, /* Select Page 0 */
|
||||||
2, 0x0c, 0x87, /* Power up the MDAC divider with value 7 */
|
0x51, 0xc0, /* Power up Left and Right ADC Channels */
|
||||||
2, 0x0d, 0x00, /* Program the OSR of DAC to 128 */
|
0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */
|
||||||
2, 0x0e, 0x80,
|
|
||||||
2, 0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */
|
|
||||||
//2, 0x3c, 25, /* Set the DAC Mode to PRB_P25 */
|
|
||||||
2, 0x1b, 0x0c, /* Set the BCLK,WCLK as output */
|
|
||||||
2, 0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */
|
|
||||||
2, 0x25, 0xee, /* DAC power up */
|
|
||||||
|
|
||||||
2, 0x12, 0x82, /* Power up the NADC divider with value 2 */
|
|
||||||
2, 0x13, 0x87, /* Power up the MADC divider with value 7 */
|
|
||||||
2, 0x14, 0x80, /* Program the OSR of ADC to 128 */
|
|
||||||
2, 0x3d, 0x01, /* Select ADC PRB_R1 */
|
|
||||||
0 // sentinel
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t conf_data_routing[] = {
|
static const uint8_t conf_data_ch3_select[] = {
|
||||||
2, 0x00, 0x01, /* Select Page 1 */
|
// reg, data,
|
||||||
2, 0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/
|
0x00, 0x01, /* Select Page 1 */
|
||||||
2, 0x02, 0x01, /* Enable Master Analog Power Control */
|
0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */
|
||||||
2, 0x7b, 0x01, /* Set the REF charging time to 40ms */
|
0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */
|
||||||
2, 0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */
|
|
||||||
2, 0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */
|
|
||||||
|
|
||||||
2, 0x3d, 0x00, /* Select ADC PTM_R4 */
|
|
||||||
2, 0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */
|
|
||||||
2, 0x7b, 0x01, /* Set the REF charging time to 40ms */
|
|
||||||
2, 0x34, 0x10, /* Route IN2L to LEFT_P with 10K */
|
|
||||||
2, 0x36, 0x10, /* Route IN2R to LEFT_N with 10K */
|
|
||||||
2, 0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */
|
|
||||||
2, 0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */
|
|
||||||
2, 0x3b, 0, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */
|
|
||||||
2, 0x3c, 0, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */
|
|
||||||
0 // sentinel
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t conf_data_unmute[] = {
|
static const uint8_t conf_data_ch1_select[] = {
|
||||||
2, 0x00, 0x00, /* Select Page 0 */
|
// reg, data,
|
||||||
2, 0x51, 0xc0, /* Power up Left and Right ADC Channels */
|
0x00, 0x01, /* Select Page 1 */
|
||||||
2, 0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */
|
0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */
|
||||||
0 // sentinel
|
0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static inline void
|
||||||
tlv320aic3204_bulk_write(const uint8_t *buf, int len)
|
tlv320aic3204_bulk_write(const uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
int addr = AIC3204_ADDR;
|
(void)i2cMasterTransmitTimeout(&I2CD1, AIC3204_ADDR, buf, len, NULL, 0, 1000);
|
||||||
i2cAcquireBus(&I2CD1);
|
|
||||||
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
|
|
||||||
i2cReleaseBus(&I2CD1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -109,49 +113,32 @@ tlv320aic3204_read(uint8_t d0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tlv320aic3204_config(const uint8_t *data)
|
tlv320aic3204_config(const uint8_t *data, int len)
|
||||||
{
|
{
|
||||||
const uint8_t *p = data;
|
i2cAcquireBus(&I2CD1);
|
||||||
while (*p) {
|
for (;len--;data+=2)
|
||||||
uint8_t len = *p++;
|
tlv320aic3204_bulk_write(data, 2);
|
||||||
tlv320aic3204_bulk_write(p, len);
|
i2cReleaseBus(&I2CD1);
|
||||||
p += len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tlv320aic3204_init(void)
|
void tlv320aic3204_init(void)
|
||||||
{
|
{
|
||||||
tlv320aic3204_config(conf_data_pll);
|
tlv320aic3204_config(conf_data, sizeof(conf_data)/2);
|
||||||
tlv320aic3204_config(conf_data_clk);
|
|
||||||
tlv320aic3204_config(conf_data_routing);
|
|
||||||
wait_ms(40);
|
wait_ms(40);
|
||||||
tlv320aic3204_config(conf_data_unmute);
|
tlv320aic3204_config(conf_data_unmute, sizeof(conf_data_unmute)/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tlv320aic3204_select(int channel)
|
void tlv320aic3204_select(int channel)
|
||||||
{
|
{
|
||||||
const uint8_t ch3[] = {
|
tlv320aic3204_config(channel ? conf_data_ch1_select : conf_data_ch3_select, sizeof(conf_data_ch3_select)/2);
|
||||||
2, 0x00, 0x01, /* Select Page 1 */
|
|
||||||
2, 0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */
|
|
||||||
2, 0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */
|
|
||||||
0 // sentinel
|
|
||||||
};
|
|
||||||
const uint8_t ch1[] = {
|
|
||||||
2, 0x00, 0x01, /* Select Page 1 */
|
|
||||||
2, 0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */
|
|
||||||
2, 0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */
|
|
||||||
0 // sentinel
|
|
||||||
};
|
|
||||||
tlv320aic3204_config(channel ? ch1 : ch3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tlv320aic3204_set_gain(int lgain, int rgain)
|
void tlv320aic3204_set_gain(int lgain, int rgain)
|
||||||
{
|
{
|
||||||
uint8_t data[] = {
|
uint8_t data[] = {
|
||||||
2, 0x00, 0x01, /* Select Page 1 */
|
0x00, 0x01, /* Select Page 1 */
|
||||||
2, 0x3b, lgain, /* Unmute Left MICPGA, set gain */
|
0x3b, lgain, /* Unmute Left MICPGA, set gain */
|
||||||
2, 0x3c, rgain, /* Unmute Right MICPGA, set gain */
|
0x3c, rgain, /* Unmute Right MICPGA, set gain */
|
||||||
0 // sentinel
|
};
|
||||||
};
|
tlv320aic3204_config(data, sizeof(data)/2);
|
||||||
tlv320aic3204_config(data);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
80
ui.c
80
ui.c
|
|
@ -25,12 +25,12 @@
|
||||||
//#include <stdlib.h>
|
//#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
uistat_t uistat = {
|
uistat_t uistat = {
|
||||||
digit: 6,
|
digit: 6,
|
||||||
current_trace: 0,
|
current_trace: 0,
|
||||||
lever_mode: LM_MARKER,
|
lever_mode: LM_MARKER,
|
||||||
marker_delta: FALSE,
|
marker_delta: FALSE,
|
||||||
|
marker_tracking : FALSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NO_EVENT 0
|
#define NO_EVENT 0
|
||||||
|
|
@ -41,9 +41,9 @@ uistat_t uistat = {
|
||||||
#define EVT_DOWN 0x20
|
#define EVT_DOWN 0x20
|
||||||
#define EVT_REPEAT 0x40
|
#define EVT_REPEAT 0x40
|
||||||
|
|
||||||
#define BUTTON_DOWN_LONG_TICKS 5000 /* 1sec */
|
#define BUTTON_DOWN_LONG_TICKS 5000 /* 1sec */
|
||||||
#define BUTTON_DOUBLE_TICKS 5000 /* 500ms */
|
#define BUTTON_DOUBLE_TICKS 2500 /* 500ms */
|
||||||
#define BUTTON_REPEAT_TICKS 1000 /* 100ms */
|
#define BUTTON_REPEAT_TICKS 625 /* 125ms */
|
||||||
#define BUTTON_DEBOUNCE_TICKS 200
|
#define BUTTON_DEBOUNCE_TICKS 200
|
||||||
|
|
||||||
/* lever switch assignment */
|
/* lever switch assignment */
|
||||||
|
|
@ -59,7 +59,7 @@ static uint32_t last_button_down_ticks;
|
||||||
static uint32_t last_button_repeat_ticks;
|
static uint32_t last_button_repeat_ticks;
|
||||||
static int8_t inhibit_until_release = FALSE;
|
static int8_t inhibit_until_release = FALSE;
|
||||||
|
|
||||||
uint8_t operation_requested = OP_NONE;
|
volatile uint8_t operation_requested = OP_NONE;
|
||||||
|
|
||||||
int8_t previous_marker = -1;
|
int8_t previous_marker = -1;
|
||||||
|
|
||||||
|
|
@ -71,8 +71,14 @@ enum {
|
||||||
KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, KM_SCALE, KM_REFPOS, KM_EDELAY, KM_VELOCITY_FACTOR, KM_SCALEDELAY
|
KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, KM_SCALE, KM_REFPOS, KM_EDELAY, KM_VELOCITY_FACTOR, KM_SCALEDELAY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NUMINPUT_LEN 10
|
||||||
|
|
||||||
static uint8_t ui_mode = UI_NORMAL;
|
static uint8_t ui_mode = UI_NORMAL;
|
||||||
static uint8_t keypad_mode;
|
static uint8_t keypad_mode;
|
||||||
|
static uint8_t keypads_last_index;
|
||||||
|
static char kp_buf[NUMINPUT_LEN+1];
|
||||||
|
static int8_t kp_index = 0;
|
||||||
|
static uint8_t menu_current_level = 0;
|
||||||
static int8_t selection = 0;
|
static int8_t selection = 0;
|
||||||
|
|
||||||
// Set structure align as WORD (save flash memory)
|
// Set structure align as WORD (save flash memory)
|
||||||
|
|
@ -98,18 +104,13 @@ static int16_t last_touch_y;
|
||||||
//int16_t touch_cal[4] = { 1000, 1000, 10*16, 12*16 };
|
//int16_t touch_cal[4] = { 1000, 1000, 10*16, 12*16 };
|
||||||
//int16_t touch_cal[4] = { 620, 600, 130, 180 };
|
//int16_t touch_cal[4] = { 620, 600, 130, 180 };
|
||||||
|
|
||||||
int awd_count;
|
//int awd_count;
|
||||||
//int touch_x, touch_y;
|
//int touch_x, touch_y;
|
||||||
|
|
||||||
#define NUMINPUT_LEN 10
|
|
||||||
|
|
||||||
#define KP_CONTINUE 0
|
#define KP_CONTINUE 0
|
||||||
#define KP_DONE 1
|
#define KP_DONE 1
|
||||||
#define KP_CANCEL 2
|
#define KP_CANCEL 2
|
||||||
|
|
||||||
static char kp_buf[NUMINPUT_LEN+1];
|
|
||||||
static int8_t kp_index = 0;
|
|
||||||
|
|
||||||
static void ui_mode_normal(void);
|
static void ui_mode_normal(void);
|
||||||
static void ui_mode_menu(void);
|
static void ui_mode_menu(void);
|
||||||
static void ui_mode_numeric(int _keypad_mode);
|
static void ui_mode_numeric(int _keypad_mode);
|
||||||
|
|
@ -130,33 +131,29 @@ static int btn_check(void)
|
||||||
int status = 0;
|
int status = 0;
|
||||||
uint32_t ticks = chVTGetSystemTime();
|
uint32_t ticks = chVTGetSystemTime();
|
||||||
if (changed & (1<<BIT_PUSH)) {
|
if (changed & (1<<BIT_PUSH)) {
|
||||||
if (ticks - last_button_down_ticks >= BUTTON_DEBOUNCE_TICKS) {
|
if ((cur_button & (1<<BIT_PUSH))
|
||||||
if (cur_button & (1<<BIT_PUSH)) {
|
&& ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS) {
|
||||||
// button released
|
// button released
|
||||||
status |= EVT_BUTTON_SINGLE_CLICK;
|
status |= EVT_BUTTON_SINGLE_CLICK;
|
||||||
if (inhibit_until_release) {
|
if (inhibit_until_release) {
|
||||||
status = 0;
|
status = 0;
|
||||||
inhibit_until_release = FALSE;
|
inhibit_until_release = FALSE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
last_button_down_ticks = ticks;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed & (1<<BIT_UP1)) {
|
if (changed & (1<<BIT_UP1)) {
|
||||||
if ((cur_button & (1<<BIT_UP1))
|
if ((cur_button & (1<<BIT_UP1))
|
||||||
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
|
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
|
||||||
status |= EVT_UP;
|
status |= EVT_UP;
|
||||||
}
|
}
|
||||||
last_button_down_ticks = ticks;
|
|
||||||
}
|
}
|
||||||
if (changed & (1<<BIT_DOWN1)) {
|
if (changed & (1<<BIT_DOWN1)) {
|
||||||
if ((cur_button & (1<<BIT_DOWN1))
|
if ((cur_button & (1<<BIT_DOWN1))
|
||||||
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
|
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
|
||||||
status |= EVT_DOWN;
|
status |= EVT_DOWN;
|
||||||
}
|
}
|
||||||
last_button_down_ticks = ticks;
|
|
||||||
}
|
}
|
||||||
|
last_button_down_ticks = ticks;
|
||||||
last_button = cur_button;
|
last_button = cur_button;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
@ -169,15 +166,14 @@ static int btn_wait_release(void)
|
||||||
int changed = last_button ^ cur_button;
|
int changed = last_button ^ cur_button;
|
||||||
uint32_t ticks = chVTGetSystemTime();
|
uint32_t ticks = chVTGetSystemTime();
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
if (!inhibit_until_release) {
|
if (!inhibit_until_release) {
|
||||||
if ((cur_button & (1<<BIT_PUSH))
|
if ((cur_button & (1<<BIT_PUSH))
|
||||||
&& ticks - last_button_down_ticks >= BUTTON_DOWN_LONG_TICKS) {
|
&& ticks >= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS) {
|
||||||
inhibit_until_release = TRUE;
|
inhibit_until_release = TRUE;
|
||||||
return EVT_BUTTON_DOWN_LONG;
|
return EVT_BUTTON_DOWN_LONG;
|
||||||
}
|
}
|
||||||
if ((changed & (1<<BIT_PUSH))
|
if ((changed & (1<<BIT_PUSH))
|
||||||
&& ticks - last_button_down_ticks < BUTTON_DOWN_LONG_TICKS) {
|
&& ticks < last_button_down_ticks + BUTTON_DOWN_LONG_TICKS) {
|
||||||
return EVT_BUTTON_SINGLE_CLICK;
|
return EVT_BUTTON_SINGLE_CLICK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,14 +186,12 @@ static int btn_wait_release(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ticks - last_button_down_ticks >= BUTTON_DOWN_LONG_TICKS
|
if (ticks >= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS
|
||||||
&& ticks - last_button_repeat_ticks >= BUTTON_REPEAT_TICKS) {
|
&& ticks >= last_button_repeat_ticks + BUTTON_REPEAT_TICKS) {
|
||||||
if (cur_button & (1<<BIT_DOWN1)) {
|
if (cur_button & (1<<BIT_DOWN1))
|
||||||
status |= EVT_DOWN | EVT_REPEAT;
|
status |= EVT_DOWN | EVT_REPEAT;
|
||||||
}
|
if (cur_button & (1<<BIT_UP1))
|
||||||
if (cur_button & (1<<BIT_UP1)) {
|
|
||||||
status |= EVT_UP | EVT_REPEAT;
|
status |= EVT_UP | EVT_REPEAT;
|
||||||
}
|
|
||||||
last_button_repeat_ticks = ticks;
|
last_button_repeat_ticks = ticks;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
@ -776,7 +770,7 @@ menu_marker_search_cb(int item, uint8_t data)
|
||||||
i = marker_search_right(markers[active_marker].index);
|
i = marker_search_right(markers[active_marker].index);
|
||||||
break;
|
break;
|
||||||
case 4: /* tracking */
|
case 4: /* tracking */
|
||||||
marker_tracking = !marker_tracking;
|
uistat.marker_tracking = !uistat.marker_tracking;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i != -1)
|
if (i != -1)
|
||||||
|
|
@ -1047,7 +1041,6 @@ const menuitem_t menu_top[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MENU_STACK_DEPTH_MAX 4
|
#define MENU_STACK_DEPTH_MAX 4
|
||||||
uint8_t menu_current_level = 0;
|
|
||||||
const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = {
|
const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = {
|
||||||
menu_top, NULL, NULL, NULL
|
menu_top, NULL, NULL, NULL
|
||||||
};
|
};
|
||||||
|
|
@ -1171,7 +1164,6 @@ typedef struct {
|
||||||
} keypads_t;
|
} keypads_t;
|
||||||
|
|
||||||
static const keypads_t *keypads;
|
static const keypads_t *keypads;
|
||||||
static uint8_t keypads_last_index;
|
|
||||||
|
|
||||||
static const keypads_t keypads_freq[] = {
|
static const keypads_t keypads_freq[] = {
|
||||||
{ 1, 3, KP_PERIOD },
|
{ 1, 3, KP_PERIOD },
|
||||||
|
|
@ -1345,7 +1337,7 @@ menu_item_modify_attribute(const menuitem_t *menu, int item,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (menu == menu_marker_search) {
|
} else if (menu == menu_marker_search) {
|
||||||
if (item == 4 && marker_tracking) {
|
if (item == 4 && uistat.marker_tracking) {
|
||||||
*bg = DEFAULT_MENU_TEXT_COLOR;
|
*bg = DEFAULT_MENU_TEXT_COLOR;
|
||||||
*fg = config.menu_normal_color;
|
*fg = config.menu_normal_color;
|
||||||
}
|
}
|
||||||
|
|
@ -1535,7 +1527,7 @@ fetch_numeric_target(void)
|
||||||
x /= 10;
|
x /= 10;
|
||||||
uistat.digit = n;
|
uistat.digit = n;
|
||||||
}
|
}
|
||||||
uistat.previous_value = uistat.value;
|
// uistat.previous_value = uistat.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -2152,7 +2144,7 @@ touch_lever_mode_select(void)
|
||||||
static
|
static
|
||||||
void ui_process_touch(void)
|
void ui_process_touch(void)
|
||||||
{
|
{
|
||||||
awd_count++;
|
// awd_count++;
|
||||||
adc_stop(ADC1);
|
adc_stop(ADC1);
|
||||||
|
|
||||||
int status = touch_check();
|
int status = touch_check();
|
||||||
|
|
@ -2189,14 +2181,10 @@ void ui_process_touch(void)
|
||||||
void
|
void
|
||||||
ui_process(void)
|
ui_process(void)
|
||||||
{
|
{
|
||||||
switch (operation_requested) {
|
if (operation_requested&OP_LEVER)
|
||||||
case OP_LEVER:
|
|
||||||
ui_process_lever();
|
ui_process_lever();
|
||||||
break;
|
if (operation_requested&OP_TOUCH)
|
||||||
case OP_TOUCH:
|
|
||||||
ui_process_touch();
|
ui_process_touch();
|
||||||
break;
|
|
||||||
}
|
|
||||||
operation_requested = OP_NONE;
|
operation_requested = OP_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2204,7 +2192,7 @@ ui_process(void)
|
||||||
static void extcb1(EXTDriver *extp, expchannel_t channel) {
|
static void extcb1(EXTDriver *extp, expchannel_t channel) {
|
||||||
(void)extp;
|
(void)extp;
|
||||||
(void)channel;
|
(void)channel;
|
||||||
operation_requested = OP_LEVER;
|
operation_requested|=OP_LEVER;
|
||||||
//cur_button = READ_PORT() & BUTTON_MASK;
|
//cur_button = READ_PORT() & BUTTON_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2259,7 +2247,7 @@ test_touch(int *x, int *y)
|
||||||
void
|
void
|
||||||
handle_touch_interrupt(void)
|
handle_touch_interrupt(void)
|
||||||
{
|
{
|
||||||
operation_requested = OP_TOUCH;
|
operation_requested|= OP_TOUCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue