audio I2s Quad + octo2811 : conflict ?

Status
Not open for further replies.

nuage125

Member
Hi,
In my project, I would like to use one AudioOutputI2SQuad (4 HPs) and the library octo2811 but it seems there are some conflicts betwwen these two great libraries.
When I comment the modulo 3 in the file output_i2s_quad.cpp (line 68)
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1) | // DMA_TCD_ATTR_DMOD(3);
octo2811 works well ! but sound doesn't work...
when I leave this end of line uncommented, a lot of leds are off, few leds stay on (this led can be red only, green only or blue only) even if the signal sended to the strip is off for all.

If I use output_i2s (not quad) all is working well (but only 2 HPs of course).

Can you help me please ?

Olivier

PS : I have changed the pin 15 by the 28 in the octo2811 library.
 
Oh, maybe the longer DMA transfers are causing too much latency for OctoWS2811's DMA?

The DMA controller has a 2 level priority preemption scheme. So far I've never actually tried using it. Maybe it's time to try adding this to OctoWS2811?
 
Thank you so much Paul !
I think too that it was a pb like that.
unfortunately, I can't test it from now.
Do yo u think that the method :
DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3, DMAChannel &ch4)
could be the solution ? ch1 2 3 could be for the leds and ch4 for audio ?
thank you again,
Olivier
 
This is a tough problem which I really need to look into.

Can you post a (hopefully small) program which reproduces this problem? That could save me quite a bit of time and (hopefully) produce a solution sooner.
 
Hi Paul !
I have made the most simple program that I can do but you have to solder pin 28 with pin 16 and of course a teensy on 2 audio card + octo2811 with for example 60 leds on pin 2.
Normally, few leds should be on (blue or red or green).
Thank you so much for your help, Paul !
Olivier

#include <Audio.h>
#include <i2c_t3.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include "OctoWS2811.h"



//
//GND VIN
//PIN0: RX1_BT AGND
//PIN1: TX1_BT 3.3V
//PIN2: PIN23: I2S LRCLK
//PIN3: reserved Octo PIN22: I2S TX
//PIN4: reserved Octo PIN21:
//PIN5: GPIO1_DISTO0 PIN20: GPIO1_DISTO3
//PIN6: AUDIO MEMCS (?) PIN19: SCL
//PIN7: SD MOSI PIN18: SDA
//PIN8: GPIO1_DISTO1 PIN17: GPIO1_DISTO2
//PIN9: I2S BCLK PIN16: reserved OctoWS2811
//PIN10: SD SDCS PIN15: I2S_2_TX
//PIN11: I2S MCLK PIN14: SCLK
//PIN12: SD MISO PIN13: I2S RX

//PIN28 linked to PIN 16 for DMA LEDS

AudioOutputI2SQuad audioOutput;
const int ledsPerStrip = 60;
DMAMEM int displayMemory[ledsPerStrip*6];
int drawingMemory[ledsPerStrip*6];
const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);


// Use these with the audio adaptor board
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14

#define NONE 0x000000

int colorList[6]={RED,GREEN,BLUE,PINK,YELLOW,ORANGE};

void switchoff(){
for ( int i=0 ; i<60 ; i++){
leds.setPixel(i, NONE);
}
leds.show();
}

void setup() {

Serial.begin(115200);
AudioMemory(10);

leds.begin();
leds.show();
switchoff();

delay(200);
}

void loop() {

}
 
Looking at this now. Sorry about the long delay.

