#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; 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); } } void * _sbrk(ptrdiff_t __incr); void * _sbrk(ptrdiff_t __incr) { /* FIXME Do we even need this? */ return NULL; } void _init(void); void _init() { /* FIXME Do we even need this? */ } 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); } }