STM32 Audio Codec

by JonMackey in Circuits > Arduino

82 Views, 0 Favorites, 0 Comments

STM32 Audio Codec

STM32 Audio Codec.jpeg
STM32 Audio Codec Demo

This is an STM32 project that uses the TLV320AIC3204 codec.

This STM32 project's PCB is essentially a demo board for the Texas Instruments TLV320AIC3204 audio codec with the addition of a display and remote control via a 433MHz radio, TTL serial or USB.

The project supports WAV and MP3 audio formats.

The board supports up to three input sources and two outputs.

The configuration shown in the photos has two 3.5mm jacks, one for line in 1, and the headphone jack.

If needed, it would be simple to add the remaining 3.5mm jacks. Line in 3 can also optionally be either an on-board or external microphone.


The implementation example for this instructable is a replacement for my old Audio Alert project. The audio quality is much better and it's much easier to manage the sound files. In normal operation, the Audio Alert passes audio from input 1 through to the headphone jack. When an alert request is received via the radio, serial port or USB, the input stream is half muted, the alert tone plays, followed by the associated sound file. I use this in my woodshop to let me know when the dust collector bin is full or when the dust collector filter needs cleaning. In the woodshop the alert message is sent from my Dust Collector Monitor project.

Supplies

(1) 1mm pitch, 10cm, 12P, AB (reversed) FFC cable source

(4) M2x3 Button head stainless steel screws source

(4) M2x5 Button head stainless steel screws source

(4) M2x6 Button head stainless steel screws source

(8) M2xL2xOD3.2 brass inserts source

(8) M2xL3xOD3.2 brass inserts source

Optional:

(1) 433MHz RFM69CW module source

(1) 433MHz PCB Antenna, 40x7mm, with ipex connector source


The main board and parts list is available on PCBWay here.

The display board and parts list is available on PCBWay here.

As noted above, both of these (bare) boards are available on PCBWay.com. I’ve been using PCBWay since the first board I designed. High quality boards at a reasonable price, with excellent customer service.

The Boards

Main PCB w radio.jpeg
Annotated Board.jpeg

The audio section of the PCB is based on the TI reference design.

The project uses a STMicroelectronics STM32F412RE processor. This processor has the speed and enough memory to easily support the codec. The crystals are placed as recommended by the STMicroelectronics AN2867 design guide, chapter 7.2. The capacitor values selected take into account the capacitance of the traces from the processor to the crystal pads.


Soldering the main board

- add the STM32F412 and the TLV320AIC3204 to the board first before any other parts. The pins on the STM32F412 have a 0.5mm pitch making them difficult to mount. The TLV320AIC3204 is in a VQFN 32 pin 0.5mm pitch package. It’s easier to accurately check continuity on these two parts before the board is fully populated.

- mount the rest of the surface mount parts.


Soldering the display board

- add the 40 pin FFC connector to the board first before any other parts. The pins on the connector have a 0.5mm pitch making them difficult to mount. It’s easier to accurately check continuity on the connector before the board is fully populated.

- mount the rest of the surface mount parts.


Mounting the display

The 4” display should be mounted to the back of the display board using three strips of double sided tape suitable for displays. I recommend using 8mm wide 3M brand 9080 double sided tape.

The 3D Parts

3D Parts.png

Print the 3D parts. The Top, Middle, and dust cover prints need to be rotated by 180° on the X or Y axis. Once rotated, no support is needed.


Note that only the input line 1 and headphone jacks have holes in the Middle and Base prints. Let me know if you need the holes for all or some of the remaining jacks and I'll generate the STLs.

The Software

Arduino Config.png

I chose to develop this project using the Arduino IDE rather than the STMicroelectronics STM32CubeMX IDE because my display classes are dependent on the Arduino environment.

The software for this project can be downloaded from GitHub here.

If you don't already have the STM32 boards package loaded, you can load it via Arduino IDE->Tools->Board->Boards Manager... Then load the "STM32 boards groups".


Other than standard Arduino IDE and STMicroelectronics package, this project uses the following libraries:

- libmad - MPEG audio decoder library.

Copyright (C) 2000-2004 Underbit Technologies, Inc.

This project uses an edited version of libmad. I'm using Phil Schatzmann's version.

- SdFat version 2.3.0 - provides access to FAT16/FAT32/exFAT file systems on SD.

Copyright (C) 2011..2020 Bill Greiman


Some STM32 initialization code was generated using STM32CubeMX and copied to my sources.

Configure the board in the Arduino IDE's Tool menu based on the screenshot above.

Open the Arduino IDE Settings and point the Sketchbook Location to the STM32 Audio codec folder, the folder that contains the libraries folder.

Open the sketch AudioAlert.ino and verify that it builds.


If there are no errors, attach your ST-Link to the ST-Link header on the main board and upload the sketch. Note that you should only connect 3 wires: GND, SWCLK and SWIO. You don't want to power the main board via the ST-Link cable. The board should be powered via the USB-C connector (plugged into a wall wart or computer.)