The first big problem I see is pin 15. OctoWS2811 needs that pin for one of the 3 DMA triggers it uses. :(
 
I'm working on the OctoWS2811 library, to remove this long-standing dependency on these pins. I suspect this project might "just work" if OctoWS2811 need pin 15 for a DMA trigger.
 
I've edited OctoWS2811 to now use only pin 32 on Teensy 3.1 and 3.2. Now pin 15 is unused, so it should be possible to use it for audio while OctoWS2811 runs.

Years ago, the only way I could get OctoWS2811 working was with real PWM signals on 3 pins, using the pin change interrupts to trigger DMA. I had tried to use the timers directly, but always failed. This time around, I found much more info about how to clear the DMA flags inside the timers in the K66 manual. Freescale never documented this in the K20 manuals. Turns out a 3 step sequence is needed, which I never would have guessed. But with the new docs, I was finally able to get the timers to trigger the DMA channels directly.

The K20 chips still lack a DMA trigger for timer overflow, so one physical pin with the PWM signal is still needed. On Teensy 3.2 this used to be pin 16. I changed from FTM1 to FTM2 and moved the reserved pin to pin 32, which is on the bottom side. Now pins 3, 4, 15 and 16 should be available for any other use without interference from OctoWS2811.

Latest code is on github:

https://github.com/PaulStoffregen/OctoWS2811

Later today I'll try running with AudioOutputI2SQuad. The program on msg #5 has compile errors. If you're still here and reading this and you'd like me to test with a program you supply, please post it now. Otherwise I'll just make something up which may or may not be close to your needs.
 
Thank you very much Paul !
If I understand you use only 1 DMA for OctoWS2811 !
Why pin 32 instead of pin 28 (it would be better for me :) )
In my program, I use distometers to modify volume and light. I have not the hardware with me to test different program.

perhaps this code is correct ? :


#include <Audio.h>
#include <i2c_t3.h>
#include "vlc6180x.h"
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include "OctoWS2811.h"

const int ledsPerStrip = 60;
DMAMEM int displayMemory[ledsPerStrip*6];
int drawingMemory[ledsPerStrip*6];
const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);
AudioOutputI2SQuad audioOutput;

AudioSynthWaveformSine sine0; //xy=657,415
AudioSynthWaveformSine sine1;
AudioSynthWaveformSine sine2;
AudioSynthWaveformSine sine3;

/******************* SINUS *********************/
/*AudioConnection patchCord1(sine0, 0, audioOutput, 0);
AudioConnection patchCord2(sine2, 0, audioOutput, 1);
//AudioConnection patchCord3(playSdWav2, 0, audioOutput, 2);
//AudioConnection patchCord4(playSdWav2, 1, audioOutput, 3);
AudioConnection patchCord3(sine2, 0, audioOutput, 2);
AudioConnection patchCord4(sine3, 0, audioOutput, 3);

AudioControlSGTL5000 sgtl5000_1;
AudioControlSGTL5000 sgtl5000_2;

// Use these with the audio adaptor board
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14

void setup() {

Serial.begin(115200);

AudioMemory(20);

leds.begin();
leds.show();
delay(50);

//Wire.begin(I2C_MASTER, 0x00, I2C_PINS_16_17, I2C_PULLUP_INT, I2C_RATE_400);
sgtl5000_1.setAddress(LOW);
sgtl5000_1.enable();
sgtl5000_1.volume(0.6);
delay(200);


sgtl5000_2.setAddress(HIGH);
sgtl5000_2.enable();
sgtl5000_2.volume(0.6);
delay(200);

SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);

if (!(SD.begin(SDCARD_CS_PIN))) {
// stop here, but print a message repetitively
while (1) {
Serial.println("Unable to access the SD card");
Serial1.println("Unable to access the SD card");
delay(500);
}
}
/* TCAselect(TCA_AUDIO_1_2);
writeByte(TPA2016_ADDRESS,0x06,0x20); //default : 3A
writeByte(TPA2016_ADDRESS,0x07,0x01); //default : C2
delay(200);
TCAselect(TCA_AUDIO_3_4);
writeByte(TPA2016_ADDRESS,0x06,0x20); //default : 3A
writeByte(TPA2016_ADDRESS,0x07,0x01); //default : C2*/

sine0.frequency(440,0.2);
sine1.frequency(220,0.2);
sine2.frequency(440,0.2);
sine3.frequency(440,0.2);
}


void loop() {

for (int i=0; i < 60; i++) {
leds.setPixel(i, 0x000000FF);
leds.show();
delayMicroseconds(8000);
}
for (int i=0; i < 60; i++) {
leds.setPixel(59-i, 0x0000000);
leds.show();
delayMicroseconds(8000);
}
}
 
If I understand you use only 1 DMA for OctoWS2811 !

