diff --git a/Documentation/DeveloperInfo/FPGA_protocol.pdf b/Documentation/DeveloperInfo/FPGA_protocol.pdf
index c30225d..e95fab7 100644
Binary files a/Documentation/DeveloperInfo/FPGA_protocol.pdf and b/Documentation/DeveloperInfo/FPGA_protocol.pdf differ
diff --git a/Documentation/DeveloperInfo/FPGA_protocol.tex b/Documentation/DeveloperInfo/FPGA_protocol.tex
index 459343e..76e55b2 100644
--- a/Documentation/DeveloperInfo/FPGA_protocol.tex
+++ b/Documentation/DeveloperInfo/FPGA_protocol.tex
@@ -343,10 +343,10 @@ The register contains the number of points per sweep negative one, e.g. set to 1
\rwbits{9}{2}{Window[1:0]}
\rwbits{11}{1}{SCEN}
\rwbits{12}{1}{LCEN}
-\robits{13}{3}{reserved}
+\robits{13}{2}{reserved}
%\rwbits{13}{1}{EXP2}
%\rwbits{14}{1}{EXP1}
-%\rwbits{15}{1}{PSEN}
+\rwbits{15}{1}{PSEN}
\end{tikzpicture}
\end{center}
\begin{itemize}
@@ -426,7 +426,40 @@ Each point in the sweep is done in stages. Each stage consists of (optionally) r
\item \textbf{IH:} Individual halt: Sets the behavior of the "halt sweep" bit (see section~\ref{sweepconfig}). If 1, the sampling is halted before each stage. If 0, the sampling is only halted before the point and all stages are executed without additional halts inbetween.
\item \textbf{Port 1 stage} Number of stage during which the source signal is routed to port 1. Must not have the same value as Port 2 stage.
\item \textbf{Port 2 stage} Number of stage during which the source signal is routed to port 2. Must not have the same value as Port 1 stage.
+\end{itemize}
+\subsection{Hardware override register: 0x07}
+Allows overwriting hardware settings, regardless of whether a sweep is active or not.
+\label{reg:hw_override}
+\begin{center}
+\begin{tikzpicture}
+\bitrect{16}{16-\bit}
+\rwbits{0}{1}{OWE}
+\rwbits{1}{7}{Attenuator[6:0]}
+\rwbits{8}{2}{SourceFilter}
+\rwbits{10}{1}{BS}
+\rwbits{11}{1}{P1EN}
+\rwbits{12}{1}{P2EN}
+\robits{13}{3}{reserved}
+\end{tikzpicture}
+\end{center}
+\begin{itemize}
+\item \textbf{OWE:} Overwrite enable. If 1, this register is used to configure the hardware. If 0, all other bits in the register are ignored. Must be set to 0 for valid sweep operation.
+\item \textbf{Attenuator[6:0]:} Attenuator setting
+\item \textbf{SourceFilter:} Low pass filter selection for source signal
+\begin{center}
+\begin{tabular}{ c|c }
+Setting & Selected Band\\
+ \hline
+00 & \SIrange{0}{900}{\mega\hertz}\\
+01 & \SIrange{900}{1800}{\mega\hertz}\\
+10 & \SIrange{1800}{3500}{\mega\hertz}\\
+11 & \SIrange{3500}{6000}{\mega\hertz}\\
+\end{tabular}
+\end{center}
+\item \textbf{BS: Band select.} Set to 0 for highband, set to 1 for lowband.
+\item \textbf{P1EN:} Route signal to port 1. Must not be enabled at the same time as P2EN.
+\item \textbf{P2EN:} Route signal to port 2. Must not be enabled at the same time as P1EN.
\end{itemize}
\subsection{MAX2871 Default Values Registers: 0x08-0x0F}
diff --git a/FPGA/VNA/SPIConfig.vhd b/FPGA/VNA/SPIConfig.vhd
index 8503c4b..5d7aaa9 100644
--- a/FPGA/VNA/SPIConfig.vhd
+++ b/FPGA/VNA/SPIConfig.vhd
@@ -72,6 +72,10 @@ entity SPICommands is
SWEEP_HALTED : in STD_LOGIC;
SWEEP_RESUME : out STD_LOGIC;
+ -- hardware overwrite signals
+ SPI_OVERWRITE_ENABLED : out STD_LOGIC;
+ SPI_OVERWRITE_DATA : out STD_LOGIC_VECTOR(14 downto 0);
+
-- DFT signals
DFT_BIN1_PHASEINC : out STD_LOGIC_VECTOR (15 downto 0);
DFT_DIFFBIN_PHASEINC : out STD_LOGIC_VECTOR (15 downto 0);
@@ -166,6 +170,9 @@ begin
INTERRUPT_ASSERTED <= '0';
latched_result <= (others => '0');
+ SPI_OVERWRITE_ENABLED <= '0';
+ SPI_OVERWRITE_DATA <= (others => '0');
+
DFT_BIN1_PHASEINC <= (others => '0');
DFT_DIFFBIN_PHASEINC <= (others => '0');
dft_next <= '0';
@@ -249,6 +256,8 @@ begin
INDIVIDUAL_HALT <= spi_buf_out(12);
PORT1_STAGE <= spi_buf_out(5 downto 3);
PORT2_STAGE <= spi_buf_out(2 downto 0);
+ when 7 => SPI_OVERWRITE_ENABLED <= spi_buf_out(15);
+ SPI_OVERWRITE_DATA <= spi_buf_out(14 downto 0);
when 8 => MAX2871_DEF_0(15 downto 0) <= spi_buf_out;
when 9 => MAX2871_DEF_0(31 downto 16) <= spi_buf_out;
when 10 => MAX2871_DEF_1(15 downto 0) <= spi_buf_out;
diff --git a/FPGA/VNA/VNA.gise b/FPGA/VNA/VNA.gise
index 67a2b99..2f95209 100644
--- a/FPGA/VNA/VNA.gise
+++ b/FPGA/VNA/VNA.gise
@@ -224,7 +224,7 @@
-
+
@@ -253,7 +253,7 @@
-
+
@@ -275,7 +275,7 @@
-
+
@@ -284,7 +284,7 @@
-
+
@@ -298,7 +298,7 @@
-
+
@@ -312,7 +312,7 @@
-
+
@@ -365,7 +365,7 @@
-
+
diff --git a/FPGA/VNA/top.bin b/FPGA/VNA/top.bin
index 1ed3339..061f534 100644
Binary files a/FPGA/VNA/top.bin and b/FPGA/VNA/top.bin differ
diff --git a/FPGA/VNA/top.vhd b/FPGA/VNA/top.vhd
index 3879038..a3b61ac 100644
--- a/FPGA/VNA/top.vhd
+++ b/FPGA/VNA/top.vhd
@@ -268,6 +268,8 @@ architecture Behavioral of top is
RESET_MINMAX : out STD_LOGIC;
SWEEP_HALTED : in STD_LOGIC;
SWEEP_RESUME : out STD_LOGIC;
+ SPI_OVERWRITE_ENABLED : out STD_LOGIC;
+ SPI_OVERWRITE_DATA : out STD_LOGIC_VECTOR(14 downto 0);
DFT_BIN1_PHASEINC : out STD_LOGIC_VECTOR (15 downto 0);
DFT_DIFFBIN_PHASEINC : out STD_LOGIC_VECTOR (15 downto 0);
DFT_RESULT_READY : in STD_LOGIC;
@@ -339,6 +341,8 @@ architecture Behavioral of top is
signal source_unlocked : std_logic;
signal lo_unlocked : std_logic;
+ signal source_filter : std_logic_vector(1 downto 0);
+
-- ADC signals
signal adc_trigger_sample : std_logic;
signal adc_port1_ready : std_logic;
@@ -372,8 +376,9 @@ architecture Behavioral of top is
signal sweep_port2_stage : STD_LOGIC_VECTOR (2 downto 0);
signal sweep_config_data : std_logic_vector(95 downto 0);
signal sweep_config_address : std_logic_vector(12 downto 0);
- signal source_filter : std_logic_vector(1 downto 0);
+ signal sweep_source_filter : std_logic_vector(1 downto 0);
signal sweep_band : std_logic;
+ signal sweep_attenuator : std_logic_vector(6 downto 0);
signal sweep_config_write_address : std_logic_vector(12 downto 0);
signal sweep_config_write_data : std_logic_vector(95 downto 0);
@@ -419,6 +424,10 @@ architecture Behavioral of top is
signal debug : std_logic_vector(10 downto 0);
signal intr : std_logic;
+ -- HW overwrite signals
+ signal HW_overwrite_enabled : std_logic;
+ signal HW_overwrite_data : std_logic_vector(14 downto 0);
+
-- DFT signals
signal dft_bin1_phaseinc : std_logic_vector (15 downto 0);
signal dft_diffbin_phaseinc : std_logic_vector (15 downto 0);
@@ -436,20 +445,20 @@ begin
LEDS(2) <= SOURCE_LD;
LEDS(3) <= LO1_LD;
-- Sweep and active port
- PORT_SELECT2 <= sweep_excite_port2 and portswitch_en;
- PORT2_SELECT <= sweep_excite_port2 and portswitch_en;
- PORT_SELECT1 <= sweep_excite_port1 and portswitch_en;
- PORT1_SELECT <= sweep_excite_port1 and portswitch_en;
- BAND_SELECT_HIGH <= not sweep_band;
- BAND_SELECT_LOW <= sweep_band;
+ PORT_SELECT2 <= (sweep_excite_port2 and portswitch_en) when HW_overwrite_enabled = '0' else HW_overwrite_data(3);
+ PORT2_SELECT <= (sweep_excite_port2 and portswitch_en) when HW_overwrite_enabled = '0' else HW_overwrite_data(3);
+ PORT_SELECT1 <= (sweep_excite_port1 and portswitch_en) when HW_overwrite_enabled = '0' else HW_overwrite_data(4);
+ PORT1_SELECT <= (sweep_excite_port1 and portswitch_en) when HW_overwrite_enabled = '0' else HW_overwrite_data(4);
+ BAND_SELECT_HIGH <= not sweep_band when HW_overwrite_enabled = '0' else not HW_overwrite_data(5);
+ BAND_SELECT_LOW <= sweep_band when HW_overwrite_enabled = '0' else HW_overwrite_data(5);
PORT1_MIX2_EN <= port1mix_en;
PORT1_MIX1_EN <= not port1mix_en;
PORT2_MIX2_EN <= port2mix_en;
PORT2_MIX1_EN <= not port2mix_en;
REF_MIX2_EN <= refmix_en;
REF_MIX1_EN <= not refmix_en;
- LEDS(4) <= not (not sweep_reset and sweep_excite_port2 and portswitch_en);
- LEDS(5) <= not (not sweep_reset and sweep_excite_port1 and portswitch_en);
+ LEDS(4) <= not (not sweep_reset and sweep_excite_port2 and portswitch_en) when HW_overwrite_enabled = '0' else not HW_overwrite_data(3);
+ LEDS(5) <= not (not sweep_reset and sweep_excite_port1 and portswitch_en) when HW_overwrite_enabled = '0' else not HW_overwrite_data(4);
-- Uncommitted LEDs
LEDS(7 downto 6) <= user_leds(1 downto 0);
--LEDS(7) <= '0';
@@ -675,8 +684,8 @@ begin
PLL_LOCKED => plls_locked,
SWEEP_HALTED => sweep_halted,
SWEEP_RESUME => sweep_resume,
- ATTENUATOR => ATTENUATION,
- SOURCE_FILTER => source_filter,
+ ATTENUATOR => sweep_attenuator,
+ SOURCE_FILTER => sweep_source_filter,
STAGES => sweep_stages,
INDIVIDUAL_HALT => sweep_individual_halt,
PORT1_STAGE => sweep_port1_stage,
@@ -689,11 +698,14 @@ begin
);
-- Source filter mapping
+ source_filter <= sweep_source_filter when HW_overwrite_enabled = '0' else HW_overwrite_data(7 downto 6);
FILT_IN_C1 <= '0' when source_filter = "00" or source_filter = "10" else '1';
FILT_IN_C2 <= '0' when source_filter = "11" or source_filter = "10" else '1';
FILT_OUT_C1 <= '0' when source_filter = "00" or source_filter = "10" else '1';
FILT_OUT_C2 <= '0' when source_filter = "00" or source_filter = "01" else '1';
+ ATTENUATION <= sweep_attenuator when HW_overwrite_enabled = '0' else HW_overwrite_data(14 downto 8);
+
-- PLL/SPI mux
-- only select FPGA SPI slave when both AUX1 and AUX2 are low
fpga_select <= nss_sync when aux1_sync = '0' and aux2_sync = '0' else '1';
@@ -756,6 +768,8 @@ begin
INDIVIDUAL_HALT => sweep_individual_halt,
PORT1_STAGE => sweep_port1_stage,
PORT2_STAGE => sweep_port2_stage,
+ SPI_OVERWRITE_ENABLED => HW_overwrite_enabled,
+ SPI_OVERWRITE_DATA => HW_overwrite_data,
DFT_BIN1_PHASEINC => dft_bin1_phaseinc,
DFT_DIFFBIN_PHASEINC => dft_diffbin_phaseinc,
DFT_RESULT_READY => dft_ready,
diff --git a/Software/VNA_embedded/Application/App.cpp b/Software/VNA_embedded/Application/App.cpp
index 25e4322..048d4dd 100644
--- a/Software/VNA_embedded/Application/App.cpp
+++ b/Software/VNA_embedded/Application/App.cpp
@@ -259,6 +259,7 @@ inline void App_Process() {
// insert the last received packet (restarts the timed out operation)
USBPacketReceived(last_measure_packet);
}
+ HW::updateDeviceStatus();
}
}
diff --git a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp
index 7f47c4e..2181eaa 100644
--- a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp
+++ b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp
@@ -356,6 +356,27 @@ uint16_t FPGA::GetStatus() {
return (uint16_t) status[0] << 8 | status[1];
}
+void FPGA::OverwriteHardware(uint8_t attenuation, LowpassFilter filter, bool lowband, bool port1_enabled, bool port2_enabled) {
+ uint16_t val = 0;
+ val |= 0x8000; // enable overwrite
+ val |= (attenuation & 0x7F) << 8;
+ val |= (int) filter << 6;
+ if (lowband) {
+ val |= 0x0020;
+ }
+ if (port1_enabled) {
+ val |= 0x0010;
+ }
+ if (port2_enabled) {
+ val |= 0x0008;
+ }
+ WriteRegister(Reg::HardwareOverwrite, val);
+}
+
+void FPGA::DisableHardwareOverwrite() {
+ WriteRegister(Reg::HardwareOverwrite, 0x0000);
+}
+
FPGA::ADCLimits FPGA::GetADCLimits() {
uint16_t cmd = 0xE000;
SwitchBytes(cmd);
diff --git a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp
index 98cd586..149870b 100644
--- a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp
+++ b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp
@@ -18,6 +18,7 @@ enum class Reg {
ADCPrescaler = 0x04,
PhaseIncrement = 0x05,
SweepSetup = 0x06,
+ HardwareOverwrite = 0x07,
MAX2871Def0LSB = 0x08,
MAX2871Def0MSB = 0x09,
MAX2871Def1LSB = 0x0A,
@@ -134,6 +135,9 @@ void ResetADCLimits();
void ResumeHaltedSweep();
uint16_t GetStatus();
+void OverwriteHardware(uint8_t attenuation, LowpassFilter filter, bool lowband, bool port1_enabled, bool port2_enabled);
+void DisableHardwareOverwrite();
+
void StartSweep();
void AbortSweep();
diff --git a/Software/VNA_embedded/Application/Generator.cpp b/Software/VNA_embedded/Application/Generator.cpp
index acbb85c..4bdc682 100644
--- a/Software/VNA_embedded/Application/Generator.cpp
+++ b/Software/VNA_embedded/Application/Generator.cpp
@@ -2,73 +2,59 @@
#include "Generator.hpp"
#include "Manual.hpp"
#include "Hardware.hpp"
+#include "HW_HAL.hpp"
#include "max2871.hpp"
#include "Si5351C.hpp"
-void Generator::Setup(Protocol::GeneratorSettings g) {
- if(g.activePort == 0) {
- // both ports disabled, no need to configure PLLs
- HW::SetIdle();
- return;
- }
- Protocol::ManualControlV1 m;
- // LOs not required
- m.LO1CE = 0;
- m.LO1Frequency = 1000000000;
- m.LO1RFEN = 0;
- m.LO1RFEN = 0;
- m.LO2EN = 0;
- m.LO2Frequency = 60000000;
- m.Port1EN = 0;
- m.Port2EN = 0;
- m.RefEN = 0;
- m.Samples = 131072;
- m.WindowType = (int) FPGA::Window::None;
+using namespace HWHAL;
- switch(g.activePort) {
- case 1:
- m.AmplifierEN = 1;
- m.PortSwitch = 0;
- break;
- case 2:
- m.AmplifierEN = 1;
- m.PortSwitch = 1;
- break;
+void Generator::Setup(Protocol::GeneratorSettings g) {
+ HW::SetMode(HW::Mode::Generator);
+ if(g.activePort == 0) {
+ // both ports disabled, no need to configure PLLs
+ Si5351.Disable(SiChannel::LowbandSource);
+ FPGA::Disable(FPGA::Periphery::SourceChip);
+ FPGA::Disable(FPGA::Periphery::Amplifier);
+ FPGA::Disable(FPGA::Periphery::SourceRF);
+ FPGA::Disable(FPGA::Periphery::PortSwitch);
+ FPGA::DisableHardwareOverwrite();
+ return;
}
+
g.frequency = Cal::FrequencyCorrectionToDevice(g.frequency);
auto amplitude = HW::GetAmplitudeSettings(g.cdbm_level, g.frequency, g.applyAmplitudeCorrection, g.activePort == 2);
// Select correct source
+ bool bandSelect;
+ FPGA::LowpassFilter lp = FPGA::LowpassFilter::M947;
if(g.frequency < HW::BandSwitchFrequency) {
- m.SourceLowEN = 1;
- m.SourceLowFrequency = g.frequency;
- m.SourceHighCE = 0;
- m.SourceHighRFEN = 0;
- m.SourceHighFrequency = HW::BandSwitchFrequency;
- m.SourceHighLowpass = (int) FPGA::LowpassFilter::M947;
- m.SourceHighPower = (int) MAX2871::Power::n4dbm;
- m.SourceHighband = false;
- m.SourceLowPower = (int) amplitude.lowBandPower;
+ bandSelect = true;
+ FPGA::Disable(FPGA::Periphery::SourceChip);
+ Si5351.SetCLK(SiChannel::LowbandSource, g.frequency, Si5351C::PLL::B,
+ amplitude.lowBandPower);
+ Si5351.Enable(SiChannel::LowbandSource);
} else {
- m.SourceLowEN = 0;
- m.SourceLowFrequency = HW::BandSwitchFrequency;
- m.SourceHighCE = 1;
- m.SourceHighRFEN = 1;
- m.SourceHighFrequency = g.frequency;
+ bandSelect = false;
+ Si5351.Disable(SiChannel::LowbandSource);
+ FPGA::Enable(FPGA::Periphery::SourceChip);
+ FPGA::SetMode(FPGA::Mode::SourcePLL);
+ Source.SetPowerOutA(amplitude.highBandPower);
+ Source.SetFrequency(g.frequency);
+ Source.Update();
+ FPGA::SetMode(FPGA::Mode::FPGA);
if(g.frequency < 900000000UL) {
- m.SourceHighLowpass = (int) FPGA::LowpassFilter::M947;
+ lp = FPGA::LowpassFilter::M947;
} else if(g.frequency < 1800000000UL) {
- m.SourceHighLowpass = (int) FPGA::LowpassFilter::M1880;
+ lp = FPGA::LowpassFilter::M1880;
} else if(g.frequency < 3500000000UL) {
- m.SourceHighLowpass = (int) FPGA::LowpassFilter::M3500;
+ lp = FPGA::LowpassFilter::M3500;
} else {
- m.SourceHighLowpass = (int) FPGA::LowpassFilter::None;
+ lp = FPGA::LowpassFilter::None;
}
- m.SourceHighband = true;
- m.SourceHighPower = (int) amplitude.highBandPower;
- m.SourceLowPower = (int) Si5351C::DriveStrength::mA2;
}
- m.attenuator = amplitude.attenuator;
- Manual::Setup(m);
+ FPGA::OverwriteHardware(amplitude.attenuator, lp, bandSelect, g.activePort == 1, g.activePort == 2);
HW::SetOutputUnlevel(amplitude.unlevel);
+ FPGA::Enable(FPGA::Periphery::Amplifier, true);
+ FPGA::Enable(FPGA::Periphery::SourceRF, true);
+ FPGA::Enable(FPGA::Periphery::PortSwitch, true);
}
diff --git a/Software/VNA_embedded/Application/Hardware.cpp b/Software/VNA_embedded/Application/Hardware.cpp
index f4a3d0a..200d5ef 100644
--- a/Software/VNA_embedded/Application/Hardware.cpp
+++ b/Software/VNA_embedded/Application/Hardware.cpp
@@ -8,6 +8,7 @@
#include "Manual.hpp"
#include "delay.hpp"
#include "SpectrumAnalyzer.hpp"
+#include "Communication.h"
#include
#define LOG_LEVEL LOG_LEVEL_INFO
@@ -139,6 +140,8 @@ bool HW::Init() {
return false;
}
+ FPGA::DisableHardwareOverwrite();
+
// Set default ADC samplerate
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, ADCprescaler);
// Set phase increment according to
@@ -229,6 +232,7 @@ void HW::SetIdle() {
unlevel = false;
FPGA::AbortSweep();
FPGA::SetMode(FPGA::Mode::FPGA);
+ FPGA::DisableHardwareOverwrite();
FPGA::Enable(FPGA::Periphery::SourceChip, false);
FPGA::Enable(FPGA::Periphery::SourceRF, false);
FPGA::Enable(FPGA::Periphery::LO1Chip, false);
@@ -289,7 +293,7 @@ HW::AmplitudeSettings HW::GetAmplitudeSettings(int16_t cdbm, uint64_t freq, bool
bool HW::TimedOut() {
constexpr uint64_t timeout = 1000000;
- if(activeMode != Mode::Idle && Delay::get_us() - lastISR > timeout) {
+ if(activeMode != Mode::Idle && activeMode != Mode::Generator && Delay::get_us() - lastISR > timeout) {
return true;
} else {
return false;
@@ -420,6 +424,28 @@ uint64_t HW::getLastISRTimestamp() {
return lastISR;
}
+void HW::updateDeviceStatus() {
+ if(activeMode == Mode::Idle || activeMode == Mode::Generator) {
+ static uint32_t last_update = 0;
+ if(HAL_GetTick() - last_update >= 1000) {
+ last_update = HAL_GetTick();
+ HW::Ref::update();
+ Protocol::PacketInfo packet;
+ packet.type = Protocol::PacketType::DeviceStatusV1;
+ // Enable PLL chips for temperature reading
+ bool srcEn = FPGA::IsEnabled(FPGA::Periphery::SourceChip);
+ bool LOEn = FPGA::IsEnabled(FPGA::Periphery::LO1Chip);
+ FPGA::Enable(FPGA::Periphery::SourceChip);
+ FPGA::Enable(FPGA::Periphery::LO1Chip);
+ HW::getDeviceStatus(&packet.statusV1, true);
+ // restore PLL state
+ FPGA::Enable(FPGA::Periphery::SourceChip, srcEn);
+ FPGA::Enable(FPGA::Periphery::LO1Chip, LOEn);
+ Communication::Send(packet);
+ }
+ }
+}
+
uint16_t HW::getDFTPhaseInc() {
return DFTphaseInc;
}
diff --git a/Software/VNA_embedded/Application/Hardware.hpp b/Software/VNA_embedded/Application/Hardware.hpp
index e81a26f..a6d029d 100644
--- a/Software/VNA_embedded/Application/Hardware.hpp
+++ b/Software/VNA_embedded/Application/Hardware.hpp
@@ -88,6 +88,7 @@ static constexpr Protocol::DeviceInfo Info = {
enum class Mode {
Idle,
Manual,
+ Generator,
VNA,
SA,
};
@@ -101,6 +102,8 @@ uint64_t getLastISRTimestamp();
void SetOutputUnlevel(bool unlev);
+void updateDeviceStatus();
+
using AmplitudeSettings = struct _amplitudeSettings {
uint8_t attenuator;
union {