Electronics > Microcontrollers

This code is so broken it some how fixes itself.

(1/8) > >>

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

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod