struct COHPSK *cohpsk_create(void);
void cohpsk_destroy(struct COHPSK *coh);
-void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[]);
+void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[], int nbits);
void cohpsk_clip(COMP tx_fdm[]);
void cohpsk_demod(struct COHPSK *cohpsk, float rx_bits[], int *sync, COMP rx_fdm[], int *nin_frame);
void cohpsk_get_demod_stats(struct COHPSK *cohpsk, struct MODEM_STATS *stats);
void bits_to_qpsk_symbols(COMP tx_symb[][COHPSK_NC*ND], int tx_bits[], int nbits)
{
- int i, r, c, p_r, data_r, d;
+ int i, r, c, p_r, data_r, d, diversity;
short bits;
- /* check number of bits supplied matchs number of QPSK symbols in the frame */
+ /* check allowed number of bits supplied matches number of QPSK
+ symbols in the frame */
- assert((NSYMROW*COHPSK_NC)*2 == nbits);
+ assert( (NSYMROW*COHPSK_NC*2 == nbits) || (NSYMROW*COHPSK_NC*2*ND == nbits));
+
+ /* if we input twice as many bits we don't do diversity */
+
+ if (NSYMROW*COHPSK_NC*2 == nbits) {
+ diversity = 1; /* diversity mode */
+ }
+ else {
+ diversity = 2; /* twice as many bits, non diversity mode */
+ }
/*
Insert two rows of Nc pilots at beginning of data frame.
r = 0;
for(p_r=0; p_r<2; p_r++) {
- for(c=0; c<COHPSK_NC; c++) {
- tx_symb[r][c].real = pilots_coh[p_r][c]/sqrtf(ND);
+ for(c=0; c<COHPSK_NC*ND; c++) {
+ tx_symb[r][c].real = pilots_coh[p_r][c % COHPSK_NC]/sqrtf(ND);
tx_symb[r][c].imag = 0.0;
}
r++;
}
for(data_r=0; data_r<NSYMROW; data_r++, r++) {
-
- for(c=0; c<COHPSK_NC; c++) {
+ for(c=0; c<COHPSK_NC*diversity; c++) {
i = c*NSYMROW + data_r;
bits = (tx_bits[2*i]&0x1)<<1 | (tx_bits[2*i+1]&0x1);
tx_symb[r][c] = fcmult(1.0/sqrtf(ND),qpsk_mod[bits]);
assert(p_r == NPILOTSFRAME);
assert(r == NSYMROWPILOT);
- /* copy to other carriers (diversity) */
+ /* if in diversity mode, copy symbols to upper carriers */
- for(d=1; d<ND; d++) {
+ for(d=1; d<1+ND-diversity; d++) {
for(r=0; r<NSYMROWPILOT; r++) {
for(c=0; c<COHPSK_NC; c++) {
tx_symb[r][c+COHPSK_NC*d] = tx_symb[r][c];
}
}
}
-
}
AUTHOR......: David Rowe
DATE CREATED: 5/4/2015
- COHPSK modulator, take a frame of COHPSK_BITS_PER_FRAME bits and
- generates a frame of COHPSK_NOM_SAMPLES_PER_FRAME modulated symbols.
+ COHPSK modulator, take a frame of COHPSK_BITS_PER_FRAME or
+ 2*COHPSK_BITS_PER_FRAME bits and generates a frame of
+ COHPSK_NOM_SAMPLES_PER_FRAME modulated symbols.
+
+ if nbits == COHPSK_BITS_PER_FRAME, diveristy mode is used, if nbits
+ == 2*COHPSK_BITS_PER_FRAME diversity mode is not used.
The output signal is complex to support single sided frequency
shifting, for example when testing frequency offsets in channel
\*---------------------------------------------------------------------------*/
-void cohpsk_mod(struct COHPSK *coh, COMP tx_fdm[], int tx_bits[])
+void cohpsk_mod(struct COHPSK *coh, COMP tx_fdm[], int tx_bits[], int nbits)
{
struct FDMDV *fdmdv = coh->fdmdv;
COMP tx_symb[NSYMROWPILOT][COHPSK_NC*ND];
COMP tx_onesym[COHPSK_NC*ND];
int r,c;
- bits_to_qpsk_symbols(tx_symb, tx_bits, COHPSK_BITS_PER_FRAME);
+ bits_to_qpsk_symbols(tx_symb, tx_bits, nbits);
for(r=0; r<NSYMROWPILOT; r++) {
for(c=0; c<COHPSK_NC*ND; c++)
/* Generated by write_pilot_file() Octave function */
-#define NSYMROW 4 /* number of data symbols on each row (i.e. each carrier) */
+#define NSYMROW 4 /* number of data symbols per carrier (number of rows) */
#define NS 4 /* number of data symbols between pilots */
-#define NPILOTSFRAME 2 /* number of pilot symbols on each row */
+#define NPILOTSFRAME 2 /* number of pilot symbols per carrier */
#define PILOTS_NC 7 /* number of carriers */
-#define NSYMROWPILOT 6 /* length of row after pilots inserted */
+#define NSYMROWPILOT 6 /* number of rows after pilots inserted */
#define LOG_FRAMES 100
#define SYNC_FRAMES 12 /* sync state uses up extra log storage as we reprocess several times */
+int opt_exists(char *argv[], int argc, char opt[]) {
+ int i;
+ for (i=0; i<argc; i++) {
+ if (strcmp(argv[i], opt) == 0) {
+ return i;
+ }
+ }
+ return 0;
+}
+
int main(int argc, char *argv[])
{
FILE *fin, *fout, *foct;
float *rx_phi_log = NULL;
COMP *rx_symb_log = NULL;
float f_est_log[LOG_FRAMES], ratio_log[LOG_FRAMES];
- int i, r, c, log_data_r, oct, logframes;
+ int i, r, c, log_data_r, oct, logframes, arg, diversity;
if (argc < 3) {
- printf("usage: %s InputModemRawFile OutputOneBitPerIntFile [OctaveLogFile]\n", argv[0]);
+ fprintf(stderr, "\n");
+ printf("usage: %s InputModemRawFile OutputOneCharPerBitFile [-o OctaveLogFile] [--nd]\n", argv[0]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, " -o Octave log file for testing\n");
+ fprintf(stderr, " --nd non-diversity mode, output frames of %d bits\n", ND*COHPSK_BITS_PER_FRAME);
+ fprintf(stderr, "\n");
exit(1);
}
foct = NULL;
oct = 0;
- if (argc == 4) {
- if ( (foct = fopen(argv[3],"wt")) == NULL ) {
+ if ((arg = opt_exists(argv, argc, "-o")) != 0) {
+ if ( (foct = fopen(argv[arg+1],"wt")) == NULL ) {
fprintf(stderr, "Error opening output Octave file: %s: %s.\n",
- argv[3], strerror(errno));
+ argv[4], strerror(errno));
exit(1);
}
oct = 1;
}
+ if (opt_exists(argv, argc, "--nd")) {
+ diversity = 2;
+ } else {
+ diversity = 1;
+ }
+ fprintf(stderr, "cohpsk_demod: diversity: %d\n", diversity);
+
cohpsk = cohpsk_create();
cohpsk_set_verbose(cohpsk, 0);
cohpsk_demod(cohpsk, rx_bits, &sync, rx_fdm, &nin_frame);
if (sync) {
- for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
- rx_bits_char[i] = rx_bits[i] < 0.0;
- fwrite(rx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fout);
+ if (diversity == 1) {
+ for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+ rx_bits_char[i] = rx_bits[i] < 0.0;
+ fwrite(rx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fout);
+ }
+ else {
+ for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+ rx_bits_char[i] = cohpsk->rx_bits_lower[i] < 0.0;
+ fwrite(rx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fout);
+ for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+ rx_bits_char[i] = cohpsk->rx_bits_upper[i] < 0.0;
+ fwrite(rx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fout);
+ }
if (oct) {
for(r=0; r<NSYMROW; r++, log_data_r++) {
#include "codec2_cohpsk.h"
#include "codec2_fdmdv.h"
+int opt_exists(char *argv[], int argc, char opt[]) {
+ int i;
+ for (i=0; i<argc; i++) {
+ if (strcmp(argv[i], opt) == 0) {
+ return i;
+ }
+ }
+ return 0;
+}
+
int main(int argc, char *argv[])
{
FILE *fin, *fout;
struct COHPSK *cohpsk;
- char tx_bits_char[COHPSK_BITS_PER_FRAME];
- int tx_bits[COHPSK_BITS_PER_FRAME];
+ char tx_bits_char[2*COHPSK_BITS_PER_FRAME];
+ int tx_bits[2*COHPSK_BITS_PER_FRAME];
COMP tx_fdm[COHPSK_NOM_SAMPLES_PER_FRAME];
short tx_fdm_scaled[COHPSK_NOM_SAMPLES_PER_FRAME];
- int frames;
+ int frames, diversity;
int i;
if (argc < 3) {
- printf("usage: %s InputOneCharPerBitFile OutputModemRawFile\n", argv[0]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "usage: %s InputOneCharPerBitFile OutputModemRawFile [-nd]\n", argv[0]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, " --nd non-diversity mode, input frames of %d bits\n", 2*COHPSK_BITS_PER_FRAME);
+ fprintf(stderr, "\n");
exit(1);
}
cohpsk = cohpsk_create();
+ if (opt_exists(argv, argc, "--nd")) {
+ diversity = 2;
+ }
+ else {
+ diversity = 1;
+ }
+ fprintf(stderr, "diversity: %d\n", diversity);
+
frames = 0;
- while(fread(tx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME, fin) == COHPSK_BITS_PER_FRAME) {
+ while(fread(tx_bits_char, sizeof(char), COHPSK_BITS_PER_FRAME*diversity, fin) == COHPSK_BITS_PER_FRAME*diversity) {
frames++;
-
- for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
+
+ for(i=0; i<COHPSK_BITS_PER_FRAME*diversity; i++)
tx_bits[i] = tx_bits_char[i];
- cohpsk_mod(cohpsk, tx_fdm, tx_bits);
+ cohpsk_mod(cohpsk, tx_fdm, tx_bits, COHPSK_BITS_PER_FRAME*diversity);
cohpsk_clip(tx_fdm);
/* scale and save to disk as shorts */
/* cohpsk modulator */
- cohpsk_mod(f->cohpsk, tx_fdm, f->codec_bits);
+ cohpsk_mod(f->cohpsk, tx_fdm, f->codec_bits, COHPSK_BITS_PER_FRAME);
if (f->clip)
cohpsk_clip(tx_fdm);
for(i=0; i<f->n_nat_modem_samples; i++)
#include "H2064_516_sparse.h" \r
#endif\r
\r
+int opt_exists(char *argv[], int argc, char opt[]) {\r
+ int i;\r
+ for (i=0; i<argc; i++) {\r
+ if (strcmp(argv[i], opt) == 0) {\r
+ return 1;\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
void extract_output(char out_char[], int DecodedBits[], int ParityCheckCount[], int max_iter, int CodeLength, int NumberParityBits);\r
\r
int main(int argc, char *argv[])\r
NumberParityBits = NUMBERPARITYBITS;\r
\r
if (argc < 2) {\r
- fprintf(stderr, "usage: %s --test\n", argv[0]);\r
+ fprintf(stderr, "\n");\r
+ fprintf(stderr, "usage: %s --test\n\n", argv[0]);\r
fprintf(stderr, " Run internal self test and print code parameters.\n\n");\r
- fprintf(stderr, "usage: %s InOneSymbolPerDouble OutOneBitPerByte [--sd]\n", argv[0]);\r
- fprintf(stderr, " InOneSymbolPerDouble is a file of double LLRs. If the\n");\r
- fprintf(stderr, " --sd flag is used the input file can be Soft Decision\n");\r
- fprintf(stderr, " symbols, and LLRs will be calculated internally. Use -\n");\r
- fprintf(stderr, " for the file names to use stdin/stdout.\n");\r
+ fprintf(stderr, "usage: %s InOneSymbolPerDouble OutOneBitPerByte [--sd] [--half]\n\n", argv[0]);\r
+ fprintf(stderr, " InOneSymbolPerDouble Input file of double LLRs, use - for the \n"); \r
+ fprintf(stderr, " file names to use stdin/stdout\n");\r
+ fprintf(stderr, " --sd Treat input file samples as Soft Decision\n");\r
+ fprintf(stderr, " demod outputs rather than LLRs\n");\r
+ fprintf(stderr, " --half Load framesize/2 input samples for each decode\n");\r
+ fprintf(stderr, " attempt, only output decoded bits if decoder\n");\r
+ fprintf(stderr, " converges. Form of frame sync.\n");\r
+ fprintf(stderr, "\n");\r
exit(0);\r
}\r
\r
}\r
else {\r
FILE *fin, *fout;\r
- int sdinput;\r
+ int sdinput, readhalfframe, nread, offset, iter;\r
\r
/* File I/O mode ------------------------------------------------*/\r
\r
}\r
\r
sdinput = 0;\r
- //printf("argc: %d\n", argc);\r
- if (argc == 4)\r
- if (strcmp(argv[3], "--sd") == 0)\r
- sdinput = 1;\r
+ readhalfframe = 0;\r
+ if (opt_exists(argv, argc, "--sd")) {\r
+ sdinput = 1;\r
+ }\r
+ if (opt_exists(argv, argc, "--half")) {\r
+ readhalfframe = 1;\r
+ }\r
\r
double *input_double = calloc(CodeLength, sizeof(double));\r
\r
- while(fread(input_double, sizeof(double), CodeLength, fin) == CodeLength) {\r
+ nread = CodeLength;\r
+ offset = 0;\r
+ if (readhalfframe) {\r
+ nread = CodeLength/2;\r
+ offset = CodeLength/2;\r
+ for(i=0; i<offset; i++) {\r
+ input_double[i] = 0.0;\r
+ }\r
+ }\r
+\r
+ while(fread(&input_double[offset], sizeof(double), nread, fin) == nread) {\r
if (sdinput) {\r
sd_to_llr(input_double, input_double, CodeLength);\r
}\r
\r
- run_ldpc_decoder(&ldpc, out_char, input_double);\r
+ iter = run_ldpc_decoder(&ldpc, out_char, input_double);\r
+ fprintf(stderr, "%4d ", iter);\r
+\r
+ // output data bits if decoder converged\r
\r
- //printf("%4d ", iter);\r
- // just output data bits\r
- fwrite(out_char, sizeof(char), NUMBERROWSHCOLS, fout);\r
+ if (iter != MAX_ITER) {\r
+ fwrite(out_char, sizeof(char), NUMBERROWSHCOLS, fout);\r
+ }\r
+\r
+ for(i=0; i<offset; i++) {\r
+ input_double[i] = input_double[i+offset];\r
+ }\r
}\r
\r
free(input_double);\r