Browse Source

Use DMAChannel begin()

dds
PaulStoffregen 10 years ago
parent
commit
cb5c9e9729
7 changed files with 97 additions and 98 deletions
  1. +7
    -0
      Audio.h
  2. +35
    -34
      input_i2s.cpp
  3. +1
    -4
      input_i2s.h
  4. +18
    -19
      output_dac.cpp
  5. +1
    -4
      output_dac.h
  6. +34
    -33
      output_i2s.cpp
  7. +1
    -4
      output_i2s.h

+ 7
- 0
Audio.h View File

#error "The Audio Library only works with Teensy 3.X. Teensy 2.0 is unsupported." #error "The Audio Library only works with Teensy 3.X. Teensy 2.0 is unsupported."
#endif #endif


#include "DMAChannel.h"
#ifndef DMACHANNEL_HAS_BEGIN
#error "You need to update DMAChannel.h & DMAChannel.cpp"
#error "https://github.com/PaulStoffregen/cores/blob/master/teensy3/DMAChannel.h"
#error "https://github.com/PaulStoffregen/cores/blob/master/teensy3/DMAChannel.cpp"
#endif

// When changing multiple audio object settings that must update at // When changing multiple audio object settings that must update at
// the same time, these functions allow the audio library interrupt // the same time, these functions allow the audio library interrupt
// to be disabled. For example, you may wish to begin playing a note // to be disabled. For example, you may wish to begin playing a note

+ 35
- 34
input_i2s.cpp View File

audio_block_t * AudioInputI2S::block_right = NULL; audio_block_t * AudioInputI2S::block_right = NULL;
uint16_t AudioInputI2S::block_offset = 0; uint16_t AudioInputI2S::block_offset = 0;
bool AudioInputI2S::update_responsibility = false; bool AudioInputI2S::update_responsibility = false;
DMAChannel AudioInputI2S::dma;




void AudioInputI2S::begin(void) void AudioInputI2S::begin(void)
{ {
dma(); // Allocate the DMA channel first
dma.begin(true); // Allocate the DMA channel first


//block_left_1st = NULL; //block_left_1st = NULL;
//block_right_1st = NULL; //block_right_1st = NULL;


CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0 CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0


dma().TCD->SADDR = &I2S0_RDR0;
dma().TCD->SOFF = 0;
dma().TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma().TCD->NBYTES_MLNO = 2;
dma().TCD->SLAST = 0;
dma().TCD->DADDR = i2s_rx_buffer;
dma().TCD->DOFF = 2;
dma().TCD->CITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
dma().TCD->DLASTSGA = -sizeof(i2s_rx_buffer);
dma().TCD->BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
dma().TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma().triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_RX);
dma.TCD->SADDR = &I2S0_RDR0;
dma.TCD->SOFF = 0;
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma.TCD->NBYTES_MLNO = 2;
dma.TCD->SLAST = 0;
dma.TCD->DADDR = i2s_rx_buffer;
dma.TCD->DOFF = 2;
dma.TCD->CITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
dma.TCD->DLASTSGA = -sizeof(i2s_rx_buffer);
dma.TCD->BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_RX);
update_responsibility = update_setup(); update_responsibility = update_setup();
dma().enable();
dma.enable();


I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR; I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR;
I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE; // TX clock enable, because sync'd to TX I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE; // TX clock enable, because sync'd to TX
dma().attachInterrupt(isr);
dma.attachInterrupt(isr);
} }


void AudioInputI2S::isr(void) void AudioInputI2S::isr(void)
audio_block_t *left, *right; audio_block_t *left, *right;


//digitalWriteFast(3, HIGH); //digitalWriteFast(3, HIGH);
daddr = (uint32_t)(dma().TCD->DADDR);
dma().clearInterrupt();
daddr = (uint32_t)(dma.TCD->DADDR);
dma.clearInterrupt();


