2021-11-06 09:59 PM
Let's say you're loading the SAI 32-bit ADR or BDR data registers. Using 24-bit data size, I2S protocol. More concretely, what values do you load for 0 amplitude, max positive, and max negative?
Do you center it? Eg map 0 amplitude to 2^32 / 2, max positive to 2^32 / 2 + 2^24 / 2, and max negative to 2^32/2 - 2^24 / 2?
Do you map 0 amplitude to 2^24 / 2, max positive to 2/24, and max negative to 0?
Solved! Go to Solution.
2021-11-07 01:49 AM
Which STM32?
As given in the FIFO subchapter of I2S chapter in RM, data written to SAI_xDR are right-aligned, i.e. the most significant bits beyond the set transfer data width are ignored. In other words, if you use 24-bit transfer and you write 0x12345678, then it's the same as if you'd written 0x00345678 or 0xFF345678.
For the rest of data, SAI does not care, simply transmits them. It's upon the device on the other end of the wire to interpret the data. I've never seen an I2S DAC which would not support two's complement (transmitted as MSB-first), as the primary data format (I've seen some which supported additional data formats, but that's probably rare). This is btw. also the requirement of the I2S specification.
That means, mid is 0x000000, max positive is 0x7FFFFF and max negative is 0x800000 (for sake of "symmetry" you might see 0x800001 as max negative if you want, but the difference is negligible).
JW
2021-11-07 01:49 AM
Which STM32?
As given in the FIFO subchapter of I2S chapter in RM, data written to SAI_xDR are right-aligned, i.e. the most significant bits beyond the set transfer data width are ignored. In other words, if you use 24-bit transfer and you write 0x12345678, then it's the same as if you'd written 0x00345678 or 0xFF345678.
For the rest of data, SAI does not care, simply transmits them. It's upon the device on the other end of the wire to interpret the data. I've never seen an I2S DAC which would not support two's complement (transmitted as MSB-first), as the primary data format (I've seen some which supported additional data formats, but that's probably rare). This is btw. also the requirement of the I2S specification.
That means, mid is 0x000000, max positive is 0x7FFFFF and max negative is 0x800000 (for sake of "symmetry" you might see 0x800001 as max negative if you want, but the difference is negligible).
JW
2021-11-07 08:15 AM
H743.
Thank you re `the most significant bits beyond the set transfer data width are ignored`. It appears that this is the crux of it: I can multiply the float by *1<<23* to get it into an `i24` range, then cast as `i32` to satisfy the protocol/peripheral, then cast again as `u32` to satisfy the SAI API I'm using. The `u32` cast is a no-op, but is required to satisfy the compiler. The printed `u32` numbers are outside the 24-bit rng, but the extra `1`s are discarded as you said.
The part in your comment about 2s complement is also key here. Thank you, and resolved! * max negative is 0x800000* is also counter-intuitive, but works here.
Resulting code:
```rust
BUF[i] = ((val * (1<<23)) as i32) as u32;
```