i2c_cxx.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2020 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifdef __cpp_exceptions
  15. #include "i2c_cxx.hpp"
  16. using namespace std;
  17. namespace idf {
  18. #define I2C_CHECK_THROW(err) CHECK_THROW_SPECIFIC((err), I2CException)
  19. I2CException::I2CException(esp_err_t error) : ESPException(error) { }
  20. I2CTransferException::I2CTransferException(esp_err_t error) : I2CException(error) { }
  21. I2CBus::I2CBus(i2c_port_t i2c_number) : i2c_num(i2c_number) { }
  22. I2CBus::~I2CBus() { }
  23. I2CMaster::I2CMaster(i2c_port_t i2c_number,
  24. int scl_gpio,
  25. int sda_gpio,
  26. uint32_t clock_speed,
  27. bool scl_pullup,
  28. bool sda_pullup)
  29. : I2CBus(i2c_number)
  30. {
  31. i2c_config_t conf = {};
  32. conf.mode = I2C_MODE_MASTER;
  33. conf.scl_io_num = scl_gpio;
  34. conf.scl_pullup_en = scl_pullup;
  35. conf.sda_io_num = sda_gpio;
  36. conf.sda_pullup_en = sda_pullup;
  37. conf.master.clk_speed = clock_speed;
  38. I2C_CHECK_THROW(i2c_param_config(i2c_num, &conf));
  39. I2C_CHECK_THROW(i2c_driver_install(i2c_num, conf.mode, 0, 0, 0));
  40. }
  41. I2CMaster::~I2CMaster()
  42. {
  43. i2c_driver_delete(i2c_num);
  44. }
  45. void I2CMaster::sync_write(uint8_t i2c_addr, const vector<uint8_t> &data)
  46. {
  47. I2CWrite writer(data);
  48. writer.do_transfer(i2c_num, i2c_addr);
  49. }
  50. std::vector<uint8_t> I2CMaster::sync_read(uint8_t i2c_addr, size_t n_bytes)
  51. {
  52. I2CRead reader(n_bytes);
  53. return reader.do_transfer(i2c_num, i2c_addr);
  54. }
  55. vector<uint8_t> I2CMaster::sync_transfer(uint8_t i2c_addr,
  56. const std::vector<uint8_t> &write_data,
  57. size_t read_n_bytes)
  58. {
  59. if (!read_n_bytes) throw I2CException(ESP_ERR_INVALID_ARG);
  60. I2CComposed composed_transfer;
  61. composed_transfer.add_write(write_data);
  62. composed_transfer.add_read(read_n_bytes);
  63. return composed_transfer.do_transfer(i2c_num, i2c_addr)[0];
  64. }
  65. I2CSlave::I2CSlave(i2c_port_t i2c_number,
  66. int scl_gpio,
  67. int sda_gpio,
  68. uint8_t slave_addr,
  69. size_t rx_buf_len,
  70. size_t tx_buf_len,
  71. bool scl_pullup,
  72. bool sda_pullup)
  73. : I2CBus(i2c_number)
  74. {
  75. i2c_config_t conf = {};
  76. conf.mode = I2C_MODE_SLAVE;
  77. conf.scl_io_num = scl_gpio;
  78. conf.scl_pullup_en = scl_pullup;
  79. conf.sda_io_num = sda_gpio;
  80. conf.sda_pullup_en = sda_pullup;
  81. conf.slave.addr_10bit_en = 0;
  82. conf.slave.slave_addr = slave_addr;
  83. I2C_CHECK_THROW(i2c_param_config(i2c_num, &conf));
  84. I2C_CHECK_THROW(i2c_driver_install(i2c_num, conf.mode, rx_buf_len, tx_buf_len, 0));
  85. }
  86. I2CSlave::~I2CSlave()
  87. {
  88. i2c_driver_delete(i2c_num);
  89. }
  90. int I2CSlave::write_raw(const uint8_t *data, size_t data_len, chrono::milliseconds timeout)
  91. {
  92. return i2c_slave_write_buffer(i2c_num, data, data_len, (TickType_t) timeout.count() / portTICK_RATE_MS);
  93. }
  94. int I2CSlave::read_raw(uint8_t *buffer, size_t buffer_len, chrono::milliseconds timeout)
  95. {
  96. return i2c_slave_read_buffer(i2c_num, buffer, buffer_len, (TickType_t) timeout.count() / portTICK_RATE_MS);
  97. }
  98. I2CWrite::I2CWrite(const vector<uint8_t> &bytes, chrono::milliseconds driver_timeout)
  99. : I2CTransfer<void>(driver_timeout), bytes(bytes) { }
  100. void I2CWrite::queue_cmd(i2c_cmd_handle_t handle, uint8_t i2c_addr)
  101. {
  102. I2C_CHECK_THROW(i2c_master_start(handle));
  103. I2C_CHECK_THROW(i2c_master_write_byte(handle, i2c_addr << 1 | I2C_MASTER_WRITE, true));
  104. I2C_CHECK_THROW(i2c_master_write(handle, bytes.data(), bytes.size(), true));
  105. }
  106. void I2CWrite::process_result() { }
  107. I2CRead::I2CRead(size_t size, chrono::milliseconds driver_timeout)
  108. : I2CTransfer<vector<uint8_t> >(driver_timeout), bytes(size) { }
  109. void I2CRead::queue_cmd(i2c_cmd_handle_t handle, uint8_t i2c_addr)
  110. {
  111. I2C_CHECK_THROW(i2c_master_start(handle));
  112. I2C_CHECK_THROW(i2c_master_write_byte(handle, i2c_addr << 1 | I2C_MASTER_READ, true));
  113. I2C_CHECK_THROW(i2c_master_read(handle, bytes.data(), bytes.size(), I2C_MASTER_LAST_NACK));
  114. }
  115. vector<uint8_t> I2CRead::process_result()
  116. {
  117. return bytes;
  118. }
  119. I2CComposed::I2CComposed(chrono::milliseconds driver_timeout)
  120. : I2CTransfer<vector<vector<uint8_t> > >(driver_timeout), transfer_list() { }
  121. void I2CComposed::CompTransferNodeRead::queue_cmd(i2c_cmd_handle_t handle, uint8_t i2c_addr)
  122. {
  123. I2C_CHECK_THROW(i2c_master_write_byte(handle, i2c_addr << 1 | I2C_MASTER_READ, true));
  124. I2C_CHECK_THROW(i2c_master_read(handle, bytes.data(), bytes.size(), I2C_MASTER_LAST_NACK));
  125. }
  126. void I2CComposed::CompTransferNodeRead::process_result(std::vector<std::vector<uint8_t> > &read_results)
  127. {
  128. read_results.push_back(bytes);
  129. }
  130. void I2CComposed::CompTransferNodeWrite::queue_cmd(i2c_cmd_handle_t handle, uint8_t i2c_addr)
  131. {
  132. I2C_CHECK_THROW(i2c_master_write_byte(handle, i2c_addr << 1 | I2C_MASTER_WRITE, true));
  133. I2C_CHECK_THROW(i2c_master_write(handle, bytes.data(), bytes.size(), true));
  134. }
  135. void I2CComposed::add_read(size_t size)
  136. {
  137. if (!size) throw I2CException(ESP_ERR_INVALID_ARG);
  138. transfer_list.push_back(make_shared<CompTransferNodeRead>(size));
  139. }
  140. void I2CComposed::add_write(std::vector<uint8_t> bytes)
  141. {
  142. if (bytes.empty()) throw I2CException(ESP_ERR_INVALID_ARG);
  143. transfer_list.push_back(make_shared<CompTransferNodeWrite>(bytes));
  144. }
  145. void I2CComposed::queue_cmd(i2c_cmd_handle_t handle, uint8_t i2c_addr)
  146. {
  147. for (auto it = transfer_list.begin(); it != transfer_list.end(); it++) {
  148. I2C_CHECK_THROW(i2c_master_start(handle));
  149. (*it)->queue_cmd(handle, i2c_addr);
  150. }
  151. }
  152. std::vector<std::vector<uint8_t> > I2CComposed::process_result()
  153. {
  154. std::vector<std::vector<uint8_t> > results;
  155. for (auto it = transfer_list.begin(); it != transfer_list.end(); it++) {
  156. (*it)->process_result(results);
  157. }
  158. return results;
  159. }
  160. } // idf
  161. #endif // __cpp_exceptions