if (daddr < (uint32_t)i2s_rx_buffer + sizeof(i2s_rx_buffer) / 2) { if (daddr < (uint32_t)i2s_rx_buffer + sizeof(i2s_rx_buffer) / 2) {
// DMA is receiving to the first half of the buffer // DMA is receiving to the first half of the buffer


void AudioInputI2Sslave::begin(void) void AudioInputI2Sslave::begin(void)
{ {
dma(); // Allocate the DMA channel first
dma.begin(true); // Allocate the DMA channel first


//block_left_1st = NULL; //block_left_1st = NULL;
//block_right_1st = NULL; //block_right_1st = NULL;


CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0 CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0


dma().TCD->SADDR = &I2S0_RDR0;
dma().TCD->SOFF = 0;
dma().TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma().TCD->NBYTES_MLNO = 2;
dma().TCD->SLAST = 0;
dma().TCD->DADDR = i2s_rx_buffer;
dma().TCD->DOFF = 2;
dma().TCD->CITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
dma().TCD->DLASTSGA = -sizeof(i2s_rx_buffer);
dma().TCD->BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
dma().TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma().triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_RX);
dma.TCD->SADDR = &I2S0_RDR0;
dma.TCD->SOFF = 0;
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma.TCD->NBYTES_MLNO = 2;
dma.TCD->SLAST = 0;
dma.TCD->DADDR = i2s_rx_buffer;
dma.TCD->DOFF = 2;
dma.TCD->CITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
dma.TCD->DLASTSGA = -sizeof(i2s_rx_buffer);
dma.TCD->BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_RX);
update_responsibility = update_setup(); update_responsibility = update_setup();
dma().enable();
dma.enable();


I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR; I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR;
I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE; // TX clock enable, because sync'd to TX I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE; // TX clock enable, because sync'd to TX
dma().attachInterrupt(isr);
dma.attachInterrupt(isr);
} }





+ 1
- 4
input_i2s.h View File

protected: protected:
AudioInputI2S(int dummy): AudioStream(0, NULL) {} // to be used only inside AudioInputI2Sslave !! AudioInputI2S(int dummy): AudioStream(0, NULL) {} // to be used only inside AudioInputI2Sslave !!
static bool update_responsibility; static bool update_responsibility;
static inline DMAChannel &dma() __attribute__((always_inline)) {
static DMAChannel mydma;
return mydma;
}
static DMAChannel dma;
static void isr(void); static void isr(void);
private: private:
static audio_block_t *block_left; static audio_block_t *block_left;

+ 18
- 19
output_dac.cpp View File

audio_block_t * AudioOutputAnalog::block_left_1st = NULL; audio_block_t * AudioOutputAnalog::block_left_1st = NULL;
audio_block_t * AudioOutputAnalog::block_left_2nd = NULL; audio_block_t * AudioOutputAnalog::block_left_2nd = NULL;
bool AudioOutputAnalog::update_responsibility = false; bool AudioOutputAnalog::update_responsibility = false;
DMAChannel AudioOutputAnalog::dma;


