Skip to content

Commit 5b74338

Browse files
committed
Correct operation at sample rates > 12ksps
1 parent 02c2d98 commit 5b74338

File tree

2 files changed

+232
-106
lines changed

2 files changed

+232
-106
lines changed

radioCWModulator_F32.cpp

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,22 @@
55
*
66
* License: MIT License. Use at your own risk.
77
*/
8+
// Update notes are in radioCWModulator_F32.h
89

910
#include "radioCWModulator_F32.h"
1011
#include "sinTable512_f32.h"
1112

1213
void radioCWModulator_F32::update(void) {
13-
float32_t keyData[128]; // CW key down and up, 0.0f and 1.0f
14-
float32_t modulateCW[128]; // Storage for data to modulate sine wave
14+
15+
if(!enableXmit)
16+
return;
17+
18+
float32_t circTemp[64]; // Storage for data from Gaussian
19+
uint16_t tempIndex;
1520
uint16_t index, i;
1621
float32_t a, b;
1722
audio_block_f32_t *blockOut;
18-
23+
int32_t circIndexSave24;
1924
blockOut = AudioStream_F32::allocate_f32(); // Output block
2025
if (!blockOut) return;
2126

@@ -25,19 +30,24 @@ void radioCWModulator_F32::update(void) {
2530

2631
// We always generate CW at 12 ksps. The number of data points in this
2732
// generation varies to provide 128 output output points after
28-
// interpolation to 48 or 96 ksps.
29-
for(i=0; i<nSamplesPerUpdate; i++)
33+
// interpolation to 24, 48 or 96 ksps. So for each update(), we generate
34+
// 128 points if sample rate is 12 ksps and 32 if it is 48 ksps, etc. The
35+
// remainder are filled in by interpolation, below.
36+
for(i=0; i<nSamplesPerUpdate; i++)
3037
{
31-
timeMsF += timeSamplesMs;
38+
// Code is generated at 12 ksps, so always increment by 1000mSec/12000:
39+
timeMsF += 0.0833333; // in milliSec
3240
timeMsI = (uint32_t)(0.5 + timeMsF);
33-
34-
if(!enableXmit) // Just leave the key up and no new characters
41+
if(manualCW)
3542
{
36-
levelCW = 0.0f;
37-
goto noXmit;
43+
if(keyDown)
44+
levelCW = 1.0f;
45+
else
46+
levelCW = 0.0f;
47+
goto noAuto;
3848
}
3949

40-
switch(stateCW)
50+
switch(stateCW) // Sort out the automatic keying
4151
{
4252
case IDLE_CW:
4353
timeMsF = 0.0f;
@@ -164,44 +174,67 @@ void radioCWModulator_F32::update(void) {
164174
break;
165175
}
166176
} // end switch
167-
noXmit:
168-
keyData[i] = levelCW;
169-
} // end, over all 128 times
177+
noAuto:
178+
dataBuf12[i] = levelCW; // A float, 128 to 16 of them, starting at i=0
179+
} // end, over all 128 to 16 times
170180

171-
arm_fir_f32(&GaussLPFInst, keyData, keyData, nSamplesPerUpdate);
181+
if(sampleRate == SR_12KSPS)
182+
// Do anti-key-click shaping of the 0.0 and 1.0 values.
183+
arm_fir_f32(&GaussLPFInst, dataBuf12, dataBuf12, 128);
184+
else
185+
// Use dataBuf12A for FIR output, 64, 32, or 16 points
186+
arm_fir_f32(&GaussLPFInst, dataBuf12, dataBuf12A, nSamplesPerUpdate);
172187

173-
// INTERPOLATE - Interpolate here to support higher sample rates,
174-
// while using the same spectral LPF. To this point we have 128, 32
175-
// or 16 "active" data points for 12, 48, or 96ksps.
176-
//
177-
// 0 1 2 3 4 5 6 7 8 9 i
178-
// 0 0 0 0 1 1 1 1 2 2 i/4
179-
// t 0 0 0 t 0 0 0 t 0 i==4*(i/4)
180-
//
181-
if(nSample > 1) // Only needs interpolation if >1
188+
// For SR_12KSPS there is no interpolation
189+
190+
/* INTERPOLATE - Interpolate here to support higher sample rates,
191+
while using the same spectral LPF. To this point we have 64, 32
192+
or 16 "active" data points for 24, 48, or 96ksps, in dataBuf12A[].
193+
*/
194+
if(sampleRate == SR_24KSPS)
182195
{
183-
for(i=0; i<128; i++)
184-
{
185-
if( i==(nSample*(1/nSample)) )
186-
modulateCW[i]= keyData[i/nSample];
187-
else
188-
modulateCW[i] = 0.0f;
189-
}
190-
arm_fir_f32(&interpolateLPFInst, modulateCW, keyData, 128);
196+
for(int kk=0; kk<64; kk++) dataBuf12A[kk] *= 2.0f;
197+
arm_fir_interpolate_f32 (&interp12_24Inst, dataBuf12A, dataBuf24, 64);
198+
}
199+
else if(sampleRate == SR_48KSPS)
200+
{
201+
for(int kk=0; kk<32; kk++) dataBuf12A[kk] *= 4.0f;
202+
arm_fir_interpolate_f32 (&interp12_24Inst, dataBuf12A, dataBuf24, 32);
203+
arm_fir_interpolate_f32 (&interp24_48Inst, dataBuf24, dataBuf48, 64);
204+
}
205+
else if(sampleRate == SR_96KSPS)
206+
{
207+
for(int kk=0; kk<16; kk++) dataBuf12A[kk] *= 8.0f;
208+
arm_fir_interpolate_f32 (&interp12_24Inst, dataBuf12A, dataBuf24, 16);
209+
arm_fir_interpolate_f32 (&interp24_48Inst, dataBuf24, dataBuf48, 32);
210+
arm_fir_interpolate_f32 (&interp48_96Inst, dataBuf48, dataBuf96, 64);
191211
}
192212

193-
// Interpolation is done, now amplitude modulate CW onto a sine wave.
194-
for (i=0; i < 128; i++)
213+
// Interpolation is complete, now amplitude modulate CW onto a sine wave.
214+
for (i=0; i < 128; i++) // Always 128 modulation signals
195215
{
216+
float32_t vOut;
217+
if(sampleRate == SR_12KSPS)
218+
vOut = dataBuf12[i];
219+
else if(sampleRate == SR_24KSPS)
220+
vOut = dataBuf24[i];
221+
else if(sampleRate == SR_48KSPS)
222+
vOut = dataBuf48[i];
223+
else if(sampleRate == SR_96KSPS)
224+
vOut = dataBuf96[i];
225+
196226
phaseS += phaseIncrement;
197227
if (phaseS > 512.0f) phaseS -= 512.0f;
198228
index = (uint16_t) phaseS;
199229
float32_t deltaPhase = phaseS - (float32_t)index;
200230
// Read two nearest values of input value from the sine table
201231
a = sinTable512_f32[index];
202232
b = sinTable512_f32[index+1];
203-
blockOut->data[i] = magnitude*keyData[i]*(a+(b-a)*deltaPhase);
233+
blockOut->data[i] = magnitude*vOut*(a+(b-a)*deltaPhase);
204234
}
205235
AudioStream_F32::transmit(blockOut);
206236
AudioStream_F32::release (blockOut);
207-
}
237+
} // End update()
238+
239+
240+

0 commit comments

Comments
 (0)