HF-Core Platform 0.1.0-dev
Hardware-Agnostic Handler Layer & RTOS Utilities for HardFOC
Loading...
Searching...
No Matches
esp32_bus_setup.hpp
Go to the documentation of this file.
1
19#pragma once
20
21#include "esp32_test_config.hpp"
22
23// ESP32 internal interface implementations
24#include "mcu/esp32/EspAdc.h"
25#include "mcu/esp32/EspGpio.h"
26#include "mcu/esp32/EspI2c.h"
27#include "mcu/esp32/EspSpi.h"
28
29#include <memory>
30
31// ESP-IDF headers (C linkage)
32#ifdef __cplusplus
33extern "C" {
34#endif
35#include "esp_log.h"
36#ifdef __cplusplus
37}
38#endif
39
40static const char* BUS_TAG = "BusSetup";
41
42// ═══════════════════════════════════════════════════════════════════════════
43// I2C BUS — Shared by BNO08x, PCA9685, PCAL95555 handlers
44// ═══════════════════════════════════════════════════════════════════════════
45
54inline EspI2cBus* get_shared_i2c_bus() noexcept {
55 static std::unique_ptr<EspI2cBus> bus;
56 if (!bus) {
57 hf_i2c_master_bus_config_t bus_cfg = {};
58 bus_cfg.i2c_port = static_cast<i2c_port_t>(I2C_PORT_NUM);
59 bus_cfg.sda_io_num = static_cast<hf_pin_num_t>(PIN_I2C_SDA);
60 bus_cfg.scl_io_num = static_cast<hf_pin_num_t>(PIN_I2C_SCL);
61 bus_cfg.flags.enable_internal_pullup = true;
62
63 bus = std::make_unique<EspI2cBus>(bus_cfg);
64 if (!bus->Initialize()) {
65 ESP_LOGE(BUS_TAG, "I2C bus initialization failed (SDA=%d, SCL=%d)",
67 bus.reset();
68 return nullptr;
69 }
70 ESP_LOGI(BUS_TAG, "I2C bus initialized (SDA=%d, SCL=%d, %d Hz)",
72 }
73 return bus.get();
74}
75
81inline BaseI2c* get_i2c_device(uint8_t address) noexcept {
82 auto* bus = get_shared_i2c_bus();
83 if (!bus) return nullptr;
84
85 // Create device config and add to bus using CreateDevice/GetDevice pattern
86 hf_i2c_device_config_t dev_cfg = {};
87 dev_cfg.device_address = address;
88 dev_cfg.scl_speed_hz = I2C_CLOCK_HZ;
89 int dev_index = bus->CreateDevice(dev_cfg);
90 if (dev_index < 0) {
91 ESP_LOGE(BUS_TAG, "Failed to create I2C device at 0x%02X", address);
92 return nullptr;
93 }
94 auto* dev = bus->GetDevice(dev_index);
95 if (!dev || !dev->EnsureInitialized()) {
96 ESP_LOGE(BUS_TAG, "Failed to initialize I2C device at 0x%02X", address);
97 return nullptr;
98 }
99 ESP_LOGI(BUS_TAG, "I2C device added at 0x%02X", address);
100 return dev;
101}
102
103// ═══════════════════════════════════════════════════════════════════════════
104// SPI BUS — Shared by AS5047U, TMC9660 handlers
105// ═══════════════════════════════════════════════════════════════════════════
106
111inline EspSpiBus* get_shared_spi_bus() noexcept {
112 static std::unique_ptr<EspSpiBus> spi;
113 if (!spi) {
114 hf_spi_bus_config_t spi_cfg = {};
115 spi_cfg.host = static_cast<hf_host_id_t>(SPI_HOST_ID);
116 spi_cfg.mosi_pin = static_cast<hf_pin_num_t>(PIN_SPI_MOSI);
117 spi_cfg.miso_pin = static_cast<hf_pin_num_t>(PIN_SPI_MISO);
118 spi_cfg.sclk_pin = static_cast<hf_pin_num_t>(PIN_SPI_SCLK);
119 spi_cfg.dma_channel = 0; // 0 = auto DMA channel selection
120
121 spi = std::make_unique<EspSpiBus>(spi_cfg);
122 if (!spi->Initialize()) {
123 ESP_LOGE(BUS_TAG, "SPI bus initialization failed");
124 spi.reset();
125 return nullptr;
126 }
127 ESP_LOGI(BUS_TAG, "SPI bus initialized (MOSI=%d, MISO=%d, SCLK=%d)",
129 }
130 return spi.get();
131}
132
133// ═══════════════════════════════════════════════════════════════════════════
134// GPIO — Factory for individual pins
135// ═══════════════════════════════════════════════════════════════════════════
136
144inline std::unique_ptr<EspGpio> create_gpio(
145 int pin_num,
146 hf_gpio_direction_t direction = hf_gpio_direction_t::HF_GPIO_DIRECTION_INPUT,
147 hf_gpio_active_state_t active_state = hf_gpio_active_state_t::HF_GPIO_ACTIVE_HIGH) noexcept {
148
149 auto gpio = std::make_unique<EspGpio>(
150 static_cast<hf_pin_num_t>(pin_num), direction, active_state);
151
152 if (!gpio->Initialize()) {
153 ESP_LOGE(BUS_TAG, "GPIO%d initialization failed", pin_num);
154 return nullptr;
155 }
156 return gpio;
157}
158
159// ═══════════════════════════════════════════════════════════════════════════
160// ADC — For NTC thermistor handler
161// ═══════════════════════════════════════════════════════════════════════════
162
167inline EspAdc* get_shared_adc() noexcept {
168 static std::unique_ptr<EspAdc> adc;
169 if (!adc) {
170 hf_adc_unit_config_t adc_cfg = {};
171 adc_cfg.unit_id = static_cast<uint8_t>(NTC_ADC_UNIT);
172 adc_cfg.bit_width = hf_adc_bitwidth_t::WIDTH_12BIT;
173
174 adc = std::make_unique<EspAdc>(adc_cfg);
175 if (!adc->Initialize()) {
176 ESP_LOGE(BUS_TAG, "ADC initialization failed (unit=%d)", NTC_ADC_UNIT);
177 adc.reset();
178 return nullptr;
179 }
180 ESP_LOGI(BUS_TAG, "ADC initialized (unit=%d, 12-bit)", NTC_ADC_UNIT);
181 }
182 return adc.get();
183}
184
185// ═══════════════════════════════════════════════════════════════════════════
186// I2C BUS SCAN UTILITY
187// ═══════════════════════════════════════════════════════════════════════════
188
198inline int scan_i2c_bus(EspI2cBus* bus) noexcept {
199 if (!bus) return 0;
200
201 int found = 0;
202 ESP_LOGI(BUS_TAG, "── I2C Bus Scan ─────────────────────────");
203 ESP_LOGI(BUS_TAG, " 0 1 2 3 4 5 6 7 8 9 A B C D E F");
204
205 for (uint8_t row = 0; row < 8; ++row) {
206 char line[64];
207 int pos = snprintf(line, sizeof(line), "%02X: ", row << 4);
208 for (uint8_t col = 0; col < 16; ++col) {
209 uint8_t addr = (row << 4) | col;
210 if (addr < 0x08 || addr > 0x77) {
211 pos += snprintf(line + pos, sizeof(line) - pos, " ");
212 continue;
213 }
214 // Probe the address using the bus's built-in probe method
215 if (bus->ProbeDevice(addr)) {
216 pos += snprintf(line + pos, sizeof(line) - pos, "%02X ", addr);
217 found++;
218 } else {
219 pos += snprintf(line + pos, sizeof(line) - pos, "-- ");
220 }
221 }
222 ESP_LOGI(BUS_TAG, "%s", line);
223 }
224 ESP_LOGI(BUS_TAG, "Found %d device(s)", found);
225 ESP_LOGI(BUS_TAG, "─────────────────────────────────────────");
226 return found;
227}
EspI2cBus * get_shared_i2c_bus() noexcept
Create and initialize the shared I2C bus.
Definition esp32_bus_setup.hpp:54
BaseI2c * get_i2c_device(uint8_t address) noexcept
Get an I2C device handle for a specific address on the shared bus.
Definition esp32_bus_setup.hpp:81
static const char * BUS_TAG
Definition esp32_bus_setup.hpp:40
int scan_i2c_bus(EspI2cBus *bus) noexcept
Scan the I2C bus for responding devices.
Definition esp32_bus_setup.hpp:198
EspSpiBus * get_shared_spi_bus() noexcept
Create and initialize the shared SPI bus.
Definition esp32_bus_setup.hpp:111
std::unique_ptr< EspGpio > create_gpio(int pin_num, hf_gpio_direction_t direction=hf_gpio_direction_t::HF_GPIO_DIRECTION_INPUT, hf_gpio_active_state_t active_state=hf_gpio_active_state_t::HF_GPIO_ACTIVE_HIGH) noexcept
Create an EspGpio for a specific pin.
Definition esp32_bus_setup.hpp:144
EspAdc * get_shared_adc() noexcept
Create and initialize the shared ADC instance.
Definition esp32_bus_setup.hpp:167
Centralized hardware pin and address configuration for hf-core tests.
#define I2C_CLOCK_HZ
Definition esp32_test_config.hpp:35
#define I2C_PORT_NUM
Definition esp32_test_config.hpp:32
#define PIN_SPI_MISO
Definition esp32_test_config.hpp:46
#define PIN_I2C_SCL
Definition esp32_test_config.hpp:29
#define PIN_SPI_MOSI
Definition esp32_test_config.hpp:43
#define SPI_HOST_ID
Definition esp32_test_config.hpp:52
#define NTC_ADC_UNIT
Definition esp32_test_config.hpp:107
#define PIN_I2C_SDA
Definition esp32_test_config.hpp:26
#define PIN_SPI_SCLK
Definition esp32_test_config.hpp:49