Skip to content

Commit

Permalink
Hardware (CPLD-based) synchronisation
Browse files Browse the repository at this point in the history
=======================================

This commit allows to synchronise multiple HackRFs with a synchronisation error **below 1 sampling period**

> WARNING: Use this at your own risk. If you don't know what you are doing you may damage your HackRF.
> The author takes no responsability for potential damages

Usage example: synchronise two HackRFs
======================================
1. Chose the master HackRF which will send the synchronisation pulse (HackRF0). HackRF1 will represent the slave hackrf.
2. Retreive the serial number of both HackRFs using `hackrf_info`
3. Use a wire to connect `SYNC_CMD` of HackRF0 to `SYNC_IN` of HackRF0 and HackRF1
4. Run `hackrf_transfer` with the argument `-H 1` to enable hardware synchronisation:
    ```
    $ hackrf_tranfer ... -r rec1.bin -d HackRF1_serial -H 1 | hackrf_transfer ... -r rec0.bin -d HackRF0_serial -H 1
    ```
rec0.bin and rec1.bin will have a time offset below 1 sampling period.
The 1PPS output of GNSS receivers can be used to synchronise HackRFs even if they are far from each other.
>DON'T APPLY INCOMPATIBLE VOLTAGE LEVELS TO THE CPLD PINS

Signal | Header |Pin | Description
-------|--------|----|------------
`SYNC_IN` | P28 | 16 | Synchronisation pulse input
`SYNC_CMD` | P28 | 15 | Synchronisation pulse output

Note:
=====
I had to remove CPLD-based decimation to use a GPIO for enabling hardware.

