En el caso de RTTY 45.45 baudios, también tendrá símbolos que no son un número entero de muestras, por lo que necesita una función que pueda llamarse cada muestra y luego indicar su valor de retorno cuando ese símbolo haya finalizado. Y necesita un acumulador de fase, que mantiene una cuenta corriente de dónde está la fase de la onda sinusoidal.
Para enviar símbolos cuya longitud no sea un múltiplo entero de la frecuencia de muestreo, necesita esta función ...
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;
}
Para usarlo, genere la siguiente muestra de onda sinusoidal y llame a esta función, luego verifique si el valor de retorno NO es igual a dos. Si no es igual a dos, avance al siguiente símbolo y decida si está enviando una marca de espacio, luego llame a esta función nuevamente dentro del bloque de código que se ejecuta cuando descubrió que el valor de retorno no es igual a dos.
Y aquí está el acumulador de fase del firmware de Rockbox, con un cambio para permitir cambios en la amplitud (el volumen total es 32767, el volumen completo desfasado 180 grados es -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;
}