diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 062d7fe9..700e19f5 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -88,26 +88,26 @@ bool sample_rate_set(const uint32_t sample_rate_hz) { #ifdef JAWBREAKER uint32_t p1 = 4608; - switch(sample_rate_hz) { - case 5000000: - p1 = 9728; // 800MHz / 80 = 10 MHz (SGPIO), 5 MHz (codec) - break; - - case 10000000: - p1 = 4608; // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec) - break; - - case 12500000: - p1 = 3584; // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec) - break; - - case 16000000: - p1 = 2688; // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec) - break; - - case 20000000: - p1 = 2048; // 800MHz / 20 = 40 MHz (SGPIO), 20 MHz (codec) + switch(sample_rate_hz) { + case 8000000: + p1 = SI_INTDIV(50); // 800MHz / 50 = 16 MHz (SGPIO), 8 MHz (codec) break; + + case 10000000: + p1 = SI_INTDIV(40); // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec) + break; + + case 12500000: + p1 = SI_INTDIV(32); // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec) + break; + + case 16000000: + p1 = SI_INTDIV(25); // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec) + break; + + case 20000000: + p1 = SI_INTDIV(20); // 800MHz / 20 = 40 MHz (SGPIO), 20 MHz (codec) + break; default: return false; @@ -117,13 +117,13 @@ bool sample_rate_set(const uint32_t sample_rate_hz) { si5351c_configure_multisynth(0, p1, 0, 1, 1); /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ - si5351c_configure_multisynth(1, p1, 0, 1, 0); + si5351c_configure_multisynth(1, p1, 0, 1, 0);//p1 doesn't matter /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ - si5351c_configure_multisynth(2, p1, 0, 1, 0); + si5351c_configure_multisynth(2, p1, 0, 1, 0);//p1 doesn't matter /* MS0/CLK3 is the source for the external clock output. */ - si5351c_configure_multisynth(3, p1, 0, 1, 0); + //si5351c_configure_multisynth(3, p1, 0, 1, 0); // no clk out return true; #endif @@ -186,19 +186,23 @@ void cpu_clock_init(void) */ /* MS4/CLK4 is the source for the RFFC5071 mixer. */ - si5351c_configure_multisynth(4, 1536, 0, 1, 0); /* 50MHz */ - - /* MS5/CLK5 is the source for the MAX2837 clock input. */ - si5351c_configure_multisynth(5, 2048, 0, 1, 0); /* 40MHz */ + si5351c_configure_multisynth(4, 16*128-512, 0, 1, 0); /* 800/16 = 50MHz */ + + /* MS5/CLK5 is the source for the MAX2837 clock input. */ + si5351c_configure_multisynth(5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */ /* MS7/CLK7 is the source for the LPC43xx microcontroller. */ - //si5351c_configure_multisynth(7, 8021, 0, 3, 0); /* 12MHz */ + //uint8_t ms7data[] = { 91, 40, 0x0 }; + //si5351c_write(ms7data, sizeof(ms7data)); #endif /* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */ sample_rate_set(10000000); si5351c_configure_clock_control(); + // soft reset + uint8_t resetdata[] = { 177, 0xac }; + si5351c_write(resetdata, sizeof(resetdata)); si5351c_enable_clock_outputs(); //FIXME disable I2C @@ -405,6 +409,9 @@ void pin_setup(void) { scu_pinmux(SCU_SSP1_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + + /* Configure external clock in */ + //scu_pinmux(P4_7, SCU_CLK_IN | SCU_CONF_FUNCTION1); } void enable_1v8_power(void) { diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index eff4b498..59b478b3 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -87,7 +87,16 @@ void si5351c_disable_oeb_pin_control() /* Power down all CLKx */ void si5351c_power_down_all_clocks() { - uint8_t data[] = { 16, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0 }; + uint8_t data[] = { 16 + , SI5351C_CLK_POWERDOWN + , SI5351C_CLK_POWERDOWN + , SI5351C_CLK_POWERDOWN + , SI5351C_CLK_POWERDOWN + , SI5351C_CLK_POWERDOWN + , SI5351C_CLK_POWERDOWN + , SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE + , SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE + }; si5351c_write(data, sizeof(data)); } @@ -127,8 +136,11 @@ void si5351c_configure_pll_sources_for_xtal() /* MultiSynth NA (PLL1) */ void si5351c_configure_pll1_multisynth() { - uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 }; - si5351c_write(data, sizeof(data)); + //init plla and pllb to (0x0e00+512)/128*25mhz xtal = 800mhz -> int mode + uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 }; + si5351c_write(data, sizeof(data)); + //~ data[0] =34;// pllb + //~ si5351c_write(data, sizeof(data)); } void si5351c_configure_multisynth(const uint_fast8_t ms_number, @@ -215,67 +227,25 @@ void si5351c_configure_clock_control() #endif #ifdef JAWBREAKER -/* - * Registers 16 through 23: CLKx Control - * CLK0: - * CLK0_PDN=0 (powered up) - * MS0_INT=1 (integer mode) - * MS0_SRC=0 (PLLA as source for MultiSynth 0) - * CLK0_INV=0 (not inverted) - * CLK0_SRC=3 (MS0 as input source) - * CLK0_IDRV=3 (8mA) - * CLK1: - * CLK1_PDN=0 (powered up) - * MS1_INT=1 (integer mode) - * MS1_SRC=0 (PLLA as source for MultiSynth 1) - * CLK1_INV=0 (not inverted) - * CLK1_SRC=2 (MS0 as input source) - * CLK1_IDRV=3 (8mA) - * CLK2: - * CLK2_PDN=0 (powered up) - * MS2_INT=1 (integer mode) - * MS2_SRC=0 (PLLA as source for MultiSynth 2) - * CLK2_INV=0 (not inverted) - * CLK2_SRC=2 (MS0 as input source) - * CLK2_IDRV=3 (8mA) - * CLK3: - * CLK3_PDN=0 (powered up) - * MS3_INT=1 (integer mode) - * MS3_SRC=0 (PLLA as source for MultiSynth 3) - * CLK3_INV=0 (inverted) - * CLK3_SRC=2 (MS0 as input source) - * CLK3_IDRV=3 (8mA) - * CLK4: - * CLK4_PDN=0 (powered up) - * MS4_INT=1 (integer mode) - * MS4_SRC=0 (PLLA as source for MultiSynth 4) - * CLK4_INV=0 (not inverted) - * CLK4_SRC=3 (MS4 as input source) - * CLK4_IDRV=3 (8mA) - * CLK5: - * CLK5_PDN=0 (powered up) - * MS5_INT=1 (integer mode) - * MS5_SRC=0 (PLLA as source for MultiSynth 5) - * CLK5_INV=0 (not inverted) - * CLK5_SRC=3 (MS5 as input source) - * CLK5_IDRV=3 (8mA) - * CLK6: (not connected) - * CLK5_PDN=1 (powered down) - * MS5_INT=1 (integer mode) - * CLK7: (not connected) - * CLK7_PDN=1 (powered down) - * MS7_INT=0 (fractional mode -- to support 12MHz to LPC) - */ void si5351c_configure_clock_control() { - uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x4F, 0x4F, 0xC0, 0x80 }; + uint8_t data[] = {16 + ,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA) + ,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA) + ,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA) + ,SI5351C_CLK_POWERDOWN /*not connected, clock out*/ + ,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA) + ,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA) + ,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/ + ,SI5351C_CLK_POWERDOWN/* pllb int mode*/| SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA) + }; si5351c_write(data, sizeof(data)); } #endif -/* Enable CLK outputs 0, 1, 2, 3, 4, 5 only. */ -void si5351c_enable_clock_outputs() -{ - uint8_t data[] = { 3, 0xC0 }; - si5351c_write(data, sizeof(data)); -} +/* Enable CLK outputs 0, 1, 2, 4, 5, 7 only. */ + void si5351c_enable_clock_outputs() + { + uint8_t data[] = { 3, 0xC8 }; + si5351c_write(data, sizeof(data)); + } diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 8cd583ed..ac57a8f9 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -30,8 +30,30 @@ extern "C" #include +#define SI_INTDIV(x) (x*128-512) #define SI5351C_I2C_ADDR (0x60 << 1) +#define SI5351C_CLK_POWERDOWN (1<<7) +#define SI5351C_CLK_INT_MODE (1<<6) + +#define SI5351C_CLK_PLL_SRC(x) (x<<5) +#define SI5351C_CLK_PLL_SRC_A 0 +#define SI5351C_CLK_PLL_SRC_B 1 + +#define SI5351C_CLK_INV (1<<4) + +#define SI5351C_CLK_SRC(x) (x<<2) +#define SI5351C_CLK_SRC_XTAL 0 +#define SI5351C_CLK_SRC_CLKIN 1 +#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2 +#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3 + +#define SI5351C_CLK_IDRV(x) (x<<0) +#define SI5351C_CLK_IDRV_2MA 0 +#define SI5351C_CLK_IDRV_4MA 1 +#define SI5351C_CLK_IDRV_6MA 2 +#define SI5351C_CLK_IDRV_8MA 3 + void si5351c_disable_all_outputs(); void si5351c_disable_oeb_pin_control(); void si5351c_power_down_all_clocks(); diff --git a/host/hackrf-tools/src/hackrf_si5351c.c b/host/hackrf-tools/src/hackrf_si5351c.c index 398b7272..f9e86910 100644 --- a/host/hackrf-tools/src/hackrf_si5351c.c +++ b/host/hackrf-tools/src/hackrf_si5351c.c @@ -107,40 +107,56 @@ int dump_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number) uint_fast8_t reg_base; uint16_t parameters[8]; uint32_t p1,p2,p3,r_div; + uint_fast8_t div_lut[] = {1,2,4,8,16,32,64,128}; - reg_base = 42 + (ms_number * 8); - for(i=0; i<8; i++) { - uint_fast8_t reg_number = reg_base + i; - int result = hackrf_si5351c_read(device, reg_number, ¶meters[i]); - if( result != HACKRF_SUCCESS ) { - return result; - } - } - - p1 = - (parameters[2] & 0x03 << 16) - | (parameters[3] << 8) - | parameters[4] - ; - p2 = - (parameters[5] & 0x0F << 16) - | (parameters[6] << 8) - | parameters[7] - ; - p3 = - (parameters[5] & 0xF0 << 12) - | (parameters[0] << 8) - | parameters[1] - ; - r_div = - (parameters[2] >> 4) & 0x7 - ; - - printf("MS%d:", ms_number); - printf("\tp1 = %u\n", p1); - printf("\tp2 = %u\n", p2); - printf("\tp3 = %u\n", p3); - printf("\toutput divider = %u\n", 1 << r_div); + printf("MS%d:", ms_number); + if(ms_number <6){ + reg_base = 42 + (ms_number * 8); + for(i=0; i<8; i++) { + uint_fast8_t reg_number = reg_base + i; + int result = hackrf_si5351c_read(device, reg_number, ¶meters[i]); + if( result != HACKRF_SUCCESS ) { + return result; + } + } + + p1 = + (parameters[2] & 0x03 << 16) + | (parameters[3] << 8) + | parameters[4] + ; + p2 = + (parameters[5] & 0x0F << 16) + | (parameters[6] << 8) + | parameters[7] + ; + p3 = + (parameters[5] & 0xF0 << 12) + | (parameters[0] << 8) + | parameters[1] + ; + r_div = + (parameters[2] >> 4) & 0x7 + ; + + printf("\tp1 = %u\n", p1); + printf("\tp2 = %u\n", p2); + printf("\tp3 = %u\n", p3); + } else { + // MS6 and 7 are integer only + reg_base = 90; + for(i=0; i<3; i++) { + uint_fast8_t reg_number = reg_base + i; + int result = hackrf_si5351c_read(device, reg_number, ¶meters[i]); + if( result != HACKRF_SUCCESS ) { + return result; + } + } + + r_div = (ms_number == 6) ? parameters[2] & 0x7 : parameters[2] & 0x70 >> 4 ; + printf("\tp1_int = %u\n", (ms_number == 6) ? parameters[0] : parameters[1]); + } + printf("\toutput divider = %u\n", div_lut[r_div]); return HACKRF_SUCCESS; } diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index d1e2a35c..3274ef30 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -318,6 +318,9 @@ static void usage() { printf("\t-t # Transmit data from file.\n"); printf("\t[-f set_freq_hz] # Set Freq in Hz between [%lluMHz, %lluMHz[.\n", FREQ_MIN_HZ/FREQ_ONE_MHZ, FREQ_MAX_HZ/FREQ_ONE_MHZ); printf("\t[-a set_amp] # Set Amp 1=Enable, 0=Disable.\n"); + printf("\t[-l gain_db] # Set lna gain, 0-40dB, 8dB steps\n"); + printf("\t[-i gain_db] # Set vga(if) gain, 0-62dB, 2dB steps\n"); + printf("\t[-x gain_db] # Set TX vga gain, 0-47dB, 1dB steps\n"); printf("\t[-s sample_rate_hz] # Set sample rate in Hz (5/10/12.5/16/20MHz, default %lldMHz).\n", DEFAULT_SAMPLE_RATE_HZ/FREQ_ONE_MHZ); printf("\t[-n num_samples] # Number of samples to transfer (default is unlimited).\n"); printf("\t[-b baseband_filter_bw_hz] # Set baseband filter bandwidth in MHz.\n\tPossible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz, default < sample_rate_hz.\n" ); @@ -359,8 +362,9 @@ int main(int argc, char** argv) { int exit_code = EXIT_SUCCESS; struct timeval t_end; float time_diff; + unsigned int lna_gain=8, vga_gain=20, txvga_gain=0; - while( (opt = getopt(argc, argv, "wr:t:f:a:s:n:b:")) != EOF ) + while( (opt = getopt(argc, argv, "wr:t:f:a:s:n:b:l:i:x:")) != EOF ) { result = HACKRF_SUCCESS; switch( opt ) @@ -389,6 +393,18 @@ int main(int argc, char** argv) { result = parse_u32(optarg, &_enable); break; + case 'l': + result = parse_u32(optarg, &lna_gain); + break; + + case 'i': + result = parse_u32(optarg, &vga_gain); + break; + + case 'x': + result = parse_u32(optarg, &txvga_gain); + break; + case 's': sample_rate = true; result = parse_u32(optarg, &sample_rate_hz); @@ -592,9 +608,12 @@ int main(int argc, char** argv) { } if( transceiver_mode == TRANSCEIVER_MODE_RX ) { - result = hackrf_start_rx(device, rx_callback, NULL); + result = hackrf_set_vga_gain(device, vga_gain); + result |= hackrf_set_lna_gain(device, lna_gain); + result |= hackrf_start_rx(device, rx_callback, NULL); } else { - result = hackrf_start_tx(device, tx_callback, NULL); + result = hackrf_set_txvga_gain(device, txvga_gain); + result |= hackrf_start_tx(device, tx_callback, NULL); } if( result != HACKRF_SUCCESS ) { printf("hackrf_start_?x() failed: %s (%d)\n", hackrf_error_name(result), result); diff --git a/host/libhackrf/CMakeLists.txt b/host/libhackrf/CMakeLists.txt index 4bfc7d8d..fba159ce 100644 --- a/host/libhackrf/CMakeLists.txt +++ b/host/libhackrf/CMakeLists.txt @@ -32,13 +32,12 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules) if(MSVC) set(THREADS_USE_PTHREADS_WIN32 true) -find_package(Threads REQUIRED) else() add_definitions(-Wall) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90") endif() find_package(USB1 REQUIRED) - +find_package(Threads REQUIRED) include_directories(${LIBUSB_INCLUDE_DIR} ${THREADS_PTHREADS_INCLUDE_DIR})