FabGL
ESP32 Display Controller and Graphics Library
vgadirectcontroller.cpp
1/*
2 Created by Fabrizio Di Vittorio (fdivitto2013@gmail.com) - <http://www.fabgl.com>
3 Copyright (c) 2019-2022 Fabrizio Di Vittorio.
4 All rights reserved.
5
6
7* Please contact fdivitto2013@gmail.com if you need a commercial license.
8
9
10* This library and related software is available under GPL v3.
11
12 FabGL is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
16
17 FabGL is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with FabGL. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26
27
28#include <alloca.h>
29#include <stdarg.h>
30#include <math.h>
31#include <string.h>
32
33#include "freertos/FreeRTOS.h"
34#include "freertos/task.h"
35
36#include "soc/i2s_struct.h"
37#include "soc/i2s_reg.h"
38#include "driver/periph_ctrl.h"
39#include "soc/rtc.h"
40#include "esp_spi_flash.h"
41#include "esp_heap_caps.h"
42
43#include "fabutils.h"
44#include "vgadirectcontroller.h"
46
47
48
49#pragma GCC optimize ("O2")
50
51
52namespace fabgl {
53
54
55
56
57
58/*************************************************************************************/
59/* VGADirectController definitions */
60
61
62VGADirectController * VGADirectController::s_instance = nullptr;
63volatile int VGADirectController::s_scanLine;
64lldesc_t volatile * VGADirectController::s_frameResetDesc;
65bool VGADirectController::s_VSync;
66lldesc_t volatile * * VGADirectController::s_DMALines = nullptr;
67
68
69
71 : m_linesCount(2),
72 m_lines(nullptr),
73 m_drawScanlineCallback(nullptr),
74 m_autoRun(autoRun)
75{
76 s_instance = this;
77}
78
79
80void VGADirectController::init()
81{
82 VGABaseController::init();
83 m_doubleBufferOverDMA = false;
84}
85
86
87void VGADirectController::allocateViewPort()
88{
89 m_lines = (uint8_t**) heap_caps_malloc(sizeof(uint8_t*) * m_linesCount, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
90 m_lines[0] = (uint8_t*) heap_caps_malloc(m_viewPortWidth * m_linesCount, MALLOC_CAP_DMA);
91 for (int i = 1; i < m_linesCount; ++i)
92 m_lines[i] = m_lines[0] + i * m_viewPortWidth;
93 s_DMALines = new lldesc_t volatile *[m_viewPortHeight];
94}
95
96
97void VGADirectController::freeViewPort()
98{
99 VGABaseController::freeViewPort();
100
101 heap_caps_free((void*)m_lines[0]);
102 heap_caps_free((void*)m_lines);
103 m_lines = nullptr;
104 delete s_DMALines;
105}
106
107
108void VGADirectController::setResolution(VGATimings const& timings, int viewPortWidth, int viewPortHeight, bool doubleBuffered)
109{
110 // fail if setDrawScanlineCallback() has not been called
111 if (!m_drawScanlineCallback)
112 return;
113
114 VGABaseController::setResolution(timings, viewPortWidth, viewPortHeight, doubleBuffered);
115
116 if (m_autoRun)
117 run();
118}
119
120
122{
123 // must be started before interrupt alloc
124 startGPIOStream();
125
126 s_scanLine = 0;
127
128 // ESP_INTR_FLAG_LEVEL1: should be less than PS2Controller interrupt level, necessary when running on the same core
129 if (m_isr_handle == nullptr) {
130 CoreUsage::setBusiestCore(FABGLIB_VIDEO_CPUINTENSIVE_TASKS_CORE);
131 esp_intr_alloc_pinnedToCore(ETS_I2S1_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM, ISRHandler, this, &m_isr_handle, FABGLIB_VIDEO_CPUINTENSIVE_TASKS_CORE);
132 I2S1.int_clr.val = 0xFFFFFFFF;
133 I2S1.int_ena.out_eof = 1;
134 }
135}
136
137
138void VGADirectController::onSetupDMABuffer(lldesc_t volatile * buffer, bool isStartOfVertFrontPorch, int scan, bool isVisible, int visibleRow)
139{
140 if (isVisible) {
141 s_DMALines[visibleRow] = buffer;
142
143 buffer->buf = (uint8_t *) m_lines[visibleRow % m_linesCount];
144
145 // generate interrupt every half m_linesCount
146 if ((scan == 0 && (visibleRow % (m_linesCount / 2)) == 0)) {
147 if (visibleRow == 0)
148 s_frameResetDesc = buffer;
149 buffer->eof = 1;
150 }
151 }
152}
153
154
155void VGADirectController::setScanlineBuffer(int scanline, uint8_t volatile * lineBuffer)
156{
157 s_DMALines[scanline]->buf = lineBuffer;
158}
159
160
161uint8_t volatile * VGADirectController::getScanlineBuffer(int scanline)
162{
163 return s_DMALines[scanline]->buf;
164}
165
166
167uint8_t volatile * VGADirectController::getDefaultScanlineBuffer(int scanline)
168{
169 return m_lines[scanline % m_linesCount];
170}
171
172
173void VGADirectController::setPixelAt(PixelDesc const & pixelDesc, Rect & updateRect)
174{
175}
176
177
178void VGADirectController::absDrawLine(int X1, int Y1, int X2, int Y2, RGB888 color)
179{
180}
181
182
183void VGADirectController::rawFillRow(int y, int x1, int x2, RGB888 color)
184{
185}
186
187
188void VGADirectController::rawFillRow(int y, int x1, int x2, uint8_t colorIndex)
189{
190}
191
192
193void VGADirectController::rawInvertRow(int y, int x1, int x2)
194{
195}
196
197
198void VGADirectController::rawCopyRow(int x1, int x2, int srcY, int dstY)
199{
200}
201
202
203void VGADirectController::swapRows(int yA, int yB, int x1, int x2)
204{
205}
206
207
208void VGADirectController::drawEllipse(Size const & size, Rect & updateRect)
209{
210}
211
212
213void VGADirectController::clear(Rect & updateRect)
214{
215}
216
217
218void VGADirectController::VScroll(int scroll, Rect & updateRect)
219{
220}
221
222
223void VGADirectController::HScroll(int scroll, Rect & updateRect)
224{
225}
226
227
228void VGADirectController::drawGlyph(Glyph const & glyph, GlyphOptions glyphOptions, RGB888 penColor, RGB888 brushColor, Rect & updateRect)
229{
230}
231
232
233void VGADirectController::invertRect(Rect const & rect, Rect & updateRect)
234{
235}
236
237
238void VGADirectController::swapFGBG(Rect const & rect, Rect & updateRect)
239{
240}
241
242
243void VGADirectController::copyRect(Rect const & source, Rect & updateRect)
244{
245}
246
247
248void VGADirectController::readScreen(Rect const & rect, RGB888 * destBuf)
249{
250}
251
252
253void VGADirectController::rawDrawBitmap_Native(int destX, int destY, Bitmap const * bitmap, int X1, int Y1, int XCount, int YCount)
254{
255}
256
257
258void VGADirectController::rawDrawBitmap_Mask(int destX, int destY, Bitmap const * bitmap, void * saveBackground, int X1, int Y1, int XCount, int YCount)
259{
260}
261
262
263void VGADirectController::rawDrawBitmap_RGBA2222(int destX, int destY, Bitmap const * bitmap, void * saveBackground, int X1, int Y1, int XCount, int YCount)
264{
265}
266
267
268void VGADirectController::rawDrawBitmap_RGBA8888(int destX, int destY, Bitmap const * bitmap, void * saveBackground, int X1, int Y1, int XCount, int YCount)
269{
270}
271
272
273void IRAM_ATTR VGADirectController::ISRHandler(void * arg)
274{
275 #if FABGLIB_VGAXCONTROLLER_PERFORMANCE_CHECK
276 auto s1 = getCycleCount();
277 #endif
278
279 if (I2S1.int_st.out_eof) {
280
281 auto ctrl = (VGADirectController *) arg;
282
283 auto viewPortHeight = ctrl->m_viewPortHeight;
284
285 auto desc = (volatile lldesc_t*) I2S1.out_eof_des_addr;
286
287 if (desc == s_frameResetDesc) {
288 s_scanLine = 0;
289 s_VSync = false;
290 }
291
292 int linesCount = ctrl->m_linesCount;
293 int scanLine = (s_scanLine + linesCount / 2) % viewPortHeight;
294
295 const auto lineIndex = scanLine & (linesCount - 1);
296
297 ctrl->m_drawScanlineCallback(ctrl->m_drawScanlineArg, (uint8_t*)(ctrl->m_lines[lineIndex]), scanLine);
298
299 s_scanLine += linesCount / 2;
300
301 if (s_scanLine >= viewPortHeight)
302 s_VSync = true;
303
304 }
305
306 #if FABGLIB_VGAXCONTROLLER_PERFORMANCE_CHECK
307 s_vgapalctrlcycles += getCycleCount() - s1;
308 #endif
309
310 I2S1.int_clr.val = I2S1.int_st.val;
311}
312
313
314
315} // end of namespace
316
void run()
Begins to call the callback function and to display video frames.
void setScanlineBuffer(int scanline, uint8_t volatile *lineBuffer)
Sets a scanline buffer.
uint8_t volatile * getDefaultScanlineBuffer(int scanline)
Gets default scanline buffer.
VGADirectController(bool autoRun=true)
Initializes a new instance of VGADirectController.
uint8_t volatile * getScanlineBuffer(int scanline)
Gets current scanline buffer.
#define FABGLIB_VIDEO_CPUINTENSIVE_TASKS_CORE
Definition: fabglconf.h:142
int16_t X1
Definition: fabutils.h:0
int16_t Y2
Definition: fabutils.h:3
int16_t X2
Definition: fabutils.h:2
int16_t Y1
Definition: fabutils.h:1
This file contains some utility classes and functions.
Represents a rectangle.
Definition: fabutils.h:248
This file contains fabgl::GPIOStream definition.
This file contains fabgl::VGADirectController definition.