Bläddra i källkod

Reassign DMA channels for compatibility with OctoWS2811

dds
PaulStoffregen 10 år sedan
förälder
incheckning
33ad99be10
7 ändrade filer med 170 tillägg och 76 borttagningar
  1. +18
    -18
      input_adc.cpp
  2. +8
    -1
      input_adc.h
  3. +35
    -35
      input_i2s.cpp
  4. +10
    -3
      input_i2s.h
  5. +19
    -18
      output_pwm.cpp
  6. +8
    -1
      output_pwm.h
  7. +72
    -0
      utility/dma_chan.h

+ 18
- 18
input_adc.cpp Visa fil

@@ -84,25 +84,25 @@ void AudioInputAnalog::begin(unsigned int pin)
SIM_SCGC7 |= SIM_SCGC7_DMA;
SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
DMA_CR = 0;
DMA_TCD2_SADDR = &ADC0_RA;
DMA_TCD2_SOFF = 0;
DMA_TCD2_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
DMA_TCD2_NBYTES_MLNO = 2;
DMA_TCD2_SLAST = 0;
DMA_TCD2_DADDR = analog_rx_buffer;
DMA_TCD2_DOFF = 2;
DMA_TCD2_CITER_ELINKNO = sizeof(analog_rx_buffer) / 2;
DMA_TCD2_DLASTSGA = -sizeof(analog_rx_buffer);
DMA_TCD2_BITER_ELINKNO = sizeof(analog_rx_buffer) / 2;
DMA_TCD2_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
DMAMUX0_CHCFG2 = DMAMUX_DISABLE;
DMAMUX0_CHCFG2 = DMAMUX_SOURCE_ADC0 | DMAMUX_ENABLE;
DMA_TCD_SADDR(AUDIO_IN_ADC_DMA_CHANNEL) = &ADC0_RA;
DMA_TCD_SOFF(AUDIO_IN_ADC_DMA_CHANNEL) = 0;
DMA_TCD_ATTR(AUDIO_IN_ADC_DMA_CHANNEL) = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
DMA_TCD_NBYTES_MLNO(AUDIO_IN_ADC_DMA_CHANNEL) = 2;
DMA_TCD_SLAST(AUDIO_IN_ADC_DMA_CHANNEL) = 0;
DMA_TCD_DADDR(AUDIO_IN_ADC_DMA_CHANNEL) = analog_rx_buffer;
DMA_TCD_DOFF(AUDIO_IN_ADC_DMA_CHANNEL) = 2;
DMA_TCD_CITER_ELINKNO(AUDIO_IN_ADC_DMA_CHANNEL) = sizeof(analog_rx_buffer) / 2;
DMA_TCD_DLASTSGA(AUDIO_IN_ADC_DMA_CHANNEL) = -sizeof(analog_rx_buffer);
DMA_TCD_BITER_ELINKNO(AUDIO_IN_ADC_DMA_CHANNEL) = sizeof(analog_rx_buffer) / 2;
DMA_TCD_CSR(AUDIO_IN_ADC_DMA_CHANNEL) = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
DMAMUX0_CHCFG(AUDIO_IN_ADC_DMA_CHANNEL) = DMAMUX_DISABLE;
DMAMUX0_CHCFG(AUDIO_IN_ADC_DMA_CHANNEL) = DMAMUX_SOURCE_ADC0 | DMAMUX_ENABLE;
update_responsibility = update_setup();
DMA_SERQ = 2;
NVIC_ENABLE_IRQ(IRQ_DMA_CH2);
DMA_SERQ = AUDIO_IN_ADC_DMA_CHANNEL;
NVIC_ENABLE_IRQ(IRQ_DMA_CH(AUDIO_IN_ADC_DMA_CHANNEL));
}

