diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index e0978bb0..b4629921 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -36,6 +36,7 @@ extern "C" #define BOARD_ID_JELLYBEAN 0 #define BOARD_ID_JAWBREAKER 1 #define BOARD_ID_HACKRF_ONE 2 +#define BOARD_ID_RAD10 3 #ifdef JELLYBEAN #define BOARD_ID BOARD_ID_JELLYBEAN @@ -49,6 +50,10 @@ extern "C" #define BOARD_ID BOARD_ID_HACKRF_ONE #endif +#ifdef RAD10 +#define BOARD_ID BOARD_ID_RAD10 +#endif + /* * SCU PinMux */ @@ -104,7 +109,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 RAD10) #define SCU_PINMUX_SGPIO8 (P9_6) #endif #define SCU_PINMUX_SGPIO9 (P4_3) diff --git a/firmware/common/max2871.c b/firmware/common/max2871.c index 387a2e25..3e454978 100644 --- a/firmware/common/max2871.c +++ b/firmware/common/max2871.c @@ -1,3 +1,5 @@ +#include + /* * - The input is fixed to 50 MHz * f_REF = 50 MHz @@ -113,3 +115,32 @@ * f_ERROR range: 0 MHz - 1 MHz * */ + +void mixer_init(void) +{} +void mixer_setup(void) +{} + +/* Set frequency (MHz). */ +uint64_t mixer_set_frequency(uint16_t mhz) +{ + (void) mhz; + return mhz; +} + +void mixer_tx(void) +{} +void mixer_rx(void) +{} +void mixer_rxtx(void) +{} +void mixer_enable(void) +{} +void mixer_disable(void) +{} +void mixer_set_gpo(uint8_t gpo) +{ + (void) gpo; +} + + diff --git a/firmware/common/mixer.h b/firmware/common/mixer.h new file mode 100644 index 00000000..1ee30057 --- /dev/null +++ b/firmware/common/mixer.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012 Michael Ossmann + * Copyright 2014 Jared Boone + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __MIXER_H +#define __MIXER_H + +/* Initialize chip. Call _setup() externally, as it calls _init(). */ +extern void mixer_init(void); +extern void mixer_setup(void); + +/* Set frequency (MHz). */ +extern uint64_t mixer_set_frequency(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(void); +extern void mixer_rx(void); +extern void mixer_rxtx(void); +extern void mixer_enable(void); +extern void mixer_disable(void); + +extern void mixer_set_gpo(uint8_t); + +#endif // __MIXER_H diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 46aaac44..36507df6 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -27,12 +27,12 @@ #include -#include +#include #include #include #include -#if (defined JAWBREAKER || defined HACKRF_ONE) +#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD10) /* * RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on * the RFFC5072. @@ -41,6 +41,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 rad10 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 */ @@ -83,6 +86,83 @@ uint8_t switchctrl = SWITCHCTRL_SAFE; */ #define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */ +#ifdef RAD10 +static void switchctrl_set_rad10(uint8_t ctrl) { + (void)ctrl; +#if 0 + if (ctrl & SWITCHCTRL_TX) { + gpio_set(PORT_TX, PIN_TX); + gpio_clear(PORT_RX, PIN_RX); + } else { + gpio_clear(PORT_TX, PIN_TX); + gpio_set(PORT_RX, PIN_RX); + } + + if (ctrl & SWITCHCTRL_MIX_BYPASS) { + gpio_set(PORT_MIX_BYPASS, PIN_MIX_BYPASS); + gpio_clear(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS); + if (ctrl & SWITCHCTRL_TX) { + gpio_set(PORT_TX_MIX_BP, PIN_TX_MIX_BP); + gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP); + } else { + gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP); + gpio_set(PORT_RX_MIX_BP, PIN_RX_MIX_BP); + } + } else { + gpio_clear(PORT_MIX_BYPASS, PIN_MIX_BYPASS); + gpio_set(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS); + gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP); + gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP); + } + + if (ctrl & SWITCHCTRL_HP) { + gpio_set(PORT_HP, PIN_HP); + gpio_clear(PORT_LP, PIN_LP); + } else { + gpio_clear(PORT_HP, PIN_HP); + gpio_set(PORT_LP, PIN_LP); + } + + if (ctrl & SWITCHCTRL_AMP_BYPASS) { + gpio_set(PORT_AMP_BYPASS, PIN_AMP_BYPASS); + gpio_clear(PORT_TX_AMP, PIN_TX_AMP); + gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR); + gpio_clear(PORT_RX_AMP, PIN_RX_AMP); + gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR); + } else if (ctrl & SWITCHCTRL_TX) { + gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS); + gpio_set(PORT_TX_AMP, PIN_TX_AMP); + gpio_clear(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR); + gpio_clear(PORT_RX_AMP, PIN_RX_AMP); + gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR); + } else { + gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS); + gpio_clear(PORT_TX_AMP, PIN_TX_AMP); + gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR); + gpio_set(PORT_RX_AMP, PIN_RX_AMP); + gpio_clear(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR); + } + + /* + * 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_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR); + if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR) + gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR); + + if (ctrl & SWITCHCTRL_ANT_PWR) { + mixer_set_gpo(0x00); /* turn on antenna power by clearing GPO1 */ + } else { + mixer_set_gpo(0x01); /* turn off antenna power by setting GPO1 */ + } +#endif +} +#endif + + #ifdef HACKRF_ONE static void switchctrl_set_hackrf_one(uint8_t ctrl) { if (ctrl & SWITCHCTRL_TX) { @@ -149,18 +229,20 @@ static void switchctrl_set_hackrf_one(uint8_t ctrl) { gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR); if (ctrl & SWITCHCTRL_ANT_PWR) { - rffc5071_set_gpo(0x00); /* turn on antenna power by clearing GPO1 */ + mixer_set_gpo(0x00); /* turn on antenna power by clearing GPO1 */ } else { - rffc5071_set_gpo(0x01); /* turn off antenna power by setting GPO1 */ + mixer_set_gpo(0x01); /* turn off antenna power by setting GPO1 */ } } #endif static void switchctrl_set(const uint8_t gpo) { #ifdef JAWBREAKER - rffc5071_set_gpo(gpo); + mixer_set_gpo(gpo); #elif HACKRF_ONE switchctrl_set_hackrf_one(gpo); +#elif RAD10 + switchctrl_set_rad10(gpo); #else (void)gpo; #endif @@ -215,7 +297,7 @@ void rf_path_init(void) { max2837_setup(); max2837_start(); - rffc5071_setup(); + mixer_setup(); switchctrl_set(switchctrl); } @@ -229,11 +311,11 @@ void rf_path_set_direction(const rf_path_direction_t direction) { /* TX amplifier is in path, be sure to enable TX amplifier. */ switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR; } - rffc5071_tx(); + mixer_tx(); if( switchctrl & SWITCHCTRL_MIX_BYPASS ) { - rffc5071_disable(); + mixer_disable(); } else { - rffc5071_enable(); + mixer_enable(); } ssp1_set_mode_max5864(); max5864_tx(); @@ -248,11 +330,11 @@ void rf_path_set_direction(const rf_path_direction_t direction) { /* RX amplifier is in path, be sure to enable RX amplifier. */ switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR; } - rffc5071_rx(); + mixer_rx(); if( switchctrl & SWITCHCTRL_MIX_BYPASS ) { - rffc5071_disable(); + mixer_disable(); } else { - rffc5071_enable(); + mixer_enable(); } ssp1_set_mode_max5864(); max5864_rx(); @@ -268,7 +350,7 @@ void rf_path_set_direction(const rf_path_direction_t direction) { #endif /* Set RF path to receive direction when "off" */ switchctrl &= ~SWITCHCTRL_TX; - rffc5071_disable(); + mixer_disable(); ssp1_set_mode_max5864(); max5864_standby(); ssp1_set_mode_max2837(); @@ -285,18 +367,18 @@ void rf_path_set_filter(const rf_path_filter_t filter) { default: case RF_PATH_FILTER_BYPASS: switchctrl |= SWITCHCTRL_MIX_BYPASS; - rffc5071_disable(); + mixer_disable(); break; case RF_PATH_FILTER_LOW_PASS: switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS); - rffc5071_enable(); + mixer_enable(); break; case RF_PATH_FILTER_HIGH_PASS: switchctrl &= ~SWITCHCTRL_MIX_BYPASS; switchctrl |= SWITCHCTRL_HP; - rffc5071_enable(); + mixer_enable(); break; } diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 96745eb4..4a31c38f 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -33,6 +33,7 @@ #include #include +#include "mixer.h" #include "rffc5071.h" #include "rffc5071_regs.def" // private register def macros @@ -87,9 +88,9 @@ uint16_t rffc5071_regs[RFFC5071_NUM_REGS]; uint32_t rffc5071_regs_dirty = 0x7fffffff; /* Set up all registers according to defaults specified in docs. */ -void rffc5071_init(void) +void mixer_init(void) { - LOG("# rffc5071_init\n"); + LOG("# mixer_init\n"); memcpy(rffc5071_regs, rffc5071_regs_default, sizeof(rffc5071_regs)); rffc5071_regs_dirty = 0x7fffffff; @@ -101,10 +102,10 @@ void rffc5071_init(void) * Set up pins for GPIO and SPI control, configure SSP peripheral for SPI, and * set our own default register configuration. */ -void rffc5071_setup(void) +void mixer_setup(void) { - rffc5071_init(); - LOG("# rffc5071_setup\n"); + mixer_init(); + LOG("# mixer_setup\n"); #if !defined TEST /* Configure GPIO pins. */ scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST); @@ -363,7 +364,7 @@ void rffc5071_regs_commit(void) } } -void rffc5071_tx(void) { +void mixer_tx(void) { LOG("# rffc5071_tx\n"); set_RFFC5071_ENBL(0); set_RFFC5071_FULLD(0); @@ -371,7 +372,7 @@ void rffc5071_tx(void) { rffc5071_regs_commit(); } -void rffc5071_rx(void) { +void mixer_rx(void) { LOG("# rfc5071_rx\n"); set_RFFC5071_ENBL(0); set_RFFC5071_FULLD(0); @@ -383,22 +384,22 @@ void rffc5071_rx(void) { * This function turns on both mixer (full-duplex) on the RFFC5071, but our * current hardware designs do not support full-duplex operation. */ -void rffc5071_rxtx(void) { +void mixer_rxtx(void) { LOG("# rfc5071_rxtx\n"); set_RFFC5071_ENBL(0); set_RFFC5071_FULLD(1); /* mixer 1 and mixer 2 (RXTX) */ rffc5071_regs_commit(); - rffc5071_enable(); + mixer_enable(); } -void rffc5071_disable(void) { +void mixer_disable(void) { LOG("# rfc5071_disable\n"); set_RFFC5071_ENBL(0); rffc5071_regs_commit(); } -void rffc5071_enable(void) { +void mixer_enable(void) { LOG("# rfc5071_enable\n"); set_RFFC5071_ENBL(1); rffc5071_regs_commit(); @@ -475,17 +476,17 @@ uint64_t rffc5071_config_synth_int(uint16_t lo) { } /* !!!!!!!!!!! hz is currently ignored !!!!!!!!!!! */ -uint64_t rffc5071_set_frequency(uint16_t mhz) { +uint64_t mixer_set_frequency(uint16_t mhz) { uint32_t tune_freq; - rffc5071_disable(); + mixer_disable(); tune_freq = rffc5071_config_synth_int(mhz); - rffc5071_enable(); + mixer_enable(); return tune_freq; } -void rffc5071_set_gpo(uint8_t gpo) +void mixer_set_gpo(uint8_t gpo) { /* We set GPO for both paths just in case. */ set_RFFC5071_P1GPO(gpo); @@ -497,18 +498,18 @@ void rffc5071_set_gpo(uint8_t gpo) #ifdef TEST int main(int ac, char **av) { - rffc5071_setup(); + mixer_setup(); rffc5071_tx(0); - rffc5071_set_frequency(500, 0); - rffc5071_set_frequency(525, 0); - rffc5071_set_frequency(550, 0); - rffc5071_set_frequency(1500, 0); - rffc5071_set_frequency(1525, 0); - rffc5071_set_frequency(1550, 0); - rffc5071_disable(); - rffc5071_rx(0); - rffc5071_disable(); - rffc5071_rxtx(); - rffc5071_disable(); + mixer_set_frequency(500, 0); + mixer_set_frequency(525, 0); + mixer_set_frequency(550, 0); + mixer_set_frequency(1500, 0); + mixer_set_frequency(1525, 0); + mixer_set_frequency(1550, 0); + mixer_disable(); + mixer_rx(0); + mixer_disable(); + mixer_rxtx(); + mixer_disable(); } #endif //TEST diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 98c31a3e..fa72c3b6 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -32,10 +32,6 @@ extern uint32_t rffc5071_regs_dirty; #define RFFC5071_REG_SET_CLEAN(r) rffc5071_regs_dirty &= ~(1UL< +#include #include #include @@ -53,9 +53,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; @@ -69,16 +69,16 @@ bool set_freq(const uint64_t freq) rf_path_set_filter(RF_PATH_FILTER_LOW_PASS); /* 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; + 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(RFFC5071_freq_mhz); - max2837_set_frequency(real_RFFC5071_freq_hz - freq); + real_mixer_freq_hz = mixer_set_frequency(mixer_freq_mhz); + max2837_set_frequency(real_mixer_freq_hz - freq); sgpio_cpld_stream_rx_set_q_invert(1); }else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) { rf_path_set_filter(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_freq_hz); sgpio_cpld_stream_rx_set_q_invert(0); }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ) ) @@ -94,10 +94,10 @@ bool set_freq(const uint64_t freq) max2837_freq_nominal_hz = 2500000000 + ((freq - 5100000000) / 9); } rf_path_set_filter(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(RFFC5071_freq_mhz); - max2837_set_frequency(freq - real_RFFC5071_freq_hz); + real_mixer_freq_hz = mixer_set_frequency(mixer_freq_mhz); + max2837_set_frequency(freq - real_mixer_freq_hz); sgpio_cpld_stream_rx_set_q_invert(0); }else { @@ -136,7 +136,7 @@ bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz, sgpio_cpld_stream_rx_set_q_invert(0); } if (path != RF_PATH_FILTER_BYPASS) { - (void)rffc5071_set_frequency(lo_freq_hz / FREQ_ONE_MHZ); + (void)mixer_set_frequency(lo_freq_hz / FREQ_ONE_MHZ); } return true; } diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index df5d5c96..d2581ac1 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -59,6 +59,12 @@ else() set(MCU_PARTNO LPC4330) endif() +if(BOARD STREQUAL "RAD10") + set(MIXER max2871) +else() + set(MIXER rffc5071) +endif() + if(NOT DEFINED SRC_M0) set(SRC_M0 "${PATH_HACKRF_FIRMWARE_COMMON}/m0_sleep.c") endif() @@ -136,7 +142,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c - ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c + ${PATH_HACKRF_FIRMWARE_COMMON}/${MIXER}.c m0_bin.s ) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index e842d82b..53f41505 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -116,8 +116,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 RAD10 + NULL, + NULL, +#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, diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index d822c924..ac8f7e70 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -25,7 +25,10 @@ #include #include #include + +#ifndef RAD10 #include +#endif #include #include @@ -105,6 +108,7 @@ usb_request_status_t usb_vendor_request_read_si5351c( } } +#ifndef RAD10 usb_request_status_t usb_vendor_request_write_rffc5071( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage @@ -145,3 +149,4 @@ usb_request_status_t usb_vendor_request_read_rffc5071( return USB_REQUEST_STATUS_OK; } } +#endif