diff --git a/configure.ac b/configure.ac index 81c3c3b..f09cec0 100644 --- a/configure.ac +++ b/configure.ac @@ -19,6 +19,7 @@ AC_CONFIG_SUBDIRS([examples/0blink]) AC_CONFIG_SUBDIRS([examples/0hello]) AC_CONFIG_SUBDIRS([examples/0ledctrl]) AC_CONFIG_SUBDIRS([examples/1rmtblink]) +AC_CONFIG_SUBDIRS([examples/1rmtdht]) AC_CONFIG_SUBDIRS([examples/1rmtmorse]) AC_CONFIG_SUBDIRS([examples/1rmtmusic]) AC_CONFIG_SUBDIRS([examples/1rmtws2812]) @@ -35,6 +36,7 @@ AC_CONFIG_FILES([ examples/0hello/Makefile examples/0ledctrl/Makefile examples/1rmtblink/Makefile + examples/1rmtdht/Makefile examples/1rmtmorse/Makefile examples/1rmtmusic/Makefile examples/1rmtws2812/Makefile diff --git a/examples/1rmtdht/Makefile.am b/examples/1rmtdht/Makefile.am new file mode 100644 index 0000000..f8424be --- /dev/null +++ b/examples/1rmtdht/Makefile.am @@ -0,0 +1,37 @@ +include $(top_srcdir)/scripts/elf2bin.mk +include $(top_srcdir)/ld/flags.mk + +noinst_HEADERS = defines.h + +AM_CFLAGS = -std=c11 -flto + +if WITH_BINARIES +AM_LDFLAGS += \ + -T $(top_srcdir)/ld/esp32.rom.ld \ + -T $(top_srcdir)/ld/esp32.rom.libgcc.ld \ + -T $(top_srcdir)/ld/esp32.rom.newlib-data.ld \ + -T $(top_srcdir)/ld/esp32.rom.newlib-locale.ld \ + -T $(top_srcdir)/ld/esp32.rom.newlib-nano.ld \ + -T $(top_srcdir)/ld/esp32.rom.newlib-time.ld \ + -T $(top_srcdir)/ld/esp32.rom.redefined.ld \ + -T $(top_srcdir)/ld/esp32.rom.syscalls.ld +else +AM_LDFLAGS += \ + -T $(top_srcdir)/ld/esp32.rom.ld \ + -T $(top_srcdir)/ld/esp32.rom.libgcc.ld \ + -T $(top_srcdir)/ld/esp32.rom.redefined.ld \ + -T $(top_srcdir)/ld/esp32.rom.syscalls.ld +endif + +AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/modules +LDADD = $(top_builddir)/src/libesp32basic.a $(top_builddir)/modules/libesp32modules.a + +bin_PROGRAMS = \ + rmtdht.elf + +if WITH_BINARIES +CLEANFILES = \ + rmtdht.bin +endif + +BUILT_SOURCES = $(CLEANFILES) diff --git a/examples/1rmtdht/README.md b/examples/1rmtdht/README.md new file mode 100644 index 0000000..2c23cc0 --- /dev/null +++ b/examples/1rmtdht/README.md @@ -0,0 +1,21 @@ +### DHT22 sensor sampling example + +In this example we periodically read sensor data (temperature and rel. humidity) +from DHT22 external device. +Special 1-wire protocol is used when communicating to DHT22. +The 1-wire protocol is implemented in `modules/dht22.c`. + +#### Hardware components + +* S1: DHT22 temp/hum sensor + +#### Connections + +``` +ESP32.GPIO2 -- S1.OUT +ESP32.GND -- S1.- +ESP32.VCC -- S1.+ +``` + +#### Practices + diff --git a/examples/1rmtdht/defines.h b/examples/1rmtdht/defines.h new file mode 100644 index 0000000..a767e29 --- /dev/null +++ b/examples/1rmtdht/defines.h @@ -0,0 +1,39 @@ +/* + * Copyright 2024 SZIGETI János + * + * This file is part of Bilis ESP32 Basic, which is released under GNU General Public License.version 3. + * See LICENSE or for full license details. + */ +#ifndef DEFINES_H +#define DEFINES_H + +#ifdef __cplusplus +extern "C" { +#endif + + // TIMINGS + // const -- do not change this value +#define APB_FREQ_HZ 80000000U // 80 MHz + + // variables +#define TIM0_0_DIVISOR 2U +#define START_APP_CPU 0U +#define SCHEDULE_FREQ_HZ 1000U // 1KHz + + // derived invariants +#define CLK_FREQ_HZ (APB_FREQ_HZ / TIM0_0_DIVISOR) // 40 MHz +#define TICKS_PER_MS (CLK_FREQ_HZ / 1000U) // 40000 +#define TICKS_PER_US (CLK_FREQ_HZ / 1000000U) // 40 +#define NS_PER_TICKS (1000000000 / CLK_FREQ_HZ) + +#define TICKS2NS(X) ((X) * NS_PER_TICKS) +#define TICKS2US(X) ((X) / TICKS_PER_US) +#define MS2TICKS(X) ((X) * TICKS_PER_MS) +#define HZ2APBTICKS(X) (APB_FREQ_HZ / (X)) + +#ifdef __cplusplus +} +#endif + +#endif /* DEFINES_H */ + diff --git a/examples/1rmtdht/rmtdht.c b/examples/1rmtdht/rmtdht.c new file mode 100644 index 0000000..c6773c4 --- /dev/null +++ b/examples/1rmtdht/rmtdht.c @@ -0,0 +1,109 @@ +/* + * Copyright 2024 SZIGETI János + * + * This file is part of Bilis ESP32 Basic, which is released under GNU General Public License.version 3. + * See LICENSE or for full license details. + */ +#include +#include +#include +#include +#include + +#include "dht22.h" +#include "gpio.h" +#include "main.h" +#include "rmt.h" +#include "defines.h" +#include "romfunctions.h" +#include "iomux.h" +#include "dport.h" +#include "timg.h" +#include "utils/uartutils.h" + +// =================== Hard constants ================= +// #1: Timings +#define RMTDHT_PERIOD_MS 2000U ///< Higher than 8 * 0.2s, so RMT blinks will not overlap. + +// #2: Channels / wires / addresses +#define RMTDHT_GPIO 21U +#define RMTDHT_CH RMT_CH0 +#define RMTINT_CH 23U + +// ============= Local types =============== + +// ================ Local function declarations ================= +static void _rmtdht_init(); +static void _rmtdht_cycle(uint64_t u64Ticks); + +// =================== Global constants ================ +const bool gbStartAppCpu = START_APP_CPU; +const uint16_t gu16Tim00Divisor = TIM0_0_DIVISOR; +const uint64_t gu64tckSchedulePeriod = (CLK_FREQ_HZ / SCHEDULE_FREQ_HZ); + +// ==================== Local Data ================ +static SDht22Descriptor gsDht22Desc; + +// ==================== Implementation ================ + +void _done_rx(void *pvParam, SDht22Data *psParam) { + uart_printf(&gsUART0, "INVALID: %02X %02X %02X %02X %02X\n", + psParam->au8Invalid[0], + psParam->au8Invalid[1], + psParam->au8Invalid[2], + psParam->au8Invalid[3], + psParam->au8Invalid[4] + ); + uart_printf(&gsUART0, "DATA: %02X %02X %02X %02X %02X\n", + psParam->au8Data[0], + psParam->au8Data[1], + psParam->au8Data[2], + psParam->au8Data[3], + psParam->au8Data[4] + ); + uart_printf(&gsUART0, "raw data (%c) T: %d, RH: %u\n", + dht22_data_valid(psParam) ? '+' : '-', + dht22_get_temp(psParam), + dht22_get_rhum(psParam) + ); +} + +static void _rmtdht_init() { + rmt_isr_init(); + rmt_init_controller(true, true); + gsDht22Desc = dht22_config(RMTDHT_CH, _done_rx, NULL); + dht22_init(RMTDHT_GPIO, APB_FREQ_HZ, &gsDht22Desc); + + rmt_isr_start(CPU_PRO, RMTINT_CH); +} + +static void _rmtdht_cycle(uint64_t u64Ticks) { + static uint64_t u64NextTick = 0; + + if (u64NextTick <= u64Ticks) { + dht22_run(&gsDht22Desc); + + u64NextTick += MS2TICKS(RMTDHT_PERIOD_MS); + } +} + +// ====================== Interface functions ========================= + +void prog_init_pro_pre() { + gsUART0.CLKDIV = APB_FREQ_HZ / 115200; + + _rmtdht_init(); +} + +void prog_init_app() { +} + +void prog_init_pro_post() { +} + +void prog_cycle_app(uint64_t u64tckNow) { +} + +void prog_cycle_pro(uint64_t u64tckNow) { + _rmtdht_cycle(u64tckNow); +} diff --git a/examples/Makefile.am b/examples/Makefile.am index 7c3e446..2d3ccfd 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,2 +1,2 @@ AUTOMAKE_OPTIONS = -SUBDIRS=0blink 0button 0hello 0ledctrl 1rmtblink 1rmtmorse 1rmtmusic 3prog1 1rmtws2812 +SUBDIRS=0blink 0button 0hello 0ledctrl 1rmtblink 1rmtdht 1rmtmorse 1rmtmusic 3prog1 1rmtws2812 diff --git a/modules/Makefile.am b/modules/Makefile.am index 0e3cba3..8556471 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -5,10 +5,10 @@ libesp32modules_a_AR=$(AR) rcs lib_LIBRARIES = libesp32modules.a -include_HEADERS = bh1750.h bme280.h ws2812.h +include_HEADERS = bh1750.h bme280.h dht22.h ws2812.h nodist_include_HEADERS = -libesp32modules_a_SOURCES = bh1750.c bme280.c ws2812.c +libesp32modules_a_SOURCES = bh1750.c bme280.c dht22.c ws2812.c nodist_libesp32modules_a_SOURCES = CLEANFILES = diff --git a/modules/dht22.c b/modules/dht22.c new file mode 100644 index 0000000..375b342 --- /dev/null +++ b/modules/dht22.c @@ -0,0 +1,186 @@ +/* + * Copyright 2025 SZIGETI János + * + * This file is part of Bilis ESP32 Basic, which is released under GNU General Public License.version 3. + * See LICENSE or for full license details. + */ + +#include +#include + +#include "dht22.h" +#include "rmt.h" + +#define DHT_HOSTPULLDOWN_IVAL_US 1100U ///< The communication begins with host sending out signal 0 for 1.1 ms. + +// measured: [70..73] and [23..27] +#define DHT_BIT1_IVAL_LO_US 68 +#define DHT_BIT1_IVAL_HI_US 75 +#define DHT_BIT0_IVAL_LO_US 22 +#define DHT_BIT0_IVAL_HI_US 29 + +#define DHT22_IDLE_US 90 ///< If the input signal is constant 0 or 1 for more than 90 µs, the RX process is done. + +#define RMT_FREQ_KHZ 1000U ///< 1MHz -- clk: 1µs +#define RMT_CLK_NS (1000000 / RMT_FREQ_KHZ) +#if (1000 == RMT_FREQ_KHZ) +#define US_TO_RMTCLK(X) (X) +#define RMTCLK_TO_US(X) (X) +#else +#define US_TO_RMTCLK(X) (((X) * RMT_FREQ_KHZ) / 1000) +#define RMTCLK_TO_US(X) (((X) * 1000) / RMT_FREQ_KHZ) +#endif +#define RMTDHT_FILTER_THRES 50U ///< RMT filters out spikes shorter than that many APB clocks. + +// ================ Local function declarations ================= +static inline bool _u16ltz(uint16_t u16Value); +static inline int16_t _u16abs(uint16_t u16Value); +static inline int16_t _u16toi16(uint16_t u16Value); +static void _rmt_config_channel(const ERmtChannel eChannel, uint8_t u8Divisor); +static void _rxstart(void *pvParam); +static void _rxready(void *pvParam); +// =================== Global constants ================ + +// ==================== Local Data ================ + +// ==================== Implementation ================ +static inline bool _u16ltz(uint16_t u16Value) { + return (u16Value & (1 << 15)); +} + +static inline int16_t _u16abs(uint16_t u16Value) { + return (u16Value & 0x7fff); +} + +static inline int16_t _u16toi16(uint16_t u16Value) { + return _u16ltz(u16Value) ? + -_u16abs(u16Value) : + u16Value; +} + +static void _rmt_config_channel(ERmtChannel eChannel, uint8_t u8Divisor) { + // rmt channel config + SRmtChConf rChConf = { + .r0 = + {.u8DivCnt = u8Divisor, .u4MemSize = 1, + .u16IdleThres = US_TO_RMTCLK(DHT22_IDLE_US)}, + .r1 = + {.bRefAlwaysOn = 1, .bRefCntRst = 1, .bMemRdRst = 1, + .bIdleOutLvl = 1, .bIdleOutEn = 1, + .bRxFilterEn = 1, .u8RxFilterThres = RMTDHT_FILTER_THRES} + }; + gpsRMT->asChConf[eChannel] = rChConf; + + gpsRMT->arTxLim[eChannel].u9Val = 256; // currently unused +} + +static void _rxstart(void *pvParam) { + SDht22Descriptor *psParam = (SDht22Descriptor*)pvParam; + rmt_start_rx(psParam->eChannel, 1); + +} + +static void _rxready(void *pvParam) { + SDht22Descriptor *psParam = (SDht22Descriptor*)pvParam; + + RegAddr prData = rmt_ram_addr(psParam->eChannel, 1, 0); + uint32_t u32RecvSize = gpsRMT->asStatus[psParam->eChannel].u9RxIdx; + uint32_t u32DataOfs = u32RecvSize - (DHT22_DATA_LEN * 8) - 1; + bool bLowEnd = (prData[u32RecvSize - 1] & RMT_ENTRYMAX) == 0; + uint8_t u8Shr = bLowEnd ? 0 : 16; + + memset(&psParam->sData, 0, sizeof (psParam->sData)); + + for (int i = 0; i < (DHT22_DATA_LEN * 8); ++i) { + int iByte = i / 8; + int iBit = 7 - (i % 8); + uint32_t u32Dat = (prData[u32DataOfs + i]) >> u8Shr; + bool bLevel0 = (0 != (u32Dat & RMT_SIGNAL1)); + uint16_t u16Duration0 = RMTCLK_TO_US(u32Dat & RMT_ENTRYMAX); + bool bValid = bLevel0; + bool bValue = false; + if (DHT_BIT0_IVAL_LO_US <= u16Duration0 && u16Duration0 <= DHT_BIT0_IVAL_HI_US) { + bValue = false; + } else if (DHT_BIT1_IVAL_LO_US <= u16Duration0 && u16Duration0 <= DHT_BIT1_IVAL_HI_US) { + bValue = true; + } else { + bValid = false; + } + if (bValue) + psParam->sData.au8Data[iByte] |= (1 << iBit); + if (!bValid) + psParam->sData.au8Invalid[iByte] |= (1 << iBit); + } + + psParam->fReadyCb(psParam->pvReadyCbParam, &psParam->sData); +} + +// ============== Interface functions ============== + +/** + * Initializes DHT22 communication environment. + * @param u8Pin GPIO pin. + * @param u32ApbClkFreq APB clock frequency. + * @param psDht22Desc DHT22 communication descriptor. + */ +void dht22_init(uint8_t u8Pin, uint32_t u32ApbClkFreq, SDht22Descriptor *psDht22Desc) { + rmt_init_channel(psDht22Desc->eChannel, u8Pin, false); + _rmt_config_channel(psDht22Desc->eChannel, u32ApbClkFreq / (1000 * RMT_FREQ_KHZ)); + rmt_isr_register(psDht22Desc->eChannel, RMT_INT_TXEND, _rxstart, psDht22Desc); + rmt_isr_register(psDht22Desc->eChannel, RMT_INT_RXEND, _rxready, psDht22Desc); +} + +/** + * Starts a DHT22 communication process. + * @param psDht22Desc DHT22 communication descriptor. + */ +void dht22_run(SDht22Descriptor *psDht22Desc) { + static const uint32_t u32Tx0 = (RMT_SIGNAL0 | US_TO_RMTCLK(DHT_HOSTPULLDOWN_IVAL_US)) | (RMT_SIGNAL1 << 16); + + SRmtChConf1Reg sConf1 = {.raw = 0}; + sConf1.bMemOwner = 1; + gsRMT.asChConf[psDht22Desc->eChannel].r1.raw |= sConf1.raw; + + rmt_ram_addr(psDht22Desc->eChannel, 1, 0)[0] = u32Tx0; + + rmt_start_tx(psDht22Desc->eChannel, 1); +} + +/** + * Gets humidity data from received and bit-decoded data. + * @param psData Received bit-decoded data. + * @return Humidity data with 1-digit precision. + */ +uint16_t dht22_get_rhum(const SDht22Data *psData) { + return (psData->au8Data[0] << 8) | psData->au8Data[1]; +} + +/** + * Gets temperature data from received and bit-decoded data. + * @param psData Received bit-decoded data. + * @return Temperature data with 1-digit precision. + */ +int16_t dht22_get_temp(const SDht22Data *psData) { + uint16_t u16T0 = (psData->au8Data[2] << 8) | psData->au8Data[3]; + return _u16toi16(u16T0); +} + +/** + * Tells if the received data is valid. + * @param psData Received bit-decoded data. + * @return The data does not contains any invalid bit and the checksum matches. + */ +bool dht22_data_valid(const SDht22Data *psData) { + bool bAllBitValid = true; + uint8_t u8DataSum = 0; + + for (int i = 0; i < DHT22_DATA_LEN; ++i) { + bAllBitValid &= (psData->au8Invalid[i] == 0); + } + for (int i = 0; i < DHT22_DATA_LEN - 1; ++i) { + u8DataSum += psData->au8Data[i]; + } + bool bCheckSum = (u8DataSum == psData->au8Data[DHT22_DATA_LEN - 1]); + return bAllBitValid && bCheckSum; +} + diff --git a/modules/dht22.h b/modules/dht22.h new file mode 100644 index 0000000..707a856 --- /dev/null +++ b/modules/dht22.h @@ -0,0 +1,75 @@ +/* + * Copyright 2025 SZIGETI János + * + * This file is part of Bilis ESP32 Basic, which is released under GNU General Public License.version 3. + * See LICENSE or for full license details. + */ +#ifndef DHT22_H +#define DHT22_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "rmt.h" + +#define DHT22_DATA_LEN 5 + + // ============= Types =============== + + /** + * This struct contains bit decoded DHT22 data. + * The raw data (signal level and duration) is not stored. + */ + typedef struct { + uint8_t au8Data[DHT22_DATA_LEN]; ///< Stores raw data decoded bit-by-bit from RMT RAM entries. + uint8_t au8Invalid[DHT22_DATA_LEN]; ///< Shows which bits could not be decoded from RMT RAM entries. + } SDht22Data; + + /** + * Function type of the callback that gets invoked, + * when the DHT22 data is received and bit decoded. + * pvParam is Arbitrary data passed to the function, + * whereas psData contains the result of the bit-decoding. + */ + typedef void (*FDht22Callback)(void *pvParam, SDht22Data *psData); + + /** + * Contains data that the interface functions require. + */ + typedef struct { + ERmtChannel eChannel; ///< RMT channel. + FDht22Callback fReadyCb; ///< Callback to invoke when all the data is received and decoded. + void *pvReadyCbParam; ///< First parameter to pass to the callback function. + SDht22Data sData; ///< Store decoded sensor data. + } SDht22Descriptor; + + // ============= Inline functions =============== + + /** + * Creates and initializes SDht22Descriptor instance. + * @param eChannel Identifies the RMT channel. + * @param fReadyCb Callback to invoke when the data is received and decoded. + * @param pvReadyCbParam First parameter to pass to the callback. + * @return Initialized descriptor instance. + */ + static inline SDht22Descriptor dht22_config(ERmtChannel eChannel, FDht22Callback fReadyCb, void *pvReadyCbParam) { + SDht22Descriptor sRet = {.eChannel = eChannel, .fReadyCb = fReadyCb, .pvReadyCbParam = pvReadyCbParam}; + return sRet; + } + + + // ============= Interface function declaration =============== + void dht22_init(uint8_t u8Pin, uint32_t u32ApbClkFreq, SDht22Descriptor *psDht22Desc); + void dht22_run(SDht22Descriptor *psDht22Desc); + uint16_t dht22_get_rhum(const SDht22Data *psData); + int16_t dht22_get_temp(const SDht22Data *psData); + bool dht22_data_valid(const SDht22Data *psData); + + +#ifdef __cplusplus +} +#endif + +#endif /* DHT22_H */ + diff --git a/src/rmt.h b/src/rmt.h index 9aa42ab..810f514 100644 --- a/src/rmt.h +++ b/src/rmt.h @@ -26,18 +26,18 @@ extern "C" { // ============== Types ============== typedef enum { - RMT_INT_RAW = 0, ///< Raw interrupt status (RO) - RMT_INT_ST = 1, ///< Masked interrupt status (RO) - RMT_INT_ENA = 2, ///< Interrupts with active bits are enabled (and shown in masked interrupt status), interrupts with inactive bits are disabled (RW) - RMT_INT_CLR = 3 ///< Setting a bit clears the given interrupt (WO) - } ERmtIntReg; ///< Types of interrupt registers. + RMT_INT_RAW = 0, ///< Raw interrupt status (RO) + RMT_INT_ST = 1, ///< Masked interrupt status (RO) + RMT_INT_ENA = 2, ///< Interrupts with active bits are enabled (and shown in masked interrupt status), interrupts with inactive bits are disabled (RW) + RMT_INT_CLR = 3 ///< Setting a bit clears the given interrupt (WO) + } ERmtIntReg; ///< Types of interrupt registers. typedef enum { - RMT_INT_TXEND = 0, ///< TX is done. - RMT_INT_RXEND = 1, ///< RX is done. - RMT_INT_ERR = 2, ///< An error occured. + RMT_INT_TXEND = 0, ///< TX is done. + RMT_INT_RXEND = 1, ///< RX is done. + RMT_INT_ERR = 2, ///< An error occured. RMT_INT_TXTHRES = 3 ///< TX threshold is reached. - } ERmtIntType; ///< Types of RMT interrupt. + } ERmtIntType; ///< Types of RMT interrupt. typedef enum { RMT_CH0 = 0, @@ -53,14 +53,14 @@ extern "C" { typedef volatile union { volatile struct { - uint32_t u8DivCnt : 8; ///< The divisor for the channel clock of channel n. (R/W) + uint32_t u8DivCnt : 8; ///< The divisor for the channel clock of channel n. (R/W) - uint32_t u16IdleThres : 16; ///< In receive mode, when no edge is detected on the input signal for longer than REG_IDLE_THRES_CHn channel clock cycles, the receive process is finished. (R/W) + uint32_t u16IdleThres : 16; ///< In receive mode, when no edge is detected on the input signal for longer than REG_IDLE_THRES_CHn channel clock cycles, the receive process is finished. (R/W) - uint32_t u4MemSize : 4; ///< The amount of memory blocks allocated to channel n. (R/W) - uint32_t bCarrierEn : 1; ///< Carrier modulation is enabled with 1, while carrier modulation is disabled with 0. (R/W) - uint32_t bCarrierOutLvl : 1; ///< Used when the carrier wave is being transmitted. Transmit on low output level with 0, and transmit on high output level with 1. (R/W) - uint32_t bMemPd : 1; ///< Power down the entire RMT RAM block.Reset (It only exists in RMT_CH0CONF0). 1: power down memory; 0: power up memory. (R/W) + uint32_t u4MemSize : 4; ///< The amount of memory blocks allocated to channel n. (R/W) + uint32_t bCarrierEn : 1; ///< Carrier modulation is enabled with 1, while carrier modulation is disabled with 0. (R/W) + uint32_t bCarrierOutLvl : 1; ///< Used when the carrier wave is being transmitted. Transmit on low output level with 0, and transmit on high output level with 1. (R/W) + uint32_t bMemPd : 1; ///< Power down the entire RMT RAM block.Reset (It only exists in RMT_CH0CONF0). 1: power down memory; 0: power up memory. (R/W) uint32_t rsvd31 : 1; }; volatile uint32_t raw; @@ -69,22 +69,22 @@ extern "C" { typedef volatile union { volatile struct { - uint32_t bTxStart : 1; ///< Set this bit to start sending data on channel n. (R/W) - uint32_t bRxEn : 1; ///< Set this bit to enable receiving data on channel n. (R/W) - uint32_t bMemWrRst : 1; ///< Set this bit to reset the write-RAM address for channel n by accessing the receiver. (R/W) - uint32_t bMemRdRst : 1; ///< Set this bit to reset the read-RAM address for channel n by accessing the transmitter. (R/W) - uint32_t bFifoRst : 1; ///< Undocumented bit. Probably resets FIFO internal counters (R/W). - uint32_t bMemOwner : 1; ///< Number 1 indicates that the receiver is using the RAM, while 0 indicates that the transmitter is using the RAM. (R/W) - uint32_t bTxContiMode : 1; ///< If this bit is set, instead of going to an idle state when transmission ends, the transmitter will restart transmission. This results in a repeating output signal. (R/W) - uint32_t bRxFilterEn : 1; ///< receive filter’s enable-bit for channel n. (R/W) + uint32_t bTxStart : 1; ///< Set this bit to start sending data on channel n. (R/W) + uint32_t bRxEn : 1; ///< Set this bit to enable receiving data on channel n. (R/W) + uint32_t bMemWrRst : 1; ///< Set this bit to reset the write-RAM address for channel n by accessing the receiver. (R/W) + uint32_t bMemRdRst : 1; ///< Set this bit to reset the read-RAM address for channel n by accessing the transmitter. (R/W) + uint32_t bFifoRst : 1; ///< Undocumented bit. Probably resets FIFO internal counters (R/W). + uint32_t bMemOwner : 1; ///< Number 1 indicates that the RX process can write the RAM (R/W). + uint32_t bTxContiMode : 1; ///< If this bit is set, instead of going to an idle state when transmission ends, the transmitter will restart transmission. This results in a repeating output signal. (R/W) + uint32_t bRxFilterEn : 1; ///< receive filter’s enable-bit for channel n. (R/W) uint32_t u8RxFilterThres : 8; ///< In receive mode, channel n ignores input pulse when the pulse width is smaller than this value in APB clock periods. (R/W) - uint32_t bRefCntRst : 1; ///< Setting this bit resets the clock divider of channel n. (R/W) - uint32_t bRefAlwaysOn : 1; ///< Select the channel’s base clock. 1:clk_apb; 0:clk_ref. (R/W) - uint32_t bIdleOutLvl : 1; ///< The level of output signals in channel n when the latter is in IDLE state. (R/W) - uint32_t bIdleOutEn : 1; ///< Output enable-control bit for channel n in IDLE state. (R/W) - uint32_t rsvd20 : 12; ///< Reserved + uint32_t bRefCntRst : 1; ///< Setting this bit resets the clock divider of channel n. (R/W) + uint32_t bRefAlwaysOn : 1; ///< Select the channel’s base clock. 1:clk_apb; 0:clk_ref. (R/W) + uint32_t bIdleOutLvl : 1; ///< The level of output signals in channel n when the latter is in IDLE state. (R/W) + uint32_t bIdleOutEn : 1; ///< Output enable-control bit for channel n in IDLE state. (R/W) + uint32_t rsvd20 : 12; ///< Reserved }; volatile uint32_t raw; } SRmtChConf1Reg; @@ -97,8 +97,8 @@ extern "C" { typedef volatile union { volatile struct { - uint32_t u16Low : 16; ///< If carrier is enabled, this value defines the length of low level in the carrier wave (APB/REF ticks). - uint32_t u16High : 16; ///< If carrier is enabled, this value defines the length of high level in the carrier wave (APB/REF ticks). + uint32_t u16Low : 16; ///< If carrier is enabled, this value defines the length of low level in the carrier wave (APB/REF ticks). + uint32_t u16High : 16; ///< If carrier is enabled, this value defines the length of high level in the carrier wave (APB/REF ticks). }; volatile uint32_t raw; } SRmtChCarrierDutyReg; @@ -106,7 +106,7 @@ extern "C" { typedef union { volatile struct { - uint32_t u9Val : 9; ///< After sending this amount of TX entries, TX_THR_EVENT interrupt is produced. + uint32_t u9Val : 9; ///< After sending this amount of TX entries, TX_THR_EVENT interrupt is produced. uint32_t rsvd9 : 23; }; volatile uint32_t raw; @@ -127,13 +127,14 @@ extern "C" { typedef union { volatile struct { - uint32_t rsvd0 : 12; ///< ??, Probably RX status - uint32_t u9TxIdx : 9; ///< TX mem idx - uint32_t bTxWrapped : 1; ///< TX memory pointer is below the channel's memory block (mem idx offset is -512) + uint32_t u9RxIdx : 9; ///< RX mem idx + uint32_t rsvd9 : 3; ///< ???, probably RX status + uint32_t u9TxIdx : 9; ///< TX mem idx + uint32_t bTxWrapped : 1; ///< TX memory pointer is below the channel's memory block (mem idx offset is -512) uint32_t rsvd22 : 2; - uint32_t bTxState : 1; ///< TX process is ongoing + uint32_t bTxState : 1; ///< TX process is ongoing uint32_t rsvd25 : 7; - }; + } ; volatile uint32_t raw; } SRmtStatusReg;