Please don't take this personally as I understand you were just providing a quick, rather than a fully engineered example, but I hated your solution! But note that: this is as it applies to this specific case - robust, optimized library solutions for common problems can avoid developers continually reinventing the wheel with their own unique, new buggy versions. They are often a very good idea.
But your example doesn't, being inflexible, fragile and worse, produces the wrong results. It doesn't help me as someone in the position of writing Dave's original code - it makes my life harder!
I won't take offence at constructive criticism, don't worry.
The example I provided was made to demonstrate the principle of parting code out into separate logical units and show that it adds clarity to the code. The idea behind it is that as you read through a piece of code, it's easy to get a general understanding of what is going on.
"Okay, I'm inside an ADC conversion complete interrupt, so first I read the sample from the ADC registers, then it gets filtered and then passed into a scaling function that returns SI units. Then I compare that to some parameters and do xyz."
Having the ADC register gymnastics, filters and scaling functions in separate files and functions, with descriptive names, makes the signal flow clear even without adding comments to the code. Nobody is stopping you from adding comments, but the code is understandable without them.
On the other hand, reading through code that has everything bundled together inside the ISR, requires more effort to understand what's going on.
"I'm inside an ADC conversion complete interrupt, then I'm reading register ADCH, shifting that up and then adding the value from register ADCL. All of the elements in this array are being shifted and here I'm putting the newly assembled number to the beginning. Now I'm summing all of the elements inside the array,..."
Again, the latter is perfectly fine for a blob of code that is meant as a proof of concept, but you'd rather not have that when multiple people are working on the same code.
Your criticisms of the filter code itself are valid. I haven't taken the time to even try and compile that, I just quickly typed something up to show an example.
But the ‘elegant solution’ is just as rubbish and unnecessary in a 500K LOC project as in a simple test program. Yes we know you were illustrating the concept of reusability with a simple example but it is definitely not always ‘absolutely crucial’ no matter how big the project. Even complex functions that look like they should be provided in a library shouldn't always - especially in embedded, details matter, often performance related.
I'd disagree. Splitting things into functional units is not optional if you're talking about half a million lines of code, the code would be impossible to maintain otherwise. A hefty amount of documentation would be needed to boot.
There are always costs as well as advantages.
It's always like that, no way around it. If meeting some strict timings requires being wary of every single CPU clock cycle, then subroutine calls would of course be undesirable. My statements obviously don't apply to those cases.