<jupyter_start><jupyter_text>GPIO DemoThis demo shows how to use the Xilinx's MMIO driver to interact with partially reconfigurable regions.  Download the static bitstreamWe first need to download the static or full bitstream before any partial bitstreams can be downloaded. Note that if the bitstream is not in the same directory as the notebook then the full path needs to be provided.<jupyter_code>from prio import PrIoOverlay

FULL_BITSTREAM_PATH = "/usr/local/lib/python3.6/dist-packages/prio/"
PARTIAL_BITSTREAM_PATH  = "/usr/local/lib/python3.6/dist-packages/prio/partial/"

overlay = PrIoOverlay(FULL_BITSTREAM_PATH + "prio.bit")<jupyter_output><empty_output><jupyter_text>Set up the reconfigurable regionNotice that as with the full bitstream, the full path to the partial bitstream must be provided when is located outside of the current notebook's directory.We will download partial bitstream and retrieve the initilized mmio driver for future use. Note that the pynq package provides a wrapper for AXI GPIO modules specifically, but we will use the MMIO driver instead to demonstrate how to build custom drivers.<jupyter_code>overlay.pr_download("pr_0", PARTIAL_BITSTREAM_PATH + "pr_0_gpio.bit")

gpio0 = overlay.pr_0.axi_gpio_0.mmio<jupyter_output><empty_output><jupyter_text>MMIO DemosThe following Demos use MMIO to read and write to the registers in the GPIO hardware inside different PR regions to demonstrate simple examples increasing in complexity.  Demo: Constant OutputOutputs a constant pattern to the **`pr_0`**. pins.**Hardware Setup:** For this demo, we suggest using at least one LED to check the output of every pin. These LEDs should be hooked up to the top row of **`PMOD 0`**. Every other pin should be high.![](images/gpio_hw_setup1.JPG)<jupyter_code># Constants for register offsets
DATA_OFFSET = 	0x00
TRI_OFFSET  =	0x04

# Convenient constants for setting the tri-state buffers
ALL_INPUTS  = 	0xFFFF
ALL_OUTPUTS =   0x00

# Desired pattern of gpio output.
LED_PATTERN = 0b1010

# Sets the direction of all pins in region 0 to output.
gpio0.write(TRI_OFFSET, ALL_OUTPUTS)

# Sets the value of all the pins in region 0 so everyother pin is high.
gpio0.write(DATA_OFFSET, LED_PATTERN)<jupyter_output><empty_output><jupyter_text>Demo: Binary CounterThis demo will output the count, in binary, of a counter to the pins of **`pr_0`**.**Hardware Setup:** This Demo should use the same LED setup as the **`Constant Output`** Demo<jupyter_code>import time

OUTPUTS_OFF = 0b0

# Sets the direction of all pins in region 0 to  output.
gpio0.write(TRI_OFFSET, ALL_OUTPUTS)

# Counts from 0 to 15 in binary
for output in range(0, 16):
    
    gpio0.write(DATA_OFFSET,output)
    
    #pauses for a half second
    time.sleep(0.5)
    

#sets the value of all the pins in region 0 so everyother pin is high.
gpio0.write(DATA_OFFSET, OUTPUTS_OFF)<jupyter_output><empty_output><jupyter_text>Demo: Blink TestThe following demonstrates the Input and Output functionalities of GPIO interface by toggling the value on top-right pin on **`PMOD 1`**, and reading that value from the bottom-right pin on **`PMOD 1`**. This value will then be echoed to the top-right pin on **`PMOD 0`**.**Hardware Setup:** Keep the LEDs connected to the top row of **`PMOD 0`**. Connect a wire from the top-right pin on **`PMOD 1`** to the bottom-right pin on **`PMOD 1`**.![](images/gpio_hw_setup2.JPG)The LED connected to the top-right pin on **`PMOD 0`** will indicate the current value being read from bottom-right pin on **`PMOD 1`**. This LED should toggle on and off.  Setup additional reconfigurable regionsSince this demo requires two additional PR regions, we must setup them up with the following code.<jupyter_code>overlay.pr_download("pr_1", PARTIAL_BITSTREAM_PATH + "pr_1_gpio.bit")
gpio1 = overlay.pr_1.axi_gpio_0.mmio

overlay.pr_download("pr_3", PARTIAL_BITSTREAM_PATH + "pr_3_gpio.bit")
gpio3 = overlay.pr_3.axi_gpio_0.mmio
import time

# Since only the right most pin is needed as an output
# for the LEDs, that one is set to an output(0), while
# the rest are set to inputs (1).
gpio0.write(TRI_OFFSET, 0xe)

gpio1.write(TRI_OFFSET, ALL_OUTPUTS)
gpio3.write(TRI_OFFSET, ALL_INPUTS)

led_value = 0

for i in range(20):
    time.sleep(0.5)
    gpio1.write(DATA_OFFSET,led_value)
    led_value = led_value ^ 0b10000001
    
    val = gpio3.read(DATA_OFFSET) & 0x01

    gpio0.write(DATA_OFFSET, val)
    if val:
        print('on')
    else:
        print('off')<jupyter_output>off
