Skip to content

Commit

Permalink
Working version
Browse files Browse the repository at this point in the history
  • Loading branch information
pjsg committed Feb 4, 2024
1 parent 92f5075 commit c3300a8
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 49 deletions.
69 changes: 26 additions & 43 deletions components/modules/matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* Then we disable all the columns and then drive each column low in turn. Hopefully
* one of the rows will go low. This is a keypress. We only report the first keypress found.
* we start a timer to handle debounce.
* On timer expiry, see if any key is pressed, if so, just wait agin (maybe should use interrupts)
* On timer expiry, see if any key is pressed, if so, just wait again
* If no key is pressed, run timer again. On timer expiry, re-enable interrupts.
*
* Philip Gladstone, N1DQ
Expand All @@ -21,14 +21,8 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>


#include <stdio.h>

#include "driver/gpio.h"

#define M_DEBUG printf

#define MATRIX_PRESS_INDEX 0
#define MATRIX_RELEASE_INDEX 1

Expand Down Expand Up @@ -65,7 +59,6 @@ typedef struct {
uint32_t write_offset; // Accessed by ISR
uint8_t last_character;
matrix_event_t queue[QUEUE_SIZE];
void *callback_arg;
} DATA;

static task_handle_t tasknumber;
Expand Down Expand Up @@ -93,24 +86,24 @@ static void lmatrix_timer_done(void *param);
d->read_offset++; \
}

