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-2021 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. Feel free to use FabGL in free software and hardware:
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"
45 #include "devdrivers/swgenerator.h"
46 
47 
48 
49 #pragma GCC optimize ("O2")
50 
51 
52 namespace fabgl {
53 
54 
55 
56 
57 
58 /*************************************************************************************/
59 /* VGADirectController definitions */
60 
61 
62 VGADirectController * VGADirectController::s_instance = nullptr;
63 volatile int VGADirectController::s_scanLine;
64 lldesc_t volatile * VGADirectController::s_frameResetDesc;
65 bool VGADirectController::s_VSync;
66 
67 
68 
70  : m_linesCount(2),
71  m_lines(nullptr),
72  m_drawScanlineCallback(nullptr),
73  m_autoRun(autoRun)
74 {
75  s_instance = this;
76 }
77 
78 
79 void VGADirectController::init()
80 {
81  VGABaseController::init();
82  m_doubleBufferOverDMA = false;
83 }
84 
85 
86 void VGADirectController::allocateViewPort()
87 {
88  m_lines = (uint8_t**) heap_caps_malloc(sizeof(uint8_t*) * m_linesCount, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
89  m_lines[0] = (uint8_t*) heap_caps_malloc(m_viewPortWidth * m_linesCount, MALLOC_CAP_DMA);
90  for (int i = 1; i < m_linesCount; ++i)
91  m_lines[i] = m_lines[0] + i * m_viewPortWidth;
92 }
93 
94 
95 void VGADirectController::freeViewPort()
96 {
97  VGABaseController::freeViewPort();
98 
99  heap_caps_free((void*)m_lines[0]);
100  heap_caps_free((void*)m_lines);
101  m_lines = nullptr;
102 }
103 
104 
105 void VGADirectController::setResolution(VGATimings const& timings, int viewPortWidth, int viewPortHeight, bool doubleBuffered)
106 {
107  // fail if setDrawScanlineCallback() has not been called
108  if (!m_drawScanlineCallback)
109  return;
110 
111  VGABaseController::setResolution(timings, viewPortWidth, viewPortHeight, doubleBuffered);
112 
113  if (m_autoRun)
114  run();
115 }
116 
117 
119 {
120  // must be started before interrupt alloc
121  startGPIOStream();
122 
123  s_scanLine = 0;
124 
125  // ESP_INTR_FLAG_LEVEL1: should be less than PS2Controller interrupt level, necessary when running on the same core
126  if (m_isr_handle == nullptr) {
127  CoreUsage::setBusiestCore(FABGLIB_VIDEO_CPUINTENSIVE_TASKS_CORE);
128  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);
129  I2S1.int_clr.val = 0xFFFFFFFF;
130  I2S1.int_ena.out_eof = 1;
131  }
132 }
133 
134 
135 void VGADirectController::onSetupDMABuffer(lldesc_t volatile * buffer, bool isStartOfVertFrontPorch, int scan, bool isVisible, int visibleRow)
136 {
137  if (isVisible) {
138  buffer->buf = (uint8_t *) m_lines[visibleRow % m_linesCount];
139 
140  // generate interrupt every half m_linesCount
141  if ((scan == 0 && (visibleRow % (m_linesCount / 2)) == 0)) {
142  if (visibleRow == 0)
143  s_frameResetDesc = buffer;
144  buffer->eof = 1;
145  }
146  }
147 }
148 
149 
150 void VGADirectController::setPixelAt(PixelDesc const & pixelDesc, Rect & updateRect)
151 {
152 }
153 
154 
155 void VGADirectController::absDrawLine(int X1, int Y1, int X2, int Y2, RGB888 color)
156 {
157 }
158 
159 
160 void VGADirectController::rawFillRow(int y, int x1, int x2, RGB888 color)
161 {
162 }
163 
164 
165 void VGADirectController::rawFillRow(int y, int x1, int x2, uint8_t colorIndex)
166 {
167 }
168 
169 
170 void VGADirectController::rawInvertRow(int y, int x1, int x2)
171 {
172 }
173 
174 
175 void VGADirectController::rawCopyRow(int x1, int x2, int srcY, int dstY)
176 {
177 }
178 
179 
180 void VGADirectController::swapRows(int yA, int yB, int x1, int x2)
181 {
182 }
183 
184 
185 void VGADirectController::drawEllipse(Size const & size, Rect & updateRect)
186 {
187 }
188 
189 
190 void VGADirectController::clear(Rect & updateRect)
191 {
192 }
193 
194 
195 void VGADirectController::VScroll(int scroll, Rect & updateRect)
196 {
197 }
198 
199 
200 void VGADirectController::HScroll(int scroll, Rect & updateRect)
201 {
202 }
203 
204 
205 void VGADirectController::drawGlyph(Glyph const & glyph, GlyphOptions glyphOptions, RGB888 penColor, RGB888 brushColor, Rect & updateRect)
206 {
207 }
208 
209 
210 void VGADirectController::invertRect(Rect const & rect, Rect & updateRect)
211 {
212 }
213 
214 
215 void VGADirectController::swapFGBG(Rect const & rect, Rect & updateRect)
216 {
217 }
218 
219 
220 void VGADirectController::copyRect(Rect const & source, Rect & updateRect)
221 {
222 }
223 
224 
225 void VGADirectController::readScreen(Rect const & rect, RGB888 * destBuf)
226 {
227 }
228 
229 
230 void VGADirectController::rawDrawBitmap_Native(int destX, int destY, Bitmap const * bitmap, int X1, int Y1, int XCount, int YCount)
231 {
232 }
233 
234 
235 void VGADirectController::rawDrawBitmap_Mask(int destX, int destY, Bitmap const * bitmap, void * saveBackground, int X1, int Y1, int XCount, int YCount)
236 {
237 }
238 
239 
240 void VGADirectController::rawDrawBitmap_RGBA2222(int destX, int destY, Bitmap const * bitmap, void * saveBackground, int X1, int Y1, int XCount, int YCount)
241 {
242 }
243 
244 
245 void VGADirectController::rawDrawBitmap_RGBA8888(int destX, int destY, Bitmap const * bitmap, void * saveBackground, int X1, int Y1, int XCount, int YCount)
246 {
247 }
248 
249 
250 void IRAM_ATTR VGADirectController::ISRHandler(void * arg)
251 {
252  #if FABGLIB_VGAXCONTROLLER_PERFORMANCE_CHECK
253  auto s1 = getCycleCount();
254  #endif
255 
256  if (I2S1.int_st.out_eof) {
257 
258  auto ctrl = (VGADirectController *) arg;
259 
260  auto viewPortHeight = ctrl->m_viewPortHeight;
261 
262  auto desc = (volatile lldesc_t*) I2S1.out_eof_des_addr;
263 
264  if (desc == s_frameResetDesc) {
265  s_scanLine = 0;
266  s_VSync = false;
267  }
268 
269  int linesCount = ctrl->m_linesCount;
270  int scanLine = (s_scanLine + linesCount / 2) % viewPortHeight;
271 
272  const auto lineIndex = scanLine & (linesCount - 1);
273 
274  ctrl->m_drawScanlineCallback(ctrl->m_drawScanlineArg, (uint8_t*)(ctrl->m_lines[lineIndex]), scanLine);
275 
276  s_scanLine += linesCount / 2;
277 
278  if (s_scanLine >= viewPortHeight)
279  s_VSync = true;
280 
281  }
282 
283  #if FABGLIB_VGAXCONTROLLER_PERFORMANCE_CHECK
284  s_vgapalctrlcycles += getCycleCount() - s1;
285  #endif
286 
287  I2S1.int_clr.val = I2S1.int_st.val;
288 }
289 
290 
291 
292 } // end of namespace
293 
int16_t X2
Definition: fabutils.h:179
int16_t Y2
Definition: fabutils.h:180
int16_t Y1
Definition: fabutils.h:178
This file contains fabgl::GPIOStream definition.
int16_t X1
Definition: fabutils.h:177
#define FABGLIB_VIDEO_CPUINTENSIVE_TASKS_CORE
Definition: fabglconf.h:138
This file contains some utility classes and functions.
Definition: canvas.cpp:36
This file contains fabgl::VGADirectController definition.
void run()
Begins to call the callback function and to display video frames.
VGADirectController(bool autoRun=true)
Initializes a new instance of VGADirectController.