From 6ab94e0b318884bbcb95e2ea3835f951502e1d99 Mon Sep 17 00:00:00 2001 From: jaseg Date: Wed, 14 Oct 2020 12:47:28 +0200 Subject: Move firmware into subdirectory --- fw/hid-dials/Src/main.c | 465 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 465 insertions(+) create mode 100644 fw/hid-dials/Src/main.c (limited to 'fw/hid-dials/Src/main.c') diff --git a/fw/hid-dials/Src/main.c b/fw/hid-dials/Src/main.c new file mode 100644 index 0000000..4ccbca0 --- /dev/null +++ b/fw/hid-dials/Src/main.c @@ -0,0 +1,465 @@ + +#include + +#include "main.h" +#include "usb_device.h" +#include "usbd_hid.h" + +#define HID_MEDIA_REPORT 2 +#define HYSTERESIS 200 + +ADC_HandleTypeDef hadc; +DMA_HandleTypeDef hdma_adc; + +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 { + /* 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); + +struct key_t +{ + uint8_t id; + uint8_t modifier; + uint8_t reserved; + uint8_t keycode[6]; +} key; + +uint16_t ADCreg[8]; +uint16_t ADCval[8]; +uint16_t ADClast[8]; + +/* FIXME debug remove */ +TIM_TypeDef *tim1 = TIM1; +TIM_TypeDef *tim3 = TIM3; + +int main(void) +{ + HAL_Init(); + + SystemClock_Config(); + + MX_GPIO_Init(); + MX_USB_HID_INIT(); + + __HAL_RCC_TIM1_CLK_ENABLE(); + __HAL_RCC_TIM3_CLK_ENABLE(); + + TIM1->SMCR = 3; // Encoder mode 3 + TIM1->CCER = 0; // rising edge polarity + TIM1->ARR = 0xFFFF; // count from 0-ARR or ARR-0 + TIM1->CCMR1 = 0x0101; // f_DTS/16, N=8, IC1->TI1, IC2->TI2 + TIM1->CNT = 0; // Initialize counter + TIM1->EGR = 1; // Generate an update event + TIM1->CR1 = 1; // Enable the counter + + TIM3->SMCR = 3; // Encoder mode 3 + TIM3->CCER = 0; // rising edge polarity + TIM3->ARR = 0xFFFF; // count from 0-ARR or ARR-0 + TIM3->CCMR1 = 0x0101; // f_DTS/16, N=8, IC1->TI1, IC2->TI2 + TIM3->CNT = 0; // Initialize counter + TIM3->EGR = 1; // Generate an update event + TIM3->CR1 = 1; // Enable the counter + + while (1) { + 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); + + /* Gang both encoders */ + vol_delta += tim3_delta - tim1_delta; + +#define VOL_DELTA_INC 4 + 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; + } + } 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] = +{ + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + 0x2a, // BS Backspace + 0x2b, // TAB Tab + 0x28, // LF Enter + 0x00, // VT + 0x00, // FF + 0x00, // CR + 0x00, // SO + 0x00, // SI + 0x00, // DEL + 0x00, // DC1 + 0x00, // DC2 + 0x00, // DC3 + 0x00, // DC4 + 0x00, // NAK + 0x00, // SYN + 0x00, // ETB + 0x00, // CAN + 0x00, // EM + 0x00, // SUB + 0x00, // ESC + 0x00, // FS + 0x00, // GS + 0x00, // RS + 0x00, // US + + 0x2c, // ' ' + 0x1e|0x80, // ! + 0x34|0x80, // " + 0x20|0x80, // # + 0x21|0x80, // $ + 0x22|0x80, // % + 0x24|0x80, // & + 0x34, // ' + 0x26|0x80, // ( + 0x27|0x80, // ) + 0x25|0x80, // * + 0x2e|0x80, // + + 0x36, // , + 0x2d, // - + 0x37, // . + 0x38, // / + 0x27, // 0 + 0x1e, // 1 + 0x1f, // 2 + 0x20, // 3 + 0x21, // 4 + 0x22, // 5 + 0x23, // 6 + 0x24, // 7 + 0x25, // 8 + 0x26, // 9 + 0x33|0x80, // : + 0x33, // ; + 0x36|0x80, // < + 0x2e, // = + 0x37|0x80, // > + 0x38|0x80, // ? + 0x1f|0x80, // @ + 0x04|0x80, // A + 0x05|0x80, // B + 0x06|0x80, // C + 0x07|0x80, // D + 0x08|0x80, // E + 0x09|0x80, // F + 0x0a|0x80, // G + 0x0b|0x80, // H + 0x0c|0x80, // I + 0x0d|0x80, // J + 0x0e|0x80, // K + 0x0f|0x80, // L + 0x10|0x80, // M + 0x11|0x80, // N + 0x12|0x80, // O + 0x13|0x80, // P + 0x14|0x80, // Q + 0x15|0x80, // R + 0x16|0x80, // S + 0x17|0x80, // T + 0x18|0x80, // U + 0x19|0x80, // V + 0x1a|0x80, // W + 0x1b|0x80, // X + 0x1c|0x80, // Y + 0x1d|0x80, // Z + 0x2f, // [ + 0x31, // bslash + 0x30, // ] + 0x23|0x80, // ^ + 0x2d|0x80, // _ + 0x35, // ` + 0x04, // a + 0x05, // b + 0x06, // c + 0x07, // d + 0x08, // e + 0x09, // f + 0x0a, // g + 0x0b, // h + 0x0c, // i + 0x0d, // j + 0x0e, // k + 0x0f, // l + 0x10, // m + 0x11, // n + 0x12, // o + 0x13, // p + 0x14, // q + 0x15, // r + 0x16, // s + 0x17, // t + 0x18, // u + 0x19, // v + 0x1a, // w + 0x1b, // x + 0x1c, // y + 0x1d, // z + 0x2f|0x80, // { + 0x31|0x80, // | + 0x30|0x80, // } + 0x35|0x80, // ~ + 0 // DEL +}; + + +void sendChar(uint8_t ch){ + if( ch > 128 ) ch -=128; + + key.id = 1; + key.keycode[0]=_asciimap[ch]&0x7F; + key.keycode[1]=0; + + if ( _asciimap[ch] & 0x80) key.modifier |= 0x02; + + for(int i=0; i< 4;i++){ + USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t *)&key, sizeof(key)); + HAL_Delay(10); + } + memset(key.keycode, 0 , sizeof(key.keycode)); + key.modifier = 0; + USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t *)&key, sizeof(key)); + HAL_Delay(10); +} + +void sendCharWrong(uint8_t ch){ + key.id = 1; + key.keycode[0]=ch&0x7F; + key.keycode[1]=0; + + if ( _asciimap[ch] & 0x80) key.modifier |= 0x02; + + for(int i=0; i< 4;i++){ + USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t *)&key, sizeof(key)); + HAL_Delay(10); + } + memset(key.keycode, 0 , sizeof(key.keycode)); + key.modifier = 0; + USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t *)&key, sizeof(key)); + HAL_Delay(10); +} + +void sendKeybits(uint8_t keybits){ + uint8_t report[2]; + report[0]= HID_MEDIA_REPORT; + report[1]= keybits; + USBD_HID_SendReport(&hUsbDeviceFS, report, 2); +} + +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI14|RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.HSI14State = RCC_HSI14_ON; + RCC_OscInitStruct.HSI14CalibrationValue = 16; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI48; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); + + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + +} + +static void MX_GPIO_Init(void) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /* 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){ + HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,1); + HAL_Delay(100); + HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,0); + HAL_Delay(100); + } +} + -- cgit