#include #include // replicate a 2-bit color across the whole byte. Optimization for setpixel byte replicate(byte color) { return (color << 6) | (color << 4) | (color << 2) | color; } // Set pixel at (x,y) to color. (note that color is replicated). void setpixel(byte x, byte y, byte color) { /* Because of the way the sprites are laid out in setup(), it's not too hard to translate the pixel (x,y) to an address and mask. Taking the two byte values as x7-x0 and y7-y0, the address of the pixel is: x5 x4 y7 y6 y5 y4 y3 y2 y1 y0 x3 x2 x1 x0 (x6, x7) gives the value of the mask. */ unsigned int addr = RAM_SPRIMG | (x & 0xf) | (y << 4) | ((x & 0x30) << 8); byte mask = 0xc0 >> ((x >> 5) & 6); GD.wr(addr, (GD.rd(addr) & ~mask) | (color & mask)); } // Draw color line from (x0,y0) to (x1,y1). void line(byte x0, byte y0, byte x1, byte y1, byte color) { byte swap; #define SWAP(a, b) (swap = (a), (a) = (b), (b) = swap) color = replicate(color); byte steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { SWAP(x0, y0); SWAP(x1, y1); } if (x0 > x1) { SWAP(x0, x1); SWAP(y0, y1); } int deltax = x1 - x0; int deltay = abs(y1 - y0); int error = deltax / 2; char ystep; if (y0 < y1) ystep = 1; else ystep = -1; byte x; byte y = y0; for (x = x0; x < x1; x++) { if (steep) setpixel(y, x, color); else setpixel(x, y, color); error -= deltay; if (error < 0) { y += ystep; error += deltax; } } } struct point { int x, y; char xv, yv; }; static struct point triangle[3]; #define RANDOM_RGB() RGB(random(256),random(256),random(256)) // Restart the drawing static void restart() { // Clear the screen GD.fill(RAM_SPRIMG, 0, 16384); // Position triangle at random byte i; for (i = 0; i < 3; i++) { triangle[i].x = 3 + random(250); triangle[i].y = 3 + random(250); } triangle[0].xv = 1; triangle[0].yv = 1; triangle[1].xv = -1; triangle[1].yv = 1; triangle[2].xv = 1; triangle[2].yv = -1; // Choose a random palette GD.wr16(PALETTE4A, RGB(0,0,0)); GD.wr16(PALETTE4A + 2, RANDOM_RGB()); GD.wr16(PALETTE4A + 4, RANDOM_RGB()); GD.wr16(PALETTE4A + 6, RANDOM_RGB()); } void setup() { int i; Serial.begin(1000000); // JCB GD.begin(); GD.ascii(); GD.putstr(0, 0,"Bitmap demonstration"); // Draw 256 sprites left to right, top to bottom, all in 4-color // palette mode. By doing them in column-wise order, the address // calculation in setpixel is made simpler. // First 64 use bits 0-1, next 64 use bits 2-4, etc. // This gives a 256 x 256 4-color bitmap. for (i = 0; i < 256; i++) { int x = 72 + 16 * ((i >> 4) & 15); int y = 22 + 16 * (i & 15); int image = i & 63; /* image 0-63 */ int pal = 3 - (i >> 6); /* palettes bits in columns 3,2,1,0 */ GD.sprite(i, x, y, image, 0x8 | (pal << 1), 0); } restart(); } void loop() { static byte color; if (random(1000) == 0) restart(); line(triangle[0].x, triangle[0].y, triangle[1].x, triangle[1].y, color); line(triangle[1].x, triangle[1].y, triangle[2].x, triangle[2].y, color); line(triangle[2].x, triangle[2].y, triangle[0].x, triangle[0].y, color); color = (color + 1) & 3; byte i; for (i = 0; i < 3; i++) { triangle[i].x += triangle[i].xv; triangle[i].y += triangle[i].yv; if (triangle[i].x == 0 || triangle[i].x == 255) triangle[i].xv = -triangle[i].xv; if (triangle[i].y == 0 || triangle[i].y == 255) triangle[i].yv = -triangle[i].yv; } static int ss; // JCB // GD.screenshot(ss++); // JCB }