PerryBebbington:
Thanks for the explanation.
Is this reliable:
If (digitalRead(somePin)) ...
I would expect that to be true if the pin is high. What you have said casts doubt on that.
You have assumed that digitalRead() is required to return a non zero value when a pin is high.
Even if you looked at the code for a specific platform to see that it does, the API documentation makes no such guarantee so a platform implementer does not have to implement it this way.
As such, code that makes that assumption is not guaranteed to be portable across all implementations.
It will likely work, but it isn't guaranteed to work, since is not conforming to the documentation which simply says that digitalRead() returns HIGH or LOW and is silent on anything else such as the type or value of those symbols.
The proper way to ensure full portability be:
If (digitalRead(somePin) == HIGH) ...
It can be even more tricky for digitalWrite()
Suppose you pass in a non zero value to digitalWrite() but it is not the specific value of HIGH.
Depending on how the code is implemented, it may or may not work as you intended to set the pin high.
For example, suppose you have some code that uses bits in a lookup table to set the state of a pin where 1 bits set the pin high and zero bits set the pin low.
To "optimize" the code, you simply mask the value from the bit table down to the desired bit and pass that masked value as the value parameter to digitalWrite()
digitalWrite() will receive a zero when the bit is not set, and some power of 2 value when a bit is set.
If the digitalWrite() code is implemented like this:
if (val == LOW)
// set pin low
else
// set pin high
it will work.
If it happens to be implemented like this:
if (val == HIGH)
// set pin low
else
// set pin high
If HIGH does not match the value of your non-zero value, you will get a low pin for all non-zero values other than the one that matches HIGH.
This "mess" was created by some sloppiness from the arduino.cc team in their APIs and API semantics.
From the very earliest days, they were not very good at defining the APIs and corresponding documentation.
Most peoples assumption is that the digital i/o functions like digitalRead() and digitalWrite() operate based on zero vs non-zero values and that HIGH and LOW are simply convenience symbols and so lots and lots of code as been written with that assumption (which according to the documentation is not guaranteed to be correct)
This all came to a head with the megaavr platform which decided to take advantage of creating types for the HIGH and LOW symbols for type checking of the parameter. While it is allowed, I'm not sure that the type checking is worth it at this point given all the existing code that was improperly written that breaks when this is done.
In fact in the megaavr platform they ended up creating some compatibility function overloads that will allow existing code that abused the API to continue to work.
So at this point, having HIGH and LOW as enums is pretty much pointless.
Given the incorrect assumptions that so many people have made and written code around those assumptions over the years, my recommendation would be just give up and re-document digitalRead() and digitalWrite() to work the way people have assumed they work. i.e. zero means low and non-zero means high.
This would not break any existing code and would ensure that all platforms implement it consistently, which is not assured at this point.
But as of today, the only way to ensure portability is to not assume anything about the symbols HIGH and LOW.
i.e. write code that never takes short cuts and always compares against those values or always passes in one of those values.
--- bill