123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- #include <SPI.h>
- #include <GD.h>
- // 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
- }
|