# Introduction

PIO means Programmable Input/Output and this is the simplest way of controlling and measuring digital voltage levels on the pins of the AVR32 processor pins connected to the bus connectors.
To use a GPIO pin as a PIO, you must first set the pin to be an input or an output. If you set it as an input, you can then check the input voltage to see whether it has a low or a high value coming into it, for example to check the position of a switch. If you set it to be an output, you can program it to output a low voltage or a high voltage to control lights, motors or other circuits.
For PIO pins that are inputs, you can also ask that, when the voltage on that pin changes from 0 to 1 or from 1 to 0, this will generate an interrupt. When this happens, the processor will stop what it is doing, run a special piece of code called an interrupt routine, and when it has finished doing that it will go back and continue what it was doing when the interrupt happened.
Lastly, each pin has an optional pull-up resistor that can be enabled so that, if nothing is connected to a pin that is an input, it will float up to logic "1" instead of waving up and down at random. This is the usual way to connect switches or pushbuttons: you program a pull-up resistor on the pin, then connect the switch between the pin and zero volts so that when contact is closed you will read a value of 0, and when the contact is open you will read a value of 1.

# Hardware view

Any of the AT32UC3A chip's peripheral pins can be read as a digital input or set as an output and programmed to 0 or 1 logic level.
When a pin is set to be an output, a 0 logic output connects the pin to 0 volts, while a logic 1 ("high") value puts 3.3 volts on it with a maximum current supply or drain of 4 milliamperes for both states.
When they are set to be inputs, a voltage level from 0.0 to 0.8 volts reads as a "0" (low) input, and a voltage level from 2.0 volts to 5.0 volts reads as a "1" (high) input. Values from 0.8 to 2.0 volts may read as high or low and are not certain.
Some pins of the Mizar32 can only be used as programmable I/O pins because they are not used for anything else. Others carry signals to various peripheral devices but, if those devices are not being used, the pins can be used as PIO pins instead.
Other pins are critical to the correct functioning of the processor, for example those used to access the SDRAM, oscillators and other on-board circuitry; if you use those as PIO pins the board will probably crash and need its reset button pressing.

## Dedicated PIO pins

| Pin | Name | Bus pin | eLua name | PicoLisp |
| PA2 | GPIO2 | BUS5 pin 11 | pio.PA_2 | 'PA_2 |
| PA7 | GPIO7 | BUS5 pin 12 | pio.PA_7 | 'PA_7 |
| PB17 | GPIO49 | BUS5 pin 8 | pio.PB_17 | 'PB_17 |
| PB18 | GPIO50 | BUS5 pin 9 | pio.PB_18 | 'PB_18 |
| PB29 | GPIO61 | On-board LED | pio.PB_29 | 'PB_29 |
| PB30 | GPIO62 | BUS6 pin 9 | pio.PB_30 | 'PB_30 |
| PB31 | GPIO63 | BUS6 pin 10 | pio.PB_31 | 'PB_31 |
| PX16 | GPIO88 | User button | pio.PX_16 | 'PX_16 |
| PX19 | GPIO85 | BUS6 pin 12 | pio.PX_19 | 'PX_19 |
| PX22 | GPIO82 | BUS6 pin 11 | pio.PX_22 | 'PX_22 |
| PX33 | GPIO71 | BUS5 pin 10 | pio.PX_33 | 'PX_33 |

## Optional PIO pins

Unused ADC, PWM, SPI or UART pins can also be used as PIO pins. See those sections for the relevant pin names. This brings the total number of usable PIOs to 66.

# Software view

The PIO Alcor6L module allows you to set any pin as a logic input or to set it as an output and put 0v or 3.3V on it and you can enable a pull-up resistor on any pin.

## Driving a pin as an output

This example lights the on-board LED.
In eLua:
In PicoLisp:
Note that, straight after a reset, the LED lights up at line 2 because the reset state is that all pins are low and the onboard LED lights when the signal is low. To set a pin as an output whose value starts high, you need to call pio.pin.sethigh before calling pio.pin.setdir.

## Reading the voltage on a pin as an input (eLua)

Here is an example of reading one PIO pin and driving another in response to it. We will read the pin connected to the onboard user button and, as long as it is pressed down, we will make the on-board LED flicker.

## Reading the voltage on a pin as an input (PicoLisp)

In PicoLisp, here is how to do it.

## Programmable pull-up resistors

