Merge pull request #329 from schneider42/rad1o

rad1o support
This commit is contained in:
Michael Ossmann
2017-02-14 21:30:48 -07:00
committed by GitHub
28 changed files with 1285 additions and 100 deletions

View File

@ -37,6 +37,7 @@ script:
- cd ../..
- mkdir firmware/build-hackrf-one
- mkdir firmware/build-jawbreaker
- mkdir firmware/build-rad1o
- cd firmware/libopencm3
- make
- cd ../build-hackrf-one
@ -45,6 +46,9 @@ script:
- cd ../build-jawbreaker
- cmake -DBOARD=JAWBREAKER ..
- make
- cd ../build-rad1o
- cmake -DBOARD=RAD1O ..
- make
addons:
apt:

View File

@ -32,6 +32,7 @@ $ make
$ hackrf_spiflash -w hackrf_usb.bin
If you have a Jawbreaker, add -DBOARD=JAWBREAKER to the cmake command.
If you have a rad1o, use -DBOARD=RAD1O instead.
It is possible to use a USB Device Firmware Upgrade (DFU) method to load

View File

@ -0,0 +1,17 @@
#ifndef HACKRF_UI_H
#define HACKRF_UI_H
#include <rf_path.h>
#include <stdint.h>
void hackrf_ui_init(void) __attribute__((weak));
void hackrf_ui_setFrequency(uint64_t _freq) __attribute__((weak));
void hackrf_ui_setSampleRate(uint32_t _sample_rate) __attribute__((weak));
void hackrf_ui_setDirection(const rf_path_direction_t _direction) __attribute__((weak));
void hackrf_ui_setFilterBW(uint32_t bw) __attribute__((weak));
void hackrf_ui_setLNAPower(bool _lna_on) __attribute__((weak));
void hackrf_ui_setBBLNAGain(const uint32_t gain_db) __attribute__((weak));
void hackrf_ui_setBBVGAGain(const uint32_t gain_db) __attribute__((weak));
void hackrf_ui_setBBTXVGAGain(const uint32_t gain_db) __attribute__((weak));
#endif

View File

