def receive_prefix(symbols): S = common.take(symbols, len(train.prefix))[:, config.carrier_index] sliced = np.round(S) if pylab: pylab.figure() show.constellation(S, sliced, 'Prefix') bits = np.array(np.abs(sliced), dtype=int) if any(bits != train.prefix): raise ValueError('Incorrect prefix') log.info('Prefix OK') nonzeros = np.array(train.prefix, dtype=bool) pilot_tone = S[nonzeros] phase = np.unwrap(np.angle(pilot_tone)) / (2 * np.pi) indices = np.arange(len(phase)) a, b = sigproc.linear_regression(indices, phase) freq_err = a / (config.Tsym * config.Fc) last_phase = a * indices[-1] + b log.debug('Current phase on carrier: %.3f', last_phase) expected_phase, = set(np.angle(sliced[nonzeros]) / (2 * np.pi)) log.debug('Excepted phase on carrier: %.3f', expected_phase) sampling_err = (last_phase - expected_phase) * config.Nsym log.info('Frequency error: %.2f ppm', freq_err * 1e6) log.info('Sampling error: %.2f samples', sampling_err) return freq_err, sampling_err
def train_receiver(symbols, freqs): filters = {} scaling_factor = len(freqs) # to avoid saturation training = np.array(train.equalizer) if pylab: pylab.figure() symbols = common.take(symbols, len(training) * len(freqs)) for i, freq in enumerate(freqs): size = len(training) offset = i * size S = symbols[offset:offset+size, i] filt = sigproc.train(S, training * scaling_factor) filters[freq] = filt Y = list(filt(S)) y = np.array(Y) / scaling_factor if pylab: pylab.subplot(HEIGHT, WIDTH, i+1) show.constellation(y, modem.qam.symbols, 'Train: $F_c = {}Hz$'.format(freq)) pylab.plot(S.real, S.imag, '.-') train_result = np.round(y) if not all(train_result == training): raise ValueError('#{} training failed on {} Hz'.format(i, freq)) noise = y - training Pnoise = sigproc.power(noise) log.info('%10.1f kHz: Noise sigma=%.4f, SNR=%.1f dB', freq/1e3, Pnoise**0.5, 10*np.log10(1/Pnoise)) return filters
def main(args): log.info('Running MODEM @ {:.1f} kbps'.format(modem.modem_bps / 1e3)) fd = sys.stdin signal = stream.iread(fd) skipped = common.take(signal, args.skip) log.debug('Skipping first %.3f seconds', len(skipped) / float(modem.baud)) stream.check = common.check_saturation size = 0 signal, amplitude = detect(signal, config.Fc) bits = receive(signal, modem.freqs, gain=1.0/amplitude) try: for chunk in decode(bits): sys.stdout.write(chunk) size = size + len(chunk) except Exception: log.exception('Decoding failed') duration = time.time() - stats['rx_start'] audio_time = stats['rx_bits'] / float(modem.modem_bps) log.debug('Demodulated %.3f kB @ %.3f seconds (%.1f%% realtime)', stats['rx_bits'] / 8e3, duration, 100 * duration / audio_time) log.info('Received %.3f kB @ %.3f seconds = %.3f kB/s', size * 1e-3, duration, size * 1e-3 / duration) if pylab: pylab.figure() symbol_list = np.array(stats['symbol_list']) for i, freq in enumerate(modem.freqs): pylab.subplot(HEIGHT, WIDTH, i+1) show.constellation(symbol_list[i], modem.qam.symbols, '$F_c = {} Hz$'.format(freq))