void AudioOutputAnalog::begin(void) void AudioOutputAnalog::begin(void)
{ {
dma(); // Allocate the DMA channel first
dma.begin(true); // Allocate the DMA channel first


SIM_SCGC2 |= SIM_SCGC2_DAC0; SIM_SCGC2 |= SIM_SCGC2_DAC0;
DAC0_C0 = DAC_C0_DACEN; // 1.2V VDDA is DACREF_2 DAC0_C0 = DAC_C0_DACEN; // 1.2V VDDA is DACREF_2
PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG | PDB_SC_PDBIE | PDB_SC_DMAEN; PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG | PDB_SC_PDBIE | PDB_SC_DMAEN;


dma().TCD->SADDR = dac_buffer;
dma().TCD->SOFF = 2;
dma().TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma().TCD->NBYTES_MLNO = 2;
dma().TCD->SLAST = -sizeof(dac_buffer);
dma().TCD->DADDR = &DAC0_DAT0L;
dma().TCD->DOFF = 0;
dma().TCD->CITER_ELINKNO = sizeof(dac_buffer) / 2;
dma().TCD->DLASTSGA = 0;
dma().TCD->BITER_ELINKNO = sizeof(dac_buffer) / 2;
dma().TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma().triggerAtHardwareEvent(DMAMUX_SOURCE_PDB);
dma.TCD->SADDR = dac_buffer;
dma.TCD->SOFF = 2;
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma.TCD->NBYTES_MLNO = 2;
dma.TCD->SLAST = -sizeof(dac_buffer);
dma.TCD->DADDR = &DAC0_DAT0L;
dma.TCD->DOFF = 0;
dma.TCD->CITER_ELINKNO = sizeof(dac_buffer) / 2;
dma.TCD->DLASTSGA = 0;
dma.TCD->BITER_ELINKNO = sizeof(dac_buffer) / 2;
dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_PDB);
update_responsibility = update_setup(); update_responsibility = update_setup();
dma().enable();
dma().attachInterrupt(isr);
dma.enable();
dma.attachInterrupt(isr);
} }


void AudioOutputAnalog::analogReference(int ref) void AudioOutputAnalog::analogReference(int ref)
audio_block_t *block; audio_block_t *block;
uint32_t saddr; uint32_t saddr;


//saddr = (uint32_t)DMA_TCD4_SADDR;
//DMA_CINT = 4;
saddr = (uint32_t)(dma().TCD->SADDR);
dma().clearInterrupt();
saddr = (uint32_t)(dma.TCD->SADDR);
dma.clearInterrupt();
if (saddr < (uint32_t)dac_buffer + sizeof(dac_buffer) / 2) { if (saddr < (uint32_t)dac_buffer + sizeof(dac_buffer) / 2) {
// DMA is transmitting the first half of the buffer // DMA is transmitting the first half of the buffer
// so we must fill the second half // so we must fill the second half

+ 1
- 4
output_dac.h View File

static audio_block_t *block_left_2nd; static audio_block_t *block_left_2nd;
static bool update_responsibility; static bool update_responsibility;
audio_block_t *inputQueueArray[1]; audio_block_t *inputQueueArray[1];
static inline DMAChannel &dma() __attribute__((always_inline)) {
static DMAChannel mydma;
return mydma;
}
static DMAChannel dma;
static void isr(void); static void isr(void);
}; };



+ 34
- 33
output_i2s.cpp View File

uint16_t AudioOutputI2S::block_right_offset = 0; uint16_t AudioOutputI2S::block_right_offset = 0;
bool AudioOutputI2S::update_responsibility = false; bool AudioOutputI2S::update_responsibility = false;
DMAMEM static uint32_t i2s_tx_buffer[AUDIO_BLOCK_SAMPLES]; DMAMEM static uint32_t i2s_tx_buffer[AUDIO_BLOCK_SAMPLES];
DMAChannel AudioOutputI2S::dma;


void AudioOutputI2S::begin(void) void AudioOutputI2S::begin(void)
{ {
dma(); // Allocate the DMA channel first
dma.begin(true); // Allocate the DMA channel first


block_left_1st = NULL; block_left_1st = NULL;
block_right_1st = NULL; block_right_1st = NULL;
config_i2s(); config_i2s();
CORE_PIN22_CONFIG = PORT_PCR_MUX(6); // pin 22, PTC1, I2S0_TXD0 CORE_PIN22_CONFIG = PORT_PCR_MUX(6); // pin 22, PTC1, I2S0_TXD0


dma().TCD->SADDR = i2s_tx_buffer;
dma().TCD->SOFF = 2;
dma().TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma().TCD->NBYTES_MLNO = 2;
dma().TCD->SLAST = -sizeof(i2s_tx_buffer);
dma().TCD->DADDR = &I2S0_TDR0;
dma().TCD->DOFF = 0;
dma().TCD->CITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
dma().TCD->DLASTSGA = 0;
dma().TCD->BITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
dma().TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma().triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_TX);
dma.TCD->SADDR = i2s_tx_buffer;
dma.TCD->SOFF = 2;
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma.TCD->NBYTES_MLNO = 2;
dma.TCD->SLAST = -sizeof(i2s_tx_buffer);
dma.TCD->DADDR = &I2S0_TDR0;
dma.TCD->DOFF = 0;
dma.TCD->CITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
dma.TCD->DLASTSGA = 0;
dma.TCD->BITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_TX);
update_responsibility = update_setup(); update_responsibility = update_setup();
dma().enable();
dma.enable();


