OpenSourceSimWheelESP32
Open-source wireless steering wheel/button box for ESP32 boards
Loading...
Searching...
No Matches
HAL.hpp
Go to the documentation of this file.
1
12#pragma once
13
14//-------------------------------------------------------------------
15// Imports
16//-------------------------------------------------------------------
17
18#include "InternalTypes.hpp"
19#include "SimWheelTypes.hpp"
20
21#if !CD_CI
22#include "driver/i2c_types.h" // For I2C operation
23#include "driver/i2c_master.h" // For I2C operation
24#endif
25
26//-------------------------------------------------------------------
27// GLOBALS
28//-------------------------------------------------------------------
29
31#define AS_GPIO(pin) static_cast<gpio_num_t>((int)(pin))
33#define AS_PORT(bus) static_cast<i2c_port_num_t>(bus)
35#define GPIO_SET_LEVEL(pin, level) gpio_set_level(static_cast<gpio_num_t>((int)(pin)), (level))
37#define I2C_SLAVE(dev) static_cast<i2c_master_dev_handle_t>(dev)
39#define GPIO_GET_LEVEL(pin) gpio_get_level(static_cast<gpio_num_t>((int)(pin)))
41typedef void (*ISRHandler)(void *arg);
42
43#if !CD_CI
45#define DELAY_TICKS(ticks) vTaskDelay(ticks)
47#define DELAY_MS(ms) vTaskDelay(pdMS_TO_TICKS(ms))
48#else
49#define DELAY_TICKS(ticks) std::this_thread::sleep_for(std::chrono::microseconds(ticks))
50#define DELAY_MS(ms) std::this_thread::sleep_for(std::chrono::milliseconds(ms))
51#endif
52
53// Each CPU instruction takes 6.25 nanoseconds in an ESP32 RISC-V @ 160 Mhz
54// Each CPU instruction takes 4.16 nanoseconds in an ESP32 Xtensa @ 240 Mhz
55
57#define NS_PER_LOOP ((4000 + CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ - 1) / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
58
66#define active_wait_ns(n) \
67 for (uint32_t i = 0; i < n; i += NS_PER_LOOP) \
68 asm("");
69
70//-------------------------------------------------------------------
71// Exceptions
72//-------------------------------------------------------------------
73
78class i2c_error : public std::runtime_error
79{
80public:
88 i2c_error(int sda, int scl, int bus)
89 : std::runtime_error(
90 "I2C: unable to initialize bus. SDA=" +
91 std::to_string(sda) +
92 " SCL=" +
93 std::to_string(scl) +
94 " BUS=" +
95 std::to_string(bus)) {}
96
103 i2c_error(uint8_t address)
104 : std::runtime_error(
105 "I2C: invalid address " +
106 std::to_string((int)address) +
107 " (dec)") {}
108
109 virtual ~i2c_error() noexcept {}
110};
111
116class i2c_device_not_found : public std::runtime_error
117{
118public:
125 i2c_device_not_found(uint8_t address, int bus = 0)
126 : std::runtime_error(
127 "I2C: device not found, but required. Bus=" +
128 std::to_string(bus) +
129 " Hw/Full address=" +
130 std::to_string(address) +
131 " (dec)") {}
132
133 virtual ~i2c_device_not_found() noexcept {}
134};
135
140class i2c_full_address_unknown : public std::runtime_error
141{
142public:
149 i2c_full_address_unknown(uint8_t hwAddress, int bus = 0)
150 : std::runtime_error(
151 "I2C: unable to detect full address. Bus=" +
152 std::to_string(bus) +
153 " HW address=" +
154 std::to_string(hwAddress) +
155 " (dec)") {}
156
157 virtual ~i2c_full_address_unknown() noexcept {}
158};
159
160//-------------------------------------------------------------------
161// API
162//-------------------------------------------------------------------
163
164namespace internals
165{
166 //---------------------------------------------------------------
167 // Hardware abstraction
168 //---------------------------------------------------------------
169
170 namespace hal
171 {
172
173 //---------------------------------------------------------------
174 // I2C bus operation
175 //---------------------------------------------------------------
176
177 namespace i2c
178 {
201 GPIO sda,
202 GPIO scl,
203 I2CBus bus,
204 bool enableInternalPullup = true);
205
214 I2CBus bus = I2CBus::PRIMARY);
215
216#if !CD_CI
227 i2c_master_dev_handle_t add_device(
228 uint8_t address7bits,
229 uint8_t max_speed_multiplier,
230 I2CBus bus);
231
237 void remove_device(i2c_master_dev_handle_t i2c_device);
238#endif
239
251 bool probe(
252 uint8_t address7bits,
253 I2CBus bus = I2CBus::PRIMARY);
254
262 void probe(
263 std::vector<uint8_t> &result,
264 I2CBus bus = I2CBus::PRIMARY);
265
276 uint8_t address7bits,
277 uint8_t minAddress = 0,
278 uint8_t maxAddress = 127);
279
296 std::vector<uint8_t> &fullAddressList,
297 uint8_t hardwareAddress,
298 uint8_t hardwareAddressMask = 0b00000111);
299 } // namespace i2c
300
301 //---------------------------------------------------------------
302 // GPIO operation
303 //---------------------------------------------------------------
304
305 namespace gpio
306 {
317 int getADCreading(ADC_GPIO pin, int sampleCount = 1);
318
328 void forOutput(OutputGPIO pin, bool initialLevel, bool openDrain);
329
338 InputGPIO pin,
339 bool enablePullDown,
340 bool enablePullUp);
341
342#if CD_CI
352 void setFakeADCReading(const std::vector<int> &injectedADCValues);
353#endif
354
362 void enableISR(InputGPIO pin, ISRHandler handler, void *param = nullptr);
363
364 } // namespace gpio
365 } // namespace hal
366} // namespace internals
void enableISR(InputGPIO pin, ISRHandler handler, void *param=nullptr)
Enable an interrupt service routine.
void(* ISRHandler)(void *arg)
Interrupt Service Routine.
Definition HAL.hpp:41
i2c_master_dev_handle_t add_device(uint8_t address7bits, uint8_t max_speed_multiplier, I2CBus bus)
Add an slave device ensuring the bus is initialized.
void abortOnInvalidAddress(uint8_t address7bits, uint8_t minAddress=0, uint8_t maxAddress=127)
Abort and reboot on an invalid I2C address.
void forOutput(OutputGPIO pin, bool initialLevel, bool openDrain)
Configure a pin for output.
void require(I2CBus bus=I2CBus::PRIMARY)
Ensure the I2C bus is initialized.
int getADCreading(ADC_GPIO pin, int sampleCount=1)
Get the mean of some continuous ADC readings.
void forInput(InputGPIO pin, bool enablePullDown, bool enablePullUp)
Configure a pin for digital input.
void remove_device(i2c_master_dev_handle_t i2c_device)
Remove an slave device.
bool probe(uint8_t address7bits, I2CBus bus=I2CBus::PRIMARY)
Check slave device availability on an I2C bus.
uint8_t findFullAddress(std::vector< uint8_t > &fullAddressList, uint8_t hardwareAddress, uint8_t hardwareAddressMask=0b00000111)
Find the full address of a device.
void initialize(GPIO sda, GPIO scl, I2CBus bus, bool enableInternalPullup=true)
Initialize an I2C bus to certain pins.
Types and constants used everywhere for firmware implementation.
Types and constants required for custom firmware setup.
I2CBus
I2C bus controller.
Exception for I2C devices not found.
Definition HAL.hpp:117
i2c_device_not_found(uint8_t address, int bus=0)
Construct a new i2c_device_not_found exception.
Definition HAL.hpp:125
Exception for I2C bus initialization failure.
Definition HAL.hpp:79
i2c_error(uint8_t address)
Invalid I2C address exception.
Definition HAL.hpp:103
i2c_error(int sda, int scl, int bus)
Unable to initialize the I2C bus exception.
Definition HAL.hpp:88
Exception for unknown full I2C address.
Definition HAL.hpp:141
i2c_full_address_unknown(uint8_t hwAddress, int bus=0)
Construct a new i2c_full_address_unknown exception.
Definition HAL.hpp:149
ADC-capable GPIO pin number.
GPIO pin number.
Input-capable GPIO pin number.
Output-capable GPIO pin number.