Parcourir la source

Merge pull request #1 from MickMad/master

Add objects to use with Mikroe Audio Codec PROTO (AudioContolWM8731master, AudioInputI2Sslave, AudioOutpuI2Sslave), with example
dds
Paul Stoffregen il y a 11 ans
Parent
révision
8020f09e02
3 fichiers modifiés avec 246 ajouts et 4 suppressions
  1. +154
    -1
      Audio.cpp
  2. +32
    -3
      Audio.h
  3. +60
    -0
      examples/PlaySineMikroe/PlaySineMikroe.ino

+ 154
- 1
Audio.cpp Voir le fichier

@@ -672,6 +672,82 @@ void AudioOutputI2S::config_i2s(void)



/******************************************************************/

void AudioOutputI2Sslave::begin(void)
{
//pinMode(2, OUTPUT);
block_left_1st = NULL;
block_right_1st = NULL;

AudioOutputI2Sslave::config_i2s();
CORE_PIN22_CONFIG = PORT_PCR_MUX(6); // pin 22, PTC1, I2S0_TXD0

DMA_CR = 0;
DMA_TCD0_SADDR = i2s_tx_buffer;
DMA_TCD0_SOFF = 2;
DMA_TCD0_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
DMA_TCD0_NBYTES_MLNO = 2;
DMA_TCD0_SLAST = -sizeof(i2s_tx_buffer);
DMA_TCD0_DADDR = &I2S0_TDR0;
DMA_TCD0_DOFF = 0;
DMA_TCD0_CITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
DMA_TCD0_DLASTSGA = 0;
DMA_TCD0_BITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
DMA_TCD0_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;

DMAMUX0_CHCFG0 = DMAMUX_DISABLE;
DMAMUX0_CHCFG0 = DMAMUX_SOURCE_I2S0_TX | DMAMUX_ENABLE;
update_responsibility = update_setup();
DMA_SERQ = 0;

I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE | I2S_TCSR_FR;
NVIC_ENABLE_IRQ(IRQ_DMA_CH0);
}

void AudioOutputI2Sslave::config_i2s(void)
{
SIM_SCGC6 |= SIM_SCGC6_I2S;
SIM_SCGC7 |= SIM_SCGC7_DMA;
SIM_SCGC6 |= SIM_SCGC6_DMAMUX;

// if either transmitter or receiver is enabled, do nothing
if (I2S0_TCSR & I2S_TCSR_TE) return;
if (I2S0_RCSR & I2S_RCSR_RE) return;

// Select input clock 0
// Configure to input the bit-clock from pin, bypasses the MCLK divider
I2S0_MCR = I2S_MCR_MICS(0);
I2S0_MDR = 0;

// configure transmitter
I2S0_TMR = 0;
I2S0_TCR1 = I2S_TCR1_TFW(1); // watermark at half fifo size
I2S0_TCR2 = I2S_TCR2_SYNC(0) | I2S_TCR2_BCP;

I2S0_TCR3 = I2S_TCR3_TCE;
I2S0_TCR4 = I2S_TCR4_FRSZ(1) | I2S_TCR4_SYWD(15) | I2S_TCR4_MF
| I2S_TCR4_FSE | I2S_TCR4_FSP;

I2S0_TCR5 = I2S_TCR5_WNW(15) | I2S_TCR5_W0W(15) | I2S_TCR5_FBT(15);

// configure receiver (sync'd to transmitter clocks)
I2S0_RMR = 0;
I2S0_RCR1 = I2S_RCR1_RFW(1);
I2S0_RCR2 = I2S_RCR2_SYNC(1) | I2S_TCR2_BCP;

I2S0_RCR3 = I2S_RCR3_RCE;
I2S0_RCR4 = I2S_RCR4_FRSZ(1) | I2S_RCR4_SYWD(15) | I2S_RCR4_MF
| I2S_RCR4_FSE | I2S_RCR4_FSP | I2S_RCR4_FSD;

I2S0_RCR5 = I2S_RCR5_WNW(15) | I2S_RCR5_W0W(15) | I2S_RCR5_FBT(15);

// configure pin mux for 3 clock signals
CORE_PIN23_CONFIG = PORT_PCR_MUX(6); // pin 23, PTC2, I2S0_TX_FS (LRCLK)
CORE_PIN9_CONFIG = PORT_PCR_MUX(6); // pin 9, PTC3, I2S0_TX_BCLK
CORE_PIN11_CONFIG = PORT_PCR_MUX(6); // pin 11, PTC6, I2S0_MCLK
}

/******************************************************************/


@@ -821,6 +897,49 @@ void AudioInputI2S::update(void)
/******************************************************************/


void AudioInputI2Sslave::begin(void)
{
//block_left_1st = NULL;
//block_right_1st = NULL;

//pinMode(3, OUTPUT);
//digitalWriteFast(3, HIGH);
//delayMicroseconds(500);
//digitalWriteFast(3, LOW);

AudioOutputI2Sslave::config_i2s();

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;
update_responsibility = update_setup();
DMA_SERQ = 1;

// 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);
}



/******************************************************************/





@@ -2068,7 +2187,7 @@ bool AudioControlWM8731::enable(void)
write(WM8731_REG_DIGITAL, 0x08); // DAC soft mute
write(WM8731_REG_ANALOG, 0x00); // disable all

