I've wanted to learn a bit about DSP, so a TU seemed like the perfect
project. It is now driving my model 15 with ITTY!
This is running on a PIC32MZ. I plan on checking how much time it is
spending doing stuff and perhaps it would run on the PIC32MX.
Here's my code as of right now:
int main ( void ){
biquad *MarkFilter; // Audio BPF for mark
biquad *SpaceFilter; // Audio BPF for space
biquad *MarkDataFilter; // Mark LPF after filtered data squaring
biquad *SpaceDataFilter;
uint16_t AdcSample;
double DdsFreq=100.0;
/* Initialize all modules */
SYS_Initialize ( NULL );
TMR2_Start();
OCMP1_Enable();
AudioPwmSet(0.0);
ADCHS_ChannelConversionStart(4);
MarkFilter = BiQuad_new(BPF, 0.0, 2125.0, 8000.0, 50.0); // Q-50
SpaceFilter = BiQuad_new(BPF, 0.0, 2295.0, 8000.0, 50.0);
// Create biquad BPF for mark and space, 0 dB gain, 2.125 or 2.296
kHz, 8 kHz sample freq,, 50 Jz BW
MarkDataFilter=BiQuad_new(LPF, 0.0, 136.0, 8000.0, 0.707 );
SpaceDataFilter=BiQuad_new(LPF, 0.0, 136.0, 8000.0, 0.707 );
while ( true )
{
if(Timer2TimeoutCounter==0){ // We have timed out 10 times,
so it has been 125 us
if(ADCHS_ChannelResultIsReady(4)){
AdcSample=ADCHS_ChannelResultGet(4);
AdcSamplef=(double)(AdcSample-2048)/2048.0;
ADCHS_ChannelConversionStart(4);
}
// Tone Sweep
DdsFreq*=1.00001;
if(DdsFreq>2295.0) DdsFreq=2125.0;
DdsFreqSet(DdsFreq);
// End tone sweep
//sample=DdsNextSample();
MarkSample=BiQuad(AdcSamplef,MarkFilter);
SpaceSample=BiQuad(AdcSamplef,SpaceFilter);
DiscrimOut=BiQuad(fabs(MarkSample),
MarkDataFilter)-BiQuad(fabs(SpaceSample), SpaceDataFilter);
if(DiscrimOut>=0){ // Mark
LATDbits.LATD4=1;
LATBbits.LATB1=0; // light green LED
LATBbits.LATB5=1; // red LED off
}else{
LATDbits.LATD4=0;
LATBbits.LATB1=1; // green LED off
LATBbits.LATB5=0; // red LED on
}
AudioPwmSet(AdcSamplef);
Timer2TimeoutCounter=10; // come back in 125 us. PWM
frequency is 80 kHz, so change every 10 cycles
}
/* Maintain state machines of all polled MPLAB Harmony modules. */
SYS_Tasks ( );
}
Timer 2 is generating 80 kHz PWM. Every 10 times around, the ADC is read
and started again. The ADC is converted to a double precision float called
AdcSamplef. This runs through a bandpass filter for mark and another for
space. The absolute values of the outputs of the filters are computed
(same as full wave rectification). The results go into a low pass filter
for mark and another for space. If the absolute value of the mark LPF is
greater than that of the space LPF, the SSR is turned on causing loop
current (mark). Otherwise, the loop current is interrupted (space).
There is also some Direct Digital Synthesis code in there for test. When a
frequency is set, DdsRadiansPerSample is set telling the DDS code how many
radians to add to the last value, then do a sine lookup. The result of the
DDS can be sent to the audio output (for transmit audio).
The audio output is 80 kHz PWM generated by timer 2 and an output compare
module. The duty cycle is updated at 8 kHz. The PWM goes to a single pole
RC LPF with a cutoff of 4 kHz. This is followed by a 2 pole active LPF
with the same cutoff. For testing right now, the AdcSamplef is being fed
to the audio output. I can hear it on speakers and see it on the scope.
Next steps:
1. I plan to do a long transmission from punched tape and record the audio
on an SDR (probably KFS). I will then vary filter parameters and see what
gives me the lowest error rate with noise and QSB.
2. I'll get the transmit side running. That will include an opto detecting
loop current which will then FSK the DDS. I'll put an LPF between the data
and the DDS to minimize keyclicks.
Fun stuff!
Harold
--
Not sent from an iPhone.
______________________________________________________________
GreenKeys mailing list