static void set_gpio_mode_input(int pin, gpio_int_type_t intr) {
static esp_err_t set_gpio_mode_input(int pin, gpio_int_type_t intr) {
gpio_config_t config = {.pin_bit_mask = 1LL << pin,
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = intr};

gpio_config(&config);
return gpio_config(&config);
}

static void set_gpio_mode_output(int pin) {
static esp_err_t set_gpio_mode_output(int pin) {
gpio_config_t config = {.pin_bit_mask = 1LL << pin,
.mode = GPIO_MODE_OUTPUT_OD,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE
};

gpio_config(&config);
return gpio_config(&config);
}

static void set_columns(DATA *d, int level) {
Expand All @@ -119,15 +112,19 @@ static void set_columns(DATA *d, int level) {
}
}

static void initialize_pins(DATA *d) {
static void initialize_pins(lua_State *L, DATA *d) {
for (int i = 0; i < d->column_count; i++) {
set_gpio_mode_output(d->columns[i]);
if (set_gpio_mode_output(d->columns[i]) != ESP_OK) {
luaL_error(L, "Unable to configure pins");
}
}

set_columns(d, 0);

for (int i = 0; i < d->row_count; i++) {
set_gpio_mode_input(d->rows[i], GPIO_INTR_NEGEDGE);
if (set_gpio_mode_input(d->rows[i], GPIO_INTR_NEGEDGE) != ESP_OK) {
luaL_error(L, "Unable to configure pins");
}
}
}

Expand All @@ -138,7 +135,7 @@ static void disable_row_interrupts(DATA *d) {
}

// Just takes the channel number. Cleans up the resources used.
int matrix_close(DATA *d) {
static int matrix_close(DATA *d) {
if (!d) {
return 0;
}
Expand All @@ -157,7 +154,7 @@ int matrix_close(DATA *d) {
}

// Character returned is 0 .. max if pressed. -1 if not.
static int matrix_get_character(DATA *d, bool trace)
static int matrix_get_character(DATA *d)
{
set_columns(d, 1);
disable_row_interrupts(d);
Expand All @@ -167,16 +164,11 @@ static int matrix_get_character(DATA *d, bool trace)
// We are either waiting for a negative edge (keypress) or a positive edge
// (keyrelease)

//M_DEBUG("matrix_get_character called\n");

for (int i = 0; i < d->column_count && character < 0; i++) {
gpio_set_level(d->columns[i], 0);

for (int j = 0; j < d->row_count && character < 0; j++) {
if (gpio_get_level(d->rows[j]) == 0) {
if (trace) {
//M_DEBUG("Found keypress at %d %d\n", i, j);
}
// We found a keypress
character = j * d->column_count + i;
}
Expand All @@ -185,15 +177,12 @@ static int matrix_get_character(DATA *d, bool trace)
gpio_set_level(d->columns[i], 1);
}

//M_DEBUG("returning %d\n", character);

return character;
}

static void matrix_queue_character(DATA *d, int character)
{
// If character is >= 0 then we have found the character -- so send it.
// M_DEBUG("Skipping queuing\n");

if ((d->state == WAITING_FOR_PRESS && character >= 0) || (d->state == WAITING_FOR_RELEASE && character < 0)) {
if (character >= 0) {
Expand All @@ -218,15 +207,15 @@ static void matrix_interrupt(void *arg) {
// This function runs with high priority
DATA *d = (DATA *)arg;

int character = matrix_get_character(d, false);
int character = matrix_get_character(d);

matrix_queue_character(d, character);

d->state = character >= 0 ? WAITING_FOR_RELEASE : WAITING_FOR_PRESS;
esp_timer_start_once(d->timer_handle, 5000);
}

bool matrix_has_queued_event(DATA *d) {
static bool matrix_has_queued_event(DATA *d) {
if (!d) {
return false;
}
Expand Down Expand Up @@ -321,7 +310,9 @@ static void callback_call(lua_State* L, DATA *d, int cbnum, int key, uint32_t ti
if (d) {
lua_rawgeti(L, LUA_REGISTRYINDEX, d->character_ref);
lua_rawgeti(L, -1, key);
callback_callOne(L, d->callback[cbnum], 1 << cbnum, -1, time);
if (lua_type(L, -1) != LUA_TNIL) {
callback_callOne(L, d->callback[cbnum], 1 << cbnum, -1, time);
}
lua_pop(L, 2);
}
}
Expand All @@ -338,16 +329,16 @@ static void getpins(lua_State *L, int argno, int count, uint8_t *dest)
// Lua: setup({cols}, {rows}, {characters})
static int lmatrix_setup( lua_State* L )
{
// Get the sizes of the first two tables
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TTABLE);
luaL_checktype(L, 3, LUA_TTABLE);

// Get the sizes of the first two tables
size_t columns = lua_rawlen(L, 1);
size_t rows = lua_rawlen(L, 2);

if (columns > 255 || rows > 255) {
return luaL_error(L, "Too many rows or columns");
if (columns > 255 || rows > 255 || !rows || !columns) {
return luaL_error(L, "Number of rows or columns out of range");
}

DATA *d = (DATA *)lua_newuserdata(L, sizeof(DATA) + rows + columns);
Expand All @@ -368,6 +359,8 @@ static int lmatrix_setup( lua_State* L )
.arg = d
};

d->open = true;

esp_timer_create(&timer_args, &d->timer_handle);

for (int i = 0; i < CALLBACK_COUNT; i++) {
Expand All @@ -378,12 +371,10 @@ static int lmatrix_setup( lua_State* L )
lua_pushvalue(L, 3);
d->character_ref = luaL_ref(L, LUA_REGISTRYINDEX);

d->open = true;

for (int i = 0; i < d->row_count; i++) {
gpio_isr_handler_add(d->rows[i], matrix_interrupt, d);
}
initialize_pins(d);
initialize_pins(L, d);

return 1;
}
Expand Down Expand Up @@ -454,9 +445,7 @@ static void lmatrix_timer_done(void *param)

// We need to see if the key is still pressed, and if so, enable rising edge interrupts

int character = matrix_get_character(d, true);

//M_DEBUG("Timer fired with character %d (waiting for release %d)\n", character, d->state);
int character = matrix_get_character(d);

matrix_queue_character(d, character);

Expand All @@ -468,8 +457,6 @@ static void lmatrix_timer_done(void *param)
d->state = WAITING_FOR_PRESS;
}

//M_DEBUG("Timer: Waiting for release is %d\n", d->state);

if (d->state == WAITING_FOR_PRESS) {
for (int i = 0; i < d->row_count; i++) {
gpio_set_intr_type(d->rows[i], GPIO_INTR_NEGEDGE);
Expand All @@ -484,8 +471,6 @@ static void lmatrix_task(task_param_t param, task_prio_t prio)
{
(void) prio;

//M_DEBUG("Task invoked\n");

bool need_to_post = false;
lua_State *L = lua_getstate();

Expand All @@ -500,8 +485,6 @@ static void lmatrix_task(task_param_t param, task_prio_t prio)
// If there is pending stuff, queue another task
task_post_medium(tasknumber, param);
}

//M_DEBUG("Task done\n");
}


Expand Down
10 changes: 4 additions & 6 deletions docs/modules/matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ in all.

## Sources for parts

- Amazon: This [search](http://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Dindustrial&field-keywords=rotary+encoder+push+button&rh=n%3A16310091%2Ck%3Arotary+encoder+push+button) shows a variety.
- Ebay: Somewhat cheaper in this [search](http://www.ebay.com/sch/i.html?_from=R40&_trksid=p2050601.m570.l1313.TR0.TRC0.H0.Xrotary+encoder+push+button.TRS0&_nkw=rotary+encoder+push+button&_sacat=0)
- Adafruit: [rotary encoder](https://www.adafruit.com/products/377)
- Aliexpress: This [search](http://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20160217173657&SearchText=rotary+encoder+push+button) reveals all sorts of shapes and sizes.
- Adafruit: [Matrix keypad](https://www.adafruit.com/search?q=matrix+keypad)
- Aliexpress: This [search](https://www.aliexpress.us/w/wholesale-matrix-keypad.html) reveals all sorts of shapes and sizes.

## Constants
- `matrix.PRESS = 1` The eventtype for a keyboard key press
Expand All @@ -36,7 +34,7 @@ The keyboard object.

#### Example

keyboard = matrix.setup({5,6,7}, {8,9,10,11}, { "1", "2", "3", "4", "5", "6", "7", "8", "9", "#", "0", "*"})
keyboard = matrix.setup({17, 4, 18}, {16, 21, 19, 5}, { "1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"})

#### Notes
If an entry in the key characters table is nil, then that key press will not be reported.
Expand All @@ -48,7 +46,7 @@ Sets a callback on specific events.
`keyboard:on(eventtype[, callback])`

#### Parameters
- `eventtype` This defines the type of event being registered. This can be one or more of `matrix.PRESS` and `matrix.RELEASE`.
- `eventtype` This defines the type of event being registered. This can be one or more of `matrix.PRESS` and `matrix.RELEASE`. `matrix.ALL` covers all the event types.
- `callback` This is a function that will be invoked when the specified event happens.

If the callback is None or omitted, then the registration is cancelled.
Expand Down

0 comments on commit c3300a8

Please sign in to comment.