parent
4e643baf5f
commit
1b2b9182e0
@ -1,4 +1,4 @@ |
||||
idf_component_register( |
||||
SRCS "gay-ipod-fw.cpp" "dac.cpp" "gpio-expander.cpp" "battery.cpp" "storage.cpp" |
||||
SRCS "gay-ipod-fw.cpp" "dac.cpp" "gpio-expander.cpp" "battery.cpp" "storage.cpp" "i2c.cpp" |
||||
INCLUDE_DIRS "." |
||||
REQUIRES "esp_adc_cal" "fatfs") |
||||
|
@ -0,0 +1,44 @@ |
||||
#include "i2c.h" |
||||
#include "assert.h" |
||||
|
||||
namespace gay_ipod { |
||||
|
||||
I2CTransaction::I2CTransaction() { |
||||
handle_ = i2c_cmd_link_create(); |
||||
assert(handle_ != NULL && "failed to create command link"); |
||||
} |
||||
|
||||
I2CTransaction::~I2CTransaction() { |
||||
i2c_cmd_link_delete(handle_); |
||||
} |
||||
|
||||
esp_err_t I2CTransaction::Execute() { |
||||
return i2c_master_cmd_begin(I2C_NUM_0, handle_, kI2CTimeout); |
||||
} |
||||
|
||||
I2CTransaction& I2CTransaction::start() { |
||||
ESP_ERROR_CHECK(i2c_master_start(handle_)); |
||||
return *this; |
||||
} |
||||
|
||||
I2CTransaction& I2CTransaction::stop() { |
||||
ESP_ERROR_CHECK(i2c_master_stop(handle_)); |
||||
return *this; |
||||
} |
||||
|
||||
I2CTransaction& I2CTransaction::write_addr(uint8_t addr, uint8_t op) { |
||||
write_ack(addr << 1 | op); |
||||
return *this; |
||||
} |
||||
|
||||
I2CTransaction& I2CTransaction::write_ack(uint8_t data) { |
||||
ESP_ERROR_CHECK(i2c_master_write_byte(handle_, data, true)); |
||||
return *this; |
||||
} |
||||
|
||||
I2CTransaction& I2CTransaction::read(uint8_t *dest, i2c_ack_type_t ack) { |
||||
ESP_ERROR_CHECK(i2c_master_read_byte(handle_, dest, ack)); |
||||
return *this; |
||||
} |
||||
|
||||
} // namespace gay_ipod
|
@ -0,0 +1,80 @@ |
||||
#pragma once |
||||
|
||||
#include "driver/i2c.h" |
||||
#include "hal/i2c_types.h" |
||||
#include <cstdint> |
||||
|
||||
namespace gay_ipod { |
||||
|
||||
/*
|
||||
* Convenience wrapper for performing an I2C transaction with a reasonable |
||||
* preconfigured timeout, automatic management of a heap-based command buffer, |
||||
* and a terser API for enqueuing bytes. |
||||
* |
||||
* Any error codes from the underlying ESP IDF are treated as fatal, since they |
||||
* typically represent invalid arguments or OOMs. |
||||
*/ |
||||
class I2CTransaction { |
||||
public: |
||||
static const uint8_t kI2CTimeout = 100 / portTICK_RATE_MS; |
||||
|
||||
I2CTransaction(); |
||||
~I2CTransaction(); |
||||
|
||||
/*
|
||||
* Executes all enqueued commands, returning the result code. Possible error |
||||
* codes, per the ESP-IDF docs: |
||||
* |
||||
* ESP_OK Success |
||||
* ESP_ERR_INVALID_ARG Parameter error |
||||
* ESP_FAIL Sending command error, slave doesn’t ACK the transfer. |
||||
* ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode. |
||||
* ESP_ERR_TIMEOUT Operation timeout because the bus is busy. |
||||
*/ |
||||
esp_err_t Execute(); |
||||
|
||||
/*
|
||||
* Enqueues a start condition. May also be used for repeated start conditions. |
||||
*/ |
||||
I2CTransaction& start(); |
||||
/* Enqueues a stop condition. */ |
||||
I2CTransaction& stop(); |
||||
|
||||
/*
|
||||
* Enqueues writing the given 7 bit address, followed by one bit indicating |
||||
* whether this is a read or write request. |
||||
* |
||||
* This command will expect an ACK before continuing. |
||||
*/ |
||||
I2CTransaction& write_addr(uint8_t addr, uint8_t op); |
||||
|
||||
/*
|
||||
* Enqueues one or more bytes to be written. The transaction will wait for |
||||
* an ACK to be returned before writing the next byte. |
||||
*/ |
||||
I2CTransaction& write_ack(uint8_t data); |
||||
template <typename ...More> |
||||
I2CTransaction& write_ack(uint8_t data, More... more) { |
||||
write_ack(data); |
||||
write_ack(more...); |
||||
return *this; |
||||
} |
||||
|
||||
/*
|
||||
* Enqueues a read of one byte into the given uint8. Responds with the given |
||||
* ACK/NACK type. |
||||
*/ |
||||
I2CTransaction& read(uint8_t *dest, i2c_ack_type_t ack); |
||||
|
||||
/* Returns the underlying command buffer. */ |
||||
i2c_cmd_handle_t handle() { return handle_; } |
||||
|
||||
// Cannot be moved or copied, since doing so is probably an error. Pass a
|
||||
// reference instead.
|
||||
I2CTransaction(const I2CTransaction&) = delete; |
||||
I2CTransaction& operator=(const I2CTransaction&) = delete; |
||||
private: |
||||
i2c_cmd_handle_t handle_; |
||||
}; |
||||
|
||||
} // namespace gay_ipod
|
Loading…
Reference in new issue