portapack-mayhem/firmware/common/message.hpp
furrtek 57c759627d Fixed mic tx not working the first time it was entered
Fixed SD card FAT wipe (buffer size too big)
Cleared some warnings from ADSB rx
Updated binary
2018-02-01 11:17:51 +00:00

1019 lines
20 KiB
C++

/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* 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 __MESSAGE_H__
#define __MESSAGE_H__
#include <cstdint>
#include <cstddef>
#include <cstring>
#include <array>
#include <functional>
#include <algorithm>
#include "pocsag_packet.hpp"
#include "baseband_packet.hpp"
#include "ert_packet.hpp"
#include "tpms_packet.hpp"
#include "pocsag_packet.hpp"
#include "sonde_packet.hpp"
#include "adsb_frame.hpp"
#include "jammer.hpp"
#include "dsp_fir_taps.hpp"
#include "dsp_iir.hpp"
#include "fifo.hpp"
#include "utility.hpp"
#include "ch.h"
class Message {
public:
static constexpr size_t MAX_SIZE = 512;
enum class ID : uint32_t {
/* Assign consecutive IDs. IDs are used to index array. */
RSSIStatistics = 0,
BasebandStatistics = 1,
ChannelStatistics = 2,
DisplayFrameSync = 3,
AudioStatistics = 4,
TPMSPacket = 6,
Shutdown = 8,
AISPacket = 7,
ERTPacket = 9,
SondePacket = 10,
UpdateSpectrum = 11,
NBFMConfigure = 12,
WFMConfigure = 13,
AMConfigure = 14,
ChannelSpectrumConfig = 15,
SpectrumStreamingConfig = 16,
DisplaySleep = 17,
CaptureConfig = 18,
CaptureThreadDone = 19,
ReplayConfig = 20,
ReplayThreadDone = 21,
AFSKRxConfigure = 22,
StatusRefresh = 23,
TXProgress = 30,
Retune = 31,
TonesConfigure = 32,
AFSKTxConfigure = 33,
PitchRSSIConfigure = 34,
OOKConfigure = 35,
RDSConfigure = 36,
AudioTXConfig = 37,
POCSAGConfigure = 38,
DTMFTXConfig = 39,
ADSBConfigure = 40,
JammerConfigure = 41,
WidebandSpectrumConfig = 42,
FSKConfigure = 43,
SSTVConfigure = 44,
SigGenConfig = 43,
SigGenTone = 44,
POCSAGPacket = 50,
ADSBFrame = 51,
AFSKData = 52,
TestAppPacket = 53,
RequestSignal = 60,
FIFOData = 61,
AudioLevelReport = 70,
CodedSquelch = 71,
MAX
};
constexpr Message(
ID id
) : id { id }
{
}
const ID id;
};
struct RSSIStatistics {
uint32_t accumulator { 0 };
uint32_t min { 0 };
uint32_t max { 0 };
uint32_t count { 0 };
};
class RSSIStatisticsMessage : public Message {
public:
constexpr RSSIStatisticsMessage(
const RSSIStatistics& statistics
) : Message { ID::RSSIStatistics },
statistics { statistics }
{
}
RSSIStatistics statistics;
};
struct BasebandStatistics {
uint32_t idle_ticks { 0 };
uint32_t main_ticks { 0 };
uint32_t rssi_ticks { 0 };
uint32_t baseband_ticks { 0 };
bool saturation { false };
};
class BasebandStatisticsMessage : public Message {
public:
constexpr BasebandStatisticsMessage(
const BasebandStatistics& statistics
) : Message { ID::BasebandStatistics },
statistics { statistics }
{
}
BasebandStatistics statistics;
};
struct ChannelStatistics {
int32_t max_db;
size_t count;
constexpr ChannelStatistics(
int32_t max_db = -120,
size_t count = 0
) : max_db { max_db },
count { count }
{
}
};
class ChannelStatisticsMessage : public Message {
public:
constexpr ChannelStatisticsMessage(
const ChannelStatistics& statistics
) : Message { ID::ChannelStatistics },
statistics { statistics }
{
}
ChannelStatistics statistics;
};
class DisplayFrameSyncMessage : public Message {
public:
constexpr DisplayFrameSyncMessage(
) : Message { ID::DisplayFrameSync }
{
}
};
struct AudioStatistics {
int32_t rms_db;
int32_t max_db;
size_t count;
constexpr AudioStatistics(
) : rms_db { -120 },
max_db { -120 },
count { 0 }
{
}
constexpr AudioStatistics(
int32_t rms_db,
int32_t max_db,
size_t count
) : rms_db { rms_db },
max_db { max_db },
count { count }
{
}
};
class DisplaySleepMessage : public Message {
public:
constexpr DisplaySleepMessage(
) : Message { ID::DisplaySleep }
{
}
};
class StatusRefreshMessage : public Message {
public:
constexpr StatusRefreshMessage(
) : Message { ID::StatusRefresh }
{
}
};
class AudioStatisticsMessage : public Message {
public:
constexpr AudioStatisticsMessage(
const AudioStatistics& statistics
) : Message { ID::AudioStatistics },
statistics { statistics }
{
}
AudioStatistics statistics;
};
class SpectrumStreamingConfigMessage : public Message {
public:
enum class Mode : uint32_t {
Stopped = 0,
Running = 1,
};
constexpr SpectrumStreamingConfigMessage(
Mode mode
) : Message { ID::SpectrumStreamingConfig },
mode { mode }
{
}
Mode mode { Mode::Stopped };
};
class WidebandSpectrumConfigMessage : public Message {
public:
constexpr WidebandSpectrumConfigMessage (
size_t sampling_rate,
size_t trigger
) : Message { ID::WidebandSpectrumConfig },
sampling_rate { sampling_rate },
trigger { trigger }
{
}
size_t sampling_rate { 0 };
size_t trigger { 0 };
};
struct ChannelSpectrum {
std::array<uint8_t, 256> db { { 0 } };
uint32_t sampling_rate { 0 };
uint32_t channel_filter_pass_frequency { 0 };
uint32_t channel_filter_stop_frequency { 0 };
};
using ChannelSpectrumFIFO = FIFO<ChannelSpectrum>;
class ChannelSpectrumConfigMessage : public Message {
public:
static constexpr size_t fifo_k = 2;
constexpr ChannelSpectrumConfigMessage(
ChannelSpectrumFIFO* fifo
) : Message { ID::ChannelSpectrumConfig },
fifo { fifo }
{
}
ChannelSpectrumFIFO* fifo { nullptr };
};
class AISPacketMessage : public Message {
public:
constexpr AISPacketMessage(
const baseband::Packet& packet
) : Message { ID::AISPacket },
packet { packet }
{
}
baseband::Packet packet;
};
class TPMSPacketMessage : public Message {
public:
constexpr TPMSPacketMessage(
const tpms::SignalType signal_type,
const baseband::Packet& packet
) : Message { ID::TPMSPacket },
signal_type { signal_type },
packet { packet }
{
}
tpms::SignalType signal_type;
baseband::Packet packet;
};
class POCSAGPacketMessage : public Message {
public:
constexpr POCSAGPacketMessage(
const pocsag::POCSAGPacket& packet
) : Message { ID::POCSAGPacket },
packet { packet }
{
}
pocsag::POCSAGPacket packet;
};
class ADSBFrameMessage : public Message {
public:
constexpr ADSBFrameMessage(
const adsb::ADSBFrame& frame
) : Message { ID::ADSBFrame },
frame { frame }
{
}
adsb::ADSBFrame frame;
};
class AFSKDataMessage : public Message {
public:
constexpr AFSKDataMessage(
const bool is_data,
const uint32_t value
) : Message { ID::AFSKData },
is_data { is_data },
value { value }
{
}
bool is_data;
uint32_t value;
};
class CodedSquelchMessage : public Message {
public:
constexpr CodedSquelchMessage(
const uint32_t value
) : Message { ID::CodedSquelch },
value { value }
{
}
uint32_t value;
};
class ShutdownMessage : public Message {
public:
constexpr ShutdownMessage(
) : Message { ID::Shutdown }
{
}
};
class ERTPacketMessage : public Message {
public:
constexpr ERTPacketMessage(
const ert::Packet::Type type,
const baseband::Packet& packet
) : Message { ID::ERTPacket },
type { type },
packet { packet }
{
}
ert::Packet::Type type;
baseband::Packet packet;
};
class SondePacketMessage : public Message {
public:
constexpr SondePacketMessage(
const sonde::Packet::Type type,
const baseband::Packet& packet
) : Message { ID::SondePacket },
type { type },
packet { packet }
{
}
sonde::Packet::Type type;
baseband::Packet packet;
};
class TestAppPacketMessage : public Message {
public:
constexpr TestAppPacketMessage(
const baseband::Packet& packet
) : Message { ID::TestAppPacket },
packet { packet }
{
}
baseband::Packet packet;
};
class UpdateSpectrumMessage : public Message {
public:
constexpr UpdateSpectrumMessage(
) : Message { ID::UpdateSpectrum }
{
}
};
class NBFMConfigureMessage : public Message {
public:
constexpr NBFMConfigureMessage(
const fir_taps_real<24> decim_0_filter,
const fir_taps_real<32> decim_1_filter,
const fir_taps_real<32> channel_filter,
const size_t channel_decimation,
const size_t deviation,
const iir_biquad_config_t audio_hpf_config,
const iir_biquad_config_t audio_deemph_config,
const uint8_t squelch_level
) : Message { ID::NBFMConfigure },
decim_0_filter(decim_0_filter),
decim_1_filter(decim_1_filter),
channel_filter(channel_filter),
channel_decimation { channel_decimation },
deviation { deviation },
audio_hpf_config(audio_hpf_config),
audio_deemph_config(audio_deemph_config),
squelch_level(squelch_level)
{
}
const fir_taps_real<24> decim_0_filter;
const fir_taps_real<32> decim_1_filter;
const fir_taps_real<32> channel_filter;
const size_t channel_decimation;
const size_t deviation;
const iir_biquad_config_t audio_hpf_config;
const iir_biquad_config_t audio_deemph_config;
const uint8_t squelch_level;
};
class WFMConfigureMessage : public Message {
public:
constexpr WFMConfigureMessage(
const fir_taps_real<24> decim_0_filter,
const fir_taps_real<16> decim_1_filter,
const fir_taps_real<64> audio_filter,
const size_t deviation,
const iir_biquad_config_t audio_hpf_config,
const iir_biquad_config_t audio_deemph_config
) : Message { ID::WFMConfigure },
decim_0_filter(decim_0_filter),
decim_1_filter(decim_1_filter),
audio_filter(audio_filter),
deviation { deviation },
audio_hpf_config(audio_hpf_config),
audio_deemph_config(audio_deemph_config)
{
}
const fir_taps_real<24> decim_0_filter;
const fir_taps_real<16> decim_1_filter;
const fir_taps_real<64> audio_filter;
const size_t deviation;
const iir_biquad_config_t audio_hpf_config;
const iir_biquad_config_t audio_deemph_config;
};
class AMConfigureMessage : public Message {
public:
enum class Modulation : int32_t {
DSB = 0,
SSB = 1,
};
constexpr AMConfigureMessage(
const fir_taps_real<24> decim_0_filter,
const fir_taps_real<32> decim_1_filter,
const fir_taps_real<32> decim_2_filter,
const fir_taps_complex<64> channel_filter,
const Modulation modulation,
const iir_biquad_config_t audio_hpf_config
) : Message { ID::AMConfigure },
decim_0_filter(decim_0_filter),
decim_1_filter(decim_1_filter),
decim_2_filter(decim_2_filter),
channel_filter(channel_filter),
modulation { modulation },
audio_hpf_config(audio_hpf_config)
{
}
const fir_taps_real<24> decim_0_filter;
const fir_taps_real<32> decim_1_filter;
const fir_taps_real<32> decim_2_filter;
const fir_taps_complex<64> channel_filter;
const Modulation modulation;
const iir_biquad_config_t audio_hpf_config;
};
// TODO: Put this somewhere else, or at least the implementation part.
class StreamBuffer {
uint8_t* data_;
size_t used_;
size_t capacity_;
public:
constexpr StreamBuffer(
void* const data = nullptr,
const size_t capacity = 0
) : data_ { static_cast<uint8_t*>(data) },
used_ { 0 },
capacity_ { capacity }
{
}
size_t write(const void* p, const size_t count) {
const auto copy_size = std::min(capacity_ - used_, count);
memcpy(&data_[used_], p, copy_size);
used_ += copy_size;
return copy_size;
}
size_t read(void* p, const size_t count) {
const auto copy_size = std::min(used_, count);
memcpy(p, &data_[capacity_ - used_], copy_size);
used_ -= copy_size;
return copy_size;
}
bool is_full() const {
return used_ >= capacity_;
}
bool is_empty() const {
return used_ == 0;
}
void* data() const {
return data_;
}
size_t size() const {
return used_;
}
size_t capacity() const {
return capacity_;
}
void set_size(const size_t value) {
used_ = value;
}
void empty() {
used_ = 0;
}
};
struct CaptureConfig {
const size_t write_size;
const size_t buffer_count;
uint64_t baseband_bytes_received;
uint64_t baseband_bytes_dropped;
FIFO<StreamBuffer*>* fifo_buffers_empty;
FIFO<StreamBuffer*>* fifo_buffers_full;
constexpr CaptureConfig(
const size_t write_size,
const size_t buffer_count
) : write_size { write_size },
buffer_count { buffer_count },
baseband_bytes_received { 0 },
baseband_bytes_dropped { 0 },
fifo_buffers_empty { nullptr },
fifo_buffers_full { nullptr }
{
}
size_t dropped_percent() const {
if( baseband_bytes_dropped == 0 ) {
return 0;
} else {
const size_t percent = baseband_bytes_dropped * 100U / baseband_bytes_received;
return std::max(1U, percent);
}
}
};
class CaptureConfigMessage : public Message {
public:
constexpr CaptureConfigMessage(
CaptureConfig* const config
) : Message { ID::CaptureConfig },
config { config }
{
}
CaptureConfig* const config;
};
struct ReplayConfig {
const size_t read_size;
const size_t buffer_count;
uint64_t baseband_bytes_received;
FIFO<StreamBuffer*>* fifo_buffers_empty;
FIFO<StreamBuffer*>* fifo_buffers_full;
constexpr ReplayConfig(
const size_t read_size,
const size_t buffer_count
) : read_size { read_size },
buffer_count { buffer_count },
baseband_bytes_received { 0 },
fifo_buffers_empty { nullptr },
fifo_buffers_full { nullptr }
{
}
};
class ReplayConfigMessage : public Message {
public:
constexpr ReplayConfigMessage(
ReplayConfig* const config
) : Message { ID::ReplayConfig },
config { config }
{
}
ReplayConfig* const config;
};
class TXProgressMessage : public Message {
public:
constexpr TXProgressMessage(
) : Message { ID::TXProgress }
{
}
uint32_t progress = 0;
bool done = false;
};
class AFSKRxConfigureMessage : public Message {
public:
constexpr AFSKRxConfigureMessage(
const uint32_t baudrate,
const uint32_t word_length,
const uint32_t trigger_value,
const bool trigger_word
) : Message { ID::AFSKRxConfigure },
baudrate(baudrate),
word_length(word_length),
trigger_value(trigger_value),
trigger_word(trigger_word)
{
}
const uint32_t baudrate;
const uint32_t word_length;
const uint32_t trigger_value;
const bool trigger_word;
};
class PitchRSSIConfigureMessage : public Message {
public:
constexpr PitchRSSIConfigureMessage(
const bool enabled,
const int32_t rssi
) : Message { ID::PitchRSSIConfigure },
enabled(enabled),
rssi(rssi)
{
}
const bool enabled;
const int32_t rssi;
};
class TonesConfigureMessage : public Message {
public:
constexpr TonesConfigureMessage(
const uint32_t fm_delta,
const uint32_t pre_silence,
const uint16_t tone_count,
const bool dual_tone,
const bool audio_out
) : Message { ID::TonesConfigure },
fm_delta(fm_delta),
pre_silence(pre_silence),
tone_count(tone_count),
dual_tone(dual_tone),
audio_out(audio_out)
{
}
const uint32_t fm_delta;
const uint32_t pre_silence;
const uint16_t tone_count;
const bool dual_tone;
const bool audio_out;
};
class RDSConfigureMessage : public Message {
public:
constexpr RDSConfigureMessage(
const uint16_t length
) : Message { ID::RDSConfigure },
length(length)
{
}
const uint16_t length = 0;
};
class RetuneMessage : public Message {
public:
constexpr RetuneMessage(
) : Message { ID::Retune }
{
}
int64_t freq = 0;
uint32_t range = 0;
};
class AudioLevelReportMessage : public Message {
public:
constexpr AudioLevelReportMessage(
) : Message { ID::AudioLevelReport }
{
}
uint32_t value = 0;
};
class AudioTXConfigMessage : public Message {
public:
constexpr AudioTXConfigMessage(
const uint32_t divider,
const float deviation_hz,
const float audio_gain,
const uint32_t tone_key_delta,
const float tone_key_mix_weight
) : Message { ID::AudioTXConfig },
divider(divider),
deviation_hz(deviation_hz),
audio_gain(audio_gain),
tone_key_delta(tone_key_delta),
tone_key_mix_weight(tone_key_mix_weight)
{
}
const uint32_t divider;
const float deviation_hz;
const float audio_gain;
const uint32_t tone_key_delta;
const float tone_key_mix_weight;
};
class SigGenConfigMessage : public Message {
public:
constexpr SigGenConfigMessage(
const uint32_t bw,
const uint32_t shape,
const uint32_t duration
) : Message { ID::SigGenConfig },
bw(bw),
shape(shape),
duration(duration)
{
}
const uint32_t bw;
const uint32_t shape;
const uint32_t duration;
};
class SigGenToneMessage : public Message {
public:
constexpr SigGenToneMessage(
const uint32_t tone_delta
) : Message { ID::SigGenTone },
tone_delta(tone_delta)
{
}
const uint32_t tone_delta;
};
class AFSKTxConfigureMessage : public Message {
public:
constexpr AFSKTxConfigureMessage(
const uint32_t samples_per_bit,
const uint32_t phase_inc_mark,
const uint32_t phase_inc_space,
const uint8_t repeat,
const uint32_t fm_delta,
const uint8_t symbol_count
) : Message { ID::AFSKTxConfigure },
samples_per_bit(samples_per_bit),
phase_inc_mark(phase_inc_mark),
phase_inc_space(phase_inc_space),
repeat(repeat),
fm_delta(fm_delta),
symbol_count(symbol_count)
{
}
const uint32_t samples_per_bit;
const uint32_t phase_inc_mark;
const uint32_t phase_inc_space;
const uint8_t repeat;
const uint32_t fm_delta;
const uint8_t symbol_count;
};
class OOKConfigureMessage : public Message {
public:
constexpr OOKConfigureMessage(
const uint32_t stream_length,
const uint32_t samples_per_bit,
const uint8_t repeat,
const uint32_t pause_symbols
) : Message { ID::OOKConfigure },
stream_length(stream_length),
samples_per_bit(samples_per_bit),
repeat(repeat),
pause_symbols(pause_symbols)
{
}
const uint32_t stream_length;
const uint32_t samples_per_bit;
const uint8_t repeat;
const uint32_t pause_symbols;
};
class SSTVConfigureMessage : public Message {
public:
constexpr SSTVConfigureMessage(
const uint8_t vis_code,
const uint32_t pixel_duration
) : Message { ID::SSTVConfigure },
vis_code(vis_code),
pixel_duration(pixel_duration)
{
}
const uint8_t vis_code;
const uint32_t pixel_duration;
};
class FSKConfigureMessage : public Message {
public:
constexpr FSKConfigureMessage(
const uint32_t stream_length,
const uint32_t samples_per_bit,
const uint32_t shift,
const uint32_t progress_notice
) : Message { ID::FSKConfigure },
stream_length(stream_length),
samples_per_bit(samples_per_bit),
shift(shift),
progress_notice(progress_notice)
{
}
const uint32_t stream_length;
const uint32_t samples_per_bit;
const uint32_t shift;
const uint32_t progress_notice;
};
class POCSAGConfigureMessage : public Message {
public:
constexpr POCSAGConfigureMessage(
const pocsag::BitRate bitrate
) : Message { ID::POCSAGConfigure },
bitrate(bitrate)
{
}
const pocsag::BitRate bitrate;
};
class ADSBConfigureMessage : public Message {
public:
constexpr ADSBConfigureMessage(
const uint32_t test
) : Message { ID::ADSBConfigure },
test(test)
{
}
const uint32_t test;
};
class JammerConfigureMessage : public Message {
public:
constexpr JammerConfigureMessage(
const bool run,
const jammer::JammerType type,
const uint32_t speed
) : Message { ID::JammerConfigure },
run(run),
type(type),
speed(speed)
{
}
const bool run;
const jammer::JammerType type;
const uint32_t speed;
};
class DTMFTXConfigMessage : public Message {
public:
constexpr DTMFTXConfigMessage(
const uint32_t bw,
const uint32_t tone_length,
const uint32_t pause_length
) : Message { ID::DTMFTXConfig },
bw(bw),
tone_length(tone_length),
pause_length(pause_length)
{
}
const uint32_t bw;
const uint32_t tone_length;
const uint32_t pause_length;
};
// TODO: use streaming buffer instead
// TODO: rename (not only used for requests)
class RequestSignalMessage : public Message {
public:
enum class Signal : char {
FillRequest = 1,
BeepRequest = 2,
Squelched = 3
};
constexpr RequestSignalMessage(
Signal signal
) : Message { ID::RequestSignal },
signal ( signal )
{
}
Signal signal;
};
class FIFODataMessage : public Message {
public:
constexpr FIFODataMessage(
const int8_t * data
) : Message { ID::FIFOData },
data ( data )
{
}
const int8_t * data;
};
class CaptureThreadDoneMessage : public Message {
public:
constexpr CaptureThreadDoneMessage(
uint32_t error = 0
) : Message { ID::CaptureThreadDone },
error { error }
{
}
uint32_t error;
};
class ReplayThreadDoneMessage : public Message {
public:
constexpr ReplayThreadDoneMessage(
uint32_t return_code = 0
) : Message { ID::ReplayThreadDone },
return_code { return_code }
{
}
uint32_t return_code;
};
#endif/*__MESSAGE_H__*/