From 549c943979dece29eea52786f0aac6f74d18fb68 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 17 Oct 2012 17:00:36 -0700 Subject: [PATCH] Add USB control of LPF baseband filter. Add max2837_set_lpf_bandwidth() function to choose available LPF filter bandwidth based on bandwidth in Hz. Change configuration of MAX2837 to set LPF_EN and FT at max2837_setup(), not in max2837_rx() or max2837_tx() (which was overriding prior filter configuration). --- firmware/common/hackrf_core.c | 5 ++ firmware/common/hackrf_core.h | 1 + firmware/common/max2837.c | 54 +++++++++++++++++++--- firmware/common/max2837.h | 4 ++ firmware/usb_performance/usb_performance.c | 20 ++++++++ host/libhackrf/examples/hackrf_transfer.c | 6 +++ host/libhackrf/src/hackrf.c | 20 ++++++++ host/libhackrf/src/hackrf.h | 1 + 8 files changed, 105 insertions(+), 6 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index f32214b3..c6efb1dc 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -22,6 +22,7 @@ #include "hackrf_core.h" #include "si5351c.h" +#include "max2837.h" #include #include #include @@ -126,6 +127,10 @@ bool sample_rate_set(const uint32_t sample_rate_hz) { #endif } +bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) { + return max2837_set_lpf_bandwidth(bandwidth_hz); +} + /* clock startup for Jellybean with Lemondrop attached */ void cpu_clock_init(void) { diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 35e7eb30..b406ba90 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -218,6 +218,7 @@ void pin_setup(void); void enable_1v8_power(void); bool sample_rate_set(const uint32_t sampling_rate_hz); +bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz); #ifdef __cplusplus } diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 464aa8b3..c525947d 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -115,6 +115,11 @@ void max2837_setup(void) /* maximum rx output common-mode voltage */ set_MAX2837_BUFF_VCM(MAX2837_BUFF_VCM_1_25); + /* configure baseband filter for 8 MHz TX */ + set_MAX2837_LPF_EN(1); + set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_RxLPF); + set_MAX2837_FT(MAX2837_FT_5M); + max2837_regs_commit(); } @@ -192,10 +197,7 @@ void max2837_tx(void) LOG("# max2837_tx\n"); #if !defined TEST - /* configure baseband filter for 8 MHz TX */ - set_MAX2837_LPF_EN(1); set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_TxLPF); - set_MAX2837_FT(MAX2837_FT_8M); max2837_regs_commit(); gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE); @@ -206,10 +208,7 @@ void max2837_rx(void) { LOG("# max2837_rx\n"); - /* configure baseband filter for 8 MHz RX */ - set_MAX2837_LPF_EN(1); set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_RxLPF); - set_MAX2837_FT(MAX2837_FT_8M); max2837_regs_commit(); #if !defined TEST @@ -290,6 +289,49 @@ void max2837_set_frequency(uint32_t freq) max2837_regs_commit(); } +typedef struct { + uint32_t bandwidth_hz; + uint32_t ft; +} max2837_ft_t; + +static const max2837_ft_t max2837_ft[] = { + { 1750000, MAX2837_FT_1_75M }, + { 2500000, MAX2837_FT_2_5M }, + { 3500000, MAX2837_FT_3_5M }, + { 5000000, MAX2837_FT_5M }, + { 5500000, MAX2837_FT_5_5M }, + { 6000000, MAX2837_FT_6M }, + { 7000000, MAX2837_FT_7M }, + { 8000000, MAX2837_FT_8M }, + { 9000000, MAX2837_FT_9M }, + { 10000000, MAX2837_FT_10M }, + { 12000000, MAX2837_FT_12M }, + { 14000000, MAX2837_FT_14M }, + { 15000000, MAX2837_FT_15M }, + { 20000000, MAX2837_FT_20M }, + { 24000000, MAX2837_FT_24M }, + { 28000000, MAX2837_FT_28M }, + { 0, 0 }, +}; + +bool max2837_set_lpf_bandwidth(const uint32_t bandwidth_hz) { + const max2837_ft_t* p = max2837_ft; + while( p->bandwidth_hz != 0 ) { + if( p->bandwidth_hz >= bandwidth_hz ) { + break; + } + p++; + } + + if( p->bandwidth_hz != 0 ) { + set_MAX2837_FT(p->ft); + max2837_regs_commit(); + return true; + } else { + return false; + } +} + #ifdef TEST int main(int ac, char **av) { diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 50cf38d7..4983ca7e 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -1,6 +1,9 @@ #ifndef __MAX2837_H #define __MAX2837_H +#include +#include + /* TODO - make this a private header for max2837.c only, make new max2837.h */ /* 32 registers, each containing 10 bits of data. */ @@ -40,6 +43,7 @@ extern void max2837_stop(void); /* Set frequency in Hz. Frequency setting is a multi-step function * where order of register writes matters. */ extern void max2837_set_frequency(uint32_t freq); +bool max2837_set_lpf_bandwidth(const uint32_t bandwidth_hz); extern void max2837_tx(void); extern void max2837_rx(void); diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 0e462ed7..a7ecac7f 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -309,6 +309,22 @@ bool usb_vendor_request_set_sample_rate( } } +bool usb_vendor_request_set_baseband_filter_bandwidth( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + if( stage == USB_TRANSFER_STAGE_SETUP ) { + const uint32_t bandwidth = (endpoint->setup.index << 16) | endpoint->setup.value; + if( baseband_filter_bandwidth_set(bandwidth) ) { + usb_endpoint_schedule_ack(endpoint->in); + return true; + } + return false; + } else { + return true; + } +} + void usb_vendor_request( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage @@ -340,6 +356,10 @@ void usb_vendor_request( success = usb_vendor_request_set_sample_rate(endpoint, stage); break; + case 7: + success = usb_vendor_request_set_baseband_filter_bandwidth(endpoint, stage); + break; + default: break; } diff --git a/host/libhackrf/examples/hackrf_transfer.c b/host/libhackrf/examples/hackrf_transfer.c index 13defc3e..b6e80b7c 100644 --- a/host/libhackrf/examples/hackrf_transfer.c +++ b/host/libhackrf/examples/hackrf_transfer.c @@ -171,6 +171,12 @@ int main(int argc, char** argv) { return -1; } + result = hackrf_baseband_filter_bandwidth_set(device, 5000000); + if( result != HACKRF_SUCCESS ) { + printf("hackrf_baseband_filter_bandwidth_set() failed: %s (%d)\n", hackrf_error_name(result), result); + return -1; + } + if( transceiver_mode == TRANSCEIVER_MODE_RX ) { result = hackrf_start_rx(device, rx_callback); } else { diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 518a276c..a3efcf82 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -35,6 +35,7 @@ typedef enum { HACKRF_VENDOR_REQUEST_SI5351C_WRITE = 4, HACKRF_VENDOR_REQUEST_SI5351C_READ = 5, HACKRF_VENDOR_REQUEST_SAMPLE_RATE_SET = 6, + HACKRF_VENDOR_REQUEST_BASEBAND_FILTER_BANDWIDTH_SET = 7, } hackrf_vendor_request; typedef enum { @@ -353,6 +354,25 @@ int hackrf_sample_rate_set(hackrf_device* device, const uint32_t sampling_rate_h } } +int hackrf_baseband_filter_bandwidth_set(hackrf_device* device, const uint32_t bandwidth_hz) { + int result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_BASEBAND_FILTER_BANDWIDTH_SET, + bandwidth_hz & 0xffff, + bandwidth_hz >> 16, + NULL, + 0, + 0 + ); + + if( result != 0 ) { + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + static void* transfer_threadproc(void* arg) { hackrf_device* device = (hackrf_device*)arg; diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index e8113471..8c288ebd 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -68,6 +68,7 @@ int hackrf_si5351c_read(hackrf_device* device, uint16_t register_number, uint16_ int hackrf_si5351c_write(hackrf_device* device, uint16_t register_number, uint16_t value); int hackrf_sample_rate_set(hackrf_device* device, const uint32_t sampling_rate_hz); +int hackrf_baseband_filter_bandwidth_set(hackrf_device* device, const uint32_t bandwidth_hz); const char* hackrf_error_name(enum hackrf_error errcode);