ESPixelStick Firmware
Firmware for the ESPixelStick
Loading...
Searching...
No Matches
OutputUart.hpp
Go to the documentation of this file.
1#pragma once
2/*
3 * OutputUart.hpp - Uart driver code for ESPixelStick Uart Channel
4 *
5 * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver
6 * Copyright (c) 2015 Shelby Merrick
7 * http://www.forkineye.com
8 *
9 * This program is provided free for you to use in any way that you wish,
10 * subject to the laws and regulations where you are using it. Due diligence
11 * is strongly suggested before using this code. Please give credit where due.
12 *
13 * The Author makes no warranty of any kind, express or implied, with regard
14 * to this program or the documentation contained in this document. The
15 * Author shall not be liable in any event for incidental or consequential
16 * damages in connection with, or arising out of, the furnishing, performance
17 * or use of these programs.
18 *
19 */
20
21#include "ESPixelStick.h"
22#if defined(SUPPORT_UART)
23
24#if defined(ARDUINO_ARCH_ESP32)
25# include <soc/uart_reg.h>
26# include <driver/uart.h>
27# include <driver/gpio.h>
28#endif
29
30#include "OutputPixel.hpp"
31#include "OutputSerial.hpp"
32
33class c_OutputUart
34{
35public:
36 enum UartDatauint32_t
37 {
38 OUTPUT_UART_5N1 = 0,
39 OUTPUT_UART_5N2,
40 OUTPUT_UART_6N1,
41 OUTPUT_UART_6N2,
42 OUTPUT_UART_7N1,
43 OUTPUT_UART_7N2,
44 OUTPUT_UART_8N1,
45 OUTPUT_UART_8N2,
46 };
47
48// TX FIFO trigger level. WS2811 40 bytes gives 100us before the FIFO goes empty
49// We need to fill the FIFO at a rate faster than 0.3us per byte (1.2us/pixel)
50#define DEFAULT_UART_FIFO_TRIGGER_LEVEL (17)
51
52 enum TranslateIntensityData_t
53 {
54 NoTranslation = 0,
55 OneToOne,
56 TwoToOne,
57 };
58
59 enum UartDataBitTranslationId_t
60 {
61 Uart_DATA_BIT_00_ID = 0,
62 Uart_DATA_BIT_01_ID,
63 Uart_DATA_BIT_10_ID,
64 Uart_DATA_BIT_11_ID,
65 Uart_LIST_END,
66 Uart_INVALID_VALUE,
67 Uart_NUM_BIT_TYPES = Uart_LIST_END,
68 };
69
70 struct ConvertIntensityToUartDataStreamEntry_t
71 {
72 uint8_t Translation;
73 c_OutputUart::UartDataBitTranslationId_t Id;
74 };
75 typedef ConvertIntensityToUartDataStreamEntry_t CitudsArray_t;
76
77 struct OutputUartConfig_t
78 {
79 OM_PortId_t OutputPortId = OM_PortId_t(-1);
80 gpio_num_t DataPin = gpio_num_t(-1);
81 uart_port_t UartId = uart_port_t(-1);
82 uint32_t IntensityDataWidth = 8; // 8 bits in a byte
83 UartDatauint32_t UartDataSize = UartDatauint32_t::OUTPUT_UART_8N2;
84 uint32_t FrameStartBreakUS = 0;
85 uint32_t FrameStartMarkAfterBreakUS = 0;
86 TranslateIntensityData_t TranslateIntensityData = TranslateIntensityData_t::NoTranslation;
87 bool InvertOutputPolarity = false;
88 uint32_t Baudrate = 57600; // current transmit rate
89 c_OutputPixel *pPixelDataSource = nullptr;
90 uint32_t FiFoTriggerLevel = DEFAULT_UART_FIFO_TRIGGER_LEVEL;
91 uint16_t NumInterIntensityBreakBits = 0;
92 uint16_t NumInterIntensityMABbits = 0;
93 bool TriggerIsrExternally = false;
94 const CitudsArray_t *CitudsArray = nullptr;
95
96 #if defined(SUPPORT_OutputProtocol_FireGod) || defined(SUPPORT_OutputProtocol_DMX) || defined(SUPPORT_OutputProtocol_Serial) || defined(SUPPORT_OutputProtocol_Renard)
97 c_OutputSerial *pSerialDataSource = nullptr;
98 #endif // defined(SUPPORT_OutputProtocol_FireGod) || defined(SUPPORT_OutputProtocol_DMX) || defined(SUPPORT_OutputProtocol_Serial) || defined(SUPPORT_OutputProtocol_Renard)
99 };
100
101 c_OutputUart ();
102 virtual ~c_OutputUart ();
103 void Begin (c_OutputUart::OutputUartConfig_t & config);
104 bool SetConfig (ArduinoJson::JsonObject &jsonConfig);
105 void GetConfig (ArduinoJson::JsonObject &jsonConfig);
106 void GetDriverName (String &sDriverName) { sDriverName = CN_OutputUart; }
107 void GetStatus (ArduinoJson::JsonObject &jsonStatus);
108 void PauseOutput (bool State);
109 void StartNewFrame ();
110
111 void ISR_UART_Handler();
112 void ISR_Handler_SendIntensityData();
113
114private:
115 void StartUart ();
116 bool RegisterUartIsrHandler ();
117 void InitializeUart ();
118 void set_pin ();
119 void TerminateSerialPortOperation ();
120 void RestoreSerialPortOperation ();
121 void ISR_ReportNewFrame ();
122 void StartBreak ();
123 void EndBreak ();
124 void GenerateBreak (uint32_t DurationInUs, uint32_t MarkDurationInUs);
125 void SetIntensityDataWidth ();
126 void SetIntensity2Uart (uint8_t value, UartDataBitTranslationId_t ID);
127
128 OutputUartConfig_t OutputUartConfig;
129
130 uint8_t Intensity2Uart[UartDataBitTranslationId_t::Uart_LIST_END];
131 bool OutputIsPaused = false;
132 uint32_t TxIntensityDataStartingMask = 0x80;
133 bool HasBeenInitialized = false;
134 uint32_t NumUartSlotsPerIntensityValue = 1;
135 uint32_t MarkAfterInterintensityBreakBitCCOUNT = 0;
136 uint32_t ActiveIsrMask = 0;
137#if defined(ARDUINO_ARCH_ESP32)
138 intr_handle_t IsrHandle = nullptr;
139 SemaphoreHandle_t WaitFrameDone;
140#endif // defined(ARDUINO_ARCH_ESP32)
141
142 void ISR_StartNewDataFrame();
143 void CalculateEnableUartInterruptFlags();
144 uint32_t ISR_getUartFifoLength();
145 bool ISR_MoreDataToSend();
146 bool ISR_GetNextIntensityToSend(uint32_t &DataToSend);
147 void ISR_enqueueUartData(uint8_t value);
148 void EnableUartInterrupts();
149 void ISR_ClearUartInterrupts();
150 void ISR_DisableUartInterrupts();
151
152// #define USE_UART_DEBUG_COUNTERS
153#ifdef USE_UART_DEBUG_COUNTERS
154 // debug counters
155 uint32_t DataCallbackCounter = 0;
156 uint32_t DataTaskcounter = 0;
157 uint32_t RxIsr = 0;
158 uint32_t ErrorIsr = 0;
159 uint32_t FiFoISRcounter = 0;
160 uint32_t BreakIsrCounter = 0;
161 uint32_t IdleIsrCounter = 0;
162 uint32_t IsrIsNotForUs = 0;
163 uint32_t UnknownIsr = 0;
164 uint32_t TimerIsrCounter = 0;
165 uint32_t TimerIsrNoDataToSend = 0;
166 uint32_t TimerIsrSendData = 0;
167 uint32_t FrameThresholdCounter = 0;
168 uint32_t FrameEndISRcounter = 0;
169 uint32_t FrameStartCounter = 0;
170 uint32_t IntensityValuesSent = 0;
171 uint32_t IntensityBitsSent = 0;
172 uint32_t IntensityValuesSentLastFrame = 0;
173 uint32_t IntensityBitsSentLastFrame = 0;
174 uint32_t IncompleteFrame = 0;
175 uint32_t EnqueueCounter = 0;
176 uint32_t FiFoNotEmpty = 0;
177 uint32_t FiFoEmpty = 0;
178 uint32_t TxStopped = 0;
179
180#endif // def USE_UART_DEBUG_COUNTERS
181
182#ifndef UART_TX_BRK_DONE_INT_ENA
183# define UART_TX_BRK_DONE_INT_ENA 0
184#endif // ndef | UART_TX_BRK_DONE_INT_ENA
185
186#ifndef UART_TX_BRK_IDLE_DONE_INT_ENA
187# define UART_TX_BRK_IDLE_DONE_INT_ENA 0
188#endif // ndef | UART_TX_BRK_IDLE_DONE_INT_ENA
189
190#ifndef UART_INTR_MASK
191# if defined(ARDUINO_ARCH_ESP32)
192# define UART_INTR_MASK uint32_t((1 << 18) - 1)
193# elif defined(ARDUINO_ARCH_ESP8266)
194# define UART_INTR_MASK uint32_t((1 << 8) - 1)
195# endif // defined(ARDUINO_ARCH_ESP8266)
196#endif // UART_INTR_MASK
197
198#ifndef ESP_INTR_FLAG_IRAM
199# define ESP_INTR_FLAG_IRAM 0
200#endif // ndef ESP_INTR_FLAG_IRAM
201
202// timer interrupt support for GECE on ESP8266
203#if defined(ARDUINO_ARCH_ESP8266)
204
205public:
206
207 void IRAM_ATTR ISR_Timer_Handler();
208
209private:
210 void CalculateInterIntensityMabTime();
211 inline bool IsUartTimerInUse() __attribute__((gnu_inline, const))
212 {
213 return (OutputUartConfig.NumInterIntensityBreakBits || OutputUartConfig.NumInterIntensityMABbits);
214 } // IsUartTimerInUse
215
216 // Cycle counter
217 // static uint32_t _getCycleCount(void) __attribute__((always_inline));
218 static inline uint32_t _getCycleCount(void)
219 {
220 uint32_t ccount;
221 __asm__ __volatile__("rsr %0,ccount" : "=a"(ccount));
222 return ccount;
223 }
224
225#endif // defined(ARDUINO_ARCH_ESP8266)
226};
227#endif // defined(SUPPORT_UART)
const CN_PROGMEM char CN_OutputUart[]
Definition ConstNames.cpp:168
uint8_t OM_PortId_t
Definition OutputMgrPortDefs.hpp:71
Definition OutputPixel.hpp:28
struct FSEQParsedRangeEntry __attribute__
config_t config
Definition main.cpp:98
void GetDriverName(String &Name)
Definition main.cpp:121
void GetConfig(JsonObject &json)
Definition main.cpp:507
void SetConfig(const char *DataString)
Definition main.cpp:329