diff --git a/IO.cpp b/IO.cpp index 00521aa..b419cfe 100644 --- a/IO.cpp +++ b/IO.cpp @@ -1,8 +1,8 @@ /* * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU - * Copyright (C) 2017 by Danilo DB4PLE - + * Copyright (C) 2017 by Danilo DB4PLE + * 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 of the License, or @@ -105,9 +105,9 @@ void CIO::process() uint8_t bit; uint32_t scantime; uint8_t control; - + m_ledCount++; - + if (m_started) { // Two seconds timeout if (m_watchdog >= 19200U) { @@ -194,7 +194,7 @@ void CIO::process() if (m_rxBuffer.getData() >= 1U) { m_rxBuffer.get(bit, control); - + switch (m_modemState_prev) { case STATE_DSTAR: dstarRX.databit(bit); @@ -229,9 +229,9 @@ void CIO::process() } void CIO::start() -{ +{ m_TotalModes = 0U; - + if(m_dstarEnable) { m_Modes[m_TotalModes] = STATE_DSTAR; m_TotalModes++; @@ -252,7 +252,7 @@ void CIO::start() m_Modes[m_TotalModes] = STATE_NXDN; m_TotalModes++; } - + #if defined(ENABLE_SCAN_MODE) if(m_TotalModes > 1U) m_scanEnable = true; @@ -267,9 +267,9 @@ void CIO::start() if (m_started) return; - + startInt(); - + m_started = true; } @@ -284,7 +284,7 @@ void CIO::write(uint8_t* data, uint16_t length, const uint8_t* control) else m_txBuffer.put(data[i], control[i]); } - + // Switch the transmitter on if needed if (!m_tx) { setTX(); @@ -338,6 +338,30 @@ uint8_t CIO::setFreq(uint32_t frequency_rx, uint32_t frequency_tx, uint8_t rf_po return 4U; #endif +// Check if we have a single, dualband or duplex board +#if defined (ZUMSPOT_ADF7021) + if (!(io.hasSingleADF7021())) { + // There are two ADF7021s on the board + if (io.isDualBand()) { + // Dual band + if ((frequency_tx <= VHF2_MAX) && (frequency_rx <= VHF2_MAX)) { + // Turn on VHF side + io.setBandVHF(true); + } else if ((frequency_tx >= UHF1_MIN) && (frequency_rx >= UHF1_MIN)) { + // Turn on UHF side + io.setBandVHF(false); + } + } else if (!io.isDualBand()) { + // Duplex board + if ((frequency_tx < UHF1_MIN) || (frequency_rx < UHF1_MIN)) { + // Reject VHF frequencies + return 4U; + } + } + } + +#endif + // Configure frequency m_frequency_rx = frequency_rx; m_frequency_tx = frequency_tx; diff --git a/IO.h b/IO.h index b455cff..bbc546b 100644 --- a/IO.h +++ b/IO.h @@ -1,8 +1,8 @@ /* * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU - * Copyright (C) 2017 by Danilo DB4PLE - + * Copyright (C) 2017 by Danilo DB4PLE + * 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 of the License, or @@ -124,6 +124,9 @@ public: uint32_t getWatchdog(void); void getIntCounter(uint16_t &int1, uint16_t &int2); void selfTest(void); + void setBandVHF(bool vhf_on); + bool hasSingleADF7021(void); + bool isDualBand(void); // RF interface API void setTX(void); @@ -164,7 +167,7 @@ private: uint16_t m_RX_F_divider; uint8_t m_TX_N_divider; uint16_t m_TX_F_divider; - + bool m_started; CBitRB m_rxBuffer; CBitRB m_txBuffer; diff --git a/IOSTM.cpp b/IOSTM.cpp index 5b77e04..6c75837 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -115,6 +115,15 @@ #define PIN_RXD GPIO_Pin_4 #define PORT_RXD GPIOB +#define PIN_SGL_DBL GPIO_Pin_12 +#define PORT_SGL_DBL GPIOA + +#define PIN_DL_DPX GPIO_Pin_15 +#define PORT_DL_DPX GPIOC + +#define PIN_SET_BAND GPIO_Pin_15 +#define PORT_SET_BAND GPIOA + // TXD used in SPI Data mode of ADF7021 // TXD is TxRxCLK of ADF7021, standard TX/RX data interface #define PIN_TXD GPIO_Pin_3 @@ -122,6 +131,17 @@ #define PIN_TXD_INT GPIO_PinSource3 #define PORT_TXD_INT GPIO_PortSourceGPIOB +#if defined(DUPLEX) +#define PIN_RXD2 GPIO_Pin_11 +#define PORT_RXD2 GPIOA + +// TXD2 is TxRxCLK of the second ADF7021, standard TX/RX data interface +#define PIN_TXD2 GPIO_Pin_8 +#define PORT_TXD2 GPIOA +#define PIN_TXD2_INT GPIO_PinSource8 +#define PORT_TXD2_INT GPIO_PortSourceGPIOA +#endif + // CLKOUT used in SPI Data mode of ADF7021 #define PIN_CLKOUT GPIO_Pin_15 #define PORT_CLKOUT GPIOA @@ -280,10 +300,17 @@ extern "C" { #if defined(DUPLEX) void EXTI9_5_IRQHandler(void) { + #if defined(ZUMSPOT_ADF7021) + if(EXTI_GetITStatus(EXTI_Line8)!=RESET) { + io.interrupt2(); + EXTI_ClearITPendingBit(EXTI_Line8); + } + #else if(EXTI_GetITStatus(EXTI_Line5)!=RESET) { io.interrupt2(); EXTI_ClearITPendingBit(EXTI_Line5); } + #endif } #endif @@ -301,13 +328,37 @@ void CIO::Init() #endif RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); - + #if defined(PI_HAT_7021_REV_02) GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); #elif defined(ZUMSPOT_ADF7021) || defined(LIBRE_KIT_ADF7021) || defined(MMDVM_HS_HAT_REV12) || defined(MMDVM_HS_DUAL_HAT_REV10) || defined(NANO_HOTSPOT) || defined(NANO_DV_REV11) || defined(D2RG_MMDVM_HS) GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); #endif +#if defined(ZUMSPOT_ADF7021) + // Pin defines if the board has a single ADF7021 or double + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_Pin = PIN_SGL_DBL; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; + GPIO_Init(PORT_SGL_DBL, &GPIO_InitStruct); + + // Pin defines if the board is dual band or duplex + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_Pin = PIN_DL_DPX; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; + GPIO_Init(PORT_DL_DPX, &GPIO_InitStruct); + + // Pin will set UHF or VHF + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_Pin = PIN_SET_BAND; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_Init(PORT_SET_BAND, &GPIO_InitStruct); + // TODO: Remove this line + // GPIO_WriteBit(PORT_SET_BAND, PIN_SET_BAND, Bit_RESET); + +#endif + +#if defined(STM32_USB_HOST) // Pin PA11,PA12 = LOW, USB Reset GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; @@ -316,6 +367,8 @@ void CIO::Init() GPIO_WriteBit(GPIOA, GPIO_Pin_11, Bit_RESET); GPIO_WriteBit(GPIOA, GPIO_Pin_12, Bit_RESET); +#endif + #if defined(LONG_USB_RESET) // 10 ms delay delay_us(10000U); @@ -343,7 +396,7 @@ void CIO::Init() GPIO_InitStruct.GPIO_Pin = PIN_SDATA; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_SDATA, &GPIO_InitStruct); - + // Pin SREAD GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_SREAD; @@ -355,14 +408,14 @@ void CIO::Init() GPIO_InitStruct.GPIO_Pin = PIN_SLE; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_SLE, &GPIO_InitStruct); - + #if defined(DUPLEX) // Pin SLE2 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_SLE2; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_SLE2, &GPIO_InitStruct); - + // Pin RXD2 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_RXD2; @@ -393,6 +446,7 @@ void CIO::Init() #endif GPIO_Init(PORT_TXD, &GPIO_InitStruct); #if defined(DUPLEX) + GPIO_InitStruct.GPIO_Pin = PIN_TXD2; GPIO_Init(PORT_TXD2, &GPIO_InitStruct); #endif @@ -403,7 +457,7 @@ void CIO::Init() GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(PORT_CLKOUT, &GPIO_InitStruct); #endif - + // Pin LED GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_LED; @@ -416,37 +470,37 @@ void CIO::Init() GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_DEB, &GPIO_InitStruct); - // D-Star LED + // D-Star LED GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_DSTAR_LED; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_DSTAR_LED, &GPIO_InitStruct); - // DMR LED + // DMR LED GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_DMR_LED; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_DMR_LED, &GPIO_InitStruct); - // YSF LED + // YSF LED GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_YSF_LED; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_YSF_LED, &GPIO_InitStruct); - // P25 LED + // P25 LED GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_P25_LED; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_P25_LED, &GPIO_InitStruct); - // NXDN LED + // NXDN LED GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_NXDN_LED; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_NXDN_LED, &GPIO_InitStruct); - // POCSAG LED + // POCSAG LED GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_POCSAG_LED; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; @@ -458,7 +512,7 @@ void CIO::Init() GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_PTT_LED, &GPIO_InitStruct); - // COS LED + // COS LED GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_COS_LED; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; @@ -496,7 +550,11 @@ void CIO::Init() // Connect EXTI5 Line GPIO_EXTILineConfig(PORT_TXD2_INT, PIN_TXD2_INT); // Configure EXT5 line + #if defined(ZUMSPOT_ADF7021) + EXTI_InitStructure2.EXTI_Line = EXTI_Line8; + #else EXTI_InitStructure2.EXTI_Line = EXTI_Line5; + #endif #endif #endif @@ -505,7 +563,7 @@ void CIO::Init() EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); - + #if defined(DUPLEX) EXTI_InitStructure2.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure2.EXTI_Trigger = EXTI_Trigger_Rising; @@ -517,7 +575,7 @@ void CIO::Init() void CIO::startInt() { NVIC_InitTypeDef NVIC_InitStructure; - + #if defined(DUPLEX) NVIC_InitTypeDef NVIC_InitStructure2; #endif @@ -546,7 +604,7 @@ void CIO::startInt() NVIC_InitStructure.NVIC_IRQChannelSubPriority = 15; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); - + #if defined(DUPLEX) NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure2.NVIC_IRQChannelSubPriority = 15; @@ -557,18 +615,18 @@ void CIO::startInt() #if defined(BIDIR_DATA_PIN) // RXD pin is bidirectional in standard interfaces -void CIO::Data_dir_out(bool dir) +void CIO::Data_dir_out(bool dir) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = PIN_RXD; - + if(dir) GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; else GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; - + GPIO_Init(PORT_RXD, &GPIO_InitStruct); } #endif @@ -696,6 +754,17 @@ void CIO::COS_pin(bool on) GPIO_WriteBit(PORT_COS_LED, PIN_COS_LED, on ? Bit_SET : Bit_RESET); } +void CIO::setBandVHF(bool vhf_on) { + GPIO_WriteBit(PORT_SET_BAND, PIN_SET_BAND, vhf_on ? Bit_SET : Bit_RESET); +} + +bool CIO::hasSingleADF7021() { + return GPIO_ReadInputDataBit(PORT_SGL_DBL, PIN_SGL_DBL) == Bit_SET; +} + +bool CIO::isDualBand() { + return GPIO_ReadInputDataBit(PORT_DL_DPX, PIN_DL_DPX) == Bit_SET; +} /** * Function delay_us() from stm32duino project diff --git a/SerialPort.cpp b/SerialPort.cpp index ea0af12..917a2d8 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -318,6 +318,11 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) DEBUG1("Full duplex not supported with this firmware"); return 6U; } +#elif defined(DUPLEX) && defined(ZUMSPOT_ADF7021) + if (io.isDualBand() && m_duplex && m_calState == STATE_IDLE && modemState != STATE_DSTARCAL) { + DEBUG1("Full duplex is not supported on this board"); + return 6U; + } #endif dstarTX.setTXDelay(txDelay); diff --git a/configs/ZUMspot_dualband.h b/configs/ZUMspot_dualband.h new file mode 100644 index 0000000..f21c673 --- /dev/null +++ b/configs/ZUMspot_dualband.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2017,2018,2019 by Andy Uribe CA6JAU + * + * 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 of the License, 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(CONFIG_H) +#define CONFIG_H + +// Select one board (STM32F103 based boards) +// 1) ZUMspot RPi or ZUMspot USB: +#define ZUMSPOT_ADF7021 +// 2) Libre Kit board or any homebrew hotspot with modified RF7021SE and Blue Pill STM32F103: +// #define LIBRE_KIT_ADF7021 +// 3) MMDVM_HS_Hat revisions 1.1, 1.2 and 1.4 (DB9MAT & DF2ET) +// #define MMDVM_HS_HAT_REV12 +// 4) MMDVM_HS_Dual_Hat revisions 1.0 (DB9MAT & DF2ET & DO7EN) +// #define MMDVM_HS_DUAL_HAT_REV10 +// 5) Nano hotSPOT (BI7JTA) +// #define NANO_HOTSPOT +// 6) NanoDV NPi or USB revisions 1.0 (BG4TGO & BG5HHP) +// #define NANO_DV_REV10 + +// Enable ADF7021 support: +#define ENABLE_ADF7021 + +// Enable full duplex support with dual ADF7021 (valid for homebrew hotspots only): +// #define DUPLEX + +// TCXO of the ADF7021 +// For 14.7456 MHz: +#define ADF7021_14_7456 +// For 12.2880 MHz: +// #define ADF7021_12_2880 + +// Configure receiver gain for ADF7021 +// AGC automatic, default settings: +#define AD7021_GAIN_AUTO +// AGC automatic with high LNA linearity: +// #define AD7021_GAIN_AUTO_LIN +// AGC OFF, lowest gain: +// #define AD7021_GAIN_LOW +// AGC OFF, highest gain: +// #define AD7021_GAIN_HIGH + +// Host communication selection: +#define STM32_USART1_HOST +// #define STM32_USB_HOST +// #define STM32_I2C_HOST + +// I2C host address: +#define I2C_ADDR 0x22 + +// Enable mode detection: +#define ENABLE_SCAN_MODE + +// Send RSSI value: +#define SEND_RSSI_DATA + +// Enable Nextion LCD serial port repeater on USART2 (ZUMspot Libre Kit and ZUMspot RPi): +#define SERIAL_REPEATER +#define SERIAL_REPEATER_BAUD 9600 + +// Enable Nextion LCD serial port repeater on USART1 (Do not use with STM32_USART1_HOST enabled): +// #define SERIAL_REPEATER_USART1 + +// Enable P25 Wide modulation: +// #define ENABLE_P25_WIDE + +// Disable mode LEDs blink during scan mode: +// #define QUIET_MODE_LEDS + +// Engage a constant or descreet Service LED mode once repeater is running +// #define CONSTANT_SRV_LED +// #define CONSTANT_SRV_LED_INVERTED +// #define DISCREET_SRV_LED +// #define DISCREET_SRV_LED_INVERTED + +// Use the YSF and P25 LEDs for NXDN +// #define USE_ALTERNATE_NXDN_LEDS + +// Use the D-Star and DMR LEDs for POCSAG +// #define USE_ALTERNATE_POCSAG_LEDS + +// Enable for RPi 3B+, USB mode +// #define LONG_USB_RESET + +// Enable modem debug messages +#define ENABLE_DEBUG + +// Disable frequency bands check +// #define DISABLE_FREQ_CHECK + +// Disable frequency restrictions (satellite, ISS, etc) +// #define DISABLE_FREQ_BAN + +#endif diff --git a/configs/ZUMspot_duplex.h b/configs/ZUMspot_duplex.h index 1a5a05d..e90676f 100644 --- a/configs/ZUMspot_duplex.h +++ b/configs/ZUMspot_duplex.h @@ -21,9 +21,9 @@ // Select one board (STM32F103 based boards) // 1) ZUMspot RPi or ZUMspot USB: -// #define ZUMSPOT_ADF7021 +#define ZUMSPOT_ADF7021 // 2) Libre Kit board or any homebrew hotspot with modified RF7021SE and Blue Pill STM32F103: -#define LIBRE_KIT_ADF7021 +// #define LIBRE_KIT_ADF7021 // 3) MMDVM_HS_Hat revisions 1.1, 1.2 and 1.4 (DB9MAT & DF2ET) // #define MMDVM_HS_HAT_REV12 // 4) MMDVM_HS_Dual_Hat revisions 1.0 (DB9MAT & DF2ET & DO7EN) @@ -52,14 +52,14 @@ #define AD7021_GAIN_AUTO // AGC automatic with high LNA linearity: // #define AD7021_GAIN_AUTO_LIN -// AGC OFF, lowest gain: +// AGC OFF, lowest gain: // #define AD7021_GAIN_LOW // AGC OFF, highest gain: // #define AD7021_GAIN_HIGH // Host communication selection: -// #define STM32_USART1_HOST -#define STM32_USB_HOST +#define STM32_USART1_HOST +// #define STM32_USB_HOST // #define STM32_I2C_HOST // I2C host address: @@ -69,7 +69,7 @@ #define ENABLE_SCAN_MODE // Send RSSI value: -// #define SEND_RSSI_DATA +#define SEND_RSSI_DATA // Enable Nextion LCD serial port repeater on USART2 (ZUMspot Libre Kit and ZUMspot RPi): #define SERIAL_REPEATER @@ -84,7 +84,7 @@ // Disable mode LEDs blink during scan mode: // #define QUIET_MODE_LEDS -// Engage a constant or descreet Service LED mode once repeater is running +// Engage a constant or descreet Service LED mode once repeater is running // #define CONSTANT_SRV_LED // #define CONSTANT_SRV_LED_INVERTED // #define DISCREET_SRV_LED @@ -97,10 +97,10 @@ // #define USE_ALTERNATE_POCSAG_LEDS // Enable for RPi 3B+, USB mode -#define LONG_USB_RESET +// #define LONG_USB_RESET // Enable modem debug messages -// #define ENABLE_DEBUG +#define ENABLE_DEBUG // Disable frequency bands check // #define DISABLE_FREQ_CHECK diff --git a/scripts/build_fw.sh b/scripts/build_fw.sh index a70ea1b..d93c0c9 100755 --- a/scripts/build_fw.sh +++ b/scripts/build_fw.sh @@ -40,10 +40,16 @@ make clean # Building ZUMspot Duplex cp ~/MMDVM_HS/configs/ZUMspot_duplex.h ~/MMDVM_HS/Config.h -make bl +make mv ~/MMDVM_HS/bin/mmdvm_f1bl.bin ~/MMDVM_HS/bin/zumspot_duplex_fw.bin make clean +# Building ZUMspot Dualband +cp ~/MMDVM_HS/configs/ZUMspot_dualband.h ~/MMDVM_HS/Config.h +make +mv ~/MMDVM_HS/bin/mmdvm_f1bl.bin ~/MMDVM_HS/bin/zumspot_dualband_fw.bin +make clean + # Building MMDVM_HS_Hat cp ~/MMDVM_HS/configs/MMDVM_HS_Hat.h ~/MMDVM_HS/Config.h make