@ -22,14 +22,13 @@
*/
#include "hackrf_core.h"
#include "hackrf-ui.h"
#include "si5351c.h"
#include "spi_ssp.h"
#include "max2837.h"
#include "max2837_target.h"
#include "max5864.h"
#include "max5864_target.h"
#include "rffc5071.h"
#include "rffc5071_spi.h"
#include "w25q80bv.h"
#include "w25q80bv_target.h"
#include "i2c_bus.h"
@ -47,10 +46,13 @@
#define WAIT_CPU_CLOCK_INIT_DELAY (10000)
/* GPIO Output PinMux */
static struct gpio_t gpio_led[3] = {
static struct gpio_t gpio_led[] = {
GPIO(2, 1),
GPIO(2, 2),
GPIO(2, 8)
GPIO(2, 8),
#ifdef RAD1O
GPIO(5, 26),
#endif
};
static struct gpio_t gpio_1v8_enable = GPIO(3, 6);
@ -74,19 +76,7 @@ static struct gpio_t gpio_max2837_b7 = GPIO(2, 15);
/* MAX5864 SPI chip select (AD_CS) GPIO PinMux */
static struct gpio_t gpio_max5864_select = GPIO(2, 7);
/* RFFC5071 GPIO serial interface PinMux */
#ifdef JELLYBEAN
static struct gpio_t gpio_rffc5072_select = GPIO(3, 8);
static struct gpio_t gpio_rffc5072_clock = GPIO(3, 9);
static struct gpio_t gpio_rffc5072_data = GPIO(3, 10);
static struct gpio_t gpio_rffc5072_reset = GPIO(3, 11);
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
static struct gpio_t gpio_rffc5072_select = GPIO(2, 13);
static struct gpio_t gpio_rffc5072_clock = GPIO(5, 6);
static struct gpio_t gpio_rffc5072_data = GPIO(3, 3);
static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14);
#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O)
/*
static struct gpio_t gpio_sync_in_a = GPIO(3, 8);
static struct gpio_t gpio_sync_in_b = GPIO(3, 9);
@ -108,6 +98,9 @@ static struct gpio_t gpio_sync_out_b = GPIO(3, 9);
#ifdef HACKRF_ONE
static struct gpio_t gpio_vaa_disable = GPIO(2, 9);
#endif
#ifdef RAD1O
static struct gpio_t gpio_vaa_enable = GPIO(2, 9);
#endif
static struct gpio_t gpio_w25q80bv_hold = GPIO(1, 14);
static struct gpio_t gpio_w25q80bv_wp = GPIO(1, 15);
@ -129,6 +122,20 @@ static struct gpio_t gpio_amp_bypass = GPIO(0, 14);
static struct gpio_t gpio_rx_amp = GPIO(1, 11);
static struct gpio_t gpio_no_rx_amp_pwr = GPIO(1, 12);
#endif
#ifdef RAD1O
static struct gpio_t gpio_tx_rx_n = GPIO(0, 11);
static struct gpio_t gpio_tx_rx = GPIO(0, 14);
static struct gpio_t gpio_by_mix = GPIO(1, 12);
static struct gpio_t gpio_by_mix_n = GPIO(2, 10);
static struct gpio_t gpio_by_amp = GPIO(1, 0);
static struct gpio_t gpio_by_amp_n = GPIO(5, 5);
static struct gpio_t gpio_mixer_en = GPIO(5, 16);
static struct gpio_t gpio_low_high_filt = GPIO(2, 11);
static struct gpio_t gpio_low_high_filt_n = GPIO(2, 12);
static struct gpio_t gpio_tx_amp = GPIO(2, 15);
static struct gpio_t gpio_rx_lna = GPIO(5, 15);
#endif
#if 0
/* GPIO Input */
static struct gpio_t gpio_boot[] = {
@ -141,7 +148,7 @@ static struct gpio_t gpio_boot[] = {
/* CPLD JTAG interface GPIO pins */
static struct gpio_t gpio_cpld_tdo = GPIO(5, 18);
static struct gpio_t gpio_cpld_tck = GPIO(3, 0);
#ifdef HACKRF_ONE
#if defined HACKRF_ONE || defined RAD1O
static struct gpio_t gpio_cpld_tms = GPIO(3, 4);
static struct gpio_t gpio_cpld_tdi = GPIO(3, 1);
#else
@ -244,25 +251,6 @@ max5864_driver_t max5864 = {
.target_init = max5864_target_init,
};
const rffc5071_spi_config_t rffc5071_spi_config = {
.gpio_select = &gpio_rffc5072_select,
.gpio_clock = &gpio_rffc5072_clock,
.gpio_data = &gpio_rffc5072_data,
};
spi_bus_t spi_bus_rffc5071 = {
.config = &rffc5071_spi_config,
.start = rffc5071_spi_start,
.stop = rffc5071_spi_stop,
.transfer = rffc5071_spi_transfer,
.transfer_gather = rffc5071_spi_transfer_gather,
};
rffc5071_driver_t rffc5072 = {
.bus = &spi_bus_rffc5071,
.gpio_reset = &gpio_rffc5072_reset,
};
const ssp_config_t ssp_config_w25q80bv = {
.data_bits = SSP_DATA_8BITS,
.serial_clock_rate = 2,
@ -313,6 +301,19 @@ rf_path_t rf_path = {
.gpio_rx_amp = &gpio_rx_amp,
.gpio_no_rx_amp_pwr = &gpio_no_rx_amp_pwr,
#endif
#ifdef RAD1O
.gpio_tx_rx_n = &gpio_tx_rx_n,
.gpio_tx_rx = &gpio_tx_rx,
.gpio_by_mix = &gpio_by_mix,
.gpio_by_mix_n = &gpio_by_mix_n,
.gpio_by_amp = &gpio_by_amp,
.gpio_by_amp_n = &gpio_by_amp_n,
.gpio_mixer_en = &gpio_mixer_en,
.gpio_low_high_filt = &gpio_low_high_filt,
.gpio_low_high_filt_n = &gpio_low_high_filt_n,
.gpio_tx_amp = &gpio_tx_amp,
.gpio_rx_lna = &gpio_rx_lna,
#endif
};
jtag_gpio_t jtag_gpio_cpld = {
@ -377,6 +378,8 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
uint32_t a, b, c;
uint32_t rem;
hackrf_ui_setSampleRate(rate_num/2);
/* Find best config */
a = (VCO_FREQ * rate_denom) / rate_num;
@ -461,6 +464,8 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
return false;
}
hackrf_ui_setSampleRate(sample_rate_hz);
/* NOTE: Because MS1, 2, 3 outputs are slaved to PLLA, the p1, p2, p3
* values are irrelevant. */
@ -476,7 +481,7 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
return true;
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O)
uint32_t p1 = 4608;
uint32_t p2 = 0;
uint32_t p3 = 0;
@ -541,7 +546,11 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
}
bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) {
return max2837_set_lpf_bandwidth(&max2837, bandwidth_hz);
uint32_t bandwidth_hz_real = max2837_set_lpf_bandwidth(&max2837, bandwidth_hz);
if(bandwidth_hz_real) hackrf_ui_setFilterBW(bandwidth_hz_real);
return bandwidth_hz_real != 0;
}
/* clock startup for Jellybean with Lemondrop attached
@ -616,6 +625,33 @@ void cpu_clock_init(void)
si5351c_write(&clock_gen, ms7data, sizeof(ms7data));
#endif
#ifdef RAD1O
/* rad1o clocks:
* CLK0 -> MAX5864/CPLD
* CLK1 -> CPLD
* CLK2 -> SGPIO
* CLK3 -> External Clock Output
* CLK4 -> MAX2837
* CLK5 -> MAX2871
* CLK6 -> none
* CLK7 -> LPC4330 (but LPC4330 starts up on its own crystal) */
/* MS3/CLK3 is the source for the external clock output. */
si5351c_configure_multisynth(&clock_gen, 3, 80*128-512, 0, 1, 0); /* 800/80 = 10MHz */
/* MS4/CLK4 is the source for the MAX2837 clock input. */
si5351c_configure_multisynth(&clock_gen, 4, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */
/* MS5/CLK5 is the source for the RFFC5071 mixer. */
si5351c_configure_multisynth(&clock_gen, 5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */
/* MS6/CLK6 is unused. */
/* MS7/CLK7 is the source for the LPC43xx microcontroller. */
uint8_t ms7data[] = { 90, 255, 20, 0 };
si5351c_write(&clock_gen, ms7data, sizeof(ms7data));
#endif
/* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */
sample_rate_set(10000000);
@ -893,6 +929,9 @@ void pin_setup(void) {
scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_LED2, SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_LED3, SCU_GPIO_NOPULL);
#ifdef RAD1O
scu_pinmux(SCU_PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4);
#endif
scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_NOPULL);
@ -908,6 +947,9 @@ void pin_setup(void) {
gpio_output(&gpio_led[0]);
gpio_output(&gpio_led[1]);
gpio_output(&gpio_led[2]);
#ifdef RAD1O
gpio_output(&gpio_led[3]);
#endif
gpio_output(&gpio_1v8_enable);
@ -928,11 +970,29 @@ void pin_setup(void) {
gpio_output(&gpio_sync_out_b);
#endif
#ifdef RAD1O
/* Configure RF power supply (VAA) switch control signal as output */
gpio_output(&gpio_vaa_enable);
/* Safe state: start with VAA turned off: */
disable_rf_power();
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 */
SCU_SFSI2C0 = SCU_I2C0_NOMINAL;
spi_bus_start(&spi_bus_ssp1, &ssp_config_max2837);
spi_bus_start(&spi_bus_rffc5071, &rffc5071_spi_config);
mixer_bus_setup(&mixer);
rf_path_pin_setup(&rf_path);
@ -960,6 +1020,16 @@ void disable_rf_power(void) {
}
#endif
#ifdef RAD1O
void enable_rf_power(void) {
gpio_set(&gpio_vaa_enable);
}
void disable_rf_power(void) {
gpio_clear(&gpio_vaa_enable);
}
#endif
void led_on(const led_t led) {
gpio_set(&gpio_led[led]);
}
@ -1001,4 +1071,3 @@ void hw_sync_copy_state() {
bool hw_sync_ready() {
return (gpio_read(&gpio_sync_in_a) && gpio_read(&gpio_sync_in_b));
}

View File

@ -37,7 +37,7 @@ extern "C"
#include "max2837.h"
#include "max5864.h"
#include "rffc5071.h"
#include "mixer.h"
#include "w25q80bv.h"
#include "sgpio.h"
#include "rf_path.h"
@ -47,6 +47,7 @@ extern "C"
#define BOARD_ID_JELLYBEAN 0
#define BOARD_ID_JAWBREAKER 1
#define BOARD_ID_HACKRF_ONE 2
#define BOARD_ID_RAD1O 3
#ifdef JELLYBEAN
#define BOARD_ID BOARD_ID_JELLYBEAN
@ -60,6 +61,10 @@ extern "C"
#define BOARD_ID BOARD_ID_HACKRF_ONE
#endif
#ifdef RAD1O
#define BOARD_ID BOARD_ID_RAD1O
#endif
/*
* SCU PinMux
*/
@ -68,6 +73,9 @@ extern "C"
#define SCU_PINMUX_LED1 (P4_1) /* GPIO2[1] on P4_1 */
#define SCU_PINMUX_LED2 (P4_2) /* GPIO2[2] on P4_2 */
#define SCU_PINMUX_LED3 (P6_12) /* GPIO2[8] on P6_12 */
#ifdef RAD1O
#define SCU_PINMUX_LED4 (PB_6) /* GPIO5[26] on PB_6 */
#endif
#define SCU_PINMUX_EN1V8 (P6_10) /* GPIO3[6] on P6_10 */
@ -92,7 +100,7 @@ extern "C"
/* CPLD JTAG interface */
#define SCU_PINMUX_CPLD_TDO (P9_5) /* GPIO5[18] */
#define SCU_PINMUX_CPLD_TCK (P6_1) /* GPIO3[ 0] */
#ifdef HACKRF_ONE
#if (defined HACKRF_ONE || defined RAD1O)
#define SCU_PINMUX_CPLD_TMS (P6_5) /* GPIO3[ 4] */
#define SCU_PINMUX_CPLD_TDI (P6_2) /* GPIO3[ 1] */
#else
@ -112,7 +120,7 @@ extern "C"
#ifdef JELLYBEAN
#define SCU_PINMUX_SGPIO8 (P1_12)
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O)
#define SCU_PINMUX_SGPIO8 (P9_6)
#endif
#define SCU_PINMUX_SGPIO9 (P4_3)
@ -134,6 +142,12 @@ extern "C"
#define SCU_XCVR_B6 (P5_5) /* GPIO2[14] on P5_5 */
#define SCU_XCVR_B7 (P5_6) /* GPIO2[15] on P5_6 */
#endif
#ifdef RAD1O
#define SCU_XCVR_RXHP (P8_1) /* GPIO[] on P8_1 */
#define SCU_XCVR_B6 (P8_2) /* GPIO[] on P8_2 */
#define SCU_XCVR_B7 (P9_3) /* GPIO[] on P8_3 */
#endif
#define SCU_XCVR_ENABLE (P4_6) /* GPIO2[6] on P4_6 */
#define SCU_XCVR_RXENABLE (P4_5) /* GPIO2[5] on P4_5 */
#define SCU_XCVR_TXENABLE (P4_4) /* GPIO2[4] on P4_4 */
@ -155,6 +169,15 @@ extern "C"
#define SCU_MIXER_SDATA (P6_4) /* GPIO3[3] on P6_4 */
#define SCU_MIXER_RESETX (P5_5) /* GPIO2[14] on P5_5 */
#endif
#ifdef RAD1O
#define SCU_VCO_CE (P5_4) /* GPIO2[13] on P5_4 */
#define SCU_VCO_SCLK (P2_6) /* GPIO5[6] on P2_6 */
#define SCU_VCO_SDATA (P6_4) /* GPIO3[3] on P6_4 */
#define SCU_VCO_LE (P5_5) /* GPIO2[14] on P5_5 */
#define SCU_VCO_MUX (PB_5) /* GPIO5[25] on PB_5 */
#define SCU_MIXER_EN (P6_8) /* GPIO5[16] on P6_8 */
#define SCU_SYNT_RFOUT_EN (P6_9) /* GPIO3[5] on P6_9 */
#endif
/* RF LDO control */
#ifdef JAWBREAKER
@ -165,6 +188,10 @@ extern "C"
#ifdef HACKRF_ONE
#define SCU_NO_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#endif
#ifdef RAD1O
#define SCU_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#endif
/* SPI flash */
#define SCU_SSP0_MISO (P3_6)
@ -190,6 +217,18 @@ extern "C"
#define SCU_RX_AMP (P2_11) /* GPIO1[11] on P2_11 */
#define SCU_NO_RX_AMP_PWR (P2_12) /* GPIO1[12] on P2_12 */
#endif
#ifdef RAD1O
#define SCU_BY_AMP (P1_7) /* GPIO1[0] on P1_7 */
#define SCU_BY_AMP_N (P2_5) /* GPIO5[5] on P2_5 */
#define SCU_TX_RX (P2_10) /* GPIO0[14] on P2_10 */
#define SCU_TX_RX_N (P2_11) /* GPIO1[11] on P2_11 */
#define SCU_BY_MIX (P2_12) /* GPIO1[12] on P2_12 */
#define SCU_BY_MIX_N (P5_1) /* GPIO2[10] on P5_1 */
#define SCU_LOW_HIGH_FILT (P5_2) /* GPIO2[11] on P5_2 */
#define SCU_LOW_HIGH_FILT_N (P5_3) /* GPIO2[12] on P5_3 */
#define SCU_TX_AMP (P5_6) /* GPIO2[15] on P5_6 */
#define SCU_RX_LNA (P6_7) /* GPIO5[15] on P6_7 */
#endif
/* TODO add other Pins */
#define SCU_PINMUX_GPIO3_8 (P7_0) /* GPIO3[8] */
@ -240,7 +279,7 @@ extern const ssp_config_t ssp_config_max5864;
extern max2837_driver_t max2837;
extern max5864_driver_t max5864;
extern rffc5071_driver_t rffc5072;
extern mixer_driver_t mixer;
extern w25q80bv_driver_t spi_flash;
extern sgpio_config_t sgpio_config;
extern rf_path_t rf_path;
@ -262,7 +301,7 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom);
bool sample_rate_set(const uint32_t sampling_rate_hz);
bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz);
#ifdef HACKRF_ONE
#if (defined HACKRF_ONE || defined RAD1O)
void enable_rf_power(void);
void disable_rf_power(void);
#endif
@ -271,6 +310,7 @@ typedef enum {
LED1 = 0,
LED2 = 1,
LED3 = 2,
LED4 = 3,
} led_t;
void led_on(const led_t led);

View File

@ -279,7 +279,7 @@ static const max2837_ft_t max2837_ft[] = {
{ 0, 0 },
};
bool max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz) {
uint32_t max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz) {
const max2837_ft_t* p = max2837_ft;
while( p->bandwidth_hz != 0 ) {
if( p->bandwidth_hz >= bandwidth_hz ) {
@ -291,10 +291,9 @@ bool max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandw
if( p->bandwidth_hz != 0 ) {
set_MAX2837_FT(drv, p->ft);
max2837_regs_commit(drv);
return true;
} else {
return false;
}
return p->bandwidth_hz;
}
bool max2837_set_lna_gain(max2837_driver_t* const drv, const uint32_t gain_db) {

View File

@ -91,7 +91,7 @@ extern void max2837_stop(max2837_driver_t* const drv);
/* Set frequency in Hz. Frequency setting is a multi-step function
* where order of register writes matters. */
extern void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq);
bool max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz);
uint32_t max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz);
bool max2837_set_lna_gain(max2837_driver_t* const drv, const uint32_t gain_db);
bool max2837_set_vga_gain(max2837_driver_t* const drv, const uint32_t gain_db);
bool max2837_set_txvga_gain(max2837_driver_t* const drv, const uint32_t gain_db);

