One digitalWrite command for processor AND MCP23017

I have a project which uses an MCP23017 for extra ports. Some of those ports are for things like the CS line for an SD card. As such, the driver for the SD card would need to use the digitalWrite of the MCP driver. And this is the case for many drivers in my project. I want to come up with an alias of digitalWrite which handles both the MCP ports and the processor port. My idea is to "index" the MCP pin numbers by adding 100 to their values, so MCP pin 4 would be pin 104, for example. Then I can pick between digitalWrite or mcp.digitalWrite base on the pin numbers being above or below 100. The problem is that me solution introduces a circular reference to myDigitalWrite. Any better ideas on how to do this?

#define digitalWrite(a,b) myDigitalWrite(a,b)

void myDigitalWrite(uint8_t pin, uint8_t value)
{
    if(pin <= 100)  // digitalWrite from processor
    {
        digitalWrite(pin, value);  // circular reference... becomes myDigitalWrite
    }
    else    // digitalWrite from MCP23017
    {
        pin = pin - 100;
        mcp.digitalWrite(pin, value);  // circular reference... becomes mcp.myDigitalWrite
    }
}

I think this can't be resolved without of editing the sourcecode of the SD driver

I agree with @b707. Your idea will not work. You may have to use a real Arduino pin for the CS pin of the SD card and move some other function, like a button or led, to the MCP chip.

you could write an wrapper which can handle either a discrete pin on the Arduino or on a MCP (or any other port expander).
Additionally you would need to modify the SD card library not to use plain digitalWrite, but your wrapper.

or you modify the digitalWrite of your arduino core

but for simplicity: i would just use a discrete Arduino pin if needed in another library...

You have much bigger issues.

While there is a way to avoid eliminating a circular reference.
You can do that by putting all the code of "myDigitalWrite()" inside the digitalWrite() macro.
i.e. make a function like macro definition called digitalWrite()
cpp does not re-expand a macro by the same name inside a macro definition.
This is a very intentional and useful feature of cpp.
i.e. a reference to digitalWrite() inside a macro called digitalWrite() will be left alone and will not attempt do circular expansion.

However, the issue is that as @b707 pointed out you would need to have this macro definition inside the SD library code in order to be used by the SD library code.
This requires modifying the SD library code.

That is were the issues begin.
The SD library plays some games to get very fast pin control.
To do this, it does raw port i/o bypassing the slow Arduino.cc AVR core library digital i.o. functions like digitalWrite()
They implement a function called fastDigitalWrite() inside the Sd2Card.cpp file that does raw port i/o by using its own mapping tables.
While doing this allows for fast pin control, it is has potential issues.
Issues like it assumes the pin mappings for boards and is difficult to any sort of modification like you are wanting to do.

Assuming you could modify the SD code to use your macro, you would need be prepared that the code potentially could potentially (and likely will) run significantly slower.

My suggestion is see if you can come with some other solution that doesn't need to alter or mess with the pins used by the SD code.

--- bill

Thanks. Interesting. The only SD pin involved in my situation is the chip select. That should not be getting turned on and off during a read or write so it should not really matter. But I will read the SD code and see.

The code has to send low level SPI commands to the device.
Each time a low level command is sent to the device, chip select is controlled.
Remember that there will be many SPI commands going across SPI to perform a simple file system read.

If you want to play at this level, I'd suggest that you go study the actual code in the SD library.
The low level stuff is in Sd2Card.cpp

--- bill

Thanks. I grew up coding "low-level".

One other thing to keep in mind is that the best performance on the AVR will be to use h/w SPI.
And when using h/w spi you have to use the h/w SPI pins.
If you muck around with the h/w SPI SS pin (slave select), like use it for some other purpose, then it affects spi transfers. So you can't really use the h/w SPI SS pin as a general i/o pin if you want to use h/w SPI.

See the AVR documentation for further details on this.

--- bill