Contents
Overview 2
Method 2
Hardware 3
Software 3
EVMOMAPL137 Code Explanation in Words: 4
3D Display Cube Code Explanation in Words: 5
Images (full-size photos are attached): 5
Build Process: 6
Initial trials: 8
Code: 8
Conclusion: 8
Problem Statement
Currently, there are no commercially available 3D FFT displays in existence. Just about every home stereo system has a 2D frequency vs. amplitude display and every computer can produce one graphically. My project is to create a true 3D FFT display of audio frequencies on an 8X8X8 3D array of LEDs.
The general idea for my project is to display an eight point 8-bit resolution FFT on a vertical 8X8 plane of LEDs. Then this 8x8 plane of LEDs, which is part of a cube 8 LEDs deep, will be translated through the cube to produce a moving 3D FFT display. So, there are 83 = 512 LEDs. At some rate that is viewable to human eyes (discovered by trial and error), the single current 8x8 FFT plane regress back through the 8 planes till it is lost from the scope of the cube. This occurs continuously so that a volumetric real-time 8 frame FFT is created. The time between each frame is variable, but must be slow enough to perceive and yet fast enough to appear to change in real-time.
Method
In order to accomplish this goal, three things must occur. First the hardware of the display must support the task which is to allow communication with the EVMOMAPL137 development board to accept FFT data and be able to light up 512 LEDs correctly at a data rate that appears seamless to human vision. Second, the software on both the display and the EVMOMAPL137 must be compatible so that the FFT produced by the DSP can be meaningfully represented on the display. Lastly, a basic understanding of digital signal processing is necessary. More specifically, knowledge of how to use the results of the FFT is needed.
Hardware
The hardware chosen for the task of displaying the FFT is centered on ATMEL’s ATMEGA32 microprocessor. The ATMEGA32 is an 8 bit 16MHz microprocessor with 32 input/output (i/o) ports. Switching 512 LEDs would normally require 512 ports, however using multiplexing, the task can be accomplished with a lot fewer. By connecting the cathodes of each layer together, each layer can have ground applied individually. Combining that with having each column’s anodes tied together allows individual addressing of every LED individually with only 64 + 8 microprocessor ports (64 anodes + 8 cathodes). The appearance of several or even all of the LEDs being on is based on persistence of vision. With a very high refresh rate, the switching is invisible to human eyes.
Now, the method of converting 32 (i/o) ports into 64+8 = 72 is based on multiplexing. First, 3 ports are designated for addressing. Using a 74HC138 (3 to 8) de-multiplexer chip, those 3 pins are converted into 8 which address 8 separate 74HC574 8-bit latch ICs. These latch ICs all share the same 8 bit input data bus which is supplied by directly by 8 ports on the ATMEGA32. At any instant all the latches contain the same data on their inputs; however their outputs are controlled by an output enable pin which is fed by the 3 to 8 de-multiplexer. So, while their inputs all have the same data, their outputs will be different depending on which latch is enabled. The outputs of these latch ICs are tied directly to the anode columns of the array of LEDs. All 8 of the cathode layers are controlled by 8 (i/o) ports on the ATMEGA32. Each of these ports is buffered through standard PN2222A npn transistors due to port current limitations of the microprocessor. This method allows complete control of all 512 LEDs individually using only 8+8+3 (i/o) ports on the microprocessor along with 9 other ICs. So that leaves (i/o) ports for communication, programming and LEDs for debugging. Communication with the cube is accomplished over UART with the EVMOMAPL137 at 38400 baud. The refresh rate of the communication link is determined by setting a variable counter in code to allow sending every “x” number of buffers. Currently it is set to (1 /(0.0058 * 15)) seconds = 11.94/sec. The refresh rate of the cube array is 1309 FPS so, there is no chance that the switching will be visible to human eyes (or video for that matter).
Software
The software used is comprised of the EVMOMAPL137 and the ATMEGA32 programming. An FFT algorithm, the UART-transmit code, FFT data preparation, and a pass-through function all take place in the EVMOMAPL137 programming. The ATMEGA’s code consists of UART receive, array control software, and a stand-alone autonomous sequence of animations.
EVMOMAPL137 Code Explanation in Words:
The EVMOMAPL137 FFT code consists of a mixed radix implementation of the FFT provided by Texas Instruments that is optimized for use with the EVMOMAPL137. Although the FFT implementation is capable of performing mixed radix FFT calculations, this implementation makes use of radix 2. Because it is radix 2, a bit reversal table is required to recombine the individual 2 point DFTs from the lowest level of the FFT. FFT implementations make use of the fact that the sums of period waveforms that compose the signal are themselves periodic to one another. This allows an “N” point FFT to be decomposed into N/radix number of radix DFTs. The most common radix is 2. Performing an N point DFT would consume a large number of processor cycles; however a 2 point DFT is a trivial matter for a DSP to perform. Recombination of the individual DFTs is based on the twiddle factors which are constant coefficients of the FFT terms corresponding to vectors around the unit circle. For N=128 there are 128 twiddle factors and each factor is the same for each pass around the unit circle. For each pass by a particular angle the twiddle factor is the same and for those on opposing vectors it is of opposite polarity. This makes the FFT efficient since the number of twiddle factors is always N and they never change.
The UART code is an asynchronous serial communication method. This is built into the EVMOMAPL137. I only needed to add the header file, set the baud rate to 38400, and call the function when I wanted to send data.
The organization of the raw FFT data for display involved obtaining the N/2 amplitudes of the raw data which is linear in both frequency and amplitude to something that is intelligible to a person observing the 8 point 3D display. For frequency spacing, I first attempted a logarithmic approach to this, but found it difficult to implement and the results were less than optimal. One problem is that an N=128 point FFT has ((1/128) * 22050 Hz) as the smallest bin size. Logarithmic FFT requires each band to be 10 times larger than the previous band. With N=128 bands, a log implementation runs out after 3 bands. Next I tried an exponential spread, which worked. The only thing that was undesirable was the lack of response at the high frequency bands. It would seem that most of the energy content of the audio band of frequencies exists at the low end. To produce a display that has a better apparent response at the high frequencies, I placed more frequencies into the highest frequency band. In fact, in my current implementation, the highest band (far right) contains (96 * (22050/128)) Hz = 16.583 KHz. The next lower (2nd from right) contains only (16 * (22050/128)) Hz = 2.756 KHz. The next lower contains (8 * (22050/128)) Hz = 1.378 KHz. The next lower contains (4 * (22050/128)) Hz = 689 Hz. The next contains (2 * (22050/128)) Hz = 344 Hz. The last 3 each have (1 * (22050/128)) Hz = 172 Hz. This may not be a standard method of distributing the frequency band, but it does produce a better visual response. Also, it is technically accurate in that the frequencies are all represented and their relative positions are maintained. As long as the distribution is known, the result can be understood.
As for amplitude scaling, the method chosen maps the highest amplitude to the highest possible led on the cube which is position 8. The LEDs range in position from 0-9. Binning the amplitudes is accomplished by finding the max value of any band’s amplitude and assigning it the highest position. The lowest position is assigned the “0” position. Using this method, no information is lost and there is always information on the display. Unfortunately, this also means that when no music is playing there will always be an output because there is always noise present in any system. My implementation maps that noise from the highest to lowest position based on the difference between the loudest and quietest values (dynamic range) at any given moment. When music is playing, its magnitude is much greater in loudness than the noise and so no noise is displayed, but when there’s no audio playing noise is displayed at one particular band at all times. I assume this is noise from the computer, the cube display circuit, or the EVMOMAPL137.
Once frequency and amplitude scaling is done the data is sent as an 8 byte by 8 byte array that refreshes the entire cube each time it is sent. This means that 11 times each second the entire cube’s contents are refreshed via the UART communication link.
3D Display Cube Code Explanation in Words:
The display cube code consists of 2 parts: the autonomous code which runs pre-loaded animations and the UART mode code which sets the cube to listen for an 8 by 8 array. The UART baud rate is set to 38400 bps. Basically when it receives an 8 by 8 array of bytes the code sends that data to the array via the data bus, multiplexed output enable and ground layer control. The display circuit treats the entire cube as a 2D array rather than a 3D array. The reason for this is that only one bit is needed to turn on or off a single LED. So 8 by 8 bytes is 64 * 8 = 512 bits. This is exactly enough bits to address the entire cube. A 3D array would be a waste of 64*7= 448 bits (56 bytes). If the cube were capable of more than 2 distinct states, then a 3D array would be necessary.
Images (full-size photos are attached):
Build Process
Initial trials
Results
The final results are positive. The display performs the function required very nicely. Although the implementation of the scaling both in frequency and amplitude are perhaps non-standard, the result is a functional and aesthetically pleasing three dimensional FFT display.
Code
Due to the space the code would consume in this document, please refer to the SRC folder of the included code build directory.
Concluding Remarks
I will freely admit that my code is lacking some of the elements that were taught throughout the semester. For example, tone generation, filtering, and compression techniques. I had intended to produce something different than what had been produced before and during this semester, which is what led me to this hardware intensive project. Honestly, I considered implementing some band pass filters that would correspond to the bands of my FFT display, however the build process took so long that I found myself with less than a week to complete the code portion. That fact coupled with the fact that Final exams are just around the corner caused me to reconsider any further code modifications at this time. I want to stress that if time permitted, I would have liked to have made additions and improvements, but time is limited and must be allocated with discretion.
Overall, this project was a thoroughly enjoyable process with up and downs that I did not expect. It took more time than anticipated to build the hardware and there were multiple setbacks and hardware faults throughout the process. Coding proved to take less time than anticipated thanks to much help from Jacob, however issues with frequency and amplitude scaling still led to long hours in the lab. I must admit, I learned more during the project about the EVMOMAPL137 board and Code Composer Studio than during the rest of the semester combined. I actually began to assist other students in debugging and implementing their code. Learning about the topic of digital signal processing and especially the hardware side of the subject has been extremely interesting to the point that it has influenced my project choice for senior design.