Skip to content

Commit 0714d6e

Browse files
committed
Merge branch 'develop'
2 parents 23e84e7 + 2f32e3f commit 0714d6e

4 files changed

Lines changed: 623 additions & 134 deletions

File tree

src/m5_unit_component/adapter_gpio.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,6 @@ m5::hal::error::error_t AdapterGPIOBase::GPIOImpl::read_analog(uint16_t& value,
405405

406406
#if defined(M5_UNIT_UNIFIED_USING_ADC_ONESHOT)
407407
// ESP-IDF 5.x
408-
409408
adc_unit_t unit = (ch < 10) ? ADC_UNIT_1 : ADC_UNIT_2;
410409
adc_channel_t channel = static_cast<adc_channel_t>((ch < 10) ? ch : (ch - 10));
411410

src/m5_unit_component/adapter_gpio_v1.cpp

Lines changed: 187 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,17 @@
1212

1313
#if !defined(M5_UNIT_UNIFIED_USING_RMT_V2)
1414

15-
#include <esp_clk.h>
15+
// #include <esp_clk.h>
16+
#include <esp32/clk.h>
1617
using namespace m5::unit::gpio;
1718

1819
namespace {
1920

2021
uint32_t using_rmt_channel_bits{};
2122

22-
rmt_channel_t retrieve_available_rmt_channel()
23+
rmt_channel_t retrieve_available_rmt_channel(const int8_t first = 0)
2324
{
24-
for (int_fast8_t ch = 0; ch < RMT_CHANNEL_MAX; ++ch) {
25+
for (int_fast8_t ch = first; ch < RMT_CHANNEL_MAX; ++ch) {
2526
if (((1U << ch) & using_rmt_channel_bits) == 0) {
2627
return (rmt_channel_t)ch;
2728
}
@@ -48,124 +49,247 @@ void clear_use_rmt_channel(const int ch)
4849
rmt_config_t to_rmt_config_tx(const adapter_config_t& cfg, const uint32_t apb_freq_hz)
4950
{
5051
rmt_config_t out{};
51-
out.rmt_mode = RMT_MODE_TX;
52-
out.mem_block_num = cfg.tx.mem_blocks;
53-
54-
out.clk_div = calculate_rmt_clk_div(apb_freq_hz, cfg.tx.tick_ns);
55-
out.tx_config.carrier_en = false;
56-
out.tx_config.idle_output_en = cfg.tx.idle_output;
52+
out.rmt_mode = RMT_MODE_TX;
53+
out.mem_block_num = std::min<uint8_t>(cfg.tx.mem_blocks, 8u);
54+
out.clk_div = calculate_rmt_clk_div(apb_freq_hz, cfg.tx.tick_ns);
55+
out.tx_config.loop_en = cfg.tx.loop_enabled;
56+
// out.tx_config.carrier_en = cfg.tx.carrier_enabled;
57+
out.tx_config.idle_output_en = cfg.tx.idle_output_enabled;
5758
out.tx_config.idle_level = cfg.tx.idle_level_high ? RMT_IDLE_LEVEL_HIGH : RMT_IDLE_LEVEL_LOW;
58-
out.tx_config.loop_en = cfg.tx.loop_enabled;
5959
return out;
6060
}
6161

62-
#if 0
6362
rmt_config_t to_rmt_config_rx(const adapter_config_t& cfg, const uint32_t apb_freq_hz)
6463
{
6564
rmt_config_t out{};
66-
out.rmt_mode = RMT_MODE_RX;
67-
out.mem_block_num = cfg.tx.mem_blocks;
68-
out.clk_div = calculate_rmt_clk_div(apb_freq_hz, cfg.rx.tick_ns);
69-
out.rx_config.filter_en = true;
70-
out.rx_config.filter_ticks_thresh = 30;
71-
out.rx_config.idle_threshold = 300;
65+
out.rmt_mode = RMT_MODE_RX;
66+
out.mem_block_num = std::min<uint8_t>(cfg.rx.mem_blocks, 8u);
67+
out.clk_div = calculate_rmt_clk_div(apb_freq_hz, cfg.rx.tick_ns);
68+
out.rx_config.filter_en = cfg.rx.filter_enabled;
69+
out.rx_config.filter_ticks_thresh =
70+
std::min<uint8_t>(static_cast<uint32_t>(cfg.rx.filter_ticks_threshold) * 1000 / cfg.rx.tick_ns, 255U);
71+
out.rx_config.idle_threshold =
72+
static_cast<uint16_t>(static_cast<uint32_t>(cfg.rx.idle_ticks_threshold) * 1000 / cfg.rx.tick_ns);
7273
return out;
7374
}
75+
76+
void dump_rmt_config(const rmt_config_t& cfg, const char* title = "RMT CONFIG")
77+
{
78+
M5_LIB_LOGI("=== %s ===", title);
79+
M5_LIB_LOGI("rmt_mode : %s", cfg.rmt_mode == RMT_MODE_TX ? "TX" : "RX");
80+
M5_LIB_LOGI("channel : %d", static_cast<int>(cfg.channel));
81+
M5_LIB_LOGI("gpio_num : %d", static_cast<int>(cfg.gpio_num));
82+
M5_LIB_LOGI("mem_block_num : %d", cfg.mem_block_num);
83+
M5_LIB_LOGI("clk_div : %d", cfg.clk_div);
84+
85+
if (cfg.rmt_mode == RMT_MODE_TX) {
86+
M5_LIB_LOGI("TX CONFIG:");
87+
M5_LIB_LOGI(" loop_en : %s", cfg.tx_config.loop_en ? "true" : "false");
88+
M5_LIB_LOGI(" carrier_en : %s", cfg.tx_config.carrier_en ? "true" : "false");
89+
M5_LIB_LOGI(" idle_output_en : %s", cfg.tx_config.idle_output_en ? "true" : "false");
90+
M5_LIB_LOGI(" idle_level : %d", cfg.tx_config.idle_level);
91+
M5_LIB_LOGI(" carrier_freq_hz : %d", cfg.tx_config.carrier_freq_hz);
92+
M5_LIB_LOGI(" carrier_duty : %d%%", cfg.tx_config.carrier_duty_percent);
93+
M5_LIB_LOGI(" carrier_level : %d", cfg.tx_config.carrier_level);
94+
} else {
95+
M5_LIB_LOGI("RX CONFIG:");
96+
M5_LIB_LOGI(" filter_en : %s", cfg.rx_config.filter_en ? "true" : "false");
97+
M5_LIB_LOGI(" filter_thresh : %d", cfg.rx_config.filter_ticks_thresh);
98+
M5_LIB_LOGI(" idle_threshold : %d", cfg.rx_config.idle_threshold);
99+
}
100+
}
101+
102+
#if 0
103+
void dump_items(const rmt_item32_t* items, const uint32_t item_num)
104+
{
105+
for (uint32_t i = 0; i < item_num; ++i) {
106+
auto d = items[i];
107+
M5_LIB_LOGI("[%02u]:{%u,%u,%u,%u}", i, d.duration0, d.level0, d.duration1, d.level1);
108+
}
109+
}
74110
#endif
111+
75112
} // namespace
76113

77114
namespace m5 {
78115
namespace unit {
79116

80117
class GPIOImplV1 : public AdapterGPIOBase::GPIOImpl {
81118
public:
82-
GPIOImplV1() : AdapterGPIOBase::GPIOImpl(-1, -1)
83-
{
84-
}
85-
GPIOImplV1(const int8_t rx_pin, const int8_t tx_pin) : AdapterGPIOBase::GPIOImpl(rx_pin, tx_pin)
119+
explicit GPIOImplV1(const int8_t rx_pin = -1, const int8_t tx_pin = -1) : AdapterGPIOBase::GPIOImpl(rx_pin, tx_pin)
86120
{
121+
_rx_config.channel = RMT_CHANNEL_MAX;
122+
_tx_config.channel = RMT_CHANNEL_MAX;
87123
}
88124
virtual ~GPIOImplV1()
89125
{
90-
rmt_tx_stop(_tx_config.channel);
91-
rmt_driver_uninstall(_tx_config.channel);
92-
clear_use_rmt_channel(_tx_config.channel);
93-
94-
rmt_rx_stop(_rx_config.channel);
95-
rmt_driver_uninstall(_rx_config.channel);
96-
clear_use_rmt_channel(_rx_config.channel);
126+
if (_tx_config.channel != RMT_CHANNEL_MAX) {
127+
rmt_tx_stop(_tx_config.channel);
128+
rmt_driver_uninstall(_tx_config.channel);
129+
clear_use_rmt_channel(_tx_config.channel);
130+
}
131+
if (_rx_config.channel != RMT_CHANNEL_MAX) {
132+
rmt_rx_stop(_rx_config.channel);
133+
rmt_driver_uninstall(_rx_config.channel);
134+
clear_use_rmt_channel(_rx_config.channel);
135+
}
97136
}
98137

99138
virtual bool begin(const gpio::adapter_config_t& cfg) override
100139
{
101140
_adapter_cfg = cfg;
102141

103-
if (_tx_config.clk_div || _rx_config.clk_div) {
104-
M5_LIB_LOGD("Already begun");
105-
return true;
106-
}
107-
108142
// RMT TX
109-
if (cfg.mode == gpio::Mode::RmtTX || cfg.mode == gpio::Mode::RmtRXTX) {
143+
if (_tx_config.channel == RMT_CHANNEL_MAX &&
144+
(cfg.mode == gpio::Mode::RmtTX || cfg.mode == gpio::Mode::RmtRXTX)) {
110145
rmt_channel_t ch = retrieve_available_rmt_channel();
111146
if (ch >= RMT_CHANNEL_MAX) {
112-
M5_LIB_LOGE("RMT(v1) No room on channel");
147+
M5_LIB_LOGE("RMT(v1) No room on TX channel");
113148
return false;
114149
}
115-
declrare_use_rmt_channel(ch);
116-
M5_LIB_LOGI("Retrive RMT(v1) %u", ch);
117-
118150
_tx_config = to_rmt_config_tx(cfg, esp_clk_apb_freq());
119151
_tx_config.channel = ch;
120152
_tx_config.gpio_num = tx_pin();
121153

154+
dump_rmt_config(_tx_config, "TX");
155+
122156
auto err = rmt_config(&_tx_config);
123157
if (err != ESP_OK) {
124-
M5_LIB_LOGE("Failed to configurate %d:%s", err, esp_err_to_name(err));
158+
M5_LIB_LOGE("Failed to config TX %d:%s", err, esp_err_to_name(err));
125159
return false;
126160
}
161+
127162
err = rmt_driver_install(_tx_config.channel, 0, 0);
128163
if (err != ESP_OK) {
129-
M5_LIB_LOGE("Failed to install %d:%s", err, esp_err_to_name(err));
164+
M5_LIB_LOGE("Failed to install TX %d:%s", err, esp_err_to_name(err));
130165
return false;
131166
}
167+
168+
if (_adapter_cfg.tx.invert_signal) {
169+
gpio_matrix_out(_tx_config.gpio_num, _tx_config.channel + RMT_SIG_OUT0_IDX, true, false);
170+
}
171+
172+
declrare_use_rmt_channel(ch);
173+
M5_LIB_LOGI("Retrive RMT(v1) TX %d/%u", tx_pin(), ch);
132174
}
133175
// RMT RX
134-
if (cfg.mode == gpio::Mode::RmtRX || cfg.mode == gpio::Mode::RmtRXTX) {
135-
// TODO
136-
}
176+
if (_rx_config.channel == RMT_CHANNEL_MAX &&
177+
(cfg.mode == gpio::Mode::RmtRX || cfg.mode == gpio::Mode::RmtRXTX)) {
178+
#if defined(CONFIG_IDF_TARGET_ESP32S3)
179+
int8_t first = 4; // RX channel 4 - 7
180+
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
181+
int8_t first = 2; // RX channel 2 - 3
182+
#else
183+
int8_t first = 0;
184+
#endif
185+
rmt_channel_t ch = retrieve_available_rmt_channel(first);
186+
if (ch >= RMT_CHANNEL_MAX) {
187+
M5_LIB_LOGE("RMT(v1) No room on RX channel");
188+
return false;
189+
}
190+
191+
_rx_config = to_rmt_config_rx(cfg, esp_clk_apb_freq());
192+
_rx_config.channel = ch;
193+
_rx_config.gpio_num = rx_pin();
194+
195+
dump_rmt_config(_rx_config, "RX");
137196

197+
auto err = rmt_config(&_rx_config);
198+
if (err != ESP_OK) {
199+
M5_LIB_LOGE("Failed to config RX %d:%s", err, esp_err_to_name(err));
200+
return false;
201+
}
202+
203+
err = rmt_driver_install(_rx_config.channel, cfg.rx.ring_buffer_size, 0);
204+
if (err != ESP_OK) {
205+
M5_LIB_LOGE("Failed to install RX %d:%s", err, esp_err_to_name(err));
206+
return false;
207+
}
208+
209+
if (_adapter_cfg.rx.invert_signal) {
210+
gpio_matrix_in(_rx_config.gpio_num, _rx_config.channel + RMT_SIG_IN0_IDX, true);
211+
}
212+
213+
declrare_use_rmt_channel(ch);
214+
M5_LIB_LOGI("Retrieve RMT(v1) RX %d/%u", rx_pin(), ch);
215+
216+
if (rmt_rx_start(_rx_config.channel, true) != ESP_OK) {
217+
M5_LIB_LOGE("Failed to start RX");
218+
return false;
219+
}
220+
221+
// Discard garbage
222+
size_t rx_size{};
223+
RingbufHandle_t rb{};
224+
rmt_get_ringbuf_handle(_rx_config.channel, &rb);
225+
if (rb) {
226+
rmt_item32_t* items = (rmt_item32_t*)xRingbufferReceive(rb, &rx_size, 10 / portTICK_PERIOD_MS);
227+
if (items) {
228+
vRingbufferReturnItem(rb, items);
229+
}
230+
}
231+
}
138232
return true;
139233
}
140234

141235
m5::hal::error::error_t writeWithTransaction(const uint8_t* data, const size_t len, const uint32_t waitMs) override
142236
{
143-
if (_adapter_cfg.mode == Mode::RmtTX || _adapter_cfg.mode == Mode::RmtRXTX) {
144-
auto err = rmt_write_items(_tx_config.channel, (gpio::m5_rmt_item_t*)data, len, true);
237+
if (_tx_config.channel == RMT_CHANNEL_MAX) {
238+
M5_LIB_LOGE("Invalid channel");
239+
return m5::hal::error::error_t::UNKNOWN_ERROR;
240+
}
241+
242+
// m5::utility::log::dump(data, len, false);
243+
// dump_items((rmt_item32_t*)data, len / sizeof(rmt_item32_t));
244+
245+
auto err = rmt_write_items(_tx_config.channel, (gpio::m5_rmt_item_t*)data, len / sizeof(rmt_item32_t), false);
246+
if (err != ESP_OK) {
247+
M5_LIB_LOGE("Failed to write %d:%s", err, esp_err_to_name(err));
248+
return m5::hal::error::error_t::UNKNOWN_ERROR;
249+
}
250+
if (err == ESP_OK && waitMs) {
251+
// M5_LIB_LOGE(">>> wait_tx_done %d,%u", _tx_config.channel, waitMs);
252+
err = rmt_wait_tx_done(_tx_config.channel, waitMs);
145253
if (err != ESP_OK) {
146-
M5_LIB_LOGE("Failed to write %d:%s", err, esp_err_to_name(err));
147-
return m5::hal::error::error_t::UNKNOWN_ERROR;
254+
M5_LIB_LOGE("Failed to wait %d:%s", err, esp_err_to_name(err));
148255
}
149-
if (err == ESP_OK && waitMs) {
150-
err = rmt_wait_tx_done(_tx_config.channel, pdMS_TO_TICKS(50));
151-
if (err != ESP_OK) {
152-
M5_LIB_LOGE("Failed to wait %d:%s", err, esp_err_to_name(err));
153-
}
154-
}
155-
return err == ESP_OK ? m5::hal::error::error_t::OK : m5::hal::error::error_t::UNKNOWN_ERROR;
156256
}
157-
158-
M5_LIB_LOGE("Failed invalid config");
159-
return m5::hal::error::error_t::UNKNOWN_ERROR;
257+
return err == ESP_OK ? m5::hal::error::error_t::OK : m5::hal::error::error_t::UNKNOWN_ERROR;
160258
}
161259

162-
void copy_from(GPIOImplV1* ptr)
260+
m5::hal::error::error_t readWithTransaction(uint8_t* data, const size_t len)
163261
{
164-
_rx_pin = ptr->_rx_pin;
165-
_tx_pin = ptr->_tx_pin;
166-
_adapter_cfg = ptr->_adapter_cfg;
167-
_rx_config = ptr->_rx_config;
168-
_tx_config = ptr->_tx_config;
262+
if (_rx_config.channel == RMT_CHANNEL_MAX) {
263+
M5_LIB_LOGE("Invalid channel");
264+
return m5::hal::error::error_t::UNKNOWN_ERROR;
265+
}
266+
267+
if (len < 4) {
268+
M5_LIB_LOGE("length too small %zu", len);
269+
return m5::hal::error::error_t::INVALID_ARGUMENT;
270+
}
271+
272+
RingbufHandle_t rb{};
273+
if (rmt_get_ringbuf_handle(_rx_config.channel, &rb) != ESP_OK || rb == nullptr) {
274+
M5_LIB_LOGE("Failed to get RX ringbuffer");
275+
return m5::hal::error::error_t::UNKNOWN_ERROR;
276+
}
277+
278+
size_t max_len = len - 2; // Top of 2bytes is receive length
279+
size_t rx_size{};
280+
rmt_item32_t* items = (rmt_item32_t*)xRingbufferReceive(rb, &rx_size, pdMS_TO_TICKS(50));
281+
282+
// dump_items(items, rx_size / sizeof(rmt_item32_t));
283+
*(uint16_t*)data = 0;
284+
if (items && rx_size) {
285+
uint16_t rlen = std::min<uint16_t>(rx_size, max_len);
286+
*(uint16_t*)data = rlen;
287+
memcpy(data + 2, items, rlen);
288+
}
289+
if (items) {
290+
vRingbufferReturnItem(rb, items);
291+
}
292+
return rx_size ? m5::hal::error::error_t::OK : m5::hal::error::error_t::TIMEOUT_ERROR;
169293
}
170294

171295
protected:

0 commit comments

Comments
 (0)