Analog tv app (#334)

* Analog TV app (PAL)

* Icon on main menu

* Analog TV should be yellow

Works for PAL only know, it would be nice to add NTSC in the future, or some customizable sync
This commit is contained in:
Erwin Ried
2020-04-20 06:50:24 +02:00
committed by GitHub
parent 40531e9230
commit e43f814861
14 changed files with 1410 additions and 0 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
@@ -338,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,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__*/