A Self-Filling Audio Player (Radio on Demand without Internet)
This Project has morphed a little bit. It was initially meant as an "MP3 Player for a Person with reduced Eyesight". https://forums.parallax.com/discussion/175150/ideas-for-a-mp3-player-for-a-person-with-reduced-eyesight#latest The discussion over there opened my view that with large SD cards today MP3 is not really inevitable anymore. I then searched, how to obtain audio material. In this process it became obvious, that in my region there is a radio station SWR2 which broadcasts programs, which are probably of interest for the user person. So it would be nice to record certain broadcasts. Actually you can have podcasts of these, if you have internet access. Focal area of usage of this project is for speech, which must be clearly understandable, so hifi quality is not necessary here.
What does it do?
This is an Audioplayer, which fills itself (Audio files on SD-card) with radio broadcasts, which are sent regularly due to a fixed weekly timetable. There are 4 categories of broadcasts defined:
"Wissen", which is 30 Minutes of in depth information about a topic;
For each category there are 3 soundfiles with maximum of 2 hours length each available, which are overwritten in a rolling scheme. So you have available the last 3 broadcasts of each category.
For each category, there is a push button, which starts playing the last broadcast. If you press this button again, the next older one of this category is played.
There are also push buttons to stop audio and to start playing a fixed radio station directly.
There is an analog volume knob also.
A display is available, but it should be possible to use the machine without reading it.
So this is something like "Radio-on-Demand" without internet.
Audio has to be sampled with an accurate clock rate.
On the other hand, while SD cards are most often very fast, they can have "write latency". The internal controller then needs very much longer to write the data as on average. See here for some examples: https://jblopen.com/sd-card-benchmarks/
To achieve the completely accurate adc and dac clock rate, this project uses a dedicated core for adc and dac. When recording, this core/cog writes into a circular fifo buffer. A second cog tries to keep this buffer empty and writes to SD-card. For playback the chain is reversed. Now the SD-card cog tries to keep the buffer filled and the dac cog reads from it. While such things can be done with interrupts on other controllers, it is very much more easy to use dedicated cores. Additional cores are used for display, scheduler and button user interface.
During the project I learned, that the quality of the ADC of P2 is adequate for this project. On the contrary to 16bit CD quality, FM radio broadcasts dynamic range are compressed because of reduced Signal/Noise ratio. The datasheet of the FM receiver chip states S/N=57dB.
Frequency bandwidth of the radio chip is 100Hz…14kHz.
An enabler to use P2 for the project was the Kiss board. https://forums.parallax.com/discussion/172225/kiss-eval-board-general-discussion/p1 Many thanks here!
Why Forth (TAQOZ)?
An interactive language is very convenient during software development, as you can always try out small samples of code, whithout of the need for debugging code. Or perhaps sometimes with small debugging code. Forth is the simplest in a row of interactive languages Forth-Lua-MicroPython. Because it is simple, it is fast and it is compact. With Forth, there is no problem to have a lot of library routines, a compiler, an interpreter, an assembler, a video buffer and the application on board of P2's 512kB without external RAM. Taqoz Forth makes it even possible to have allmost full access to the interactive console in parallel to the running application.
Many thanks for Taqoz and many thanks for the Glossary, which makes it usable!!!
For convenience and better readability I like to use value type variables and local value type variables.
A 1.8' ST7735 TFT display is used. In Taqoz there is a bitmap VGA driver, which is modified to use 4 colors (2 bits). It is possible to switch the print channel from serial to the vga and back. There is a character set implemented. So here we use these nice features of Taqoz. The new ST7735 driver implemented here consists only of:
- A private SPI bus with separate pins, with it's assembler routines. Their bit bang code is largely copied from routines in Taqoz.
- Some Init routine.
- A routine to enlarge the size of graphics/text for better readability. Each original pixel in the left lower corner of the vga screen is copied into 4 pixels. This is done in place in the video buffer. After the process, the lower left quarter is enlarged to fill the whole screen.
- A routine, to convert the 2-bit VGA color code to 16-bit color code of the display and to send it to the display for each pixel.
Radio and Real-Time-Clock:
As a FM-radio chip RDA5807M is used. https://datasheet.lcsc.com/szlcsc/RDA5807M_C82537.pdf
These can be bought on very tiny breakout boards.
This chip has also RDS, which can provide day of week and time including summertime. It was one of the most time consuming parts of this project to get this working. A helpful site is:
Also very helpful (German): https://mikrocontroller.net/topic/313562
Received RDS data is often incorrect. To get the RDS time, the radio is switched to the strongest station and the RDS feature is switched on. It is a common method to wait for two consecutive equal results. This method can take it's time and I modified it here: Data is fed into a 3 stage fifo buffer and taken for valid, if the new result is equal to any of the previous results in the buffer.
Update: With a shorter antenna and lower signal strength, I had a lot of bad data. Now the procedure is more critical. It stores the two most frequent results and takes the top result, if it reaches a certain probability. The station sends 3 datasets just after a new minute. 5 of these 4 have to have the same time.
With this method time reception takes 1…3 minutes at my place. Every night at 3.30AM the P2 clock is set from the RDS. Taqoz provides routines to use the main counter of P2 for a real time clock.
For better audio quality, the RDS feature of the chip is switched off.
Update 2: As the reception of RDS time was not sufficiently reliable at the place of the user person, I now use a DS3231 RTC with battery backup. Every night at 3:30 a reboot will occur with for 10 minutes an attempt to update the RTC if plausible. For plausibility the date has to be completely accurate and the minutes within 2 and the hours within 2 (summer/winter).
A PAM8403 module is used as audio amplifier.
ADC and DAC
For ADC smart pin adc Sync2 mode, with gain 10, 8192clocks for 14bits resolution (S/N ratio is less!) with 24.4kHz sample frequency is used. So audio frequency bandwidth is <12.2kHz.
For DAC smart pin 16bit Dither mode is used. The adc gives the pace. A dedicated cog #6 is used for solid sample rate. Originally I planned to have a direct analog connection between the radio chip and the amplifier for maximum sound quality. Some sort of relay switch would be needed. At the moment there is no such line and even direct radio takes the route over the adc and dac.
Circular Audio data buffer and SD access
A 64kB buffer is used by a dedicated cog which uses Taqoz routines to read or write to SD. Taqoz makes it extremely simple to write to SD-card. Just open a file. To write a long into a RAM location, Forth uses the syntax:
DATA ADDRESS ! For example: 10 20 !
To write to SD, we can instead use:
DATA ADDRESS SD! For example 10 20 SD!
The address is relative to the beginning of the file. A 4kB Buffer is used to read or write chunks of data from/to SD. Taqoz takes care to always have the right buffer in RAM.
Dedicated cog #5 is used to handle SD- access.
Taqoz seems to have some limitations for the SD. I had some difficulties to use some 32GB cards. And I was not able to have more than 3*4 audio files on a 16GB card, which should have plenty of additional space.
There is a Forth word (Program) createAllAudioFiles to be used with the console to prepare the empty sound files, which use their own format.
Information to the Screen, Buttons, autoLevel, watchdog and Scheduler
Using the feature of polled multitasking these tasks are done in background by cog0, which also serves the interactive serial console. These tasks are state machine words, which are called each after another, when the console is waiting for key input. This method is suitable for less timecritical tasks and has the advantage of being cooperative. So only one of these tasks is active at one time and can use a ressource. Cycle time of these polls is normally 6…66 ms. Only RDS time decoding blocks any other activities.
AutoLevel is a slow compressor, which reduces audio output of the radio chip, if there is overflow. After some time, when only low level was detected, the volume is increased.
There is a regular timer interrupt implemented in Cog0, which is counted. If the counter is not reset, the timer-interrupt routine will cause a reboot. The regular reset is done by a polled task. So this can check, if the Taqoz polled tasks are still working. The scheduler also does reboot every night at 3:30am, which causes the system to get the accurate RDS time.
Writing to the display is split into 2 tasks. The fist step writes text to the vga buffer and is done by a polled task. Then cog #4 takes over, enlarges the picture then converts and sends it to the display. As enlarging and sending data takes some time, splitting helps to keep low the cycling time of the polled tasks. Handshake is done with a global variable.
For simplicity of handling for the user, settings like the broadcast frequencies/stations or the timetable must be edited in the source code and cannot be altered without PC.
As all tasks of the device are done either as separate cog tasks or as background polled tasks, the Forth serial console ist still fully available. This can be used to inspect global variables and so forth. As Taqoz only allows one open file, here is necessary some caution.
One poem a day
There is now the feature added, that if you long-press the blue (green) button, then you will hear one preselected-per-day poem (ballade), stored as WAV files on the SD card.
Source is included as is. It could be more tidy, I think.... If there are questions, just ask.
Comments, suggestions? - Does somebody know some DAB+ module for an attractive price?
I always receive much help and interesting inspiration from so many people here, many thanks!