236
firmware/common/max2871.c Normal file
View File

@ -0,0 +1,236 @@
#include "max2871.h"
#include "max2871_regs.h"
#if (defined DEBUG)
#include <stdio.h>
#define LOG printf
#else
#define LOG(x,...)
#include <libopencm3/lpc43xx/ssp.h>
#include <libopencm3/lpc43xx/scu.h>
#include "hackrf_core.h"
#endif
#include <stdint.h>
#include <string.h>
static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v);
static void max2871_write_registers(max2871_driver_t* const drv);
static void delay_ms(int ms);
void max2871_setup(max2871_driver_t* const drv)
{
/* Configure GPIO pins. */
scu_pinmux(SCU_VCO_CE, SCU_GPIO_FAST);
scu_pinmux(SCU_VCO_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
/* Only used for the debug pin config: scu_pinmux(SCU_VCO_SCLK, SCU_GPIO_FAST); */
scu_pinmux(SCU_VCO_SDATA, SCU_GPIO_FAST);
scu_pinmux(SCU_VCO_LE, SCU_GPIO_FAST);
scu_pinmux(SCU_VCO_MUX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_SYNT_RFOUT_EN, SCU_GPIO_FAST);
/* Set GPIO pins as outputs. */
gpio_output(drv->gpio_vco_ce);
gpio_output(drv->gpio_vco_sclk);
gpio_output(drv->gpio_vco_sdata);
gpio_output(drv->gpio_vco_le);
gpio_output(drv->gpio_synt_rfout_en);
/* MUX is an input */
gpio_input(drv->gpio_vco_mux);
/* set to known state */
gpio_set(drv->gpio_vco_ce); /* active high */
gpio_clear(drv->gpio_vco_sclk);
gpio_clear(drv->gpio_vco_sdata);
gpio_set(drv->gpio_vco_le); /* active low */
gpio_set(drv->gpio_synt_rfout_en); /* active high */
max2871_regs_init();
int i;
for(i = 5; i >= 0; i--) {
max2871_spi_write(drv, i, max2871_get_register(i));
delay_ms(20);
}
max2871_set_INT(1);
max2871_set_N(4500);
max2871_set_FRAC(0);
max2871_set_CPL(0);
max2871_set_CPT(0);
max2871_set_P(1);
max2871_set_M(0);
max2871_set_LDS(0);
max2871_set_SDN(0);
max2871_set_MUX(0x0C); /* Register 6 readback */
max2871_set_DBR(0);
max2871_set_RDIV2(0);
max2871_set_R(1); /* 40 MHz f_PFD */
max2871_set_REG4DB(1);
max2871_set_CP(15); /* ?: CP charge pump current 0-15 */
max2871_set_LDF(1); /* INT-N */
max2871_set_LDP(0); /* ?: Lock-Detect Precision */
max2871_set_PDP(1);
max2871_set_SHDN(0);
max2871_set_TRI(0);
max2871_set_RST(0);
max2871_set_VCO(0);
max2871_set_VAS_SHDN(0);
max2871_set_VAS_TEMP(1);
max2871_set_CSM(0);
max2871_set_MUTEDEL(1);
max2871_set_CDM(0);
max2871_set_CDIV(0);
max2871_set_SDLDO(0);
max2871_set_SDDIV(0);
max2871_set_SDREF(0);
max2871_set_BS(20*40); /* For 40 MHz f_PFD */
max2871_set_FB(1); /* Do not put DIVA into the feedback loop */
max2871_set_DIVA(0);
max2871_set_SDVCO(0);
max2871_set_MTLD(1);
max2871_set_BDIV(0);
max2871_set_RFB_EN(0);
max2871_set_BPWR(0);
max2871_set_RFA_EN(0);
max2871_set_APWR(3);
max2871_set_SDPLL(0);
max2871_set_F01(1);
max2871_set_LD(1);
max2871_set_ADCS(0);
max2871_set_ADCM(0);
max2871_write_registers(drv);
max2871_set_frequency(drv, 3500);
}
static void delay_ms(int ms)
{
uint32_t i;
while(ms--) {
for (i = 0; i < 20000; i++) {
__asm__("nop");
}
}
}
static void serial_delay(void)
{
uint32_t i;
for (i = 0; i < 2; i++)
__asm__("nop");
}
/* SPI register write
*
* Send 32 bits:
* First 29 bits are data
* Last 3 bits are register number */
static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v) {
#if DEBUG
LOG("0x%04x -> reg%d\n", v, r);
#else
uint32_t bits = 32;
uint32_t msb = 1 << (bits -1);
uint32_t data = v | r;
/* make sure everything is starting in the correct state */
gpio_set(drv->gpio_vco_le);
gpio_clear(drv->gpio_vco_sclk);
gpio_clear(drv->gpio_vco_sdata);
/* start transaction by bringing LE low */
gpio_clear(drv->gpio_vco_le);
while (bits--) {
if (data & msb)
gpio_set(drv->gpio_vco_sdata);
else
gpio_clear(drv->gpio_vco_sdata);
data <<= 1;
serial_delay();
gpio_set(drv->gpio_vco_sclk);
serial_delay();
gpio_clear(drv->gpio_vco_sclk);
}
gpio_set(drv->gpio_vco_le);
#endif
}
static uint32_t max2871_spi_read(max2871_driver_t* const drv)
{
uint32_t bits = 32;
uint32_t data = 0;
max2871_spi_write(drv, 0x06, 0x0);
serial_delay();
gpio_set(drv->gpio_vco_sclk);
serial_delay();
gpio_clear(drv->gpio_vco_sclk);
serial_delay();
while (bits--) {
gpio_set(drv->gpio_vco_sclk);
serial_delay();
gpio_clear(drv->gpio_vco_sclk);
serial_delay();
data <<= 1;
data |= gpio_read(drv->gpio_vco_mux) ? 1 : 0;
}
return data;
}
static void max2871_write_registers(max2871_driver_t* const drv)
{
int i;
for(i = 5; i >= 0; i--) {
max2871_spi_write(drv, i, max2871_get_register(i));
}
}
/* Set frequency (MHz). */
uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz)
{
int n = mhz / 40;
int diva = 0;
while(n * 40 < 3000) {
n *= 2;
diva += 1;
}
max2871_set_RFA_EN(0);
max2871_write_registers(drv);
max2871_set_N(n);
max2871_set_DIVA(diva);
max2871_write_registers(drv);
while(max2871_spi_read(drv) & MAX2871_VASA);
max2871_set_RFA_EN(1);
max2871_write_registers(drv);
return (mhz/40)*40 * 1000000;
}
void max2871_enable(max2871_driver_t* const drv)
{
gpio_set(drv->gpio_vco_ce);
}
void max2871_disable(max2871_driver_t* const drv)
{
gpio_clear(drv->gpio_vco_ce);
}

