You will need to write directly to the registers.
Teensyduino defines names CORE_PINx_CONFIG, where "x" is the pin number, which makes it a little simpler.
For example, if you want to put pin 5 into open drain mode, you'd use:
Code:
CORE_PIN5_CONFIG = PORT_PCR_ODE | PORT_PCR_MUX(1);
I haven't personally tested this mode, but my belief is digitalWrite() ought to work once it's in this mode, but writing HIGH will make the pin disconnected instead of driven high.
Some more research would be in order here, but I did a cursory test, and it appears to me that digitalWrite() messes with some of the port control bits. Maybe it works ok for I2C (I didn't try that), but for generic IO ports (pin 16 in my case), there is most definitely some fishy behavior.
From the K20P64M72SF1RM spec, it looks like the open drain (ODE) bit and pull enable (PE) functions are supposed to be independent, but my testing casts some doubt on this assumption.
My test circuit consisted of using an LED to see where current is flowing, and this code:
Code:
void setup()
{
digitalWrite(16, HIGH); //since the signal is active LOW, pre-set the pin to HIGH (inactive)
CORE_PIN16_CONFIG = PORT_PCR_ODE | PORT_PCR_MUX(1); //turn on the Open Drain feature
pinMode(16, OUTPUT); //and make the pin an output
}
void loop()
{
delay(5000);
digitalWrite(16, LOW); //assert
delay(500);
digitalWrite(16, HIGH); //de-assert
}
First part of the test: connected pin 16 -->LED-->resistor-->Vin. This is typically how you'd hook up an LED when you have an active LOW signal. In this configuration, I expected to see the following behavior:
* When Port 16 is HIGH (not asserted) = LED off
* When Port 16 is LOW (asserted) = LED on
And indeed, this is exactly what I saw. The LED was off for 5 seconds, and blinked on for 0.5 seconds, and repeated.
However, that does not tell us whether the HIGH state is connected to Vin or just floats (disconnected). To determine that, I switched the polarity of the LED as follows: connected pin 16-->LED-->resistor-->GND. In this configuration I would expect to see the LED stay OFF all the time. Here is the behavior I observed in this configuration:
* When the sketch started, PORT 16 started out HIGH (not asserted), and as expected, the LED was OFF for 5 seconds.
* When the port went LOW (asserted) after 5 seconds, the LED remained OFF, as expected.
* When the port returned to HIGH (not asserted), however, the LED came ON (NOT EXPECTED BEHAVIOR!)
This means there is some kind of leakage going on when the port is in the HIGH state. This can be very bad in some circuits (parts can be destroyed). Some kind of pull-up became enabled when the digitalWrite() function was called.
To try and "fix" the problem, I inserted another instruction to re-enable the Open Drain feature as soon as the port was set back to HIGH, as follows:
Code:
void setup()
{
digitalWrite(16, HIGH); //since the signal is active LOW, pre-set the pin to HIGH (inactive)
CORE_PIN16_CONFIG = PORT_PCR_ODE | PORT_PCR_MUX(1); //turn on the Open Drain feature
pinMode(16, OUTPUT); //and make the pin an output
}
void loop()
{
delay(5000);
digitalWrite(16, LOW); //assert
delay(500);
digitalWrite(16, HIGH); //de-assert
CORE_PIN16_CONFIG = PORT_PCR_ODE | PORT_PCR_MUX(1); //turn on the Open Drain feature AGAIN
}
In this configuration, the LED behaved as expected, and never lit. Therefore, I conclude that digitalWrite() must destroy the ODE setting. This software fix, however, is not ideal, because there is a small but finite amount of time between the digitalWrite(16, HIGH) and re-enabling ODE where a voltage differential is present between the pin and GND.
So the takeaway here is be very careful when configuring the IO ports using the CORE_PINx_CONFIG, because your setting will probably get blown away as soon as you call digitalWrite().