diff options
-rw-r--r-- | hid-dials/Src/main.c | 197 |
1 files changed, 167 insertions, 30 deletions
diff --git a/hid-dials/Src/main.c b/hid-dials/Src/main.c index 0aa694f..4ccbca0 100644 --- a/hid-dials/Src/main.c +++ b/hid-dials/Src/main.c @@ -15,10 +15,38 @@ PCD_HandleTypeDef hpcd_USB_FS; void SystemClock_Config(void);
static void MX_GPIO_Init(void);
+static void key_matrix_select(int row);
+static int key_matrix_query(int debounce_time);
+static uint32_t poll_encoders(void);
+static uint32_t poll_keys(void);
enum keybits {
- KEYBITS_VOL_UP = 0x20,
- KEYBITS_VOL_DOWN = 0x40,
+ /* These match up with the record descriptor in usbd_hid.c */
+ KEYBITS_NEXT = 0x01,
+ KEYBITS_PREV = 0x02,
+ KEYBITS_STOP = 0x04,
+ KEYBITS_PLAY_PAUSE = 0x08,
+ KEYBITS_MUTE = 0x10,
+ KEYBITS_VOL_UP = 0x20,
+ KEYBITS_VOL_DOWN = 0x40,
+};
+
+enum key_names {
+ KEY_2 = 0,
+ KEY_3 = 1,
+ KEY_1 = 2,
+ KEY_ENC = 3,
+ KEY_4 = 4
+};
+
+enum keymap_rows {
+ KEYMAP_BOTTOM_LEFT_ENC = 0,
+ KEYMAP_TOP_RIGHT_ENC = 1,
+};
+
+enum key_matrix_params {
+ KEY_MATRIX_ROWS = 5,
+ KEY_MATRIX_COLS = 2,
};
void sendKeybits(uint8_t keybits);
@@ -67,39 +95,69 @@ int main(void) TIM3->EGR = 1; // Generate an update event
TIM3->CR1 = 1; // Enable the counter
- uint16_t tim1_last = TIM1->CNT, tim3_last = TIM3->CNT;
- int vol_delta = 0;
- bool tx_vol_reset = 0;
while (1) {
- uint16_t tim1_now = TIM1->CNT, tim3_now = TIM3->CNT;
- int16_t tim1_delta = (int16_t)(tim1_now - tim1_last);
- int16_t tim3_delta = (int16_t)(tim3_now - tim3_last);
+ uint32_t keybits = poll_encoders();
+ for (int i=0; i<10; i++) {
+ keybits |= poll_keys();
+ HAL_Delay(1);
+ }
+ sendKeybits(keybits);
+ }
+}
+
+static uint32_t poll_encoders() {
+ static bool tx_vol_reset = 0;
+ static uint16_t tim1_last = 0, tim3_last = 0; /* timers init to 0 */
+ static int vol_delta = 0;
+
+ uint16_t tim1_now = TIM1->CNT, tim3_now = TIM3->CNT;
+ int16_t tim1_delta = (int16_t)(tim1_now - tim1_last);
+ int16_t tim3_delta = (int16_t)(tim3_now - tim3_last);
- vol_delta += tim3_delta - tim1_delta;
+ /* Gang both encoders */
+ vol_delta += tim3_delta - tim1_delta;
#define VOL_DELTA_INC 4
- uint8_t keybits = 0;
- if (!tx_vol_reset) {
- if (vol_delta >= VOL_DELTA_INC) {
- keybits |= KEYBITS_VOL_UP;
- vol_delta -= VOL_DELTA_INC;
- tx_vol_reset = 1;
- } else if (vol_delta <= -VOL_DELTA_INC) {
- keybits |= KEYBITS_VOL_DOWN;
- vol_delta += VOL_DELTA_INC;
- tx_vol_reset = 1;
- }
- } else {
- tx_vol_reset = 0;
+ uint8_t keybits = 0;
+ if (!tx_vol_reset) {
+ /* Customize encoder action here */
+ if (vol_delta >= VOL_DELTA_INC) {
+ keybits |= KEYBITS_VOL_UP;
+ vol_delta -= VOL_DELTA_INC;
+ tx_vol_reset = 1;
+ } else if (vol_delta <= -VOL_DELTA_INC) {
+ keybits |= KEYBITS_VOL_DOWN;
+ vol_delta += VOL_DELTA_INC;
+ tx_vol_reset = 1;
}
- sendKeybits(keybits);
-
- tim1_last = tim1_now;
- tim3_last = tim3_now;
- HAL_Delay(10);
+ } else {
+ tx_vol_reset = 0;
}
+
+ tim1_last = tim1_now;
+ tim3_last = tim3_now;
+ return keybits;
}
+static uint32_t poll_keys() {
+ int debounce_time = 5; /* 5 * 10 ms loop timing increments */
+ uint32_t val = key_matrix_query(debounce_time);
+ uint32_t state = val&0xffff, edges = val>>16;
+ uint32_t pressed = state & edges;
+ (void)edges; /* unused */
+ uint32_t keybits = 0;
+
+ if (pressed & (1 << KEY_3))
+ keybits |= KEYBITS_PLAY_PAUSE;
+ if (pressed & (1 << KEY_3 << KEY_MATRIX_ROWS))
+ keybits |= KEYBITS_PREV;
+ if (pressed & (1 << KEY_4 << KEY_MATRIX_ROWS))
+ keybits |= KEYBITS_NEXT;
+ if (pressed & (1 << KEY_ENC << KEY_MATRIX_ROWS))
+ keybits |= KEYBITS_MUTE;
+
+ return keybits;
+}
const uint8_t _asciimap[128] =
{
@@ -308,14 +366,93 @@ static void MX_GPIO_Init(void) { __HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
- GPIOA->MODER = 0x28000000 | (2<<(8*2)) | (2<<(9*2));
- GPIOB->MODER = (2<<(4*2)) | (2<<(5*2));
- GPIOA->PUPDR = 0x24000000 | (1<<(8*2)) | (1<<(9*2));
+ /* Left encoder (SW2) A/B inputs: PA9/PA8 (TIM1 CH1/2)
+ * Right encoder (SW7) A/B inputs: PB4/PB5 (TIM3 CH1/2)
+ * Key matrix: PB2 -> encoder switches left/right
+ * PB8 -> SW3/8
+ * PB1 -> SW4/9
+ * PA15 -> SW5/10
+ * PA0 -> SW6/11
+ * key matrix inputs: PA1/PA4
+ *
+ * Physical key layout:
+ *
+ * +------------|USB|------------+
+ * | SW9 SW11 SW10 SW8 |
+ * | SW2 SW7 |
+ * | SW4 SW6 SW5 SW3 |
+ * +-----------------------------+
+ *
+ * Logical key layout:
+ *
+ * +------------|USB|------------+
+ * | KT1 KT2 KT3 KT4 |
+ * | EL ER |
+ * | KB1 KB2 KB3 KB4 |
+ * +-----------------------------+
+ *
+ */
+ GPIOA->MODER = 0x28000000 | (2<<(8*2)) | (2<<(9*2)) | (1<<(15*2))| (1<<(0*2));
+ GPIOB->MODER = (2<<(4*2)) | (2<<(5*2)) | (1<<(1*2)) | (1<<(2*2)) | (1<<(8*2));
+ GPIOA->PUPDR = 0x24000000 | (1<<(8*2)) | (1<<(9*2)) | (2<<(1*2)) | (2<<(4*2));
GPIOB->PUPDR = (1<<(4*2)) | (1<<(5*2));
GPIOA->AFR[1]= 0x00000022;
GPIOB->AFR[0]= 0x00110000;
}
+static void key_matrix_select(int row) {
+ uint16_t bsrr_a = 0, bsrr_b = 0;
+ /* A0 -> A15 -> B1 -> B2 -> B8 */
+ switch (row) {
+ case 0: bsrr_a = 1<<0; break;
+ case 1: bsrr_a = 1<<15; break;
+ case 2: bsrr_b = 1<<1; break;
+ case 3: bsrr_b = 1<<2; break;
+ case 4: bsrr_b = 1<<8; break;
+ }
+ uint16_t mask_a = (1<<15) | (1<<0), mask_b = (1<<1) | (1<<2) | (1<<8);
+ /* Reset all pins except for selected pin */
+ GPIOA->BSRR = (mask_a<<16) ^ ((bsrr_a<<16) | bsrr_a) ;
+ GPIOB->BSRR = (mask_b<<16) ^ ((bsrr_b<<16) | bsrr_b) ;
+}
+
+static int key_matrix_query(int debounce_time) {
+ static int debounce_states[KEY_MATRIX_COLS][KEY_MATRIX_ROWS] = {0};
+ static int key_matrix_row = -1;
+ static uint32_t matrix_state = 0;
+ uint32_t matrix_state_edges = 0;
+ if (key_matrix_row < 0) { /* On first iteration just set outputs and return */
+ key_matrix_row = 0;
+ key_matrix_select(0);
+ return 0;
+ }
+
+ int input = GPIOA->IDR;
+ int pressed[KEY_MATRIX_COLS] = { input & (1<<4), input & (1<<1) };
+ for (int i=0; i<KEY_MATRIX_COLS; i++) {
+ if (debounce_states[i][key_matrix_row] > 0) {
+ /* debounce timer running */
+ debounce_states[i][key_matrix_row]--;
+ } else {
+ uint32_t bit = 1 << key_matrix_row << (KEY_MATRIX_ROWS * i);
+ uint32_t old_matrix_state = matrix_state;
+ if (pressed[i])
+ matrix_state |= bit;
+ else
+ matrix_state &= ~bit;
+
+ uint32_t edge = old_matrix_state ^ matrix_state;
+ if (edge)
+ debounce_states[i][key_matrix_row] = debounce_time;
+ matrix_state_edges |= edge;
+ }
+ }
+
+ key_matrix_row = (key_matrix_row+1) % KEY_MATRIX_ROWS;
+ key_matrix_select(key_matrix_row);
+ return (matrix_state_edges<<16) | matrix_state;
+}
+
void Error_Handler(void)
{
while(1){
|