Created
May 25, 2020 18:24
-
-
Save AnthonyDiGirolamo/c240e49642f4748adf9d3e0a02da0a01 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Wire.h> | |
#include "Adafruit_MCP23017.h" | |
Adafruit_MCP23017 mcp; | |
#define NUM_ROWS 5 | |
#define NUM_COLS 10 | |
uint32_t hold_time[NUM_ROWS][NUM_COLS]; | |
char key_matrix[NUM_ROWS][NUM_COLS] = { | |
{'<', '^', 'v', '>', '1', '2', '3', '4', '5', '6'}, | |
{'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'}, | |
{'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '7'}, | |
{'S', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', 'B'}, | |
{'T', 'C', 'A', 'F', ' ', ' ', 'A', 'C', 'S', '\n'}, | |
}; | |
// bit positions | |
#define COL0 0 // PORTA | |
#define COL1 1 // PORTA | |
#define ROW0 2 // PORTA | |
#define ROW1 3 // PORTA | |
#define ROW2 4 // PORTA | |
#define ROW3 5 // PORTA | |
#define ROW4 6 // PORTA | |
// nothing on PORTA pin 7 | |
#define COL8 8+0 // PORTB | |
#define COL9 8+1 // PORTB | |
#define COL2 8+2 // PORTB | |
#define COL3 8+3 // PORTB | |
#define COL4 8+4 // PORTB | |
#define COL5 8+5 // PORTB | |
#define COL6 8+6 // PORTB | |
#define COL7 8+7 // PORTB | |
uint8_t col_bit_positions[] = { | |
COL0, | |
COL1, | |
COL2, | |
COL3, | |
COL4, | |
COL5, | |
COL6, | |
COL7, | |
COL8, | |
COL9, | |
}; | |
uint8_t row_bit_positions[] = { | |
ROW0, | |
ROW1, | |
ROW2, | |
ROW3, | |
ROW4, | |
}; | |
uint16_t last_row_read[NUM_ROWS]; | |
uint16_t this_row_read[NUM_ROWS]; | |
void setup() { | |
Serial.begin(115200); | |
delay(2000); | |
for (uint8_t row=0; row<NUM_ROWS; row++) { | |
last_row_read[row] = 0; | |
for (uint8_t col=0; col<NUM_COLS; col++) { | |
hold_time[row][col] = 0; | |
} | |
} | |
Serial.println("mcp.begin"); | |
mcp.begin(); // use default address 0 | |
// // All pins as inputs | |
// mcp.writeRegister(MCP23017_IODIRA, b11111111); | |
// mcp.writeRegister(MCP23017_IODIRB, b11111111); | |
// // All pull-ups | |
// mcp.writeRegister(MCP23017_GPPUA, b11111111); | |
// mcp.writeRegister(MCP23017_GPPUB, b11111111); | |
// Set all pin output to 0 | |
mcp.writeGPIOAB(0); | |
Serial.println("iodir"); | |
// COLS as inputs ROWS as outputs | |
mcp.writeRegister(MCP23017_IODIRA, 0x03); // b00000011 | |
mcp.writeRegister(MCP23017_IODIRB, 0xFF); // b11111111 | |
Serial.println("gppu"); | |
// Pullup COLS | |
mcp.writeRegister(MCP23017_GPPUA, 0x03); // b00000011 | |
mcp.writeRegister(MCP23017_GPPUB, 0xFF); // b11111111 | |
pinMode(13, OUTPUT); // use the p13 LED as debugging | |
} // setup() | |
// Set the row pin we want to scan to LOW (ground) and all others to HIGH | |
// row: 0-4 | |
void activate_row(uint8_t row) { | |
// Set current ROW output to LOW | |
uint8_t current_row; | |
current_row = 1 << (row+2); // ROW=0: current_row = 00000100 | |
current_row = current_row ^ 0x7C; // ROW=0: current_row = 01111000 | |
mcp.writeRegister(MCP23017_GPIOA, current_row); | |
} | |
void activate_cols() { | |
// ROWS as inputs COLS as outputs | |
mcp.writeRegister(MCP23017_IODIRA, 0x7C); // b01111100 | |
mcp.writeRegister(MCP23017_IODIRB, 0x00); // b00000000 | |
// Pullup ROWS | |
mcp.writeRegister(MCP23017_GPPUA, 0x7C); // b01111100 | |
mcp.writeRegister(MCP23017_GPPUB, 0x00); // b00000000 | |
} | |
void print_16_bits(uint16_t n) { | |
char s[32]; | |
sprintf(s, "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", | |
(n & 0x08000 ? 1 : 0), \ | |
(n & 0x04000 ? 1 : 0), \ | |
(n & 0x02000 ? 1 : 0), \ | |
(n & 0x01000 ? 1 : 0), \ | |
(n & 0x0800 ? 1 : 0), \ | |
(n & 0x0400 ? 1 : 0), \ | |
(n & 0x0200 ? 1 : 0), \ | |
(n & 0x0100 ? 1 : 0), \ | |
(n & 0x080 ? 1 : 0), \ | |
(n & 0x040 ? 1 : 0), \ | |
(n & 0x020 ? 1 : 0), \ | |
(n & 0x010 ? 1 : 0), \ | |
(n & 0x08 ? 1 : 0), \ | |
(n & 0x04 ? 1 : 0), \ | |
(n & 0x02 ? 1 : 0), \ | |
(n & 0x01 ? 1 : 0)); | |
Serial.println(s); | |
} | |
bool button_pressed(uint8_t row, uint8_t button_bit_position) { | |
// !(this button == 0) and (last_button == 1) | |
return (!(this_row_read[row] & (1<<button_bit_position)) | |
&& (last_row_read[row] & (1<<button_bit_position))); | |
} | |
bool button_released(uint8_t row, uint8_t button_bit_position) { | |
// !(this button == 1) and (last_button == 0) | |
return ((this_row_read[row] & (1<<button_bit_position)) | |
&& !(last_row_read[row] & (1<<button_bit_position))); | |
} | |
bool button_held(uint8_t row, uint8_t button_bit_position) { | |
return !(this_row_read[row] & (1<<button_bit_position)); | |
} | |
uint16_t last_update_millis = 0; | |
uint16_t this_update_millis = 0; | |
uint32_t current_hold_time = 0; | |
uint8_t currently_held_key_row = 0; | |
uint8_t currently_held_key_col = 0; | |
void loop() { | |
bool matrix_changed = false; | |
uint8_t row, r, c; | |
uint8_t pressed_or_released = 0; | |
last_update_millis = this_update_millis; | |
// Save last_row_reads | |
for (row=0; row<NUM_ROWS; row++) { | |
last_row_read[row] = this_row_read[row]; | |
} | |
// Update matrix row values | |
for (row=0; row<NUM_ROWS; row++) { | |
activate_row(row); | |
this_row_read[row] = mcp.readGPIOAB(); | |
if (this_row_read[row] != last_row_read[row]) { | |
matrix_changed = true; | |
} | |
} | |
this_update_millis = millis(); | |
if (matrix_changed) { | |
// print out all rows | |
Serial.write("\n\n\n"); | |
Serial.write("Last millis diff: "); | |
Serial.println(this_update_millis - last_update_millis); | |
Serial.println(" C R C"); | |
Serial.println(" 76543298x4321010"); | |
for (r=0; r<NUM_ROWS; r++) { | |
Serial.print("ROW"); Serial.print(r); Serial.print(": "); | |
print_16_bits(this_row_read[r]); | |
} | |
} | |
// update debounce time, maybe not necessary? | |
for (r=0; r<NUM_ROWS; r++) { | |
for (c=0; c<NUM_COLS; c++) { | |
if (button_pressed(r, col_bit_positions[c])) { | |
Serial.print(key_matrix[r][c]); | |
currently_held_key_row = r; | |
currently_held_key_col = c; | |
current_hold_time = this_update_millis - last_update_millis; | |
} | |
else if (button_released(r, col_bit_positions[c])) { | |
current_hold_time = 0; | |
} | |
else if (button_held(r, col_bit_positions[c])) { | |
// only repeat the last key held | |
if (currently_held_key_row == r && currently_held_key_col == c) { | |
if (current_hold_time > 230) { | |
Serial.print(key_matrix[r][c]); | |
current_hold_time = 200; | |
} | |
else { | |
current_hold_time = current_hold_time + (this_update_millis - last_update_millis); | |
} | |
} | |
} | |
// else if (button_held(r, col_bit_positions[c])) { | |
// Serial.print("Held "); | |
// Serial.print(" Row "); | |
// Serial.print(r); | |
// Serial.print(" Col "); | |
// Serial.println(c); | |
// } | |
} | |
} | |
// end update hold_time | |
} // loop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment