The bottom line here is that I'm in over my head and I have too many questions to just drop this all into a stackoverflow question and hope for an answer. Where do I find the definition and function of SPI0_SR, DMAMUX_SOURCE_SPI0_TX, etc? Why would you set SPI0_SR to 0xFF0F0000? Where do all of these register names and magic numbers come from? Do these terms get defined in the processor's datasheet? Is there a guide I'm missing?
Why I ask:
For a current project I need to continuously read data from an SD card, decompress it (almost entirely with lookup tables, nothing complex) and stream it out at a constant 8.6Mb/s. Between the hardware SPI interface and the DMA features, this seems like a very realistic goal on the Teensy 3.6.
I'm running into a lot of trouble though.
Firstly, it looks like the wire library outputs data at whatever speed it feels like. The SPISettings that you feed it looks to be more of a suggestion than anything else; it can't really hit a perfect 8.6Mb/s.
A kind user's suggestion here was to run in SPI slave mode, and use analogWriteFrequency() to generate the needed clock signal (then you can just feed it from that pwm pin into the SCK pin). That seems to work just fine, but introduces some new problems. The way I found to use the Teensy in SPI Slave mode was through one of a few libraries, the newest of which has no documentation in its github page, so source code comments in its example, and a lot of magic numbers in the .cpp file. Tonton81 has done some really impressive work here, I think, but I have no idea what value I need to pass in for "spimode"/"_fmsz".
In order to read, decompress, and output SD card data all continuously, I was planning on using a double-buffer and a DMA transfer to SPI, but dmachannel seems to be more or less undocumented as well. I got it to work using some copy/pasted code from these forums:
Which is pretty perfect if we're running in SPI Master mode but only outputs data on every other byte in slave mode for some reason.
Why I ask:
For a current project I need to continuously read data from an SD card, decompress it (almost entirely with lookup tables, nothing complex) and stream it out at a constant 8.6Mb/s. Between the hardware SPI interface and the DMA features, this seems like a very realistic goal on the Teensy 3.6.
I'm running into a lot of trouble though.
Firstly, it looks like the wire library outputs data at whatever speed it feels like. The SPISettings that you feed it looks to be more of a suggestion than anything else; it can't really hit a perfect 8.6Mb/s.
A kind user's suggestion here was to run in SPI slave mode, and use analogWriteFrequency() to generate the needed clock signal (then you can just feed it from that pwm pin into the SCK pin). That seems to work just fine, but introduces some new problems. The way I found to use the Teensy in SPI Slave mode was through one of a few libraries, the newest of which has no documentation in its github page, so source code comments in its example, and a lot of magic numbers in the .cpp file. Tonton81 has done some really impressive work here, I think, but I have no idea what value I need to pass in for "spimode"/"_fmsz".
In order to read, decompress, and output SD card data all continuously, I was planning on using a double-buffer and a DMA transfer to SPI, but dmachannel seems to be more or less undocumented as well. I got it to work using some copy/pasted code from these forums:
Code:
SPI0_SR = 0xFF0F0000;
SPI0_RSER = 0x00;
SPI0_RSER = SPI_RSER_TFFF_RE | SPI_RSER_TFFF_DIRS; // Make sure SPI triggers a DMA transfer after each transmit
dmachannel.sourceBuffer(data, 8); // The data for which we wish to transmit and its length
dmachannel.destination((volatile uint8_t&)SPI0_PUSHR); // Move data into the SPI FIFO register
dmachannel.triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX); // Only transfer data once the previous byte has been transmited (This is to ensure all bytes are sent)
// dmachannel.disableOnCompletion(); // Stop after transmitting all 256 bytes
dmachannel.interruptAtCompletion();
// dmachannel.attachInterrupt(dmaFinishedTest);
dmachannel.enable(); // Begin transmit