first commit
This commit is contained in:
commit
5893b00dd2
1669 changed files with 1982740 additions and 0 deletions
21
libraries/M5HAL/LICENSE
Normal file
21
libraries/M5HAL/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 M5Stack Technology CO LTD
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
21
libraries/M5HAL/README.md
Normal file
21
libraries/M5HAL/README.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# M5HAL
|
||||
|
||||
## Overview
|
||||
HAL(Hardware Abstraction Layer) for M5 Products.
|
||||
|
||||
**UNDER DEVELOPMENT**
|
||||
|
||||
Currently, we are in a state of minimal cooperation with M5UnitUnified.
|
||||
Please wait a little while as it will be modified in the future.
|
||||
|
||||
---
|
||||
## 概要
|
||||
M5 製品向けの HAL (ハードウェア抽象化レイヤ)です。
|
||||
|
||||
**開発中**
|
||||
現在、M5UnitUnifiedとの連携は最小限の状態です。
|
||||
今後改修されますので、今しばらくお待ちください。
|
||||
|
||||
|
||||
|
||||
|
||||
25
libraries/M5HAL/library.json
Normal file
25
libraries/M5HAL/library.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "M5HAL",
|
||||
"description": "Hardware Abstraction Layer(HAL) for M5 Products",
|
||||
"keywords": "M5HAL",
|
||||
"authors": {
|
||||
"name": "M5Stack",
|
||||
"url": "http://www.m5stack.com"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/m5stack/M5HAL.git"
|
||||
},
|
||||
"dependencies": [],
|
||||
"version": "0.0.2",
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf",
|
||||
"*"
|
||||
],
|
||||
"platforms": [
|
||||
"espressif32"
|
||||
],
|
||||
"headers": "M5HAL.hpp",
|
||||
"license": "MIT"
|
||||
}
|
||||
11
libraries/M5HAL/library.properties
Normal file
11
libraries/M5HAL/library.properties
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
name=M5HAL
|
||||
version=0.0.2
|
||||
author=M5Stack
|
||||
maintainer=M5Stack
|
||||
sentence=Hardware Abstraction Layer(HAL) for M5 Products
|
||||
paragraph=M5Stack, M5Stack Core2, M5Stack CoreInk, M5StickC, M5StickC-Plus, M5Paper, M5Tough, M5ATOM, M5STAMP, M5Station, See more on http://M5Stack.com
|
||||
category=Other
|
||||
url=https://github.com/m5stack/M5HAL.git
|
||||
architectures=esp32
|
||||
includes=M5HAL.hpp
|
||||
depends=
|
||||
16
libraries/M5HAL/src/M5HAL.cpp
Normal file
16
libraries/M5HAL/src/M5HAL.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#include "M5HAL.hpp"
|
||||
#include "m5_hal/bus/bus.inl"
|
||||
#include "m5_hal/bus/i2c.inl"
|
||||
#include "m5_hal/bus/spi.inl"
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
// Arduino環境の場合のみ、Arduino用の実装を用意
|
||||
#if M5HAL_FRAMEWORK_HAS_ARDUINO
|
||||
#include "./m5_hal/frameworks/arduino/impl.inl"
|
||||
#endif
|
||||
44
libraries/M5HAL/src/M5HAL.hpp
Normal file
44
libraries/M5HAL/src/M5HAL.hpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef M5_HAL_HPP
|
||||
#define M5_HAL_HPP
|
||||
|
||||
#include <M5Utility.hpp>
|
||||
|
||||
#include "./m5_hal/platform_checker.hpp"
|
||||
#include "./m5_hal/framework_checker.hpp"
|
||||
#include "./m5_hal/bus/i2c.hpp"
|
||||
#include "./m5_hal/bus/spi.hpp"
|
||||
|
||||
#include "./m5_hal/bus/bus.hpp"
|
||||
#include "./m5_hal/interface/gpio.hpp"
|
||||
|
||||
#define M5HAL_STATIC_MACRO_STRING(x) #x
|
||||
// clang-format off
|
||||
#define M5HAL_STATIC_MACRO_CONCAT(x, y) M5HAL_STATIC_MACRO_STRING(x/y)
|
||||
// clang-format on
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
#undef M5HAL_STATIC_MACRO_PATH_HEADER
|
||||
|
||||
// Arduinoフレームワークがある場合は準備
|
||||
#if M5HAL_FRAMEWORK_HAS_ARDUINO
|
||||
#include "./m5_hal/frameworks/arduino/header.hpp"
|
||||
|
||||
// 対象プラットフォームが特定されない場合は Arduino経由の実装を利用
|
||||
#if 1 // M5HAL_TARGET_PLATFORM_NUMBER == 0
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
using namespace frameworks::arduino;
|
||||
}
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
200
libraries/M5HAL/src/m5_hal/bus/bus.hpp
Normal file
200
libraries/M5HAL/src/m5_hal/bus/bus.hpp
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
|
||||
#ifndef M5_HAL_BUS_HPP_
|
||||
#define M5_HAL_BUS_HPP_
|
||||
|
||||
#include "../interface/gpio.hpp"
|
||||
#include "../interface/io.hpp"
|
||||
#include "../error.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
/*!
|
||||
@namespace m5
|
||||
@brief Toplevel namespace of M5
|
||||
*/
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
|
||||
namespace bus {
|
||||
|
||||
struct Bus;
|
||||
struct AccessConfig;
|
||||
struct Accessor;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// 通信バスの初期化に必要な条件を記述するため基底インターフェイス
|
||||
struct BusConfig {
|
||||
virtual ~BusConfig() = default;
|
||||
virtual types::bus_type_t getBusType(void) const = 0;
|
||||
types::periph_t periph;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// 実際の通信に必要な条件を記述するための基底インターフェイス
|
||||
struct AccessConfig {
|
||||
virtual ~AccessConfig() = default;
|
||||
virtual types::bus_type_t getBusType(void) const = 0;
|
||||
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;
|
||||
virtual const AccessConfig& getAccessConfig(void) const = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
protected:
|
||||
Bus& _bus;
|
||||
};
|
||||
|
||||
template <typename TBusAccessInterface>
|
||||
struct DefaultBusExtension {
|
||||
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& operator=(const BusAccessor&) = delete;
|
||||
|
||||
BusAccessor(BusAccessor&& other)
|
||||
: _owner(other.owner), _bus(other.bus), _access(other.access), _extension(other.access)
|
||||
{
|
||||
other._owner = false;
|
||||
}
|
||||
void release()
|
||||
{
|
||||
if (this->_owner) {
|
||||
this->_bus.release();
|
||||
}
|
||||
this->_owner = false;
|
||||
}
|
||||
BusAccessor& operator=(BusAccessor&& other)
|
||||
{
|
||||
this->release();
|
||||
this->_owner = other._owner;
|
||||
this->_bus = other._bus;
|
||||
this->_access = other._access;
|
||||
this->_extension = TExtension(this->_access);
|
||||
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;
|
||||
}
|
||||
|
||||
~BusAccessor()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _owner = true;
|
||||
TBus& _bus;
|
||||
TBusAccessInterface& _access;
|
||||
TExtension _extension;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// 通信バスの基底インターフェイス
|
||||
struct Bus {
|
||||
public:
|
||||
virtual ~Bus() = default;
|
||||
virtual types::bus_type_t getBusType(void) const = 0;
|
||||
|
||||
// initとreleaseはユーザーは直接呼ばない。 createBus / releaseBus経由で使用する。
|
||||
|
||||
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 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)
|
||||
{
|
||||
if (Accessor && _Accessor.get() == Accessor) {
|
||||
_Accessor.reset(nullptr);
|
||||
return error::error_t::OK;
|
||||
}
|
||||
return error::error_t::INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// 無条件でバスをロックしたい場合に使用する
|
||||
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; }
|
||||
|
||||
} // namespace bus
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
15
libraries/M5HAL/src/m5_hal/bus/bus.inl
Normal file
15
libraries/M5HAL/src/m5_hal/bus/bus.inl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
#include "bus.hpp"
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace bus {
|
||||
|
||||
const BusConfig& Accessor::getBusConfig(void) const
|
||||
{
|
||||
return _bus.getConfig();
|
||||
}
|
||||
|
||||
} // namespace bus
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
108
libraries/M5HAL/src/m5_hal/bus/i2c.hpp
Normal file
108
libraries/M5HAL/src/m5_hal/bus/i2c.hpp
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#ifndef M5_HAL_BUS_I2C_HPP_
|
||||
#define M5_HAL_BUS_I2C_HPP_
|
||||
|
||||
#include "./bus.hpp"
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace bus {
|
||||
|
||||
struct I2CBusConfig : public BusConfig {
|
||||
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;
|
||||
uint32_t timeout_msec = 1000;
|
||||
uint16_t i2c_addr;
|
||||
bool address_is_10bit = false;
|
||||
};
|
||||
|
||||
namespace i2c {
|
||||
struct I2CMasterAccessor : public Accessor {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
class SoftwareI2CMasterAccessor : public I2CMasterAccessor {
|
||||
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;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
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 {
|
||||
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
|
||||
|
||||
#endif
|
||||
335
libraries/M5HAL/src/m5_hal/bus/i2c.inl
Normal file
335
libraries/M5HAL/src/m5_hal/bus/i2c.inl
Normal file
|
|
@ -0,0 +1,335 @@
|
|||
|
||||
#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{200};
|
||||
|
||||
void delayCycle(uint32_t count)
|
||||
{
|
||||
for (uint32_t i = count; i > 0; --i) {
|
||||
__asm__ __volatile__("nop");
|
||||
}
|
||||
}
|
||||
|
||||
m5::stl::expected<I2CBus*, m5::hal::error::error_t> getBus(const I2CBusConfig& config)
|
||||
{
|
||||
// @TODO ソフトウェアSPIの複数のインスタンスを管理できるようにすること。
|
||||
static SoftwareI2CBus bus;
|
||||
bus.init(config);
|
||||
return &bus;
|
||||
}
|
||||
|
||||
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_LOGV("SoftwareI2C::init: ok %s", __PRETTY_FUNCTION__);
|
||||
|
||||
_config.pin_scl->setMode(m5::hal::types::gpio_mode_t::Output_OpenDrain);
|
||||
_config.pin_scl->writeLow();
|
||||
_config.pin_sda->setMode(m5::hal::types::gpio_mode_t::Output_OpenDrain);
|
||||
_config.pin_sda->writeLow();
|
||||
_config.pin_scl->writeHigh();
|
||||
delayCycle(128);
|
||||
_config.pin_sda->writeHigh();
|
||||
|
||||
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)
|
||||
{
|
||||
/// @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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
auto result = new SoftwareI2CMasterAccessor(*this, (I2CMasterAccessConfig&)access_config);
|
||||
_Accessor.reset(result);
|
||||
M5_LIB_LOGV("SoftwareI2C::beginAccess: ok %s", __PRETTY_FUNCTION__);
|
||||
return result;
|
||||
}
|
||||
|
||||
m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::sendDummyClockWhileSdaLow(size_t count)
|
||||
{
|
||||
auto bc = static_cast<const I2CBusConfig&>(getBusConfig());
|
||||
|
||||
auto sda = bc.pin_sda;
|
||||
auto scl = bc.pin_scl;
|
||||
|
||||
/// SDAがLOWになっている場合は処理
|
||||
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();
|
||||
delayCycle(delay_cycle);
|
||||
}
|
||||
}
|
||||
if (count == 0) {
|
||||
return m5::stl::make_unexpected(error::error_t::I2C_BUS_ERROR);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::sendStartCondition(void)
|
||||
{
|
||||
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;
|
||||
|
||||
// start condition
|
||||
scl->writeHigh();
|
||||
delayCycle(delay_cycle);
|
||||
sda->writeLow();
|
||||
delayCycle(delay_cycle);
|
||||
scl->writeLow();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::sendStopCondition(void)
|
||||
{
|
||||
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;
|
||||
|
||||
auto res = sendDummyClockWhileSdaLow();
|
||||
if (res.has_value()) {
|
||||
// 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 scl = bc.pin_scl;
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
if (result.has_value()) return {};
|
||||
return m5::stl::make_unexpected(result.error());
|
||||
}
|
||||
|
||||
m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::startRead(void)
|
||||
{
|
||||
auto ac = static_cast<const I2CMasterAccessConfig&>(getAccessConfig());
|
||||
sendStartCondition();
|
||||
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());
|
||||
}
|
||||
|
||||
m5::stl::expected<void, m5::hal::error::error_t> I2CMasterAccessor::stop(void)
|
||||
{
|
||||
return sendStopCondition();
|
||||
}
|
||||
|
||||
m5::stl::expected<size_t, m5::hal::error::error_t> SoftwareI2CMasterAccessor::write(const uint8_t* data, size_t len)
|
||||
{
|
||||
auto bc = static_cast<const I2CBusConfig&>(getBusConfig());
|
||||
auto ac = static_cast<const I2CMasterAccessConfig&>(getAccessConfig());
|
||||
|
||||
auto scl = bc.pin_scl;
|
||||
auto sda = bc.pin_sda;
|
||||
|
||||
/// @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++;
|
||||
|
||||
// 最初の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();
|
||||
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)
|
||||
{
|
||||
auto bc = static_cast<const I2CBusConfig&>(getBusConfig());
|
||||
auto ac = static_cast<const I2CMasterAccessConfig&>(getAccessConfig());
|
||||
|
||||
auto scl = bc.pin_scl;
|
||||
auto sda = bc.pin_sda;
|
||||
|
||||
/// @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();
|
||||
|
||||
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;
|
||||
}
|
||||
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; }
|
||||
|
||||
} // namespace i2c
|
||||
} // namespace bus
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
137
libraries/M5HAL/src/m5_hal/bus/spi.hpp
Normal file
137
libraries/M5HAL/src/m5_hal/bus/spi.hpp
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
#ifndef M5_HAL_BUS_SPI_HPP_
|
||||
#define M5_HAL_BUS_SPI_HPP_
|
||||
|
||||
#include "./bus.hpp"
|
||||
|
||||
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;
|
||||
};
|
||||
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
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
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;
|
||||
};
|
||||
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_command_length = 0; // コマンド部のビット長
|
||||
uint8_t spi_address_length = 0; // アドレス部のビット長
|
||||
uint8_t spi_dummy_cycle = 0; // アドレスからデータへ移る際のダミーサイクル数
|
||||
};
|
||||
|
||||
namespace spi {
|
||||
struct SPIMasterAccessor : public Accessor {
|
||||
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 {
|
||||
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 {
|
||||
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;
|
||||
};
|
||||
|
||||
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
|
||||
145
libraries/M5HAL/src/m5_hal/bus/spi.inl
Normal file
145
libraries/M5HAL/src/m5_hal/bus/spi.inl
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
|
||||
#include "spi.hpp"
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace bus {
|
||||
namespace spi {
|
||||
|
||||
m5::stl::expected<SPIBus*, m5::hal::error::error_t> getBus(const SPIBusConfig& config)
|
||||
{
|
||||
// @TODO ソフトウェアSPIの複数のインスタンスを管理できるようにすること。
|
||||
static SoftwareSPIBus spi_bus;
|
||||
spi_bus.init(config);
|
||||
return &spi_bus;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
_config = static_cast<const SPIBusConfig&>(config);
|
||||
M5_LIB_LOGV("SoftwareSPI::init: ok %s", __PRETTY_FUNCTION__);
|
||||
if (_config.pin_clk) {
|
||||
_config.pin_clk->setMode(m5::hal::types::gpio_mode_t::Output);
|
||||
}
|
||||
if (_config.pin_dc) {
|
||||
_config.pin_dc->setMode(m5::hal::types::gpio_mode_t::Output);
|
||||
}
|
||||
if (_config.pin_mosi) {
|
||||
_config.pin_mosi->setMode(m5::hal::types::gpio_mode_t::Output);
|
||||
}
|
||||
if (_config.pin_miso) {
|
||||
_config.pin_miso->setMode(m5::hal::types::gpio_mode_t::Input);
|
||||
}
|
||||
return error::error_t::OK;
|
||||
}
|
||||
|
||||
m5::stl::expected<Accessor*, m5::hal::error::error_t> SoftwareSPIBus::beginAccess(const AccessConfig& access_config)
|
||||
{
|
||||
/// @TODO ここで排他制御&ロック処理を行うこと。
|
||||
if (_Accessor.get() != nullptr) {
|
||||
M5_LIB_LOGE("SoftwareSPI::beginAccess: error %s", __PRETTY_FUNCTION__);
|
||||
return nullptr;
|
||||
}
|
||||
if (access_config.getBusType() != getBusType()) {
|
||||
M5_LIB_LOGE("SoftwareSPI::beginAccess: error %s", __PRETTY_FUNCTION__);
|
||||
return nullptr;
|
||||
}
|
||||
auto result = new SoftwareSPIMasterAccessor(*this, (const SPIMasterAccessConfig&)access_config);
|
||||
_Accessor.reset(result);
|
||||
M5_LIB_LOGV("SoftwareSPI::beginAccess: ok %s", __PRETTY_FUNCTION__);
|
||||
return result;
|
||||
}
|
||||
|
||||
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 cpol = (ac.spi_mode & 2);
|
||||
auto sclk = bc.pin_clk;
|
||||
do {
|
||||
sclk->write(!cpol);
|
||||
sclk->write(cpol);
|
||||
} while (--count);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
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 pin_dc = bc.pin_dc;
|
||||
if (pin_dc) pin_dc->write(false);
|
||||
auto res = write(data, len);
|
||||
if (pin_dc) pin_dc->write(true);
|
||||
return res;
|
||||
}
|
||||
|
||||
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 cmd_len = (ac.spi_command_length >> 3);
|
||||
if (cmd_len) {
|
||||
if (pin_dc) pin_dc->write(false);
|
||||
auto res = write(data, cmd_len);
|
||||
data += cmd_len;
|
||||
auto datalen = len - cmd_len;
|
||||
if (pin_dc) pin_dc->write(true);
|
||||
if (!res || datalen == 0) return res;
|
||||
res = write(data, datalen);
|
||||
if (!res) {
|
||||
return res;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
return write(data, len);
|
||||
}
|
||||
|
||||
m5::stl::expected<void, m5::hal::error::error_t> SPIMasterAccessor::cs_control(bool cs_level)
|
||||
{
|
||||
auto pin_cs = static_cast<const SPIMasterAccessConfig&>(getAccessConfig()).pin_cs;
|
||||
if (pin_cs) pin_cs->write(cs_level);
|
||||
return {};
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
m5::stl::expected<size_t, m5::hal::error::error_t> SoftwareSPIMasterAccessor::write(const uint8_t* data, size_t len)
|
||||
{
|
||||
auto bc = static_cast<const SPIBusConfig&>(getBusConfig());
|
||||
auto ac = static_cast<const SPIMasterAccessConfig&>(getAccessConfig());
|
||||
|
||||
bool cpol = (ac.spi_mode & 2);
|
||||
bool cpha = (ac.spi_mode & 1);
|
||||
bool flip = cpol ^ cpha;
|
||||
auto sclk = bc.pin_clk;
|
||||
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);
|
||||
} while (++result < len);
|
||||
sclk->write(cpol);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace spi
|
||||
} // namespace bus
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
37
libraries/M5HAL/src/m5_hal/error.hpp
Normal file
37
libraries/M5HAL/src/m5_hal/error.hpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
#ifndef M5_HAL_ERROR_HPP
|
||||
#define M5_HAL_ERROR_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace m5 {
|
||||
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 エラーコード細分化する
|
||||
};
|
||||
using error_t = ErrorType;
|
||||
|
||||
constexpr bool isError(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
|
||||
|
||||
#endif
|
||||
22
libraries/M5HAL/src/m5_hal/framework_checker.hpp
Normal file
22
libraries/M5HAL/src/m5_hal/framework_checker.hpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef M5_HAL_FRAMEWORK_CHECKER_HPP
|
||||
#define M5_HAL_FRAMEWORK_CHECKER_HPP
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#define M5HAL_FRAMEWORK_HAS_ARDUINO 1
|
||||
#else
|
||||
#define M5HAL_FRAMEWORK_HAS_ARDUINO 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<FreeRTOS.h>) || __has_include(<freertos/FreeRTOS.h>)
|
||||
#define M5HAL_FRAMEWORK_HAS_FREERTOS 1
|
||||
#else
|
||||
#define M5HAL_FRAMEWORK_HAS_FREERTOS 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<SDL2/SDL.h>) || __has_include(<SDL.h>)
|
||||
#define M5HAL_FRAMEWORK_HAS_SDL 1
|
||||
#else
|
||||
#define M5HAL_FRAMEWORK_HAS_SDL 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
79
libraries/M5HAL/src/m5_hal/frameworks/arduino/header.hpp
Normal file
79
libraries/M5HAL/src/m5_hal/frameworks/arduino/header.hpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#ifndef M5_HAL_FRAMEWORKS_ARDUINO_HEADER_HPP
|
||||
#define M5_HAL_FRAMEWORKS_ARDUINO_HEADER_HPP
|
||||
|
||||
#include "../../interface/gpio.hpp"
|
||||
#include "../../bus/bus.hpp"
|
||||
#if __has_include(<Arduino.h>)
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO)
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
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;
|
||||
|
||||
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を束ねた概念を表すインターフェイス
|
||||
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:
|
||||
};
|
||||
|
||||
// ポートを含めて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:
|
||||
};
|
||||
|
||||
interface::gpio::GPIO* getGPIO(void);
|
||||
interface::gpio::Pin* getPin(types::gpio_number_t pinNumber);
|
||||
|
||||
} // namespace gpio
|
||||
|
||||
namespace bus {
|
||||
namespace i2c {
|
||||
|
||||
// bus::I2CBus* createBus(TwoWire& _wire);
|
||||
|
||||
} // namespace i2c
|
||||
} // namespace bus
|
||||
} // namespace arduino
|
||||
} // namespace frameworks
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
119
libraries/M5HAL/src/m5_hal/frameworks/arduino/impl.inl
Normal file
119
libraries/M5HAL/src/m5_hal/frameworks/arduino/impl.inl
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#ifndef M5_HAL_PLATFORMS_ARDUINO_IMPL_INL
|
||||
#define M5_HAL_PLATFORMS_ARDUINO_IMPL_INL
|
||||
|
||||
#include "../src/m5_hal/bus/bus.hpp"
|
||||
#include <M5Utility.hpp>
|
||||
|
||||
#if __has_include(<Arduino.h>)
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
#if defined(ARDUINO)
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace frameworks {
|
||||
namespace arduino {
|
||||
namespace gpio {
|
||||
|
||||
interface::gpio::GPIO* getGPIO(void)
|
||||
{
|
||||
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);
|
||||
return getGPIO()->getPin(pinNumber);
|
||||
}
|
||||
|
||||
interface::gpio::Port* GPIO::getPort(uint8_t portNumber)
|
||||
{
|
||||
static Port s_port_instance;
|
||||
return &s_port_instance;
|
||||
}
|
||||
|
||||
interface::gpio::Pin* GPIO::getPin(types::gpio_number_t pinNumber)
|
||||
{
|
||||
M5_LIB_LOGV("GPIO::getPin %d", pinNumber);
|
||||
return getPort(0)->getPin(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) {
|
||||
s_pins_pointer.resize(pinNumber + 1);
|
||||
}
|
||||
if (s_pins_pointer[pinNumber] == nullptr) {
|
||||
s_pins_instance.push_back(Pin(pinNumber));
|
||||
s_pins_pointer[pinNumber] = &s_pins_instance.back();
|
||||
}
|
||||
return s_pins_pointer[pinNumber];
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// M5_LIB_LOGV("Pin::setHigh [pin %d]", _gpio_number);
|
||||
digitalWrite(_gpio_number, true);
|
||||
}
|
||||
void Pin::writeLow(void)
|
||||
{
|
||||
// M5_LIB_LOGV("Pin::setLow [pin %d]", _gpio_number);
|
||||
digitalWrite(_gpio_number, false);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gpio
|
||||
|
||||
namespace bus {
|
||||
namespace i2c {
|
||||
// interface::bus::I2C* createBus(TwoWire& _wire)
|
||||
// {
|
||||
// return nullptr;
|
||||
// }
|
||||
} // namespace i2c
|
||||
} // namespace bus
|
||||
|
||||
//
|
||||
|
||||
} // namespace arduino
|
||||
} // namespace frameworks
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
18
libraries/M5HAL/src/m5_hal/gpio/gpio.hpp
Normal file
18
libraries/M5HAL/src/m5_hal/gpio/gpio.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef M5_HAL_GPIO_GPIO_HPP_
|
||||
#define M5_HAL_GPIO_GPIO_HPP_
|
||||
|
||||
#include "../interface/gpio.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace gpio {
|
||||
class GPIO { /* Empty*/
|
||||
};
|
||||
}; // namespace gpio
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
93
libraries/M5HAL/src/m5_hal/interface/gpio.hpp
Normal file
93
libraries/M5HAL/src/m5_hal/interface/gpio.hpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
|
||||
#ifndef M5_HAL_INTERFACE_GPIO_HPP
|
||||
#define M5_HAL_INTERFACE_GPIO_HPP
|
||||
|
||||
#include "../types.hpp"
|
||||
#include <vector>
|
||||
|
||||
/*!
|
||||
@namespace m5
|
||||
@brief Toplevel namespace of M5
|
||||
*/
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace interface {
|
||||
// 抽象化されたGPIOインターフェースを置く。これは LowLayerではなく汎用的なもの。
|
||||
// このGPIOインターフェースを継承してGPIOエキスパンダの実装を作ることもできる。
|
||||
namespace gpio {
|
||||
|
||||
// 単一のデジタルピンを表すインターフェイス
|
||||
struct Pin {
|
||||
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 types::gpio_number_t getGpioNumber(void) const = 0;
|
||||
virtual void setMode(types::gpio_mode_t mode) = 0;
|
||||
};
|
||||
|
||||
// 複数のPinを保持する概念を表すインターフェイス
|
||||
struct Port {
|
||||
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 Pin* getPin(types::gpio_number_t gpioNumber) = 0;
|
||||
virtual void digitalWrite(types::gpio_number_t gpioNumber, bool value)
|
||||
{
|
||||
getPin(gpioNumber)->write(value);
|
||||
}
|
||||
virtual bool digitalRead(types::gpio_number_t gpioNumber)
|
||||
{
|
||||
return getPin(gpioNumber)->read();
|
||||
}
|
||||
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
|
||||
{
|
||||
return _pins.size() > pinNumber ? _pins[pinNumber] : nullptr;
|
||||
}
|
||||
void setPin(uint8_t pinNumber, Pin* pin)
|
||||
{
|
||||
if (_pins.size() > pinNumber) _pins[pinNumber] = pin;
|
||||
}
|
||||
size_t getPinCount(void) const
|
||||
{
|
||||
return _pins.size();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<Pin*> _pins;
|
||||
};
|
||||
|
||||
} // namespace gpio
|
||||
} // namespace interface
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
88
libraries/M5HAL/src/m5_hal/interface/io.hpp
Normal file
88
libraries/M5HAL/src/m5_hal/interface/io.hpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
|
||||
#ifndef M5_HAL_INTERFACE_IO_HPP_
|
||||
#define M5_HAL_INTERFACE_IO_HPP_
|
||||
|
||||
#include "../error.hpp"
|
||||
#include "../types.hpp"
|
||||
|
||||
#include <M5Utility.hpp>
|
||||
|
||||
#include <future>
|
||||
|
||||
/*!
|
||||
@namespace m5
|
||||
@brief Toplevel namespace of M5
|
||||
*/
|
||||
namespace m5 {
|
||||
|
||||
namespace hal {
|
||||
|
||||
namespace interface {
|
||||
|
||||
namespace io {
|
||||
|
||||
// struct AsyncParam {
|
||||
// public:
|
||||
// // タイムアウト時間を設定する変数 (呼び出し側が設定しておく。0なら処理を終えるかエラーになるまで無限待ち)
|
||||
// uint32_t timeout_ms;
|
||||
|
||||
// // read/writeの結果得られた長さを格納する変数
|
||||
// size_t length;
|
||||
|
||||
// // 処理の結果を格納する変数 (ASYNC_RUNNINGの場合はまだ処理中)
|
||||
// error::error_t error;
|
||||
// };
|
||||
|
||||
struct Input {
|
||||
public:
|
||||
virtual ~Input() = default;
|
||||
|
||||
// @param data 読み込んだデータを格納するバッファ
|
||||
// @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 m5::stl::expected<size_t, m5::hal::error::error_t> availableRead(void) const
|
||||
{
|
||||
return m5::stl::make_unexpected(error::error_t::NOT_IMPLEMENTED);
|
||||
};
|
||||
};
|
||||
|
||||
struct Output {
|
||||
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 m5::stl::expected<size_t, m5::hal::error::error_t> availableWrite(void) const
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace interface
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
67
libraries/M5HAL/src/m5_hal/platform_checker.hpp
Normal file
67
libraries/M5HAL/src/m5_hal/platform_checker.hpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#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_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_ESP32_P4 316
|
||||
#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
|
||||
|
||||
#if defined(ESP_PLATFORM)
|
||||
#if __has_include(<sdkconfig.h>)
|
||||
#include <sdkconfig.h>
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
#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
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32P4)
|
||||
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_ESP32_P4
|
||||
#define M5HAL_TARGET_PLATFORM_PATH m5_hal/platforms/espressif/esp32p4
|
||||
#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
|
||||
// clang-format on
|
||||
|
||||
#undef XSTR
|
||||
#undef STR
|
||||
|
||||
#if !defined(M5HAL_TARGET_PLATFORM_NUMBER)
|
||||
#define M5HAL_TARGET_PLATFORM_NUMBER M5HAL_PLATFORM_NUMBER_UNKNOWN
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef M5_HAL_PLATFORMS_ESPRESSIF_ESP32_HEADER_HPP
|
||||
#define M5_HAL_PLATFORMS_ESPRESSIF_ESP32_HEADER_HPP
|
||||
|
||||
#include "../../../interface/gpio.hpp"
|
||||
#include "../../../bus/bus.hpp"
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace platforms {
|
||||
|
||||
// namespace esp32 {}
|
||||
// namespace current_platform {
|
||||
// using namespace esp32;
|
||||
// }
|
||||
|
||||
namespace esp32 {
|
||||
namespace types {
|
||||
|
||||
enum class PeripheralType : uint8_t {
|
||||
none = 0,
|
||||
i2c0,
|
||||
i2c1,
|
||||
spi2,
|
||||
spi3,
|
||||
};
|
||||
using periph_t = PeripheralType;
|
||||
|
||||
} // namespace types
|
||||
|
||||
namespace gpio {
|
||||
interface::gpio::GPIO* getGPIO(void);
|
||||
} // namespace gpio
|
||||
|
||||
} // namespace esp32
|
||||
} // namespace platforms
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef M5_HAL_PLATFORMS_ESPRESSIF_ESP32C6_HEADER_HPP
|
||||
#define M5_HAL_PLATFORMS_ESPRESSIF_ESP32C6_HEADER_HPP
|
||||
|
||||
#include "../../../interface/gpio.hpp"
|
||||
// #include "../../../interface/bus.hpp"
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace platforms {
|
||||
namespace esp32 {
|
||||
namespace gpio {
|
||||
interface::gpio::GPIO* getGPIO(void);
|
||||
} // namespace gpio
|
||||
namespace bus {
|
||||
namespace i2c {
|
||||
} // namespace i2c
|
||||
} // namespace bus
|
||||
} // namespace esp32
|
||||
} // namespace platforms
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef M5_HAL_PLATFORMS_ESPRESSIF_ESP32P4_HEADER_HPP
|
||||
#define M5_HAL_PLATFORMS_ESPRESSIF_ESP32P4_HEADER_HPP
|
||||
|
||||
#include "../../../interface/gpio.hpp"
|
||||
// #include "../../../interface/bus.hpp"
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace platforms {
|
||||
namespace esp32 {
|
||||
namespace gpio {
|
||||
interface::gpio::GPIO* getGPIO(void);
|
||||
} // namespace gpio
|
||||
namespace bus {
|
||||
namespace i2c {
|
||||
} // namespace i2c
|
||||
} // namespace bus
|
||||
} // namespace esp32
|
||||
} // namespace platforms
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef M5_HAL_PLATFORMS_ESPRESSIF_ESP32S3_HEADER_HPP
|
||||
#define M5_HAL_PLATFORMS_ESPRESSIF_ESP32S3_HEADER_HPP
|
||||
|
||||
#include "../../../interface/gpio.hpp"
|
||||
#include "../../../interface/bus.hpp"
|
||||
|
||||
namespace m5 {
|
||||
namespace hal {
|
||||
namespace platforms {
|
||||
namespace esp32 {
|
||||
namespace gpio {
|
||||
interface::gpio::GPIO* getGPIO(void);
|
||||
} // namespace gpio
|
||||
namespace bus {
|
||||
namespace i2c {
|
||||
} // namespace i2c
|
||||
} // namespace bus
|
||||
} // namespace esp32
|
||||
} // namespace platforms
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
65
libraries/M5HAL/src/m5_hal/types.hpp
Normal file
65
libraries/M5HAL/src/m5_hal/types.hpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
#ifndef M5_HAL_TYPES_HPP
|
||||
#define M5_HAL_TYPES_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
// #include <M5Utility.hpp>
|
||||
|
||||
namespace m5 {
|
||||
|
||||
namespace hal {
|
||||
|
||||
namespace types {
|
||||
|
||||
enum class PeripheralType : uint8_t;
|
||||
using periph_t = PeripheralType;
|
||||
|
||||
// GPIOピンの通し番号型
|
||||
typedef int16_t gpio_number_t;
|
||||
// typedef m5::utility::BitSegment<3, int16_t> gpio_number_t;
|
||||
// class gpio_number_t : public m5::utility::BitSegment<3, int16_t> {
|
||||
// public:
|
||||
// inline constexpr gpio_number_t() = default;
|
||||
// inline constexpr gpio_number_t(const base_type v) : BitSegment(v) {
|
||||
// }
|
||||
// inline constexpr int16_t port(void) const { return upper(); }
|
||||
// inline constexpr int16_t pin(void) const { return lower(); }
|
||||
// inline void port(int16_t v) { upper(v); }
|
||||
// inline void pin(int16_t v) { lower(v); }
|
||||
// };
|
||||
/*
|
||||
マイナスの値は未設定や無効値として扱う
|
||||
※ : ポートに所属しているピンの数が3bit (8本) の場合
|
||||
gpio_number_t の下位 3bit がピン番号、上位 12bit がポート番号となる
|
||||
|
||||
※ : ポートに所属しているピンの数が5bit (32本) の場合
|
||||
gpio_number_t の下位 5bit がピン番号、上位 10bit がポート番号となる
|
||||
*/
|
||||
|
||||
enum class GpioMode : uint8_t {
|
||||
Input = 0,
|
||||
Output,
|
||||
Output_OpenDrain,
|
||||
};
|
||||
using gpio_mode_t = GpioMode;
|
||||
|
||||
enum class BusType : uint8_t {
|
||||
UNKNOWN = 0,
|
||||
I2C,
|
||||
SPI,
|
||||
I2S,
|
||||
UART,
|
||||
|
||||
PWM,
|
||||
GPIO,
|
||||
ADC,
|
||||
DAC,
|
||||
};
|
||||
using bus_type_t = BusType;
|
||||
|
||||
} // namespace types
|
||||
} // namespace hal
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue