
#include <Wire.h>
#include <Keyboard.h>
#define MCP1_ADDR 0x20
#define MCP2_ADDR 0x21
#define GPIOA 0x12
#define GPIOB 0x13
#define IODIRA 0x00
#define IODIRB 0x01
#define GPPUA 0x0C
#define GPPUB 0x0D
#define DEBOUNCE_MS 40
struct KeyDef {
uint8_t key;
};
KeyDef keymap[32] = {
{'1'}, {'2'}, {'3'}, {'4'}, {'5'}, {'6'}, {'7'}, {'8'},
{'9'}, {'0'}, {'q'}, {'w'}, {'e'}, {'r'}, {'t'}, {'y'},
{'u'}, {'i'}, {'o'}, {'p'}, {'a'}, {'s'}, {'d'}, {'f'},
{'g'}, {'h'}, {'j'}, {'k'}, {'l'}, {'z'}, {'x'}, {'c'}
};
uint8_t last_state[4] = {0xFF,0xFF,0xFF,0xFF};
unsigned long debounce_time[32];
void mcp_write(uint8_t addr, uint8_t reg, uint8_t val)
{
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.write(val);
Wire.endTransmission();
}
uint8_t mcp_read(uint8_t addr, uint8_t reg)
{
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(addr,(uint8_t)1);
if(Wire.available())
return Wire.read();
return 0xFF;
}
void sendShortcut(uint8_t key)
{
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press(key);
delay(5);
Keyboard.releaseAll();
}
void processBank(uint8_t current, uint8_t bank)
{
unsigned long now = millis();
for(uint8_t i=0;i<8;i++)
{
bool pressed_now = !(current & (1<<i));
bool pressed_last = !(last_state[bank] & (1<<i));
uint8_t key_index = bank*8 + i;
if(pressed_now != pressed_last)
{
if(now - debounce_time[key_index] > DEBOUNCE_MS)
{
debounce_time[key_index] = now;
if(pressed_now)
{
sendShortcut(keymap[key_index].key);
}
}
}
}
last_state[bank] = current;
}
void setup()
{
Wire.begin();
Keyboard.begin();
mcp_write(MCP1_ADDR,IODIRA,0xFF);
mcp_write(MCP1_ADDR,IODIRB,0xFF);
mcp_write(MCP2_ADDR,IODIRA,0xFF);
mcp_write(MCP2_ADDR,IODIRB,0xFF);
mcp_write(MCP1_ADDR,GPPUA,0xFF);
mcp_write(MCP1_ADDR,GPPUB,0xFF);
mcp_write(MCP2_ADDR,GPPUA,0xFF);
mcp_write(MCP2_ADDR,GPPUB,0xFF);
last_state[0] = mcp_read(MCP1_ADDR,GPIOA);
last_state[1] = mcp_read(MCP1_ADDR,GPIOB);
last_state[2] = mcp_read(MCP2_ADDR,GPIOA);
last_state[3] = mcp_read(MCP2_ADDR,GPIOB);
}
void loop()
{
uint8_t m1a = mcp_read(MCP1_ADDR,GPIOA);
uint8_t m1b = mcp_read(MCP1_ADDR,GPIOB);
uint8_t m2a = mcp_read(MCP2_ADDR,GPIOA);
uint8_t m2b = mcp_read(MCP2_ADDR,GPIOB);
processBank(m1a,0);
processBank(m1b,1);
processBank(m2a,2);
processBank(m2b,3);
delay(5);
}
https://www.printables.com/model/1691052-streamdeck-diy