29 #include "freertos/FreeRTOS.h" 30 #include "freertos/task.h" 32 #include "soc/i2s_struct.h" 33 #include "soc/i2s_reg.h" 34 #include "driver/periph_ctrl.h" 35 #include "rom/lldesc.h" 37 #include "esp_spi_flash.h" 38 #include "esp_heap_caps.h" 60 volatile uint8_t * * VGAPalettedController::s_viewPort;
61 volatile uint8_t * * VGAPalettedController::s_viewPortVisible;
62 lldesc_t
volatile * VGAPalettedController::s_frameResetDesc;
63 volatile int VGAPalettedController::s_scanLine;
65 #if FABGLIB_VGAXCONTROLLER_PERFORMANCE_CHECK 66 volatile uint64_t s_vgapalctrlcycles = 0;
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;
107 VGABaseController::end();
113 VGABaseController::suspendBackgroundPrimitiveExecution();
114 while (m_taskProcessingPrimitives)
119 void VGAPalettedController::checkViewPortSize()
121 m_viewPortHeight &= ~(m_linesCount - 1);
125 void VGAPalettedController::allocateViewPort()
127 VGABaseController::allocateViewPort(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, m_viewPortWidth / m_viewPortRatioDiv * m_viewPortRatioMul);
129 for (
int i = 0; i < m_linesCount; ++i)
130 m_lines[i] = (uint8_t*) heap_caps_malloc(m_viewPortWidth, MALLOC_CAP_DMA);
134 void VGAPalettedController::freeViewPort()
136 VGABaseController::freeViewPort();
138 for (
int i = 0; i < m_linesCount; ++i) {
139 heap_caps_free((
void*)m_lines[i]);
140 m_lines[i] =
nullptr;
145 void VGAPalettedController::setResolution(VGATimings
const& timings,
int viewPortWidth,
int viewPortHeight,
bool doubleBuffered)
147 VGABaseController::setResolution(timings, viewPortWidth, viewPortHeight, doubleBuffered);
149 s_viewPort = m_viewPort;
150 s_viewPortVisible = m_viewPortVisible;
153 for (
int i = 0; i < m_viewPortHeight; ++i)
154 memset((
void*)(m_viewPort[i]), 0, m_viewPortWidth / m_viewPortRatioDiv * m_viewPortRatioMul);
156 setupDefaultPalette();
157 updateRGB2PaletteLUT();
159 calculateAvailableCyclesForDrawings();
165 if (m_isr_handle ==
nullptr) {
166 CoreUsage::setBusiestCore(FABGLIB_VIDEO_CPUINTENSIVE_TASKS_CORE);
167 esp_intr_alloc_pinnedToCore(ETS_I2S1_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM, m_isrHandler,
this, &m_isr_handle, FABGLIB_VIDEO_CPUINTENSIVE_TASKS_CORE);
168 I2S1.int_clr.val = 0xFFFFFFFF;
169 I2S1.int_ena.out_eof = 1;
172 if (m_primitiveExecTask ==
nullptr) {
173 xTaskCreatePinnedToCore(primitiveExecTask,
"" , FABGLIB_VGAPALETTEDCONTROLLER_PRIMTASK_STACK_SIZE,
this, FABGLIB_VGAPALETTEDCONTROLLER_PRIMTASK_PRIORITY, &m_primitiveExecTask, CoreUsage::quietCore());
180 void VGAPalettedController::onSetupDMABuffer(lldesc_t
volatile * buffer,
bool isStartOfVertFrontPorch,
int scan,
bool isVisible,
int visibleRow)
183 buffer->buf = (uint8_t *) m_lines[visibleRow % m_linesCount];
186 if ((scan == 0 && (visibleRow % (m_linesCount / 2)) == 0)) {
188 s_frameResetDesc = buffer;
195 int VGAPalettedController::getPaletteSize()
213 void VGAPalettedController::updateRGB2PaletteLUT()
215 auto paletteSize = getPaletteSize();
216 for (
int r = 0; r < 4; ++r)
217 for (
int g = 0; g < 4; ++g)
218 for (
int b = 0; b < 4; ++b) {
220 rgb222_to_hsv(r, g, b, &H1, &S1, &V1);
222 int bestDst = 1000000000;
223 for (
int i = 0; i < paletteSize; ++i) {
225 rgb222_to_hsv(m_palette[i].
R, m_palette[i].
G, m_palette[i].
B, &H2, &S2, &V2);
229 int dst = AH * AH + AS * AS + AV * AV;
230 if (dst <= bestDst) {
237 m_packedRGB222_to_PaletteIndex[r | (g << 2) | (b << 4)] = bestIdx;
243 void VGAPalettedController::calculateAvailableCyclesForDrawings()
247 if (m_processPrimitivesOnBlank) {
249 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));
252 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));
256 m_primitiveExecTimeoutCycles = getCPUFrequencyMHz() * availtime_us;
262 void VGAPalettedController::primitiveExecTask(
void * arg)
264 auto ctrl = (VGAPalettedController *) arg;
267 if (!ctrl->m_primitiveProcessingSuspended) {
268 auto startCycle = ctrl->backgroundPrimitiveTimeoutEnabled() ? getCycleCount() : 0;
269 Rect updateRect = Rect(SHRT_MAX, SHRT_MAX, SHRT_MIN, SHRT_MIN);
270 ctrl->m_taskProcessingPrimitives =
true;
273 if (ctrl->getPrimitive(&prim, 0) ==
false)
275 ctrl->execPrimitive(prim, updateRect,
false);
276 if (ctrl->m_primitiveProcessingSuspended)
278 }
while (!ctrl->backgroundPrimitiveTimeoutEnabled() || (startCycle + ctrl->m_primitiveExecTimeoutCycles > getCycleCount()));
279 ctrl->showSprites(updateRect);
280 ctrl->m_taskProcessingPrimitives =
false;
284 ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
290 void VGAPalettedController::swapBuffers()
292 VGABaseController::swapBuffers();
293 s_viewPort = m_viewPort;
294 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.
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.