123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- class GDTransport {
- int fd;
- uint8_t writebuf[4096];
- size_t nwrite;
- public:
- void begin() {
- const char *DEV = "/dev/spidev0.0";
- fd = open(DEV, O_RDWR);
- if (fd <= 0) {
- perror(DEV);
- exit(1);
- }
- uint32_t speed = 500000;
- ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
- scu(0, 0, 0);
- #if PROTO == 0
- scu(0x44, 0, 0); // from external crystal
- #endif
- #if PROTO == 1
- scu(0x48, 0, 0); // from internal oscillator
- #endif
- scu(0x68, 0, 0);
- delay(50);
- wp = 0;
- freespace = 4096 - 4;
- stream();
- }
- static void default_spi_ioc(struct spi_ioc_transfer *ps) {
- memset(ps, 0, sizeof(*ps));
- ps->speed_hz = 20000000;
- ps->bits_per_word = 8;
- }
- // Raw read from GD2 memory
- void __read(void *dst, uint32_t addr, uint32_t n) {
- struct spi_ioc_transfer mesg[2];
- default_spi_ioc(&mesg[0]);
- default_spi_ioc(&mesg[1]);
- uint8_t tx[] = {(addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr >> 0) & 0xff, 0xff};
- mesg[0].tx_buf = (__u64)tx;
- mesg[0].len = 4;
- mesg[0].cs_change = 0;
- mesg[1].rx_buf = (__u64)dst;
- mesg[1].len = n;
- mesg[1].cs_change = 1;
- ioctl(fd, SPI_IOC_MESSAGE(2), mesg);
- // printf("__read(%x %d) %x\n", addr, n, *(byte*)dst);
- }
- // Raw write to GD2 memory
- void __write(uint32_t addr, void *src, uint32_t n) {
- // printf("__write(%x %d)\n", addr, n);
- fflush(stdout);
- struct spi_ioc_transfer mesg[2];
- default_spi_ioc(&mesg[0]);
- default_spi_ioc(&mesg[1]);
- uint8_t tx[] = {0x80 | ((addr >> 16) & 0xff), (addr >> 8) & 0xff, (addr >> 0) & 0xff};
- mesg[0].tx_buf = (__u64)tx;
- mesg[0].len = 3;
- mesg[0].cs_change = 0;
- mesg[1].tx_buf = (__u64)src;
- mesg[1].len = n;
- mesg[1].cs_change = 1;
- ioctl(fd, SPI_IOC_MESSAGE(2), mesg);
- }
- void spisend(uint8_t b) {
- writebuf[nwrite++] = b;
- }
- void cmd32(uint32_t x) {
- if (freespace < 4) {
- getfree(4);
- }
- wp += 4;
- freespace -= 4;
- union {
- uint32_t c;
- uint8_t b[4];
- };
- c = x;
- spisend(b[0]);
- spisend(b[1]);
- spisend(b[2]);
- spisend(b[3]);
- }
- void cmdbyte(byte x) {
- if (freespace == 0) {
- getfree(1);
- }
- wp++;
- freespace--;
- spisend(x);
- }
- void cmd_n(byte *s, uint16_t n) {
- if (freespace < n) {
- getfree(n);
- }
- wp += n;
- freespace -= n;
- while (n) {
- n --;
- spisend(*s++);
- }
- }
- void flush() {
- getfree(0);
- }
- uint16_t rp() {
- uint16_t r = __rd16(REG_CMD_READ);
- if (r == 0xfff) {
- REPORT(/*EXCEPTION*/r);
- for (;;) ;
- }
- return r;
- }
- void finish() {
- wp &= 0xffc;
- stopstream();
- __wr16(REG_CMD_WRITE, wp);
- while (rp() != wp)
- ;
- stream();
- }
- byte rd(uint32_t addr)
- {
- stopstream(); // stop streaming
- byte r;
- __read(&r, addr, 1);
- stream();
- return r;
- }
- void wr(uint32_t addr, byte v)
- {
- stopstream(); // stop streaming
- __write(addr, &v, 1);
- stream();
- }
- uint16_t rd16(uint32_t addr)
- {
- stopstream(); // stop streaming
- uint16_t r = 0;
- __read(&r, addr, 2);
- stream();
- return r;
- }
- void wr16(uint32_t addr, uint32_t v)
- {
- stopstream(); // stop streaming
- __write(addr, &v, 2);
- stream();
- }
- uint32_t rd32(uint32_t addr)
- {
- stopstream(); // stop streaming
- uint32_t r = 0;
- __read(&r, addr, 4);
- stream();
- return r;
- }
- void rd_n(byte *dst, uint32_t addr, uint32_t n)
- {
- stopstream(); // stop streaming
- __read(dst, addr, n);
- stream();
- }
- void wr_n(uint32_t addr, byte *src, uint32_t n)
- {
- stopstream(); // stop streaming
- __write(addr, src, n);
- stream();
- }
- void wr32(uint32_t addr, unsigned long v)
- {
- stopstream(); // stop streaming
- __write(addr, &v, 4);
- stream();
- }
- uint32_t getwp(void) {
- return RAM_CMD + (wp & 0xffc);
- }
- void bulk(uint32_t addr) {
- /*
- __end(); // stop streaming
- __start(addr);
- */
- }
- void resume(void) {
- stream();
- }
- void stopstream() // flush any streamed output
- {
- if (nwrite != 0) {
- __write(wptr0, writebuf, nwrite);
- nwrite = 0;
- }
- }
- void stop() // end the SPI transaction
- {
- wp &= 0xffc;
- stopstream();
- __wr16(REG_CMD_WRITE, wp);
- // while (__rd16(REG_CMD_READ) != wp) ;
- }
- void __end() // end the SPI transaction
- {
- stopstream();
- }
- void stream(void) {
- nwrite = 0;
- wptr0 = RAM_CMD + wp;
- }
- uint16_t __rd16(uint32_t addr)
- {
- uint16_t r;
- __read(&r, addr, sizeof(r));
- return r;
- }
- void __wr16(uint32_t addr, uint16_t v)
- {
- __write(addr, &v, sizeof(v));
- }
- void scu(byte a, byte b, byte c)
- {
- uint8_t scu0[3] = { a, 0x00, 0x00 };
- write(fd, scu0, 3);
- delay(4);
- }
- void getfree(uint16_t n)
- {
- wp &= 0xfff;
- stopstream();
- __wr16(REG_CMD_WRITE, wp & 0xffc);
- do {
- uint16_t fullness = (wp - rp()) & 4095;
- freespace = (4096 - 4) - fullness;
- } while (freespace < n);
- stream();
- }
- byte streaming;
- uint16_t wp;
- uint16_t freespace;
- uint32_t wptr0;
- };
|