If there are no errors, proceed to the next step or continue below for more detail about the software.


About the software:

The project code, as written, provides the following:

- An STM32 specific class to control the TLV320AIC3204 audio codec. This class is in no way complete in terms of all of the possible functions provided by the codec. One of the codec DAC functions is to generate tones. You determine each tone's frequency and the duration. The tones can be strung together.

- A rudimentary file system based on 32 bit tags rather than filenames. File data is stored on a Winbond 25Qxx serial flash chip. The file sector map is stored on a AT24C EEPROM. This separation allows the sector map to be updated without constantly writing to the NOR flash chip. The 25Qxx flash chip is rated for at least 100K write cycles, where the AT24C can be written at least 1M times.

- The radio code is a port of Felix Rusu's RFM69 library. Copyright LowPowerLab LLC 2018. My port supports a subset of the features provided in Felix Rusu's library.

- My display controller can drive many common displays such as TFT_ILI9488, OLED_SSD1306, etc.. The display controller base class provides basic drawing commands, such as MoveTo, Fill, DrawLine, DrawCircle, DrawFrame, DrawRoundedRect, etc..

- Text is rendered using my XFont library. Any vector font file can be converted to a single point size compressed bitmap font using my SubsetFontCreator app. The resulting file is a header that is compiled into the Arduino sketch. The compressed bitmap font file is either 1-bit, for use on monochrome displays, or 8-bit antialiased, for use on color displays. 1-bit can also be used on color displays if flash is limited.

- My XView library is a high level set of classes used to draw and manage the user interface. Commonly used classes are XButton, XDialogBox, XAlert, XMenu, XKeyboard, XTextField, XLabel, etc.. The individual views are drawn in a hierarchical order to facilitate hit testing and drawing. Custom subclasses are used for project specific views.

- This project uses a resistive touch screen. The class XPT2046 handles converting the values returned by the XPT2046 resistive touch screen controller IC to global display coordinates. The values returned by the controller aren't linear. As part of the setup process, a table is created to map the values returned to a more linear value, both in x/y location and z pen pressure. The conversion is still a work in progress but it works well enough.

Assembly

Assy.jpeg

After printing the 3D parts, add brass inserts as shown.


Install (4) M2 x 3 x 3.2OD Base Inserts

Base Inserts


Install (4) M2 x 2 x 3.2OD Middle Inserts

Middle Inserts


Install (4) M2 x 2 x 3.2OD Top Inserts

Top Inserts


Install (4) M2 x 5 screws to mount the board in the Base print.

PCB Mounted


Setup

Shop Setup

Shop Headphones

The pictures above shows the setup I use in my shop.

This board is powered via the USB-C connector.

The software as configured will use the TTL serial pins for serial communication. If you prefer USB, you can enable USB serial via the Arduino IDE Tools menu. The TTL baud rate is 19200.

Attach a USB serial to TTL module to the 3 pin serial header located near the display connector.

Using the switch next to the USB-C connector, apply power by sliding the switch away from the USB-C connector.

When the board is powered for the first time you should see the following:

Starting...

OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE

RCC_OscInitStruct.LSEState = RCC_LSE_ON


If there is no response from the AT24C64 IC, you will see:

"AT24C64 is not responding." otherwise you should see:

"prefsRead". The software will ignore any uninitialized prefs.


If there is no response from the TLV320AIC3204 IC you will see:

TLV is not responding


The processor frequency will be displayed as:

MCU Frequency = 96000000


The display will be initialized. Because the display is write-only, there is no software check to determine if it's working. If it's not working properly you'll get a white screen, and/or garbage, or nothing. When this happens, check the solder joints on the 40 pin connector and on the mcu.


A check is made to see if the RFM69 radio module was installed. You'll see:

Radio initialized or Radio not found.


Finally, because the power-on sound file hasn't been loaded so you'll see:

PWON not found.

You will correct this by adding the power-on sound file as tag 'PWON' via the Manage Files screen.


Scroll down to the bottom of AudioAlertSTM32::Update() routine in the file AudioAlertSTM32.cpp, to see the list of serial commands.

There are a few single character commands that should be executed on new boards to test basic functionality. All commands should be terminated with a linefeed character.


Commands:

"N" - Checks to see if the NOR Flash 25Q64 is responding.

"R" - Checks to see if the TLV320AIC3204 is responding to basic commands.


If no errors were reported when executing these commands, connect a headphone to the headphone jack. Test the TLV320AIC3204 further by playing a series of tones by entering:

"T S" - this plays the special information tone as you would get on your phone when a number is out of service. For this project, this tone is played before an alert sound file is played.


If you heard the tones played then format the file system by entering:

"F Y" - This command erases and initializes the Flash file system.


If successful you should see:

Format completed.


The touchscreen needs to be aligned before it is used. This can be done manually or you can try loading the settings file "AASettings.txt" from SD using the serial command "l".


