Input Functions

While one of the purposes of the Cow Pi boards is to teach memory-mapped I/O, the CowPi library provides functions that work with the peripheral input/output devices for bootstrapping/scaffolding purposes. These functions can, of course, also be used when memory-mapped I/O is not a required part of an assignment.

Even if you are working with memory-mapped I/O, you will benefit from using the Debouncing code.

Simple Inputs

Using the pushbuttons and slide switches are straight-forward.

bool cowpi_left_button_is_pressed(void)

Reports whether the left button is pressed.

There is no debouncing. This is a portable implementation, not a memory-mapped implementation.

Assumes the left button is in Arduino pin D8 or Raspberry Pi Pico pin GP2. A pressed button grounds a pulled-high input.

Returns:

true if the button is pressed, false otherwise

bool cowpi_right_button_is_pressed(void)

Reports whether the right button is pressed.

There is no debouncing. This is a portable implementation, not a memory-mapped implementation.

Assumes the right button is in Arduino pin D9 or Raspberry Pi Pico pin GP3. A pressed button grounds a pulled-high input.

Returns:

true if the button is pressed, false otherwise

bool cowpi_left_switch_is_in_left_position(void)

Reports whether the left switch is in the left position.

There is no debouncing. This is a portable implementation, not a memory-mapped implementation.

Assumes the left switch is in:

  • Arduino pin A4 (D18) if SPI (but not I2C) is in use or if no protocol is in use; assumes the switch is in pin D11 if I2C (but not SPI) is in use.

  • Raspberry Pi Pico pin GP14.

A switch in the left position grounds a pulled-high input.

Returns:

true if the switch is in the left position, false otherwise

bool cowpi_right_switch_is_in_left_position(void)

Reports whether the right switch is in the left position.

There is no debouncing. This is a portable implementation, not a memory-mapped implementation.

Assumes the right switch is in:

  • Arduino pin A5 (D19) if SPI (but not I2C) is in use or if no protocol is in use; assumes the switch is in pin D10 if I2C (but not SPI) is in use.

  • Raspberry Pi Pico pin GP15.

A switch in the left position grounds a pulled-high input.

Returns:

true if the switch is in the left position, false otherwise

bool cowpi_left_switch_is_in_right_position(void)

Reports whether the left switch is in the right position.

There is no debouncing. This is a portable implementation, not a memory-mapped implementation.

Assumes the left switch is in:

  • Arduino pin A4 (D18) if SPI (but not I2C) is in use or if no protocol is in use; assumes the switch is in pin D11 if I2C (but not SPI) is in use.

  • Raspberry Pi Pico pin GP14.

A switch in the right position floats, allowing pulled-high input to remain high.

Returns:

true if the switch is in the right position, false otherwise

bool cowpi_right_switch_is_in_right_position(void)

Reports whether the right switch is in the right position.

There is no debouncing. This is a portable implementation, not a memory-mapped implementation.

Assumes the right switch is in:

  • Arduino pin A5 (D19) if SPI (but not I2C) is in use or if no protocol is in use; assumes the switch is in pin D10 if I2C (but not SPI) is in use.

  • Raspberry Pi Pico pin GP15.

A switch in the right position floats, allowing pulled-high input to remain high.

Returns:

true if the switch is in the right position, false otherwise



Scanned Inputs

We provide a function to scan the matrix keypad, returning the character for up to one pressed key. This function will work with any Cow Pi board.

char cowpi_get_keypress(void)

Scans the keypad to determine which, if any, key was pressed.