21
firmware/common/max2871.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef MAX2871_H
#define MAX2871_H
#include "gpio.h"
#include <stdint.h>
typedef struct {
gpio_t gpio_vco_ce;
gpio_t gpio_vco_sclk;
gpio_t gpio_vco_sdata;
gpio_t gpio_vco_le;
gpio_t gpio_synt_rfout_en;
gpio_t gpio_vco_mux;
} max2871_driver_t;
extern void max2871_setup(max2871_driver_t* const drv);
extern uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz);
extern void max2871_enable(max2871_driver_t* const drv);
extern void max2871_disable(max2871_driver_t* const drv);
#endif

View File

@ -0,0 +1,299 @@
#include "max2871_regs.h"
#include <stdint.h>
static uint32_t registers[6];
void max2871_regs_init(void)
{
registers[0] = 0x007D0000;
registers[1] = 0x2000FFF9;
registers[2] = 0x00004042;
registers[3] = 0x0000000B;
registers[4] = 0x6180B23C;
registers[5] = 0x00400005;
}
uint32_t max2871_get_register(int reg)
{
return registers[reg];
}
void max2871_set_INT(uint32_t v)
{
registers[0] &= ~(0x1 << 31);
registers[0] |= v << 31;
}
void max2871_set_N(uint32_t v)
{
registers[0] &= ~(0xFFFF << 15);
registers[0] |= v << 15;
}
void max2871_set_FRAC(uint32_t v)
{
registers[0] &= ~(0xFFF << 3);
registers[0] |= v << 3;
}
void max2871_set_CPL(uint32_t v)
{
registers[1] &= ~(0x3 << 29);
registers[1] |= v << 29;
}
void max2871_set_CPT(uint32_t v)
{
registers[1] &= ~(0x3 << 27);
registers[1] |= v << 27;
}
void max2871_set_P(uint32_t v)
{
registers[1] &= ~(0xFFF << 15);
registers[1] |= v << 15;
}
void max2871_set_M(uint32_t v)
{
registers[1] &= ~(0xFFF << 3);
registers[1] |= v << 3;
}
void max2871_set_LDS(uint32_t v)
{
registers[2] &= ~(0x1 << 31);
registers[2] |= v << 31;
}
void max2871_set_SDN(uint32_t v)
{
registers[2] &= ~(0x3 << 29);
registers[2] |= v << 29;
}
void max2871_set_MUX(uint32_t v)
{
registers[2] &= ~(0x7 << 26);
registers[5] &= ~(0x1 << 18);
registers[2] |= (v & 0x7) << 26;
registers[5] |= ((v & 0x8) >> 3) << 18;
}
void max2871_set_DBR(uint32_t v)
{
registers[2] &= ~(0x1 << 25);
registers[2] |= v << 25;
}
void max2871_set_RDIV2(uint32_t v)
{
registers[2] &= ~(0x1 << 24);
registers[2] |= v << 24;
}
void max2871_set_R(uint32_t v)
{
registers[2] &= ~(0x3FF << 14);
registers[2] |= v << 14;
}
void max2871_set_REG4DB(uint32_t v)
{
registers[2] &= ~(0x1 << 13);
registers[2] |= v << 13;
}
void max2871_set_CP(uint32_t v)
{
registers[2] &= ~(0xF << 9);
registers[2] |= v << 9;
}
void max2871_set_LDF(uint32_t v)
{
registers[2] &= ~(0x1 << 8);
registers[2] |= v << 8;
}
void max2871_set_LDP(uint32_t v)
{
registers[2] &= ~(0x1 << 7);
registers[2] |= v << 7;
}
void max2871_set_PDP(uint32_t v)
{
registers[2] &= ~(0x1 << 6);
registers[2] |= v << 6;
}
void max2871_set_SHDN(uint32_t v)
{
registers[2] &= ~(0x1 << 5);
registers[2] |= v << 5;
}
void max2871_set_TRI(uint32_t v)
{
registers[2] &= ~(0x1 << 4);
registers[2] |= v << 4;
}
void max2871_set_RST(uint32_t v)
{
registers[2] &= ~(0x1 << 3);
registers[2] |= v << 3;
}
void max2871_set_VCO(uint32_t v)
{
registers[3] &= ~(0x3F << 26);
registers[3] |= v << 26;
}
void max2871_set_VAS_SHDN(uint32_t v)
{
registers[3] &= ~(0x1 << 25);
registers[3] |= v << 25;
}
void max2871_set_VAS_TEMP(uint32_t v)
{
registers[3] &= ~(0x1 << 24);
registers[3] |= v << 24;
}
void max2871_set_CSM(uint32_t v)
{
registers[3] &= ~(0x1 << 18);
registers[3] |= v << 18;
}
void max2871_set_MUTEDEL(uint32_t v)
{
registers[3] &= ~(0x1 << 17);
registers[3] |= v << 17;
}
void max2871_set_CDM(uint32_t v)
{
registers[3] &= ~(0x3 << 15);
registers[3] |= v << 15;
}
void max2871_set_CDIV(uint32_t v)
{
registers[3] &= ~(0xFFF << 3);
registers[3] |= v << 3;
}
void max2871_set_SDLDO(uint32_t v)
{
registers[4] &= ~(0x1 << 28);
registers[4] |= v << 28;
}
void max2871_set_SDDIV(uint32_t v)
{
registers[4] &= ~(0x1 << 27);
registers[4] |= v << 27;
}
void max2871_set_SDREF(uint32_t v)
{
registers[4] &= ~(0x1 << 26);
registers[4] |= v << 26;
}
void max2871_set_BS(uint32_t v)
{
registers[4] &= ~(0x3 << 24);
registers[4] &= ~(0xFF << 12);
registers[4] |= ((v & 0x300) >> 8) << 24;
registers[4] |= (v & 0xFF) << 12;
}
void max2871_set_FB(uint32_t v)
{
registers[4] &= ~(0x1 << 23);
registers[4] |= v << 23;
}
void max2871_set_DIVA(uint32_t v)
{
registers[4] &= ~(0x7 << 20);
registers[4] |= v << 20;
}
void max2871_set_SDVCO(uint32_t v)
{
registers[4] &= ~(0x1 << 11);
registers[4] |= v << 11;
}
void max2871_set_MTLD(uint32_t v)
{
registers[4] &= ~(0x1 << 10);
registers[4] |= v << 10;
}
void max2871_set_BDIV(uint32_t v)
{
registers[4] &= ~(0x1 << 9);
registers[4] |= v << 9;
}
void max2871_set_RFB_EN(uint32_t v)
{
registers[4] &= ~(0x1 << 8);
registers[4] |= v << 8;
}
void max2871_set_BPWR(uint32_t v)
{
registers[4] &= ~(0x3 << 6);
registers[4] |= v << 6;
}
void max2871_set_RFA_EN(uint32_t v)
{
registers[4] &= ~(0x1 << 5);
registers[4] |= v << 5;
}
void max2871_set_APWR(uint32_t v)
{
registers[4] &= ~(0x3 << 3);
registers[4] |= v << 3;
}
void max2871_set_SDPLL(uint32_t v)
{
registers[5] &= ~(0x1 << 25);
registers[5] |= v << 25;
}
void max2871_set_F01(uint32_t v)
{
registers[5] &= ~(0x1 << 24);
registers[5] |= v << 24;
}
void max2871_set_LD(uint32_t v)
{
registers[5] &= ~(0x3 << 22);
registers[5] |= v << 22;
}
void max2871_set_ADCS(uint32_t v)
{
registers[5] &= ~(0x1 << 6);
registers[5] |= v << 6;
}
void max2871_set_ADCM(uint32_t v)
{
registers[5] &= ~(0x7 << 3);
registers[5] |= v << 3;
}

