Jump to content

Educational BoosterPack 8 bit FFT Spectrum Analyzer Attempt

Recommended Posts

So what have you been doing with your Educational BoosterPack lately  :smile:



  • This is based on the fix_fft code that's been floating around for many years.
  • I tried both 16 bit and 8 bit, currently fixed to 8 bit as I see no difference for my needs (i.e. limited precision, range), I would invest in a good pre-amp for better results.


Things to do

  • More precision timing to achieve the frequency band I want.
  • Better front-end, currently using 1/2 LM258.
  • Adopt non-linear horizontal scale, currently linear scale at about 800Hz...1.6Khz, 2.4KHz, 3.2Khz....
  • Adopt logarithm amplitude to make the bars make sense to your eyes.
  • Add / enhance effects like attack / retreat rate.
  • Add dynamic sampling / scaling to input signals.
Link to post
Share on other sites

That is awesome! Nice work! I sent a link to the CircuitCo folks who made that BoosterPack. I think they'll like it!




I am going to post it on TI forum when finished. My friends here are more tolerating on my incomplete work.


Will have more details and code when things progresses.


Right now it can do 16 bands w/ 32 samples or 32 bands w/ 64 samples, I display only 16 as display is confined by the LCD. It measures up to 16Khz in either case.


At 32 bands, It's 500Hz between amplitudes and I can pick 500Hz, 1Khz, 1.5Khz on low end, with 12Khz, 14Khz, 16Khz on the high end. But still I want to find a way to do have 60Hz, 120Hz, 200Hz etc at the low end of the spectrum. Will try to do two pass w/ different sampling rate and see if it could work.


Also thanks Rei Vilo for the excellent review on the BoosterPack, I relied on the information / links when building this.

Link to post
Share on other sites

You're welcome!


This is really an impressive project. Do you plan to use the Educational BoosterPack built-in microphone?


Thanks for your comment.


I did not start out w/ the microphone, but I just did when I tried to explore / maximize what to do w/ the booster. Will upload a video in a day or two.


As a bonus, I also utilize the booster potentiometer to bias / offset my op-amp input.


Now the front-end use a single 358 and do two stages before going back to ADC4. And I use the potentiometer to bias the input voltage. I worked out very nicely to my liking.


You will noticed in the original video, the high-bands are all off, that's caused by doing very high gain and only one stage, plus the 358 is not good at high frequencies.


I did change my sampling to have it limited to 8Khz (on 32 bands, which I hand-pick 16 to display on LCD). The reason is I don't have good op-amps handy for the gain bandwidth. A LM324 would do a little bit better but you really need to order audio grade to handle the job. As just an experiment, I am not going to invest.


I am happy enough to post the code, also in a day or so.


//   LM358 Dual Op-Amp, GBW @0.7Mhz, each stage @x100 gain, bandwidth is 7Khz
//                     +------------------------------+
//                    _|_                             |
//                    ___                             |
//                   + |   ---------------            |
//                     +-1|----.       Vcc|8          |
//                     |. |    ^      .---|7--+-------|-----o (A)
//                100k| | |   / \     ^   |   |.      |.
//                    |_| |  /__+\   / \  |  | |100k | |1k
//       0.1u          |  |   | |   /__+\ |  |_|     |_|
// ( o--||--[ 1k  ]--+-2|---+ |    | |  |   |       |
// (C) o-------------+---3|-----+    +-|--|6--+-------+
//                   |   4|Gnd         +--|5----+
//                   |     ---------------      |
//                   |                          |
//                   +--------------------------+
//  (A) to P1.4 EduBoost Mic jumper middle pin
//  ( to Condenser Mic, EduBoost Mic Jumper top pin 
//  (C) to Potentiometer, EduBooster Potentiometer Jumper top pin
//  (*) connect Gnd + Vcc to Launchpad


/EDIT fixed smileys in code.




Link to post
Share on other sites



  • 8 bit integer FFT
  • 32 samples at 500Hz separation
  • shows 16 amplitudes of 250Hz, 500Hz, 750Hz,....... 5.75Khz, 6.75Khz, 7.75Khz non-linear
  • partial logarithm map to show amplitudes, limited as resolution has been reduced for 8 bit FFT
  • LM358 two stage mic pre-amp at 100x 100x gain (can be improve vastly w/ better op-amps)
  • utilize Educational BoosterPack; mic for input, potentiometer for pre-amp biasing
  • draws power from launchpad
  • square signal generator from TA0.1 toggling, good for initial testing






