Untitled
unknown
c_cpp
a year ago
6.2 kB
6
Indexable
// // Created by cpasjuste on 30/05/23. // #include <cstdio> #include "platform.h" #include "pico_display_buffered.h" #include "st7789.h" using namespace mb; static int s_core1_busy = 0; static PicoDisplayBuffered *s_display; static uint16_t in_ram(s_line_buffer)[240]; static void in_ram(draw)(Surface *surface, const Display::ScaleMode &mode, const Utility::Vec2i &pos, const Utility::Vec2i &size); _Noreturn static void in_ram(core1_main)(); union core_cmd { struct { uint8_t index = 0; }; uint32_t full; }; PicoDisplayBuffered::PicoDisplayBuffered(const Utility::Vec2i &displaySize, const Utility::Vec2i &renderSize, const ScaleMode &scaleMode, const Buffering &buffering) : Display(displaySize, renderSize, scaleMode, buffering) { // my own core1 crap s_display = this; // init st7789 display st7789_init(); // alloc frames buffers p_surfaces[0] = new Surface(m_renderSize); if (m_buffering == Buffering::Double) { p_surfaces[1] = new Surface(m_renderSize); // launch core1 multicore_launch_core1(core1_main); printf("PicoDisplay: st7789 pio with double buffering @ %ix%i\r\n", m_renderSize.x, m_renderSize.y); } else { printf("PicoDisplay: st7789 pio with single buffering @ %ix%i\r\n", m_renderSize.x, m_renderSize.y); } // clear the display PicoDisplayBuffered::clear(); } void in_ram(PicoDisplayBuffered::setCursorPos)(int16_t x, int16_t y) { m_cursor = {x, y}; } void in_ram(PicoDisplayBuffered::setPixel)(uint16_t color) { if (color != m_colorKey) { p_surfaces[m_bufferIndex]->setPixel(m_cursor, color); } // emulate tft lcd "put_pixel" m_cursor.x++; if (m_cursor.x >= m_displaySize.x) { m_cursor.x = 0; m_cursor.y += 1; } } void in_ram(PicoDisplayBuffered::clear)() { auto buffer = p_surfaces[m_bufferIndex]->getPixels(); if (m_clearColor == Color::Black || m_clearColor == Color::White) { memset((uint16_t *) buffer, m_clearColor, p_surfaces[m_bufferIndex]->getPixelsSize()); } else { int size = m_pitch * m_renderSize.y; uint64_t color64 = (uint64_t) m_clearColor << 48; color64 |= (uint64_t) m_clearColor << 32; color64 |= (uint64_t) m_clearColor << 16; color64 |= m_clearColor; for (uint_fast16_t i = 0; i < size; i += 8) { *(uint64_t *) (buffer + i) = color64; } } } void in_ram(PicoDisplayBuffered::flip)() { if (m_buffering == Buffering::Double) { // wait until previous flip on core1 complete while (__atomic_load_n(&s_core1_busy, __ATOMIC_SEQ_CST)) tight_loop_contents(); // send "flip" cmd to core1 __atomic_store_n(&s_core1_busy, 1, __ATOMIC_SEQ_CST); union core_cmd cmd{.index = m_bufferIndex}; multicore_fifo_push_blocking(cmd.full); // flip buffer m_bufferIndex = !m_bufferIndex; } else if (m_buffering == Buffering::Single) { draw(p_surfaces[m_bufferIndex], m_scaleMode, {}, m_displaySize); } } _Noreturn static void in_ram(core1_main)() { union core_cmd cmd{}; while (true) { cmd.full = multicore_fifo_pop_blocking(); draw(s_display->getSurface(cmd.index), s_display->getScaleMode(), {0, 0}, s_display->getDisplaySize()); __atomic_store_n(&s_core1_busy, 0, __ATOMIC_SEQ_CST); } } static void in_ram(draw)(Surface *surface, const Display::ScaleMode &mode, const Utility::Vec2i &pos, const Utility::Vec2i &size) { // render size is equal to display size if (surface->getSize() == size) { auto buffer = surface->getPixels(); uint16_t pitch = s_display->getPitch(); uint8_t bpp = s_display->getBpp(); st7789_set_cursor(0, 0); for (uint_fast16_t y = 0; y < size.y; y++) { for (uint_fast16_t x = 0; x < size.x; x++) { st7789_put(*(uint16_t *) (buffer + y * pitch + x * bpp)); } } } else { auto pixels = surface->getPixels(); auto pitch = surface->getPitch(); auto bpp = surface->getBpp(); auto srcSize = surface->getSize(); st7789_set_cursor(pos.x, pos.y); if (mode == Display::ScaleMode::Nearest) { int x, y; int xRatio = (srcSize.x << 16) / size.x + 1; int yRatio = (srcSize.y << 16) / size.y + 1; for (uint8_t i = 0; i < size.y; i++) { // computer line for (uint8_t j = 0; j < size.x; j++) { x = (j * xRatio) >> 16; y = (i * yRatio) >> 16; s_line_buffer[j + pos.x] = *(uint16_t *) (pixels + y * pitch + x * bpp); } // render line if (size.x == DISPLAY_WIDTH) { for (uint_fast16_t k = 0; k < size.x; k++) { st7789_put(s_line_buffer[k]); } } else { st7789_set_cursor(pos.x, i + pos.y); for (uint_fast16_t k = 0; k < size.x; k++) { st7789_put(s_line_buffer[k]); } } } } else { for (uint_fast16_t y = 0; y < srcSize.y; y++) { for (uint_fast16_t i = 0; i < 2; i++) { for (uint_fast16_t x = 0; x < srcSize.x; x += 2) { // line 1 auto p1 = *(uint16_t *) (pixels + y * pitch + x * bpp); st7789_put(p1); st7789_put(mode == mb::Display::Point ? p1 : Display::Color::Black); // line 2 auto p2 = *(uint16_t *) (pixels + y * pitch + (x + 1) * bpp); st7789_put(p2); st7789_put(mode == mb::Display::Point ? p2 : Display::Color::Black); } } } } } }
Editor is loading...
Leave a Comment