mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-11 00:59:28 +00:00
Fixed LCR and Xylos transmitters
This commit is contained in:
@@ -140,6 +140,8 @@ CPPSRC = main.cpp \
|
||||
matched_filter.cpp \
|
||||
proc_audiotx.cpp \
|
||||
proc_playaudio.cpp \
|
||||
proc_xylos.cpp \
|
||||
proc_fsk_lcr.cpp \
|
||||
dsp_squelch.cpp \
|
||||
clock_recovery.cpp \
|
||||
packet_builder.cpp \
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "audio_compressor.hpp"
|
||||
|
||||
float GainComputer::operator()(const float x) const {
|
||||
const auto abs_x = std::abs(x);
|
||||
const auto db = (abs_x < lin_floor) ? db_floor : log2_db_k * fast_log2(abs_x);
|
||||
const auto overshoot_db = db - threshold_db;
|
||||
if( knee_width_db > 0.0f ) {
|
||||
const auto w2 = knee_width_db / 2.0f;
|
||||
const auto a = w2 / (knee_width_db * knee_width_db);
|
||||
const auto in_transition = (overshoot_db > -w2) && (overshoot_db < w2);
|
||||
const auto rectified_overshoot = in_transition ? (a * std::pow(overshoot_db + w2, 2.0f)) : std::max(overshoot_db, 0.0f);
|
||||
return rectified_overshoot * slope;
|
||||
} else {
|
||||
const auto rectified_overshoot = std::max(overshoot_db, 0.0f);
|
||||
return rectified_overshoot * slope;
|
||||
}
|
||||
}
|
||||
|
||||
void FeedForwardCompressor::execute_in_place(const buffer_f32_t& buffer) {
|
||||
constexpr float makeup_gain = std::pow(10.0f, (threshold - (threshold / ratio)) / -20.0f);
|
||||
for(size_t i=0; i<buffer.count; i++) {
|
||||
buffer.p[i] = execute_once(buffer.p[i]) * makeup_gain;
|
||||
}
|
||||
}
|
||||
|
||||
float FeedForwardCompressor::execute_once(const float x) {
|
||||
const auto gain_db = gain_computer(x);
|
||||
const auto peak_db = -peak_detector(-gain_db);
|
||||
const auto gain = fast_pow2(peak_db * (3.321928094887362f / 20.0f));
|
||||
return x * gain;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __AUDIO_COMPRESSOR_H__
|
||||
#define __AUDIO_COMPRESSOR_H__
|
||||
|
||||
#include "dsp_types.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
/* Code based on article in Journal of the Audio Engineering Society
|
||||
* Vol. 60, No. 6, 2012 June, by Dimitrios Giannoulis, Michael Massberg,
|
||||
* Joshua D. Reiss "Digital Dynamic Range Compressor Design – A Tutorial
|
||||
* and Analysis"
|
||||
*/
|
||||
|
||||
class GainComputer {
|
||||
public:
|
||||
constexpr GainComputer(
|
||||
float ratio,
|
||||
float threshold
|
||||
) : ratio { ratio },
|
||||
slope { 1.0f / ratio - 1.0f },
|
||||
threshold_db { threshold }
|
||||
{
|
||||
}
|
||||
|
||||
float operator()(const float x) const;
|
||||
|
||||
private:
|
||||
const float ratio;
|
||||
const float slope;
|
||||
const float threshold_db;
|
||||
|
||||
static constexpr float knee_width_db = 0.0f;
|
||||
|
||||
static constexpr float db_floor = -120.0f;
|
||||
static constexpr float lin_floor = std::pow(10.0f, db_floor / 20.0f);
|
||||
static constexpr float log2_db_k = 20.0f * std::log10(2.0f);
|
||||
};
|
||||
|
||||
class PeakDetectorBranchingSmooth {
|
||||
public:
|
||||
constexpr PeakDetectorBranchingSmooth(
|
||||
float att_a,
|
||||
float rel_a
|
||||
) : att_a { att_a },
|
||||
rel_a { rel_a }
|
||||
{
|
||||
}
|
||||
|
||||
float operator()(const float db) {
|
||||
const auto a = (db > state) ? att_a : rel_a;
|
||||
state = db + a * (state - db);
|
||||
return state;
|
||||
}
|
||||
|
||||
private:
|
||||
float state { 0.0f };
|
||||
const float att_a;
|
||||
const float rel_a;
|
||||
};
|
||||
|
||||
class FeedForwardCompressor {
|
||||
public:
|
||||
void execute_in_place(const buffer_f32_t& buffer);
|
||||
|
||||
private:
|
||||
static constexpr float fs = 12000.0f;
|
||||
static constexpr float ratio = 10.0f;
|
||||
static constexpr float threshold = -30.0f;
|
||||
|
||||
GainComputer gain_computer { ratio, threshold };
|
||||
PeakDetectorBranchingSmooth peak_detector { tau_alpha(0.010f, fs), tau_alpha(0.300f, fs) };
|
||||
|
||||
float execute_once(const float x);
|
||||
|
||||
static constexpr float tau_alpha(const float tau, const float fs) {
|
||||
return std::exp(-1.0f / (tau * fs));
|
||||
}
|
||||
};
|
||||
|
||||
#endif/*__AUDIO_COMPRESSOR_H__*/
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "proc_playaudio.hpp"
|
||||
#include "proc_audiotx.hpp"
|
||||
#include "proc_xylos.hpp"
|
||||
#include "proc_fsk_lcr.hpp"
|
||||
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
@@ -120,6 +122,8 @@ BasebandProcessor* BasebandThread::create_processor(const int32_t mode) {
|
||||
switch(mode) {
|
||||
case 0: return new PlayAudioProcessor();
|
||||
case 1: return new AudioTXProcessor();
|
||||
case 2: return new XylosProcessor();
|
||||
case 3: return new LCRFSKProcessor();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __OOK_HPP__
|
||||
#define __OOK_HPP__
|
||||
|
||||
#include "phase_detector.hpp"
|
||||
#include "phase_accumulator.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <complex>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
class OOKSlicerMagSquaredInt {
|
||||
public:
|
||||
using symbol_t = bool;
|
||||
|
||||
constexpr OOKSlicerMagSquaredInt(
|
||||
const float samples_per_symbol
|
||||
) : mag2_threshold_leak_factor {
|
||||
static_cast<uint32_t>(
|
||||
factor_sq(-1.0f / (8.0f * samples_per_symbol)) * float(1ULL << 32)
|
||||
)
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
symbol_t operator()(const std::complex<int16_t> in) {
|
||||
const uint32_t real2 = in.real() * in.real();
|
||||
const uint32_t imag2 = in.imag() * in.imag();
|
||||
const uint32_t mag2 = real2 + imag2;
|
||||
|
||||
const uint32_t mag2_attenuated = mag2 >> 3; // Approximation of (-4.5dB)^2
|
||||
mag2_threshold = (uint64_t(mag2_threshold) * uint64_t(mag2_threshold_leak_factor)) >> 32;
|
||||
mag2_threshold = std::max(mag2_threshold, mag2_attenuated);
|
||||
const bool symbol = (mag2 > mag2_threshold);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint32_t mag2_threshold_leak_factor;
|
||||
uint32_t mag2_threshold = 0;
|
||||
|
||||
constexpr float factor_sq(float db) {
|
||||
return std::pow(10.0f, db / (10.0f / 2));
|
||||
}
|
||||
};
|
||||
|
||||
class OOKClockRecovery {
|
||||
public:
|
||||
constexpr OOKClockRecovery(
|
||||
const float samples_per_symbol
|
||||
) : symbol_phase_inc_nominal { static_cast<uint32_t>(std::round((1ULL << 32) / samples_per_symbol)) },
|
||||
phase_detector { samples_per_symbol },
|
||||
phase_accumulator { symbol_phase_inc_nominal }
|
||||
{
|
||||
}
|
||||
|
||||
template<typename SymbolHandler>
|
||||
void operator()(const uint32_t slicer_history, SymbolHandler symbol_handler) {
|
||||
if( phase_accumulator() ) {
|
||||
const auto detector_result = phase_detector(slicer_history);
|
||||
phase_accumulator.set_inc(symbol_phase_inc_nominal + detector_result.error * (symbol_phase_inc_nominal >> 3));
|
||||
symbol_handler(detector_result.symbol);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const uint32_t symbol_phase_inc_nominal;
|
||||
PhaseDetectorEarlyLateGate phase_detector;
|
||||
PhaseAccumulator phase_accumulator;
|
||||
};
|
||||
|
||||
#endif/*__OOK_HPP__*/
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PHASE_ACCUMULATOR_HPP__
|
||||
#define __PHASE_ACCUMULATOR_HPP__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class PhaseAccumulator {
|
||||
public:
|
||||
constexpr PhaseAccumulator(
|
||||
const uint32_t phase_inc
|
||||
) : phase_inc { phase_inc }
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()() {
|
||||
const auto last_phase = phase;
|
||||
phase += phase_inc;
|
||||
return (phase < last_phase);
|
||||
}
|
||||
|
||||
void set_inc(const uint32_t new_phase_inc) {
|
||||
phase_inc = new_phase_inc;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t phase { 0 };
|
||||
uint32_t phase_inc;
|
||||
};
|
||||
|
||||
#endif/*__PHASE_ACCUMULATOR_HPP__*/
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PHASE_DETECTOR_HPP__
|
||||
#define __PHASE_DETECTOR_HPP__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cmath>
|
||||
|
||||
class PhaseDetectorEarlyLateGate {
|
||||
public:
|
||||
using history_t = uint32_t;
|
||||
|
||||
using symbol_t = bool;
|
||||
using error_t = int;
|
||||
|
||||
struct result_t {
|
||||
symbol_t symbol;
|
||||
error_t error;
|
||||
};
|
||||
|
||||
constexpr PhaseDetectorEarlyLateGate(
|
||||
const float samples_per_symbol
|
||||
) : late_mask { (1U << static_cast<size_t>(std::ceil(samples_per_symbol / 2))) - 1 },
|
||||
early_mask { late_mask << static_cast<size_t>(std::floor(samples_per_symbol / 2)) },
|
||||
sample_bit { static_cast<size_t>(std::floor(samples_per_symbol / 2)) }
|
||||
{
|
||||
}
|
||||
|
||||
result_t operator()(const history_t symbol_history) const {
|
||||
// history = ...0111, early
|
||||
// history = ...1110, late
|
||||
|
||||
const symbol_t symbol = (symbol_history >> sample_bit) & 1;
|
||||
const int late_side = __builtin_popcount(symbol_history & late_mask);
|
||||
const int early_side = __builtin_popcount(symbol_history & early_mask);
|
||||
const int lateness = late_side - early_side;
|
||||
const int direction = lateness; //std::min(std::max(lateness, -1), 1);
|
||||
const error_t error = direction;
|
||||
return { symbol, error };
|
||||
}
|
||||
|
||||
private:
|
||||
const history_t late_mask;
|
||||
const history_t early_mask;
|
||||
const size_t sample_bit;
|
||||
};
|
||||
|
||||
#endif/*__PHASE_DETECTOR_HPP__*/
|
||||
@@ -23,63 +23,9 @@
|
||||
#include "proc_audiotx.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "sine_table.hpp"
|
||||
#include "audio_output.hpp"
|
||||
#include "lfsr_random.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
uint32_t lfsr(uint32_t v) {
|
||||
|
||||
enum {
|
||||
length = 31,
|
||||
tap_0 = 31,
|
||||
tap_1 = 18,
|
||||
shift_amount_0 = 12,
|
||||
shift_amount_1 = 12,
|
||||
shift_amount_2 = 8
|
||||
};
|
||||
|
||||
const lfsr_word_t zero = 0;
|
||||
v = (
|
||||
(
|
||||
v << shift_amount_0
|
||||
) | (
|
||||
(
|
||||
(v >> (tap_0 - shift_amount_0)) ^
|
||||
(v >> (tap_1 - shift_amount_0))
|
||||
) & (
|
||||
~(~zero << shift_amount_0)
|
||||
)
|
||||
)
|
||||
);
|
||||
v = (
|
||||
(
|
||||
v << shift_amount_1
|
||||
) | (
|
||||
(
|
||||
(v >> (tap_0 - shift_amount_1)) ^
|
||||
(v >> (tap_1 - shift_amount_1))
|
||||
) & (
|
||||
~(~zero << shift_amount_1)
|
||||
)
|
||||
)
|
||||
);
|
||||
v = (
|
||||
(
|
||||
v << shift_amount_2
|
||||
) | (
|
||||
(
|
||||
(v >> (tap_0 - shift_amount_2)) ^
|
||||
(v >> (tap_1 - shift_amount_2))
|
||||
) & (
|
||||
~(~zero << shift_amount_2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void AudioTXProcessor::execute(const buffer_c8_t& buffer){
|
||||
|
||||
for (size_t i = 0; i<buffer.count; i++) {
|
||||
@@ -91,7 +37,7 @@ void AudioTXProcessor::execute(const buffer_c8_t& buffer){
|
||||
aphase += 90000;
|
||||
|
||||
//FM
|
||||
frq = sample * 2500;
|
||||
frq = sample * 1000;
|
||||
|
||||
phase = (phase + frq);
|
||||
sphase = phase + (256<<16);
|
||||
|
||||
@@ -25,12 +25,6 @@
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
|
||||
#include "audio_output.hpp"
|
||||
#include "spectrum_collector.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class AudioTXProcessor : public BasebandProcessor {
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "proc_tpms.hpp"
|
||||
|
||||
#include "dsp_fir_taps.hpp"
|
||||
|
||||
TPMSProcessor::TPMSProcessor() {
|
||||
decim_0.configure(taps_200k_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_200k_decim_1.taps, 131072);
|
||||
}
|
||||
|
||||
void TPMSProcessor::execute(const buffer_c8_t& buffer) {
|
||||
/* 2.4576MHz, 2048 samples */
|
||||
|
||||
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||
const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer);
|
||||
const auto decimator_out = decim_1_out;
|
||||
|
||||
/* 307.2kHz, 256 samples */
|
||||
feed_channel_stats(decimator_out);
|
||||
|
||||
for(size_t i=0; i<decimator_out.count; i++) {
|
||||
if( mf.execute_once(decimator_out.p[i]) ) {
|
||||
clock_recovery(mf.get_output());
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i=0; i<decim_1_out.count; i+=channel_decimation) {
|
||||
const auto sliced = ook_slicer_5sps(decim_1_out.p[i]);
|
||||
slicer_history = (slicer_history << 1) | sliced;
|
||||
|
||||
ook_clock_recovery_subaru(slicer_history, [this](const bool symbol) {
|
||||
this->packet_builder_ook_subaru.execute(symbol);
|
||||
});
|
||||
ook_clock_recovery_gmc(slicer_history, [this](const bool symbol) {
|
||||
this->packet_builder_ook_gmc.execute(symbol);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void TPMSProcessor::consume_symbol(
|
||||
const float raw_symbol
|
||||
) {
|
||||
const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0;
|
||||
packet_builder.execute(sliced_symbol);
|
||||
}
|
||||
|
||||
void TPMSProcessor::payload_handler(
|
||||
const baseband::Packet& packet
|
||||
) {
|
||||
const TPMSPacketMessage message { tpms::SignalType::FLM, packet };
|
||||
shared_memory.application_queue.push(message);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PROC_TPMS_H__
|
||||
#define __PROC_TPMS_H__
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
|
||||
#include "channel_decimator.hpp"
|
||||
#include "matched_filter.hpp"
|
||||
|
||||
#include "clock_recovery.hpp"
|
||||
#include "symbol_coding.hpp"
|
||||
#include "packet_builder.hpp"
|
||||
#include "baseband_packet.hpp"
|
||||
|
||||
#include "ook.hpp"
|
||||
|
||||
#include "message.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <bitset>
|
||||
|
||||
// Translate+rectangular filter
|
||||
// sample=307.2k, deviation=38400, symbol=19200
|
||||
// Length: 16 taps, 1 symbols, 2 cycles of sinusoid
|
||||
constexpr std::array<std::complex<float>, 16> rect_taps_307k2_1t_p { {
|
||||
{ 6.2500000000e-02f, 0.0000000000e+00f }, { 4.4194173824e-02f, 4.4194173824e-02f },
|
||||
{ 0.0000000000e+00f, 6.2500000000e-02f }, { -4.4194173824e-02f, 4.4194173824e-02f },
|
||||
{ -6.2500000000e-02f, 0.0000000000e+00f }, { -4.4194173824e-02f, -4.4194173824e-02f },
|
||||
{ 0.0000000000e+00f, -6.2500000000e-02f }, { 4.4194173824e-02f, -4.4194173824e-02f },
|
||||
{ 6.2500000000e-02f, 0.0000000000e+00f }, { 4.4194173824e-02f, 4.4194173824e-02f },
|
||||
{ 0.0000000000e+00f, 6.2500000000e-02f }, { -4.4194173824e-02f, 4.4194173824e-02f },
|
||||
{ -6.2500000000e-02f, 0.0000000000e+00f }, { -4.4194173824e-02f, -4.4194173824e-02f },
|
||||
{ 0.0000000000e+00f, -6.2500000000e-02f }, { 4.4194173824e-02f, -4.4194173824e-02f },
|
||||
} };
|
||||
|
||||
class TPMSProcessor : public BasebandProcessor {
|
||||
public:
|
||||
TPMSProcessor();
|
||||
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
|
||||
private:
|
||||
std::array<complex16_t, 512> dst;
|
||||
const buffer_c16_t dst_buffer {
|
||||
dst.data(),
|
||||
dst.size()
|
||||
};
|
||||
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0;
|
||||
dsp::decimate::FIRC16xR16x16Decim2 decim_1;
|
||||
|
||||
dsp::matched_filter::MatchedFilter mf { rect_taps_307k2_1t_p, 8 };
|
||||
|
||||
clock_recovery::ClockRecovery<clock_recovery::FixedErrorFilter> clock_recovery {
|
||||
38400, 19200, { 0.0555f },
|
||||
[this](const float symbol) { this->consume_symbol(symbol); }
|
||||
};
|
||||
PacketBuilder<BitPattern, NeverMatch, FixedLength> packet_builder {
|
||||
{ 0b010101010101010101010101010110, 30, 1 },
|
||||
{ },
|
||||
{ 256 },
|
||||
[this](const baseband::Packet& packet) {
|
||||
this->payload_handler(packet);
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr float channel_rate_in = 307200.0f;
|
||||
static constexpr size_t channel_decimation = 8;
|
||||
static constexpr float channel_sample_rate = channel_rate_in / channel_decimation;
|
||||
OOKSlicerMagSquaredInt ook_slicer_5sps { 5 };
|
||||
uint32_t slicer_history { 0 };
|
||||
|
||||
OOKClockRecovery ook_clock_recovery_subaru {
|
||||
channel_sample_rate / 8192.0f
|
||||
};
|
||||
|
||||
PacketBuilder<BitPattern, NeverMatch, FixedLength> packet_builder_ook_subaru {
|
||||
{ 0b010101010101010101011110, 24, 0 },
|
||||
{ },
|
||||
{ 80 },
|
||||
[](const baseband::Packet& packet) {
|
||||
const TPMSPacketMessage message { tpms::SignalType::Subaru, packet };
|
||||
shared_memory.application_queue.push(message);
|
||||
}
|
||||
};
|
||||
OOKClockRecovery ook_clock_recovery_gmc {
|
||||
channel_sample_rate / 8400.0f
|
||||
};
|
||||
|
||||
PacketBuilder<BitPattern, NeverMatch, FixedLength> packet_builder_ook_gmc {
|
||||
{ 0b01010101010101010101010101100101, 32, 0 },
|
||||
{ },
|
||||
{ 192 },
|
||||
[](const baseband::Packet& packet) {
|
||||
const TPMSPacketMessage message { tpms::SignalType::GMC, packet };
|
||||
shared_memory.application_queue.push(message);
|
||||
}
|
||||
};
|
||||
void consume_symbol(const float symbol);
|
||||
void payload_handler(const baseband::Packet& packet);
|
||||
};
|
||||
|
||||
#endif/*__PROC_TPMS_H__*/
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "proc_xylos.hpp"
|
||||
|
||||
#include "dsp_iir_config.hpp"
|
||||
//#include "audio_output.hpp"
|
||||
#include "audio_output.hpp"
|
||||
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "sine_table.hpp"
|
||||
@@ -75,7 +75,7 @@ void XylosProcessor::execute(const buffer_c8_t& buffer) {
|
||||
// Audio preview sample generation: 1536000/48000 = 32
|
||||
if (as >= 31) {
|
||||
as = 0;
|
||||
preview_audio_buffer.p[ai++] = sample * 128;
|
||||
audio[ai++] = sample * 128;
|
||||
} else {
|
||||
as++;
|
||||
}
|
||||
@@ -92,5 +92,5 @@ void XylosProcessor::execute(const buffer_c8_t& buffer) {
|
||||
buffer.p[i] = {(int8_t)re,(int8_t)im};
|
||||
}
|
||||
|
||||
//audio_output.write(preview_audio_buffer);
|
||||
//audio_output.write(audio_buffer);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
|
||||
//#include "audio_output.hpp"
|
||||
#include "audio_output.hpp"
|
||||
#include "baseband_processor.hpp"
|
||||
|
||||
#define CCIR_TONELENGTH 15360-1 // 1536000/10/10
|
||||
@@ -40,11 +40,12 @@ public:
|
||||
|
||||
private:
|
||||
int16_t audio_data[64];
|
||||
|
||||
const buffer_s16_t preview_audio_buffer {
|
||||
audio_data,
|
||||
sizeof(int16_t)*64
|
||||
};
|
||||
|
||||
std::array<int16_t, 64> audio;
|
||||
/*const buffer_s16_t audio_buffer {
|
||||
audio.data(),
|
||||
audio.size()
|
||||
};*/
|
||||
|
||||
uint32_t ccir_phases[16] = {
|
||||
(uint32_t)(1981*PHASEV),
|
||||
@@ -74,7 +75,7 @@ private:
|
||||
int32_t sample, frq;
|
||||
TXDoneMessage message;
|
||||
|
||||
//AudioOutput audio_output;
|
||||
AudioOutput audio_output;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __STREAM_INPUT_H__
|
||||
#define __STREAM_INPUT_H__
|
||||
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include "fifo.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
class StreamInput {
|
||||
public:
|
||||
StreamInput(const size_t K) :
|
||||
K { K },
|
||||
data { std::make_unique<uint8_t[]>(1UL << K) },
|
||||
fifo { data.get(), K }
|
||||
{
|
||||
// TODO: Send stream creation message.
|
||||
shared_memory.FIFO_HACK = &fifo;
|
||||
}
|
||||
|
||||
~StreamInput() {
|
||||
// TODO: Send stream distruction message.
|
||||
shared_memory.FIFO_HACK = nullptr;
|
||||
}
|
||||
|
||||
size_t write(const void* const data, const size_t length) {
|
||||
const auto written = fifo.in(reinterpret_cast<const uint8_t*>(data), length);
|
||||
|
||||
const auto last_bytes_written = bytes_written;
|
||||
bytes_written += written;
|
||||
if( (bytes_written & event_bytes_mask) < (last_bytes_written & event_bytes_mask) ) {
|
||||
creg::m4txevent::assert();
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
uint64_t written() const {
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
private:
|
||||
const size_t K;
|
||||
const uint64_t event_bytes_mask = (1ULL << (K - 2)) - 1;
|
||||
uint64_t bytes_written = 0;
|
||||
std::unique_ptr<uint8_t[]> data;
|
||||
FIFO<uint8_t> fifo;
|
||||
};
|
||||
|
||||
#endif/*__STREAM_INPUT_H__*/
|
||||
Reference in New Issue
Block a user