detect pin mode possible?

Hi all,
Is there a way to "detect" the mode of a pin?
Thanks!

Yes. Why do you want to? This was asked recently.

Thank you. And sorry to open a new thread, I actually did some googling before posting but probably the search criteria was poorly chosen.

I want it for the same reason with that guy that asked that question on the other thread. I am building an API to remotely control the Arduino over http as a project for my school, and it has to be generic.

So I want to know if there’s anyway to read the current pin mode for a given pin.

I know that I can initialize all pins to some specific mode in my setup(), then keep in an array all calls to pinMode() but I was more curious to know if that was possible.

For example, what if I don’t want to initialize the pins to some arbitrary state at setup? What if I want to just leave them as they happened to be at a given moment.

For example, what if I don't want to initialize the pins to some arbitrary state at setup?

Pins are always set to some mode. They default to INPUT unless YOU define otherwise.

What if I want to just leave them as they happened to be at a given moment.

Then, don't do anything. They still have a known state when setup() gets called.

I think it is simpler that I initially thought, it was a good idea to look at arduino/wiring_digital.c where I found the definition of pinMode():

void pinMode(uint8_t pin, uint8_t mode)
{
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	volatile uint8_t *reg, *out;

	if (port == NOT_A_PIN) return;

	// JWS: can I let the optimizer do this?
	reg = portModeRegister(port);
	out = portOutputRegister(port);

	if (mode == INPUT) { 
		uint8_t oldSREG = SREG;
                cli();
		*reg &= ~bit;
		*out &= ~bit;
		SREG = oldSREG;
	} else if (mode == INPUT_PULLUP) {
		uint8_t oldSREG = SREG;
                cli();
		*reg &= ~bit;
		*out |= bit;
		SREG = oldSREG;
	} else {
		uint8_t oldSREG = SREG;
                cli();
		*reg |= bit;
		SREG = oldSREG;
	}
}

that was easily reversed to a "getter":

uint8_t getPinMode(uint8_t pin)
{
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *reg = portModeRegister(port);

  if (*reg & bit) {
    return OUTPUT;
  } else {
    volatile uint8_t *out = portOutputRegister(port);
    if (*out & bit) {
      return INPUT_PULLUP;
    } else {
      return INPUT;
    }
  }
}

this compiles but I can't test it now. I'm still not sure about the "oldSREG = SREG" trick and the CLI that are used in pinMode()

afasias:
this compiles but I can’t test it now. I’m still not sure about the “oldSREG = SREG” trick and the CLI that are used in pinMode()

cli() disables interrupts, and SREG = oldSREG restores them to the state they were at when oldSREG was saved.

The general rule is that you’ll want to save the status register (SREG) somewhere in your function (doesn’t matter where) before cli(). You’ll want to call cli() right before you do any manipulation of ports (eg reg and out). Then right after you finish manipulating the ports you want to restore the status register.

However, I think reading them without disabling interrupts is okay because they’re 1 byte and therefore atomic. Get a second opinion, though.

WizenedEE:

afasias:
this compiles but I can't test it now. I'm still not sure about the "oldSREG = SREG" trick and the CLI that are used in pinMode()

cli() disables interrupts, and SREG = oldSREG restores them to the state they were at when oldSREG was saved.

The general rule is that you'll want to save the status register (SREG) somewhere in your function (doesn't matter where) before cli(). You'll want to call cli() right before you do any manipulation of ports (eg reg and out). Then right after you finish manipulating the ports you want to restore the status register.

However, I think reading them without disabling interrupts is okay because they're 1 byte and therefore atomic. Get a second opinion, though.

I also think that a single byte read is atomic by nature on a 8 bit AVR chip.

Now if you do ever have the need to 'protect code' requiring atomic protection that arduino has the needed functions already defined for you that will handle saving and restoring the SREG register:

void loop()
{
  noInterrupts();
  // critical, time-sensitive code here
  interrupts();
  // other code here
}

retrolefty:
Now if you do ever have the need to 'protect code' requiring atomic protection that arduino has the needed functions already defined for you that will handle saving and restoring the SREG register:

Er, not really. interrupts() just enables interrupts, it doesn't restore the SREG. They're also just #defined as sei() and cli() and I don't see a reason to further obfuscate code by giving it other names.

However, there does exist code that will properly restore the SREG:

ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  // time sensitive code or reading variables shared by interrupt
}
// normal code

http://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html