336 lines
9.0 KiB
C++
336 lines
9.0 KiB
C++
/*
|
|
* Copyright (C) OpenTX
|
|
*
|
|
* Based on code named
|
|
* 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 "opentx.h"
|
|
|
|
#if defined(__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
#include "usb_dcd_int.h"
|
|
#include "usb_bsp.h"
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif
|
|
|
|
HardwareOptions hardwareOptions;
|
|
|
|
void watchdogInit(unsigned int duration)
|
|
{
|
|
IWDG->KR = 0x5555; // Unlock registers
|
|
IWDG->PR = 3; // Divide by 32 => 1kHz clock
|
|
IWDG->KR = 0x5555; // Unlock registers
|
|
IWDG->RLR = duration;
|
|
IWDG->KR = 0xAAAA; // reload
|
|
IWDG->KR = 0xCCCC; // start
|
|
}
|
|
|
|
#if defined(SPORT_UPDATE_PWR_GPIO)
|
|
void sportUpdateInit()
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStructure;
|
|
GPIO_InitStructure.GPIO_Pin = SPORT_UPDATE_PWR_GPIO_PIN;
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
|
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
|
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
|
GPIO_Init(SPORT_UPDATE_PWR_GPIO, &GPIO_InitStructure);
|
|
}
|
|
|
|
void sportUpdatePowerOn()
|
|
{
|
|
GPIO_SPORT_UPDATE_PWR_GPIO_ON(SPORT_UPDATE_PWR_GPIO, SPORT_UPDATE_PWR_GPIO_PIN);
|
|
}
|
|
|
|
void sportUpdatePowerOff()
|
|
{
|
|
GPIO_SPORT_UPDATE_PWR_GPIO_OFF(SPORT_UPDATE_PWR_GPIO, SPORT_UPDATE_PWR_GPIO_PIN);
|
|
}
|
|
|
|
void sportUpdatePowerInit()
|
|
{
|
|
if (g_eeGeneral.sportUpdatePower == 1)
|
|
sportUpdatePowerOn();
|
|
else
|
|
sportUpdatePowerOff();
|
|
}
|
|
#endif
|
|
|
|
void boardInit()
|
|
{
|
|
RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph |
|
|
PCBREV_RCC_AHB1Periph |
|
|
KEYS_RCC_AHB1Periph |
|
|
LCD_RCC_AHB1Periph |
|
|
AUDIO_RCC_AHB1Periph |
|
|
BACKLIGHT_RCC_AHB1Periph |
|
|
ADC_RCC_AHB1Periph |
|
|
I2C_RCC_AHB1Periph |
|
|
SD_RCC_AHB1Periph |
|
|
HAPTIC_RCC_AHB1Periph |
|
|
INTMODULE_RCC_AHB1Periph |
|
|
EXTMODULE_RCC_AHB1Periph |
|
|
TELEMETRY_RCC_AHB1Periph |
|
|
SPORT_UPDATE_RCC_AHB1Periph |
|
|
AUX_SERIAL_RCC_AHB1Periph |
|
|
TRAINER_RCC_AHB1Periph |
|
|
TRAINER_MODULE_RCC_AHB1Periph |
|
|
BT_RCC_AHB1Periph |
|
|
GYRO_RCC_AHB1Periph,
|
|
ENABLE);
|
|
|
|
RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph |
|
|
LCD_RCC_APB1Periph |
|
|
AUDIO_RCC_APB1Periph |
|
|
ADC_RCC_APB1Periph |
|
|
BACKLIGHT_RCC_APB1Periph |
|
|
HAPTIC_RCC_APB1Periph |
|
|
INTERRUPT_xMS_RCC_APB1Periph |
|
|
TIMER_2MHz_RCC_APB1Periph |
|
|
I2C_RCC_APB1Periph |
|
|
SD_RCC_APB1Periph |
|
|
TRAINER_RCC_APB1Periph |
|
|
TELEMETRY_RCC_APB1Periph |
|
|
AUX_SERIAL_RCC_APB1Periph |
|
|
INTMODULE_RCC_APB1Periph |
|
|
TRAINER_MODULE_RCC_APB1Periph |
|
|
BT_RCC_APB1Periph |
|
|
GYRO_RCC_APB1Periph,
|
|
ENABLE);
|
|
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG |
|
|
BACKLIGHT_RCC_APB2Periph |
|
|
ADC_RCC_APB2Periph |
|
|
HAPTIC_RCC_APB2Periph |
|
|
INTMODULE_RCC_APB2Periph |
|
|
EXTMODULE_RCC_APB2Periph |
|
|
TRAINER_MODULE_RCC_APB2Periph |
|
|
BT_RCC_APB2Periph |
|
|
TELEMETRY_RCC_APB2Periph,
|
|
ENABLE);
|
|
|
|
#if defined(BLUETOOTH) && !defined(PCBX9E)
|
|
bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE, true);
|
|
#endif
|
|
|
|
pwrInit();
|
|
|
|
#if defined(AUTOUPDATE)
|
|
telemetryPortInit(FRSKY_SPORT_BAUDRATE, TELEMETRY_SERIAL_WITHOUT_DMA);
|
|
sportSendByteLoop(0x7E);
|
|
#endif
|
|
|
|
#if defined(STATUS_LEDS)
|
|
ledInit();
|
|
ledGreen();
|
|
#endif
|
|
|
|
keysInit();
|
|
|
|
#if defined(ROTARY_ENCODER_NAVIGATION)
|
|
rotaryEncoderInit();
|
|
#endif
|
|
|
|
delaysInit();
|
|
|
|
#if NUM_PWMSTICKS > 0
|
|
sticksPwmInit();
|
|
delay_ms(20);
|
|
if (pwm_interrupt_count < 32) {
|
|
hardwareOptions.sticksPwmDisabled = true;
|
|
}
|
|
#endif
|
|
|
|
adcInit();
|
|
lcdInit(); // delaysInit() must be called before
|
|
audioInit();
|
|
init2MhzTimer();
|
|
init5msTimer();
|
|
__enable_irq();
|
|
i2cInit();
|
|
usbInit();
|
|
|
|
#if defined(DEBUG) && defined(AUX_SERIAL_GPIO)
|
|
auxSerialInit(0, 0); // default serial mode (None if DEBUG not defined)
|
|
TRACE("\nTaranis board started :)");
|
|
#endif
|
|
|
|
#if defined(HAPTIC)
|
|
hapticInit();
|
|
#endif
|
|
|
|
#if defined(PXX2_PROBE)
|
|
intmodulePxx2Probe();
|
|
#endif
|
|
|
|
#if defined(DEBUG)
|
|
DBGMCU_APB1PeriphConfig(DBGMCU_IWDG_STOP|DBGMCU_TIM1_STOP|DBGMCU_TIM2_STOP|DBGMCU_TIM3_STOP|DBGMCU_TIM6_STOP|DBGMCU_TIM8_STOP|DBGMCU_TIM10_STOP|DBGMCU_TIM13_STOP|DBGMCU_TIM14_STOP, ENABLE);
|
|
#endif
|
|
|
|
#if defined(PWR_BUTTON_PRESS)
|
|
if (WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
|
|
pwrOn();
|
|
}
|
|
#endif
|
|
|
|
#if defined(TOPLCD_GPIO)
|
|
toplcdInit();
|
|
#endif
|
|
|
|
if (HAS_SPORT_UPDATE_CONNECTOR()) {
|
|
sportUpdateInit();
|
|
}
|
|
|
|
#if defined(JACK_DETECT_GPIO)
|
|
initJackDetect();
|
|
#endif
|
|
|
|
initSpeakerEnable();
|
|
enableSpeaker();
|
|
|
|
initHeadphoneTrainerSwitch();
|
|
|
|
#if defined(GYRO)
|
|
gyroInit();
|
|
#endif
|
|
|
|
#if defined(RTCLOCK) && !defined(COPROCESSOR)
|
|
rtcInit(); // RTC must be initialized before rambackupRestore() is called
|
|
#endif
|
|
|
|
backlightInit();
|
|
}
|
|
|
|
void boardOff()
|
|
{
|
|
#if defined(STATUS_LEDS) && !defined(BOOT)
|
|
ledOff();
|
|
#endif
|
|
|
|
BACKLIGHT_DISABLE();
|
|
|
|
#if defined(TOPLCD_GPIO) && !defined(BOOT)
|
|
toplcdOff();
|
|
#endif
|
|
|
|
#if defined(PWR_BUTTON_PRESS)
|
|
while (pwrPressed()) {
|
|
WDG_RESET();
|
|
}
|
|
#endif
|
|
|
|
lcdOff();
|
|
SysTick->CTRL = 0; // turn off systick
|
|
pwrOff();
|
|
|
|
// disable interrupts
|
|
__disable_irq();
|
|
|
|
while (1) {
|
|
WDG_RESET();
|
|
#if defined(PWR_BUTTON_PRESS)
|
|
// X9E/X7 needs watchdog reset because CPU is still running while
|
|
// the power key is held pressed by the user.
|
|
// The power key should be released by now, but we must make sure
|
|
if (!pwrPressed()) {
|
|
// Put the CPU into sleep to reduce the consumption,
|
|
// it might help with the RTC reset issue
|
|
PWR->CR |= PWR_CR_CWUF;
|
|
/* Select STANDBY mode */
|
|
PWR->CR |= PWR_CR_PDDS;
|
|
/* Set SLEEPDEEP bit of Cortex System Control Register */
|
|
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
|
/* Request Wait For Event */
|
|
__WFE();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// this function must not return!
|
|
}
|
|
|
|
uint16_t getBatteryVoltage()
|
|
{
|
|
int32_t instant_vbat = anaIn(TX_VOLTAGE); // using filtered ADC value on purpose
|
|
instant_vbat = (instant_vbat * BATT_SCALE * (128 + g_eeGeneral.txVoltageCalibration) ) / 26214;
|
|
instant_vbat += 20; // add 0.2V because of the diode TODO check if this is needed, but removal will break existing calibrations!
|
|
return (uint16_t)instant_vbat;
|
|
}
|
|
|
|
#if defined(AUDIO_SPEAKER_ENABLE_GPIO)
|
|
void initSpeakerEnable()
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStructure;
|
|
|
|
GPIO_InitStructure.GPIO_Pin = AUDIO_SPEAKER_ENABLE_GPIO_PIN;
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
|
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
|
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
|
GPIO_Init(AUDIO_SPEAKER_ENABLE_GPIO, &GPIO_InitStructure);
|
|
}
|
|
|
|
void enableSpeaker()
|
|
{
|
|
GPIO_SetBits(AUDIO_SPEAKER_ENABLE_GPIO, AUDIO_SPEAKER_ENABLE_GPIO_PIN);
|
|
}
|
|
|
|
void disableSpeaker()
|
|
{
|
|
GPIO_ResetBits(AUDIO_SPEAKER_ENABLE_GPIO, AUDIO_SPEAKER_ENABLE_GPIO_PIN);
|
|
}
|
|
#endif
|
|
|
|
#if defined(HEADPHONE_TRAINER_SWITCH_GPIO)
|
|
void initHeadphoneTrainerSwitch()
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStructure;
|
|
|
|
GPIO_InitStructure.GPIO_Pin = HEADPHONE_TRAINER_SWITCH_GPIO_PIN;
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
|
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
|
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
|
GPIO_Init(HEADPHONE_TRAINER_SWITCH_GPIO, &GPIO_InitStructure);
|
|
}
|
|
|
|
void enableHeadphone()
|
|
{
|
|
GPIO_ResetBits(HEADPHONE_TRAINER_SWITCH_GPIO, HEADPHONE_TRAINER_SWITCH_GPIO_PIN);
|
|
}
|
|
|
|
void enableTrainer()
|
|
{
|
|
GPIO_SetBits(HEADPHONE_TRAINER_SWITCH_GPIO, HEADPHONE_TRAINER_SWITCH_GPIO_PIN);
|
|
}
|
|
#endif
|
|
|
|
#if defined(JACK_DETECT_GPIO)
|
|
void initJackDetect(void)
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStructure;
|
|
|
|
GPIO_InitStructure.GPIO_Pin = JACK_DETECT_GPIO_PIN;
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
|
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
|
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
|
GPIO_Init(JACK_DETECT_GPIO, &GPIO_InitStructure);
|
|
}
|
|
#endif |