No caso de RTTY 45.45 baud, você também terá símbolos que não são um número inteiro de amostras, portanto, você precisa de uma função que possa ser chamada de cada amostra e, em seguida, sinalizar seu valor de retorno quando esse símbolo terminar. E você precisa de um acumulador de fase, que mantenha um registro constante de onde está a fase da onda senoidal.
Para enviar símbolos cujo comprimento não seja um múltiplo inteiro da taxa de amostragem, você precisa desta função ...
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 usá-lo, gere a próxima amostra de onda senoidal e chame essa função e verifique se o valor de retorno NÃO é igual a dois. Se não for igual a dois, avance para o próximo símbolo e decida se está enviando uma marca de espaço, depois chame essa função novamente dentro do bloco de código que será executado quando você descobrir que o valor de retorno não é igual a dois.
E aqui está o acumulador de fase do firmware Rockbox, com uma alteração para permitir alterações na amplitude (o volume total é 32767, o volume total fora de fase de 180 graus é -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;
}