diff --git a/README.md b/README.md index f549319882..bdae9839ad 100644 --- a/README.md +++ b/README.md @@ -721,100 +721,101 @@ your specific needs. ADS816x AMS5915 APA102 +AS5047 AT24MAC402 -SPI Flash +SPI Flash BME280 BMI088 BMP085 BNO055 CAT24AA -CYCLE-COUNTER +CYCLE-COUNTER DRV832X DS1302 DS1631 DS18B20 EA-DOG -Encoder Input +Encoder Input Encoder Input BitBang Encoder Output BitBang FT245 FT6x06 Gpio Sampler -HCLAx +HCLAx HD44780 HMC58x HMC6343 HX711 I2C-EEPROM -ILI9341 +ILI9341 IS31FL3733 ITG3200 IXM42XXX L3GD20 LAN8720A -LAWICEL +LAWICEL LIS302DL LIS3DSH LIS3MDL LM75 LP503x -LSM303A +LSM303A LSM6DS33 LSM6DSO LTC2984 MAX31855 MAX31865 -MAX6966 +MAX6966 MAX7219 MCP23x17 MCP2515 MCP3008 MCP7941x -MCP990X +MCP990X MMC5603 MS5611 MS5837 NOKIA5110 NRF24 -TFT-DISPLAY +TFT-DISPLAY PAT9125EL PCA8574 PCA9535 PCA9548A PCA9685 -QMC5883L +QMC5883L SH1106 SIEMENS-S65 SIEMENS-S75 SK6812 SK9822 -SSD1306 +SSD1306 ST7586S ST7789 STTS22H STUSB4500 SX1276 -SX128X +SX128X TCS3414 TCS3472 TLC594x TMP102 TMP12x -TMP175 +TMP175 TOUCH2046 VL53L0 VL6180 diff --git a/examples/nucleo_g474re/as5047/main.cpp b/examples/nucleo_g474re/as5047/main.cpp new file mode 100644 index 0000000000..d7feb52b31 --- /dev/null +++ b/examples/nucleo_g474re/as5047/main.cpp @@ -0,0 +1,79 @@ +// coding: utf-8 +/* + * Copyright (c) 2024, Henrik Hose + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +using SpiMaster = SpiMaster1; + +using Cs = modm::platform::GpioB10; +using Mosi = modm::platform::GpioB5; +using Miso = modm::platform::GpioB4; +using Sck = modm::platform::GpioB3; + +using namespace Board; +using namespace modm::literals; + +class EncoderThread : public modm::pt::Protothread +{ +public: + EncoderThread() : encoder(data) {} + + bool + run() + { + PT_BEGIN(); + + while (true) + { + PT_CALL(encoder.readout()); + + MODM_LOG_INFO << "\nNew readout:" << modm::endl; + MODM_LOG_INFO << " angle degree: " << data.getAngleDeg() << " degrees" << modm::endl; + MODM_LOG_INFO << " angle rad: " << data.getAngleRad() << " radians" << modm::endl; + MODM_LOG_INFO << " angle raw: " << data.getAngleRaw() << modm::endl; + + timeout.restart(std::chrono::milliseconds(500)); + PT_WAIT_UNTIL(timeout.isExpired()); + } + + PT_END(); + } + +private: + modm::as5047::Data data; + modm::As5047 encoder; + + modm::ShortTimeout timeout; +} encoderThread; + +int +main() +{ + Board::initialize(); + + Cs::setOutput(modm::Gpio::High); + + SpiMaster::connect(); + SpiMaster::initialize(); + + MODM_LOG_INFO << "==========AS5047 Test==========" << modm::endl; + MODM_LOG_DEBUG << "Debug logging here" << modm::endl; + MODM_LOG_INFO << "Info logging here" << modm::endl; + MODM_LOG_WARNING << "Warning logging here" << modm::endl; + MODM_LOG_ERROR << "Error logging here" << modm::endl; + MODM_LOG_INFO << "===============================" << modm::endl; + + while (true) { encoderThread.run(); } + + return 0; +} \ No newline at end of file diff --git a/examples/nucleo_g474re/as5047/project.xml b/examples/nucleo_g474re/as5047/project.xml new file mode 100644 index 0000000000..4b86fa2b25 --- /dev/null +++ b/examples/nucleo_g474re/as5047/project.xml @@ -0,0 +1,14 @@ + + modm:nucleo-g474re + + + + + modm:driver:as5047 + modm:platform:gpio + modm:platform:spi:1 + modm:processing:protothread + modm:processing:timer + modm:build:scons + + \ No newline at end of file diff --git a/src/modm/driver/encoder/as5047.hpp b/src/modm/driver/encoder/as5047.hpp new file mode 100644 index 0000000000..0f597a0f01 --- /dev/null +++ b/src/modm/driver/encoder/as5047.hpp @@ -0,0 +1,157 @@ +// coding: utf-8 +// ---------------------------------------------------------------------------- +/* + * Copyright (c) 2024, Henrik Hose + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#ifndef MODM_AS5047_HPP +#define MODM_AS5047_HPP + +#include +#include +#include +#include +#include +#include + +namespace modm +{ + +/// @cond +namespace detail +{ +constexpr uint16_t +as5047_setMsbToEvenParity(const uint16_t num) +{ + uint16_t par = 0x7fff & num; + par ^= par >> 8; + par ^= par >> 4; + par ^= par >> 2; + par ^= par >> 1; + return ((par & 1) << 15) | (0x7fff & num); +} +} // namespace detail +/// @endcond + +/// @ingroup modm_driver_as5047 +struct as5047 +{ + enum class Errorfl : uint16_t + { + Parerr = Bit2, + Invcomm = Bit1, + Frerr = Bit0, + }; + MODM_FLAGS16(Errorfl) + + enum class Prog : uint16_t + { + Progver = Bit6, + Progotp = Bit3, + Otpref = Bit2, + Progen = Bit0, + }; + MODM_FLAGS16(Prog) + + enum class Diaagc : uint16_t + { + Magl = Bit11, + Magh = Bit10, + Cof = Bit9, + Lf = Bit8, + }; + MODM_FLAGS16(Diaagc) + + enum class Register : uint16_t + { + ReadNop = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x0000)), + ReadErrfl = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x0001)), + ReadProg = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x0003)), + ReadDiaagc = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x3FFC)), + ReadMag = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x3FFD)), + ReadAngleunc = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x3FFE)), + ReadAnglecom = detail::as5047_setMsbToEvenParity(((1 << 14) | 0x3FFF)), + + }; + + struct modm_packed Data + { + /// @return + constexpr float + getAngleRad() const + { + const uint16_t angle = data & 0x3fff; + return static_cast(angle) / 16383.f * 2.f * std::numbers::pi_v; + } + + /// @return + constexpr float + getAngleDeg() const + { + const uint16_t angle = data & 0x3fff; + return static_cast(angle) / 16383.f * 360.f; + } + + /// @return + constexpr uint16_t + getAngleRaw() const + { + const uint16_t angle = data & 0x3fff; + return angle; + } + + uint16_t data; + }; +}; // struct as5047 + +/** + * @tparam SpiMaster + * @tparam Cs + * + * @author Henrik Hose + * @ingroup modm_driver_as5047 + */ +template +class As5047 : public as5047, public modm::SpiDevice, protected modm::NestedResumable<5> +{ +public: + using Data = as5047::Data; + + /** + * @param data pointer to buffer of the internal data of type Data + */ + As5047(Data &data); + + /// Call this function once before using the device + modm::ResumableResult + initialize(); + + /// Read the raw data from the sensor + modm::ResumableResult + readout(); + + /// Get the data object for this sensor + inline Data & + getData() + { + return data; + } + +private: + Data &data; + uint8_t inBuffer[2]; + uint8_t outBuffer[2]; +}; + +} // namespace modm + +#include "as5047_impl.hpp" + +#endif // MODM_AS5047_HPP \ No newline at end of file diff --git a/src/modm/driver/encoder/as5047.lb b/src/modm/driver/encoder/as5047.lb new file mode 100644 index 0000000000..a556ebdb74 --- /dev/null +++ b/src/modm/driver/encoder/as5047.lb @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2024, Henrik Hose +# +# This file is part of the modm project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# ----------------------------------------------------------------------------- + +def init(module): + module.name = ":driver:as5047" + module.description = """\ +# AS5047 14 bit Absolute Encoder SPI Driver + +[Datasheet](https://ams.com/documents/20143/36005/AS5047D_DS000394_2-00.pdf) +""" + +def prepare(module, options): + module.depends( + ":architecture:gpio", + ":architecture:spi.device", + ":processing:resumable" + ) + return True + +def build(env): + env.outbasepath = "modm/src/modm/driver/encoder" + env.copy("as5047.hpp") + env.copy("as5047_impl.hpp") diff --git a/src/modm/driver/encoder/as5047_impl.hpp b/src/modm/driver/encoder/as5047_impl.hpp new file mode 100644 index 0000000000..df23d7187e --- /dev/null +++ b/src/modm/driver/encoder/as5047_impl.hpp @@ -0,0 +1,54 @@ +// coding: utf-8 +// ---------------------------------------------------------------------------- +/* + * Copyright (c) 2024, Henrik Hose + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#ifndef MODM_AS5047_HPP +#error "Don't include this file directly, use 'as5047.hpp' instead!" +#endif + +namespace modm +{ + +template +As5047::As5047(Data &data) : data(data) +{ + this->attachConfigurationHandler([]() { SpiMaster::setDataMode(SpiMaster::DataMode::Mode1); }); + Cs::setOutput(modm::Gpio::High); +} + +template +modm::ResumableResult +As5047::readout() +{ + RF_BEGIN(); + + RF_WAIT_UNTIL(this->acquireMaster()); + + Cs::reset(); + outBuffer[1] = static_cast(Register::ReadAngleunc); + outBuffer[0] = static_cast(static_cast(Register::ReadAngleunc) >> 8); + RF_CALL(SpiMaster::transfer(outBuffer, inBuffer, 2)); + Cs::set(); + + modm::delay_us(1); + + Cs::reset(); + outBuffer[1] = 0; + outBuffer[0] = 0; + RF_CALL(SpiMaster::transfer(outBuffer, inBuffer, 2)); + data.data = static_cast(inBuffer[1]) | (static_cast(inBuffer[0]) << 8); + + if (this->releaseMaster()) { Cs::set(); } + RF_END(); +} + +} // namespace modm \ No newline at end of file