wiring.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #ifndef CS
  2. #define CS 8
  3. #endif
  4. class GDTransport {
  5. public:
  6. void ios() {
  7. pinMode(CS, OUTPUT);
  8. digitalWrite(CS, HIGH);
  9. pinMode(9, OUTPUT);
  10. digitalWrite(9, HIGH);
  11. SPI.begin();
  12. }
  13. void begin() {
  14. ios();
  15. SPI.begin();
  16. SPI.setClockDivider(SPI_CLOCK_DIV2);
  17. SPSR = (1 << SPI2X);
  18. hostcmd(0x00);
  19. #if PROTO == 0
  20. hostcmd(0x44); // from external crystal
  21. #endif
  22. hostcmd(0x68);
  23. wp = 0;
  24. freespace = 4096 - 4;
  25. stream();
  26. }
  27. void cmd32(uint32_t x) {
  28. if (freespace < 4) {
  29. getfree(4);
  30. }
  31. wp += 4;
  32. freespace -= 4;
  33. union {
  34. uint32_t c;
  35. uint8_t b[4];
  36. };
  37. c = x;
  38. SPI.transfer(b[0]);
  39. SPI.transfer(b[1]);
  40. SPI.transfer(b[2]);
  41. SPI.transfer(b[3]);
  42. }
  43. void cmdbyte(byte x) {
  44. if (freespace == 0) {
  45. getfree(1);
  46. }
  47. wp++;
  48. freespace--;
  49. SPI.transfer(x);
  50. }
  51. void cmd_n(byte *s, uint16_t n) {
  52. if (freespace < n) {
  53. getfree(n);
  54. }
  55. wp += n;
  56. freespace -= n;
  57. while (n > 8) {
  58. n -= 8;
  59. SPI.transfer(*s++);
  60. SPI.transfer(*s++);
  61. SPI.transfer(*s++);
  62. SPI.transfer(*s++);
  63. SPI.transfer(*s++);
  64. SPI.transfer(*s++);
  65. SPI.transfer(*s++);
  66. SPI.transfer(*s++);
  67. }
  68. while (n--)
  69. SPI.transfer(*s++);
  70. }
  71. void flush() {
  72. getfree(0);
  73. }
  74. uint16_t rp() {
  75. uint16_t r = __rd16(REG_CMD_READ);
  76. if (r == 0xfff) {
  77. REPORT(/*EXCEPTION*/r);
  78. for (;;) ;
  79. }
  80. return r;
  81. }
  82. void finish() {
  83. wp &= 0xffc;
  84. __end();
  85. __wr16(REG_CMD_WRITE, wp);
  86. while (rp() != wp)
  87. ;
  88. stream();
  89. }
  90. byte rd(uint32_t addr)
  91. {
  92. __end(); // stop streaming
  93. __start(addr);
  94. SPI.transfer(0); // dummy
  95. byte r = SPI.transfer(0);
  96. stream();
  97. return r;
  98. }
  99. void wr(uint32_t addr, byte v)
  100. {
  101. __end(); // stop streaming
  102. __wstart(addr);
  103. SPI.transfer(v);
  104. stream();
  105. }
  106. uint16_t rd16(uint32_t addr)
  107. {
  108. uint16_t r = 0;
  109. __end(); // stop streaming
  110. __start(addr);
  111. SPI.transfer(0);
  112. r = SPI.transfer(0);
  113. r |= (SPI.transfer(0) << 8);
  114. stream();
  115. return r;
  116. }
  117. void wr16(uint32_t addr, uint32_t v)
  118. {
  119. __end(); // stop streaming
  120. __wstart(addr);
  121. SPI.transfer(v);
  122. SPI.transfer(v >> 8);
  123. stream();
  124. }
  125. uint32_t rd32(uint32_t addr)
  126. {
  127. __end(); // stop streaming
  128. __start(addr);
  129. SPI.transfer(0);
  130. union {
  131. uint32_t c;
  132. uint8_t b[4];
  133. };
  134. b[0] = SPI.transfer(0);
  135. b[1] = SPI.transfer(0);
  136. b[2] = SPI.transfer(0);
  137. b[3] = SPI.transfer(0);
  138. stream();
  139. return c;
  140. }
  141. void rd_n(byte *dst, uint32_t addr, uint16_t n)
  142. {
  143. __end(); // stop streaming
  144. __start(addr);
  145. SPI.transfer(0);
  146. while (n--)
  147. *dst++ = SPI.transfer(0);
  148. stream();
  149. }
  150. void wr_n(uint32_t addr, byte *src, uint16_t n)
  151. {
  152. __end(); // stop streaming
  153. __wstart(addr);
  154. while (n--)
  155. SPI.transfer(*src++);
  156. stream();
  157. }
  158. void wr32(uint32_t addr, unsigned long v)
  159. {
  160. __end(); // stop streaming
  161. __wstart(addr);
  162. SPI.transfer(v);
  163. SPI.transfer(v >> 8);
  164. SPI.transfer(v >> 16);
  165. SPI.transfer(v >> 24);
  166. stream();
  167. }
  168. uint32_t getwp(void) {
  169. return RAM_CMD + (wp & 0xffc);
  170. }
  171. void bulk(uint32_t addr) {
  172. __end(); // stop streaming
  173. __start(addr);
  174. }
  175. void resume(void) {
  176. // REPORT(__rd16(REG_ID));
  177. stream();
  178. }
  179. static void __start(uint32_t addr) // start an SPI transaction to addr
  180. {
  181. digitalWrite(CS, LOW);
  182. SPI.transfer(addr >> 16);
  183. SPI.transfer(highByte(addr));
  184. SPI.transfer(lowByte(addr));
  185. }
  186. static void __wstart(uint32_t addr) // start an SPI write transaction to addr
  187. {
  188. digitalWrite(CS, LOW);
  189. SPI.transfer(0x80 | (addr >> 16));
  190. SPI.transfer(highByte(addr));
  191. SPI.transfer(lowByte(addr));
  192. }
  193. static void __end() // end the SPI transaction
  194. {
  195. digitalWrite(CS, HIGH);
  196. }
  197. void stop() // end the SPI transaction
  198. {
  199. wp &= 0xffc;
  200. __end();
  201. __wr16(REG_CMD_WRITE, wp);
  202. // while (__rd16(REG_CMD_READ) != wp) ;
  203. }
  204. void stream(void) {
  205. __end();
  206. __wstart(RAM_CMD + (wp & 0xfff));
  207. }
  208. static unsigned int __rd16(uint32_t addr)
  209. {
  210. unsigned int r;
  211. __start(addr);
  212. SPI.transfer(0); // dummy
  213. r = SPI.transfer(0);
  214. r |= (SPI.transfer(0) << 8);
  215. __end();
  216. return r;
  217. }
  218. static void __wr16(uint32_t addr, unsigned int v)
  219. {
  220. __wstart(addr);
  221. SPI.transfer(lowByte(v));
  222. SPI.transfer(highByte(v));
  223. __end();
  224. }
  225. static void hostcmd(byte a)
  226. {
  227. digitalWrite(CS, LOW);
  228. SPI.transfer(a);
  229. SPI.transfer(0x00);
  230. SPI.transfer(0x00);
  231. digitalWrite(CS, HIGH);
  232. delay(60);
  233. }
  234. void getfree(uint16_t n)
  235. {
  236. wp &= 0xfff;
  237. __end();
  238. __wr16(REG_CMD_WRITE, wp & 0xffc);
  239. do {
  240. uint16_t fullness = (wp - rp()) & 4095;
  241. freespace = (4096 - 4) - fullness;
  242. } while (freespace < n);
  243. stream();
  244. }
  245. byte streaming;
  246. uint16_t wp;
  247. uint16_t freespace;
  248. };