
I was once very impressed with
this post about creating a light-music device on a microcontroller as a gift for my beloved. And once it was my time to make such a gift. Considering the differences from the author of the aforementioned project in skills and tools; Being very limited in preparation time (3-4 days), I went the other way and developed my music device for installation in a casket bought in a souvenir shop. It has a simpler design and ease of manufacture. The article describes the details of my project and their motivation. Carefully, photos (about 1Mb in total).
Scheme

As you can see, there are very few details. Power supply in the range of +3 .. + 4.8V from three AAA batteries is suitable without the use of stabilizers for both the D1 microcontroller (PIC16F753) and the DA1 amplifier (TDA7052A). This amplifier chip is unique in its kind, because among its counterparts, it requires a minimum number of external elements. The use of a power amplifier is necessary: ​​when you try to connect the output of the microcontroller directly to the speaker, you will not be able to get sufficient volume.
For the operation of the amplifier, a capacitor C1 with a capacity of 220 ÎĽF is required. Without a capacitor it is impossible: if the internal resistance of the power supply is not sufficiently small, then it will sound quiet and with strong distortions. A capacitor C4 is also required for decoupling the DC audio signal. Trimming Resistor R2 adjusts the volume. R1 limits the range of adjustment. Together with the capacitor C3, it also forms a low pass filter. In principle, you can not put C3. At first I wanted to do this, but then it seemed to me that in order to reduce the distortion of sound, it would be better to remove the ultrasonic frequencies from it, putting C3.
')
The TDA7052A (unlike the TDA7052) has a separate volume control input by applying the appropriate voltage to it (not shown in the diagram). But an attempt to use it in no way simplifies the scheme and does not improve its work. Fortunately, by leaving this input unconnected, the normal operation of the amplifier is not disturbed.
A few words about the choice of the microcontroller. The main criterion is the supply voltage range. When the battery is almost discharged, the voltage on it sags to 3V (1V per cell). In the fresh state, the voltage can rise to + 4.8V and even more. Unfortunately, more modern 16-bit microcontrollers, which have high speed and a lot of memory, usually require power in the range of +2.7 .. + 3.6V. To lower the voltage, one would have to apply a stabilizer, and not just any, but with a low voltage drop (Low Drop-out), given the voltage on the battery at the end of its service. I decided not to complicate things. From Microchip controllers (I have the most experience with them and I have a programmer), therefore, only 8-bit ones are suitable. It would also be possible to use 16-bit from the PIC24F series. In the next music box, I probably will. Still, the PIC16F753 is very cramped in both speed and memory. But he has a built-in 9-bit DAC, which is very suitable for sound synthesis.
For simplicity and reliability, I also decided not to use any power and power management schemes. A simple switch (not shown) breaks the battery circuit, and that’s it.
Assembly
We buy the appropriate size and type of casket. I found this one. Unfortunately, the rectangular box was not found, it would be easier to work with it.

I did not make a circuit board. There are no conditions for this at home, but it is too long and expensive to order at the factory. Therefore, I collected the circuit on the breadboard. It was possible to cut a piece of board according to the size of the box with a jigsaw. The dimensions and shape predetermined the layout of the parts. Here is a photo at the intermediate stages of assembly:

Wires at the time of writing and debugging the firmware connected programmer. I put the chips on the sockets, and for good reason: of the two amplifier circuits bought on the radio base, one turned out to be a bat. It was possible to avoid her soldering.

View from the back of the board. As you can see, long or intersecting connections are made with MGTF wire, and short - with cut off legs from capacitors and resistors. After checking the performance of the circuit on the test firmware, you can begin to develop and debug the main program. More about her below.
After the firmware is fully debugged, turn off the programmer, rewire the speaker and set the switch. Last check.

After that, you need to mount everything in the box and close the top with a cardboard box for aesthetics. From a black cardboard in the form of a box we cut and bend such a construction.

Cut a hole for the switch with a knife. An awl pierced the holes above the speaker. Next, glue the switch to the cardboard and the speaker on a regular place of the board:

The final look of the open box:

