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 Stefano Fasciani

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sinth.cpp Source File

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 }