Custom wavtooeasy board

[settings]
mode = serial
sample_rate = 44100
speakers_volume = 19
headphone_volume = -7
disable_leds = false

heres my config file, is there a specific way i need to format the sd card?
i also have been playing around with the schematic, now when theres no sd card, both leds blink but with the sd card no led comes on

I wouldn’t know. Perhaps with the SD inserted the program is not starting at all because a HW issue of some kind.

The normal behavior is green LED fixed ON with red LED blinking slowly. Whenever an audio file is playing, the red LED will blink faster.

The SD card should be formatted with FAT32 file system.

Hello, @Ivan , I didn’t know you were thr o e that wrote the code fir the wavetooeasy. Wow

I am really grateful for your assistance so far.
I have one more query, I am having issues getting the audio from thr dac, thr stm32 communicates with my arduino, and it starts playing the wav file, the led blinds rapidly, however the dac doesn’t produce any audio and when I price thr i2s pins, I don’t see any signal,
My questions are

  1. Would the stm32 send out it’s i2s data even if the dac isn’t communicating with it
  2. Is it possible to connect another dac (eg pcm5102)to the i2s pins of the stm32, because I know in your schematic, the stm communicates with thr dac through i2s and i2c.
  3. How do I enable debug mode, and when I do, would the debug info be sent over serial , or do I need to use the jtag

Hi @Oluwadara_Olaifa,

  1. I don’t think so. You can try to avoid initializing the codec by commenting these two lines.

  2. You’ll probably need to modify the source. I don’t remember how the pcm5102 codec works.

  3. Try setting this constant to 1. You’ll lose serial mode (sending commands over serial to play wav files).

