Add 4 more examples in "screensavers" subdir

This commit is contained in:
Phillip Burgess 2023-04-17 22:17:59 -07:00 committed by ladyada
parent 28f931609e
commit ec5c86ef26
8 changed files with 117589 additions and 0 deletions

View file

@ -0,0 +1,153 @@
// "Aquarium" example for PicoDVI library. If just starting out,
// see the 8bit_double_buffer which explains the PicoDVI groundwork.
// Comments in THIS file are mostly distinct & new concepts.
// The flying toasters example also goes into more detail.
// IF NO OUTPUT OR RED FLICKER SCANLINES: try Tools->Optimize->(-O3)
#include <PicoDVI.h>
#include "sprites.h" // Graphics data
DVIGFX8 display(DVI_RES_320x240p60, true, adafruit_feather_dvi_cfg);
// See notes in 8bit_double_buffer regarding 400x240 mode.
//DVIGFX8 display(DVI_RES_400x240p60, true, adafruit_feather_dvi_cfg);
// Also requires -O3 setting.
// This structure holds pointers to sprite graphics and masks in sprites.h.
const struct {
const uint8_t *sprite[2][2]; // L/R directions and A/B frames
const uint8_t *mask[2][2]; // Same
} spritedata[] = {
// There are FOUR sprites/masks for each fish (and kelp):
// two left-facing, two right-facing, and A/B frames for each.
{ sprite0LA , sprite0LB , sprite0RA , sprite0RB , mask0LA , mask0LB , mask0RA , mask0RB },
{ sprite1LA , sprite1LB , sprite1RA , sprite1RB , mask1LA , mask1LB , mask1RA , mask1RB },
{ sprite2LA , sprite2LB , sprite2RA , sprite2RB , mask2LA , mask2LB , mask2RA , mask2RB },
{ sprite3LA , sprite3LB , sprite3RA , sprite3RB, mask3LA , mask3LB , mask3RA , mask3RB },
{ sprite4LA , sprite4LB , sprite4RA , sprite4RB , mask4LA , mask4LB , mask4RA , mask4RB },
{ sprite5LA , sprite5LB , sprite5RA , sprite5RB , mask5LA , mask5LB , mask5RA , mask5RB },
{ sprite6LA , sprite6LB , sprite6RA , sprite6RB , mask6LA , mask6LB , mask6RA , mask6RB },
{ sprite7LA , sprite7LB , sprite7RA , sprite7RB , mask7LA , mask7LB , mask7RA , mask7RB },
{ sprite8LA , sprite8LB , sprite8RA , sprite8RB , mask8LA , mask8LB , mask8RA , mask8RB },
{ sprite9LA , sprite9LB , sprite9RA , sprite9RB , mask9LA , mask9LB , mask9RA , mask9RB },
{ sprite10LA, sprite10LB, sprite10RA, sprite10RB, mask10LA, mask10LB, mask10RA, mask10RB },
{ sprite11LA, sprite11LB, sprite11RA, sprite11RB, mask11LA, mask11LB, mask11RA, mask11RB },
{ sprite12LA, sprite12LB, sprite12RA, sprite12RB, mask12LA, mask12LB, mask12RA, mask12RB },
{ sprite13LA, sprite13LB, sprite13RA, sprite13RB, mask13LA, mask13LB, mask13RA, mask13RB },
{ sprite14LA, sprite14LB, sprite14RA, sprite14RB, mask14LA, mask14LB, mask14RA, mask14RB },
{ sprite15LA, sprite15LB, sprite15RA, sprite15RB, mask15LA, mask15LB, mask15RA, mask15RB },
{ sprite16LA, sprite16LB, sprite16RA, sprite16RB, mask16LA, mask16LB, mask16RA, mask16RB },
{ sprite17LA, sprite17LB, sprite17RA, sprite17RB, mask17LA, mask17LB, mask17RA, mask17RB },
// Bubbles are a special case. No right/left versions, but A/B frames.
// To use same struct (not a special case), just duplicate each 2X.
{ sprite18A , sprite18B , sprite18A , sprite18B , mask18A , mask18B , mask18A , mask18B },
};
#define N_SPRITES 12 // MUST be >= 6
// This structure contains positions and other data for the sprites
// in motion (notice it's not "const", because contents change).
struct {
int16_t pos[2]; // sprite position (X,Y) * 16
int8_t speed; // sprite speed (-16 to -8 or +8 to +16)
uint8_t index; // which index (in spritedata) to use
uint8_t offset; // Timer offset to de-sync each sprite's animation
} sprite[N_SPRITES];
// Initialize one sprite (index passed to function) to a random offscreen
// position, also randomizing speed and sprite (fish) type.
void randomsprite(uint8_t i) {
// To move the sprites at slightly different speeds, coordinates are
// stored in 1/16 pixel units. When drawing, the stored values get
// divided by 16 to yield final pixel coordinates.
sprite[i].speed = random(8, 17); // 1/2 to 1 pixel per frame
if (random(2)) { // 50/50 random chance...
sprite[i].speed *= -1; // Fish moves right-to-left
sprite[i].pos[0] = (display.width() + random(64)) * 16; // Start off right edge
} else { // Fish moves left-to-right
sprite[i].pos[0] = random(64, 128) * -16; // Start off left edge
}
// WHEEL. OF. FISH. -2 here is to ignore last 2 sprites (kelp, bubbles)
sprite[i].index = random(sizeof spritedata / sizeof spritedata[0] - 2);
if (sprite[i].index == 8) { // Sprite #8 is crab, keep close to ground
sprite[i].pos[1] = random(display.height() - 96, display.height() - 64) * 16;
} else { // Is a fish, upper part of screen
sprite[i].pos[1] = random(display.height() - 96) * 16;
}
sprite[i].offset = random(256); // De-synchronize sprite animation
}
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);
}
// Initialize color palette from table in sprites.h. Rather than
// calling setColor() for each one, we can just dump it directly...
memcpy(display.getPalette(), palette, sizeof palette);
display.swap(false, true); // Duplicate same palette to front & back buffers
// Randomize initial sprite states
randomSeed(analogRead(A0)); // Seed randomness from unused analog in
int range = display.width() + 64;
for (int i=0; i<3; i++) { // FIRST THREE sprites...
sprite[i].index = 17; // Are always kelp
sprite[i].speed = random(2) ? 1 : -1; // 50/50 left/right flip
sprite[i].pos[0] = (random(range * i / 3, range * (i + 1) / 3 - 64) - 32) * 16;
sprite[i].pos[1] = random(display.height() - 120, display.height() - 100) * 16;
sprite[i].offset = random(256);
}
for (int i=3; i<6; i++) { // NEXT THREE sprites...
sprite[i].index = 18; // Are always bubbles
sprite[i].speed = 0;
sprite[i].pos[0] = display.width() * 16; // Start them all offscreen
sprite[i].pos[1] = random(display.height()) * 8;
sprite[i].offset = random(256);
}
for (int i=6; i<N_SPRITES; i++) randomsprite(i); // Rest are fish
}
uint8_t frame = 0; // Counter for animation
void loop() { // Runs once every frame
display.fillScreen(0); // Clear back framebuffer,
for (int x=0; x<display.width(); x += 192) { // Tile background sprite
// Although DVIGFX8 is a COLOR display type, we leverage GFX's
// drawGrayscaleBitmap() function to draw the sprites...it saves us
// writing a ton of code this way.
display.drawGrayscaleBitmap(x, display.height() - 64, gravel, 192, 64);
}
for (int i=0; i<N_SPRITES; i++) { // and then the rest of the sprites...
uint8_t dir = sprite[i].speed > 0; // Left/right
uint8_t fr = ((frame + sprite[i].offset) >> 4) & 1; // A/B frame
if (sprite[i].speed) { // FISH or KELP; 64x64 sprite
display.drawGrayscaleBitmap(sprite[i].pos[0] / 16, sprite[i].pos[1] / 16,
spritedata[sprite[i].index].sprite[dir][fr],
spritedata[sprite[i].index].mask[dir][fr], 64, 64);
if (abs(sprite[i].speed) > 1) { // Not kelp...
sprite[i].pos[0] += sprite[i].speed; // Update position, check if offscreen...
if (((sprite[i].speed > 0) && (sprite[i].pos[0] > (display.width() * 16))) ||
((sprite[i].speed < 0) && (sprite[i].pos[0] < -64 * 16)))
randomsprite(i); // Replace with a new fish
}
} else { // Is BUBBLES
display.drawGrayscaleBitmap(sprite[i].pos[0] / 16, sprite[i].pos[1] / 16,
spritedata[sprite[i].index].sprite[0][fr],
spritedata[sprite[i].index].mask[0][fr], 64, 16);
sprite[i].pos[1] -= 16; // Move up by 1 pixel
if (sprite[i].pos[1] < -256) { // Off top of screen?
int j = random(6, N_SPRITES); // Pick a random fish,
sprite[i].pos[0] = sprite[j].pos[0]; // and move bubbles there
sprite[i].pos[1] = sprite[j].pos[1] + 384;
}
}
}
// Swap front/back buffers, do not duplicate current screen state
// to next frame, we'll draw it new from scratch each time.
display.swap();
frame++; // Increment animation counter; "rolls over" 0-255 automatically.
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,41 @@
// "Logo bounce" example for PicoDVI library. If just starting out,
// see the 1bit_double_buffer which explains the PicoDVI groundwork.
// Comments in THIS file are mostly distinct & new concepts.
// IF NO OUTPUT OR RED FLICKER SCANLINES: try Tools->Optimize->(-O3)
#include <PicoDVI.h>
#include "sprite.h" // Graphics data
DVIGFX1 display(DVI_RES_640x480p60, true, adafruit_feather_dvi_cfg);
// See notes in 1bit_double_buffer regarding 800x480 mode.
//DVIGFX1 display(DVI_RES_800x480p60, true, adafruit_feather_dvi_cfg);
// May also require -O3 setting.
int x = 0; // Start logo at
int y = 0; // top left corner,
int vx = 1; // moving right
int vy = 1; // and down
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() { // Runs once every frame
display.fillScreen(0); // Clear back framebuffer, then draw sprite:
display.drawBitmap(x, y, sprite, SPRITE_WIDTH, SPRITE_HEIGHT, 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();
// Update sprite position, bouncing off all 4 sides
x += vx; // Horizontal
if ((x == 0) || (x == (display.width() - SPRITE_WIDTH))) vx *= -1;
y += vy; // Vertical
if ((y == 0) || (y == (display.height() - SPRITE_HEIGHT))) vy *= -1;
}

View file

@ -0,0 +1,386 @@
// "DVI video" logo sprite. Generated from a 1-bit PNG using ImageMagick:
// magick sprite.png -define h:format=gray -depth 1 sprite.h
// (then edited a bit for this program)
// The sprite was intentionally planned with dimensions that are both
// prime numbers, and then starts from the upper-left corner. This should
// make the bounce SUPER annoying, taking hours or days to ever hit an
// exact corner again!
#define SPRITE_WIDTH 239
#define SPRITE_HEIGHT 149
static const uint8_t sprite[] = {
0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00,
0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00,
0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00,
0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFC,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xEF,
0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x80,
0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x1F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0x9F,
0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF,
0xFF, 0x80, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
0x00, 0x07, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF,
0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xFF, 0xFE, 0x1F,
0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xE0,
0x00, 0x1F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF,
0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xFF, 0xF8, 0x3F,
0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xE0,
0x00, 0x7F, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF,
0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F,
0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF,
0xFE, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xF0,
0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x03, 0xFF,
0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xC0, 0x7F,
0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF,
0xFE, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xF8,
0x03, 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x03, 0xFF,
0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0x00, 0x7F,
0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF,
0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xF8,
0x07, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF,
0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0xFF,
0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
0xFC, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFC,
0x1F, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFF,
0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xF8, 0x00, 0xFF,
0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
0xFC, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFC,
0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x0F, 0xFF,
0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xE0, 0x01, 0xFF,
0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF,
0xF8, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0xFE,
0xFF, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x3F, 0xFF,
0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF,
0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x03, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
0xF0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x03, 0xFF, 0xFF,
0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x03, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x07, 0xFF,
0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF,
0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
0xFF, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xFF, 0xFF,
0xFE, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x07, 0xFF,
0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF,
0xE0, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x1F, 0xFF, 0xFF,
0xFF, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF8, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF,
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0xFF,
0xFF, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x0F, 0xFF,
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
0xFF, 0xFC, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xFF,
0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF,
0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x1F, 0xFF,
0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF,
0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x1F, 0xFF,
0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xFF,
0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF,
0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF,
0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF,
0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x7F, 0xFF,
0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00,
0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00,
0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFC, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x80, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00,
0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00,
0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7F, 0x80, 0x01, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFF, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF,
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x01,
0xFE, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x3F,
0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3F, 0xC0, 0x03, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x03,
0xFC, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x3F,
0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1F, 0xE0, 0x07, 0xF8, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xFF,
0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x07,
0xF8, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFE, 0x07, 0xFF, 0x00, 0x00, 0x3F,
0x80, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFE, 0x01, 0xFF, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x07, 0xFC, 0x00,
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF8, 0x0F,
0xE0, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFE, 0x00, 0xFF, 0x80, 0x00, 0x3F,
0x80, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xFC, 0x1F, 0xE0, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFE, 0x00, 0x7F, 0x80, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x0F, 0xF0, 0x00,
0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x1F,
0xC0, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFE, 0x00, 0x7F, 0x80, 0x00, 0x3F,
0xFF, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xFE, 0x3F, 0xC0, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFE, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xE0, 0x00,
0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x3F,
0x80, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFE, 0x00, 0x3F, 0x80, 0x00, 0x3F,
0xFF, 0xE0, 0x00, 0x1F, 0xE0, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xFF, 0x7F, 0x80, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFE, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x0F, 0xF0, 0x00,
0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F,
0x00, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFE, 0x00, 0x7F, 0x80, 0x00, 0x3F,
0x80, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFE, 0x00, 0x7F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x0F, 0xF8, 0x00,
0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE,
0x00, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFE, 0x00, 0xFF, 0x80, 0x00, 0x3F,
0x80, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFE, 0x01, 0xFF, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x07, 0xFE, 0x00,
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC,
0x00, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFE, 0x0F, 0xFE, 0x00, 0x00, 0x3F,
0x80, 0x00, 0x00, 0x07, 0xFF, 0x80, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xFF,
0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8,
0x00, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x3F,
0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0,
0x00, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x3F,
0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFF, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF,
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,138 @@
// "Flying toasters" example for PicoDVI library. If just starting out,
// see the 8bit_double_buffer which explains the PicoDVI groundwork.
// Comments in THIS file are mostly distinct & new concepts.
// IF NO OUTPUT OR RED FLICKER SCANLINES: try Tools->Optimize->(-O3)
#include <PicoDVI.h>
#include "sprites.h" // Graphics data
DVIGFX8 display(DVI_RES_320x240p60, true, adafruit_feather_dvi_cfg);
// See notes in 8bit_double_buffer regarding 400x240 mode.
//DVIGFX8 display(DVI_RES_400x240p60, true, adafruit_feather_dvi_cfg);
// Also requires -O3 setting.
// This structure holds pointers to sprite graphics and masks in sprites.h.
// First 8 are toasters, last 3 are toast.
const struct {
const uint8_t *sprite;
const uint8_t *mask;
} spritedata[] = {
{ toaster0, toaster0_mask}, // There are really only 4 unique frames
{ toaster1, toaster1_mask}, // of toaster flapping. Instead of code to
{ toaster2, toaster2_mask}, // handle the back-and-forth motion, just
{ toaster3, toaster3_mask}, // refer to frames in the desired sequence.
{ toaster3, toaster3_mask}, // This also doubles up the first and last
{ toaster2, toaster2_mask}, // frames to create a small pause at those
{ toaster1, toaster1_mask}, // points in the loop.
{ toaster0, toaster0_mask},
{ toast0 , toast_mask}, // Light,
{ toast1 , toast_mask}, // medium and
{ toast2 , toast_mask}, // dark toast - all use the same mask.
};
// 12 sprites seems to be about the limit for this code to maintain
// consistent 60 frames/sec updates. Double-buffered graphics synchronize
// to display refresh, and if something can't complete in one frame,
// everything is stalled until the next. It's especially annoying in
// edge cases with some frames take 1/60 sec but others take 1/30.
// See notes at end of file regarding potential improvements.
#define N_SPRITES 12
// This structure contains positions and other data for the sprites
// in motion (notice it's not "const", because contents change).
struct {
int16_t pos[2]; // sprite position (X,Y) * 16
int8_t speed; // sprite speed
uint8_t frame; // for animation
} sprite[N_SPRITES];
// Initialize one sprite (index passed to function) to a random offscreen
// position, also randomizing speed and sprite type (toaster or toast).
void randomsprite(uint8_t i) {
// To move the sprites at slightly different speeds, coordinates are
// stored in 1/16 pixel units. When drawing, the stored values get
// divided by 16 to yield final pixel coordinates.
sprite[i].pos[0] = display.width() * 16; // Off right edge
sprite[i].pos[1] = random(-display.width() / 2, display.height()) * 16;
sprite[i].speed = random(8, 17); // Move 1/2 to 1 pixel per frame
// The spritedata array has 8 toaster frames and 3 toasts; just picking
// one randomly gives us 8/11 odds of a toaster (with a random initial
// wing position) and 3/11 of toast (with random done-ness), good mix.
sprite[i].frame = random(sizeof spritedata / sizeof spritedata[0]);
}
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);
}
// Initialize color palette from table in sprites.h. Rather than
// calling setColor() for each one, we can just dump it directly...
memcpy(display.getPalette(), palette, sizeof palette);
display.swap(false, true); // Duplicate same palette to front & back buffers
// Randomize initial sprite states
randomSeed(analogRead(A0)); // Seed randomness from unused analog in
for (int i=0; i<N_SPRITES; i++) randomsprite(i);
}
uint8_t flap = 0; // Counter for flapping animation
void loop() { // Runs once every frame
display.fillScreen(0); // Clear back framebuffer,
for (int i=0; i<N_SPRITES; i++) { // and draw each sprite there...
// Although DVIGFX8 is a COLOR display type, we leverage GFX's
// drawGrayscaleBitmap() function to draw the sprites...it saves us
// writing a ton of code this way. See notes at end of this file.
// Also here's the "divide position by 16" mentioned earlier:
display.drawGrayscaleBitmap(sprite[i].pos[0] / 16, sprite[i].pos[1] / 16,
spritedata[sprite[i].frame].sprite, spritedata[sprite[i].frame].mask,
64, 64); // All sprites are 64x64 to simplify this code
// After drawing each sprite, update its position
sprite[i].pos[0] -= sprite[i].speed; // Move left
sprite[i].pos[1] += sprite[i].speed / 2; // Move down (X:Y 2:1 ratio)
// Every fourth video frame, IF this sprite is a toaster (frame is 0-7),
// increment the sprite index and wrap around back to 0 if necessary...
if ((!(flap & 3)) && (sprite[i].frame < 8)) {
sprite[i].frame = (sprite[i].frame + 1) & 7; // Loop 0-7
} // else is video frame 1-3 or is toast (not animated)
// If the sprite has moved off the left or bottom edges, reassign it:
if ((sprite[i].pos[0] < -64 * 16) || (sprite[i].pos[1] > display.height() * 16))
randomsprite(i);
}
// Swap front/back buffers, do not duplicate current screen state
// to next frame, we'll draw it new from scratch each time.
display.swap();
flap++; // Increment animation counter; "rolls over" 0-255 automatically.
}
/*
NOTES ON EFFICIENCY
This was written to be a silly and somewhat simple example. No care is
taken to minimize program size or speed, so it's NOT a good role model
for complex situations, but it was quick to produce. Given time and effort,
what could be improved?
- As written, every sprite is 64x64 pixels, period. Makes it very easy to
draw. Flash space could be saved by cropping each sprite to a minimum
bounding rectangle...tradeoff being there would need to be a table of
sizes and X/Y offsets to maintain consistent motion when animating.
Demo's using ~230K -- just a fraction of available flash -- and life is
short so it's just not a priority here.
- The GFX library's drawGrayscaleBitmap() function is used because it's
there and works for our needs, but is not especially efficient (testing
clipping on every pixel) and expects 1 byte/pixel data. Since this demo's
sprites are all 16-color, "packing" 2 pixels/byte is possible, using half
as much flash. A function could be written both to handle clipping more
efficiently and to de-pack and draw sprite data straight to framebuffer,
but would likely increase source code 2-3X and confuse novices.
- The sprite data is all stored in flash memory, which is slower to access
than RAM. RAM is scarce (perhaps ~64K after PicoDVI claims a framebuffer),
but the sprites might still fit, especially if packed 2 pixels/byte. It's
not a bottleneck now AS WRITTEN (due to drawGrayscaleBitmap() itself being
a bit pokey), but if sprite-drawing were handled as mentioned above, could
be possible to increase the sprite count while maintaining frame rate by
adding the __not_in_flash attribute to these tables (see Pico SDK docs).
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,205 @@
// "TV host" example for PicoDVI library. If just starting out,
// see the 8bit_double_buffer which explains the PicoDVI groundwork.
// Comments in THIS file are mostly distinct & new concepts.
// IF NO OUTPUT OR RED FLICKER SCANLINES: try Tools->Optimize->(-O3)
#include <PicoDVI.h>
#include "sprites.h" // Graphics data
DVIGFX8 display(DVI_RES_320x240p60, true, adafruit_feather_dvi_cfg);
// See notes in 8bit_double_buffer regarding 400x240 mode.
//DVIGFX8 display(DVI_RES_400x240p60, true, adafruit_feather_dvi_cfg);
// Also requires -O3 setting.
#define SPRITE_WIDTH 256
#define SPRITE_HEIGHT 207
// This structure holds pointers to sprite graphics and masks in sprites.h.
const struct {
const uint8_t *sprite;
const uint8_t *mask;
} spritedata[] = {
{ sprite0 , mask0 },
{ sprite1 , mask1 },
{ sprite2 , mask2 },
{ sprite3 , mask3 },
{ sprite4 , mask4 },
{ sprite5 , mask5 },
{ sprite6 , mask6 },
{ sprite7 , mask7 },
{ sprite8 , mask8 },
{ sprite9 , mask9 },
{ sprite10, mask10 },
{ sprite11, mask11 },
{ sprite12, mask12 },
{ sprite13, mask13 },
{ sprite14, mask14 },
{ sprite15, mask15 },
{ sprite16, mask16 }
};
#define NUM_SPRITES (sizeof spritedata / sizeof spritedata[0])
// Spinning cube implements 3D rotation & projection, but takes every
// mathematical shortcut; not recommended as a starting point for proper
// 3D drawing. Check out Wikipedia, Foley & Van Dam, etc.
#define STEPS 20 // Number of lines between cube edges
#define CAM_Z 1.8 // Camera position along Z axis; approx sqrt(3) * 1.05
float scale; // Calc'd once per frame for in/out bounce effect
float min_scale = sqrt((display.width() * display.width() + display.height() * display.height()) / 4) / M_SQRT2 * 2.0;
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);
}
// Initialize color palette from table in sprites.h. Rather than
// calling setColor() for each one, we can just dump it directly...
memcpy(display.getPalette(), palette, sizeof palette);
// And then override the last few entries for our background cube...
display.setColor(0, 0, 0, 0); // Black background
display.setColor(253, 255, 0, 255); // Index 253 = magenta
display.setColor(254, 0, 255, 255); // Index 254 = cyan
display.setColor(255, 255, 255, 0); // Index 255 = yellow
display.swap(false, true); // Duplicate same palette into front & back buffers
}
const float corners[8][3] = { // Cube vertices in original coord space
{ -1, -1, -1 },
{ 1, -1, -1 },
{ -1, 1, -1 },
{ 1, 1, -1 },
{ -1, -1, 1 },
{ 1, -1, 1 },
{ -1, 1, 1 },
{ 1, 1, 1 },
};
float rotated[8][3]; // Cube vertices after rotation applied
// (Cam is stationary, cube is transformed, rather than other way around)
// Draw one face of the cube, if it's visible (not back-facing).
// Some points & doubled-up lines could be avoided with more care,
// but code would be somewhat longer. Not a bottleneck here, so...
void face(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4, uint8_t p5, uint8_t color) {
// p1-p4 are indices of 4 corners, p5 is a perpendicular point (surface normal)
float vx = rotated[p1][0]; // Vector from cam to first point
float vy = rotated[p1][1]; // (not normalized)
float vz = rotated[p1][2] - CAM_Z;
float nx = rotated[p5][0] - rotated[p1][0]; // Surface normal
float ny = rotated[p5][1] - rotated[p1][1]; // (not normalized)
float nz = rotated[p5][2] - rotated[p1][2];
// Dot product of vectors. Since only the sign of the result is needed
// below, the two vectors do not require normalization first.
float dot = vx * nx + vy * ny + vz * nz;
if (dot < 0) { // Facing camera?
for(int i=0; i<STEPS; i++) { // Interpolate parallel lines...
float s1 = (float)i / (float)(STEPS - 1); // Weighting of p1, p3
float s2 = 1.0 - s1; // Weighting of p2, p4
// Interpolate between p1, p2
float t1x = rotated[p1][0] * s1 + rotated[p2][0] * s2;
float t1y = rotated[p1][1] * s1 + rotated[p2][1] * s2;
float t1z = rotated[p1][2] * s1 + rotated[p2][2] * s2;
// Interpolate between p3, p4
float t2x = rotated[p3][0] * s1 + rotated[p4][0] * s2;
float t2y = rotated[p3][1] * s1 + rotated[p4][1] * s2;
float t2z = rotated[p3][2] * s1 + rotated[p4][2] * s2;
// Project interpolated endpoints to image plane @ Z=0
float dz = t1z - CAM_Z; // Camera to point
int x1 = display.width() / 2 + int(t1x / dz * scale);
int y1 = display.height() / 2 + int(t1y / dz * scale);
dz = t2z - CAM_Z; // Camera to point
int x2 = display.width() / 2 + int(t2x / dz * scale);
int y2 = display.height() / 2 + int(t2y / dz * scale);
display.drawLine(x1, y1, x2, y2, color);
}
}
}
uint8_t frame = 0; // For animation timing
bool stutter = false; // If true, doing A/B stutter animation
uint32_t duration = 3000; // Time to hold current mode, in milliseconds
uint32_t lastModeSwitchTime = 0;
uint8_t var[2] = { 4, 4 }; // Mode-specific variables
uint8_t spritenum = 0; // Active sprite index
void loop() { // Runs once every frame
display.fillScreen(0); // Clear back framebuffer, will do full redraw...
// This does the in & out bounce effect (bit of a cheat but less math
// than moving camera in & out. Cam stays in one position just far
// enough that it's never inside cube, need not handle Z clipping.)
scale = min_scale * (1.0 + (float)abs((long)(millis() & 4095) - 2048) / 8192.0); // 1.0-1.25X
// Rotate cube vertices from corners[] to rotated[]
float now = millis() / 1000.0; // Elapsed time in seconds
float rx = now * -0.19; // X, Y, Z rotation
float ry = now * 0.23;
float rz = now * 0.13;
float cx = cos(rx);
float cy = cos(ry);
float cz = cos(rz);
float sx = sin(rx);
float sy = sin(ry);
float sz = sin(rz);
for (int i=0; i<8; i++) {
float x1 = corners[i][0];
float y1 = corners[i][1];
float z1 = corners[i][2];
float y2 = y1 * cx - z1 * sx;
float z2 = y1 * sx + z1 * cx;
float x2 = x1 * cy - z2 * sy;
float z3 = x1 * sy + z2 * cy;
float x3 = x2 * cz - y2 * sz;
float y3 = x2 * sz + y2 * cz;
rotated[i][0] = x3;
rotated[i][1] = y3;
rotated[i][2] = z3;
}
face(0, 1, 4, 5, 2, 253); // Test & draw 6 faces of cube
face(0, 2, 4, 6, 1, 254);
face(2, 3, 6, 7, 0, 253);
face(1, 3, 5, 7, 0, 254);
face(0, 1, 2, 3, 4, 255);
face(4, 5, 6, 7, 0, 255);
// Check if switching in/out of stutter mode
if ((millis() - lastModeSwitchTime) >= duration) { // Time to switch?
lastModeSwitchTime = millis(); // Note time,
stutter = !stutter; // and make the switch
if (stutter) { // If entering stutter mode...
duration = random(250, 500); // Go for 1/4 to 1/2 second
var[0] = random(NUM_SPRITES); // Pick 2 different sprites
var[1] = (var[0] + 1 + random(NUM_SPRITES - 1)) % NUM_SPRITES;
} else { // Returning to regular mode...
duration = random(2000, 5000); // Go for 2-5 seconds
var[0] = random(3, 6); // Hold each pose for 3-5 frames
}
}
// Choose sprite to display based on current mode...
if (stutter) {
// Every second frame, alternate between two sprites
spritenum = var[((frame >> 1) & 1)];
} else {
// Pick among random frames (may repeat, is OK)
if (!(frame % var[0])) {
spritenum = random(NUM_SPRITES);
}
}
// Overlay big sprite. Although DVIGFX8 is a COLOR display type,
// we leverage GFX's drawGrayscaleBitmap() function to draw it...
// saves us writing a ton of code this way.
display.drawGrayscaleBitmap((display.width() - SPRITE_WIDTH) / 2,
display.height() - SPRITE_HEIGHT, spritedata[spritenum].sprite,
spritedata[spritenum].mask, SPRITE_WIDTH, SPRITE_HEIGHT);
// Swap front/back buffers, do not duplicate current screen state
// to next frame, we'll draw it new from scratch each time.
display.swap();
frame++; // For animation timing; wraps around 0-255
}