on
off
on
off
on
off
on
off
on
off
on
off
on
off
on
off
on
off
on<jupyter_text>The Use of a Wrapper ClassMMIO can be far easier to use when its wrapped inside of a class. Below is a simple class that uses the MMIO driver from the partial regions to set the tri-state buffer and read and write values.<jupyter_code>class GPIO():	
    # Constants for register offsets
	DATA_OFFSET = 	0x00
	TRI_OFFSET =	0x04
	 
    # Convenient constants for setting the direction of tri-state buffers
	ALL_INPUTS = 	0xFFFF
	ALL_OUTPUTS = 	0x0000


    # Extracts the mmio driver from the PR region assuming that Xilinx's 
    # driver associated with the AXI interface is named "axi_gpio_0"
	def __init__(self, partial_region):
		self._mmio = partial_region.axi_gpio_0.mmio

    # Used to set the directions of the tri-state buffers
	def setDirection(self, direction):
		self._mmio.write(self.TRI_OFFSET, direction)

    # Used to retrieve the directions of the tri-state buffers
	def getDirection(self):
		return self._mmio.read(self.TRI_OFFSET)

    # Used to set the value of pins when the tri-state buffers are
    # set as outputs
	def setValue(self, value):
		self._mmio.write(self.DATA_OFFSET, value)

    # Used to retrieve the value of pins when the tri-state buffers are
    # set as inputs
	def getValue(self):
		return self._mmio.read(self.DATA_OFFSET)<jupyter_output><empty_output><jupyter_text>GPIO Wrapper DemosBelow are all of the demos repeated with the GPIO wrapper class. There are a few extra peculiarities that should be noted.  Demo: Constant OutputOutputs a constant output in the **`pr_0`** pins.**Hardware Setup:** For this demo, we suggest using at least one LED to check the output of every pin. These LEDs should be hooked up to the top row of **`PMOD 0`**. Every other pin should be high.![](images/gpio_hw_setup1.JPG)<jupyter_code>overlay.pr_download("pr_0", PARTIAL_BITSTREAM_PATH + "pr_0_gpio.bit")

gpio0 = GPIO(overlay.pr_0)
LED_PATTERN = 0b1010

gpio0.setDirection(ALL_OUTPUTS)

gpio0.setValue(LED_PATTERN)<jupyter_output><empty_output><jupyter_text>Demo: Binary CounterThis demo will output the count, in binary, of a counter to the pins of **`pr_0`**.** Hardware Setup:** This Demo should use the same LED setup as the **`Constant Output`** Demo<jupyter_code>import time

gpio0.setDirection(ALL_OUTPUTS)

for output in range(0, 16):
    
    gpio0.setValue(output)
    
    time.sleep(0.5)<jupyter_output><empty_output><jupyter_text>Demo: Blink TestThe following demonstrates the Input and Output functionalities of GPIO interface by toggling the value on top-right pin on **`PMOD 1`**, and reading that value from the bottom-right pin on **`PMOD 1`**. This value will then be echoed to the top-right pin on **`PMOD 0`**.**Hardware Setup:** Keep the LEDs connected to the top row of **`PMOD 0`**. Connect a wire from the top-right pin on **`PMOD 1`** to the bottom-right pin on **`PMOD 1`**.![](images/gpio_hw_setup2.JPG)The LED connected to the top-right pin on **`PMOD 0`** will indicate the current value being read from bottom-right pin on **`PMOD 1`**. This LED should toggle on and off.  Setup additional reconfigurable regionsSince this demo requires two additional PR regions, we must setup them up with the following code. **IMPORTANT:** It's important to note below that after a partial region is set up, and a bitstream for that region is downloaded, the GPIO driver must be instantiated before another partial region is set up. Once another partial region is setup, the previous one will lose it's GPIO driver, and will have a generic MMIO axi interface driver.<jupyter_code>overlay.pr_download("pr_1", PARTIAL_BITSTREAM_PATH + "pr_1_gpio.bit")
gpio1 = GPIO(overlay.pr_1)

overlay.pr_download("pr_3", PARTIAL_BITSTREAM_PATH + "pr_3_gpio.bit")
gpio3 = GPIO(overlay.pr_3)
import time

gpio0.setDirection(0xe)

# Configure as output
gpio1.setDirection(ALL_OUTPUTS)
gpio3.setDirection(ALL_INPUTS)

# Blink LED for 10s
led_value = 0

for i in range(10):
    time.sleep(0.5)
    gpio1.setValue(led_value)
    led_value = led_value ^ 0b10000001
    
    val = gpio3.getValue() & 0x01
    print(val)
    if val:
        print('on')
    else:
        print('off')<jupyter_output>0
off
1
on
0
off
1
on
0
off
1
on
0
off
1
on
0
off
1
on
{'fraction_non_alphanumeric': 0.0808, 'fraction_numerical': 0.02057142857142857, 'mean_word_length': 4.6204238921001926, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '90222', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2916, 'n_tokens_neox': 2758, 'n_words': 1082, 'path': 'boards/ZCU104/notebooks/prio/gpio.ipynb', 'repo_name': 'byuccl/PYNQ-PRIO', 'size': '8750'}