write(WM8731_REG_POWERDOWN, 0x60); // linein, mic, adc, dac, lineout
write(WM8731_REG_POWERDOWN, 0x00); // codec powerdown

write(WM8731_REG_LHEADOUT, 0x80); // volume off
write(WM8731_REG_RHEADOUT, 0x80);
@@ -2105,6 +2224,40 @@ bool AudioControlWM8731::volumeInteger(unsigned int n)



/******************************************************************/


bool AudioControlWM8731master::enable(void)
{
Wire.begin();
delay(5);
//write(WM8731_REG_RESET, 0);

write(WM8731_REG_INTERFACE, 0x42); // I2S, 16 bit, MCLK master
write(WM8731_REG_SAMPLING, 0x20); // 256*Fs, 44.1 kHz, MCLK/1

// In order to prevent pops, the DAC should first be soft-muted (DACMU),
// the output should then be de-selected from the line and headphone output
// (DACSEL), then the DAC powered down (DACPD).

write(WM8731_REG_DIGITAL, 0x08); // DAC soft mute
write(WM8731_REG_ANALOG, 0x00); // disable all
write(WM8731_REG_POWERDOWN, 0x00); // codec powerdown

write(WM8731_REG_LHEADOUT, 0x80); // volume off
write(WM8731_REG_RHEADOUT, 0x80);

delay(100); // how long to power up?

write(WM8731_REG_ACTIVE, 1);
delay(5);
write(WM8731_REG_DIGITAL, 0x00); // DAC unmuted
write(WM8731_REG_ANALOG, 0x10); // DAC selected

return true;
}

/******************************************************************/

#define CHIP_ID 0x0000

+ 32
- 3
Audio.h Voir le fichier

@@ -189,11 +189,13 @@ public:
virtual void update(void);
void begin(void);
friend void dma_ch1_isr(void);
protected:
AudioInputI2S(int dummy): AudioStream(0, NULL) {} // to be used only inside AudioInputI2Sslave !!
static bool update_responsibility; // TODO: implement and test this.
private:
static audio_block_t *block_left;
static audio_block_t *block_right;
static uint16_t block_offset;
static bool update_responsibility; // TODO: implement and test this.
};


@@ -205,19 +207,40 @@ public:
void begin(void);
friend void dma_ch0_isr(void);
friend class AudioInputI2S;
private:
protected:
AudioOutputI2S(int dummy): AudioStream(2, inputQueueArray) {} // to be used only inside AudioOutputI2Sslave !!
static void config_i2s(void);
static audio_block_t *block_left_1st;
static audio_block_t *block_right_1st;
static bool update_responsibility;
private:
static audio_block_t *block_left_2nd;
static audio_block_t *block_right_2nd;
static uint16_t block_left_offset;
static uint16_t block_right_offset;
static bool update_responsibility;
audio_block_t *inputQueueArray[2];
};


class AudioInputI2Sslave : public AudioInputI2S
{
public:
AudioInputI2Sslave(void) : AudioInputI2S(0) { begin(); }
void begin(void);
friend void dma_ch1_isr(void);
};


class AudioOutputI2Sslave : public AudioOutputI2S
{
public:
AudioOutputI2Sslave(void) : AudioOutputI2S(0) { begin(); } ;
void begin(void);
friend class AudioInputI2Sslave;
friend void dma_ch0_isr(void);
protected:
static void config_i2s(void);
};



@@ -399,6 +422,7 @@ class AudioControlWM8731 : public AudioControl
{
public:
bool enable(void);
bool disable(void) { return false; }
bool volume(float n) { return volumeInteger(n * 0.8 + 47.499); }
bool inputLevel(float n) { return false; }
bool inputSelect(int n) { return false; }
@@ -407,6 +431,11 @@ protected:
bool volumeInteger(unsigned int n); // range: 0x2F to 0x7F
};

class AudioControlWM8731master : public AudioControlWM8731
{
public:
bool enable(void);
};


class AudioControlSGTL5000 : public AudioControl

+ 60
- 0
examples/PlaySineMikroe/PlaySineMikroe.ino Voir le fichier

@@ -0,0 +1,60 @@
#include <Audio.h>
#include <Wire.h>
#include <SD.h>

AudioSynthWaveform mysine(AudioWaveformSine);
AudioOutputI2Sslave dac;

AudioControlWM8731master codec;

AudioConnection c1(mysine,dac);

int volume = 0;

void setup() {
codec.enable();
delay(100);
while (!Serial) ;
Serial.println("Begin AudioTest");
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(15);

mysine.frequency(440);
mysine.amplitude(0.9);

codec.volume(70);

Serial.println("setup done");
}




void loop() {
/*
Serial.print("cpu: ");
Serial.print(AudioProcessorUsage());
Serial.print(", max: ");
Serial.print(AudioProcessorUsageMax());
Serial.print(", memory: ");
Serial.print(AudioMemoryUsage());
Serial.print(", max: ");
Serial.print(AudioMemoryUsageMax());
Serial.println("");
*/
//int n;
//n = analogRead(15);
//Serial.println(n);
//if (n != volume) {
//volume = n;
//codec.volume((float)n / 10.23);
//}
//n = analogRead(16) / 8;
//Serial.println(n);
//mysine.frequency(200 + n * 4);
//delay(5);
}

Chargement…
Annuler
Enregistrer