Program for PIC and music preparation
1. Sound synthesis
Having a 9-bit DAC, in principle, you can get a rather complex audio signal, but in the case of the PIC16F753 the possibilities are limited due to the small size of the program memory of the microcontroller - only 2048 words. As experience shows, even a simple player program, written in assembly language and optimized for code size, takes about 1000 words, so there is very little for notes. And absolutely nothing is left to store samples when using such a method of sound synthesis as
Wavetable . The use of such powerful methods as
FM synthesis is hampered by insufficient processor speed and the absence of a hardware multiplier in it. Therefore, there remains only the synthesis of rectangles - symmetric, or with variable porosity. The second option gives some variety of timbres - see, for example, the collection
“This is Tritone 2” (also available on
Youtube ). This method I implemented in the box. It was possible to realize a polyphonic sound: 4 independent audio channels. You can control the volume of each channel.
We find the frequency corresponding to the desired note, according to the formula of
uniform temperament : f = 440 * 2 ^ (n / 12), where n is the number of the note in semitones, n = 0 corresponds to "A" of the first octave. Since we have 4 channels, we need to simultaneously generate 4 signals and sum them up before output. The most common solution is to use a common sampling rate for all channels. At the same time, the processor calculates an output count for each channel at regular intervals. The values ​​obtained are summarized and fed to the DAC.
The desired periods of rectangular signals, in general, are not multiples of the sampling period. Say, for the “la” note of the second octave, we have n = 12, f = 880 Hz. With a sampling frequency of Fs = 27777.8 Hz, each signal period should last ~ 31.57 output samples, which is unrealizable. There are three ways out:
- Round up the period to a whole number of samples. In this case, the resulting period will differ from the specified one, i.e. music will be fake.
- Vary the period duration within plus or minus one sample so that the average period of the received signal is 1 / f. From the point of view of signal processing theory, this is equivalent to the nearest neighbor interpolation. As a result, there are significant non-harmonic distortions in the sound, peaks at extraneous frequencies appear in the spectrum. At the hearing, the signal simply becomes "dirty."
- Interpolate according to Shannon. This approach eliminates falsity and gives the best sound quality, but in 8-bit microcontrollers is unacceptable because of the complexity of the calculations.
So in practice, you can choose between options 1) and 2). Both of them are used in software synthesis of multi-channel music on a 1-bit audio output in computers such as the ZX Spectrum. I personally prefer option 1). With a sufficiently high sampling rate, on not too high notes, the frequency rounding off is insignificant, and the false is almost imperceptible.
The sampling frequency must be longitudinal to the processor clock frequency and low enough so that the processor has time to carry out all the necessary calculations for each output sample. On the other hand, it should be as high as possible in order to reduce falsehood and expand the range of reproducible notes. For the work of the player program, a table with the periods of each note is necessary. To calculate this table and calculate the deviation of the received signal frequencies from the desired ones, it was written
program at Matlabfs = 2e6/72; notes = -24:26; f = zeros(size(notes)); d = zeros(size(notes)); fa = zeros(size(notes)); ndifs = zeros(size(notes)); for i=1:length(notes) f(i) = 440*2^(notes(i)/12); k = round(fs/f(i)); fa(i) = fs/k; na = 12*log2(fa(i)/440); ndifs(i) = na-notes(i); d(i) = k; fprintf('%10.1f %10.1f %3d %4.2f\n',f(i),fa(i),notes(i),ndifs(i)); end plot(ndifs); ylim([-0.5 0.5]); fprintf('\n\n'); for i=1:length(notes) fprintf('\tretlw\tH''%02X''\n',d(i)); end
For each note, the program calculates the period of the signal in samples at the selected sampling rate, rounds it to a whole and performs a downward recalculation into the note number. In these logarithmic units, the deviation is estimated, the graph of which is displayed on the screen:

You can experiment by changing the sampling rate, that is, the number of processor cycles per one period. Empirically, I picked up a coefficient of 72, which gives the minimum achievable note deviations in a given range.
2. Firmware architecture
PIC16F753 has three timers, but only timer 2 can be programmed to generate interrupts with a specified period. With its help, we get interrupts at the audio sample rate, i.e. every 72 processor cycles. The interrupt routine calculates the next value to output to the DAC. To avoid sound distortion, it is necessary to update the level on the DAC at strictly equal intervals. Since the calculations may take different times depending on the state of the program, there are two options. The first is to “trim” all the branches of the calculations so that they are executed in the same number of cycles. The second is to immediately output the value calculated during the processing of the previous interruption to the DAC, and then calculate the value for the output in the next interruption. I chose the second path. At the same time, the interrupt handling procedure is performed every time at different times, but on the other hand, between interrupts there remains on average more processor time for background calculations.
By interrupts, the generation of stationary signals — rectangles of constant frequency, duty cycle, and amplitude — works. These parameters are stored in the corresponding memory cells. When running the firmware, interrupts are never prohibited. This ensures that there are no inhomogeneities and discontinuities in the sound, except for the moments of switching the generation parameters. It turns out the same mode of operation as if the system had a sound chip, like Atari Pokey or AY-3-8910: these chips also form stationary signals on each channel until the processor changes the values ​​of the parameters in the internal registers of these chips.
The generation parameters are updated by procedures running in the background (i.e., between interrupts). Here I activated timer-1 to ensure the frequency of calling the procedure for updating parameters - 50 Hz. The same or close frequency is used for these purposes in music players on 8-bit computers.
The rest of the firmware architecture is determined by the representation of music in memory. I went on the principle of
tracker music , which basically created music on 8-bit computers. I will not go into details here, there is a lot of material on this topic on the Internet.
3. Preparing music
Chip music needs something to edit, and today one of the easiest ways is to use
Open Modplug Tracker . It is necessary to prepare several samples that sound at least approximately similar to the sound of the chip, and create music in the tracker using them, using no more than 4 channels. In this case, you also can not use the special effects of the tracker, except those that are implemented in our chip player. As a result, a tracker file is created in
.it format. I also wrote a converter program that converts notes from an it file into a format recognized by my PIC16F753 firmware. The converter swears if it encounters notes in the it-file outside the range or unsupported commands by the firmware. Tools from the it-file are completely ignored by the converter. They are only needed to control the sound of the music during editing.
Samples of rectangles of various porosity, which are needed while editing music, I generated with special programs on Matlab. But this was done a long time ago as part of another project - the
conversion of music from the ZX Spectrum , so now I just took the tools from those old modules and made music for the box on their base.
As a result of the converter operation, a text file is created in the PIC assembler format. Its contents need to be copied to the end of the firmware source and compiled. The result will be the firmware in the form of a hex-file with the desired music.
Unfortunately, I do not have the talent of a composer or an arranger, so I managed only to get a piece of a famous thing by V. Mozart. At the same time, part of the player’s capabilities has remained unused. It would be easy to add sound effects and much more to the player, but again, where can we get someone who can make a beautiful sound on them?
If readers are willing and able to create beautiful chip music for caskets and similar musical handicrafts on microcontrollers, I will be glad to cooperate.
Sources
The full source code of the firmware, the music converter software, as well as the it-file with the music I used in this box, can be downloaded from
Github .