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-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.
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"
49 #include "devdrivers/swgenerator.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 
77 namespace fabgl {
78 
79 
80 
81 #if FABGLIB_VGAXCONTROLLER_PERFORMANCE_CHECK
82  extern volatile uint64_t s_vgapalctrlcycles;
83 #endif
84 
85 
86 
92  Sync,
95 };
96 
97 
99 struct VGATimings {
100  char label[22];
101  int frequency;
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;
110  char HSyncLogic;
111  char VSyncLogic;
112  uint8_t scanCount;
113  uint8_t multiScanBlack;
115 };
116 
117 
118 
119 class VGABaseController : public GenericBitmappedDisplayController {
120 
121 public:
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 
318 protected:
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 
389 private:
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::GPIOStream definition.
This file contains fabgl::BitmappedDisplayController definition.
VGAScanStart
Represents one of the four blocks of horizontal or vertical line.
Specifies the VGA timings. This is a modeline decoded.
This file contains some utility classes and functions.
#define FABGLIB_VIEWPORT_MEMORY_POOL_COUNT
Definition: fabglconf.h:126
Definition: canvas.cpp:36
This file contains FabGL library configuration settings, like number of supported colors...
VGAScanStart HStartingBlock