phjanderson
Member
I'm trying to build a synthesizer using a Teensy. My current test setup consists of:
I'm polling the potentiometers and encoders 1 by 1 in a function called from the loop() section.
The code used to read the values from I2C (using Wire.h):
And I'm writing the RGB values to the leds using:
The display communication is handled through the LiquidCrystal_I2C library.
All seemed to work wel until I added a Ladder filter component to the code (probably because it's a more CPU intensive component). The sound would start but almost instantly hang. Disabling the code for interaction with the LCD made no difference. Disabling the code for polling the I2C potentiometers and encoders fixed the problem.
It felt to me that there was probably something going on with audio interrupts causing I2C communication to fail and hang with timeouts, so I tried wrapping the code that reads from the potentiometers and encoders with AudioNoInterrupts() and AudioInterrupts():
That seems to fix the problem
I tried searching for other people having the similar issues or more information in general about Teensy 4 audio / I2C interrupt interaction, but couldn't find anything useful.
The Audio Library Processor Usage & Interrupts page on the PJRC website mentions:
The bottom of that page contains a section called Understanding Audio Library Scheduling, which unfortunately only contains several TODOs.
I have the following questions:
- Teensy 4.1
- M5Stack 8Angle (8 potentiometers, 1 switch and 9 RGB leds through I2C)
- M5Stack 8Encoder (8 rotary encoders, 1 switch and 9 RGB leds through I2C)
- 20x4 char LCD connected through I2C using a level shifter
- I2S stereo DAC
- MIDI keyboard connected through the USB Host connector
I'm polling the potentiometers and encoders 1 by 1 in a function called from the loop() section.
The code used to read the values from I2C (using Wire.h):
Code:
int32_t Unit::readLong(uint8_t addr, uint8_t reg) const
{
int32_t value;
Wire.beginTransmission(addr);
Wire.send(reg);
Wire.endTransmission();
Wire.requestFrom(addr, (uint8_t)4);
Wire.readBytes((uint8_t *)&value, 4);
return value;
}
And I'm writing the RGB values to the leds using:
Code:
void Unit::writeBytes(uint8_t addr, uint8_t reg, uint8_t *bytes, size_t size) const
{
Wire.beginTransmission(addr);
Wire.send(reg);
Wire.write(bytes, size);
Wire.endTransmission();
}
The display communication is handled through the LiquidCrystal_I2C library.
All seemed to work wel until I added a Ladder filter component to the code (probably because it's a more CPU intensive component). The sound would start but almost instantly hang. Disabling the code for interaction with the LCD made no difference. Disabling the code for polling the I2C potentiometers and encoders fixed the problem.
It felt to me that there was probably something going on with audio interrupts causing I2C communication to fail and hang with timeouts, so I tried wrapping the code that reads from the potentiometers and encoders with AudioNoInterrupts() and AudioInterrupts():
Code:
AudioNoInterrupts();
int16_t value = m5Unit8Angle.getAnalogInput(angleId, 127);
AudioInterrupts();
I tried searching for other people having the similar issues or more information in general about Teensy 4 audio / I2C interrupt interaction, but couldn't find anything useful.
The Audio Library Processor Usage & Interrupts page on the PJRC website mentions:
So my usage of AudioNoInterrupts() and AudioInterrupts() methods doesn't seem to be the intended usage of those functions.The AudioNoInterrupts function allows you to briefly suspend the audio library, which allows you to change multiple object's settings and have them all take effect at the same time when the library resumes.
The bottom of that page contains a section called Understanding Audio Library Scheduling, which unfortunately only contains several TODOs.
I have the following questions:
- Just to be sure: is my I2C code correct?
- What could be the cause of the problem and why does using AudioNoInterrupts() and AudioInterrupts() solve the problem?
- Is there a better / different way to do the I2C communication I could try to see if it makes any difference?