Let me start off with my setup:
Parts:
I can use FastLed library just fine by itself with the prop shield but when I also try to use Audio Libraries DAC object (AudioOutputAnalog) the leds go haywire. I've tracked down the problem to the DAC's DMA ISR do,while loops. Looks like the loops fill the dac buffer with data and that seems where the problem is because when I comment the loop out the LEDS work fine, of course the DAC won't work though.
And this is the code I used for testing that shows the problem:
I tried disabling the Audio interrupts and core interrupts to no avail. I tried to dig into the FastLED code but got to annoyed so I'm wondering if the octo library can be used with the prop shield?
Parts:
- Teensy 3.2, Arduino 1.6.13, Teensyduino 1.32-beta2
- Prop Shield
- WS2812 Led Strip, 50 leds in a grid.
- Powered by Desk power supply or Lipo battery with 5 V booster, both produce the same problem.
I can use FastLed library just fine by itself with the prop shield but when I also try to use Audio Libraries DAC object (AudioOutputAnalog) the leds go haywire. I've tracked down the problem to the DAC's DMA ISR do,while loops. Looks like the loops fill the dac buffer with data and that seems where the problem is because when I comment the loop out the LEDS work fine, of course the DAC won't work though.
Code:
[FONT=Menlo][COLOR=#bb2ca2]void[/COLOR] AudioOutputAnalog::isr([COLOR=#bb2ca2]void[/COLOR])[/FONT]
[FONT=Menlo]{[/FONT]
[FONT=Menlo] [COLOR=#bb2ca2]const[/COLOR] int16_t *src, *end;[/FONT]
[FONT=Menlo] int16_t *dest;[/FONT]
[FONT=Menlo] audio_block_t *block;[/FONT]
[FONT=Menlo] uint32_t saddr;[/FONT]
[FONT=Menlo]
[/FONT]
[FONT=Menlo] saddr = (uint32_t)(dma.TCD->SADDR);[/FONT]
[FONT=Menlo] dma.clearInterrupt();[/FONT]
[FONT=Menlo] [COLOR=#bb2ca2]if[/COLOR] (saddr < (uint32_t)dac_buffer + [COLOR=#bb2ca2]sizeof[/COLOR](dac_buffer) / [COLOR=#272ad8]2[/COLOR]) {[/FONT]
[COLOR=#008400][FONT=Menlo]// DMA is transmitting the first half of the buffer[/FONT][/COLOR]
[COLOR=#008400][FONT=Menlo]// so we must fill the second half[/FONT][/COLOR]
[FONT=Menlo] dest = (int16_t *)&dac_buffer[AUDIO_BLOCK_SAMPLES];[/FONT]
[FONT=Menlo] end = (int16_t *)&dac_buffer[AUDIO_BLOCK_SAMPLES*[COLOR=#272ad8]2[/COLOR]];[/FONT]
[FONT=Menlo] } [COLOR=#bb2ca2]else[/COLOR] {[/FONT]
[COLOR=#008400][FONT=Menlo]// DMA is transmitting the second half of the buffer[/FONT][/COLOR]
[COLOR=#008400][FONT=Menlo]// so we must fill the first half[/FONT][/COLOR]
[FONT=Menlo] dest = (int16_t *)dac_buffer;[/FONT]
[FONT=Menlo] end = (int16_t *)&dac_buffer[AUDIO_BLOCK_SAMPLES];[/FONT]
[FONT=Menlo] }[/FONT]
[FONT=Menlo] block = AudioOutputAnalog::block_left_1st;[/FONT]
[FONT=Menlo] [COLOR=#bb2ca2]if[/COLOR] (block) {[/FONT]
[FONT=Menlo] src = block->data;
[/FONT]
[COLOR=#008400][FONT=Menlo][COLOR=#FF0000] /*do {[/COLOR][/FONT][/COLOR]
[COLOR=#008400][FONT=Menlo][COLOR=#FF0000] // TODO: this should probably dither [/COLOR][/FONT][/COLOR]
[COLOR=#008400][FONT=Menlo][COLOR=#FF0000] *dest++ = ((*src++) + 32767) >> 4;[/COLOR][/FONT][/COLOR]
[COLOR=#008400][FONT=Menlo][COLOR=#FF0000] } while (dest < end);*/[/COLOR][/FONT][/COLOR][FONT=Menlo]
[/FONT]
[FONT=Menlo] AudioStream::release(block);[/FONT]
[FONT=Menlo] AudioOutputAnalog::block_left_1st = AudioOutputAnalog::block_left_2nd;[/FONT]
[FONT=Menlo] AudioOutputAnalog::block_left_2nd = [COLOR=#bb2ca2]NULL[/COLOR];[/FONT]
[FONT=Menlo] } [COLOR=#bb2ca2]else[/COLOR] {
[/FONT]
[COLOR=#ff0000][FONT=Menlo] /*do {[/FONT]
[FONT=Menlo] *dest++ = 2047;[/FONT]
[FONT=Menlo] } while (dest < end);*/
[/FONT][/COLOR]
[FONT=Menlo] }[/FONT]
[FONT=Menlo] [COLOR=#bb2ca2]if[/COLOR] (AudioOutputAnalog::update_responsibility) AudioStream::update_all();[/FONT]
[FONT=Menlo]}[/FONT]
Code:
/*
LED's(#) are arranged in a grid seen
below, this is just one strip
broken up into many strips.
Where the arrows point to direction
of the signal path and the last led
of each row connect directly below it.
#<-#<-#<-#<-#<-#<-#<-#<-#<-#<--Power, GND, Signal
#->#->#->#->#->#->#->#->#->#
#<-#<-#<-#<-#<-#<-#<-#<-#<-#
#->#->#->#->#->#->#->#->#->#
#<-#<-#<-#<-#<-#<-#<-#<-#<-#
#->#->#->#->#->#->#->#->#->#
#<-#<-#<-#<-#<-#<-#<-#<-#<-#
#->#->#->#->#->#->#->#->#->#
#<-#<-#<-#<-#<-#<-#<-#<-#<-#
#->#->#->#->#->#->#->#->#-># (end of strip)
Led pattern for this sketch should
just starts at the bottom and turn on
a row of LEDS the moves to the next
row above. Once at the top row start
over.
*/
#include "FastLED.h"
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
AudioSynthWaveformSine sinewave;
AudioOutputAnalog dac;
AudioConnection patch(sinewave, dac);
#define NUM_LEDS 50
#define DATA_PIN 11
#define DAC_ENABLE 5
#define LED_ENABLE 7
CRGB leds[NUM_LEDS];
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(DAC_ENABLE, OUTPUT);
pinMode(LED_ENABLE, OUTPUT);
//digitalWrite(DAC_ENABLE, HIGH);
digitalWrite(LED_ENABLE, HIGH);
AudioMemory(10);
while (!Serial);
delay(100);
Serial.println("Start FastLED w/ Audio Library DAC Problem Test.");
FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(60);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Black;
}
FastLED.show();
delay(50);
sinewave.amplitude(0.5);
sinewave.frequency(440);
}
void loop() {
for (int x = 9; x >= 0; x--) {
for (int i = 4; i >= 0; i--) {
int value = (i % 2);
if (value) value = (i * 10) + 9 - x;
else value = (i * 10) + x;
leds[value] = CRGB::Red;
}
//__disable_irq();
//AudioNoInterrupts();
FastLED.show();
//AudioInterrupts();
//__enable_irq();
delay(100);
}
delay(100);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Black;
}
//__disable_irq();
//AudioNoInterrupts();
FastLED.show();
//AudioInterrupts();
//__enable_irq();
Serial.print("Current Usgae: ");
Serial.print(AudioProcessorUsage());
Serial.print(" | Usage Max: ");
Serial.print(AudioProcessorUsageMax());
Serial.print(" | Memory: ");
Serial.print(AudioMemoryUsage());
Serial.print(" | Memory Max: ");
Serial.println(AudioMemoryUsageMax());
delay(1000);
}