Sometimes a sharp image is more important that a variety of colors. PicoDVI has a setting offering double the resolution on each axis — 640×480, or 800×480 in wide mode — if you’re fine with strictly black-and-white graphics. Even with all the extra pixels, this uses only half the RAM of the 8-bit modes, or one fourth the 16-bit mode: about 38K for single-buffered 640×480 graphics, 75K double-buffered (and 47 or 94K for the widescreen variants).
The global display declaration is very similar to the 8-bit version:
DVIGFX1 display(DVI_RES_640x480p60, false, adafruit_feather_dvi_cfg);
The display type is DVIGFX1 now (instead of DVIGFX8), and the resolution doubled by requesting DVI_RES_640x480p60. Second argument is false because this example is single-buffered, and the remaining arguments (pinout and optional voltage setting) are the same as before. Remember that you may need to adjust the flash memory timing if using the widescreen DVI_RES_800x480p60 mode.
The remaining code in loop() then just draws lines between random endpoints, randomly selecting color 0 (black) or color 1 (white). Any GFX function could be used here — circles, text (including fonts) and so forth — using just those two color values. That’s all there is to it!
This is the bouncing-balls demo again, but strictly black-and-white. You can probably predict how this will all go…
DVIGFX1 display(DVI_RES_640x480p60, true, adafruit_feather_dvi_cfg);
Second argument is true now for double buffering, and the rest is all the same. No color palette is set up this time because 1-bit mode is always just black (0) or white (1).
loop() then works similarly to the 8-bit version: clear the whole screen, draw circles (outlined this time), update their positions for next time, and swap front/back buffers. swap() can optionally accept a single true/false argument (rather than two in the 8-bit case) whether to copy the front framebuffer contents to the back. It’s not used in this case because the full screen is redrawn; false is implied if not provided.
// Simple 1-bit Adafruit_GFX-compatible framebuffer for PicoDVI.
#include <PicoDVI.h>
// Here's how a 640x480 1-bit (black, white) framebuffer is declared.
// Second argument ('false' here) means NO double-buffering; all drawing
// operations are shown as they occur. Third argument is a hardware
// configuration -- examples are written for Adafruit Feather RP2040 DVI,
// but that's easily switched out for boards like the Pimoroni Pico DV
// (use 'pimoroni_demo_hdmi_cfg') or Pico DVI Sock ('pico_sock_cfg').
DVIGFX1 display(DVI_RES_640x480p60, false, adafruit_feather_dvi_cfg);
// An 800x480 mode is possible but pushes overclocking even higher than
// 640x480 mode. SOME BOARDS MIGHT SIMPLY NOT BE COMPATIBLE WITH THIS.
// May require selecting QSPI div4 clock (Tools menu) to slow down flash
// accesses, may require further over-volting the CPU to 1.25 or 1.3 V.
//DVIGFX1 display(DVI_RES_800x480p60, false, adafruit_feather_dvi_cfg);
void setup() { // Runs once on startup
if (!display.begin()) { // Blink LED if insufficient RAM
pinMode(LED_BUILTIN, OUTPUT);
for (;;) digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
}
}
void loop() {
// Draw random lines
display.drawLine(random(display.width()), random(display.height()), // Start X,Y
random(display.width()), random(display.height()), // End X,Y
random(2)); // Color (0 or 1)
}
// Double-buffered 1-bit Adafruit_GFX-compatible framebuffer for PicoDVI.
// Animates without redraw flicker. Requires Adafruit_GFX >= 1.11.5
#include <PicoDVI.h>
// Here's how a 640x480 1-bit (black, white) framebuffer is declared.
// Second argument ('true' here) enables double-buffering for flicker-free
// animation. Third argument is a hardware configuration -- examples are
// written for Adafruit Feather RP2040 DVI, but that's easily switched out
// for boards like the Pimoroni Pico DV (use 'pimoroni_demo_hdmi_cfg') or
// Pico DVI Sock ('pico_sock_cfg').
DVIGFX1 display(DVI_RES_640x480p60, true, adafruit_feather_dvi_cfg);
// An 800x480 mode is possible but pushes overclocking even higher than
// 640x480 mode. SOME BOARDS MIGHT SIMPLY NOT BE COMPATIBLE WITH THIS.
// May require selecting QSPI div4 clock (Tools menu) to slow down flash
// accesses, may require further over-volting the CPU to 1.25 or 1.3 V.
//DVIGFX1 display(DVI_RES_800x480p60, true, adafruit_feather_dvi_cfg);
#define N_BALLS 100 // Number of bouncy balls to draw
struct {
int16_t pos[2]; // Ball position (X,Y)
int8_t vel[2]; // Ball velocity (X,Y)
} ball[N_BALLS];
void setup() { // Runs once on startup
if (!display.begin()) { // Blink LED if insufficient RAM
pinMode(LED_BUILTIN, OUTPUT);
for (;;) digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
}
// Randomize initial ball positions and velocities
for (int i=0; i<N_BALLS; i++) {
ball[i].pos[0] = 10 + random(display.width() - 20);
ball[i].pos[1] = 10 + random(display.height() - 20);
do {
ball[i].vel[0] = 4 - random(9);
ball[i].vel[1] = 4 - random(9);
} while ((ball[i].vel[0] == 0) && (ball[i].vel[1] == 0));
}
}
void loop() {
display.fillScreen(0); // Clear back framebuffer...
// And draw bouncy balls (circles) there
for (int i=0; i<N_BALLS; i++) {
display.drawCircle(ball[i].pos[0], ball[i].pos[1], 40, 1);
// After drawing each one, update positions, bounce off edges.
ball[i].pos[0] += ball[i].vel[0];
if ((ball[i].pos[0] <= 0) || (ball[i].pos[0] >= display.width())) ball[i].vel[0] *= -1;
ball[i].pos[1] += ball[i].vel[1];
if ((ball[i].pos[1] <= 0) || (ball[i].pos[1] >= display.height())) ball[i].vel[1] *= -1;
}
// Swap front/back buffers, do not duplicate current screen state to next frame,
// we'll draw it new from scratch each time.
display.swap();
}
Page last edited January 22, 2025
Text editor powered by tinymce.