View File

@ -0,0 +1,56 @@
#ifndef MAX2871_REGS_H
#define MAX2871_REGS_H
#include <stdint.h>
#define MAX2871_VASA (1 << 9)
void max2871_regs_init(void);
uint32_t max2871_get_register(int reg);
void max2871_set_INT(uint32_t v);
void max2871_set_N(uint32_t v);
void max2871_set_FRAC(uint32_t v);
void max2871_set_CPL(uint32_t v);
void max2871_set_CPT(uint32_t v);
void max2871_set_P(uint32_t v);
void max2871_set_M(uint32_t v);
void max2871_set_LDS(uint32_t v);
void max2871_set_SDN(uint32_t v);
void max2871_set_MUX(uint32_t v);
void max2871_set_DBR(uint32_t v);
void max2871_set_RDIV2(uint32_t v);
void max2871_set_R(uint32_t v);
void max2871_set_REG4DB(uint32_t v);
void max2871_set_CP(uint32_t v);
void max2871_set_LDF(uint32_t v);
void max2871_set_LDP(uint32_t v);
void max2871_set_PDP(uint32_t v);
void max2871_set_SHDN(uint32_t v);
void max2871_set_TRI(uint32_t v);
void max2871_set_RST(uint32_t v);
void max2871_set_VCO(uint32_t v);
void max2871_set_VAS_SHDN(uint32_t v);
void max2871_set_VAS_TEMP(uint32_t v);
void max2871_set_CSM(uint32_t v);
void max2871_set_MUTEDEL(uint32_t v);
void max2871_set_CDM(uint32_t v);
void max2871_set_CDIV(uint32_t v);
void max2871_set_SDLDO(uint32_t v);
void max2871_set_SDDIV(uint32_t v);
void max2871_set_SDREF(uint32_t v);
void max2871_set_BS(uint32_t v);
void max2871_set_FB(uint32_t v);
void max2871_set_DIVA(uint32_t v);
void max2871_set_SDVCO(uint32_t v);
void max2871_set_MTLD(uint32_t v);
void max2871_set_BDIV(uint32_t v);
void max2871_set_RFB_EN(uint32_t v);
void max2871_set_BPWR(uint32_t v);
void max2871_set_RFA_EN(uint32_t v);
void max2871_set_APWR(uint32_t v);
void max2871_set_SDPLL(uint32_t v);
void max2871_set_F01(uint32_t v);
void max2871_set_LD(uint32_t v);
void max2871_set_ADCS(uint32_t v);
void max2871_set_ADCM(uint32_t v);
#endif

144
firmware/common/mixer.c Normal file
View File

@ -0,0 +1,144 @@
#include "mixer.h"
#include "rffc5071.h"
#include "rffc5071_spi.h"
#include "max2871.h"
#include "gpio_lpc.h"
/* RFFC5071 GPIO serial interface PinMux */
#if (defined JAWBREAKER || defined HACKRF_ONE)
static struct gpio_t gpio_rffc5072_select = GPIO(2, 13);
static struct gpio_t gpio_rffc5072_clock = GPIO(5, 6);
static struct gpio_t gpio_rffc5072_data = GPIO(3, 3);
static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14);
#endif
#ifdef RAD1O
static struct gpio_t gpio_vco_ce = GPIO(2, 13);
static struct gpio_t gpio_vco_sclk = GPIO(5, 6);
static struct gpio_t gpio_vco_sdata = GPIO(3, 3);
static struct gpio_t gpio_vco_le = GPIO(2, 14);
static struct gpio_t gpio_vco_mux = GPIO(5, 25);
static struct gpio_t gpio_synt_rfout_en = GPIO(3, 5);
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
const rffc5071_spi_config_t rffc5071_spi_config = {
.gpio_select = &gpio_rffc5072_select,
.gpio_clock = &gpio_rffc5072_clock,
.gpio_data = &gpio_rffc5072_data,
};
spi_bus_t spi_bus_rffc5071 = {
.config = &rffc5071_spi_config,
.start = rffc5071_spi_start,
.stop = rffc5071_spi_stop,
.transfer = rffc5071_spi_transfer,
.transfer_gather = rffc5071_spi_transfer_gather,
};
mixer_driver_t mixer = {
.bus = &spi_bus_rffc5071,
.gpio_reset = &gpio_rffc5072_reset,
};
#endif
#ifdef RAD1O
mixer_driver_t mixer = {
.gpio_vco_ce = &gpio_vco_ce,
.gpio_vco_sclk = &gpio_vco_sclk,
.gpio_vco_sdata = &gpio_vco_sdata,
.gpio_vco_le = &gpio_vco_le,
.gpio_synt_rfout_en = &gpio_synt_rfout_en,
.gpio_vco_mux = &gpio_vco_mux,
};
#endif
void mixer_bus_setup(mixer_driver_t* const mixer)
{
#if (defined JAWBREAKER || defined HACKRF_ONE)
(void) mixer;
spi_bus_start(&spi_bus_rffc5071, &rffc5071_spi_config);
#endif
#ifdef RAD1O
(void) mixer;
#endif
}
void mixer_setup(mixer_driver_t* const mixer)
{
#if (defined JAWBREAKER || defined HACKRF_ONE)
rffc5071_setup(mixer);
#endif
#ifdef RAD1O
max2871_setup(mixer);
#endif
}
uint64_t mixer_set_frequency(mixer_driver_t* const mixer, uint16_t mhz)
{
#if (defined JAWBREAKER || defined HACKRF_ONE)
return rffc5071_set_frequency(mixer, mhz);
#endif
#ifdef RAD1O
return max2871_set_frequency(mixer, mhz);
#endif
}
void mixer_tx(mixer_driver_t* const mixer)
{
#if (defined JAWBREAKER || defined HACKRF_ONE)
rffc5071_tx(mixer);
#endif
#ifdef RAD1O
(void) mixer;
#endif
}
void mixer_rx(mixer_driver_t* const mixer)
{
#if (defined JAWBREAKER || defined HACKRF_ONE)
rffc5071_rx(mixer);
#endif
#ifdef RAD1O
(void) mixer;
#endif
}
void mixer_rxtx(mixer_driver_t* const mixer)
{
#if (defined JAWBREAKER || defined HACKRF_ONE)
rffc5071_rxtx(mixer);
#endif
#ifdef RAD1O
(void) mixer;
#endif
}
void mixer_enable(mixer_driver_t* const mixer)
{
#if (defined JAWBREAKER || defined HACKRF_ONE)
rffc5071_enable(mixer);
#endif
#ifdef RAD1O
(void) mixer;
#endif
}
void mixer_disable(mixer_driver_t* const mixer)
{
#if (defined JAWBREAKER || defined HACKRF_ONE)
rffc5071_disable(mixer);
#endif
#ifdef RAD1O
(void) mixer;
#endif
}
void mixer_set_gpo(mixer_driver_t* const mixer, uint8_t gpo)
{
#if (defined JAWBREAKER || defined HACKRF_ONE)
rffc5071_set_gpo(mixer, gpo);
#endif
#ifdef RAD1O
(void) mixer;
(void) gpo;
#endif
}

