diff --git a/gpio/m0/index.html b/gpio/m0/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..5c644ac3baf5194494a61abd581d6a47af59e4ce
--- /dev/null
+++ b/gpio/m0/index.html
@@ -0,0 +1,153 @@
+<html>
+<head>
+<style>
+pre code {
+  background-color: #eee;
+  border: 1px solid #999;
+  display: block;
+  padding: 20px;
+}
+</style>
+
+
+</head>
+<body>
+
+<h1>M0 - ATSAMD21</h1>
+
+<figure>
+<img src='m0-feather.jpg'>
+<figcaption>Ring oscillator with M0.</figcaption>
+</figure>
+
+<p>This ring oscillator runs on the 'M0' ATSAMD21, which is a fairly popular microcontroller with an Arm Cortex M0 at it's heart. It has native USB functionality, and is supported with an Adafruit bootloader, making writing and running code fairly straightforward. I used Adafruit's Feather dev board for this test.</p>
+
+<p>I dug through the arduino cores and printed out their lookup tables so that I could write the registers down... This was a great (albeit tangential) exercise.</p>
+
+<pre>
+<code>
+/*
+   I found most of these definitions in the arduino cores in
+   AppData/Local/Arduino15/packages/adafruit/hardware/samd/1.0.19/cores/arduino/wiring_digital.c & wiring_digital.h
+*/
+
+#define PIN_LED_PORT 0
+#define PIN_LED_PIN 17
+
+#define PIN_10_PORT 0
+#define PIN_10_PIN 18
+
+#define PIN_11_PORT 0
+#define PIN_11_PIN 16
+
+#define LED_OUTSET PORT->Group[PIN_LED_PORT].OUTSET.reg
+#define LED_OUTCLR PORT->Group[PIN_LED_PORT].OUTCLR.reg
+
+#define RING_PORT_OUTSET PORT->Group[PIN_10_PORT].OUTSET.reg
+#define RING_PORT_OUTCLR PORT->Group[PIN_10_PORT].OUTCLR.reg
+#define RING_PORT_OUT_MASK (1UL << PIN_10_PIN)
+
+#define RING_PORT_IN PORT->Group[PIN_11_PORT].IN.reg
+#define RING_PORT_IN_MASK (1UL << PIN_11_PIN)
+
+void setup() {
+  // set a pin to in
+  PORT->Group[PIN_LED_PORT].PINCFG[PIN_LED_PIN].reg = (uint8_t)(PORT_PINCFG_INEN);
+  // setting same pin to out (arduino configures an output as both, so it can read its own state. handy
+  PORT->Group[PIN_LED_PORT].DIRSET.reg = (uint32_t)(1 << PIN_LED_PIN);
+
+  // set 10 to output
+  PORT->Group[PIN_10_PORT].DIRSET.reg = (uint32_t)(1 << PIN_10_PIN);
+
+  // set 11 to input
+  PORT->Group[PIN_11_PORT].PINCFG[PIN_11_PIN].reg = (uint8_t)(PORT_PINCFG_INEN);
+
+  // do loop
+  while (1) { // no loop just c
+    RING_PORT_IN & RING_PORT_IN_MASK ? RING_PORT_OUTCLR = RING_PORT_OUT_MASK : RING_PORT_OUTSET = RING_PORT_OUT_MASK;
+  }
+}
+
+void loop() {
+
+}
+</code>
+</pre>
+
+<p>This enabled me to write the code that I ran during the test, where the M0 clocked at 1.45MHz. Scope traces and code below.</p>
+
+<figure>
+<img src="m0-scope.jpg" height=25%>
+<figcaption>Adafruit Feather dev board used in this test.</figcaption>
+</figure>
+
+<pre>
+  <code>
+/*
+   I found most of these definitions in the arduino cores in
+   AppData/Local/Arduino15/packages/adafruit/hardware/samd/1.0.19/cores/arduino/wiring_digital.c & wiring_digital.h
+   also samd/1.0.19/variants/variant.h and variant.cpp and pins_arduino.h
+*/
+
+#define PIN_10_PORT 0
+#define PIN_10_PIN 18
+
+#define PIN_11_PORT 0
+#define PIN_11_PIN 16
+
+#define RING_PORT_OUTSET PORT->Group[PIN_10_PORT].OUTSET.reg
+#define RING_PORT_OUTCLR PORT->Group[PIN_10_PORT].OUTCLR.reg
+#define RING_PORT_OUT_MASK (1UL << PIN_10_PIN)
+
+#define RING_PORT_IN PORT->Group[PIN_11_PORT].IN.reg
+#define RING_PORT_IN_MASK (1UL << PIN_11_PIN)
+
+void setup() {
+  // set 10 to output
+  PORT->Group[PIN_10_PORT].DIRSET.reg = (uint32_t)(1 << PIN_10_PIN);
+
+  // set 11 to input
+  PORT->Group[PIN_11_PORT].PINCFG[PIN_11_PIN].reg = (uint8_t)(PORT_PINCFG_INEN);
+
+  // do loop
+  while (1) { // no loop just c
+    RING_PORT_IN & RING_PORT_IN_MASK ? RING_PORT_OUTCLR = RING_PORT_OUT_MASK : RING_PORT_OUTSET = RING_PORT_OUT_MASK;
+  }
+}
+
+void loop() {
+
+}
+</code>
+</pre>
+
+
+<p>With the Arduino digitalWrite and digitalRead calls, the ring is ~162khz</p>
+
+<figure>
+<img src='m0-scope-arduino.jpg'>
+<figcaption>Ring oscillator with M0 using Arduino library calls.</figcaption>
+</figure>
+
+<p>The code for this is below. About 1us of this latency is 'loop' call overhead.</p>
+
+<pre>
+<code>
+void setup() {
+  // put your setup code here, to run once:
+  pinMode(10, OUTPUT);
+  pinMode(11, INPUT);
+}
+
+void loop() {
+  // put your main code here, to run repeatedly:
+  digitalWrite(10, 1-digitalRead(11));
+}
+</code>
+</pre>
+
+<p><a href='../../index.html'>Back</a></p>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/gpio/m0/m0-feather.jpg b/gpio/m0/m0-feather.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..080beaeeea9704ce7c97bc48b3c0b3969d7ec5dc
Binary files /dev/null and b/gpio/m0/m0-feather.jpg differ
diff --git a/gpio/m0/m0-scope-arduino.jpg b/gpio/m0/m0-scope-arduino.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d2578e9e88cd5033ccf934e1999e18d8562fda77
Binary files /dev/null and b/gpio/m0/m0-scope-arduino.jpg differ
diff --git a/gpio/m0/m0-scope.jpg b/gpio/m0/m0-scope.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..8d38ab7b48e4e3de411b8b2a836d642321fbe0d3
Binary files /dev/null and b/gpio/m0/m0-scope.jpg differ
diff --git a/gpio/m0/m0_arduino/m0_arduino.ino b/gpio/m0/m0_arduino/m0_arduino.ino
new file mode 100644
index 0000000000000000000000000000000000000000..e82f9d7e4214de1f27ebad2722c3f9ee142545c8
--- /dev/null
+++ b/gpio/m0/m0_arduino/m0_arduino.ino
@@ -0,0 +1,12 @@
+void setup() {
+  // put your setup code here, to run once:
+  pinMode(10, OUTPUT);
+  pinMode(11, INPUT);
+
+}
+
+void loop() {
+  while (1) {
+    digitalWrite(10, 1 - digitalRead(11));
+  }
+}
diff --git a/gpio/m0/m0_port/m0_port.ino b/gpio/m0/m0_port/m0_port.ino
new file mode 100644
index 0000000000000000000000000000000000000000..32643ad39078ed6e305f691b39639762370752ff
--- /dev/null
+++ b/gpio/m0/m0_port/m0_port.ino
@@ -0,0 +1,41 @@
+/*
+   I found most of these definitions in the arduino cores in
+   AppData/Local/Arduino15/packages/adafruit/hardware/samd/1.0.19/cores/arduino/wiring_digital.c & wiring_digital.h
+*/
+
+#define PIN_LED_PORT 0
+#define PIN_LED_PIN 17
+
+#define PIN_10_PORT 0
+#define PIN_10_PIN 18
+
+#define PIN_11_PORT 0
+#define PIN_11_PIN 16
+
+uint32_t ulPin = 11;
+
+void setup() {
+  // set a pin to in / out ... starting
+  PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg = (uint8_t)(PORT_PINCFG_INEN) ;
+  PORT->Group[g_APinDescription[ulPin].ulPort].DIRSET.reg = (uint32_t)(1 << g_APinDescription[ulPin].ulPin) ;
+
+  //pinMode(10, OUTPUT);
+  //pinMode(11, INPUT);
+
+}
+
+void loop() {
+  EPortType port = g_APinDescription[ulPin].ulPort;
+  uint32_t pin = g_APinDescription[ulPin].ulPin;
+  uint32_t pinMask = (1ul << pin);
+
+  Serial.print("11, port: ");
+  Serial.print(port);
+  Serial.print(" pin: ");
+  Serial.print(pin);
+  Serial.println("");
+  PORT->Group[port].OUTSET.reg = pinMask;
+  delay(100);
+  PORT->Group[port].OUTCLR.reg = pinMask;
+  delay(100);
+}
diff --git a/gpio/m0/m0_portSearch/m0_portSearch.ino b/gpio/m0/m0_portSearch/m0_portSearch.ino
new file mode 100644
index 0000000000000000000000000000000000000000..d33aecf5830cd19d265ea1bed23c9cdc108ca56e
--- /dev/null
+++ b/gpio/m0/m0_portSearch/m0_portSearch.ino
@@ -0,0 +1,35 @@
+/*
+   I found most of these definitions in the arduino cores in
+   AppData/Local/Arduino15/packages/adafruit/hardware/samd/1.0.19/cores/arduino/wiring_digital.c & wiring_digital.h
+   also samd/1.0.19/variants/variant.h and variant.cpp and pins_arduino.h
+*/
+
+#define PIN_10_PORT 0
+#define PIN_10_PIN 18
+
+#define PIN_11_PORT 0
+#define PIN_11_PIN 16
+
+#define RING_PORT_OUTSET PORT->Group[PIN_10_PORT].OUTSET.reg
+#define RING_PORT_OUTCLR PORT->Group[PIN_10_PORT].OUTCLR.reg
+#define RING_PORT_OUT_MASK (1UL << PIN_10_PIN)
+
+#define RING_PORT_IN PORT->Group[PIN_11_PORT].IN.reg
+#define RING_PORT_IN_MASK (1UL << PIN_11_PIN)
+
+void setup() {
+  // set 10 to output
+  PORT->Group[PIN_10_PORT].DIRSET.reg = (uint32_t)(1 << PIN_10_PIN);
+
+  // set 11 to input
+  PORT->Group[PIN_11_PORT].PINCFG[PIN_11_PIN].reg = (uint8_t)(PORT_PINCFG_INEN);
+
+  // do loop
+  while (1) { // no loop just c
+    RING_PORT_IN & RING_PORT_IN_MASK ? RING_PORT_OUTCLR = RING_PORT_OUT_MASK : RING_PORT_OUTSET = RING_PORT_OUT_MASK;
+  }
+}
+
+void loop() {
+
+}
diff --git a/ring.json b/ring.json
index a6a5778f43802d6f9293789e53bcfdabf17e5d66..6a83b0a7f9d056f040de5c5af0db9267957011d9 100644
--- a/ring.json
+++ b/ring.json
@@ -63,6 +63,26 @@
 		}
 	],
 	"gpio":[
+		{
+			"name":"M0, arduino",
+			"serial_number":"",
+			"subdirectory_path":"gpio/m0",
+			"dev_board_price":19.00,
+			"dev_board_sales link":"",
+			"ic_price":2.1,
+			"ic_sales_link":"",
+			"ring_period":6.14
+		},
+		{
+			"name":"M0, port",
+			"serial_number":"",
+			"subdirectory_path":"gpio/m0",
+			"dev_board_price":5.00,
+			"dev_board_sales link":"",
+			"ic_price":2.1,
+			"ic_sales_link":"",
+			"ring_period":0.687
+		},
 		{
 			"name":"nucleo, mbed",
 			"serial_number":"",