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

Committer:
stefanofasciani
Date:
Sun Jan 01 13:54:19 2017 +0000
Revision:
3:cd1cb0003a3d
Parent:
2:a1330350c32e
First Commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
stefanofasciani 2:a1330350c32e 1
stefanofasciani 2:a1330350c32e 2 // Author: Stefano Fasciani - stefanofasciani@stefanofasciani.com
stefanofasciani 2:a1330350c32e 3 // Date 7/8/2016
stefanofasciani 2:a1330350c32e 4 // FM Sinth for DISCO_F746NG and ADXL345
stefanofasciani 2:a1330350c32e 5
stefanofasciani 2:a1330350c32e 6 #include "sinth.h"
stefanofasciani 2:a1330350c32e 7
stefanofasciani 2:a1330350c32e 8 float table[TABLE_SIZE];
stefanofasciani 2:a1330350c32e 9 int16_t out_buffer[AUDIO_BLOCK_SIZE*2];
stefanofasciani 2:a1330350c32e 10 float osc_buf[AUDIO_BLOCK_SIZE/2];
stefanofasciani 2:a1330350c32e 11 __IO uint32_t audio_out_buffer_state = BUFFER_OFFSET_NONE;
stefanofasciani 2:a1330350c32e 12 float idx_1 = 0;
stefanofasciani 2:a1330350c32e 13 float idx_2 = 0;
stefanofasciani 2:a1330350c32e 14 float filt_old_samp = 0;
stefanofasciani 2:a1330350c32e 15 static float frqTL = 0.04266666666667;
stefanofasciani 2:a1330350c32e 16 static float two_pi_48k = 1.3089969389957471826927680763665e-4;
stefanofasciani 2:a1330350c32e 17 int acc_readings[3];
stefanofasciani 2:a1330350c32e 18 int update_round = 0;
stefanofasciani 2:a1330350c32e 19
stefanofasciani 2:a1330350c32e 20 void BSP_AUDIO_OUT_TransferComplete_CallBack(void){
stefanofasciani 2:a1330350c32e 21 audio_out_buffer_state = BUFFER_OFFSET_FULL;
stefanofasciani 2:a1330350c32e 22 return;
stefanofasciani 2:a1330350c32e 23 }
stefanofasciani 2:a1330350c32e 24
stefanofasciani 2:a1330350c32e 25
stefanofasciani 2:a1330350c32e 26 void BSP_AUDIO_OUT_HalfTransfer_CallBack(void){
stefanofasciani 2:a1330350c32e 27 audio_out_buffer_state = BUFFER_OFFSET_HALF;
stefanofasciani 2:a1330350c32e 28 return;
stefanofasciani 2:a1330350c32e 29 }
stefanofasciani 2:a1330350c32e 30
stefanofasciani 2:a1330350c32e 31 uint8_t SetSysClock_PLL_HSE_200MHz()
stefanofasciani 2:a1330350c32e 32 {
stefanofasciani 2:a1330350c32e 33 RCC_ClkInitTypeDef RCC_ClkInitStruct;
stefanofasciani 2:a1330350c32e 34 RCC_OscInitTypeDef RCC_OscInitStruct;
stefanofasciani 2:a1330350c32e 35
stefanofasciani 2:a1330350c32e 36 // Enable power clock
stefanofasciani 2:a1330350c32e 37 __PWR_CLK_ENABLE();
stefanofasciani 2:a1330350c32e 38
stefanofasciani 2:a1330350c32e 39 // Enable HSE oscillator and activate PLL with HSE as source
stefanofasciani 2:a1330350c32e 40 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
stefanofasciani 2:a1330350c32e 41 RCC_OscInitStruct.HSEState = RCC_HSE_ON; /* External xtal on OSC_IN/OSC_OUT */
stefanofasciani 2:a1330350c32e 42
stefanofasciani 2:a1330350c32e 43 // Warning: this configuration is for a 25 MHz xtal clock only
stefanofasciani 2:a1330350c32e 44 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
stefanofasciani 2:a1330350c32e 45 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
stefanofasciani 2:a1330350c32e 46 RCC_OscInitStruct.PLL.PLLM = 25; // VCO input clock = 1 MHz (25 MHz / 25)
stefanofasciani 2:a1330350c32e 47 RCC_OscInitStruct.PLL.PLLN = 400; // VCO output clock = 400 MHz (1 MHz * 400)
stefanofasciani 2:a1330350c32e 48 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLLCLK = 200 MHz (400 MHz / 2)
stefanofasciani 2:a1330350c32e 49 RCC_OscInitStruct.PLL.PLLQ = 8; // USB clock = 50 MHz (400 MHz / 8)
stefanofasciani 2:a1330350c32e 50
stefanofasciani 2:a1330350c32e 51 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
stefanofasciani 2:a1330350c32e 52 {
stefanofasciani 2:a1330350c32e 53 return 0; // FAIL
stefanofasciani 2:a1330350c32e 54 }
stefanofasciani 2:a1330350c32e 55
stefanofasciani 2:a1330350c32e 56 // Activate the OverDrive to reach the 216 MHz Frequency
stefanofasciani 2:a1330350c32e 57 if (HAL_PWREx_EnableOverDrive() != HAL_OK)
stefanofasciani 2:a1330350c32e 58 {
stefanofasciani 2:a1330350c32e 59 return 0; // FAIL
stefanofasciani 2:a1330350c32e 60 }
stefanofasciani 2:a1330350c32e 61
stefanofasciani 2:a1330350c32e 62 // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers
stefanofasciani 2:a1330350c32e 63 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
stefanofasciani 2:a1330350c32e 64 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 200 MHz
stefanofasciani 2:a1330350c32e 65 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 200 MHz
stefanofasciani 2:a1330350c32e 66 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 50 MHz
stefanofasciani 2:a1330350c32e 67 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // 100 MHz
stefanofasciani 2:a1330350c32e 68
stefanofasciani 2:a1330350c32e 69 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
stefanofasciani 2:a1330350c32e 70 {
stefanofasciani 2:a1330350c32e 71 return 0; // FAIL
stefanofasciani 2:a1330350c32e 72 }
stefanofasciani 2:a1330350c32e 73 HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_4);
stefanofasciani 2:a1330350c32e 74 return 1; // OK
stefanofasciani 2:a1330350c32e 75 }
stefanofasciani 2:a1330350c32e 76
stefanofasciani 2:a1330350c32e 77 void sint_osc(){
stefanofasciani 2:a1330350c32e 78
stefanofasciani 2:a1330350c32e 79 int i;
stefanofasciani 2:a1330350c32e 80 float mod;
stefanofasciani 2:a1330350c32e 81 int indexBase;
stefanofasciani 2:a1330350c32e 82 float indexFract, value1, value2;
stefanofasciani 2:a1330350c32e 83
stefanofasciani 2:a1330350c32e 84 for (i=0;i<AUDIO_BLOCK_SIZE/2;i++){
stefanofasciani 2:a1330350c32e 85 indexBase = floor(idx_2);
stefanofasciani 2:a1330350c32e 86 indexFract = idx_2 - (float)indexBase;
stefanofasciani 2:a1330350c32e 87 value1 = table[indexBase];
stefanofasciani 2:a1330350c32e 88 value2 = table[(indexBase+1)%TABLE_SIZE];
stefanofasciani 2:a1330350c32e 89 mod = moddepth*(value1 + ((value2 - value1) * indexFract));
stefanofasciani 2:a1330350c32e 90
stefanofasciani 2:a1330350c32e 91 indexBase = floor(idx_1);
stefanofasciani 2:a1330350c32e 92 indexFract = idx_1 - (float)indexBase;
stefanofasciani 2:a1330350c32e 93 value1 = table[indexBase];
stefanofasciani 2:a1330350c32e 94 value2 = table[(indexBase+1)%TABLE_SIZE];
stefanofasciani 2:a1330350c32e 95 osc_buf[i] = amplitude*(value1 + ((value2 - value1) * indexFract));
stefanofasciani 2:a1330350c32e 96
stefanofasciani 2:a1330350c32e 97 idx_1 = idx_1 + ((frqTL * pitch) + mod);
stefanofasciani 2:a1330350c32e 98 while (idx_1 >= TABLE_SIZE){
stefanofasciani 2:a1330350c32e 99 idx_1 -= TABLE_SIZE;
stefanofasciani 2:a1330350c32e 100 }
stefanofasciani 2:a1330350c32e 101 while (idx_1 < 0){
stefanofasciani 2:a1330350c32e 102 idx_1 += TABLE_SIZE;
stefanofasciani 2:a1330350c32e 103 }
stefanofasciani 2:a1330350c32e 104 idx_2 = idx_2 + (frqTL * modrate);
stefanofasciani 2:a1330350c32e 105 while (idx_2 >= TABLE_SIZE){
stefanofasciani 2:a1330350c32e 106 idx_2 -= TABLE_SIZE;
stefanofasciani 2:a1330350c32e 107 }
stefanofasciani 2:a1330350c32e 108 while (idx_2 < 0){
stefanofasciani 2:a1330350c32e 109 idx_2 += TABLE_SIZE;
stefanofasciani 2:a1330350c32e 110 }
stefanofasciani 2:a1330350c32e 111
stefanofasciani 2:a1330350c32e 112 }
stefanofasciani 2:a1330350c32e 113
stefanofasciani 2:a1330350c32e 114 osc_buf[0] = filter*osc_buf[0] + (1-filter)*filt_old_samp;
stefanofasciani 2:a1330350c32e 115 for(i=1;i<AUDIO_BLOCK_SIZE/2;i++){
stefanofasciani 2:a1330350c32e 116 osc_buf[i] = filter*osc_buf[i] + (1-filter)*osc_buf[i-1];
stefanofasciani 2:a1330350c32e 117 }
stefanofasciani 2:a1330350c32e 118 filt_old_samp = osc_buf[(AUDIO_BLOCK_SIZE/2)-1];
stefanofasciani 2:a1330350c32e 119
stefanofasciani 2:a1330350c32e 120
stefanofasciani 2:a1330350c32e 121 return;
stefanofasciani 2:a1330350c32e 122 }
stefanofasciani 2:a1330350c32e 123
stefanofasciani 2:a1330350c32e 124 void copy_buffer(int offset){
stefanofasciani 2:a1330350c32e 125 int i;
stefanofasciani 2:a1330350c32e 126 for(i=0;i<AUDIO_BLOCK_SIZE/2;i++){
stefanofasciani 2:a1330350c32e 127 out_buffer[offset+(i*2)] = out_buffer[offset+(i*2)+1] = (int16_t)(30000*osc_buf[i]);
stefanofasciani 2:a1330350c32e 128 }
stefanofasciani 2:a1330350c32e 129
stefanofasciani 2:a1330350c32e 130 return;
stefanofasciani 2:a1330350c32e 131 }
stefanofasciani 2:a1330350c32e 132
stefanofasciani 2:a1330350c32e 133
stefanofasciani 2:a1330350c32e 134 void init_sin_table(){
stefanofasciani 2:a1330350c32e 135
stefanofasciani 2:a1330350c32e 136 int i;
stefanofasciani 2:a1330350c32e 137 for(i=0;i<TABLE_SIZE;i++){
stefanofasciani 2:a1330350c32e 138 table[i] = sinf((float)(two_pi_48k*(23.4375f)*(float)i));
stefanofasciani 2:a1330350c32e 139 }
stefanofasciani 2:a1330350c32e 140 return;
stefanofasciani 2:a1330350c32e 141 }
stefanofasciani 2:a1330350c32e 142
stefanofasciani 2:a1330350c32e 143 float map_full(float x, float in_min, float in_max, float out_min, float out_max) {
stefanofasciani 2:a1330350c32e 144 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
stefanofasciani 2:a1330350c32e 145 }
stefanofasciani 2:a1330350c32e 146
stefanofasciani 2:a1330350c32e 147 float map(float x, float out_min, float out_max) {
stefanofasciani 2:a1330350c32e 148 return (x - 0.0f) * (out_max - out_min) / (1.0f - 0.0f) + out_min;
stefanofasciani 2:a1330350c32e 149 }
stefanofasciani 2:a1330350c32e 150
stefanofasciani 2:a1330350c32e 151 float get_touch_horizontal(){
stefanofasciani 2:a1330350c32e 152 float temp = map_full(TS.touchX[0],1,480,0.0,1.0);
stefanofasciani 2:a1330350c32e 153 if(temp > 1)temp=1;
stefanofasciani 2:a1330350c32e 154 else if(temp < 0)temp=0;
stefanofasciani 2:a1330350c32e 155 return temp;
stefanofasciani 2:a1330350c32e 156 }
stefanofasciani 2:a1330350c32e 157
stefanofasciani 2:a1330350c32e 158 float get_touch_vertical(){
stefanofasciani 2:a1330350c32e 159 float temp = map_full(TS.touchY[0],1,272,0.0,1.0);
stefanofasciani 2:a1330350c32e 160 if(temp > 1)temp=1;
stefanofasciani 2:a1330350c32e 161 else if(temp < 0)temp=0;
stefanofasciani 2:a1330350c32e 162 return temp;
stefanofasciani 2:a1330350c32e 163 }
stefanofasciani 2:a1330350c32e 164
stefanofasciani 2:a1330350c32e 165 float get_acc_horizontal(){
stefanofasciani 2:a1330350c32e 166 float temp = map_full((float)(int16_t)acc_readings[1],230,-230,0.0,1.0); //for full range -/+256
stefanofasciani 2:a1330350c32e 167 if(temp > 1)temp=1;
stefanofasciani 2:a1330350c32e 168 else if(temp < 0)temp=0;
stefanofasciani 2:a1330350c32e 169 return temp;
stefanofasciani 2:a1330350c32e 170 }
stefanofasciani 2:a1330350c32e 171
stefanofasciani 2:a1330350c32e 172 float get_acc_vertical(){
stefanofasciani 2:a1330350c32e 173 float temp = map_full((float)(int16_t)acc_readings[0],230,-230,0.0,1.0); //for full range -/+256
stefanofasciani 2:a1330350c32e 174 if(temp > 1)temp=1;
stefanofasciani 2:a1330350c32e 175 else if(temp < 0)temp=0;
stefanofasciani 2:a1330350c32e 176 return temp;
stefanofasciani 2:a1330350c32e 177 }
stefanofasciani 2:a1330350c32e 178
stefanofasciani 2:a1330350c32e 179 void display_keyboard(){
stefanofasciani 2:a1330350c32e 180
stefanofasciani 2:a1330350c32e 181 lcd.SetTextColor(LCD_COLOR_LIGHTRED);
stefanofasciani 2:a1330350c32e 182 lcd.FillRect(2,0,38,272);
stefanofasciani 2:a1330350c32e 183 lcd.FillRect(82,0,38,272);
stefanofasciani 2:a1330350c32e 184 lcd.FillRect(162,0,38,272);
stefanofasciani 2:a1330350c32e 185 lcd.FillRect(202,0,38,272);
stefanofasciani 2:a1330350c32e 186 lcd.FillRect(282,0,38,272);
stefanofasciani 2:a1330350c32e 187 lcd.FillRect(362,0,38,272);
stefanofasciani 2:a1330350c32e 188 lcd.FillRect(442,0,38,272);
stefanofasciani 2:a1330350c32e 189
stefanofasciani 2:a1330350c32e 190 lcd.SetTextColor(LCD_COLOR_DARKRED);
stefanofasciani 2:a1330350c32e 191 lcd.FillRect(42,0,38,272);
stefanofasciani 2:a1330350c32e 192 lcd.FillRect(122,0,38,272);
stefanofasciani 2:a1330350c32e 193 lcd.FillRect(242,0,38,272);
stefanofasciani 2:a1330350c32e 194 lcd.FillRect(322,0,38,272);
stefanofasciani 2:a1330350c32e 195 lcd.FillRect(402,0,38,272);
stefanofasciani 2:a1330350c32e 196
stefanofasciani 2:a1330350c32e 197 lcd.SetTextColor(LCD_COLOR_BLACK);
stefanofasciani 2:a1330350c32e 198 lcd.FillRect(1,21,480,232);
stefanofasciani 2:a1330350c32e 199
stefanofasciani 2:a1330350c32e 200 return;
stefanofasciani 2:a1330350c32e 201 }
stefanofasciani 2:a1330350c32e 202
stefanofasciani 2:a1330350c32e 203 float get_note_pitch(){
stefanofasciani 2:a1330350c32e 204
stefanofasciani 2:a1330350c32e 205 float pitch = 0;
stefanofasciani 2:a1330350c32e 206
stefanofasciani 2:a1330350c32e 207 if((TS.touchX[0]>=1)&&(TS.touchX[0]<=40)) pitch = 523.25f;
stefanofasciani 2:a1330350c32e 208 else if((TS.touchX[0]>=41)&&(TS.touchX[0]<=80)) pitch = 554.37f;
stefanofasciani 2:a1330350c32e 209 else if((TS.touchX[0]>=81)&&(TS.touchX[0]<=120)) pitch = 587.33f;
stefanofasciani 2:a1330350c32e 210 else if((TS.touchX[0]>=121)&&(TS.touchX[0]<=160)) pitch = 622.25f;
stefanofasciani 2:a1330350c32e 211 else if((TS.touchX[0]>=161)&&(TS.touchX[0]<=200)) pitch = 659.25f;
stefanofasciani 2:a1330350c32e 212 else if((TS.touchX[0]>=201)&&(TS.touchX[0]<=240)) pitch = 698.46f;
stefanofasciani 2:a1330350c32e 213 else if((TS.touchX[0]>=241)&&(TS.touchX[0]<=280)) pitch = 739.99f;
stefanofasciani 2:a1330350c32e 214 else if((TS.touchX[0]>=281)&&(TS.touchX[0]<=320)) pitch = 783.99f;
stefanofasciani 2:a1330350c32e 215 else if((TS.touchX[0]>=321)&&(TS.touchX[0]<=360)) pitch = 830.61f;
stefanofasciani 2:a1330350c32e 216 else if((TS.touchX[0]>=361)&&(TS.touchX[0]<=400)) pitch = 880.00;
stefanofasciani 2:a1330350c32e 217 else if((TS.touchX[0]>=401)&&(TS.touchX[0]<=440)) pitch = 932.33;
stefanofasciani 2:a1330350c32e 218 else if((TS.touchX[0]>=441)&&(TS.touchX[0]<=480)) pitch = 987.77;
stefanofasciani 2:a1330350c32e 219
stefanofasciani 2:a1330350c32e 220 return pitch;
stefanofasciani 2:a1330350c32e 221 }