The user button's electrical circuit is quite simple: when the button is pressed, it connects its PIO pin to zero volts, giving a low input value, and there is a resistor connected between the PIO pin and 3.3 volts so that if the button is not pressed the PIO pin is gently pulled up to 3.3V and reads as a high value.
Other PIO pins that are not connected to anything, if you program them as inputs, will pick up random noise from the surrounding environment and give values that are sometimes high and sometimes low. The programmable pull-up resistors are a way to ensure that, if no signal is connected to an input pin, it will gently be pulled up to a high value instead of floating randomly.
This example turns one of the unused GPIO pins into a PIO input, but ensures that, if nothing is physically connected to it, it will always return a high value of 1.
If you remove the pio.pin.setpull line from the following code (on my test board, at least), it prints mostly zeroes but if you touch the underside of the Mizar32 board the value flickers between 0 and 1. With the pio.pin.setpull line included, the input value is always 1 unless you connect the pin it to a GND pin (e.g. BUS5 pin 14) with a piece of wire.
In eLua:
In PicoLisp:
Although Alcor6L also has a similar primitive PULLDOWN, the AVR32 chip used in the Mizar32 does not have programmable pull-down resistors in its hardware, so using this will provoke an error message.
To disable the pull-up resistor again, you use
| Language | Example |
| eLua | pio.pin.setpull(pin, pio.NOPULL) |
| PicoLisp | (pio-pin-setpull pin *pio-nopull*) |

## Open-collector outputs

Another use for the programmable pull-up resistors is to implement "open-collector outputs". In this scheme of things, a pin can be in one of two states: either it is being driven as a 0 output or it being read as an input. The pull-up resistor ensures that, if no one is driving it as an output, everyone will read it as a high value. This is used when several computers need to communicate over a single signal wire in such a way that any computer can talk with any other one without needing a master-slave relationship or a way to negotiate who is controlling the bus. Using this system, any computer can read the wire to see if its value is high or low, and any computer can drive the wire to a low value, to be read by all the others. This is different from driving a wire as a high or low output because if one computer is driving it high and another is driving it low at the same time, that could damage the computers in question and would certainly result in garbled communication.
A simple example would be a system to turn a house light on and off in a way that can be activated by any one of several switch units. The I2C bus, instead, is an advanced example that uses open-collector outputs on its signal wires so that any one of the computers on an I2C bus to talk with any other one without ever causing conflicting signals on the bus wires.
The following code implements an open-collector output on a PIO pin, giving one function to configure it as an OC pin, one function to drive it as a low output and one to set it as an input and tell you what value is on the wire at the moment:
In eLua:
In PicoLisp:

## Interrupts

Please note: There is currently no support for interrupt handling in PicoLisp. See issue #12. You can however use interrupts in eLua.
You can arrange for your own Lua function to be called whenever the logic level changes on a GPIO pin, without having to keep checking the pin all the time.
You can ask for your interrupt function to be called either when the logic level on a GPIO pin goes from 0 to 1, when it goes from 1 to 0 or both.
The following example creates an interrupt function and arranges for it to be called every time the user button is pressed. The circuitry of the user button is such that its GPIO pin is high when the button is not pressed and low when it is pressed, so we ask for our interrupt routine to be called when the logic level of the pin goes from high to low.
Any GPIO pin can be made to react to edge-based interrupts, whether they are inputs, outputs or have some completely different function.
You can enable the positive edge interrupt function for a pin, the negative edge interrupt function, or both. If you enable both, you can either make both kinds of interrupt be handled by the same function, or by two different functions.

## Decoding pin numbers

Functions like pio.PB_29 return numbers that are used internally in eLua to identify the GPIO pins. You do not need to know anything about the values of these numbers except in one circumstance: when you have several edge-triggered interrupts enabled on different GPIO pins at the same time.
You see, you can only tell cpu.set_int_handler to call a single function for all positive edge interrupts and one other function (or the same one) for all negative-edge interrupts, but you can find out which GPIO pin caused the interrupt by inspecting the parameter that is passed to your interrupt-handling function, which we have called resnum in the code examples above.
This is the "resource number", the internal number that eLua uses to represent the pin, and it is the same as the value returned by pio.PX_16 and so on.
So you can say, in your interrupt function,
or
however, if you have enabled many pin interrupts and wish to decode it into a port number and a pin number, you can do so using
For pins on Port A, port will be 0 and pin will be from 0 to 31. For pins on Port B, port will be 1 and pin will be from 0 to 31. For pins on Port C, port will be 2 and pin will be from 0 to 5. For pins on Port X, port will be 23 and pin will be from 0 to 39.

# Further reading

* The Open collector article on Wikipedia
* The Atmel AT32UC3A datasheet Chapter 22: General-Purpose Input/Output Controller (GPIO)
* The PIO section of the eLua manual for details of all eLua pio.* functions