2013-10-28 13:19:25 +00:00

147 lines
3.2 KiB
Plaintext

#include <SPI.h>
#include <GD.h>
static PROGMEM prog_uint32_t crc_table[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
unsigned long crc_update(unsigned long crc, byte data)
{
byte tbl_idx;
tbl_idx = crc ^ (data >> (0 * 4));
crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
tbl_idx = crc ^ (data >> (1 * 4));
crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
return crc;
}
void setup()
{
Serial.begin(115200);
GD.begin();
GD.ascii();
GD.putstr(0, 0, "memloader");
}
static byte get1()
{
while (!Serial.available())
;
return Serial.read();
}
static uint16_t get2()
{
int r = get1();
return (r << 8) + get1();
}
static void crc_mem(uint16_t a, uint16_t n)
{
unsigned long crc = ~0;
GD.__start(a);
while (n--)
crc = crc_update(crc, SPI.transfer(0));
GD.__end();
crc = ~crc;
Serial.write(crc >> 24);
Serial.write(crc >> 16);
Serial.write(crc >> 8);
Serial.write(crc);
}
static byte mirror[256];
static void copycoll()
{
GD.waitvblank();
GD.waitvblank();
GD.__start(COLLISION);
int i;
for (i = 0; i < 256; i++)
mirror[i] = SPI.transfer(0);
GD.__end();
}
void loop()
{
int i;
// Commands arrive on the serial connection, and trigger various SPI
// actions. The commands are:
//
// len addr block read/write, depending on hi bit of addr
// 0 'L' yy line CRC. Captures line yy, returns the CRC32
// 0 'c' COLLISION dump. Returns the 256 bytes of COLLISION
// 0 'C' COLLISION CRC. Returns the CRC32 of COLLISION
// 0 'M' addr len RAM CRC. Returns the CRC32 of len bytes at addr
byte len = get1();
if (len) {
unsigned short addr;
addr = get2();
GD.__start(addr);
if (addr & 0x8000) {
while (len--)
SPI.transfer(get1());
} else {
while (len--)
Serial.write(SPI.transfer(0));
}
GD.__end();
} else switch (get1()) {
case 'L': { // one-line CRC
unsigned int yy;
yy = get2();
GD.wr16(SCREENSHOT_Y, 0x8000 | yy);
while ((GD.rd(SCREENSHOT_Y + 1) & 0x80) == 0)
;
crc_mem(SCREENSHOT, 800);
GD.wr16(SCREENSHOT_Y, 0);
break;
}
case 'F': { // full-screen CRC
unsigned int yy;
for (yy = 0; yy < 300; yy++) {
GD.wr16(SCREENSHOT_Y, 0x8000 | yy);
while ((GD.rd(SCREENSHOT_Y + 1) & 0x80) == 0)
;
crc_mem(SCREENSHOT, 800);
}
GD.wr16(SCREENSHOT_Y, 0);
break;
}
case 'c': {
copycoll();
for (i = 0; i < 256; i++) {
Serial.write(mirror[i]);
}
break;
}
case 'C': {
copycoll();
unsigned long crc = ~0;
for (i = 0; i < 256; i++)
crc = crc_update(crc, mirror[i]);
crc = ~crc;
Serial.write(crc >> 24);
Serial.write(crc >> 16);
Serial.write(crc >> 8);
Serial.write(crc);
break;
}
case 'M': {
uint16_t a = get2();
uint16_t s = get2();
crc_mem(a, s);
}
}
}