Я использую C API для связи с устройством через SPI.Все команды приводят к 3-байтовому регистру с устройства.Поскольку std :: array хорош и совместим с C API, я написал небольшую оболочку, которая отправляет команду и возвращает 3-байтовый массив.
Регистр "STATUS" более сложный, и поэтому я создал структурув нем только один 3-байтовый массив std ::.Основная цель - дать возможность простым const-методам обрабатывать все смещения, маскирование, CRC и т. Д., Которые нужны регистру.
using devReg = std::array<uint8_t, 3>;
struct Status {
// default to all null
explicit Status() : raw{0} {}
// construct from std::array
explicit Status(const devReg& a) : raw(a) {}
// assign to and from std::array
Status& operator=(const devReg& a) { raw = a; return *this; }
// convert to std::array
explicit operator devReg&() { return raw; }
explicit operator const devReg&() const { return raw; }
devReg raw; // raw data
/// Indicates the FIFO watermark has been hit
constexpr bool eint() const { return raw[0]&0x80U; }
/*** Many other simple functions to handle the spare bitfields and validate data ***/
};
devReg cmdRead(const RegAddress cmd)
{
std::array<uint8_t, 3> buf = {0};
SPIShim::select();
// send write command: shift reg address right once and set bit 0
SPIShim::write(static_cast<uint8_t>(cmd));
SPIShim::read(buf.data(), buf.size());
SPIShim::deSelect();
return buf;
}
bool cmdWrite(const RegAddress cmd, const std::array<uint8_t, 3>& r)
{
SPIShim::select();
// send read command: shift reg address left once and clear bit 0
SPIShim::write(static_cast<uint8_t>(cmd));
const size_t count = SPIShim::write(r.data(), r.size());
SPIShim::deSelect();
return count == 3;
}
// Works
Status getStatus1() {
Status s(cmdRead(RegAddress::STATUS));
return s;
}
// Works
Status getStatus2() {
Status s;
s = cmdRead(RegAddress::STATUS);
return s;
}
// Works
Status getStatus3() {
return static_cast<Status>(cmdRead(RegAddress::STATUS));
}
// error: conversion from 'devReg' to non-scalar type 'Status' requested
Status getStatus4() {
Status s = cmdRead(RegAddress::STATUS);
return s;
}
// error: could not convert 'cmdRead(1) from 'devReg to 'Status'
Status getStatus5() {
return cmdRead(RegAddress::STATUS);
}
// error: no known conversion for argument 2 from 'Status' to 'const devReg&'
bool setStatus(const Status& s) {
cmdWrite(RegAddress::STATUS, s);
}
Я вроде понимаю, почему getStatus4()
не работает, я думаю, std:: массив будет нуждаться в перегрузке оператора в качестве члена, который я не могу добавить.Но я не очень понимаю, почему getStatus5()
не работает.И похоже, что перегрузка explicit operator const devReg&()
должна заставить setStatus()
работать!
В чем здесь проблема?В конце я хотел бы создать простые структуры, которые содержат один базовый std :: array и несколько функций, но в показанных случаях он работает взаимозаменяемо с эквивалентным std :: array.
Примечание: Простой обходной путь - возврат с использованием статического приведения и передача в функцию массива с помощью s.raw
.Так что на самом деле я ищу лучшего понимания здесь и, если это возможно, немного более приятный код.