Simple FM Sound Synthesis with touch screen and accelerometer control, based on STM32F746G-DISCO
Dependencies: ADXL345 AUDIO_DISCO_F746NG BSP_DISCO_F746NG LCD_DISCO_F746NG SDRAM_DISCO_F746NG TS_DISCO_F746NG mbed-dev
Fork of Workshop_5 by
Diff: main.cpp
- Revision:
- 2:a1330350c32e
- Parent:
- 0:da04816fb411
- Child:
- 3:cd1cb0003a3d
--- a/main.cpp Thu Mar 24 20:51:24 2016 +0000 +++ b/main.cpp Tue Aug 23 06:34:53 2016 +0000 @@ -1,136 +1,160 @@ -#include "mbed.h" -#include "AUDIO_DISCO_F746NG.h" -#include "SDRAM_DISCO_F746NG.h" +//*********** +// WORKSHOP 4 +//*********** + +// Author: Stefano Fasciani - stefanofasciani@stefanofasciani.com +// Date 7/8/2016 +// FM Sinth for DISCO_F746NG and ADXL345 +// Frequency Modulation Sound SYnthesis With Fixed Parameters Displayed on LCD + + +#include "sinth.h" + + +ADXL345 accelerometer(D11,D12,D13,D10); +TS_DISCO_F746NG ts; +TS_StateTypeDef TS; AUDIO_DISCO_F746NG audio; -// audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized and FMC enabled SDRAM_DISCO_F746NG sdram; - -DigitalOut led_green(LED1); -DigitalOut led_red(LED2); +LCD_DISCO_F746NG lcd; Serial pc(USBTX, USBRX); -typedef enum -{ - BUFFER_OFFSET_NONE = 0, - BUFFER_OFFSET_HALF = 1, - BUFFER_OFFSET_FULL = 2, -}BUFFER_StateTypeDef; + +//FM Synthesis Parameters +float amplitude = 0.5; //numbers between 0.0 and 1.0 +float pitch = 400; // numbers between 50 and 5000 +float modrate = 0; // numbers between -1000 and 1000 +float moddepth = 0; //numbers between -1000 and 1000 +float filter = 1.0f; //numbers between 0.0 (full filter) and 1.0 (do not filter) + + -#define AUDIO_BLOCK_SIZE ((uint32_t)512) -#define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */ -#define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ -__IO uint32_t audio_rec_buffer_state = BUFFER_OFFSET_NONE; -static uint8_t SetSysClock_PLL_HSE_200MHz(); +void get_parameters(){ + + char temp_string[20]; + + //read input data + ts.GetState(&TS); + accelerometer.getOutput(acc_readings); + + + if(TS.touchDetected){ + //map to synthesis parameters + amplitude = 0.5; //map(get_touch_vertical(),0.0,1.0); + } + else { + amplitude = 0; + } + + + pitch = get_note_pitch(); //map(get_touch_horizontal(),50.0,5000.0); + + modrate = map(get_acc_horizontal(), //input + 0, //modrate range minimum (not less than -1000) + 200.0); //modrate range maximum (not higher than 1000) + + moddepth = map(get_acc_vertical(), //input + -100.0, //moddepth range minimum (not less than -1000) + 100.0); //moddepth range maximum (not higher than 1000) + + + + filter = map(get_touch_vertical(), //input + 0.0, //filter range minimum (not less than 0.0) + 0.7); //filter range maximum (not higher than 1.0) + + + //update display + switch(update_round){ + case 0: + sprintf(temp_string,"%f",amplitude); lcd.DisplayStringAt(250, LINE(1),(uint8_t *)temp_string, LEFT_MODE); + case 1: + sprintf(temp_string,"%f",pitch); lcd.DisplayStringAt(250, LINE(3),(uint8_t *)temp_string, LEFT_MODE); + case 2: + sprintf(temp_string,"%f",modrate); lcd.DisplayStringAt(250, LINE(5),(uint8_t *)temp_string, LEFT_MODE); + case 3: + sprintf(temp_string,"%f",moddepth); lcd.DisplayStringAt(250, LINE(7),(uint8_t *)temp_string, LEFT_MODE); + case 4: + sprintf(temp_string,"%f",filter); lcd.DisplayStringAt(250, LINE(9),(uint8_t *)temp_string, LEFT_MODE); + } + update_round++; + if(update_round>4)update_round=0; + + return; +} + + + int main() { + + //initialize touch screen + ts.Init(lcd.GetXSize(), lcd.GetYSize()); + wait(0.2); + + // lcd initialization to display synthesis parameter + lcd.Clear(LCD_COLOR_BLACK); + display_keyboard(); + lcd.SetBackColor(LCD_COLOR_BLACK); + lcd.SetTextColor(LCD_COLOR_LIGHTBLUE); + lcd.DisplayStringAt(10, LINE(1),(uint8_t *)"AMPLITUDE :", LEFT_MODE); + lcd.DisplayStringAt(10, LINE(3),(uint8_t *)"PITCH (Hz) :", LEFT_MODE); + lcd.DisplayStringAt(10, LINE(5),(uint8_t *)"MOD.RATE (Hz):", LEFT_MODE); + lcd.DisplayStringAt(10, LINE(7),(uint8_t *)"MOD.DEPTH :", LEFT_MODE); + lcd.DisplayStringAt(10, LINE(9),(uint8_t *)"FILTER :", LEFT_MODE); + + wait(0.2); + + + //initialize accelerometer + accelerometer.getDevId(); + accelerometer.setPowerControl(0x00); + accelerometer.setDataFormatControl(0x0B); + accelerometer.setDataRate(ADXL345_3200HZ); + accelerometer.setPowerControl(0x08); + wait(0.2); + + //sound synthesis initialization + init_sin_table(); SetSysClock_PLL_HSE_200MHz(); pc.baud(9600); - - pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n"); - led_red = 0; - - pc.printf("\nAUDIO RECORD INIT OK\n"); - pc.printf("Microphones sound streamed to headphones\n"); - - /* Initialize SDRAM buffers */ - memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2); - memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2); - audio_rec_buffer_state = BUFFER_OFFSET_NONE; - - /* Start Recording */ - audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); - - /* Start Playback */ + memset((void *)out_buffer, 0, AUDIO_BLOCK_SIZE*2*sizeof(uint16_t)); + audio_out_buffer_state = BUFFER_OFFSET_NONE; audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); - audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2); + audio.OUT_Play((uint16_t*)out_buffer, AUDIO_BLOCK_SIZE * 2 * sizeof(int16_t)); while (1) { - /* Wait end of half block recording */ - while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) { - } - audio_rec_buffer_state = BUFFER_OFFSET_NONE; - /* Copy recorded 1st half block */ - memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE); - /* Wait end of one block recording */ - while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { - } - audio_rec_buffer_state = BUFFER_OFFSET_NONE; - /* Copy recorded 2nd half block */ - memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE); + + while(audio_out_buffer_state != BUFFER_OFFSET_HALF); + audio_out_buffer_state = BUFFER_OFFSET_NONE; + get_parameters(); + sint_osc(); + copy_buffer(0); + + + while(audio_out_buffer_state != BUFFER_OFFSET_FULL); + audio_out_buffer_state = BUFFER_OFFSET_NONE; + get_parameters(); + sint_osc(); + copy_buffer(AUDIO_BLOCK_SIZE); + } } -/*------------------------------------------------------------------------------------- - Callbacks implementation: - the callbacks API are defined __weak in the stm32746g_discovery_audio.c file - and their implementation should be done in the user code if they are needed. - Below some examples of callback implementations. - -------------------------------------------------------------------------------------*/ -/** - * @brief Manages the DMA Transfer complete interrupt. - * @param None - * @retval None - */ -void BSP_AUDIO_IN_TransferComplete_CallBack(void) -{ - audio_rec_buffer_state = BUFFER_OFFSET_FULL; - return; -} - -/** - * @brief Manages the DMA Half Transfer complete interrupt. - * @param None - * @retval None - */ -void BSP_AUDIO_IN_HalfTransfer_CallBack(void) -{ - audio_rec_buffer_state = BUFFER_OFFSET_HALF; - return; -} -static uint8_t SetSysClock_PLL_HSE_200MHz() -{ - RCC_ClkInitTypeDef RCC_ClkInitStruct; - RCC_OscInitTypeDef RCC_OscInitStruct; - - // Enable power clock - __PWR_CLK_ENABLE(); - - // Enable HSE oscillator and activate PLL with HSE as source - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; - RCC_OscInitStruct.HSEState = RCC_HSE_ON; /* External xtal on OSC_IN/OSC_OUT */ +/* +CONNECTION DISCO_F746NG to ADXL345 +D10 - SS - CS +D11 - MOSI - SDA +D12 - MISO - SDO +D13 - SCK - SCL +3V3 - VCC - VCC +GND - GND - GND +*/ - // Warning: this configuration is for a 25 MHz xtal clock only - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLM = 25; // VCO input clock = 1 MHz (25 MHz / 25) - RCC_OscInitStruct.PLL.PLLN = 400; // VCO output clock = 400 MHz (1 MHz * 400) - RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLLCLK = 200 MHz (400 MHz / 2) - RCC_OscInitStruct.PLL.PLLQ = 8; // USB clock = 50 MHz (400 MHz / 8) - - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) - { - return 0; // FAIL - } + + - // Activate the OverDrive to reach the 216 MHz Frequency - if (HAL_PWREx_EnableOverDrive() != HAL_OK) - { - return 0; // FAIL - } - - // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers - RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 200 MHz - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 200 MHz - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 50 MHz - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // 100 MHz - - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) - { - return 0; // FAIL - } - HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_4); - return 1; // OK -} + +