52
firmware/common/mixer.h Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright 2012 Michael Ossmann
* Copyright 2014 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.
*/
#ifndef __MIXER_H
#define __MIXER_H
#if (defined JAWBREAKER || defined HACKRF_ONE)
#include "rffc5071.h"
typedef rffc5071_driver_t mixer_driver_t;
#endif
#ifdef RAD1O
#include "max2871.h"
typedef max2871_driver_t mixer_driver_t;
#endif
#include <stdint.h>
extern void mixer_bus_setup(mixer_driver_t* const mixer);
extern void mixer_setup(mixer_driver_t* const mixer);
/* Set frequency (MHz). */
extern uint64_t mixer_set_frequency(mixer_driver_t* const mixer, uint16_t mhz);
/* Set up rx only, tx only, or full duplex. Chip should be disabled
* before _tx, _rx, or _rxtx are called. */
extern void mixer_tx(mixer_driver_t* const mixer);
extern void mixer_rx(mixer_driver_t* const mixer);
extern void mixer_rxtx(mixer_driver_t* const mixer);
extern void mixer_enable(mixer_driver_t* const mixer);
extern void mixer_disable(mixer_driver_t* const mixer);
extern void mixer_set_gpo(mixer_driver_t* const drv, uint8_t gpo);
#endif // __MIXER_H

View File

@ -26,12 +26,14 @@
#include <hackrf_core.h>
#include <rffc5071.h>
#include "hackrf-ui.h"
#include <mixer.h>
#include <max2837.h>
#include <max5864.h>
#include <sgpio.h>
#if (defined JAWBREAKER || defined HACKRF_ONE)
#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O)
/*
* RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on
* the RFFC5072.
@ -40,6 +42,9 @@
* SWITCHCTRL_NO_TX_AMP_PWR and SWITCHCTRL_NO_RX_AMP_PWR are not normally used
* on HackRF One as the amplifier power is instead controlled only by
* SWITCHCTRL_AMP_BYPASS.
*
* The rad1o also uses GPIO pins to control the different switches. The amplifiers
* are also connected to the LPC.
*/
#define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* GPO1 turn off TX amp power */
#define SWITCHCTRL_AMP_BYPASS (1 << 1) /* GPO2 bypass amp section */
@ -148,9 +153,73 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) {
gpio_set(rf_path->gpio_no_rx_amp_pwr);
if (ctrl & SWITCHCTRL_ANT_PWR) {
rffc5071_set_gpo(&rffc5072, 0x00); /* turn on antenna power by clearing GPO1 */
mixer_set_gpo(&mixer, 0x00); /* turn on antenna power by clearing GPO1 */
} else {
rffc5071_set_gpo(&rffc5072, 0x01); /* turn off antenna power by setting GPO1 */
mixer_set_gpo(&mixer, 0x01); /* turn off antenna power by setting GPO1 */
}
}
#endif
#ifdef RAD1O
static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) {
if (ctrl & SWITCHCTRL_TX) {
gpio_set(rf_path->gpio_tx_rx_n);
gpio_clear(rf_path->gpio_tx_rx);
} else {
gpio_clear(rf_path->gpio_tx_rx_n);
gpio_set(rf_path->gpio_tx_rx);
}
if (ctrl & SWITCHCTRL_MIX_BYPASS) {
gpio_clear(rf_path->gpio_by_mix);
gpio_set(rf_path->gpio_by_mix_n);
gpio_clear(rf_path->gpio_mixer_en);
} else {
gpio_set(rf_path->gpio_by_mix);
gpio_clear(rf_path->gpio_by_mix_n);
gpio_set(rf_path->gpio_mixer_en);
}
if (ctrl & SWITCHCTRL_HP) {
gpio_set(rf_path->gpio_low_high_filt);
gpio_clear(rf_path->gpio_low_high_filt_n);
} else {
gpio_clear(rf_path->gpio_low_high_filt);
gpio_set(rf_path->gpio_low_high_filt_n);
}
if (ctrl & SWITCHCTRL_AMP_BYPASS) {
gpio_clear(rf_path->gpio_by_amp);
gpio_set(rf_path->gpio_by_amp_n);
gpio_clear(rf_path->gpio_tx_amp);
gpio_clear(rf_path->gpio_rx_lna);
} else if (ctrl & SWITCHCTRL_TX) {
gpio_set(rf_path->gpio_by_amp);
gpio_clear(rf_path->gpio_by_amp_n);
gpio_set(rf_path->gpio_tx_amp);
gpio_clear(rf_path->gpio_rx_lna);
} else {
gpio_set(rf_path->gpio_by_amp);
gpio_clear(rf_path->gpio_by_amp_n);
gpio_clear(rf_path->gpio_tx_amp);
gpio_set(rf_path->gpio_rx_lna);
}
/*
* These normally shouldn't be set post-Jawbreaker, but they can be
* used to explicitly turn off power to the amplifiers while AMP_BYPASS
* is unset:
*/
if (ctrl & SWITCHCTRL_NO_TX_AMP_PWR) {
gpio_clear(rf_path->gpio_tx_amp);
}
if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR) {
gpio_clear(rf_path->gpio_rx_lna);
}
}
#endif
@ -158,9 +227,11 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) {
static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) {
#ifdef JAWBREAKER
(void) rf_path; /* silence unused param warning */
rffc5071_set_gpo(&rffc5072, gpo);
mixer_set_gpo(&mixer, gpo);
#elif HACKRF_ONE
switchctrl_set_hackrf_one(rf_path, gpo);
#elif RAD1O
switchctrl_set_rad1o(rf_path, gpo);
#else
(void)gpo;
#endif
@ -201,6 +272,41 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
gpio_output(rf_path->gpio_mix_bypass);
gpio_output(rf_path->gpio_rx);
/*
* Safe (initial) switch settings turn off both amplifiers and antenna port
* power and enable both amp bypass and mixer bypass.
*/
switchctrl_set(rf_path, SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS);
#elif RAD1O
/* Configure RF switch control signals */
scu_pinmux(SCU_BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_BY_AMP_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_TX_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_TX_RX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_BY_MIX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_BY_MIX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_LOW_HIGH_FILT, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_LOW_HIGH_FILT_N,SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_RX_LNA, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_MIXER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
/* Configure RF power supply (VAA) switch */
scu_pinmux(SCU_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
/* Configure RF switch control signals as outputs */
gpio_output(rf_path->gpio_tx_rx_n);
gpio_output(rf_path->gpio_tx_rx);
gpio_output(rf_path->gpio_by_mix);
gpio_output(rf_path->gpio_by_mix_n);
gpio_output(rf_path->gpio_by_amp);
gpio_output(rf_path->gpio_by_amp_n);
gpio_output(rf_path->gpio_mixer_en);
gpio_output(rf_path->gpio_low_high_filt);
gpio_output(rf_path->gpio_low_high_filt_n);
gpio_output(rf_path->gpio_tx_amp);
gpio_output(rf_path->gpio_rx_lna);
/*
* Safe (initial) switch settings turn off both amplifiers and antenna port
* power and enable both amp bypass and mixer bypass.
@ -220,7 +326,7 @@ void rf_path_init(rf_path_t* const rf_path) {
max2837_setup(&max2837);
max2837_start(&max2837);
rffc5071_setup(&rffc5072);
mixer_setup(&mixer);
switchctrl_set(rf_path, switchctrl);
}
@ -234,11 +340,11 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
/* TX amplifier is in path, be sure to enable TX amplifier. */
rf_path->switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR;
}
rffc5071_tx(&rffc5072);
mixer_tx(&mixer);
if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) {
rffc5071_disable(&rffc5072);
mixer_disable(&mixer);
} else {
rffc5071_enable(&rffc5072);
mixer_enable(&mixer);
}
ssp1_set_mode_max5864();
max5864_tx(&max5864);
@ -253,11 +359,11 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
/* RX amplifier is in path, be sure to enable RX amplifier. */
rf_path->switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR;
}
rffc5071_rx(&rffc5072);
mixer_rx(&mixer);
if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) {
rffc5071_disable(&rffc5072);
mixer_disable(&mixer);
} else {
rffc5071_enable(&rffc5072);
mixer_enable(&mixer);
}
ssp1_set_mode_max5864();
max5864_rx(&max5864);
@ -274,7 +380,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
rf_path_set_lna(rf_path, 0);
/* Set RF path to receive direction when "off" */
rf_path->switchctrl &= ~SWITCHCTRL_TX;
rffc5071_disable(&rffc5072);
mixer_disable(&mixer);
ssp1_set_mode_max5864();
max5864_standby(&max5864);
ssp1_set_mode_max2837();
@ -284,6 +390,8 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
}
switchctrl_set(rf_path, rf_path->switchctrl);
hackrf_ui_setDirection(direction);
}
void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) {
@ -291,18 +399,18 @@ void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter)
default:
case RF_PATH_FILTER_BYPASS:
rf_path->switchctrl |= SWITCHCTRL_MIX_BYPASS;
rffc5071_disable(&rffc5072);
mixer_disable(&mixer);
break;
case RF_PATH_FILTER_LOW_PASS:
rf_path->switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS);
rffc5071_enable(&rffc5072);
mixer_enable(&mixer);
break;
case RF_PATH_FILTER_HIGH_PASS:
rf_path->switchctrl &= ~SWITCHCTRL_MIX_BYPASS;
rf_path->switchctrl |= SWITCHCTRL_HP;
rffc5071_enable(&rffc5072);
mixer_enable(&mixer);
break;
}
@ -326,6 +434,8 @@ void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable) {
}
switchctrl_set(rf_path, rf_path->switchctrl);
hackrf_ui_setLNAPower(enable);
}
/* antenna port power control */

