Merge pull request #21 from jboone/master
Transmit support, and various small code consolidations and fixes.
This commit is contained in:
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Michael Ossmann <mike@ossmann.com>
|
||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* 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
|
@ -75,12 +75,23 @@ 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('<H', os.path.getsize('$(*).bin') / 512 + 1))) + ' ff ff ff ff')" | xxd -g1 -r > _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 $(*).elf $(*).bin
|
||||
$(Q)$(OBJCOPY) -Obinary -j .text -j .ARM.exidx $(*).elf $(*).bin
|
||||
|
||||
%.hex: %.elf
|
||||
@#printf " OBJCOPY $(*).hex\n"
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
||||
@ -83,159 +89,61 @@ void sgpio_test_interface() {
|
||||
}
|
||||
}
|
||||
|
||||
void sgpio_configure_for_tx() {
|
||||
void sgpio_configure(
|
||||
const transceiver_mode_t transceiver_mode,
|
||||
const bool multi_slice
|
||||
) {
|
||||
// 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 =
|
||||
(1L << 11) | // direction
|
||||
(1L << 10); // disable
|
||||
(cpld_direction << 11)
|
||||
| (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: TX: data to CPLD
|
||||
(1L << 10) | // disable
|
||||
(0L << 9) | // capture
|
||||
(0L << 8) | // clock
|
||||
0xFF; // 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
|
||||
(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_for_rx_deep() {
|
||||
// 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)
|
||||
SGPIO_OUT_MUX_CFG_P_OE_CFG(0)
|
||||
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(output_multiplexing_mode)
|
||||
;
|
||||
}
|
||||
|
||||
const uint_fast8_t slice_indices[] = {
|
||||
@ -249,35 +157,46 @@ void sgpio_configure_for_rx_deep() {
|
||||
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;
|
||||
|
||||
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;
|
||||
for(uint_fast8_t i=0; i<slice_count; i++) {
|
||||
const uint_fast8_t slice_index = slice_indices[i];
|
||||
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;
|
||||
|
||||
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_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) = (0x1f << 8) | (0x1f << 0);
|
||||
SGPIO_REG(slice_index) = 0xFFFFFFFF; // Primary output data register
|
||||
SGPIO_REG_SS(slice_index) = 0xFFFFFFFF; // Shadow output data register
|
||||
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
|
||||
|
||||
slice_enable_mask |= (1 << slice_index);
|
||||
}
|
||||
@ -298,4 +217,4 @@ void sgpio_cpld_stream_disable() {
|
||||
|
||||
bool sgpio_cpld_stream_is_enabled() {
|
||||
return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0;
|
||||
}
|
||||
}
|
||||
|
@ -22,11 +22,14 @@
|
||||
#ifndef __SGPIO_H__
|
||||
#define __SGPIO_H__
|
||||
|
||||
#include <hackrf_core.h>
|
||||
|
||||
void sgpio_configure_pin_functions();
|
||||
void sgpio_test_interface();
|
||||
void sgpio_configure_for_tx();
|
||||
void sgpio_configure_for_rx();
|
||||
void sgpio_configure_for_rx_deep();
|
||||
void sgpio_configure(
|
||||
const transceiver_mode_t transceiver_mode,
|
||||
const bool multi_slice
|
||||
);
|
||||
void sgpio_cpld_stream_enable();
|
||||
void sgpio_cpld_stream_disable();
|
||||
bool sgpio_cpld_stream_is_enabled();
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include <sgpio.h>
|
||||
|
||||
void tx_test() {
|
||||
sgpio_configure_for_tx();
|
||||
sgpio_configure(TRANSCEIVER_MODE_TX, false);
|
||||
|
||||
// LSB goes out first, samples are 0x<Q1><I1><Q0><I0>
|
||||
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;
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <sgpio.h>
|
||||
|
||||
void tx_test() {
|
||||
sgpio_configure_for_tx();
|
||||
sgpio_configure(TRANSCEIVER_MODE_TX, false);
|
||||
|
||||
// LSB goes out first, samples are 0x<Q1><I1><Q0><I0>
|
||||
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;
|
||||
|
@ -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
|
||||
|
@ -28,9 +28,8 @@
|
||||
|
||||
#include "usb_type.h"
|
||||
|
||||
#define ATTR_ALIGNED(x) __attribute__ ((aligned(x)))
|
||||
#define ATTR_SECTION(x) __attribute__ ((section(x)))
|
||||
|
||||
// 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
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include "usb_descriptor.h"
|
||||
#include "usb_standard_request.h"
|
||||
|
||||
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;
|
||||
static const uint32_t usb_bulk_buffer_mask = 32768 - 1;
|
||||
@ -202,12 +204,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(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();
|
||||
|
||||
sgpio_configure_for_rx_deep();
|
||||
|
||||
nvic_set_priority(NVIC_M4_SGPIO_IRQ, 0);
|
||||
nvic_enable_irq(NVIC_M4_SGPIO_IRQ);
|
||||
@ -237,15 +242,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 +306,28 @@ 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]);
|
||||
}
|
||||
|
||||
while(true) {
|
||||
// Wait until buffer 0 is transmitted/received.
|
||||
while( usb_bulk_buffer_offset < 16384 );
|
||||
|
||||
// Set up IN transfer of buffer 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(
|
||||
(transceiver_mode == TRANSCEIVER_MODE_RX)
|
||||
? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out,
|
||||
&usb_td_bulk[1]
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_request.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -25,15 +25,35 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
// 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 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 {
|
||||
|
@ -21,13 +21,25 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libusb-1.0/libusb.h>
|
||||
|
||||
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 +60,27 @@ void write_callback(struct libusb_transfer* transfer) {
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if( argc != 2 ) {
|
||||
printf("Usage: usb_test <file to capture to>\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 +88,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_index<transfer_count; transfer_index++) {
|
||||
libusb_free_transfer(transfers[transfer_index]);
|
||||
}
|
||||
free(transfers);
|
||||
}
|
||||
|
||||
struct libusb_transfer** prepare_transfers(
|
||||
libusb_device_handle* const device,
|
||||
const uint_fast8_t endpoint_address,
|
||||
const uint32_t transfer_count,
|
||||
const uint32_t buffer_size,
|
||||
libusb_transfer_cb_fn callback
|
||||
) {
|
||||
struct libusb_transfer** const transfers = calloc(transfer_count, sizeof(struct libusb_transfer));
|
||||
if( transfers == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(uint32_t transfer_index=0; transfer_index<transfer_count; transfer_index++) {
|
||||
transfers[transfer_index] = libusb_alloc_transfer(0);
|
||||
if( transfers[transfer_index] == 0 ) {
|
||||
if( transfers[transfer_index] == NULL ) {
|
||||
free_transfers(transfers, transfer_count);
|
||||
printf("libusb_alloc_transfer() failed\n");
|
||||
return -6;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
libusb_fill_bulk_transfer(
|
||||
@ -108,23 +136,113 @@ int main(int argc, char** argv) {
|
||||
endpoint_address,
|
||||
(unsigned char*)malloc(buffer_size),
|
||||
buffer_size,
|
||||
&write_callback,
|
||||
callback,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
if( transfers[transfer_index]->buffer == 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;
|
||||
}
|
||||
|
||||
static void usage() {
|
||||
printf("Usage:\n");
|
||||
printf("\tGo fish.\n");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int opt;
|
||||
bool receive = false;
|
||||
bool transmit = false;
|
||||
const char* path = NULL;
|
||||
|
||||
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;
|
||||
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 +276,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;
|
||||
|
Reference in New Issue
Block a user