#include "draw_demo.h" #include "framebuffer.h" #include "pico/platform.h" #include static bool valid_coord(uint16_t x, uint16_t y) { if (x < 0 || x >= HPIXEL) return false; if (y < 0 || y >= VPIXEL) return false; return true; } // just because i did not need all the letters // and didn't want to fill a proper array :-) const Letter letters[] = { {'A', 6, (Point[]){{0, 7}, {0, 0}, {7, 0}, {7, 7}, {7, 3}, {0, 3}}}, {'G', 6, (Point[]){{7, 0}, {0, 0}, {0, 7}, {7, 7}, {7, 3}, {3, 3}}}, {'L', 3, (Point[]){{0, 0}, {0, 7}, {7, 7}}}, {'M', 5, (Point[]){{0, 7}, {0, 0}, {3, 3}, {7, 0}, {7, 7}}}, {'O', 5, (Point[]){{0, 0}, {0, 7}, {7, 7}, {7, 0}, {0, 0}}}, {'P', 5, (Point[]){{0, 7}, {0, 0}, {7, 0}, {7, 3}, {0, 3}}}, {'R', 6, (Point[]){{0, 7}, {0, 0}, {7, 0}, {7, 3}, {0, 3}, {7, 7}}}, {'S', 6, (Point[]){{0, 7}, {7, 7}, {7, 3}, {0, 3}, {0, 0}, {7, 0}}}, }; void draw_path(uint16_t x, uint16_t y, Point points[], size_t len) { Point *old_point = &points[0]; for (int i = 1; i < len; ++i) { Point *current_point = &points[i]; draw_line(x + old_point->x, y + old_point->y, x + current_point->x, y + current_point->y, true); old_point = current_point; } } void draw_letter(uint16_t x, uint16_t y, char c) { for (int i = 0; i < count_of(letters); ++i) { if (letters[i].letter == c) { draw_path(x, y, letters[i].points, letters[i].len); break; } } } void draw_string(uint16_t x, uint16_t y, const char *s) { while (*s != 0) { draw_letter(x, y, *s); s++; x += 9; } } void draw_demo(void) { // draw a little demo // clear frame buffer memset(&frame[0], 0, sizeof(frame)); // horizontal lines draw_line(0, 0, 640 - 1, 0, true); draw_line(0, 240 - 1, 640 - 1, 240 - 1, true); draw_line(0, 480 - 1, 640 - 1, 480 - 1, true); // vertical lines draw_line(0, 0, 0, 480 - 1, true); draw_line(320 - 1, 0, 320 - 1, 480 - 1, true); draw_line(638, 0, 638, 480 - 1, true); // last pixel of a line can't be set, see set_pixel() // cat eye for (uint16_t x = 0; x < 640; x += 20) { draw_line(x, 0, 0, (480 - x * 480 / 640), true); draw_line(640, x * 480 / 640, 640 - x, 480, true); } // string draw_string(200, 200, "GLG PROGRAMS"); } void draw_simple_line(uint16_t x, uint16_t y, uint16_t len, bool horizontal) { for (uint16_t i = 0; i < len; ++i) { if (horizontal) set_pixel(x + i, y); else set_pixel(x, y + i); } } void draw_line(uint16_t _x0, uint16_t _y0, uint16_t _x1, uint16_t _y1, bool fill) { const float x0 = _x0; const float y0 = _y0; const float x1 = _x1; const float y1 = _y1; if (x0 != x1) { const uint16_t x_begin = MIN(x0, x1); const uint16_t x_end = MAX(x0, x1); for (uint16_t x = x_begin; x < x_end; ++x) { const uint16_t y = (y1 - y0) * (x - x0) / (x1 - x0) + y0; if (fill) set_pixel(x, y); else clear_pixel(x, y); } } else { const uint16_t y_begin = MIN(y0, y1); const uint16_t y_end = MAX(y0, y1); for (uint16_t y = y_begin; y < y_end; ++y) { if (fill) set_pixel(x0, y); else clear_pixel(x0, y); } } } void set_pixel(uint16_t x, uint16_t y) { // ignore out of frame pixels if (!valid_coord(x, y)) return; // Since there is not much space in PIO program memory, // it is not possible to set the last pixel of a line, // because there is not enough program space to unset it // in the hardware, and, if left set, will mess with // the sync signals. if (x == 639) return; // skip wasted blanking lines // (see frame struct declaration) y += VBBLANK + VSPULSE - 1; // set bit frame[y * 80 + x / 8] |= (1 << x % 8); } void clear_pixel(uint16_t x, uint16_t y) { if (!valid_coord(x, y)) return; y += VBBLANK + VSPULSE - 1; frame[y * 80 + x / 8] &= ~(1 << x % 8); }