A Library for the Gameduino shield

Dependencies:   Arduino

Dependents:   Gameduino_Asteroids_game Gameduino_Ball_demo Gameduino_Bitmap_demo Gameduino_chessboard_demo ... more

This is a library for the Gameduino, a shield for the Arduino. It uses a secondary library to recreate the arduino functionality. This is to keep this library as close to the original as possible. The original was released by James Bowman, who designed the Gameduino. His webpage (http://excamera.com/sphinx/gameduino/) has tutorials and plenty of other information on the Gameduino. I have published a lot of the demos on his page and they can be found here:

Asteroids:

Import programGameduino_Asteroids_game

Asteroids game using a Gameduino

Ball demo:

Import programGameduino_Ball_demo

Bouncing ball demo for the Gameduino

Bitmap demo:

Import programGameduino_Bitmap_demo

Bitmap demo for the Gameduino

Chessboard demo:

Import programGameduino_chessboard_demo

Chessboard demo for the Gameduino

Collision demo:

Import programGameduino_collision_demo

Collision demo for the Gameduino

Frogger game:

Import programGameduino_Frogger_game

Frogger game for the Gameduino

jkcollision demo:

Import programGameduino_jkcollision_demo

jkcollision demo for the Gameduino

Joystick test:

Import programGameduino_Joystick_test

Joystick test program for the Gameduino

Manic miner game:

Import programGameduino_Manic_Miner_game

Manic miner game for the Gameduino

Palettes demo:

Import programGameduino_Palettes_demo

Palettes demo for the Gameduino

Rotate demo:

Import programGameduino_Rotate_demo

Sprite rotation demo for the Gameduino

Screenshot demo:

Import programGameduino_screenshot_test

Screen shot demo and test program for the Gameduino

This needs to run a python script, more information and the script can be found on the gameduino site.

Scroll demo:

Import programGameduino_Scroll_demo

Scroll demo for the Gameduino

snow demo:

Import programGameduino_Snow_demo

White noise demo for the Gameduino

spinning dna demo:

Import programGameduino_Spinning_DNA_demo

Spinning dna graphics demo for the Gameduino

split screen demo:

Import programGameduino_Split_Screen_demo

Split screen graphics demo for the Gameduino

256 sprites demo:

Import programGameduino_Sprites256_demo

Sprite control demo for the Gameduino

I've also ported Invaders, written for the arduino by Colin (couldn't find his surname) and can be found at http://www.artlum.com/gameduino/gameduino.html:

Import programGameduino_Invaders_game

Invaders game for the Gameduino

and made a template for gameduino based projects. I have used an mbeduino board and have included a a file shield.h which contains the pinouts for this board. This can easily be modified to your needs. As a default I have chosen to use pull ups on the joystick inputs and switch down to 0V. This can be quickly altered and this is at the top of most main.c files, with the exception of invaders. This has more configuration options in the joystick files.

