33 #include "freertos/FreeRTOS.h" 34 #include "freertos/task.h" 36 #include "soc/i2s_struct.h" 37 #include "soc/i2s_reg.h" 38 #include "driver/periph_ctrl.h" 40 #include "esp_spi_flash.h" 41 #include "esp_heap_caps.h" 49 #pragma GCC optimize ("O2") 63 volatile uint8_t * * VGAPalettedController::s_viewPort;
64 volatile uint8_t * * VGAPalettedController::s_viewPortVisible;
65 lldesc_t
volatile * VGAPalettedController::s_frameResetDesc;
66 volatile int VGAPalettedController::s_scanLine;
71 VGAPalettedController::VGAPalettedController(
int linesCount,
NativePixelFormat nativePixelFormat,
int viewPortRatioDiv,
int viewPortRatioMul, intr_handler_t isrHandler)
72 : m_linesCount(linesCount),
73 m_nativePixelFormat(nativePixelFormat),
74 m_viewPortRatioDiv(viewPortRatioDiv),
75 m_viewPortRatioMul(viewPortRatioMul),
76 m_isrHandler(isrHandler)
78 m_lines = (
volatile uint8_t**) heap_caps_malloc(
sizeof(uint8_t*) * m_linesCount, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL);
79 m_palette = (RGB222*) heap_caps_malloc(
sizeof(RGB222) * getPaletteSize(), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
83 VGAPalettedController::~VGAPalettedController()
85 heap_caps_free(m_palette);
86 heap_caps_free(m_lines);
90 void VGAPalettedController::init()
92 VGABaseController::init();
94 m_doubleBufferOverDMA =
false;
95 m_taskProcessingPrimitives =
false;
96 m_processPrimitivesOnBlank =
false;
97 m_primitiveExecTask =
nullptr;
101 void VGAPalettedController::end()
103 if (m_primitiveExecTask) {
104 vTaskDelete(m_primitiveExecTask);
105 m_primitiveExecTask =
nullptr;
106 m_taskProcessingPrimitives =
false;
108 VGABaseController::end();
114 VGABaseController::suspendBackgroundPrimitiveExecution();
115 while (m_taskProcessingPrimitives)
120 void VGAPalettedController::checkViewPortSize()
122 m_viewPortHeight &= ~(m_linesCount - 1);
126 void VGAPalettedController::allocateViewPort()
128 VGABaseController::allocateViewPort(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, m_viewPortWidth / m_viewPortRatioDiv * m_viewPortRatioMul);
130 for (
int i = 0; i < m_linesCount; ++i)
131 m_lines[i] = (uint8_t*) heap_caps_malloc(m_viewPortWidth, MALLOC_CAP_DMA);
135 void VGAPalettedController::freeViewPort()
137 VGABaseController::freeViewPort();
139 for (
int i = 0; i < m_linesCount; ++i) {
140 heap_caps_free((
void*)m_lines[i]);
141 m_lines[i] =
nullptr;
146 void VGAPalettedController::setResolution(VGATimings
const& timings,
int viewPortWidth,
int viewPortHeight,
bool doubleBuffered)
148 VGABaseController::setResolution(timings, viewPortWidth, viewPortHeight, doubleBuffered);
150 s_viewPort = m_viewPort;
151 s_viewPortVisible = m_viewPortVisible;
154 for (
int i = 0; i < m_viewPortHeight; ++i)
155 memset((
void*)(m_viewPort[i]), 0, m_viewPortWidth / m_viewPortRatioDiv * m_viewPortRatioMul);
157 setupDefaultPalette();
158 updateRGB2PaletteLUT();
160 calculateAvailableCyclesForDrawings();
166 if (m_isr_handle ==
nullptr) {
169 I2S1.int_clr.val = 0xFFFFFFFF;
170 I2S1.int_ena.out_eof = 1;
173 if (m_primitiveExecTask ==
nullptr) {
181 void VGAPalettedController::onSetupDMABuffer(lldesc_t
volatile * buffer,
bool isStartOfVertFrontPorch,
int scan,
bool isVisible,
int visibleRow)
184 buffer->buf = (uint8_t *) m_lines[visibleRow % m_linesCount];
187 if ((scan == 0 && (visibleRow % (m_linesCount / 2)) == 0)) {
189 s_frameResetDesc = buffer;
196 int VGAPalettedController::getPaletteSize()
214 void VGAPalettedController::updateRGB2PaletteLUT()
216 auto paletteSize = getPaletteSize();
217 for (
int r = 0; r < 4; ++r)
218 for (
int g = 0; g < 4; ++g)
219 for (
int b = 0; b < 4; ++b) {
221 rgb222_to_hsv(r, g, b, &H1, &S1, &V1);
223 int bestDst = 1000000000;
224 for (
int i = 0; i < paletteSize; ++i) {
226 rgb222_to_hsv(m_palette[i].
R, m_palette[i].
G, m_palette[i].
B, &H2, &S2, &V2);
230 int dst = AH * AH + AS * AS + AV * AV;
231 if (dst <= bestDst) {
238 m_packedRGB222_to_PaletteIndex[r | (g << 2) | (b << 4)] = bestIdx;
244 void VGAPalettedController::calculateAvailableCyclesForDrawings()
248 if (m_processPrimitivesOnBlank) {
250 availtime_us = ceil(1000000.0 / m_timings.frequency * m_timings.scanCount * m_HLineSize * (m_linesCount / 2 + m_timings.VFrontPorch + m_timings.VSyncPulse + m_timings.VBackPorch + m_viewPortRow));
253 availtime_us = ceil(1000000.0 / m_timings.frequency * m_timings.scanCount * m_HLineSize * (m_timings.VVisibleArea + m_timings.VFrontPorch + m_timings.VSyncPulse + m_timings.VBackPorch));
257 m_primitiveExecTimeoutCycles = getCPUFrequencyMHz() * availtime_us;
263 void VGAPalettedController::primitiveExecTask(
void * arg)
265 auto ctrl = (VGAPalettedController *) arg;
268 if (!ctrl->m_primitiveProcessingSuspended) {
269 auto startCycle = ctrl->backgroundPrimitiveTimeoutEnabled() ? getCycleCount() : 0;
270 Rect updateRect = Rect(SHRT_MAX, SHRT_MAX, SHRT_MIN, SHRT_MIN);
271 ctrl->m_taskProcessingPrimitives =
true;
274 if (ctrl->getPrimitive(&prim, 0) ==
false)
276 ctrl->execPrimitive(prim, updateRect,
false);
277 if (ctrl->m_primitiveProcessingSuspended)
279 }
while (!ctrl->backgroundPrimitiveTimeoutEnabled() || (startCycle + ctrl->m_primitiveExecTimeoutCycles > getCycleCount()));
280 ctrl->showSprites(updateRect);
281 ctrl->m_taskProcessingPrimitives =
false;
285 ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
291 void VGAPalettedController::swapBuffers()
293 VGABaseController::swapBuffers();
294 s_viewPort = m_viewPort;
295 s_viewPortVisible = m_viewPortVisible;
virtual void resumeBackgroundPrimitiveExecution()=0
Resumes drawings after suspendBackgroundPrimitiveExecution().
NativePixelFormat nativePixelFormat()
Represents the native pixel format used by this display.
This file contains fabgl::GPIOStream definition.
#define FABGLIB_VGAPALETTEDCONTROLLER_PRIMTASK_STACK_SIZE
#define FABGLIB_VIDEO_CPUINTENSIVE_TASKS_CORE
void suspendBackgroundPrimitiveExecution()
Suspends drawings.
This file contains some utility classes and functions.
This file contains fabgl::VGAPalettedController definition.
NativePixelFormat
This enum defines the display controller native pixel format.
#define FABGLIB_VGAPALETTEDCONTROLLER_PRIMTASK_PRIORITY