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
235 // abstract method of BitmappedDisplayController
236 int getViewPortWidth() { return m_viewPortWidth; }
237
238 // abstract method of BitmappedDisplayController
239 int getViewPortHeight() { return m_viewPortHeight; }
240
254 void moveScreen(int offsetX, int offsetY);
255
270 void shrinkScreen(int shrinkX, int shrinkY);
271
272 VGATimings * getResolutionTimings() { return &m_timings; }
273
281 uint8_t getBitsPerChannel() { return m_bitsPerChannel; }
282
283 virtual int colorsCount() { return 1 << (3 * m_bitsPerChannel); }
284
298 uint8_t * getScanline(int y) { return (uint8_t*) m_viewPort[y]; }
299
312 uint8_t createRawPixel(RGB222 rgb) { return preparePixel(rgb); }
313
314 uint8_t createBlankRawPixel() { return m_HVSync; }
315
316
317
318protected:
319
320 static void setupGPIO(gpio_num_t gpio, int bit, gpio_mode_t mode);
321
322 void startGPIOStream();
323
324 void freeBuffers();
325
326 virtual void freeViewPort();
327
328 virtual void init();
329
330 bool setDMABuffersCount(int buffersCount);
331
332 uint8_t packHVSync(bool HSync, bool VSync);
333
334 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); }
335
336 uint8_t preparePixelWithSync(RGB222 rgb, bool HSync, bool VSync);
337
338 void fillVertBuffers(int offsetY);
339
340 void fillHorizBuffers(int offsetX);
341
342 int fill(uint8_t volatile * buffer, int startPos, int length, uint8_t red, uint8_t green, uint8_t blue, bool hsync, bool vsync);
343
344 int calcRequiredDMABuffersCount(int viewPortHeight);
345
346 bool isMultiScanBlackLine(int scan);
347
348 void setDMABufferBlank(int index, void volatile * address, int length, int scan, bool isStartOfVertFrontPorch);
349 void setDMABufferView(int index, int row, int scan, volatile uint8_t * * viewPort, bool onVisibleDMA);
350 void setDMABufferView(int index, int row, int scan, bool isStartOfVertFrontPorch);
351
352 virtual void onSetupDMABuffer(lldesc_t volatile * buffer, bool isStartOfVertFrontPorch, int scan, bool isVisible, int visibleRow) = 0;
353
354 void volatile * getDMABuffer(int index, int * length);
355
356 void allocateViewPort(uint32_t allocCaps, int rowlen);
357 virtual void allocateViewPort() = 0;
358 virtual void checkViewPortSize() { };
359
360 // abstract method of BitmappedDisplayController
361 virtual void swapBuffers();
362
363
364 // when double buffer is enabled the "drawing" view port is always m_viewPort, while the "visible" view port is always m_viewPortVisible
365 // when double buffer is not enabled then m_viewPort = m_viewPortVisible
366 volatile uint8_t * * m_viewPort;
367 volatile uint8_t * * m_viewPortVisible;
368
369 // true: double buffering is implemented in DMA
370 bool m_doubleBufferOverDMA;
371
372 volatile int m_primitiveProcessingSuspended; // 0 = enabled, >0 suspended
373
374 volatile int16_t m_viewPortWidth;
375 volatile int16_t m_viewPortHeight;
376
377 intr_handle_t m_isr_handle;
378
379 VGATimings m_timings;
380 int16_t m_HLineSize;
381
382 volatile int16_t m_viewPortCol;
383 volatile int16_t m_viewPortRow;
384
385 // contains H and V signals for visible line
386 volatile uint8_t m_HVSync;
387
388
389private:
390
391
392 // bits per channel on VGA output
393 // 1 = 8 colors, 2 = 64 colors, set by begin()
394 int m_bitsPerChannel;
395
396 GPIOStream m_GPIOStream;
397
398 lldesc_t volatile * m_DMABuffers;
399 int m_DMABuffersCount;
400
401 // when double buffer is enabled at DMA level the running DMA buffer is always m_DMABuffersVisible
402 // when double buffer is not enabled then m_DMABuffers = m_DMABuffersVisible
403 lldesc_t volatile * m_DMABuffersHead;
404 lldesc_t volatile * m_DMABuffersVisible;
405
406 // These buffers contains a full line, with FrontPorch, Sync, BackPorch and blank visible area, in the
407 // order specified by timings.HStartingBlock
408 volatile uint8_t * m_HBlankLine_withVSync;
409 volatile uint8_t * m_HBlankLine;
410
411 uint8_t * m_viewPortMemoryPool[FABGLIB_VIEWPORT_MEMORY_POOL_COUNT + 1]; // last allocated pool is nullptr
412
413 int16_t m_rawFrameHeight;
414
415};
416
417
418
419
420
421
422
423
424} // end of namespace
This file contains fabgl::BitmappedDisplayController definition.
#define FABGLIB_VIEWPORT_MEMORY_POOL_COUNT
Definition: fabglconf.h:126
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.