diff --git a/firmware/common/Makefile_inc.mk b/firmware/common/Makefile_inc.mk index 4b51f8fa..8917beda 100644 --- a/firmware/common/Makefile_inc.mk +++ b/firmware/common/Makefile_inc.mk @@ -50,7 +50,7 @@ OBJDUMP = $(PREFIX)-objdump GDB = $(PREFIX)-gdb TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX) -CFLAGS += -std=c99 -Os -g3 -Wall -Wextra -I$(LIBOPENCM3)/include -I../common \ +CFLAGS += -std=gnu99 -Os -g3 -Wall -Wextra -I$(LIBOPENCM3)/include -I../common \ -fno-common -mcpu=cortex-m4 -mthumb -MD \ -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ $(HACKRF_OPTS) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 062d7fe9..d1be02e7 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -39,6 +39,69 @@ void delay(uint32_t duration) __asm__("nop"); } +bool set_fracrate(const float freq) { + + uint32_t MSx_P1,MSx_P2,MSx_P3; + uint32_t b,c; + float div = (800/freq); + uint32_t a = (uint32_t)div; + float x = div-a; + + if(a != div){ + uint32_t j=0,k=1,l=1,m=1; + while (k <= 0xFFFF && m <= 0xFFFF){ + float n = (float)(j+l)/(k+m); + if( x == n){ + if(k + m <= 0xFFFF){ + b=j+l; c=k+m; + break; + } else if(m > k){ + b=l; c=m; + break; + } else { + b=j; c=k; + break; + } + } + else if(x > n){ + j+=l; k+=m; + } + else{ + l+=j; m+=k; + } + } + if (k > 0xFFFF){ + b=l; c=m; + } + else{ + b=j; c=k; + } + } else { + b=0; c=1; + } + + MSx_P1 = 128*a + (128 * b/c) - 512; + MSx_P2 = (128*b)%c; + MSx_P3 = c; + + + /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ + si5351c_configure_multisynth(0, MSx_P1, MSx_P2, MSx_P3, 1); + + /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ + si5351c_configure_multisynth(1, 0, 0, 0, 0);//p1 doesn't matter + + /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ + si5351c_configure_multisynth(2, 0, 0, 0, 0);//p1 doesn't matter + + /* MS0/CLK3 is the source for the external clock output. */ + //si5351c_configure_multisynth(3, p1, 0, 1, 0); // no clk out + + return true; + +} + + bool sample_rate_set(const uint32_t sample_rate_hz) { #ifdef JELLYBEAN /* Due to design issues, Jellybean/Lemondrop frequency plan is limited. @@ -88,26 +151,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 +180,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 +249,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 +472,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/hackrf_core.h b/firmware/common/hackrf_core.h index 462f8b1d..d32f27e4 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -259,6 +259,7 @@ void pin_setup(void); void enable_1v8_power(void); +bool set_fracrate(const float sampling_rate_mhz); bool sample_rate_set(const uint32_t sampling_rate_hz); bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz); diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index eff4b498..6cc0d253 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_FRAC_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 | SI5351C_CLK_INT_MODE /* pllb int mode*/| SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_B) | 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..12f1dc3a 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -30,8 +30,31 @@ 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_FRAC_MODE (0<<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/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 83059efa..e42fbb9e 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -67,6 +67,12 @@ typedef struct { set_freq_params_t set_freq_params; +typedef struct { + float freq_mhz; +} set_sample_r_params_t; + +set_sample_r_params_t set_sample_r_params; + uint8_t switchctrl = 0; void update_switches(void) @@ -696,6 +702,28 @@ usb_request_status_t usb_vendor_request_set_freq( } } +usb_request_status_t usb_vendor_request_set_fracrate( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage) +{ + if (stage == USB_TRANSFER_STAGE_SETUP) + { + usb_endpoint_schedule(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t)); + return USB_REQUEST_STATUS_OK; + } else if (stage == USB_TRANSFER_STAGE_DATA) + { + if( set_fracrate(set_sample_r_params.freq_mhz*2) ) + { + usb_endpoint_schedule_ack(endpoint->in); + return USB_REQUEST_STATUS_OK; + } + return USB_REQUEST_STATUS_STALL; + } else + { + return USB_REQUEST_STATUS_OK; + } +} + usb_request_status_t usb_vendor_request_set_amp_enable( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { @@ -821,7 +849,8 @@ static const usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_read_partid_serialno, usb_vendor_request_set_lna_gain, usb_vendor_request_set_vga_gain, - usb_vendor_request_set_txvga_gain + usb_vendor_request_set_txvga_gain, + usb_vendor_request_set_fracrate }; static const uint32_t vendor_request_handler_count = 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..3423c8f0 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -318,7 +318,10 @@ 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[-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[-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 (8/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..9e376720 100644 --- a/host/libhackrf/CMakeLists.txt +++ b/host/libhackrf/CMakeLists.txt @@ -31,19 +31,56 @@ set(VERSION ${VERSION_STRING}) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules) if(MSVC) -set(THREADS_USE_PTHREADS_WIN32 true) -find_package(Threads REQUIRED) + set(THREADS_USE_PTHREADS_WIN32 true) else() -add_definitions(-Wall) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90") + add_definitions(-Wall) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90") + + INCLUDE(TestBigEndian) + TEST_BIG_ENDIAN(BIGENDIAN) + if(${BIGENDIAN}) + add_definitions(-DBIG_ENDIAN) + endif(${BIGENDIAN}) endif() find_package(USB1 REQUIRED) - +find_package(Threads REQUIRED) include_directories(${LIBUSB_INCLUDE_DIR} ${THREADS_PTHREADS_INCLUDE_DIR}) add_subdirectory(src) +######################################################################## +# Create Pkg Config File +######################################################################## +FOREACH(inc ${LIBUSB_INCLUDE_DIR}) + LIST(APPEND HACKRF_PC_CFLAGS "-I${inc}") +ENDFOREACH(inc) + +# use space-separation format for the pc file +STRING(REPLACE ";" " " HACKRF_PC_CFLAGS "${HACKRF_PC_CFLAGS}") +STRING(REPLACE ";" " " HACKRF_PC_LIBS "${HACKRF_PC_LIBS}") + +# unset these vars to avoid hard-coded paths to cross environment +IF(CMAKE_CROSSCOMPILING) + UNSET(HACKRF_PC_CFLAGS) + UNSET(HACKRF_PC_LIBS) +ENDIF(CMAKE_CROSSCOMPILING) + +set(prefix ${CMAKE_INSTALL_PREFIX}) +set(exec_prefix \${prefix}) +set(libdir \${exec_prefix}/lib) +set(includedir \${prefix}/include) + +CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/libhackrf.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/libhackrf.pc +@ONLY) + +INSTALL( + FILES ${CMAKE_CURRENT_BINARY_DIR}/libhackrf.pc + DESTINATION lib/pkgconfig +) + ######################################################################## # Create uninstall target ######################################################################## diff --git a/host/libhackrf/libhackrf.pc.in b/host/libhackrf/libhackrf.pc.in new file mode 100644 index 00000000..5c9c18d4 --- /dev/null +++ b/host/libhackrf/libhackrf.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: HackRF Library +Description: C Utility Library +Version: @VERSION@ +Cflags: -I${includedir}/ @HACKRF_PC_CFLAGS@ +Libs: -L${libdir} -lhackrf +Libs.private: @HACKRF_PC_LIBS@ diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 410f8f3b..e31fb714 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -33,6 +33,13 @@ typedef int bool; #define true 1 #define false 0 #endif + +#ifdef BIG_ENDIAN +#define TO_LE(x) __builtin_bswap32(x) +#else +#define TO_LE(x) x +#endif + // TODO: Factor this into a shared #include so that firmware can use // the same values. typedef enum { @@ -57,6 +64,7 @@ typedef enum { HACKRF_VENDOR_REQUEST_SET_LNA_GAIN = 19, HACKRF_VENDOR_REQUEST_SET_VGA_GAIN = 20, HACKRF_VENDOR_REQUEST_SET_TXVGA_GAIN = 21, + HACKRF_VENDOR_REQUEST_SET_FRACRATE = 22, } hackrf_vendor_request; typedef enum { @@ -731,8 +739,8 @@ int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz) /* Convert Freq Hz 64bits to Freq MHz (32bits) & Freq Hz (32bits) */ l_freq_mhz = (uint32_t)(freq_hz / FREQ_ONE_MHZ); l_freq_hz = (uint32_t)(freq_hz - (((uint64_t)l_freq_mhz) * FREQ_ONE_MHZ)); - set_freq_params.freq_mhz = l_freq_mhz; - set_freq_params.freq_hz = l_freq_hz; + set_freq_params.freq_mhz = TO_LE(l_freq_mhz); + set_freq_params.freq_hz = TO_LE(l_freq_hz); length = sizeof(set_freq_params_t); result = libusb_control_transfer( @@ -754,6 +762,42 @@ int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz) } } + +typedef struct { + float freq_mhz; +} set_fracrate_params_t; + + +int ADDCALL hackrf_set_fracrate(hackrf_device* device, const float freq_mhz) +{ + uint32_t l_freq_mhz; + uint32_t l_freq_hz; + set_fracrate_params_t set_fracrate_params; + uint8_t length; + int result; + + set_fracrate_params.freq_mhz = TO_LE(freq_mhz); + length = sizeof(set_fracrate_params_t); + + result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_SET_FRACRATE, + 0, + 0, + (unsigned char*)&set_fracrate_params, + length, + 0 + ); + + if (result < length) + { + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + int ADDCALL hackrf_set_amp_enable(hackrf_device* device, const uint8_t value) { int result; @@ -797,6 +841,14 @@ int ADDCALL hackrf_board_partid_serialno_read(hackrf_device* device, read_partid { return HACKRF_ERROR_LIBUSB; } else { + + read_partid_serialno->part_id[0] = TO_LE(read_partid_serialno->part_id[0]); + read_partid_serialno->part_id[0] = TO_LE(read_partid_serialno->part_id[1]); + read_partid_serialno->serial_no[0] = TO_LE(read_partid_serialno->serial_no[0]); + read_partid_serialno->serial_no[1] = TO_LE(read_partid_serialno->serial_no[1]); + read_partid_serialno->serial_no[2] = TO_LE(read_partid_serialno->serial_no[2]); + read_partid_serialno->serial_no[3] = TO_LE(read_partid_serialno->serial_no[3]); + return HACKRF_SUCCESS; } } @@ -804,6 +856,7 @@ int ADDCALL hackrf_board_partid_serialno_read(hackrf_device* device, read_partid int ADDCALL hackrf_set_lna_gain(hackrf_device* device, uint32_t value) { int result; + uint8_t retval; if( value > 40 ) { @@ -812,16 +865,16 @@ int ADDCALL hackrf_set_lna_gain(hackrf_device* device, uint32_t value) result = libusb_control_transfer( device->usb_device, - LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, HACKRF_VENDOR_REQUEST_SET_LNA_GAIN, 0, value, - NULL, - 0, + &retval, + 1, 0 ); - if( result != 0 ) + if( result != 1 || !retval ) { return HACKRF_ERROR_INVALID_PARAM; } else { @@ -832,6 +885,7 @@ int ADDCALL hackrf_set_lna_gain(hackrf_device* device, uint32_t value) int ADDCALL hackrf_set_vga_gain(hackrf_device* device, uint32_t value) { int result; + uint8_t retval; if( value > 62 ) { @@ -840,16 +894,16 @@ int ADDCALL hackrf_set_vga_gain(hackrf_device* device, uint32_t value) result = libusb_control_transfer( device->usb_device, - LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, HACKRF_VENDOR_REQUEST_SET_VGA_GAIN, 0, value, - NULL, - 0, + &retval, + 1, 0 ); - if( result != 0 ) + if( result != 1 || !retval ) { return HACKRF_ERROR_INVALID_PARAM; } else { @@ -860,6 +914,7 @@ int ADDCALL hackrf_set_vga_gain(hackrf_device* device, uint32_t value) int ADDCALL hackrf_set_txvga_gain(hackrf_device* device, uint32_t value) { int result; + uint8_t retval; if( value > 47 ) { @@ -868,16 +923,16 @@ int ADDCALL hackrf_set_txvga_gain(hackrf_device* device, uint32_t value) result = libusb_control_transfer( device->usb_device, - LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, HACKRF_VENDOR_REQUEST_SET_TXVGA_GAIN, 0, value, - NULL, - 0, + &retval, + 1, 0 ); - if( result != 0 ) + if( result != 1 || !retval ) { return HACKRF_ERROR_INVALID_PARAM; } else { @@ -894,7 +949,7 @@ static void* transfer_threadproc(void* arg) while( (device->streaming) && (do_exit == false) ) { error = libusb_handle_events_timeout(g_libusb_context, &timeout); - if( error != 0 ) + if( (error != 0) && (error != LIBUSB_ERROR_INTERRUPTED) ) { device->streaming = false; } diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 14968319..96d2dcf6 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -129,6 +129,7 @@ extern ADDAPI int ADDCALL hackrf_board_id_read(hackrf_device* device, uint8_t* v extern ADDAPI int ADDCALL hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length); extern ADDAPI int ADDCALL hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz); +extern ADDAPI int ADDCALL hackrf_set_fracrate(hackrf_device* device, const float freq_mhz); /* external amp, bool on/off */ extern ADDAPI int ADDCALL hackrf_set_amp_enable(hackrf_device* device, const uint8_t value);