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

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
-}
+
+