#include <stdio.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "freertos/event_groups.h"
// Attempt to create the event group.
xCreatedEventGroup = xEventGroupCreate();
// Was the event group created successfully?
if( xCreatedEventGroup == NULL )
{
// The event group was not created because there was insufficient
// FreeRTOS heap available.
}
else
{
// The event group was created.
}
// Bits
#define BIT_0 ( 1 << 0 )
#define BIT_1 ( 1 << 1 )
// Bits usados para sincronizar las tareas de lectura y actuliazacion
// del estado del keypad
#define KEYPAD_READY_TO_READ BIT_0
#define KEYPAD_STATE_UPDATE BIT_1
// Keypad 4x4
#define ROW_1_PIN GPIO_NUM_34
#define ROW_2_PIN GPIO_NUM_35
#define ROW_3_PIN GPIO_NUM_36
#define ROW_4_PIN GPIO_NUM_37
#define COL_1_PIN GPIO_NUM_18
#define COL_2_PIN GPIO_NUM_19
#define COL_3_PIN GPIO_NUM_21
#define COL_4_PIN GPIO_NUM_22
void setup_gpio(void);
void leer_keypad_4x4_task(void*);
void mostrar_keypad_4x4_task(void*);
static uint8_t estado_matriz[4][4];
static EventGroupHandle_t xKeypadEvents = NULL;
void app_main() {
printf("Hello, Wokwi!\n");
while (true) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void setup_gpio(void)
{
// Keypad 4x4
gpio_config_t keypad_conf = {};
// Configurar como entrada las filas del teclado
keypad_conf.pin_bit_mask =
(1ULL << ROW_1_PIN) | (1ULL << ROW_2_PIN) |
(1ULL << ROW_3_PIN) | (1ULL << ROW_4_PIN);
keypad_conf.mode = GPIO_MODE_INPUT;
keypad_conf.pull_up_en = GPIO_PULLUP_ENABLE;
keypad_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
keypad_conf.intr_type = GPIO_INTR_DISABLE;
//configure GPIO with the given settings
gpio_config(&keypad_conf);
// Configurar como salida las columnas del teclado
keypad_conf.pin_bit_mask =
(1ULL << COL_1_PIN) | (1ULL << COL_2_PIN) |
(1ULL << COL_3_PIN) | (1ULL << COL_4_PIN);
keypad_conf.mode = GPIO_MODE_OUTPUT;
keypad_conf.pull_up_en = GPIO_PULLUP_DISABLE;
keypad_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
keypad_conf.intr_type = GPIO_INTR_DISABLE;
//configure GPIO with the given settings
gpio_config(&keypad_conf);
}
void leer_keypad_4x4_task(void *pvParameters)
{
const uint8_t rows_pins[4] = {ROW_1_PIN, ROW_2_PIN, ROW_3_PIN, ROW_4_PIN};
const uint8_t cols_pins[4] = {COL_1_PIN, COL_2_PIN, COL_3_PIN, COL_4_PIN};
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
EventBits_t uxBits;
while (true) {
uxBits = xEventGroupWaitBits(
xKeypadEvents,
KEYPAD_READY_TO_READ,
pdTRUE, // KEYPAD_READY_TO_READ should be cleared before returning.
pdTRUE, // Wait for all bits
xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
if( ( uxBits & KEYPAD_READY_TO_READ ) != 0 )
{
// xEventGroupWaitBits() returned because KEYPAD_READY_TO_READ was set.
for (uint8_t col = 0; col < 4; col++) {
gpio_set_level(cols_pins[0], !(col == 0));
gpio_set_level(cols_pins[1], !(col == 1));
gpio_set_level(cols_pins[2], !(col == 2));
gpio_set_level(cols_pins[3], !(col == 3));
for (uint8_t row = 0; row < 4; row++) {
if ( !gpio_get_level(rows_pins[row]) ) {
vTaskDelay(50 / portTICK_PERIOD_MS); // quitar rebote
estado_matriz[row][col] = !gpio_get_level(rows_pins[row]);
}
}
}
xEventGroupSetBits(xKeypadEvents, KEYPAD_STATE_UPDATE );
vTaskDelay(500 / portTICK_PERIOD_MS); // Esperar al menos 500 ms antes de volver a leer
}
}
}
void mostrar_keypad_4x4_task(void*)
{
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
EventBits_t uxBits;
while (true) {
uxBits = xEventGroupWaitBits(
xKeypadEvents,
KEYPAD_STATE_UPDATE,
pdTRUE, // KEYPAD_STATE_UPDATE should be cleared before returning.
pdTRUE, // Wait for all bits
xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
if( ( uxBits & KEYPAD_STATE_UPDATE ) != 0 )
{
// xEventGroupWaitBits() returned because KEYPAD_STATE_UPDATE was set.
for (uint8_t col = 0; col < 4; col++) {
gpio_set_level(cols_pins[0], !(col == 0));
gpio_set_level(cols_pins[1], !(col == 1));
gpio_set_level(cols_pins[2], !(col == 2));
gpio_set_level(cols_pins[3], !(col == 3));
for (uint8_t row = 0; row < 4; row++) {
if ( !gpio_get_level(rows_pins[row]) ) {
vTaskDelay(50 / portTICK_PERIOD_MS); // quitar rebote
estado_matriz[row][col] = !gpio_get_level(rows_pins[row]);
}
}
}
xEventGroupSetBits(xKeypadEvents, KEYPAD_READY_TO_READ);
vTaskDelay(2000 / portTICK_PERIOD_MS); // Actulizar el estado cada 2 seg
}
}
while (true) {
for (uint8_t col = 0; col < 4; col++) {
gpio_set_level(cols_pins[0], !(col == 0));
gpio_set_level(cols_pins[1], !(col == 1));
gpio_set_level(cols_pins[2], !(col == 2));
gpio_set_level(cols_pins[3], !(col == 3));
for (uint8_t row = 0; row < 4; row++) {
if ( !gpio_get_level(rows_pins[row]) ) {
vTaskDelay(50 / portTICK_PERIOD_MS); // quitar rebote
estado_matriz[row][col] = !gpio_get_level(rows_pins[row]);
}
}
}
vTaskDelay(500 / portTICK_PERIOD_MS);
}
pritf("Sensor Matrix State: \n");
for (uint8_t row = 0; row < 4; row++) {
if ( !gpio_get_level(rows_pins[row]) ) {
vTaskDelay(50 / portTICK_PERIOD_MS); // quitar rebote
estado_matriz[row][col] = !gpio_get_level(rows_pins[row]);
}
}
}
pritf("Row 1: " "%" PRIu8 "%" PRIu8 "%" PRIu8 "%" PRIu8,
estado_matriz[0][0]);
Row 1: 0 1 0 0
Row 2: 1 0 1 0
Row 3: 0 0 0 1
Row 4: 1 1 0 0")
for ()
}