Nel caso di RTTY 45.45 baud, avrai anche simboli che non sono un numero intero di campioni, quindi hai bisogno di una funzione che può essere chiamata ogni campione e quindi segnalare il suo valore di ritorno quando quel simbolo è terminato. E hai bisogno di un accumulatore di fase, che mantiene un conteggio corrente su dove si trova la fase dell'onda sinusoidale.
Per inviare simboli la cui lunghezza non è un multiplo intero della frequenza di campionamento è necessaria questa funzione ...
int millisecondTimer(double milliseconds, double samplerate, int resettime)
{
static int fracsample=0;
static int counter=0;
static int retvalue=0;
static int first=1;
static double oldmilliseconds=1.0;
static int whole_samples=0;
static int samerror=32768;
if(resettime==1)
{
samerror=0;
counter=0;
retvalue=1;
first=1;
}
if(first==1 || milliseconds !=oldmilliseconds)
{
double samplesneeded=1;
double wholesamples=0;
samplesneeded=(samplerate) * (milliseconds /1000.0);
samerror=(modf(samplesneeded, &wholesamples)) * 32768.0;
whole_samples=wholesamples;
first=0;
}
if(counter<=whole_samples)
{
retvalue=2;
counter++;
}
else
{
counter-=whole_samples;
retvalue=1;
fracsample+=samerror;
oldmilliseconds=milliseconds;
if(fracsample>=32768)
{
fracsample-=32768;
counter--;
}
}
return retvalue;
}
Per usarlo, genera il prossimo campione di onda sinusoidale e chiama questa funzione, quindi controlla se il valore di ritorno NON è uguale a due. Se non è uguale a due, passa al simbolo successivo e decidi se stai inviando un segno di spazio, quindi chiama di nuovo questa funzione all'interno del blocco di codice che viene eseguito quando scopri che il valore restituito non è uguale a due.
Ed ecco l'accumulatore di fase dal firmware Rockbox, con una modifica per consentire cambiamenti di ampiezza (il volume completo è 32767, il volume pieno sfasato di 180 gradi è -32768).
signed short lerpsin(float frequency,signed short amplitude,unsigned long samplerate)
{
/* 128 sixteen bit sine samples + guard point */
static unsigned long phase=0;
unsigned int pos =0;
unsigned short frac=0;
static unsigned long step=0;
static float old_frequency=0;
signed short diff=0;
static const signed short sinetab[129] =
{
0, 1607, 3211, 4807, 6392, 7961, 9511, 11038,
12539, 14009, 15446, 16845, 18204, 19519, 20787, 22004,
23169, 24278, 25329, 26318, 27244, 28105, 28897, 29621,
30272, 30851, 31356, 31785, 32137, 32412, 32609, 32727,
32767, 32727, 32609, 32412, 32137, 31785, 31356, 30851,
30272, 29621, 28897, 28105, 27244, 26318, 25329, 24278,
23169, 22004, 20787, 19519, 18204, 16845, 15446, 14009,
12539, 11038, 9511, 7961, 6392, 4807, 3211, 1607,
0, -1607, -3211, -4807, -6392, -7961, -9511, -11038,
-12539, -14009, -15446, -16845, -18204, -19519, -20787, -22004,
-23169, -24278, -25329, -26318, -27244, -28105, -28897, -29621,
-30272, -30851, -31356, -31785, -32137, -32412, -32609, -32727,
-32767, -32727, -32609, -32412, -32137, -31785, -31356, -30851,
-30272, -29621, -28897, -28105, -27244, -26318, -25329, -24278,
-23169, -22004, -20787, -19519, -18204, -16845, -15446, -14009,
-12539, -11038, -9511, -7961, -6392, -4807, -3211, -1607,
0,
};
if(frequency!=old_frequency)
{
step = 0x100000000ull*frequency / samplerate;
}
phase+=step;
pos = phase >> 25;
frac = (phase & 0x01ffffff) >> 9;
diff = sinetab[pos + 1] - sinetab[pos];
old_frequency=frequency;
return ((-((sinetab[pos] + (frac*diff >> 16)))) * amplitude) >> 15;
}