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.
Diff: GD.cpp
- Revision:
- 1:e047847f1cda
- Parent:
- 0:a2d36977aec3
--- a/GD.cpp Sun Aug 05 12:47:00 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2011 by James Bowman <jamesb@excamera.com> - * Gameduino library for mbed. Ported from Arduino by Chris Dick - * - */ - -#include "GD.h" -GDClass GD; -extern DigitalOut cs; -extern SPI spi; // mosi, miso, sclk -extern Serial pc; - - -void GDClass::begin() -{ - delay(250); // give Gameduino time to boot - - spi.format(8,0); - spi.frequency(8000000); - - cs = 1; - - GD.wr(J1_RESET, 1); // HALT coprocessor - __wstart(RAM_SPR); // Hide all sprites - for (int i = 0; i < 512; i++) - GD.xhide(); - __end(); - fill(RAM_PIC, 0, 1024 * 10); // Zero all character RAM - fill(RAM_SPRPAL, 0, 2048); // Sprite palletes black - fill(RAM_SPRIMG, 0, 64 * 256); // Clear all sprite data - fill(VOICES, 0, 256); // Silence - fill(PALETTE16A, 0, 128); // Black 16-, 4-palletes and COMM - - GD.wr16(SCROLL_X, 0); - GD.wr16(SCROLL_Y, 0); - GD.wr(JK_MODE, 0); - GD.wr(SPR_DISABLE, 0); - GD.wr(SPR_PAGE, 0); - GD.wr(IOMODE, 0); - GD.wr16(BG_COLOR, 0); - GD.wr16(SAMPLE_L, 0); - GD.wr16(SAMPLE_R, 0); - GD.wr16(SCREENSHOT_Y, 0); - GD.wr(MODULATOR, 64); -} - -void GDClass::end() { -} - -void GDClass::__start(unsigned int addr) // start an spi transaction to addr -{ - cs = 0; - spi.write(highByte(addr)); - spi.write(lowByte(addr)); -} - -void GDClass::__wstart(unsigned int addr) // start an spi write transaction to addr -{ - __start(0x8000|addr); -} - -void GDClass::__wstartspr(unsigned int sprnum) -{ - __start((0x8000 | RAM_SPR) + (sprnum << 2)); - spr = 0; -} - -void GDClass::__end() // end the spi transaction -{ - cs = 1; -} - -byte GDClass::rd(unsigned int addr) -{ - __start(addr); - byte r = spi.write(0); - __end(); - return r; -} - -void GDClass::wr(unsigned int addr, byte v) -{ - __wstart(addr); - spi.write(v); - __end(); -} - -unsigned int GDClass::rd16(unsigned int addr) -{ - unsigned int r; - - __start(addr); - r = spi.write(0); - r |= (spi.write(0) << 8); - __end(); - return r; -} - -void GDClass::wr16(unsigned int addr, unsigned int v) -{ - __wstart(addr); - spi.write(lowByte(v)); - spi.write(highByte(v)); - __end(); -} - -void GDClass::fill(int addr, byte v, unsigned int count) -{ - __wstart(addr); - while (count--) - spi.write(v); - __end(); -} - -void GDClass::copy(unsigned int addr, PROGMEM prog_uchar *src, int count) -{ - __wstart(addr); - while (count--) { - spi.write(pgm_read_byte_near(src)); - src++; - } - __end(); -} - - - -void GDClass::microcode(PROGMEM prog_uchar *src, int count) -{ - wr(J1_RESET, 1); - copy(J1_CODE, src, count); - wr(J1_RESET, 0); -} - - - -void GDClass::setpal(int pal, unsigned int rgb) -{ - wr16(RAM_PAL + (pal << 1), rgb); -} - -void GDClass::sprite(int spr, int x, int y, byte image, byte palette, byte rot, byte jk) -{ - __wstart(RAM_SPR + (spr << 2)); - spi.write(lowByte(x)); - spi.write((palette << 4) | (rot << 1) | (highByte(x) & 1)); - spi.write(lowByte(y)); - spi.write((jk << 7) | (image << 1) | (highByte(y) & 1)); - __end(); -} - -void GDClass::xsprite(int ox, int oy, signed char x, signed char y, byte image, byte palette, byte rot, byte jk) -{ - if (rot & 2) - x = -16-x; - if (rot & 4) - y = -16-y; - if (rot & 1) { - int s; - s = x; x = y; y = s; - } - ox += x; - oy += y; - spi.write(lowByte(ox)); - spi.write((palette << 4) | (rot << 1) | (highByte(ox) & 1)); - spi.write(lowByte(oy)); - spi.write((jk << 7) | (image << 1) | (highByte(oy) & 1)); - spr++; -} - -void GDClass::xhide() -{ - spi.write(lowByte(400)); - spi.write(highByte(400)); - spi.write(lowByte(400)); - spi.write(highByte(400)); - spr++; -} - -void GDClass::plots(int ox, int oy, PROGMEM sprplot *psp, byte count, byte rot, byte jk) -{ - while (count--) { - struct sprplot sp; - sp = *psp++; - GD.xsprite(ox, oy, sp.x, sp.y, sp.image, sp.palette, rot, jk); - } -} - -void GDClass::sprite2x2(int spr, int x, int y, byte image, byte palette, byte rot, byte jk) -{ - __wstart(0x3000 + (spr << 2)); - GD.xsprite(x, y, -16, -16, image + 0, palette, rot, jk); - GD.xsprite(x, y, 0, -16, image + 1, palette, rot, jk); - GD.xsprite(x, y, -16, 0, image + 2, palette, rot, jk); - GD.xsprite(x, y, 0, 0, image + 3, palette, rot, jk); - __end(); -} - -void GDClass::waitvblank() -{ - // Wait for the VLANK to go from 0 to 1: this is the start - // of the vertical blanking interval. - - while (rd(VBLANK) == 1) - ; - while (rd(VBLANK) == 0) - ; -} - -/* Fixed ascii font, useful for debug */ - -#include "font8x8.h" -static byte stretch[16] = { - 0x00, 0x03, 0x0c, 0x0f, - 0x30, 0x33, 0x3c, 0x3f, - 0xc0, 0xc3, 0xcc, 0xcf, - 0xf0, 0xf3, 0xfc, 0xff -}; - - -void GDClass::ascii() -{ - long i; - for (i = 0; i < 768; i++) { - byte b = font8x8[i]; - byte h = stretch[b >> 4]; - byte l = stretch[b & 0xf]; - GD.wr(0x1000 + (16 * ' ') + (2 * i), h); - GD.wr(0x1000 + (16 * ' ') + (2 * i) + 1, l); - } - for (i = 0x20; i < 0x80; i++) { - GD.setpal(4 * i + 0, TRANSPARENT); - GD.setpal(4 * i + 3, RGB(255,255,255)); - } - GD.fill(RAM_PIC, ' ', 4096); -} - -void GDClass::putstr(int x, int y, const char *s) -{ - GD.__wstart((y << 6) + x); - while (*s) - spi.write(*s++); - GD.__end(); -} - -void GDClass::voice(int v, byte wave, unsigned int freq, byte lamp, byte ramp) -{ - __wstart(VOICES + (v << 2)); - spi.write(lowByte(freq)); - spi.write(highByte(freq) | (wave << 7)); - spi.write(lamp); - spi.write(ramp); - __end(); -} - -void GDClass::screenshot(unsigned int frame) -{ - int yy, xx; - byte undone[38]; // 300-long bitmap of lines pending - - // initialize to 300 ones - memset(undone, 0xff, 37); - undone[37] = 0xf; - int nundone = 300; - - pc.putc(0xa5); // sync byte - pc.putc(lowByte(frame)); - pc.putc(highByte(frame)); - - while (nundone) { - // find a pending line a short distance ahead of the raster - int hwline = GD.rd16(SCREENSHOT_Y) & 0x1ff; - for (yy = (hwline + 7) % 300; ((undone[yy>>3] >> (yy&7)) & 1) == 0; yy = (yy + 1) % 300) - ; - GD.wr16(SCREENSHOT_Y, 0x8000 | yy); // ask for it - - // housekeeping while waiting: mark line done and send yy - undone[yy>>3] ^= (1 << (yy&7)); - nundone--; - pc.putc(lowByte(yy)); - pc.putc(highByte(yy)); - while ((GD.rd(SCREENSHOT_Y + 1) & 0x80) == 0) - ; - - // Now send the line, compressing zero pixels - uint16_t zeroes = 0; - for (xx = 0; xx < 800; xx += 2) { - uint16_t v = GD.rd16(SCREENSHOT + xx); - if (v == 0) { - zeroes++; - } else { - if (zeroes) { - pc.putc(lowByte(zeroes)); - pc.putc(0x80 | highByte(zeroes)); - zeroes = 0; - } - pc.putc(lowByte(v)); - pc.putc(highByte(v)); - } - } - if (zeroes) { - pc.putc(lowByte(zeroes)); - pc.putc(0x80 | highByte(zeroes)); - } - } - GD.wr16(SCREENSHOT_Y, 0); // restore screen to normal -} - -class GDflashbits { -public: - void begin(PROGMEM prog_uchar *s) { - src = s; - mask = 0x01; - } - byte get1(void) { - byte r = (pgm_read_byte_near(src) & mask) != 0; - mask <<= 1; - if (!mask) { - mask = 1; - src++; - } - return r; - } - unsigned short getn(byte n) { - unsigned short r = 0; - while (n--) { - r <<= 1; - r |= get1(); - } - return r; - } -private: - PROGMEM prog_uchar *src; - byte mask; -}; - -static GDflashbits GDFB; - -void GDClass::uncompress(unsigned int addr, PROGMEM prog_uchar *src) -{ - GDFB.begin(src); - byte b_off = GDFB.getn(4); - byte b_len = GDFB.getn(4); - byte minlen = GDFB.getn(2); - unsigned short items = GDFB.getn(16); - while (items--) { - if (GDFB.get1() == 0) { - GD.wr(addr++, GDFB.getn(8)); - } else { - int offset = -GDFB.getn(b_off) - 1; - int l = GDFB.getn(b_len) + minlen; - while (l--) { - GD.wr(addr, GD.rd(addr + offset)); - addr++; - } - } - } -}