221 lines
5.5 KiB
C++
221 lines
5.5 KiB
C++
/*
|
|
* Copyright (C) EdgeTX
|
|
*
|
|
* Based on code named
|
|
* opentx - https://github.com/opentx/opentx
|
|
* th9x - http://code.google.com/p/th9x
|
|
* er9x - http://code.google.com/p/er9x
|
|
* gruvin9x - http://code.google.com/p/gruvin9x
|
|
*
|
|
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "hal/key_driver.h"
|
|
|
|
#include "stm32_hal_ll.h"
|
|
#include "stm32_gpio_driver.h"
|
|
|
|
#include "hal.h"
|
|
#include "delays_driver.h"
|
|
#include "keys.h"
|
|
|
|
/* The output bit-order has to be:
|
|
0 LHL TR7L (Left equals down)
|
|
1 LHR TR7R
|
|
2 LVD TR5D
|
|
3 LVU TR5U
|
|
4 RVD TR6D
|
|
5 RVU TR6U
|
|
6 RHL TR8L
|
|
7 RHR TR8R
|
|
8 LSD TR1D
|
|
9 LSU TR1U
|
|
10 RSD TR2D
|
|
11 RSU TR2U
|
|
12 EX1D TR3D
|
|
13 EX1U TR3U
|
|
14 EX2D TR4D
|
|
15 EX2U TR4U
|
|
*/
|
|
|
|
enum PhysicalTrims
|
|
{
|
|
TR7L = 0,
|
|
TR7R,
|
|
TR5D = 2,
|
|
TR5U,
|
|
TR6D = 4,
|
|
TR6U,
|
|
TR8L = 6,
|
|
TR8R,
|
|
TR1D = 8,
|
|
TR1U,
|
|
TR2D = 10,
|
|
TR2U,
|
|
TR3D = 12,
|
|
TR3U,
|
|
TR4D = 14,
|
|
TR4U,
|
|
};
|
|
|
|
void keysInit()
|
|
{
|
|
stm32_gpio_enable_clock(GPIOB);
|
|
stm32_gpio_enable_clock(GPIOC);
|
|
stm32_gpio_enable_clock(GPIOD);
|
|
stm32_gpio_enable_clock(GPIOG);
|
|
stm32_gpio_enable_clock(GPIOH);
|
|
stm32_gpio_enable_clock(GPIOJ);
|
|
|
|
LL_GPIO_InitTypeDef pinInit;
|
|
LL_GPIO_StructInit(&pinInit);
|
|
pinInit.Mode = LL_GPIO_MODE_INPUT;
|
|
pinInit.Pull = LL_GPIO_PULL_DOWN;
|
|
|
|
pinInit.Pin = KEYS_GPIOB_PINS;
|
|
LL_GPIO_Init(GPIOB, &pinInit);
|
|
|
|
pinInit.Pin = KEYS_GPIOC_PINS;
|
|
LL_GPIO_Init(GPIOC, &pinInit);
|
|
|
|
pinInit.Pin = KEYS_GPIOD_PINS;
|
|
LL_GPIO_Init(GPIOD, &pinInit);
|
|
|
|
pinInit.Pin = KEYS_GPIOH_PINS;
|
|
LL_GPIO_Init(GPIOH, &pinInit);
|
|
|
|
pinInit.Pin = KEYS_GPIOJ_PINS;
|
|
LL_GPIO_Init(GPIOJ, &pinInit);
|
|
|
|
// Matrix outputs
|
|
pinInit.Mode = LL_GPIO_MODE_OUTPUT;
|
|
pinInit.Pull = LL_GPIO_PULL_NO;
|
|
|
|
pinInit.Pin = KEYS_OUT_GPIOG_PINS;
|
|
LL_GPIO_Init(GPIOG, &pinInit);
|
|
|
|
pinInit.Pin = KEYS_OUT_GPIOH_PINS;
|
|
LL_GPIO_Init(GPIOH, &pinInit);
|
|
}
|
|
|
|
static uint32_t _readKeyMatrix()
|
|
{
|
|
// This function avoids concurrent matrix agitation
|
|
|
|
uint32_t result = 0;
|
|
/* Bit 0 - TR3 down
|
|
* Bit 1 - TR3 up
|
|
* Bit 2 - TR4 down
|
|
* Bit 3 - TR4 up
|
|
* Bit 4 - TR5 down
|
|
* Bit 5 - TR5 up
|
|
* Bit 6 - TR6 down
|
|
* Bit 7 - TR6 up
|
|
* Bit 8 - TR7 left
|
|
* Bit 9 - TR7 right
|
|
* Bit 10 - TR8 left
|
|
* Bit 11 - TR8 right
|
|
*/
|
|
|
|
volatile static struct
|
|
{
|
|
uint32_t oldResult = 0;
|
|
uint8_t ui8ReadInProgress = 0;
|
|
} syncelem;
|
|
|
|
if (syncelem.ui8ReadInProgress != 0) return syncelem.oldResult;
|
|
|
|
// ui8ReadInProgress was 0, increment it
|
|
syncelem.ui8ReadInProgress++;
|
|
// Double check before continuing, as non-atomic, non-blocking so far
|
|
// If ui8ReadInProgress is above 1, then there was concurrent task calling it, exit
|
|
if (syncelem.ui8ReadInProgress > 1) return syncelem.oldResult;
|
|
|
|
// If we land here, we have exclusive access to Matrix
|
|
LL_GPIO_ResetOutputPin(TRIMS_GPIO_OUT1, TRIMS_GPIO_OUT1_PIN);
|
|
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT2, TRIMS_GPIO_OUT2_PIN);
|
|
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT3, TRIMS_GPIO_OUT3_PIN);
|
|
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT4, TRIMS_GPIO_OUT4_PIN);
|
|
delay_us(10);
|
|
if (~TRIMS_GPIO_REG_IN1 & TRIMS_GPIO_PIN_IN1)
|
|
result |= 1 << TR7L;
|
|
if (~TRIMS_GPIO_REG_IN2 & TRIMS_GPIO_PIN_IN2)
|
|
result |= 1 << TR7R;
|
|
if (~TRIMS_GPIO_REG_IN3 & TRIMS_GPIO_PIN_IN3)
|
|
result |= 1 << TR5D;
|
|
if (~TRIMS_GPIO_REG_IN4 & TRIMS_GPIO_PIN_IN4)
|
|
result |= 1 << TR5U;
|
|
|
|
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT1, TRIMS_GPIO_OUT1_PIN);
|
|
LL_GPIO_ResetOutputPin(TRIMS_GPIO_OUT2, TRIMS_GPIO_OUT2_PIN);
|
|
delay_us(10);
|
|
if (~TRIMS_GPIO_REG_IN1 & TRIMS_GPIO_PIN_IN1)
|
|
result |= 1 << TR3D;
|
|
if (~TRIMS_GPIO_REG_IN2 & TRIMS_GPIO_PIN_IN2)
|
|
result |= 1 << TR3U;
|
|
if (~TRIMS_GPIO_REG_IN3 & TRIMS_GPIO_PIN_IN3)
|
|
result |= 1 << TR4U;
|
|
if (~TRIMS_GPIO_REG_IN4 & TRIMS_GPIO_PIN_IN4)
|
|
result |= 1 << TR4D;
|
|
|
|
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT2, TRIMS_GPIO_OUT2_PIN);
|
|
LL_GPIO_ResetOutputPin(TRIMS_GPIO_OUT3, TRIMS_GPIO_OUT3_PIN);
|
|
delay_us(10);
|
|
if (~TRIMS_GPIO_REG_IN1 & TRIMS_GPIO_PIN_IN1)
|
|
result |= 1 << TR6U;
|
|
if (~TRIMS_GPIO_REG_IN2 & TRIMS_GPIO_PIN_IN2)
|
|
result |= 1 << TR6D;
|
|
if (~TRIMS_GPIO_REG_IN3 & TRIMS_GPIO_PIN_IN3)
|
|
result |= 1 << TR8L;
|
|
if (~TRIMS_GPIO_REG_IN4 & TRIMS_GPIO_PIN_IN4)
|
|
result |= 1 << TR8R;
|
|
|
|
LL_GPIO_SetOutputPin(TRIMS_GPIO_OUT3, TRIMS_GPIO_OUT3_PIN);
|
|
|
|
syncelem.oldResult = result;
|
|
syncelem.ui8ReadInProgress = 0;
|
|
|
|
return result;
|
|
}
|
|
|
|
uint32_t readKeys()
|
|
{
|
|
uint32_t result = 0;
|
|
|
|
if (getHatsAsKeys()) {
|
|
uint32_t mkeys = _readKeyMatrix();
|
|
if (mkeys & (1 << TR4D)) result |= 1 << KEY_ENTER;
|
|
if (mkeys & (1 << TR4U)) result |= 1 << KEY_EXIT;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
uint32_t readTrims()
|
|
{
|
|
uint32_t result = 0;
|
|
|
|
result |= _readKeyMatrix();
|
|
|
|
if (~TRIMS_GPIO_REG_TR1U & TRIMS_GPIO_PIN_TR1U)
|
|
result |= 1 << (TR1U);
|
|
if (~TRIMS_GPIO_REG_TR1D & TRIMS_GPIO_PIN_TR1D)
|
|
result |= 1 << (TR1D);
|
|
|
|
if (~TRIMS_GPIO_REG_TR2U & TRIMS_GPIO_PIN_TR2U)
|
|
result |= 1 << (TR2U);
|
|
if (~TRIMS_GPIO_REG_TR2D & TRIMS_GPIO_PIN_TR2D)
|
|
result |= 1 << (TR2D);
|
|
|
|
return result;
|
|
}
|