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
sinth.cpp
00001 00002 // Author: Stefano Fasciani - stefanofasciani@stefanofasciani.com 00003 // Date 7/8/2016 00004 // FM Sinth for DISCO_F746NG and ADXL345 00005 00006 #include "sinth.h" 00007 00008 float table[TABLE_SIZE]; 00009 int16_t out_buffer[AUDIO_BLOCK_SIZE*2]; 00010 float osc_buf[AUDIO_BLOCK_SIZE/2]; 00011 __IO uint32_t audio_out_buffer_state = BUFFER_OFFSET_NONE; 00012 float idx_1 = 0; 00013 float idx_2 = 0; 00014 float filt_old_samp = 0; 00015 static float frqTL = 0.04266666666667; 00016 static float two_pi_48k = 1.3089969389957471826927680763665e-4; 00017 int acc_readings[3]; 00018 int update_round = 0; 00019 00020 void BSP_AUDIO_OUT_TransferComplete_CallBack(void){ 00021 audio_out_buffer_state = BUFFER_OFFSET_FULL; 00022 return; 00023 } 00024 00025 00026 void BSP_AUDIO_OUT_HalfTransfer_CallBack(void){ 00027 audio_out_buffer_state = BUFFER_OFFSET_HALF; 00028 return; 00029 } 00030 00031 uint8_t SetSysClock_PLL_HSE_200MHz() 00032 { 00033 RCC_ClkInitTypeDef RCC_ClkInitStruct; 00034 RCC_OscInitTypeDef RCC_OscInitStruct; 00035 00036 // Enable power clock 00037 __PWR_CLK_ENABLE(); 00038 00039 // Enable HSE oscillator and activate PLL with HSE as source 00040 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 00041 RCC_OscInitStruct.HSEState = RCC_HSE_ON; /* External xtal on OSC_IN/OSC_OUT */ 00042 00043 // Warning: this configuration is for a 25 MHz xtal clock only 00044 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 00045 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 00046 RCC_OscInitStruct.PLL.PLLM = 25; // VCO input clock = 1 MHz (25 MHz / 25) 00047 RCC_OscInitStruct.PLL.PLLN = 400; // VCO output clock = 400 MHz (1 MHz * 400) 00048 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLLCLK = 200 MHz (400 MHz / 2) 00049 RCC_OscInitStruct.PLL.PLLQ = 8; // USB clock = 50 MHz (400 MHz / 8) 00050 00051 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 00052 { 00053 return 0; // FAIL 00054 } 00055 00056 // Activate the OverDrive to reach the 216 MHz Frequency 00057 if (HAL_PWREx_EnableOverDrive() != HAL_OK) 00058 { 00059 return 0; // FAIL 00060 } 00061 00062 // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers 00063 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); 00064 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 200 MHz 00065 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 200 MHz 00066 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 50 MHz 00067 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // 100 MHz 00068 00069 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) 00070 { 00071 return 0; // FAIL 00072 } 00073 HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_4); 00074 return 1; // OK 00075 } 00076 00077 void sint_osc(){ 00078 00079 int i; 00080 float mod; 00081 int indexBase; 00082 float indexFract, value1, value2; 00083 00084 for (i=0;i<AUDIO_BLOCK_SIZE/2;i++){ 00085 indexBase = floor(idx_2); 00086 indexFract = idx_2 - (float)indexBase; 00087 value1 = table[indexBase]; 00088 value2 = table[(indexBase+1)%TABLE_SIZE]; 00089 mod = moddepth*(value1 + ((value2 - value1) * indexFract)); 00090 00091 indexBase = floor(idx_1); 00092 indexFract = idx_1 - (float)indexBase; 00093 value1 = table[indexBase]; 00094 value2 = table[(indexBase+1)%TABLE_SIZE]; 00095 osc_buf[i] = amplitude*(value1 + ((value2 - value1) * indexFract)); 00096 00097 idx_1 = idx_1 + ((frqTL * pitch) + mod); 00098 while (idx_1 >= TABLE_SIZE){ 00099 idx_1 -= TABLE_SIZE; 00100 } 00101 while (idx_1 < 0){ 00102 idx_1 += TABLE_SIZE; 00103 } 00104 idx_2 = idx_2 + (frqTL * modrate); 00105 while (idx_2 >= TABLE_SIZE){ 00106 idx_2 -= TABLE_SIZE; 00107 } 00108 while (idx_2 < 0){ 00109 idx_2 += TABLE_SIZE; 00110 } 00111 00112 } 00113 00114 osc_buf[0] = filter*osc_buf[0] + (1-filter)*filt_old_samp; 00115 for(i=1;i<AUDIO_BLOCK_SIZE/2;i++){ 00116 osc_buf[i] = filter*osc_buf[i] + (1-filter)*osc_buf[i-1]; 00117 } 00118 filt_old_samp = osc_buf[(AUDIO_BLOCK_SIZE/2)-1]; 00119 00120 00121 return; 00122 } 00123 00124 void copy_buffer(int offset){ 00125 int i; 00126 for(i=0;i<AUDIO_BLOCK_SIZE/2;i++){ 00127 out_buffer[offset+(i*2)] = out_buffer[offset+(i*2)+1] = (int16_t)(30000*osc_buf[i]); 00128 } 00129 00130 return; 00131 } 00132 00133 00134 void init_sin_table(){ 00135 00136 int i; 00137 for(i=0;i<TABLE_SIZE;i++){ 00138 table[i] = sinf((float)(two_pi_48k*(23.4375f)*(float)i)); 00139 } 00140 return; 00141 } 00142 00143 float map_full(float x, float in_min, float in_max, float out_min, float out_max) { 00144 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 00145 } 00146 00147 float map(float x, float out_min, float out_max) { 00148 return (x - 0.0f) * (out_max - out_min) / (1.0f - 0.0f) + out_min; 00149 } 00150 00151 float get_touch_horizontal(){ 00152 float temp = map_full(TS.touchX[0],1,480,0.0,1.0); 00153 if(temp > 1)temp=1; 00154 else if(temp < 0)temp=0; 00155 return temp; 00156 } 00157 00158 float get_touch_vertical(){ 00159 float temp = map_full(TS.touchY[0],1,272,0.0,1.0); 00160 if(temp > 1)temp=1; 00161 else if(temp < 0)temp=0; 00162 return temp; 00163 } 00164 00165 float get_acc_horizontal(){ 00166 float temp = map_full((float)(int16_t)acc_readings[1],230,-230,0.0,1.0); //for full range -/+256 00167 if(temp > 1)temp=1; 00168 else if(temp < 0)temp=0; 00169 return temp; 00170 } 00171 00172 float get_acc_vertical(){ 00173 float temp = map_full((float)(int16_t)acc_readings[0],230,-230,0.0,1.0); //for full range -/+256 00174 if(temp > 1)temp=1; 00175 else if(temp < 0)temp=0; 00176 return temp; 00177 } 00178 00179 void display_keyboard(){ 00180 00181 lcd.SetTextColor(LCD_COLOR_LIGHTRED); 00182 lcd.FillRect(2,0,38,272); 00183 lcd.FillRect(82,0,38,272); 00184 lcd.FillRect(162,0,38,272); 00185 lcd.FillRect(202,0,38,272); 00186 lcd.FillRect(282,0,38,272); 00187 lcd.FillRect(362,0,38,272); 00188 lcd.FillRect(442,0,38,272); 00189 00190 lcd.SetTextColor(LCD_COLOR_DARKRED); 00191 lcd.FillRect(42,0,38,272); 00192 lcd.FillRect(122,0,38,272); 00193 lcd.FillRect(242,0,38,272); 00194 lcd.FillRect(322,0,38,272); 00195 lcd.FillRect(402,0,38,272); 00196 00197 lcd.SetTextColor(LCD_COLOR_BLACK); 00198 lcd.FillRect(1,21,480,232); 00199 00200 return; 00201 } 00202 00203 float get_note_pitch(){ 00204 00205 float pitch = 0; 00206 00207 if((TS.touchX[0]>=1)&&(TS.touchX[0]<=40)) pitch = 523.25f; 00208 else if((TS.touchX[0]>=41)&&(TS.touchX[0]<=80)) pitch = 554.37f; 00209 else if((TS.touchX[0]>=81)&&(TS.touchX[0]<=120)) pitch = 587.33f; 00210 else if((TS.touchX[0]>=121)&&(TS.touchX[0]<=160)) pitch = 622.25f; 00211 else if((TS.touchX[0]>=161)&&(TS.touchX[0]<=200)) pitch = 659.25f; 00212 else if((TS.touchX[0]>=201)&&(TS.touchX[0]<=240)) pitch = 698.46f; 00213 else if((TS.touchX[0]>=241)&&(TS.touchX[0]<=280)) pitch = 739.99f; 00214 else if((TS.touchX[0]>=281)&&(TS.touchX[0]<=320)) pitch = 783.99f; 00215 else if((TS.touchX[0]>=321)&&(TS.touchX[0]<=360)) pitch = 830.61f; 00216 else if((TS.touchX[0]>=361)&&(TS.touchX[0]<=400)) pitch = 880.00; 00217 else if((TS.touchX[0]>=401)&&(TS.touchX[0]<=440)) pitch = 932.33; 00218 else if((TS.touchX[0]>=441)&&(TS.touchX[0]<=480)) pitch = 987.77; 00219 00220 return pitch; 00221 }
Generated on Tue Jul 12 2022 16:59:03 by 1.7.2