Hi There, how are you all?
I've seen around here many people having trouble to control Sigma DSPs in real time. So I decided to write a little "walkthrough" guide. Let's get started:
Now that you SOMEHOW came up with your IIR filter coefficients, you surely would like to load them into the DSP, right? GOOD!
If you don’t know how to come up with the coefficients, you can do it by hitting the books and doing the math, using Matlab’s FDATOOL, using GNU Octave or being struck by lightning. If you know any other method, please let me know!
Three steps are necessary:
1 – Conversion from Floating point to 5.23 Fixed point
2 – Breaking of 32-bit values into 4x 8-bit values that can be sent via I2C / SPI
3 – Safeload the content, so it can be dynamically updated in real time.
You must convert the floating point numbers, like 1.2934645 to FIXED point, simply because SigmaDSPs are fixed-point.
That’s EASY! All you have to do is multiply it by 0x00800000 (hexadecimal) or 8388608 (decimal). Yep, they’re the same.
So, let’s say you just did 1.2934645 * 8388608 = 10,850,366.
Floating point: 1.2934645
5.23 Fixed point: 10,850,366.
Happy!? Well, I’m not, I wish these were dollars in my bank account.
Now you see, this is a BIG number. Big numbers need big variables to hold them, and you’re likely to be using a 32-bit long one to hold it. So, we must break this 32-bit big fat variable in four skinny 8-bit variables. That is necessary because the I2C / SPI buses are 8-bit wide.
What would you like best to carry around in your car? A BIG FAT 450 pound girl or FOUR 112.5 smoking hot girls? That’s why the buses are 8-bit long.
10,850,366 (decimal) = 0x00A5903E (hexadecimal). This is out FAT girl that cannot be carried around.
What we need:
0x00, 0xA5, 0x90, 0x3E – FOUR skinny hot girls that you happily fit in your car!
Several methods exists to break 32-bit variable into 4x 8-bit variables. There’s one bellow (works only in BYTE ADDRESSABLE systems), yeah, the code looks dumb for the sake of simplicity, so it has no loops to automate the process:
#include //Everything you need. For the program! Not talking about cars, girls, boats…
float Value32=1.254789; //Random float value
unsigned char *pValue32; //Pointer to that value
unsigned char Value8_pt1=0; // 4 x Chars to "carry" the broken Float value
unsigned char Value8_pt2=0;
unsigned char Value8_pt3=0;
unsigned char Value8_pt4=0;
void main (void)
//Lets break the initial float value in 4x 8-bit parts:
pValue32 = (unsigned char *) &Value32; //Receives the address of the initial Float variable
Value8_pt1 = *pValue32; //Receives bits 0 to 7
pValue32++; //Increment pointer
Value8_pt2 = *pValue32;//Receives bits 8 to 15
pValue32++; //Increment pointer
Value8_pt3 = *pValue32;//Receives bits 16 to 23
pValue32++; //Increment pointer
Value8_pt4 = *pValue32;//Receives bits 24 to 31
Impressive? Nah... Turning one big fat girl into four hot skinny girls THAT would be impressive!
Now that we’ve got our skinny girls, we must travel around and reach our destination! In order to load this data into SigmaDSP in real time without causing clicks, noises and unstable behavior, we must use the SAFELOAD method.
For ADAU1442/5/6, Software Safeload method must be used. You can find it, kindly posted by our friend Brett, here:
If you’re using older ones, like ADAU1701 for example, you must utilize the Hardware Safeload method that I’ll describe now:
The Safeload can load up to FIVE sections at once. Why? Because an IIR filter, the so called biquad, needs five coefficients: B0, B1, B2, A1, A2. 5 sections = 5 x 4 bytes. So up to 20-bytes can be safeloaded in a single shot.
For each section there is a Safeload ADDRESS register and a Safeload DATA register that are directly related to each other. Let’s call them “The parents”. They can only work together.
When you want to load a coefficient, you want that to reach a certain memory space in the parameter ram memory of the DSP.
If you perform a write directly to that desired memory space, unwanted effects will happen, such as clicks and pop noises. Think of it as marrying a girl without asking “the parents”… Prepare your EARS!!!
So it’s polite that you ask “the parents” prior to that. Then it should be much smoother!
After “The parents” let you marry their daughter, you need “The padre” to seal the deal.
“The padre” is the DSP Core Control Register. It has a bit that you must “flip” in order to trig the safeload transfer. So the whole deal is:
1- Write the Safeload ADDR register with the desired position (address) of the Parameter RAM that you want to load the data.
2- Write the Safeload DATA register with the data that you want to load into the Parameter RAM memory space
3- Trigger the Safeload transfer by flipping the Bit 5 of the Core Control Register. ONLY AFTER YOU’RE DONE LOADING ALL SECTIONS.
Let me make a note here because it sounds confusing:
You write the Safeload ADDRESS register with THE ADDRESS OF the Parameter RAM memory. Attention, this writing contains TWO addresses: The "safeload address register" address and the "parameter memory region" address.
You write the Safeload DATA register with THE DATA you would like to load TO the Parameter RAM memory. So THIS write contains the "safeload data register" address and the DATA itself, that can't be more than 4 bytes long. Actually it is 28-bit long, but that doesn't really matter... By the way, attention to the "Dummy" byte 3, it MUST be there ok?
As I said before, we have 5 safeload sections, each section can safeload 4-bytes that corresponds to ONE coefficient, so, FOR EACH coefficient of a biquad, you must perform the procedure above. As the very last part, trigger the Safeload action by flipping the DSP Core Control Register bit. Here it is:
You can write the whole register, which is 16-bit long, no problem. The DSP will continue the operation normally during the write and it will not reset or cause any noises. After you're finished writing this register, you should immediately see the effect of your new coefficients loaded into the DSP!
That's all folks! I sincerely hope it's not much overwhelming and that it is clear enough. Please point out any mistakes (even grammar mistakes) because I did not revised this yet so I'm pretty sure it's far from perfect. Another thing is, if it lacks in clarity please show me where and why so I can fix it.