Problem with FastLed Library and Audio Library Dac Object

Status
Not open for further replies.

duff

Well-known member
Let me start off with my setup:

Parts:
  1. Teensy 3.2, Arduino 1.6.13, Teensyduino 1.32-beta2
  2. Prop Shield
  3. WS2812 Led Strip, 50 leds in a grid.
  4. 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]
And this is the code I used for testing that shows the problem:
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);
}
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?
 
So to followup on this thread I found an answer to my Audio library DAC FastLED problem, The WS2812 tight timing gets all mucked up with the Audio Interrupts so you need to add this to the top of your code before including FastLed
#define FASTLED_ALLOW_INTERRUPTS 0
Now this solves the LED part but now I need to see if disabling interrupts will effect the Audio Library. So not trying to make head or tails of what the FastLED library is doing, the code layout sucks IMHO, and is a pain in ass to even try to follow, I gave up, don't have the time.

Now my question: Can the OctoWS2811 library work with the prop shield? , Paul, anyone?
 
Now my question: Can the OctoWS2811 library work with the prop shield? , Paul, anyone?
Several of the pins overlap between the octows2811 shield and the prop shield (2, 5, 6, 7, 12), and neither 11 nor 13 are used for LEDs on the octows2811. So I doubt it would work without some rework, but perhaps it does.
 
Several of the pins overlap between the octows2811 shield and the prop shield (2, 5, 6, 7, 12), and neither 11 nor 13 are used for LEDs on the octows2811. So I doubt it would work without some rework, but perhaps it does.
Thanks Michael, I'm not really into reworking any libraries or looking into it either, since this is for a gift I need something that works now. Probably won't buy anymore prop shields now either, seems to me that if you sell a shield that has both options for Audio and Leds that the software should work, or maybe not?
 
Thanks Michael, I'm not really into reworking any libraries or looking into it either, since this is for a gift I need something that works now. Probably won't buy anymore prop shields now either, seems to me that if you sell a shield that has both options for Audio and Leds that the software should work, or maybe not?

The prop shield works well for me using both WS2812 (neopixel) LEDs and audio sound, using the normal Adafruit_Neopixel library, and the Audio library support for the DAC. Granted, I don't have tons of LEDs, and I don't really stress out the audio features (mostly I've used it to play MP3 songs).

The prop shield does not work well with the octows2811 shield nor the audio shield because of pin overlap.
 
Ok, I'll check that Adafruit library out, been up for the last 3 days getting all the hardware working and when the recommended libraries where used and didn't work together out of the box I was a bit demoralized. I did read that SPI based LEDS work fine with interrupts and FastLED but I have a crap load of the WS2812's so those are the ones I need to use.
 
Try using the OctoWS2811 library without the shield. That's what I did to get the audio adapter and my WS2812s w/ fastLED working at the same time.
 
It's pretty easy to modify any example that uses I2S audio output, to instead send to a different type of output.

For an example, check out the PT8211 page. Scroll down to "Modifying Existing Code For PT8211". The process is basically the same, just use "AudioOutputAnalog" instead of "AudioOutputPT8211".
 
Status
Not open for further replies.
Back
Top