From e2c05fbfe21c831478d66cda7edc152b3ac2dbeb Mon Sep 17 00:00:00 2001 From: TitanMKD Date: Tue, 26 Feb 2013 00:17:18 +0100 Subject: [PATCH 01/14] Draft in progress (not tested at all) set_freq(). --- firmware/common/hackrf_core.c | 90 ++++++++++++++++++++++ firmware/common/hackrf_core.h | 2 + firmware/usb_performance/usb_performance.c | 20 ++++- host/libhackrf/examples/hackrf_transfer.c | 62 ++++++++++++++- host/libhackrf/src/hackrf.c | 23 +++++- host/libhackrf/src/hackrf.h | 2 + 6 files changed, 195 insertions(+), 4 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 5f312bee..ca19304f 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -1,6 +1,7 @@ /* * Copyright 2012 Michael Ossmann * Copyright 2012 Jared Boone + * Copyright 2013 Benjamin Vernoux * * This file is part of HackRF. * @@ -23,12 +24,28 @@ #include "hackrf_core.h" #include "si5351c.h" #include "max2837.h" +#include "rffc5071.h" #include #include #include #include #include +/* Define for set_tune_freq() */ +#define FREQ_ONE_MHZ (1000*1000) + +#define MIN_LP_FREQ_MHZ (30) +#define MAX_LP_FREQ_MHZ (2300) + +#define MIN_BYPASS_FREQ_MHZ (2300) +#define MAX_BYPASS_FREQ_MHZ (2700) + +#define MIN_HP_FREQ_MHZ (2700) +#define MAX_HP_FREQ_MHZ (6000) + +#define MAX2837_FREQ_NOMINAL_HZ (2600000000) +#define MAX2837_FREQ_NOMINAL_MHZ (MAX2837_FREQ_NOMINAL_HZ / FREQ_ONE_MHZ) + void delay(uint32_t duration) { uint32_t i; @@ -391,3 +408,76 @@ void pin_setup(void) { void enable_1v8_power(void) { gpio_set(PORT_EN1V8, PIN_EN1V8); } + +/* +Set freq/tuning between 30MHz to 6000 MHz +hz between 0 to 999999 Hz (not checked) +return false on error or true if success. +*/ +bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) +{ + bool success; + uint32_t RFFC5071_freq_mhz; + uint32_t MAX2837_freq_hz; + uint32_t real_RFFC5071_freq_mhz; + uint32_t tmp_hz; + + success = true; + + if(freq_mhz >= MIN_LP_FREQ_MHZ) + { + if(freq_mhz < MAX_LP_FREQ_MHZ) + { + /* TODO fix/check Switch to LP mode (shall not change RX/TX mode) */ + rffc5071_set_gpo(0); /* SWITCHCTRL_LP = 0 */ + + RFFC5071_freq_mhz = MAX2837_FREQ_NOMINAL_MHZ - freq_mhz; + /* Set Freq and read real freq */ + real_RFFC5071_freq_mhz = rffc5071_set_frequency(RFFC5071_freq_mhz, 0); + if(real_RFFC5071_freq_mhz < RFFC5071_freq_mhz) + { + tmp_hz = -((RFFC5071_freq_mhz - real_RFFC5071_freq_mhz) * FREQ_ONE_MHZ); + }else + { + tmp_hz = ((real_RFFC5071_freq_mhz - RFFC5071_freq_mhz) * FREQ_ONE_MHZ); + } + MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; + max2837_set_frequency(MAX2837_freq_hz); + }else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) + { + /* TODO fix/check Switch to SWITCHCTRL_MIX_BYPASS mode (shall not change RX/TX mode) */ + rffc5071_set_gpo(SWITCHCTRL_MIX_BYPASS); + + MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; + /* RFFC5071_freq_mhz <= not used in Bypass mode */ + max2837_set_frequency(MAX2837_freq_hz); + }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz < MAX_HP_FREQ_MHZ) ) + { + /* TODO fix/check Switch to SWITCHCTRL_HP mode (shall not change RX/TX mode) */ + rffc5071_set_gpo(SWITCHCTRL_HP); + + //switch_ctrl = SWITCHCTRL_HP; + RFFC5071_freq_mhz = freq_mhz - MAX2837_FREQ_NOMINAL_MHZ; + /* Set Freq and read real freq */ + real_RFFC5071_freq_mhz = rffc5071_set_frequency(RFFC5071_freq_mhz, 0); + if(real_RFFC5071_freq_mhz < RFFC5071_freq_mhz) + { + tmp_hz = ((RFFC5071_freq_mhz - real_RFFC5071_freq_mhz) * FREQ_ONE_MHZ); + }else + { + tmp_hz = -((real_RFFC5071_freq_mhz - RFFC5071_freq_mhz) * FREQ_ONE_MHZ); + } + MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; + max2837_set_frequency(MAX2837_freq_hz); + }else + { + /* Error freq_mhz too high */ + success = false; + } + }else + { + /* Error freq_mhz too low */ + success = false; + } + return success; +} diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 71f017da..2d04be8f 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -258,6 +258,8 @@ 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); +bool set_freq(uint32_t freq_mhz, uint32_t freq_hz); + #ifdef __cplusplus } #endif diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 2bb56aaa..a4dfd69d 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -491,6 +491,23 @@ usb_request_status_t usb_vendor_request_read_version_string( return USB_REQUEST_STATUS_OK; } +usb_request_status_t usb_vendor_request_set_freq( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + if( stage == USB_TRANSFER_STAGE_SETUP ) { + const uint32_t freq_mhz = (endpoint->setup.index << 16) | endpoint->setup.value; + const uint32_t freq_hz = 0; /* TODO fix this and retrieve a 32bits */ + if( set_freq(freq_mhz, freq_hz) ) { + usb_endpoint_schedule_ack(endpoint->in); + return USB_REQUEST_STATUS_OK; + } + return USB_REQUEST_STATUS_STALL; + } else { + return USB_REQUEST_STATUS_OK; + } +} + static const usb_request_handler_fn vendor_request_handler[] = { NULL, usb_vendor_request_set_transceiver_mode, @@ -507,7 +524,8 @@ static const usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_read_spiflash, usb_vendor_request_write_cpld, usb_vendor_request_read_board_id, - usb_vendor_request_read_version_string + usb_vendor_request_read_version_string, + usb_vendor_request_set_freq }; static const uint32_t vendor_request_handler_count = diff --git a/host/libhackrf/examples/hackrf_transfer.c b/host/libhackrf/examples/hackrf_transfer.c index dd3dc1f1..99724805 100644 --- a/host/libhackrf/examples/hackrf_transfer.c +++ b/host/libhackrf/examples/hackrf_transfer.c @@ -42,6 +42,9 @@ #include #include +#define FREQ_MIN_MHZ (30) +#define FREQ_MAX_MHZ (6000) + #if defined _WIN32 #define sleep(a) Sleep( (a*1000) ) #endif @@ -59,6 +62,30 @@ TimevalDiff(const struct timeval *a, const struct timeval *b) return (a->tv_sec - b->tv_sec) + 1e-6f * (a->tv_usec - b->tv_usec); } +int parse_int(char* s, uint32_t* const value) { + uint_fast8_t base = 10; + if( strlen(s) > 2 ) { + if( s[0] == '0' ) { + if( (s[1] == 'x') || (s[1] == 'X') ) { + base = 16; + s += 2; + } else if( (s[1] == 'b') || (s[1] == 'B') ) { + base = 2; + s += 2; + } + } + } + + char* s_end = s; + const unsigned long ulong_value = strtoul(s, &s_end, base); + if( (s != s_end) && (*s_end == 0) ) { + *value = ulong_value; + return HACKRF_SUCCESS; + } else { + return HACKRF_ERROR_INVALID_PARAM; + } +} + FILE* fd = NULL; volatile uint32_t byte_count = 0; @@ -67,6 +94,9 @@ bool transmit = false; struct timeval time_start; struct timeval t_start; +bool freq = false; +uint32_t freq_mhz; + int rx_callback(hackrf_transfer* transfer) { if( fd != NULL ) { @@ -105,6 +135,7 @@ static void usage() { printf("Usage:\n"); printf("\t-r # Receive data into file.\n"); printf("\t-t # Transmit data from file.\n"); + printf("\t-f # Set Frequency in MHz (between [%ld, %ld[).\n", FREQ_MIN_MHZ, FREQ_MAX_MHZ); } static hackrf_device* device = NULL; @@ -168,8 +199,10 @@ void sigint_callback_handler(int signum) int main(int argc, char** argv) { int opt; const char* path = NULL; + int result; - while( (opt = getopt(argc, argv, "r:t:")) != EOF ) { + while( (opt = getopt(argc, argv, "r:t:f:")) != EOF ) { + result = HACKRF_SUCCESS; switch( opt ) { case 'r': receive = true; @@ -181,10 +214,26 @@ int main(int argc, char** argv) { path = optarg; break; + case 'f': + freq = true; + result = parse_int(optarg, &freq_mhz); + break; + default: usage(); return EXIT_FAILURE; } + + if( result != HACKRF_SUCCESS ) { + printf("argument error: %s (%d)\n", hackrf_error_name(result), result); + usage(); + break; + } + } + + if( freq ) { + if( (freq_mhz >= 6000) || (freq_mhz < 30) ) + printf("argument error: frequency shall be between [%ld, %ld[.\n", FREQ_MIN_MHZ, FREQ_MAX_MHZ); } if( transmit == receive ) @@ -213,7 +262,7 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - int result = hackrf_init(); + result = hackrf_init(); if( result != HACKRF_SUCCESS ) { printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result); usage(); @@ -262,6 +311,15 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } + if( freq ) { + printf("call hackrf_set_freq(%ld MHz)\n", freq_mhz); + result = hackrf_set_freq(device, freq_mhz); + if( result != HACKRF_SUCCESS ) { + printf("hackrf_set_freq() failed: %s (%d)\n", hackrf_error_name(result), result); + return EXIT_FAILURE; + } + } + gettimeofday(&t_start, NULL); gettimeofday(&time_start, NULL); diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index a5e7872c..a069f896 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -44,7 +44,8 @@ typedef enum { HACKRF_VENDOR_REQUEST_SPIFLASH_READ = 12, HACKRF_VENDOR_REQUEST_CPLD_WRITE = 13, HACKRF_VENDOR_REQUEST_BOARD_ID_READ = 14, - HACKRF_VENDOR_REQUEST_VERSION_STRING_READ = 15 + HACKRF_VENDOR_REQUEST_VERSION_STRING_READ = 15, + HACKRF_VENDOR_REQUEST_SET_FREQ = 16 } hackrf_vendor_request; typedef enum { @@ -569,6 +570,26 @@ int hackrf_version_string_read(hackrf_device* device, char* version, } } +int hackrf_set_freq(hackrf_device* device, const uint32_t freq_mhz) { + /* TODO add freq_hz in addition from 0 to 999999Hz */ + int result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_SET_FREQ, + freq_mhz & 0xffff, + freq_mhz >> 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 67f18e1b..601ad12c 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -93,6 +93,8 @@ int hackrf_board_id_read(hackrf_device* device, uint8_t* value); int hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length); +int hackrf_set_freq(hackrf_device* device, const uint32_t freq_mhz); + const char* hackrf_error_name(enum hackrf_error errcode); const char* hackrf_board_id_name(enum hackrf_board_id board_id); From 155a688d11b164573cb9d5dbd7663e15bda34fdb Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 Mar 2013 10:35:49 -0700 Subject: [PATCH 02/14] updated rffc test/commments --- firmware/common/rffc5071.c | 4 ++-- firmware/common/rffc5071.h | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 5e2e9a19..e5a0c3e8 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -535,7 +535,7 @@ void rffc5071_set_gpo(uint8_t gpo) int main(int ac, char **av) { rffc5071_setup(); - rffc5071_tx(); + rffc5071_tx(0); rffc5071_set_frequency(500, 0); rffc5071_set_frequency(525, 0); rffc5071_set_frequency(550, 0); @@ -543,7 +543,7 @@ int main(int ac, char **av) rffc5071_set_frequency(1525, 0); rffc5071_set_frequency(1550, 0); rffc5071_disable(); - rffc5071_rx(); + rffc5071_rx(0); rffc5071_disable(); rffc5071_rxtx(); rffc5071_disable(); diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 9b81fd46..f55bf9a7 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -36,12 +36,12 @@ extern uint32_t rffc5071_regs_dirty; * RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on * the RFFC5072. */ -#define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* turn off TX amp power */ -#define SWITCHCTRL_AMP_BYPASS (1 << 1) /* bypass amp section */ -#define SWITCHCTRL_TX (1 << 2) /* 1 for TX mode, 0 for RX mode */ -#define SWITCHCTRL_MIX_BYPASS (1 << 3) /* bypass RFFC5072 mixer section */ -#define SWITCHCTRL_HP (1 << 4) /* 1 for high-pass, 0 for low-pass */ -#define SWITCHCTRL_NO_RX_AMP_PWR (1 << 5) /* turn off RX amp power */ +#define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* GPO1 turn off TX amp power */ +#define SWITCHCTRL_AMP_BYPASS (1 << 1) /* GPO2 bypass amp section */ +#define SWITCHCTRL_TX (1 << 2) /* GPO3 1 for TX mode, 0 for RX mode */ +#define SWITCHCTRL_MIX_BYPASS (1 << 3) /* GPO4 bypass RFFC5072 mixer section */ +#define SWITCHCTRL_HP (1 << 4) /* GPO5 1 for high-pass, 0 for low-pass */ +#define SWITCHCTRL_NO_RX_AMP_PWR (1 << 5) /* GPO6 turn off RX amp power */ /* * Safe (initial) switch settings turn off both amplifiers and enable both amp From 2039b23e202c1f03d1628a32f078939663ee6a26 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 Mar 2013 12:34:32 -0700 Subject: [PATCH 03/14] basic rffc5071 tx/rx control from USB --- firmware/usb_performance/usb_performance.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 2bb56aaa..8a5c59c2 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -187,6 +187,8 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { gpio_set(PORT_LED1_3, PIN_LED2); usb_endpoint_init(&usb_endpoint_bulk_in); + rffc5071_rx(switchctrl); + rffc5071_set_frequency(1700, 0); // 2600 MHz IF - 1700 MHz LO = 900 MHz RF max2837_start(); max2837_rx(); } else if (transceiver_mode == TRANSCEIVER_MODE_TX) { @@ -194,6 +196,8 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { gpio_set(PORT_LED1_3, PIN_LED3); usb_endpoint_init(&usb_endpoint_bulk_out); + rffc5071_tx(switchctrl); + rffc5071_set_frequency(1700, 0); // 2600 MHz IF - 1700 MHz LO = 900 MHz RF max2837_start(); max2837_tx(); } else { @@ -666,8 +670,6 @@ int main(void) { #ifdef JAWBREAKER switchctrl = SWITCHCTRL_AMP_BYPASS; #endif - rffc5071_rx(switchctrl); - rffc5071_set_frequency(1700, 0); // 2600 MHz IF - 1700 MHz LO = 900 MHz RF while(true) { // Wait until buffer 0 is transmitted/received. From 0c342f9ceaf4fcd2a217f2fafe9a22bec87c10c2 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 Mar 2013 14:56:32 -0700 Subject: [PATCH 04/14] .gitignore additions: .dfu in /firmware, .pdf and .svg in /hardware --- firmware/.gitignore | 1 + hardware/.gitignore | 2 ++ 2 files changed, 3 insertions(+) diff --git a/firmware/.gitignore b/firmware/.gitignore index 756442ec..ec522d99 100644 --- a/firmware/.gitignore +++ b/firmware/.gitignore @@ -6,3 +6,4 @@ *.map *.o *.srec +*.dfu diff --git a/hardware/.gitignore b/hardware/.gitignore index 64039541..4fe684ca 100644 --- a/hardware/.gitignore +++ b/hardware/.gitignore @@ -19,3 +19,5 @@ $savepcb.* # other kicad generated files *.csv +*.svg +*.pdf From 50f7481682d69650eb2ac40afd93d3e1d9bdd1f9 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 Mar 2013 15:18:05 -0700 Subject: [PATCH 05/14] usb_vendor_request_set_amp_enable --- firmware/usb_performance/usb_performance.c | 34 +++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 8a5c59c2..f3c3e13a 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -495,6 +495,37 @@ usb_request_status_t usb_vendor_request_read_version_string( 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) +{ + if (stage == USB_TRANSFER_STAGE_SETUP) { + switch (endpoint->setup.value) { + case 0: + switchctrl |= SWITCHCTRL_AMP_BYPASS; + if (transceiver_mode == TRANSCEIVER_MODE_RX) { + rffc5071_rx(switchctrl); + } else if (transceiver_mode == TRANSCEIVER_MODE_TX) { + rffc5071_tx(switchctrl); + } + usb_endpoint_schedule_ack(endpoint->in); + return USB_REQUEST_STATUS_OK; + case 1: + switchctrl &= ~SWITCHCTRL_AMP_BYPASS; + if (transceiver_mode == TRANSCEIVER_MODE_RX) { + rffc5071_rx(switchctrl); + } else if (transceiver_mode == TRANSCEIVER_MODE_TX) { + rffc5071_tx(switchctrl); + } + usb_endpoint_schedule_ack(endpoint->in); + return USB_REQUEST_STATUS_OK; + default: + return USB_REQUEST_STATUS_STALL; + } + } else { + return USB_REQUEST_STATUS_OK; + } +} + static const usb_request_handler_fn vendor_request_handler[] = { NULL, usb_vendor_request_set_transceiver_mode, @@ -511,7 +542,8 @@ static const usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_read_spiflash, usb_vendor_request_write_cpld, usb_vendor_request_read_board_id, - usb_vendor_request_read_version_string + usb_vendor_request_read_version_string, + usb_vendor_request_set_amp_enable }; static const uint32_t vendor_request_handler_count = From e3784c886ecc505f643f294cd79955424aefa1b9 Mon Sep 17 00:00:00 2001 From: TitanMKD Date: Thu, 7 Mar 2013 23:24:00 +0100 Subject: [PATCH 06/14] set_freq for firmware & host. tested basicly checking with debugger value mhz/hz from host to fw. --- firmware/common/hackrf_core.c | 2 +- firmware/usb_performance/usb_performance.c | 28 ++++++++++++++----- host/libhackrf/examples/hackrf_transfer.c | 24 ++++++++--------- host/libhackrf/src/hackrf.c | 31 +++++++++++++++++----- host/libhackrf/src/hackrf.h | 4 +-- 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index ca19304f..cfcabfa8 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -410,7 +410,7 @@ void enable_1v8_power(void) { } /* -Set freq/tuning between 30MHz to 6000 MHz +Set freq/tuning between 30MHz to 6000 MHz (less than 16bits really used) hz between 0 to 999999 Hz (not checked) return false on error or true if success. */ diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 3243e94d..06e0c111 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -53,6 +53,15 @@ const uint_fast8_t usb_td_bulk_count = sizeof(usb_td_bulk) / sizeof(usb_td_bulk[ uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN]; char version_string[] = VERSION_STRING; +typedef struct { + uint32_t freq_mhz; + uint32_t freq_hz; +} set_freq_params_t; + +set_freq_params_t set_freq_params; + +uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN]; + uint8_t switchctrl = 0; static void usb_init_buffers_bulk() { @@ -497,17 +506,22 @@ usb_request_status_t usb_vendor_request_read_version_string( usb_request_status_t usb_vendor_request_set_freq( usb_endpoint_t* const endpoint, - const usb_transfer_stage_t stage -) { - if( stage == USB_TRANSFER_STAGE_SETUP ) { - const uint32_t freq_mhz = (endpoint->setup.index << 16) | endpoint->setup.value; - const uint32_t freq_hz = 0; /* TODO fix this and retrieve a 32bits */ - if( set_freq(freq_mhz, freq_hz) ) { + const usb_transfer_stage_t stage) +{ + if (stage == USB_TRANSFER_STAGE_SETUP) + { + usb_endpoint_schedule(endpoint->out, &set_freq_params, sizeof(set_freq_params_t)); + return USB_REQUEST_STATUS_OK; + } else if (stage == USB_TRANSFER_STAGE_DATA) + { + if( set_freq(set_freq_params.freq_mhz, set_freq_params.freq_hz) ) + { usb_endpoint_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; - } else { + } else + { return USB_REQUEST_STATUS_OK; } } diff --git a/host/libhackrf/examples/hackrf_transfer.c b/host/libhackrf/examples/hackrf_transfer.c index 99724805..8f6b8595 100644 --- a/host/libhackrf/examples/hackrf_transfer.c +++ b/host/libhackrf/examples/hackrf_transfer.c @@ -42,8 +42,8 @@ #include #include -#define FREQ_MIN_MHZ (30) -#define FREQ_MAX_MHZ (6000) +#define FREQ_MIN_HZ (30000000ull) /* 30MHz */ +#define FREQ_MAX_HZ (6000000000ull) /* 6000MHz */ #if defined _WIN32 #define sleep(a) Sleep( (a*1000) ) @@ -62,7 +62,7 @@ TimevalDiff(const struct timeval *a, const struct timeval *b) return (a->tv_sec - b->tv_sec) + 1e-6f * (a->tv_usec - b->tv_usec); } -int parse_int(char* s, uint32_t* const value) { +int parse_u64(char* s, uint64_t* const value) { uint_fast8_t base = 10; if( strlen(s) > 2 ) { if( s[0] == '0' ) { @@ -77,9 +77,9 @@ int parse_int(char* s, uint32_t* const value) { } char* s_end = s; - const unsigned long ulong_value = strtoul(s, &s_end, base); + const unsigned long long u64_value = strtoull(s, &s_end, base); if( (s != s_end) && (*s_end == 0) ) { - *value = ulong_value; + *value = u64_value; return HACKRF_SUCCESS; } else { return HACKRF_ERROR_INVALID_PARAM; @@ -95,7 +95,7 @@ struct timeval time_start; struct timeval t_start; bool freq = false; -uint32_t freq_mhz; +uint64_t freq_hz; int rx_callback(hackrf_transfer* transfer) { if( fd != NULL ) @@ -135,7 +135,7 @@ static void usage() { printf("Usage:\n"); printf("\t-r # Receive data into file.\n"); printf("\t-t # Transmit data from file.\n"); - printf("\t-f # Set Frequency in MHz (between [%ld, %ld[).\n", FREQ_MIN_MHZ, FREQ_MAX_MHZ); + printf("\t-f # Set Frequency in MHz (between [%lld, %lld[).\n", FREQ_MIN_HZ, FREQ_MAX_HZ); } static hackrf_device* device = NULL; @@ -216,7 +216,7 @@ int main(int argc, char** argv) { case 'f': freq = true; - result = parse_int(optarg, &freq_mhz); + result = parse_u64(optarg, &freq_hz); break; default: @@ -232,8 +232,8 @@ int main(int argc, char** argv) { } if( freq ) { - if( (freq_mhz >= 6000) || (freq_mhz < 30) ) - printf("argument error: frequency shall be between [%ld, %ld[.\n", FREQ_MIN_MHZ, FREQ_MAX_MHZ); + if( (freq_hz >= FREQ_MAX_HZ) || (freq_hz < FREQ_MIN_HZ) ) + printf("argument error: frequency shall be between [%lld, %lld[.\n", FREQ_MIN_HZ, FREQ_MAX_HZ); } if( transmit == receive ) @@ -312,8 +312,8 @@ int main(int argc, char** argv) { } if( freq ) { - printf("call hackrf_set_freq(%ld MHz)\n", freq_mhz); - result = hackrf_set_freq(device, freq_mhz); + printf("call hackrf_set_freq(%lld Hz)\n", freq_hz); + result = hackrf_set_freq(device, freq_hz); if( result != HACKRF_SUCCESS ) { printf("hackrf_set_freq() failed: %s (%d)\n", hackrf_error_name(result), result); return EXIT_FAILURE; diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index a069f896..379da48a 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -570,20 +570,39 @@ int hackrf_version_string_read(hackrf_device* device, char* version, } } -int hackrf_set_freq(hackrf_device* device, const uint32_t freq_mhz) { - /* TODO add freq_hz in addition from 0 to 999999Hz */ +typedef struct { + uint32_t freq_mhz; /* From 30 to 6000MHz */ + uint32_t freq_hz; /* From 0 to 999999Hz */ + /* Final Freq = freq_mhz+freq_hz */ +} set_freq_params_t; +#define FREQ_ONE_MHZ (1000*1000ull) + +int hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz) +{ + uint32_t l_freq_mhz; + uint32_t l_freq_hz; + set_freq_params_t set_freq_params; + uint8_t length; + + /* 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; + length = sizeof(set_freq_params_t); + int result = libusb_control_transfer( device->usb_device, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, HACKRF_VENDOR_REQUEST_SET_FREQ, - freq_mhz & 0xffff, - freq_mhz >> 16, - NULL, 0, + 0, + (unsigned char*)&set_freq_params, + length, 0 ); - if( result != 0 ) { + if (result < length) { return HACKRF_ERROR_LIBUSB; } else { return HACKRF_SUCCESS; diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 601ad12c..31775142 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -93,8 +93,8 @@ int hackrf_board_id_read(hackrf_device* device, uint8_t* value); int hackrf_version_string_read(hackrf_device* device, char* version, uint8_t length); -int hackrf_set_freq(hackrf_device* device, const uint32_t freq_mhz); - +int hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz); + const char* hackrf_error_name(enum hackrf_error errcode); const char* hackrf_board_id_name(enum hackrf_board_id board_id); From 8a9664c0ad59f2b6e907e4552491c7740edb882c Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 Mar 2013 16:08:44 -0700 Subject: [PATCH 07/14] started amp_enable in libhackrf --- host/libhackrf/src/hackrf.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 379da48a..4964dd3d 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -45,7 +45,8 @@ typedef enum { HACKRF_VENDOR_REQUEST_CPLD_WRITE = 13, HACKRF_VENDOR_REQUEST_BOARD_ID_READ = 14, HACKRF_VENDOR_REQUEST_VERSION_STRING_READ = 15, - HACKRF_VENDOR_REQUEST_SET_FREQ = 16 + HACKRF_VENDOR_REQUEST_SET_FREQ = 16, + HACKRF_VENDOR_REQUEST_AMP_ENABLE = 17 } hackrf_vendor_request; typedef enum { @@ -570,6 +571,26 @@ int hackrf_version_string_read(hackrf_device* device, char* version, } } +static int hackrf_set_amp_enable(hackrf_device* device, uint8_t value) +{ + int result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_AMP_ENABLE, + value, + 0, + NULL, + 0, + 0 + ); + + if (result != 0) { + return HACKRF_ERROR_LIBUSB; + } else { + return HACKRF_SUCCESS; + } +} + typedef struct { uint32_t freq_mhz; /* From 30 to 6000MHz */ uint32_t freq_hz; /* From 0 to 999999Hz */ From 9ad6758af1c766ddc885ed20bccf63407c47b982 Mon Sep 17 00:00:00 2001 From: TitanMKD Date: Fri, 8 Mar 2013 00:47:17 +0100 Subject: [PATCH 08/14] Added hackrf_set_amp_enable() in hackrf_transfer. --- host/libhackrf/examples/hackrf_transfer.c | 65 +++++++++++++++++++++-- host/libhackrf/src/hackrf.c | 40 +++++++------- host/libhackrf/src/hackrf.h | 2 + 3 files changed, 82 insertions(+), 25 deletions(-) diff --git a/host/libhackrf/examples/hackrf_transfer.c b/host/libhackrf/examples/hackrf_transfer.c index 8f6b8595..f80cd62c 100644 --- a/host/libhackrf/examples/hackrf_transfer.c +++ b/host/libhackrf/examples/hackrf_transfer.c @@ -86,6 +86,30 @@ int parse_u64(char* s, uint64_t* const value) { } } +int parse_int(char* s, uint32_t* const value) { + uint_fast8_t base = 10; + if( strlen(s) > 2 ) { + if( s[0] == '0' ) { + if( (s[1] == 'x') || (s[1] == 'X') ) { + base = 16; + s += 2; + } else if( (s[1] == 'b') || (s[1] == 'B') ) { + base = 2; + s += 2; + } + } + } + + char* s_end = s; + const unsigned long ulong_value = strtoul(s, &s_end, base); + if( (s != s_end) && (*s_end == 0) ) { + *value = ulong_value; + return HACKRF_SUCCESS; + } else { + return HACKRF_ERROR_INVALID_PARAM; + } +} + FILE* fd = NULL; volatile uint32_t byte_count = 0; @@ -96,7 +120,10 @@ struct timeval t_start; bool freq = false; uint64_t freq_hz; - + +bool amp = false; +uint32_t amp_enable; + int rx_callback(hackrf_transfer* transfer) { if( fd != NULL ) { @@ -135,7 +162,8 @@ static void usage() { printf("Usage:\n"); printf("\t-r # Receive data into file.\n"); printf("\t-t # Transmit data from file.\n"); - printf("\t-f # Set Frequency in MHz (between [%lld, %lld[).\n", FREQ_MIN_HZ, FREQ_MAX_HZ); + printf("\t[-f set_freq_hz] # Set Freq in Hz (between [%lld, %lld[).\n", FREQ_MIN_HZ, FREQ_MAX_HZ); + printf("\t[-a set_amp] # Set Amp 1=Enable, 0=Disable.\n"); } static hackrf_device* device = NULL; @@ -201,7 +229,7 @@ int main(int argc, char** argv) { const char* path = NULL; int result; - while( (opt = getopt(argc, argv, "r:t:f:")) != EOF ) { + while( (opt = getopt(argc, argv, "r:t:f:a:")) != EOF ) { result = HACKRF_SUCCESS; switch( opt ) { case 'r': @@ -218,7 +246,12 @@ int main(int argc, char** argv) { freq = true; result = parse_u64(optarg, &freq_hz); break; - + + case 'a': + amp = true; + result = parse_int(optarg, &_enable); + break; + default: usage(); return EXIT_FAILURE; @@ -233,9 +266,22 @@ int main(int argc, char** argv) { if( freq ) { if( (freq_hz >= FREQ_MAX_HZ) || (freq_hz < FREQ_MIN_HZ) ) - printf("argument error: frequency shall be between [%lld, %lld[.\n", FREQ_MIN_HZ, FREQ_MAX_HZ); + { + printf("argument error: set_freq_hz shall be between [%lld, %lld[.\n", FREQ_MIN_HZ, FREQ_MAX_HZ); + usage(); + return EXIT_FAILURE; + } } + if( amp ) { + if( amp_enable > 1 ) + { + printf("argument error: set_amp shall be 0 or 1.\n"); + usage(); + return EXIT_FAILURE; + } + } + if( transmit == receive ) { if( transmit == true ) @@ -319,6 +365,15 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } } + + if( amp ) { + printf("call hackrf_set_amp_enable(%ld)\n", amp_enable); + result = hackrf_set_amp_enable(device, (uint8_t)amp_enable); + if( result != HACKRF_SUCCESS ) { + printf("hackrf_set_amp_enable() failed: %s (%d)\n", hackrf_error_name(result), result); + return EXIT_FAILURE; + } + } gettimeofday(&t_start, NULL); gettimeofday(&time_start, NULL); diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 4964dd3d..5bb77745 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -571,26 +571,6 @@ int hackrf_version_string_read(hackrf_device* device, char* version, } } -static int hackrf_set_amp_enable(hackrf_device* device, uint8_t value) -{ - int result = libusb_control_transfer( - device->usb_device, - LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, - HACKRF_VENDOR_REQUEST_AMP_ENABLE, - value, - 0, - NULL, - 0, - 0 - ); - - if (result != 0) { - return HACKRF_ERROR_LIBUSB; - } else { - return HACKRF_SUCCESS; - } -} - typedef struct { uint32_t freq_mhz; /* From 30 to 6000MHz */ uint32_t freq_hz; /* From 0 to 999999Hz */ @@ -630,6 +610,26 @@ int hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz) } } +int hackrf_set_amp_enable(hackrf_device* device, const uint8_t value) +{ + int result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_AMP_ENABLE, + value, + 0, + 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 31775142..c8dea87d 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -95,6 +95,8 @@ int hackrf_version_string_read(hackrf_device* device, char* version, int hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz); +int hackrf_set_amp_enable(hackrf_device* device, const uint8_t value); + const char* hackrf_error_name(enum hackrf_error errcode); const char* hackrf_board_id_name(enum hackrf_board_id board_id); From 052d842f3694ce1d6c6fffb2c6c3965759bc474b Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 Mar 2013 16:56:37 -0700 Subject: [PATCH 09/14] temporary fix for gpo/switchctrl. only works for TX --- firmware/common/hackrf_core.c | 9 ++++++--- firmware/usb_performance/usb_performance.c | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index cfcabfa8..be06f579 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -429,7 +429,7 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) if(freq_mhz < MAX_LP_FREQ_MHZ) { /* TODO fix/check Switch to LP mode (shall not change RX/TX mode) */ - rffc5071_set_gpo(0); /* SWITCHCTRL_LP = 0 */ + //rffc5071_set_gpo(0); /* SWITCHCTRL_LP = 0 */ RFFC5071_freq_mhz = MAX2837_FREQ_NOMINAL_MHZ - freq_mhz; /* Set Freq and read real freq */ @@ -443,18 +443,20 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) } MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; max2837_set_frequency(MAX2837_freq_hz); + rffc5071_tx(0); }else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) { /* TODO fix/check Switch to SWITCHCTRL_MIX_BYPASS mode (shall not change RX/TX mode) */ - rffc5071_set_gpo(SWITCHCTRL_MIX_BYPASS); + //rffc5071_set_gpo(SWITCHCTRL_MIX_BYPASS); MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; /* RFFC5071_freq_mhz <= not used in Bypass mode */ max2837_set_frequency(MAX2837_freq_hz); + rffc5071_tx(SWITCHCTRL_MIX_BYPASS); }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz < MAX_HP_FREQ_MHZ) ) { /* TODO fix/check Switch to SWITCHCTRL_HP mode (shall not change RX/TX mode) */ - rffc5071_set_gpo(SWITCHCTRL_HP); + //rffc5071_set_gpo(SWITCHCTRL_HP); //switch_ctrl = SWITCHCTRL_HP; RFFC5071_freq_mhz = freq_mhz - MAX2837_FREQ_NOMINAL_MHZ; @@ -469,6 +471,7 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) } MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; max2837_set_frequency(MAX2837_freq_hz); + rffc5071_tx(SWITCHCTRL_HP); }else { /* Error freq_mhz too high */ diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 9058923c..f8058c82 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -197,7 +197,7 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { usb_endpoint_init(&usb_endpoint_bulk_in); rffc5071_rx(switchctrl); - rffc5071_set_frequency(1700, 0); // 2600 MHz IF - 1700 MHz LO = 900 MHz RF + //rffc5071_set_frequency(1700, 0); // 2600 MHz IF - 1700 MHz LO = 900 MHz RF max2837_start(); max2837_rx(); } else if (transceiver_mode == TRANSCEIVER_MODE_TX) { @@ -206,7 +206,7 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { usb_endpoint_init(&usb_endpoint_bulk_out); rffc5071_tx(switchctrl); - rffc5071_set_frequency(1700, 0); // 2600 MHz IF - 1700 MHz LO = 900 MHz RF + //rffc5071_set_frequency(1700, 0); // 2600 MHz IF - 1700 MHz LO = 900 MHz RF max2837_start(); max2837_tx(); } else { From 1a2f871520320ca1da665f7cd92c5e251f530084 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 Mar 2013 17:35:48 -0700 Subject: [PATCH 10/14] moved set_freq out of hackrf_core to facilitate switchctrl fixes --- firmware/common/hackrf_core.c | 91 ---------------------- firmware/common/hackrf_core.h | 2 - firmware/usb_performance/usb_performance.c | 90 +++++++++++++++++++++ 3 files changed, 90 insertions(+), 93 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index be06f579..d1e7e0b7 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -31,21 +31,6 @@ #include #include -/* Define for set_tune_freq() */ -#define FREQ_ONE_MHZ (1000*1000) - -#define MIN_LP_FREQ_MHZ (30) -#define MAX_LP_FREQ_MHZ (2300) - -#define MIN_BYPASS_FREQ_MHZ (2300) -#define MAX_BYPASS_FREQ_MHZ (2700) - -#define MIN_HP_FREQ_MHZ (2700) -#define MAX_HP_FREQ_MHZ (6000) - -#define MAX2837_FREQ_NOMINAL_HZ (2600000000) -#define MAX2837_FREQ_NOMINAL_MHZ (MAX2837_FREQ_NOMINAL_HZ / FREQ_ONE_MHZ) - void delay(uint32_t duration) { uint32_t i; @@ -408,79 +393,3 @@ void pin_setup(void) { void enable_1v8_power(void) { gpio_set(PORT_EN1V8, PIN_EN1V8); } - -/* -Set freq/tuning between 30MHz to 6000 MHz (less than 16bits really used) -hz between 0 to 999999 Hz (not checked) -return false on error or true if success. -*/ -bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) -{ - bool success; - uint32_t RFFC5071_freq_mhz; - uint32_t MAX2837_freq_hz; - uint32_t real_RFFC5071_freq_mhz; - uint32_t tmp_hz; - - success = true; - - if(freq_mhz >= MIN_LP_FREQ_MHZ) - { - if(freq_mhz < MAX_LP_FREQ_MHZ) - { - /* TODO fix/check Switch to LP mode (shall not change RX/TX mode) */ - //rffc5071_set_gpo(0); /* SWITCHCTRL_LP = 0 */ - - RFFC5071_freq_mhz = MAX2837_FREQ_NOMINAL_MHZ - freq_mhz; - /* Set Freq and read real freq */ - real_RFFC5071_freq_mhz = rffc5071_set_frequency(RFFC5071_freq_mhz, 0); - if(real_RFFC5071_freq_mhz < RFFC5071_freq_mhz) - { - tmp_hz = -((RFFC5071_freq_mhz - real_RFFC5071_freq_mhz) * FREQ_ONE_MHZ); - }else - { - tmp_hz = ((real_RFFC5071_freq_mhz - RFFC5071_freq_mhz) * FREQ_ONE_MHZ); - } - MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; - max2837_set_frequency(MAX2837_freq_hz); - rffc5071_tx(0); - }else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) - { - /* TODO fix/check Switch to SWITCHCTRL_MIX_BYPASS mode (shall not change RX/TX mode) */ - //rffc5071_set_gpo(SWITCHCTRL_MIX_BYPASS); - - MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; - /* RFFC5071_freq_mhz <= not used in Bypass mode */ - max2837_set_frequency(MAX2837_freq_hz); - rffc5071_tx(SWITCHCTRL_MIX_BYPASS); - }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz < MAX_HP_FREQ_MHZ) ) - { - /* TODO fix/check Switch to SWITCHCTRL_HP mode (shall not change RX/TX mode) */ - //rffc5071_set_gpo(SWITCHCTRL_HP); - - //switch_ctrl = SWITCHCTRL_HP; - RFFC5071_freq_mhz = freq_mhz - MAX2837_FREQ_NOMINAL_MHZ; - /* Set Freq and read real freq */ - real_RFFC5071_freq_mhz = rffc5071_set_frequency(RFFC5071_freq_mhz, 0); - if(real_RFFC5071_freq_mhz < RFFC5071_freq_mhz) - { - tmp_hz = ((RFFC5071_freq_mhz - real_RFFC5071_freq_mhz) * FREQ_ONE_MHZ); - }else - { - tmp_hz = -((real_RFFC5071_freq_mhz - RFFC5071_freq_mhz) * FREQ_ONE_MHZ); - } - MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; - max2837_set_frequency(MAX2837_freq_hz); - rffc5071_tx(SWITCHCTRL_HP); - }else - { - /* Error freq_mhz too high */ - success = false; - } - }else - { - /* Error freq_mhz too low */ - success = false; - } - return success; -} diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 2d04be8f..71f017da 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -258,8 +258,6 @@ 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); -bool set_freq(uint32_t freq_mhz, uint32_t freq_hz); - #ifdef __cplusplus } #endif diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index f8058c82..5b52660b 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -64,6 +64,96 @@ uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN]; uint8_t switchctrl = 0; +#define FREQ_ONE_MHZ (1000*1000) + +#define MIN_LP_FREQ_MHZ (30) +#define MAX_LP_FREQ_MHZ (2300) + +#define MIN_BYPASS_FREQ_MHZ (2300) +#define MAX_BYPASS_FREQ_MHZ (2700) + +#define MIN_HP_FREQ_MHZ (2700) +#define MAX_HP_FREQ_MHZ (6000) + +#define MAX2837_FREQ_NOMINAL_HZ (2600000000) +#define MAX2837_FREQ_NOMINAL_MHZ (MAX2837_FREQ_NOMINAL_HZ / FREQ_ONE_MHZ) + +/* + * Set freq/tuning between 30MHz to 6000 MHz (less than 16bits really used) + * hz between 0 to 999999 Hz (not checked) + * return false on error or true if success. + */ +bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) +{ + bool success; + uint32_t RFFC5071_freq_mhz; + uint32_t MAX2837_freq_hz; + uint32_t real_RFFC5071_freq_mhz; + uint32_t tmp_hz; + + success = true; + + if(freq_mhz >= MIN_LP_FREQ_MHZ) + { + if(freq_mhz < MAX_LP_FREQ_MHZ) + { + /* TODO fix/check Switch to LP mode (shall not change RX/TX mode) */ + //rffc5071_set_gpo(0); /* SWITCHCTRL_LP = 0 */ + + RFFC5071_freq_mhz = MAX2837_FREQ_NOMINAL_MHZ - freq_mhz; + /* Set Freq and read real freq */ + real_RFFC5071_freq_mhz = rffc5071_set_frequency(RFFC5071_freq_mhz, 0); + if(real_RFFC5071_freq_mhz < RFFC5071_freq_mhz) + { + tmp_hz = -((RFFC5071_freq_mhz - real_RFFC5071_freq_mhz) * FREQ_ONE_MHZ); + }else + { + tmp_hz = ((real_RFFC5071_freq_mhz - RFFC5071_freq_mhz) * FREQ_ONE_MHZ); + } + MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; + max2837_set_frequency(MAX2837_freq_hz); + rffc5071_tx(0); + }else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) + { + /* TODO fix/check Switch to SWITCHCTRL_MIX_BYPASS mode (shall not change RX/TX mode) */ + //rffc5071_set_gpo(SWITCHCTRL_MIX_BYPASS); + + MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; + /* RFFC5071_freq_mhz <= not used in Bypass mode */ + max2837_set_frequency(MAX2837_freq_hz); + rffc5071_tx(SWITCHCTRL_MIX_BYPASS); + }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz < MAX_HP_FREQ_MHZ) ) + { + /* TODO fix/check Switch to SWITCHCTRL_HP mode (shall not change RX/TX mode) */ + //rffc5071_set_gpo(SWITCHCTRL_HP); + + //switch_ctrl = SWITCHCTRL_HP; + RFFC5071_freq_mhz = freq_mhz - MAX2837_FREQ_NOMINAL_MHZ; + /* Set Freq and read real freq */ + real_RFFC5071_freq_mhz = rffc5071_set_frequency(RFFC5071_freq_mhz, 0); + if(real_RFFC5071_freq_mhz < RFFC5071_freq_mhz) + { + tmp_hz = ((RFFC5071_freq_mhz - real_RFFC5071_freq_mhz) * FREQ_ONE_MHZ); + }else + { + tmp_hz = -((real_RFFC5071_freq_mhz - RFFC5071_freq_mhz) * FREQ_ONE_MHZ); + } + MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; + max2837_set_frequency(MAX2837_freq_hz); + rffc5071_tx(SWITCHCTRL_HP); + }else + { + /* Error freq_mhz too high */ + success = false; + } + }else + { + /* Error freq_mhz too low */ + success = false; + } + return success; +} + static void usb_init_buffers_bulk() { usb_td_bulk[0].next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; usb_td_bulk[0].total_bytes From 8e46c6058c9eb9e7b29e3f413e1ea77e68ba1f67 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 Mar 2013 17:45:27 -0700 Subject: [PATCH 11/14] switchctrl updated by set_freq() --- firmware/usb_performance/usb_performance.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 5b52660b..0355387d 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -97,8 +97,7 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) { if(freq_mhz < MAX_LP_FREQ_MHZ) { - /* TODO fix/check Switch to LP mode (shall not change RX/TX mode) */ - //rffc5071_set_gpo(0); /* SWITCHCTRL_LP = 0 */ + switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS); RFFC5071_freq_mhz = MAX2837_FREQ_NOMINAL_MHZ - freq_mhz; /* Set Freq and read real freq */ @@ -112,22 +111,20 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) } MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; max2837_set_frequency(MAX2837_freq_hz); - rffc5071_tx(0); + rffc5071_tx(switchctrl); }else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) { - /* TODO fix/check Switch to SWITCHCTRL_MIX_BYPASS mode (shall not change RX/TX mode) */ - //rffc5071_set_gpo(SWITCHCTRL_MIX_BYPASS); + switchctrl |= SWITCHCTRL_MIX_BYPASS; MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; /* RFFC5071_freq_mhz <= not used in Bypass mode */ max2837_set_frequency(MAX2837_freq_hz); - rffc5071_tx(SWITCHCTRL_MIX_BYPASS); + rffc5071_tx(switchctrl); }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz < MAX_HP_FREQ_MHZ) ) { - /* TODO fix/check Switch to SWITCHCTRL_HP mode (shall not change RX/TX mode) */ - //rffc5071_set_gpo(SWITCHCTRL_HP); + switchctrl &= ~SWITCHCTRL_MIX_BYPASS; + switchctrl |= SWITCHCTRL_HP; - //switch_ctrl = SWITCHCTRL_HP; RFFC5071_freq_mhz = freq_mhz - MAX2837_FREQ_NOMINAL_MHZ; /* Set Freq and read real freq */ real_RFFC5071_freq_mhz = rffc5071_set_frequency(RFFC5071_freq_mhz, 0); @@ -140,7 +137,7 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) } MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; max2837_set_frequency(MAX2837_freq_hz); - rffc5071_tx(SWITCHCTRL_HP); + rffc5071_tx(switchctrl); }else { /* Error freq_mhz too high */ From 6dc82ae9669c3d7e205e539acb42742b403d2ce5 Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Thu, 7 Mar 2013 17:52:31 -0700 Subject: [PATCH 12/14] finished switchctrl handling --- firmware/usb_performance/usb_performance.c | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 0355387d..e7b47b4c 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -64,6 +64,15 @@ uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN]; uint8_t switchctrl = 0; +void update_switches(void) +{ + if (transceiver_mode == TRANSCEIVER_MODE_RX) { + rffc5071_rx(switchctrl); + } else if (transceiver_mode == TRANSCEIVER_MODE_TX) { + rffc5071_tx(switchctrl); + } +} + #define FREQ_ONE_MHZ (1000*1000) #define MIN_LP_FREQ_MHZ (30) @@ -111,7 +120,7 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) } MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; max2837_set_frequency(MAX2837_freq_hz); - rffc5071_tx(switchctrl); + update_switches(); }else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) { switchctrl |= SWITCHCTRL_MIX_BYPASS; @@ -119,7 +128,7 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; /* RFFC5071_freq_mhz <= not used in Bypass mode */ max2837_set_frequency(MAX2837_freq_hz); - rffc5071_tx(switchctrl); + update_switches(); }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz < MAX_HP_FREQ_MHZ) ) { switchctrl &= ~SWITCHCTRL_MIX_BYPASS; @@ -137,7 +146,7 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz) } MAX2837_freq_hz = MAX2837_FREQ_NOMINAL_HZ + tmp_hz + freq_hz; max2837_set_frequency(MAX2837_freq_hz); - rffc5071_tx(switchctrl); + update_switches(); }else { /* Error freq_mhz too high */ @@ -620,20 +629,12 @@ usb_request_status_t usb_vendor_request_set_amp_enable( switch (endpoint->setup.value) { case 0: switchctrl |= SWITCHCTRL_AMP_BYPASS; - if (transceiver_mode == TRANSCEIVER_MODE_RX) { - rffc5071_rx(switchctrl); - } else if (transceiver_mode == TRANSCEIVER_MODE_TX) { - rffc5071_tx(switchctrl); - } + update_switches(); usb_endpoint_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; case 1: switchctrl &= ~SWITCHCTRL_AMP_BYPASS; - if (transceiver_mode == TRANSCEIVER_MODE_RX) { - rffc5071_rx(switchctrl); - } else if (transceiver_mode == TRANSCEIVER_MODE_TX) { - rffc5071_tx(switchctrl); - } + update_switches(); usb_endpoint_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; default: From b1821ae8da5983246a42c91617c4998b47d7f664 Mon Sep 17 00:00:00 2001 From: TitanMKD Date: Fri, 8 Mar 2013 02:10:51 +0100 Subject: [PATCH 13/14] read_spiflash fixed. (Probably need to flush SPIFI "internal cache" before to read to be sure to read real SPIFI data). --- firmware/usb_performance/usb_performance.c | 32 ++++++++++++++--- host/libhackrf/examples/hackrf_spiflash.c | 40 ++++++++++++++-------- 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index e7b47b4c..b8a6815c 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -541,22 +541,44 @@ usb_request_status_t usb_vendor_request_write_spiflash( usb_request_status_t usb_vendor_request_read_spiflash( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + uint32_t i; uint32_t addr; uint16_t len; + uint8_t* u8_addr_pt; - if (stage == USB_TRANSFER_STAGE_SETUP) { + if (stage == USB_TRANSFER_STAGE_SETUP) + { addr = (endpoint->setup.value << 16) | endpoint->setup.index; len = endpoint->setup.length; if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES) || ((addr + len) > W25Q80BV_NUM_BYTES)) { return USB_REQUEST_STATUS_STALL; } else { - //FIXME need implementation - //usb_endpoint_schedule(endpoint->in, &endpoint->buffer, len); - usb_endpoint_schedule_ack(endpoint->out); + /* TODO flush SPIFI "cache" before to read the SPIFI memory */ + u8_addr_pt = (uint8_t*)addr; + for(i=0; iin, &spiflash_buffer[0], len); return USB_REQUEST_STATUS_OK; } - } else { + } else if (stage == USB_TRANSFER_STAGE_DATA) + { + addr = (endpoint->setup.value << 16) | endpoint->setup.index; + len = endpoint->setup.length; + /* This check is redundant but makes me feel better. */ + if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES) + || ((addr + len) > W25Q80BV_NUM_BYTES)) + { + return USB_REQUEST_STATUS_STALL; + } else + { + usb_endpoint_schedule_ack(endpoint->out); + return USB_REQUEST_STATUS_OK; + } + } else + { return USB_REQUEST_STATUS_OK; } } diff --git a/host/libhackrf/examples/hackrf_spiflash.c b/host/libhackrf/examples/hackrf_spiflash.c index 4f0749b1..17d1dfd3 100644 --- a/host/libhackrf/examples/hackrf_spiflash.c +++ b/host/libhackrf/examples/hackrf_spiflash.c @@ -41,7 +41,7 @@ static struct option long_options[] = { { 0, 0, 0, 0 }, }; -int parse_int(char* s, uint32_t* const value) +int parse_u32(char* s, uint32_t* const value) { uint_fast8_t base = 10; if (strlen(s) > 2) { @@ -57,9 +57,9 @@ int parse_int(char* s, uint32_t* const value) } char* s_end = s; - const long long_value = strtol(s, &s_end, base); + const uint32_t u32_value = strtoul(s, &s_end, base); if ((s != s_end) && (*s_end == 0)) { - *value = long_value; + *value = u32_value; return HACKRF_SUCCESS; } else { return HACKRF_ERROR_INVALID_PARAM; @@ -80,12 +80,13 @@ int main(int argc, char** argv) int opt; uint32_t address = 0; uint32_t length = 0; + uint32_t tmp_length; uint16_t xfer_len = 0; const char* path = NULL; hackrf_device* device = NULL; int result = HACKRF_SUCCESS; int option_index = 0; - uint8_t data[MAX_LENGTH]; + static uint8_t data[MAX_LENGTH]; uint8_t* pdata = &data[0]; FILE* fd = NULL; bool read = false; @@ -95,11 +96,11 @@ int main(int argc, char** argv) &option_index)) != EOF) { switch (opt) { case 'a': - result = parse_int(optarg, &address); + result = parse_u32(optarg, &address); break; case 'l': - result = parse_int(optarg, &length); + result = parse_u32(optarg, &length); break; case 'r': @@ -113,6 +114,7 @@ int main(int argc, char** argv) break; default: + fprintf(stderr, "opt error: %d\n", opt); usage(); return EXIT_FAILURE; } @@ -179,14 +181,24 @@ int main(int argc, char** argv) return EXIT_FAILURE; } - if (read) { - result = hackrf_spiflash_read(device, address, length, data); - if (result != HACKRF_SUCCESS) { - fprintf(stderr, "hackrf_spiflash_read() failed: %s (%d)\n", - hackrf_error_name(result), result); - fclose(fd); - fd = NULL; - return EXIT_FAILURE; + if (read) + { + tmp_length = length; + while (tmp_length) + { + xfer_len = (tmp_length > 256) ? 256 : tmp_length; + printf("Reading %d bytes from 0x%06x.\n", xfer_len, address); + result = hackrf_spiflash_read(device, address, xfer_len, pdata); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_spiflash_read() failed: %s (%d)\n", + hackrf_error_name(result), result); + fclose(fd); + fd = NULL; + return EXIT_FAILURE; + } + address += xfer_len; + pdata += xfer_len; + tmp_length -= xfer_len; } const ssize_t bytes_written = fwrite(data, 1, length, fd); if (bytes_written != length) { From 6620fe6ba930c1af0ff78a6d36a836e6cd3eb7b6 Mon Sep 17 00:00:00 2001 From: TitanMKD Date: Sat, 9 Mar 2013 11:47:28 +0100 Subject: [PATCH 14/14] Add host(hackrf_info)/fw(usb_performance) IAP read part id/serial no(to be confirmed). --- firmware/common/rom_iap.c | 101 ++++++++++++++++ firmware/common/rom_iap.h | 121 +++++++++++++++++++ firmware/usb_performance/Makefile | 3 +- firmware/usb_performance/Makefile_rom_to_ram | 3 +- firmware/usb_performance/usb_performance.c | 45 ++++++- host/libhackrf/examples/hackrf_info.c | 18 ++- host/libhackrf/src/hackrf.c | 26 +++- host/libhackrf/src/hackrf.h | 7 ++ 8 files changed, 318 insertions(+), 6 deletions(-) create mode 100644 firmware/common/rom_iap.c create mode 100644 firmware/common/rom_iap.h diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c new file mode 100644 index 00000000..a3ad3a55 --- /dev/null +++ b/firmware/common/rom_iap.c @@ -0,0 +1,101 @@ +/* + * Copyright 2013 Benjamin Vernoux + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + #include "hackrf_core.h" +#include + +#include "rom_iap.h" + +#define ROM_IAP_ADDR (0x10400100) +#define ROM_IAP_UNDEF_ADDR (0x12345678) + +#define ROM_OTP_PART_ID_ADDR (0x40045000) +#define ROM_OTP_SERIAL_NO_ADDR (0x40045050) /* To be confirmed */ + +typedef void (* IAP_t)(uint32_t [],uint32_t[]); + +typedef struct { + const IAP_t IAP; /* If equal to 0x12345678 IAP not implemented */ + /* Other TBD */ +} *pENTRY_ROM_API_t; +#define pROM_API ((pENTRY_ROM_API_t)ROM_IAP_ADDR) + +/* + See Errata sheet ES_LPC43X0_A.pdf (LPC4350/30/20/10 Rev A) + 3.5 IAP.1: In-Application Programming API not present on flashless parts + Introduction: + The LPC43x0 microcontrollers contain an APIfor In-Application Programming of flash + memory. This API also allows identification of the part. + Problem: + On the LPC43x0 microcontrollers, the IAP API is not present. The ISP interface is present + which allows the part to be identified externally (via the UART) but part identification is not + possible internally using the IAP call because it is not implemented. + The first word of the Part ID can be read directly from OTP at 0x40045000. The second word of the Part ID is always +'0' on flashless parts. */ + +bool iap_is_implemented(void) +{ + bool res; + if( *((uint32_t*)ROM_IAP_ADDR) != ROM_IAP_UNDEF_ADDR ) + { + res = true; + }else + { + res = false; + } + return res; +} + +isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res) +{ + uint32_t* p_u32_data; + + if( iap_is_implemented() ) + { + pROM_API->IAP( (uint32_t*)&iap_cmd_res->cmd_param, (uint32_t*)&iap_cmd_res->status_res); + }else + { + /* Alternative way to retrieve Part Id & Serial No on MCU with no IAP */ + switch(iap_cmd_res->cmd_param.command_code) + { + case IAP_CMD_READ_PART_ID_NO: + p_u32_data = (uint32_t*)ROM_OTP_PART_ID_ADDR; + iap_cmd_res->status_res.iap_result[0] = p_u32_data[0]; + iap_cmd_res->status_res.iap_result[1] = p_u32_data[1]; + iap_cmd_res->status_res.status_ret = CMD_SUCCESS; + break; + + case IAP_CMD_READ_SERIAL_NO: + p_u32_data = (uint32_t*)ROM_OTP_SERIAL_NO_ADDR; + iap_cmd_res->status_res.iap_result[0] = p_u32_data[0]; + iap_cmd_res->status_res.iap_result[1] = p_u32_data[1]; + iap_cmd_res->status_res.iap_result[2] = p_u32_data[2]; + iap_cmd_res->status_res.iap_result[3] = p_u32_data[3]; + iap_cmd_res->status_res.status_ret = CMD_SUCCESS; + break; + + default: + iap_cmd_res->status_res.status_ret = ERROR_IAP_NOT_IMPLEMENTED; + break; + } + } + return iap_cmd_res->status_res.status_ret; +} diff --git a/firmware/common/rom_iap.h b/firmware/common/rom_iap.h new file mode 100644 index 00000000..69761dbe --- /dev/null +++ b/firmware/common/rom_iap.h @@ -0,0 +1,121 @@ +/* + * Copyright 2013 Benjamin Vernoux + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __ROM_IAP__ +#define __ROM_IAP__ + +#include + +typedef enum +{ + /* TODO define other commands */ + + IAP_CMD_INIT_IAP = 49, + /* Command Init IAP + Input Command code: 49 (decimal) + Return Code CMD_SUCCESS + Result None + Description Initializes and prepares the flash for erase and write operations. + Stack usage 88 B */ + + IAP_CMD_READ_PART_ID_NO = 54, + /* Read part identification number + Command Read part identification number + Input Command code: 54 (decimal) + Parameters:None + Return Code CMD_SUCCESS | + Result Result0:Part Identification Number. + Result1:Part Identification Number. + Description This command is used to read the part identification number. See Table 1082 + “LPC43xx part identification numbers”. + The command returns two words: word0 followed by word1. Word 0 corresponds + to the part id and word1 indicates the flash configuration or contains 0x0 for + flashless parts. + Stack usage 8 B */ + + IAP_CMD_READ_SERIAL_NO = 58 + /* Read device serial number + Input Command code: 58 (decimal) + Parameters: None + Return Code CMD_SUCCESS + Result Result0:First 32-bit word of Device Identification Number (at the lowest address) + Result1:Second 32-bit word of Device Identification Number + Result2:Third 32-bit word of Device Identification Number + Result3:Fourth 32-bit word of Device Identification Number + Description This command is used to read the device identification number. The serial number + may be used to uniquely identify a single unit among all LPC43xx devices. + Stack usage 8 B */ +} iap_cmd_code_t; + +/* ISP/IAP Return Code */ +typedef enum +{ + CMD_SUCCESS = 0x00000000, /* CMD_SUCCESS Command is executed successfully. Sent by ISP handler only when command given by the host has been completely and successfully executed. */ + INVALID_COMMAND = 0x00000001, /* Invalid command. */ + SRC_ADDR_ERROR = 0x00000002, /* Source address is not on word boundary. */ + DST_ADDR_ERROR = 0x00000003, /* Destination address not on word or 256 byte boundary. */ + SRC_ADDR_NOT_MAPPED = 0x00000004, /* Source address is not mapped in the memory map. Count value is taken into consideration where applicable. */ + DST_ADDR_NOT_MAPPED = 0x00000005, /* Destination address is not mapped in the memory map. Count value is taken into consideration where applicable.*/ + COUNT_ERROR = 0x00000006, /* Byte count is not multiple of 4 or is not a permitted value. */ + INVALID_SECTOR = 0x00000007, /* Sector number is invalid or end sector number is greater than start sector number. */ + SECTOR_NOT_BLANK = 0x00000008, /* Sector is not blank. */ + SECTOR_NOT_PREP_WRITE_OP = 0x00000009, /* Command to prepare sector for write operation was not executed. */ + COMPARE_ERROR = 0x0000000A, /* Source and destination data not equal. */ + BUSY = 0x0000000B, /* Flash programming hardware interface is busy. */ + PARAM_ERROR = 0x0000000C, /* Insufficient number of parameters or invalid parameter. */ + ADDR_ERROR = 0x0000000D, /* Address is not on word boundary. */ + ADDR_NOT_MAPPED = 0x0000000E, /* Address is not mapped in the memory map. Count value is taken in to consideration where applicable. */ + CMD_LOCKED = 0x0000000F, /* Command is locked. */ + INVALID_CODE = 0x00000010, /* Unlock code is invalid. */ + INVALID_BAUD_RATE = 0x00000011, /* Invalid baud rate setting. */ + INVALID_STOP_BIT = 0x00000012, /* Invalid stop bit setting. */ + CODE_READ_PROTECTION_ENABLED = 0x00000013, /* Code read protection enabled. */ + INVALID_FLASH_UNIT = 0x00000014, /* Invalid flash unit. */ + USER_CODE_CHECKSUM = 0x00000015, + ERROR_SETTING_ACTIVE_PARTITION = 0x00000016, + + /* Special Error */ + ERROR_IAP_NOT_IMPLEMENTED = 0x00000100 /* IAP is not implemented in this part */ +} isp_iap_ret_code_t; + +typedef struct +{ + /* Input Command/Param */ + struct + { + iap_cmd_code_t command_code; + uint32_t iap_param[5]; + } cmd_param; + + /* Output Status/Result */ + struct + { + isp_iap_ret_code_t status_ret; + uint32_t iap_result[4]; + } status_res; +} iap_cmd_res_t; + +/* Check if IAP is implemented */ +bool iap_is_implemented(void); + +isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res); + +#endif//__ROM_IAP__ diff --git a/firmware/usb_performance/Makefile b/firmware/usb_performance/Makefile index b13d29e2..b6324b25 100644 --- a/firmware/usb_performance/Makefile +++ b/firmware/usb_performance/Makefile @@ -38,6 +38,7 @@ SRC = $(BINARY).c \ ../common/cpld_jtag.c \ ../common/xapp058/lenval.c \ ../common/xapp058/micro.c \ - ../common/xapp058/ports.c + ../common/xapp058/ports.c \ + ../common/rom_iap.c include ../common/Makefile_inc.mk diff --git a/firmware/usb_performance/Makefile_rom_to_ram b/firmware/usb_performance/Makefile_rom_to_ram index 0ec7bb8e..ea246313 100644 --- a/firmware/usb_performance/Makefile_rom_to_ram +++ b/firmware/usb_performance/Makefile_rom_to_ram @@ -38,7 +38,8 @@ SRC = usb_performance.c \ ../common/cpld_jtag.c \ ../common/xapp058/lenval.c \ ../common/xapp058/micro.c \ - ../common/xapp058/ports.c + ../common/xapp058/ports.c \ + ../common/rom_iap.c LDSCRIPT = ../common/LPC4330_M4_rom_to_ram.ld include ../common/Makefile_inc.mk diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index b8a6815c..38e0e334 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "usb.h" #include "usb_type.h" @@ -667,6 +668,47 @@ usb_request_status_t usb_vendor_request_set_amp_enable( } } +typedef struct { + uint32_t part_id[2]; + uint32_t serial_no[4]; +} read_partid_serialno_t; + +usb_request_status_t usb_vendor_request_read_partid_serialno( + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) +{ + uint8_t length; + read_partid_serialno_t read_partid_serialno; + iap_cmd_res_t iap_cmd_res; + + if (stage == USB_TRANSFER_STAGE_SETUP) + { + /* Read IAP Part Number Identification */ + iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_PART_ID_NO; + iap_cmd_call(&iap_cmd_res); + if(iap_cmd_res.status_res.status_ret != CMD_SUCCESS) + return USB_REQUEST_STATUS_STALL; + + read_partid_serialno.part_id[0] = iap_cmd_res.status_res.iap_result[0]; + read_partid_serialno.part_id[1] = iap_cmd_res.status_res.iap_result[1]; + + /* Read IAP Serial Number Identification */ + iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO; + iap_cmd_call(&iap_cmd_res); + if(iap_cmd_res.status_res.status_ret != CMD_SUCCESS) + return USB_REQUEST_STATUS_STALL; + + read_partid_serialno.serial_no[0] = iap_cmd_res.status_res.iap_result[0]; + read_partid_serialno.serial_no[1] = iap_cmd_res.status_res.iap_result[1]; + read_partid_serialno.serial_no[2] = iap_cmd_res.status_res.iap_result[2]; + read_partid_serialno.serial_no[3] = iap_cmd_res.status_res.iap_result[3]; + + length = (uint8_t)sizeof(read_partid_serialno_t); + usb_endpoint_schedule(endpoint->in, &read_partid_serialno, length); + usb_endpoint_schedule_ack(endpoint->out); + } + return USB_REQUEST_STATUS_OK; +} + static const usb_request_handler_fn vendor_request_handler[] = { NULL, usb_vendor_request_set_transceiver_mode, @@ -685,7 +727,8 @@ static const usb_request_handler_fn vendor_request_handler[] = { usb_vendor_request_read_board_id, usb_vendor_request_read_version_string, usb_vendor_request_set_freq, - usb_vendor_request_set_amp_enable + usb_vendor_request_set_amp_enable, + usb_vendor_request_read_partid_serialno }; static const uint32_t vendor_request_handler_count = diff --git a/host/libhackrf/examples/hackrf_info.c b/host/libhackrf/examples/hackrf_info.c index 387a83ef..d83b9696 100644 --- a/host/libhackrf/examples/hackrf_info.c +++ b/host/libhackrf/examples/hackrf_info.c @@ -32,6 +32,7 @@ int main(int argc, char** argv) int result = HACKRF_SUCCESS; uint8_t board_id = BOARD_ID_INVALID; char version[255 + 1]; + read_partid_serialno_t read_partid_serialno; result = hackrf_init(); if (result != HACKRF_SUCCESS) { @@ -55,7 +56,6 @@ int main(int argc, char** argv) hackrf_error_name(result), result); return EXIT_FAILURE; } - printf("Board ID Number: %d (%s)\n", board_id, hackrf_board_id_name(board_id)); @@ -65,9 +65,23 @@ int main(int argc, char** argv) hackrf_error_name(result), result); return EXIT_FAILURE; } - printf("Firmware Version: %s\n", version); + result = hackrf_board_partid_serialno_read(device, &read_partid_serialno); + if (result != HACKRF_SUCCESS) { + fprintf(stderr, "hackrf_board_partid_serialno_read() failed: %s (%d)\n", + hackrf_error_name(result), result); + return EXIT_FAILURE; + } + printf("Part ID Number: 0x%08x 0x%08x\n", + read_partid_serialno.part_id[0], + read_partid_serialno.part_id[1]); + printf("Serial Number: 0x%08x 0x%08x 0x%08x 0x%08x\n", + read_partid_serialno.serial_no[0], + read_partid_serialno.serial_no[1], + read_partid_serialno.serial_no[2], + read_partid_serialno.serial_no[3]); + result = hackrf_close(device); if (result != HACKRF_SUCCESS) { fprintf(stderr, "hackrf_close() failed: %s (%d)\n", diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 5bb77745..bb323cde 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -46,7 +46,8 @@ typedef enum { HACKRF_VENDOR_REQUEST_BOARD_ID_READ = 14, HACKRF_VENDOR_REQUEST_VERSION_STRING_READ = 15, HACKRF_VENDOR_REQUEST_SET_FREQ = 16, - HACKRF_VENDOR_REQUEST_AMP_ENABLE = 17 + HACKRF_VENDOR_REQUEST_AMP_ENABLE = 17, + HACKRF_VENDOR_REQUEST_BOARD_PARTID_SERIALNO_READ = 18 } hackrf_vendor_request; typedef enum { @@ -629,6 +630,29 @@ int hackrf_set_amp_enable(hackrf_device* device, const uint8_t value) return HACKRF_SUCCESS; } } + +int hackrf_board_partid_serialno_read(hackrf_device* device, read_partid_serialno_t* read_partid_serialno) +{ + uint8_t length; + + length = sizeof(read_partid_serialno_t); + int result = libusb_control_transfer( + device->usb_device, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + HACKRF_VENDOR_REQUEST_BOARD_PARTID_SERIALNO_READ, + 0, + 0, + (unsigned char*)read_partid_serialno, + length, + 0 + ); + + if (result < length) { + 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 c8dea87d..5a1314e2 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -52,6 +52,11 @@ typedef struct { int valid_length; } hackrf_transfer; +typedef struct { + uint32_t part_id[2]; + uint32_t serial_no[4]; +} read_partid_serialno_t; + typedef int (*hackrf_sample_block_cb_fn)(hackrf_transfer* transfer); int hackrf_init(); @@ -97,6 +102,8 @@ int hackrf_set_freq(hackrf_device* device, const uint64_t freq_hz); int hackrf_set_amp_enable(hackrf_device* device, const uint8_t value); +int hackrf_board_partid_serialno_read(hackrf_device* device, read_partid_serialno_t* read_partid_serialno); + const char* hackrf_error_name(enum hackrf_error errcode); const char* hackrf_board_id_name(enum hackrf_board_id board_id);