I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE | I2S_TCSR_FR; I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE | I2S_TCSR_FR;
dma().attachInterrupt(isr);
dma.attachInterrupt(isr);
} }




audio_block_t *block; audio_block_t *block;
uint32_t saddr, offset; uint32_t saddr, offset;


saddr = (uint32_t)(dma().TCD->SADDR);
dma().clearInterrupt();
saddr = (uint32_t)(dma.TCD->SADDR);
dma.clearInterrupt();
if (saddr < (uint32_t)i2s_tx_buffer + sizeof(i2s_tx_buffer) / 2) { if (saddr < (uint32_t)i2s_tx_buffer + sizeof(i2s_tx_buffer) / 2) {
// DMA is transmitting the first half of the buffer // DMA is transmitting the first half of the buffer
// so we must fill the second half // so we must fill the second half


void AudioOutputI2Sslave::begin(void) void AudioOutputI2Sslave::begin(void)
{ {
dma(); // Allocate the DMA channel first
dma.begin(true); // Allocate the DMA channel first


//pinMode(2, OUTPUT); //pinMode(2, OUTPUT);
block_left_1st = NULL; block_left_1st = NULL;
AudioOutputI2Sslave::config_i2s(); AudioOutputI2Sslave::config_i2s();
CORE_PIN22_CONFIG = PORT_PCR_MUX(6); // pin 22, PTC1, I2S0_TXD0 CORE_PIN22_CONFIG = PORT_PCR_MUX(6); // pin 22, PTC1, I2S0_TXD0


dma().TCD->SADDR = i2s_tx_buffer;
dma().TCD->SOFF = 2;
dma().TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma().TCD->NBYTES_MLNO = 2;
dma().TCD->SLAST = -sizeof(i2s_tx_buffer);
dma().TCD->DADDR = &I2S0_TDR0;
dma().TCD->DOFF = 0;
dma().TCD->CITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
dma().TCD->DLASTSGA = 0;
dma().TCD->BITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
dma().TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma().triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_TX);
dma.TCD->SADDR = i2s_tx_buffer;
dma.TCD->SOFF = 2;
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
dma.TCD->NBYTES_MLNO = 2;
dma.TCD->SLAST = -sizeof(i2s_tx_buffer);
dma.TCD->DADDR = &I2S0_TDR0;
dma.TCD->DOFF = 0;
dma.TCD->CITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
dma.TCD->DLASTSGA = 0;
dma.TCD->BITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_TX);
update_responsibility = update_setup(); update_responsibility = update_setup();
dma().enable();
dma.enable();


I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE | I2S_TCSR_FR; I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE | I2S_TCSR_FR;
dma().attachInterrupt(isr);
dma.attachInterrupt(isr);
} }


void AudioOutputI2Sslave::config_i2s(void) void AudioOutputI2Sslave::config_i2s(void)

+ 1
- 4
output_i2s.h View File

static audio_block_t *block_left_1st; static audio_block_t *block_left_1st;
static audio_block_t *block_right_1st; static audio_block_t *block_right_1st;
static bool update_responsibility; static bool update_responsibility;
static inline DMAChannel &dma() __attribute__((always_inline)) {
static DMAChannel mydma;
return mydma;
}
static DMAChannel dma;
static void isr(void); static void isr(void);
private: private:
static audio_block_t *block_left_2nd; static audio_block_t *block_left_2nd;

Loading…
Cancel
Save