%Current fixed processing buffer size, in non-ME bits
nbit = 192;
+
states.Rb = Rb;
states.Rs = Rb*2; % Manchester-encoded bitrate
states.Fs = Fs;
states.Ts = Fs/states.Rs;
- states.N = nbit*states.Ts;
+ states.N = nbit*2*states.Ts;
+ %states.N
+ %states.N = floor(states.Rs*.080)*states.Ts
+ %states.N
states.nin = states.N; % Samples in the next demod cycle
states.nstash = states.Ts*2; % How many samples to stash away between proc cycles for timing adjust
states.nmem = states.N+(4*states.Ts);
states.nsym = nbit*2;
states.nbit = nbit;
+
+ %tates.nsym = floor(states.Rs*.080);
+ %states.nbit = floor(states.Rb*.080)
%Old sample memory
states.oldsamps = zeros(1,states.nmem);
ssamps(nold+1:nmem) = rx;
states.oldsamps = ssamps;
- rx_filt = zeros(1,nsym*Ts);
+ rx_filt = zeros(1,(nsym+1)*Ts);
+ length(rx_filt)
%Integrate Ts input samples at every offset
%This is the same thing as filtering with a filter of all ones
% out to Ts.
% It's implemented like this for ease of C-porting
for ii=(1:(nsym+1)*Ts)
st = ii;
- en = st+Ts;
+ en = st+Ts-1;
rx_filt(ii) = sum(ssamps(st:en));
end
+
+ length(rx_filt)
% Fine timing estimation ------------------------------------------------------
add_executable(fmfsk_mod fmfsk_mod.c)
target_link_libraries(fmfsk_mod ${CMAKE_REQUIRED_LIBRARIES} codec2)
+add_executable(fmfsk_demod fmfsk_demod.c modem_probe.c octave.c)
+target_link_libraries(fmfsk_demod ${CMAKE_REQUIRED_LIBRARIES} codec2)
+
add_executable(cohpsk_demod cohpsk_demod.c octave.c)
target_link_libraries(cohpsk_demod ${CMAKE_REQUIRED_LIBRARIES} codec2)
#include <stdlib.h>
#include <math.h>
#include <string.h>
+#include <stdio.h>
+
#include "fmfsk.h"
#include "modem_probe.h"
fmfsk->Rs = Rb*2;
fmfsk->Fs = Fs;
fmfsk->Ts = Fs/fmfsk->Rs;
- fmfsk->N = nbits*fmfsk->Ts;
+ fmfsk->N = nbits*2*fmfsk->Ts;
fmfsk->nmem = fmfsk->N+(fmfsk->Ts*4);
fmfsk->nsym = nbits*2;
fmfsk->nbit = nbits;
* float mod_out[] - Buffer for N samples of modulated FMFSK
* uint8_t tx_bits[] - Buffer containing Nbits unpacked bits
*/
+//void fmfsk_mod(struct FMFSK *fmfsk, float fmfsk_out[],uint8_t bits_in[]){
+// int i,j;
+// int Ts = fmfsk->Ts;
+// int N = fmfsk->N;
+//
+// for(i=0;i<N;){
+// /* Save a manchester-encoded 0 */
+// if(bits_in[i] == 0){
+// for(j=0; j<Ts; j++)
+// fmfsk_out[i++] = -1;
+// for(j=0; j<Ts; j++)
+// fmfsk_out[i++] = 1;
+// } else {
+// /* Save a manchester-encoded 1 */
+// for(j=0; j<Ts; j++)
+// fmfsk_out[i++] = 1;
+// for(j=0; j<Ts; j++)
+// fmfsk_out[i++] = -1;
+// }
+// }
+//}
+
void fmfsk_mod(struct FMFSK *fmfsk, float fmfsk_out[],uint8_t bits_in[]){
int i,j;
int nbit = fmfsk->nbit;
/* Save a manchester-encoded 0 */
if(bits_in[i] == 0){
for(j=0; j<Ts; j++)
- fmfsk_out[ j+i*Ts] = -1;
+ fmfsk_out[ j+i*Ts*2] = -1;
for(j=0; j<Ts; j++)
- fmfsk_out[Ts+j+i*Ts] = 1;
+ fmfsk_out[Ts+j+i*Ts*2] = 1;
} else {
/* Save a manchester-encoded 1 */
for(j=0; j<Ts; j++)
- fmfsk_out[ j+i*Ts] = 1;
+ fmfsk_out[ j+i*Ts*2] = 1;
for(j=0; j<Ts; j++)
- fmfsk_out[Ts+j+i*Ts] = -1;
+ fmfsk_out[Ts+j+i*Ts*2] = -1;
}
}
}
-
/*
* Demodulate some number of FMFSK samples. The number of samples to be
* demodulated can be found by calling fmfsk_nin().
memcpy(&oldsamps[nold], &fmfsk_in[0] , sizeof(float)*nin );
/* Allocate memory for filtering */
- float *rx_filt = alloca(sizeof(float)*nsym*Ts);
+ float *rx_filt = alloca(sizeof(float)*(nsym+1)*Ts);
/* Integrate over Ts input symbols at every offset */
for(i=0; i<(nsym+1)*Ts; i++){
t=0;
/* Integrate over some samples */
- for(j=i;j<i+Ts;j++){
+ for(j=i;j<i+Ts-1;j++){
t += oldsamps[j];
}
rx_filt[i] = t;
dphi_ft.real = cos(2*M_PI*(float)Rs/(float)Fs);
dphi_ft.imag = sin(2*M_PI*(float)Rs/(float)Fs);
- for(i=0; i<nsym*Ts; i++){
+ x.real = 0;
+ x.imag = 0;
+
+ for(i=0; i<(nsym+1)*Ts; i++){
/* Apply non-linearity */
t = rx_filt[i]*rx_filt[i];
}
/* Figure out the normalized RX timing, using David's magic number */
- norm_rx_timing = atan2f(x.imag,x.real)/(2*M_PI) - .042;
+ norm_rx_timing = atan2f(x.imag,x.real)/(2*M_PI) - .42;
rx_timing = (int)lroundf(norm_rx_timing*(float)Ts);
+ fprintf(stderr,"norm_rx_timing: %f rx_timing:%d\n",norm_rx_timing,rx_timing);
/* Figure out how far offset the sample points are */
sample_offset = (Ts/2)+Ts+rx_timing-1;
currv = rx_filt[sample_offset+(i*Ts)];
mdiff = lastv - currv;
mbit = mdiff>0 ? 1 : 0;
+ lastv = currv;
+ mdiff = mdiff>0 ? mdiff : 0-mdiff;
+ //printf("md %f\n",mdiff);
/* Put bit in it's stream */
- if((i&2)==1){
+ if((i%2)==1){
apeven += mdiff;
/* Even stream goes in LSB */
rx_bits[i>>1] |= mbit ? 0x1 : 0x0;
}else{
apodd += mdiff;
/* Odd in second-to-LSB */
- rx_bits[i>>1] |= mbit ? 0x2 : 0x0;
+ rx_bits[i>>1] = mbit ? 0x2 : 0x0;
}
}
-
if(apeven>apodd){
+ fprintf(stderr,"even has it\n");
/* Zero out odd bits from output bitstream */
for(i=0;i<nbit;i++)
rx_bits[i] &= 0x1;
}else{
+ fprintf(stderr,"it's odd\n");
/* Shift odd bits into LSB and even bits out of existence */
for(i=0;i<nbit;i++)
rx_bits[i] = (rx_bits[i]&0x2)>>1;
}
/* Save last sample of int stream for next demod round */
- fmfsk->lodd = rx_filt[sample_offset+((nsym-1)*Ts)];
+ fmfsk->lodd = lastv;
modem_probe_samp_f("t_norm_rx_timing",&norm_rx_timing,1);
modem_probe_samp_f("t_rx_filt",rx_filt,nsym*Ts);
--- /dev/null
+/*---------------------------------------------------------------------------*\
+
+ FILE........: fsk_demod.c
+ AUTHOR......: Brady O'Brien
+ DATE CREATED: 8 January 2016
+
+ C test driver for fsk_demod in fsk.c. Reads in a stream of 32 bit cpu endian
+ floats and writes out the detected bits
+
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2016 David Rowe
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1, as
+ published by the Free Software Foundation. This program is
+ distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include "fmfsk.h"
+
+#define MODEMPROBE_ENABLE
+#include "modem_probe.h"
+#include "codec2_fdmdv.h"
+
+int main(int argc,char *argv[]){
+ struct FMFSK *fmfsk;
+ int Fs,Rb;
+ FILE *fin,*fout;
+ uint8_t *bitbuf;
+ int16_t *rawbuf;
+ float *modbuf;
+ int i,t;
+
+ if(argc<4){
+ fprintf(stderr,"usage: %s SampleFreq BitRate InputModemRawFile OutputOneBitPerCharFile [OctaveLogFile]\n",argv[0]);
+ exit(1);
+ }
+
+ /* Extract parameters */
+ Fs = atoi(argv[1]);
+ Rb = atoi(argv[2]);
+
+ /* Open files */
+ if(strcmp(argv[3],"-")==0){
+ fin = stdin;
+ }else{
+ fin = fopen(argv[3],"r");
+ }
+
+ if(strcmp(argv[4],"-")==0){
+ fout = stdout;
+ }else{
+ fout = fopen(argv[4],"w");
+ }
+
+
+ if(argc>4)
+ modem_probe_init("fmfsk2",argv[5]);
+
+ /* set up FSK */
+ fmfsk = fmfsk_create(Fs,Rb);
+
+ if(fin==NULL || fout==NULL || fmfsk==NULL){
+ fprintf(stderr,"Couldn't open test vector files\n");
+ goto cleanup;
+ }
+
+ /* allocate buffers for processing */
+ bitbuf = (uint8_t*)alloca(sizeof(uint8_t)*fmfsk->nbit);
+ rawbuf = (int16_t*)alloca(sizeof(int16_t)*(fmfsk->N+fmfsk->Ts*2));
+ modbuf = (float*)alloca(sizeof(float)*(fmfsk->N+fmfsk->Ts*2));
+
+ /* Demodulate! */
+ while( fread(rawbuf,sizeof(int16_t),fmfsk_nin(fmfsk),fin) == fmfsk_nin(fmfsk) ){
+ for(i=0;i<fmfsk_nin(fmfsk);i++){
+ modbuf[i] = ((float)rawbuf[i])/FDMDV_SCALE;
+ }
+
+ modem_probe_samp_f("t_d_sampin",modbuf,fmfsk_nin(fmfsk));
+ fmfsk_demod(fmfsk,bitbuf,modbuf);
+
+ for(i=0;i<fmfsk->nbit;i++){
+ t = (int)bitbuf[i];
+ modem_probe_samp_i("t_d_bitout",&t,1);
+ }
+
+ fwrite(bitbuf,sizeof(uint8_t),fmfsk->nbit,fout);
+
+ if(fin == stdin || fout == stdin){
+ fflush(fin);
+ fflush(fout);
+ }
+ }
+
+ modem_probe_close();
+ cleanup:
+ fclose(fin);
+ fclose(fout);
+ fmfsk_destroy(fmfsk);
+ exit(0);
+}
+
while( fread(bitbuf,sizeof(uint8_t),fmfsk->nbit,fin) == fmfsk->nbit ){
fmfsk_mod(fmfsk,modbuf,bitbuf);
for(i=0; i<fmfsk->N; i++){
- rawbuf[i] = (int16_t)(modbuf[i]*(float)FDMDV_SCALE);
- }
+ rawbuf[i] = (int16_t)(modbuf[i]*(float)FDMDV_SCALE);
+ }
fwrite(rawbuf,sizeof(int16_t),fmfsk->N,fout);
- if(fin == stdin || fout == stdin){
- fflush(fin);
- fflush(fout);
- }
+ if(fin == stdin || fout == stdin){
+ fflush(fin);
+ fflush(fout);
+ }
}
cleanup:
/* Demodulate! */
while( fread(rawbuf,sizeof(int16_t),fsk_nin(fsk),fin) == fsk_nin(fsk) ){
- for(i=0;i<fsk_nin(fsk);i++){
- modbuf[i] = ((float)rawbuf[i])/FDMDV_SCALE;
- }
- modem_probe_samp_f("t_d_sampin",modbuf,fsk_nin(fsk));
+ for(i=0;i<fsk_nin(fsk);i++){
+ modbuf[i] = ((float)rawbuf[i])/FDMDV_SCALE;
+ }
+ modem_probe_samp_f("t_d_sampin",modbuf,fsk_nin(fsk));
fsk_demod(fsk,bitbuf,modbuf);
for(i=0;i<fsk->Nbits;i++){
- t = (int)bitbuf[i];
- modem_probe_samp_i("t_d_bitout",&t,1);
- }
+ t = (int)bitbuf[i];
+ modem_probe_samp_i("t_d_bitout",&t,1);
+ }
fwrite(bitbuf,sizeof(uint8_t),fsk->Nbits,fout);
if(fin == stdin || fout == stdin){
- fflush(fin);
- fflush(fout);
- }
+ fflush(fin);
+ fflush(fout);
+ }
}
modem_probe_close();
add_executable(tfsk tfsk.c ../src/kiss_fft.c ../src/kiss_fftr.c ../src/octave.c ../src/modem_probe.c)
target_link_libraries(tfsk m)
+add_executable(tfmfsk tfmfsk.c ../src/octave.c ../src/modem_probe.c)
+target_link_libraries(tfmfsk m)
+
#add_executable(t48_8 t48_8.c ../src/fdmdv.c ../src/kiss_fft.c)
#target_link_libraries(t48_8 codec2)
--- /dev/null
+/*---------------------------------------------------------------------------*\
+
+ FILE........: tfmfsk.c
+ AUTHOR......: Brady O'Brien
+ DATE CREATED: 8 February 2016
+
+ C test driver for fmfsk_mod and fmfsk_demod in fmfsk.c. Reads a file with input
+ bits/rf and spits out modulated/demoduladed samples and a dump of internal
+ state. To run unit test, see octave/tfmfsk.m
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2016 David Rowe
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1, as
+ published by the Free Software Foundation. This program is
+ distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#define MODEMPROBE_ENABLE
+
+#include "modem_probe.h"
+#include <stdio.h>
+
+/* Note: This is a dirty hack to force fsk.c to compile with modem probing enabled */
+#include "fmfsk.c"
+
+#define ST_BITS 10000
+#define ST_FS 48000
+#define ST_RS 2400
+#define ST_EBNO 8
+
+#define TEST_SELF_FULL 1 /* No-arg self test */
+#define TEST_MOD 2 /* Test modulator using in and out file */
+#define TEST_DEMOD 3 /* Test demodulator using in and out file */
+
+
+int main(int argc,char *argv[]){
+ struct FMFSK *fmfsk;
+ int Fs,Rs;
+ FILE *fin,*fout;
+
+ uint8_t *bitbuf = NULL;
+ float *modbuf = NULL;
+ uint8_t *bitbufp;
+ float *modbufp;
+
+ size_t bitbufsize = 0;
+ size_t modbufsize = 0;
+
+ int test_type;
+
+ int i;
+
+ fin = NULL;
+ fout = NULL;
+
+ /* Set up full self-test */
+ if(argc == 1){
+ test_type = TEST_SELF_FULL;
+ modem_probe_init("fmfsk","fmfsk_tfmfsk_log.txt");
+ Fs = ST_FS;
+ Rs = ST_RS;
+ } else if (argc<7){
+ /* Not running any test */
+ printf("Usage: %s [(M|D) SampleRate BitRate InputFile OutputFile OctaveLogFile]\n",argv[0]);
+ exit(1);
+ } else {
+ /* Running stim-drivin test */
+ /* Mod test */
+ if(strcmp(argv[1],"M")==0 || strcmp(argv[1],"m")==0) {
+ test_type = TEST_MOD;
+ /* Demod test */
+ } else if(strcmp(argv[1],"D")==0 || strcmp(argv[1],"d")==0) {
+ test_type = TEST_DEMOD;
+ } else {
+ printf("Must specify mod or demod test with M or D\n");
+ exit(1);
+ }
+ /* Extract parameters */
+ Fs = atoi(argv[2]);
+ Rs = atoi(argv[3]);
+
+ /* Open files */
+ fin = fopen(argv[4],"r");
+ fout = fopen(argv[5],"w");
+
+ if(fin == NULL || fout == NULL){
+ printf("Couldn't open test vector files\n");
+ exit(1);
+ }
+ /* Init modem probing */
+ modem_probe_init("fmfsk",argv[6]);
+
+ }
+
+ srand(1);
+
+ /* set up FSK */
+ fmfsk = fmfsk_create(Fs,Rs);
+ /* Modulate! */
+ if(test_type == TEST_MOD || test_type == TEST_SELF_FULL){
+ /* Generate random bits for self test */
+ if(test_type == TEST_SELF_FULL){
+ bitbufsize = ST_BITS;
+ bitbuf = (uint8_t*) malloc(sizeof(uint8_t)*ST_BITS);
+ for(i=0; i<ST_BITS; i++){
+ /* Generate a randomish bit */
+ bitbuf[i] = (uint8_t)(rand()&0x01);
+ }
+ } else { /* Load bits from a file */
+ /* Figure out how many bits are in the input file */
+ fseek(fin, 0L, SEEK_END);
+ bitbufsize = ftell(fin);
+ fseek(fin, 0L, SEEK_SET);
+ bitbuf = malloc(sizeof(uint8_t)*bitbufsize);
+ i = 0;
+ /* Read in some bits */
+ bitbufp = bitbuf;
+ while( fread(bitbufp,sizeof(uint8_t),fmfsk->nbit,fin) == fmfsk->nbit){
+ i++;
+ bitbufp+=fmfsk->nbit;
+ /* Make sure we don't break the buffer */
+ if(i*fmfsk->nbit > bitbufsize){
+ bitbuf = realloc(bitbuf,sizeof(uint8_t)*(bitbufsize+fmfsk->nbit));
+ bitbufsize += fmfsk->nbit;
+ }
+ }
+ }
+ /* Allocate modulation buffer */
+ modbuf = (float*)malloc(sizeof(float)*(bitbufsize/fmfsk->nbit)*fmfsk->N*4);
+ modbufsize = (bitbufsize/fmfsk->nbit)*fmfsk->N;
+ /* Do the modulation */
+ modbufp = modbuf;
+ bitbufp = bitbuf;
+ while( bitbufp < bitbuf+bitbufsize){
+ fmfsk_mod(fmfsk, modbufp, bitbufp);
+ modbufp += fmfsk->N;
+ bitbufp += fmfsk->nbit;
+ }
+ /* For a mod-only test, write out the result */
+ if(test_type == TEST_MOD){
+ fwrite(modbuf,sizeof(float),modbufsize,fout);
+ free(modbuf);
+ }
+ /* Free bit buffer */
+ free(bitbuf);
+ }
+
+ /* Add channel imp here */
+
+
+ /* Now test the demod */
+ if(test_type == TEST_DEMOD || test_type == TEST_SELF_FULL){
+ free(modbuf);
+ modbuf = malloc(sizeof(float)*(fmfsk->N+fmfsk->Ts*2));
+ bitbuf = malloc(sizeof(uint8_t)*fmfsk->nbit);
+ /* Demod-only test */
+ if(test_type == TEST_DEMOD){
+ while( fread(modbuf,sizeof(float),fmfsk_nin(fmfsk),fin) == fmfsk_nin(fmfsk) ){
+ fmfsk_demod(fmfsk,bitbuf,modbuf);
+ fwrite(bitbuf,sizeof(uint8_t),fmfsk->nbit,fout);
+ }
+ }
+ /* Demod after channel imp. and mod */
+ else{
+ bitbufp = bitbuf;
+ modbufp = modbuf;
+ while( modbufp < modbuf + modbufsize){
+ fmfsk_demod(fmfsk,bitbuf,modbuf);
+ modbufp += fmfsk_nin(fmfsk);
+ }
+ }
+ free(bitbuf);
+ }
+
+ modem_probe_close();
+ if(test_type == TEST_DEMOD || test_type == TEST_MOD){
+ fclose(fin);
+ fclose(fout);
+ }
+ fmfsk_destroy(fmfsk);
+ exit(0);
+}
+