FabGL
ESP32 Display Controller and Graphics Library
vgabasecontroller.h
Go to the documentation of this file.
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#pragma once
28
29
30
38#include <stdint.h>
39#include <stddef.h>
40#include <atomic>
41
42#include "driver/gpio.h"
43
44#include "freertos/FreeRTOS.h"
45#include "freertos/queue.h"
46
47#include "fabglconf.h"
48#include "fabutils.h"
50#include "displaycontroller.h"
51
52
53
54
55#define VGA_RED_BIT 0
56#define VGA_GREEN_BIT 2
57#define VGA_BLUE_BIT 4
58#define VGA_HSYNC_BIT 6
59#define VGA_VSYNC_BIT 7
60
61#define VGA_SYNC_MASK ((1 << VGA_HSYNC_BIT) | (1 << VGA_VSYNC_BIT))
62
63
64// pixel 0 = byte 2, pixel 1 = byte 3, pixel 2 = byte 0, pixel 3 = byte 1 :
65// pixel : 0 1 2 3 4 5 6 7 8 9 10 11 ...etc...
66// byte : 2 3 0 1 6 7 4 5 10 11 8 9 ...etc...
67// dword : 0 1 2 ...etc...
68// Thanks to https://github.com/paulscottrobson for the new macro. Before was: (row[((X) & 0xFFFC) + ((2 + (X)) & 3)])
69#define VGA_PIXELINROW(row, X) (row[(X) ^ 2])
70
71// requires variables: m_viewPort
72#define VGA_PIXEL(X, Y) VGA_PIXELINROW(m_viewPort[(Y)], X)
73#define VGA_INVERT_PIXEL(X, Y) { auto px = &VGA_PIXEL((X), (Y)); *px = ~(*px ^ VGA_SYNC_MASK); }
74
75
76
77namespace fabgl {
78
79
80
81#if FABGLIB_VGAXCONTROLLER_PERFORMANCE_CHECK
82 extern volatile uint64_t s_vgapalctrlcycles;
83#endif
84
85
86
95};
96
97
99struct VGATimings {
100 char label[22];
102 int16_t HVisibleArea;
103 int16_t HFrontPorch;
104 int16_t HSyncPulse;
105 int16_t HBackPorch;
106 int16_t VVisibleArea;
107 int16_t VFrontPorch;
108 int16_t VSyncPulse;
109 int16_t VBackPorch;
112 uint8_t scanCount;
115};
116
117
118
119class VGABaseController : public GenericBitmappedDisplayController {
120
121public:
122
123 VGABaseController();
124
125 // unwanted methods
126 VGABaseController(VGABaseController const&) = delete;
127 void operator=(VGABaseController const&) = delete;
128
145 void begin(gpio_num_t redGPIO, gpio_num_t greenGPIO, gpio_num_t blueGPIO, gpio_num_t HSyncGPIO, gpio_num_t VSyncGPIO);
146
166 void begin(gpio_num_t red1GPIO, gpio_num_t red0GPIO, gpio_num_t green1GPIO, gpio_num_t green0GPIO, gpio_num_t blue1GPIO, gpio_num_t blue0GPIO, gpio_num_t HSyncGPIO, gpio_num_t VSyncGPIO);
167
178 void begin();
179
180 virtual void end();
181
182 static bool convertModelineToTimings(char const * modeline, VGATimings * timings);
183
184 // abstract method of BitmappedDisplayController
185 virtual void suspendBackgroundPrimitiveExecution();
186
187 // abstract method of BitmappedDisplayController
188 virtual void resumeBackgroundPrimitiveExecution();
189
217 void setResolution(char const * modeline, int viewPortWidth = -1, int viewPortHeight = -1, bool doubleBuffered = false);
218
219 virtual void setResolution(VGATimings const& timings, int viewPortWidth = -1, int viewPortHeight = -1, bool doubleBuffered = false);
220
226 int getViewPortCol() { return m_viewPortCol; }
227
233 int getViewPortRow() { return m_viewPortRow; }
234
248 void moveScreen(int offsetX, int offsetY);
249
264 void shrinkScreen(int shrinkX, int shrinkY);
265
266 VGATimings * getResolutionTimings() { return &m_timings; }
267
275 uint8_t getBitsPerChannel() { return m_bitsPerChannel; }
276
277 virtual int colorsCount() { return 1 << (3 * m_bitsPerChannel); }
278
292 uint8_t * getScanline(int y) { return (uint8_t*) m_viewPort[y]; }
293
306 uint8_t createRawPixel(RGB222 rgb) { return preparePixel(rgb); }
307
308 uint8_t createBlankRawPixel() { return m_HVSync; }
309
310
311
312protected:
313
314 static void setupGPIO(gpio_num_t gpio, int bit, gpio_mode_t mode);
315
316 void startGPIOStream();
317
318 void freeBuffers();
319
320 virtual void freeViewPort();
321
322 virtual void init();
323
324 bool setDMABuffersCount(int buffersCount);
325
326 uint8_t packHVSync(bool HSync, bool VSync);
327
328 uint8_t inline __attribute__((always_inline)) preparePixel(RGB222 rgb) { return m_HVSync | (rgb.B << VGA_BLUE_BIT) | (rgb.G << VGA_GREEN_BIT) | (rgb.R << VGA_RED_BIT); }
329
330 uint8_t preparePixelWithSync(RGB222 rgb, bool HSync, bool VSync);
331
332 void fillVertBuffers(int offsetY);
333
334 void fillHorizBuffers(int offsetX);
335
336 int fill(uint8_t volatile * buffer, int startPos, int length, uint8_t red, uint8_t green, uint8_t blue, bool hsync, bool vsync);
337
338 int calcRequiredDMABuffersCount(int viewPortHeight);
339
340 bool isMultiScanBlackLine(int scan);
341
342 void setDMABufferBlank(int index, void volatile * address, int length, int scan, bool isStartOfVertFrontPorch);
343 void setDMABufferView(int index, int row, int scan, volatile uint8_t * * viewPort, bool onVisibleDMA);
344 void setDMABufferView(int index, int row, int scan, bool isStartOfVertFrontPorch);
345
346 virtual void onSetupDMABuffer(lldesc_t volatile * buffer, bool isStartOfVertFrontPorch, int scan, bool isVisible, int visibleRow) = 0;
347
348 void volatile * getDMABuffer(int index, int * length);
349
350 void allocateViewPort(uint32_t allocCaps, int rowlen);
351 virtual void allocateViewPort() = 0;
352 virtual void checkViewPortSize() { };
353
354 // abstract method of BitmappedDisplayController
355 virtual void swapBuffers();
356
357
358 // when double buffer is enabled the "drawing" view port is always m_viewPort, while the "visible" view port is always m_viewPortVisible
359 // when double buffer is not enabled then m_viewPort = m_viewPortVisible
360 volatile uint8_t * * m_viewPort;
361 volatile uint8_t * * m_viewPortVisible;
362
363 // true: double buffering is implemented in DMA
364 bool m_doubleBufferOverDMA;
365
366 volatile int m_primitiveProcessingSuspended; // 0 = enabled, >0 suspended
367
368 intr_handle_t m_isr_handle;
369
370 VGATimings m_timings;
371 int16_t m_HLineSize;
372
373 volatile int16_t m_viewPortCol;
374 volatile int16_t m_viewPortRow;
375
376 // contains H and V signals for visible line
377 volatile uint8_t m_HVSync;
378
379
380private:
381
382
383 // bits per channel on VGA output
384 // 1 = 8 colors, 2 = 64 colors, set by begin()
385 int m_bitsPerChannel;
386
387 GPIOStream m_GPIOStream;
388
389 lldesc_t volatile * m_DMABuffers;
390 int m_DMABuffersCount;
391
392 // when double buffer is enabled at DMA level the running DMA buffer is always m_DMABuffersVisible
393 // when double buffer is not enabled then m_DMABuffers = m_DMABuffersVisible
394 lldesc_t volatile * m_DMABuffersHead;
395 lldesc_t volatile * m_DMABuffersVisible;
396
397 // These buffers contains a full line, with FrontPorch, Sync, BackPorch and blank visible area, in the
398 // order specified by timings.HStartingBlock
399 volatile uint8_t * m_HBlankLine_withVSync;
400 volatile uint8_t * m_HBlankLine;
401
402 uint8_t * * m_viewPortMemoryPool; // array ends with nullptr
403
404 int16_t m_rawFrameHeight;
405
406};
407
408
409
410
411
412
413
414
415} // end of namespace
This file contains fabgl::BitmappedDisplayController definition.
This file contains FabGL library configuration settings, like number of supported colors,...
This file contains some utility classes and functions.
VGAScanStart
Represents one of the four blocks of horizontal or vertical line.
VGAScanStart HStartingBlock
Specifies the VGA timings. This is a modeline decoded.
This file contains fabgl::GPIOStream definition.