Skip to content

Commit

Permalink
Make input ADC and output DAC play nicely together
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulStoffregen committed Sep 15, 2014
1 parent 6bdf3a0 commit bdd6750
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 191 deletions.
41 changes: 0 additions & 41 deletions examples/HardwareTesting/PassThroughAnalog/PassThroughAnalog.ino

This file was deleted.

41 changes: 41 additions & 0 deletions examples/HardwareTesting/PassThroughMono/PassThroughMono.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include "utility/pdb.h"

// GUItool: begin automatically generated code
AudioInputAnalog adc1; //xy=161,80
AudioOutputAnalog dac1; //xy=329,47
AudioOutputPWM pwm1; //xy=331,125
AudioConnection patchCord1(adc1, dac1);
AudioConnection patchCord2(adc1, pwm1);
// GUItool: end automatically generated code

void setup() {
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);
}

void loop() {
// Do nothing here. The Audio flows automatically

// When AudioInputAnalog is running, analogRead() must NOT be used.
delay(200);
Serial.print("PDB: SC=");
Serial.print(PDB0_SC, HEX);
Serial.print(", CONFIG=");
Serial.print(PDB_CONFIG, HEX);
Serial.print(", MOD=");
Serial.print(PDB0_MOD);
Serial.print(", IDLY=");
Serial.print(PDB0_IDLY);
Serial.print(", CH0C1=");
Serial.print(PDB0_CH0C1);
Serial.print(", DMA: ");
Serial.print(dma_channel_allocated_mask, HEX);
Serial.println();
}


This file was deleted.

16 changes: 5 additions & 11 deletions gui/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ <h3>Notes</h3>


