Merge branch 'master' into gps-sim

This commit is contained in:
Erwin Ried
2020-04-20 10:51:20 +02:00
committed by GitHub
29 changed files with 2928 additions and 137 deletions

View File

@@ -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

View 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;
}

View 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__*/

View 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;
}

View 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__*/

View 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;
}

View 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__*/

View 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;
}

View 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__*/