hid fw working as intended

This commit is contained in:
jaseg 2020-06-28 16:09:04 +02:00
parent 0aa7b8871e
commit 1e6e8a2062

View file

@ -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);
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;
uint32_t keybits = poll_encoders();
for (int i=0; i<10; i++) {
keybits |= poll_keys();
HAL_Delay(1);
}
sendKeybits(keybits);
tim1_last = tim1_now;
tim3_last = tim3_now;
HAL_Delay(10);
}
}
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] =
{
@ -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){