View File

@ -56,6 +56,19 @@ typedef struct rf_path_t {
gpio_t gpio_rx_amp;
gpio_t gpio_no_rx_amp_pwr;
#endif
#ifdef RAD1O
gpio_t gpio_tx_rx_n;
gpio_t gpio_tx_rx;
gpio_t gpio_by_mix;
gpio_t gpio_by_mix_n;
gpio_t gpio_by_amp;
gpio_t gpio_by_amp_n;
gpio_t gpio_mixer_en;
gpio_t gpio_low_high_filt;
gpio_t gpio_low_high_filt_n;
gpio_t gpio_tx_amp;
gpio_t gpio_rx_lna;
#endif
} rf_path_t;
void rf_path_pin_setup(rf_path_t* const rf_path);

View File

@ -27,6 +27,10 @@
#include <sgpio.h>
#ifdef RAD1O
static void update_q_invert(sgpio_config_t* const config);
#endif
void sgpio_configure_pin_functions(sgpio_config_t* const config) {
scu_pinmux(SCU_PINMUX_SGPIO0, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
scu_pinmux(SCU_PINMUX_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
@ -88,6 +92,12 @@ void sgpio_configure(
| (1L << 10) // disable codec data stream during configuration (Output SGPIO10 High)
;
#ifdef RAD1O
/* The data direction might have changed. Check if we need to
* adjust the q inversion. */
update_q_invert(config);
#endif
// Enable SGPIO pin outputs.
const uint_fast16_t sgpio_gpio_data_direction =
(direction == SGPIO_DIRECTION_TX)
@ -264,6 +274,48 @@ bool sgpio_cpld_stream_rx_set_decimation(sgpio_config_t* const config, const uin
return (skip_n < 8);
}
#ifdef RAD1O
/* The rad1o hardware has a bug which makes it
* necessary to also switch between the two options based
* on TX or RX mode.
*
* We use the state of the pin to determine which way we
* have to go.
*
* As TX/RX can change without sgpio_cpld_stream_rx_set_q_invert
* being called, we store a local copy of its parameter. */
static bool sgpio_invert = false;
/* Called when TX/RX changes od sgpio_cpld_stream_rx_set_q_invert
* gets called. */
static void update_q_invert(sgpio_config_t* const config) {
/* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode) */
bool tx_mode = (SGPIO_GPIO_OUTREG & (1 << 11)) > 0;
/* 0.13: P1_18 */
if( !sgpio_invert & !tx_mode) {
gpio_write(config->gpio_rx_q_invert, 1);
} else if( !sgpio_invert & tx_mode) {
gpio_write(config->gpio_rx_q_invert, 0);
} else if( sgpio_invert & !tx_mode) {
gpio_write(config->gpio_rx_q_invert, 0);
} else if( sgpio_invert & tx_mode) {
gpio_write(config->gpio_rx_q_invert, 1);
}
}
void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert) {
if( invert ) {
sgpio_invert = true;
} else {
sgpio_invert = false;
}
update_q_invert(config);
}
#else
void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert) {
gpio_write(config->gpio_rx_q_invert, invert);
}
#endif

View File

@ -243,10 +243,42 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll
}
#endif
/* Enable CLK outputs 0, 1, 2, 3, 4, 5, 7 only. */
#ifdef RAD1O
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source)
{
(void) source;
uint8_t pll;
/* PLLA on XTAL */
pll = SI5351C_CLK_PLL_SRC_A;
/* Clock to CPU is deactivated as it is not used and creates noise */
/* External clock output is deactivated as it is not used and creates noise */
uint8_t data[] = {16
,SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA)
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA)
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
};
si5351c_write(drv, data, sizeof(data));
}
#endif
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
{
#ifdef RAD1O
/* Enable CLK outputs 0, 1, 2, 4, 5 only. */
/* 7: Clock to CPU is deactivated as it is not used and creates noise */
/* 3: External clock output is deactivated as it is not used and creates noise */
uint8_t data[] = { 3, ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5))};
#else
/* Enable CLK outputs 0, 1, 2, 3, 4, 5, 7 only. */
uint8_t data[] = { 3, 0x40 };
#endif
si5351c_write(drv, data, sizeof(data));
}

View File

@ -22,8 +22,10 @@
#include "tuning.h"
#include "hackrf-ui.h"
#include <hackrf_core.h>
#include <rffc5071.h>
#include <mixer.h>
#include <max2837.h>
#include <sgpio.h>
@ -54,9 +56,9 @@ uint64_t freq_cache = 100000000;
bool set_freq(const uint64_t freq)
{
bool success;
uint32_t RFFC5071_freq_mhz;
uint32_t mixer_freq_mhz;
uint32_t MAX2837_freq_hz;
uint64_t real_RFFC5071_freq_hz;
uint64_t real_mixer_freq_hz;
const uint32_t freq_mhz = freq / 1000000;
const uint32_t freq_hz = freq % 1000000;
@ -68,18 +70,22 @@ bool set_freq(const uint64_t freq)
if(freq_mhz < MAX_LP_FREQ_MHZ)
{
rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS);
#ifdef RAD1O
max2837_freq_nominal_hz = 2300000000;
#else
/* IF is graduated from 2650 MHz to 2343 MHz */
max2837_freq_nominal_hz = 2650000000 - (freq / 7);
RFFC5071_freq_mhz = (max2837_freq_nominal_hz / FREQ_ONE_MHZ) + freq_mhz;
#endif
mixer_freq_mhz = (max2837_freq_nominal_hz / FREQ_ONE_MHZ) + freq_mhz;
/* Set Freq and read real freq */
real_RFFC5071_freq_hz = rffc5071_set_frequency(&rffc5072, RFFC5071_freq_mhz);
max2837_set_frequency(&max2837, real_RFFC5071_freq_hz - freq);
real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz);
max2837_set_frequency(&max2837, real_mixer_freq_hz - freq);
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1);
}else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) )
{
rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS);
MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz;
/* RFFC5071_freq_mhz <= not used in Bypass mode */
/* mixer_freq_mhz <= not used in Bypass mode */
max2837_set_frequency(&max2837, MAX2837_freq_hz);
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
}else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ) )
@ -95,10 +101,10 @@ bool set_freq(const uint64_t freq)
max2837_freq_nominal_hz = 2500000000 + ((freq - 5100000000) / 9);
}
rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS);
RFFC5071_freq_mhz = freq_mhz - (max2837_freq_nominal_hz / FREQ_ONE_MHZ);
mixer_freq_mhz = freq_mhz - (max2837_freq_nominal_hz / FREQ_ONE_MHZ);
/* Set Freq and read real freq */
real_RFFC5071_freq_hz = rffc5071_set_frequency(&rffc5072, RFFC5071_freq_mhz);
max2837_set_frequency(&max2837, freq - real_RFFC5071_freq_hz);
real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz);
max2837_set_frequency(&max2837, freq - real_mixer_freq_hz);
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
}else
{
@ -108,6 +114,7 @@ bool set_freq(const uint64_t freq)
max2837_set_mode(&max2837, prior_max2837_mode);
if( success ) {
freq_cache = freq;
hackrf_ui_setFrequency(freq);
}
return success;
}
@ -137,7 +144,7 @@ bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz,
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
}
if (path != RF_PATH_FILTER_BYPASS) {
(void)rffc5071_set_frequency(&rffc5072, lo_freq_hz / FREQ_ONE_MHZ);
(void)mixer_set_frequency(&mixer, lo_freq_hz / FREQ_ONE_MHZ);
}
return true;
}

