memloader.ino 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #include <SPI.h>
  2. #include <GD.h>
  3. static const PROGMEM uint32_t crc_table[16] = {
  4. 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
  5. 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
  6. 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
  7. 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
  8. };
  9. unsigned long crc_update(unsigned long crc, byte data)
  10. {
  11. byte tbl_idx;
  12. tbl_idx = crc ^ (data >> (0 * 4));
  13. crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
  14. tbl_idx = crc ^ (data >> (1 * 4));
  15. crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
  16. return crc;
  17. }
  18. void setup()
  19. {
  20. Serial.begin(115200);
  21. GD.begin();
  22. GD.ascii();
  23. GD.putstr(0, 0, "memloader");
  24. }
  25. static byte get1()
  26. {
  27. while (!Serial.available())
  28. ;
  29. return Serial.read();
  30. }
  31. static uint16_t get2()
  32. {
  33. int r = get1();
  34. return (r << 8) + get1();
  35. }
  36. static void crc_mem(uint16_t a, uint16_t n)
  37. {
  38. unsigned long crc = ~0;
  39. GD.__start(a);
  40. while (n--)
  41. crc = crc_update(crc, SPI.transfer(0));
  42. GD.__end();
  43. crc = ~crc;
  44. Serial.write(crc >> 24);
  45. Serial.write(crc >> 16);
  46. Serial.write(crc >> 8);
  47. Serial.write(crc);
  48. }
  49. static byte mirror[256];
  50. static void copycoll()
  51. {
  52. GD.waitvblank();
  53. GD.waitvblank();
  54. GD.__start(COLLISION);
  55. int i;
  56. for (i = 0; i < 256; i++)
  57. mirror[i] = SPI.transfer(0);
  58. GD.__end();
  59. }
  60. void loop()
  61. {
  62. int i;
  63. // Commands arrive on the serial connection, and trigger various SPI
  64. // actions. The commands are:
  65. //
  66. // len addr block read/write, depending on hi bit of addr
  67. // 0 'L' yy line CRC. Captures line yy, returns the CRC32
  68. // 0 'c' COLLISION dump. Returns the 256 bytes of COLLISION
  69. // 0 'C' COLLISION CRC. Returns the CRC32 of COLLISION
  70. // 0 'M' addr len RAM CRC. Returns the CRC32 of len bytes at addr
  71. byte len = get1();
  72. if (len) {
  73. unsigned short addr;
  74. addr = get2();
  75. GD.__start(addr);
  76. if (addr & 0x8000) {
  77. while (len--)
  78. SPI.transfer(get1());
  79. } else {
  80. while (len--)
  81. Serial.write(SPI.transfer(0));
  82. }
  83. GD.__end();
  84. } else switch (get1()) {
  85. case 'L': { // one-line CRC
  86. unsigned int yy;
  87. yy = get2();
  88. GD.wr16(SCREENSHOT_Y, 0x8000 | yy);
  89. while ((GD.rd(SCREENSHOT_Y + 1) & 0x80) == 0)
  90. ;
  91. crc_mem(SCREENSHOT, 800);
  92. GD.wr16(SCREENSHOT_Y, 0);
  93. break;
  94. }
  95. case 'F': { // full-screen CRC
  96. unsigned int yy;
  97. for (yy = 0; yy < 300; yy++) {
  98. GD.wr16(SCREENSHOT_Y, 0x8000 | yy);
  99. while ((GD.rd(SCREENSHOT_Y + 1) & 0x80) == 0)
  100. ;
  101. crc_mem(SCREENSHOT, 800);
  102. }
  103. GD.wr16(SCREENSHOT_Y, 0);
  104. break;
  105. }
  106. case 'c': {
  107. copycoll();
  108. for (i = 0; i < 256; i++) {
  109. Serial.write(mirror[i]);
  110. }
  111. break;
  112. }
  113. case 'C': {
  114. copycoll();
  115. unsigned long crc = ~0;
  116. for (i = 0; i < 256; i++)
  117. crc = crc_update(crc, mirror[i]);
  118. crc = ~crc;
  119. Serial.write(crc >> 24);
  120. Serial.write(crc >> 16);
  121. Serial.write(crc >> 8);
  122. Serial.write(crc);
  123. break;
  124. }
  125. case 'M': {
  126. uint16_t a = get2();
  127. uint16_t s = get2();
  128. crc_mem(a, s);
  129. }
  130. }
  131. }