To manually align the display, there are two buttons on the main board labeled Enter and Cancel. Pressing the Enter button or sending the command ‘e’ via the serial port, will display the alignment screen as shown below.


Aligning the display


Follow the displayed instructions. Keep selecting the white dot within the circle till the magenta dot covers or nearly covers the white dot.


Alignment Accuracy

Alignment Done


As noted in the instructions in the screenshot above, you keep selecting the white dot within the white circle as they appear in each corner after each click till the accuracy is acceptable. Acceptable is defined as the magenta dots completely or mostly covering the associated white dots. You then press the Enter button on the main board or send the letter ‘e’ via the serial port, the alignment parameters will be saved to the EEPROM. Pressing Cancel on the main board or sending the letter ‘c’ via the serial port, exits display alignment without saving the settings to EEPROM.


Test the touch screen. If it's not accurate enough, repeat the alignment. I find stopping after entering the top-right / bottom-left points works best.


If you've installed a CR2032 battery in the holder on the back of the board, you can set the time via the utilities screen.


Utilities Menu

Utilities - Set time


Select each field that needs to be adjusted. Adjust the date and time, then press the Set button.

Adjusting the pen force settings can also be performed by pressing Adjust. I've noticed that pressing with the same force in different locations on the display returns wildly different z values. This is my attempt to correct this. As noted earlier, this is a work in progress. Follow the instructions. The result is a 3x3 grid of 9 points. Using these points, bilinear interpolation is applied to each raw Z value to get a more consistent Z value regardless of where you press on the display.

General Operation

Main screen.png

From the main screen you can set the gain for input line 1, the DAC, and the headphones. The gain range for each is determined by the range specified for each in the TLV320AIC3204 documentation. As noted in the image above, the input line when set to pass through, has a gain range of -72dB to 0dB, meaning you can only attenuate the signal. The other two have the ability to amplify. By adjusting the gain settings you can balance the inputs to the headphone amplifier and use the headphone gain for the final volume.

Clicking anywhere within the slider will map the click to the gain at that point. Fine adjustment can be made by pressing the small speaker icon on either side of the slider.


The gain settings shown above were iteratively arrived at by recording the output using the GarageBand app on the Mac. The max amplitudes shown in GarageBand for test sound files (DAC) and the input line were balanced when the DAC gain was set to -8dB, with zero input line attenuation.



Manage Files Menu

Manage Files


The files are loaded and managed from the Manage Files screen.

To load a file, insert an SD card containing the files to be loaded. For each file, select the file in the top left menu. Use the up and down scroll buttons within the menu to navigate as needed.


Manage Select File

Manage File Selected


Once the file is selected, click in the text field to the left of the Add button.


Manage Selected Tag


Using the keyboard that appears, enter a unique one to four character tag for this file.


Manage Pre Add

Manage File Added


If successfully added, the tag will appear in the menu to the left of the Play button. Pressing the play button will play the sound file or prepend the alert tone depending on the state of the "Play as alert" checkbox.

The files are referenced by tag. The original filename is lost. Once added, the file is solely referenced by its tag.

Note that you can also add non-sound files. Other than for hidden files, no file extension filtering is done because I may add the ability to run scripts. Non sound files are currently ignored.

The Format button will remove all files stored on the board. This is the same format as described in the Setup step.

The rest of the Manage Files functions should be obvious and don't require an explanation.

As noted in the intro, the implementation example for this project is an updated Audio Alert. The Audio Alert receives a four byte tag when an external event occurs. The event arrives either via the optional radio or serially. If by radio, it's a Hope RF RFM69 module. This module supports the concept of a network ID, an address, followed by a message of up to about 60 bytes. For this project the network ID is 100, and the address is 1. To send an alert request to the Audio Alert you use the same network ID and a unique address. The message is four bytes and should be the same as one of the tags assigned to a loaded sound file. If the file exists, the input line 1 is muted, the alert tone is played, followed by the sound file. If the file doesn't exist, rather than playing the alert tone, the disconnected tone is played. This is the same tone you would hear if for some reason a phone call was disconnected because the signal was lost, etc..

The alert can also be triggered serially by sending either "P Axxxx" where xxxx is the sound file's tag. To simply play a sound file, send "P xxxx".

When the alert is played, the input line isn't fully muted, its gain is only reduced by half. This has the effect of mixing the alert with the input line in the background. If a full mute of the input line is desired, mHalfMuteIN1Action in the function AudioAlertSTM32::QueueSoundFile() should be changed to mMuteIN1Action.

The Audio Alert implementation only scratches the surface of what the TLV320AIC3204 audio codec is cabable of. Take a look at the project by Frank Rudley to see how the codec can be applied here.

Note that Frank used the TLV320AIC3254. My board can support either IC and anything that can run on the 3204 can run on the 3254. Although I haven't tried it, my board could also support the STM32F722RxT6 Frank uses by reassigning five pins in the Config.h file to align with the 722 pin assignments.


That's it. I hope you found this project interesting. Send me a message if you have any questions.