More info:
==========
[M. Bartolucci, J. A. Del Peral-Rosado, R. Estatuet-Castillo, J. A. Garcia-Molina, M. Crisci and G. E. Corazza, "Synchronisation of low-cost open source SDRs for navigation applications," 2016 8th ESA Workshop on Satellite Navigation Technologies and European Workshop on GNSS Signals and Signal Processing (NAVITEC), Noordwijk, 2016, pp. 1-7.](http://ieeexplore.ieee.org/document/7849328/)

[Alternative link](http://spcomnav.uab.es/docs/conferences/Bartolucci_NAVITEC_2016.pdf)
  • Loading branch information
Marco Bartolucci authored and Marco Bartolucci committed May 16, 2017
1 parent 747d8e2 commit 533f9ee
Show file tree
Hide file tree
Showing 12 changed files with 48 additions and 87 deletions.
31 changes: 11 additions & 20 deletions firmware/common/hackrf_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,12 @@ static struct gpio_t gpio_cpld_tms = GPIO(3, 1);
static struct gpio_t gpio_cpld_tdi = GPIO(3, 4);
#endif

static struct gpio_t gpio_rx_decimation[3] = {
GPIO(5, 12),
GPIO(5, 13),
GPIO(5, 14),
};
//static struct gpio_t gpio_rx_decimation[3] = {
// GPIO(5, 12),
// GPIO(5, 13),
// GPIO(5, 14),
//};
static struct gpio_t gpio_hw_sync_enable = GPIO(5,12);
static struct gpio_t gpio_rx_q_invert = GPIO(0, 13);

i2c_bus_t i2c0 = {
Expand Down Expand Up @@ -242,11 +243,7 @@ w25q80bv_driver_t spi_flash = {

sgpio_config_t sgpio_config = {
.gpio_rx_q_invert = &gpio_rx_q_invert,
.gpio_rx_decimation = {
&gpio_rx_decimation[0],
&gpio_rx_decimation[1],
&gpio_rx_decimation[2],
},
.gpio_hw_sync_enable = &gpio_hw_sync_enable,
.slice_mode_multislice = true,
};

Expand Down Expand Up @@ -824,11 +821,6 @@ void pin_setup(void) {
scu_pinmux(SCU_PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);

//gpio_input(&gpio_sync_in_a);
//gpio_input(&gpio_sync_in_b);

//gpio_output(&gpio_sync_out_a);
//gpio_output(&gpio_sync_out_b);
#endif

#ifdef RAD1O
Expand All @@ -841,11 +833,6 @@ void pin_setup(void) {
scu_pinmux(SCU_PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);

//gpio_input(&gpio_sync_in_a);
//gpio_input(&gpio_sync_in_b);

//gpio_output(&gpio_sync_out_a);
//gpio_output(&gpio_sync_out_b);
#endif

/* enable input on SCL and SDA pins */
Expand Down Expand Up @@ -902,3 +889,7 @@ void led_off(const led_t led) {
void led_toggle(const led_t led) {
gpio_toggle(&gpio_led[led]);
}

void hw_sync_enable(const hw_sync_mode_t hw_sync_mode){
gpio_write(&gpio_hw_sync_enable, hw_sync_mode==1);
}
6 changes: 1 addition & 5 deletions firmware/common/hackrf_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,7 @@ void led_on(const led_t led);
void led_off(const led_t led);
void led_toggle(const led_t led);

void hw_sync_syn();
void hw_sync_stop();
void hw_sync_ack();
bool hw_sync_ready();
void hw_sync_copy_state();
void hw_sync_enable(const hw_sync_mode_t hw_sync_mode);


#ifdef __cplusplus
Expand Down
21 changes: 2 additions & 19 deletions firmware/common/sgpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,11 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) {
scu_pinmux(SCU_PINMUX_SGPIO14, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[13] */
scu_pinmux(SCU_PINMUX_SGPIO15, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[14] */

sgpio_cpld_stream_rx_set_decimation(config, 1);
sgpio_cpld_stream_rx_set_q_invert(config, 0);
hw_sync_enable(0);

gpio_output(config->gpio_rx_q_invert);
gpio_output(config->gpio_rx_decimation[0]);
gpio_output(config->gpio_rx_decimation[1]);
gpio_output(config->gpio_rx_decimation[2]);
gpio_output(config->gpio_hw_sync_enable);
}

void sgpio_set_slice_mode(
Expand Down Expand Up @@ -258,21 +256,6 @@ bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config) {
return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */
}

bool sgpio_cpld_stream_rx_set_decimation(sgpio_config_t* const config, const uint_fast8_t n) {
/* CPLD interface is three bits, SGPIO[15:13]:
* 111: decimate by 1 (skip_n=0, skip no samples)
* 110: decimate by 2 (skip_n=1, skip every other sample)
* 101: decimate by 3 (skip_n=2, skip two of three samples)
* ...
* 000: decimate by 8 (skip_n=7, skip seven of eight samples)
*/
const uint_fast8_t skip_n = n - 1;
gpio_write(config->gpio_rx_decimation[0], (skip_n & 1) == 0);
gpio_write(config->gpio_rx_decimation[1], (skip_n & 2) == 0);
gpio_write(config->gpio_rx_decimation[2], (skip_n & 4) == 0);

return (skip_n < 8);
}

#ifdef RAD1O
/* The rad1o hardware has a bug which makes it
Expand Down
2 changes: 1 addition & 1 deletion firmware/common/sgpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ typedef enum {

typedef struct sgpio_config_t {
gpio_t gpio_rx_q_invert;
gpio_t gpio_rx_decimation[3];
gpio_t gpio_hw_sync_enable;
bool slice_mode_multislice;
} sgpio_config_t;

Expand Down
12 changes: 0 additions & 12 deletions firmware/cpld/sgpio_if/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,6 @@ RF codec.
CPLD-based triggered capture
============================

Code related to the paper:

[M. Bartolucci, J. A. del Peral-Rosado, R. Estatuet-Castillo, J. A. Garcia-Molina, M. Crisci, G. E. Corazza, "Synchronisation of low-cost open source SDRs for navigation applications", Proc. 8th ESA Workshop on Satellite Navigation User Equipment Technologies (NAVITEC), Dec 16 2016](http://spcomnav.uab.es/docs/conferences/Bartolucci_NAVITEC_2016.pdf)

Please read the paper for hardware correction and additional details.

* If you don't want to build use `default_sync.xsvf` to flash the CPLD
* This is still a very rough implementation. Synchronization can't be disabled!

Requirements
============

To build this VHDL project and produce an SVF file for flashing the CPLD:

* Xilinx WebPACK 13.4 for Windows or Linux.
Expand Down
Binary file modified firmware/cpld/sgpio_if/default.xsvf
100644 → 100755
Binary file not shown.
Binary file removed firmware/cpld/sgpio_if/default_sync.xsvf
Binary file not shown.
40 changes: 20 additions & 20 deletions firmware/cpld/sgpio_if/top.jed
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Programmer Jedec Bit Map
Date Extracted: Mon May 15 12:52:29 2017
Date Extracted: Mon May 15 14:19:25 2017

QF25812*
QP100*
Expand Down Expand Up @@ -368,7 +368,7 @@ L012869 000101111001111101000000011*

Note Block 2 *
Note Block 2 ZIA *
L012896 1111111111111111*
L012896 1111111011100111*
L012912 1111111111111111*
L012928 1111111011110011*
L012944 1111111111111111*
Expand Down Expand Up @@ -410,17 +410,17 @@ L013504 1111111111111111*
L013520 1111111111111111*

Note Block 2 PLA AND array *
L013536 11110111110111011111111111111111111111111111111111111111111111111011111111111111*
L013616 11111011111011011111111111111111111111111111111111111111111111111011111111111111*
L013696 11110111111011111111111111110111111111111111111111111111111111111111111111111111*
L013776 11111011110111111111111111110111111111111111111111111111111111111111111111111111*
L013856 11111011111111111111111111111111111110111111111111111111111111111111111111111111*
L013936 11111011111111111111111101111111111110111111111111111111111111111111111111111111*
L014016 11111111111111111111111110111111111101111111111111111111111111111111111111111111*
L013536 10110111110111111111111111111111111111111111111111111111111111111011111111111111*
L013616 10111011111011111111111111111111111111111111111111111111111111111011111111111111*
L013696 11110111110111011111111111111111111111111111111111111111111111111011111111111111*
L013776 11111011111011011111111111111111111111111111111111111111111111111011111111111111*
L013856 11110111111011111111111111110111111111111111111111111111111111111111111111111111*
L013936 11111011110111111111111111110111111111111111111111111111111111111111111111111111*
L014016 11111011111111111111111111111111111110111111111111111111111111111111111111111111*
L014096 11111111111011111111111111111111111111111111111111111111111111111111111111111111*
L014176 11110111111111111111111110111111111111111111111111111111111111111111111111111111*
L014256 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L014336 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L014176 11111011111111111111111101111111111110111111111111111111111111111111111111111111*
L014256 11111111111111111111111110111111111101111111111111111111111111111111111111111111*
L014336 11110111111111111111111110111111111111111111111111111111111111111111111111111111*
L014416 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L014496 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L014576 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
Expand Down Expand Up @@ -472,13 +472,13 @@ L018016 0111111111111111*
L018032 0111111111111111*
L018048 0111111111111111*
L018064 0111111111111111*
L018080 1101011100111000*
L018096 1111110111111111*
L018112 1111110111111111*
L018080 0111111111111111*
L018096 0111111111111111*
L018112 1101011100111000*
L018128 1111111111111111*
L018144 1111110111111111*
L018160 1111111111111111*
L018176 1111111111111111*
L018160 1111110111111111*
L018176 1111110111111111*
L018192 1111111111111111*
L018208 1111111111111111*
L018224 1111111111111111*
Expand Down Expand Up @@ -528,7 +528,7 @@ L018896 1111111111111111*
Note Block 2 I/O Macrocell Configuration 27 bits *
N Aclk ClkOp Clk:2 ClkFreq R:2 P:2 RegMod:2 INz:2 FB:2 InReg St XorIn:2 RegCom Oe:4 Tm Slw Pu*
L018912 000101111001110100000000011*
L018939 000001111001111110011111100*
L018939 000001111000011100011111100*
L018966 000101111000011101001000111*
L018993 000001111001111110011111100*
L019020 000101111000011101001000111*
Expand Down Expand Up @@ -753,5 +753,5 @@ L025810 0*
Note I/O Bank 1 Vcco *
L025811 0*

C0C4E*
AACE
C0AA8*
AABC
3 changes: 2 additions & 1 deletion firmware/cpld/sgpio_if/top.ucf
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ NET "HOST_DATA<6>" LOC = "P61" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ;
NET "HOST_DATA<7>" LOC = "P77" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ;
NET "HOST_DIRECTION" LOC = "P71" | IOSTANDARD = LVCMOS33 ;
NET "HOST_DISABLE" LOC = "P76" | IOSTANDARD = LVCMOS33 ;
NET "HOST_Q_INVERT" LOC = "P70" | IOSTANDARD = LVCMOS33 ;
NET "HOST_Q_INVERT" LOC = "P70" | IOSTANDARD = LVCMOS33 ;
NET "HOST_SYNC_EN" LOC = "P90" | IOSTANDARD = LVCMOS33 ;
NET "HOST_SYNC" LOC = "P55" | IOSTANDARD = LVCMOS33;
NET "HOST_SYNC_CMD" LOC = "P56" | IOSTANDARD = LVCMOS33 | SLEW = SLOW ;

Expand Down
13 changes: 8 additions & 5 deletions firmware/cpld/sgpio_if/top.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ use UNISIM.vcomponents.all;
entity top is
Port(
HOST_DATA : inout std_logic_vector(7 downto 0);
HOST_CAPTURE : out std_logic;
HOST_CAPTURE : out std_logic;
HOST_SYNC_EN : in std_logic;
HOST_SYNC_CMD : out std_logic;
HOST_SYNC : in std_logic;
HOST_DISABLE : in std_logic;
Expand All @@ -56,7 +57,8 @@ architecture Behavioral of top is
signal transfer_direction_i : transfer_direction;

signal host_data_enable_i : std_logic;
signal host_data_capture_o : std_logic;
signal host_data_capture_o : std_logic;
signal host_sync_enable : std_logic := '0';
signal host_sync_o : std_logic := '0';
signal host_sync_i : std_logic := '0';
signal host_sync_latched : std_logic := '0';
Expand Down Expand Up @@ -94,7 +96,8 @@ begin
else (others => 'Z');
data_from_host_i <= HOST_DATA;

HOST_CAPTURE <= host_data_capture_o;
HOST_CAPTURE <= host_data_capture_o;
host_sync_enable <= HOST_SYNC_EN;
host_sync_i <= HOST_SYNC;
HOST_SYNC_CMD <= host_sync_o;

Expand Down Expand Up @@ -153,11 +156,11 @@ begin
if rising_edge(host_clk_i) then
if transfer_direction_i = to_dac then
if codec_clk_i = '1' then
host_data_capture_o <= host_data_enable_i and host_sync_latched;
host_data_capture_o <= host_data_enable_i and (host_sync_latched or not host_sync_enable);
end if;
else
if codec_clk_i = '0' then
host_data_capture_o <= host_data_enable_i and host_sync_latched;
host_data_capture_o <= host_data_enable_i and (host_sync_latched or not host_sync_enable);
end if;
end if;
end if;
Expand Down
5 changes: 2 additions & 3 deletions firmware/hackrf_usb/usb_api_transceiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,8 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) {
si5351c_activate_best_clock_source(&clock_gen);

if( _hw_sync_mode != HW_SYNC_MODE_OFF) {
hw_sync_enable();
}
hw_sync_enable(_hw_sync_mode);

baseband_streaming_enable(&sgpio_config);
}
}
Expand Down
2 changes: 1 addition & 1 deletion host/hackrf-tools/src/hackrf_transfer.c
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ int main(int argc, char** argv) {
}

if(hw_sync) {
fprintf(stderr, "call hackrf_set_hw_sync_mode(%d)\n", hw_sync);
fprintf(stderr, "call hackrf_set_hw_sync_mode(%d)\n", hw_sync_enable);
result = hackrf_set_hw_sync_mode(device, hw_sync_enable ? HW_SYNC_MODE_ON : HW_SYNC_MODE_OFF);
if( result != HACKRF_SUCCESS ) {
fprintf(stderr, "hackrf_set_hw_sync_mode() failed: %s (%d)\n", hackrf_error_name(result), result);
Expand Down

0 comments on commit 533f9ee

Please sign in to comment.