|
|
@@ -152,9 +152,113 @@ void AudioOutputAnalog::isr(void) |
|
|
|
if (AudioOutputAnalog::update_responsibility) AudioStream::update_all(); |
|
|
|
} |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
|
|
|
#elif defined (__MKL26Z64__) |
|
|
|
|
|
|
|
DMAMEM static uint16_t dac_buffer1[AUDIO_BLOCK_SAMPLES]; |
|
|
|
DMAMEM static uint16_t dac_buffer2[AUDIO_BLOCK_SAMPLES]; |
|
|
|
audio_block_t * AudioOutputAnalog::block_left_1st = NULL; |
|
|
|
bool AudioOutputAnalog::update_responsibility = false; |
|
|
|
DMAChannel AudioOutputAnalog::dma1(false); |
|
|
|
DMAChannel AudioOutputAnalog::dma2(false); |
|
|
|
|
|
|
|
void AudioOutputAnalog::begin(void) |
|
|
|
{ |
|
|
|
dma1.begin(true); // Allocate the DMA channels first |
|
|
|
dma2.begin(true); // Allocate the DMA channels first |
|
|
|
|
|
|
|
delay(2500); |
|
|
|
Serial.println("AudioOutputAnalog begin"); |
|
|
|
delay(10); |
|
|
|
|
|
|
|
SIM_SCGC6 |= SIM_SCGC6_DAC0; |
|
|
|
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // VDDA (3.3V) ref |
|
|
|
// slowly ramp up to DC voltage, approx 1/4 second |
|
|
|
for (int16_t i=0; i<2048; i+=8) { |
|
|
|
*(int16_t *)&(DAC0_DAT0L) = i; |
|
|
|
delay(1); |
|
|
|
} |
|
|
|
|
|
|
|
// commandeer FTM1 for timing (PWM on pin 3 & 4 will become 22 kHz) |
|
|
|
FTM1_SC = 0; |
|
|
|
FTM1_CNT = 0; |
|
|
|
FTM1_MOD = (uint32_t)((F_PLL/2) / AUDIO_SAMPLE_RATE_EXACT + 0.5); |
|
|
|
FTM1_SC = FTM_SC_CLKS(1); |
|
|
|
|
|
|
|
dma1.sourceBuffer(dac_buffer1, sizeof(dac_buffer1)); |
|
|
|
dma1.destination(*(int16_t *)&DAC0_DAT0L); |
|
|
|
dma1.interruptAtCompletion(); |
|
|
|
dma1.disableOnCompletion(); |
|
|
|
dma1.triggerAtCompletionOf(dma2); |
|
|
|
dma1.triggerAtHardwareEvent(DMAMUX_SOURCE_FTM1_OV); |
|
|
|
dma1.attachInterrupt(isr1); |
|
|
|
|
|
|
|
dma2.sourceBuffer(dac_buffer2, sizeof(dac_buffer2)); |
|
|
|
dma2.destination(*(int16_t *)&DAC0_DAT0L); |
|
|
|
dma2.interruptAtCompletion(); |
|
|
|
dma2.disableOnCompletion(); |
|
|
|
dma2.triggerAtCompletionOf(dma1); |
|
|
|
dma2.triggerAtHardwareEvent(DMAMUX_SOURCE_FTM1_OV); |
|
|
|
dma2.attachInterrupt(isr2); |
|
|
|
|
|
|
|
update_responsibility = update_setup(); |
|
|
|
/* |
|
|
|
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(); |
|
|
|
dma.enable(); |
|
|
|
dma.attachInterrupt(isr); |
|
|
|
*/ |
|
|
|
} |
|
|
|
|
|
|
|
void AudioOutputAnalog::isr1(void) |
|
|
|
{ |
|
|
|
dma1.clearInterrupt(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
void AudioOutputAnalog::isr2(void) |
|
|
|
{ |
|
|
|
dma2.clearInterrupt(); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void AudioOutputAnalog::update(void) |
|
|
|
{ |
|
|
|
audio_block_t *block; |
|
|
|
block = receiveReadOnly(); |
|
|
|
if (block) { |
|
|
|
__disable_irq(); |
|
|
|
if (block_left_1st == NULL) { |
|
|
|
block_left_1st = block; |
|
|
|
__enable_irq(); |
|
|
|
} else { |
|
|
|
audio_block_t *tmp = block_left_1st; |
|
|
|
block_left_1st = block; |
|
|
|
__enable_irq(); |
|
|
|
release(tmp); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
void AudioOutputAnalog::begin(void) |
|
|
|
{ |
|
|
|
} |