ADAU1451 and SIGMASTUDIOTYPE_8_24
I am working on a linux driver to interface with a ADAU1451 that is running a program developed in sigma studio. I have exported the header files and am able to interact with the device over spi but I find the SigmaStudioFW.h quite lacking. The generated files have SIGMASTUDIOTYPE_8_24 as the type for most parameters but it is not listed in the SigmaStudioFW.h there is also not a macro for the conversion or a description of the conversion in the file. I have a very large parameter fine with most parameters being SIGMASTUDIOTYPE_8_24 and using a conversion SIGMASTUDIOTYPE_8_24_CONVERT(x). The parameters being input appear to be floating point numbers but as there is no definition this is hard to derive the proper operations. The value in the below example appears to be -10db which matches the value in sigma studio. I assume that the value is 2 words as the register size as 8.24 is a 32bit number but the addresses go in increments of one and a typical register in the device is 16bit so this this a bit off. Any help would be appreciated and documentation and accompanying code needs to be added to sigma studio.
/* Module Channel 1 Volume_3 - Single Volume*/
#define MOD_CHANNEL1VOLUME_3_COUNT 2
#define MOD_CHANNEL1VOLUME_3_DEVICE "IC1"
#define MOD_CHANNEL1VOLUME_3_ALG0_TARGET_ADDR 757
#define MOD_CHANNEL1VOLUME_3_ALG0_TARGET_VALUE SIGMASTUDIOTYPE_8_24_CONVERT(0.316227766016838)
#define MOD_CHANNEL1VOLUME_3_ALG0_TARGET_TYPE SIGMASTUDIOTYPE_8_24
#define MOD_CHANNEL1VOLUME_3_ALG0_SLEW_MODE_ADDR 758
#define MOD_CHANNEL1VOLUME_3_ALG0_SLEW_MODE_FIXPT 0x0000208A
#define MOD_CHANNEL1VOLUME_3_ALG0_SLEW_MODE_VALUE SIGMASTUDIOTYPE_INTEGER_CONVERT(8330)
#define MOD_CHANNEL1VOLUME_3_ALG0_SLEW_MODE_TYPE SIGMASTUDIOTYPE_INTEGER
Audio Signal Processors
adau1451
sigmastudiotype_8_24_convert
SigmaDSP Audio Processors
sigmastudiotype_8_24
emcnicholas,
These coefficients are not floating point values. They are fixed point. The number format and conversion does take a little getting used to, but it's actually pretty simple and efficient. I have updated the page describing the fixed point numeric formatting to provide more information on the 8.24 format used by the ADAU145x family. I think this might clear a lot of your problems. Please take a look here and let me know if you have questions that directly apply to your application.
Ken
Ken while i appreciate the number format and have developed the converter the exports from sigma are not the best for developing a kernel module for control as the export is in floating point that requires conversion and floating point math is not permitted in kernel space. Also the SigmaStudioFW.h file is rather lacking as the macro defs are completely missing.
Hi
are there functions to convert to 8.24 formats available?
Hello emcnicholas,
O ne little comment you made in your original question was about addresses of the registers. The way we address the registers is sequential, 16-bit register to 16-bit register and not by byte. So this is why you do not see the value going up by two bytes. You cannot address just half of the register, you must address the entire 16 bit register as one word. We do the same thing for the 32-bit data memories. They are addressed as a full 32bit word and you cannot get to the individual bytes.
Dave T
Hello Brettcoupe,
Try asking this question in the Linux space on this forum. The engineers there are much more familiar with the Linux drivers than I am.
Dave T
Hi Ken, I am going through the process of writing a driver for the ADAU1452 and also being slowed down by these conversions. The article is helpful but explicit macro definitions (forward and reverse) would be even more helpful. The code must exist somewhere and it's not in the SigmaStudio header file.
Also according to my understanding 8.24 is 32 bit format, in the examples only 24bits are shown and they are identical to the 5.23 format. Is that correct?
In any case this seems to work for me (so far):
# Convert number to 5.23 format
def to_523(param_dec):
# multiply decimal by 2^23
param223 = param_dec * (1 << 23)
# convert to positive binary
param227 = int(param223 + (1 << 27))
param_hex = [None] * 4
param_hex[0] = (param227 >> 24) & 0xFF
param_hex[1] = (param227 >> 16) & 0xFF
param_hex[2] = (param227 >> 8) & 0xFF
param_hex[3] = param227 & 0xFF
# Invert sign bit to get correct sign
param_hex[0] = param_hex[0] ^ 0x08
return param_hex
# Convert number to 8.24 format SIGMASTUDIO_8_24_CONVERT
def to_824(param_dec):
# multiply decimal by 2^24
param224 = param_dec * (1 << 24)
# convert to positive binary
param231 = int(param224 + (1 << 31))
param_hex = [None] * 4
param_hex[0] = (param231 >> 24) & 0xFF
param_hex[1] = (param231 >> 16) & 0xFF
param_hex[2] = (param231 >> 8) & 0xFF
param_hex[3] = param231 & 0xFF
# Invert sign bit to get correct sign
param_hex[0] = param_hex[0] ^ 0x80
return param_hex
# Convert number to int 32 format
def to_int(param_dec):
param_hex = [None] * 4
param_hex[0] = (param_dec >> 24) & 0xFF
param_hex[1] = (param_dec >> 16) & 0xFF
param_hex[2] = (param_dec >> 8) & 0xFF
param_hex[3] = param_dec & 0xFF
return param_hex
And the output:
-----5.23 Test-----
0.0 = [0x00, 0x00, 0x00, 0x00, ]
0.25 = [0x00, 0x20, 0x00, 0x00, ]
0.5 = [0x00, 0x40, 0x00, 0x00, ]
1.0 = [0x00, 0x80, 0x00, 0x00, ]
2.0 = [0x01, 0x00, 0x00, 0x00, ]
4.0 = [0x02, 0x00, 0x00, 0x00, ]
-16 = [0x08, 0x00, 0x00, 0x00, ]
-4 = [0x0e, 0x00, 0x00, 0x00, ]
-1 = [0x0f, 0x80, 0x00, 0x00, ]
-0.5 = [0x0f, 0xc0, 0x00, 0x00, ]
-0.25 = [0x0f, 0xe0, 0x00, 0x00, ]
0.000100016593933 = [0x00, 0x00, 0x03, 0x47, ]
-0.476439774036 = [0x0f, 0xc3, 0x04, 0x05, ]
0.369109928608 = [0x00, 0x2f, 0x3e, 0xfe, ]
-----8.24 Test-----
0.0 = [0x00, 0x00, 0x00, 0x00, ]
0.25 = [0x00, 0x40, 0x00, 0x00, ]
0.5 = [0x00, 0x80, 0x00, 0x00, ]
1.0 = [0x01, 0x00, 0x00, 0x00, ]
2.0 = [0x02, 0x00, 0x00, 0x00, ]
4.0 = [0x04, 0x00, 0x00, 0x00, ]
-16 = [0xf0, 0x00, 0x00, 0x00, ]
-4 = [0xfc, 0x00, 0x00, 0x00, ]
-1 = [0xff, 0x00, 0x00, 0x00, ]
-0.5 = [0xff, 0x80, 0x00, 0x00, ]
-0.25 = [0xff, 0xc0, 0x00, 0x00, ]
0.000100016593933 = [0x00, 0x00, 0x06, 0x8e, ]
-0.476439774036 = [0xff, 0x86, 0x08, 0x0b, ]
0.369109928608 = [0x00, 0x5e, 0x7d, 0xfd, ]
-----INT Test-----
0 = [0x00, 0x00, 0x00, 0x00, ]
1 = [0x00, 0x00, 0x00, 0x01, ]
2 = [0x00, 0x00, 0x00, 0x02, ]
3 = [0x00, 0x00, 0x00, 0x03, ]
4 = [0x00, 0x00, 0x00, 0x04, ]
-4 = [0xff, 0xff, 0xff, 0xfc, ]
-3 = [0xff, 0xff, 0xff, 0xfd, ]
-2 = [0xff, 0xff, 0xff, 0xfe, ]
-1 = [0xff, 0xff, 0xff, 0xff, ]
8330 = [0x00, 0x00, 0x20, 0x8a, ]
Why are you toggling the sign bit twice? This has no effect. Just multiply by (1 << 24) and encode as 32-bit big-endian integer.
You seem to be using python. There you can simply do:
from struct import pack
def to_824(x):
return pack(">i", int(x * 0x1000000))
Besides being shorter, it has the additional benefit of verifying the argument is within valid range (which your code currently doesn't). Note that this returns a bytes object, which is generally the appropriate type for binary data, but you can just cast it to list() if you prefer a list of integers like your code produces.
Antala,
The reason that the macros are only included as stub functions is that the native format of the host microcontroller is not known. It may be an 8-biit, 32-bit, or 64-bit processor, and the conversions will differ. Also, the controlling code may be fixed or floating point. We don’t make assumptions because they are often incorrect.
8.24 format is only a 32-bit format in that it is 32 bits long. It is a fixed point value with an integer part and a fractional part. It is, admittedly, awkward to convert between floating point values and fixed point values (such as 8.24) because the floating point format has a much larger dynamic range. 8.24 is limited to the range 128 (-1 LSB) to -128. The IEEE standard for 32-bit floating point has an 8-bit exponent and a 24-bit mantissa. Therefore, you will lose precision converting from floating point to 8.24 unless the exponent happens to be 1 or -1.
If you have a two’s complement, 32-bit integer that represents your full scale signal, divide by 2^24 to get a number in 8.24 format without loss of precision.
Similarly, multiply an 8.24 value by 2^24 to get a 32-bit, 2’s complement integer. In most cases, however, audio is represented in the range of 1 to -1, (e.g., when communicating with ADCs and DAC)s.
If you have a floating point value in the range 128 (-1LSB) to -128, then mask the integer portion and put it in the upper 8 bits, and mask the fractional portion and put it in the lower 24 bits.
If you have a floating point outside this range, then you will have to decide how you want to do your scaling. Again, this is an implementation-specific decision that makes it not practical for us to provide boilerplate code that would work, for example, in a kernel driver without any knowledge of the input and output data range. This is a fixed point DSP, and therefore not compliant with IEEE standard, C-style data types.
Note that 5.23 is the native format for older SigmaDSP processors and has no relevance to the ADAU145x or ADAU146x families of processors.
I hope this helps,
Ken
Thanks, much neater.
There are many errors on the numeric formatting page, particularly in the 8.24 section. Accurate information is available here and here.
There are many errors on the numeric formatting page, particularly in the 8.24 section. Accurate information is available here and here
and here
Please log in to reply.