void dma_ch2_isr(void)
void DMA_ISR(AUDIO_IN_ADC_DMA_CHANNEL)(void)
{
uint32_t daddr, offset;
const uint16_t *src, *end;
@@ -110,8 +110,8 @@ void dma_ch2_isr(void)
audio_block_t *left;

//digitalWriteFast(3, HIGH);
daddr = (uint32_t)DMA_TCD2_DADDR;
DMA_CINT = 2;
daddr = (uint32_t)(DMA_TCD_DADDR(AUDIO_IN_ADC_DMA_CHANNEL));
DMA_CINT = AUDIO_IN_ADC_DMA_CHANNEL;

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

+ 8
- 1
input_adc.h Visa fil

@@ -28,6 +28,13 @@
#define input_adc_h_

#include "AudioStream.h"
#include "utility/dma_chan.h"

#ifdef __MK20DX128__
#define AUDIO_IN_ADC_DMA_CHANNEL 2
#else
#define AUDIO_IN_ADC_DMA_CHANNEL 6
#endif

class AudioInputAnalog : public AudioStream
{
@@ -35,7 +42,7 @@ public:
AudioInputAnalog(unsigned int pin) : AudioStream(0, NULL) { begin(pin); }
virtual void update(void);
void begin(unsigned int pin);
friend void dma_ch2_isr(void);
friend void DMA_ISR(AUDIO_IN_ADC_DMA_CHANNEL)(void);
private:
static audio_block_t *block_left;
static uint16_t block_offset;

+ 35
- 35
input_i2s.cpp Visa fil

@@ -50,30 +50,30 @@ void AudioInputI2S::begin(void)
CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0

DMA_CR = 0;
DMA_TCD1_SADDR = &I2S0_RDR0;
DMA_TCD1_SOFF = 0;
DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
DMA_TCD1_NBYTES_MLNO = 2;
DMA_TCD1_SLAST = 0;
DMA_TCD1_DADDR = i2s_rx_buffer;
DMA_TCD1_DOFF = 2;
DMA_TCD1_CITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
DMA_TCD1_DLASTSGA = -sizeof(i2s_rx_buffer);
DMA_TCD1_BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
DMA_TCD1_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
DMAMUX0_CHCFG1 = DMAMUX_DISABLE;
DMAMUX0_CHCFG1 = DMAMUX_SOURCE_I2S0_RX | DMAMUX_ENABLE;
DMA_TCD_SADDR(AUDIO_IN_I2S_DMA_CHANNEL) = &I2S0_RDR0;
DMA_TCD_SOFF(AUDIO_IN_I2S_DMA_CHANNEL) = 0;
DMA_TCD_ATTR(AUDIO_IN_I2S_DMA_CHANNEL) = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
DMA_TCD_NBYTES_MLNO(AUDIO_IN_I2S_DMA_CHANNEL) = 2;
DMA_TCD_SLAST(AUDIO_IN_I2S_DMA_CHANNEL) = 0;
DMA_TCD_DADDR(AUDIO_IN_I2S_DMA_CHANNEL) = i2s_rx_buffer;
DMA_TCD_DOFF(AUDIO_IN_I2S_DMA_CHANNEL) = 2;
DMA_TCD_CITER_ELINKNO(AUDIO_IN_I2S_DMA_CHANNEL) = sizeof(i2s_rx_buffer) / 2;
DMA_TCD_DLASTSGA(AUDIO_IN_I2S_DMA_CHANNEL) = -sizeof(i2s_rx_buffer);
DMA_TCD_BITER_ELINKNO(AUDIO_IN_I2S_DMA_CHANNEL) = sizeof(i2s_rx_buffer) / 2;
DMA_TCD_CSR(AUDIO_IN_I2S_DMA_CHANNEL) = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
DMAMUX0_CHCFG(AUDIO_IN_I2S_DMA_CHANNEL) = DMAMUX_DISABLE;
DMAMUX0_CHCFG(AUDIO_IN_I2S_DMA_CHANNEL) = DMAMUX_SOURCE_I2S0_RX | DMAMUX_ENABLE;
update_responsibility = update_setup();
DMA_SERQ = 1;
DMA_SERQ = AUDIO_IN_I2S_DMA_CHANNEL;

// TODO: is I2S_RCSR_BCE appropriate if sync'd to transmitter clock?
//I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR;
I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_FRDE | I2S_RCSR_FR;
NVIC_ENABLE_IRQ(IRQ_DMA_CH1);
NVIC_ENABLE_IRQ(IRQ_DMA_CH(AUDIO_IN_I2S_DMA_CHANNEL));
}

void dma_ch1_isr(void)
void DMA_ISR(AUDIO_IN_I2S_DMA_CHANNEL)(void)
{
uint32_t daddr, offset;
const int16_t *src, *end;
@@ -81,8 +81,8 @@ void dma_ch1_isr(void)
audio_block_t *left, *right;

//digitalWriteFast(3, HIGH);
daddr = (uint32_t)DMA_TCD1_DADDR;
DMA_CINT = 1;
daddr = (uint32_t)(DMA_TCD_DADDR(AUDIO_IN_I2S_DMA_CHANNEL));
DMA_CINT = AUDIO_IN_I2S_DMA_CHANNEL;

if (daddr < (uint32_t)i2s_rx_buffer + sizeof(i2s_rx_buffer) / 2) {
// DMA is receiving to the first half of the buffer
@@ -189,27 +189,27 @@ void AudioInputI2Sslave::begin(void)
CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0

DMA_CR = 0;
DMA_TCD1_SADDR = &I2S0_RDR0;
DMA_TCD1_SOFF = 0;
DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
DMA_TCD1_NBYTES_MLNO = 2;
DMA_TCD1_SLAST = 0;
DMA_TCD1_DADDR = i2s_rx_buffer;
DMA_TCD1_DOFF = 2;
DMA_TCD1_CITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
DMA_TCD1_DLASTSGA = -sizeof(i2s_rx_buffer);
DMA_TCD1_BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2;
DMA_TCD1_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
DMAMUX0_CHCFG1 = DMAMUX_DISABLE;
DMAMUX0_CHCFG1 = DMAMUX_SOURCE_I2S0_RX | DMAMUX_ENABLE;
DMA_TCD_SADDR(AUDIO_IN_I2S_DMA_CHANNEL) = &I2S0_RDR0;
DMA_TCD_SOFF(AUDIO_IN_I2S_DMA_CHANNEL) = 0;
DMA_TCD_ATTR(AUDIO_IN_I2S_DMA_CHANNEL) = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
DMA_TCD_NBYTES_MLNO(AUDIO_IN_I2S_DMA_CHANNEL) = 2;
DMA_TCD_SLAST(AUDIO_IN_I2S_DMA_CHANNEL) = 0;
DMA_TCD_DADDR(AUDIO_IN_I2S_DMA_CHANNEL) = i2s_rx_buffer;
DMA_TCD_DOFF(AUDIO_IN_I2S_DMA_CHANNEL) = 2;
DMA_TCD_CITER_ELINKNO(AUDIO_IN_I2S_DMA_CHANNEL) = sizeof(i2s_rx_buffer) / 2;
DMA_TCD_DLASTSGA(AUDIO_IN_I2S_DMA_CHANNEL) = -sizeof(i2s_rx_buffer);
DMA_TCD_BITER_ELINKNO(AUDIO_IN_I2S_DMA_CHANNEL) = sizeof(i2s_rx_buffer) / 2;
DMA_TCD_CSR(AUDIO_IN_I2S_DMA_CHANNEL) = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
DMAMUX0_CHCFG(AUDIO_IN_I2S_DMA_CHANNEL) = DMAMUX_DISABLE;
DMAMUX0_CHCFG(AUDIO_IN_I2S_DMA_CHANNEL) = DMAMUX_SOURCE_I2S0_RX | DMAMUX_ENABLE;
update_responsibility = update_setup();
DMA_SERQ = 1;
DMA_SERQ = AUDIO_IN_I2S_DMA_CHANNEL;

// TODO: is I2S_RCSR_BCE appropriate if sync'd to transmitter clock?
//I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR;
I2S0_RCSR |= I2S_RCSR_RE | I2S_RCSR_FRDE | I2S_RCSR_FR;
NVIC_ENABLE_IRQ(IRQ_DMA_CH1);
NVIC_ENABLE_IRQ(IRQ_DMA_CH(AUDIO_IN_I2S_DMA_CHANNEL));
}



+ 10
- 3
input_i2s.h Visa fil

@@ -24,10 +24,17 @@
* THE SOFTWARE.
*/

#ifndef input_i2s_h_
#define _input_i2sh_
#ifndef _input_i2s_h_
#define _input_i2s_h_

#include "AudioStream.h"
#include "utility/dma_chan.h"

#ifdef __MK20DX128__
#define AUDIO_IN_I2S_DMA_CHANNEL 1
#else
#define AUDIO_IN_I2S_DMA_CHANNEL 5
#endif

class AudioInputI2S : public AudioStream
{
@@ -35,7 +42,7 @@ public:
AudioInputI2S(void) : AudioStream(0, NULL) { begin(); }
virtual void update(void);
void begin(void);
friend void dma_ch1_isr(void);
friend void DMA_ISR(AUDIO_IN_I2S_DMA_CHANNEL)(void);
protected:
AudioInputI2S(int dummy): AudioStream(0, NULL) {} // to be used only inside AudioInputI2Sslave !!
static bool update_responsibility;

+ 19
- 18
output_pwm.cpp Visa fil

@@ -55,22 +55,23 @@ void AudioOutputPWM::begin(void)
SIM_SCGC7 |= SIM_SCGC7_DMA;
SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
DMA_CR = 0;
DMA_TCD3_SADDR = pwm_dma_buffer;
DMA_TCD3_SOFF = 4;
DMA_TCD3_ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2) | DMA_TCD_ATTR_DMOD(4);
DMA_TCD3_NBYTES_MLNO = 8;
DMA_TCD3_SLAST = -sizeof(pwm_dma_buffer);
DMA_TCD3_DADDR = &FTM1_C0V;
DMA_TCD3_DOFF = 8;
DMA_TCD3_CITER_ELINKNO = sizeof(pwm_dma_buffer) / 8;
DMA_TCD3_DLASTSGA = 0;
DMA_TCD3_BITER_ELINKNO = sizeof(pwm_dma_buffer) / 8;
DMA_TCD3_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
DMAMUX0_CHCFG3 = DMAMUX_DISABLE;
DMAMUX0_CHCFG3 = DMAMUX_SOURCE_FTM1_CH0 | DMAMUX_ENABLE;
DMA_SERQ = 3;
DMA_TCD_SADDR(AUDIO_OUT_PWM_DMA_CHANNEL) = pwm_dma_buffer;
DMA_TCD_SOFF(AUDIO_OUT_PWM_DMA_CHANNEL) = 4;
DMA_TCD_ATTR(AUDIO_OUT_PWM_DMA_CHANNEL) = DMA_TCD_ATTR_SSIZE(2)
| DMA_TCD_ATTR_DSIZE(2) | DMA_TCD_ATTR_DMOD(4);
DMA_TCD_NBYTES_MLNO(AUDIO_OUT_PWM_DMA_CHANNEL) = 8;
DMA_TCD_SLAST(AUDIO_OUT_PWM_DMA_CHANNEL) = -sizeof(pwm_dma_buffer);
DMA_TCD_DADDR(AUDIO_OUT_PWM_DMA_CHANNEL) = &FTM1_C0V;
DMA_TCD_DOFF(AUDIO_OUT_PWM_DMA_CHANNEL) = 8;
DMA_TCD_CITER_ELINKNO(AUDIO_OUT_PWM_DMA_CHANNEL) = sizeof(pwm_dma_buffer) / 8;
DMA_TCD_DLASTSGA(AUDIO_OUT_PWM_DMA_CHANNEL) = 0;
DMA_TCD_BITER_ELINKNO(AUDIO_OUT_PWM_DMA_CHANNEL) = sizeof(pwm_dma_buffer) / 8;
DMA_TCD_CSR(AUDIO_OUT_PWM_DMA_CHANNEL) = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
DMAMUX0_CHCFG(AUDIO_OUT_PWM_DMA_CHANNEL) = DMAMUX_DISABLE;
DMAMUX0_CHCFG(AUDIO_OUT_PWM_DMA_CHANNEL) = DMAMUX_SOURCE_FTM1_CH0 | DMAMUX_ENABLE;
DMA_SERQ = AUDIO_OUT_PWM_DMA_CHANNEL;
update_responsibility = update_setup();
NVIC_ENABLE_IRQ(IRQ_DMA_CH3);
NVIC_ENABLE_IRQ(IRQ_DMA_CH(AUDIO_OUT_PWM_DMA_CHANNEL));
}

void AudioOutputPWM::update(void)
@@ -96,15 +97,15 @@ void AudioOutputPWM::update(void)
}
}

