Toto je starší verze dokumentu!
Cílem této práce je vytvořit hudební systém MPC, který bude schopný nahrávat zvuky a následně je reprodukovat. K realizaci tohoto systému byla využita vývojová deska STM32F4DISCOVERY, která obsahuje integrovaný mikrofon MP45DT02 MEMS.Rovněž potřebujeme sluchátka, USB flash disk a tlačítka popřípadě maticovou klávesnici.
Aplikace přechází mezi stavem nahrávání zvuků nebo přehrávání uložených zvuků podle toho, zda bylo zmáčnuto USER button na vývojové desce. Dojde-li ke k prvnímu stisku tlačítka, tak dochází ke zvolení režumu nahrávání („Audio recording“). Uživatel po stisknu tlačítka stiskne libovolnou klávesu na klávesnici a tím přiřadí nahrávaný zvuk k dané klávese.Po opětovném stisnutí tlačítka se audiostopa uloží na USB flash disk pod názvem podle toho jaká klávesa byla stisknuta a zařízení přechází do stavu přehrávání (Audio playback). Ve stavu přehrávání dochází k reprodukci uložených zvuků podle toho jakou klávesu stiskneme. Níže lze vidět vývojový diagram této aplikace.
Mikrofon MP45DT02 je připojen přes sběrnici I2S pomocí jednoho datového a jednoho hodinového pinu. Hodiny I2S jsou nastaveny na 1024MHz podle výstupní vzokrovací frekvence audio souboru (16KHz) a zvoleného decimačního faktoru (64). I2S je nastavena tak, aby vyvolala přerušení pokaždé, když je příjmuto 16bit vzorků. Vzorky z mikrofunu jsou ve formátu PDM (Pulse density modulation) a jsou pomocí externé knihovny fultru PDMlib převáděny na 16-bit PCM a výsledná audio stopa „.wav“ je uložena na USB. Pro přehrávání je rovněž využito I2S sběrnice a DMA, kdy jsou jednotlivé bloky dat (1024bytes) přenášeny z USB do interní SRAM paměti. Při přehrávání jsou použity dva buffery. Jeden slouží k ukládání dat z USB a druhý k přehrávání vzorků pomocí externího kodeku DAC. Níže je přiložen vývojový diagram pro proces nahrávání.
Základem pro mojí aplikaci je Audio playback and recording example pro STM32F4DISCOVERY (AN3997-Aplication note) a program KEIL. Audio playback and recording example projekt obsahuje následující knihovny:
Naše aplikace je založena na výše zmíněných knihovnách a je tedy potřeba tyto knihovny upravit podle námi požadované funkce.Nejdříve jsem v souboru souboru main.h definoval nové názvy souborů, se kterými program pracuje při přehrávání a nahrávaní zvuků, tak aby ve výsledku bylo možno nahrát tři různé zvuky a následně je po stisku určíté klávesy přehrát. Celá aplikace je tvořena pro možnost uložení tří zvuků. Při potřeba uložit více zvuků je postup obdobný.
/* Select the media where the Wave file is stored */ #if !defined (MEDIA_IntFLASH) && !defined (MEDIA_USB_KEY) //#define MEDIA_IntFLASH /* Wave file stored in internal flash */ //#define MEDIA_USB_KEY /* Wave file stored in USB flash */ #endif /* Uncomment this define to disable repeat option */ //#define PLAY_REPEAT_OFF #if defined MEDIA_USB_KEY /* You can change the Wave file name as you need, but do not exceed 11 characters */ #define WAVE_NAME "0:audio.wav" #define REC_WAVE_NAME "0:rec.wav" #define WAVE_NAME_1 "0:audi1.wav" #define REC_WAVE_NAME_1 "0:rec1.wav" #define WAVE_NAME_2 "0:audi2.wav" #define REC_WAVE_NAME_2 "0:rec2.wav"
V tomto souboru je nastavení časovače pro LED diody a obsluha hlavního kódu který je větven podle toho, zda pro vzorky využíváme interní nebo externí úložiště. V nekonečné smyčce je poté spouštěna funkce USBH_Process. Kód byl doplněn o volání funkce GPIO_Init(), která obsahuje nastavení pinů pro klávesnici (definováno v stm32f4_discovery.c).
/* Includes ------------------------------------------------------------------*/ #include "main.h" /** @addtogroup STM32F4-Discovery_Audio_Player_Recorder * @{ */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ #if defined MEDIA_USB_KEY USB_OTG_CORE_HANDLE USB_OTG_Core; USBH_HOST USB_Host; #endif RCC_ClocksTypeDef RCC_Clocks; __IO uint8_t RepeatState = 0; __IO uint16_t CCR_Val = 16826; extern __IO uint8_t LED_Toggle; /* Private function prototypes -----------------------------------------------*/ static void TIM_LED_Config(void); /* Private functions ---------------------------------------------------------*/ /** * @brief Main program. * @param None * @retval None */ int main(void) { /* Initialize LEDS */ STM_EVAL_LEDInit(LED3); STM_EVAL_LEDInit(LED4); STM_EVAL_LEDInit(LED5); STM_EVAL_LEDInit(LED6); /* Green Led On: start of application */ STM_EVAL_LEDOn(LED4); /* SysTick end of count event each 10ms */ RCC_GetClocksFreq(&RCC_Clocks); SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); /* Configure TIM4 Peripheral to manage LEDs lighting */ TIM_LED_Config(); /* Initialize the repeat status */ RepeatState = 0; LED_Toggle = 7; #if defined MEDIA_IntFLASH WavePlayBack(I2S_AudioFreq_48k); while (1); #elif defined MEDIA_USB_KEY /* Initialize User Button */ STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_EXTI); GPIO_Init(); /* Init Host Library */ USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &USBH_MSC_cb, &USR_Callbacks); while (1) { /* Host Task handler */ USBH_Process(&USB_OTG_Core, &USB_Host); } #endif } /** * @brief Configures the TIM Peripheral for Led toggling. * @param None * @retval None */ static void TIM_LED_Config(void) { TIM_OCInitTypeDef TIM_OCInitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; uint16_t prescalervalue = 0; /* TIM4 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* Enable the TIM3 gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Initialize Leds mounted on STM324F4-EVAL board */ STM_EVAL_LEDInit(LED3); STM_EVAL_LEDInit(LED4); STM_EVAL_LEDInit(LED6); /* Compute the prescaler value */ prescalervalue = (uint16_t) ((SystemCoreClock ) / 550000) - 1; /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 65535; TIM_TimeBaseStructure.TIM_Prescaler = prescalervalue; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); /* Enable TIM4 Preload register on ARR */ TIM_ARRPreloadConfig(TIM4, ENABLE); /* TIM PWM1 Mode configuration: Channel */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR_Val; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; /* Output Compare PWM1 Mode configuration: Channel2 */ TIM_OC1Init(TIM4, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Disable); /* TIM Interrupts enable */ TIM_ITConfig(TIM4, TIM_IT_CC1 , ENABLE); /* TIM4 enable counter */ TIM_Cmd(TIM4, ENABLE); } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ while (1) { } } #endif
Cílem této práce bylo vytvořit hudební systém MPC, který bude schopný nahrávat zvuky a následně je reprodukovat. Bylo dosaženo náhrávání zvuků do různých souboru na USB, podle toho jaká klávesa byla stisknuta. Zvuky jsou pak při přepnutí do režimu přehrávání reprodukovány, podle toho jaká klávesa je stisknuta. Bohužel se při práci na projektu nepodařilo dosáhnout efektu mixování zvuků tak, aby dva zvuky mohly být reprodukovány součastně. Aplikace nyní funguje tak, že jsou zvuky přehrávány postupně a jednotlivý audiosoubor je vždy dohrán až do konce. Možným pokračováním na projektu by bylo ošetření zákmitů tlačítek, využití celé maticové klávesnice a celková změna v řešení projektu, kdy by bylo využito možnosti přerušení při stisku určité
kláves y a část uživatelského kódu by byla napsána do obsluhy tohoto přerušení, což by nejspíše vyžadovalo větší změny v použitých knihovnách audio playback examplu .