Sunday, March 11, 2012

Generating and outputting white, pink and red noise (or, all that effort just to generate signals you'd usually rather be without)

I've completed the design and verification of the noise generation software and hardware.  I have finalized the software for generating colored noise from white noise samples and I have mocked up the headphone amplifier circuit and verified that it works and performs as expected

CPU use by noise generation algorithms

One important last step in implementing the colored noise generators is determining how long they take to execute.  If it takes 300 cycles to generate a single sample of pink noise, and you've only got 200 cycles to do it per sample, you're going to fall behind.  Alternatively, the algorithm could take on average 100 cycles to complete, but 210 cycles in the worst case; what do you do to handle that worst case?  Additionally, how many extra cycles do you need per sample to do housekeeping tasks and run other subroutines?

In my situation, I need to generate a noise sample at regular intervals.  If the generator, on average, costs more cycles than you've got, you can increase your clock frequency, decrease your sample rat or try desperately to increase the efficiency of your code.  If the average execution time is good, but the worst-case takes too long, you can perform the above interventions or write some sort of wrapper function that keeps a sample or two generated ahead of time, to allow for the worst-case samples.

Looking at the actual execution statistics, however, leads me to believe that I have a more than acceptable margin even in the worst cases.  To get real, live cycle costs, I coded up a firmware that looks at a counter immediately before and after use of the algorithms, then transmits the difference over the serial port.  I then left the thing to run for about a second's worth of data (about 44100 samples for each of the three generators); the summary stats are:

  • White Noise: 10 cycles average, 10 cycles worst case, 10 cycles best case
  • Pink Noise: 90 cycles average, 99 cycles worst case, 88 cycles best case
  • Red Noise: 56 cycles average, 70 cycles worst case, 52 cycles best case

Since I'm running the CPU at 32MHz, and my sample rate is 44100Hz, that give me about 725 cycles per sample to get thing done; several times more than a comfortable margin even in the worst cases.  Since I am likely to only be generating the samples in a mode where other interactions/tasks are minimized (that is, not much else should be going on while the user has the device on), it may even be possible to reduce the CPU speed to improve battery life.

Verification of amplifier hardware design

I'm using Maxim's MAX9724B fixed-gain headphone amplifier IC.  I chose this part because:

  • It's monolithic: feedback resistors are internal and issues with stability and such have been taken care of by Maxim's engineers.
  • It contains a charge-pump voltage inverter to allow for bipolar output simply and easily from a positive rail; this allows for louder maximum output and removes the need for large output DC-blocking capacitors.  Additionally, if I end up needing a negative rail for other things, the device is designed to provide a little more current than it needs.
  • Click-and-pop suppression, RF noise rejection, very small package size.

Here's the chip, connected to the necessary capacitors and headphone jack.  I soldered onto that extra-tiny 12-pin TQFN by hand (this was a ridiculous experience).


I plugged everything in, and it worked.  The voltage on the charge pump output was -3.3V, and the headphone outputs sounded good.  I hooked up the scope to the outputs to see if the amplifier was rounding out the DAC switching transitions.  They were slightly rounded, but still very obvious.  However, as I just said, the outputs sounded okay, so I don't feel the need to alter the design to include lowpassing to get rid of the last of the switching transitions.

Next Steps

The only bits of hardware left to verify are the display and the REM detector; of course, these are likely going to be more difficult than the preceding hardware and software.  The display should be fairly straightforward in hardware, but coding the drivers will be more involved; It may be possible that someone has already implemented such software and I can crib off of that.

From the little bit I've already done prototyping the REM detector, it's likely to be somewhat temperamental.     The level of illumination provided by the IR LED has to be large enough to result in a big REM signal, but small enough that the zero-frequency current offset saturates the transimpedance amplifier.  It seems likely that the optimal illumination level will change between users and possibly even for single users between uses. As a result, I'll likely need to code in a feedback controller to optimize the illumination level for whatever the current operating conditions are.  I also need to nail down the properties of the REM differential current signal, to determine how often I need to sample the signal and whether it will be possible to gate the illumination signal in time with the sampling to minimize power usage.

(There is still the matter of the battery charge circuit; however, I trust the part data sheets and the IC has about a million pins, so manual soldering is going to suck if I try to mock it up.)

No comments:

Post a Comment