From 0f81d361c7542cd7c460adbd2f542a03637b6065 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 10 Oct 2012 22:11:44 -0700 Subject: [PATCH 01/20] Added code to support transmit from usb_test host program. Reorganization of code to support making usb_test a useful utility... --- host/usb_test/usb_test.c | 135 ++++++++++++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 30 deletions(-) diff --git a/host/usb_test/usb_test.c b/host/usb_test/usb_test.c index 29f08a86..5ce79244 100644 --- a/host/usb_test/usb_test.c +++ b/host/usb_test/usb_test.c @@ -24,10 +24,20 @@ #include #include +#include #include #include +const uint16_t hackrf_usb_pid = 0x1d50; +const uint16_t hackrf_usb_vid = 0x604b; + +typedef enum { + TRANSCEIVER_MODE_RX, + TRANSCEIVER_MODE_TX, +} transceiver_mode_t; +static transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_RX; + static float TimevalDiff(const struct timeval *a, const struct timeval *b) { @@ -48,31 +58,27 @@ void write_callback(struct libusb_transfer* transfer) { } } -int main(int argc, char** argv) { - if( argc != 2 ) { - printf("Usage: usb_test \n"); - return -1; - } - - const uint32_t buffer_size = 16384; - - fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); - if( fd == -1 ) { - printf("Failed to open file for write\n"); - return -2; +void read_callback(struct libusb_transfer* transfer) { + if( transfer->status == LIBUSB_TRANSFER_COMPLETED ) { + byte_count += transfer->actual_length; + read(fd, transfer->buffer, transfer->actual_length); + libusb_submit_transfer(transfer); + } else { + printf("transfer status was not 'completed'\n"); } +} - libusb_context* context = NULL; +libusb_device_handle* open_device(libusb_context* const context) { int result = libusb_init(NULL); if( result != 0 ) { printf("libusb_init() failed: %d\n", result); - return -4; + return NULL; } - libusb_device_handle* device = libusb_open_device_with_vid_pid(context, 0x1d50, 0x604b); + libusb_device_handle* device = libusb_open_device_with_vid_pid(context, hackrf_usb_pid, hackrf_usb_vid); if( device == NULL ) { printf("libusb_open_device_with_vid_pid() failed\n"); - return -5; + return NULL; } //int speed = libusb_get_device_speed(device); @@ -80,26 +86,46 @@ int main(int argc, char** argv) { result = libusb_set_configuration(device, 1); if( result != 0 ) { + libusb_close(device); printf("libusb_set_configuration() failed: %d\n", result); - return -6; + return NULL; } result = libusb_claim_interface(device, 0); if( result != 0 ) { + libusb_close(device); printf("libusb_claim_interface() failed: %d\n", result); - return -7; + return NULL; } - - unsigned char endpoint_address = 0x81; - //unsigned char endpoint_address = 0x02; - const uint32_t transfer_count = 1024; - struct libusb_transfer* transfers[transfer_count]; + return device; +} + +void free_transfers(struct libusb_transfer** const transfers, const uint32_t transfer_count) { + for(uint32_t transfer_index=0; transfer_indexbuffer == 0 ) { + if( transfers[transfer_index]->buffer == NULL ) { + free_transfers(transfers, transfer_count); printf("malloc() failed\n"); - return -7; + return NULL; } int error = libusb_submit_transfer(transfers[transfer_index]); if( error != 0 ) { + free_transfers(transfers, transfer_count); printf("libusb_submit_transfer() failed: %d\n", error); - return -8; + return NULL; } } + return transfers; +} + +int main(int argc, char** argv) { + if( argc != 2 ) { + printf("Usage: usb_test \n"); + return -1; + } + + const char* const path = argv[1]; + + fd = -1; + uint_fast8_t endpoint_address = 0; + libusb_transfer_cb_fn callback = NULL; + + if( transceiver_mode == TRANSCEIVER_MODE_RX ) { + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); + endpoint_address = 0x81; + callback = &write_callback; + } else { + fd = open(path, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + endpoint_address = 0x02; + callback = &read_callback; + } + + if( fd == -1 ) { + printf("Failed to open file: errno %d\n", errno); + return fd; + } + + libusb_context* const context = NULL; + libusb_device_handle* const device = open_device(context); + if( device == NULL ) { + return -3; + } + + const uint32_t transfer_count = 1024; + const uint32_t buffer_size = 16384; + struct libusb_transfer** const transfers = prepare_transfers( + device, endpoint_address, transfer_count, buffer_size, callback + ); + if( transfers == NULL ) { + return -4; + } + ////////////////////////////////////////////////////////////// struct timeval timeout = { 0, 500000 }; @@ -158,7 +231,9 @@ int main(int argc, char** argv) { call_count += 1; } while(1); - result = libusb_release_interface(device, 0); + free_transfers(transfers, transfer_count); + + int result = libusb_release_interface(device, 0); if( result != 0 ) { printf("libusb_release_interface() failed: %d\n", result); return -2000; From 8291d7fac040ecb7c4882db300da16d246908495 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 11 Oct 2012 13:04:30 -0700 Subject: [PATCH 02/20] Add SGPIO configuration function for "deep" (8-slice) TX mode. --- firmware/common/sgpio.c | 79 +++++++++++++++++++++++++++++++++++++++++ firmware/common/sgpio.h | 1 + 2 files changed, 80 insertions(+) diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 2db69608..e38c3d3e 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -146,6 +146,85 @@ void sgpio_configure_for_tx() { ; } +void sgpio_configure_for_tx_deep() { + // Disable all counters during configuration + SGPIO_CTRL_ENABLE = 0; + + sgpio_configure_pin_functions(); + + // Set SGPIO output values. + SGPIO_GPIO_OUTREG = + (1L << 11) | // direction + (1L << 10); // disable + + // Enable SGPIO pin outputs. + SGPIO_GPIO_OENREG = + (1L << 11) | // direction: TX: data to CPLD + (1L << 10) | // disable + (0L << 9) | // capture + (0L << 8) | // clock + 0xFF; // data: output + + SGPIO_OUT_MUX_CFG( 8) = 0; // SGPIO: Input: clock + SGPIO_OUT_MUX_CFG( 9) = 0; // SGPIO: Input: qualifier + SGPIO_OUT_MUX_CFG(10) = (0L << 4) | (4L << 0); // GPIO: Output: disable + SGPIO_OUT_MUX_CFG(11) = (0L << 4) | (4L << 0); // GPIO: Output: direction + + for(uint_fast8_t i=0; i<8; i++) { + // SGPIO pin 0 outputs slice A bit "i". + SGPIO_OUT_MUX_CFG(i) = + (0L << 4) | // P_OE_CFG = 0 + (11L << 0); // P_OUT_CFG = 11, dout_doutm8c (8-bit mode 8c) + } + + const uint_fast8_t slice_indices[] = { + SGPIO_SLICE_A, + SGPIO_SLICE_I, + SGPIO_SLICE_E, + SGPIO_SLICE_J, + SGPIO_SLICE_C, + SGPIO_SLICE_K, + SGPIO_SLICE_F, + SGPIO_SLICE_L, + }; + + uint32_t slice_enable_mask = 0; + for(uint_fast8_t i=0; i<8; i++) { + uint_fast8_t slice_index = slice_indices[i]; + const uint_fast8_t concat_order = 3; + const uint_fast8_t concat_enable = 1; + SGPIO_MUX_CFG(slice_index) = + (concat_order << 12) | // CONCAT_ORDER = 3 (eight slices) + (concat_enable << 11) | // CONCAT_ENABLE = 1 (concatenate data) + (0L << 9) | // QUALIFIER_SLICE_MODE = X + (1L << 7) | // QUALIFIER_PIN_MODE = 1 (SGPIO9) + (3L << 5) | // QUALIFIER_MODE = 3 (external SGPIO pin) + (0L << 3) | // CLK_SOURCE_SLICE_MODE = X + (0L << 1) | // CLK_SOURCE_PIN_MODE = 0 (SGPIO8) + (1L << 0); // EXT_CLK_ENABLE = 1, external clock signal (slice) + + SGPIO_SLICE_MUX_CFG(slice_index) = + (0L << 8) | // INV_QUALIFIER = 0 (use normal qualifier) + (3L << 6) | // PARALLEL_MODE = 3 (shift 8 bits per clock) + (0L << 4) | // DATA_CAPTURE_MODE = 0 (detect rising edge) + (0L << 3) | // INV_OUT_CLK = X + (1L << 2) | // CLKGEN_MODE = 1 (use external pin clock) + (1L << 1) | // CLK_CAPTURE_MODE = 1 (use falling clock edge) + (0L << 0); // MATCH_MODE = 0 (do not match data) + + SGPIO_PRESET(slice_index) = 0; // External clock, don't care + SGPIO_COUNT(slice_index) = 0; // External clock, don't care + SGPIO_POS(slice_index) = (0x1f << 8) | (0x1f << 0); + SGPIO_REG(slice_index) = 0xFFFFFFFF; // Primary output data register + SGPIO_REG_SS(slice_index) = 0xFFFFFFFF; // Shadow output data register + + slice_enable_mask |= (1 << slice_index); + } + + // Start SGPIO operation by enabling slice clocks. + SGPIO_CTRL_ENABLE = slice_enable_mask; +} + void sgpio_configure_for_rx() { // Disable all counters during configuration SGPIO_CTRL_ENABLE = 0; diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index 8b8f471c..d41acef4 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -25,6 +25,7 @@ void sgpio_configure_pin_functions(); void sgpio_test_interface(); void sgpio_configure_for_tx(); +void sgpio_configure_for_tx_deep(); void sgpio_configure_for_rx(); void sgpio_configure_for_rx_deep(); void sgpio_cpld_stream_enable(); From fb9ce63f7f5ca464028eff2783a0bb7b6894f38c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 11 Oct 2012 13:06:27 -0700 Subject: [PATCH 03/20] Add (manual) switch for TX and RX mode. Add code for configuring TX mode. TODO: Consolidate lots of repetitive code. --- firmware/usb_performance/usb_performance.c | 85 ++++++++++++++++------ 1 file changed, 64 insertions(+), 21 deletions(-) diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 5a6989e3..b5eaa6fa 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -38,6 +38,12 @@ #include "usb_descriptor.h" #include "usb_standard_request.h" +typedef enum { + TRANSCEIVER_MODE_RX, + TRANSCEIVER_MODE_TX, +} transceiver_mode_t; +static transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_TX; + uint8_t* const usb_bulk_buffer = (uint8_t*)0x20004000; static volatile uint32_t usb_bulk_buffer_offset = 0; static const uint32_t usb_bulk_buffer_mask = 32768 - 1; @@ -202,12 +208,15 @@ bool usb_set_configuration( // hard-coding, this whole function can move into a shared/reusable // library. if( device->configuration && (device->configuration->number == 1) ) { - usb_endpoint_init(&usb_endpoint_bulk_in); - usb_endpoint_init(&usb_endpoint_bulk_out); + if( transceiver_mode == TRANSCEIVER_MODE_RX ) { + sgpio_configure_for_rx_deep(); + usb_endpoint_init(&usb_endpoint_bulk_in); + } else { + sgpio_configure_for_tx_deep(); + usb_endpoint_init(&usb_endpoint_bulk_out); + } usb_init_buffers_bulk(); - - sgpio_configure_for_rx_deep(); nvic_set_priority(NVIC_M4_SGPIO_IRQ, 0); nvic_enable_irq(NVIC_M4_SGPIO_IRQ); @@ -237,15 +246,26 @@ void sgpio_irqhandler() { SGPIO_CLR_STATUS_1 = 0xFFFFFFFF; uint32_t* const p = (uint32_t*)&usb_bulk_buffer[usb_bulk_buffer_offset]; - p[7] = SGPIO_REG_SS(SGPIO_SLICE_A); - p[6] = SGPIO_REG_SS(SGPIO_SLICE_I); - p[5] = SGPIO_REG_SS(SGPIO_SLICE_E); - p[4] = SGPIO_REG_SS(SGPIO_SLICE_J); - p[3] = SGPIO_REG_SS(SGPIO_SLICE_C); - p[2] = SGPIO_REG_SS(SGPIO_SLICE_K); - p[1] = SGPIO_REG_SS(SGPIO_SLICE_F); - p[0] = SGPIO_REG_SS(SGPIO_SLICE_L); - + if( transceiver_mode == TRANSCEIVER_MODE_RX ) { + p[7] = SGPIO_REG_SS(SGPIO_SLICE_A); + p[6] = SGPIO_REG_SS(SGPIO_SLICE_I); + p[5] = SGPIO_REG_SS(SGPIO_SLICE_E); + p[4] = SGPIO_REG_SS(SGPIO_SLICE_J); + p[3] = SGPIO_REG_SS(SGPIO_SLICE_C); + p[2] = SGPIO_REG_SS(SGPIO_SLICE_K); + p[1] = SGPIO_REG_SS(SGPIO_SLICE_F); + p[0] = SGPIO_REG_SS(SGPIO_SLICE_L); + } else { + SGPIO_REG_SS(SGPIO_SLICE_A) = p[7]; + SGPIO_REG_SS(SGPIO_SLICE_I) = p[6]; + SGPIO_REG_SS(SGPIO_SLICE_E) = p[5]; + SGPIO_REG_SS(SGPIO_SLICE_J) = p[4]; + SGPIO_REG_SS(SGPIO_SLICE_C) = p[3]; + SGPIO_REG_SS(SGPIO_SLICE_K) = p[2]; + SGPIO_REG_SS(SGPIO_SLICE_F) = p[1]; + SGPIO_REG_SS(SGPIO_SLICE_L) = p[0]; + } + usb_bulk_buffer_offset = (usb_bulk_buffer_offset + 32) & usb_bulk_buffer_mask; } @@ -290,14 +310,37 @@ int main(void) { max2837_rx(); ssp1_set_mode_max5864(); max5864_xcvr(); - - while(true) { - while( usb_bulk_buffer_offset < 16384 ); - usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[0]); - - while( usb_bulk_buffer_offset >= 16384 ); - usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[1]); - } + // TODO: If this turns out to be the same code, simplify. + if( transceiver_mode == TRANSCEIVER_MODE_RX ) { + while(true) { + // Wait until buffer 0 is received. + while( usb_bulk_buffer_offset < 16384 ); + + // Set up IN transfer to send buffer 0. + usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[0]); + + // Wait until buffer 1 is received. + while( usb_bulk_buffer_offset >= 16384 ); + + // Set up IN transfer to send buffer 1. + usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[1]); + } + } else { + while(true) { + // Wait until buffer 0 is transmitted. + while( usb_bulk_buffer_offset < 16384 ); + + // Set up OUT transfer to fill buffer 0. + usb_endpoint_schedule_no_int(&usb_endpoint_bulk_out, &usb_td_bulk[0]); + + // Wait until buffer 1 is transmitted. + while( usb_bulk_buffer_offset >= 16384 ); + + // Set up OUT transfer to fill buffer 1. + usb_endpoint_schedule_no_int(&usb_endpoint_bulk_out, &usb_td_bulk[1]); + } + } + return 0; } From c0cb64f3166a7c3b3d026369e6de8222a7e49db6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 11 Oct 2012 13:07:25 -0700 Subject: [PATCH 04/20] Add support for TX mode. Add getopt control of RX or TX mode. --- host/usb_test/usb_test.c | 55 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/host/usb_test/usb_test.c b/host/usb_test/usb_test.c index 5ce79244..c984898c 100644 --- a/host/usb_test/usb_test.c +++ b/host/usb_test/usb_test.c @@ -21,7 +21,9 @@ #include #include +#include #include +#include #include #include @@ -156,13 +158,56 @@ struct libusb_transfer** prepare_transfers( return transfers; } +static void usage() { + printf("Usage:\n"); + printf("\tGo fish.\n"); +} + int main(int argc, char** argv) { - if( argc != 2 ) { - printf("Usage: usb_test \n"); - return -1; - } + int opt; + bool receive = false; + bool transmit = false; + const char* path = NULL; - const char* const path = argv[1]; + while( (opt = getopt(argc, argv, "r:t:")) != EOF ) { + switch( opt ) { + case 'r': + receive = true; + path = optarg; + break; + + case 't': + transmit = true; + path = optarg; + break; + + default: + usage(); + return 1; + } + } + + if( transmit == receive ) { + if( transmit == true ) { + fprintf(stderr, "receive and transmit options are mutually exclusive\n"); + } else { + fprintf(stderr, "specify either transmit or receive option\n"); + } + return 1; + } + + if( receive ) { + transceiver_mode = TRANSCEIVER_MODE_RX; + } + + if( transmit ) { + transceiver_mode = TRANSCEIVER_MODE_TX; + } + + if( path == NULL ) { + fprintf(stderr, "specify a path to a file to transmit/receive\n"); + return 1; + } fd = -1; uint_fast8_t endpoint_address = 0; From 6f0fda0beeafc7e4739fe9078fcb8dbb951b0740 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 11 Oct 2012 15:12:25 -0700 Subject: [PATCH 05/20] Moved transceiver_mode_t to hackrf_core.h. Changed transceiver_mode to volatile, since it's liable to be accessed at interrupt time. --- firmware/common/hackrf_core.h | 5 +++++ firmware/usb_performance/usb_performance.c | 6 +----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 37722b1c..7eb57698 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -200,6 +200,11 @@ extern "C" /* TODO add other Pins */ +typedef enum { + TRANSCEIVER_MODE_RX, + TRANSCEIVER_MODE_TX, +} transceiver_mode_t; + void delay(uint32_t duration); void cpu_clock_init(void); diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index b5eaa6fa..a4f7fd0d 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -38,11 +38,7 @@ #include "usb_descriptor.h" #include "usb_standard_request.h" -typedef enum { - TRANSCEIVER_MODE_RX, - TRANSCEIVER_MODE_TX, -} transceiver_mode_t; -static transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_TX; +static volatile transceiver_mode_t transceiver_mode = TRANSCEIVER_MODE_TX; uint8_t* const usb_bulk_buffer = (uint8_t*)0x20004000; static volatile uint32_t usb_bulk_buffer_offset = 0; From 1bad2d8536e7486616aa7234ead9f42c700e966a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 11 Oct 2012 15:18:16 -0700 Subject: [PATCH 06/20] Consolidated two "deep" SGPIO configuration functions into one, qualified by transceiver mode (RX or TX). 95-ish % of the code was common. --- firmware/common/sgpio.c | 101 +++------------------ firmware/common/sgpio.h | 5 +- firmware/usb_performance/usb_performance.c | 4 +- 3 files changed, 20 insertions(+), 90 deletions(-) diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index e38c3d3e..d81a5ac2 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -146,85 +146,6 @@ void sgpio_configure_for_tx() { ; } -void sgpio_configure_for_tx_deep() { - // Disable all counters during configuration - SGPIO_CTRL_ENABLE = 0; - - sgpio_configure_pin_functions(); - - // Set SGPIO output values. - SGPIO_GPIO_OUTREG = - (1L << 11) | // direction - (1L << 10); // disable - - // Enable SGPIO pin outputs. - SGPIO_GPIO_OENREG = - (1L << 11) | // direction: TX: data to CPLD - (1L << 10) | // disable - (0L << 9) | // capture - (0L << 8) | // clock - 0xFF; // data: output - - SGPIO_OUT_MUX_CFG( 8) = 0; // SGPIO: Input: clock - SGPIO_OUT_MUX_CFG( 9) = 0; // SGPIO: Input: qualifier - SGPIO_OUT_MUX_CFG(10) = (0L << 4) | (4L << 0); // GPIO: Output: disable - SGPIO_OUT_MUX_CFG(11) = (0L << 4) | (4L << 0); // GPIO: Output: direction - - for(uint_fast8_t i=0; i<8; i++) { - // SGPIO pin 0 outputs slice A bit "i". - SGPIO_OUT_MUX_CFG(i) = - (0L << 4) | // P_OE_CFG = 0 - (11L << 0); // P_OUT_CFG = 11, dout_doutm8c (8-bit mode 8c) - } - - const uint_fast8_t slice_indices[] = { - SGPIO_SLICE_A, - SGPIO_SLICE_I, - SGPIO_SLICE_E, - SGPIO_SLICE_J, - SGPIO_SLICE_C, - SGPIO_SLICE_K, - SGPIO_SLICE_F, - SGPIO_SLICE_L, - }; - - uint32_t slice_enable_mask = 0; - for(uint_fast8_t i=0; i<8; i++) { - uint_fast8_t slice_index = slice_indices[i]; - const uint_fast8_t concat_order = 3; - const uint_fast8_t concat_enable = 1; - SGPIO_MUX_CFG(slice_index) = - (concat_order << 12) | // CONCAT_ORDER = 3 (eight slices) - (concat_enable << 11) | // CONCAT_ENABLE = 1 (concatenate data) - (0L << 9) | // QUALIFIER_SLICE_MODE = X - (1L << 7) | // QUALIFIER_PIN_MODE = 1 (SGPIO9) - (3L << 5) | // QUALIFIER_MODE = 3 (external SGPIO pin) - (0L << 3) | // CLK_SOURCE_SLICE_MODE = X - (0L << 1) | // CLK_SOURCE_PIN_MODE = 0 (SGPIO8) - (1L << 0); // EXT_CLK_ENABLE = 1, external clock signal (slice) - - SGPIO_SLICE_MUX_CFG(slice_index) = - (0L << 8) | // INV_QUALIFIER = 0 (use normal qualifier) - (3L << 6) | // PARALLEL_MODE = 3 (shift 8 bits per clock) - (0L << 4) | // DATA_CAPTURE_MODE = 0 (detect rising edge) - (0L << 3) | // INV_OUT_CLK = X - (1L << 2) | // CLKGEN_MODE = 1 (use external pin clock) - (1L << 1) | // CLK_CAPTURE_MODE = 1 (use falling clock edge) - (0L << 0); // MATCH_MODE = 0 (do not match data) - - SGPIO_PRESET(slice_index) = 0; // External clock, don't care - SGPIO_COUNT(slice_index) = 0; // External clock, don't care - SGPIO_POS(slice_index) = (0x1f << 8) | (0x1f << 0); - SGPIO_REG(slice_index) = 0xFFFFFFFF; // Primary output data register - SGPIO_REG_SS(slice_index) = 0xFFFFFFFF; // Shadow output data register - - slice_enable_mask |= (1 << slice_index); - } - - // Start SGPIO operation by enabling slice clocks. - SGPIO_CTRL_ENABLE = slice_enable_mask; -} - void sgpio_configure_for_rx() { // Disable all counters during configuration SGPIO_CTRL_ENABLE = 0; @@ -287,24 +208,30 @@ void sgpio_configure_for_rx() { ; } -void sgpio_configure_for_rx_deep() { +void sgpio_configure_deep(const transceiver_mode_t transceiver_mode) { // Disable all counters during configuration SGPIO_CTRL_ENABLE = 0; sgpio_configure_pin_functions(); // Set SGPIO output values. + const uint_fast8_t cpld_direction = + (transceiver_mode == TRANSCEIVER_MODE_TX) ? 1 : 0; SGPIO_GPIO_OUTREG = - (0L << 11) | // direction + (cpld_direction << 11) | // direction (1L << 10); // disable // Enable SGPIO pin outputs. + const uint_fast16_t sgpio_gpio_data_direction = + (transceiver_mode == TRANSCEIVER_MODE_TX) + ? (0xFF << 0) + : (0x00 << 0); SGPIO_GPIO_OENREG = - (1L << 11) | // direction: RX: data from CPLD + (1L << 11) | // direction (1L << 10) | // disable (0L << 9) | // capture (0L << 8) | // clock - 0x00; // data: input + sgpio_gpio_data_direction; // data: output SGPIO_OUT_MUX_CFG( 8) = 0; // SGPIO: Input: clock SGPIO_OUT_MUX_CFG( 9) = 0; // SGPIO: Input: qualifier @@ -312,9 +239,10 @@ void sgpio_configure_for_rx_deep() { SGPIO_OUT_MUX_CFG(11) = (0L << 4) | (4L << 0); // GPIO: Output: direction for(uint_fast8_t i=0; i<8; i++) { + // SGPIO pin 0 outputs slice A bit "i". SGPIO_OUT_MUX_CFG(i) = (0L << 4) | // P_OE_CFG = 0 - (9L << 0); // P_OUT_CFG = 9, dout_doutm8a (8-bit mode 8a) + (11L << 0); // P_OUT_CFG = 11, dout_doutm8c (8-bit mode 8c) } const uint_fast8_t slice_indices[] = { @@ -331,8 +259,9 @@ void sgpio_configure_for_rx_deep() { uint32_t slice_enable_mask = 0; for(uint_fast8_t i=0; i<8; i++) { uint_fast8_t slice_index = slice_indices[i]; - const uint_fast8_t concat_order = (slice_index == SGPIO_SLICE_A) ? 0 : 3; - const uint_fast8_t concat_enable = (slice_index == SGPIO_SLICE_A) ? 0 : 1; + const bool input_slice = (i == 0) && (transceiver_mode == TRANSCEIVER_MODE_RX); + const uint_fast8_t concat_order = input_slice ? 0 : 3; + const uint_fast8_t concat_enable = input_slice ? 0 : 1; SGPIO_MUX_CFG(slice_index) = (concat_order << 12) | // CONCAT_ORDER = 3 (eight slices) (concat_enable << 11) | // CONCAT_ENABLE = 1 (concatenate data) diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index d41acef4..622ed802 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -22,12 +22,13 @@ #ifndef __SGPIO_H__ #define __SGPIO_H__ +#include + void sgpio_configure_pin_functions(); void sgpio_test_interface(); void sgpio_configure_for_tx(); -void sgpio_configure_for_tx_deep(); void sgpio_configure_for_rx(); -void sgpio_configure_for_rx_deep(); +void sgpio_configure_deep(const transceiver_mode_t transceiver_mode); void sgpio_cpld_stream_enable(); void sgpio_cpld_stream_disable(); bool sgpio_cpld_stream_is_enabled(); diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index a4f7fd0d..7e8752ef 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -205,10 +205,10 @@ bool usb_set_configuration( // library. if( device->configuration && (device->configuration->number == 1) ) { if( transceiver_mode == TRANSCEIVER_MODE_RX ) { - sgpio_configure_for_rx_deep(); + sgpio_configure_deep(transceiver_mode); usb_endpoint_init(&usb_endpoint_bulk_in); } else { - sgpio_configure_for_tx_deep(); + sgpio_configure_deep(transceiver_mode); usb_endpoint_init(&usb_endpoint_bulk_out); } From 1b5574d2b9f28376c94b0254f82e4731c946c0f5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 11 Oct 2012 15:19:01 -0700 Subject: [PATCH 07/20] RX and TX sample buffer loops turned out to be the same, so they're consolidated. --- firmware/usb_performance/usb_performance.c | 37 ++++++---------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 7e8752ef..1a54927a 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -307,35 +307,18 @@ int main(void) { ssp1_set_mode_max5864(); max5864_xcvr(); - // TODO: If this turns out to be the same code, simplify. - if( transceiver_mode == TRANSCEIVER_MODE_RX ) { - while(true) { - // Wait until buffer 0 is received. - while( usb_bulk_buffer_offset < 16384 ); + while(true) { + // Wait until buffer 0 is transmitted/received. + while( usb_bulk_buffer_offset < 16384 ); - // Set up IN transfer to send buffer 0. - usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[0]); - - // Wait until buffer 1 is received. - while( usb_bulk_buffer_offset >= 16384 ); + // Set up IN transfer of buffer 0. + usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[0]); + + // Wait until buffer 1 is transmitted/received. + while( usb_bulk_buffer_offset >= 16384 ); - // Set up IN transfer to send buffer 1. - usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[1]); - } - } else { - while(true) { - // Wait until buffer 0 is transmitted. - while( usb_bulk_buffer_offset < 16384 ); - - // Set up OUT transfer to fill buffer 0. - usb_endpoint_schedule_no_int(&usb_endpoint_bulk_out, &usb_td_bulk[0]); - - // Wait until buffer 1 is transmitted. - while( usb_bulk_buffer_offset >= 16384 ); - - // Set up OUT transfer to fill buffer 1. - usb_endpoint_schedule_no_int(&usb_endpoint_bulk_out, &usb_td_bulk[1]); - } + // Set up IN transfer of buffer 1. + usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[1]); } return 0; From 9b579232a72f9b47ed507b5679c6e0bf5fdb160b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 11 Oct 2012 15:45:28 -0700 Subject: [PATCH 08/20] Consolidated single-slice SGPIO configuration functions into single sgpio_configure() function. --- firmware/common/sgpio.c | 156 +++------------------ firmware/common/sgpio.h | 7 +- firmware/sgpio-rx/sgpio-rx.c | 4 +- firmware/sgpio/sgpio.c | 4 +- firmware/usb_performance/usb_performance.c | 4 +- 5 files changed, 30 insertions(+), 145 deletions(-) diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index d81a5ac2..c04f39da 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -83,132 +83,10 @@ void sgpio_test_interface() { } } -void sgpio_configure_for_tx() { - // Disable all counters during configuration - SGPIO_CTRL_ENABLE = 0; - - sgpio_configure_pin_functions(); - - // Set SGPIO output values. - SGPIO_GPIO_OUTREG = - (1L << 11) | // direction - (1L << 10); // disable - - // Enable SGPIO pin outputs. - SGPIO_GPIO_OENREG = - (1L << 11) | // direction: TX: data to CPLD - (1L << 10) | // disable - (0L << 9) | // capture - (0L << 8) | // clock - 0xFF; // data: output - - SGPIO_OUT_MUX_CFG( 8) = 0; // SGPIO: Input: clock - SGPIO_OUT_MUX_CFG( 9) = 0; // SGPIO: Input: qualifier - SGPIO_OUT_MUX_CFG(10) = (0L << 4) | (4L << 0); // GPIO: Output: disable - SGPIO_OUT_MUX_CFG(11) = (0L << 4) | (4L << 0); // GPIO: Output: direction - - for(uint_fast8_t i=0; i<8; i++) { - // SGPIO pin 0 outputs slice A bit "i". - SGPIO_OUT_MUX_CFG(i) = - (0L << 4) | // P_OE_CFG = 0 - (9L << 0); // P_OUT_CFG = 9, dout_doutm8a (8-bit mode 8a) - } - - // Slice A - SGPIO_MUX_CFG(SGPIO_SLICE_A) = - (0L << 12) | // CONCAT_ORDER = 0 (self-loop) - (1L << 11) | // CONCAT_ENABLE = 1 (concatenate data) - (0L << 9) | // QUALIFIER_SLICE_MODE = X - (1L << 7) | // QUALIFIER_PIN_MODE = 1 (SGPIO9) - (3L << 5) | // QUALIFIER_MODE = 3 (external SGPIO pin) - (0L << 3) | // CLK_SOURCE_SLICE_MODE = X - (0L << 1) | // CLK_SOURCE_PIN_MODE = 0 (SGPIO8) - (1L << 0); // EXT_CLK_ENABLE = 1, external clock signal (slice) - - SGPIO_SLICE_MUX_CFG(SGPIO_SLICE_A) = - (0L << 8) | // INV_QUALIFIER = 0 (use normal qualifier) - (3L << 6) | // PARALLEL_MODE = 3 (shift 8 bits per clock) - (0L << 4) | // DATA_CAPTURE_MODE = 0 (detect rising edge) - (0L << 3) | // INV_OUT_CLK = 0 (normal clock) - (1L << 2) | // CLKGEN_MODE = 1 (use external pin clock) - (0L << 1) | // CLK_CAPTURE_MODE = 0 (use rising clock edge) - (0L << 0); // MATCH_MODE = 0 (do not match data) - - SGPIO_PRESET(SGPIO_SLICE_A) = 0; - SGPIO_COUNT(SGPIO_SLICE_A) = 0; - SGPIO_POS(SGPIO_SLICE_A) = (0x3L << 8) | (0x3L << 0); - SGPIO_REG(SGPIO_SLICE_A) = 0x80808080; // Primary output data register - SGPIO_REG_SS(SGPIO_SLICE_A) = 0x80808080; // Shadow output data register - - // Start SGPIO operation by enabling slice clocks. - SGPIO_CTRL_ENABLE = - (1L << SGPIO_SLICE_A) - ; -} - -void sgpio_configure_for_rx() { - // Disable all counters during configuration - SGPIO_CTRL_ENABLE = 0; - - sgpio_configure_pin_functions(); - - // Set SGPIO output values. - SGPIO_GPIO_OUTREG = - (0L << 11) | // direction - (1L << 10); // disable - - // Enable SGPIO pin outputs. - SGPIO_GPIO_OENREG = - (1L << 11) | // direction: RX: data from CPLD - (1L << 10) | // disable - (0L << 9) | // capture - (0L << 8) | // clock - 0x00; // data: input - - SGPIO_OUT_MUX_CFG( 8) = 0; // SGPIO: Input: clock - SGPIO_OUT_MUX_CFG( 9) = 0; // SGPIO: Input: qualifier - SGPIO_OUT_MUX_CFG(10) = (0L << 4) | (4L << 0); // GPIO: Output: disable - SGPIO_OUT_MUX_CFG(11) = (0L << 4) | (4L << 0); // GPIO: Output: direction - - for(uint_fast8_t i=0; i<8; i++) { - SGPIO_OUT_MUX_CFG(i) = - (0L << 4) | // P_OE_CFG = 0 - (9L << 0); // P_OUT_CFG = 9, dout_doutm8a (8-bit mode 8a) - } - - // Slice A - SGPIO_MUX_CFG(SGPIO_SLICE_A) = - (0L << 12) | // CONCAT_ORDER = X - (0L << 11) | // CONCAT_ENABLE = 0 (concatenate data) - (0L << 9) | // QUALIFIER_SLICE_MODE = X - (1L << 7) | // QUALIFIER_PIN_MODE = 1 (SGPIO9) - (3L << 5) | // QUALIFIER_MODE = 3 (external SGPIO pin) - (0L << 3) | // CLK_SOURCE_SLICE_MODE = X - (0L << 1) | // CLK_SOURCE_PIN_MODE = 0 (SGPIO8) - (1L << 0); // EXT_CLK_ENABLE = 1, external clock signal (slice) - - SGPIO_SLICE_MUX_CFG(SGPIO_SLICE_A) = - (0L << 8) | // INV_QUALIFIER = 0 (use normal qualifier) - (3L << 6) | // PARALLEL_MODE = 3 (shift 8 bits per clock) - (0L << 4) | // DATA_CAPTURE_MODE = 0 (detect rising edge) - (0L << 3) | // INV_OUT_CLK = X - (1L << 2) | // CLKGEN_MODE = 1 (use external pin clock) - (1L << 1) | // CLK_CAPTURE_MODE = 1 (use falling clock edge) - (0L << 0); // MATCH_MODE = 0 (do not match data) - - SGPIO_PRESET(SGPIO_SLICE_A) = 0; - SGPIO_COUNT(SGPIO_SLICE_A) = 0; - SGPIO_POS(SGPIO_SLICE_A) = (0 << 8) | (0 << 0); - SGPIO_REG(SGPIO_SLICE_A) = 0xCAFEBABE; // Primary output data register - SGPIO_REG_SS(SGPIO_SLICE_A) = 0xDEADBEEF; // Shadow output data register - - // Start SGPIO operation by enabling slice clocks. - SGPIO_CTRL_ENABLE = - (1L << SGPIO_SLICE_A) - ; -} - -void sgpio_configure_deep(const transceiver_mode_t transceiver_mode) { +void sgpio_configure( + const transceiver_mode_t transceiver_mode, + const bool multi_slice +) { // Disable all counters during configuration SGPIO_CTRL_ENABLE = 0; @@ -238,11 +116,13 @@ void sgpio_configure_deep(const transceiver_mode_t transceiver_mode) { SGPIO_OUT_MUX_CFG(10) = (0L << 4) | (4L << 0); // GPIO: Output: disable SGPIO_OUT_MUX_CFG(11) = (0L << 4) | (4L << 0); // GPIO: Output: direction + const uint_fast8_t output_multiplexing_mode = + multi_slice ? 11 : 9; for(uint_fast8_t i=0; i<8; i++) { // SGPIO pin 0 outputs slice A bit "i". SGPIO_OUT_MUX_CFG(i) = (0L << 4) | // P_OE_CFG = 0 - (11L << 0); // P_OUT_CFG = 11, dout_doutm8c (8-bit mode 8c) + (output_multiplexing_mode << 0); } const uint_fast8_t slice_indices[] = { @@ -256,15 +136,19 @@ void sgpio_configure_deep(const transceiver_mode_t transceiver_mode) { SGPIO_SLICE_L, }; + const bool single_slice = !multi_slice; + const uint_fast8_t slice_count = multi_slice ? 8 : 1; + uint32_t slice_enable_mask = 0; - for(uint_fast8_t i=0; i<8; i++) { - uint_fast8_t slice_index = slice_indices[i]; + for(uint_fast8_t i=0; i void tx_test() { - sgpio_configure_for_tx(); + sgpio_configure(TRANSCEIVER_MODE_TX, false); // LSB goes out first, samples are 0x volatile uint32_t buffer[] = { @@ -54,7 +54,7 @@ void tx_test() { } void rx_test() { - sgpio_configure_for_rx(); + sgpio_configure(TRANSCEIVER_MODE_RX, false); volatile uint32_t buffer[4096]; uint32_t i = 0; diff --git a/firmware/sgpio/sgpio.c b/firmware/sgpio/sgpio.c index 88008313..fbf40ffd 100644 --- a/firmware/sgpio/sgpio.c +++ b/firmware/sgpio/sgpio.c @@ -31,7 +31,7 @@ #include void tx_test() { - sgpio_configure_for_tx(); + sgpio_configure(TRANSCEIVER_MODE_TX, false); // LSB goes out first, samples are 0x volatile uint32_t buffer[] = { @@ -52,7 +52,7 @@ void tx_test() { } void rx_test() { - sgpio_configure_for_rx(); + sgpio_configure(TRANSCEIVER_MODE_RX, false); volatile uint32_t buffer[4096]; uint32_t i = 0; diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 1a54927a..2766981d 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -205,10 +205,10 @@ bool usb_set_configuration( // library. if( device->configuration && (device->configuration->number == 1) ) { if( transceiver_mode == TRANSCEIVER_MODE_RX ) { - sgpio_configure_deep(transceiver_mode); + sgpio_configure(transceiver_mode, true); usb_endpoint_init(&usb_endpoint_bulk_in); } else { - sgpio_configure_deep(transceiver_mode); + sgpio_configure(transceiver_mode, true); usb_endpoint_init(&usb_endpoint_bulk_out); } From a1af4356b62eec3ae978be02ed9eba38ea7016e8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 11 Oct 2012 20:46:21 -0700 Subject: [PATCH 09/20] Reworked sgpio.c to make use of #defines for fields, instead of hard-coding shifts. Proper. --- firmware/common/sgpio.c | 99 ++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index c04f39da..451e9c52 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -59,17 +59,23 @@ void sgpio_test_interface() { // Make all SGPIO controlled by SGPIO's "GPIO" registers for (uint_fast8_t i = 0; i < 16; i++) { - SGPIO_OUT_MUX_CFG(i) = (0L << 4) | (4L << 0); + SGPIO_OUT_MUX_CFG(i) = + SGPIO_OUT_MUX_CFG_P_OE_CFG(0) + | SGPIO_OUT_MUX_CFG_P_OUT_CFG(4); } // Set SGPIO output values. - SGPIO_GPIO_OUTREG = (1L << host_direction_sgpio_pin) - | (1L << host_disable_sgpio_pin); + SGPIO_GPIO_OUTREG = + (1L << host_direction_sgpio_pin) + | (1L << host_disable_sgpio_pin); // Enable SGPIO pin outputs. - SGPIO_GPIO_OENREG = (1L << host_direction_sgpio_pin) - | (1L << host_disable_sgpio_pin) | (0L << host_capture_sgpio_pin) - | (0L << host_clock_sgpio_pin) | (0xFF << 0); + SGPIO_GPIO_OENREG = + (1L << host_direction_sgpio_pin) + | (1L << host_disable_sgpio_pin) + | (0L << host_capture_sgpio_pin) + | (0L << host_clock_sgpio_pin) + | (0xFF << 0); // Configure SGPIO slices. @@ -96,8 +102,9 @@ void sgpio_configure( const uint_fast8_t cpld_direction = (transceiver_mode == TRANSCEIVER_MODE_TX) ? 1 : 0; SGPIO_GPIO_OUTREG = - (cpld_direction << 11) | // direction - (1L << 10); // disable + (cpld_direction << 11) + | (1L << 10) // disable + ; // Enable SGPIO pin outputs. const uint_fast16_t sgpio_gpio_data_direction = @@ -105,24 +112,38 @@ void sgpio_configure( ? (0xFF << 0) : (0x00 << 0); SGPIO_GPIO_OENREG = - (1L << 11) | // direction - (1L << 10) | // disable - (0L << 9) | // capture - (0L << 8) | // clock - sgpio_gpio_data_direction; // data: output + (1L << 11) // direction + | (1L << 10) // disable + | (0L << 9) // capture + | (0L << 8) // clock + | sgpio_gpio_data_direction + ; - SGPIO_OUT_MUX_CFG( 8) = 0; // SGPIO: Input: clock - SGPIO_OUT_MUX_CFG( 9) = 0; // SGPIO: Input: qualifier - SGPIO_OUT_MUX_CFG(10) = (0L << 4) | (4L << 0); // GPIO: Output: disable - SGPIO_OUT_MUX_CFG(11) = (0L << 4) | (4L << 0); // GPIO: Output: direction + SGPIO_OUT_MUX_CFG( 8) = // SGPIO: Input: clock + SGPIO_OUT_MUX_CFG_P_OE_CFG(0) + | SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) + ; + SGPIO_OUT_MUX_CFG( 9) = // SGPIO: Input: qualifier + SGPIO_OUT_MUX_CFG_P_OE_CFG(0) + | SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) + ; + SGPIO_OUT_MUX_CFG(10) = // GPIO: Output: disable + SGPIO_OUT_MUX_CFG_P_OE_CFG(0) + | SGPIO_OUT_MUX_CFG_P_OUT_CFG(4) + ; + SGPIO_OUT_MUX_CFG(11) = // GPIO: Output: direction + SGPIO_OUT_MUX_CFG_P_OE_CFG(0) + | SGPIO_OUT_MUX_CFG_P_OUT_CFG(4) + ; const uint_fast8_t output_multiplexing_mode = multi_slice ? 11 : 9; for(uint_fast8_t i=0; i<8; i++) { // SGPIO pin 0 outputs slice A bit "i". SGPIO_OUT_MUX_CFG(i) = - (0L << 4) | // P_OE_CFG = 0 - (output_multiplexing_mode << 0); + SGPIO_OUT_MUX_CFG_P_OE_CFG(0) + | SGPIO_OUT_MUX_CFG_P_OUT_CFG(output_multiplexing_mode) + ; } const uint_fast8_t slice_indices[] = { @@ -146,28 +167,34 @@ void sgpio_configure( const uint_fast8_t concat_order = (input_slice || single_slice) ? 0 : 3; const uint_fast8_t concat_enable = (input_slice || single_slice) ? 0 : 1; const uint_fast8_t pos = multi_slice ? 0x1f : 0x03; + SGPIO_MUX_CFG(slice_index) = - (concat_order << 12) | - (concat_enable << 11) | - (0L << 9) | // QUALIFIER_SLICE_MODE = X - (1L << 7) | // QUALIFIER_PIN_MODE = 1 (SGPIO9) - (3L << 5) | // QUALIFIER_MODE = 3 (external SGPIO pin) - (0L << 3) | // CLK_SOURCE_SLICE_MODE = X - (0L << 1) | // CLK_SOURCE_PIN_MODE = 0 (SGPIO8) - (1L << 0); // EXT_CLK_ENABLE = 1, external clock signal (slice) + SGPIO_MUX_CFG_CONCAT_ORDER(concat_order) + | SGPIO_MUX_CFG_CONCAT_ENABLE(concat_enable) + | SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) + | SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) + | SGPIO_MUX_CFG_QUALIFIER_MODE(3) + | SGPIO_MUX_CFG_CLK_SOURCE_SLICE_MODE(0) + | SGPIO_MUX_CFG_CLK_SOURCE_PIN_MODE(0) + | SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) + ; SGPIO_SLICE_MUX_CFG(slice_index) = - (0L << 8) | // INV_QUALIFIER = 0 (use normal qualifier) - (3L << 6) | // PARALLEL_MODE = 3 (shift 8 bits per clock) - (0L << 4) | // DATA_CAPTURE_MODE = 0 (detect rising edge) - (0L << 3) | // INV_OUT_CLK = X - (1L << 2) | // CLKGEN_MODE = 1 (use external pin clock) - (1L << 1) | // CLK_CAPTURE_MODE = 1 (use falling clock edge) - (0L << 0); // MATCH_MODE = 0 (do not match data) + SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) + | SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(3) + | SGPIO_SLICE_MUX_CFG_DATA_CAPTURE_MODE(0) + | SGPIO_SLICE_MUX_CFG_INV_OUT_CLK(0) + | SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) + | SGPIO_SLICE_MUX_CFG_CLK_CAPTURE_MODE(1) + | SGPIO_SLICE_MUX_CFG_MATCH_MODE(0) + ; SGPIO_PRESET(slice_index) = 0; // External clock, don't care SGPIO_COUNT(slice_index) = 0; // External clock, don't care - SGPIO_POS(slice_index) = (pos << 8) | (pos << 0); + SGPIO_POS(slice_index) = + SGPIO_POS_POS_RESET(pos) + | SGPIO_POS_POS(pos) + ; SGPIO_REG(slice_index) = 0x80808080; // Primary output data register SGPIO_REG_SS(slice_index) = 0x80808080; // Shadow output data register @@ -190,4 +217,4 @@ void sgpio_cpld_stream_disable() { bool sgpio_cpld_stream_is_enabled() { return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; -} \ No newline at end of file +} From 9824a723b779981e3c5ddd320627e1fcb0741770 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 12 Oct 2012 09:45:18 -0700 Subject: [PATCH 10/20] Moved invariant in sgpio_configure() loop out of loop. Originally, so I could use the value to calculate another invariant. --- firmware/common/sgpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 451e9c52..d53c3f87 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -157,6 +157,7 @@ void sgpio_configure( SGPIO_SLICE_L, }; + const uint_fast8_t pos = multi_slice ? 0x1f : 0x03; const bool single_slice = !multi_slice; const uint_fast8_t slice_count = multi_slice ? 8 : 1; @@ -166,7 +167,6 @@ void sgpio_configure( const bool input_slice = (i == 0) && (transceiver_mode == TRANSCEIVER_MODE_RX); const uint_fast8_t concat_order = (input_slice || single_slice) ? 0 : 3; const uint_fast8_t concat_enable = (input_slice || single_slice) ? 0 : 1; - const uint_fast8_t pos = multi_slice ? 0x1f : 0x03; SGPIO_MUX_CFG(slice_index) = SGPIO_MUX_CFG_CONCAT_ORDER(concat_order) From 8d14de21ce0d502daaa42c7ecee37a153a64ce06 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 12 Oct 2012 09:46:49 -0700 Subject: [PATCH 11/20] Fixed prior commit, where I lost the switch between endpoints based on RX or TX mode. --- firmware/usb_performance/usb_performance.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index 2766981d..376863b8 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -312,13 +312,21 @@ int main(void) { while( usb_bulk_buffer_offset < 16384 ); // Set up IN transfer of buffer 0. - usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[0]); + usb_endpoint_schedule_no_int( + (transceiver_mode == TRANSCEIVER_MODE_RX) + ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, + &usb_td_bulk[0] + ); // Wait until buffer 1 is transmitted/received. while( usb_bulk_buffer_offset >= 16384 ); // Set up IN transfer of buffer 1. - usb_endpoint_schedule_no_int(&usb_endpoint_bulk_in, &usb_td_bulk[1]); + usb_endpoint_schedule_no_int( + (transceiver_mode == TRANSCEIVER_MODE_RX) + ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, + &usb_td_bulk[1] + ); } return 0; From f4b6f08500bd5984f42d975686baa1a90adcd851 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 13 Oct 2012 11:06:39 -0700 Subject: [PATCH 12/20] Fixed incorrect field with for MAX2837 VGAgain_SPI_EN field. For boards that have no B7:B1 connections, this could prove extra problematic...and for boards that do, but aren't driving those pins from the LPC. --- firmware/common/max2837_regs.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/max2837_regs.def b/firmware/common/max2837_regs.def index 96291866..097be4f7 100644 --- a/firmware/common/max2837_regs.def +++ b/firmware/common/max2837_regs.def @@ -133,7 +133,7 @@ __MREG__(MAX2837_LPF_MODE_SEL,6,9,1) // set to enable mode in reg 2 ModeCtrl /* REG 8 */ __MREG__(MAX2837_LNAgain_SPI_EN,8,0,1) // set to override pin control of LNA -__MREG__(MAX2837_VGAgain_SPI_EN,8,1,0) // set to override pin control of VGA +__MREG__(MAX2837_VGAgain_SPI_EN,8,1,1) // set to override pin control of VGA __MREG__(MAX2837_EN_Bias_Trim,8,2,1) // route bias current to bondpad __MREG__(MAX2837_BIAS_TRIM_SPI,8,7,3) // down=00000, up=11111, nom=10000 __MREG__(MAX2837_BIAS_TRIM_CNTRL,8,8,1) // enable BIAS_TRIM_SPI value From 168c92a3d0080a957d17288654b16d7dc407ea45 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 13 Oct 2012 11:07:17 -0700 Subject: [PATCH 13/20] Now that RxVGA gain control is working correctly, gain needs to be backed WAAAY off to get a usable capture in a fairly noisy 2.4GHz environment. --- firmware/common/max2837.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 633fbca1..8ad9dadf 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -110,7 +110,7 @@ void max2837_setup(void) set_MAX2837_LNAgain_SPI_EN(1); set_MAX2837_LNAgain(MAX2837_LNAgain_MAX); /* maximum gain */ set_MAX2837_VGAgain_SPI_EN(1); - set_MAX2837_VGA(0x00); /* minimum attenuation */ + set_MAX2837_VGA(0x18); /* reasonable gain for noisy 2.4GHz environment */ /* maximum rx output common-mode voltage */ set_MAX2837_BUFF_VCM(MAX2837_BUFF_VCM_1_25); From 57866227bfd1629444a8c3e471a8564c1a9f4e51 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 13 Oct 2012 11:37:54 -0700 Subject: [PATCH 14/20] Remove weird LDSCRIPT that isn't necessary now. Change .bin generation to include only ROM-able sections. TODO: Is there a better way to do the objcopy? It'd be great to put everything in the "rom" region into the .bin, instead of having to list out -j section for each of the sections that go to ROM. --- firmware/common/LPC4330_M4_ram_only.ld | 38 -------------------------- firmware/common/Makefile_inc.mk | 2 +- firmware/usb_performance/Makefile | 1 - 3 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 firmware/common/LPC4330_M4_ram_only.ld diff --git a/firmware/common/LPC4330_M4_ram_only.ld b/firmware/common/LPC4330_M4_ram_only.ld deleted file mode 100644 index 4149fbd7..00000000 --- a/firmware/common/LPC4330_M4_ram_only.ld +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012 Michael Ossmann - * Copyright 2012 Jared Boone - * - * 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. - */ - -/* Linker script for HackRF Jellybean (LPC4330, 1M SPI flash, 264K SRAM). */ - -MEMORY -{ - ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 128K - ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 72K - ram_ahb1 (rwx) : ORIGIN = 0x20000000, LENGTH = 16K - /* Removed 32K of AHB SRAM for USB buffer. Straddles two blocks of RAM - * to get performance benefit of having two USB buffers addressable - * simultaneously (on two different buses of the AHB multilayer matrix) - */ - ram_ahb2 (rwx) : ORIGIN = 0x2000C000, LENGTH = 16K -} - -/* Include the common ld script. */ -INCLUDE libopencm3_lpc43xx_ram_only.ld diff --git a/firmware/common/Makefile_inc.mk b/firmware/common/Makefile_inc.mk index 8ea2f6be..58b9588d 100644 --- a/firmware/common/Makefile_inc.mk +++ b/firmware/common/Makefile_inc.mk @@ -80,7 +80,7 @@ flash: $(BINARY).flash %.bin: %.elf @#printf " OBJCOPY $(*).bin\n" - $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin + $(Q)$(OBJCOPY) -Obinary -j .text -j .ARM.exidx $(*).elf $(*).bin %.hex: %.elf @#printf " OBJCOPY $(*).hex\n" diff --git a/firmware/usb_performance/Makefile b/firmware/usb_performance/Makefile index 7222a2f4..cdde8dd1 100644 --- a/firmware/usb_performance/Makefile +++ b/firmware/usb_performance/Makefile @@ -35,5 +35,4 @@ SRC = $(BINARY).c \ ../common/max5864.c \ ../common/rffc5071.c -LDSCRIPT = ../common/LPC4330_M4_ram_only.ld include ../common/Makefile_inc.mk From 4cf0ba236d5f41028a5b526fdb875b1ff1de72cd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 13 Oct 2012 12:29:03 -0700 Subject: [PATCH 15/20] Extended common Makefile to include targets for DFU file generation and programming. --- firmware/common/Makefile_inc.mk | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/firmware/common/Makefile_inc.mk b/firmware/common/Makefile_inc.mk index 58b9588d..891495c0 100644 --- a/firmware/common/Makefile_inc.mk +++ b/firmware/common/Makefile_inc.mk @@ -75,9 +75,20 @@ all: images images: $(BINARY).images flash: $(BINARY).flash +program: $(BINARY).dfu + $(Q)dfu-util --device 1fc9:000c --alt 0 --download $(BINARY).dfu + %.images: %.bin %.hex %.srec %.list @#echo "*** $* images generated ***" +%.dfu: %.bin + $(Q)rm -f _tmp.dfu _header.bin + $(Q)cp $(*).bin _tmp.dfu + $(Q)dfu-suffix --vid=0x1fc9 --pid=0x000c --did=0x0 -s 0 -a _tmp.dfu + $(Q)python -c "import os.path; import struct; print('0000000: da ff ' + ' '.join(map(lambda s: '%02x' % ord(s), struct.pack(' _header.bin + $(Q)cat _header.bin _tmp.dfu >$(*).dfu + $(Q)rm -f _tmp.dfu _header.bin + %.bin: %.elf @#printf " OBJCOPY $(*).bin\n" $(Q)$(OBJCOPY) -Obinary -j .text -j .ARM.exidx $(*).elf $(*).bin @@ -107,6 +118,8 @@ clean: $(Q)rm -f *.d $(Q)rm -f *.elf $(Q)rm -f *.bin + $(Q)rm -f *.dfu + $(Q)rm -f _tmp.dfu _header.bin $(Q)rm -f *.hex $(Q)rm -f *.srec $(Q)rm -f *.list From d398cfcc1df723ef2e2bad6e171ccda992805eb9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 13 Oct 2012 16:58:22 -0700 Subject: [PATCH 16/20] Use new ssp_transfer() function instead of ssp_write(). Implement max2837_spi_read(). --- firmware/common/max2837.c | 7 +++---- firmware/common/max5864.c | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 8ad9dadf..464aa8b3 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -121,10 +121,9 @@ void max2837_setup(void) /* SPI register read. */ uint16_t max2837_spi_read(uint8_t r) { gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); - // FIXME: Unimplemented. - r=r; + const uint16_t value = ssp_transfer(SSP1_NUM, (uint16_t)((1 << 15) | (r << 10))); gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); - return 0; + return value & 0x3ff; } /* SPI register write */ @@ -137,7 +136,7 @@ void max2837_spi_write(uint8_t r, uint16_t v) { LOG("0x%03x -> reg%d\n", v, r); #else gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); - ssp_write(SSP1_NUM, (uint16_t)((r << 10) | (v & 0x3ff))); + ssp_transfer(SSP1_NUM, (uint16_t)((r << 10) | (v & 0x3ff))); gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); #endif } diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index a0f5dcff..094ed700 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -29,7 +29,7 @@ void max5864_spi_write(uint_fast8_t value) { gpio_clear(PORT_AD_CS, PIN_AD_CS); - ssp_write(SSP1_NUM, value); + ssp_transfer(SSP1_NUM, value); gpio_set(PORT_AD_CS, PIN_AD_CS); } From 7e34950b24d7e6bb75c03c90883546acbe94ad60 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 13 Oct 2012 17:01:42 -0700 Subject: [PATCH 17/20] Relocate compiler #defines for PACKED, ALIGNED, SECTION. --- firmware/usb_performance/usb.h | 3 --- firmware/usb_performance/usb_type.h | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/firmware/usb_performance/usb.h b/firmware/usb_performance/usb.h index 7b9c9390..a2ab9fb1 100644 --- a/firmware/usb_performance/usb.h +++ b/firmware/usb_performance/usb.h @@ -28,9 +28,6 @@ #include "usb_type.h" -#define ATTR_ALIGNED(x) __attribute__ ((aligned(x))) -#define ATTR_SECTION(x) __attribute__ ((section(x))) - extern bool usb_set_configuration( usb_device_t* const device, const uint_fast8_t configuration_number diff --git a/firmware/usb_performance/usb_type.h b/firmware/usb_performance/usb_type.h index 54287fd5..1bfb3205 100644 --- a/firmware/usb_performance/usb_type.h +++ b/firmware/usb_performance/usb_type.h @@ -25,6 +25,11 @@ #include #include +// TODO: Move this to some common compiler-tricks location. +#define ATTR_PACKED __attribute__((packed)) +#define ATTR_ALIGNED(x) __attribute__ ((aligned(x))) +#define ATTR_SECTION(x) __attribute__ ((section(x))) + typedef struct { uint8_t request_type; uint8_t request; From 048feb131652ad33b322fa9e7a70e06dee05cb1b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 13 Oct 2012 17:02:55 -0700 Subject: [PATCH 18/20] Miscellaneous USB notes and naming clean-up. --- firmware/usb_performance/usb.h | 2 ++ firmware/usb_performance/usb_request.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/firmware/usb_performance/usb.h b/firmware/usb_performance/usb.h index a2ab9fb1..ccaa9184 100644 --- a/firmware/usb_performance/usb.h +++ b/firmware/usb_performance/usb.h @@ -28,6 +28,8 @@ #include "usb_type.h" +// TODO: This is a lame move, requiring an extern to be defined to complete +// the interface between this API and the application. extern bool usb_set_configuration( usb_device_t* const device, const uint_fast8_t configuration_number diff --git a/firmware/usb_performance/usb_request.h b/firmware/usb_performance/usb_request.h index a637924f..2d32bcea 100644 --- a/firmware/usb_performance/usb_request.h +++ b/firmware/usb_performance/usb_request.h @@ -38,7 +38,7 @@ typedef enum { } usb_transfer_stage_t; typedef void (*usb_request_handler_fn)( - usb_endpoint_t* const response, + usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage ); From 3c17bad7432c732d5b822cc31c5a041391449fd2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 13 Oct 2012 17:03:28 -0700 Subject: [PATCH 19/20] Stall USB endpoint if control request is not handled. --- firmware/usb_performance/usb_request.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/firmware/usb_performance/usb_request.c b/firmware/usb_performance/usb_request.c index df6ae427..bfa4ea75 100644 --- a/firmware/usb_performance/usb_request.c +++ b/firmware/usb_performance/usb_request.c @@ -19,6 +19,7 @@ * Boston, MA 02110-1301, USA. */ +#include "usb.h" #include "usb_request.h" #include @@ -49,6 +50,9 @@ static void usb_request( if( handler ) { handler(endpoint, stage); + } else { + // USB 2.0 section 9.2.7 "Request Error" + usb_endpoint_stall(endpoint); } } From f32c6b34caef56e6bc84fbccfb5ce24832baafa7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 13 Oct 2012 17:06:24 -0700 Subject: [PATCH 20/20] Create unions in usb_setup_t so that value, index, and length can be read as words, not just high/low bytes. --- .../usb_performance/usb_standard_request.c | 4 +-- firmware/usb_performance/usb_type.h | 29 ++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/firmware/usb_performance/usb_standard_request.c b/firmware/usb_performance/usb_standard_request.c index 1b42bd5e..286d783b 100644 --- a/firmware/usb_performance/usb_standard_request.c +++ b/firmware/usb_performance/usb_standard_request.c @@ -67,7 +67,7 @@ static void usb_send_descriptor( usb_endpoint_t* const endpoint, uint8_t* const descriptor_data ) { - const uint32_t setup_length = (endpoint->setup.length_h << 8) | endpoint->setup.length_l; + const uint32_t setup_length = endpoint->setup.length; uint32_t descriptor_length = descriptor_data[0]; if( descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION ) { descriptor_length = (descriptor_data[3] << 8) | descriptor_data[2]; @@ -221,7 +221,7 @@ static void usb_standard_request_set_configuration( static void usb_standard_request_get_configuration_setup( usb_endpoint_t* const endpoint ) { - if( (endpoint->setup.length_h == 0) && (endpoint->setup.length_l == 1) ) { + if( endpoint->setup.length == 1 ) { endpoint->buffer[0] = 0; if( endpoint->device->configuration ) { endpoint->buffer[0] = endpoint->device->configuration->number; diff --git a/firmware/usb_performance/usb_type.h b/firmware/usb_performance/usb_type.h index 1bfb3205..fed3172b 100644 --- a/firmware/usb_performance/usb_type.h +++ b/firmware/usb_performance/usb_type.h @@ -30,15 +30,30 @@ #define ATTR_ALIGNED(x) __attribute__ ((aligned(x))) #define ATTR_SECTION(x) __attribute__ ((section(x))) -typedef struct { +typedef struct ATTR_PACKED { uint8_t request_type; uint8_t request; - uint8_t value_l; - uint8_t value_h; - uint8_t index_l; - uint8_t index_h; - uint8_t length_l; - uint8_t length_h; + union { + struct { + uint8_t value_l; + uint8_t value_h; + }; + uint16_t value; + }; + union { + struct { + uint8_t index_l; + uint8_t index_h; + }; + uint16_t index; + }; + union { + struct { + uint8_t length_l; + uint8_t length_h; + }; + uint16_t length; + }; } usb_setup_t; typedef enum {