[BUG] Issue in the calculation of the phase parameters for triangular wave phase
Hello,
Just a bug report. I believe there is a bug in the implementation of the phase offset parameter calculation for the Triangular wave generator. From my understanding the phase parameter is encoded over two words, the first one is 0-256 and represents the 8 higher bits. The second is in the 5.23 float format and represent the fractional part. I think the person who wrote the graphical element used round instead of truncation for the first word as one gets the following mapping:
0deg => 0, 0 // all good
180deg => 128, 0 // all good
2deg => 1, 0.42 // all good
1 deg => 1, 0.71 // Bad as it's higher than for 2 deg! it should be 0, 0.71 instead
In the end I generate those parameters from I2C so I don't care that the UI is broken but I just found this while checking what my microcontroller is writing vs what SigmaStudio generates
Edit Notes
Missing word
[edited by: GLeclerc at 9:08 PM (GMT -4) on 18 Apr 2024]
Audio Signal Processors
bug_report
software
sigma studio 4.7
SigmaDSP Audio Processors
adau1701
Show More
Hello GLeclerc,
Thanks for reporting this and also for forcing me to become more familiar with this block. It is one I have not used often.
I did some investigations of my own. You said you are using SigmaStudio4.7 and an ADAU1701. The library for the ADAU1701 and the ADAU1761 has a triangle wave generator but that version is much simpler and does not have a phase control. Therefore you must be using a Sigma300/350 but then you referred to the format as 5.23 which is the format for the ADAU1701 and the ADAU1761. So I am a bit confused?
So I will go with the assumption that you have to be using an ADAU1452 or similar processor that has an 8.24 format.
Sorry that this is going to be a bit of a book. I need to make a video of this while it is fresh in my mind!
I just studied the parameters that the block is using by putting in different values and seeing the results in the Params window and also in the actual analog output of the codec.
I put together a program where I grew a triangle wave generator and routed one to the left and the other to the right channel to watch the phase relationship on an oscilloscope.
I do want to add to this discussion for others who read this that the phase setting is somewhat useless if you drag in two different blocks into the project. The blocks will be asynchronous. To actually get a phase delay from one to the other you have to use one block and grow it. Then they will be synchronous and you will see the delay. Also, when going out to a converter keep the frequency low because a triangle wave has lots of high harmonics that will alias unless you run it through a low pass filter before going out to the DAC.
Baseline: Here is a screenshot of my project:
Here is the parameter list with both set to 0 phase shift
These are basically counters that step through the wave and I am fairly certain it is using a linear interpolation between the points of the table to generate the waveform.
If you hit refresh you will see that they are constantly changing as the program counts every certain number of samples. That is how it changes the frequency. But this is not the topic of this discussion.
So when you change the phase of one of them, both of them are updated at the same time to keep the counters in the same phase relationship. So with your microcontroller you will have to do the same. Here is what was sent when I set one of them to zero and they are now both set to 0 degrees. You see there are four writes. Actually one burst write since the parameters are stored in consecutive memory locations.
There are two 32 bit values for the counter. A high and a low value that is concatenated to make one 64 bit value but for this variable only 43 bits are being used. Actually, only 42 bits so there may be a small bug here that does not affect the operation. However, I think this is intentional... let me explain.
For phase you can only go from 0 to 360 degrees. 360 degrees is really 0 degrees when you are talking about a repeating waveform. So this small "bug" is probably intentional because you can enter 360 degrees into the GUI and you get the same result as if you entered 0. The counter wraps in the same place.
In my investigation I entered 360 and saw the upper "hi" variable has a 1024 in it.
If I enter 180 degrees it has a 512. So clearly it counts from 0 to 1023 and then wraps around. The lower 32 bits are involved in this counting of course. I also noticed that there is a variable for a "mask" and that holds a 1023 which is interesting and I would not mess with that.
So there is a whole number portion which is eleven bits and that is the hi parameter. The whole number portion.
The lo parameter is the fractional portion.
This whole number portion will be divided into 360 degrees with a whole number and a fractional part.
To experiment with the math I entered 180 degrees which will evenly divide and there should not be a fractional part.
Low and behold, look at the results:
The high is 512 and the low is zero.
This means that the ten bit resolution was divided in half with no remainder to make a fractional part. the formula would be like this [(2"10) *2/]360 or it could be written as
2^10 / (360/2).
2^10=1024
likewise, if I put in 90 degrees I get 256 and no fractional part.
So now on to your examples.
By the way, to get the fractional part we need to take the entire number of 32 bit values and multiply that by the fractional part. So that would be 2^32 times the decimal fractional part.
So a setting of 1 degrees would be 1/360th of 1024.
1024/360 = 2.844444 repeating 4
So the whole number portion should be a "2"
The fractional portion is a 0.8444444
2^32 * 0.84444444= 3,626,861,081 and I will truncate the fractional part since it is a repeating number and I just used "6" fours. 0.8444444
Translated to hex I get 0xD8 2D 82 19
This should be the 32 bit fractional number in the parameters. Let's look at the results from SigmaStudio:
Pretty much right on!
The whole number portion is a 2
The fractional portion is 0xD8 2D 82 D8
When I went back in and used more than 12 digits for the multiplier I got exactly the same fractional number in hex.
So this verifies we are doing the math correctly.
Now on to the 2 degree setting you mentioned.
So 2/360th of 1024 = 5.6888888888888
The whole number portion should be a 5.
The fractional = 2^32 * 0.6888888888888 = 2,958,755,248
in Hex = 0xB0 5B 05 B0
This is what SigmaStudio produced:
Exactly the same result that I calculated!
So in short, I do not see the problem you are reporting.
Dave T
Sorry If I got you into this tangent but I didn't make a mistake I was indeed talking about ADAU1701, which has two blocks for triangular wave. I'm using the second one
Does your write up still apply here ? I assume it doesn't as it seems that we don't have have the same parameter names
Hello GLeclerc,
Now there is something that I will laugh about because it is not worth getting stressed and angry about! you have found a "bug" in the SigmStudio library that should not be there and made me look foolish! I never use the regular Toolbox, I prefer the Tree-Toolbox.
So after your post I went back into SigmaStudio. From the Tree Toolbox I dropped saw only one version. I dropped it into the schematic. Then I removed the algorithm and then added it back in half expecting to see two options but I only saw one!! So then I opened the regular toolbox and there it is!!
Here is a screenshot of both. Both of these toll boxes are supposed to have the same blocks available!
So thanks for the education and I am glad we figured that out.
I took a quick look at it. Obviously the number format will be different. It appears to operate in a similar way. At first glance it looks like it uses 256 not 1024 but I think this is not true. I think it wraps around to the lower word? I will have to study this further. I do not have the time to look into this today. This entire week will be difficult actually. So I looked at it a bi more. It looks like it is 1024 again but only the top three bits are in the top word. Then it looks like the bottom word does not use all 28 bits. It looks like the bottom 21 bits are used as the fractional part. Then one bit is not used and then the LSB of the four whole number bits. This means it only uses 25 bits so why break it up into a high and low word? This will need some more investigation on my part but I was able to calculate one degree of change using 2^21 as the fractional part but it does not all work out. So I guess I have more work to do.
I do want to add one other detail. The reason this works for the Sigma300/350 is that the parameters are put in one set right after the other set in memory. In the ADAU1701 things are different. In this core I noticed the complier did not put them in order. This is because you can only safeload five words at a time. Now, they still could have done it and there may be a way to still do it. Why is this important? Because when you do a safeload write, it is done in one sample period. If you do two safeload writes, it is not done in the same sample period so if the goal is to reset the counters at exactly the same time it will not be possible when you do it in two different safeloads. I noticed that SigmaStdio is doing it in two safeloads. I think it still could have been done in one.
Then I also noticed that if I refresh the params window the phase relationship of the two waveforms change. This is probably because the core is interrupted when memory is being accessed. It was a shortcoming of this core than we fixed in later cores. You HAVE to do safeload writes to prevent clicks and pops or other issues like this.
When I look at the parameters. I see that I could write five memory locations that would include both phase settings and one of the gain settings.
So there may be a way to work around this with your microcontroller.
Dave T
Hello,
Thanks for taking the time! However I ended up with an easier to control solution. A sawtooth function and then for every derivative I need an OR block of two Tolerance ranges block. It let me easily control phase and duty cycle (I don't need the triangle/sawtooth for other than modulation purposes). So if you are busy definitely don't feel like you have to spend time on this!
However I wonder If I am doing something wrong. Aren't users supposed to be controlling those blocks via I2C? AD doesn't want us to write our own code and forces us to use predefined blocks. Shouldn't those blocks and their parameters properly documented. If not I think we should have the source code so that we don't have to reverse engineer the format of parameters ?
Hello GLeclerc,
In a perfect world we would have very detailed documentation for every block but early on there were a couple of issues. The 1st was that there were many blocks to write and only a handful of programmers with limited time. Then the other issue was that there was competition that was copying what we were doing so we limited what we documented. Several years ago we started updating the documentation but there are hundreds of blocks and then EngineerZone has come in to help with this documentation. Many of this information is on the forum now and can be searched. I am also going to make videos for the YouTube channel but that will also take a while because there are hundreds of blocks!
Dave T
Makes sense! I completely understand where you are coming from, good support is hard and you (personally) do incredible job! I know you probably have no power over this but legacy companies like AD have a tendency to underestimate the benefits of open source and the amount of tooling people and academics develop when they are given the chance. I really don't think the ADAUx line-up is would have its value decreased by opening the assembly spec (doesn't need to include support effort from AD). There are already countless competitors with the Cortex Mx cores and DSP libraries for those. In my opinion the benefits of ADAUx would still hold if parts of it were open. It would still be a good, power efficient, easy to integrate, easy to interface, with self boot capabilities chip.
I personally plan to continue building more with this platform (both for research projects and consumer products) but there are definitely scenarios where I picked other parts and wouldn't have if I had assembly access to the core.
As an academic I also see how great ADAU1701 would be to teach digital signal processing if there was an open source multi-platform stack that could be used on a classroom issued board with an USB to I2C chip directly on it. And we all know that students tend to stick with tools they learn on (see Matlab) so it would be beneficial for AD too.
Sorry for the rant and thank you again for your support. I ended up achieving what I wanted and in the end that's the most important!
Hello GLeclerc,
Thanks a lot for the rant!!! I agree with a lot of what you said and stay tuned for some improvements down the road a little. You should contact me directly. I am working on supporting schools more actively and I feel the SigmaDSP is a great platform to learn a lot of basic theory early on in an EE program. Plus do it in a fun way! I have actually been trying to get a course going at one of the schools that I teach at but so far I have not had success. I do want to plant seeds at other schools and perhaps go visit to give workshops and lectures.
Dave T
Please log in to reply.









