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" 57 static inline __attribute__((always_inline))
void VGA16_SETPIXELINROW(uint8_t * row,
int x,
int value) {
59 row[brow] = (x & 1) ? ((row[brow] & 0xf0) | value) : ((row[brow] & 0x0f) | (value << 4));
62 static inline __attribute__((always_inline))
int VGA16_GETPIXELINROW(uint8_t * row,
int x) {
64 return ((x & 1) ? (row[brow] & 0x0f) : ((row[brow] & 0xf0) >> 4));
67 #define VGA16_INVERTPIXELINROW(row, x) (row)[(x) >> 1] ^= (0xf0 >> (((x) & 1) << 2)) 69 static inline __attribute__((always_inline))
void VGA16_SETPIXEL(
int x,
int y,
int value) {
70 auto row = (uint8_t*) VGA16Controller::sgetScanline(y);
72 row[brow] = (x & 1) ? ((row[brow] & 0xf0) | value) : ((row[brow] & 0x0f) | (value << 4));
75 #define VGA16_GETPIXEL(x, y) VGA16_GETPIXELINROW((uint8_t*)VGA16Controller::s_viewPort[(y)], (x)) 77 #define VGA16_INVERT_PIXEL(x, y) VGA16_INVERTPIXELINROW((uint8_t*)VGA16Controller::s_viewPort[(y)], (x)) 86 VGA16Controller * VGA16Controller::s_instance =
nullptr;
90 VGA16Controller::VGA16Controller()
97 void VGA16Controller::setupDefaultPalette()
99 for (
int colorIndex = 0; colorIndex < 16; ++colorIndex) {
100 RGB888 rgb888((
Color)colorIndex);
109 m_palette[index] = color;
110 auto packed222 = RGB888toPackedRGB222(color);
111 for (
int i = 0; i < 16; ++i) {
112 m_packedPaletteIndexPair_to_signals[(index << 4) | i] &= 0xFF00;
113 m_packedPaletteIndexPair_to_signals[(index << 4) | i] |= (m_HVSync | packed222);
114 m_packedPaletteIndexPair_to_signals[(i << 4) | index] &= 0x00FF;
115 m_packedPaletteIndexPair_to_signals[(i << 4) | index] |= (m_HVSync | packed222) << 8;
120 void VGA16Controller::setPixelAt(PixelDesc
const & pixelDesc,
Rect & updateRect)
122 genericSetPixelAt(pixelDesc, updateRect,
123 [&] (
RGB888 const & color) {
return RGB888toPaletteIndex(color); },
131 void VGA16Controller::absDrawLine(
int X1,
int Y1,
int X2,
int Y2, RGB888 color)
133 genericAbsDrawLine(
X1,
Y1,
X2,
Y2, color,
134 [&] (RGB888
const & color) {
return RGB888toPaletteIndex(color); },
135 [&] (
int Y,
int X1,
int X2, uint8_t colorIndex) { rawFillRow(
Y,
X1,
X2, colorIndex); },
136 [&] (
int Y,
int X1,
int X2) { rawInvertRow(
Y,
X1,
X2); },
138 [&] (
int X,
int Y) { VGA16_INVERT_PIXEL(
X,
Y); }
144 void VGA16Controller::rawFillRow(
int y,
int x1,
int x2, RGB888 color)
146 rawFillRow(y, x1, x2, RGB888toPaletteIndex(color));
151 void VGA16Controller::rawFillRow(
int y,
int x1,
int x2, uint8_t colorIndex)
153 uint8_t * row = (uint8_t*) m_viewPort[y];
156 for (; x <= x2 && (x & 3) != 0; ++x) {
157 VGA16_SETPIXELINROW(row, x, colorIndex);
161 int sz = (x2 & ~3) - x;
162 memset((
void*)(row + x / 2), colorIndex | (colorIndex << 4), sz / 2);
166 for (; x <= x2; ++x) {
167 VGA16_SETPIXELINROW(row, x, colorIndex);
173 void VGA16Controller::rawInvertRow(
int y,
int x1,
int x2)
175 auto row = m_viewPort[y];
176 for (
int x = x1; x <= x2; ++x)
177 VGA16_INVERTPIXELINROW(row, x);
181 void VGA16Controller::rawCopyRow(
int x1,
int x2,
int srcY,
int dstY)
183 auto srcRow = (uint8_t*) m_viewPort[srcY];
184 auto dstRow = (uint8_t*) m_viewPort[dstY];
187 for (; x <= x2 && (x & 3) != 0; ++x) {
188 VGA16_SETPIXELINROW(dstRow, x, VGA16_GETPIXELINROW(srcRow, x));
191 auto src = (uint16_t*)(srcRow + x / 2);
192 auto dst = (uint16_t*)(dstRow + x / 2);
193 for (
int right = (x2 & ~3); x < right; x += 4)
196 for (x = (x2 & ~3); x <= x2; ++x) {
197 VGA16_SETPIXELINROW(dstRow, x, VGA16_GETPIXELINROW(srcRow, x));
202 void VGA16Controller::swapRows(
int yA,
int yB,
int x1,
int x2)
204 auto rowA = (uint8_t*) m_viewPort[yA];
205 auto rowB = (uint8_t*) m_viewPort[yB];
208 for (; x <= x2 && (x & 3) != 0; ++x) {
209 uint8_t a = VGA16_GETPIXELINROW(rowA, x);
210 uint8_t b = VGA16_GETPIXELINROW(rowB, x);
211 VGA16_SETPIXELINROW(rowA, x, b);
212 VGA16_SETPIXELINROW(rowB, x, a);
215 auto a = (uint16_t*)(rowA + x / 2);
216 auto b = (uint16_t*)(rowB + x / 2);
217 for (
int right = (x2 & ~3); x < right; x += 4)
220 for (x = (x2 & ~3); x <= x2; ++x) {
221 uint8_t a = VGA16_GETPIXELINROW(rowA, x);
222 uint8_t b = VGA16_GETPIXELINROW(rowB, x);
223 VGA16_SETPIXELINROW(rowA, x, b);
224 VGA16_SETPIXELINROW(rowB, x, a);
229 void VGA16Controller::drawEllipse(Size
const & size, Rect & updateRect)
231 genericDrawEllipse(size, updateRect,
232 [&] (RGB888
const & color) {
return RGB888toPaletteIndex(color); },
238 void VGA16Controller::clear(Rect & updateRect)
240 hideSprites(updateRect);
241 uint8_t paletteIndex = RGB888toPaletteIndex(getActualBrushColor());
242 uint8_t pattern = paletteIndex | (paletteIndex << 4);
243 for (
int y = 0; y < m_viewPortHeight; ++y)
244 memset((uint8_t*) m_viewPort[y], pattern, m_viewPortWidth / 2);
250 void VGA16Controller::VScroll(
int scroll, Rect & updateRect)
252 genericVScroll(scroll, updateRect,
253 [&] (
int yA,
int yB,
int x1,
int x2) { swapRows(yA, yB, x1, x2); },
254 [&] (
int yA,
int yB) { tswap(m_viewPort[yA], m_viewPort[yB]); },
255 [&] (
int y,
int x1,
int x2, RGB888 color) { rawFillRow(y, x1, x2, color); }
260 void VGA16Controller::HScroll(
int scroll, Rect & updateRect)
262 hideSprites(updateRect);
263 uint8_t back4 = RGB888toPaletteIndex(getActualBrushColor());
265 int Y1 = paintState().scrollingRegion.Y1;
266 int Y2 = paintState().scrollingRegion.Y2;
267 int X1 = paintState().scrollingRegion.X1;
268 int X2 = paintState().scrollingRegion.X2;
271 bool HScrolllingRegionAligned = ((
X1 & 3) == 0 && (
width & 3) == 0);
275 for (
int y =
Y1; y <=
Y2; ++y) {
276 if (HScrolllingRegionAligned) {
278 uint8_t * row = (uint8_t*) (m_viewPort[y]) +
X1 / 2;
279 for (
int s = -scroll; s > 0;) {
283 auto sz =
width & ~1;
284 memmove(row, row + sc / 2, (sz - sc) / 2);
285 rawFillRow(y,
X2 - sc + 1,
X2, back4);
293 auto w = (uint16_t *) (row +
width / 2) - 1;
294 for (
int i = 0; i <
width; i += 4) {
295 const uint16_t p4 = *w;
296 *w-- = (p4 << 4 & 0xf000) | (prev << 8 & 0x0f00) | (p4 << 4 & 0x00f0) | (p4 >> 12 & 0x000f);
297 prev = p4 >> 4 & 0x000f;
304 auto row = (uint8_t*) m_viewPort[y];
305 for (
int x =
X1; x <=
X2 + scroll; ++x)
306 VGA16_SETPIXELINROW(row, x, VGA16_GETPIXELINROW(row, x - scroll));
308 rawFillRow(y,
X2 + 1 + scroll,
X2, back4);
311 }
else if (scroll > 0) {
313 for (
int y =
Y1; y <=
Y2; ++y) {
314 if (HScrolllingRegionAligned) {
316 uint8_t * row = (uint8_t*) (m_viewPort[y]) +
X1 / 2;
317 for (
int s = scroll; s > 0;) {
321 auto sz =
width & ~1;
322 memmove(row + sc / 2, row, (sz - sc) / 2);
323 rawFillRow(y,
X1,
X1 + sc - 1, back4);
331 auto w = (uint16_t *) row;
332 for (
int i = 0; i <
width; i += 4) {
333 const uint16_t p4 = *w;
334 *w++ = (p4 << 12 & 0xf000) | (p4 >> 4 & 0x0f00) | (prev << 4) | (p4 >> 4 & 0x000f);
335 prev = p4 >> 8 & 0x000f;
342 auto row = (uint8_t*) m_viewPort[y];
343 for (
int x =
X2 - scroll; x >=
X1; --x)
344 VGA16_SETPIXELINROW(row, x + scroll, VGA16_GETPIXELINROW(row, x));
346 rawFillRow(y,
X1,
X1 + scroll - 1, back4);
354 void VGA16Controller::drawGlyph(Glyph
const & glyph, GlyphOptions glyphOptions, RGB888 penColor, RGB888 brushColor, Rect & updateRect)
356 genericDrawGlyph(glyph, glyphOptions, penColor, brushColor, updateRect,
357 [&] (RGB888
const & color) {
return RGB888toPaletteIndex(color); },
358 [&] (
int y) {
return (uint8_t*) m_viewPort[y]; },
364 void VGA16Controller::invertRect(Rect
const & rect, Rect & updateRect)
366 genericInvertRect(rect, updateRect,
367 [&] (
int Y,
int X1,
int X2) { rawInvertRow(
Y,
X1,
X2); }
372 void VGA16Controller::swapFGBG(Rect
const & rect, Rect & updateRect)
374 genericSwapFGBG(rect, updateRect,
375 [&] (RGB888
const & color) {
return RGB888toPaletteIndex(color); },
376 [&] (
int y) {
return (uint8_t*) m_viewPort[y]; },
385 void VGA16Controller::copyRect(Rect
const & source, Rect & updateRect)
387 genericCopyRect(source, updateRect,
388 [&] (
int y) {
return (uint8_t*) m_viewPort[y]; },
396 void VGA16Controller::readScreen(Rect
const & rect, RGB888 * destBuf)
398 for (
int y = rect.Y1; y <= rect.Y2; ++y) {
399 auto row = (uint8_t*) m_viewPort[y];
400 for (
int x = rect.X1; x <= rect.X2; ++x, ++destBuf) {
401 const RGB222 v = m_palette[VGA16_GETPIXELINROW(row, x)];
402 *destBuf = RGB888(v.R * 85, v.G * 85, v.B * 85);
408 void VGA16Controller::rawDrawBitmap_Native(
int destX,
int destY, Bitmap
const * bitmap,
int X1,
int Y1,
int XCount,
int YCount)
410 genericRawDrawBitmap_Native(destX, destY, (uint8_t*) bitmap->data, bitmap->width,
X1,
Y1, XCount, YCount,
411 [&] (
int y) { return (uint8_t*) m_viewPort[y]; },
417 void VGA16Controller::rawDrawBitmap_Mask(
int destX,
int destY, Bitmap
const * bitmap,
void * saveBackground,
int X1,
int Y1,
int XCount,
int YCount)
419 auto foregroundColorIndex = RGB888toPaletteIndex(bitmap->foregroundColor);
420 genericRawDrawBitmap_Mask(destX, destY, bitmap, (uint8_t*)saveBackground,
X1,
Y1, XCount, YCount,
421 [&] (
int y) {
return (uint8_t*) m_viewPort[y]; },
423 [&] (uint8_t * row,
int x) { VGA16_SETPIXELINROW(row, x, foregroundColorIndex); }
428 void VGA16Controller::rawDrawBitmap_RGBA2222(
int destX,
int destY, Bitmap
const * bitmap,
void * saveBackground,
int X1,
int Y1,
int XCount,
int YCount)
430 genericRawDrawBitmap_RGBA2222(destX, destY, bitmap, (uint8_t*)saveBackground,
X1,
Y1, XCount, YCount,
431 [&] (
int y) {
return (uint8_t*) m_viewPort[y]; },
433 [&] (uint8_t * row,
int x, uint8_t src) { VGA16_SETPIXELINROW(row, x, RGB2222toPaletteIndex(src)); }
438 void VGA16Controller::rawDrawBitmap_RGBA8888(
int destX,
int destY, Bitmap
const * bitmap,
void * saveBackground,
int X1,
int Y1,
int XCount,
int YCount)
440 genericRawDrawBitmap_RGBA8888(destX, destY, bitmap, (uint8_t*)saveBackground,
X1,
Y1, XCount, YCount,
441 [&] (
int y) {
return (uint8_t*) m_viewPort[y]; },
442 [&] (uint8_t * row,
int x) {
return VGA16_GETPIXELINROW(row, x); },
443 [&] (uint8_t * row,
int x,
RGBA8888 const & src) { VGA16_SETPIXELINROW(row, x, RGB8888toPaletteIndex(src)); }
448 #pragma GCC optimize ("O2") 451 void IRAM_ATTR VGA16Controller::ISRHandler(
void * arg)
453 #if FABGLIB_VGAXCONTROLLER_PERFORMANCE_CHECK 454 auto s1 = getCycleCount();
457 auto ctrl = (VGA16Controller *) arg;
459 if (I2S1.int_st.out_eof) {
461 auto const desc = (lldesc_t*) I2S1.out_eof_des_addr;
463 if (desc == s_frameResetDesc)
466 auto const width = ctrl->m_viewPortWidth;
467 auto const height = ctrl->m_viewPortHeight;
468 auto const packedPaletteIndexPair_to_signals = (uint16_t
const *) ctrl->m_packedPaletteIndexPair_to_signals;
469 auto const lines = ctrl->m_lines;
471 int scanLine = (s_scanLine + VGA16_LinesCount / 2) %
height;
473 auto lineIndex = scanLine & (VGA16_LinesCount - 1);
475 for (
int i = 0; i < VGA16_LinesCount / 2; ++i) {
477 auto src = (uint8_t
const *) s_viewPortVisible[scanLine];
478 auto dest = (uint16_t*) lines[lineIndex];
481 for (
int col = 0; col <
width; col += 16) {
483 auto src1 = *(src + 0);
484 auto src2 = *(src + 1);
485 auto src3 = *(src + 2);
486 auto src4 = *(src + 3);
487 auto src5 = *(src + 4);
488 auto src6 = *(src + 5);
489 auto src7 = *(src + 6);
490 auto src8 = *(src + 7);
494 auto v1 = packedPaletteIndexPair_to_signals[src1];
495 auto v2 = packedPaletteIndexPair_to_signals[src2];
496 auto v3 = packedPaletteIndexPair_to_signals[src3];
497 auto v4 = packedPaletteIndexPair_to_signals[src4];
498 auto v5 = packedPaletteIndexPair_to_signals[src5];
499 auto v6 = packedPaletteIndexPair_to_signals[src6];
500 auto v7 = packedPaletteIndexPair_to_signals[src7];
501 auto v8 = packedPaletteIndexPair_to_signals[src8];
521 s_scanLine += VGA16_LinesCount / 2;
523 if (scanLine >=
height && !ctrl->m_primitiveProcessingSuspended && spi_flash_cache_enabled()) {
526 vTaskNotifyGiveFromISR(ctrl->m_primitiveExecTask, NULL);
531 #if FABGLIB_VGAXCONTROLLER_PERFORMANCE_CHECK 532 s_vgapalctrlcycles += getCycleCount() - s1;
535 I2S1.int_clr.val = I2S1.int_st.val;
Represents a 24 bit RGB color.
This file contains fabgl::VGA16Controller definition.
This file contains fabgl::GPIOStream definition.
Color
This enum defines named colors.
void setPaletteItem(int index, RGB888 const &color)
Determines color of specified palette item.
This file contains some utility classes and functions.
NativePixelFormat
This enum defines the display controller native pixel format.