From 1e6e8a2062923b434b2f4f5f2a9f8c0098135b01 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 28 Jun 2020 16:09:04 +0200 Subject: hid fw working as intended --- hid-dials/Src/main.c | 197 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file 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 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){ -- cgit