digitalReadFast() not working on Mega [Solved]

The following short program works fine on an Uno but not on a genuine Mega. It will work on the Mega if I use digitalRead() in place of digitalReadFast()

It seems to me strange that digitalWriteFast() works when digitalReadFast() does not.

I wonder if anyone has experienced this or knows of a solution.

I got the digitalWriteFast library here

// python-build-start
// action, upload
// board, arduino:avr:uno
// port, /dev/ttyACM0
// ide, 1.8.6
// python-build-end

// ide, 1.6.3
// ide, 1.5.6-r2

// arduino:avr:uno
// arduino:avr:mega:cpu=atmega2560

#include "./digitalWriteFast.h"

const byte outPin = 7;
const byte inPin = 8;

byte selectVal;

void setup() {
 pinMode(outPin, OUTPUT);
 pinMode(inPin, INPUT_PULLUP);
 digitalWriteFast(outPin, HIGH);
 delay(2000);
}


void loop() {
 selectVal = digitalReadFast(inPin);
 //~ selectVal = digitalRead(inPin);
 if (selectVal == HIGH) {
 digitalWriteFast(outPin, LOW);
 }
 else {
 digitalWriteFast(outPin, HIGH);
 }

}

Thanks for reading.

...R

I don't see any mistakes in the digitalWriteFast library that might cause digitalReadFast to fail on Arduino MEGA.

if (selectVal == HIGH) {

Comparing against HIGH is dangerous, since for quite some time and some people, digitalRead() returns a “boolean” value, where 0 means LOW and anything else is fair game for HIGH.
In fact, the library you reference has:

# define BIT_READ(value, bit) ((value) & (1UL << (bit)))

and

#define __digitalReadFast(P ) \
   :
( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) )
   :

So it will return (1<<bit) rather than HIGH, for set bits.
(it is only a coincidence that this works on Uno, because pin8 is PB0)

That should probably be considered a bug.

Probably good, but not really correct, fix:

# define BIT_READ(value, bit) (!!((value) & (1UL << (bit))))

In some relatively unrelated experiments, I’ve seen that the compiler will optimize away the !! when it can,
so if (digitalReadFast(8)) { // blah } still compiles to an SBIS instruction or equiv…

westfw: Comparing against HIGH is dangerous, since for quite some time and some people, digitalRead() returns a "boolean" value, where 0 means LOW and anything else is fair game for HIGH.

I'm not sure I understand what you had in mind as the alternative as you say that 0 is LOW and anything else is HIGH.

The code seems to work properly if I change

if (selectVal == HIGH) {

to

if (selectVal != 0) {

Also I added a line to print the value of selectVal and tried it on a few different I/O pins. For some it was 32 and for another it was 4.

AFAIK digitalRead() returns a 0 or 1 and I had assumed that digitalWriteFast() would be the same.

Thanks for your insight.

...R

Another option would be declaring 'selectVal' as 'bool' instead of 'byte'.

Yet another option is to treat 'selectVal' as a bool:

if (selectVal) {

Yet another option is to treat 'selectVal' as a bool:

if (selectVal) {

That would be my preferred style as well. Note that digitalRead() is supposed to return a "PinStatus" enum these days, which is distinctly NOT a boolean. Which is unfortunate, IMO. :-(

The correct patch is probably like:

#define __digitalReadFast(P ) \
   :
( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH : LOW )

No "issues" capability on those repositories. :-( We'll see how this goes: https://github.com/watterott/Arduino-Libs/pull/9

johnwasser: Another option would be declaring 'selectVal' as 'bool' instead of 'byte'.

I have not had time to do more tests until now.

And, yes, declaring selectVal as bool works.

In fact the original manifestation of the problem was with code like this

if (digitalReadFast(inPin) == HIGH) {

which works fine with the regular digitalRead()

And a small modification like this

if ((bool) digitalReadFast(inPin) == HIGH) {

also solves the problem.

The fact remains that digitalReadFast() does not behave the same as digitalRead().

I appreciate the efforts of people to get the library updated. I don't plan to make any changes to my own copy of the library simply so that if I recommend it to others they will be using the same code as I am.

...R

(The pull request has been merged. Nice quick work by Andreas Watterott...)

westfw: (The pull request has been merged. Nice quick work by Andreas Watterott...)

What are the implications of that?

...R

Robin2:
What are the implications of that?

Next time you install the library it will return LOW or HIGH instead of the pin mask.

johnwasser:
Next time you install the library it will return LOW or HIGH instead of the pin mask.

Thanks. I will download it again and try it. That was quick.

…R

I have now downloaded the latest version of the library and it works "properly"

Many thanks to @westfw for taking the trouble to propose the update.

...R