void dma_ch3_isr(void)
void DMA_ISR(AUDIO_OUT_PWM_DMA_CHANNEL)(void)
{
int16_t *src;
uint32_t *dest;
audio_block_t *block;
uint32_t saddr, offset;

saddr = (uint32_t)DMA_TCD3_SADDR;
DMA_CINT = 3;
saddr = (uint32_t)(DMA_TCD_SADDR(AUDIO_OUT_PWM_DMA_CHANNEL));
DMA_CINT = AUDIO_OUT_PWM_DMA_CHANNEL;
if (saddr < (uint32_t)pwm_dma_buffer + sizeof(pwm_dma_buffer) / 2) {
// DMA is transmitting the first half of the buffer
// so we must fill the second half

+ 8
- 1
output_pwm.h Visa fil

@@ -28,6 +28,13 @@
#define output_pwm_h_

#include "AudioStream.h"
#include "utility/dma_chan.h"

#ifdef __MK20DX128__
#define AUDIO_OUT_PWM_DMA_CHANNEL 3
#else
#define AUDIO_OUT_PWM_DMA_CHANNEL 7
#endif

class AudioOutputPWM : public AudioStream
{
@@ -35,7 +42,7 @@ public:
AudioOutputPWM(void) : AudioStream(1, inputQueueArray) { begin(); }
virtual void update(void);
void begin(void);
friend void dma_ch3_isr(void);
friend void DMA_ISR(AUDIO_OUT_PWM_DMA_CHANNEL)(void);
private:
static audio_block_t *block_1st;
static audio_block_t *block_2nd;

+ 72
- 0
utility/dma_chan.h Visa fil

@@ -0,0 +1,72 @@
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
*
* Development of this audio library was funded by PJRC.COM, LLC by sales of
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
* open source software by purchasing Teensy or other PJRC products.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice, development funding notice, and this permission
* notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#ifndef dma_chan_h_
#define dma_chan_h_

#define DMA_ISR(ch) DMA_ISR_EXP(ch)
#define DMA_ISR_EXP(ch) dma_ch ## ch ## _isr

#define IRQ_DMA_CH(ch) IRQ_DMA_CH_EXP(ch)
#define IRQ_DMA_CH_EXP(ch) IRQ_DMA_CH ## ch

#define DMAMUX0_CHCFG(ch) DMAMUX0_CHCFG_EXP(ch)
#define DMAMUX0_CHCFG_EXP(ch) DMAMUX0_CHCFG ## ch

#define DMA_TCD_SADDR(ch) DMA_TCD_SADDR_EXP(ch)
#define DMA_TCD_SADDR_EXP(ch) DMA_TCD ## ch ## _SADDR

#define DMA_TCD_SOFF(ch) DMA_TCD_SOFF_EXP(ch)
#define DMA_TCD_SOFF_EXP(ch) DMA_TCD ## ch ## _SOFF

#define DMA_TCD_ATTR(ch) DMA_TCD_ATTR_EXP(ch)
#define DMA_TCD_ATTR_EXP(ch) DMA_TCD ## ch ## _ATTR

#define DMA_TCD_NBYTES_MLNO(ch) DMA_TCD_NBYTES_MLNO_EXP(ch)
#define DMA_TCD_NBYTES_MLNO_EXP(ch) DMA_TCD ## ch ## _NBYTES_MLNO

#define DMA_TCD_SLAST(ch) DMA_TCD_SLAST_EXP(ch)
#define DMA_TCD_SLAST_EXP(ch) DMA_TCD ## ch ## _SLAST

#define DMA_TCD_DADDR(ch) DMA_TCD_DADDR_EXP(ch)
#define DMA_TCD_DADDR_EXP(ch) DMA_TCD ## ch ## _DADDR

#define DMA_TCD_DOFF(ch) DMA_TCD_DOFF_EXP(ch)
#define DMA_TCD_DOFF_EXP(ch) DMA_TCD ## ch ## _DOFF

#define DMA_TCD_CITER_ELINKNO(ch) DMA_TCD_CITER_ELINKNO_EXP(ch)
#define DMA_TCD_CITER_ELINKNO_EXP(ch) DMA_TCD ## ch ## _CITER_ELINKNO

#define DMA_TCD_DLASTSGA(ch) DMA_TCD_DLASTSGA_EXP(ch)
#define DMA_TCD_DLASTSGA_EXP(ch) DMA_TCD ## ch ## _DLASTSGA

#define DMA_TCD_BITER_ELINKNO(ch) DMA_TCD_BITER_ELINKNO_EXP(ch)
#define DMA_TCD_BITER_ELINKNO_EXP(ch) DMA_TCD ## ch ## _BITER_ELINKNO

#define DMA_TCD_CSR(ch) DMA_TCD_CSR_EXP(ch)
#define DMA_TCD_CSR_EXP(ch) DMA_TCD ## ch ## _CSR

#endif

Laddar…
Avbryt
Spara