diff --git a/.github/workflows/Continuous-integration.yml b/.github/workflows/Continuous-integration.yml index 7d9340a..20d3a6e 100644 --- a/.github/workflows/Continuous-integration.yml +++ b/.github/workflows/Continuous-integration.yml @@ -59,8 +59,10 @@ jobs: id: compile uses: stm32duino/actions/compile-examples@main with: - board-pattern: "NUCLEO_L476RG" - + custom-config: "./extras/build_config.json" + board-pattern: "NUCLEO_L476RG|NUCLEO_H503RB" + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} # Use the output from the `Compilation` step - name: Compilation Errors if: failure() diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..942a9fa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +# v3.21 implemented semantic changes regarding $ +# See https://cmake.org/cmake/help/v3.21/command/target_link_libraries.html#linking-object-libraries-via-target-objects +cmake_minimum_required(VERSION 3.21) + +add_library(LPS22DF INTERFACE) +add_library(LPS22DF_usage INTERFACE) + +target_include_directories(LPS22DF_usage INTERFACE + src +) + + +target_link_libraries(LPS22DF_usage INTERFACE + base_config +) + +target_link_libraries(LPS22DF INTERFACE LPS22DF_usage) + + + +add_library(LPS22DF_bin OBJECT EXCLUDE_FROM_ALL + src/lps22df_reg.c + src/LPS22DFSensor.cpp +) +target_link_libraries(LPS22DF_bin PUBLIC LPS22DF_usage) + +target_link_libraries(LPS22DF INTERFACE + LPS22DF_bin + $ +) + diff --git a/examples/LPS22DF_I3C_Basic/LPS22DF_I3C_Basic.ino b/examples/LPS22DF_I3C_Basic/LPS22DF_I3C_Basic.ino new file mode 100644 index 0000000..628c670 --- /dev/null +++ b/examples/LPS22DF_I3C_Basic/LPS22DF_I3C_Basic.ino @@ -0,0 +1,53 @@ +#include "I3C.h" +#include "LPS22DFSensor.h" + +static const uint8_t LPS22DF_DYN_ADDR = 0x30; + +LPS22DFSensor sensor(&I3C, LPS22DF_I3C_ADD_H, LPS22DF_DYN_ADDR); + +void setup() { + Serial.begin(115200); + while (!Serial) {} + delay(1000); + + Serial.println("=== LPS22DF SETDASA ==="); + + if (!I3C.begin(I3C_SDA, I3C_SCL, 1000000U)) { + Serial.println("begin() failed"); + while (1) {} + } + + if (!I3C.resetDynamicAddresses()) { + Serial.println("resetDynamicAddresses() failed"); + while (1) {} + } + + if (sensor.begin() != LPS22DF_OK) { + Serial.println("sensor.begin() failed"); + while (1) {} + } + + if (sensor.Enable() != LPS22DF_OK) { + Serial.println("sensor.Enable() failed"); + while (1) {} + } + + Serial.println("LPS22DF ready"); +} + +void loop() { + float p = 0.0f; + float t = 0.0f; + + if (sensor.GetPressure(&p) == LPS22DF_OK && sensor.GetTemperature(&t) == LPS22DF_OK) { + Serial.print("P = "); + Serial.print(p, 2); + Serial.print(" hPa T = "); + Serial.print(t, 1); + Serial.println(" C"); + } else { + Serial.println("Read failed"); + } + + delay(500); +} diff --git a/examples/LPS22DF_I3C_DynAddrAssign/LPS22DF_I3C_DynAddrAssign.ino b/examples/LPS22DF_I3C_DynAddrAssign/LPS22DF_I3C_DynAddrAssign.ino new file mode 100644 index 0000000..b707966 --- /dev/null +++ b/examples/LPS22DF_I3C_DynAddrAssign/LPS22DF_I3C_DynAddrAssign.ino @@ -0,0 +1,71 @@ +#include "I3C.h" +#include "LPS22DFSensor.h" + +LPS22DFSensor sensor(&I3C, 0x00); + +void setup() { + Serial.begin(115200); + while (!Serial) {} + delay(1000); + + Serial.println("=== LPS22DF DAA ==="); + + if (!I3C.begin(I3C_SDA, I3C_SCL, 1000000U)) { + Serial.println("begin() failed"); + while (1) {} + } + + I3CDiscoveredDevice devices[8]{}; + size_t found = 0; + + if (I3C.discover(devices, 8, &found)) { + Serial.println("discover() failed"); + while (1) {} + } + + uint8_t lpsDynAddr = 0U; + + for (size_t i = 0; i < found; ++i) { + Serial.println(devices[i].pid,HEX); + if (devices[i].pid == LPS22DF_I3C_PID_H) { + lpsDynAddr = devices[i].dynAddr; + break; + } + } + + sensor.set_address(lpsDynAddr); + + if (lpsDynAddr == 0U) { + Serial.println("Sensor not found failed"); + while (1) {} + } + + if (sensor.begin() != LPS22DF_OK) { + Serial.println("sensor.begin() failed"); + while (1) {} + } + + if (sensor.Enable() != LPS22DF_OK) { + Serial.println("sensor.Enable() failed"); + while (1) {} + } + + Serial.println("LPS22DF ready"); +} + +void loop() { + float p = 0.0f; + float t = 0.0f; + + if (sensor.GetPressure(&p) == LPS22DF_OK && sensor.GetTemperature(&t) == LPS22DF_OK) { + Serial.print("P = "); + Serial.print(p, 2); + Serial.print(" hPa T = "); + Serial.print(t, 1); + Serial.println(" C"); + } else { + Serial.println("Read failed"); + } + + delay(500); +} diff --git a/examples/LPS22DF_I3C_IBI/LPS22DF_I3C_IBI.ino b/examples/LPS22DF_I3C_IBI/LPS22DF_I3C_IBI.ino new file mode 100644 index 0000000..6003483 --- /dev/null +++ b/examples/LPS22DF_I3C_IBI/LPS22DF_I3C_IBI.ino @@ -0,0 +1,46 @@ +#include "I3C.h" +#include "LPS22DFSensor.h" + +LPS22DFSensor sensor(&I3C, LPS22DF_I3C_ADD_H, 0x30); +static volatile bool ibiPending = false; + +void setup() { + Serial.begin(115200); + while (!Serial) {} + + I3C.begin(I3C_SDA, I3C_SCL, 1000000U); + I3C.onIbi([](const I3CControllerIbiInfo&, void*) { + ibiPending = true; + }, + nullptr); + + sensor.begin(); + sensor.SetOutputDataRate(10.0f); + sensor.ConfigureDataReadyOnI3cIbi(); + sensor.EnableIbiOnBus(); + sensor.Enable(); + + Serial.println("Waiting for IBI ..."); +} + +void loop() { + if (!ibiPending && !I3C.hasIbi()) { + return; + } + + ibiPending = false; + + I3CControllerIbiInfo ibi{}; + if (!I3C.readIbi(ibi)) { + return; + } + + float p, t; + if (sensor.GetPressure(&p) == LPS22DF_OK && sensor.GetTemperature(&t) == LPS22DF_OK) { + Serial.print(" P = "); + Serial.print(p, 2); + Serial.print(" hPa, T = "); + Serial.print(t, 1); + Serial.println(" C"); + } +} diff --git a/extras/build_config.json b/extras/build_config.json new file mode 100644 index 0000000..9253f07 --- /dev/null +++ b/extras/build_config.json @@ -0,0 +1,25 @@ +{ + "cores": [ + { + "maintainer": "STMicroelectronics", + "architecture": "stm32", + "boards": [ + ], + "sketches": [ + { + "pattern": "[^I][^3][^C]", + "applicable": true, + "boards": [ + "NUCLEO_L476RG", + "NUCLEO_H503RB" + ] + }, + { + "pattern": "I3C", + "applicable": true, + "boards": [ "NUCLEO_H503RB"] + } + ] + } + ] +} diff --git a/extras/codespell-ignore-words-list.txt b/extras/codespell-ignore-words-list.txt index 6f65d22..8df130b 100644 --- a/extras/codespell-ignore-words-list.txt +++ b/extras/codespell-ignore-words-list.txt @@ -1 +1,2 @@ +daa ths \ No newline at end of file diff --git a/src/LPS22DFSensor.cpp b/src/LPS22DFSensor.cpp index 70d11ee..d2ff1e7 100644 --- a/src/LPS22DFSensor.cpp +++ b/src/LPS22DFSensor.cpp @@ -71,6 +71,33 @@ LPS22DFSensor::LPS22DFSensor(SPIClass *spi, int cs_pin, uint32_t spi_speed) : de enabled = 0L; } +#if defined(I3C_SUPPORTED) +LPS22DFSensor::LPS22DFSensor(I3CBus *i3c, uint8_t staticAddr7, uint8_t dynAddr7) +{ + reg_ctx.write_reg = LPS22DF_io_write; + reg_ctx.read_reg = LPS22DF_io_read; + reg_ctx.handle = (void *)this; + + dev_i2c = NULL; + dev_spi = NULL; + dev_i3c = i3c; + + address = (dynAddr7 != 0) ? dynAddr7 : staticAddr7; + i3c_static7 = staticAddr7; + i3c_dyn7 = dynAddr7; + + enabled = 0U; + initialized = 0U; + + bus_type = LPS22DF_I3C_BUS; +} + +void LPS22DFSensor::set_address(uint8_t dynAddr7) +{ + address = dynAddr7; +} +#endif + /** * @brief Configure the sensor in order to be used * @retval 0 in case of success, an error code otherwise @@ -86,21 +113,70 @@ LPS22DFStatusTypeDef LPS22DFSensor::begin() digitalWrite(cs_pin, HIGH); } +#if defined(I3C_SUPPORTED) + if (dev_i3c != nullptr) { + Serial.println("I3C"); + + bool doAutoSetdasa = (i3c_static7 != 0) && (i3c_dyn7 != 0); + + if (doAutoSetdasa) { + dev_i3c->setClock(1000000); // 1 MHz mixte I3C+I2C + + if (!dev_i3c->assignDynamicAddress(i3c_static7, i3c_dyn7)) { + Serial.println("I3C: SETDASA failed"); + return LPS22DF_ERROR; + } + + address = i3c_dyn7; + + uint8_t id = 0; + if (ReadID(&id) != LPS22DF_OK || id != LPS22DF_ID) { + Serial.print("I3C: probe failed after SETDASA, id=0x"); + Serial.println(id, HEX); + return LPS22DF_ERROR; + } + + Serial.println("I3C: dynamic address and WHO_AM_I OK"); + } else { + + uint8_t id = 0; + if (ReadID(&id) != LPS22DF_OK || id != LPS22DF_ID) { + Serial.print("I3C: manual mode: WHO_AM_I failed, id=0x"); + Serial.println(id, HEX); + return LPS22DF_ERROR; + } + Serial.println("I3C: manual mode, WHO_AM_I OK at address 0x"); + Serial.println(address, HEX); + } + dev_i3c->setClock(12500000); + } +#endif + /* Set bdu and if_inc recommended for driver usage */ if (lps22df_init_set(®_ctx, LPS22DF_DRV_RDY) != LPS22DF_OK) { return LPS22DF_ERROR; } /* Select bus interface */ - if (bus_type == LPS22DF_SPI_3WIRES_BUS) { /* SPI 3-Wires */ + if (bus_type == LPS22DF_SPI_3WIRES_BUS) { bus_mode.interface = lps22df_bus_mode_t::LPS22DF_SPI_3W; - } else if (bus_type == LPS22DF_SPI_4WIRES_BUS) { /* SPI 3-Wires */ + } else if (bus_type == LPS22DF_SPI_4WIRES_BUS) { bus_mode.interface = lps22df_bus_mode_t::LPS22DF_SPI_4W; - } else { + } +#if defined(I3C_SUPPORTED) + else if (bus_type == LPS22DF_I3C_BUS) { + bus_mode.interface = lps22df_bus_mode_t::LPS22DF_INT_PIN_ON_I3C; + } +#endif + else { bus_mode.interface = lps22df_bus_mode_t::LPS22DF_SEL_BY_HW; } bus_mode.filter = lps22df_bus_mode_t::LPS22DF_AUTO; +#if defined(I3C_SUPPORTED) + bus_mode.i3c_ibi_time = lps22df_bus_mode_t::LPS22DF_IBI_1ms; +#endif + if (lps22df_bus_mode_set(®_ctx, &bus_mode) != LPS22DF_OK) { return LPS22DF_ERROR; } @@ -501,3 +577,41 @@ int32_t LPS22DF_io_read(void *handle, uint8_t ReadAddr, uint8_t *pBuffer, uint16 { return ((LPS22DFSensor *)handle)->IO_Read(pBuffer, ReadAddr, nBytesToRead); } + +#if defined(I3C_SUPPORTED) +LPS22DFStatusTypeDef LPS22DFSensor::ConfigureDataReadyOnI3cIbi() +{ + if (dev_i3c == nullptr) { + return LPS22DF_ERROR; + } + + if (Write_Reg(LPS22DF_IF_CTRL, 0x80) != LPS22DF_OK) { + return LPS22DF_ERROR; + } + + if (Write_Reg(LPS22DF_CTRL_REG4, 0x30) != LPS22DF_OK) { + return LPS22DF_ERROR; + } + + return LPS22DF_OK; +} + +LPS22DFStatusTypeDef LPS22DFSensor::EnableIbiOnBus(uint8_t targetIndex, + uint32_t timeoutMs, + bool withPayload) +{ + if (dev_i3c == nullptr) { + return LPS22DF_ERROR; + } + + if (dev_i3c->enableIbi(targetIndex, address, withPayload, false, timeoutMs) != 0) { + return LPS22DF_ERROR; + } + + if (dev_i3c->enableControllerEvents() != 0) { + return LPS22DF_ERROR; + } + + return LPS22DF_OK; +} +#endif \ No newline at end of file diff --git a/src/LPS22DFSensor.h b/src/LPS22DFSensor.h index 42cd083..f4a650d 100644 --- a/src/LPS22DFSensor.h +++ b/src/LPS22DFSensor.h @@ -41,6 +41,10 @@ #ifndef __LPS22DFSensor_H__ #define __LPS22DFSensor_H__ +/* Core compatibility --------------------------------------------------------*/ +#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION <= 0x020C0000) + #error "This library is not compatible with core version used. Please update the core." +#endif /* Includes ------------------------------------------------------------------*/ /* For compatibility with ESP32 platforms */ @@ -54,13 +58,27 @@ #include "SPI.h" #include "lps22df_reg.h" +#if (defined(I3C1_BASE) || defined(I3C2_BASE)) && !defined(I3C_SUPPORTED) + #define I3C_SUPPORTED + #include "I3C.h" +#endif /* Defines -------------------------------------------------------------------*/ #define LPS22DF_I2C_BUS 0U #define LPS22DF_SPI_4WIRES_BUS 1U #define LPS22DF_SPI_3WIRES_BUS 2U +#if defined(I3C_SUPPORTED) + #define LPS22DF_I3C_BUS 3U + /** I3C/I2C Device Static Address 7 bit format if SA0=0 -> 0x5C if SA0=1 -> 0x5D **/ + #define LPS22DF_I3C_ADD_L 0x5CU + #define LPS22DF_I3C_ADD_H 0x5DU + + /** I3C/I2C Device PID**/ + static const uint64_t LPS22DF_I3C_PID_L = 0x020800B4100BULL; + static const uint64_t LPS22DF_I3C_PID_H = 0x020800B4900BULL; +#endif /* Typedefs ------------------------------------------------------------------*/ @@ -79,6 +97,9 @@ class LPS22DFSensor { public: LPS22DFSensor(TwoWire *i2c, uint8_t address = LPS22DF_I2C_ADD_H); LPS22DFSensor(SPIClass *spi, int cs_pin, uint32_t spi_speed = 2000000); +#if defined(I3C_SUPPORTED) + LPS22DFSensor(I3CBus *i3c, uint8_t staticAddr7 = 0, uint8_t dynAddr7 = 0); +#endif LPS22DFStatusTypeDef begin(); LPS22DFStatusTypeDef end(); @@ -100,6 +121,13 @@ class LPS22DFSensor { LPS22DFStatusTypeDef Set_One_Shot(); LPS22DFStatusTypeDef Get_One_Shot_Status(uint8_t *Status); + LPS22DFStatusTypeDef ConfigureDataReadyOnI3cIbi(); + LPS22DFStatusTypeDef EnableIbiOnBus(uint8_t targetIndex = 1, + uint32_t timeoutMs = 1000, + bool withPayload = true); + + void set_address(uint8_t dynAddr7); + /** * @brief Utility function to read data. * @param pBuffer: pointer to data to be read. @@ -144,6 +172,14 @@ class LPS22DFSensor { return 0; } +#if defined(I3C_SUPPORTED) + if (dev_i3c) { + if (dev_i3c->readRegBuffer(address, RegisterAddr, pBuffer, NumByteToRead) == 0) { + return 0; + } + } +#endif + return 1; } @@ -188,6 +224,15 @@ class LPS22DFSensor { return 0; } +#if defined(I3C_SUPPORTED) + if (dev_i3c) { + if (dev_i3c->writeRegBuffer(address, RegisterAddr, pBuffer, NumByteToWrite) == 0) { + return 0; + } + return 1; + } +#endif + return 1; } @@ -198,6 +243,9 @@ class LPS22DFSensor { /* Helper classes. */ TwoWire *dev_i2c; SPIClass *dev_spi; +#if defined(I3C_SUPPORTED) + I3CBus *dev_i3c; +#endif uint32_t bus_type; /*0 means I2C, 1 means SPI 4-Wires, 2 means SPI-3-Wires */ uint8_t initialized; @@ -209,6 +257,11 @@ class LPS22DFSensor { int cs_pin; uint32_t spi_speed; +#if defined(I3C_SUPPORTED) + uint8_t i3c_static7; + uint8_t i3c_dyn7; +#endif + lps22df_ctx_t reg_ctx; };