Three DMA channels are still used. The difference is 2 of them are now directly triggered by the timers inside the chip, without using pins.

Previously I was not able to figure out some of the finer points of how to use the timers to trigger DMA, so I resorted to putting the PWM signals onto 3 pins and then using the pin edge detection to trigger DMA. Fortunately, Freescale improved their documentation on the newest chips. That was the key info missing years ago when I created OctoWS2811.

Why pin 32 instead of pin 28 (it would be better for me :) )

It has to be pin 25 or 32. Pin 28 doesn't have PWM controllable from FTM2.

The new K66 chip adds the ability to trigger on timer overflow. K20 doesn't this. Overflow trigger is the missing feature that requires still using 1 pin.

perhaps this code is correct ? :

No, and quite frankly far from it. Audio and i2c_t3 don't work together. You also have a library called vlc6180x.h without info about where to install it. When you post code using any lib that doesn't come from Teensyduino or Arduino's lib manager, I need clear info about exactly where to download it.

I was going to write my own little test program yesterday, but then got sidetracked by the sudden release of Arduino 1.6.10. I'm wrapping up another urgent thing, and then I plan to look at this again tomorrow or over the weekend. If you want me to test with a program of your choosing, please post it ASAP. Please make sure it compiles. Broken examples waste a lot of time....
 
I tested again with this program:

Code:
// https://forum.pjrc.com/threads/35283-audio-I2s-Quad-octo2811-conflict

#include <OctoWS2811.h>
#include <Audio.h>

const int ledsPerStrip = 240;

DMAMEM int displayMemory[ledsPerStrip*6];
int drawingMemory[ledsPerStrip*6];

const int config = WS2811_GRB | WS2811_800kHz;

OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);

AudioSynthWaveformSine sine0;
AudioSynthWaveformSine sine1;
AudioSynthWaveformSine sine2;
AudioSynthWaveformSine sine3;
AudioOutputI2SQuad audioOutput;
//AudioOutputI2S audioOutput;
AudioControlSGTL5000 sgtl5000_1;
AudioControlSGTL5000 sgtl5000_2;
AudioConnection patchCord1(sine0, 0, audioOutput, 0);
AudioConnection patchCord2(sine1, 0, audioOutput, 1);
AudioConnection patchCord3(sine2, 0, audioOutput, 2);
AudioConnection patchCord4(sine3, 0, audioOutput, 3);

void setup() {
  //pinMode(9, OUTPUT);
  AudioMemory(12);
  /*
  sgtl5000_1.setAddress(LOW);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.6);
  sgtl5000_2.setAddress(HIGH);
  sgtl5000_2.enable();
  sgtl5000_2.volume(0.6);
  */
  sine0.frequency(440.00);
  sine1.frequency(493.88);
  sine2.frequency(523.25);
  sine3.frequency(587.33);
  sine0.amplitude(0.99);
  sine1.amplitude(0.99);
  sine2.amplitude(0.99);
  sine3.amplitude(0.99);

  leds.begin();
  leds.show();
}

// Less intense...
#define RED    0x160000
#define GREEN  0x001600
#define BLUE   0x000016
#define YELLOW 0x101400
#define PINK   0x120009
#define ORANGE 0x100400
#define WHITE  0x101010

void loop() {
  Serial.println("loop");
  int microsec = 2000000 / leds.numPixels();  // change them all in 2 seconds
  colorWipe(RED, microsec);
  colorWipe(GREEN, microsec);
  colorWipe(BLUE, microsec);
  colorWipe(YELLOW, microsec);
  colorWipe(PINK, microsec);
  colorWipe(ORANGE, microsec);
  colorWipe(WHITE, microsec);
}

void colorWipe(int color, int wait)
{
  for (int i=0; i < leds.numPixels(); i++) {
    leds.setPixel(i, color);
    leds.show();
    delayMicroseconds(wait);
  }
}

Turns out 96 MHz just doesn't seem to be fast enough for OctoWS2811 and quad audio output, but it works great when Teensy clocks at 120 MHz.

I tested with 1.30-beta1. The 120 MHz option now appears at the end of Tools > CPU Speed.
 
Status
Not open for further replies.
Back
Top