Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Gameduino_Asteroids_game Gameduino_Ball_demo Gameduino_Bitmap_demo Gameduino_chessboard_demo ... more
GD.cpp@4:84c1ca3e1be0, 2012-12-20 (annotated)
- 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?
User | Revision | Line number | New 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 | } |