Chips interact with the simulator using digital pins. The pins are defined in a JSON file, called {chip-name}.chip.json (replace {chip-name} with the actual name of the chip). For instance, the following JSON file defines a chip with 4 pins (IN, OUT, VCC, GND):
{
"name": "Inverter",
"author": "Uri Shaked",
"pins": ["OUT", "IN", "VCC", "GND"]
}
The GPIO pins API allows your chip implementation code to interact with the GPIO pins:
pin_init
pin_t pin_init(const char *name, uint32_t mode)
Initializes the given pin, and returns a pin identifier for use with the other pin methods. The mode parameters configure the initial state of the pin. The following values are available:
INPUT - configures the pin as a digital input
INPUT_PULLUP - configures the pin as a digital input, and attaches a pull-up register to the pin.
INPUT_PULLDOWN - configures the pin as a digital input, and attaches a pull-down register to the pin.
OUTPUT - configures the pin as a digital output
OUTPUT_LOW - configures the pin as a digital output, sets the value of the pin to LOW
OUTPUT_HIGH - configures the pin as a digital output, sets the value of the pin to HIGH
ANALOG - configures the pin as an analog pin. See the Analog API section for more detail.
Note: pin_init() can only be called from chip_init(). Do not call it at a later time. You can use pin_mode() to change the mode of a pin at any time.
pin_mode
void pin_mode(pin_t pin, uint32_t mode)
Configures the given pin as digital input or output. The valid values for mode are the same as pin_init(): INPUT, INPUT_PULLUP, INPUT_PULLDOWN, OUTPUT, OUTPUT_LOW, OUTPUT_HIGH, and ANALOG.
pin_write
void pin_write(pin_t pin, uint32_t value)
Set the output value for a digital pin. Use the LOW and HIGH constants for value.
pin_read
uint32_t pin_read(pin_t pin)
Reads the current digital value of the pin, returns either LOW or HIGH.
pin_watch
bool pin_watch(pin_t pin, pin_watch_config_t *config)
Listens for changes in the digital value of the given pin. The config structure contains the following fields:
| Field | Type | Description |
|---|
edge | uint32_t | What pin value changes we listen for (RISING, FALLING or BOTH) |
pin_change | callback | Called when the pin value changes (see below) |
user_data | void * | Data that will be passed in the first argument to pin_change |
The valid values for edge are:
BOTH - Listen for any value change
FALLING - Listen for HIGH to LOW changes
RISING - Listen for LOW to HIGH changes
You can only have one watch for a pin at any given time. The function returns true if the watch was successfully set, or false in case there is already a watch defined for this pin (and thus the new watch was not set).
The pin_change callback signature is as follows:
void chip_pin_change(void *user_data, pin_t pin, uint32_t value) {
// value will either be HIGH or LOW
}
Usage example:
const pin_watch_config_t watch_config = {
.edge = FALLING,
.pin_change = chip_pin_change,
.user_data = chip,
};
pin_watch(pin, &watch_config);
pin_watch_stop
void pin_watch_stop(pin_t pin)
Stops watching for changes on the given pin.