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: sinth.cpp
- Revision:
- 2:a1330350c32e
diff -r 00e079bad171 -r a1330350c32e sinth.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sinth.cpp Tue Aug 23 06:34:53 2016 +0000 @@ -0,0 +1,221 @@ + +// Author: Stefano Fasciani - stefanofasciani@stefanofasciani.com +// Date 7/8/2016 +// FM Sinth for DISCO_F746NG and ADXL345 + +#include "sinth.h" + +float table[TABLE_SIZE]; +int16_t out_buffer[AUDIO_BLOCK_SIZE*2]; +float osc_buf[AUDIO_BLOCK_SIZE/2]; +__IO uint32_t audio_out_buffer_state = BUFFER_OFFSET_NONE; +float idx_1 = 0; +float idx_2 = 0; +float filt_old_samp = 0; +static float frqTL = 0.04266666666667; +static float two_pi_48k = 1.3089969389957471826927680763665e-4; +int acc_readings[3]; +int update_round = 0; + +void BSP_AUDIO_OUT_TransferComplete_CallBack(void){ + audio_out_buffer_state = BUFFER_OFFSET_FULL; + return; +} + + +void BSP_AUDIO_OUT_HalfTransfer_CallBack(void){ + audio_out_buffer_state = BUFFER_OFFSET_HALF; + return; +} + +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 */ + + // 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 +} + +void sint_osc(){ + + int i; + float mod; + int indexBase; + float indexFract, value1, value2; + + for (i=0;i<AUDIO_BLOCK_SIZE/2;i++){ + indexBase = floor(idx_2); + indexFract = idx_2 - (float)indexBase; + value1 = table[indexBase]; + value2 = table[(indexBase+1)%TABLE_SIZE]; + mod = moddepth*(value1 + ((value2 - value1) * indexFract)); + + indexBase = floor(idx_1); + indexFract = idx_1 - (float)indexBase; + value1 = table[indexBase]; + value2 = table[(indexBase+1)%TABLE_SIZE]; + osc_buf[i] = amplitude*(value1 + ((value2 - value1) * indexFract)); + + idx_1 = idx_1 + ((frqTL * pitch) + mod); + while (idx_1 >= TABLE_SIZE){ + idx_1 -= TABLE_SIZE; + } + while (idx_1 < 0){ + idx_1 += TABLE_SIZE; + } + idx_2 = idx_2 + (frqTL * modrate); + while (idx_2 >= TABLE_SIZE){ + idx_2 -= TABLE_SIZE; + } + while (idx_2 < 0){ + idx_2 += TABLE_SIZE; + } + + } + + osc_buf[0] = filter*osc_buf[0] + (1-filter)*filt_old_samp; + for(i=1;i<AUDIO_BLOCK_SIZE/2;i++){ + osc_buf[i] = filter*osc_buf[i] + (1-filter)*osc_buf[i-1]; + } + filt_old_samp = osc_buf[(AUDIO_BLOCK_SIZE/2)-1]; + + + return; +} + +void copy_buffer(int offset){ + int i; + for(i=0;i<AUDIO_BLOCK_SIZE/2;i++){ + out_buffer[offset+(i*2)] = out_buffer[offset+(i*2)+1] = (int16_t)(30000*osc_buf[i]); + } + + return; +} + + +void init_sin_table(){ + + int i; + for(i=0;i<TABLE_SIZE;i++){ + table[i] = sinf((float)(two_pi_48k*(23.4375f)*(float)i)); + } + return; +} + +float map_full(float x, float in_min, float in_max, float out_min, float out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +float map(float x, float out_min, float out_max) { + return (x - 0.0f) * (out_max - out_min) / (1.0f - 0.0f) + out_min; +} + +float get_touch_horizontal(){ + float temp = map_full(TS.touchX[0],1,480,0.0,1.0); + if(temp > 1)temp=1; + else if(temp < 0)temp=0; + return temp; +} + +float get_touch_vertical(){ + float temp = map_full(TS.touchY[0],1,272,0.0,1.0); + if(temp > 1)temp=1; + else if(temp < 0)temp=0; + return temp; +} + +float get_acc_horizontal(){ + float temp = map_full((float)(int16_t)acc_readings[1],230,-230,0.0,1.0); //for full range -/+256 + if(temp > 1)temp=1; + else if(temp < 0)temp=0; + return temp; +} + +float get_acc_vertical(){ + float temp = map_full((float)(int16_t)acc_readings[0],230,-230,0.0,1.0); //for full range -/+256 + if(temp > 1)temp=1; + else if(temp < 0)temp=0; + return temp; +} + +void display_keyboard(){ + + lcd.SetTextColor(LCD_COLOR_LIGHTRED); + lcd.FillRect(2,0,38,272); + lcd.FillRect(82,0,38,272); + lcd.FillRect(162,0,38,272); + lcd.FillRect(202,0,38,272); + lcd.FillRect(282,0,38,272); + lcd.FillRect(362,0,38,272); + lcd.FillRect(442,0,38,272); + + lcd.SetTextColor(LCD_COLOR_DARKRED); + lcd.FillRect(42,0,38,272); + lcd.FillRect(122,0,38,272); + lcd.FillRect(242,0,38,272); + lcd.FillRect(322,0,38,272); + lcd.FillRect(402,0,38,272); + + lcd.SetTextColor(LCD_COLOR_BLACK); + lcd.FillRect(1,21,480,232); + + return; +} + +float get_note_pitch(){ + + float pitch = 0; + + if((TS.touchX[0]>=1)&&(TS.touchX[0]<=40)) pitch = 523.25f; + else if((TS.touchX[0]>=41)&&(TS.touchX[0]<=80)) pitch = 554.37f; + else if((TS.touchX[0]>=81)&&(TS.touchX[0]<=120)) pitch = 587.33f; + else if((TS.touchX[0]>=121)&&(TS.touchX[0]<=160)) pitch = 622.25f; + else if((TS.touchX[0]>=161)&&(TS.touchX[0]<=200)) pitch = 659.25f; + else if((TS.touchX[0]>=201)&&(TS.touchX[0]<=240)) pitch = 698.46f; + else if((TS.touchX[0]>=241)&&(TS.touchX[0]<=280)) pitch = 739.99f; + else if((TS.touchX[0]>=281)&&(TS.touchX[0]<=320)) pitch = 783.99f; + else if((TS.touchX[0]>=321)&&(TS.touchX[0]<=360)) pitch = 830.61f; + else if((TS.touchX[0]>=361)&&(TS.touchX[0]<=400)) pitch = 880.00; + else if((TS.touchX[0]>=401)&&(TS.touchX[0]<=440)) pitch = 932.33; + else if((TS.touchX[0]>=441)&&(TS.touchX[0]<=480)) pitch = 987.77; + + return pitch; +}