initial commit

This commit is contained in:
2026-09-25 10:48:51 +10:00
commit b90beea8ae
1020 changed files with 131665 additions and 0 deletions
@@ -0,0 +1,107 @@
// Double-buffered DMA on auxiliary SPI peripheral on pins 11/12/13.
// Continuously alternates between two data buffers...one is filled
// with new data as the other is being transmitted.
#include <SPI.h>
#include <Adafruit_ZeroDMA.h>
#include "utility/dma.h"
#include "wiring_private.h" // pinPeripheral() function
// Declare our own SPI peripheral 'mySPI' on pins 11/12/13:
// (Do not call this SPI1; Arduino Zero and Metro M0 already
// have an SPI1 (the EDBG interface) and it won't compile.)
#if defined(ARDUINO_SAMD_ADAFRUIT)
SPIClass mySPI( // Adafruit SAMD board support calls this SPIClass
#else
SPIClassSAMD mySPI( // Arduino SAMD now calls it SPIClassSAMD
#endif
&sercom1, // -> Sercom peripheral
34, // MISO pin (also digital pin 12)
37, // SCK pin (also digital pin 13)
35, // MOSI pin (also digital pin 11)
SPI_PAD_0_SCK_1, // TX pad (MOSI, SCK pads)
SERCOM_RX_PAD_3); // RX pad (MISO pad)
Adafruit_ZeroDMA myDMA;
ZeroDMAstatus stat; // DMA status codes returned by some functions
// Data we'll issue to mySPI. There are TWO buffers; one being
// filled with new data while the other's being transmitted in
// the background.
#define DATA_LENGTH 512
uint8_t source_memory[2][DATA_LENGTH],
buffer_being_filled = 0, // Index of 'filling' buffer
buffer_value = 0; // Value of fill
volatile bool transfer_is_done = true; // Done yet?
// Callback for end-of-DMA-transfer
void dma_callback(Adafruit_ZeroDMA *dma) {
(void) dma;
transfer_is_done = true;
}
DmacDescriptor *desc; // DMA descriptor address (so we can change contents)
void setup() {
Serial.begin(115200);
while(!Serial); // Wait for Serial monitor before continuing
Serial.println("DMA test: SPI data out");
mySPI.begin();
// Assign pins 11, 12, 13 to SERCOM functionality
pinPeripheral(11, PIO_SERCOM);
pinPeripheral(12, PIO_SERCOM);
pinPeripheral(13, PIO_SERCOM);
// Configure DMA for SERCOM1 (our 'mySPI' port on 11/12/13)
Serial.println("Configuring DMA trigger");
myDMA.setTrigger(SERCOM1_DMAC_ID_TX);
myDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
Serial.print("Allocating DMA channel...");
stat = myDMA.allocate();
myDMA.printStatus(stat);
desc = myDMA.addDescriptor(
source_memory[buffer_being_filled], // move data from here
(void *)(&SERCOM1->SPI.DATA.reg), // to here
DATA_LENGTH, // this many...
DMA_BEAT_SIZE_BYTE, // bytes/hword/words
true, // increment source addr?
false); // increment dest addr?
Serial.println("Adding callback");
// register_callback() can optionally take a second argument
// (callback type), default is DMA_CALLBACK_TRANSFER_DONE
myDMA.setCallback(dma_callback);
}
void loop() {
// Fill buffer with new data. The other buffer might
// still be transmitting in the background via DMA.
memset(source_memory[buffer_being_filled], buffer_value, DATA_LENGTH);
// Wait for prior transfer to complete before starting new one...
Serial.print("Waiting on prior transfer...");
while(!transfer_is_done) Serial.write('.');
mySPI.endTransaction();
Serial.println("Done!");
// Modify the DMA descriptor using the newly-filled buffer as source...
myDMA.changeDescriptor(desc, // DMA descriptor address
source_memory[buffer_being_filled]); // New src; dst & count don't change
// Begin new transfer...
Serial.println("Starting new transfer job");
mySPI.beginTransaction(SPISettings(12000000, MSBFIRST, SPI_MODE0));
transfer_is_done = false; // Reset 'done' flag
stat = myDMA.startJob(); // Go!
myDMA.printStatus(stat);
// Switch buffer indices so the alternate buffer is filled/xfer'd
// on the next pass.
buffer_being_filled = 1 - buffer_being_filled;
buffer_value++;
}