mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-14 11:47:43 +00:00
Merge branch 'master' into gps-sim
This commit is contained in:
@@ -116,6 +116,7 @@ set(CPPSRC
|
||||
dsp_goertzel.cpp
|
||||
matched_filter.cpp
|
||||
spectrum_collector.cpp
|
||||
tv_collector.cpp
|
||||
stream_input.cpp
|
||||
stream_output.cpp
|
||||
dsp_squelch.cpp
|
||||
@@ -311,7 +312,19 @@ set(MODE_CPPSRC
|
||||
proc_afskrx.cpp
|
||||
)
|
||||
DeclareTargets(PAFR afskrx)
|
||||
### NRF RX
|
||||
|
||||
set(MODE_CPPSRC
|
||||
proc_nrfrx.cpp
|
||||
)
|
||||
DeclareTargets(PNRR nrfrx)
|
||||
|
||||
### BTLE RX
|
||||
|
||||
set(MODE_CPPSRC
|
||||
proc_btlerx.cpp
|
||||
)
|
||||
DeclareTargets(PBTR btlerx)
|
||||
### AIS
|
||||
|
||||
set(MODE_CPPSRC
|
||||
@@ -326,6 +339,13 @@ set(MODE_CPPSRC
|
||||
)
|
||||
DeclareTargets(PAMA am_audio)
|
||||
|
||||
### AM TV
|
||||
|
||||
set(MODE_CPPSRC
|
||||
proc_am_tv.cpp
|
||||
)
|
||||
DeclareTargets(PAMT am_tv)
|
||||
|
||||
### Audio transmit
|
||||
|
||||
set(MODE_CPPSRC
|
||||
|
86
firmware/baseband/proc_am_tv.cpp
Normal file
86
firmware/baseband/proc_am_tv.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
* Copyright (C) 2020 Shao
|
||||
*
|
||||
* 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_am_tv.hpp"
|
||||
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "dsp_fft.hpp"
|
||||
#include "event_m4.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||
if( !configured ) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::fill(spectrum.begin(), spectrum.end(), 0);
|
||||
|
||||
for(size_t i=0; i<spectrum.size(); i++) {
|
||||
spectrum[i] += buffer.p[i];
|
||||
}
|
||||
|
||||
const buffer_c16_t buffer_c16 {spectrum.data(),spectrum.size(),buffer.sampling_rate};
|
||||
channel_spectrum.feed(buffer_c16);
|
||||
|
||||
int8_t re, im;
|
||||
int8_t mag;
|
||||
|
||||
for (size_t i = 0; i < 128; i++)
|
||||
{
|
||||
re = buffer.p[i].real();
|
||||
im = buffer.p[i].imag();
|
||||
mag = __builtin_sqrtf((re * re) + (im * im)) ;
|
||||
const unsigned int v = re + 127.0f; //timescope
|
||||
audio_spectrum.db[i] = std::max(0U, std::min(255U, v));
|
||||
}
|
||||
AudioSpectrumMessage message { &audio_spectrum };
|
||||
shared_memory.application_queue.push(message);
|
||||
}
|
||||
|
||||
void WidebandFMAudio::on_message(const Message* const message) {
|
||||
switch(message->id) {
|
||||
case Message::ID::UpdateSpectrum:
|
||||
case Message::ID::SpectrumStreamingConfig:
|
||||
channel_spectrum.on_message(message);
|
||||
break;
|
||||
|
||||
case Message::ID::WFMConfigure:
|
||||
configure(*reinterpret_cast<const WFMConfigureMessage*>(message));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WidebandFMAudio::configure(const WFMConfigureMessage& message) {
|
||||
configured = true;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
EventDispatcher event_dispatcher { std::make_unique<WidebandFMAudio>() };
|
||||
event_dispatcher.run();
|
||||
return 0;
|
||||
}
|
65
firmware/baseband/proc_am_tv.hpp
Normal file
65
firmware/baseband/proc_am_tv.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
* Copyright (C) 2020 Shao
|
||||
*
|
||||
* 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_AM_TV_H__
|
||||
#define __PROC_AM_TV_H__
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
#include "rssi_thread.hpp"
|
||||
|
||||
#include "dsp_types.hpp"
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
#include "block_decimator.hpp"
|
||||
|
||||
#include "tv_collector.hpp"
|
||||
|
||||
class WidebandFMAudio : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
|
||||
void on_message(const Message* const message) override;
|
||||
|
||||
private:
|
||||
static constexpr size_t baseband_fs = 2000000;
|
||||
|
||||
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive };
|
||||
RSSIThread rssi_thread { NORMALPRIO + 10 };
|
||||
|
||||
std::array<complex16_t, 512> dst { };
|
||||
const buffer_c16_t dst_buffer {
|
||||
dst.data(),
|
||||
dst.size()
|
||||
};
|
||||
|
||||
AudioSpectrum audio_spectrum { };
|
||||
TvCollector channel_spectrum { };
|
||||
std::array<complex16_t, 256> spectrum { };
|
||||
|
||||
bool configured { false };
|
||||
void configure(const WFMConfigureMessage& message);
|
||||
|
||||
};
|
||||
|
||||
#endif/*__PROC_AM_TV_H__*/
|
339
firmware/baseband/proc_btlerx.cpp
Normal file
339
firmware/baseband/proc_btlerx.cpp
Normal file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
* Copyright (C) 2020 Shao
|
||||
*
|
||||
* 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_btlerx.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include "event_m4.hpp"
|
||||
|
||||
void BTLERxProcessor::execute(const buffer_c8_t& buffer) {
|
||||
if (!configured) return;
|
||||
|
||||
// FM demodulation
|
||||
|
||||
/*const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||
const auto channel = decim_1.execute(decim_0_out, dst_buffer);
|
||||
|
||||
feed_channel_stats(channel);
|
||||
|
||||
auto audio_oversampled = demod.execute(channel, work_audio_buffer);*/
|
||||
|
||||
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||
feed_channel_stats(decim_0_out);
|
||||
|
||||
auto audio_oversampled = demod.execute(decim_0_out, work_audio_buffer);
|
||||
|
||||
/*std::fill(spectrum.begin(), spectrum.end(), 0);
|
||||
for(size_t i=0; i<spectrum.size(); i++) {
|
||||
spectrum[i] += buffer.p[i];
|
||||
}
|
||||
const buffer_c16_t buffer_c16 {spectrum.data(),spectrum.size(),buffer.sampling_rate};
|
||||
feed_channel_stats(buffer_c16);
|
||||
|
||||
auto audio_oversampled = demod.execute(buffer_c16, work_audio_buffer);*/
|
||||
// Audio signal processing
|
||||
for (size_t c = 0; c < audio_oversampled.count; c++) {
|
||||
int result;
|
||||
|
||||
/*const int32_t sample_int = audio_oversampled.p[c] * 32768.0f;
|
||||
int32_t current_sample = __SSAT(sample_int, 16);
|
||||
current_sample /= 128;*/
|
||||
|
||||
int32_t current_sample = audio_oversampled.p[c]; //if I directly use this, some results can pass crc but not correct.
|
||||
rb_head++;
|
||||
rb_head=(rb_head)%RB_SIZE;
|
||||
|
||||
rb_buf[rb_head] = current_sample;
|
||||
|
||||
skipSamples = skipSamples - 1;
|
||||
|
||||
|
||||
if (skipSamples<1)
|
||||
{
|
||||
|
||||
|
||||
int32_t threshold_tmp=0;
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
threshold_tmp = threshold_tmp + (int32_t)rb_buf[(rb_head+c)%RB_SIZE];
|
||||
}
|
||||
g_threshold = (int32_t)threshold_tmp/8;
|
||||
|
||||
|
||||
int transitions=0;
|
||||
if (rb_buf[(rb_head+9)%RB_SIZE] > g_threshold)
|
||||
{
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head + c)%RB_SIZE] > rb_buf[(rb_head + c + 1)%RB_SIZE])
|
||||
transitions = transitions + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head + c)%RB_SIZE] < rb_buf[(rb_head + c + 1)%RB_SIZE])
|
||||
transitions = transitions + 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool packet_detected=false;
|
||||
//if ( transitions==4 && abs(g_threshold)<15500)
|
||||
if ( transitions==4)
|
||||
{
|
||||
|
||||
|
||||
uint8_t packet_data[500];
|
||||
int packet_length;
|
||||
uint32_t packet_crc;
|
||||
uint32_t calced_crc;
|
||||
uint64_t packet_addr_l;
|
||||
uint32_t result;
|
||||
uint8_t crc[3];
|
||||
uint8_t packet_header_arr[2];
|
||||
|
||||
packet_addr_l=0;
|
||||
for (int i=0;i<4;i++)
|
||||
{
|
||||
bool current_bit;
|
||||
uint8_t byte=0;
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head + (i+1)*8 + c)%RB_SIZE] > g_threshold)
|
||||
current_bit = true;
|
||||
else
|
||||
current_bit = false;
|
||||
byte |= current_bit << (7-c);
|
||||
}
|
||||
uint8_t byte_temp = (uint8_t) (((byte * 0x0802LU & 0x22110LU) | (byte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
|
||||
packet_addr_l|=((uint64_t)byte_temp)<<(8*i);
|
||||
}
|
||||
|
||||
channel_number = 38;
|
||||
|
||||
|
||||
for (int t=0;t<2;t++)
|
||||
{
|
||||
bool current_bit;
|
||||
uint8_t byte=0;
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head + 5*8+t*8 + c)%RB_SIZE] > g_threshold)
|
||||
current_bit = true;
|
||||
else
|
||||
current_bit = false;
|
||||
byte |= current_bit << (7-c);
|
||||
}
|
||||
|
||||
packet_header_arr[t] = byte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t byte_temp2 = (uint8_t) (((channel_number * 0x0802LU & 0x22110LU) | (channel_number * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
|
||||
uint8_t lfsr_1 = byte_temp2 | 2;
|
||||
int header_length = 2;
|
||||
int header_counter = 0;
|
||||
while(header_length--)
|
||||
{
|
||||
for(uint8_t i = 0x80; i; i >>= 1)
|
||||
{
|
||||
if(lfsr_1 & 0x80)
|
||||
{
|
||||
lfsr_1 ^= 0x11;
|
||||
(packet_header_arr[header_counter]) ^= i;
|
||||
}
|
||||
lfsr_1 <<= 1;
|
||||
}
|
||||
header_counter = header_counter + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (packet_addr_l==0x8E89BED6)
|
||||
{
|
||||
|
||||
uint8_t byte_temp3 = (uint8_t) (((packet_header_arr[1] * 0x0802LU & 0x22110LU) | (packet_header_arr[1] * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
|
||||
packet_length=byte_temp3&0x3F;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_length=0;
|
||||
}
|
||||
|
||||
for (int t=0;t<packet_length+2+3;t++)
|
||||
{
|
||||
bool current_bit;
|
||||
uint8_t byte=0;
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head + 5*8+t*8 + c)%RB_SIZE] > g_threshold)
|
||||
current_bit = true;
|
||||
else
|
||||
current_bit = false;
|
||||
byte |= current_bit << (7-c);
|
||||
}
|
||||
|
||||
packet_data[t] = byte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t byte_temp4 = (uint8_t) (((channel_number * 0x0802LU & 0x22110LU) | (channel_number * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
|
||||
uint8_t lfsr_2 = byte_temp4 | 2;
|
||||
int pdu_crc_length = packet_length+2+3;
|
||||
int pdu_crc_counter = 0;
|
||||
while(pdu_crc_length--)
|
||||
{
|
||||
for(uint8_t i = 0x80; i; i >>= 1)
|
||||
{
|
||||
if(lfsr_2 & 0x80)
|
||||
{
|
||||
lfsr_2 ^= 0x11;
|
||||
(packet_data[pdu_crc_counter]) ^= i;
|
||||
}
|
||||
lfsr_2 <<= 1;
|
||||
}
|
||||
pdu_crc_counter = pdu_crc_counter + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (packet_addr_l==0x8E89BED6)
|
||||
{
|
||||
crc[0]=crc[1]=crc[2]=0x55;
|
||||
}
|
||||
else
|
||||
{
|
||||
crc[0]=crc[1]=crc[2]=0;
|
||||
}
|
||||
|
||||
uint8_t v, t, d, crc_length;
|
||||
uint32_t crc_result=0;
|
||||
crc_length = packet_length + 2;
|
||||
int counter = 0;
|
||||
while(crc_length--)
|
||||
{
|
||||
uint8_t byte_temp5 = (uint8_t) (((packet_data[counter] * 0x0802LU & 0x22110LU) | (packet_data[counter] * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
|
||||
d = byte_temp5;
|
||||
for(v = 0; v < 8; v++, d >>= 1)
|
||||
{
|
||||
t = crc[0] >> 7;
|
||||
crc[0] <<= 1;
|
||||
if(crc[1] & 0x80) crc[0] |= 1;
|
||||
crc[1] <<= 1;
|
||||
if(crc[2] & 0x80) crc[1] |= 1;
|
||||
crc[2] <<= 1;
|
||||
if(t != (d & 1))
|
||||
{
|
||||
crc[2] ^= 0x5B;
|
||||
crc[1] ^= 0x06;
|
||||
}
|
||||
}
|
||||
counter = counter + 1;
|
||||
}
|
||||
for (v=0;v<3;v++) crc_result=(crc_result<<8)|crc[v];
|
||||
calced_crc = crc_result;
|
||||
|
||||
packet_crc=0;
|
||||
for (int c=0;c<3;c++) packet_crc=(packet_crc<<8)|packet_data[packet_length+2+c];
|
||||
|
||||
if (packet_addr_l==0x8E89BED6)
|
||||
//if (packet_crc==calced_crc)
|
||||
{
|
||||
uint8_t mac_data[6];
|
||||
int counter = 0;
|
||||
for (int i = 7; i >= 2; i--)
|
||||
{
|
||||
uint8_t byte_temp6 = (uint8_t) (((packet_data[i] * 0x0802LU & 0x22110LU) | (packet_data[i] * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
|
||||
//result = byte_temp6;
|
||||
mac_data[counter] = byte_temp6;
|
||||
counter = counter + 1;
|
||||
}
|
||||
|
||||
data_message.is_data = false;
|
||||
data_message.value = 'A';
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
data_message.is_data = true;
|
||||
data_message.value = mac_data[0];
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
data_message.is_data = true;
|
||||
data_message.value = mac_data[1];
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
data_message.is_data = true;
|
||||
data_message.value = mac_data[2];
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
data_message.is_data = true;
|
||||
data_message.value = mac_data[3];
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
data_message.is_data = true;
|
||||
data_message.value = mac_data[4];
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
data_message.is_data = true;
|
||||
data_message.value = mac_data[5];
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
data_message.is_data = false;
|
||||
data_message.value = 'B';
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
packet_detected = true;
|
||||
}
|
||||
else
|
||||
packet_detected = false;
|
||||
}
|
||||
|
||||
if (packet_detected)
|
||||
{
|
||||
skipSamples=20;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BTLERxProcessor::on_message(const Message* const message) {
|
||||
if (message->id == Message::ID::BTLERxConfigure)
|
||||
configure(*reinterpret_cast<const BTLERxConfigureMessage*>(message));
|
||||
}
|
||||
|
||||
void BTLERxProcessor::configure(const BTLERxConfigureMessage& message) {
|
||||
decim_0.configure(taps_200k_wfm_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_200k_wfm_decim_1.taps, 131072);
|
||||
demod.configure(audio_fs, 5000);
|
||||
|
||||
configured = true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
EventDispatcher event_dispatcher { std::make_unique<BTLERxProcessor>() };
|
||||
event_dispatcher.run();
|
||||
return 0;
|
||||
}
|
95
firmware/baseband/proc_btlerx.hpp
Normal file
95
firmware/baseband/proc_btlerx.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
* Copyright (C) 2020 Shao
|
||||
*
|
||||
* 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_BTLERX_H__
|
||||
#define __PROC_BTLERX_H__
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
#include "rssi_thread.hpp"
|
||||
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
|
||||
#include "audio_output.hpp"
|
||||
|
||||
#include "fifo.hpp"
|
||||
#include "message.hpp"
|
||||
|
||||
class BTLERxProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
|
||||
void on_message(const Message* const message) override;
|
||||
|
||||
private:
|
||||
static constexpr size_t baseband_fs = 4000000;
|
||||
static constexpr size_t audio_fs = baseband_fs / 8 / 8 / 2;
|
||||
|
||||
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive };
|
||||
RSSIThread rssi_thread { NORMALPRIO + 10 };
|
||||
|
||||
std::array<complex16_t, 512> dst { };
|
||||
const buffer_c16_t dst_buffer {
|
||||
dst.data(),
|
||||
dst.size()
|
||||
};
|
||||
|
||||
std::array<complex16_t, 512> spectrum { };
|
||||
const buffer_c16_t spectrum_buffer {
|
||||
spectrum.data(),
|
||||
spectrum.size()
|
||||
};
|
||||
|
||||
const buffer_s16_t work_audio_buffer {
|
||||
(int16_t*)dst.data(),
|
||||
sizeof(dst) / sizeof(int16_t)
|
||||
};
|
||||
|
||||
|
||||
// Array size ok down to 375 bauds (24000 / 375)
|
||||
std::array<int32_t, 64> delay_line { 0 };
|
||||
std::array<int16_t, 1000> rb_buf { 0 };
|
||||
|
||||
/*dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0 { };
|
||||
dsp::decimate::FIRC16xR16x32Decim8 decim_1 { };
|
||||
dsp::decimate::FIRAndDecimateComplex channel_filter { };*/
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0 { };
|
||||
dsp::decimate::FIRC16xR16x16Decim2 decim_1 { };
|
||||
|
||||
dsp::demodulate::FM demod { };
|
||||
int rb_head {-1};
|
||||
int32_t g_threshold {0};
|
||||
uint8_t channel_number {38};
|
||||
int skipSamples {1000};
|
||||
int RB_SIZE {1000};
|
||||
|
||||
bool configured { false };
|
||||
|
||||
|
||||
void configure(const BTLERxConfigureMessage& message);
|
||||
|
||||
AFSKDataMessage data_message { false, 0 };
|
||||
};
|
||||
|
||||
#endif/*__PROC_BTLERX_H__*/
|
286
firmware/baseband/proc_nrfrx.cpp
Normal file
286
firmware/baseband/proc_nrfrx.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
* Copyright (C) 2020 Shao
|
||||
*
|
||||
* 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_nrfrx.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include "event_m4.hpp"
|
||||
|
||||
void NRFRxProcessor::execute(const buffer_c8_t& buffer) {
|
||||
if (!configured) return;
|
||||
|
||||
// FM demodulation
|
||||
|
||||
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||
feed_channel_stats(decim_0_out);
|
||||
|
||||
auto audio_oversampled = demod.execute(decim_0_out, work_audio_buffer);
|
||||
// Audio signal processing
|
||||
for (size_t c = 0; c < audio_oversampled.count; c++) {
|
||||
int result;
|
||||
int g_srate = 4; //4 for 250KPS
|
||||
//int g_srate = 1; //1 for 1MPS, not working yet
|
||||
int32_t current_sample = audio_oversampled.p[c]; //if I directly use this, some results can pass crc but not correct.
|
||||
rb_head++;
|
||||
rb_head=(rb_head)%RB_SIZE;
|
||||
|
||||
rb_buf[rb_head] = current_sample;
|
||||
|
||||
skipSamples = skipSamples - 1;
|
||||
|
||||
|
||||
if (skipSamples<1)
|
||||
{
|
||||
|
||||
|
||||
int32_t threshold_tmp=0;
|
||||
for (int c=0;c<8*g_srate;c++)
|
||||
{
|
||||
threshold_tmp = threshold_tmp + (int32_t)rb_buf[(rb_head+c)%RB_SIZE];
|
||||
}
|
||||
|
||||
g_threshold = (int32_t)threshold_tmp/(8*g_srate);
|
||||
|
||||
int transitions=0;
|
||||
if (rb_buf[(rb_head + 9*g_srate)%RB_SIZE] > g_threshold)
|
||||
{
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head + c*g_srate)%RB_SIZE] > rb_buf[(rb_head + (c+1)*g_srate)%RB_SIZE])
|
||||
transitions = transitions + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head + c*g_srate)%RB_SIZE] < rb_buf[(rb_head + (c+1)*g_srate)%RB_SIZE])
|
||||
transitions = transitions + 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool packet_detected=false;
|
||||
//if ( transitions==4 && abs(g_threshold)<15500)
|
||||
if ( transitions==4 && abs(g_threshold)<15500)
|
||||
{
|
||||
int packet_length = 0;
|
||||
uint8_t tmp_buf[10];
|
||||
uint8_t packet_data[500];
|
||||
uint8_t packet_packed[50];
|
||||
uint16_t pcf;
|
||||
uint32_t packet_crc;
|
||||
uint32_t calced_crc;
|
||||
uint64_t packet_addr_l;
|
||||
|
||||
/* extract address */
|
||||
packet_addr_l=0;
|
||||
|
||||
for (int t=0;t<5;t++)
|
||||
{
|
||||
bool current_bit;
|
||||
uint8_t byte=0;
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head+(1*8+t*8+c)*g_srate)%RB_SIZE] > g_threshold)
|
||||
current_bit = true;
|
||||
else
|
||||
current_bit = false;
|
||||
byte |= current_bit << (7-c);
|
||||
}
|
||||
tmp_buf[t]=byte;
|
||||
}
|
||||
|
||||
for (int t=0;t<5;t++) packet_addr_l|=((uint64_t)tmp_buf[t])<<(4-t)*8;
|
||||
|
||||
//channel_number = 26;
|
||||
|
||||
|
||||
/* extract pcf */
|
||||
for (int t=0;t<2;t++)
|
||||
{
|
||||
bool current_bit;
|
||||
uint8_t byte=0;
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head+(6*8+t*8+c)*g_srate)%RB_SIZE] > g_threshold)
|
||||
current_bit = true;
|
||||
else
|
||||
current_bit = false;
|
||||
byte |= current_bit << (7-c);
|
||||
}
|
||||
tmp_buf[t]=byte;
|
||||
}
|
||||
|
||||
pcf = tmp_buf[0]<<8 | tmp_buf[1];
|
||||
pcf >>=7;
|
||||
|
||||
/* extract packet length, avoid excessive length packets */
|
||||
if(packet_length == 0)
|
||||
packet_length=(int)pcf>>3;
|
||||
if (packet_length>32)
|
||||
packet_detected = false;
|
||||
|
||||
/* extract data */
|
||||
for (int t=0;t<packet_length;t++)
|
||||
{
|
||||
bool current_bit;
|
||||
uint8_t byte=0;
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head+(6*8+9+t*8+c)*g_srate)%RB_SIZE] > g_threshold)
|
||||
current_bit = true;
|
||||
else
|
||||
current_bit = false;
|
||||
byte |= current_bit << (7-c);
|
||||
}
|
||||
packet_data[t]=byte;
|
||||
}
|
||||
|
||||
/* Prepare packed bit stream for CRC calculation */
|
||||
uint64_t packet_header=packet_addr_l;
|
||||
packet_header<<=9;
|
||||
packet_header|=pcf;
|
||||
for (int c=0;c<7;c++){
|
||||
packet_packed[c]=(packet_header>>((6-c)*8))&0xFF;
|
||||
}
|
||||
|
||||
for (int c=0;c<packet_length;c++){
|
||||
packet_packed[c+7]=packet_data[c];
|
||||
}
|
||||
|
||||
/* calculate packet crc */
|
||||
const uint8_t* data = packet_packed;
|
||||
size_t data_len = 7+packet_length;
|
||||
bool bit;
|
||||
uint8_t cc;
|
||||
uint_fast16_t crc=0x3C18;
|
||||
while (data_len--) {
|
||||
cc = *data++;
|
||||
for (uint8_t i = 0x80; i > 0; i >>= 1)
|
||||
{
|
||||
bit = crc & 0x8000;
|
||||
if (cc & i)
|
||||
{
|
||||
bit = !bit;
|
||||
}
|
||||
crc <<= 1;
|
||||
if (bit)
|
||||
{
|
||||
crc ^= 0x1021;
|
||||
}
|
||||
}
|
||||
crc &= 0xffff;
|
||||
}
|
||||
calced_crc = (uint16_t)(crc & 0xffff);
|
||||
|
||||
/* extract crc */
|
||||
for (int t=0;t<2;t++)
|
||||
{
|
||||
bool current_bit;
|
||||
uint8_t byte=0;
|
||||
for (int c=0;c<8;c++)
|
||||
{
|
||||
if (rb_buf[(rb_head+((6+packet_length)*8+9+t*8+c)*g_srate)%RB_SIZE] > g_threshold)
|
||||
current_bit = true;
|
||||
else
|
||||
current_bit = false;
|
||||
byte |= current_bit << (7-c);
|
||||
}
|
||||
tmp_buf[t]=byte;
|
||||
}
|
||||
packet_crc = tmp_buf[0]<<8 | tmp_buf[1];
|
||||
|
||||
/* NRF24L01+ packet found, dump information */
|
||||
//if (packet_addr_l==0xE7E7E7E7)
|
||||
if (packet_crc==calced_crc)
|
||||
{
|
||||
data_message.is_data = false;
|
||||
data_message.value = 'A';
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
data_message.is_data = true;
|
||||
data_message.value = packet_addr_l;
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
for (int c=0;c<7;c++)
|
||||
{
|
||||
data_message.is_data = true;
|
||||
data_message.value = packet_addr_l >> 8;
|
||||
shared_memory.application_queue.push(data_message);
|
||||
}
|
||||
/*data_message.is_data = true;
|
||||
data_message.value = packet_addr_l;
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
data_message.is_data = true;
|
||||
data_message.value = packet_addr_l >> 8;
|
||||
shared_memory.application_queue.push(data_message);*/
|
||||
|
||||
data_message.is_data = false;
|
||||
data_message.value = 'B';
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
for (int c=0;c<packet_length;c++)
|
||||
{
|
||||
data_message.is_data = true;
|
||||
data_message.value = packet_data[c];
|
||||
shared_memory.application_queue.push(data_message);
|
||||
}
|
||||
|
||||
data_message.is_data = false;
|
||||
data_message.value = 'C';
|
||||
shared_memory.application_queue.push(data_message);
|
||||
|
||||
|
||||
packet_detected = true;
|
||||
}
|
||||
else
|
||||
packet_detected = false;
|
||||
}
|
||||
|
||||
if (packet_detected)
|
||||
{
|
||||
skipSamples=20;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NRFRxProcessor::on_message(const Message* const message) {
|
||||
if (message->id == Message::ID::NRFRxConfigure)
|
||||
configure(*reinterpret_cast<const NRFRxConfigureMessage*>(message));
|
||||
}
|
||||
|
||||
void NRFRxProcessor::configure(const NRFRxConfigureMessage& message) {
|
||||
decim_0.configure(taps_200k_wfm_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_200k_wfm_decim_1.taps, 131072);
|
||||
demod.configure(audio_fs, 5000);
|
||||
|
||||
configured = true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
EventDispatcher event_dispatcher { std::make_unique<NRFRxProcessor>() };
|
||||
event_dispatcher.run();
|
||||
return 0;
|
||||
}
|
96
firmware/baseband/proc_nrfrx.hpp
Normal file
96
firmware/baseband/proc_nrfrx.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
* Copyright (C) 2020 Shao
|
||||
*
|
||||
* 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_NRFRX_H__
|
||||
#define __PROC_NRFRX_H__
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
#include "rssi_thread.hpp"
|
||||
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
|
||||
#include "audio_output.hpp"
|
||||
|
||||
#include "fifo.hpp"
|
||||
#include "message.hpp"
|
||||
|
||||
class NRFRxProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
|
||||
void on_message(const Message* const message) override;
|
||||
|
||||
private:
|
||||
static constexpr size_t baseband_fs = 4000000;
|
||||
static constexpr size_t audio_fs = baseband_fs / 8 / 8 / 2;
|
||||
|
||||
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive };
|
||||
RSSIThread rssi_thread { NORMALPRIO + 10 };
|
||||
|
||||
std::array<complex16_t, 512> dst { };
|
||||
const buffer_c16_t dst_buffer {
|
||||
dst.data(),
|
||||
dst.size()
|
||||
};
|
||||
|
||||
std::array<complex16_t, 512> spectrum { };
|
||||
const buffer_c16_t spectrum_buffer {
|
||||
spectrum.data(),
|
||||
spectrum.size()
|
||||
};
|
||||
|
||||
const buffer_s16_t work_audio_buffer {
|
||||
(int16_t*)dst.data(),
|
||||
sizeof(dst) / sizeof(int16_t)
|
||||
};
|
||||
|
||||
|
||||
// Array size ok down to 375 bauds (24000 / 375)
|
||||
std::array<int32_t, 64> delay_line { 0 };
|
||||
std::array<int16_t, 1000> rb_buf { 0 };
|
||||
|
||||
/*dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0 { };
|
||||
dsp::decimate::FIRC16xR16x32Decim8 decim_1 { };
|
||||
dsp::decimate::FIRAndDecimateComplex channel_filter { };*/
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0 { };
|
||||
dsp::decimate::FIRC16xR16x16Decim2 decim_1 { };
|
||||
|
||||
dsp::demodulate::FM demod { };
|
||||
int rb_head {-1};
|
||||
int32_t g_threshold {0};
|
||||
//uint8_t g_srate {8};
|
||||
uint8_t channel_number {38};
|
||||
int skipSamples {1000};
|
||||
int RB_SIZE {1000};
|
||||
|
||||
bool configured { false };
|
||||
|
||||
|
||||
void configure(const NRFRxConfigureMessage& message);
|
||||
|
||||
AFSKDataMessage data_message { false, 0 };
|
||||
};
|
||||
|
||||
#endif/*__PROC_NRFRX_H__*/
|
122
firmware/baseband/tv_collector.cpp
Normal file
122
firmware/baseband/tv_collector.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2020 Shao
|
||||
*
|
||||
* 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 "tv_collector.hpp"
|
||||
|
||||
#include "dsp_fft.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
#include "event_m4.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
#include "event_m4.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
void TvCollector::on_message(const Message* const message) {
|
||||
switch(message->id) {
|
||||
case Message::ID::UpdateSpectrum:
|
||||
update();
|
||||
break;
|
||||
|
||||
case Message::ID::SpectrumStreamingConfig:
|
||||
set_state(*reinterpret_cast<const SpectrumStreamingConfigMessage*>(message));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TvCollector::set_state(const SpectrumStreamingConfigMessage& message) {
|
||||
if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) {
|
||||
start();
|
||||
} else {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
void TvCollector::start() {
|
||||
streaming = true;
|
||||
ChannelSpectrumConfigMessage message { &fifo };
|
||||
shared_memory.application_queue.push(message);
|
||||
}
|
||||
|
||||
void TvCollector::stop() {
|
||||
streaming = false;
|
||||
fifo.reset_in();
|
||||
}
|
||||
|
||||
void TvCollector::set_decimation_factor(
|
||||
const size_t decimation_factor
|
||||
) {
|
||||
channel_spectrum_decimator.set_factor(decimation_factor);
|
||||
}
|
||||
|
||||
/* TODO: Refactor to register task with idle thread?
|
||||
* It's sad that the idle thread has to call all the way back here just to
|
||||
* perform the deferred task on the buffer of data we prepared.
|
||||
*/
|
||||
|
||||
void TvCollector::feed(
|
||||
const buffer_c16_t& channel
|
||||
) {
|
||||
// Called from baseband processing thread.
|
||||
channel_spectrum_decimator.feed(channel,[this](const buffer_c16_t& data) {this->post_message(data);});
|
||||
}
|
||||
|
||||
void TvCollector::post_message(const buffer_c16_t& data) {
|
||||
// Called from baseband processing thread.
|
||||
float re, im;
|
||||
float mag;
|
||||
float max;
|
||||
if( streaming && !channel_spectrum_request_update ) {
|
||||
for(size_t i=0; i<256; i++)
|
||||
{
|
||||
const auto s = data.p[i];
|
||||
re = (float)(data.p[i].real());
|
||||
im = (float)(data.p[i].imag());
|
||||
mag = __builtin_sqrtf((re * re) + (im * im)) ;
|
||||
channel_spectrum[i] = {mag, mag};
|
||||
}
|
||||
channel_spectrum_sampling_rate = data.sampling_rate;
|
||||
channel_spectrum_request_update = true;
|
||||
EventDispatcher::events_flag(EVT_MASK_SPECTRUM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TvCollector::update() {
|
||||
// Called from idle thread (after EVT_MASK_SPECTRUM is flagged)
|
||||
if( streaming && channel_spectrum_request_update ) {
|
||||
ChannelSpectrum spectrum;
|
||||
spectrum.sampling_rate = channel_spectrum_sampling_rate;
|
||||
for(size_t i=0; i<spectrum.db.size(); i++) {
|
||||
const auto corrected_sample = channel_spectrum[i].real();
|
||||
const unsigned int v = corrected_sample + 127.0f;
|
||||
spectrum.db[i] = std::max(0U, std::min(255U, v));
|
||||
}
|
||||
fifo.in(spectrum);
|
||||
}
|
||||
|
||||
channel_spectrum_request_update = false;
|
||||
}
|
66
firmware/baseband/tv_collector.hpp
Normal file
66
firmware/baseband/tv_collector.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2020 Shao
|
||||
*
|
||||
* 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 __TV_COLLECTOR_H__
|
||||
#define __TV_COLLECTOR_H__
|
||||
|
||||
#include "dsp_types.hpp"
|
||||
#include "complex.hpp"
|
||||
|
||||
#include "block_decimator.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
#include "message.hpp"
|
||||
|
||||
class TvCollector {
|
||||
public:
|
||||
void on_message(const Message* const message);
|
||||
|
||||
void set_decimation_factor(const size_t decimation_factor);
|
||||
|
||||
void feed(
|
||||
const buffer_c16_t& channel
|
||||
);
|
||||
|
||||
private:
|
||||
BlockDecimator<complex16_t, 256> channel_spectrum_decimator { 1 };
|
||||
ChannelSpectrum fifo_data[1 << ChannelSpectrumConfigMessage::fifo_k] { };
|
||||
ChannelSpectrumFIFO fifo { fifo_data, ChannelSpectrumConfigMessage::fifo_k };
|
||||
|
||||
volatile bool channel_spectrum_request_update { false };
|
||||
bool streaming { false };
|
||||
std::array<std::complex<float>, 256> channel_spectrum { };
|
||||
uint32_t channel_spectrum_sampling_rate { 0 };
|
||||
|
||||
void post_message(const buffer_c16_t& data);
|
||||
|
||||
void set_state(const SpectrumStreamingConfigMessage& message);
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void update();
|
||||
|
||||
};
|
||||
|
||||
#endif/*__TV_COLLECTOR_H__*/
|
Reference in New Issue
Block a user