Simone: a game of visual memory and speed
port_keyboard.h File Reference

Header for the portable functions to interact with the HW of the keyboards. The functions must be implemented in the platform-specific code. More...

#include <stdint.h>
#include <stdbool.h>

Macros

#define PORT_KEYBOARD_MAIN_ID
 
#define PORT_KEYBOARDS_TIMEOUT_MS
 
#define PORT_KEYBOARD_MAIN_DEBOUNCE_TIME_MS
 

Enumerations

enum  PORT_KEYBOARD_COL_IDS {
  PORT_KEYBOARD_COL_0,
  PORT_KEYBOARD_COL_1,
  PORT_KEYBOARD_COL_2,
  PORT_KEYBOARD_COL_3
}
 Enumeration to define the columns indexes of the keyboard. This enumeration is used to identify the columns when handling the interrupts. More...
 

Functions

void port_keyboard_init (uint8_t keyboard_id)
 Configure the HW specifications of a given keyboard. More...
 
void port_keyboard_excite_row (uint8_t keyboard_id, uint8_t row_idx)
 Set the given row to high and lower the others. More...
 
void port_keyboard_start_scan (uint8_t keyboard_id)
 Start the scanning of a keyboard. More...
 
void port_keyboard_stop_scan (uint8_t keyboard_id)
 Stop the scanning of a keyboard. More...
 
void port_keyboard_excite_next_row (uint8_t keyboard_id)
 Update the row to be excited. More...
 
bool port_keyboard_get_key_pressed_status (uint8_t keyboard_id)
 Return the status of the keyboard (pressed or not). More...
 
void port_keyboard_set_key_pressed_status (uint8_t keyboard_id, bool status)
 Set the status of the keyboard (pressed or not). More...
 
bool port_keyboard_get_row_timeout_status (uint8_t keyboard_id)
 Return the status of the column timeout flag. More...
 
void port_keyboard_set_row_timeout_status (uint8_t keyboard_id, bool status)
 Set the status of the row timeout flag. More...
 
char port_keyboard_get_key_value (uint8_t keyboard_id)
 Return the char representing the key pressed of a given keyboard based on its row that is being excited. This assumes that the matrix of chars is flattened (i.e., it is not a 2D array, but all rows are in a single array), thus it is necessary to calculate only one index. More...
 
char port_keyboard_get_invalid_key_value (uint8_t keyboard_id)
 Return the null key value of a given keyboard. More...
 

Detailed Description

Header for the portable functions to interact with the HW of the keyboards. The functions must be implemented in the platform-specific code.

Author
Sistemas Digitales II
Date
2026-01-01

Macro Definition Documentation

◆ PORT_KEYBOARD_MAIN_DEBOUNCE_TIME_MS

#define PORT_KEYBOARD_MAIN_DEBOUNCE_TIME_MS

Keyboard's keys debounce time in milliseconds

◆ PORT_KEYBOARD_MAIN_ID

#define PORT_KEYBOARD_MAIN_ID

Keyboard identifier that represents the keyboard of the system

◆ PORT_KEYBOARDS_TIMEOUT_MS

#define PORT_KEYBOARDS_TIMEOUT_MS

Keyboard scanning timeout in milliseconds

Enumeration Type Documentation

◆ PORT_KEYBOARD_COL_IDS

Enumeration to define the columns indexes of the keyboard. This enumeration is used to identify the columns when handling the interrupts.

Enumerator
PORT_KEYBOARD_COL_0 

First column of the keyboard

PORT_KEYBOARD_COL_1 

Second column of the keyboard

PORT_KEYBOARD_COL_2 

Third column of the keyboard

PORT_KEYBOARD_COL_3 

Fourth column of the keyboard

Function Documentation

◆ port_keyboard_excite_next_row()

void port_keyboard_excite_next_row ( uint8_t  keyboard_id)

Update the row to be excited.

✅ 1. Update the current_excited_row to move to the next row. If the index equals or greater than the number of rows indicated in the layout, move to the first row.
    💡 You can use the % (modulo) operator to get the remainder of the division
✅ 2. Call the function port_keyboard_excite_row() to excite the new row.

Parameters
keyboard_idKeyboard ID. This index is used to get the correct keyboard status struct.

◆ port_keyboard_excite_row()

void port_keyboard_excite_row ( uint8_t  keyboard_id,
uint8_t  row_idx 
)

Set the given row to high and lower the others.

TODO alumnos:

