SPI using DMA Can a Teensy be a Master and a Slave

Status
Not open for further replies.

OldMan

Member
hi everyone

Seasons greetings

I hoping someone might be able to help me I'll try to keep it short. (Honestly ;-) )
I've been working with this excellent code https://forum.pjrc.com/threads/27651-SPI-DMA-slave-problem
I'm trying to integrate it into a synth Osc Filter Vca project. It involves the use of currently 3 x Teensy 3.2
I'm trying to use each teensy to try and spread the processing of Osscilators Filters etc whilst maintaing a high sample rate. Everything is interrupt driven at 23uS
Here is a Picture which shows the current configuration.
DrawingForForum.png


I started off with just 2 Teensy's one used as a oscillator and one as a filter to spread the code
Using a variation of the code i can have 4 + oscillator on Teensy 1 with spare code headroom which then SPi's using DMA to Teensy 2 to filter a single oscillator therefore
I can add any number of filter Teensys one for each voice giving me the ability to do true polyphonic. (It works great )

So now what i'm trying to achieve (If its at all possible) is to have the filter Teensy receive from the Oscillator then process through filter code. and send out to Teensy 3.
This obviously involves Switching from being a slave to being a master all within 23uS

The code that follows is for the Filter Teensy. (without the filter code itself 10uS ) I've moved thing round from the original code and have got to a position where in the main ISR if i change
" SlaveOrMaster = 0;//If you change this to 1 we transmit if 0 then we receive" it works as either Master or Slave. Utilising Clocks on both pin 14 and 13.

But one of the problems is if i move the SPI TRANSMIT SETUP_in the setup
into the masterSPI void it really not happy. So I'm wondering if its really possible for a Teensy to be both Master and Slave. I apologise if my approach seems a bit like hitting everything with a hammer to get it to work.
But i'm un tutored so normally have shall we say a unique approach.

If i could even get a clue if its possible that would be great
If i could get any hints that would be marvellous
If anyone has any other ideas on an alternative approach

I'm currently of the opionion it might not be possible and may have to resort to using the DAC on the Filter Teensy and then use ADC to get it into the 3rd Teensy for processing

If you got this far thanks for reading and Merry Christmas

A very old man
Code:
#include <TimerOne.h>
#define MasterNDAT 1
#define SlaveNDAT 8

#define SPI_CLOCK   (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(48 / 5) * ((1+1)/2) = 9.8 MHz
uint16_t xx[MasterNDAT];//Master
uint16_t  yy[SlaveNDAT];//Slave


volatile uint16_t printme;
volatile  long testData = 0;
volatile  int SlaveOrMaster = 0;
int SlaveISRclock = 5;
int MasterISRclock = 4;

void setup() {
  pinMode (SlaveISRclock , INPUT);//ISR driven from Teensy 1
  pinMode (MasterISRclock , OUTPUT);//ISR driving Teensy 3

  // ______________SPI TRANSMIT SETUP________
  SIM_SCGC6 |= SIM_SCGC6_SPI0;//Transmit Setup
  CORE_PIN2_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); // Master Setup SRE slew rate enable
  CORE_PIN13_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2); // Master Setup DSE drive strength enable
  CORE_PIN7_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);//Master Setup this is transmit pin

  //ISR driven from Teensy 1
  attachInterrupt(SlaveISRclock, mainISR, RISING);
}

void loop() {
Serial.println (printme); delay (80);//TestPrint
}//eo void loop


void mainISR() {

  SlaveOrMaster = 0;

  //Slave 8 Channels
  if (SlaveOrMaster == 0) {
    slaveSPI();
    printme = (yy[7]);
    analogWrite(A14, printme); //Just for testing
  }

  //_____________________________________________________________________
  // Put code here to Receive Data on Channel 7 Process then send out to Tennsy 3
  //_____________________________________________________________________

  SlaveOrMaster = 0;//If you change this to 1 we transmit if 0 then we receive

  //Master 1 Channel
  if (SlaveOrMaster == 1) {
    digitalWriteFast (MasterISRclock, HIGH);
    masterSPI(testData++);
    digitalWriteFast (MasterISRclock, LOW);
    if (testData > 9999) {
      testData = 0; //Test data reset
    }
  }

} //EO MainISR


