Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Diff: SITAEL_Sound-Generation.cpp
- Revision:
- 3:7df960e4e4d5
diff -r 93bba36e0c06 -r 7df960e4e4d5 SITAEL_Sound-Generation.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SITAEL_Sound-Generation.cpp Wed Aug 31 14:01:23 2022 +0000 @@ -0,0 +1,371 @@ +// Tested : NUCLEO F207ZG +// Tested : NUCLEO L476RG +#include "mbed.h" + +// Definizione periferiche +Serial pc(USBTX, USBRX); +//AnalogOut OutWave(PA_5); //F207ZG +AnalogOut OutWave(PA_4); //L476RG +DigitalOut DigitalWave(PA_1); +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); + +// definizione della frequenza delle note ottava centrale del pianoforte +#define Z 100.00 // diagnostica +#define C 261.63 +#define Cd 277.18 +#define Db 277.18 +#define D 293.66 +#define Dd 311.13 +#define Eb 311.13 +#define E 329.63 +#define F 349.23 +#define Fd 369.99 +#define Gb 369.99 +#define G 392.9 +#define Gd 415.3 +#define Ab 415.3 +#define A 440.0 +#define Ad 466.16 +#define Bb 466.16 +#define B 493.18 + + + + + + +// numero di campioni che compongono un periodo della sinusoide in Output sull'ADC +#define SAMPLESINENUM 45// consigliabile avere multipli di 45 + +// parametri dell'onda coseno da generare +#define PI (3.141592653589793238462) +#define AMPLITUDE 32767 //(1.0) // x * 3.3V +#define PHASE (PI/2) // 2*pi è un periodo +#define OFFSET 32767 //(0x7FFF) + +// numero di note componenti la scala diatonica +#define NUMTONE 120 + +// Output LED di diagnostica +DigitalOut led(LED1); + +// ticker per la generazione dell'onda con DAC +Ticker SampleOutTicker; + +// Buffer contenente la sinusoide da porre in output. +unsigned short usaSine[SAMPLESINENUM]; + +// prototipo di funzione che genera i campioni della sinusoide da utilizzare per la generazione tramite DAC +void CalculateSinewave(void); + +// carattere in arrivo dal PC +volatile char cReadChar=0; +volatile char cOldReadChar=0; + +// indice, nell'array, del campione da porre in output +volatile int nSampleOutIndex; +// contatore dei campioni in output sul DAC +volatile int nSampleOutCount; +// Periodo di generazione campioni in output DeltaT = T/NumSample +double fDeltaT; +// amplificazione per il dato da spedire sull'ADC +volatile double fAmp; +//volatile double fAmpNew; +// flag per bloccare la generazione del segnale +volatile bool bStop; +// frequenza segnale da generare +volatile double fFreq; +// periodo della sinusoide da generare +double fPeriod; +double dDiatonic[NUMTONE]; + +//**************************** +// Create the sinewave buffer +//**************************** +void CalculateSinewave(int nOffset, int nAmplitude, double fPhase) +{ + // variabile contenente l'angolo in radianti + double fRads; + // indici per i cicli + int nIndex; + // passo in frequenza fissato dal numero di campioni in cui voglio dividere un periodo di sinusoide: DeltaF = 360°/NUMSAMPLE + double fDeltaF; + // angolo per il quale bisogna calcolare il valore di sinusoide: fAngle = nIndex*DeltaF + double fAngle; + + fDeltaF = 360.0/SAMPLESINENUM; + for (nIndex = 0; nIndex < SAMPLESINENUM; nIndex++) + { + fAngle = nIndex*fDeltaF; // angolo per il quale bisogna calcolare il campione di sinusoide + fRads = (PI * fAngle)/180.0; // Convert degree in radian + //usaSine[nIndex] = AMPLITUDE * cos(fRads + PHASE) + OFFSET; + usaSine[nIndex] = nAmplitude * cos(fRads + fPhase) + nOffset; + } +} + + +//********************************************** +// Crea le frequenze delle note del pianoforte +//********************************************** +void CreateDiatonic() +{ + int nTono; + int nOttava; + + // ottava centrale = ottava 4 + dDiatonic[4*12+0]=261.63; // C + dDiatonic[4*12+1]=277.18; // C#/Db + dDiatonic[4*12+2]=293.66; // D + dDiatonic[4*12+3]=311.13; // D#/Eb + dDiatonic[4*12+4]=329.63; // E + dDiatonic[4*12+5]=349.23; // F + dDiatonic[4*12+6]=369.99; // F#/Gb + dDiatonic[4*12+7]=392.00; // G + dDiatonic[4*12+8]=415.30; // G#/Ab + dDiatonic[4*12+9]=440.00; // A + dDiatonic[4*12+10]=466.16; // A#/Bb + dDiatonic[4*12+11]=493.88; // B + + // dalla ottava 5 alla 9 + for(nOttava=5; nOttava<9; nOttava++) + { + for(nTono=0; nTono<12; nTono++) + { + dDiatonic[(nOttava*12)+nTono]=dDiatonic[((nOttava-1)*12)+nTono]*2; + } + } + + // dalla ottava 0 alla 3 + for(nOttava=3; nOttava>=0; nOttava--) + { + for(nTono=0; nTono<12; nTono++) + { + dDiatonic[(nOttava*12)+nTono]=dDiatonic[((nOttava+1)*12)+nTono]/2; + } + } +} + +//*************************** +// generazione sample da DAC +//*************************** +void SampleOut() +{ + // se è stato inviato il comando Stop, non fare niente fino a nuovo comando + if(bStop) + { + } + else // se non è stato inviato il comando di bStop continua + { + // output del campione della forma d'onda + OutWave.write_u16(usaSine[nSampleOutIndex]); + + // incrementa l'indice del campione in output, modulo NUMSAMPLE: se NUMSAMPLE è 360, nSampleOutIndex va da 0 a 359 + nSampleOutIndex++; + if(nSampleOutIndex >= SAMPLESINENUM) + { + nSampleOutIndex=0; + } + + } +} + + + + +//******************* +// Loop Principale +//******************* +int main() +{ + // configura velocità della comunicazione seriale su USB-VirtualCom e invia messaggio di benvenuto + pc.baud(921600); //921600 bps + + + // messaggio di benvenuto + pc.printf("\r\nHallo \r\n"); + pc.printf("\r\n*** SineWave Generation ***\r\n"); + + //inizializza variabili + cReadChar = 0; + nSampleOutIndex=0; + nSampleOutCount=0; + bStop=true; + + // test dei LED + led1=1; //Verde + wait_ms(1000); + led1=0; + led2=1; // Blu + wait_ms(1000); + led2=0; + led3=1; //Rosso + wait_ms(1000); + led3=0; + //+++++++++++++++++++++++++++++++++++ START Test ONDA DIGITALE ++++++++++++++++++++++++++++++++++++++ + /* + led1=1; + led2=1; + led3=1; + while(true) + { + DigitalWave=0; + //wait_us(2024); //SI + //wait_us(2551); //SOL + wait_ms(300); //MI + DigitalWave=1; + wait_ms(300); + } + */ + //+++++++++++++++++++++++++++++++++++ END Test ONDA DIGITALE +++++++++++++++++++++++++++++++++++++++++++++ + + + //+++++++++++++++++++++++++++++++++++ START Test ONDA ANALOGICA ++++++++++++++++++++++++++++++++++++++++++ + fFreq=20.0; // frequenza della sinusoide di test + pc.printf("\n\r--- Generazione LA = %.2f Hz ampiezza nominale ---\n\r", fFreq); + bStop = false; + // genera la frequenza relativa alla nota che è stata selezionata + fAmp = 0.3; // coefficiente per il quale viene moltiplicato l'ampiezza massima + fDeltaT = 1.0/(fFreq*SAMPLESINENUM); + CalculateSinewave(32767, (32767*fAmp), (PI/2.0)); // generazione della sinusoide con valori nominali + SampleOutTicker.attach(&SampleOut,fDeltaT); // avvia output della sinusoide per generazione + while(true){}; + //+++++++++++++++++++++++++++++++++++ END Test ONDA ANALOGICA ++++++++++++++++++++++++++++++++++++++++++++ + + //+++++++++++++++++++++++++++++++++++ START Test ONDA ANALOGICA ++++++++++++++++++++++++++++++++++++++++++++++ + + // variabile contenente l'angolo in radianti + double fRads; + // passo in frequenza fissato dal numero di campioni in cui voglio dividere un periodo di sinusoide: DeltaF = 360°/NUMSAMPLE + double fDeltaF; + // angolo per il quale bisogna calcolare il valore di sinusoide: fAngle = nIndex*DeltaF + double fAngle; + + fFreq=10.0;// frequenza della sinusoide DO da generare + pc.printf("\n\r--- Generazione frequenza = %.2f Hz ---\n\r", fFreq); + + + nSampleOutIndex=0; + while(true) + { + + // output del campione della forma d'onda + //OutWave.write_u16( 32767*cos(nSampleOutIndex/3.14)); + OutWave.write_u16( nSampleOutIndex); + + // incrementa l'indice del campione in output, modulo NUMSAMPLE: se NUMSAMPLE è 360, nSampleOutIndex va da 0 a 359 + nSampleOutIndex++; + if(nSampleOutIndex >= 32768) + { + nSampleOutIndex =0; + } + + wait_ms(10); + } + + //+++++++++++++++++++++++++++++++++++ END Test ONDA ANALOGICA ++++++++++++++++++++++++++++++++++++++++++ + + //+++++++++++++++++++++++++++++++++++ START Loop principale ++++++++++++++++++++++++++++++++++++++++++ + while(true) + { + // verifica se è arrivato un carattere dalla seriale del pc + if(pc.readable()) + //if (true) + { + cReadChar = pc.getc(); // Read hyperterminal + //cReadChar = 'C'; + // genera la nota corrispondente al carattere ricevuto + switch(cReadChar) + { + //DO + case 'c': + case 'C': + { + fFreq=261.63;// frequenza della sinusoide DO da generare + pc.printf("\n\r--- Generazione DO = %.2f Hz ampiezza nominale ---\n\r", fFreq); + bStop = false; + } break; + // RE + case 'd': + case 'D': + { + fFreq=293.66;// frequenza della sinusoide RE da generare + pc.printf("\n\r--- Generazione RE = %.2f Hz ampiezza nominale ---\n\r", fFreq); + bStop = false; + } break; + // RE#/MIb + case 'm': + case 'M': + { + fFreq=311.13; + pc.printf("\n\r--- Generazione Mib = %.2f Hz ampiezza nominale ---\n\r", fFreq); + bStop = false; + } break; + case 'e': + case 'E': + { + fFreq=329.63; // frequenza della sinusoide MI da generare + pc.printf("\n\r--- Generazione MI = %.2f Hz ampiezza nominale ---\n\r", fFreq); + bStop = false; + } break; + case 'f': + case 'F': + { + fFreq=349.23;// frequenza della sinusoide FA da generare + pc.printf("\n\r--- Generazione FA = %.2f Hz ampiezza nominale ---\n\r", fFreq); + bStop = false; + } break; + + // SOL + case 'g': + case 'G': + { + fFreq=392.0; + pc.printf("\n\r--- Generazione SOL = %.2f Hz ampiezza nominale ---\n\r", fFreq); + bStop = false; + } break; + // LA + case 'a': + case 'A': + { + fFreq=440.0; // frequenza della sinusoide LA da generare + pc.printf("\n\r--- Generazione LA = %.2f Hz ampiezza nominale ---\n\r", fFreq); + bStop = false; + } break; + //SI + case 'b': + case 'B': + { + fFreq=493.88;// frequenza della sinusoide SI da generare + pc.printf("\n\r--- Generazione SI = %.2f Hz ampiezza nominale ---\n\r", fFreq); + bStop = false; + } break; + + // pausa + case ' ': + { + bStop=true; + pc.printf("\n\r--- Generation Stopped ---\n\r"); + } break; + default: + { + bStop=true; // se la nota non è riconosciuta blocca la generazione + pc.printf("\n\r--- Wrong Tone ---\n\r"); + } break; + } // switch (cReadChar) + + // genera la frequenza relativa alla nota che è stata selezionata + fAmp = 1.0; // coefficiente per il quale viene moltiplicato l'ampiezza massima + fDeltaT = 1.0/(fFreq*SAMPLESINENUM); + CalculateSinewave(32767, (32767*fAmp), (PI/2.0)); // generazione della sinusoide con valori nominali + SampleOutTicker.attach(&SampleOut,fDeltaT); // avvia output della sinusoide per generazione + } + else // se non è stato premuto nessun tasto diagnostica + { + + } + } + + +} \ No newline at end of file