Hello Ivan thank you for your last message it really helped me find the issue, (It was the hps switch of the lm49450 as well as the i2c resistors I left out.

I have gotten the ability to play wavs now. However I am currently having a noise issue. The circuit is totally silent when nothing is playing, however as I play a wav file, there’s an audible noise . Do you have any ideas,
Is this typical?
Ps I am using a boost converter to supply the 5v(tps61023) and a 3.3v ldo. I have attached a sample. I am playing a file containing 10 seconds of silence on the wavtooeasy.

Sorry for the late reply. I was out of office.

It sounds like electrical interference. Maybe a layout problem. The WaveTooEasy is completely silent (noise wise) whenever there is audio or not.

Thanks Ivan. I actually fixed it, the noise was coming from a boost converter I chose.

I am in the process of modifying how the io mode works , I have 6 buttons on my device and I want to use them to control 6 wavs. The catch is that I have multiple folders with wavs, and I want to switch to other folders using the 6th button.
Do you have any advise for me?
I am abit stuck

i modified the initializeio mode function but im looking for a way to dynamically change the folder the wavs are in. i plan on having 6 folders(00 to 05 each containing 6 wavs. then 6 buttons that play the wavs in those folders(1.wav to 6.wav) however to change folders i want to press either an extra button or the button 6 then an extra button that would switch to the folder corresponding to that button

bool initializeIoMode()
{
    // Initialize players list
    players.initialize(true);

    // hardcoded settings for pin1 through pin6
    for (uint8_t i = 0; i < 6; i++)
    {
        char file_path[128];
      sprintf(file_path, "\\%s\\%i.wav", current_folder, i+1);

        io_pins[i] = new IoPin(i, file_path, PinActiveLow, EdgeTrigger, PlayModeNormal, 5.0, DeassertPause, 5);
        if (!io_pins[i]->begin())
        {
            debugMsg(DebugError, "Could not initialize pin %i", i);
            return false;
        }
    }

    return true;
}


thats my current code

@Ivan i would appreciate your advose.
also do you know if the stm32f4 would work with the adafruit neopixel library. i am considering rgb leds

Hi @Oluwadara_Olaifa ,

Doing a program like that will require to heavily modify the code. Perhaps modifying the IoPin class to do what you want it to do.

I wouldn’t know. There is the LedStrip Library included in the core files, but I never tested it with the WaveTooEasy (it works fine with PropBoard). It uses the SPI on pins PB5, PA6 and PA5, so I don’t think it will work on WaveTooEasy HW since PB5 is not exposed. Maybe in your board it is, or you can search for another combination of SPI pins, but again it will require some study to understand its limits on WaveTooEasy HW.

hi ivan, on my board pb5 us exposed however pb6 is in use by the i2c port for the lm49450
there are 3 ports, I2C1(PB6/7), I2C2(PB10/3), I2C3(PA8/PB4)
i2c 2 looks like the most suitable. Any idea where in the code i can change the port? then I can use the spi led controller.
if i focus my attention to the io pin class would i be able to modify it?
can i use the arduino pin naming and functions, like (digitalRead(pa0); )?
or do i need to use the io_pins[i] array (digitalRead(io_pins[2])

The function that initializes the SPI is here: https://github.com/Artekit/artekit_stm32f401-core/blob/master/libraries/SPI/src/SPI.cpp#L43

You can use digitalRead and digitalWrite with pins on the WaveTooEasy. The values for those functions can be found here: https://github.com/Artekit/artekit_stm32f401-core/blob/master/variants/wavetooeasy_v1/variant.h#L51

The mapping for the pins is here: https://github.com/Artekit/artekit_stm32f401-core/blob/master/variants/wavetooeasy_v1/variant.cpp#L47

If you use the Arduino way, you shouldn’t use the IoPin class for those pins. The IoPin class is there to glue together IO handling and audio playing.

Hi, Ivan, I put modifying the button controls on hold for abit. I have been trying to swap the lm49450 to an adau1701 that also has i2s however the code seems to be deeply meshed with the i2c functions provided by the lm49450.
I also noticed a couple of files in the bootloader, do you have any advise for me concerning making these modifications.

It’s really kicking my butt so far

Hi @Oluwadara_Olaifa,

I wouldn’t know how to help on this. You can try to replace the 7 function calls for the codec in the Audio Manager module.

The functions for the codec are the ones starting with “lm49450”.

I don’t recall files in the bootloader regarding audio.

Hello Ivan, how do I compile the bootloader file to get a bin file?
@Ivan

Sorry @Oluwadara_Olaifa for the late reply.

The bootloader compiles with GCC. I used Eclipse CDT + ARM Cortex Plugin + GCC, and OpenOCD for flashing.

thanks, i have a working sketch currently for the stm32, can you suggest any improvements? i basically stole functions from the player.h file as well as the led strip library of the prop board

#include <Arduino.h>
#include "Player.h"
#include "Led.h"
#include <LedStrip.h>
LedStrip myLedStrip;
// Initialize PlayersPool instance
PlayersPool players = PlayersPool::getInstance();
Player* channelPlayers[6] = {NULL, NULL, NULL, NULL, NULL, NULL};

#define DEBOUNCE_DELAY 50  // in milliseconds
bool lastChannelStates[6] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};  // assume all pins are HIGH initially
unsigned long lastDebounceTimes[6] = {0, 0, 0, 0, 0, 0};

BoardLed led1(LED1);
BoardLed led2(LED2);

// Additional variables for bank switching
bool bankSwitchMode = false;
unsigned long bankSwitchStartTime = 0;
const unsigned long BANK_SWITCH_DURATION = 3000; // 3 seconds
const unsigned long LONG_PRESS_DURATION = 2000; // 2 seconds
unsigned long channel6PressStartTime = 0;
bool channel6Pressed = false;
char currentBank = '1';  // Default bank

bool checkingLongPress = false;  // New flag to track if we're checking for a long press on CHANNEL6

void debugMsg(const char* type, const char* format, int pin_num) {
    char msg[100];
    sprintf(msg, format, pin_num);
    Serial.print(type);
    Serial.print(": ");
    Serial.println(msg);
}

void releaseIfStopped(Player*& player) {
    if (player && player->getStatus() == playerStopped) {
        players.release(player);
        player = NULL;
    }
}

static void pollAudioActivityLED() {
    static bool playing = false;
    led2.setOn();

    if (Audio.isPlaying() && !playing) {
        playing = true;
        led1.stopBlink();
        led1.blink(250, 125);
    } else if (!Audio.isPlaying() && playing) {
        playing = false;
        led1.stopBlink();
        led1.blink(1000, 500);
    }
}

void setup() {
    Serial.begin(9600);
    Audio.begin(44100);
    led1.initialize();
    led2.initialize();
    pinMode(CHANNEL1, INPUT);
    pinMode(CHANNEL2, INPUT);
    pinMode(CHANNEL3, INPUT);
    pinMode(CHANNEL4, INPUT);
    pinMode(CHANNEL5, INPUT);
    pinMode(CHANNEL6, INPUT);

    led2.setOn();
    led1.blink(1000, 500);
 myLedStrip.begin(6, WS2812B);
    players.initialize();



     // Set the 1st LED with white color
    myLedStrip.set(1, 255, 255, 255);

    // Set the 2nd LED with red color
    myLedStrip.set(2, 255, 0, 0);

    // Set the 3rd LED with green color
    myLedStrip.set(3, 0, 255, 0);

    // Set the 4th LED with blue color
    myLedStrip.set(4, 0, 0, 255);

    // Update all the LEDs
    myLedStrip.update();

    // Delay a second
    delay(1000);

    // Sets all the LEDs with some color
    // Note the first parameter: when zero
    // all the LEDs are set with the same color
    myLedStrip.set(0, 111, 55, 255);

    // Update all the LEDs
    myLedStrip.update();

    // Delay half a second
    delay(500);
}

void loop() {
    pollAudioActivityLED();

    bool currentChannel6State = digitalRead(CHANNEL6);
    debugMsg("DebugInfo", "Current Channel 6 State:", currentChannel6State);

    if (currentChannel6State == LOW && !channel6Pressed) {
        channel6PressStartTime = millis();
        channel6Pressed = true;
        checkingLongPress = true;  
        debugMsg("DebugInfo", "Channel 6 Press Detected", 0);
    } else if (currentChannel6State == HIGH && channel6Pressed) {
        channel6Pressed = false;
        channel6PressStartTime = 0;
        checkingLongPress = false;
        debugMsg("DebugInfo", "Channel 6 Release Detected", 0);
    }

    if (channel6Pressed && (millis() - channel6PressStartTime > LONG_PRESS_DURATION)) {
        led1.blink(500, 500);
        led2.blink(500, 500);
        bankSwitchMode = true;
        bankSwitchStartTime = millis();
        channel6Pressed = false;
    }

    if (bankSwitchMode && (millis() - bankSwitchStartTime > BANK_SWITCH_DURATION)) {
        bankSwitchMode = false;
        led1.stopBlink();
        led2.stopBlink();
    }

    if (bankSwitchMode) {
        for (int i = 0; i < 5; i++) {
            int pin = CHANNEL1 + i;
            if (digitalRead(pin) == LOW) {
                currentBank = '1' + i;
                bankSwitchMode = false;
                led1.stopBlink();
                led2.stopBlink();
                break;
            }
        }
    } else {
        for (int i = 0; i < 6; i++) {
            int pin = CHANNEL1 + i;
            bool currentReading = digitalRead(pin);

            if (checkingLongPress && i == 5) continue;

            if (currentReading != lastChannelStates[i]) {
                lastDebounceTimes[i] = millis();
            }

            if ((millis() - lastDebounceTimes[i]) > DEBOUNCE_DELAY) {
                if (currentReading == LOW && !channelPlayers[i]) {
                    channelPlayers[i] = players.acquire();
                    if (channelPlayers[i]) {
                        char filename[] = "\\0X\\Y.wav";
                        filename[2] = currentBank;
                        filename[4] = '1' + i;
                        if (!channelPlayers[i]->play(filename, PlayModeNormal)) {
                            debugMsg("DebugError", "Pin %i - error playing", pin);
                            players.release(channelPlayers[i]);
                        } else {
                            debugMsg("DebugInfo", "Pin %i playing", pin);
                        }
                    }
                }
                releaseIfStopped(channelPlayers[i]);
            }

            lastChannelStates[i] = currentReading;
        }
    }

    players.poll();
    delay(100);
}

Hello @Oluwadara_Olaifa,

I’m glad you could combine all the pieces together!

I can see one thing. Maybe changing

void releaseIfStopped(Player*& player)

into

void releaseIfStopped(Player* player)

Just for clarity.

hello ivan i extracted this function from your prop bord power api however i cant seem to figure out the naming convention for this " ADC_Channel_17". i changed the read battery pin to ADC_Channel_14 thinking it would be conneted to pc4 instead of pc0 that you used(ADC_Channel_10)

`uint16_t readBattery()
{
uint16_t battery;
uint16_t vrefint;

// Read VREFINT
while (ADC_GetSoftwareStartConvStatus(ADC1) != RESET);
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 1, ADC_SampleTime_84Cycles);
ADC_SoftwareStartConv(ADC1);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

vrefint = ADC1->DR;

while (ADC_GetSoftwareStartConvStatus(ADC1) != RESET);
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_84Cycles);
ADC_SoftwareStartConv(ADC1);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

battery = ADC1->DR;
battery = battery * 1210 / vrefint;

return battery / 0.233f;
}`

@ivan i am making some slight changes to the bootloader can i possibly get your gcc commands for compiling the bootloader bin