Modify digitalWrite

Hi!
I'm creating a new board using a MKR-WiFi-1010 which uses an MCP-23008 expansor to control 4 Digital Outputs using Adafruit_MCP23008 library.

In the Arduino IDE, I have the following program:

image

The idea is to modify Arduino's core digitalWrite() function in order to mask the use of the mcp object so the user only needs to write the following code:

void setup(){
pinMode(myPin, OUTPUT);
digitalWrite(myPin, HIGH);
}

So what I want to do is to modify pinMode() and digitalWrite() functions to include this new feature. New code for this funcion would do something like this:

inline void digitalWrite(pin_size_t pinNumber, int status){
if(!isExpandedPin(pinNumber)){
digitalWrite(pinNumber, (PinStatus)status);
return
}
else{
mcp.digitalWrite(pinNumber);
}

As you can see, I have a function that detects if it is an expanded pin. If it is not, it means is a normal pin from the MKR WiFi 1010 but if it is an expanded pin, then it needs to use the mcp object.

I tried to modify pinMode() and digitalWrite() functions inside cores/arduino/api/Compat.h
including Adafruit_MCP23008.h in that file and using it as I did in the Arduino IDE setup() funcion but it doesn't compile. This library has several dependencies and I included all of them.

I'm also trying to modify digitalWrite() function in the file cores/arduino/wiring_digital.c but when I include Adafruit_MCP23008.h file it doesn't recognises the class Adafruit_MCP23008. I'm not sure if it is because wiring_digital.c is a .c file and not a .cpp file.

Anyways, I'm looking for any advice on how to modify this digitalWrite() funcion and in which file I can find the correct digitalWrite() used in the Arduino IDE setup() and loop() functions.

Thank you very much.

It would be easier to extend the Adafruit_MCP-23008 class to a sub class that would redirect pins 0-n (where n-1 is the number of digital pins on the MKR) to the system digitalWrite(), and higher number pins to the expansion port. I think a cleaner solution as well.

When you create an object like that, call it gpio or something instead of mcp.

2 Likes

I would not mess with existing functions, just create new ones that will know about your specifics and call those or indeed extend the Adafruit_MCP-23008 class

2 Likes

Thank you for your answer.

I think I understand your solution but it is not what I'm trying to do.
I'm building a new package with my boards and my own core (based on samd Arduino core). Extending Adafruit_MCP-23008 class to differenciate between extended and normal pins is a good solution but it is not what I'm aiming for because this solution would imply the user to use an object of this sub-class. Then, the user must know that in order to use my board it has to create an object like this:

mySubclass myObject;
and then use it as follows:
myObject.digitalWrite(pin, status);

My idea is to hide those details from the user so he only needs to write:
digitalWrite(pin, status)

that is, the function used in all Arduino boards.

To summerize, I need digitalWrite(pin, status) to behave as I want in order to hide those details from the user.

The final user will see a name for the pin in the board and will write digitalWrite(pinName, status). He will not know anything about MCP23008 expansor and nothing about additional software requirements such as creating an object of the class MCP23008/MCP23008_subclass.

On the internet I found suggestions about making those functions weak:

__attribute __ (weak)
so they got overriden.

I also thought about changing the name for the Arduino defined functions as follows:
_digitalWrite(pin, status) (adding underscore)
and then define in a separete file written by me a function called:
digitalWrite(pin, status) (without underscore)

Would that do the trick and be a good practice?

Thank you very much for your time.

how would your custom digitalWrite function know about the Adafruit_MCP23008 configuration?

I don't think that the user has to create the object. Look how it's done in e.g. the Serial class(es): the Serial object (as an example) is simply available without it explicitely being created by the user.

1 Like

in my core I have a function that defines the default I/O modes, so the user doesn't need to do it. the function which does it is the following:

image

This function is called in cores/myCore/main.cpp
I added the funcion in the main function:

int main( void ){
custom_initDefaultIOPins();
setup();

for (;; ){
loop();
return 0;
}

So my idea is that digitalWrite() function will know about Adafruit_MCP23008 configuration because I'll use and extern object corresponding to the MCP_23008 class properly configured and with the .begin() already done. As I did in the custom function custem_InitDefaultIOPins.

thank your for your answer.
You are right. I can create the object for the user and he will be able to use it.
However, I don't want the user to use this object. With that solution, the user has to do

myObject.digitalWrite();

to control the digital outputs.

I just want the user to write digitalWrite();
and it will be the function digitalWrite() that will use this object internally, hiding those details from the user.

if you are writing a new board / Core, you can probably provide wiring_analog.c and wiring_digital.c matching your needs I would suppose (never done it)

1 Like

...but I think they should know that.

1 Like

Yes. You can't use C++ objects in a C (.c) source file. You could probably rename 'wiring_digital.c' to 'wiring_digital.cpp' but then you will have to remove the functions from the 'extern "C"' block in Arduino.h

2 Likes