Electronics > Microcontrollers
This code is so broken it some how fixes itself.
paulca:
So this code works. It shouldn't, but it does. (Friend wrote it, acchmm). I just find it amusing how broken it is that it seems to fix itself.
The SAI's are in 16bit extended.
The for loop is nuts. There are not 8 16bit ints there. There are 8 8bit ints. Yet it works. In fact a whole bunch of different viarities work also.
for (int i = 0; i < 8; i+=4)
Is my favourite.
for (int i = 0; i < 2; i++) // Nope , not even with a int32_t buffer.
for (int i = 0; i < 4; i++) // Nope
for (int i = 0; i < 8; i++) // YES
for (int i = 0; i < 8; i+=2) // YES
for (int i = 0; i < 8; i+=4) // YES
I think it's just lucky word alignment.
--- Code: --- int16_t buffer[8];
float gain = 0.75f;
while (1) {
HAL_SAI_Receive(&hsai_BlockA1, (uint8_t*) buffer, 8, 10);
for (int i = 0; i < 8; i++) {
double sample = buffer[i];
sample = sample * gain; // pre-gain
sample = PeakFilter_Update(&bassBoost, sample);
sample = PeakFilter_Update(&midCut, sample);
sample = PeakFilter_Update(&highBoost, sample);
buffer[i] = (int16_t) sample;
}
HAL_SAI_Transmit(&hsai_BlockA2, (uint8_t*) buffer, 8, 10);
}
--- End code ---
EDIT: I'm laughing at myself but this is a classic example. Classic. Your code works first time. "That was easy". Never pay any attention. "Some time later...", "That doesn't look right... I'll take a look...."
"Wait. How does this work? How did this ever work? What the hell?"
No... I'm not looking for help to fix it. I can see a symetry of problems that if fixes will make it make sense, but I just found it funny. Symmetrical insanity just happens to work.
EDIT2: Oh and it has many other issues to boot.
Sherlock Holmes:
--- Quote from: paulca on January 27, 2023, 08:21:59 pm ---So this code works. It shouldn't, but it does. (Friend wrote it, acchmm). I just find it amusing how broken it is that it seems to fix itself.
The SAI's are in 16bit extended.
The for loop is nuts. There are not 8 16bit ints there. There are 8 8bit ints. Yet it works. In fact a whole bunch of different viarities work also.
for (int i = 0; i < 8; i+=4)
Is my favourite.
for (int i = 0; i < 2; i++) // Nope , not even with a int32_t buffer.
for (int i = 0; i < 4; i++) // Nope
for (int i = 0; i < 8; i++) // YES
for (int i = 0; i < 8; i+=2) // YES
for (int i = 0; i < 8; i+=4) // YES
I think it's just lucky word alignment.
--- Code: --- int16_t buffer[8];
float gain = 0.75f;
while (1) {
HAL_SAI_Receive(&hsai_BlockA1, (uint8_t*) buffer, 8, 10);
for (int i = 0; i < 8; i++) {
double sample = buffer[i];
sample = sample * gain; // pre-gain
sample = PeakFilter_Update(&bassBoost, sample);
sample = PeakFilter_Update(&midCut, sample);
sample = PeakFilter_Update(&highBoost, sample);
buffer[i] = (int16_t) sample;
}
HAL_SAI_Transmit(&hsai_BlockA2, (uint8_t*) buffer, 8, 10);
}
--- End code ---
EDIT: I'm laughing at myself but this is a classic example. Classic. Your code works first time. "That was easy". Never pay any attention. "Some time later...", "That doesn't look right... I'll take a look...."
"Wait. How does this work? How did this ever work? What the hell?"
No... I'm not looking for help to fix it. I can see a symetry of problems that if fixes will make it make sense, but I just found it funny. Symmetrical insanity just happens to work.
EDIT2: Oh and it has many other issues to boot.
--- End quote ---
How do you distinguish between "works" and "broken"?
Sherlock Holmes:
Note:
--- Code: ---HAL_SAI_Receive(&hsai_BlockA1, (uint8_t*) buffer, 8, 10);
--- End code ---
If that 8 is the size of the buffer to write to, then only 8 bytes are being used despite the fact the declared buffer is 16 bytes long...
The code declares a 16 byte buffer, but it only ever needs and uses an 8 byte buffer, so long as buffer is at least 8 bytes long, everything is fine - is that what you're talking about though?
thm_w:
--- Quote from: Sherlock Holmes on January 27, 2023, 09:37:58 pm ---Note:
--- Code: ---HAL_SAI_Receive(&hsai_BlockA1, (uint8_t*) buffer, 8, 10);
--- End code ---
If that 8 is the size of the buffer to write to, then only 8 bytes are being used despite the fact the declared buffer is 16 bytes long...
The code declares a 16 byte buffer, but it only ever needs and uses an 8 byte buffer, so long as buffer is at least 8 bytes long, everything is fine - is that what you're talking about though?
--- End quote ---
16 bytes are used, assuming HAL_SAI_Recieve is set to 16-bit (instead of 8-bit) in the initialization. Which OP is saying it is.
I think the point is that HAL_SAI_Receive is writing to an address using 16-bit each time, but then OP thought the loop was pulling out data 8-bit at a time?
Which I don't think it is, because buffer is a 16-bit array, right?
int16_t buffer = {1, 2, 3, 4};
buffer[0] = 1
buffer[1] = 2
hans:
That function looks like typical C HAL hackery mess - where 8 defines the number of items and not the number of bytes, and the item size is configured elsewhere. It increments the dataPtr by 2 bytes at a time, and only after byte increments casts it to 16-bits for the write operation. That is functionally correct, but IMO very odd way of dealing with sizes, pointers and casts. But I rest my case, C does not really allow for a type generic implementation without either macros (= bigger mess) or C++ templates..
Anyhow, if we assume that OP tested a SAI passthrough which works and does not discard any samples, then it kind of is a mystery what behaviour is observed. As Sherlock says, what does broken and what does working look like? Are there really zero differences to spot for the 3 different "YES" situations listed?
Considering that the filter behaviour can be tested independently.. one may be able to generate a sweep of input frequencies into a buffer and pull it through the suspecting code. The output samples can then be plotted in e.g. a bode plot. It's a bit tedious work to set up the testbench, and perhaps there are frameworks or tools that don't require you to write everything yourself (e.g. thinking of MATLAB/Octave), but it could give some insight what the numerical operations are affecting to your raw ADC/DAC samples.
However, I think some sort of unit testing is always beneficial for DSP or business logic code like this. The HAL functions serve their purposes of transferring in ADC/DAC data with some real-time element attached to it (not to cause time-related glitches etc.), but other than that the calculations can be modelled very well on a PC with unit tests instead. If that catches 95% of the mistakes before uploading to hardware, it can reduce the head scratching alot between distrusting the HAL configuration/usage and/or your own tested application code.
Navigation
[0] Message Index
[#] Next page
Go to full version