View File

@ -72,7 +72,7 @@ void usb_peripheral_reset() {
while( (RESET_ACTIVE_STATUS0 & RESET_CTRL0_USB0_RST) == 0 );
}
static void usb_phy_enable() {
void usb_phy_enable() {
CREG_CREG0 &= ~CREG_CREG0_USB0PHY;
}

View File

@ -29,6 +29,7 @@
#include "usb_type.h"
void usb_peripheral_reset();
void usb_phy_enable();
void usb_device_init(
const uint_fast8_t device_ordinal,

View File

@ -61,11 +61,10 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv)
drv->target_init(drv);
device_id = 0;
while(device_id != W25Q80BV_DEVICE_ID_RES)
{
do {
device_id = w25q80bv_get_device_id(drv);
}
} while(device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
}
uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv)
@ -117,11 +116,10 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv)
{
uint8_t device_id;
device_id = 0;
while(device_id != W25Q80BV_DEVICE_ID_RES)
{
do {
device_id = w25q80bv_get_device_id(drv);
}
} while(device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
w25q80bv_write_enable(drv);
w25q80bv_wait_while_busy(drv);
@ -165,11 +163,10 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len,
uint16_t first_block_len;
uint8_t device_id;
device_id = 0;
while(device_id != W25Q80BV_DEVICE_ID_RES)
{
do {
device_id = w25q80bv_get_device_id(drv);
}
} while(device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
/* do nothing if we would overflow the flash */
if ((len > drv->num_bytes) || (addr > drv->num_bytes)

View File

@ -27,6 +27,8 @@
#include <stdint.h>
#include <stddef.h>
#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */
#define W25Q16DV_DEVICE_ID_RES 0x14 /* Expected device_id for W25Q16DV */
#include "spi_bus.h"
#include "gpio.h"

View File

@ -104,10 +104,9 @@ macro(DeclareTargets)
${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c
${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c
${PATH_HACKRF_FIRMWARE_COMMON}/max5864_target.c
${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c
${PATH_HACKRF_FIRMWARE_COMMON}/mixer.c
${PATH_HACKRF_FIRMWARE_COMMON}/i2c_bus.c
${PATH_HACKRF_FIRMWARE_COMMON}/i2c_lpc.c
${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_spi.c
${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv.c
${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv_target.c
${PATH_HACKRF_FIRMWARE_COMMON}/spi_bus.c
@ -115,6 +114,20 @@ macro(DeclareTargets)
${PATH_HACKRF_FIRMWARE_COMMON}/gpio_lpc.c
)
if(BOARD STREQUAL "RAD1O")
SET(SRC_M4
${SRC_M4}
${PATH_HACKRF_FIRMWARE_COMMON}/max2871.c
${PATH_HACKRF_FIRMWARE_COMMON}/max2871_regs.c
)
else()
SET(SRC_M4
${SRC_M4}
${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c
${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_spi.c
)
endif()
configure_file(
${PATH_HACKRF_FIRMWARE_COMMON}/m0_bin.s.cmake
m0_bin.s

View File

@ -46,6 +46,8 @@
#include "usb_api_transceiver.h"
#include "usb_bulk_buffer.h"
#include "hackrf-ui.h"
static const usb_request_handler_fn vendor_request_handler[] = {
NULL,
usb_vendor_request_set_transceiver_mode,
@ -55,8 +57,13 @@ static const usb_request_handler_fn vendor_request_handler[] = {
usb_vendor_request_read_si5351c,
usb_vendor_request_set_sample_rate_frac,
usb_vendor_request_set_baseband_filter_bandwidth,
#ifdef RAD1O
NULL, // write_rffc5071 not used
NULL, // read_rffc5071 not used
#else
usb_vendor_request_write_rffc5071,
usb_vendor_request_read_rffc5071,
#endif
usb_vendor_request_erase_spiflash,
usb_vendor_request_write_spiflash,
usb_vendor_request_read_spiflash,
@ -154,8 +161,11 @@ void usb_set_descriptor_by_serial_number(void)
int main(void) {
pin_setup();
enable_1v8_power();
#ifdef HACKRF_ONE
#if (defined HACKRF_ONE || defined RAD1O)
enable_rf_power();
/* Let the voltage stabilize */
delay(1000000);
#endif
cpu_clock_init();
@ -176,6 +186,8 @@ int main(void) {
nvic_set_priority(NVIC_USB0_IRQ, 255);
hackrf_ui_init();
usb_run(&usb_device);
rf_path_init(&rf_path);

View File

@ -107,6 +107,7 @@ usb_request_status_t usb_vendor_request_read_si5351c(
}
}
#ifndef RAD1O
usb_request_status_t usb_vendor_request_write_rffc5071(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
@ -115,7 +116,7 @@ usb_request_status_t usb_vendor_request_write_rffc5071(
{
if( endpoint->setup.index < RFFC5071_NUM_REGS )
{
rffc5071_reg_write(&rffc5072, endpoint->setup.index, endpoint->setup.value);
rffc5071_reg_write(&mixer, endpoint->setup.index, endpoint->setup.value);
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
}
@ -134,7 +135,7 @@ usb_request_status_t usb_vendor_request_read_rffc5071(
{
if( endpoint->setup.index < RFFC5071_NUM_REGS )
{
value = rffc5071_reg_read(&rffc5072, endpoint->setup.index);
value = rffc5071_reg_read(&mixer, endpoint->setup.index);
endpoint->buffer[0] = value & 0xff;
endpoint->buffer[1] = value >> 8;
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2,
@ -147,3 +148,4 @@ usb_request_status_t usb_vendor_request_read_rffc5071(
return USB_REQUEST_STATUS_OK;
}
}
#endif

View File

@ -22,6 +22,7 @@
#include "usb_api_transceiver.h"
#include "hackrf-ui.h"
#include <libopencm3/cm3/vector.h>
#include <libopencm3/lpc43xx/m4/nvic.h>
#include "sgpio_isr.h"
@ -152,6 +153,7 @@ usb_request_status_t usb_vendor_request_set_lna_gain(
if( stage == USB_TRANSFER_STAGE_SETUP ) {
const uint8_t value = max2837_set_lna_gain(&max2837, endpoint->setup.index);
endpoint->buffer[0] = value;
if(value) hackrf_ui_setBBLNAGain(endpoint->setup.index);
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
NULL, NULL);
usb_transfer_schedule_ack(endpoint->out);
@ -166,6 +168,7 @@ usb_request_status_t usb_vendor_request_set_vga_gain(
if( stage == USB_TRANSFER_STAGE_SETUP ) {
const uint8_t value = max2837_set_vga_gain(&max2837, endpoint->setup.index);
endpoint->buffer[0] = value;
if(value) hackrf_ui_setBBVGAGain(endpoint->setup.index);
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
NULL, NULL);
usb_transfer_schedule_ack(endpoint->out);
@ -180,6 +183,7 @@ usb_request_status_t usb_vendor_request_set_txvga_gain(
if( stage == USB_TRANSFER_STAGE_SETUP ) {
const uint8_t value = max2837_set_txvga_gain(&max2837, endpoint->setup.index);
endpoint->buffer[0] = value;
if(value) hackrf_ui_setBBTXVGAGain(endpoint->setup.index);
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
NULL, NULL);
usb_transfer_schedule_ack(endpoint->out);

View File

@ -30,6 +30,8 @@
#define USB_PRODUCT_ID (0x6089)
#elif JAWBREAKER
#define USB_PRODUCT_ID (0x604B)
#elif RAD1O
#define USB_PRODUCT_ID (0xCC15)
#else
#define USB_PRODUCT_ID (0xFFFF)
#endif

View File

@ -36,7 +36,7 @@ int main(void)
ssp1_set_mode_max2837();
max2837_setup(&max2837);
rffc5071_setup(&rffc5072);
mixer_setup(&mixer);
led_on(LED2);
max2837_set_frequency(&max2837, freq);