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<<in_pin; +const uint8_t out_pin = 22; +const uint32_t out_mask = 1ul<<out_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":"",