diff --git a/gpio/atsamd51/index.html b/gpio/atsamd51/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..a86988becf05915e16230d5285d6e76c4c48d4a0
--- /dev/null
+++ b/gpio/atsamd51/index.html
@@ -0,0 +1,89 @@
+<html>
+<head>
+<style>
+pre code {
+  background-color: #eee;
+  border: 1px solid #999;
+  display: block;
+  padding: 20px;
+}
+</style>
+
+
+</head>
+<body>
+
+<h1>ATSAMD51</h1>
+
+<figure>
+<img src='ring.jpg' height=50%>
+<figcaption>Ring oscillator with ATSAMD51J19</figcaption>
+</figure>
+
+<p>This ring oscillator runs on the ATSAMD51J19 MCU using the Adafruit Feather dev board.  The ATSAMD51J19 has an ARM Cortex-M4 running with a max speed of 120 MHz.  Code for the oscillator is available <a href='ring.ino'>here</a>, or visible below.</p>
+
+<pre>
+<code>
+#define portin PORT->Group[PORTA].IN.reg
+#define outclr PORT->Group[PORTA].OUTCLR.reg
+#define outset PORT->Group[PORTA].OUTSET.reg
+#define out PORT->Group[PORTA].OUT.reg
+#define outtgl PORT->Group[PORTA].OUTTGL.reg
+
+
+const uint8_t in_pin = 21;
+const uint32_t in_mask = 1ul&lt&ltin_pin;
+const uint8_t out_pin = 22;
+const uint32_t out_mask = 1ul&lt&ltout_pin;
+
+void setup() {
+  
+  // Set pin mode according to chapter '32.6.3 I/O Pin Configuration'
+  // enable input, to support reading back values, with pullups disabled
+  PORT->Group[PORTA].PINCFG[out_pin].reg = (uint8_t)(PORT_PINCFG_INEN) ;
+  // Set pin to output mode  
+  PORT->Group[PORTA].DIRSET.reg = out_mask;
+  // Set in pin to input mode
+  PORT->Group[PORTA].PINCFG[in_pin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
+  PORT->Group[PORTA].DIRCLR.reg = in_pin ;
+  
+  //make sure port synchronizer always active, else we'll use extra clock cycles.
+  //I'm not sure I'm activating the synchronizer correctly, because I don't see a change when I add this... 
+  PORT->Group[PORTA].CTRL.reg = in_mask; 
+
+  //loop
+  while(1){    
+    //ternary operator: assymetric 300ns (200-100)
+    //portin & in_mask ? outclr = out_mask : outset = out_mask;
+    //portin & in_mask ? outclr = out_mask : out = out_mask;
+    
+    //full port inversion: symmetric 300ns
+    out = ~(portin);
+
+    //bitwise xor: 300ns
+    //out = ((portin ^ in_mask) << 1);
+
+    //if else, 300ns
+    /*if (portin & in_mask){
+      outclr = out_mask;
+    } else {
+      outset = out_mask;
+    }*/
+  }
+}
+ 
+void loop() {}
+</code>
+</pre>
+
+<p>By default the port consumes extra clock cycles to save power and only sample the input pin when a read is requested (see description below).  We can set the input synchronizer to always be active to avoid this delay.  I've tried to do this above, but I need to confirm if this was successful.</p>
+
+<img src='port-diagram.png' height=200px>
+<img src='input-synchronization.png' height=200px>
+
+
+<p><a href='../../index.html'>Back</a></p>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/gpio/atsamd51/input-synchronization.png b/gpio/atsamd51/input-synchronization.png
new file mode 100644
index 0000000000000000000000000000000000000000..b97ebca00303cc3b77dadea50d69a815dece8d7a
Binary files /dev/null and b/gpio/atsamd51/input-synchronization.png differ
diff --git a/gpio/atsamd51/port-diagram.png b/gpio/atsamd51/port-diagram.png
new file mode 100644
index 0000000000000000000000000000000000000000..d0b534c15bb52229df521044544d4d129f9301ed
Binary files /dev/null and b/gpio/atsamd51/port-diagram.png differ
diff --git a/gpio/atsamd51/ring.ino b/gpio/atsamd51/ring.ino
new file mode 100644
index 0000000000000000000000000000000000000000..a057eef4f3837b4d790c7bedb072c6571d7bda75
--- /dev/null
+++ b/gpio/atsamd51/ring.ino
@@ -0,0 +1,68 @@
+#define portin PORT->Group[PORTA].IN.reg
+#define outclr PORT->Group[PORTA].OUTCLR.reg
+#define outset PORT->Group[PORTA].OUTSET.reg
+#define out PORT->Group[PORTA].OUT.reg
+#define outtgl PORT->Group[PORTA].OUTTGL.reg
+
+//11:     { PORTA, 21, PIO_TCC_PDEC, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 },
+const uint8_t in_pin = 21;
+const uint32_t in_mask = 1ul<<in_pin;
+//12:     { PORTA, 22, PIO_TCC_PDEC, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH2, TCC0_CH2, EXTERNAL_INT_6 },
+const uint8_t out_pin = 22;
+const uint32_t out_mask = 1ul<<out_pin;
+//led:{ PORTA, 23, PIO_TCC_PDEC, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_7 }, // TCC2/WO[1]
+//const uint32_t out_mask = 1ul<<23;
+
+void setup() {
+  //set clock port for digital io
+  //PM->APBBMASK.reg |= PM_APBBMASK_PORT ;
+
+  
+  // Set pin mode according to chapter '32.6.3 I/O Pin Configuration'
+  // enable input, to support reading back values, with pullups disabled
+  PORT->Group[PORTA].PINCFG[out_pin].reg = (uint8_t)(PORT_PINCFG_INEN) ;
+  // Set pin to output mode  
+  PORT->Group[PORTA].DIRSET.reg = out_mask;
+  // Set in pin to input mode
+  PORT->Group[PORTA].PINCFG[in_pin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
+  PORT->Group[PORTA].DIRCLR.reg = in_pin ;
+  PORT->Group[PORTA].CTRL.reg = in_mask; //make sure port synchronizer always active
+
+
+  while(1){
+    /*PORT->Group[PORTA].OUTSET.reg = out_mask; // turn on led
+    delay(1000);              // wait for a second
+    PORT->Group[PORTA].OUTCLR.reg = out_mask; // turn off led
+    delay(1000);              // wait for a second
+    */
+    
+    //ternary operator: assymetric 300ns (200-100)
+    //portin & in_mask ? outclr = out_mask : outset = out_mask;
+    //portin & in_mask ? outclr = out_mask : out = out_mask;
+    out = ~(portin);
+
+    
+    //bitwise xor: 300ns
+    //out = ((portin ^ in_mask) << 1);
+
+    //if else
+    /*if (portin & in_mask){
+      outclr = out_mask;
+    } else {
+      outset = out_mask;
+    }*/
+    
+    //toggle, 10 mhz
+    //outtgl = out_mask;
+
+    //manual toggle, 20mhz
+    //outclr = out_mask;
+    //outset = out_mask;
+
+    
+  }
+  
+
+}
+ 
+void loop() {}
diff --git a/gpio/atsamd51/ring.jpg b/gpio/atsamd51/ring.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e37353cf41cd6342e28c55209aaac3f917fb13e6
Binary files /dev/null and b/gpio/atsamd51/ring.jpg differ
diff --git a/ring.json b/ring.json
index d5598693274bbc14214f05598dc8f866b7db9100..d46ebadff5d9047e4894b3d03d55bac4b760fd88 100644
--- a/ring.json
+++ b/ring.json
@@ -7,6 +7,7 @@
 		"dev_board_sales_link":"link for dev board purchase",
 		"ic_price":"price for bare ic, dollars",
 		"ic_sales_link":"link for ic purchase",
+		"cpu_frequency":"clock speed in MHz",
 		"ring_period":"period of one full ring oscillator waveform, in microseconds"
 	},
 
@@ -63,6 +64,17 @@
 		}
 	],
 	"gpio":[
+		{
+			"name":"ATSAMD51",
+			"serial_number":"",
+			"subdirectory_path":"gpio/atsamd51",
+			"dev_board_price":14.95,
+			"dev_board_sales link":"https://www.adafruit.com/product/3800",
+			"ic_price":4.31,
+			"ic_sales_link":"ATSAMD51J19A-AUTCT-ND",
+			"cpu_frequency":120,
+			"ring_period":0.27
+		},
 		{
 			"name":"ATSAMS70",
 			"serial_number":"",