Can you query the input/output setting of a pin?

OR do you have to keep track of it yourself? I'm guess keep track yourself. It would probably be faster anyways.

Wait, is it even OK to change from input to output while the program is running? I haven't checked. Should be OK right? Just make sure nothing is hooked up that would break something...

You can switch between an input and output at any time. Just keep in mind (especially important when going from IN -> OUT) that whatever the last state of the Pin was read, it will get set to.

For example: if you read an INPUT pin and it was HIGH, when you switch it to an OUTPUT it will be in the HIGH state.

CMiYC is right - you can set the pinMode() anytime. There's no magic difference between "during setup" and "while looping" periods in your program's lifetime.

You can query the input/output mode of a pin at any time also, but there is no super-handy function like pinMode() to do it. You have to use direct port manipulation.

The Atmel processor has three sets of port registers, and each set has a "port direction" register, a "port out" register, and a "port in" register. The pinMode() function changes one bit in the appropriate port direction register, and you can also read those registers. DDRB, DDRC, DDRD are the three port direction registers. Each bit in each of those registers refers to a specific i/o pin.

If that didn't scare you off, the internal Wiring file called pins_arduino.c file defines a ton of constants that describe every bit in every direct port register. The pinMode() function uses some lookup table logic to convert pin numbers into registers and bits.

Just keep track of it yourself. You can query the mode of a pin. But you're going to need to perform some bitwise operations. Arduino Reference - Arduino Reference

You'd be interested in the data direction register which would be DDR_

I'd recommend an array of bools. An example of implementation would be as follows:

bool isInput[19] = {true}; //creates an array of 20 bools and sets each value to true. The pins default to inputs on startup.

void setPinMode_Input(int pin, bool mode) //will set pin as input if mode is true, or as output if mode is false
{
      if(mode)
      {
            pinMode(pin, INPUT);
            isInput[pin] = true;
      }
      else
      {
            pinMode(pin, OUTPUT);
            isInput[pin] = false;
      }
}

So as you can see, now you no longer have a need for the pinMode function, instead use the new modified setPinMode_Input function to set the modes of the pins. Everytime you do, it will update the array accordingly.

Anytime you would like to query the mode of a pin, simply check its corresponding entry in the array. If the value in the array is true, then the pin is an input. For example

if(isInput[5] == true) //if pin 5 is an input
      //do something

[edit]Halley beat me to it[/edit]

FusiveResonance, your implementation of a set of tracking booleans is a good way to go. Except this won't work quite right, so pardon me for commenting:

bool isInput[19] = {true}; //creates an array of 20 bools and sets each value to true. The pins default to inputs on startup.

That's an array of nineteen elements (indexes 0 to 18). Also, I think it would set the first element true and leave the rest false, as well as issue a warning for mismatched initializers. Lastly, it takes extra RAM and PROGMEM to define those initializers, so an isOutput array that is not initialized will default to all-false without chewing up space. You can also do pinMode(pin, wantsOutput) and isOutput[pin] = wantsOutput directly, rather than if/else.

All good comments halley. I'll leave it upto the OP to rewrite my code:

Also, I think it would set the first element true and leave the rest false,

See this http://www.fredosaurus.com/notes-cpp/arrayptr/array-initialization.html Thats a standard method of initializing all elements in an array.

You can also do pinMode(pin, wantsOutput) and isOutput[pin] = wantsOutput directly, rather than if/else.

Good stuff. I was wondering about how INPUT and OUTPUT have been macro defined; whether 1 and 0 or vice versa. Sure enough, I couldn't find it in the documentation.

I said:

Also, I think it would set the first element true and leave the rest false,

Your website says:

If an explicit array size is specified, but an shorter initiliazation list is specified, the unspecified elements are set to zero.

So we're in agreement.

I always thought all variables get's initialized to the same value as the one given.

From site:

float p2[1000] = {0.0}; // All 1000 values initialized to zero.

This is easy to test.

void setup(){
  Serial.begin(9600);
  byte array[10] = {4};

  for(byte i=0; i<10; i++){ Serial.println(array[i],DEC); }
}

void loop(){
}

I do not have an Arduino close by, maybe someone could check? :slight_smile:

Global variables with no initializers are guaranteed to be initialized to zero. Local stack variables with no initializers are not guaranteed to be initialized to zero. If given a partial initializer, the unspecified elements are guaranteed to be initialized to zero. (They are not initialized to any repeated copy pattern from the specified elements.)

#include <stdio.h>

int global[10] = {4};

int main()
{
  int local[10] = {4};
  long another;
  int i;
  printf("global\tlocal\n");
  for (i = 0; i < 5; i++)
    printf("%d\t%d\n", global[i], local[i]);
  printf("another: %ld\n", another);
  return 0;
}
init.exe
global  local
4       4
0       0
0       0
0       0
0       0
another: 4206148

a better test would be to see what you get with

float p2[1000] = {0.1}; // All 1000 values initialized to non-zero.

It would be, except that sizeof(float x[1000]) == 4096 bytes, or twice the available RAM of an Atmel ATmega328.

If you just want to query the current INPUT/OUTPUT state of the pin, per the OP, you can use this function:

#include <pins_arduino.h>

int readPinMode(uint8_t pin)
{
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);

  if (port == NOT_A_PIN) return OUTPUT; // bad pin!

  volatile uint8_t *reg = portModeRegister(port);

  return (*reg & bit) ? OUTPUT : INPUT
}

Mikal

Thanks for clearing that up halley. I understand now.