Directly check pin for HIGH or LOW

Hey everybody,

I am only used to program ATmega uC's so I'm new to direct port access on the arduion due. I did some research but I couldn't quiet find an example for checking a digital I/O Pin for HIGH or LOW. I want to check pin 51 on the due for HIGHs and LOWs. The ATmega equivalent would be e. g. if(PINA&(1<<PINA51)) or if(~PINA&(1<<PINA51)).
I'm guessing something like if(PIO_PDSR&(1<<P0)) from page 645 in the SAM3X8E datasheet.

I hope someone can help me, thanks!

Jannik

Since pin 51 is PC12 (See Graynomad pinout diagram), you'll have to read PIOC->PIO_PDSR bit 12. Beforehand, you have to power PIOC so that you can read input state on any PIOC pin.

An example sketch:

void setup() {
  PMC->PMC_PCER0 |= PMC_PCER0_PID13;  // PIOC power ON to read PIOC input level
}

void loop() {

  while (PIOC->PIO_PDSR & PIO_PDSR_P12) {  // As long as pin 51 (PC12) is High
   //Do something
  }

}

Not quite. The input registers only have 8 bits. On the Arduino MEGA 2650, for example, the look-up table to translate Arduino pin numbers to Port and Bit are found in "hardware/arduino/avr/variants/mega/pins_arduino.h"

In the table it says that Pin 51 is Bit 2 of Port B so the code to read it would be more like:

if(PINB&(1<<PB2)) or if(~PINB&(1<<PB2))

Hey everybody,

I am only used to program ATmega uC’s so I’m new to direct port access on the arduion due. I did some research but I couldn’t quiet find an example for checking a digital I/O Pin for HIGH or LOW. I want to check pin 51 on the due for HIGHs and LOWs. The ATmega equivalent would be e. g. if(PINA&(1<<PINA51)) or if(~PINA&(1<<PINA51)).
I’m guessing something like if(PIO_PDSR&(1<<P0)) from page 645 in the SAM3X8E datasheet.

I hope someone can help me, thanks!

Jannik

just connect LED with 300 ohm resistor in series to your pin and run blink program

How does that help?

inline void digitalWriteDirect(int pin, boolean val)
{
  if (val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}
// example: digitalReadDirect(12)
inline int digitalReadDirect(int pin)
{
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

First you have to determine the translation of Pin 51. The pin mapping is in hardware/sam/1.6.12/varients/arduino_due_x/variant.cpp

  { PIOC, PIO_PC12,          ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL,                  NO_ADC, NO_ADC, NOT_ON_PWM,  NOT_ON_TIMER }, // PIN 51

Then all you have to do is figure out how to read a pin with the information provided. digitalRead() punts on that question, calling the function PIO_Get().

The meanings of the fields in the pin descriptor might be helpful. You can find that struct defined in Arduino.h:

/* Types used for the tables below */
typedef struct _PinDescription
{
  Pio* pPort ;
  uint32_t ulPin ;
  uint32_t ulPeripheralId ;
  EPioType ulPinType ;
  uint32_t ulPinConfiguration ;
  uint32_t ulPinAttribute ;
  EAnalogChannel ulAnalogChannel ; /* Analog pin in the Arduino context (label on the board) */
  EAnalogChannel ulADCChannelNumber ; /* ADC Channel number in the SAM device */
  EPWMChannel ulPWMChannel ;
  ETCChannel ulTCChannel ;
} PinDescription ;

@jannik_b, do not cross-post. Threads merged.

Surely, the arduino Core has already powered PIOC?
There was a complication with direct WRITE because the chip "protects" the full register, and the core had not set PIO_OWER (Output Write Enable Register) to permit writes: portOutputRegister and portInputRegister are useless
(This was corrected a long time ago: portOutputRegister is now writeable. · arduino/ArduinoCore-sam@f4a5479 · GitHub )

Thanks for the tip, I found some interesting threads by searching for digitalReadDirect!
But I'm not quiet sure how to use this, do I put the inline code into the setup() or do I need to include a library?
I also need it only for one pin, so to safe some time can I write like :
bool myState = !!(g_APinDescription[12].pPort -> PIO_PDSR & g_APinDescription[12].ulPin); because Pin51 = PC12 and then I check the pin like: if(myState==true)?

I think PIO_Get() is a bit overkill for my application. I only want to know if the pin is high or low but really fast.

The 'g_APinDescription' table is indexed by ARDUINO pin number so for Arduino Pin 51 you would use 51, not 12:
bool myState = !!(g_APinDescription[51].pPort->PIO_PDSR & g_APinDescription[51].ulPin);
And I already gave you the contents of that table entry (above) so you can avoid the two look-ups:
bool myState = !!(PIOC->PIO_PDSR & PIO_PC12);

Post # 5
Simple, HIGH or LOW = LED on LED off

Post # 14