Change .clang-format to the latest M5 one

This commit is contained in:
GOB
2024-09-26 12:06:04 +09:00
parent 950a9cc5b0
commit 09d831f806
20 changed files with 711 additions and 596 deletions
+2 -3
View File
@@ -7,11 +7,10 @@
#define M5HAL_STATIC_MACRO_PATH_IMPL M5HAL_STATIC_MACRO_CONCAT(M5HAL_TARGET_PLATFORM_PATH, impl.inl)
#if M5HAL_TARGET_PLATFORM_NUMBER != 0
#include M5HAL_STATIC_MACRO_PATH_IMPL
#include M5HAL_STATIC_MACRO_PATH_IMPL
#endif
// Arduino環境の場合のみ、Arduino用の実装を用意
#if M5HAL_FRAMEWORK_HAS_ARDUINO
#include "./m5_hal/frameworks/arduino/impl.inl"
#include "./m5_hal/frameworks/arduino/impl.inl"
#endif
+12 -12
View File
@@ -11,30 +11,30 @@
#include "./m5_hal/bus/bus.hpp"
#include "./m5_hal/interface/gpio.hpp"
#define M5HAL_STATIC_MACRO_STRING(x) #x
#define M5HAL_STATIC_MACRO_CONCAT(x, y) M5HAL_STATIC_MACRO_STRING(x/y)
#define M5HAL_STATIC_MACRO_PATH_HEADER M5HAL_STATIC_MACRO_CONCAT(M5HAL_TARGET_PLATFORM_PATH, header.hpp)
#define M5HAL_STATIC_MACRO_STRING(x) #x
#define M5HAL_STATIC_MACRO_CONCAT(x, y) M5HAL_STATIC_MACRO_STRING(x / y)
#define M5HAL_STATIC_MACRO_PATH_HEADER M5HAL_STATIC_MACRO_CONCAT(M5HAL_TARGET_PLATFORM_PATH, header.hpp)
#if M5HAL_TARGET_PLATFORM_NUMBER != 0
#include M5HAL_STATIC_MACRO_PATH_HEADER
#include M5HAL_STATIC_MACRO_PATH_HEADER
#endif
#undef M5HAL_STATIC_MACRO_PATH_HEADER
// Arduinoフレームワークがある場合は準備
#if M5HAL_FRAMEWORK_HAS_ARDUINO
#include "./m5_hal/frameworks/arduino/header.hpp"
#include "./m5_hal/frameworks/arduino/header.hpp"
// 対象プラットフォームが特定されない場合は Arduino経由の実装を利用
#if 1 // M5HAL_TARGET_PLATFORM_NUMBER == 0
#if 1 // M5HAL_TARGET_PLATFORM_NUMBER == 0
namespace m5 {
namespace hal {
using namespace frameworks::arduino;
}
}
namespace m5 {
namespace hal {
using namespace frameworks::arduino;
}
} // namespace m5
#endif
#endif
#endif
+93 -45
View File
@@ -24,7 +24,7 @@ struct Accessor;
//-------------------------------------------------------------------------
// 通信バスの初期化に必要な条件を記述するため基底インターフェイス
struct BusConfig {
virtual ~BusConfig() = default;
virtual ~BusConfig() = default;
virtual types::bus_type_t getBusType(void) const = 0;
types::periph_t periph;
};
@@ -32,71 +32,105 @@ struct BusConfig {
//-------------------------------------------------------------------------
// 実際の通信に必要な条件を記述するための基底インターフェイス
struct AccessConfig {
virtual ~AccessConfig() = default;
virtual ~AccessConfig() = default;
virtual types::bus_type_t getBusType(void) const = 0;
void (*callback_begin)(Accessor*) = nullptr; // 通信開始時時に呼び出すコールバック関数
void (*callback_end)(Accessor*) = nullptr; // 通信終了時に呼び出すコールバック関数
void (*callback_begin)(Accessor*) = nullptr; // 通信開始時時に呼び出すコールバック関数
void (*callback_end)(Accessor*) = nullptr; // 通信終了時に呼び出すコールバック関数
};
//-------------------------------------------------------------------------
// 特定の通信相手との各種通信条件を記述するため基底インターフェイス
struct Accessor : public interface::io::Output, public interface::io::Input
{
virtual ~Accessor(void) = default;
virtual types::bus_type_t getBusType(void) const = 0;
struct Accessor : public interface::io::Output, public interface::io::Input {
virtual ~Accessor(void) = default;
virtual types::bus_type_t getBusType(void) const = 0;
virtual const AccessConfig& getAccessConfig(void) const = 0;
Accessor(Bus& bus) : _bus { bus } {}
Bus& getBus(void) const { return _bus; };
Accessor(Bus& bus) : _bus{bus}
{
}
Bus& getBus(void) const
{
return _bus;
};
const BusConfig& getBusConfig(void) const;
virtual m5::stl::expected<void, m5::hal::error::error_t> startWrite(void) { return {}; }
virtual m5::stl::expected<void, m5::hal::error::error_t> startRead(void) { return {}; }
virtual m5::stl::expected<void, m5::hal::error::error_t> stop(void) { return {}; }
virtual m5::stl::expected<size_t, m5::hal::error::error_t> readLastNack(uint8_t* data, size_t len) { return readWithLastNackFlag(data, len, true); }
virtual m5::stl::expected<size_t, m5::hal::error::error_t> readWithLastNackFlag(uint8_t* data, size_t len, bool last_nack = false) { return read(data, len); }
virtual m5::stl::expected<void, m5::hal::error::error_t> startWrite(void)
{
return {};
}
virtual m5::stl::expected<void, m5::hal::error::error_t> startRead(void)
{
return {};
}
virtual m5::stl::expected<void, m5::hal::error::error_t> stop(void)
{
return {};
}
virtual m5::stl::expected<size_t, m5::hal::error::error_t> readLastNack(uint8_t* data, size_t len)
{
return readWithLastNackFlag(data, len, true);
}
virtual m5::stl::expected<size_t, m5::hal::error::error_t> readWithLastNackFlag(uint8_t* data, size_t len,
bool last_nack = false)
{
return read(data, len);
}
protected:
Bus& _bus;
};
template<typename TBusAccessInterface>
template <typename TBusAccessInterface>
struct DefaultBusExtension {
DefaultBusExtension(TBusAccessInterface&) {}
DefaultBusExtension(TBusAccessInterface&)
{
}
};
template<typename TBus, typename TBusAccessInterface, typename TExtension = DefaultBusExtension<TBusAccessInterface>>
template <typename TBus, typename TBusAccessInterface, typename TExtension = DefaultBusExtension<TBusAccessInterface>>
struct BusAccessor {
BusAccessor() = delete;
BusAccessor(TBus& bus, TBusAccessInterface& access) : _bus(bus), _access(access), _extension(access) {}
BusAccessor(const BusAccessor&) = delete;
BusAccessor(TBus& bus, TBusAccessInterface& access) : _bus(bus), _access(access), _extension(access)
{
}
BusAccessor(const BusAccessor&) = delete;
BusAccessor& operator=(const BusAccessor&) = delete;
BusAccessor(BusAccessor&& other) : _owner(other.owner), _bus(other.bus), _access(other.access), _extension(other.access) {
BusAccessor(BusAccessor&& other)
: _owner(other.owner), _bus(other.bus), _access(other.access), _extension(other.access)
{
other._owner = false;
}
void release() {
if( this->_owner ) {
void release()
{
if (this->_owner) {
this->_bus.release();
}
this->_owner = false;
}
BusAccessor& operator=(BusAccessor&& other) {
BusAccessor& operator=(BusAccessor&& other)
{
this->release();
this->_owner = other._owner;
this->_bus = other._bus;
this->_access = other._access;
this->_owner = other._owner;
this->_bus = other._bus;
this->_access = other._access;
this->_extension = TExtension(this->_access);
other._owner = false;
other._owner = false;
}
/*
void read() { this->_access.read(this->_bus);}
void write() { this->_access.write(this->_bus); }
void transmit() { this->_access.transmit(this->_bus); }
*/
TExtension& extension()
{
return this->_extension;
}
/*
void read() { this->_access.read(this->_bus);}
void write() { this->_access.write(this->_bus); }
void transmit() { this->_access.transmit(this->_bus); }
*/
TExtension& extension() { return this->_extension; }
~BusAccessor() {
~BusAccessor()
{
this->release();
}
protected:
bool _owner = true;
TBus& _bus;
@@ -108,7 +142,7 @@ protected:
// 通信バスの基底インターフェイス
struct Bus {
public:
virtual ~Bus() = default;
virtual ~Bus() = default;
virtual types::bus_type_t getBusType(void) const = 0;
// initとreleaseはユーザーは直接呼ばない。 createBus / releaseBus経由で使用する。
@@ -116,14 +150,21 @@ public:
virtual const BusConfig& getConfig(void) const = 0;
// バスの初期化
virtual error::error_t init(const BusConfig& config) { return error::error_t::NOT_IMPLEMENTED; }
virtual error::error_t init(const BusConfig& config)
{
return error::error_t::NOT_IMPLEMENTED;
}
// バスの解放
virtual error::error_t release(void) { return error::error_t::NOT_IMPLEMENTED; }
virtual error::error_t release(void)
{
return error::error_t::NOT_IMPLEMENTED;
}
/// @note expectedは参照をサポートしていないのでポインタを含める形とした。
virtual m5::stl::expected<Accessor*, m5::hal::error::error_t> beginAccess(const AccessConfig& access_config) = 0;
virtual error::error_t endAccess(Accessor* Accessor) {
virtual error::error_t endAccess(Accessor* Accessor)
{
if (Accessor && _Accessor.get() == Accessor) {
_Accessor.reset(nullptr);
return error::error_t::OK;
@@ -132,18 +173,25 @@ public:
}
// 無条件でバスをロックしたい場合に使用する
virtual m5::stl::expected<void, error::error_t> lock(void) { return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED); }
virtual m5::stl::expected<void, error::error_t> unlock(void) { return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED); }
virtual m5::stl::expected<void, error::error_t> lock(void)
{
return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED);
}
virtual m5::stl::expected<void, error::error_t> unlock(void)
{
return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED);
}
protected:
std::unique_ptr<Accessor> _Accessor;
};
//-------------------------------------------------------------------------
// error::error_t Bus::beginAccess(const Accessor* Accessor) { return (Accessor->getBusType() != getBusType()) ? error::error_t::INVALID_ARGUMENT : error::error_t::OK; }
// error::error_t Bus::beginAccess(const Accessor* Accessor) { return (Accessor->getBusType() != getBusType()) ?
// error::error_t::INVALID_ARGUMENT : error::error_t::OK; }
} // namespace bus
} // namespace hal
} // namespace m5
} // namespace bus
} // namespace hal
} // namespace m5
#endif
+3 -3
View File
@@ -10,6 +10,6 @@ const BusConfig& Accessor::getBusConfig(void) const
return _bus.getConfig();
}
} // namespace bus
} // namespace hal
} // namespace m5
} // namespace bus
} // namespace hal
} // namespace m5
+70 -43
View File
@@ -8,74 +8,101 @@ namespace hal {
namespace bus {
struct I2CBusConfig : public BusConfig {
types::bus_type_t getBusType(void) const override { return types::bus_type_t::I2C; };
types::bus_type_t getBusType(void) const override
{
return types::bus_type_t::I2C;
};
interface::gpio::Pin* pin_scl;
interface::gpio::Pin* pin_sda;
};
struct I2CMasterAccessConfig : public AccessConfig {
types::bus_type_t getBusType(void) const override { return types::bus_type_t::I2C; };
uint32_t freq = 100000;
types::bus_type_t getBusType(void) const override
{
return types::bus_type_t::I2C;
};
uint32_t freq = 100000;
uint32_t timeout_msec = 1000;
uint16_t i2c_addr;
bool address_is_10bit = false;
};
namespace i2c {
struct I2CMasterAccessor : public Accessor
struct I2CMasterAccessor : public Accessor {
I2CMasterAccessor(Bus& bus, const I2CMasterAccessConfig& access_config)
: Accessor{bus}, _access_config{access_config}
{
I2CMasterAccessor(Bus& bus, const I2CMasterAccessConfig& access_config) : Accessor { bus }, _access_config { access_config } {}
types::bus_type_t getBusType(void) const override { return types::bus_type_t::I2C; };
const AccessConfig& getAccessConfig(void) const override { return _access_config; }
}
types::bus_type_t getBusType(void) const override
{
return types::bus_type_t::I2C;
};
const AccessConfig& getAccessConfig(void) const override
{
return _access_config;
}
m5::stl::expected<void, m5::hal::error::error_t> startWrite(void) override;
m5::stl::expected<void, m5::hal::error::error_t> startRead(void) override;
m5::stl::expected<void, m5::hal::error::error_t> stop(void) override;
m5::stl::expected<void, m5::hal::error::error_t> startWrite(void) override;
m5::stl::expected<void, m5::hal::error::error_t> startRead(void) override;
m5::stl::expected<void, m5::hal::error::error_t> stop(void) override;
// read with ack
m5::stl::expected<size_t, m5::hal::error::error_t> read(uint8_t* data, size_t len) override { return readWithLastNackFlag(data, len, false); };
// virtual m5::stl::expected<size_t, m5::hal::error::error_t> readLastNack(uint8_t* data, size_t len) { return readWithLastNackFlag(data, len, true); }
// virtual m5::stl::expected<size_t, m5::hal::error::error_t> readWithLastNackFlag(uint8_t* data, size_t len, bool last_nack = false) = 0;
protected:
I2CMasterAccessConfig _access_config;
virtual m5::stl::expected<void, m5::hal::error::error_t> sendStartCondition(void);
virtual m5::stl::expected<void, m5::hal::error::error_t> sendStopCondition(void);
virtual m5::stl::expected<void, m5::hal::error::error_t> sendDummyClockWhileSdaLow(size_t count = 9);
virtual m5::stl::expected<void, m5::hal::error::error_t> waitClockStretch(uint_fast16_t msec);
// read with ack
m5::stl::expected<size_t, m5::hal::error::error_t> read(uint8_t* data, size_t len) override
{
return readWithLastNackFlag(data, len, false);
};
class SoftwareI2CMasterAccessor : public I2CMasterAccessor
// virtual m5::stl::expected<size_t, m5::hal::error::error_t> readLastNack(uint8_t* data, size_t len) { return
// readWithLastNackFlag(data, len, true); } virtual m5::stl::expected<size_t, m5::hal::error::error_t>
// readWithLastNackFlag(uint8_t* data, size_t len, bool last_nack = false) = 0;
protected:
I2CMasterAccessConfig _access_config;
virtual m5::stl::expected<void, m5::hal::error::error_t> sendStartCondition(void);
virtual m5::stl::expected<void, m5::hal::error::error_t> sendStopCondition(void);
virtual m5::stl::expected<void, m5::hal::error::error_t> sendDummyClockWhileSdaLow(size_t count = 9);
virtual m5::stl::expected<void, m5::hal::error::error_t> waitClockStretch(uint_fast16_t msec);
};
class SoftwareI2CMasterAccessor : public I2CMasterAccessor {
public:
SoftwareI2CMasterAccessor(Bus& bus, const I2CMasterAccessConfig& access_config)
: I2CMasterAccessor{bus, access_config}
{
public:
SoftwareI2CMasterAccessor(Bus& bus, const I2CMasterAccessConfig& access_config) : I2CMasterAccessor { bus, access_config } {}
m5::stl::expected<size_t, m5::hal::error::error_t> write(const uint8_t* data, size_t len) override;
m5::stl::expected<size_t, m5::hal::error::error_t> readWithLastNackFlag(uint8_t* data, size_t len, bool last_nack = false) override;
};
}
m5::stl::expected<size_t, m5::hal::error::error_t> write(const uint8_t* data, size_t len) override;
m5::stl::expected<size_t, m5::hal::error::error_t> readWithLastNackFlag(uint8_t* data, size_t len,
bool last_nack = false) override;
};
//-------------------------------------------------------------------------
struct I2CBus : public Bus {
types::bus_type_t getBusType(void) const override { return types::bus_type_t::I2C; };
const BusConfig& getConfig(void) const override { return _config; }
protected:
I2CBusConfig _config;
};
class SoftwareI2CBus : public I2CBus
struct I2CBus : public Bus {
types::bus_type_t getBusType(void) const override
{
public:
error::error_t init(const BusConfig& config) override;
m5::stl::expected<Accessor*, m5::hal::error::error_t> beginAccess(const AccessConfig& access_config) override;
return types::bus_type_t::I2C;
};
const BusConfig& getConfig(void) const override
{
return _config;
}
m5::stl::expected<I2CBus*, m5::hal::error::error_t> getBus(const I2CBusConfig& config);
} // namespace i2c
protected:
I2CBusConfig _config;
};
class SoftwareI2CBus : public I2CBus {
public:
error::error_t init(const BusConfig& config) override;
m5::stl::expected<Accessor*, m5::hal::error::error_t> beginAccess(const AccessConfig& access_config) override;
};
m5::stl::expected<I2CBus*, m5::hal::error::error_t> getBus(const I2CBusConfig& config);
} // namespace i2c
// static inline bus::I2CBus* createI2CBus(const bus::I2CBusConfig& config) { return i2c::createBus(config); }
} // namespace bus
} // namespace hal
} // namespace m5
} // namespace bus
} // namespace hal
} // namespace m5
#endif
+158 -173
View File
@@ -2,20 +2,17 @@
#include "i2c.hpp"
#include "../error.hpp"
namespace m5 {
namespace hal {
namespace bus {
namespace i2c {
//constexpr uint32_t DELAY_CYCLE{400};
// constexpr uint32_t DELAY_CYCLE{400};
constexpr uint32_t DELAY_CYCLE{200};
void delayCycle(uint32_t count)
{
for (uint32_t i = count; i > 0; --i)
{
for (uint32_t i = count; i > 0; --i) {
__asm__ __volatile__("nop");
}
}
@@ -28,15 +25,16 @@ m5::stl::expected<I2CBus*, m5::hal::error::error_t> getBus(const I2CBusConfig& c
return &bus;
}
error::error_t SoftwareI2CBus::init(const BusConfig& config) {
error::error_t SoftwareI2CBus::init(const BusConfig& config)
{
if (config.getBusType() != types::bus_type_t::I2C) {
M5_LIB_LOGE("SoftwareI2C::init: error %s", __PRETTY_FUNCTION__);
return error::error_t::INVALID_ARGUMENT;
}
_config = static_cast<const I2CBusConfig&>(config);
if (_config.pin_scl == nullptr || _config.pin_sda == nullptr) {
M5_LIB_LOGE("SoftwareI2C::init: error %s", __PRETTY_FUNCTION__);
return error::error_t::INVALID_ARGUMENT;
M5_LIB_LOGE("SoftwareI2C::init: error %s", __PRETTY_FUNCTION__);
return error::error_t::INVALID_ARGUMENT;
}
M5_LIB_LOGV("SoftwareI2C::init: ok %s", __PRETTY_FUNCTION__);
@@ -51,16 +49,17 @@ error::error_t SoftwareI2CBus::init(const BusConfig& config) {
return error::error_t::OK;
}
m5::stl::expected<m5::hal::bus::Accessor*, m5::hal::error::error_t> SoftwareI2CBus::beginAccess(const m5::hal::bus::AccessConfig& access_config)
m5::stl::expected<m5::hal::bus::Accessor*, m5::hal::error::error_t> SoftwareI2CBus::beginAccess(
const m5::hal::bus::AccessConfig& access_config)
{
/// @TODO ここで排他制御&ロック処理を行うこと。
if (_Accessor.get() != nullptr) {
M5_LIB_LOGE("SoftwareI2C::beginAccess: error %s", __PRETTY_FUNCTION__);
return m5::stl::make_unexpected( m5::hal::error::error_t::INVALID_ARGUMENT );
return m5::stl::make_unexpected(m5::hal::error::error_t::INVALID_ARGUMENT);
}
if (access_config.getBusType() != getBusType()) {
M5_LIB_LOGE("SoftwareI2C::beginAccess: error %s", __PRETTY_FUNCTION__);
return m5::stl::make_unexpected( m5::hal::error::error_t::INVALID_ARGUMENT );
return m5::stl::make_unexpected(m5::hal::error::error_t::INVALID_ARGUMENT);
}
auto result = new SoftwareI2CMasterAccessor(*this, (I2CMasterAccessConfig&)access_config);
_Accessor.reset(result);
@@ -76,25 +75,25 @@ m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::sendDummyClo
auto scl = bc.pin_scl;
/// SDAがLOWになっている場合は処理
if (!sda->read())
{
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE;//_nop_wait_w >> 1;
if (!sda->read()) {
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE; //_nop_wait_w >> 1;
scl->writeLow();
sda->writeHigh();
delayCycle(delay_cycle);
// SDAがHIGHになるまでクロック送出しながら待機する。;
while (!(sda->read()) && (--count))
{
scl->writeHigh();
delayCycle(delay_cycle);
scl->writeLow();
sda->writeHigh();
delayCycle(delay_cycle);
}
// SDAがHIGHになるまでクロック送出しながら待機する。;
while (!(sda->read()) && (--count)) {
scl->writeHigh();
delayCycle(delay_cycle);
scl->writeLow();
delayCycle(delay_cycle);
}
}
if (count == 0) {
return m5::stl::make_unexpected(error::error_t::I2C_BUS_ERROR);
}
if (count == 0) { return m5::stl::make_unexpected ( error::error_t::I2C_BUS_ERROR ); }
return {};
}
@@ -105,10 +104,10 @@ m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::sendStartCon
auto sda = bc.pin_sda;
auto scl = bc.pin_scl;
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE;//_nop_wait_w >> 1;
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE; //_nop_wait_w >> 1;
// start condition
// start condition
scl->writeHigh();
delayCycle(delay_cycle);
sda->writeLow();
@@ -120,46 +119,44 @@ int delay_cycle = DELAY_CYCLE;//_nop_wait_w >> 1;
m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::sendStopCondition(void)
{
auto bc = static_cast<const I2CBusConfig&>(getBusConfig());
auto bc = static_cast<const I2CBusConfig&>(getBusConfig());
auto sda = bc.pin_sda;
auto scl = bc.pin_scl;
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE;//_nop_wait_w >> 1;
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE; //_nop_wait_w >> 1;
auto res = sendDummyClockWhileSdaLow();
if (res.has_value()) {
// stop condition
sda->writeLow();
scl->writeHigh();
delayCycle(delay_cycle);
sda->writeHigh();
// stop condition
sda->writeLow();
scl->writeHigh();
delayCycle(delay_cycle);
sda->writeHigh();
}
return res;
}
m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::waitClockStretch(uint_fast16_t msec)
{
auto bc = static_cast<const I2CBusConfig&>(getBusConfig());
auto bc = static_cast<const I2CBusConfig&>(getBusConfig());
auto scl = bc.pin_scl;
auto ms = m5::utility::millis();
do
{
std::this_thread::yield();
if (scl->read())
{
return {};
}
auto ms = m5::utility::millis();
do {
std::this_thread::yield();
if (scl->read()) {
return {};
}
} while ((m5::utility::millis() - ms) < msec);
return m5::stl::make_unexpected ( error::error_t::I2C_BUS_ERROR );
return m5::stl::make_unexpected(error::error_t::I2C_BUS_ERROR);
}
m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::startWrite(void)
{
auto ac = static_cast<const I2CMasterAccessConfig&>(getAccessConfig());
sendStartCondition();
uint8_t data[] = { (uint8_t)(ac.i2c_addr << 1) };
auto result = write(data, sizeof(data));
uint8_t data[] = {(uint8_t)(ac.i2c_addr << 1)};
auto result = write(data, sizeof(data));
if (result.has_value()) return {};
return m5::stl::make_unexpected(result.error());
}
@@ -168,8 +165,8 @@ m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::startRead(vo
{
auto ac = static_cast<const I2CMasterAccessConfig&>(getAccessConfig());
sendStartCondition();
uint8_t data[] = { (uint8_t)(ac.i2c_addr << 1 | 1) };
auto result = write(data, sizeof(data));
uint8_t data[] = {(uint8_t)(ac.i2c_addr << 1 | 1)};
auto result = write(data, sizeof(data));
if (result.has_value()) return {};
return m5::stl::make_unexpected(result.error());
}
@@ -187,80 +184,75 @@ m5::stl::expected<size_t, m5::hal::error::error_t> SoftwareI2CMasterAccessor::wr
auto scl = bc.pin_scl;
auto sda = bc.pin_sda;
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE;//_nop_wait_w >> 1;
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE; //_nop_wait_w >> 1;
int_fast16_t dc0 = (delay_cycle) >> 2;
int_fast16_t dc1 = delay_cycle - dc0;
size_t result = 0;
do
{
uint_fast8_t mask = 0x80;
uint_fast8_t d = *data++;
size_t result = 0;
do {
uint_fast8_t mask = 0x80;
uint_fast8_t d = *data++;
// 最初の1bitの送信
sda->write((bool)(d & mask));
delayCycle(dc0);
scl->writeHigh();
delayCycle(dc1);
// クロックストレッチの判定と待機;
if (!scl->read())
{ // タイムアウト時間までクロックストレッチが解除されるのを待つ;
auto result = waitClockStretch(ac.timeout_msec);
if (!result)
{
M5_LIB_LOGE("TIMEOUT");
sda->writeHigh();
return m5::stl::make_unexpected ( error::error_t::TIMEOUT_ERROR );
}
}
mask >>= 1;
do
{ // 2bit~8bit目の送信;
scl->writeLow();
// 最初の1bitの送信
sda->write((bool)(d & mask));
delayCycle(dc0);
scl->writeHigh();
delayCycle(dc1);
mask >>= 1;
} while (mask);
// ACK応答チェック;
scl->writeLow(); // SCL lo
sda->writeHigh(); // SDA hi
delayCycle(dc1);
scl->writeHigh(); // hi
delayCycle(dc0);
// クロックストレッチの判定と待機;
if (!scl->read())
{ // タイムアウト時間までクロックストレッチが解除されるのを待つ;
auto result = waitClockStretch(ac.timeout_msec);
if (!result)
{
M5_LIB_LOGE("TIMEOUT2");
return m5::stl::make_unexpected ( error::error_t::TIMEOUT_ERROR );
// クロックストレッチの判定と待機;
if (!scl->read()) { // タイムアウト時間までクロックストレッチが解除されるのを待つ;
auto result = waitClockStretch(ac.timeout_msec);
if (!result) {
M5_LIB_LOGE("TIMEOUT");
sda->writeHigh();
return m5::stl::make_unexpected(error::error_t::TIMEOUT_ERROR);
}
}
}
if (sda->read())
{ // ToDo:ACK応答がない場合の処理;
M5_LIB_LOGE("NO_ACK");
{
// re-init?
scl->writeLow();
sda->writeLow();
scl->writeHigh();
delayCycle(128);
sda->writeHigh();
}
return m5::stl::make_unexpected ( error::error_t::I2C_NO_ACK );
}
scl->writeLow();
mask >>= 1;
do { // 2bit~8bit目の送信;
scl->writeLow();
sda->write((bool)(d & mask));
delayCycle(dc0);
scl->writeHigh();
delayCycle(dc1);
mask >>= 1;
} while (mask);
// ACK応答チェック;
scl->writeLow(); // SCL lo
sda->writeHigh(); // SDA hi
delayCycle(dc1);
scl->writeHigh(); // hi
delayCycle(dc0);
// クロックストレッチの判定と待機;
if (!scl->read()) { // タイムアウト時間までクロックストレッチが解除されるのを待つ;
auto result = waitClockStretch(ac.timeout_msec);
if (!result) {
M5_LIB_LOGE("TIMEOUT2");
return m5::stl::make_unexpected(error::error_t::TIMEOUT_ERROR);
}
}
if (sda->read()) { // ToDo:ACK応答がない場合の処理;
M5_LIB_LOGE("NO_ACK");
{
// re-init?
scl->writeLow();
sda->writeLow();
scl->writeHigh();
delayCycle(128);
sda->writeHigh();
}
return m5::stl::make_unexpected(error::error_t::I2C_NO_ACK);
}
scl->writeLow();
} while (++result < len);
return result;
}
m5::stl::expected<size_t, m5::hal::error::error_t> SoftwareI2CMasterAccessor::readWithLastNackFlag(uint8_t* data, size_t len, bool last_nack)
m5::stl::expected<size_t, m5::hal::error::error_t> SoftwareI2CMasterAccessor::readWithLastNackFlag(uint8_t* data,
size_t len,
bool last_nack)
{
auto bc = static_cast<const I2CBusConfig&>(getBusConfig());
auto ac = static_cast<const I2CMasterAccessConfig&>(getAccessConfig());
@@ -268,83 +260,76 @@ m5::stl::expected<size_t, m5::hal::error::error_t> SoftwareI2CMasterAccessor::re
auto scl = bc.pin_scl;
auto sda = bc.pin_sda;
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE;//_nop_wait_w;
/// @TODO:ディレイサイクル数を求める仕組みを作っておくこと。
int delay_cycle = DELAY_CYCLE; //_nop_wait_w;
int_fast16_t dc0 = (delay_cycle) >> 1;
int_fast16_t dc1 = delay_cycle - dc0;
size_t result = 0;
do
{
// 最初の1bitの受信
sda->writeHigh();
size_t result = 0;
do {
// 最初の1bitの受信
sda->writeHigh();
delayCycle(dc0);
scl->writeHigh();
delayCycle(dc1);
// クロックストレッチの判定と待機;
if (!scl->read())
{ // タイムアウト時間までクロックストレッチが解除されるのを待つ;
if (!waitClockStretch(ac.timeout_msec))
{
return m5::stl::make_unexpected ( error::error_t::TIMEOUT_ERROR );
}
}
uint_fast8_t mask = 0x80;
uint_fast8_t byte = sda->read() ? mask : 0;
mask >>= 1;
do
{
scl->writeLow();
delayCycle(dc0);
scl->writeHigh();
delayCycle(dc1);
if (sda->read())
{
byte |= mask;
// クロックストレッチの判定と待機;
if (!scl->read()) { // タイムアウト時間までクロックストレッチが解除されるのを待つ;
if (!waitClockStretch(ac.timeout_msec)) {
return m5::stl::make_unexpected(error::error_t::TIMEOUT_ERROR);
}
}
uint_fast8_t mask = 0x80;
uint_fast8_t byte = sda->read() ? mask : 0;
mask >>= 1;
} while (mask);
scl->writeLow();
/// ACKを返す (ただし、データ末尾かつNACK指定がある場合はACKを返さない);
if ((++result < len) || !last_nack)
{
sda->writeLow();
}
delayCycle(dc0);
scl->writeHigh();
delayCycle(dc1);
scl->writeLow();
*data++ = byte;
do {
scl->writeLow();
delayCycle(dc0);
scl->writeHigh();
delayCycle(dc1);
if (sda->read()) {
byte |= mask;
}
mask >>= 1;
} while (mask);
scl->writeLow();
/// ACKを返す (ただし、データ末尾かつNACK指定がある場合はACKを返さない);
if ((++result < len) || !last_nack) {
sda->writeLow();
}
delayCycle(dc0);
scl->writeHigh();
delayCycle(dc1);
scl->writeLow();
*data++ = byte;
} while (result < len);
return result;
}
// I2CBus* createBus(const I2CBusConfig& config)
// {
// static SoftwareI2CBus i2c_bus;
// return &i2c_bus;
// }
// error::error_t SoftwareI2CMasterAccessor::init(const interface::bus::BusConfig& config) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::release(void) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::start(void) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::stop(void) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::lock(void) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::unlock(void) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::beginAccess(interface::bus::Accessor* Accessor) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::endAccess(void) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::setFrequency(uint32_t freq) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::read(uint8_t* data, size_t len, interface::io::AsyncResult* async) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::write(const uint8_t* data, size_t len, interface::io::AsyncResult* async) { return error::error_t::NOT_IMPLEMENTED; }
// error::error_t SoftwareI2CMasterAccessor::init(const interface::bus::BusConfig& config) { return
// error::error_t::NOT_IMPLEMENTED; } error::error_t SoftwareI2CMasterAccessor::release(void) { return
// error::error_t::NOT_IMPLEMENTED; } error::error_t SoftwareI2CMasterAccessor::start(void) { return
// error::error_t::NOT_IMPLEMENTED; } error::error_t SoftwareI2CMasterAccessor::stop(void) { return
// error::error_t::NOT_IMPLEMENTED; } error::error_t SoftwareI2CMasterAccessor::lock(void) { return
// error::error_t::NOT_IMPLEMENTED; } error::error_t SoftwareI2CMasterAccessor::unlock(void) { return
// error::error_t::NOT_IMPLEMENTED; } error::error_t SoftwareI2CMasterAccessor::beginAccess(interface::bus::Accessor*
// Accessor) { return error::error_t::NOT_IMPLEMENTED; } error::error_t SoftwareI2CMasterAccessor::endAccess(void) {
// return error::error_t::NOT_IMPLEMENTED; } error::error_t SoftwareI2CMasterAccessor::setFrequency(uint32_t freq) {
// return error::error_t::NOT_IMPLEMENTED; } error::error_t SoftwareI2CMasterAccessor::read(uint8_t* data, size_t len,
// interface::io::AsyncResult* async) { return error::error_t::NOT_IMPLEMENTED; } error::error_t
// SoftwareI2CMasterAccessor::write(const uint8_t* data, size_t len, interface::io::AsyncResult* async) { return
// error::error_t::NOT_IMPLEMENTED; }
} // namespace i2c
} // namespace bus
} // namespace hal
} // namespace m5
} // namespace i2c
} // namespace bus
} // namespace hal
} // namespace m5
+89 -67
View File
@@ -6,110 +6,132 @@
namespace m5 {
namespace hal {
namespace bus {
/// @brief SPIバスの設定
/// @details 標準的なSPIだけでなく、QSPI,OSPIの設定も可能となっている
struct SPIBusConfig : public BusConfig {
virtual ~SPIBusConfig() = default;
types::bus_type_t getBusType(void) const override { return types::bus_type_t::SPI; };
types::bus_type_t getBusType(void) const override
{
return types::bus_type_t::SPI;
};
union {
interface::gpio::Pin* pins[9];
struct {
interface::gpio::Pin* pin_clk;
interface::gpio::Pin* pin_dc;
interface::gpio::Pin* pin_mosi; // data0
interface::gpio::Pin* pin_miso; // data1
interface::gpio::Pin* pin_d2; // data2
interface::gpio::Pin* pin_d3; // data3
interface::gpio::Pin* pin_d4; // data4
interface::gpio::Pin* pin_d5; // data5
interface::gpio::Pin* pin_d6; // data6
interface::gpio::Pin* pin_d7; // data7
interface::gpio::Pin* pin_mosi; // data0
interface::gpio::Pin* pin_miso; // data1
interface::gpio::Pin* pin_d2; // data2
interface::gpio::Pin* pin_d3; // data3
interface::gpio::Pin* pin_d4; // data4
interface::gpio::Pin* pin_d5; // data5
interface::gpio::Pin* pin_d6; // data6
interface::gpio::Pin* pin_d7; // data7
};
};
};
enum class SpiDataMode {
spi_halfduplex, // 半二重通信
spi_fullduplex,
spi_halfduplex_with_dc_pin, // 半二重通信+DCピン
spi_fullduplex_with_dc_pin, // 全二重通信+DCピン
spi_halfduplex_with_dc_bit, // 半二重通信+DCビット(9ビットSPI)
spi_fullduplex_with_dc_bit, // 全二重通信+DCビット(9ビットSPI)
spi_dual_output,
spi_dual_io,
spi_quad_output,
spi_quad_io,
spi_octal_output,
spi_octal_io,
spi_halfduplex, // 半二重通信
spi_fullduplex,
spi_halfduplex_with_dc_pin, // 半二重通信+DCピン
spi_fullduplex_with_dc_pin, // 全二重通信+DCピン
spi_halfduplex_with_dc_bit, // 半二重通信+DCビット(9ビットSPI)
spi_fullduplex_with_dc_bit, // 全二重通信+DCビット(9ビットSPI)
spi_dual_output,
spi_dual_io,
spi_quad_output,
spi_quad_io,
spi_octal_output,
spi_octal_io,
};
typedef SpiDataMode spi_data_mode_t;
struct SPIMasterAccessConfig : public AccessConfig {
virtual ~SPIMasterAccessConfig() = default;
types::bus_type_t getBusType(void) const override { return types::bus_type_t::SPI; };
types::bus_type_t getBusType(void) const override
{
return types::bus_type_t::SPI;
};
interface::gpio::Pin* pin_cs;
uint32_t freq;
spi_data_mode_t spi_data_mode;
struct {
uint8_t spi_mode:2;
uint8_t spi_order:1;
uint8_t spi_mode : 2;
uint8_t spi_order : 1;
};
uint8_t spi_command_length = 0; // コマンド部のビット長
uint8_t spi_address_length = 0; // アドレス部のビット長
uint8_t spi_dummy_cycle = 0; // アドレスからデータへ移る際のダミーサイクル数
uint8_t spi_command_length = 0; // コマンド部のビット長
uint8_t spi_address_length = 0; // アドレス部のビット長
uint8_t spi_dummy_cycle = 0; // アドレスからデータへ移る際のダミーサイクル数
};
namespace spi {
struct SPIMasterAccessor : public Accessor
struct SPIMasterAccessor : public Accessor {
SPIMasterAccessor(Bus& bus, const SPIMasterAccessConfig& access_config)
: Accessor{bus}, _access_config{access_config}
{
SPIMasterAccessor(Bus& bus, const SPIMasterAccessConfig& access_config) : Accessor { bus }, _access_config { access_config } {}
types::bus_type_t getBusType(void) const override { return types::bus_type_t::SPI; };
const AccessConfig& getAccessConfig(void) const override { return _access_config; }
virtual m5::stl::expected<size_t, m5::hal::error::error_t> writeCommand(const uint8_t* data, size_t len);
virtual m5::stl::expected<size_t, m5::hal::error::error_t> writeCommandData(const uint8_t* data, size_t len);
virtual m5::stl::expected<void, m5::hal::error::error_t> sendDummyClock(size_t count);
virtual m5::stl::expected<void, m5::hal::error::error_t> cs_control(bool cs_level);
protected:
SPIMasterAccessConfig _access_config;
};
class SoftwareSPIMasterAccessor : public SPIMasterAccessor
}
types::bus_type_t getBusType(void) const override
{
public:
SoftwareSPIMasterAccessor(Bus& bus, const SPIMasterAccessConfig& access_config) : SPIMasterAccessor { bus, access_config } {}
m5::stl::expected<size_t, m5::hal::error::error_t> read(uint8_t* data, size_t len) override;
m5::stl::expected<size_t, m5::hal::error::error_t> write(const uint8_t* data, size_t len) override;
return types::bus_type_t::SPI;
};
const AccessConfig& getAccessConfig(void) const override
{
return _access_config;
}
virtual m5::stl::expected<size_t, m5::hal::error::error_t> writeCommand(const uint8_t* data, size_t len);
virtual m5::stl::expected<size_t, m5::hal::error::error_t> writeCommandData(const uint8_t* data, size_t len);
virtual m5::stl::expected<void, m5::hal::error::error_t> sendDummyClock(size_t count);
virtual m5::stl::expected<void, m5::hal::error::error_t> cs_control(bool cs_level);
protected:
SPIMasterAccessConfig _access_config;
};
class SoftwareSPIMasterAccessor : public SPIMasterAccessor {
public:
SoftwareSPIMasterAccessor(Bus& bus, const SPIMasterAccessConfig& access_config)
: SPIMasterAccessor{bus, access_config}
{
}
m5::stl::expected<size_t, m5::hal::error::error_t> read(uint8_t* data, size_t len) override;
m5::stl::expected<size_t, m5::hal::error::error_t> write(const uint8_t* data, size_t len) override;
};
//-------------------------------------------------------------------------
struct SPIBus : public Bus {
types::bus_type_t getBusType(void) const override { return types::bus_type_t::SPI; };
const BusConfig& getConfig(void) const override { return _config; }
// virtual SPIMasterAccessor* beginAccess(const SPIMasterAccessConfig& access_config) = 0;
// Accessor* beginAccess(const AccessConfig& access_config) override { return beginAccess((const SPIMasterAccessConfig&)access_config); }
protected:
SPIBusConfig _config;
};
class SoftwareSPIBus : public SPIBus
struct SPIBus : public Bus {
types::bus_type_t getBusType(void) const override
{
public:
error::error_t init(const BusConfig& config) override;
m5::stl::expected<Accessor*, m5::hal::error::error_t> beginAccess(const AccessConfig& access_config) override;
// SPIMasterAccessor* beginAccess(const SPIMasterAccessConfig& access_config) override;
return types::bus_type_t::SPI;
};
const BusConfig& getConfig(void) const override
{
return _config;
}
m5::stl::expected<SPIBus*, m5::hal::error::error_t> getBus(const SPIBusConfig& config);
// SPIBus* createBus(const SPIBusConfig& config); // { return spi::createBus(config); }
} // namespace spi
// virtual SPIMasterAccessor* beginAccess(const SPIMasterAccessConfig& access_config) = 0;
// Accessor* beginAccess(const AccessConfig& access_config) override { return beginAccess((const
// SPIMasterAccessConfig&)access_config); }
protected:
SPIBusConfig _config;
};
class SoftwareSPIBus : public SPIBus {
public:
error::error_t init(const BusConfig& config) override;
m5::stl::expected<Accessor*, m5::hal::error::error_t> beginAccess(const AccessConfig& access_config) override;
// SPIMasterAccessor* beginAccess(const SPIMasterAccessConfig& access_config) override;
};
} // namespace bus
} // namespace hal
} // namespace m5
m5::stl::expected<SPIBus*, m5::hal::error::error_t> getBus(const SPIBusConfig& config);
// SPIBus* createBus(const SPIBusConfig& config); // { return spi::createBus(config); }
} // namespace spi
} // namespace bus
} // namespace hal
} // namespace m5
#endif
+26 -25
View File
@@ -4,7 +4,7 @@
namespace m5 {
namespace hal {
namespace bus {
namespace spi {
namespace spi {
m5::stl::expected<SPIBus*, m5::hal::error::error_t> getBus(const SPIBusConfig& config)
{
@@ -14,7 +14,8 @@ m5::stl::expected<SPIBus*, m5::hal::error::error_t> getBus(const SPIBusConfig& c
return &spi_bus;
}
error::error_t SoftwareSPIBus::init(const BusConfig& config) {
error::error_t SoftwareSPIBus::init(const BusConfig& config)
{
if (config.getBusType() != types::bus_type_t::SPI) {
M5_LIB_LOGE("SoftwareSPI::init: error %s", __PRETTY_FUNCTION__);
return error::error_t::INVALID_ARGUMENT;
@@ -56,8 +57,8 @@ m5::stl::expected<Accessor*, m5::hal::error::error_t> SoftwareSPIBus::beginAcces
m5::stl::expected<void, m5::hal::error::error_t> SPIMasterAccessor::sendDummyClock(size_t count)
{
if (count) {
auto bc = static_cast<const SPIBusConfig&>(getBusConfig());
auto ac = static_cast<const SPIMasterAccessConfig&>(getAccessConfig());
auto bc = static_cast<const SPIBusConfig&>(getBusConfig());
auto ac = static_cast<const SPIMasterAccessConfig&>(getAccessConfig());
auto cpol = (ac.spi_mode & 2);
auto sclk = bc.pin_clk;
do {
@@ -70,7 +71,7 @@ m5::stl::expected<void, m5::hal::error::error_t> SPIMasterAccessor::sendDummyClo
m5::stl::expected<size_t, m5::hal::error::error_t> SPIMasterAccessor::writeCommand(const uint8_t* data, size_t len)
{
auto bc = static_cast<const SPIBusConfig&>(getBusConfig());
auto bc = static_cast<const SPIBusConfig&>(getBusConfig());
auto pin_dc = bc.pin_dc;
if (pin_dc) pin_dc->write(false);
auto res = write(data, len);
@@ -80,9 +81,9 @@ m5::stl::expected<size_t, m5::hal::error::error_t> SPIMasterAccessor::writeComma
m5::stl::expected<size_t, m5::hal::error::error_t> SPIMasterAccessor::writeCommandData(const uint8_t* data, size_t len)
{
auto bc = static_cast<const SPIBusConfig&>(getBusConfig());
auto pin_dc = bc.pin_dc;
auto ac = static_cast<const SPIMasterAccessConfig&>(getAccessConfig());
auto bc = static_cast<const SPIBusConfig&>(getBusConfig());
auto pin_dc = bc.pin_dc;
auto ac = static_cast<const SPIMasterAccessConfig&>(getAccessConfig());
auto cmd_len = (ac.spi_command_length >> 3);
if (cmd_len) {
if (pin_dc) pin_dc->write(false);
@@ -92,8 +93,10 @@ m5::stl::expected<size_t, m5::hal::error::error_t> SPIMasterAccessor::writeComma
if (pin_dc) pin_dc->write(true);
if (!res || datalen == 0) return res;
res = write(data, datalen);
if (!res) { return res; }
return len;
if (!res) {
return res;
}
return len;
}
return write(data, len);
}
@@ -107,7 +110,7 @@ m5::stl::expected<void, m5::hal::error::error_t> SPIMasterAccessor::cs_control(b
m5::stl::expected<size_t, m5::hal::error::error_t> SoftwareSPIMasterAccessor::read(uint8_t* data, size_t len)
{
return m5::stl::make_unexpected ( error::error_t::NOT_IMPLEMENTED );
return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED);
}
m5::stl::expected<size_t, m5::hal::error::error_t> SoftwareSPIMasterAccessor::write(const uint8_t* data, size_t len)
@@ -122,23 +125,21 @@ m5::stl::expected<size_t, m5::hal::error::error_t> SoftwareSPIMasterAccessor::wr
auto mosi = bc.pin_mosi;
size_t result = 0;
do
{
uint_fast8_t mask = 0x80;
uint_fast8_t d = *data++;
do
{
mosi->write(d & mask);
sclk->write(flip);
sclk->write(!flip);
} while (mask >>= 1);
do {
uint_fast8_t mask = 0x80;
uint_fast8_t d = *data++;
do {
mosi->write(d & mask);
sclk->write(flip);
sclk->write(!flip);
} while (mask >>= 1);
} while (++result < len);
sclk->write(cpol);
return result;
}
} // namespace spi
} // namespace bus
} // namespace hal
} // namespace m5
} // namespace spi
} // namespace bus
} // namespace hal
} // namespace m5
+18 -16
View File
@@ -9,27 +9,29 @@ namespace hal {
namespace error {
enum class ErrorType : int8_t {
ASYNC_RUNNING = 1,
OK = 0,
UNKNOWN_ERROR = -1,
TIMEOUT_ERROR = -2,
INVALID_ARGUMENT = -3,
NOT_IMPLEMENTED = -4,
I2C_BUS_ERROR = -5,
I2C_NO_ACK = -6,
// @ TODO エラーコード細分化する
ASYNC_RUNNING = 1,
OK = 0,
UNKNOWN_ERROR = -1,
TIMEOUT_ERROR = -2,
INVALID_ARGUMENT = -3,
NOT_IMPLEMENTED = -4,
I2C_BUS_ERROR = -5,
I2C_NO_ACK = -6,
// @ TODO エラーコード細分化する
};
using error_t = ErrorType;
constexpr bool isError(const error_t e) {
return e < error_t::OK;
constexpr bool isError(const error_t e)
{
return e < error_t::OK;
}
constexpr bool isOk(const error_t e) {
return e == error_t::OK;
constexpr bool isOk(const error_t e)
{
return e == error_t::OK;
}
} // namespace error
} // namespace hal
} // namespace m5
} // namespace error
} // namespace hal
} // namespace m5
#endif
+7 -11
View File
@@ -1,26 +1,22 @@
#ifndef M5_HAL_FRAMEWORK_CHECKER_HPP
#define M5_HAL_FRAMEWORK_CHECKER_HPP
#if defined ( ARDUINO )
#define M5HAL_FRAMEWORK_HAS_ARDUINO 1
#if defined(ARDUINO)
#define M5HAL_FRAMEWORK_HAS_ARDUINO 1
#else
#define M5HAL_FRAMEWORK_HAS_ARDUINO 0
#define M5HAL_FRAMEWORK_HAS_ARDUINO 0
#endif
#if __has_include(<FreeRTOS.h>) || __has_include(<freertos/FreeRTOS.h>)
#define M5HAL_FRAMEWORK_HAS_FREERTOS 1
#define M5HAL_FRAMEWORK_HAS_FREERTOS 1
#else
#define M5HAL_FRAMEWORK_HAS_FREERTOS 0
#define M5HAL_FRAMEWORK_HAS_FREERTOS 0
#endif
#if __has_include(<SDL2/SDL.h>) || __has_include(<SDL.h>)
#define M5HAL_FRAMEWORK_HAS_SDL 1
#define M5HAL_FRAMEWORK_HAS_SDL 1
#else
#define M5HAL_FRAMEWORK_HAS_SDL 0
#define M5HAL_FRAMEWORK_HAS_SDL 0
#endif
#endif
+47 -41
View File
@@ -8,7 +8,7 @@
#include <Wire.h>
#endif
#if defined( ARDUINO )
#if defined(ARDUINO)
namespace m5 {
namespace hal {
@@ -16,57 +16,63 @@ namespace frameworks {
namespace arduino {
namespace gpio {
// 単一のデジタルピンを表すインターフェイス
class Pin : public interface::gpio::Pin {
public:
void write(bool value) override;
void writeHigh(void) override;
void writeLow(void) override;
bool read(void) override;
// 単一のデジタルピンを表すインターフェイス
class Pin : public interface::gpio::Pin {
public:
void write(bool value) override;
void writeHigh(void) override;
void writeLow(void) override;
bool read(void) override;
void setMode(types::gpio_mode_t mode) override;
types::gpio_number_t getGpioNumber(void) const override { return _gpio_number; }
void setMode(types::gpio_mode_t mode) override;
types::gpio_number_t getGpioNumber(void) const override
{
return _gpio_number;
}
Pin(void) = default;
Pin(types::gpio_number_t gpio_number) : _gpio_number { gpio_number }
{}
protected:
types::gpio_number_t _gpio_number;// = (int16_t)-1;
};
Pin(void) = default;
Pin(types::gpio_number_t gpio_number) : _gpio_number{gpio_number}
{
}
// 複数のPinを束ねた概念を表すインターフェイス
class Port : public interface::gpio::Port {
public:
interface::gpio::Pin* getPin(uint8_t pinNumber) override;
// uint8_t getPortNumber(void) const override { return 0; }
// void setDirection(uint8_t mask, bool isOutput);
protected:
};
protected:
types::gpio_number_t _gpio_number; // = (int16_t)-1;
};
// ポートを含めてGPIO全体を表すインターフェイス
class GPIO : public interface::gpio::GPIO {
public:
interface::gpio::Port* getPort(uint8_t portNumber) override;
interface::gpio::Pin* getPin(types::gpio_number_t pinNumber) override;
private:
};
// 複数のPinを束ねた概念を表すインターフェイス
class Port : public interface::gpio::Port {
public:
interface::gpio::Pin* getPin(uint8_t pinNumber) override;
// uint8_t getPortNumber(void) const override { return 0; }
// void setDirection(uint8_t mask, bool isOutput);
protected:
};
interface::gpio::GPIO* getGPIO(void);
interface::gpio::Pin* getPin(types::gpio_number_t pinNumber);
// ポートを含めてGPIO全体を表すインターフェイス
class GPIO : public interface::gpio::GPIO {
public:
interface::gpio::Port* getPort(uint8_t portNumber) override;
interface::gpio::Pin* getPin(types::gpio_number_t pinNumber) override;
} // namespace gpio
private:
};
interface::gpio::GPIO* getGPIO(void);
interface::gpio::Pin* getPin(types::gpio_number_t pinNumber);
} // namespace gpio
namespace bus {
namespace i2c {
namespace i2c {
// bus::I2CBus* createBus(TwoWire& _wire);
} // namespace i2c
} // namespace bus
} // namespace arduino
} // namespace frameworks
} // namespace hal
} // namespace m5
} // namespace i2c
} // namespace bus
} // namespace arduino
} // namespace frameworks
} // namespace hal
} // namespace m5
#endif
+33 -27
View File
@@ -12,7 +12,7 @@
#include <vector>
#include <list>
#if defined( ARDUINO )
#if defined(ARDUINO)
namespace m5 {
namespace hal {
@@ -22,14 +22,14 @@ namespace gpio {
interface::gpio::GPIO* getGPIO(void)
{
M5_LIB_LOGV("getGPIO\n");
M5_LIB_LOGV("getGPIO\n");
static GPIO s_gpio_instance;
return &s_gpio_instance;
}
interface::gpio::Pin* getPin(types::gpio_number_t pinNumber)
{
M5_LIB_LOGV("getPin %d", pinNumber);
M5_LIB_LOGV("getPin %d", pinNumber);
return getGPIO()->getPin(pinNumber);
}
@@ -41,11 +41,12 @@ interface::gpio::Port* GPIO::getPort(uint8_t portNumber)
interface::gpio::Pin* GPIO::getPin(types::gpio_number_t pinNumber)
{
M5_LIB_LOGV("GPIO::getPin %d", pinNumber);
M5_LIB_LOGV("GPIO::getPin %d", pinNumber);
return getPort(0)->getPin(pinNumber);
}
interface::gpio::Pin* Port::getPin(uint8_t pinNumber) {
interface::gpio::Pin* Port::getPin(uint8_t pinNumber)
{
static std::vector<Pin*> s_pins_pointer;
static std::list<Pin> s_pins_instance;
if (s_pins_pointer.size() <= pinNumber) {
@@ -63,12 +64,17 @@ void Pin::write(bool value)
// M5_LIB_LOGV("Pin::write %d [pin %d]", value, _gpio_number);
digitalWrite(_gpio_number, value);
}
bool Pin::read(void) { return digitalRead(_gpio_number); }
void Pin::writeHigh(void) {
bool Pin::read(void)
{
return digitalRead(_gpio_number);
}
void Pin::writeHigh(void)
{
// M5_LIB_LOGV("Pin::setHigh [pin %d]", _gpio_number);
digitalWrite(_gpio_number, true);
}
void Pin::writeLow(void) {
void Pin::writeLow(void)
{
// M5_LIB_LOGV("Pin::setLow [pin %d]", _gpio_number);
digitalWrite(_gpio_number, false);
}
@@ -76,37 +82,37 @@ void Pin::writeLow(void) {
void Pin::setMode(types::gpio_mode_t mode)
{
switch (mode) {
case types::gpio_mode_t::Input:
pinMode(_gpio_number, INPUT);
break;
case types::gpio_mode_t::Output:
pinMode(_gpio_number, OUTPUT);
break;
case types::gpio_mode_t::Output_OpenDrain:
pinMode(_gpio_number, OUTPUT_OPEN_DRAIN);
break;
default:
break;
case types::gpio_mode_t::Input:
pinMode(_gpio_number, INPUT);
break;
case types::gpio_mode_t::Output:
pinMode(_gpio_number, OUTPUT);
break;
case types::gpio_mode_t::Output_OpenDrain:
pinMode(_gpio_number, OUTPUT_OPEN_DRAIN);
break;
default:
break;
}
}
} // namespace gpio
} // namespace gpio
namespace bus {
namespace i2c {
namespace i2c {
// interface::bus::I2C* createBus(TwoWire& _wire)
// {
// return nullptr;
// }
} // namespace i2c
} // namespace bus
} // namespace i2c
} // namespace bus
//
} // namespace arduino
} // namespace frameworks
} // namespace hal
} // namespace m5
} // namespace arduino
} // namespace frameworks
} // namespace hal
} // namespace m5
#endif
+7 -7
View File
@@ -10,13 +10,13 @@
@namespace m5
@brief Toplevel namespace of M5
*/
namespace m5 { namespace hal { namespace gpio {
class GPIO {
};
namespace m5 {
namespace hal {
namespace gpio {
class GPIO {};
};
}
}
}; // namespace gpio
} // namespace hal
} // namespace m5
#endif
+39 -21
View File
@@ -9,67 +9,85 @@
@namespace m5
@brief Toplevel namespace of M5
*/
namespace m5 { namespace hal { namespace interface {
namespace m5 {
namespace hal {
namespace interface {
// 抽象化されたGPIOインターフェースを置く。これは LowLayerではなく汎用的なもの。
// このGPIOインターフェースを継承してGPIOエキスパンダの実装を作ることもできる。
namespace gpio {
// 単一のデジタルピンを表すインターフェイス
struct Pin {
virtual ~Pin() = default;
virtual ~Pin() = default;
virtual void write(bool value) = 0;
virtual bool read(void) = 0;
virtual void writeHigh(void) { write(true); }
virtual void writeLow(void) { write(false); }
virtual bool read(void) = 0;
virtual void writeHigh(void)
{
write(true);
}
virtual void writeLow(void)
{
write(false);
}
virtual types::gpio_number_t getGpioNumber(void) const = 0;
virtual void setMode(types::gpio_mode_t mode) = 0;
virtual void setMode(types::gpio_mode_t mode) = 0;
};
// 複数のPinを保持する概念を表すインターフェイス
struct Port {
virtual ~Port() = default;
virtual ~Port() = default;
virtual Pin* getPin(uint8_t pinNumber) = 0;
// virtual uint8_t getPortNumber(void) const = 0;
};
// Portを複数含むGPIO全体を表すインターフェイス
struct GPIO {
virtual ~GPIO() = default;
virtual Port* getPort(uint8_t portNumber) = 0;
virtual ~GPIO() = default;
virtual Port* getPort(uint8_t portNumber) = 0;
virtual Pin* getPin(types::gpio_number_t gpioNumber) = 0;
virtual void digitalWrite(types::gpio_number_t gpioNumber, bool value) {
virtual void digitalWrite(types::gpio_number_t gpioNumber, bool value)
{
getPin(gpioNumber)->write(value);
}
virtual bool digitalRead(types::gpio_number_t gpioNumber) {
virtual bool digitalRead(types::gpio_number_t gpioNumber)
{
return getPin(gpioNumber)->read();
}
virtual int analogRead(types::gpio_number_t gpioNumber) {
virtual int analogRead(types::gpio_number_t gpioNumber)
{
return -1;
}
};
// n個のピンを内包するポート (例: 2個ならGROVEコネクタ、等)
// コンストラクタにてピンの数を指定する。生成後のサイズ変更は不可とする。
// 暫定的に std::vector でポインタを保持するが、将来的にはメモリ効率を考慮して変更する可能性あり。
class MultiPinPort : public Port {
public:
MultiPinPort(size_t size) : _pins { size, nullptr } {}
Pin* getPin(uint8_t pinNumber) override {
MultiPinPort(size_t size) : _pins{size, nullptr}
{
}
Pin* getPin(uint8_t pinNumber) override
{
return _pins.size() > pinNumber ? _pins[pinNumber] : nullptr;
}
void setPin(uint8_t pinNumber, Pin* pin) {
void setPin(uint8_t pinNumber, Pin* pin)
{
if (_pins.size() > pinNumber) _pins[pinNumber] = pin;
}
size_t getPinCount(void) const { return _pins.size(); }
size_t getPinCount(void) const
{
return _pins.size();
}
protected:
std::vector<Pin*> _pins;
};
} // namespace gpio
} // namespace interface
} // namespace hal
} // namespace m5
} // namespace gpio
} // namespace interface
} // namespace hal
} // namespace m5
#endif
+22 -12
View File
@@ -41,9 +41,12 @@ public:
// @param len 読み込むデータの長さ
// @return 読み込んだデータの長さ / エラー
virtual m5::stl::expected<size_t, m5::hal::error::error_t> read(uint8_t* data, size_t len) = 0;
// virtual std::future<m5::stl::expected<size_t, m5::hal::error::error_t> > asyncRead(uint8_t* data, size_t len, AsyncParam* async = nullptr) = 0;
// virtual std::future<m5::stl::expected<size_t, m5::hal::error::error_t> > asyncRead(uint8_t* data, size_t len,
// AsyncParam* async = nullptr) = 0;
virtual m5::stl::expected<size_t, m5::hal::error::error_t> availableRead(void) const
{ return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED); };
{
return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED);
};
};
struct Output {
@@ -51,28 +54,35 @@ public:
virtual ~Output() = default;
virtual m5::stl::expected<size_t, m5::hal::error::error_t> write(const uint8_t* data, size_t len) = 0;
// virtual std::future<m5::stl::expected<size_t, m5::hal::error::error_t> > asyncWrite(const uint8_t* data, size_t len, AsyncParam* async = nullptr) = 0;
// virtual std::future<m5::stl::expected<size_t, m5::hal::error::error_t> > asyncWrite(const uint8_t* data, size_t
// len, AsyncParam* async = nullptr) = 0;
virtual m5::stl::expected<size_t, m5::hal::error::error_t> availableWrite(void) const
{ return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED); };
{
return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED);
};
};
// Push型の入力はデータが一定量たまったらコールバックが呼ばれ、readで取得する
struct PushInput : public Input {
public:
virtual ~PushInput() = default;
virtual m5::stl::expected<void, m5::hal::error::error_t> setCallbackRead(void(*cb)(PushInput* bus, size_t available_len, void* cb_obj)) = 0;
virtual ~PushInput() = default;
virtual m5::stl::expected<void, m5::hal::error::error_t> setCallbackRead(void (*cb)(PushInput* bus,
size_t available_len,
void* cb_obj)) = 0;
};
// Push型の出力は新しいデータが必要になったらコールバックが呼ばれ、writeで書き込む
struct PushOutput : public Output {
public:
virtual ~PushOutput() = default;
virtual m5::stl::expected<void, m5::hal::error::error_t> setCallbackWrite(void(*cb)(PushOutput* bus, size_t request_len, void* cb_obj)) = 0;
virtual ~PushOutput() = default;
virtual m5::stl::expected<void, m5::hal::error::error_t> setCallbackWrite(void (*cb)(PushOutput* bus,
size_t request_len,
void* cb_obj)) = 0;
};
} // namespace io
} // namespace interface
} // namespace hal
} // namespace m5
} // namespace io
} // namespace interface
} // namespace hal
} // namespace m5
#endif
+42 -44
View File
@@ -1,62 +1,60 @@
#ifndef M5_HAL_PLATFORM_CHECKER_HPP
#define M5_HAL_PLATFORM_CHECKER_HPP
#define M5HAL_PLATFORM_NUMBER_UNKNOWN 0
#define M5HAL_PLATFORM_NUMBER_WINDOWS 10
#define M5HAL_PLATFORM_NUMBER_MACOS 20
#define M5HAL_PLATFORM_NUMBER_LINUX 30
#define M5HAL_PLATFORM_NUMBER_UNKNOWN 0
#define M5HAL_PLATFORM_NUMBER_WINDOWS 10
#define M5HAL_PLATFORM_NUMBER_MACOS 20
#define M5HAL_PLATFORM_NUMBER_LINUX 30
#define M5HAL_PLATFORM_NUMBER_SDL_MAX 99
#define M5HAL_PLATFORM_NUMBER_SDL_MAX 99
#define M5HAL_PLATFORM_NUMBER_AVR 200
#define M5HAL_PLATFORM_NUMBER_ESP8266 300
#define M5HAL_PLATFORM_NUMBER_ESP32_UNKNOWN 310
#define M5HAL_PLATFORM_NUMBER_ESP32_1st 311
#define M5HAL_PLATFORM_NUMBER_ESP32_S2 312
#define M5HAL_PLATFORM_NUMBER_ESP32_S3 313
#define M5HAL_PLATFORM_NUMBER_ESP32_C3 314
#define M5HAL_PLATFORM_NUMBER_ESP32_C6 315
#define M5HAL_PLATFORM_NUMBER_RP2040 400
#define M5HAL_PLATFORM_NUMBER_SAMD21 500
#define M5HAL_PLATFORM_NUMBER_SAMD51 510
#define M5HAL_PLATFORM_NUMBER_SPRESENSE 600
#define M5HAL_PLATFORM_NUMBER_STM32 700
#define M5HAL_PLATFORM_NUMBER_AVR 200
#define M5HAL_PLATFORM_NUMBER_ESP8266 300
#define M5HAL_PLATFORM_NUMBER_ESP32_UNKNOWN 310
#define M5HAL_PLATFORM_NUMBER_ESP32_1st 311
#define M5HAL_PLATFORM_NUMBER_ESP32_S2 312
#define M5HAL_PLATFORM_NUMBER_ESP32_S3 313
#define M5HAL_PLATFORM_NUMBER_ESP32_C3 314
#define M5HAL_PLATFORM_NUMBER_ESP32_C6 315
#define M5HAL_PLATFORM_NUMBER_RP2040 400
#define M5HAL_PLATFORM_NUMBER_SAMD21 500
#define M5HAL_PLATFORM_NUMBER_SAMD51 510
#define M5HAL_PLATFORM_NUMBER_SPRESENSE 600
#define M5HAL_PLATFORM_NUMBER_STM32 700
#define XSTR(x) STR(x)
#define STR(x) #x
#define STR(x) #x
#if defined(ESP_PLATFORM)
#if __has_include(<sdkconfig.h>)
#include <sdkconfig.h>
#endif
#if defined(CONFIG_IDF_TARGET)
#if defined(CONFIG_IDF_TARGET_ESP32C3)
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32C3
#define M5HAL_TARGET_PLATFORM_PATH m5_hal / platforms / espressif / esp32c3
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32S3
#define M5HAL_TARGET_PLATFORM_PATH m5_hal / platforms / espressif / esp32s3
#elif defined(CONFIG_IDF_TARGET_ESP32)
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32_1st
#define M5HAL_TARGET_PLATFORM_PATH m5_hal / platforms / espressif / esp32
#if defined ( ESP_PLATFORM )
#if __has_include (<sdkconfig.h>)
#include <sdkconfig.h>
#endif
#if defined ( CONFIG_IDF_TARGET )
#if defined ( CONFIG_IDF_TARGET_ESP32C3 )
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32C3
#define M5HAL_TARGET_PLATFORM_PATH m5_hal/platforms/espressif/esp32c3
#elif defined ( CONFIG_IDF_TARGET_ESP32S3 )
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32S3
#define M5HAL_TARGET_PLATFORM_PATH m5_hal/platforms/espressif/esp32s3
#elif defined ( CONFIG_IDF_TARGET_ESP32 )
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32_1st
#define M5HAL_TARGET_PLATFORM_PATH m5_hal/platforms/espressif/esp32
#elif defined ( CONFIG_IDF_TARGET_ESP32C6 )
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32_C6
#define M5HAL_TARGET_PLATFORM_PATH m5_hal/platforms/espressif/esp32c6
#else
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32_UNKNOWN
#define M5HAL_TARGET_PLATFORM_PATH m5_hal/platforms/espressif/esp32_unknown
#endif
#endif
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32_C6
#define M5HAL_TARGET_PLATFORM_PATH m5_hal / platforms / espressif / esp32c6
#else
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32_UNKNOWN
#define M5HAL_TARGET_PLATFORM_PATH m5_hal / platforms / espressif / esp32_unknown
#endif
#endif
#else
#endif
#undef XSTR
#undef STR
#if !defined ( M5HAL_TARGET_PLATFORM_NUMBER )
#if !defined(M5HAL_TARGET_PLATFORM_NUMBER)
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_UNKNOWN
#endif
+11 -11
View File
@@ -17,23 +17,23 @@ namespace esp32 {
namespace types {
enum class PeripheralType : uint8_t {
none = 0,
i2c0,
i2c1,
spi2,
spi3,
none = 0,
i2c0,
i2c1,
spi2,
spi3,
};
using periph_t = PeripheralType;
} // namespace types
} // namespace types
namespace gpio {
interface::gpio::GPIO* getGPIO(void);
} // namespace gpio
} // namespace gpio
} // namespace esp32
} // namespace platforms
} // namespace hal
} // namespace m5
} // namespace esp32
} // namespace platforms
} // namespace hal
} // namespace m5
#endif
@@ -2,7 +2,7 @@
#define M5_HAL_PLATFORMS_ESPRESSIF_ESP32C6_HEADER_HPP
#include "../../../interface/gpio.hpp"
//#include "../../../interface/bus.hpp"
// #include "../../../interface/bus.hpp"
namespace m5 {
namespace hal {
@@ -10,17 +10,16 @@ namespace platforms {
namespace esp32 {
namespace gpio {
interface::gpio::GPIO* getGPIO(void);
} // namespace gpio
} // namespace gpio
namespace bus {
namespace i2c {
namespace i2c {
} // namespace i2c
} // namespace bus
} // namespace esp32
} // namespace platforms
} // namespace hal
} // namespace m5
} // namespace i2c
} // namespace bus
} // namespace esp32
} // namespace platforms
} // namespace hal
} // namespace m5
#endif
@@ -10,17 +10,16 @@ namespace platforms {
namespace esp32 {
namespace gpio {
interface::gpio::GPIO* getGPIO(void);
} // namespace gpio
} // namespace gpio
namespace bus {
namespace i2c {
namespace i2c {
} // namespace i2c
} // namespace bus
} // namespace esp32
} // namespace platforms
} // namespace hal
} // namespace m5
} // namespace i2c
} // namespace bus
} // namespace esp32
} // namespace platforms
} // namespace hal
} // namespace m5
#endif
+15 -16
View File
@@ -38,29 +38,28 @@ gpio_number_t の下位 5bit がピン番号、上位 10bit がポート番号
*/
enum class GpioMode : uint8_t {
Input = 0,
Output,
Output_OpenDrain,
Input = 0,
Output,
Output_OpenDrain,
};
using gpio_mode_t = GpioMode;
enum class BusType : uint8_t {
UNKNOWN = 0,
I2C,
SPI,
I2S,
UART,
UNKNOWN = 0,
I2C,
SPI,
I2S,
UART,
PWM,
GPIO,
ADC,
DAC,
PWM,
GPIO,
ADC,
DAC,
};
using bus_type_t = BusType;
} // namespace types
} // namespace hal
} // namespace m5
} // namespace types
} // namespace hal
} // namespace m5
#endif