Project: To automate the programming of a retro computer system into which the only way of entering code is via a hex keypad.
The keypad uses the well established row/column scanning principle - on the system, the four row lines of the keypad matrix are connected to outputs which are normally high, driven momentarily low one after the other while the system watches the state of the eight column inputs, which are pulled high by 4K7 resistors. When a key is pressed it joins a row output line to a column input line. When the system takes the row line low, the column line it is connected to by the switch is also taken low.
Each time the system takes one of the row output lines low it looks at the eight column inputs to see if any of them have gone low. If one has, the combination of the row output which was driven low along with the column input which was detected low tells the system which key was pressed.
Now, there are various ways to get an external device to mimic the actions of someone pressing keypad keys. One is to connect relay outputs across all of the keyswitches and have the external device operate the relays in the correct sequence. Reasons not to do this are: Relays are expensive (there are twenty keys on the keypad), relays take up a lot of space, relays are physically slow, so limit the maximum speed that the system can be programmed at, relays take a lot of power, relays are noisy, and finally, they can not be directly driven by microprocessor / Arduino pins.
Another way (which I have already successfully done, with a PIC chip) is to build an optocoupler matrix with the optocoupler outputs connected across the keypad switches of the target system, and have the programming device operate the optocoupler LEDs in the correct sequence to programme the target system. That actually works beautifully, but wiring up the complex optocoupler matrix and connecting it to the microcontroller ports on one side and the keypad scan lines on the other side requires the patience of a saint. (I did it once, never again).
The opto method (and the relay method) have the advantage that they are fully isolated: There is no direct wired connection between the target system's keypad scan lines and the external programming device, so the programming device can be connected to / disconnected from the target system at will without any real danger of damaging the target system even while it is powered.
However, there is a dirtier, more direct method which can be used if the programming interface can be left connected all the time, and that involves watching the row scanning output lines and providing a pulldown on the appropriate column line input at the right moment. For example, suppose the '0' key on the keypad joins row output line '0' and column input line '0' when it is pressed. Imagine key '0' -is- pressed. When the system, taking each row line low in turn as it scans the keyboard, takes row line '0' low, that causes column input line '0' to be taken low for as long as row line '0' is low. The system sees this and registers this as a '0' keypress.
Therefore, to imitate this action, the programming device needs the four row lines connected to four inputs and it needs eight open-collector or open-drain outputs connected to the column input lines. Let's say the programming device knows that the next key which needs to be pressed is '0'. It watches the row output lines (which are connected to four inputs on the programming device) and waits for row output line '0' to go low, whereupon it immediately drives column input line '0' low and holds it in that state for as long as the row output line remains low, then releases it. Since this is exactly what happens when key '0' is pressed, the system thinks that key '0' has been pressed.
And now finally to my question: An Arduino could provide the necessary 8 * open-collector or drain pulldown outputs by connecting the 8 column drive output pins to the keypad column lines using a ULN transistor driver IC, but I would like to make it even simpler by making the Arduino outputs themselves behave like open collector outputs. On a PIC chip I can do this by presetting the output latches on the port to '0' and leaving them that way. Control of the output is then done by switching the mode of the port pin from input to output. When the pin is an input, the pullup resistor on the corresponding keypad column line keeps that line high. When the port pin is switched to an output it assumes the state determined by the content of the output latch (low) and drives the keypad column line low. The question is will this 'simulation' of open-collector output work as well on an Arduino Uno (ie, on Atmega 328P) as it does on a PIC chip - can the outputs sink current as well as source it and is the relationship between the port output latch and the port pin direction mode the same as I have described it to be on the PICs?