diff --git a/FPGA/VNA/Sweep.vhd b/FPGA/VNA/Sweep.vhd index 0becdbb..ff3d517 100644 --- a/FPGA/VNA/Sweep.vhd +++ b/FPGA/VNA/Sweep.vhd @@ -101,8 +101,8 @@ begin LO_REG_1 <= MAX2871_DEF_1(31 downto 15) & CONFIG_DATA(87 downto 76) & "001"; -- LO register 3: VCO selection LO_REG_3 <= CONFIG_DATA(60 downto 55) & MAX2871_DEF_3(25 downto 3) & "011"; - -- both outputs enabled at -1dbm - LO_REG_4 <= MAX2871_DEF_4(31 downto 23) & CONFIG_DATA(63 downto 61) & MAX2871_DEF_4(19 downto 9) & "101101100"; + -- both outputs enabled at +5dbm + LO_REG_4 <= MAX2871_DEF_4(31 downto 23) & CONFIG_DATA(63 downto 61) & MAX2871_DEF_4(19 downto 9) & "111111100"; ATTENUATOR <= CONFIG_DATA(46 downto 40); SOURCE_FILTER <= CONFIG_DATA(89 downto 88); diff --git a/FPGA/VNA/VNA.gise b/FPGA/VNA/VNA.gise index ae038b9..e27506d 100644 --- a/FPGA/VNA/VNA.gise +++ b/FPGA/VNA/VNA.gise @@ -270,7 +270,7 @@ - + @@ -292,7 +292,7 @@ - + @@ -301,10 +301,12 @@ - + + + @@ -315,7 +317,7 @@ - + @@ -329,7 +331,7 @@ - + @@ -375,7 +377,7 @@ - + diff --git a/FPGA/VNA/top.bin b/FPGA/VNA/top.bin index 0cfcb44..db1dac4 100644 Binary files a/FPGA/VNA/top.bin and b/FPGA/VNA/top.bin differ diff --git a/Software/PC_Application/.gitignore b/Software/PC_Application/.gitignore index 6089be0..a9e45de 100644 --- a/Software/PC_Application/.gitignore +++ b/Software/PC_Application/.gitignore @@ -71,4 +71,6 @@ Thumbs.db # -------- *.dll *.exe +Application + diff --git a/Software/PC_Application/Application b/Software/PC_Application/Application deleted file mode 100755 index 7eabee1..0000000 Binary files a/Software/PC_Application/Application and /dev/null differ diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index c24ee7b..d9749c3 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -207,7 +207,7 @@ VNA::VNA(AppWindow *window) auto dbm = new QDoubleSpinBox(); dbm->setValue(settings.cdbm_excitation * 100); dbm->setFixedWidth(95); - dbm->setRange(-42.0, -10.0); + dbm->setRange(-100.0, 100.0); dbm->setSingleStep(0.25); dbm->setSuffix("dbm"); dbm->setToolTip("Stimulus level"); diff --git a/Software/VNA_embedded/Application/Drivers/USB/usb.c b/Software/VNA_embedded/Application/Drivers/USB/usb.c index adcad8f..b06eab3 100644 --- a/Software/VNA_embedded/Application/Drivers/USB/usb.c +++ b/Software/VNA_embedded/Application/Drivers/USB/usb.c @@ -17,8 +17,11 @@ static uint8_t USBD_Class_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum); static uint8_t *USBD_Class_GetFSCfgDesc (uint16_t *length); static uint8_t *USBD_Class_GetDeviceQualifierDescriptor (uint16_t *length); -static usbd_callback_t cb; +static usbd_recv_callback_t cb; static uint8_t usb_receive_buffer[1024]; +static uint8_t usb_transmit_fifo[4096]; +static uint16_t usb_transmit_read_index = 0; +static uint16_t usb_transmit_fifo_level = 0; static bool data_transmission_active = false; static bool log_transmission_active = true; @@ -145,17 +148,43 @@ static uint8_t USBD_Class_Setup(USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef } return USBD_OK; } + +static bool trigger_next_fifo_transmission() { + data_transmission_active = true; + uint16_t continous_length = sizeof(usb_transmit_fifo) - usb_transmit_read_index; + if(continous_length > usb_transmit_fifo_level) { + continous_length = usb_transmit_fifo_level; + } + if(continous_length > sizeof(usb_transmit_fifo)/ 4) { + continous_length = sizeof(usb_transmit_fifo) / 4; + } + hUsbDeviceFS.ep_in[EP_DATA_IN_ADDRESS & 0x7F].total_length = continous_length; + return USBD_LL_Transmit(&hUsbDeviceFS, EP_DATA_IN_ADDRESS, &usb_transmit_fifo[usb_transmit_read_index], continous_length) == USBD_OK; +} + static uint8_t USBD_Class_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { // A bulk transfer is complete when the endpoint does on of the following: // - Has transferred exactly the amount of data expected // - Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet + if(epnum == (EP_DATA_IN_ADDRESS & 0x7F)) { + // transmission of fifo data, mark as empty + __disable_irq(); + usb_transmit_fifo_level -= pdev->ep_in[epnum].total_length; + usb_transmit_read_index += pdev->ep_in[epnum].total_length; + usb_transmit_read_index %= sizeof(usb_transmit_fifo); + __enable_irq(); + } if (pdev->ep_in[epnum].total_length && !(pdev->ep_in[epnum].total_length % USB_FS_MAX_PACKET_SIZE)) { pdev->ep_in[epnum].total_length = 0; USBD_LL_Transmit(pdev, epnum, NULL, 0); } else { if(epnum == (EP_DATA_IN_ADDRESS & 0x7F)) { - data_transmission_active = false; + if(usb_transmit_fifo_level > 0) { + trigger_next_fifo_transmission(); + } else { + data_transmission_active = false; + } } else { log_transmission_active = false; } @@ -182,30 +211,53 @@ static uint8_t *USBD_Class_GetDeviceQualifierDescriptor(uint16_t *length) return USBD_DeviceQualifierDesc; } -void usb_init(usbd_callback_t callback) { - cb = callback; +void usb_init(usbd_recv_callback_t receive_callback) { + cb = receive_callback; USBD_Init(&hUsbDeviceFS, &FS_Desc, 0); USBD_RegisterClass(&hUsbDeviceFS, &USBD_ClassDriver); USBD_Start(&hUsbDeviceFS); - HAL_NVIC_SetPriority(USB_HP_IRQn, 7, 0); + HAL_NVIC_SetPriority(USB_HP_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USB_HP_IRQn); HAL_NVIC_SetPriority(USB_LP_IRQn, 7, 0); HAL_NVIC_EnableIRQ(USB_LP_IRQn); } bool usb_transmit(const uint8_t *data, uint16_t length) { + // attempt to add data to fifo + if(usb_transmit_fifo_level + length > sizeof(usb_transmit_fifo)) { + // data won't fit, abort + return false; + } + // grab pointer to write position + __disable_irq(); + uint16_t write_index = usb_transmit_read_index + usb_transmit_fifo_level; + __enable_irq(); + write_index %= sizeof(usb_transmit_fifo); + // copy the data to the fifo + uint16_t continous_length = sizeof(usb_transmit_fifo) - write_index; + if(continous_length > length) { + // can copy all data at once + memcpy(&usb_transmit_fifo[write_index], data, length); + } else { + // needs to copy two data segments + memcpy(&usb_transmit_fifo[write_index], data, continous_length); + memcpy(&usb_transmit_fifo[0], data + continous_length, length - continous_length); + } + // increment fifo level + __disable_irq(); + usb_transmit_fifo_level += length; + __enable_irq(); + static bool first = true; if(first) { log_transmission_active = false; first = false; } if(!data_transmission_active) { - data_transmission_active = true; - hUsbDeviceFS.ep_in[EP_DATA_IN_ADDRESS & 0x7F].total_length = length; - return USBD_LL_Transmit(&hUsbDeviceFS, EP_DATA_IN_ADDRESS, (uint8_t*) data, length) == USBD_OK; + return trigger_next_fifo_transmission(); } else { - // already have an ongoing transmission - return false; + // still transmitting, no need to trigger + return true; } } diff --git a/Software/VNA_embedded/Application/Drivers/USB/usb.h b/Software/VNA_embedded/Application/Drivers/USB/usb.h index ab89ae7..fa3a3bb 100644 --- a/Software/VNA_embedded/Application/Drivers/USB/usb.h +++ b/Software/VNA_embedded/Application/Drivers/USB/usb.h @@ -15,9 +15,9 @@ extern "C" { #include #include -typedef void(*usbd_callback_t)(const uint8_t *buf, uint16_t len); +typedef void(*usbd_recv_callback_t)(const uint8_t *buf, uint16_t len); -void usb_init(usbd_callback_t callback); +void usb_init(usbd_recv_callback_t receive_callback); bool usb_transmit(const uint8_t *data, uint16_t length); void usb_log(const char *log, uint16_t length); diff --git a/Software/VNA_embedded/Application/Hardware.hpp b/Software/VNA_embedded/Application/Hardware.hpp index ae90e84..bdbc887 100644 --- a/Software/VNA_embedded/Application/Hardware.hpp +++ b/Software/VNA_embedded/Application/Hardware.hpp @@ -6,7 +6,7 @@ namespace HW { static constexpr uint32_t ADCSamplerate = 800000; -static constexpr uint32_t IF1 = 60000000; +static constexpr uint32_t IF1 = 62000000; static constexpr uint32_t IF2 = 250000; static constexpr uint32_t LO1_minFreq = 25000000; static constexpr uint32_t MaxSamples = 130944; @@ -21,7 +21,7 @@ static constexpr Protocol::DeviceLimits Limits = { .maxIFBW = ADCSamplerate / MinSamples, .maxPoints = MaxPoints, .cdbm_min = -4000, - .cdbm_max = -1000, + .cdbm_max = 0, .minRBW = (uint32_t) (ADCSamplerate * 2.23f / MaxSamples), .maxRBW = (uint32_t) (ADCSamplerate * 2.23f / MinSamples), }; diff --git a/Software/VNA_embedded/Application/VNA.cpp b/Software/VNA_embedded/Application/VNA.cpp index 686eae5..8072423 100644 --- a/Software/VNA_embedded/Application/VNA.cpp +++ b/Software/VNA_embedded/Application/VNA.cpp @@ -22,6 +22,7 @@ static uint16_t pointCnt; static bool excitingPort1; static Protocol::Datapoint data; static bool active = false; +static bool sourceHighPower; using IFTableEntry = struct { uint16_t pointCnt; @@ -62,14 +63,27 @@ bool VNA::Setup(Protocol::SweepSettings s, SweepCallback cb) { // has to be one less than actual number of samples FPGA::SetSamplesPerPoint(samplesPerPoint); + // Set level (not very accurate) + int16_t cdbm = s.cdbm_excitation; + if(cdbm > -1000) { + // use higher source power (approx 0dbm with no attenuation) + sourceHighPower = true; + Source.SetPowerOutA(MAX2871::Power::p5dbm, true); + } else { + // use lower source power (approx -10dbm with no attenuation) + sourceHighPower = false; + Source.SetPowerOutA(MAX2871::Power::n4dbm, true); + cdbm += 1000; + } uint8_t attenuator; - if(s.cdbm_excitation >= -1000) { + if(cdbm >= 0) { attenuator = 0; - } else if (s.cdbm_excitation <= -4175){ + } else if (cdbm <= -3175){ attenuator = 127; } else { - attenuator = (-1000 - s.cdbm_excitation) / 25; + attenuator = (-cdbm) / 25; } + FPGA::WriteMAX2871Default(Source.GetRegisters()); uint32_t last_LO2 = HW::IF1 - HW::IF2; Si5351.SetCLK(SiChannel::Port1LO2, last_LO2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2); @@ -116,12 +130,14 @@ bool VNA::Setup(Protocol::SweepSettings s, SweepCallback cb) { if (s.suppressPeaks && needs_LO2_shift) { if (IFTableIndexCnt < IFTableNumEntries) { // still room in table - LOG_INFO("Changing 2.LO at point %lu to reach correct 2.IF frequency"); needs_halt = true; IFTable[IFTableIndexCnt].pointCnt = i; // Configure LO2 for the changed IF1. This is not necessary right now but it will generate // the correct clock settings last_LO2 = actualFirstIF - HW::IF2; + LOG_INFO("Changing 2.LO to %lu at point %lu (%lu%06luHz) to reach correct 2.IF frequency", + last_LO2, i, (uint32_t ) (freq / 1000000), + (uint32_t ) (freq % 1000000)); Si5351.SetCLK(SiChannel::RefLO2, last_LO2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2); // store calculated clock configuration for later change @@ -260,7 +276,7 @@ void VNA::SweepHalted() { if (frequency < BandSwitchFrequency) { // need the Si5351 as Source Si5351.SetCLK(SiChannel::LowbandSource, frequency, Si5351C::PLL::B, - Si5351C::DriveStrength::mA2); + sourceHighPower ? Si5351C::DriveStrength::mA8 : Si5351C::DriveStrength::mA2); if (pointCnt == 0) { // First point in sweep, enable CLK Si5351.Enable(SiChannel::LowbandSource);