diff --git a/src/Makefile b/src/Makefile index 6cd3d06e9..062116a97 100644 --- a/src/Makefile +++ b/src/Makefile @@ -496,7 +496,7 @@ ifeq ($(PCB), X9D) EEPROMSRC = eeprom_avr.cpp # TODO later eeprom_conversions.cpp PULSESSRC = pulses_arm.cpp CPPSRC += sky9x/audio.cpp - CPPSRC += x9d/pwr_driver.cpp x9d/eeprom_driver.cpp x9d/pulses_driver.cpp x9d/keys_driver.cpp x9d/adc_driver.cpp x9d/audio_driver.cpp x9d/delays.cpp x9d/uart.cpp + CPPSRC += x9d/pwr_driver.cpp x9d/eeprom_driver.cpp x9d/pulses_driver.cpp x9d/keys_driver.cpp x9d/adc_driver.cpp x9d/trainer_driver.cpp x9d/audio_driver.cpp x9d/delays.cpp x9d/uart.cpp CPPSRC += bmp.cpp monitors_views.cpp SRC += x9d/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Source/Templates/system_stm32f2xx.c SRC += x9d/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/src/stm32f2xx_gpio.c diff --git a/src/sky9x/board_sky9x.cpp b/src/sky9x/board_sky9x.cpp index 59ab3ce80..09df75905 100644 --- a/src/sky9x/board_sky9x.cpp +++ b/src/sky9x/board_sky9x.cpp @@ -302,10 +302,10 @@ extern "C" void TC3_IRQHandler() //capture ppm in at 2MHz // G: We process g_ppmIns immediately here, to make servo movement as smooth as possible // while under trainee control - if (val>4000 && val < 16000) // G: Prioritize reset pulse. (Needed when less than 8 incoming pulses) + if (val>4000 && val<19000) { // G: Prioritize reset pulse. (Needed when less than 8 incoming pulses) ppmInState = 1; // triggered - else - { + } + else { if (ppmInState && ppmInState<=8) { if (val>800 && val<2200) // if valid pulse-width range diff --git a/src/x9d/Audio.c b/src/x9d/Audio.c deleted file mode 100644 index 69b641a64..000000000 --- a/src/x9d/Audio.c +++ /dev/null @@ -1,105 +0,0 @@ -/** - ****************************************************************************** - * @file Project/Audio/Audio.c - * @author X9D Application Team - * @version V 0.2 - * @date 12-JULY-2012 - * @brief This file provides drivers foe Audio module.I2S AND GPIO Included. - ****************************************************************************** -*/ - -#include "stm32f2xx.h" -#include "Audio.h" -#include "hal.h" - - -static -void Audio_GPIO_Init() -{ - GPIO_InitTypeDef GPIO_InitStructure; - - /* EnableI2C GPIO clocks */ - RCC_AHB1PeriphClockCmd(CODEC_I2S_GPIO_CLOCK, ENABLE);//GPIOA C - - /* CODEC_I2S pins configuration: WS, SCK and SD pins -----------------------------*/ - GPIO_InitStructure.GPIO_Pin = CODEC_I2S_SCK_PIN | CODEC_I2S_SD_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(CODEC_I2S_GPIO, &GPIO_InitStructure); - - GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(CODEC_I2S_WS_GPIO, &GPIO_InitStructure); - - /* Connect pins to I2S peripheral */ - GPIO_PinAFConfig(CODEC_I2S_WS_GPIO, CODEC_I2S_WS_PINSRC, CODEC_I2S_GPIO_AF); - GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SCK_PINSRC, CODEC_I2S_GPIO_AF); - GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SD_PINSRC, CODEC_I2S_GPIO_AF); - -#ifdef CODEC_MCLK_ENABLED - /* CODEC_I2S pins configuration: MCK pin */ - GPIO_InitStructure.GPIO_Pin = CODEC_I2S_MCK_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(CODEC_I2S_MCK_GPIO, &GPIO_InitStructure); - /* Connect pins to I2S peripheral */ - GPIO_PinAFConfig(CODEC_I2S_MCK_GPIO, CODEC_I2S_MCK_PINSRC, CODEC_I2S_GPIO_AF); -#endif /* CODEC_MCLK_ENABLED */ - -/*CODEC_I2S_MUTE & CODEC_I2S_FLT GPIO CONFIG*/ - GPIO_InitStructure.GPIO_Pin = CODEC_I2S_MUTE;// | CODEC_I2S_FLT; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(CODEC_I2S_GPIO, &GPIO_InitStructure); - GPIO_SetBits(CODEC_I2S_GPIO,CODEC_I2S_MUTE); - // GPIO_SetBits(CODEC_I2S_CTL_GPIO,CODEC_I2S_FLT); -} - -void I2S2_Init() -{ - I2S_InitTypeDef I2S_InitStructure; - - Audio_GPIO_Init(); - - /*CONFIG the I2S_RCC ,MUST before enabling the I2S APB clock*/ - //PLLI2SN 302,PLLI2SR 2,I2SDIV 53,I2SODD 1,FS 44.1KHZ,16bit,Error 0.0011% - RCC_PLLI2SConfig(302,2); - RCC_PLLI2SCmd(ENABLE); - RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S); - - /* Enable the CODEC_I2S peripheral clock */ - RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE); - /* CODEC_I2S peripheral configuration */ - SPI_I2S_DeInit(CODEC_I2S); - I2S_InitStructure.I2S_AudioFreq = AudioFreq; - I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; - I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; - I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;//clk 0 when idle state - I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; -#ifdef CODEC_MCLK_ENABLED - I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable; -#elif defined(CODEC_MCLK_DISABLED) - I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; -#else - #error "No selection for the MCLK output has been defined !" -#endif /* CODEC_MCLK_ENABLED */ - - /* Initialize the I2S peripheral with the structure above */ - I2S_Init(CODEC_I2S, &I2S_InitStructure); - I2S_Cmd(CODEC_I2S,ENABLE); - //interrupt -#ifdef CODEC_USE_INT - SPI_I2S_ITConfig(CODEC_I2S,SPI_I2S_IT_TXE,ENABLE); -#elif defined(CODEC_USE_DMA) -#error "DMA is not initialized" -#endif -} diff --git a/src/x9d/Audio.h b/src/x9d/Audio.h deleted file mode 100644 index fae74fb0b..000000000 --- a/src/x9d/Audio.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - ****************************************************************************** - * @file Project/Audio/Audio.h - * @author X9D Application Team - * @version V 0.2 - * @date 12-JULY-2011 - * @brief Header for Audio.c. - ****************************************************************************** -*/ -#ifndef _AUDIO_H_ -#define _AUDIO_H_ - -#include "stdint.h" -#include "Macro_define.h" - -extern const uint16_t AUDIO_SAMPLE[]; -// -void I2S2_Init(); - - -typedef struct{ - uint32_t size; //number of chars per font - uint16_t *base; //font addr -}A_SAMPLE; - -extern A_SAMPLE demo_sample; - -#endif \ No newline at end of file diff --git a/src/x9d/audio_driver.cpp b/src/x9d/audio_driver.cpp index 4ac10249c..1c92fe8eb 100644 --- a/src/x9d/audio_driver.cpp +++ b/src/x9d/audio_driver.cpp @@ -101,3 +101,94 @@ void setVolume( unsigned char volume ) void read_volume() { } */ + + +static void Audio_GPIO_Init() +{ + GPIO_InitTypeDef GPIO_InitStructure; + + /* EnableI2C GPIO clocks */ + RCC_AHB1PeriphClockCmd(CODEC_I2S_GPIO_CLOCK, ENABLE);//GPIOA C + + /* CODEC_I2S pins configuration: WS, SCK and SD pins -----------------------------*/ + GPIO_InitStructure.GPIO_Pin = CODEC_I2S_SCK_PIN | CODEC_I2S_SD_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(CODEC_I2S_GPIO, &GPIO_InitStructure); + + GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(CODEC_I2S_WS_GPIO, &GPIO_InitStructure); + + /* Connect pins to I2S peripheral */ + GPIO_PinAFConfig(CODEC_I2S_WS_GPIO, CODEC_I2S_WS_PINSRC, CODEC_I2S_GPIO_AF); + GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SCK_PINSRC, CODEC_I2S_GPIO_AF); + GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SD_PINSRC, CODEC_I2S_GPIO_AF); + +#ifdef CODEC_MCLK_ENABLED + /* CODEC_I2S pins configuration: MCK pin */ + GPIO_InitStructure.GPIO_Pin = CODEC_I2S_MCK_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(CODEC_I2S_MCK_GPIO, &GPIO_InitStructure); + /* Connect pins to I2S peripheral */ + GPIO_PinAFConfig(CODEC_I2S_MCK_GPIO, CODEC_I2S_MCK_PINSRC, CODEC_I2S_GPIO_AF); +#endif /* CODEC_MCLK_ENABLED */ + +/*CODEC_I2S_MUTE & CODEC_I2S_FLT GPIO CONFIG*/ + GPIO_InitStructure.GPIO_Pin = CODEC_I2S_MUTE;// | CODEC_I2S_FLT; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(CODEC_I2S_GPIO, &GPIO_InitStructure); + GPIO_SetBits(CODEC_I2S_GPIO,CODEC_I2S_MUTE); + // GPIO_SetBits(CODEC_I2S_CTL_GPIO,CODEC_I2S_FLT); +} + +void audioInit() +{ + I2S_InitTypeDef I2S_InitStructure; + + Audio_GPIO_Init(); + + /*CONFIG the I2S_RCC ,MUST before enabling the I2S APB clock*/ + //PLLI2SN 302,PLLI2SR 2,I2SDIV 53,I2SODD 1,FS 44.1KHZ,16bit,Error 0.0011% + RCC_PLLI2SConfig(302,2); + RCC_PLLI2SCmd(ENABLE); + RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S); + + /* Enable the CODEC_I2S peripheral clock */ + RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE); + /* CODEC_I2S peripheral configuration */ + SPI_I2S_DeInit(CODEC_I2S); + I2S_InitStructure.I2S_AudioFreq = AudioFreq; + I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; + I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; + I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;//clk 0 when idle state + I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; +#ifdef CODEC_MCLK_ENABLED + I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable; +#elif defined(CODEC_MCLK_DISABLED) + I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; +#else + #error "No selection for the MCLK output has been defined !" +#endif /* CODEC_MCLK_ENABLED */ + + /* Initialize the I2S peripheral with the structure above */ + I2S_Init(CODEC_I2S, &I2S_InitStructure); + I2S_Cmd(CODEC_I2S,ENABLE); + //interrupt +#ifdef CODEC_USE_INT + SPI_I2S_ITConfig(CODEC_I2S,SPI_I2S_IT_TXE,ENABLE); +#elif defined(CODEC_USE_DMA) +#error "DMA is not initialized" +#endif +} diff --git a/src/x9d/board_x9d.cpp b/src/x9d/board_x9d.cpp index cf97a0f56..204ac1292 100644 --- a/src/x9d/board_x9d.cpp +++ b/src/x9d/board_x9d.cpp @@ -169,6 +169,13 @@ void boardInit() keysInit(); adcInit(); delaysInit(); + audioInit(); + + // TODO init_ppm() ; + + init_trainer_ppm() ; + + init_trainer_capture() ; init5msTimer(); diff --git a/src/x9d/board_x9d.h b/src/x9d/board_x9d.h index 3eaa3ef50..c9506c9d5 100644 --- a/src/x9d/board_x9d.h +++ b/src/x9d/board_x9d.h @@ -123,8 +123,11 @@ void pwrInit(); void eepromInit(); // TODO check it's not in another include void delaysInit(); void adcInit(); -void adcRead(); +void audioInit(); +void adcRead(); +void init_trainer_ppm(); +void init_trainer_capture(); extern volatile uint16_t Analog_values[]; #define DEBUG_UART_BAUDRATE 115200 diff --git a/src/x9d/hal.h b/src/x9d/hal.h index e09577bac..deed0f2dc 100644 --- a/src/x9d/hal.h +++ b/src/x9d/hal.h @@ -70,9 +70,16 @@ #define PIN_SPORT_RX GPIO_Pin_6 //PD.06 // Trainer Port -#define PIN_TR_PPM_IN GPIO_Pin_8 //PC.08 +#define PIN_TR_PPM_IN GPIO_Pin_5 //PC.08 #define PIN_TR_PPM_OUT GPIO_Pin_9 //PC.09 +// TODO merge these constants +#define PIN_PER_3 0x030 +// #define PIN_OS2 0x0000 +#define PIN_OS25 0x2000 +// #define PIN_OS50 0x4000 +// #define PIN_OS100 0x6000 + // Cppm #define RCC_AHB1Periph_GPIOCPPM RCC_AHB1Periph_GPIOA #define PIN_CPPM_OUT GPIO_Pin_8 //PA.08 diff --git a/src/x9d/trainer_driver.cpp b/src/x9d/trainer_driver.cpp new file mode 100644 index 000000000..c03d70848 --- /dev/null +++ b/src/x9d/trainer_driver.cpp @@ -0,0 +1,177 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * open9x is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * 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 "../open9x.h" + +uint16_t TrainerPpmStream[20] = +{ + 2000, + 2200, + 2400, + 2600, + 2800, + 3000, + 3200, + 3400, + 45000-21600, + 0,0,0,0,0,0,0,0,0,0,0 +}; + +uint16_t * TrainerPulsePtr; + +void setupTrainerPulses() +{ + int16_t PPM_range = g_model.extendedLimits ? 640 * 2 : 512 * 2; //range of 0.7..1.7msec + + uint16_t *ptr ; + uint32_t p=8+g_model.ppmNCH*2; //Channels *2 + + ptr = TrainerPpmStream ; + + uint32_t rest = 22500u * 2; //Minimum Framelen=22.5 ms + rest += int32_t(g_model.ppmFrameLength) * 1000; + + for (uint32_t i = 0 ; i < p ; i += 1 ) { + uint32_t pulse = limit((int16_t)-PPM_range, g_chans512[i], (int16_t)PPM_range) + 2*PPM_CH_CENTER(i); + rest -= pulse ; + *ptr++ = pulse ; + } + *ptr++ = rest ; + *ptr = 0 ; + + TIM8->CCR2 = rest - 1000 ; // Update time + TIM8->CCR4 = (g_model.ppmDelay*50+300)*2 ; +} + +// Trainer PPM oputput PC9, Timer 8 channel 4 +void init_trainer_ppm() +{ + setupTrainerPulses() ; + TrainerPulsePtr = TrainerPpmStream ; + + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN ; // Enable portC clock + configure_pins( 0x0200, PIN_PERIPHERAL | PIN_PORTC | PIN_PER_3 | PIN_OS25 | PIN_PUSHPULL ) ; + RCC->APB2ENR |= RCC_APB2ENR_TIM8EN ; // Enable clock + + TIM8->ARR = *TrainerPulsePtr++ ; + TIM8->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz + TIM8->CCER = TIM_CCER_CC4E ; + TIM8->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE ; // PWM mode 1 + TIM8->CCR4 = 600 ; // 300 uS pulse + TIM8->BDTR = TIM_BDTR_MOE ; + TIM8->EGR = 1 ; + TIM8->DIER = TIM_DIER_UDE ; + + TIM8->SR &= ~TIM_SR_UIF ; // Clear flag + TIM8->SR &= ~TIM_SR_CC2IF ; // Clear flag + TIM8->DIER |= TIM_DIER_CC2IE ; + TIM8->DIER |= TIM_DIER_UIE ; + + TIM8->CR1 = TIM_CR1_CEN ; + NVIC_EnableIRQ(TIM8_CC_IRQn) ; + NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn) ; +} + +extern "C" void TIM8_CC_IRQHandler() +{ + TIM8->DIER &= ~TIM_DIER_CC2IE ; // stop this interrupt + TIM8->SR &= ~TIM_SR_CC2IF ; // Clear flag + + setupTrainerPulses() ; + + TrainerPulsePtr = TrainerPpmStream ; + TIM8->DIER |= TIM_DIER_UDE ; + + TIM8->SR &= ~TIM_SR_UIF ; // Clear this flag + TIM8->DIER |= TIM_DIER_UIE ; // Enable this interrupt +} + +extern "C" void TIM8_UP_TIM13_IRQHandler() +{ + TIM8->SR &= ~TIM_SR_UIF ; // Clear flag + + TIM8->ARR = *TrainerPulsePtr++ ; + if ( *TrainerPulsePtr == 0 ) + { + TIM8->SR &= ~TIM_SR_CC2IF ; // Clear this flag + TIM8->DIER |= TIM_DIER_CC2IE ; // Enable this interrupt + } +} + +// Trainer capture, PC8, Timer 3 channel 3 +void init_trainer_capture() +{ + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN ; // Enable portC clock + configure_pins( 0x0100, PIN_PERIPHERAL | PIN_PORTC | PIN_TR_PPM_IN ) ; + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN ; // Enable clock + + TIM3->ARR = 0xFFFF ; + TIM3->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1 ; // 0.5uS + TIM3->CR2 = 0 ; + TIM3->CCMR2 = TIM_CCMR2_IC3F_0 | TIM_CCMR2_IC3F_1 | TIM_CCMR2_CC3S_0 ; + TIM3->CCER = TIM_CCER_CC3E ; + TIM3->SR &= ~TIM_SR_CC3IF ; // Clear flag + TIM3->DIER |= TIM_DIER_CC3IE ; + TIM3->CR1 = TIM_CR1_CEN ; + NVIC_EnableIRQ(TIM3_IRQn) ; +} + + +extern "C" void TIM3_IRQHandler() +{ + uint16_t capture ; + static uint16_t lastCapt ; + uint16_t val ; + + capture = TIM3->CCR3 ; + + val = (uint16_t)(capture - lastCapt) / 2 ; + lastCapt = capture; + + // We prcoess g_ppmInsright here to make servo movement as smooth as possible + // while under trainee control + if ((val>4000) && (val < 19000)) { // G: Prioritize reset pulse. (Needed when less than 8 incoming pulses) + ppmInState = 1; // triggered + } + else { + if(ppmInState && (ppmInState<=8)) { + if ((val>800) && (val<2200)) { + g_ppmIns[ppmInState++ - 1] = (int16_t)(val - 1500)*(g_eeGeneral.PPM_Multiplier+10)/10; //+-500 != 512, but close enough. + } + else { + ppmInState = 0; // not triggered + } + } + } +}