Experimental direct register access

This commit is contained in:
Jan Käberich 2021-05-26 20:38:27 +02:00
parent 95a715233e
commit 9f33d47da0
26 changed files with 1761 additions and 8 deletions

View file

@ -218,6 +218,47 @@ void App_Start() {
Cal::setFrequencyCal(recv_packet.frequencyCorrection.ppm);
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
break;
case Protocol::PacketType::RequestDirectRegisterInfo:
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
LOG_INFO("Requested register devices, sending %d packets", RegisterDevice::getNumDevices());
for(uint8_t i=0;i<RegisterDevice::getNumDevices();i++) {
auto dev = RegisterDevice::getDevice(i);
Protocol::PacketInfo send;
send.type = Protocol::PacketType::DirectRegisterInfo;
send.directRegInfo = dev->getInfo();
Communication::Send(send);
}
break;
case Protocol::PacketType::DirectRegisterWrite:
if(recv_packet.directRegWrite.device >= RegisterDevice::getNumDevices()) {
// invalid device
Communication::SendWithoutPayload(Protocol::PacketType::Nack);
} else {
LOG_INFO(
"Register write: dev %u, address %u, data 0x%08x",
recv_packet.directRegWrite.device,
recv_packet.directRegWrite.address,
(uint32_t) recv_packet.directRegWrite.data);
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
auto dev = RegisterDevice::getDevice(recv_packet.directRegWrite.device);
dev->writeRegister(recv_packet.directRegWrite.address, recv_packet.directRegWrite.data);
}
break;
case Protocol::PacketType::DirectRegisterRead:
if(recv_packet.directRegWrite.device >= RegisterDevice::getNumDevices()) {
// invalid device
Communication::SendWithoutPayload(Protocol::PacketType::Nack);
} else {
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
auto dev = RegisterDevice::getDevice(recv_packet.directRegWrite.device);
Protocol::PacketInfo send;
send.type = Protocol::PacketType::DirectRegisterWrite;
send.directRegWrite.device = recv_packet.directRegRead.device;
send.directRegWrite.address = recv_packet.directRegRead.address;
send.directRegWrite.data = dev->readRegister(recv_packet.directRegRead.address);
Communication::Send(send);
}
break;
default:
// this packet type is not supported
Communication::SendWithoutPayload(Protocol::PacketType::Nack);

View file

@ -100,6 +100,9 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
case PacketType::SourceCalPoint:
case PacketType::ReceiverCalPoint: payload_size = sizeof(packet.amplitudePoint); break;
case PacketType::FrequencyCorrection: payload_size = sizeof(packet.frequencyCorrection); break;
case PacketType::DirectRegisterInfo: payload_size = sizeof(packet.directRegInfo); break;
case PacketType::DirectRegisterWrite: payload_size = sizeof(packet.directRegWrite); break;
case PacketType::DirectRegisterRead: payload_size = sizeof(packet.directRegRead); break;
case PacketType::Ack:
case PacketType::PerformFirmwareUpdate:
case PacketType::ClearFlash:
@ -109,6 +112,7 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
case PacketType::RequestReceiverCal:
case PacketType::SetIdle:
case PacketType::RequestFrequencyCorrection:
case PacketType::RequestDirectRegisterInfo:
// no payload
break;
case PacketType::None:

View file

@ -4,7 +4,7 @@
namespace Protocol {
static constexpr uint16_t Version = 5;
static constexpr uint16_t Version = 6;
#pragma pack(push, 1)
@ -68,6 +68,7 @@ using DeviceInfo = struct _deviceInfo {
uint32_t limits_maxRBW;
uint8_t limits_maxAmplitudePoints;
uint64_t limits_maxFreqHarmonic;
uint8_t num_directRegisterDevices; // number of peripheral chips whos registers are exposed via the USB API (for debugging)
};
using ManualStatus = struct _manualstatus {
@ -156,6 +157,25 @@ using FrequencyCorrection = struct _frequencycorrection {
float ppm;
};
using DirectRegisterInfo = struct _directregisterinfo {
uint8_t num;
char type[20]; // Chip partnumber
char name[20]; // Arbitrary name
};
using DirectRegisterWrite = struct _directregisterwrite {
uint8_t device;
uint32_t address;
uint64_t data;
};
using DirectRegisterRead = struct _directregisterread {
// Device will respond with DirectRegisterWrite
uint8_t device;
// uint8_t read_all:1; // if set to one, address is ignored and all registers returned (each in own packet)
uint32_t address;
};
enum class PacketType : uint8_t {
None = 0,
Datapoint = 1,
@ -180,6 +200,10 @@ enum class PacketType : uint8_t {
SetIdle = 20,
RequestFrequencyCorrection = 21,
FrequencyCorrection = 22,
RequestDirectRegisterInfo = 23,
DirectRegisterInfo = 24,
DirectRegisterWrite = 25,
DirectRegisterRead = 26,
};
using PacketInfo = struct _packetinfo {
@ -197,6 +221,9 @@ using PacketInfo = struct _packetinfo {
SpectrumAnalyzerResult spectrumResult;
AmplitudeCorrectionPoint amplitudePoint;
FrequencyCorrection frequencyCorrection;
DirectRegisterInfo directRegInfo;
DirectRegisterWrite directRegWrite;
DirectRegisterRead directRegRead;
};
};

View file

@ -0,0 +1,24 @@
#include <RegisterDevice.hpp>
#include <cstring>
uint8_t RegisterDevice::cnt = 0;
std::array<RegisterDevice*, RegisterDevice::maxDevices> RegisterDevice::devices;
Protocol::DirectRegisterInfo RegisterDevice::getInfo() {
Protocol::DirectRegisterInfo i;
i.num = num;
strncpy(i.name, name, sizeof(i.name));
i.name[sizeof(i.name) - 1] = '\0';
strncpy(i.type, type, sizeof(i.type));
i.type[sizeof(i.type) - 1] = '\0';
return i;
}
RegisterDevice* RegisterDevice::getDevice(uint8_t num) {
if(num < cnt) {
return devices[num];
} else {
return nullptr;
}
}

View file

@ -0,0 +1,41 @@
#pragma once
#include <cstdint>
#include <array>
#include "Protocol.hpp"
extern int global;
class RegisterDevice {
public:
constexpr RegisterDevice(const char *type, const char *name) :
type(type),
name(name),
num(0)
{
num = cnt;
if(cnt < maxDevices) {
devices[cnt] = this;
cnt++;
} else {
// not enough room in array. A debug message would be useful here
// but the constructor is called before any hardware initialization
// so we can do nothing here
}
}
virtual void writeRegister(uint32_t address, uint64_t data) = 0;
virtual uint64_t readRegister(uint32_t address) = 0;
Protocol::DirectRegisterInfo getInfo();
static uint8_t getNumDevices() { return cnt;};
static RegisterDevice *getDevice(uint8_t num);
private:
static constexpr uint8_t maxDevices = 10;
static std::array<RegisterDevice*,maxDevices> devices;
static uint8_t cnt;
const char *type;
const char *name;
uint8_t num;
};

View file

@ -417,3 +417,18 @@ uint8_t MAX2871::GetTemp() {
// convert to celsius and return
return 95 - 1.14f * ADC_raw;
}
void MAX2871::writeRegister(uint32_t address, uint64_t data) {
if(address <= 5) {
regs[address] = (uint32_t) data;
Update();
}
}
uint64_t MAX2871::readRegister(uint32_t address) {
if(address <= 5) {
return regs[address];
} else {
return 0;
}
}

View file

@ -1,15 +1,17 @@
#pragma once
#include "stm.hpp"
#include "RegisterDevice.hpp"
class MAX2871 {
class MAX2871 : public RegisterDevice {
public:
constexpr MAX2871(SPI_HandleTypeDef *hspi, GPIO_TypeDef *LE = nullptr,
constexpr MAX2871(const char *name, SPI_HandleTypeDef *hspi, GPIO_TypeDef *LE = nullptr,
uint16_t LEpin = 0, GPIO_TypeDef *RF_EN = nullptr,
uint16_t RF_ENpin = 0, GPIO_TypeDef *LD = nullptr, uint16_t LDpin = 0,
GPIO_TypeDef *CE = nullptr, uint16_t CEpin = 0,
GPIO_TypeDef *MUX = nullptr, uint16_t MUXpin = 0) :
regs(), f_PFD(0),
RegisterDevice("MAX2871", name),
regs(), f_PFD(0),
hspi(hspi),
CE(CE), CEpin(CEpin),
LE(LE), LEpin(LEpin),
@ -60,6 +62,9 @@ public:
uint64_t GetActualFrequency() {
return outputFrequency;
}
void writeRegister(uint32_t address, uint64_t data) override;
uint64_t readRegister(uint32_t address) override;
private:
static constexpr uint64_t MaxFreq = 6100000000; // 6GHz according to datasheet, but slight overclocking is possible

View file

@ -1,7 +1,7 @@
#include "HW_HAL.hpp"
Si5351C HWHAL::Si5351 = Si5351C(&hi2c2, 26000000);
MAX2871 HWHAL::Source = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
MAX2871 HWHAL::LO1 = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
MAX2871 HWHAL::Source = MAX2871("Source", &hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
MAX2871 HWHAL::LO1 = MAX2871("1.LO", &hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
extern SPI_HandleTypeDef hspi1;
Flash HWHAL::flash = Flash(&hspi1, FLASH_CS_GPIO_Port, FLASH_CS_Pin);

View file

@ -48,6 +48,8 @@ static constexpr int16_t LowBandMaxPower = -190;
static constexpr int16_t HighBandMinPower = -1060;
static constexpr int16_t HighBandMaxPower = -160;
static constexpr uint8_t registerDevices = 2;
static constexpr Protocol::DeviceInfo Info = {
.ProtocolVersion = Protocol::Version,
.FW_major = FW_MAJOR,
@ -75,6 +77,7 @@ static constexpr Protocol::DeviceInfo Info = {
.limits_maxRBW = (uint32_t) (ADCSamplerate * 2.23f / MinSamples),
.limits_maxAmplitudePoints = Cal::maxPoints,
.limits_maxFreqHarmonic = 18000000000,
.num_directRegisterDevices = registerDevices,
};
enum class Mode {