Committer:
TheChrisyd
Date:
Thu Dec 20 23:02:36 2012 +0000
Revision:
4:84c1ca3e1be0
Parent:
0:c9523256df08
Updated Arduino library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TheChrisyd 0:c9523256df08 1 /**
TheChrisyd 0:c9523256df08 2 * @section LICENSE
TheChrisyd 0:c9523256df08 3 * Copyright (c) 2012 James Bowman, Chris Dick
TheChrisyd 0:c9523256df08 4 *
TheChrisyd 0:c9523256df08 5 * Permission is hereby granted, free of charge, to any person obtaining a copy
TheChrisyd 0:c9523256df08 6 * of this software and associated documentation files (the "Software"), to deal
TheChrisyd 0:c9523256df08 7 * in the Software without restriction, including without limitation the rights
TheChrisyd 0:c9523256df08 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
TheChrisyd 0:c9523256df08 9 * copies of the Software, and to permit persons to whom the Software is
TheChrisyd 0:c9523256df08 10 * furnished to do so, subject to the following conditions:
TheChrisyd 0:c9523256df08 11 *
TheChrisyd 0:c9523256df08 12 * The above copyright notice and this permission notice shall be included in
TheChrisyd 0:c9523256df08 13 * all copies or substantial portions of the Software.
TheChrisyd 0:c9523256df08 14 *
TheChrisyd 0:c9523256df08 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
TheChrisyd 0:c9523256df08 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
TheChrisyd 0:c9523256df08 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
TheChrisyd 0:c9523256df08 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
TheChrisyd 0:c9523256df08 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
TheChrisyd 0:c9523256df08 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
TheChrisyd 0:c9523256df08 21 * THE SOFTWARE.
TheChrisyd 0:c9523256df08 22 *
TheChrisyd 0:c9523256df08 23 * @section DESCRIPTION
TheChrisyd 0:c9523256df08 24 * Copyright (c) 2011 by James Bowman <jamesb@excamera.com>
TheChrisyd 0:c9523256df08 25 * Gameduino library for mbed. Ported from Arduino by Chris Dick
TheChrisyd 0:c9523256df08 26 *
TheChrisyd 0:c9523256df08 27 *
TheChrisyd 0:c9523256df08 28 *
TheChrisyd 0:c9523256df08 29 *
TheChrisyd 0:c9523256df08 30 */
TheChrisyd 0:c9523256df08 31
TheChrisyd 0:c9523256df08 32 #include "GD.h"
TheChrisyd 0:c9523256df08 33
TheChrisyd 0:c9523256df08 34 GDClass::GDClass(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName utx, PinName urx)
TheChrisyd 0:c9523256df08 35 : gameduino_spi(mosi, miso, sclk)
TheChrisyd 0:c9523256df08 36 , gameduino_cs(cs)
TheChrisyd 0:c9523256df08 37 , pc(utx, urx) {
TheChrisyd 0:c9523256df08 38
TheChrisyd 0:c9523256df08 39 }
TheChrisyd 0:c9523256df08 40
TheChrisyd 0:c9523256df08 41 void GDClass::begin()
TheChrisyd 0:c9523256df08 42 {
TheChrisyd 0:c9523256df08 43 delay(250); // give Gameduino time to boot
TheChrisyd 0:c9523256df08 44 gameduino_spi.format(8,0);
TheChrisyd 0:c9523256df08 45 gameduino_spi.frequency(8000000);
TheChrisyd 0:c9523256df08 46
TheChrisyd 0:c9523256df08 47
TheChrisyd 0:c9523256df08 48 gameduino_cs = 1;
TheChrisyd 0:c9523256df08 49
TheChrisyd 0:c9523256df08 50 wr(J1_RESET, 1); // HALT coprocessor
TheChrisyd 0:c9523256df08 51 __wstart(RAM_SPR); // Hide all sprites
TheChrisyd 0:c9523256df08 52 for (int i = 0; i < 512; i++)
TheChrisyd 0:c9523256df08 53 {
TheChrisyd 0:c9523256df08 54 xhide();
TheChrisyd 0:c9523256df08 55 }
TheChrisyd 0:c9523256df08 56 __end();
TheChrisyd 0:c9523256df08 57 fill(RAM_PIC, 0, 1024 * 10); // Zero all character RAM
TheChrisyd 0:c9523256df08 58 fill(RAM_SPRPAL, 0, 2048); // Sprite palletes black
TheChrisyd 0:c9523256df08 59 fill(RAM_SPRIMG, 0, 64 * 256); // Clear all sprite data
TheChrisyd 0:c9523256df08 60 fill(VOICES, 0, 256); // Silence
TheChrisyd 0:c9523256df08 61 fill(PALETTE16A, 0, 128); // Black 16-, 4-palletes and COMM
TheChrisyd 0:c9523256df08 62
TheChrisyd 0:c9523256df08 63 wr16(SCROLL_X, 0);
TheChrisyd 0:c9523256df08 64 wr16(SCROLL_Y, 0);
TheChrisyd 0:c9523256df08 65 wr(JK_MODE, 0);
TheChrisyd 0:c9523256df08 66 wr(SPR_DISABLE, 0);
TheChrisyd 0:c9523256df08 67 wr(SPR_PAGE, 0);
TheChrisyd 0:c9523256df08 68 wr(IOMODE, 0);
TheChrisyd 0:c9523256df08 69 wr16(BG_COLOR, 0);
TheChrisyd 0:c9523256df08 70 wr16(SAMPLE_L, 0);
TheChrisyd 0:c9523256df08 71 wr16(SAMPLE_R, 0);
TheChrisyd 0:c9523256df08 72 wr16(SCREENSHOT_Y, 0);
TheChrisyd 0:c9523256df08 73 wr(MODULATOR, 64);
TheChrisyd 0:c9523256df08 74 }
TheChrisyd 0:c9523256df08 75
TheChrisyd 0:c9523256df08 76 void GDClass::end() {
TheChrisyd 0:c9523256df08 77 }
TheChrisyd 0:c9523256df08 78
TheChrisyd 0:c9523256df08 79 void GDClass::__start(unsigned int addr) // start an spi transaction to addr
TheChrisyd 0:c9523256df08 80 {
TheChrisyd 0:c9523256df08 81 gameduino_cs = 0;
TheChrisyd 0:c9523256df08 82 gameduino_spi.write(highByte(addr));
TheChrisyd 0:c9523256df08 83 gameduino_spi.write(lowByte(addr));
TheChrisyd 0:c9523256df08 84 }
TheChrisyd 0:c9523256df08 85
TheChrisyd 0:c9523256df08 86 void GDClass::__wstart(unsigned int addr) // start an spi write transaction to addr
TheChrisyd 0:c9523256df08 87 {
TheChrisyd 0:c9523256df08 88 __start(0x8000|addr);
TheChrisyd 0:c9523256df08 89 }
TheChrisyd 0:c9523256df08 90
TheChrisyd 0:c9523256df08 91 void GDClass::__wstartspr(unsigned int sprnum)
TheChrisyd 0:c9523256df08 92 {
TheChrisyd 0:c9523256df08 93 __start((0x8000 | RAM_SPR) + (sprnum << 2));
TheChrisyd 0:c9523256df08 94 spr = 0;
TheChrisyd 0:c9523256df08 95 }
TheChrisyd 0:c9523256df08 96
TheChrisyd 0:c9523256df08 97 void GDClass::__end() // end the spi transaction
TheChrisyd 0:c9523256df08 98 {
TheChrisyd 0:c9523256df08 99 gameduino_cs = 1;
TheChrisyd 0:c9523256df08 100 }
TheChrisyd 0:c9523256df08 101
TheChrisyd 0:c9523256df08 102 byte GDClass::rd(unsigned int addr)
TheChrisyd 0:c9523256df08 103 {
TheChrisyd 0:c9523256df08 104 __start(addr);
TheChrisyd 0:c9523256df08 105 byte r = gameduino_spi.write(0);
TheChrisyd 0:c9523256df08 106 __end();
TheChrisyd 0:c9523256df08 107 return r;
TheChrisyd 0:c9523256df08 108 }
TheChrisyd 0:c9523256df08 109
TheChrisyd 0:c9523256df08 110 void GDClass::wr(unsigned int addr, byte v)
TheChrisyd 0:c9523256df08 111 {
TheChrisyd 0:c9523256df08 112 __wstart(addr);
TheChrisyd 0:c9523256df08 113 gameduino_spi.write(v);
TheChrisyd 0:c9523256df08 114 __end();
TheChrisyd 0:c9523256df08 115 }
TheChrisyd 0:c9523256df08 116
TheChrisyd 0:c9523256df08 117 unsigned int GDClass::rd16(unsigned int addr)
TheChrisyd 0:c9523256df08 118 {
TheChrisyd 0:c9523256df08 119 unsigned int r;
TheChrisyd 0:c9523256df08 120
TheChrisyd 0:c9523256df08 121 __start(addr);
TheChrisyd 0:c9523256df08 122 r = gameduino_spi.write(0);
TheChrisyd 0:c9523256df08 123 r |= (gameduino_spi.write(0) << 8);
TheChrisyd 0:c9523256df08 124 __end();
TheChrisyd 0:c9523256df08 125 return r;
TheChrisyd 0:c9523256df08 126 }
TheChrisyd 0:c9523256df08 127
TheChrisyd 0:c9523256df08 128 void GDClass::wr16(unsigned int addr, unsigned int v)
TheChrisyd 0:c9523256df08 129 {
TheChrisyd 0:c9523256df08 130 __wstart(addr);
TheChrisyd 0:c9523256df08 131 gameduino_spi.write(lowByte(v));
TheChrisyd 0:c9523256df08 132 gameduino_spi.write(highByte(v));
TheChrisyd 0:c9523256df08 133 __end();
TheChrisyd 0:c9523256df08 134 }
TheChrisyd 0:c9523256df08 135
TheChrisyd 0:c9523256df08 136 void GDClass::fill(int addr, byte v, unsigned int count)
TheChrisyd 0:c9523256df08 137 {
TheChrisyd 0:c9523256df08 138 __wstart(addr);
TheChrisyd 0:c9523256df08 139 while (count--)
TheChrisyd 0:c9523256df08 140 gameduino_spi.write(v);
TheChrisyd 0:c9523256df08 141 __end();
TheChrisyd 0:c9523256df08 142 }
TheChrisyd 0:c9523256df08 143
TheChrisyd 0:c9523256df08 144 void GDClass::copy(unsigned int addr, PROGMEM prog_uchar *src, int count)
TheChrisyd 0:c9523256df08 145 {
TheChrisyd 0:c9523256df08 146 __wstart(addr);
TheChrisyd 0:c9523256df08 147 while (count--) {
TheChrisyd 0:c9523256df08 148 gameduino_spi.write(pgm_read_byte_near(src));
TheChrisyd 0:c9523256df08 149 src++;
TheChrisyd 0:c9523256df08 150 }
TheChrisyd 0:c9523256df08 151 __end();
TheChrisyd 0:c9523256df08 152 }
TheChrisyd 0:c9523256df08 153
TheChrisyd 0:c9523256df08 154
TheChrisyd 0:c9523256df08 155
TheChrisyd 0:c9523256df08 156 void GDClass::microcode(PROGMEM prog_uchar *src, int count)
TheChrisyd 0:c9523256df08 157 {
TheChrisyd 0:c9523256df08 158 wr(J1_RESET, 1);
TheChrisyd 0:c9523256df08 159 copy(J1_CODE, src, count);
TheChrisyd 0:c9523256df08 160 wr(J1_RESET, 0);
TheChrisyd 0:c9523256df08 161 }
TheChrisyd 0:c9523256df08 162
TheChrisyd 0:c9523256df08 163
TheChrisyd 0:c9523256df08 164
TheChrisyd 0:c9523256df08 165 void GDClass::setpal(int pal, unsigned int rgb)
TheChrisyd 0:c9523256df08 166 {
TheChrisyd 0:c9523256df08 167 wr16(RAM_PAL + (pal << 1), rgb);
TheChrisyd 0:c9523256df08 168 }
TheChrisyd 0:c9523256df08 169
TheChrisyd 0:c9523256df08 170 void GDClass::sprite(int spr, int x, int y, byte image, byte palette, byte rot, byte jk)
TheChrisyd 0:c9523256df08 171 {
TheChrisyd 0:c9523256df08 172 __wstart(RAM_SPR + (spr << 2));
TheChrisyd 0:c9523256df08 173 gameduino_spi.write(lowByte(x));
TheChrisyd 0:c9523256df08 174 gameduino_spi.write((palette << 4) | (rot << 1) | (highByte(x) & 1));
TheChrisyd 0:c9523256df08 175 gameduino_spi.write(lowByte(y));
TheChrisyd 0:c9523256df08 176 gameduino_spi.write((jk << 7) | (image << 1) | (highByte(y) & 1));
TheChrisyd 0:c9523256df08 177 __end();
TheChrisyd 0:c9523256df08 178 }
TheChrisyd 0:c9523256df08 179
TheChrisyd 0:c9523256df08 180 void GDClass::xsprite(int ox, int oy, signed char x, signed char y, byte image, byte palette, byte rot, byte jk)
TheChrisyd 0:c9523256df08 181 {
TheChrisyd 0:c9523256df08 182 if (rot & 2)
TheChrisyd 0:c9523256df08 183 x = -16-x;
TheChrisyd 0:c9523256df08 184 if (rot & 4)
TheChrisyd 0:c9523256df08 185 y = -16-y;
TheChrisyd 0:c9523256df08 186 if (rot & 1) {
TheChrisyd 0:c9523256df08 187 int s;
TheChrisyd 0:c9523256df08 188 s = x; x = y; y = s;
TheChrisyd 0:c9523256df08 189 }
TheChrisyd 0:c9523256df08 190 ox += x;
TheChrisyd 0:c9523256df08 191 oy += y;
TheChrisyd 0:c9523256df08 192 gameduino_spi.write(lowByte(ox));
TheChrisyd 0:c9523256df08 193 gameduino_spi.write((palette << 4) | (rot << 1) | (highByte(ox) & 1));
TheChrisyd 0:c9523256df08 194 gameduino_spi.write(lowByte(oy));
TheChrisyd 0:c9523256df08 195 gameduino_spi.write((jk << 7) | (image << 1) | (highByte(oy) & 1));
TheChrisyd 0:c9523256df08 196 spr++;
TheChrisyd 0:c9523256df08 197 }
TheChrisyd 0:c9523256df08 198
TheChrisyd 0:c9523256df08 199 void GDClass::xhide()
TheChrisyd 0:c9523256df08 200 {
TheChrisyd 0:c9523256df08 201 gameduino_spi.write(lowByte(400));
TheChrisyd 0:c9523256df08 202 gameduino_spi.write(highByte(400));
TheChrisyd 0:c9523256df08 203 gameduino_spi.write(lowByte(400));
TheChrisyd 0:c9523256df08 204 gameduino_spi.write(highByte(400));
TheChrisyd 0:c9523256df08 205 spr++;
TheChrisyd 0:c9523256df08 206 }
TheChrisyd 0:c9523256df08 207
TheChrisyd 0:c9523256df08 208 void GDClass::plots(int ox, int oy, PROGMEM sprplot *psp, byte count, byte rot, byte jk)
TheChrisyd 0:c9523256df08 209 {
TheChrisyd 0:c9523256df08 210 while (count--) {
TheChrisyd 0:c9523256df08 211 struct sprplot sp;
TheChrisyd 0:c9523256df08 212 sp = *psp++;
TheChrisyd 0:c9523256df08 213 xsprite(ox, oy, sp.x, sp.y, sp.image, sp.palette, rot, jk);
TheChrisyd 0:c9523256df08 214 }
TheChrisyd 0:c9523256df08 215 }
TheChrisyd 0:c9523256df08 216
TheChrisyd 0:c9523256df08 217 void GDClass::sprite2x2(int spr, int x, int y, byte image, byte palette, byte rot, byte jk)
TheChrisyd 0:c9523256df08 218 {
TheChrisyd 0:c9523256df08 219 __wstart(0x3000 + (spr << 2));
TheChrisyd 0:c9523256df08 220 xsprite(x, y, -16, -16, image + 0, palette, rot, jk);
TheChrisyd 0:c9523256df08 221 xsprite(x, y, 0, -16, image + 1, palette, rot, jk);
TheChrisyd 0:c9523256df08 222 xsprite(x, y, -16, 0, image + 2, palette, rot, jk);
TheChrisyd 0:c9523256df08 223 xsprite(x, y, 0, 0, image + 3, palette, rot, jk);
TheChrisyd 0:c9523256df08 224 __end();
TheChrisyd 0:c9523256df08 225 }
TheChrisyd 0:c9523256df08 226
TheChrisyd 0:c9523256df08 227 void GDClass::waitvblank()
TheChrisyd 0:c9523256df08 228 {
TheChrisyd 0:c9523256df08 229 // Wait for the VLANK to go from 0 to 1: this is the start
TheChrisyd 0:c9523256df08 230 // of the vertical blanking interval.
TheChrisyd 0:c9523256df08 231
TheChrisyd 0:c9523256df08 232 while (rd(VBLANK) == 1)
TheChrisyd 0:c9523256df08 233 ;
TheChrisyd 0:c9523256df08 234 while (rd(VBLANK) == 0)
TheChrisyd 0:c9523256df08 235 ;
TheChrisyd 0:c9523256df08 236 }
TheChrisyd 0:c9523256df08 237
TheChrisyd 0:c9523256df08 238 /* Fixed ascii font, useful for debug */
TheChrisyd 0:c9523256df08 239
TheChrisyd 0:c9523256df08 240 #include "font8x8.h"
TheChrisyd 0:c9523256df08 241 static byte stretch[16] = {
TheChrisyd 0:c9523256df08 242 0x00, 0x03, 0x0c, 0x0f,
TheChrisyd 0:c9523256df08 243 0x30, 0x33, 0x3c, 0x3f,
TheChrisyd 0:c9523256df08 244 0xc0, 0xc3, 0xcc, 0xcf,
TheChrisyd 0:c9523256df08 245 0xf0, 0xf3, 0xfc, 0xff
TheChrisyd 0:c9523256df08 246 };
TheChrisyd 0:c9523256df08 247
TheChrisyd 0:c9523256df08 248
TheChrisyd 0:c9523256df08 249 void GDClass::ascii()
TheChrisyd 0:c9523256df08 250 {
TheChrisyd 0:c9523256df08 251 long i;
TheChrisyd 0:c9523256df08 252 for (i = 0; i < 768; i++) {
TheChrisyd 0:c9523256df08 253 byte b = font8x8[i];
TheChrisyd 0:c9523256df08 254 byte h = stretch[b >> 4];
TheChrisyd 0:c9523256df08 255 byte l = stretch[b & 0xf];
TheChrisyd 0:c9523256df08 256 wr(0x1000 + (16 * ' ') + (2 * i), h);
TheChrisyd 0:c9523256df08 257 wr(0x1000 + (16 * ' ') + (2 * i) + 1, l);
TheChrisyd 0:c9523256df08 258 }
TheChrisyd 0:c9523256df08 259 for (i = 0x20; i < 0x80; i++) {
TheChrisyd 0:c9523256df08 260 setpal(4 * i + 0, TRANSPARENT);
TheChrisyd 0:c9523256df08 261 setpal(4 * i + 3, RGB(255,255,255));
TheChrisyd 0:c9523256df08 262 }
TheChrisyd 0:c9523256df08 263 fill(RAM_PIC, ' ', 4096);
TheChrisyd 0:c9523256df08 264 }
TheChrisyd 0:c9523256df08 265
TheChrisyd 0:c9523256df08 266 void GDClass::putstr(int x, int y, const char *s)
TheChrisyd 0:c9523256df08 267 {
TheChrisyd 0:c9523256df08 268 __wstart((y << 6) + x);
TheChrisyd 0:c9523256df08 269 while (*s)
TheChrisyd 0:c9523256df08 270 gameduino_spi.write(*s++);
TheChrisyd 0:c9523256df08 271 __end();
TheChrisyd 0:c9523256df08 272 }
TheChrisyd 0:c9523256df08 273
TheChrisyd 0:c9523256df08 274 void GDClass::voice(int v, byte wave, unsigned int freq, byte lamp, byte ramp)
TheChrisyd 0:c9523256df08 275 {
TheChrisyd 0:c9523256df08 276 __wstart(VOICES + (v << 2));
TheChrisyd 0:c9523256df08 277 gameduino_spi.write(lowByte(freq));
TheChrisyd 0:c9523256df08 278 gameduino_spi.write(highByte(freq) | (wave << 7));
TheChrisyd 0:c9523256df08 279 gameduino_spi.write(lamp);
TheChrisyd 0:c9523256df08 280 gameduino_spi.write(ramp);
TheChrisyd 0:c9523256df08 281 __end();
TheChrisyd 0:c9523256df08 282 }
TheChrisyd 0:c9523256df08 283
TheChrisyd 0:c9523256df08 284 void GDClass::screenshot(unsigned int frame)
TheChrisyd 0:c9523256df08 285 {
TheChrisyd 0:c9523256df08 286 int yy, xx;
TheChrisyd 0:c9523256df08 287 byte undone[38]; // 300-long bitmap of lines pending
TheChrisyd 0:c9523256df08 288
TheChrisyd 0:c9523256df08 289 // initialize to 300 ones
TheChrisyd 0:c9523256df08 290 memset(undone, 0xff, 37);
TheChrisyd 0:c9523256df08 291 undone[37] = 0xf;
TheChrisyd 0:c9523256df08 292 int nundone = 300;
TheChrisyd 0:c9523256df08 293
TheChrisyd 0:c9523256df08 294 pc.putc(0xa5); // sync byte
TheChrisyd 0:c9523256df08 295 pc.putc(lowByte(frame));
TheChrisyd 0:c9523256df08 296 pc.putc(highByte(frame));
TheChrisyd 0:c9523256df08 297
TheChrisyd 0:c9523256df08 298 while (nundone) {
TheChrisyd 0:c9523256df08 299 // find a pending line a short distance ahead of the raster
TheChrisyd 0:c9523256df08 300 int hwline = rd16(SCREENSHOT_Y) & 0x1ff;
TheChrisyd 0:c9523256df08 301 for (yy = (hwline + 7) % 300; ((undone[yy>>3] >> (yy&7)) & 1) == 0; yy = (yy + 1) % 300)
TheChrisyd 0:c9523256df08 302 ;
TheChrisyd 0:c9523256df08 303 wr16(SCREENSHOT_Y, 0x8000 | yy); // ask for it
TheChrisyd 0:c9523256df08 304
TheChrisyd 0:c9523256df08 305 // housekeeping while waiting: mark line done and send yy
TheChrisyd 0:c9523256df08 306 undone[yy>>3] ^= (1 << (yy&7));
TheChrisyd 0:c9523256df08 307 nundone--;
TheChrisyd 0:c9523256df08 308 pc.putc(lowByte(yy));
TheChrisyd 0:c9523256df08 309 pc.putc(highByte(yy));
TheChrisyd 0:c9523256df08 310 while ((rd(SCREENSHOT_Y + 1) & 0x80) == 0)
TheChrisyd 0:c9523256df08 311 ;
TheChrisyd 0:c9523256df08 312
TheChrisyd 0:c9523256df08 313 // Now send the line, compressing zero pixels
TheChrisyd 0:c9523256df08 314 uint16_t zeroes = 0;
TheChrisyd 0:c9523256df08 315 for (xx = 0; xx < 800; xx += 2) {
TheChrisyd 0:c9523256df08 316 uint16_t v = rd16(SCREENSHOT + xx);
TheChrisyd 0:c9523256df08 317 if (v == 0) {
TheChrisyd 0:c9523256df08 318 zeroes++;
TheChrisyd 0:c9523256df08 319 } else {
TheChrisyd 0:c9523256df08 320 if (zeroes) {
TheChrisyd 0:c9523256df08 321 pc.putc(lowByte(zeroes));
TheChrisyd 0:c9523256df08 322 pc.putc(0x80 | highByte(zeroes));
TheChrisyd 0:c9523256df08 323 zeroes = 0;
TheChrisyd 0:c9523256df08 324 }
TheChrisyd 0:c9523256df08 325 pc.putc(lowByte(v));
TheChrisyd 0:c9523256df08 326 pc.putc(highByte(v));
TheChrisyd 0:c9523256df08 327 }
TheChrisyd 0:c9523256df08 328 }
TheChrisyd 0:c9523256df08 329 if (zeroes) {
TheChrisyd 0:c9523256df08 330 pc.putc(lowByte(zeroes));
TheChrisyd 0:c9523256df08 331 pc.putc(0x80 | highByte(zeroes));
TheChrisyd 0:c9523256df08 332 }
TheChrisyd 0:c9523256df08 333 }
TheChrisyd 0:c9523256df08 334 wr16(SCREENSHOT_Y, 0); // restore screen to normal
TheChrisyd 0:c9523256df08 335 }
TheChrisyd 0:c9523256df08 336
TheChrisyd 0:c9523256df08 337 class GDflashbits {
TheChrisyd 0:c9523256df08 338 public:
TheChrisyd 0:c9523256df08 339 void begin(PROGMEM prog_uchar *s) {
TheChrisyd 0:c9523256df08 340 src = s;
TheChrisyd 0:c9523256df08 341 mask = 0x01;
TheChrisyd 0:c9523256df08 342 }
TheChrisyd 0:c9523256df08 343 byte get1(void) {
TheChrisyd 0:c9523256df08 344 byte r = (pgm_read_byte_near(src) & mask) != 0;
TheChrisyd 0:c9523256df08 345 mask <<= 1;
TheChrisyd 0:c9523256df08 346 if (!mask) {
TheChrisyd 0:c9523256df08 347 mask = 1;
TheChrisyd 0:c9523256df08 348 src++;
TheChrisyd 0:c9523256df08 349 }
TheChrisyd 0:c9523256df08 350 return r;
TheChrisyd 0:c9523256df08 351 }
TheChrisyd 0:c9523256df08 352 unsigned short getn(byte n) {
TheChrisyd 0:c9523256df08 353 unsigned short r = 0;
TheChrisyd 0:c9523256df08 354 while (n--) {
TheChrisyd 0:c9523256df08 355 r <<= 1;
TheChrisyd 0:c9523256df08 356 r |= get1();
TheChrisyd 0:c9523256df08 357 }
TheChrisyd 0:c9523256df08 358 return r;
TheChrisyd 0:c9523256df08 359 }
TheChrisyd 0:c9523256df08 360 private:
TheChrisyd 0:c9523256df08 361 PROGMEM prog_uchar *src;
TheChrisyd 0:c9523256df08 362 byte mask;
TheChrisyd 0:c9523256df08 363 };
TheChrisyd 0:c9523256df08 364
TheChrisyd 0:c9523256df08 365 static GDflashbits GDFB;
TheChrisyd 0:c9523256df08 366
TheChrisyd 0:c9523256df08 367 void GDClass::uncompress(unsigned int addr, PROGMEM prog_uchar *src)
TheChrisyd 0:c9523256df08 368 {
TheChrisyd 0:c9523256df08 369 GDFB.begin(src);
TheChrisyd 0:c9523256df08 370 byte b_off = GDFB.getn(4);
TheChrisyd 0:c9523256df08 371 byte b_len = GDFB.getn(4);
TheChrisyd 0:c9523256df08 372 byte minlen = GDFB.getn(2);
TheChrisyd 0:c9523256df08 373 unsigned short items = GDFB.getn(16);
TheChrisyd 0:c9523256df08 374 while (items--) {
TheChrisyd 0:c9523256df08 375 if (GDFB.get1() == 0) {
TheChrisyd 0:c9523256df08 376 wr(addr++, GDFB.getn(8));
TheChrisyd 0:c9523256df08 377 } else {
TheChrisyd 0:c9523256df08 378 int offset = -GDFB.getn(b_off) - 1;
TheChrisyd 0:c9523256df08 379 int l = GDFB.getn(b_len) + minlen;
TheChrisyd 0:c9523256df08 380 while (l--) {
TheChrisyd 0:c9523256df08 381 wr(addr, rd(addr + offset));
TheChrisyd 0:c9523256df08 382 addr++;
TheChrisyd 0:c9523256df08 383 }
TheChrisyd 0:c9523256df08 384 }
TheChrisyd 0:c9523256df08 385 }
TheChrisyd 0:c9523256df08 386 }