<script type="text/javascript">
RED.nodes.registerType('AudioInputADC',{
RED.nodes.registerType('AudioInputAnalog',{
shortName: "adc",
inputs:0,
outputs:1,
Expand All @@ -121,26 +121,20 @@ <h3>Notes</h3>
icon: "arrow-in.png"
});
</script>
<script type="text/x-red" data-help-name="AudioInputADC">
<script type="text/x-red" data-help-name="AudioInputAnalog">
<h3>Summary</h3>
<p>Receive audio using the built-in analog to digital converter.</p>
<h3>Audio Connections</h3>
<table class=doc align=center cellpadding=3>
<tr class=top><th>Port</th><th>Purpose</th></tr>
<tr class=odd><td align=center>Out 0</td><td>Audio Channel</td></tr>
</table>
<h3>Parameters</h3>
<table class=doc align=center cellpadding=3>
<tr class=top><th>Name</th><th>Type</th><th>Function</th></tr>
<tr class=odd><td align=center>Pin</td><td>Integer</td><td>Analog Pin To Use</td></tr>
</table>
<p>The pin number should be specified as "A0" to "A20"</p>
<p align=center><img src="adcpins2.jpg"></p>
<p align=center><img src="adcpins1.jpg"></p>
<h3>Functions</h3>
<p>This object has no functions to call from the Arduino sketch. It
simply streams data from the ADC to its output port.</p>
<h3>Hardware</h3>
<p>Pin A2 is used for audio input.</p>
<p align=center><img src="adcpins2.jpg"></p>
<p>Signal range is 0 to 1.2V</p>
<p>Need for DC bias, approx 0.6V</p>
<p>TODO: suggested circuity for signal input</p>
Expand All @@ -151,7 +145,7 @@ <h3>Notes</h3>
<p>TODO: actual noise measurements with different input circuitry
(it's not nearly as quiet as the audio shield)</p>
</script>
<script type="text/x-red" data-template-name="AudioInputADC">
<script type="text/x-red" data-template-name="AudioInputAnalog">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
Expand Down
59 changes: 24 additions & 35 deletions input_adc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,57 +33,43 @@ uint16_t AudioInputAnalog::block_offset = 0;
bool AudioInputAnalog::update_responsibility = false;
DMAChannel AudioInputAnalog::dma;

// #define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_CONT)
// #define PDB_PERIOD 1087 // 48e6 / 44100

void AudioInputAnalog::begin(unsigned int pin)
AudioInputAnalog::AudioInputAnalog() : AudioStream(0, NULL)
{
unsigned int pin = A2;
uint32_t i, sum=0;

// pin specified in user sketches should be A0 to A13
// numbers can be used, but the recommended usage is
// with the named constants A0 to A13
// constants A0-A9 are actually 14 to 23
// constants A10-A13 are actually 34 to 37
if (pin > 23 && !(pin >= 34 && pin <= 37)) return;

dma.begin(true); // Allocate the DMA channel first

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

// Configure the ADC and run at least one software-triggered
// conversion. This completes the self calibration stuff and
// leaves the ADC in a state that's mostly ready to use
analogReadRes(16);
analogReference(INTERNAL); // range 0 to 1.2 volts
//analogReference(DEFAULT); // range 0 to 3.3 volts
analogReadAveraging(8);
// Actually, do many normal reads, to start with a nice DC level
for (i=0; i < 1024; i++) {
sum += analogRead(pin);
}
dc_average = sum >> 10;

// testing only, enable adc interrupt
//ADC0_SC1A |= ADC_SC1_AIEN;
//while ((ADC0_SC1A & ADC_SC1_COCO) == 0) ; // wait
//NVIC_ENABLE_IRQ(IRQ_ADC0);

// set the programmable delay block to trigger the ADC at 44.1 kHz
SIM_SCGC6 |= SIM_SCGC6_PDB;
PDB0_MOD = PDB_PERIOD;
PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
PDB0_CH0C1 = 0x0101;
if (!(SIM_SCGC6 & SIM_SCGC6_PDB)
|| (PDB0_SC & PDB_CONFIG) != PDB_CONFIG
|| PDB0_MOD != PDB_PERIOD
|| PDB0_IDLY != 1
|| PDB0_CH0C1 != 0x0101) {
SIM_SCGC6 |= SIM_SCGC6_PDB;
PDB0_IDLY = 1;
PDB0_MOD = PDB_PERIOD;
PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
PDB0_CH0C1 = 0x0101;
}

// enable the ADC for hardware trigger and DMA
ADC0_SC2 |= ADC_SC2_ADTRG | ADC_SC2_DMAEN;

// set up a DMA channel to store the ADC data
dma.begin(true);
dma.TCD->SADDR = &ADC0_RA;
dma.TCD->SOFF = 0;
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
Expand All @@ -101,14 +87,15 @@ void AudioInputAnalog::begin(unsigned int pin)
dma.attachInterrupt(isr);
}


void AudioInputAnalog::isr(void)
{
uint32_t daddr, offset;
const uint16_t *src, *end;
uint16_t *dest_left;
audio_block_t *left;

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

Expand All @@ -117,26 +104,26 @@ void AudioInputAnalog::isr(void)
// need to remove data from the second half
src = (uint16_t *)&analog_rx_buffer[AUDIO_BLOCK_SAMPLES/2];
end = (uint16_t *)&analog_rx_buffer[AUDIO_BLOCK_SAMPLES];
if (AudioInputAnalog::update_responsibility) AudioStream::update_all();
if (update_responsibility) AudioStream::update_all();
} else {
// DMA is receiving to the second half of the buffer
// need to remove data from the first half
src = (uint16_t *)&analog_rx_buffer[0];
end = (uint16_t *)&analog_rx_buffer[AUDIO_BLOCK_SAMPLES/2];
}
left = AudioInputAnalog::block_left;
left = block_left;
if (left != NULL) {
offset = AudioInputAnalog::block_offset;
offset = block_offset;
if (offset > AUDIO_BLOCK_SAMPLES/2) offset = AUDIO_BLOCK_SAMPLES/2;
//if (offset <= AUDIO_BLOCK_SAMPLES/2) {
dest_left = (uint16_t *)&(left->data[offset]);
AudioInputAnalog::block_offset = offset + AUDIO_BLOCK_SAMPLES/2;
block_offset = offset + AUDIO_BLOCK_SAMPLES/2;
do {
*dest_left++ = *src++;
} while (src < end);
//}
}
//digitalWriteFast(3, LOW);
digitalWriteFast(2, LOW);
}


Expand All @@ -157,6 +144,8 @@ void AudioInputAnalog::update(void)
unsigned int dc, offset;
int16_t s, *p, *end;

//Serial.println("update");

// allocate new block (ok if NULL)
new_left = allocate();

Expand Down
4 changes: 2 additions & 2 deletions input_adc.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
class AudioInputAnalog : public AudioStream
{
public:
AudioInputAnalog(unsigned int pin) : AudioStream(0, NULL) { begin(pin); }
AudioInputAnalog();
virtual void update(void);
void begin(unsigned int pin);
friend void dma_ch9_isr(void);
private:
static audio_block_t *block_left;
static uint16_t block_offset;
Expand Down
17 changes: 12 additions & 5 deletions output_dac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,18 @@ void AudioOutputAnalog::begin(void)
}

// set the programmable delay block to trigger DMA requests
SIM_SCGC6 |= SIM_SCGC6_PDB;
PDB0_IDLY = 1;
PDB0_MOD = PDB_PERIOD;
PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG | PDB_SC_PDBIE | PDB_SC_DMAEN;
if (!(SIM_SCGC6 & SIM_SCGC6_PDB)
|| (PDB0_SC & PDB_CONFIG) != PDB_CONFIG
|| PDB0_MOD != PDB_PERIOD
|| PDB0_IDLY != 1
|| PDB0_CH0C1 != 0x0101) {
SIM_SCGC6 |= SIM_SCGC6_PDB;
PDB0_IDLY = 1;
PDB0_MOD = PDB_PERIOD;
PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
PDB0_CH0C1 = 0x0101;
}

dma.TCD->SADDR = dac_buffer;
dma.TCD->SOFF = 2;
Expand Down
Loading

0 comments on commit bdd6750

Please sign in to comment.