Files
OGX-Mini/Firmware/ESP32/main/I2CDriver/I2CDriver.h
wiredopposite aabb00f2b5 v1.0.0-alpha
2024-12-19 23:15:27 -07:00

120 lines
3.1 KiB
C++

#ifndef _I2C_DRIVER_H_
#define _I2C_DRIVER_H_
#include <cstdint>
#include <cstring>
#include <functional>
#include <driver/i2c.h>
#include "sdkconfig.h"
#include "RingBuffer.h"
class I2CDriver
{
public:
static constexpr bool MULTI_SLAVE =
#if CONFIG_MULTI_SLAVE_MODE == 0
false;
#else
true;
#endif
enum class PacketID : uint8_t { UNKNOWN = 0, SET_PAD, GET_PAD };
#pragma pack(push, 1)
struct PacketIn
{
uint8_t packet_len;
uint8_t packet_id;
uint8_t index;
uint8_t dpad;
uint16_t buttons;
uint8_t trigger_l;
uint8_t trigger_r;
int16_t joystick_lx;
int16_t joystick_ly;
int16_t joystick_rx;
int16_t joystick_ry;
PacketIn()
{
std::memset(this, 0, sizeof(PacketIn));
packet_len = sizeof(PacketIn);
packet_id = static_cast<uint8_t>(PacketID::SET_PAD);
}
};
static_assert(sizeof(PacketIn) == 16, "PacketIn is misaligned");
struct PacketOut
{
uint8_t packet_len;
uint8_t packet_id;
uint8_t index;
uint8_t rumble_l;
uint8_t rumble_r;
uint8_t reserved[3];
PacketOut()
{
std::memset(this, 0, sizeof(PacketOut));
packet_len = sizeof(PacketOut);
packet_id = static_cast<uint8_t>(PacketID::GET_PAD);
}
};
static_assert(sizeof(PacketOut) == 8, "PacketOut is misaligned");
#pragma pack(pop)
I2CDriver() = default;
~I2CDriver();
void initialize_i2c();
//Does not return
static void run_tasks(void* parameter);
//Thread safe
inline void push_task(std::function<void()> task)
{
task_queue_.push(task);
}
//Don't call directly from another thread, use in push_task
inline esp_err_t i2c_write_blocking(uint8_t address, const uint8_t* buffer, size_t len)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, true);
i2c_master_write(cmd, buffer, len, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(2));
i2c_cmd_link_delete(cmd);
return ret;
}
//Don't call directly from another thread, use in push_task
inline esp_err_t i2c_read_blocking(uint8_t address, uint8_t* buffer, size_t len)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_READ, true);
if (len > 1)
{
i2c_master_read(cmd, buffer, len - 1, I2C_MASTER_ACK);
}
i2c_master_read_byte(cmd, buffer + len - 1, I2C_MASTER_NACK);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(2));
i2c_cmd_link_delete(cmd);
return ret;
}
private:
using TaskQueue = RingBuffer<std::function<void()>, 6>;
static TaskQueue task_queue_;
};
#endif // _I2C_DRIVER_H_