From 4a3d3228a93622d8a7ab48cf1b0000079a51b208 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 7 Jan 2024 22:22:38 +0100 Subject: [PATCH] ESP32: Use SOC_RMT_MEM_WORDS_PER_CHANNEL to determine if the RMT hardware can handle DCC --- DCCRMT.cpp | 50 +++++++++++++++++++++++++++++++++++--------------- DCCWaveform.h | 8 ++++---- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/DCCRMT.cpp b/DCCRMT.cpp index cbd9af6..afada7b 100644 --- a/DCCRMT.cpp +++ b/DCCRMT.cpp @@ -1,5 +1,5 @@ /* - * © 2021-2022, Harald Barth. + * © 2021-2024, Harald Barth. * * This file is part of DCC-EX * @@ -25,6 +25,18 @@ #include "DCCWaveform.h" // for MAX_PACKET_SIZE #include "soc/gpio_sig_map.h" +// check for right type of ESP32 +#include "soc/soc_caps.h" +#ifndef SOC_RMT_MEM_WORDS_PER_CHANNEL +#error This symobol should be defined +#endif +#if SOC_RMT_MEM_WORDS_PER_CHANNEL < 64 +#warning This is not an ESP32-WROOM but some other unsupported variant +#warning You are outside of the DCC-EX supported hardware +#endif + +static const byte RMT_CHAN_PER_DCC_CHAN = 2; + // Number of bits resulting out of X bytes of DCC payload data // Each byte has one bit extra and at the end we have one EOF marker #define DATA_LEN(X) ((X)*9+1) @@ -75,12 +87,30 @@ void IRAM_ATTR interrupt(rmt_channel_t channel, void *t) { RMTChannel::RMTChannel(pinpair pins, bool isMain) { byte ch; byte plen; + + // Below we check if the DCC packet actually fits into the RMT hardware + // Currently MAX_PACKET_SIZE = 5 so with checksum there are + // MAX_PACKET_SIZE+1 data packets. Each need DATA_LEN (9) bits. + // To that we add the preamble length, the fencepost DCC end bit + // and the RMT EOF marker. + // SOC_RMT_MEM_WORDS_PER_CHANNEL is either 64 (original WROOM) or + // 48 (all other ESP32 like the -C3 or -S2 + // The formula to get the possible MAX_PACKET_SIZE is + // + // ALLOCATED = RMT_CHAN_PER_DCC_CHAN * SOC_RMT_MEM_WORDS_PER_CHANNEL + // MAX_PACKET_SIZE = floor((ALLOCATED - PREAMBLE_LEN - 2)/9 - 1) + // + if (isMain) { ch = 0; plen = PREAMBLE_BITS_MAIN; + static_assert (DATA_LEN(MAX_PACKET_SIZE+1) + PREAMBLE_BITS_MAIN + 2 <= RMT_CHAN_PER_DCC_CHAN * SOC_RMT_MEM_WORDS_PER_CHANNEL, + "Number of DCC packet bits greater than ESP32 RMT memory available"); } else { - ch = 2; + ch = RMT_CHAN_PER_DCC_CHAN; // number == offset plen = PREAMBLE_BITS_PROG; + static_assert (DATA_LEN(MAX_PACKET_SIZE+1) + PREAMBLE_BITS_PROG + 2 <= RMT_CHAN_PER_DCC_CHAN * SOC_RMT_MEM_WORDS_PER_CHANNEL, + "Number of DCC packet bits greater than ESP32 RMT memory available"); } // preamble @@ -115,7 +145,7 @@ RMTChannel::RMTChannel(pinpair pins, bool isMain) { // data: max packet size today is 5 + checksum maxDataLen = DATA_LEN(MAX_PACKET_SIZE+1); // plus checksum data = (rmt_item32_t*)malloc(maxDataLen*sizeof(rmt_item32_t)); - + rmt_config_t config; // Configure the RMT channel for TX bzero(&config, sizeof(rmt_config_t)); @@ -123,20 +153,10 @@ RMTChannel::RMTChannel(pinpair pins, bool isMain) { config.channel = channel = (rmt_channel_t)ch; config.clk_div = RMT_CLOCK_DIVIDER; config.gpio_num = (gpio_num_t)pins.pin; - config.mem_block_num = 2; // With longest DCC packet 11 inc checksum (future expansion) - // number of bits needed is 22preamble + start + - // 11*9 + extrazero + EOT = 124 - // 2 mem block of 64 RMT items should be enough - + config.mem_block_num = RMT_CHAN_PER_DCC_CHAN; + // use config ESP_ERROR_CHECK(rmt_config(&config)); addPin(pins.invpin, true); - /* - // test: config another gpio pin - gpio_num_t gpioNum = (gpio_num_t)(pin-1); - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpioNum], PIN_FUNC_GPIO); - gpio_set_direction(gpioNum, GPIO_MODE_OUTPUT); - gpio_matrix_out(gpioNum, RMT_SIG_OUT0_IDX, 0, 0); - */ // NOTE: ESP_INTR_FLAG_IRAM is *NOT* included in this bitmask ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, ESP_INTR_FLAG_LOWMED|ESP_INTR_FLAG_SHARED)); diff --git a/DCCWaveform.h b/DCCWaveform.h index 2202b53..1392288 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -2,7 +2,7 @@ * © 2021 M Steve Todd * © 2021 Mike S * © 2021 Fred Decker - * © 2020-2021 Harald Barth + * © 2020-2024 Harald Barth * © 2020-2021 Chris Harlow * All rights reserved. * @@ -33,9 +33,9 @@ // Number of preamble bits. -const int PREAMBLE_BITS_MAIN = 16; -const int PREAMBLE_BITS_PROG = 22; -const byte MAX_PACKET_SIZE = 5; // NMRA standard extended packets, payload size WITHOUT checksum. +const byte PREAMBLE_BITS_MAIN = 16; +const byte PREAMBLE_BITS_PROG = 22; +const byte MAX_PACKET_SIZE = 5; // NMRA standard extended packets, payload size WITHOUT checksum. // The WAVE_STATE enum is deliberately numbered because a change of order would be catastrophic