genera sinusoide
Dependencies: mbed
SITAEL_Sound-Generation.cpp
- Committer:
- pinofal
- Date:
- 23 months ago
- Revision:
- 3:7df960e4e4d5
File content as of revision 3:7df960e4e4d5:
// 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
{
}
}
}