Author Topic: C++ for embedded: how to learn it in 2021?  (Read 11304 times)

0 Members and 1 Guest are viewing this topic.

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
C++ for embedded: how to learn it in 2021?
« on: December 12, 2021, 12:43:47 pm »
so, I have to stand up and admit: I don't know how to program in C++, because when I write something I think it in C.

I do spend a lot of time programming in ErLang, C, and assembly (PowerPC and MIPS), and this for sure ads some kind of bias to my "C++ thinking".

Therefore, I want to forget everything, and go back as beginner for a new fresh start.

But: how to learn C++ in the correct way? In 2021? I don't need enterprise knowledge, my focus of interest is only Embedded stuff.

Let me know about books, courses, etc.

(Don't take it offensive, but for me Arduino is not a good reference about C++ ... I do find their libraries clunky and confusing)
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6266
  • Country: fi
    • My home page and email address
Re: C++ for embedded: how to learn it in 2021?
« Reply #1 on: December 12, 2021, 02:54:40 pm »
The core problem with embedded C++ is that exceptions (try, catch, throw) are not supported, but in standard (hosted) C++ environments they are the standard mechanism for error propagation.  That is the major one, but there are additional minor problems like static object initialization order, and so on.

It is my opinion that because of those differences, standard C++ programming guides are not suitable as-is.  I suppose one can pick-and-choose what to adopt, but the paradigm, approaching problems "in a C++ way", is different in embedded C++ than in standard hosted C++.

I've looked at the sources of many different embedded C/C++ open source projects, from SmoothieBoards to Arduino/PlatformIO libraries, and to me it seems that problems are approached from the "C way" (with respect to abstractions and how they are used), with freestanding C++ facilities like objects, templates, and atomics used rather like an extension to C.  Note that my experience is limited to open source projects, and therefore is likely skewed; I too would be interested in the opinion of whether this applies to proprietary projects as well, by those who have used C++ in embedded environments in many proprietary projects.

If one were to assume a similar opinion to mine, then it might help to list some of the most useful features of freestanding C++ used in embedded environments.  (I hope others will pipe up, because these are just the most important ones I've noted.)
  • Objects, classes, and inheritance

    While one can implement plain objects as structures in C, the class hierarchy and inheritance means you can move common functionality and properties to parent classes.  For example, if you drive an ILI9341-controlled display, the commands and data stay the same, but the underlying bus can be 9-bit SPI, 8-bit SPI with a separate command/data output line, or one of multiple parallel bus types.  If you implement a class for the display controller, and a class for each of the bus types, you can use multiple inheritance to create a class that inherits from both, and only contains the needed "glue" code.

    If the class interfaces are well designed, the classes can be refactored (implementation rewritten without changing the interface) if needed, and overall the code can be easier to maintain and to port to different architectures.

  • Function overloading

    In C++, you can implement "versions" of the same function that only differ by the parameters they take.  The compiler will then choose the correct one (at compile time), depending on the parameters passed.  This simplifies the interfaces and reduces programmer cognitive load, because they then only need to remember that say send() object member or function is used to send data in various forms, instead of say send_string() for strings, send_data() for arrays with specified length, and so on.

  • Templates

    Basically, when you define a class or a function, you can leave out the types of certain parameters.  When instantiated (used), the compiler will make sure that there is an implementation with the types specified at that point.  This can be extremely useful, for example if one wants to implement say fixed-point arithmetic; but the downside is that each unique combination of the types usually requires a completely new machine code implementation, so the compiled binary size can grow unexpectedly large with careless use of templates.
Again, those are just the ones that have been obvious to me.  I wonder if I should include atomics in there.. I didn't, because I've only ever used the GCC atomic built-ins and only after verifying they don't compile to function calls (i.e., emulation via some kind of locking facility).

I don't remember seeing operator overloading used in a useful manner, and personally do not except when implementing an arithmetic class (say, fixed-point arithmetic, or range arithmetic).  A lot of code (especially those targeted at AVR and ARM architectures) also happily use variable and function attributes provided by GCC and LLVM/Clang as extensions to C and C++.  I don't know how much those are frowned upon in the proprietary world using non-GCC, non-Clang toolchains.

If one wants to be cruel, they could say I myself write embedded/freestanding C++ pretty much as I'd write in a language that was a bastard mix of Python and C.  So take that into account when considering my opinions here.

Hopefully others will pipe up with their opinions and experiences.  I might be completely wrong, and need a restart in C++ myself, too.
 
The following users thanked this post: ogden, Tagli, DiTBho

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: C++ for embedded: how to learn it in 2021?
« Reply #2 on: December 12, 2021, 04:54:14 pm »
well, for the sewing industrial machine, I wrote a polymorphic b*tree algorithm in C because I was unable to use C++, and also because I tend to use C++ like if it was C, and this is very very bad!

The resulting code has to handle different kinds of keys
- uint32
- string
- rect(x,y)
and since C has neither templates nor operator-overloading I had to implement this stuff manually
- cmp { is_eq(a,b), is_ne(a,b), is_lt(a,b), is_le(a,b), is_gt(a,b), is_ge(a,b) }
- let { copy(a,b), show(a) }
- check keys and coherence, react to errors, and propagate it to the high layers
for each kind of keys ... and load them as function-pointers in every function of the library, plus a trick to convert a "key" into an array of byte in order to "pass" it to the low-level algorithms (storage, load and save from/to file).

A further problem is ... the code must be MISRA compliant (otherwise I cannot sell the software), so you cannot use too ugly tricks, and your code needs to look "polished" enough for those who care to read it.

Now it's clean and it also works solid as a rock, I can even define and manage an abstract "key", but the whole development-and-testing-process was a very unpleasant, rather masochistic experience, and it took three weeks just to debug and verify the polymorphic stuff, which is really too much time.

Proper use of C ++ could reduce the effort by several orders of magnitude I think, that's why I worry about learning it the right way :D
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: C++ for embedded: how to learn it in 2021?
« Reply #3 on: December 12, 2021, 05:38:48 pm »
Just select a subset of C++, and stick with that. C++ has a lots of nice features, but typically you can get things done using a small subset of well understood language features. Even if you were a C++ guru, the next person may not be.

Edit: It is always useful to check the compiler's assembly output, so that you really can see what kind of code is generated from the actual C++ source code. Especially in memory-limited devices, seeing the compiler's output has proven very useful to be able to keep track of device's memory usage.
« Last Edit: December 13, 2021, 11:21:28 am by Kalvin »
 
The following users thanked this post: DiTBho

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14490
  • Country: fr
Re: C++ for embedded: how to learn it in 2021?
« Reply #4 on: December 12, 2021, 07:50:12 pm »
But: how to learn C++ in the correct way? In 2021?

Probably by reading Stroustrup's book itself: https://www.stroustrup.com/4th.html
You'll get C++ as it was meant to be used, instead of the fantasy some people have about it.

As to C++ for embedded development, this is an endless source of discussion. There virtually is NO "correct way" of using C++ for embedded development, because this is undefined territory, so everyone is pretty much doing their own thing while being dead convinced it's the right way of doing it. There's been an official attempt at defining a subset of C++ for embedded development: https://en.wikipedia.org/wiki/Embedded_C%2B%2B , but it failed miserably in the end. That did not prevent people from doing exactly the same, as I just said, each in their own way, while thinking it's better than the EC++ attempt.

Here is what Stroustrup thinks about this: https://www.stroustrup.com/bs_faq.html#EC++

One question comes to mind - what is your motivation here for learning C++? This may in itself help guiding you.
 
The following users thanked this post: DiTBho

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6266
  • Country: fi
    • My home page and email address
Re: C++ for embedded: how to learn it in 2021?
« Reply #5 on: December 12, 2021, 08:21:43 pm »
well, for the sewing industrial machine, I wrote a polymorphic b*tree algorithm in C because I was unable to use C++, and also because I tend to use C++ like if it was C, and this is very very bad!
That's a good example of where the OO approach would likely have saved some work for sure.

However, other than object encapsulation and using the class structure to separate the algorithm from the three data types you needed it with, I don't really see a major difference in a freestanding C and a freestanding C++ implementations.  If you agree, then you need to concentrate on learning the aforementioned C++ features, and how to use them in your own embedded code.

A further problem is ... the code must be MISRA compliant (otherwise I cannot sell the software)
AFAIK MISRA C++ has its own list of C++ features it forbids.  AUTOSAR AP 18-10 for C++14 forbids malloc(), free(), goto, casts (except static_cast), multiple inheritance (other than one base class and any number of interface classes), friend, dynamic exceptions, function try blocks, and #pragma.

It is basically its own set of recommended and forbidden patterns and rules, that you need to abide by.  Perhaps "MISRA C++ in an embedded environment" might be a good key phrase?
 
The following users thanked this post: DiTBho

Offline AntiProtonBoy

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: au
  • I think I passed the Voight-Kampff test.
Re: C++ for embedded: how to learn it in 2021?
« Reply #6 on: December 13, 2021, 12:49:12 am »
But: how to learn C++ in the correct way? In 2021? I don't need enterprise knowledge, my focus of interest is only Embedded stuff.

Let me know about books, courses, etc.
Focus on learning the language first, then worry about the embedded stuff later.

Bjarne's books are a good start, as others have suggested, but you also look into books published by Scott Meyers, Andrei Alexandrescu, Sean Parent, Kate Gregory, Herb Sutter.
 
The following users thanked this post: DiTBho

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: C++ for embedded: how to learn it in 2021?
« Reply #7 on: December 13, 2021, 09:24:34 am »
First, define what "embedded" means for you.  Are you talking itty bitty microcontrollers like an Arduino, significantly capable single board computers like a raspberry pi, or maybe even x86 PC compatibles without a keyboard ("kiosk", "set top boxes", etc.)  I've seen people call each of those "embedded", with not-unreasonable justifications.
I agree with Nominal Animal - most "embedded C++" looks a lot like C code with some additions, while many C++ "experts" will try to convince you to make your C++ look as little like C as possible :-(  That can make the many books, tutorials, libraries, and fora about C++ relatively useless for embedded programmers.  I mean, objects are swell, I guess, but that doesn't mean that EVERYTHING has to be an object.  And to be honest, I think a lot of C++ is like Python and Arduino - it's not so much that the language itself is so great, but that you can find libraries already written that implement SOME things quite elegantly, within a C++ framework.  That's great if you have libraries that are useful to you, but only vaguely interesting if you're writing from scratch.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: C++ for embedded: how to learn it in 2021?
« Reply #8 on: December 13, 2021, 11:10:04 am »
what is your motivation here for learning C++?

I'm full of embedded examples where OO approach would likely have saved some work.
I can do OO in pure C, but it's ... rather masochistic and I'd like to save time and effort.

The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: C++ for embedded: how to learn it in 2021?
« Reply #9 on: December 13, 2021, 11:11:30 am »
@AntiProtonBoy
added to list!

  • Scott Meyers
  • Andrei Alexandrescu
  • Sean Parent
  • Kate Gregory
  • Herb Sutter

Thanks!
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: C++ for embedded: how to learn it in 2021?
« Reply #10 on: December 13, 2021, 11:18:19 am »
First, define what "embedded" means for you

I quoted sewing machine is the typical scenario where I usually work!
- not Linux, and not even close to RPI
- one/two RISC CPUs coupled with a lot of ASIC stuff

and I have to write the firmware from scratch:
- built-in tests -> C + assembly are perfect here
- bootloader -> C is perfect here
- application layers -> it usually better suites OO approach, therefore C++ ... mumble ?!?
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: C++ for embedded: how to learn it in 2021?
« Reply #11 on: December 13, 2021, 11:33:05 am »
I agree with Nominal Animal - most "embedded C++" looks a lot like C code with some additions

That's precisely what I'd like to understand and master: which additions, where to use, where to not abuse, and how to use them the right way.

In 2022 I will for sure write a new firmware for the new sewing machines (bigger and more complex machines): maybe gain pure C with manual OO, maybe "embedded C++ that looks a lot like C code but with some addictions"  :D
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: C++ for embedded: how to learn it in 2021?
« Reply #12 on: December 13, 2021, 11:53:45 am »
Here are two or three things that may come as a surprise for the beginning [embedded] C++ users:

1. The compiler is generating default constructors if not provided explicitly by the programmer.

This may not be what you want, because the default constructors created by the compiler may allocate the objects dynamically from the heap. The default constructor will be called if a programmer accidentally declares the object but doesn't specifically provide the constructor to be used. Been there, done that.

In order to prevent this, declare the default constructor for each and every class as private. This will effectively hide the default constructor, and prevent accidental invocation of the default constructor by creating a compile-time error.

2. The objects declared at global scope level, file static level, or as a static function member will be constructed before the main() is called.

This may not be what you want, and may cause confusion because the objects may be constructed in an order you did not expect.

This can be handled quite easily by creating an init()-function for each module,  and calling the modules' init()-functions from the main() in the order you want. Make these modules' init()-functions to allocate and construct the objects as required, and you are in control again.

3. Declare all destructors as virtual, unless you really want to do otherwise.
 
The following users thanked this post: Nominal Animal, DiTBho

Online magic

  • Super Contributor
  • ***
  • Posts: 6785
  • Country: pl
Re: C++ for embedded: how to learn it in 2021?
« Reply #13 on: December 13, 2021, 12:42:25 pm »
You should delete implicit constructors which you really don't want to be called under any circumstances.
Marking them private still leaves the possibility of accidental use inside a class method.

That being said, the implicit default constructor only calls the default constructors of all base classes and member objects.
It doesn't allocate memory unless one of the bases/members do.
 
The following users thanked this post: DiTBho

Offline rpiloverbd

  • Regular Contributor
  • *
  • Posts: 157
  • Country: bd
Re: C++ for embedded: how to learn it in 2021?
« Reply #14 on: December 13, 2021, 01:24:26 pm »
I think getting enrolled in an AVR microcontroller course will be helpful. I personally was benefited, worked on Atmega4809.
« Last Edit: March 29, 2022, 01:45:18 am by rpiloverbd »
 
The following users thanked this post: DiTBho

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: C++ for embedded: how to learn it in 2021?
« Reply #15 on: December 13, 2021, 02:36:08 pm »
I think getting enrolled in an AVR microcontroller course will be helpful. I personally was benefited.

Anyone specifically? Public (say, promoted by universities)? Commercial?
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online gf

  • Super Contributor
  • ***
  • Posts: 1186
  • Country: de
Re: C++ for embedded: how to learn it in 2021?
« Reply #16 on: December 13, 2021, 06:58:08 pm »
You should delete implicit constructors which you really don't want to be called under any circumstances.

And of course, if the default constructor is deleted, then the class needs at least one other constructor (different from the copy constructor) otherwise you can't create an object of the class type.

Marking them private still leaves the possibility of accidental use inside a class method.

Private was rather used with older c++ versions, where deleted constructors were not yet supported, and private was the only opportunity to hide it at least to the outside.

3. Declare all destructors as virtual, unless you really want to do otherwise.

Non-polymorphic classes don't need a virtual destructor at all (a virtual destructor rather increases the object size unnecessarily, as it implies a vtable).

A virtual destructor is basically only required for a polymorphic base class, if the polymorphic object is supposed to be deleted via a pointer to the base class.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: C++ for embedded: how to learn it in 2021?
« Reply #17 on: December 14, 2021, 12:54:54 am »
As a training exercise, you could do a lot worse than looking at a swath of Arduino code, and analyzing it to see where you think C++ mechanisms were useful, where they they were obnoxious, where they maybe SHOULD have been used, but weren't (why aren't "pins" objects?), where there are unexpected performance issues (Serial.peek() included even if never used, etc.)
(Note that this is entirely different from actually USING, much less LIKING, the Arduino code/framework/tools.  Arguably, one learns as much from their mistakes as from their good points.  (that'd be true of any C++ program, but "real" embedded C++ programs of moderate size, that are Open Source, seem to be relatively rare.)
 
The following users thanked this post: DiTBho

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
Re: C++ for embedded: how to learn it in 2021?
« Reply #18 on: December 14, 2021, 10:03:42 am »
.
« Last Edit: August 19, 2022, 04:51:40 pm by emece67 »
 
The following users thanked this post: Nominal Animal, DiTBho

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: C++ for embedded: how to learn it in 2021?
« Reply #19 on: December 14, 2021, 10:54:25 am »
"real" embedded C++ programs of moderate size, that are Open Source, seem to be relatively rare

That's why I am looking for a pay-course, or something.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
Re: C++ for embedded: how to learn it in 2021?
« Reply #20 on: December 14, 2021, 12:31:16 pm »
.
« Last Edit: August 19, 2022, 04:51:47 pm by emece67 »
 
The following users thanked this post: DiTBho

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 19522
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: C++ for embedded: how to learn it in 2021?
« Reply #21 on: December 14, 2021, 12:46:54 pm »
I do spend a lot of time programming in ErLang, C, and assembly (PowerPC and MIPS), and this for sure ads some kind of bias to my "C++ thinking".

Lucky you, and good respectively :)

Quote
Therefore, I want to forget everything, and go back as beginner for a new fresh start.

Bad idea. You want to build on your good experience, not "pollute it" with concepts that seem nice but actually aren't.

Quote
But: how to learn C++ in the correct way? In 2021? I don't need enterprise knowledge, my focus of interest is only Embedded stuff.

Learn Rust; it looks like it will become good for your career. Understand the restrictions relative to C++ and why they are there. Only then flip to C++ and choose your own subset that doesn't throw away the lessons learned and encapsulated in modern languages like Rust, Go,and xC.

Everybody else chooses their own subset of C++, so why shouldn't you! Good luck ensuring they all play nicely together.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 
The following users thanked this post: SiliconWizard, DiTBho

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: C++ for embedded: how to learn it in 2021?
« Reply #22 on: December 14, 2021, 05:32:16 pm »
Learn Rust; it looks like it will become good for your career.

Umm, I did not think about it, excellent idea  :-+

The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline AntiProtonBoy

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: au
  • I think I passed the Voight-Kampff test.
Re: C++ for embedded: how to learn it in 2021?
« Reply #23 on: December 14, 2021, 11:29:18 pm »
Here are two or three things that may come as a surprise for the beginning [embedded] C++ users:

1. The compiler is generating default constructors if not provided explicitly by the programmer.

This may not be what you want, because the default constructors created by the compiler may allocate the objects dynamically from the heap. The default constructor will be called if a programmer accidentally declares the object but doesn't specifically provide the constructor to be used. Been there, done that.

In order to prevent this, declare the default constructor for each and every class as private. This will effectively hide the default constructor, and prevent accidental invocation of the default constructor by creating a compile-time error.

2. The objects declared at global scope level, file static level, or as a static function member will be constructed before the main() is called.

This may not be what you want, and may cause confusion because the objects may be constructed in an order you did not expect.

This can be handled quite easily by creating an init()-function for each module,  and calling the modules' init()-functions from the main() in the order you want. Make these modules' init()-functions to allocate and construct the objects as required, and you are in control again.

3. Declare all destructors as virtual, unless you really want to do otherwise.

I have to respectfully disagree with some of these points. Here is why:

1. While the language standards stipulates that conceptually default constructors is called for every new object created, the C++ language also mandates that compilers should generate code with zero cost abstraction. What this means, default constructors will have no run-time cost if they don't need to do work (see code examples below). Furthermore, if you delete default constructors (as per your suggestion), then you disable your ability to create objects, which doesn't make sense at all.

Code: [Select]
// Default constructor will have no runtime cost as there is nothing to do.
struct Foo
{
int a, b, c;
};

// Compiler will generate a default constructor that initializes member variables.
struct Foo2
{
int a = 0, b = 0, c = 0;
};

// This deletes the default constructor, but then it also renders the class useless as you cant construct  it any more.
struct Foo3
{
int a, b, c;

Foo3() = delete;
};

2. Be careful with static initialisation. The order of static initialisation is undefined across different implementation files (or translation units).  See static order initialization fiasco. Also avoid using static global objects unless there is a real good reason to use one.

3. Adding virtual destructors to every object is superfluous for several reasons. First, you only need virtual destructor, if the class is participates in an inheritance hierarchy and engages in polymorphism. Second, if you add a custom destructor to your object, then you also need to implement the class constructor(s) and assignment operator(s) to conform with the rule of three/five/zero convention, which again is superfluous unless you really need to manually track internal state.

I highly recommend to reading through the C++ Core Guidelines for best practices. It's maintained by Bjarne Stroustrup and Herb Sutter. I always refer to it, to make sure I don't do anything silly in C++, because it's very easy to do.


« Last Edit: December 14, 2021, 11:32:07 pm by AntiProtonBoy »
 
The following users thanked this post: DiTBho

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 19522
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: C++ for embedded: how to learn it in 2021?
« Reply #24 on: December 15, 2021, 12:09:38 am »
I highly recommend to reading through the C++ Core Guidelines for best practices. It's maintained by Bjarne Stroustrup and Herb Sutter. I always refer to it, to make sure I don't do anything silly in C++, because it's very easy to do.

I highly recommend reading the C++ FQA; I'm partial to the section on const correctness. It is a good introduction to the difficulties you must inevitably encounter when trying to use C++.

For advanced readers, develop the arguments for and against it being (a) mandatory (b) forbidden to be able to "cast away constness". Since there are very good use cases why both are desirable, it exercised the C++ committees for about a year in the early 90s. At that point it becomes apparent that the language is becoming part of the problem, not part of the solution.

And when covid prevents you from going to work, create a valid C++ program that never finishes compiling - because the compiler spits out the sequence of prime numbers during compilation. The C++ language design committee refused to believe that was possible, until Erwin Unruh rubbed the committee's nose in it!
« Last Edit: December 15, 2021, 12:17:41 am by tggzzz »
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 
The following users thanked this post: DiTBho


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf