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#include "freertos/FreeRTOS.h" // For pdMS_TO_TICKS
25#else
26#include <thread>
27#endif
28
29//-------------------------------------------------------------------
30// GLOBALS
31//-------------------------------------------------------------------
32
34#define AS_GPIO(pin) static_cast<gpio_num_t>((int)(pin))
36#define AS_PORT(bus) static_cast<i2c_port_num_t>(bus)
38#define GPIO_SET_LEVEL(pin, level) gpio_set_level(static_cast<gpio_num_t>((int)(pin)), (level))
40#define I2C_SLAVE(dev) static_cast<i2c_master_dev_handle_t>(dev)
42#define GPIO_GET_LEVEL(pin) gpio_get_level(static_cast<gpio_num_t>((int)(pin)))
44typedef void (*ISRHandler)(void *arg);
45
46#if !CD_CI
48#define DELAY_TICKS(ticks) vTaskDelay(ticks)
50#define DELAY_MS(ms) vTaskDelay(pdMS_TO_TICKS(ms))
51#else
52#define DELAY_TICKS(ticks) std::this_thread::sleep_for(std::chrono::microseconds(ticks))
53#define DELAY_MS(ms) std::this_thread::sleep_for(std::chrono::milliseconds(ms))
54#endif
55
56// Each CPU instruction takes 6.25 nanoseconds in an ESP32 RISC-V @ 160 Mhz
57// Each CPU instruction takes 4.16 nanoseconds in an ESP32 Xtensa @ 240 Mhz
58
60#define NS_PER_LOOP ((4000 + CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ - 1) / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
61
69#define active_wait_ns(n) \
70 for (uint32_t i = 0; i < n; i += NS_PER_LOOP) \
71 asm("");
72
73//-------------------------------------------------------------------
74// Exceptions
75//-------------------------------------------------------------------
76
81class i2c_error : public std::runtime_error
82{
83public:
91 i2c_error(int sda, int scl, int bus)
92 : std::runtime_error(
93 "I2C: unable to initialize bus. SDA=" +
94 std::to_string(sda) +
95 " SCL=" +
96 std::to_string(scl) +
97 " BUS=" +
98 std::to_string(bus)) {}
99
106 i2c_error(uint8_t address)
107 : std::runtime_error(
108 "I2C: invalid address " +
109 std::to_string((int)address) +
110 " (dec)") {}
111
112 virtual ~i2c_error() noexcept {}
113};
114
119class i2c_device_not_found : public std::runtime_error
120{
121public:
128 i2c_device_not_found(uint8_t address, int bus = 0)
129 : std::runtime_error(
130 "I2C: device not found, but required. Bus=" +
131 std::to_string(bus) +
132 " Hw/Full address=" +
133 std::to_string(address) +
134 " (dec)") {}
135
136 virtual ~i2c_device_not_found() noexcept {}
137};
138
143class i2c_full_address_unknown : public std::runtime_error
144{
145public:
152 i2c_full_address_unknown(uint8_t hwAddress, int bus = 0)
153 : std::runtime_error(
154 "I2C: unable to detect full address. Bus=" +
155 std::to_string(bus) +
156 " HW address=" +
157 std::to_string(hwAddress) +
158 " (dec)") {}
159
160 virtual ~i2c_full_address_unknown() noexcept {}
161};
162
163//-------------------------------------------------------------------
164// API
165//-------------------------------------------------------------------
166
167namespace internals
168{
169 //---------------------------------------------------------------
170 // Hardware abstraction
171 //---------------------------------------------------------------
172
173 namespace hal
174 {
175
176 //---------------------------------------------------------------
177 // I2C bus operation
178 //---------------------------------------------------------------
179
180 namespace i2c
181 {
207 GPIO sda,
208 GPIO scl,
209 I2CBus bus,
210 bool enableInternalPullup = true);
211
220 I2CBus bus = I2CBus::PRIMARY);
221
222#if !CD_CI
233 i2c_master_dev_handle_t add_device(
234 uint8_t address7bits,
235 uint8_t max_speed_multiplier,
236 I2CBus bus);
237
243 void remove_device(i2c_master_dev_handle_t i2c_device);
244#endif
245
258 bool probe(
259 uint8_t address7bits,
260 I2CBus bus = I2CBus::PRIMARY);
261
269 void probe(
270 std::vector<uint8_t> &result,
271 I2CBus bus = I2CBus::PRIMARY);
272
283 uint8_t address7bits,
284 uint8_t minAddress = 0,
285 uint8_t maxAddress = 127);
286
305 std::vector<uint8_t> &fullAddressList,
306 uint8_t hardwareAddress,
307 uint8_t hardwareAddressMask = 0b00000111);
308 } // namespace i2c
309
310 //---------------------------------------------------------------
311 // GPIO operation
312 //---------------------------------------------------------------
313
314 namespace gpio
315 {
326 int getADCreading(ADC_GPIO pin, int sampleCount = 1);
327
337 void forOutput(OutputGPIO pin, bool initialLevel, bool openDrain);
338
347 InputGPIO pin,
348 bool enablePullDown,
349 bool enablePullUp);
350
351#if CD_CI
362 void setFakeADCReading(const std::vector<int> &injectedADCValues);
363#endif
364
373 InputGPIO pin,
374 ISRHandler handler,
375 void *param = nullptr);
376
377 } // namespace gpio
378 } // namespace hal
379} // 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:44
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:120
i2c_device_not_found(uint8_t address, int bus=0)
Construct a new i2c_device_not_found exception.
Definition HAL.hpp:128
Exception for I2C bus initialization failure.
Definition HAL.hpp:82
i2c_error(uint8_t address)
Invalid I2C address exception.
Definition HAL.hpp:106
i2c_error(int sda, int scl, int bus)
Unable to initialize the I2C bus exception.
Definition HAL.hpp:91
Exception for unknown full I2C address.
Definition HAL.hpp:144
i2c_full_address_unknown(uint8_t hwAddress, int bus=0)
Construct a new i2c_full_address_unknown exception.
Definition HAL.hpp:152
ADC-capable GPIO pin number.
GPIO pin number.
Input-capable GPIO pin number.
Output-capable GPIO pin number.