From bd2fab0a12da40a3ae3f7e02603401c2b55c4692 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 14 Oct 2012 12:37:16 -0700 Subject: [PATCH] Move USB SET_CONFIGURATION-time initialization of SGPIO and bulk endpoints into a separate function. Initialize transceiver mode at SET_CONFIGURATION time. Provide switching of transceiver mode via vendor request. Provide read/write access to MAX2837 registers via vendor requests. Python utility to dump MAX2837 registers. Python utility to switch transceiver RX/TX mode. --- firmware/usb_performance/usb_performance.c | 155 ++++++++++++++++----- host/usb_test/max2837_dump.py | 39 ++++++ host/usb_test/set_transceiver_mode.py | 39 ++++++ 3 files changed, 202 insertions(+), 31 deletions(-) create mode 100755 host/usb_test/max2837_dump.py create mode 100755 host/usb_test/set_transceiver_mode.py diff --git a/firmware/usb_performance/usb_performance.c b/firmware/usb_performance/usb_performance.c index ad8a398b..6d9e7145 100644 --- a/firmware/usb_performance/usb_performance.c +++ b/firmware/usb_performance/usb_performance.c @@ -158,10 +158,132 @@ usb_endpoint_t usb_endpoint_bulk_out = { .transfer_complete = 0, }; +void baseband_streaming_disable() { + sgpio_cpld_stream_disable(); + + nvic_disable_irq(NVIC_M4_SGPIO_IRQ); + + usb_endpoint_disable(&usb_endpoint_bulk_in); + usb_endpoint_disable(&usb_endpoint_bulk_out); +} + +void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { + baseband_streaming_disable(); + + transceiver_mode = new_transceiver_mode; + + usb_init_buffers_bulk(); + + if( transceiver_mode == TRANSCEIVER_MODE_RX ) { + gpio_clear(PORT_LED1_3, PIN_LED3); + usb_endpoint_init(&usb_endpoint_bulk_in); + } else { + gpio_set(PORT_LED1_3, PIN_LED3); + usb_endpoint_init(&usb_endpoint_bulk_out); + } + + sgpio_configure(transceiver_mode, true); + + nvic_set_priority(NVIC_M4_SGPIO_IRQ, 0); + nvic_enable_irq(NVIC_M4_SGPIO_IRQ); + SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A); + + sgpio_cpld_stream_enable(); +} + +bool usb_vendor_request_set_transceiver_mode( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + if( stage == USB_TRANSFER_STAGE_SETUP ) { + switch( endpoint->setup.value ) { + case 1: + set_transceiver_mode(TRANSCEIVER_MODE_RX); + usb_endpoint_schedule_ack(endpoint->in); + return true; + + case 2: + set_transceiver_mode(TRANSCEIVER_MODE_TX); + usb_endpoint_schedule_ack(endpoint->in); + return true; + + default: + return false; + } + } else { + return true; + } +} + +bool usb_vendor_request_write_max2837( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + if( stage == USB_TRANSFER_STAGE_SETUP ) { + if( endpoint->setup.index < 32 ) { + if( endpoint->setup.value < 0x3ff ) { + max2837_reg_write(endpoint->setup.index, endpoint->setup.value); + usb_endpoint_schedule_ack(endpoint->in); + return true; + } + } + return false; + } else { + return true; + } +} + +bool usb_vendor_request_read_max2837( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + if( stage == USB_TRANSFER_STAGE_SETUP ) { + if( endpoint->setup.index < 32 ) { + const uint16_t value = max2837_reg_read(endpoint->setup.index); + endpoint->buffer[0] = value >> 8; + endpoint->buffer[1] = value & 0xff; + usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 2); + usb_endpoint_schedule_ack(endpoint->out); + return true; + } + return false; + } else { + return true; + } +} + +void usb_vendor_request( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage +) { + bool success = false; + + switch(endpoint->setup.request) { + case 1: + success = usb_vendor_request_set_transceiver_mode(endpoint, stage); + break; + + case 2: + success = usb_vendor_request_write_max2837(endpoint, stage); + break; + + case 3: + success = usb_vendor_request_read_max2837(endpoint, stage); + break; + + default: + break; + } + + if( success != true ) { + usb_endpoint_stall(endpoint); + } +} + const usb_request_handlers_t usb_request_handlers = { .standard = usb_standard_request, .class = 0, - .vendor = 0, + .vendor = usb_vendor_request, .reserved = 0, }; @@ -197,36 +319,7 @@ bool usb_set_configuration( if( new_configuration != device->configuration ) { // Configuration changed. device->configuration = new_configuration; - - // TODO: This is lame. There should be a way to link stuff together so - // that changing the configuration will initialize the related - // endpoints. No hard-coding crap like this! Then, when there's no more - // hard-coding, this whole function can move into a shared/reusable - // library. - if( device->configuration && (device->configuration->number == 1) ) { - if( transceiver_mode == TRANSCEIVER_MODE_RX ) { - sgpio_configure(transceiver_mode, true); - usb_endpoint_init(&usb_endpoint_bulk_in); - } else { - sgpio_configure(transceiver_mode, true); - usb_endpoint_init(&usb_endpoint_bulk_out); - } - - usb_init_buffers_bulk(); - - nvic_set_priority(NVIC_M4_SGPIO_IRQ, 0); - nvic_enable_irq(NVIC_M4_SGPIO_IRQ); - SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A); - - sgpio_cpld_stream_enable(); - } else { - sgpio_cpld_stream_disable(); - - nvic_disable_irq(NVIC_M4_SGPIO_IRQ); - - usb_endpoint_disable(&usb_endpoint_bulk_in); - usb_endpoint_disable(&usb_endpoint_bulk_out); - } + set_transceiver_mode(transceiver_mode); if( device->configuration ) { gpio_set(PORT_LED1_3, PIN_LED1); diff --git a/host/usb_test/max2837_dump.py b/host/usb_test/max2837_dump.py new file mode 100755 index 00000000..1bda15fc --- /dev/null +++ b/host/usb_test/max2837_dump.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# +# 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. +# + +import usb +import struct + +device = usb.core.find(idVendor=0x1d50, idProduct=0x604b) +device.set_configuration() + +def read_max2837_register(register_number): + return struct.unpack('>H', device.ctrl_transfer(0xC0, 3, 0, register_number, 2))[0] + +def write_max2837_register(register_number, value): + device.ctrl_transfer(0x40, 2, value, register_number) + +def dump_max2837(): + for i in range(32): + print('%2d: %03x' % (i, read_max2837_register(i))) + +dump_max2837() diff --git a/host/usb_test/set_transceiver_mode.py b/host/usb_test/set_transceiver_mode.py new file mode 100755 index 00000000..479b86b2 --- /dev/null +++ b/host/usb_test/set_transceiver_mode.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# +# 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. +# + +import sys +import usb + +device = usb.core.find(idVendor=0x1d50, idProduct=0x604b) +device.set_configuration() + +def set_rx(): + device.ctrl_transfer(0x40, 1, 1, 0) + +def set_tx(): + device.ctrl_transfer(0x40, 1, 2, 0) + +if len(sys.argv) == 2: + if sys.argv[1] == 'tx': + set_tx() + elif sys.argv[1] == 'rx': + set_rx()