✅ 1. Retrieve the keyboard configuration struct calling _stm32f4_keyboard_get()
✅ 2. Iterate through all the rows indexes (you can get the number of rows from the keyboard's layout) and set them to LOW to ensure that only one row is excited at the same time.
✅ 3. Set the given row to HIGH.
    💡 You can use the BSRR or call the stm32f4_system_gpio_write() function.

Parameters
keyboard_idID of the keyboard to be scanned.
row_idxIndex of the row to be excited.

◆ port_keyboard_get_invalid_key_value()

char port_keyboard_get_invalid_key_value ( uint8_t  keyboard_id)

Return the null key value of a given keyboard.

This function retrieves the null key value defined in the keyboard layout.

TODO alumnos:

✅ 1. Retrieve and return the null_key field from the keyboard layout. Call the function _stm32f4_keyboard_get() to get the keyboard struct.

Parameters
keyboard_id
Returns
char

◆ port_keyboard_get_key_pressed_status()

bool port_keyboard_get_key_pressed_status ( uint8_t  keyboard_id)

Return the status of the keyboard (pressed or not).

TODO alumnos:

✅ 1. Return the value of the field flag_key_pressed. Call the function _stm32f4_keyboard_get() to get the keyboard struct.

Parameters
keyboard_idKeyboard ID. This index is used to get the correct keyboard status struct.
Returns
true If the keyboard has been pressed
false If the keyboard has not been pressed

◆ port_keyboard_get_key_value()

char port_keyboard_get_key_value ( uint8_t  keyboard_id)

Return the char representing the key pressed of a given keyboard based on its row that is being excited. This assumes that the matrix of chars is flattened (i.e., it is not a 2D array, but all rows are in a single array), thus it is necessary to calculate only one index.

✅ 1. Determine the value (char) of the key pressed based on the index of the current scanned row and the index of the column that provoked the interrupt, and return it.
    💡 You can calculate the key index as: key index = (excited row * num columns) + column interrupting.

Parameters
keyboard_idKeyboard ID. This index is used to get the correct keyboard status struct.
Returns
char Key value of the key pressed.

◆ port_keyboard_get_row_timeout_status()

bool port_keyboard_get_row_timeout_status ( uint8_t  keyboard_id)

Return the status of the column timeout flag.

TODO alumnos:

✅ 1. Return the value of the field flag_row_timeout. Call the function _stm32f4_keyboard_get() to get the keyboard struct.

Parameters
keyboard_idKeyboard ID. This index is used to get the correct keyboard status struct.
Returns
true If the column timeout has occurred
false If the column timeout has not occurred

◆ port_keyboard_init()

void port_keyboard_init ( uint8_t  keyboard_id)

Configure the HW specifications of a given keyboard.

Assuming we are using an STM32F4-based platform, this function must call the following functions:

TODO alumnos:

✅ 1. Retrieve the keyboard configuration struct calling _stm32f4_keyboard_get()
✅ 2. Call function stm32f4_system_gpio_config() with the right arguments to configure the rows as outputs with no pull up neither pull down connections (you can get the number of rows from the keyboard's layout).
✅ 3. Call function stm32f4_system_gpio_config() with the right arguments to configure the columns as inputs with pull down connections. Call also function stm32f4_system_gpio_config_exti() with the right parameters to to configure interruption mode in rising and falling edges and enabling the interrupt line for each column. Finally, call function stm32f4_system_gpio_exti_enable() with priority level to 1 and the subpriority level to 1 for all columns. All keyboards will have the same priority levels for their columns in the basic implementation. You can get the number of columns from the keyboard's layout.
✅ 4. Clean/set all the fields of the keyboard struct to their initial values. Set the value of current_excited_row to -1 to indicate that no row is being excited at the beginning.
✅ 5. Configure the timer that controls the duration of the column scanning by calling the function _timer_scan_column_config()

    💡 If any of the IRQs associated with the EXTI lines of the columns coincides with other IRQs in the system, the priority levels of this IRQ will be equal to the priority levels of the other peripheral.

Parameters
keyboard_idKeyboard ID. This index is used to select the element of the keyboards_arr[] array

◆ port_keyboard_set_key_pressed_status()

void port_keyboard_set_key_pressed_status ( uint8_t  keyboard_id,
bool  status 
)

Set the status of the keyboard (pressed or not).

This function is used to update the status of the keyboard when a key press is detected or cleared.

TODO alumnos:

✅ 1. Set the value of the field flag_key_pressed to the given status. Call the function _stm32f4_keyboard_get() to get the keyboard struct.

Parameters
keyboard_id
status

◆ port_keyboard_set_row_timeout_status()

void port_keyboard_set_row_timeout_status ( uint8_t  keyboard_id,
bool  status 
)

Set the status of the row timeout flag.

This function is used to update the status of the row timeout flag when a timeout occurs or is cleared.

TODO alumnos:

✅ 1. Set the value of the field flag_row_timeout to the given status. Call the function _stm32f4_keyboard_get() to get the keyboard struct.

Parameters
keyboard_idKeyboard ID. This index is used to get the correct keyboard status struct.
statusNew status of the row timeout flag.

◆ port_keyboard_start_scan()

void port_keyboard_start_scan ( uint8_t  keyboard_id)

Start the scanning of a keyboard.

This function starts the scanning of a keyboard by enabling the timer that controls the duration of the column scanning and setting the first row to HIGH.

TODO alumnos:

✅ 1. Reset the flag_row_timeout to indicate that a new scan is starting.
✅ 2. Reset the counter (CNT) of the timer.
✅ 3. Set the first row to be excited to HIGH and the others to LOW. You must use the appropiate function to do it.
✅ 4. Enable the timer interrupt in the NVIC using the NVIC_EnableIRQ() function and the TIMx_IRQn interrupt. ✅ 5. Enable the counter of the timer (register CR1 of the timer) to start the column scanning.

Parameters
keyboard_idKeyboard ID. This index is used to get the correct keyboard status struct.

◆ port_keyboard_stop_scan()

void port_keyboard_stop_scan ( uint8_t  keyboard_id)

Stop the scanning of a keyboard.

TODO alumnos:

✅ 1. Disable the counter of the timer (register CR1 of the timer) to stop the column scanning.
✅ 2. Disable the timer interrupt in the NVIC using the NVIC_DisableIRQ() function and the TIMx_IRQn interrupt.
✅ 3. Set all rows to LOW.

Parameters
keyboard_idKeyboard ID. This index is used to get the correct keyboard status struct.