int main(void) { struct freedv *f; short buf[FREEDV_NSAMPLES]; int nin, nout; /* init all the drivers for various peripherals */ sm1000_leds_switches_init(); dac_open(4*DAC_BUF_SZ); adc_open(); f = freedv_open(FREEDV_MODE_1600); /* LEDs into a known state */ led_pwr(1); led_ptt(0); led_rt(0); led_err(0); /* TODO: [ ] UT analog interfaces from file IO [ ] UTs for simultaneous tx & rx on analog interfaces [ ] measure CPU load of various parts with a blinky [ ] detect program assert type errors with a blinky [ ] timer tick function to measure 10ms-ish type times [ ] switch debouncing? [ ] light led with bit errors */ while(1) { if(switch_ptt()) { /* Transmit -------------------------------------------------------------------------*/ /* ADC2 is the SM1000 microphone, DAC1 is the modulator signal we send to radio tx */ if (adc2_read(buf, FREEDV_NSAMPLES) == FREEDV_NSAMPLES) { freedv_tx(f, buf, buf); dac1_write(buf, FREEDV_NSAMPLES); led_ptt(1); led_rt(0); led_err(0); } } else { /* Receive --------------------------------------------------------------------------*/ /* ADC1 is the demod in signal from the radio rx, DAC2 is the SM1000 speaker */ nin = freedv_nin(f); f->total_bit_errors = 0; if (adc1_read(buf, nin) == nin) { nout = freedv_rx(f, buf, buf); dac2_write(buf, nout); led_ptt(0); led_rt(f->fdmdv_stats.sync); led_err(f->total_bit_errors); } } } /* while(1) ... */ }
int main(void) { struct freedv *f; short adc16k[FDMDV_OS_TAPS_16K+FREEDV_NSAMPLES_16K]; short dac16k[FREEDV_NSAMPLES_16K]; short adc8k[FREEDV_NSAMPLES]; short dac8k[FDMDV_OS_TAPS_8K+FREEDV_NSAMPLES]; SWITCH_STATE ss; int nin, nout, i; /* init all the drivers for various peripherals */ SysTick_Config(SystemCoreClock/168000); /* 1 kHz SysTick */ sm1000_leds_switches_init(); dac_open(4*DAC_BUF_SZ); adc_open(4*ADC_BUF_SZ); f = freedv_open(FREEDV_MODE_1600); /* put outputs into a known state */ led_pwr(1); led_ptt(0); led_rt(0); led_err(0); not_cptt(1); /* clear filter memories */ for(i=0; i<FDMDV_OS_TAPS_16K; i++) adc16k[i] = 0.0; for(i=0; i<FDMDV_OS_TAPS_8K; i++) dac8k[i] = 0.0; ss.state = SS_IDLE; ss.mode = ANALOG; while(1) { iterate_select_state_machine(&ss); if (switch_ptt()) { /* Transmit -------------------------------------------------------------------------*/ /* ADC2 is the SM1000 microphone, DAC1 is the modulator signal we send to radio tx */ if (adc2_read(&adc16k[FDMDV_OS_TAPS_16K], FREEDV_NSAMPLES_16K) == 0) { GPIOE->ODR = (1 << 3); fdmdv_16_to_8_short(adc8k, &adc16k[FDMDV_OS_TAPS_16K], FREEDV_NSAMPLES); if (ss.mode == ANALOG) { for(i=0; i<FREEDV_NSAMPLES; i++) dac8k[FDMDV_OS_TAPS_8K+i] = adc8k[i]; fdmdv_8_to_16_short(dac16k, &dac8k[FDMDV_OS_TAPS_8K], FREEDV_NSAMPLES); dac1_write(dac16k, FREEDV_NSAMPLES_16K); } if (ss.mode == DV) { freedv_tx(f, &dac8k[FDMDV_OS_TAPS_8K], adc8k); fdmdv_8_to_16_short(dac16k, &dac8k[FDMDV_OS_TAPS_8K], FREEDV_NSAMPLES); dac1_write(dac16k, FREEDV_NSAMPLES_16K); } if (ss.mode == TONE) { while(dac1_write((short*)aSine, SINE_SAMPLES) == 0); } led_ptt(1); led_rt(0); led_err(0); not_cptt(0); GPIOE->ODR &= ~(1 << 3); } } else { /* Receive --------------------------------------------------------------------------*/ not_cptt(1); led_ptt(0); /* ADC1 is the demod in signal from the radio rx, DAC2 is the SM1000 speaker */ if (ss.mode == ANALOG) { /* force analog bypass when select down */ if (adc1_read(&adc16k[FDMDV_OS_TAPS_16K], FREEDV_NSAMPLES_16K) == 0) { fdmdv_16_to_8_short(adc8k, &adc16k[FDMDV_OS_TAPS_16K], FREEDV_NSAMPLES); for(i=0; i<FREEDV_NSAMPLES; i++) dac8k[FDMDV_OS_TAPS_8K+i] = adc8k[i]; fdmdv_8_to_16_short(dac16k, &dac8k[FDMDV_OS_TAPS_8K], FREEDV_NSAMPLES); dac2_write(dac16k, FREEDV_NSAMPLES_16K); led_rt(0); led_err(0); } } else { /* regular DV mode */ nin = freedv_nin(f); nout = nin; f->total_bit_errors = 0; if (adc1_read(&adc16k[FDMDV_OS_TAPS_16K], 2*nin) == 0) { GPIOE->ODR = (1 << 3); fdmdv_16_to_8_short(adc8k, &adc16k[FDMDV_OS_TAPS_16K], nin); nout = freedv_rx(f, &dac8k[FDMDV_OS_TAPS_8K], adc8k); fdmdv_8_to_16_short(dac16k, &dac8k[FDMDV_OS_TAPS_8K], nout); dac2_write(dac16k, 2*nout); led_rt(f->fdmdv_stats.sync); led_err(f->total_bit_errors); GPIOE->ODR &= ~(1 << 3); } } } } /* while(1) ... */ }
int main(int argc, char *argv[]) { FILE *fin, *fout, *ftxt; short *speech_out; short *demod_in; struct freedv *freedv; int nin, nout, frame = 0; struct my_callback_state my_cb_state; struct MODEM_STATS stats; int mode; int sync; int total_bits; int total_bit_errors; float snr_est; int n_speech_samples; int n_max_modem_samples; float clock_offset; int use_codecrx; struct CODEC2 *c2 = NULL; int i; if (argc < 4) { printf("usage: %s 1600|700|700B|2400A|2400B|800XA InputModemSpeechFile OutputSpeechRawFile [--test_frames] [--codecrx]\n", argv[0]); printf("e.g %s 1600 hts1a_fdmdv.raw hts1a_out.raw txtLogFile\n", argv[0]); exit(1); } mode = -1; if (!strcmp(argv[1],"1600")) mode = FREEDV_MODE_1600; if (!strcmp(argv[1],"700")) mode = FREEDV_MODE_700; if (!strcmp(argv[1],"700B")) mode = FREEDV_MODE_700B; if (!strcmp(argv[1],"2400A")) mode = FREEDV_MODE_2400A; if (!strcmp(argv[1],"2400B")) mode = FREEDV_MODE_2400B; if (!strcmp(argv[1],"800XA")) mode = FREEDV_MODE_800XA; assert(mode != -1); if (strcmp(argv[2], "-") == 0) fin = stdin; else if ( (fin = fopen(argv[2],"rb")) == NULL ) { fprintf(stderr, "Error opening input raw modem sample file: %s: %s.\n", argv[2], strerror(errno)); exit(1); } if (strcmp(argv[3], "-") == 0) fout = stdout; else if ( (fout = fopen(argv[3],"wb")) == NULL ) { fprintf(stderr, "Error opening output speech sample file: %s: %s.\n", argv[3], strerror(errno)); exit(1); } freedv = freedv_open(mode); assert(freedv != NULL); use_codecrx = 0; if (argc > 4) { for (i = 4; i < argc; i++) { if (strcmp(argv[i], "--testframes") == 0) { freedv_set_test_frames(freedv, 1); } if (strcmp(argv[i], "--codecrx") == 0) { int c2_mode; if (mode == FREEDV_MODE_700) { c2_mode = CODEC2_MODE_700; } else if ((mode == FREEDV_MODE_700B)|| (mode == FREEDV_MODE_800XA)) { c2_mode = CODEC2_MODE_700B; } else { c2_mode = CODEC2_MODE_1300; } use_codecrx = 1; c2 = codec2_create(c2_mode); assert(c2 != NULL); } } } freedv_set_snr_squelch_thresh(freedv, -100.0); freedv_set_squelch_en(freedv, 1); n_speech_samples = freedv_get_n_speech_samples(freedv); n_max_modem_samples = freedv_get_n_max_modem_samples(freedv); speech_out = (short*)malloc(sizeof(short)*n_speech_samples); assert(speech_out != NULL); demod_in = (short*)malloc(sizeof(short)*n_max_modem_samples); assert(demod_in != NULL); ftxt = fopen("freedv_rx_log.txt","wt"); assert(ftxt != NULL); my_cb_state.ftxt = ftxt; freedv_set_callback_txt(freedv, &my_put_next_rx_char, NULL, &my_cb_state); freedv_set_callback_protocol(freedv, &my_put_next_rx_proto, NULL, &my_cb_state); freedv_set_callback_data(freedv, my_datarx, my_datatx, &my_cb_state); /* Note we need to work out how many samples demod needs on each call (nin). This is used to adjust for differences in the tx and rx sample clock frequencies. Note also the number of output speech samples is time varying (nout). */ nin = freedv_nin(freedv); while(fread(demod_in, sizeof(short), nin, fin) == nin) { frame++; if (use_codecrx == 0) { /* Use the freedv_api to do everything: speech decoding, demodulating */ nout = freedv_rx(freedv, speech_out, demod_in); } else { int bits_per_codec_frame = codec2_bits_per_frame(c2); int bytes_per_codec_frame = (bits_per_codec_frame + 7) / 8; int codec_frames = freedv_get_n_codec_bits(freedv) / bits_per_codec_frame; int samples_per_frame = codec2_samples_per_frame(c2); unsigned char encoded[bytes_per_codec_frame * codec_frames]; /* Use the freedv_api to demodulate only */ nout = freedv_codecrx(freedv, encoded, demod_in); /* deccode the speech ourself (or send it to elsewhere, e.g. network) */ if (nout) { unsigned char *enc_frame = encoded; short *speech_frame = speech_out; nout = 0; for (i = 0; i < codec_frames; i++) { codec2_decode(c2, speech_frame, enc_frame); enc_frame += bytes_per_codec_frame; speech_frame += samples_per_frame; nout += samples_per_frame; } } } nin = freedv_nin(freedv); fwrite(speech_out, sizeof(short), nout, fout); freedv_get_modem_stats(freedv, &sync, &snr_est); freedv_get_modem_extended_stats(freedv,&stats); total_bit_errors = freedv_get_total_bit_errors(freedv); clock_offset = stats.clock_offset; /* log some side info to the txt file */ if (ftxt != NULL) { fprintf(ftxt, "frame: %d demod sync: %d nin:%d demod snr: %3.2f dB bit errors: %d clock_offset: %f\n", frame, sync, nin, snr_est, total_bit_errors, clock_offset); } /* if this is in a pipeline, we probably don't want the usual buffering to occur */ if (fout == stdout) fflush(stdout); if (fin == stdin) fflush(stdin); } if (freedv_get_test_frames(freedv)) { total_bits = freedv_get_total_bits(freedv); total_bit_errors = freedv_get_total_bit_errors(freedv); fprintf(stderr, "bits: %d errors: %d BER: %3.2f\n", total_bits, total_bit_errors, (float)total_bit_errors/total_bits); } free(speech_out); free(demod_in); freedv_close(freedv); fclose(fin); fclose(fout); return 0; }
int main(int argc, char *argv[]) { struct freedv *f; short adc16k[FDMDV_OS_TAPS_16K+FREEDV_NSAMPLES_16K]; short dac16k[FREEDV_NSAMPLES_16K]; short adc8k[FREEDV_NSAMPLES]; short dac8k[FDMDV_OS_TAPS_8K+FREEDV_NSAMPLES]; FILE *fin, *fout, *ftotal; int frame, nin_16k, nin, i, nout = 0; struct FDMDV_STATS stats; PROFILE_VAR(fdmdv_16_to_8_start, freedv_rx_start, fdmdv_8_to_16_start); machdep_profile_init(); f = freedv_open(FREEDV_MODE_1600); // Receive --------------------------------------------------------------------- frame = 0; fin = fopen("mod_16k.raw", "rb"); if (fin == NULL) { printf("Error opening input file\n"); exit(1); } fout = fopen("speechout_16k.raw", "wb"); if (fout == NULL) { printf("Error opening output file\n"); exit(1); } ftotal = fopen("total.txt", "wt"); assert(ftotal != NULL); /* clear filter memories */ for(i=0; i<FDMDV_OS_TAPS_16K; i++) adc16k[i] = 0.0; for(i=0; i<FDMDV_OS_TAPS_8K; i++) dac8k[i] = 0.0; nin = freedv_nin(f); nin_16k = 2*nin; nout = nin; while (fread(&adc16k[FDMDV_OS_TAPS_16K], sizeof(short), nin_16k, fin) == nin_16k) { PROFILE_SAMPLE(fdmdv_16_to_8_start); fdmdv_16_to_8_short(adc8k, &adc16k[FDMDV_OS_TAPS_16K], nin); PROFILE_SAMPLE_AND_LOG(freedv_rx_start, fdmdv_16_to_8_start, " fdmdv_16_to_8"); nout = freedv_rx(f, &dac8k[FDMDV_OS_TAPS_8K], adc8k); nin = freedv_nin(f); nin_16k = 2*nin; fdmdv_get_demod_stats(f->fdmdv, &stats); PROFILE_SAMPLE_AND_LOG(fdmdv_8_to_16_start, freedv_rx_start, " freedv_rx"); fdmdv_8_to_16_short(dac16k, &dac8k[FDMDV_OS_TAPS_8K], nout); PROFILE_SAMPLE_AND_LOG2(fdmdv_8_to_16_start, " fdmdv_8_to_16"); fprintf(ftotal, "%d\n", machdep_profile_sample() - fdmdv_16_to_8_start); machdep_profile_print_logged_samples(); fwrite(dac16k, sizeof(short), 2*nout, fout); fdmdv_get_demod_stats(f->fdmdv, &stats); printf("frame: %d nin_16k: %d sync: %d SNR: %3.2f \n", ++frame, nin_16k, stats.sync, (double)stats.snr_est); } fclose(fin); fclose(fout); fclose(ftotal); return 0; }