There is no debouncing. This is a portable implementation, not a memory-mapped implementation. Returns the ASCII representation of the character depicted on whichever key was pressed (0-9, A-D, *, #).

Assumes a common 4x4 matrix keypad with:

  • Arduino form factors: the rows in pins D4-D7 and the columns in pins A0-A3 (D14-D17 on Uno/Nano).

  • Raspberry Pi Pico: the rows in pins GP6-GP9 and the columns in pins GP10-GP13.

A pressed key grounds a pulled-high input.

Returns:

ASCII character corresponding to the key that is pressed, or NUL if no key is pressed


We also provide a function to scan the matrix keypad, returning a bit vector that indicates the position of each of the sixteen keys. This function is suitable only for Cow Pi mk3 and mk4 boards.

uint16_t cowpi_get_keypresses(void)

Scans the keypad to determine which keys have been pressed.

There is no debouncing. This is a portable implementation, not a memory-mapped implementation.

Returns a bit vector with a 1 (key pressed) or 0 (key not pressed) in each of 16 bits that correspond to the 16 keys. For keys with hexadecimal digits, the digit indicates the corresponding bit (bit0 corresponds to the “0” key; bit1 corresponds to the “1” key; …; and bit13 corresponds to the “D” key). Additionally, bit14 corresponds to the “#” key and bit15 corresponds to the “*” key.

Assumes a common 4x4 matrix keypad with:

  • Arduino form factors: the rows in pins D4-D7 and the columns in pins A0-A3 (D14-D17 on Uno/Nano).

  • Raspberry Pi Pico: the rows in pins GP6-GP9 and the columns in pins GP10-GP13.

A pressed key grounds a pulled-high input.

Warning

This function should only be called if diodes are used to isolate the keys, as on the Cow Pi mark 3 and mark 4 development boards.

Returns:

bit vector that indicates which keys are pressed and which are not pressed



Debouncing

Mechanical inputs suffer from switch bounce. As a cost-savings measure, hardware debouncing circuits are not present on the Cow Pi boards. Consequently, debouncing must be implemented in software.

The two debouncing functions we provide are identical except for the size of the datatype they work with. They require two inputs: the first is an expression to determine the input’s non-debounced value, and the second is an enumerated value that uniquely identifies which input is being debounced.

See also

The io_test example demonstrates the use of these debouncing functions.

uint8_t cowpi_debounce_byte(uint8_t current_value, enum input_names input_name)

Applies a software-based low-pass filter to an input, smoothing-out mechanical switch bounce.

When the input is stable, this function will return the input’s value. When the input is bouncing, this function will return a stable value.

The first argument is an expression that you would use to determine the input’s value if switch bounce weren’t an issue. This might be one of the CowPi library’s functions, it might be memory-mapped I/O, or it might be some other expression altogether.

Because this function cannot ascertain which input is being debounced (the expression that provides the current-value is evaluated before this function starts), you must provide additional information, in the form of the input_name argument. Most of the input_names correspond to the likely inputs that would be polled on a Cow Pi board. Providing a unique input_name allows the library to stabilize multiple bouncing inputs, such as the user pressing both pushbuttons simultaneously.

This function is suitable for inputs that can be represented in eight (or fewer) bits.

Parameters:
  • current_value – an expression that evaluates to the input’s current, un-debounced value

  • input_name – a unique enumerated value to distinguish between different inputs

Returns:

the input’s value after mechanical bouncing has been filtered-out

uint16_t cowpi_debounce_short(uint16_t current_value, enum input_names input_name)

Applies a software-based low-pass filter to an input, smoothing-out mechanical switch bounce.

When the input is stable, this function will return the input’s value. When the input is bouncing, this function will return a stable value.

The first argument is an expression that you would use to determine the input’s value if switch bounce weren’t an issue. This might be one of the CowPi library’s functions, it might be memory-mapped I/O, or it might be some other expression altogether.

Because this function cannot ascertain which input is being debounced (the expression that provides the current-value is evaluated before this function starts), you must provide additional information, in the form of the input_name argument. Most of the input_names correspond to the likely inputs that would be polled on a Cow Pi board. Providing a unique input_name allows the library to stabilize multiple bouncing inputs, such as the user pressing both pushbuttons simultaneously.

This function is suitable for inputs that can be represented in sixteen (or fewer) bits.

Parameters:
  • current_value – an expression that evaluates to the input’s current, un-debounced value

  • input_name – a unique enumerated value to distinguish between different inputs

Returns:

the input’s value after mechanical bouncing has been filtered-out


enum input_names

Identifiers to uniquely describe inputs being debounced.

Most of the provided identifiers correspond to the likely inputs that would be polled on a Cow Pi board. Two additional identifiers (INPUT_X and INPUT_Y) are available for mechanical input devices that expand a Cow Pi board.

Values:

enumerator LEFT_BUTTON_DOWN
enumerator RIGHT_BUTTON_DOWN
enumerator LEFT_SWITCH_LEFT
enumerator RIGHT_SWITCH_LEFT
enumerator LEFT_SWITCH_RIGHT
enumerator RIGHT_SWITCH_RIGHT
enumerator KEYPAD
enumerator INPUT_X
enumerator INPUT_Y
enumerator NUMBER_OF_INPUTS