void masterSPI(uint16_t data0) {

  int ii;
  for ( ii = 0; ii < MasterNDAT; ii++) {
    xx[0] = data0; //this is data out Master
  }

  KINETISK_SPI0.MCR = SPI_MCR_MSTR;//Master

  KINETISK_SPI0.CTAR0 = SPI_CLOCK |  //Master
                        SPI_CTAR_FMSZ(15) | //Master
                        SPI_CTAR_PCSSCK(0) | //Master
                        SPI_CTAR_PASC(0) | //Master
                        SPI_CTAR_PDT(0) | //Master
                        SPI_CTAR_CSSCK(0) | //Master
                        SPI_CTAR_ASC(0) | //Master
                        SPI_CTAR_DT(0); //Master

  // start SPI
  KINETISK_SPI0.RSER = SPI_RSER_TFFF_DIRS | SPI_RSER_TFFF_RE ;//Master fifo fill flag to DMA
  KINETISK_SPI0.MCR |= SPI_MCR_MSTR;
  // set transmit
  DMA_TCD0_DADDR = &SPI0_PUSHR;
  DMA_TCD0_DOFF = 0;
  DMA_TCD0_DLASTSGA = 0;
  DMA_TCD0_ATTR = 1 << 8 | 1;
  DMA_TCD0_NBYTES_MLNO = 2;
  DMA_TCD0_SADDR = xx;
  DMA_TCD0_SOFF = 2;
  DMA_TCD0_SLAST = -2 * MasterNDAT;
  DMA_TCD0_CITER_ELINKNO = DMA_TCD0_BITER_ELINKNO = MasterNDAT;
  DMA_TCD0_CSR = DMA_TCD_CSR_INTMAJOR | DMA_TCD_CSR_DREQ;
  DMAMUX0_CHCFG0 = DMAMUX_SOURCE_SPI0_TX | DMAMUX_ENABLE;
  //start DMA
  DMA_SERQ = 0;
  NVIC_ENABLE_IRQ(IRQ_DMA_CH0);//enable SPI ISR
}//eo masterSPI

///ISR for Master
void dma_ch0_isr(void)
{
  DMA_CINT = 0;
  DMA_CDNE = 0;
}



void slaveSPI(void)
{
  SIM_SCGC6 |= SIM_SCGC6_DMAMUX;//Slave Setup
  SIM_SCGC7 |= SIM_SCGC7_DMA; //Slave Setup
  DMA_CR = 0;////Slave Setup

  CORE_PIN2_CONFIG = PORT_PCR_MUX(2); ////Slave Setup
  CORE_PIN14_CONFIG = PORT_PCR_MUX(2); ////Slave Setup clock
  CORE_PIN8_CONFIG = PORT_PCR_MUX(2);//This is the data recieve pin


  //added from recieve was in void
  SPI0_CTAR0_SLAVE = SPI_CTAR_FMSZ(15);
  //spi SETUP
  KINETISK_SPI0.MCR |= SPI_MCR_CLR_TXF;
  // start SPI
  KINETISK_SPI0.RSER = SPI_RSER_RFDF_DIRS | SPI_RSER_RFDF_RE;  // receive fifo drain flag to DMA

  KINETISK_SPI0.MCR = 0;
  // set receive
  DMA_TCD1_SADDR = &SPI0_POPR;
  DMA_TCD1_SOFF = 0;
  DMA_TCD1_SLAST = 0;
  DMA_TCD1_ATTR = 1 << 8 | 1;
  DMA_TCD1_NBYTES_MLNO = 2;
  DMA_TCD1_DADDR = yy;
  DMA_TCD1_DOFF = 2;
  DMA_TCD1_DLASTSGA = -2 * SlaveNDAT;
  DMA_TCD1_CITER_ELINKNO = DMA_TCD1_BITER_ELINKNO = SlaveNDAT;
  DMA_TCD1_CSR = DMA_TCD_CSR_INTMAJOR | DMA_TCD_CSR_DREQ;
  DMAMUX0_CHCFG1 = DMAMUX_DISABLE;
  DMAMUX0_CHCFG1 = DMAMUX_SOURCE_SPI0_RX | DMAMUX_ENABLE;

  //Enable IRQ
  DMA_SERQ = 1;
  NVIC_ENABLE_IRQ(IRQ_DMA_CH1);
}// eo slaveSPI

///ISR for Slave
void dma_ch1_isr(void)
{ DMA_CINT = 1;
  DMA_CDNE = 1;
  SPI0_MCR |= SPI_MCR_HALT | SPI_MCR_MDIS;
}
 
Status
Not open for further replies.
Back
Top