The SAMD21 has two 32-bit ports, A and B. The SAMD21G variant used on the Arduino Zero uses most pins of port A, but only a few of port B. In the following examples a 0 suffix after the register's name defines the register for port A, while a 1 defines the register for port B.
The SAMD21 equivalent of AVR's PINx is the IN register. To check if a given pin, say digital pin 12 is high:
if (REG_PORT_IN0 & PORT_PA19) // if (digitalRead(12) == HIGH)
Alternatively to check if it's low:
if (!(REG_PORT_IN0 | ~PORT_PA19)) // if (digitalRead(12) == LOW)
For digital output it's possible to use the SAMD21's OUT register. This requires the register to be masked, just like the AVR's PORTx. Here's an example of the blink sketch using the OUT register:
void setup() {
// put your setup code here, to run once:
REG_PORT_DIRSET0 = PORT_PA17; // Set the direction of the port pin PA17 to an output
}
void loop() {
// put your main code here, to run repeatedly:
REG_PORT_OUT0 |= PORT_PA17; // Switch the output to 1 or HIGH
delay(1000);
REG_PORT_OUT0 &= ~PORT_PA17; // Switch the output to 0 or LOW
delay(1000);
}
However, the SAMD21 can save you overhead of having to read-modify-write to the register, by instead masking it in hardware using OUTSET and OUTCLR. Here's an example of the blink sketch using these registers:
void setup() {
// put your setup code here, to run once:
REG_PORT_DIRSET0 = PORT_PA17; // Set the direction of the port pin PA17 to an output
}
void loop() {
// put your main code here, to run repeatedly:
REG_PORT_OUTSET0 = PORT_PA17; // Switch the output to 1 or HIGH
delay(1000);
REG_PORT_OUTCLR0 = PORT_PA17; // Switch the output to 0 or LOW
delay(1000);
}
Alternatively, there's the toggle register. Here's an example of the blink sketch using the OUTTGL register:
void setup() {
// put your setup code here, to run once:
REG_PORT_DIRSET0 = PORT_PA17; // Set the direction of the port pin PA17 to an output
}
void loop() {
// put your main code here, to run repeatedly:
REG_PORT_OUTTGL0 = PORT_PA17; // Toggle the output HIGH and LOW
delay(1000);
}
The register definitions are a number of Atmel files (on my Windows machine) currently located at: C:\User\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL\SAMD21\include...
If you're using port register manipulation there are two directories named "component" and "instance". The "port.h" file in the "component" directory defines the structure of each register. Using this file you can use the format:
PORT->Group[PORTA].DIRSET.reg = PORT_PA17;
The "port.h" file in the "instance" directory gives the definitions that define the registers' absolute locations, this gives an alternative, but equivalent format used in the examples above:
REG_PORT_DIRSET0 = PORT_PA17;