messy gpio receive routines
This commit is contained in:
parent
7db0c9bf7a
commit
6239375dfa
5 changed files with 210 additions and 41 deletions
|
@ -278,11 +278,15 @@ size_t unicode_to_baudot(baudot_context_t *ctx, uint8_t *input, uint8_t input_le
|
|||
}
|
||||
|
||||
uint8_t found = 0;
|
||||
for (int x = 0; x < sizeof(baudot_map); x++)
|
||||
for (int i = 0; i < sizeof(baudot_map); i++)
|
||||
{
|
||||
// start lookup from current part of baudot map
|
||||
int x = i ^ (ctx->figures << 5);
|
||||
|
||||
if (baudot_map[x] == c)
|
||||
{
|
||||
if (ctx->figures != x >> 5)
|
||||
// switch to figures + workaround for broken carriage return on our machine :(
|
||||
if (ctx->figures != x >> 5 || (c == '\r' && !ctx->figures))
|
||||
{
|
||||
output[out_pos++] = ctx->figures ? BAUDOT_LTRS : BAUDOT_FIGS;
|
||||
ctx->figures = !ctx->figures;
|
||||
|
|
65
src/main.c
65
src/main.c
|
@ -17,6 +17,7 @@ const uint32_t TTY_EN_GPIO = 2;
|
|||
rmtuart_ctx_t rmtuart = {
|
||||
.tx_gpio = TTY_TX_GPIO,
|
||||
.rx_gpio = TTY_RX_GPIO,
|
||||
.rx_mode = RX_MODE_GPIO,
|
||||
.baudrate = 50,
|
||||
.data_bits = 5,
|
||||
.stop_bits = 1,
|
||||
|
@ -39,7 +40,7 @@ void softuart_test()
|
|||
while (1)
|
||||
{
|
||||
ESP_LOGI(TAG, "sending...");
|
||||
uint8_t data[] = {1, 2, 3, 4, 0b10101 /* 21 */, 0b01010 /* 10 */};
|
||||
uint8_t data[] = {1, 1, 1, 2, 3, 4, 0b10101 /* 21 */, 0b01010 /* 10 */};
|
||||
xStreamBufferSend(softuart.tx_buffer, &data, sizeof(data), pdMS_TO_TICKS(1000));
|
||||
for (int t = 0; t < 20; t++)
|
||||
{
|
||||
|
@ -57,23 +58,67 @@ void softuart_test()
|
|||
}
|
||||
}
|
||||
|
||||
void rmtuart_test()
|
||||
#include <string.h>
|
||||
void unicode_test()
|
||||
{
|
||||
baudot_context_t ctx = {0, 0, 0};
|
||||
uint8_t baudot[] = {0x03 /* a */, 0x19 /* b */, 0x0e /* c */, 0x1b /* fig */, 0x1a /* ę */, 0x0d /* ą */, 0x14 /* ł */, 0x1f /* letters */};
|
||||
uint8_t unicode[64] = {};
|
||||
uint8_t baudot2[64] = {};
|
||||
char *unicode2 = "zażółć gęślą jaźń ZAŻÓŁĆ GĘŚLĄ JAŹŃ";
|
||||
ESP_LOGI(TAG, "Converting baudot...");
|
||||
int baudot_len = unicode_to_baudot(&ctx, (uint8_t *)unicode2, strlen(unicode2), baudot2, sizeof(baudot2));
|
||||
ESP_LOGI(TAG, "Got baudot: %d", (int)baudot_len);
|
||||
}
|
||||
|
||||
void rmtuart_echo_test()
|
||||
{
|
||||
rmtuart_start(&rmtuart);
|
||||
while (true)
|
||||
{
|
||||
ESP_LOGI(TAG, "Done");
|
||||
for (int i = 0; i < 1; i++)
|
||||
{
|
||||
rmtuart_transmit_word(&rmtuart, 1);
|
||||
// rmtuart_transmit_word(&rmtuart, 2);
|
||||
// rmtuart_transmit_word(&rmtuart, 3);
|
||||
// rmtuart_transmit_word(&rmtuart, 4);
|
||||
// rmtuart_transmit_word(&rmtuart, 0b10101);
|
||||
// rmtuart_transmit_word(&rmtuart, 0b01010);
|
||||
xStreamBufferReset(rmtuart.tx_buffer);
|
||||
xStreamBufferReset(rmtuart.rx_buffer);
|
||||
|
||||
uint8_t tx_data[] = {1, 2, 3, 4, 5, 0b10000, 0b10001, 0b10101, 0b11111};
|
||||
int tx_size = sizeof(tx_data);
|
||||
xStreamBufferSend(rmtuart.tx_buffer, &tx_data, tx_size, pdMS_TO_TICKS(1000));
|
||||
ESP_LOGI(TAG, "%d bytes sent", sizeof(tx_data));
|
||||
|
||||
uint8_t rx_data[sizeof(tx_data) * 2] = {};
|
||||
uint8_t *rx_ptr = rx_data;
|
||||
int chunklen = 0;
|
||||
int rx_size = 0;
|
||||
while ((chunklen = xStreamBufferReceive(rmtuart.rx_buffer, rx_ptr, sizeof(rx_data) - rx_size, pdMS_TO_TICKS(rx_size < tx_size ? 5000 : 500))) > 0 && sizeof(rx_data) - rx_size > 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "%d/%d bytes received (%02x)", chunklen, rx_size, rx_data[rx_size]);
|
||||
rx_size += chunklen;
|
||||
rx_ptr += chunklen;
|
||||
}
|
||||
ESP_LOGI(TAG, "Receive finished, got %d bytes", rx_size);
|
||||
|
||||
if (rx_size != tx_size)
|
||||
{
|
||||
ESP_LOGE(TAG, "Invalid receive size");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < sizeof(tx_data); i++)
|
||||
{
|
||||
if (tx_data[i] != rx_data[i])
|
||||
{
|
||||
ESP_LOGW(TAG, "Byte %d difference: %02x vs %02x", i, tx_data[i], rx_data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Done");
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
// unicode_test();
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,10 @@ static void tcp_server_task(network_ctx_t *ctx)
|
|||
ESP_LOGI(TAG, "Sending %d bytes", read_buffer_len);
|
||||
uint8_t tx_baudot_data[64] = {0};
|
||||
size_t tx_baudot_data_len = unicode_to_baudot(&unicode_ctx, read_buffer, read_buffer_len, tx_baudot_data, sizeof(tx_baudot_data));
|
||||
xStreamBufferSend(ctx->tx_buffer, &tx_baudot_data, tx_baudot_data_len, pdMS_TO_TICKS(1000));
|
||||
if (tx_baudot_data_len > 0)
|
||||
{
|
||||
xStreamBufferSend(ctx->tx_buffer, &tx_baudot_data, tx_baudot_data_len, pdMS_TO_TICKS(1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
166
src/rmtuart.c
166
src/rmtuart.c
|
@ -8,7 +8,8 @@
|
|||
//
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_timer.h"
|
||||
#include "rmtuart.h"
|
||||
|
||||
static const char *TAG = "rmtuart";
|
||||
|
@ -145,7 +146,7 @@ void rmtuart_transmit_word(rmtuart_ctx_t *ctx, uint32_t word)
|
|||
.loop_count = 0, // no transfer loop
|
||||
};
|
||||
|
||||
uint16_t bit_ticks = ctx->resolution_hz / ctx->baudrate;
|
||||
uint16_t bit_ticks = ctx->resolution_hz / ctx->baudrate;
|
||||
|
||||
int data_len = 1;
|
||||
uint16_t data[16] = {
|
||||
|
@ -172,6 +173,81 @@ void rmtuart_transmit_word(rmtuart_ctx_t *ctx, uint32_t word)
|
|||
ESP_ERROR_CHECK(rmt_tx_wait_all_done(ctx->tx_chan, portMAX_DELAY));
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int64_t ts;
|
||||
uint8_t level;
|
||||
} gpio_status_t;
|
||||
|
||||
static void IRAM_ATTR gpio_isr_handler(rmtuart_ctx_t *ctx)
|
||||
{
|
||||
/*gpio_status_t gpio_evt = {
|
||||
esp_timer_get_time(),
|
||||
gpio_get_level(ctx->rx_gpio),
|
||||
};*/
|
||||
|
||||
// xQueueSendFromISR(ctx->gpio_evt_queue, &gpio_evt, NULL);
|
||||
if (gpio_get_level(ctx->rx_gpio) == 1 && ctx->bit_cnt == 0)
|
||||
{
|
||||
ctx->bit_cnt = 1;
|
||||
ctx->buf = 0;
|
||||
esp_timer_start_once(ctx->rx_bit_timer, 1.5 * (1000000 / ctx->baudrate));
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_bit_callback(rmtuart_ctx_t *ctx)
|
||||
{
|
||||
|
||||
if (ctx->bit_cnt <= ctx->data_bits)
|
||||
{
|
||||
ctx->buf = ctx->buf | (!gpio_get_level(ctx->rx_gpio)) << (ctx->bit_cnt - 1);
|
||||
}
|
||||
|
||||
if (ctx->bit_cnt <= ctx->data_bits)
|
||||
{
|
||||
ctx->bit_cnt += 1;
|
||||
esp_timer_start_once(ctx->rx_bit_timer, (1000000 / ctx->baudrate));
|
||||
}
|
||||
else
|
||||
{
|
||||
// uint8_t buf[32] = {ctx->buf};
|
||||
// int res = xStreamBufferSendFromISR(ctx->rx_buffer, &ctx->buf, 1, 0);
|
||||
gpio_status_t gpio_evt = {
|
||||
0,
|
||||
ctx->buf,
|
||||
};
|
||||
|
||||
xQueueSendFromISR(ctx->gpio_evt_queue, &gpio_evt, NULL);
|
||||
// int byte = ctx->buf;
|
||||
|
||||
// ctx->buf = 0;
|
||||
ctx->bit_cnt = 0;
|
||||
|
||||
// ... push byte
|
||||
}
|
||||
}
|
||||
|
||||
void gpiouart_receive_words(rmtuart_ctx_t *ctx)
|
||||
{
|
||||
int64_t last_ts = 0;
|
||||
while (true)
|
||||
{
|
||||
|
||||
gpio_status_t evt;
|
||||
if (xQueueReceive(ctx->gpio_evt_queue, &evt, pdMS_TO_TICKS(1000)))
|
||||
{
|
||||
ESP_LOGI(TAG, "%lld@%d", evt.ts, evt.level);
|
||||
uint8_t payload[32] = {evt.level};
|
||||
int res = xStreamBufferSend(ctx->rx_buffer, &payload, 1, pdMS_TO_TICKS(100));
|
||||
last_ts = evt.ts;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rmtuart_start(rmtuart_ctx_t *ctx)
|
||||
{
|
||||
// NOTE: these values may need to be adjusted if baudrate != 50
|
||||
|
@ -186,41 +262,71 @@ void rmtuart_start(rmtuart_ctx_t *ctx)
|
|||
{
|
||||
if (ctx->rx_mode == RX_MODE_RMT)
|
||||
{
|
||||
ESP_LOGI(TAG, "Create RMT RX channel");
|
||||
rmt_rx_channel_config_t rx_channel_cfg = {
|
||||
.clk_src = ctx->clk_src,
|
||||
.resolution_hz = ctx->resolution_hz,
|
||||
.mem_block_symbols = 64,
|
||||
.gpio_num = ctx->rx_gpio,
|
||||
};
|
||||
ESP_LOGI(TAG, "Create RMT RX channel");
|
||||
rmt_rx_channel_config_t rx_channel_cfg = {
|
||||
.clk_src = ctx->clk_src,
|
||||
.resolution_hz = ctx->resolution_hz,
|
||||
.mem_block_symbols = 64,
|
||||
.gpio_num = ctx->rx_gpio,
|
||||
};
|
||||
|
||||
ctx->receive_queue = xQueueCreate(1, sizeof(rmt_rx_done_event_data_t));
|
||||
ESP_ERROR_CHECK(rmt_new_rx_channel(&rx_channel_cfg, &ctx->rx_chan));
|
||||
ctx->receive_queue = xQueueCreate(1, sizeof(rmt_rx_done_event_data_t));
|
||||
ESP_ERROR_CHECK(rmt_new_rx_channel(&rx_channel_cfg, &ctx->rx_chan));
|
||||
|
||||
rmt_rx_event_callbacks_t cbs = {
|
||||
.on_recv_done = rmt_rx_done_callback,
|
||||
};
|
||||
ESP_ERROR_CHECK(rmt_rx_register_event_callbacks(ctx->rx_chan, &cbs, ctx->receive_queue));
|
||||
ESP_ERROR_CHECK(rmt_enable(ctx->rx_chan));
|
||||
rmt_rx_event_callbacks_t cbs = {
|
||||
.on_recv_done = rmt_rx_done_callback,
|
||||
};
|
||||
ESP_ERROR_CHECK(rmt_rx_register_event_callbacks(ctx->rx_chan, &cbs, ctx->receive_queue));
|
||||
ESP_ERROR_CHECK(rmt_enable(ctx->rx_chan));
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->gpio_evt_queue = xQueueCreate(10, sizeof(gpio_status_t));
|
||||
|
||||
ctx->bit_cnt = 0;
|
||||
ctx->buf = 0;
|
||||
|
||||
ESP_LOGI(TAG, "Create GPIO RX channel");
|
||||
gpio_config_t io_conf = {};
|
||||
io_conf.intr_type = GPIO_INTR_ANYEDGE;
|
||||
io_conf.pin_bit_mask = 1 << ctx->rx_gpio;
|
||||
io_conf.mode = GPIO_MODE_INPUT;
|
||||
io_conf.pull_down_en = 0;
|
||||
io_conf.pull_up_en = 0;
|
||||
gpio_config(&io_conf);
|
||||
|
||||
// install gpio isr service
|
||||
gpio_install_isr_service(0);
|
||||
// hook isr handler for specific gpio pin
|
||||
gpio_isr_handler_add(ctx->rx_gpio, (gpio_isr_t)gpio_isr_handler, (void *)ctx);
|
||||
|
||||
const esp_timer_create_args_t rx_bit_timer_config = {
|
||||
.callback = &gpio_bit_callback,
|
||||
.arg = ctx,
|
||||
/* argument specified here will be passed to timer callback function */
|
||||
.name = "gpio_rx_gpio",
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_timer_create(&rx_bit_timer_config, &ctx->rx_bit_timer));
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->tx_gpio >= 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Create RMT TX channel");
|
||||
rmt_tx_channel_config_t tx_chan_config = {
|
||||
ESP_LOGI(TAG, "Create RMT TX channel");
|
||||
rmt_tx_channel_config_t tx_chan_config = {
|
||||
.clk_src = ctx->clk_src,
|
||||
.resolution_hz = ctx->resolution_hz,
|
||||
.resolution_hz = ctx->resolution_hz,
|
||||
|
||||
.gpio_num = ctx->tx_gpio,
|
||||
.mem_block_symbols = 64,
|
||||
.trans_queue_depth = 4,
|
||||
};
|
||||
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &ctx->tx_chan));
|
||||
.gpio_num = ctx->tx_gpio,
|
||||
.mem_block_symbols = 64,
|
||||
.trans_queue_depth = 4,
|
||||
};
|
||||
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &ctx->tx_chan));
|
||||
|
||||
rmt_copy_encoder_config_t encoder_config = {};
|
||||
ESP_ERROR_CHECK(rmt_new_copy_encoder(&encoder_config, &ctx->copy_encoder));
|
||||
ESP_ERROR_CHECK(rmt_enable(ctx->tx_chan));
|
||||
rmt_copy_encoder_config_t encoder_config = {};
|
||||
ESP_ERROR_CHECK(rmt_new_copy_encoder(&encoder_config, &ctx->copy_encoder));
|
||||
ESP_ERROR_CHECK(rmt_enable(ctx->tx_chan));
|
||||
}
|
||||
|
||||
if (ctx->rx_gpio >= 0)
|
||||
|
@ -229,11 +335,15 @@ void rmtuart_start(rmtuart_ctx_t *ctx)
|
|||
{
|
||||
xTaskCreate((TaskFunction_t)rmtuart_receive_words, "rmtuart_receive_words", 4096, ctx, 40, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
xTaskCreate((TaskFunction_t)gpiouart_receive_words, "gpiouart_receive_words", 4096, ctx, 40, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->tx_gpio >= 0)
|
||||
{
|
||||
xTaskCreate((TaskFunction_t)rmtuart_transmit_words, "rmtuart_transmit_words", 2048, ctx, 40, NULL);
|
||||
xTaskCreate((TaskFunction_t)rmtuart_transmit_words, "rmtuart_transmit_words", 2048, ctx, 40, NULL);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Init finished");
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/stream_buffer.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "driver/rmt_tx.h"
|
||||
#include "driver/rmt_rx.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -24,6 +26,7 @@ typedef struct
|
|||
|
||||
StreamBufferHandle_t rx_buffer;
|
||||
StreamBufferHandle_t tx_buffer;
|
||||
QueueHandle_t gpio_evt_queue;
|
||||
|
||||
rmt_clock_source_t clk_src;
|
||||
int resolution_hz;
|
||||
|
@ -33,6 +36,10 @@ typedef struct
|
|||
rmt_encoder_handle_t copy_encoder;
|
||||
|
||||
QueueHandle_t receive_queue;
|
||||
|
||||
int bit_cnt;
|
||||
uint8_t buf;
|
||||
esp_timer_handle_t rx_bit_timer;
|
||||
} rmtuart_ctx_t;
|
||||
|
||||
void rmtuart_start(rmtuart_ctx_t *ctx);
|
||||
|
|
Loading…
Reference in a new issue