A longer video showing off the action. Although it may not show well on youtube, but I am surprise w/ the result (consider being a "toy"). The system is very responsive via the microphone and there are no annoying noise levels (I think it's w/ the pre-amp biasing and the reduced resolution.


I had built similar one w/ AVR before and I found that it's a lot easier to work w/ on msp430. The timer architecture and being 16 bit is an advantage here.




code to follow..

Link to post
Share on other sites

I had created the github project lp_8bitfft.






I wish you a good show and an enjoyable one.

I can build on gcc and ccs but did not try to run the ccs firmware.

I spent more time on the op-amp front-end. There are other general op-amps that can do the job but I want 3V power source, so I had to settle for the LM358.

I hope I had comment enough so others can make adjustments easily, and let me know if I miss something.

I am not a mathematician and really don't understand FFT, I just use the "black box".

Link to post
Share on other sites



Thanks for your comment. It would look great on one of your proto plates. You may want to put one together, it only requires a few common components.




I just added buzzer support (don't understand why I had missed that). Now the P1.3 button will cycle thru (1) no output, (2) P1.6 green LED output, (3) P2.6 buzzer output. The buzzer output you will see the bars not showing up at what it should be. I would suspect it being the frequency response / limit of both the buzzer and the condenser microphone.


You may want to do another pull if you are building. Also we need the -lm flag to link the math library.


Code is not optimized. They are places that could use some in-line assembler to speed things up if anyone is interested.

Link to post
Share on other sites
  • 4 weeks later...
  • 2 years later...



Having a nice matrix led display laying around with no use of I assembled a test circuit with launchpad and modified the code of @simpleavr to run on it.


The display is driven by four MAX7219 chips chained on SPI bus.

I noticed that the only floating point operation that your code was using is a square root operation in line 257. Once I added a fixed-point square root routine, linking with math lib is not necessary anymore - spared a lot of flash space. The fixed-point routine is also 3 times faster than mathlib floating point one: 50us vs 150us

// sqrt: 150us
#include <math.h>
// 50us
unsigned char sqrt16(unsigned short a) {
        unsigned short rem = 0, root = 0;
        int i;
        for(i = 0; i < 8; ++i) {
                root <<= 1;
                rem = ((rem << 2) + (a >> 14));
                a <<= 2;

                if(root <= rem) {
                        rem -= root;
                } else {
        return (unsigned char)(root >> 1);

Further I've added Hamm windowing to minimize spectral leakage:

// scilab 255 * window('kr',64,6)
//const unsigned short hamming[32] = { 4, 6, 9, 13, 17, 23, 29, 35, 43, 51, 60, 70, 80, 91, 102, 114, 126, 138, 151, 163, 175, 187, 198, 208, 218, 227, 234, 241, 247, 251, 253, 255 };
// scilab 255 * window('kr',64,4)
const unsigned short hamming[32] = { 23, 29, 35, 42, 50, 58, 66, 75, 84, 94, 104, 113, 124, 134, 144, 154, 164, 174, 183, 192, 201, 210, 217, 224, 231, 237, 242, 246, 250, 252, 254, 255 };
// scilab 255 * window('kr',64,2)
//const unsigned short hamming[32] = { 112, 119, 126, 133, 140, 147, 154, 161, 167, 174, 180, 186, 192, 198, 204, 209, 214, 219, 224, 228, 232, 236, 239, 242, 245, 247, 250, 251, 253, 254, 255, 255 };

Applying windowing on 32 samples uses fixed point math:

	for (i=0;i<Nx;i++) {
		int hamm = hamming[i<(FFT_SIZE-1)?i:(Nx-1)-i] * data[i];
		data[i] = (hamm >> 8);

Finally the display buffer is filled in with output of FFT function:

        unsigned long mask = 1UL;
        for (i=0; i<32; ++i, mask <<= 1) {
            for(j=0;j<8;++j) {
                    dbuff.ulongs[j] |= mask;
                    dbuff.ulongs[j] &= ~(mask);

where dbuff is display buffer organized as:

typedef union
	unsigned long longs;
	unsigned int ints[2];
	unsigned char chars[4];
} longbytes;

union {
	unsigned char bytes[8*4];
	longbytes lbytes[8];
	unsigned long ulongs[8];
} dbuff;

which make it easy to manipulate:

unsigned char spibuff[8];

void SPI_Write(unsigned char* array) {
	P2OUT &= ~LED_CS;
	unsigned int h = 8;
	while(h) {
		UCB0TXBUF = *array;
		while (UCB0STAT & UCBUSY);
		++array; --h;

void update_display() {
	unsigned char i;
	for(i = 0; i < 8; ++i) {
		spibuff[0] = spibuff[2] = spibuff[4] = spibuff[6] = i+1;
		spibuff[1] = dbuff.lbytes[i].chars[3];
		spibuff[3] = dbuff.lbytes[i].chars[2];
		spibuff[5] = dbuff.lbytes[i].chars[1];
		spibuff[7] = dbuff.lbytes[i].chars[0];

BTW I got a second 8x32 led matrix displays from the same ebay offer, and it turned out to be mirrored - LED matrix is turned around 180deg, so the update_display() routine for the other one have to push bytes in order 0 through 3, and bit-shift operations ( << and >> ) yield opposite display reaction (left vs right scroll).






Edit: correct photo attachement and source code snippets


Edited by sq7bti
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...