From 4d6877ab159a6d12f653a8a9f726e21fbe77dc62 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 16 Nov 2015 10:31:36 -0800 Subject: [PATCH 001/452] Extract FieldReader to separate header so it can be reused. --- firmware/common/ais_baseband.cpp | 27 ++--------------- firmware/common/field_reader.hpp | 50 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 firmware/common/field_reader.hpp diff --git a/firmware/common/ais_baseband.cpp b/firmware/common/ais_baseband.cpp index 841bec0b3..dcd414918 100644 --- a/firmware/common/ais_baseband.cpp +++ b/firmware/common/ais_baseband.cpp @@ -26,6 +26,7 @@ #include #include +#include "field_reader.hpp" #include "crc.hpp" // TODO: Move string formatting elsewhere!!! @@ -33,28 +34,6 @@ namespace baseband { -template -class FieldReader { -public: - constexpr FieldReader( - const T& data - ) : data { data } - { - } - - uint32_t read(const size_t start_bit, const size_t length) const { - uint32_t value = 0; - for(size_t i=start_bit; i<(start_bit + length); i++) { - value = (value << 1) | data[bit_remap(i)]; - } - return value; - } - -private: - const T& data; - const BitRemap bit_remap { }; -}; - namespace ais { struct BitRemap { @@ -69,8 +48,8 @@ struct CRCBitRemap { } }; -using FieldReader = baseband::FieldReader, BitRemap>; -using CRCFieldReader = baseband::FieldReader, CRCBitRemap>; +using FieldReader = ::FieldReader, BitRemap>; +using CRCFieldReader = ::FieldReader, CRCBitRemap>; struct PacketLengthRange { constexpr PacketLengthRange( diff --git a/firmware/common/field_reader.hpp b/firmware/common/field_reader.hpp new file mode 100644 index 000000000..4a1e05d6f --- /dev/null +++ b/firmware/common/field_reader.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __FIELD_READER_H__ +#define __FIELD_READER_H__ + +#include +#include + +template +class FieldReader { +public: + constexpr FieldReader( + const T& data + ) : data { data } + { + } + + uint32_t read(const size_t start_bit, const size_t length) const { + uint32_t value = 0; + for(size_t i=start_bit; i<(start_bit + length); i++) { + value = (value << 1) | data[bit_remap(i)]; + } + return value; + } + +private: + const T& data; + const BitRemap bit_remap { }; +}; + +#endif/*__FIELD_READER_H__*/ From 9900c29283b5cc22bfa6ef1cf65b37ad4c92bcbe Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 16 Nov 2015 10:33:08 -0800 Subject: [PATCH 002/452] Deepen BitPattern and BitHistory to 64 bits. --- firmware/common/bit_pattern.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/firmware/common/bit_pattern.hpp b/firmware/common/bit_pattern.hpp index 33a3616a5..8014e0226 100644 --- a/firmware/common/bit_pattern.hpp +++ b/firmware/common/bit_pattern.hpp @@ -31,12 +31,12 @@ public: history = (history << 1) | (bit & 1); } - uint32_t value() const { + uint64_t value() const { return history; } private: - uint32_t history { 0 }; + uint64_t history { 0 }; }; class BitPattern { @@ -49,24 +49,24 @@ public: } constexpr BitPattern( - const uint32_t code, + const uint64_t code, const size_t code_length, const size_t maximum_hanning_distance = 0 ) : code_ { code }, - mask_ { (1U << code_length) - 1U }, + mask_ { (1ULL << code_length) - 1ULL }, maximum_hanning_distance_ { maximum_hanning_distance } { } bool operator()(const BitHistory& history, const size_t) const { const auto delta_bits = (history.value() ^ code_) & mask_; - const size_t count = __builtin_popcountl(delta_bits); + const size_t count = __builtin_popcountll(delta_bits); return (count <= maximum_hanning_distance_); } private: - uint32_t code_; - uint32_t mask_; + uint64_t code_; + uint64_t mask_; size_t maximum_hanning_distance_; }; From 8967f0eaa1f7880ef315ad1650677c9485079e7a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 16 Nov 2015 10:33:50 -0800 Subject: [PATCH 003/452] Move common matchers to PacketBuilder. --- firmware/baseband/packet_builder.hpp | 14 ++++++++++++++ firmware/baseband/proc_tpms.hpp | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/firmware/baseband/packet_builder.hpp b/firmware/baseband/packet_builder.hpp index edf503579..3d756a7cf 100644 --- a/firmware/baseband/packet_builder.hpp +++ b/firmware/baseband/packet_builder.hpp @@ -29,6 +29,20 @@ #include "bit_pattern.hpp" +struct NeverMatch { + bool operator()(const BitHistory&, const size_t) const { + return false; + } +}; + +struct FixedLength { + bool operator()(const BitHistory&, const size_t symbols_received) const { + return symbols_received >= length; + } + + const size_t length; +}; + template class PacketBuilder { public: diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index 0bde7d687..dc10259a9 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -37,20 +37,6 @@ #include #include -struct NeverMatch { - bool operator()(const BitHistory&, const size_t) const { - return false; - } -}; - -struct FixedLength { - bool operator()(const BitHistory&, const size_t symbols_received) const { - return symbols_received >= length; - } - - const size_t length; -}; - // Translate+rectangular filter // sample=153.6k, deviation=38400, symbol=19200 // Length: 8 taps, 1 symbols, 2 cycles of sinusoid From ccd64f3cd996d04ec7dfeae9b32be134a4050edb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 19 Nov 2015 12:20:20 -0800 Subject: [PATCH 004/452] Add function for c8->c16 decimate by two without fs/4 shift. --- firmware/baseband/dsp_decimate.cpp | 57 ++++++++++++++++++++++++++++++ firmware/baseband/dsp_decimate.hpp | 12 +++++++ 2 files changed, 69 insertions(+) diff --git a/firmware/baseband/dsp_decimate.cpp b/firmware/baseband/dsp_decimate.cpp index e8fd1824d..bb06d33c0 100644 --- a/firmware/baseband/dsp_decimate.cpp +++ b/firmware/baseband/dsp_decimate.cpp @@ -26,6 +26,63 @@ namespace dsp { namespace decimate { +buffer_c16_t Complex8DecimateBy2CIC3::execute(buffer_c8_t src, buffer_c16_t dst) { + /* Decimates by two using a non-recursive third-order CIC filter. + */ + + /* CIC filter (decimating by two): + * D_I0 = i3 * 1 + i2 * 3 + i1 * 3 + i0 * 1 + * D_Q0 = q3 * 1 + q2 * 3 + q1 * 3 + q0 * 1 + * + * D_I1 = i5 * 1 + i4 * 3 + i3 * 3 + i2 * 1 + * D_Q1 = q5 * 1 + q4 * 3 + q3 * 3 + q2 * 1 + */ + + uint32_t i1_i0 = _i1_i0; + uint32_t q1_q0 = _q1_q0; + + /* 3:1 Scaled by 32 to normalize output to +/-32768-ish. */ + constexpr uint32_t scale_factor = 32; + constexpr uint32_t k_3_1 = 0x00030001 * scale_factor; + uint32_t* src_p = reinterpret_cast(&src.p[0]); + uint32_t* const src_end = reinterpret_cast(&src.p[src.count]); + uint32_t* dst_p = reinterpret_cast(&dst.p[0]); + while(src_p < src_end) { + const uint32_t q3_i3_q2_i2 = *(src_p++); // 3 + const uint32_t q5_i5_q4_i4 = *(src_p++); + + const uint32_t d_i0_partial = __SMUAD(k_3_1, i1_i0); // 1: = 3 * i1 + 1 * i0 + const uint32_t i3_i2 = __SXTB16(q3_i3_q2_i2, 0); // 1: (q3_i3_q2_i2 ror 0)[23:16]:(q3_i3_q2_i2 ror 0)[7:0] + const uint32_t d_i0 = __SMLADX(k_3_1, i3_i2, d_i0_partial); // 1: + 3 * i2 + 1 * i3 + + const uint32_t d_q0_partial = __SMUAD(k_3_1, q1_q0); // 1: = 3 * q1 * 1 * q0 + const uint32_t q3_q2 = __SXTB16(q3_i3_q2_i2, 8); // 1: (q3_i3_q2_i2 ror 8)[23:16]:(q3_i3_q2_i2 ror 8)[7:0] + const uint32_t d_q0 = __SMLADX(k_3_1, q3_q2, d_q0_partial); // 1: + 3 * q2 + 1 * q3 + + const uint32_t d_q0_i0 = __PKHBT(d_i0, d_q0, 16); // 1: (Rm<<16)[31:16]:Rn[15:0] + + const uint32_t d_i1_partial = __SMUAD(k_3_1, i3_i2); // 1: = 3 * i3 + 1 * i2 + const uint32_t i5_i4 = __SXTB16(q5_i5_q4_i4, 0); // 1: (q5_i5_q4_i4 ror 0)[23:16]:(q5_i5_q4_i4 ror 0)[7:0] + const uint32_t d_i1 = __SMLADX(k_3_1, i5_i4, d_i1_partial); // 1: + 1 * i5 + 3 * i4 + + const uint32_t d_q1_partial = __SMUAD(k_3_1, q3_q2); // 1: = 3 * q3 * 1 * q2 + const uint32_t q5_q4 = __SXTB16(q5_i5_q4_i4, 8); // 1: (q5_i5_q4_i4 ror 8)[23:16]:(q5_i5_q4_i4 ror 8)[7:0] + const uint32_t d_q1 = __SMLADX(k_3_1, q5_q4, d_q1_partial); // 1: + 1 * q5 + 3 * q4 + + const uint32_t d_q1_i1 = __PKHBT(d_i1, d_q1, 16); // 1: (Rm<<16)[31:16]:Rn[15:0] + + *(dst_p++) = d_q0_i0; // 3 + *(dst_p++) = d_q1_i1; + + i1_i0 = i5_i4; + q1_q0 = q5_q4; + } + _i1_i0 = i1_i0; + _q1_q0 = q1_q0; + + return { dst.p, src.count / 2, src.sampling_rate / 2 }; +} + buffer_c16_t TranslateByFSOver4AndDecimateBy2CIC3::execute(buffer_c8_t src, buffer_c16_t dst) { /* Translates incoming complex samples by -fs/4, * decimates by two using a non-recursive third-order CIC filter. diff --git a/firmware/baseband/dsp_decimate.hpp b/firmware/baseband/dsp_decimate.hpp index 9cc90b88c..f57c5e2fe 100644 --- a/firmware/baseband/dsp_decimate.hpp +++ b/firmware/baseband/dsp_decimate.hpp @@ -34,6 +34,18 @@ namespace dsp { namespace decimate { +class Complex8DecimateBy2CIC3 { +public: + buffer_c16_t execute( + buffer_c8_t src, + buffer_c16_t dst + ); + +private: + uint32_t _i1_i0 { 0 }; + uint32_t _q1_q0 { 0 }; +}; + class TranslateByFSOver4AndDecimateBy2CIC3 { public: buffer_c16_t execute( From 060da5d22762f7ab28023c49ae6caab82a93d834 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 19 Nov 2015 12:24:20 -0800 Subject: [PATCH 005/452] Add ChannelDecimator decimate by 2 and no-shift options. --- firmware/baseband/channel_decimator.cpp | 23 +++++++++++++++-------- firmware/baseband/channel_decimator.hpp | 20 ++++++++++++++------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/firmware/baseband/channel_decimator.cpp b/firmware/baseband/channel_decimator.cpp index a7e7edf73..80bd136b9 100644 --- a/firmware/baseband/channel_decimator.cpp +++ b/firmware/baseband/channel_decimator.cpp @@ -39,14 +39,10 @@ buffer_c16_t ChannelDecimator::execute_decimation(buffer_c8_t buffer) { * -> gain of 256 * -> decimation by 2 * -> 1.544MHz complex[1024], [-32768, 32512] */ - const auto stage_0_out = translate.execute(buffer, work_baseband_buffer); - - //if( fs_over_4_downconvert ) { - // // TODO: - //} else { - // Won't work until cic_0 will accept input type of buffer_c8_t. - // stage_0_out = cic_0.execute(buffer, work_baseband_buffer); - //} + auto stage_0_out = execute_stage_0(buffer, work_baseband_buffer); + if( decimation_factor == DecimationFactor::By2 ) { + return stage_0_out; + } /* 1.536MHz complex[1024], [-32768, 32512] * -> 3rd order CIC: -0.1dB @ 0.028fs, -1dB @ 0.088fs, -60dB @ 0.468fs @@ -82,3 +78,14 @@ buffer_c16_t ChannelDecimator::execute_decimation(buffer_c8_t buffer) { return cic_4_out; } + +buffer_c16_t ChannelDecimator::execute_stage_0( + buffer_c8_t buffer, + buffer_c16_t work_baseband_buffer +) { + if( fs_over_4_downconvert ) { + return translate.execute(buffer, work_baseband_buffer); + } else { + return cic_0.execute(buffer, work_baseband_buffer); + } +} diff --git a/firmware/baseband/channel_decimator.hpp b/firmware/baseband/channel_decimator.hpp index 3e20c0df9..10a650332 100644 --- a/firmware/baseband/channel_decimator.hpp +++ b/firmware/baseband/channel_decimator.hpp @@ -32,6 +32,7 @@ class ChannelDecimator { public: enum class DecimationFactor { + By2, By4, By8, By16, @@ -39,13 +40,16 @@ public: }; constexpr ChannelDecimator( - ) : decimation_factor { DecimationFactor::By32 } + ) : decimation_factor { DecimationFactor::By32 }, + fs_over_4_downconvert { true } { } constexpr ChannelDecimator( - const DecimationFactor decimation_factor - ) : decimation_factor { decimation_factor } + const DecimationFactor decimation_factor, + const bool fs_over_4_downconvert = true + ) : decimation_factor { decimation_factor }, + fs_over_4_downconvert { fs_over_4_downconvert } { } @@ -62,18 +66,22 @@ public: private: std::array work_baseband; - //const bool fs_over_4_downconvert = true; - dsp::decimate::TranslateByFSOver4AndDecimateBy2CIC3 translate; - //dsp::decimate::DecimateBy2CIC3 cic_0; + dsp::decimate::Complex8DecimateBy2CIC3 cic_0; dsp::decimate::DecimateBy2CIC3 cic_1; dsp::decimate::DecimateBy2CIC3 cic_2; dsp::decimate::DecimateBy2CIC3 cic_3; dsp::decimate::DecimateBy2CIC3 cic_4; DecimationFactor decimation_factor; + const bool fs_over_4_downconvert; buffer_c16_t execute_decimation(buffer_c8_t buffer); + + buffer_c16_t execute_stage_0( + buffer_c8_t buffer, + buffer_c16_t work_baseband_buffer + ); }; #endif/*__CHANNEL_DECIMATOR_H__*/ From 85e984ed3b672bdee15e82284d637fdf2c326528 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 19 Nov 2015 12:31:21 -0800 Subject: [PATCH 006/452] Clean up complex -> complex casting. --- firmware/baseband/proc_wideband_spectrum.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/baseband/proc_wideband_spectrum.cpp b/firmware/baseband/proc_wideband_spectrum.cpp index 17f475517..32ae65b97 100644 --- a/firmware/baseband/proc_wideband_spectrum.cpp +++ b/firmware/baseband/proc_wideband_spectrum.cpp @@ -47,7 +47,7 @@ void WidebandSpectrum::execute(buffer_c8_t buffer) { // TODO: Removed window-presum windowing, due to lack of available code RAM. // TODO: Apply window to improve spectrum bin sidelobes. for(size_t i=0; i { buffer.p[i].real(), buffer.p[i].imag() }; + spectrum[i] += buffer.p[i]; } } From 600a983d5c4dbb4d7b9fa9290c20e73e8bb87095 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 20 Nov 2015 11:01:41 -0800 Subject: [PATCH 007/452] Clean up complex -> complex casting. --- firmware/baseband/proc_ais.cpp | 7 +------ firmware/baseband/proc_tpms.cpp | 7 +------ firmware/common/complex.hpp | 7 +++++++ 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index e3005b93f..72bc5a160 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -42,12 +42,7 @@ void AISProcessor::execute(buffer_c8_t buffer) { */ for(size_t i=0; ifloat is not allowed. - const std::complex sample { - static_cast(decimator_out.p[i].real()), - static_cast(decimator_out.p[i].imag()) - }; - if( mf.execute_once(sample) ) { + if( mf.execute_once(decimator_out.p[i]) ) { clock_recovery(mf.get_output()); } } diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index edabf4681..90f441e99 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -42,12 +42,7 @@ void TPMSProcessor::execute(buffer_c8_t buffer) { */ for(size_t i=0; ifloat is not allowed. - const std::complex sample { - static_cast(decimator_out.p[i].real()), - static_cast(decimator_out.p[i].imag()) - }; - if( mf.execute_once(sample) ) { + if( mf.execute_once(decimator_out.p[i]) ) { clock_recovery(mf.get_output()); } } diff --git a/firmware/common/complex.hpp b/firmware/common/complex.hpp index d9ceb1395..b2cfc1dec 100644 --- a/firmware/common/complex.hpp +++ b/firmware/common/complex.hpp @@ -105,6 +105,13 @@ public: return _rep; } + constexpr operator std::complex() const { + return { + static_cast(_v[0]), + static_cast(_v[1]) + }; + } + private: union { int16_t _v[2]; From d96379dc9c0e25f30cccbd495b4a7ac4292b6a6a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 20 Nov 2015 11:11:14 -0800 Subject: [PATCH 008/452] Remove extra semicolons. --- firmware/common/buffer.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/common/buffer.hpp b/firmware/common/buffer.hpp index cfde42c3a..9df2d9eee 100644 --- a/firmware/common/buffer.hpp +++ b/firmware/common/buffer.hpp @@ -38,7 +38,7 @@ struct buffer_t { count { count }, sampling_rate { 0 } { - }; + } constexpr buffer_t( T* const p, @@ -48,7 +48,7 @@ struct buffer_t { count { count }, sampling_rate { sampling_rate } { - }; + } }; #endif/*__BUFFER_H__*/ From 435824e9b5b2441d3cb575eef3c15446d3064898 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 20 Nov 2015 11:21:31 -0800 Subject: [PATCH 009/452] Clean up buffer_t constructors. --- firmware/baseband/baseband_dma.cpp | 4 ++-- firmware/common/buffer.hpp | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/firmware/baseband/baseband_dma.cpp b/firmware/baseband/baseband_dma.cpp index 88bc443e4..520365d12 100644 --- a/firmware/baseband/baseband_dma.cpp +++ b/firmware/baseband/baseband_dma.cpp @@ -169,10 +169,10 @@ baseband::buffer_t wait_for_rx_buffer() { const size_t free_index = (next_index + transfers_per_buffer - 2) & transfers_mask; return { reinterpret_cast(lli_loop[free_index].destaddr), transfer_samples }; } else { - return { nullptr, 0 }; + return { }; } } else { - return { nullptr, 0 }; + return { }; } } diff --git a/firmware/common/buffer.hpp b/firmware/common/buffer.hpp index 9df2d9eee..be1846dd8 100644 --- a/firmware/common/buffer.hpp +++ b/firmware/common/buffer.hpp @@ -32,18 +32,24 @@ struct buffer_t { const uint32_t sampling_rate; constexpr buffer_t( - T* const p, - const size_t count - ) : p { p }, - count { count }, + ) : p { nullptr }, + count { 0 }, sampling_rate { 0 } { } + constexpr buffer_t( + const buffer_t& other + ) : p { other.p }, + count { other.count }, + sampling_rate { other.sampling_rate } + { + } + constexpr buffer_t( T* const p, const size_t count, - const uint32_t sampling_rate + const uint32_t sampling_rate = 0 ) : p { p }, count { count }, sampling_rate { sampling_rate } From 5928086fd9e2687de42ffcbd48eb5ab9dccf9638 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 29 Nov 2015 15:37:24 -0800 Subject: [PATCH 010/452] Simplify SD card mount status code. --- firmware/application/main.cpp | 20 ++++++++++---------- firmware/common/message.hpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index ff7e92e97..ce9a7a2fd 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -128,31 +128,31 @@ private: } } - void handle_rtc_tick() { + void update_sd_card_status() { const auto sd_card_present_now = sdc_lld_is_card_inserted(&SDCD1); if( sd_card_present_now != sd_card_present ) { sd_card_present = sd_card_present_now; + SDCardStatusMessage message { false }; + if( sd_card_present ) { if( sdcConnect(&SDCD1) == CH_SUCCESS ) { if( sd_card::filesystem::mount() == FR_OK ) { - SDCardStatusMessage message { true }; - context.message_map().send(&message); - } else { - // TODO: Error, modal warning? + message.is_mounted = true; } - } else { - // TODO: Error, modal warning? } } else { sdcDisconnect(&SDCD1); - - SDCardStatusMessage message { false }; - context.message_map().send(&message); } + + context.message_map().send(&message); } } + void handle_rtc_tick() { + update_sd_card_status(); + } + static ui::Widget* touch_widget(ui::Widget* const w, ui::TouchEvent event) { if( !w->hidden() ) { // To achieve reverse depth ordering (last object drawn is diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index fccb2cdc8..393d3b3d5 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -250,7 +250,7 @@ public: { } - const bool is_mounted; + bool is_mounted; }; class MessageHandlerMap { From 42104d217a71d337918bcb64996de3937c7c5b55 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 29 Nov 2015 15:50:58 -0800 Subject: [PATCH 011/452] Broaden SD card status detail in message. --- firmware/application/main.cpp | 8 ++++++-- firmware/application/ui_receiver.cpp | 6 +++--- firmware/application/ui_receiver.hpp | 2 +- firmware/common/message.hpp | 15 ++++++++++++--- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index ce9a7a2fd..fe90b74d3 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -133,13 +133,17 @@ private: if( sd_card_present_now != sd_card_present ) { sd_card_present = sd_card_present_now; - SDCardStatusMessage message { false }; + SDCardStatusMessage message { sd_card_present ? SDCardStatusMessage::State::Present : SDCardStatusMessage::State::NotPresent }; if( sd_card_present ) { if( sdcConnect(&SDCD1) == CH_SUCCESS ) { if( sd_card::filesystem::mount() == FR_OK ) { - message.is_mounted = true; + message.state = SDCardStatusMessage::State::Mounted; + } else { + message.state = SDCardStatusMessage::State::MountError; } + } else { + message.state = SDCardStatusMessage::State::ConnectError; } } else { sdcDisconnect(&SDCD1); diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index a4d85698b..0ff91febb 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -514,7 +514,7 @@ void ReceiverView::on_show() { message_map.register_handler(Message::ID::SDCardStatus, [this](Message* const p) { const auto message = static_cast(p); - this->on_sd_card_mounted(message->is_mounted); + this->on_sd_card_status(*message); } ); } @@ -585,8 +585,8 @@ void ReceiverView::on_packet_tpms(const TPMSPacketMessage& message) { } } -void ReceiverView::on_sd_card_mounted(const bool is_mounted) { - if( is_mounted ) { +void ReceiverView::on_sd_card_status(const SDCardStatusMessage& message) { + if( message.state == SDCardStatusMessage::State::Mounted ) { const auto open_result = f_open(&fil_tpms, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); if( open_result == FR_OK ) { const auto fil_size = f_size(&fil_tpms); diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 50353b9d6..6b2bda88e 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -475,7 +475,7 @@ private: void on_packet_ais(const AISPacketMessage& message); void on_packet_tpms(const TPMSPacketMessage& message); - void on_sd_card_mounted(const bool is_mounted); + void on_sd_card_status(const SDCardStatusMessage& message); }; } /* namespace ui */ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 393d3b3d5..9ad41875e 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -243,14 +243,23 @@ public: class SDCardStatusMessage : public Message { public: + enum class State : int32_t { + IOError = -3, + MountError = -2, + ConnectError = -1, + NotPresent = 0, + Present = 1, + Mounted = 2, + }; + constexpr SDCardStatusMessage( - bool is_mounted + State state ) : Message { ID::SDCardStatus }, - is_mounted { is_mounted } + state { state } { } - bool is_mounted; + State state; }; class MessageHandlerMap { From 600295f0db144a4c1b640ca761359902f30eea44 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 10:27:46 -0800 Subject: [PATCH 012/452] Add Signal for callbacks within a process (code executing on one core). --- firmware/application/signal.hpp | 85 +++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 firmware/application/signal.hpp diff --git a/firmware/application/signal.hpp b/firmware/application/signal.hpp new file mode 100644 index 000000000..09baf777f --- /dev/null +++ b/firmware/application/signal.hpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __SIGNAL_H__ +#define __SIGNAL_H__ + +#include +#include +#include +#include + +#include "utility.hpp" + +/* Tweaked and vastly simplified implementation of Simple::Signal, from + * https://testbit.eu/cpp11-signal-system-performance/ + * + * Original license: + * CC0 Public Domain + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +using SignalToken = uint32_t; + +template +struct Signal { + using Callback = std::function; + + SignalToken operator+=(const Callback& callback) { + const SignalToken token = next_token++; + entries.emplace_back(std::make_unique(callback, token)); + return token; + } + + bool operator-=(const SignalToken token) { + entries.remove_if([token](EntryType& entry) { + return entry.get()->token == token; + }); + return true; + } + + void emit(Args... args) { + for(auto& entry : entries) { + entry.get()->callback(args...); + }; + } + +private: + struct CallbackEntry { + const Callback callback; + const SignalToken token; + + constexpr CallbackEntry( + const Callback& callback, + const SignalToken token + ) : callback { callback }, + token { token } + { + } + }; + + using EntryType = std::unique_ptr; + + std::list entries; + SignalToken next_token = 1; +}; + +#endif/*__SIGNAL_H__*/ From c70d95dcbea3c443befa38f4bf9f50f7b4ac00c9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 10:38:35 -0800 Subject: [PATCH 013/452] Remove SDCardStatusMessage, replace with Signal, extract to separate files. --- firmware/application/Makefile | 1 + firmware/application/main.cpp | 27 +--------- firmware/application/sd_card.cpp | 73 ++++++++++++++++++++++++++++ firmware/application/sd_card.hpp | 27 +++++----- firmware/application/ui_receiver.cpp | 23 +++++---- firmware/application/ui_receiver.hpp | 4 +- firmware/common/message.hpp | 22 --------- 7 files changed, 105 insertions(+), 72 deletions(-) create mode 100644 firmware/application/sd_card.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index c2b9237e5..f02db587b 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -168,6 +168,7 @@ CPPSRC = main.cpp \ receiver_model.cpp \ spectrum_color_lut.cpp \ ais_baseband.cpp \ + sd_card.cpp \ ../common/utility.cpp \ ../common/chibios_cpp.cpp \ ../common/debug.cpp \ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index fe90b74d3..25102c4dc 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -128,33 +128,8 @@ private: } } - void update_sd_card_status() { - const auto sd_card_present_now = sdc_lld_is_card_inserted(&SDCD1); - if( sd_card_present_now != sd_card_present ) { - sd_card_present = sd_card_present_now; - - SDCardStatusMessage message { sd_card_present ? SDCardStatusMessage::State::Present : SDCardStatusMessage::State::NotPresent }; - - if( sd_card_present ) { - if( sdcConnect(&SDCD1) == CH_SUCCESS ) { - if( sd_card::filesystem::mount() == FR_OK ) { - message.state = SDCardStatusMessage::State::Mounted; - } else { - message.state = SDCardStatusMessage::State::MountError; - } - } else { - message.state = SDCardStatusMessage::State::ConnectError; - } - } else { - sdcDisconnect(&SDCD1); - } - - context.message_map().send(&message); - } - } - void handle_rtc_tick() { - update_sd_card_status(); + sd_card::poll_inserted(); } static ui::Widget* touch_widget(ui::Widget* const w, ui::TouchEvent event) { diff --git a/firmware/application/sd_card.cpp b/firmware/application/sd_card.cpp new file mode 100644 index 000000000..4e9989ab5 --- /dev/null +++ b/firmware/application/sd_card.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "sd_card.hpp" + +#include + +#include "ff.h" + +namespace sd_card { + +namespace { + +bool card_present = false; + +FATFS fs; + +FRESULT mount() { + return f_mount(&fs, "", 0); +} + +FRESULT unmount() { + return f_mount(NULL, "", 0); +} + +} /* namespace */ + +Signal status_signal; + +void poll_inserted() { + const auto card_present_now = sdc_lld_is_card_inserted(&SDCD1); + if( card_present_now != card_present ) { + card_present = card_present_now; + + Status status { card_present ? Status::Present : Status::NotPresent }; + + if( card_present ) { + if( sdcConnect(&SDCD1) == CH_SUCCESS ) { + if( mount() == FR_OK ) { + status = Status::Mounted; + } else { + status = Status::MountError; + } + } else { + status = Status::ConnectError; + } + } else { + sdcDisconnect(&SDCD1); + } + + status_signal.emit(status); + } +} + +} /* namespace sd_card */ diff --git a/firmware/application/sd_card.hpp b/firmware/application/sd_card.hpp index d7827b90e..fef7849aa 100644 --- a/firmware/application/sd_card.hpp +++ b/firmware/application/sd_card.hpp @@ -22,26 +22,25 @@ #ifndef __SD_CARD_H__ #define __SD_CARD_H__ -#include "ff.h" +#include + +#include "signal.hpp" namespace sd_card { -namespace filesystem { -namespace { +enum class Status : int32_t { + IOError = -3, + MountError = -2, + ConnectError = -1, + NotPresent = 0, + Present = 1, + Mounted = 2, +}; -FATFS fs; +extern Signal status_signal; -} +void poll_inserted(); -FRESULT mount() { - return f_mount(&fs, "", 0); -} - -FRESULT unmount() { - return f_mount(NULL, "", 0); -} - -} /* namespace filesystem */ } /* namespace sd_card */ #endif/*__SD_CARD_H__*/ diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 0ff91febb..35815e56f 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -29,6 +29,7 @@ using namespace portapack; #include "ais_baseband.hpp" +#include "sd_card.hpp" #include "ff.h" namespace ui { @@ -511,17 +512,16 @@ void ReceiverView::on_show() { this->on_packet_tpms(*message); } ); - message_map.register_handler(Message::ID::SDCardStatus, - [this](Message* const p) { - const auto message = static_cast(p); - this->on_sd_card_status(*message); - } - ); + + sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { + this->on_sd_card_status(status); + }; } void ReceiverView::on_hide() { + sd_card::status_signal -= sd_card_status_signal_token; + auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::SDCardStatus); message_map.unregister_handler(Message::ID::TPMSPacket); message_map.unregister_handler(Message::ID::AISPacket); } @@ -585,18 +585,23 @@ void ReceiverView::on_packet_tpms(const TPMSPacketMessage& message) { } } -void ReceiverView::on_sd_card_status(const SDCardStatusMessage& message) { - if( message.state == SDCardStatusMessage::State::Mounted ) { +void ReceiverView::on_sd_card_status(const sd_card::Status status) { + if( status == sd_card::Status::Mounted ) { const auto open_result = f_open(&fil_tpms, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); if( open_result == FR_OK ) { const auto fil_size = f_size(&fil_tpms); const auto seek_result = f_lseek(&fil_tpms, fil_size); if( seek_result != FR_OK ) { f_close(&fil_tpms); + // TODO: Error, indicate somehow. + } else { + // TODO: Indicate success. } } else { // TODO: Error, indicate somehow. } + } else { + // TODO: Indicate unmounted. } } diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 6b2bda88e..8ff647e3a 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -475,7 +475,9 @@ private: void on_packet_ais(const AISPacketMessage& message); void on_packet_tpms(const TPMSPacketMessage& message); - void on_sd_card_status(const SDCardStatusMessage& message); + void on_sd_card_status(const sd_card::Status status); + + SignalToken sd_card_status_signal_token; }; } /* namespace ui */ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 9ad41875e..9a2901440 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -46,7 +46,6 @@ public: TPMSPacket = 6, Shutdown = 8, AISPacket = 7, - SDCardStatus = 10, MAX }; @@ -241,27 +240,6 @@ public: } }; -class SDCardStatusMessage : public Message { -public: - enum class State : int32_t { - IOError = -3, - MountError = -2, - ConnectError = -1, - NotPresent = 0, - Present = 1, - Mounted = 2, - }; - - constexpr SDCardStatusMessage( - State state - ) : Message { ID::SDCardStatus }, - state { state } - { - } - - State state; -}; - class MessageHandlerMap { public: using MessageHandler = std::function; From 0c36a74351df9145ca96729d843d70d96e40cd13 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 10:45:34 -0800 Subject: [PATCH 014/452] Add SD card status view to receiver UI. --- firmware/application/Makefile | 1 + firmware/application/ui_navigation.cpp | 2 + firmware/application/ui_navigation.hpp | 3 + .../application/ui_sd_card_status_view.cpp | 85 +++++++++++++++++++ .../application/ui_sd_card_status_view.hpp | 50 +++++++++++ 5 files changed, 141 insertions(+) create mode 100644 firmware/application/ui_sd_card_status_view.cpp create mode 100644 firmware/application/ui_sd_card_status_view.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index f02db587b..94687405f 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -162,6 +162,7 @@ CPPSRC = main.cpp \ ui_setup.cpp \ ui_debug.cpp \ ui_baseband_stats_view.cpp \ + ui_sd_card_status_view.cpp \ ui_console.cpp \ ui_receiver.cpp \ ui_spectrum.cpp \ diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 5b3bdb8cb..f603c3cc0 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -37,7 +37,9 @@ namespace ui { SystemStatusView::SystemStatusView() { add_children({ { &portapack, + &sd_card_status_view, } }); + sd_card_status_view.set_parent_rect({ 28 * 8, 0 * 16, 2 * 8, 1 * 16 }); } /* Navigation ************************************************************/ diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index fae713e57..7307aed92 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -30,6 +30,7 @@ #include "ui_rssi.hpp" #include "ui_channel.hpp" #include "ui_audio.hpp" +#include "ui_sd_card_status_view.hpp" #include @@ -44,6 +45,8 @@ private: { 0, 0, 9 * 8, 1 * 16 }, "PortaPack", }; + + SDCardStatusView sd_card_status_view; }; class NavigationView : public View { diff --git a/firmware/application/ui_sd_card_status_view.cpp b/firmware/application/ui_sd_card_status_view.cpp new file mode 100644 index 000000000..1c7698539 --- /dev/null +++ b/firmware/application/ui_sd_card_status_view.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "ui_sd_card_status_view.hpp" + +#include +#include + +namespace ui { + +/* SDCardStatusView *****************************************************/ + +SDCardStatusView::SDCardStatusView() { + add_children({ { + &text_status, + } }); + + text_status.set("XX"); +} + +void SDCardStatusView::on_show() { + sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { + this->on_status(status); + }; +} + +void SDCardStatusView::on_hide() { + sd_card::status_signal -= sd_card_status_signal_token; +} + +void SDCardStatusView::on_status(const sd_card::Status status) { + std::string msg("??"); + + switch(status) { + case sd_card::Status::IOError: + msg = "IO"; + break; + + case sd_card::Status::MountError: + msg = "MT"; + break; + + case sd_card::Status::ConnectError: + msg = "CN"; + break; + + case sd_card::Status::NotPresent: + msg = "XX"; + break; + + case sd_card::Status::Present: + msg = "OO"; + break; + + case sd_card::Status::Mounted: + msg = "OK"; + break; + + default: + msg = "--"; + break; + } + + text_status.set(msg); +} + +} /* namespace ui */ diff --git a/firmware/application/ui_sd_card_status_view.hpp b/firmware/application/ui_sd_card_status_view.hpp new file mode 100644 index 000000000..dd542f3c2 --- /dev/null +++ b/firmware/application/ui_sd_card_status_view.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __UI_SD_CARD_STATUS_VIEW_H__ +#define __UI_SD_CARD_STATUS_VIEW_H__ + +#include "ui_widget.hpp" +#include "sd_card.hpp" + +namespace ui { + +class SDCardStatusView : public View { +public: + SDCardStatusView(); + + void on_show() override; + void on_hide() override; + +private: + Text text_status { + { 0 * 8, 0, 2 * 8, 1 * 16 }, + "", + }; + + SignalToken sd_card_status_signal_token; + + void on_status(const sd_card::Status status); +}; + +} /* namespace ui */ + +#endif/*__UI_SD_CARD_STATUS_VIEW_H__*/ From 82ff45860e136fcfc8270585a0eabd3dddfb1fa2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 11:24:48 -0800 Subject: [PATCH 015/452] Add basic ERT (OOK) utility meter reception. Extracted the Manchester formatting function for use in ERT, now also returns an indication of bits in error. --- firmware/application/receiver_model.cpp | 3 +- firmware/application/ui_receiver.cpp | 84 +++++++++++++++-- firmware/application/ui_receiver.hpp | 2 + firmware/baseband/Makefile | 1 + firmware/baseband/main.cpp | 5 + firmware/baseband/proc_ert.cpp | 117 ++++++++++++++++++++++++ firmware/baseband/proc_ert.hpp | 108 ++++++++++++++++++++++ firmware/common/message.hpp | 17 ++++ 8 files changed, 329 insertions(+), 8 deletions(-) create mode 100644 firmware/baseband/proc_ert.cpp create mode 100644 firmware/baseband/proc_ert.hpp diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index e1914ba97..709fbd9b2 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -138,7 +138,8 @@ void ReceiverModel::disable() { } int32_t ReceiverModel::tuning_offset() { - if( baseband_configuration.mode == 4 ) { + if( (baseband_configuration.mode == 4) || + (baseband_configuration.mode == 6) ) { return 0; } else { return -(sampling_rate() / 4); diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 35815e56f..b1a453566 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -512,6 +512,12 @@ void ReceiverView::on_show() { this->on_packet_tpms(*message); } ); + message_map.register_handler(Message::ID::ERTPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->on_packet_ert(*message); + } + ); sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { this->on_sd_card_status(status); @@ -522,6 +528,7 @@ void ReceiverView::on_hide() { sd_card::status_signal -= sd_card_status_signal_token; auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::ERTPacket); message_map.unregister_handler(Message::ID::TPMSPacket); message_map.unregister_handler(Message::ID::AISPacket); } @@ -537,16 +544,21 @@ void ReceiverView::on_packet_ais(const AISPacketMessage& message) { static FIL fil_tpms; -void ReceiverView::on_packet_tpms(const TPMSPacketMessage& message) { - auto payload = message.packet.payload; - auto payload_length = message.packet.bits_received; +static std::pair format_manchester( + const uint_fast8_t sense, + const std::bitset<1024>& payload, + const size_t payload_length +) { + const size_t payload_length_decoded = payload_length / 2; + const size_t payload_length_bytes = (payload_length_decoded + 7) / 8; + const size_t payload_length_symbols_rounded = payload_length_bytes * 8 * 2; std::string hex_data; std::string hex_error; uint8_t byte_data = 0; uint8_t byte_error = 0; - for(size_t i=0; i(widget_content.get()); - console->writeln(hex_data.substr(0, 240 / 8)); + console->writeln(hex_formatted.first.substr(0, 240 / 8)); if( !f_error(&fil_tpms) ) { rtc::RTC datetime; @@ -579,12 +600,51 @@ void ReceiverView::on_packet_tpms(const TPMSPacketMessage& message) { // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); - std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_data + "/" + hex_error + "\r\n"; + std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.first + "/" + hex_formatted.second + "\r\n"; f_puts(log.c_str(), &fil_tpms); f_sync(&fil_tpms); } } +static std::bitset<512> manchester_decode( + const size_t sense, + const std::bitset<1024>& encoded, + const size_t count +) { + std::bitset<512> result; + for(size_t i=0; i> 1] = encoded[i+sense]; + } + return result; +} + +static std::bitset<512> manchester_errors( + const std::bitset<1024>& encoded, + const size_t count +) { + std::bitset<512> result; + for(size_t i=0; i> 1] = (encoded[i+0] == encoded[i+1]); + } + return result; +} + +void ReceiverView::on_packet_ert(const ERTPacketMessage& message) { + auto console = reinterpret_cast(widget_content.get()); + + if( message.packet.preamble == 0x555516a3 ) { + console->writeln("IDM"); + } + if( message.packet.preamble == 0x1f2a60 ) { + console->writeln("SCM"); + const auto decoded = manchester_decode(0, message.packet.payload, message.packet.bits_received); + } + + const auto hex_formatted = format_manchester(0, message.packet.payload, message.packet.bits_received); + console->writeln(hex_formatted.first); + console->writeln(hex_formatted.second); +} + void ReceiverView::on_sd_card_status(const sd_card::Status status) { if( status == sd_card::Status::Mounted ) { const auto open_result = f_open(&fil_tpms, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); @@ -642,6 +702,15 @@ void ReceiverView::on_modulation_changed(int32_t modulation) { receiver_model.set_baseband_bandwidth(1750000); break; + case 6: + receiver_model.set_baseband_configuration({ + .mode = modulation, + .sampling_rate = 4194304, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); + break; + case 4: receiver_model.set_baseband_configuration({ .mode = modulation, @@ -667,6 +736,7 @@ void ReceiverView::on_modulation_changed(int32_t modulation) { switch(modulation) { case 3: case 5: + case 6: widget_content = std::make_unique(); add_child(widget_content.get()); break; diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 8ff647e3a..65e97f041 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -417,6 +417,7 @@ private: { "WFM ", 2 }, { "AIS ", 3 }, { "TPMS", 5 }, + { "ERT", 6 }, { "SPEC", 4 }, } }; @@ -475,6 +476,7 @@ private: void on_packet_ais(const AISPacketMessage& message); void on_packet_tpms(const TPMSPacketMessage& message); + void on_packet_ert(const ERTPacketMessage& message); void on_sd_card_status(const sd_card::Status status); SignalToken sd_card_status_signal_token; diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index ffb20d12a..8e930720b 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -140,6 +140,7 @@ CPPSRC = main.cpp \ proc_ais.cpp \ proc_wideband_spectrum.cpp \ proc_tpms.cpp \ + proc_ert.cpp \ dsp_squelch.cpp \ clock_recovery.cpp \ packet_builder.cpp \ diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 2a957ff64..70a9d43eb 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -58,6 +58,7 @@ #include "proc_ais.hpp" #include "proc_wideband_spectrum.hpp" #include "proc_tpms.hpp" +#include "proc_ert.hpp" #include "clock_recovery.hpp" #include "packet_builder.hpp" @@ -370,6 +371,10 @@ int main(void) { baseband_thread.baseband_processor = new TPMSProcessor(); break; + case 6: + baseband_thread.baseband_processor = new ERTProcessor(); + break; + default: break; } diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp new file mode 100644 index 000000000..f27396c2e --- /dev/null +++ b/firmware/baseband/proc_ert.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "proc_ert.hpp" + +#include "portapack_shared_memory.hpp" + +#include "i2s.hpp" +using namespace lpc43xx; + +float ERTProcessor::abs(const complex8_t& v) { + // const int16_t r = v.real() - offset_i; + // const int16_t i = v.imag() - offset_q; + // const uint32_t r2 = r * r; + // const uint32_t i2 = i * i; + // const uint32_t r2_i2 = r2 + i2; + // return std::sqrt(static_cast(r2_i2)); + const float r = static_cast(v.real()) - offset_i; + const float i = static_cast(v.imag()) - offset_q; + const float r2 = r * r; + const float i2 = i * i; + const float r2_i2 = r2 + i2; + return std::sqrt(r2_i2); +} + +void ERTProcessor::execute(buffer_c8_t buffer) { + /* 4.194304MHz, 2048 samples */ + // auto decimator_out = decimator.execute(buffer); + + const complex8_t* src = &buffer.p[0]; + const complex8_t* const src_end = &buffer.p[buffer.count]; + + average_i += src->real(); + average_q += src->imag(); + average_count++; + if( average_count == 2048 ) { + offset_i = static_cast(average_i) / 2048.0f; + offset_q = static_cast(average_q) / 2048.0f; + average_i = 0; + average_q = 0; + average_count = 0; + } + + const float gain = 128 * samples_per_symbol; + const float k = 1.0f / gain; + + while(src < src_end) { + float sum = 0.0f; + for(size_t i=0; i<(samples_per_symbol / 2); i++) { + sum += abs(*(src++)); + } + sum_half_period[1] = sum_half_period[0]; + sum_half_period[0] = sum; + + sum_period[2] = sum_period[1]; + sum_period[1] = sum_period[0]; + sum_period[0] = (sum_half_period[0] + sum_half_period[1]) * k; + + manchester[2] = manchester[1]; + manchester[1] = manchester[0]; + manchester[0] = sum_period[2] - sum_period[0]; + + const auto data = manchester[0] - manchester[2]; + + clock_recovery(data); + } + + i2s::i2s0::tx_mute(); +} + +void ERTProcessor::consume_symbol( + const float raw_symbol +) { + const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0; + scm_builder.execute(sliced_symbol); + idm_builder.execute(sliced_symbol); +} + +void ERTProcessor::scm_handler( + const std::bitset<1024>& payload, + const size_t bits_received +) { + ERTPacketMessage message; + message.packet.preamble = 0x1f2a60; + message.packet.payload = payload; + message.packet.bits_received = bits_received; + shared_memory.application_queue.push(message); +} + +void ERTProcessor::idm_handler( + const std::bitset<1024>& payload, + const size_t bits_received +) { + ERTPacketMessage message; + message.packet.preamble = 0x555516a3; + message.packet.payload = payload; + message.packet.bits_received = bits_received; + shared_memory.application_queue.push(message); +} diff --git a/firmware/baseband/proc_ert.hpp b/firmware/baseband/proc_ert.hpp new file mode 100644 index 000000000..bc5fcc93b --- /dev/null +++ b/firmware/baseband/proc_ert.hpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PROC_ERT_H__ +#define __PROC_ERT_H__ + +#include "baseband_processor.hpp" + +#include "channel_decimator.hpp" + +#include "clock_recovery.hpp" +#include "symbol_coding.hpp" +#include "packet_builder.hpp" + +#include "message.hpp" + +#include +#include +#include + +// ''.join(['%d%d' % (c, 1-c) for c in map(int, bin(0x1f2a60)[2:].zfill(21))]) +constexpr uint64_t scm_preamble_and_sync_manchester { 0b101010101001011001100110010110100101010101 }; +constexpr size_t scm_preamble_and_sync_length { 42 - 10 }; +constexpr size_t scm_payload_length_max { 150 }; + +// ''.join(['%d%d' % (c, 1-c) for c in map(int, bin(0x555516a3)[2:].zfill(32))]) +constexpr uint64_t idm_preamble_and_sync_manchester { 0b0110011001100110011001100110011001010110011010011001100101011010 }; +constexpr size_t idm_preamble_and_sync_length { 64 - 16 }; + +// TODO: Should be 1408, but need to widen pathway to application processor... +constexpr size_t idm_payload_length_max { 960 }; + +class ERTProcessor : public BasebandProcessor { +public: + using payload_t = std::bitset<1024>; + + void execute(buffer_c8_t buffer) override; + +private: + const uint32_t baseband_sampling_rate = 4194304; + const size_t decimation = 1; + const uint32_t symbol_rate = 32768; + + const uint32_t channel_sampling_rate = baseband_sampling_rate / decimation; + const size_t samples_per_symbol = channel_sampling_rate / symbol_rate; + const uint32_t clock_recovery_rate = symbol_rate * 2; + + // ChannelDecimator decimator { ChannelDecimator::DecimationFactor::By2, false }; + + clock_recovery::ClockRecovery clock_recovery { + clock_recovery_rate, symbol_rate, { 1.0f / 18.0f }, + [this](const float symbol) { this->consume_symbol(symbol); } + }; + + PacketBuilder scm_builder { + { scm_preamble_and_sync_manchester, scm_preamble_and_sync_length, 1 }, + { }, + { scm_payload_length_max }, + [this](const payload_t& payload, const size_t bits_received) { + this->scm_handler(payload, bits_received); + } + }; + + PacketBuilder idm_builder { + { idm_preamble_and_sync_manchester, idm_preamble_and_sync_length, 1 }, + { }, + { idm_payload_length_max }, + [this](const payload_t& payload, const size_t bits_received) { + this->idm_handler(payload, bits_received); + } + }; + + void consume_symbol(const float symbol); + void scm_handler(const payload_t& payload, const size_t bits_received); + void idm_handler(const payload_t& payload, const size_t bits_received); + + float sum_half_period[2]; + float sum_period[3]; + float manchester[3]; + + int32_t average_i { 0 }; + int32_t average_q { 0 }; + size_t average_count { 0 }; + float offset_i { 0.0f }; + float offset_q { 0.0f }; + + float abs(const complex8_t& v); +}; + +#endif/*__PROC_ERT_H__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 9a2901440..d5c0101bf 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -46,6 +46,7 @@ public: TPMSPacket = 6, Shutdown = 8, AISPacket = 7, + ERTPacket = 9, MAX }; @@ -240,6 +241,22 @@ public: } }; +struct ERTPacket { + uint64_t preamble { 0 }; + std::bitset<1024> payload; + size_t bits_received { 0 }; +}; + +class ERTPacketMessage : public Message { +public: + constexpr ERTPacketMessage( + ) : Message { ID::ERTPacket } + { + } + + ERTPacket packet; +}; + class MessageHandlerMap { public: using MessageHandler = std::function; From 426295b93e37d8838960eef13652afbffdadafba Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 11:50:29 -0800 Subject: [PATCH 016/452] Remove unnecessary Manchester decode operation. --- firmware/application/ui_receiver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index b1a453566..b82ed1467 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -637,7 +637,6 @@ void ReceiverView::on_packet_ert(const ERTPacketMessage& message) { } if( message.packet.preamble == 0x1f2a60 ) { console->writeln("SCM"); - const auto decoded = manchester_decode(0, message.packet.payload, message.packet.bits_received); } const auto hex_formatted = format_manchester(0, message.packet.payload, message.packet.bits_received); From d75f601b54429413fc89bf9ff8d5ae48eeaccc06 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 12:05:42 -0800 Subject: [PATCH 017/452] Manchester decoder into separate class. Now operates directly on data, doesn't make a new pair of data/error bitsets. --- firmware/application/ui_receiver.cpp | 85 +++++++++++++++------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index b82ed1467..0264952b1 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -544,30 +544,60 @@ void ReceiverView::on_packet_ais(const AISPacketMessage& message) { static FIL fil_tpms; +class ManchesterDecoder { +public: + struct DecodedSymbol { + bool value; + bool error; + }; + + constexpr ManchesterDecoder( + const std::bitset<1024>& encoded, + const size_t count, + const size_t sense = 0 + ) : encoded { encoded }, + count { count }, + sense { sense } + { + } + + DecodedSymbol operator[](const size_t index) const { + const auto value = encoded[index * 2 + sense]; + const auto error = encoded[index * 2 + 0] == encoded[index * 2 + 1]; + return { value, error }; + } + + size_t symbols_count() const { + return count / 2; + } + +private: + const std::bitset<1024>& encoded; + const size_t count; + const size_t sense; +}; + static std::pair format_manchester( - const uint_fast8_t sense, - const std::bitset<1024>& payload, - const size_t payload_length + const ManchesterDecoder& decoder ) { - const size_t payload_length_decoded = payload_length / 2; + const size_t payload_length_decoded = decoder.symbols_count(); const size_t payload_length_bytes = (payload_length_decoded + 7) / 8; - const size_t payload_length_symbols_rounded = payload_length_bytes * 8 * 2; + const size_t payload_length_symbols_rounded = payload_length_bytes * 8; std::string hex_data; std::string hex_error; uint8_t byte_data = 0; uint8_t byte_error = 0; - for(size_t i=0; i> 1) & 7) == 7 ) { + if( (i & 7) == 7 ) { hex_data += to_string_hex(byte_data, 2); hex_error += to_string_hex(byte_error, 2); } @@ -577,10 +607,8 @@ static std::pair format_manchester( } void ReceiverView::on_packet_tpms(const TPMSPacketMessage& message) { - auto payload = message.packet.payload; - auto payload_length = message.packet.bits_received; - - const auto hex_formatted = format_manchester(1, payload, payload_length); + const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); + const auto hex_formatted = format_manchester(decoder); auto console = reinterpret_cast(widget_content.get()); console->writeln(hex_formatted.first.substr(0, 240 / 8)); @@ -606,29 +634,6 @@ void ReceiverView::on_packet_tpms(const TPMSPacketMessage& message) { } } -static std::bitset<512> manchester_decode( - const size_t sense, - const std::bitset<1024>& encoded, - const size_t count -) { - std::bitset<512> result; - for(size_t i=0; i> 1] = encoded[i+sense]; - } - return result; -} - -static std::bitset<512> manchester_errors( - const std::bitset<1024>& encoded, - const size_t count -) { - std::bitset<512> result; - for(size_t i=0; i> 1] = (encoded[i+0] == encoded[i+1]); - } - return result; -} - void ReceiverView::on_packet_ert(const ERTPacketMessage& message) { auto console = reinterpret_cast(widget_content.get()); @@ -639,7 +644,9 @@ void ReceiverView::on_packet_ert(const ERTPacketMessage& message) { console->writeln("SCM"); } - const auto hex_formatted = format_manchester(0, message.packet.payload, message.packet.bits_received); + const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); + + const auto hex_formatted = format_manchester(decoder); console->writeln(hex_formatted.first); console->writeln(hex_formatted.second); } From 810c65dd9c063aaa82a1cd51f59bd91276a8c6c4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 15:31:59 -0800 Subject: [PATCH 018/452] Return Manchester formatted output in struct. --- firmware/application/ui_receiver.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 0264952b1..b4e6cc996 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -577,7 +577,12 @@ private: const size_t sense; }; -static std::pair format_manchester( +struct ManchesterFormatted { + const std::string data; + const std::string errors; +}; + +static ManchesterFormatted format_manchester( const ManchesterDecoder& decoder ) { const size_t payload_length_decoded = decoder.symbols_count(); @@ -611,7 +616,7 @@ void ReceiverView::on_packet_tpms(const TPMSPacketMessage& message) { const auto hex_formatted = format_manchester(decoder); auto console = reinterpret_cast(widget_content.get()); - console->writeln(hex_formatted.first.substr(0, 240 / 8)); + console->writeln(hex_formatted.data.substr(0, 240 / 8)); if( !f_error(&fil_tpms) ) { rtc::RTC datetime; @@ -628,7 +633,7 @@ void ReceiverView::on_packet_tpms(const TPMSPacketMessage& message) { // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); - std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.first + "/" + hex_formatted.second + "\r\n"; + std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; f_puts(log.c_str(), &fil_tpms); f_sync(&fil_tpms); } @@ -647,8 +652,8 @@ void ReceiverView::on_packet_ert(const ERTPacketMessage& message) { const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); const auto hex_formatted = format_manchester(decoder); - console->writeln(hex_formatted.first); - console->writeln(hex_formatted.second); + console->writeln(hex_formatted.data); + console->writeln(hex_formatted.errors); } void ReceiverView::on_sd_card_status(const sd_card::Status status) { From 7b9ba696e56a2437ba3eaee8919fe634e55c4807 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 15:36:09 -0800 Subject: [PATCH 019/452] Reserve strings length before formatting Manchester data. --- firmware/application/ui_receiver.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index b4e6cc996..11199b312 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -587,10 +587,14 @@ static ManchesterFormatted format_manchester( ) { const size_t payload_length_decoded = decoder.symbols_count(); const size_t payload_length_bytes = (payload_length_decoded + 7) / 8; + const size_t payload_length_hex_characters = payload_length_bytes * 2; const size_t payload_length_symbols_rounded = payload_length_bytes * 8; std::string hex_data; std::string hex_error; + hex_data.reserve(payload_length_hex_characters); + hex_error.reserve(payload_length_hex_characters); + uint8_t byte_data = 0; uint8_t byte_error = 0; for(size_t i=0; i Date: Tue, 1 Dec 2015 15:41:51 -0800 Subject: [PATCH 020/452] Type and name clean-up of Manchester formatter. --- firmware/application/ui_receiver.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 11199b312..ef746b3e9 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -594,21 +594,21 @@ static ManchesterFormatted format_manchester( std::string hex_error; hex_data.reserve(payload_length_hex_characters); hex_error.reserve(payload_length_hex_characters); - - uint8_t byte_data = 0; - uint8_t byte_error = 0; + + uint_fast8_t data = 0; + uint_fast8_t error = 0; for(size_t i=0; i Date: Tue, 1 Dec 2015 15:45:59 -0800 Subject: [PATCH 021/452] Clean up handling of bool -> int. C++ standard says false -> 0, true -> 1. --- firmware/application/ui_receiver.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index ef746b3e9..fccae3420 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -547,8 +547,8 @@ static FIL fil_tpms; class ManchesterDecoder { public: struct DecodedSymbol { - bool value; - bool error; + uint_fast8_t value; + uint_fast8_t error; }; constexpr ManchesterDecoder( @@ -601,10 +601,10 @@ static ManchesterFormatted format_manchester( const auto symbol = decoder[i]; data <<= 1; - data |= symbol.value ? 1 : 0; + data |= symbol.value; error <<= 1; - error |= symbol.error ? 1 : 0; + error |= symbol.error; if( (i & 7) == 7 ) { hex_data += to_string_hex(data & 0xff, 2); From 8461b0c94eda1ddf934200465422d00e82b2a69b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 15:50:07 -0800 Subject: [PATCH 022/452] Manchester formatting to next largest length in nibbles. Prior code insisted on next largest byte, for no good reason. --- firmware/application/ui_receiver.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index fccae3420..a135d4240 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -586,9 +586,8 @@ static ManchesterFormatted format_manchester( const ManchesterDecoder& decoder ) { const size_t payload_length_decoded = decoder.symbols_count(); - const size_t payload_length_bytes = (payload_length_decoded + 7) / 8; - const size_t payload_length_hex_characters = payload_length_bytes * 2; - const size_t payload_length_symbols_rounded = payload_length_bytes * 8; + const size_t payload_length_hex_characters = (payload_length_decoded + 3) / 4; + const size_t payload_length_symbols_rounded = payload_length_hex_characters * 4; std::string hex_data; std::string hex_error; @@ -606,9 +605,9 @@ static ManchesterFormatted format_manchester( error <<= 1; error |= symbol.error; - if( (i & 7) == 7 ) { - hex_data += to_string_hex(data & 0xff, 2); - hex_error += to_string_hex(error & 0xff, 2); + if( (i & 3) == 3 ) { + hex_data += to_string_hex(data & 0xf, 1); + hex_error += to_string_hex(error & 0xf, 1); } } From 32319ddf9f778a2a72b66bf093655bb2da24e026 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 16:05:23 -0800 Subject: [PATCH 023/452] Manchester decoder bounds checking. Return error symbol if reading past source data. --- firmware/application/ui_receiver.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index a135d4240..75be6dce1 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -562,9 +562,14 @@ public: } DecodedSymbol operator[](const size_t index) const { - const auto value = encoded[index * 2 + sense]; - const auto error = encoded[index * 2 + 0] == encoded[index * 2 + 1]; - return { value, error }; + const size_t encoded_index = index * 2; + if( (encoded_index + 1) < count ) { + const auto value = encoded[encoded_index + sense]; + const auto error = encoded[encoded_index + 0] == encoded[encoded_index + 1]; + return { value, error }; + } else { + return { 0, 1 }; + } } size_t symbols_count() const { From ec977ccd0526de19e53f401d6be88d06a907952e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 17:28:22 -0800 Subject: [PATCH 024/452] Implement console "\n" -> crlf() behavior. --- firmware/application/ui_console.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/firmware/application/ui_console.cpp b/firmware/application/ui_console.cpp index 0c299acdb..48c0daeb2 100644 --- a/firmware/application/ui_console.cpp +++ b/firmware/application/ui_console.cpp @@ -40,17 +40,21 @@ void Console::write(const std::string message) { const Font& font = s.font; const auto rect = screen_rect(); for(const auto c : message) { - const auto glyph = font.glyph(c); - const auto advance = glyph.advance(); - if( (pos.x + advance.x) > rect.width() ) { + if( c == '\n' ) { crlf(); + } else { + const auto glyph = font.glyph(c); + const auto advance = glyph.advance(); + if( (pos.x + advance.x) > rect.width() ) { + crlf(); + } + const Point pos_glyph { + static_cast(rect.pos.x + pos.x), + display.scroll_area_y(pos.y) + }; + display.draw_glyph(pos_glyph, glyph, s.foreground, s.background); + pos.x += advance.x; } - const Point pos_glyph { - static_cast(rect.pos.x + pos.x), - display.scroll_area_y(pos.y) - }; - display.draw_glyph(pos_glyph, glyph, s.foreground, s.background); - pos.x += advance.x; } } From f49cdfdd99fca0cfb6461fdab2138e4f13f4bb12 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 17:29:54 -0800 Subject: [PATCH 025/452] Refactor digital mode handlers into Model and View classes. --- firmware/application/ui_receiver.cpp | 231 ++++++++++++++++++--------- 1 file changed, 158 insertions(+), 73 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 75be6dce1..06590b392 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -499,26 +499,6 @@ ReceiverView::~ReceiverView() { } void ReceiverView::on_show() { - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::AISPacket, - [this](Message* const p) { - const auto message = static_cast(p); - this->on_packet_ais(*message); - } - ); - message_map.register_handler(Message::ID::TPMSPacket, - [this](Message* const p) { - const auto message = static_cast(p); - this->on_packet_tpms(*message); - } - ); - message_map.register_handler(Message::ID::ERTPacket, - [this](Message* const p) { - const auto message = static_cast(p); - this->on_packet_ert(*message); - } - ); - sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { this->on_sd_card_status(status); }; @@ -526,20 +506,6 @@ void ReceiverView::on_show() { void ReceiverView::on_hide() { sd_card::status_signal -= sd_card_status_signal_token; - - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::ERTPacket); - message_map.unregister_handler(Message::ID::TPMSPacket); - message_map.unregister_handler(Message::ID::AISPacket); -} - -void ReceiverView::on_packet_ais(const AISPacketMessage& message) { - const auto result = baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); - - auto console = reinterpret_cast(widget_content.get()); - if( result.first == "OK" ) { - console->writeln(result.second); - } } static FIL fil_tpms; @@ -619,50 +585,161 @@ static ManchesterFormatted format_manchester( return { hex_data, hex_error }; } -void ReceiverView::on_packet_tpms(const TPMSPacketMessage& message) { - const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); - const auto hex_formatted = format_manchester(decoder); +class AISModel { +public: + baseband::ais::decoded_packet on_packet(const AISPacketMessage& message) { + return baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); + } - auto console = reinterpret_cast(widget_content.get()); - console->writeln(hex_formatted.data.substr(0, 240 / 8)); +private: +}; - if( !f_error(&fil_tpms) ) { - rtc::RTC datetime; - rtcGetTime(&RTCD1, &datetime); - std::string timestamp = - to_string_dec_uint(datetime.year(), 4) + - to_string_dec_uint(datetime.month(), 2, '0') + - to_string_dec_uint(datetime.day(), 2, '0') + - to_string_dec_uint(datetime.hour(), 2, '0') + - to_string_dec_uint(datetime.minute(), 2, '0') + - to_string_dec_uint(datetime.second(), 2, '0'); +class AISView : public Console { +public: + void on_show() override { + Console::on_show(); - const auto tuning_frequency = receiver_model.tuning_frequency(); - // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! - const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); - - std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; - f_puts(log.c_str(), &fil_tpms); - f_sync(&fil_tpms); - } -} - -void ReceiverView::on_packet_ert(const ERTPacketMessage& message) { - auto console = reinterpret_cast(widget_content.get()); - - if( message.packet.preamble == 0x555516a3 ) { - console->writeln("IDM"); - } - if( message.packet.preamble == 0x1f2a60 ) { - console->writeln("SCM"); + auto& message_map = context().message_map(); + message_map.register_handler(Message::ID::AISPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->log(this->model.on_packet(*message)); + } + ); } - const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); + void on_hide() override { + auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::AISPacket); - const auto hex_formatted = format_manchester(decoder); - console->writeln(hex_formatted.data); - console->writeln(hex_formatted.errors); -} + Console::on_hide(); + } + +private: + AISModel model; + + void log(const baseband::ais::decoded_packet decoded) { + if( decoded.first == "OK" ) { + writeln(decoded.second); + } + } +}; + +class TPMSModel { +public: + ManchesterFormatted on_packet(const TPMSPacketMessage& message) { + const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); + const auto hex_formatted = format_manchester(decoder); + + if( !f_error(&fil_tpms) ) { + rtc::RTC datetime; + rtcGetTime(&RTCD1, &datetime); + std::string timestamp = + to_string_dec_uint(datetime.year(), 4) + + to_string_dec_uint(datetime.month(), 2, '0') + + to_string_dec_uint(datetime.day(), 2, '0') + + to_string_dec_uint(datetime.hour(), 2, '0') + + to_string_dec_uint(datetime.minute(), 2, '0') + + to_string_dec_uint(datetime.second(), 2, '0'); + + const auto tuning_frequency = receiver_model.tuning_frequency(); + // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! + const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); + + std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; + f_puts(log.c_str(), &fil_tpms); + f_sync(&fil_tpms); + } + + return hex_formatted; + } + +private: +}; + +class TPMSView : public Console { +public: + void on_show() override { + Console::on_show(); + + auto& message_map = context().message_map(); + message_map.register_handler(Message::ID::TPMSPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->log(this->model.on_packet(*message)); + } + ); + } + + void on_hide() override { + auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::TPMSPacket); + + Console::on_hide(); + } + +private: + TPMSModel model; + + void log(const ManchesterFormatted& formatted) { + writeln(formatted.data.substr(0, 240 / 8)); + } +}; + +class ERTModel { +public: + std::string on_packet(const ERTPacketMessage& message) { + std::string s; + + if( message.packet.preamble == 0x555516a3 ) { + s += "IDM\n"; + } + if( message.packet.preamble == 0x1f2a60 ) { + s += "SCM\n"; + } + + const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); + + const auto hex_formatted = format_manchester(decoder); + s += hex_formatted.data; + s += "\n"; + s += hex_formatted.errors; + s += "\n"; + + return s; + } + +private: +}; + +class ERTView : public Console { +public: + void on_show() override { + Console::on_show(); + + auto& message_map = context().message_map(); + message_map.register_handler(Message::ID::ERTPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->log(this->model.on_packet(*message)); + } + ); + } + + void on_hide() override { + auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::ERTPacket); + + Console::on_hide(); + } + +private: + ERTModel model; + + void log(const std::string& s) { + write(s); + } +}; void ReceiverView::on_sd_card_status(const sd_card::Status status) { if( status == sd_card::Status::Mounted ) { @@ -754,9 +831,17 @@ void ReceiverView::on_modulation_changed(int32_t modulation) { switch(modulation) { case 3: + widget_content = std::make_unique(); + add_child(widget_content.get()); + break; + case 5: + widget_content = std::make_unique(); + add_child(widget_content.get()); + break; + case 6: - widget_content = std::make_unique(); + widget_content = std::make_unique(); add_child(widget_content.get()); break; From f15716a06b7a23928c50c7adc0f0b6c2bca0cef7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 17:42:52 -0800 Subject: [PATCH 026/452] Move TPMS logging to file into TPMSModel class. --- firmware/application/ui_receiver.cpp | 47 +++++++++++++++++----------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 06590b392..f82046077 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -508,8 +508,6 @@ void ReceiverView::on_hide() { sd_card::status_signal -= sd_card_status_signal_token; } -static FIL fil_tpms; - class ManchesterDecoder { public: struct DecodedSymbol { @@ -627,11 +625,19 @@ private: class TPMSModel { public: + TPMSModel() { + open_file(); + } + + ~TPMSModel() { + f_close(&fil); + } + ManchesterFormatted on_packet(const TPMSPacketMessage& message) { const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); const auto hex_formatted = format_manchester(decoder); - if( !f_error(&fil_tpms) ) { + if( !f_error(&fil) ) { rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); std::string timestamp = @@ -647,14 +653,31 @@ public: const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; - f_puts(log.c_str(), &fil_tpms); - f_sync(&fil_tpms); + f_puts(log.c_str(), &fil); + f_sync(&fil); } return hex_formatted; } private: + FIL fil; + + void open_file() { + const auto open_result = f_open(&fil, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); + if( open_result == FR_OK ) { + const auto fil_size = f_size(&fil); + const auto seek_result = f_lseek(&fil, fil_size); + if( seek_result != FR_OK ) { + f_close(&fil); + // TODO: Error, indicate somehow. + } else { + // TODO: Indicate success. + } + } else { + // TODO: Error, indicate somehow. + } + } }; class TPMSView : public Console { @@ -743,19 +766,7 @@ private: void ReceiverView::on_sd_card_status(const sd_card::Status status) { if( status == sd_card::Status::Mounted ) { - const auto open_result = f_open(&fil_tpms, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); - if( open_result == FR_OK ) { - const auto fil_size = f_size(&fil_tpms); - const auto seek_result = f_lseek(&fil_tpms, fil_size); - if( seek_result != FR_OK ) { - f_close(&fil_tpms); - // TODO: Error, indicate somehow. - } else { - // TODO: Indicate success. - } - } else { - // TODO: Error, indicate somehow. - } + // TODO: Something? } else { // TODO: Indicate unmounted. } From c0db15f3e5aa732147f0db9600076ef909a6d86a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 19:52:48 -0800 Subject: [PATCH 027/452] Replace receiver mode ordinals with enum. --- firmware/application/ui_receiver.cpp | 30 ++++++++++++++-------------- firmware/application/ui_receiver.hpp | 27 ++++++++++++++++--------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index f82046077..6fe9b9d04 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -456,7 +456,7 @@ ReceiverView::ReceiverView( options_modulation.set_by_value(receiver_model.modulation()); options_modulation.on_change = [this](size_t n, OptionsField::value_t v) { (void)n; - this->on_modulation_changed(v); + this->on_modulation_changed(static_cast(v)); }; /* options_baseband_oversampling.set_by_value(receiver_model.baseband_oversampling()); @@ -796,31 +796,31 @@ void ReceiverView::on_vga_changed(int32_t v_db) { receiver_model.set_vga(v_db); } -void ReceiverView::on_modulation_changed(int32_t modulation) { +void ReceiverView::on_modulation_changed(ReceiverMode mode) { /* TODO: This is TERRIBLE!!! */ - switch(modulation) { - case 3: - case 5: + switch(mode) { + case ReceiverMode::AIS: + case ReceiverMode::TPMS: receiver_model.set_baseband_configuration({ - .mode = modulation, + .mode = toUType(mode), .sampling_rate = 2457600, .decimation_factor = 4, }); receiver_model.set_baseband_bandwidth(1750000); break; - case 6: + case ReceiverMode::ERT: receiver_model.set_baseband_configuration({ - .mode = modulation, + .mode = toUType(mode), .sampling_rate = 4194304, .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); break; - case 4: + case ReceiverMode::SpectrumAnalysis: receiver_model.set_baseband_configuration({ - .mode = modulation, + .mode = toUType(mode), .sampling_rate = 20000000, .decimation_factor = 1, }); @@ -829,7 +829,7 @@ void ReceiverView::on_modulation_changed(int32_t modulation) { default: receiver_model.set_baseband_configuration({ - .mode = modulation, + .mode = toUType(mode), .sampling_rate = 3072000, .decimation_factor = 4, }); @@ -840,18 +840,18 @@ void ReceiverView::on_modulation_changed(int32_t modulation) { remove_child(widget_content.get()); widget_content.reset(); - switch(modulation) { - case 3: + switch(mode) { + case ReceiverMode::AIS: widget_content = std::make_unique(); add_child(widget_content.get()); break; - case 5: + case ReceiverMode::TPMS: widget_content = std::make_unique(); add_child(widget_content.get()); break; - case 6: + case ReceiverMode::ERT: widget_content = std::make_unique(); add_child(widget_content.get()); break; diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 65e97f041..9827cdc78 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -357,6 +357,16 @@ constexpr Style style_options_group { .foreground = Color::white(), }; +enum class ReceiverMode : int32_t { + AMAudio = 0, + NarrowbandFMAudio = 1, + WidebandFMAudio = 2, + AIS = 3, + SpectrumAnalysis = 4, + TPMS = 5, + ERT = 6, +}; + class ReceiverView : public View { public: ReceiverView(NavigationView& nav, ReceiverModel& receiver_model); @@ -411,14 +421,13 @@ private: { 19 * 8, 1 * 16 }, 4, { - // TODO: Put ordinals in here... - { " AM ", 0 }, - { "NFM ", 1 }, - { "WFM ", 2 }, - { "AIS ", 3 }, - { "TPMS", 5 }, - { "ERT", 6 }, - { "SPEC", 4 }, + { " AM ", toUType(ReceiverMode::AMAudio) }, + { "NFM ", toUType(ReceiverMode::NarrowbandFMAudio) }, + { "WFM ", toUType(ReceiverMode::WidebandFMAudio) }, + { "AIS ", toUType(ReceiverMode::AIS) }, + { "TPMS", toUType(ReceiverMode::TPMS) }, + { "ERT", toUType(ReceiverMode::ERT) }, + { "SPEC", toUType(ReceiverMode::SpectrumAnalysis) }, } }; /* @@ -465,7 +474,7 @@ private: void on_rf_amp_changed(bool v); void on_lna_changed(int32_t v_db); void on_vga_changed(int32_t v_db); - void on_modulation_changed(int32_t modulation); + void on_modulation_changed(ReceiverMode mode); void on_show_options_frequency(); void on_show_options_rf_gain(); void on_frequency_step_changed(rf::Frequency f); From c1d59b644dc5202402995c029f7ddf36bb91ce1a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 20:25:57 -0800 Subject: [PATCH 028/452] Move baseband configuration to receiver mode classes. Factor out the terrible switch() and clean up redundant code. --- firmware/application/ui_receiver.cpp | 124 +++++++++++++++++---------- 1 file changed, 79 insertions(+), 45 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 6fe9b9d04..95c61cd0b 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -583,8 +583,41 @@ static ManchesterFormatted format_manchester( return { hex_data, hex_error }; } +class AudioModel { +public: + AudioModel(ReceiverMode mode) { + receiver_model.set_baseband_configuration({ + .mode = toUType(mode), + .sampling_rate = 3072000, + .decimation_factor = 4, + }); + receiver_model.set_baseband_bandwidth(1750000); + } +}; + +class AudioView : public spectrum::WaterfallWidget { +public: + AudioView( + ReceiverMode mode + ) : model { mode } + { + } + +private: + AudioModel model; +}; + class AISModel { public: + AISModel() { + receiver_model.set_baseband_configuration({ + .mode = 3, + .sampling_rate = 2457600, + .decimation_factor = 4, + }); + receiver_model.set_baseband_bandwidth(1750000); + } + baseband::ais::decoded_packet on_packet(const AISPacketMessage& message) { return baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); } @@ -626,6 +659,13 @@ private: class TPMSModel { public: TPMSModel() { + receiver_model.set_baseband_configuration({ + .mode = 5, + .sampling_rate = 2457600, + .decimation_factor = 4, + }); + receiver_model.set_baseband_bandwidth(1750000); + open_file(); } @@ -711,6 +751,15 @@ private: class ERTModel { public: + ERTModel() { + receiver_model.set_baseband_configuration({ + .mode = 6, + .sampling_rate = 4194304, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); + } + std::string on_packet(const ERTPacketMessage& message) { std::string s; @@ -764,6 +813,25 @@ private: } }; +class SpectrumAnalysisModel { +public: + SpectrumAnalysisModel() { + receiver_model.set_baseband_configuration({ + .mode = 4, + .sampling_rate = 20000000, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(12000000); + } +}; + +class SpectrumAnalysisView : public spectrum::WaterfallWidget { +public: + +private: + SpectrumAnalysisModel model; +}; + void ReceiverView::on_sd_card_status(const sd_card::Status status) { if( status == sd_card::Status::Mounted ) { // TODO: Something? @@ -797,72 +865,38 @@ void ReceiverView::on_vga_changed(int32_t v_db) { } void ReceiverView::on_modulation_changed(ReceiverMode mode) { - /* TODO: This is TERRIBLE!!! */ - switch(mode) { - case ReceiverMode::AIS: - case ReceiverMode::TPMS: - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 2457600, - .decimation_factor = 4, - }); - receiver_model.set_baseband_bandwidth(1750000); - break; - - case ReceiverMode::ERT: - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 4194304, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); - break; - - case ReceiverMode::SpectrumAnalysis: - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 20000000, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(12000000); - break; - - default: - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 3072000, - .decimation_factor = 4, - }); - receiver_model.set_baseband_bandwidth(1750000); - break; - } - remove_child(widget_content.get()); widget_content.reset(); switch(mode) { + case ReceiverMode::AMAudio: + case ReceiverMode::NarrowbandFMAudio: + case ReceiverMode::WidebandFMAudio: + widget_content = std::make_unique(mode); + break; + case ReceiverMode::AIS: widget_content = std::make_unique(); - add_child(widget_content.get()); + break; + + case ReceiverMode::SpectrumAnalysis: + widget_content = std::make_unique(); break; case ReceiverMode::TPMS: widget_content = std::make_unique(); - add_child(widget_content.get()); break; case ReceiverMode::ERT: widget_content = std::make_unique(); - add_child(widget_content.get()); break; default: - widget_content = std::make_unique(); - add_child(widget_content.get()); break; } if( widget_content ) { + add_child(widget_content.get()); const ui::Dim header_height = 3 * 16; const ui::Rect rect { 0, header_height, parent_rect.width(), static_cast(parent_rect.height() - header_height) }; widget_content->set_parent_rect(rect); From 74d6518ea13e7836a8126c165542c32402990135 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 20:55:36 -0800 Subject: [PATCH 029/452] Rename AudioModel, AudioView to Analog*. --- firmware/application/ui_receiver.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 95c61cd0b..d40dbc3ae 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -583,9 +583,9 @@ static ManchesterFormatted format_manchester( return { hex_data, hex_error }; } -class AudioModel { +class AnalogAudioModel { public: - AudioModel(ReceiverMode mode) { + AnalogAudioModel(ReceiverMode mode) { receiver_model.set_baseband_configuration({ .mode = toUType(mode), .sampling_rate = 3072000, @@ -595,16 +595,16 @@ public: } }; -class AudioView : public spectrum::WaterfallWidget { +class AnalogAudioView : public spectrum::WaterfallWidget { public: - AudioView( + AnalogAudioView( ReceiverMode mode ) : model { mode } { } private: - AudioModel model; + AnalogAudioModel model; }; class AISModel { @@ -872,7 +872,7 @@ void ReceiverView::on_modulation_changed(ReceiverMode mode) { case ReceiverMode::AMAudio: case ReceiverMode::NarrowbandFMAudio: case ReceiverMode::WidebandFMAudio: - widget_content = std::make_unique(mode); + widget_content = std::make_unique(mode); break; case ReceiverMode::AIS: From e9bf500bfceaae54db137bb8f7914f2f7ae02f01 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 21:00:31 -0800 Subject: [PATCH 030/452] Move ReceiverMode enum to receiver_model.hpp --- firmware/application/receiver_model.hpp | 10 ++++++++++ firmware/application/ui_receiver.cpp | 22 ++++++++++----------- firmware/application/ui_receiver.hpp | 26 ++++++++----------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index 5b91c1536..c2479c97a 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -33,6 +33,16 @@ class ReceiverModel { public: + enum class Mode : int32_t { + AMAudio = 0, + NarrowbandFMAudio = 1, + WidebandFMAudio = 2, + AIS = 3, + SpectrumAnalysis = 4, + TPMS = 5, + ERT = 6, + }; + constexpr ReceiverModel( ClockManager& clock_manager ) : clock_manager(clock_manager) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index d40dbc3ae..2ce21cdd7 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -456,7 +456,7 @@ ReceiverView::ReceiverView( options_modulation.set_by_value(receiver_model.modulation()); options_modulation.on_change = [this](size_t n, OptionsField::value_t v) { (void)n; - this->on_modulation_changed(static_cast(v)); + this->on_modulation_changed(static_cast(v)); }; /* options_baseband_oversampling.set_by_value(receiver_model.baseband_oversampling()); @@ -585,7 +585,7 @@ static ManchesterFormatted format_manchester( class AnalogAudioModel { public: - AnalogAudioModel(ReceiverMode mode) { + AnalogAudioModel(ReceiverModel::Mode mode) { receiver_model.set_baseband_configuration({ .mode = toUType(mode), .sampling_rate = 3072000, @@ -598,7 +598,7 @@ public: class AnalogAudioView : public spectrum::WaterfallWidget { public: AnalogAudioView( - ReceiverMode mode + ReceiverModel::Mode mode ) : model { mode } { } @@ -864,30 +864,30 @@ void ReceiverView::on_vga_changed(int32_t v_db) { receiver_model.set_vga(v_db); } -void ReceiverView::on_modulation_changed(ReceiverMode mode) { +void ReceiverView::on_modulation_changed(ReceiverModel::Mode mode) { remove_child(widget_content.get()); widget_content.reset(); switch(mode) { - case ReceiverMode::AMAudio: - case ReceiverMode::NarrowbandFMAudio: - case ReceiverMode::WidebandFMAudio: + case ReceiverModel::Mode::AMAudio: + case ReceiverModel::Mode::NarrowbandFMAudio: + case ReceiverModel::Mode::WidebandFMAudio: widget_content = std::make_unique(mode); break; - case ReceiverMode::AIS: + case ReceiverModel::Mode::AIS: widget_content = std::make_unique(); break; - case ReceiverMode::SpectrumAnalysis: + case ReceiverModel::Mode::SpectrumAnalysis: widget_content = std::make_unique(); break; - case ReceiverMode::TPMS: + case ReceiverModel::Mode::TPMS: widget_content = std::make_unique(); break; - case ReceiverMode::ERT: + case ReceiverModel::Mode::ERT: widget_content = std::make_unique(); break; diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 9827cdc78..26dbe68b4 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -357,16 +357,6 @@ constexpr Style style_options_group { .foreground = Color::white(), }; -enum class ReceiverMode : int32_t { - AMAudio = 0, - NarrowbandFMAudio = 1, - WidebandFMAudio = 2, - AIS = 3, - SpectrumAnalysis = 4, - TPMS = 5, - ERT = 6, -}; - class ReceiverView : public View { public: ReceiverView(NavigationView& nav, ReceiverModel& receiver_model); @@ -421,13 +411,13 @@ private: { 19 * 8, 1 * 16 }, 4, { - { " AM ", toUType(ReceiverMode::AMAudio) }, - { "NFM ", toUType(ReceiverMode::NarrowbandFMAudio) }, - { "WFM ", toUType(ReceiverMode::WidebandFMAudio) }, - { "AIS ", toUType(ReceiverMode::AIS) }, - { "TPMS", toUType(ReceiverMode::TPMS) }, - { "ERT", toUType(ReceiverMode::ERT) }, - { "SPEC", toUType(ReceiverMode::SpectrumAnalysis) }, + { " AM ", toUType(ReceiverModel::Mode::AMAudio) }, + { "NFM ", toUType(ReceiverModel::Mode::NarrowbandFMAudio) }, + { "WFM ", toUType(ReceiverModel::Mode::WidebandFMAudio) }, + { "AIS ", toUType(ReceiverModel::Mode::AIS) }, + { "TPMS", toUType(ReceiverModel::Mode::TPMS) }, + { "ERT", toUType(ReceiverModel::Mode::ERT) }, + { "SPEC", toUType(ReceiverModel::Mode::SpectrumAnalysis) }, } }; /* @@ -474,7 +464,7 @@ private: void on_rf_amp_changed(bool v); void on_lna_changed(int32_t v_db); void on_vga_changed(int32_t v_db); - void on_modulation_changed(ReceiverMode mode); + void on_modulation_changed(ReceiverModel::Mode mode); void on_show_options_frequency(); void on_show_options_rf_gain(); void on_frequency_step_changed(rf::Frequency f); From eb10532931ee3c9ce71e2e45123a19bcb93941f7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 21:27:14 -0800 Subject: [PATCH 031/452] Remove SD card statuc handler in ReceiverView. Wasn't doing anything useful, and probably won't. --- firmware/application/ui_receiver.cpp | 19 ------------------- firmware/application/ui_receiver.hpp | 6 ------ 2 files changed, 25 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 2ce21cdd7..66ea54736 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -29,7 +29,6 @@ using namespace portapack; #include "ais_baseband.hpp" -#include "sd_card.hpp" #include "ff.h" namespace ui { @@ -498,16 +497,6 @@ ReceiverView::~ReceiverView() { receiver_model.disable(); } -void ReceiverView::on_show() { - sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { - this->on_sd_card_status(status); - }; -} - -void ReceiverView::on_hide() { - sd_card::status_signal -= sd_card_status_signal_token; -} - class ManchesterDecoder { public: struct DecodedSymbol { @@ -832,14 +821,6 @@ private: SpectrumAnalysisModel model; }; -void ReceiverView::on_sd_card_status(const sd_card::Status status) { - if( status == sd_card::Status::Mounted ) { - // TODO: Something? - } else { - // TODO: Indicate unmounted. - } -} - void ReceiverView::focus() { button_done.focus(); } diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 26dbe68b4..a2aa22b52 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -364,9 +364,6 @@ public: void focus() override; - void on_show() override; - void on_hide() override; - private: ReceiverModel& receiver_model; @@ -476,9 +473,6 @@ private: void on_packet_ais(const AISPacketMessage& message); void on_packet_tpms(const TPMSPacketMessage& message); void on_packet_ert(const ERTPacketMessage& message); - void on_sd_card_status(const sd_card::Status status); - - SignalToken sd_card_status_signal_token; }; } /* namespace ui */ From 9a5655ad0ebb01ef905ab3ac5690eff859a80cf8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 21:27:51 -0800 Subject: [PATCH 032/452] Removed extra methods. --- firmware/application/ui_receiver.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index a2aa22b52..af948c3c7 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -469,10 +469,6 @@ private: void on_headphone_volume_changed(int32_t v); // void on_baseband_oversampling_changed(int32_t v); void on_edit_frequency(); - - void on_packet_ais(const AISPacketMessage& message); - void on_packet_tpms(const TPMSPacketMessage& message); - void on_packet_ert(const ERTPacketMessage& message); }; } /* namespace ui */ From 519f8cfebc1ad4e8909a321997b2c1fa9d6b5474 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 21:28:53 -0800 Subject: [PATCH 033/452] Extract Manchester decoder, formatter. --- firmware/application/Makefile | 1 + firmware/application/manchester.cpp | 57 ++++++++++++++++++++ firmware/application/manchester.hpp | 77 ++++++++++++++++++++++++++++ firmware/application/ui_receiver.cpp | 75 --------------------------- 4 files changed, 135 insertions(+), 75 deletions(-) create mode 100644 firmware/application/manchester.cpp create mode 100644 firmware/application/manchester.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 94687405f..60b109c9d 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -170,6 +170,7 @@ CPPSRC = main.cpp \ spectrum_color_lut.cpp \ ais_baseband.cpp \ sd_card.cpp \ + manchester.cpp \ ../common/utility.cpp \ ../common/chibios_cpp.cpp \ ../common/debug.cpp \ diff --git a/firmware/application/manchester.cpp b/firmware/application/manchester.cpp new file mode 100644 index 000000000..95205043c --- /dev/null +++ b/firmware/application/manchester.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "manchester.hpp" + +// TODO: SERIOUSLY!? Including this, just to use to_string_hex?! Refactor!!!1 +#include "ui_widget.hpp" + +ManchesterFormatted format_manchester( + const ManchesterDecoder& decoder +) { + const size_t payload_length_decoded = decoder.symbols_count(); + const size_t payload_length_hex_characters = (payload_length_decoded + 3) / 4; + const size_t payload_length_symbols_rounded = payload_length_hex_characters * 4; + + std::string hex_data; + std::string hex_error; + hex_data.reserve(payload_length_hex_characters); + hex_error.reserve(payload_length_hex_characters); + + uint_fast8_t data = 0; + uint_fast8_t error = 0; + for(size_t i=0; i +#include +#include +#include + +class ManchesterDecoder { +public: + struct DecodedSymbol { + uint_fast8_t value; + uint_fast8_t error; + }; + + constexpr ManchesterDecoder( + const std::bitset<1024>& encoded, + const size_t count, + const size_t sense = 0 + ) : encoded { encoded }, + count { count }, + sense { sense } + { + } + + DecodedSymbol operator[](const size_t index) const { + const size_t encoded_index = index * 2; + if( (encoded_index + 1) < count ) { + const auto value = encoded[encoded_index + sense]; + const auto error = encoded[encoded_index + 0] == encoded[encoded_index + 1]; + return { value, error }; + } else { + return { 0, 1 }; + } + } + + size_t symbols_count() const { + return count / 2; + } + +private: + const std::bitset<1024>& encoded; + const size_t count; + const size_t sense; +}; + +struct ManchesterFormatted { + const std::string data; + const std::string errors; +}; + +ManchesterFormatted format_manchester( + const ManchesterDecoder& decoder +); + +#endif/*__MANCHESTER_H__*/ diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 66ea54736..182b6bac3 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -497,81 +497,6 @@ ReceiverView::~ReceiverView() { receiver_model.disable(); } -class ManchesterDecoder { -public: - struct DecodedSymbol { - uint_fast8_t value; - uint_fast8_t error; - }; - - constexpr ManchesterDecoder( - const std::bitset<1024>& encoded, - const size_t count, - const size_t sense = 0 - ) : encoded { encoded }, - count { count }, - sense { sense } - { - } - - DecodedSymbol operator[](const size_t index) const { - const size_t encoded_index = index * 2; - if( (encoded_index + 1) < count ) { - const auto value = encoded[encoded_index + sense]; - const auto error = encoded[encoded_index + 0] == encoded[encoded_index + 1]; - return { value, error }; - } else { - return { 0, 1 }; - } - } - - size_t symbols_count() const { - return count / 2; - } - -private: - const std::bitset<1024>& encoded; - const size_t count; - const size_t sense; -}; - -struct ManchesterFormatted { - const std::string data; - const std::string errors; -}; - -static ManchesterFormatted format_manchester( - const ManchesterDecoder& decoder -) { - const size_t payload_length_decoded = decoder.symbols_count(); - const size_t payload_length_hex_characters = (payload_length_decoded + 3) / 4; - const size_t payload_length_symbols_rounded = payload_length_hex_characters * 4; - - std::string hex_data; - std::string hex_error; - hex_data.reserve(payload_length_hex_characters); - hex_error.reserve(payload_length_hex_characters); - - uint_fast8_t data = 0; - uint_fast8_t error = 0; - for(size_t i=0; i Date: Tue, 1 Dec 2015 21:30:52 -0800 Subject: [PATCH 034/452] Extract "apps". --- firmware/application/app_ais.hpp | 84 ++++++ firmware/application/app_analog_audio.hpp | 57 ++++ firmware/application/app_ert.hpp | 99 +++++++ .../application/app_spectrum_analysis.hpp | 51 ++++ firmware/application/app_tpms.hpp | 137 +++++++++ firmware/application/ui_receiver.cpp | 260 +----------------- 6 files changed, 433 insertions(+), 255 deletions(-) create mode 100644 firmware/application/app_ais.hpp create mode 100644 firmware/application/app_analog_audio.hpp create mode 100644 firmware/application/app_ert.hpp create mode 100644 firmware/application/app_spectrum_analysis.hpp create mode 100644 firmware/application/app_tpms.hpp diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp new file mode 100644 index 000000000..ed7f403aa --- /dev/null +++ b/firmware/application/app_ais.hpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __APP_AIS_H__ +#define __APP_AIS_H__ + +#include "receiver_model.hpp" +#include "ui_console.hpp" +#include "message.hpp" + +#include "ais_baseband.hpp" + +class AISModel { +public: + AISModel() { + receiver_model.set_baseband_configuration({ + .mode = 3, + .sampling_rate = 2457600, + .decimation_factor = 4, + }); + receiver_model.set_baseband_bandwidth(1750000); + } + + baseband::ais::decoded_packet on_packet(const AISPacketMessage& message) { + return baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); + } + +private: +}; + +namespace ui { + +class AISView : public Console { +public: + void on_show() override { + Console::on_show(); + + auto& message_map = context().message_map(); + message_map.register_handler(Message::ID::AISPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->log(this->model.on_packet(*message)); + } + ); + } + + void on_hide() override { + auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::AISPacket); + + Console::on_hide(); + } + +private: + AISModel model; + + void log(const baseband::ais::decoded_packet decoded) { + if( decoded.first == "OK" ) { + writeln(decoded.second); + } + } +}; + +} /* namespace ui */ + +#endif/*__APP_AIS_H__*/ diff --git a/firmware/application/app_analog_audio.hpp b/firmware/application/app_analog_audio.hpp new file mode 100644 index 000000000..4a620f2c6 --- /dev/null +++ b/firmware/application/app_analog_audio.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __APP_ANALOG_AUDIO_H__ +#define __APP_ANALOG_AUDIO_H__ + +#include "receiver_model.hpp" +#include "ui_spectrum.hpp" +#include "utility.hpp" + +class AnalogAudioModel { +public: + AnalogAudioModel(ReceiverModel::Mode mode) { + receiver_model.set_baseband_configuration({ + .mode = toUType(mode), + .sampling_rate = 3072000, + .decimation_factor = 4, + }); + receiver_model.set_baseband_bandwidth(1750000); + } +}; + +namespace ui { + +class AnalogAudioView : public spectrum::WaterfallWidget { +public: + AnalogAudioView( + ReceiverModel::Mode mode + ) : model { mode } + { + } + +private: + AnalogAudioModel model; +}; + +} /* namespace ui */ + +#endif/*__APP_ANALOG_AUDIO_H__*/ diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp new file mode 100644 index 000000000..5b5e01bb2 --- /dev/null +++ b/firmware/application/app_ert.hpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __APP_ERT_H__ +#define __APP_ERT_H__ + +#include "receiver_model.hpp" +#include "ui_console.hpp" +#include "message.hpp" + +#include + +class ERTModel { +public: + ERTModel() { + receiver_model.set_baseband_configuration({ + .mode = 6, + .sampling_rate = 4194304, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); + } + + std::string on_packet(const ERTPacketMessage& message) { + std::string s; + + if( message.packet.preamble == 0x555516a3 ) { + s += "IDM\n"; + } + if( message.packet.preamble == 0x1f2a60 ) { + s += "SCM\n"; + } + + const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); + + const auto hex_formatted = format_manchester(decoder); + s += hex_formatted.data; + s += "\n"; + s += hex_formatted.errors; + s += "\n"; + + return s; + } + +private: +}; + +namespace ui { + +class ERTView : public Console { +public: + void on_show() override { + Console::on_show(); + + auto& message_map = context().message_map(); + message_map.register_handler(Message::ID::ERTPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->log(this->model.on_packet(*message)); + } + ); + } + + void on_hide() override { + auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::ERTPacket); + + Console::on_hide(); + } + +private: + ERTModel model; + + void log(const std::string& s) { + write(s); + } +}; + +} /* namespace ui */ + +#endif/*__APP_ERT_H__*/ diff --git a/firmware/application/app_spectrum_analysis.hpp b/firmware/application/app_spectrum_analysis.hpp new file mode 100644 index 000000000..b3217db40 --- /dev/null +++ b/firmware/application/app_spectrum_analysis.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __APP_SPECTRUM_ANALYSIS_H__ +#define __APP_SPECTRUM_ANALYSIS_H__ + +#include "receiver_model.hpp" +#include "ui_spectrum.hpp" + +class SpectrumAnalysisModel { +public: + SpectrumAnalysisModel() { + receiver_model.set_baseband_configuration({ + .mode = 4, + .sampling_rate = 20000000, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(12000000); + } +}; + +namespace ui { + +class SpectrumAnalysisView : public spectrum::WaterfallWidget { +public: + +private: + SpectrumAnalysisModel model; +}; + +} /* namespace ui */ + +#endif/*__APP_SPECTRUM_ANALYSIS_H__*/ diff --git a/firmware/application/app_tpms.hpp b/firmware/application/app_tpms.hpp new file mode 100644 index 000000000..3a07ef626 --- /dev/null +++ b/firmware/application/app_tpms.hpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __APP_TPMS_H__ +#define __APP_TPMS_H__ + +#include "receiver_model.hpp" +#include "ui_console.hpp" +#include "message.hpp" + +#include "manchester.hpp" + +#include "ff.h" + +#include +// #include "lpc43xx_cpp.hpp" +// using namespace lpc43xx; + +// TODO: SERIOUSLY!? Including this, just to use to_string_hex?! Refactor!!!1 +#include "ui_widget.hpp" + +class TPMSModel { +public: + TPMSModel() { + receiver_model.set_baseband_configuration({ + .mode = 5, + .sampling_rate = 2457600, + .decimation_factor = 4, + }); + receiver_model.set_baseband_bandwidth(1750000); + + open_file(); + } + + ~TPMSModel() { + f_close(&fil); + } + + ManchesterFormatted on_packet(const TPMSPacketMessage& message) { + const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); + const auto hex_formatted = format_manchester(decoder); + + if( !f_error(&fil) ) { + rtc::RTC datetime; + rtcGetTime(&RTCD1, &datetime); + std::string timestamp = + ui::to_string_dec_uint(datetime.year(), 4) + + ui::to_string_dec_uint(datetime.month(), 2, '0') + + ui::to_string_dec_uint(datetime.day(), 2, '0') + + ui::to_string_dec_uint(datetime.hour(), 2, '0') + + ui::to_string_dec_uint(datetime.minute(), 2, '0') + + ui::to_string_dec_uint(datetime.second(), 2, '0'); + + const auto tuning_frequency = receiver_model.tuning_frequency(); + // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! + const auto tuning_frequency_str = ui::to_string_dec_uint(tuning_frequency, 10); + + std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; + f_puts(log.c_str(), &fil); + f_sync(&fil); + } + + return hex_formatted; + } + +private: + FIL fil; + + void open_file() { + const auto open_result = f_open(&fil, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); + if( open_result == FR_OK ) { + const auto fil_size = f_size(&fil); + const auto seek_result = f_lseek(&fil, fil_size); + if( seek_result != FR_OK ) { + f_close(&fil); + // TODO: Error, indicate somehow. + } else { + // TODO: Indicate success. + } + } else { + // TODO: Error, indicate somehow. + } + } +}; + +namespace ui { + +class TPMSView : public Console { +public: + void on_show() override { + Console::on_show(); + + auto& message_map = context().message_map(); + message_map.register_handler(Message::ID::TPMSPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->log(this->model.on_packet(*message)); + } + ); + } + + void on_hide() override { + auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::TPMSPacket); + + Console::on_hide(); + } + +private: + TPMSModel model; + + void log(const ManchesterFormatted& formatted) { + writeln(formatted.data.substr(0, 240 / 8)); + } +}; + +} /* namespace ui */ + +#endif/*__APP_TPMS_H__*/ diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 182b6bac3..9af664762 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -21,15 +21,14 @@ #include "ui_receiver.hpp" -#include "ui_spectrum.hpp" -#include "ui_console.hpp" - #include "portapack.hpp" using namespace portapack; -#include "ais_baseband.hpp" - -#include "ff.h" +#include "app_analog_audio.hpp" +#include "app_ais.hpp" +#include "app_tpms.hpp" +#include "app_ert.hpp" +#include "app_spectrum_analysis.hpp" namespace ui { @@ -497,255 +496,6 @@ ReceiverView::~ReceiverView() { receiver_model.disable(); } -class AnalogAudioModel { -public: - AnalogAudioModel(ReceiverModel::Mode mode) { - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 3072000, - .decimation_factor = 4, - }); - receiver_model.set_baseband_bandwidth(1750000); - } -}; - -class AnalogAudioView : public spectrum::WaterfallWidget { -public: - AnalogAudioView( - ReceiverModel::Mode mode - ) : model { mode } - { - } - -private: - AnalogAudioModel model; -}; - -class AISModel { -public: - AISModel() { - receiver_model.set_baseband_configuration({ - .mode = 3, - .sampling_rate = 2457600, - .decimation_factor = 4, - }); - receiver_model.set_baseband_bandwidth(1750000); - } - - baseband::ais::decoded_packet on_packet(const AISPacketMessage& message) { - return baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); - } - -private: -}; - -class AISView : public Console { -public: - void on_show() override { - Console::on_show(); - - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::AISPacket, - [this](Message* const p) { - const auto message = static_cast(p); - this->log(this->model.on_packet(*message)); - } - ); - } - - void on_hide() override { - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::AISPacket); - - Console::on_hide(); - } - -private: - AISModel model; - - void log(const baseband::ais::decoded_packet decoded) { - if( decoded.first == "OK" ) { - writeln(decoded.second); - } - } -}; - -class TPMSModel { -public: - TPMSModel() { - receiver_model.set_baseband_configuration({ - .mode = 5, - .sampling_rate = 2457600, - .decimation_factor = 4, - }); - receiver_model.set_baseband_bandwidth(1750000); - - open_file(); - } - - ~TPMSModel() { - f_close(&fil); - } - - ManchesterFormatted on_packet(const TPMSPacketMessage& message) { - const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); - const auto hex_formatted = format_manchester(decoder); - - if( !f_error(&fil) ) { - rtc::RTC datetime; - rtcGetTime(&RTCD1, &datetime); - std::string timestamp = - to_string_dec_uint(datetime.year(), 4) + - to_string_dec_uint(datetime.month(), 2, '0') + - to_string_dec_uint(datetime.day(), 2, '0') + - to_string_dec_uint(datetime.hour(), 2, '0') + - to_string_dec_uint(datetime.minute(), 2, '0') + - to_string_dec_uint(datetime.second(), 2, '0'); - - const auto tuning_frequency = receiver_model.tuning_frequency(); - // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! - const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); - - std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; - f_puts(log.c_str(), &fil); - f_sync(&fil); - } - - return hex_formatted; - } - -private: - FIL fil; - - void open_file() { - const auto open_result = f_open(&fil, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); - if( open_result == FR_OK ) { - const auto fil_size = f_size(&fil); - const auto seek_result = f_lseek(&fil, fil_size); - if( seek_result != FR_OK ) { - f_close(&fil); - // TODO: Error, indicate somehow. - } else { - // TODO: Indicate success. - } - } else { - // TODO: Error, indicate somehow. - } - } -}; - -class TPMSView : public Console { -public: - void on_show() override { - Console::on_show(); - - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::TPMSPacket, - [this](Message* const p) { - const auto message = static_cast(p); - this->log(this->model.on_packet(*message)); - } - ); - } - - void on_hide() override { - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::TPMSPacket); - - Console::on_hide(); - } - -private: - TPMSModel model; - - void log(const ManchesterFormatted& formatted) { - writeln(formatted.data.substr(0, 240 / 8)); - } -}; - -class ERTModel { -public: - ERTModel() { - receiver_model.set_baseband_configuration({ - .mode = 6, - .sampling_rate = 4194304, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); - } - - std::string on_packet(const ERTPacketMessage& message) { - std::string s; - - if( message.packet.preamble == 0x555516a3 ) { - s += "IDM\n"; - } - if( message.packet.preamble == 0x1f2a60 ) { - s += "SCM\n"; - } - - const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); - - const auto hex_formatted = format_manchester(decoder); - s += hex_formatted.data; - s += "\n"; - s += hex_formatted.errors; - s += "\n"; - - return s; - } - -private: -}; - -class ERTView : public Console { -public: - void on_show() override { - Console::on_show(); - - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::ERTPacket, - [this](Message* const p) { - const auto message = static_cast(p); - this->log(this->model.on_packet(*message)); - } - ); - } - - void on_hide() override { - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::ERTPacket); - - Console::on_hide(); - } - -private: - ERTModel model; - - void log(const std::string& s) { - write(s); - } -}; - -class SpectrumAnalysisModel { -public: - SpectrumAnalysisModel() { - receiver_model.set_baseband_configuration({ - .mode = 4, - .sampling_rate = 20000000, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(12000000); - } -}; - -class SpectrumAnalysisView : public spectrum::WaterfallWidget { -public: - -private: - SpectrumAnalysisModel model; -}; - void ReceiverView::focus() { button_done.focus(); } From 1aa1286ec128ed0a145684615d77a9374be4b2b8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 21:44:13 -0800 Subject: [PATCH 035/452] Push app_ais.hpp code into .cpp. --- firmware/application/Makefile | 1 + firmware/application/app_ais.cpp | 67 ++++++++++++++++++++++++++++++++ firmware/application/app_ais.hpp | 42 +++----------------- 3 files changed, 73 insertions(+), 37 deletions(-) create mode 100644 firmware/application/app_ais.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 60b109c9d..f317a2920 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -169,6 +169,7 @@ CPPSRC = main.cpp \ receiver_model.cpp \ spectrum_color_lut.cpp \ ais_baseband.cpp \ + app_ais.cpp \ sd_card.cpp \ manchester.cpp \ ../common/utility.cpp \ diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp new file mode 100644 index 000000000..118323ad0 --- /dev/null +++ b/firmware/application/app_ais.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "app_ais.hpp" + +#include "portapack.hpp" +using namespace portapack; + +AISModel::AISModel() { + receiver_model.set_baseband_configuration({ + .mode = 3, + .sampling_rate = 2457600, + .decimation_factor = 4, + }); + receiver_model.set_baseband_bandwidth(1750000); +} + +baseband::ais::decoded_packet AISModel::on_packet(const AISPacketMessage& message) { + return baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); +} + +namespace ui { + +void AISView::on_show() { + Console::on_show(); + + auto& message_map = context().message_map(); + message_map.register_handler(Message::ID::AISPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->log(this->model.on_packet(*message)); + } + ); +} + +void AISView::on_hide() { + auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::AISPacket); + + Console::on_hide(); +} + +void AISView::log(const baseband::ais::decoded_packet decoded) { + if( decoded.first == "OK" ) { + writeln(decoded.second); + } +} + +} /* namespace ui */ diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index ed7f403aa..606aee873 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -22,7 +22,6 @@ #ifndef __APP_AIS_H__ #define __APP_AIS_H__ -#include "receiver_model.hpp" #include "ui_console.hpp" #include "message.hpp" @@ -30,53 +29,22 @@ class AISModel { public: - AISModel() { - receiver_model.set_baseband_configuration({ - .mode = 3, - .sampling_rate = 2457600, - .decimation_factor = 4, - }); - receiver_model.set_baseband_bandwidth(1750000); - } + AISModel(); - baseband::ais::decoded_packet on_packet(const AISPacketMessage& message) { - return baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); - } - -private: + baseband::ais::decoded_packet on_packet(const AISPacketMessage& message); }; namespace ui { class AISView : public Console { public: - void on_show() override { - Console::on_show(); - - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::AISPacket, - [this](Message* const p) { - const auto message = static_cast(p); - this->log(this->model.on_packet(*message)); - } - ); - } - - void on_hide() override { - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::AISPacket); - - Console::on_hide(); - } + void on_show() override; + void on_hide() override; private: AISModel model; - void log(const baseband::ais::decoded_packet decoded) { - if( decoded.first == "OK" ) { - writeln(decoded.second); - } - } + void log(const baseband::ais::decoded_packet decoded); }; } /* namespace ui */ From 61dc25e13239b64813e6896d6af39b7325cf373a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 21:47:21 -0800 Subject: [PATCH 036/452] Move more Manchester code from .hpp to .cpp. --- firmware/application/manchester.cpp | 15 +++++++++++++++ firmware/application/manchester.hpp | 15 ++------------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/firmware/application/manchester.cpp b/firmware/application/manchester.cpp index 95205043c..877fc03b7 100644 --- a/firmware/application/manchester.cpp +++ b/firmware/application/manchester.cpp @@ -24,6 +24,21 @@ // TODO: SERIOUSLY!? Including this, just to use to_string_hex?! Refactor!!!1 #include "ui_widget.hpp" +ManchesterDecoder::DecodedSymbol ManchesterDecoder::operator[](const size_t index) const { + const size_t encoded_index = index * 2; + if( (encoded_index + 1) < count ) { + const auto value = encoded[encoded_index + sense]; + const auto error = encoded[encoded_index + 0] == encoded[encoded_index + 1]; + return { value, error }; + } else { + return { 0, 1 }; + } +} + +size_t ManchesterDecoder::symbols_count() const { + return count / 2; +} + ManchesterFormatted format_manchester( const ManchesterDecoder& decoder ) { diff --git a/firmware/application/manchester.hpp b/firmware/application/manchester.hpp index 15762a55c..5e965c854 100644 --- a/firmware/application/manchester.hpp +++ b/firmware/application/manchester.hpp @@ -44,20 +44,9 @@ public: { } - DecodedSymbol operator[](const size_t index) const { - const size_t encoded_index = index * 2; - if( (encoded_index + 1) < count ) { - const auto value = encoded[encoded_index + sense]; - const auto error = encoded[encoded_index + 0] == encoded[encoded_index + 1]; - return { value, error }; - } else { - return { 0, 1 }; - } - } + DecodedSymbol operator[](const size_t index) const; - size_t symbols_count() const { - return count / 2; - } + size_t symbols_count() const; private: const std::bitset<1024>& encoded; From 4c3b557064ac744ae44228326aefc1f5f23cfa13 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 21:53:28 -0800 Subject: [PATCH 037/452] Move app_tpms.hpp code to .cpp. --- firmware/application/Makefile | 1 + firmware/application/app_tpms.cpp | 117 ++++++++++++++++++++++++++++++ firmware/application/app_tpms.hpp | 91 ++--------------------- 3 files changed, 125 insertions(+), 84 deletions(-) create mode 100644 firmware/application/app_tpms.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index f317a2920..8702a5625 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -170,6 +170,7 @@ CPPSRC = main.cpp \ spectrum_color_lut.cpp \ ais_baseband.cpp \ app_ais.cpp \ + app_tpms.cpp \ sd_card.cpp \ manchester.cpp \ ../common/utility.cpp \ diff --git a/firmware/application/app_tpms.cpp b/firmware/application/app_tpms.cpp new file mode 100644 index 000000000..598cabcea --- /dev/null +++ b/firmware/application/app_tpms.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "app_tpms.hpp" + +#include "portapack.hpp" +using namespace portapack; + +#include +// #include "lpc43xx_cpp.hpp" +// using namespace lpc43xx; + +// TODO: SERIOUSLY!? Including this, just to use to_string_hex?! Refactor!!!1 +#include "ui_widget.hpp" + +TPMSModel::TPMSModel() { + receiver_model.set_baseband_configuration({ + .mode = 5, + .sampling_rate = 2457600, + .decimation_factor = 4, + }); + receiver_model.set_baseband_bandwidth(1750000); + + open_file(); +} + +TPMSModel::~TPMSModel() { + f_close(&fil); +} + +ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { + const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); + const auto hex_formatted = format_manchester(decoder); + + if( !f_error(&fil) ) { + rtc::RTC datetime; + rtcGetTime(&RTCD1, &datetime); + std::string timestamp = + ui::to_string_dec_uint(datetime.year(), 4) + + ui::to_string_dec_uint(datetime.month(), 2, '0') + + ui::to_string_dec_uint(datetime.day(), 2, '0') + + ui::to_string_dec_uint(datetime.hour(), 2, '0') + + ui::to_string_dec_uint(datetime.minute(), 2, '0') + + ui::to_string_dec_uint(datetime.second(), 2, '0'); + + const auto tuning_frequency = receiver_model.tuning_frequency(); + // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! + const auto tuning_frequency_str = ui::to_string_dec_uint(tuning_frequency, 10); + + std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; + f_puts(log.c_str(), &fil); + f_sync(&fil); + } + + return hex_formatted; +} + +void TPMSModel::open_file() { + const auto open_result = f_open(&fil, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); + if( open_result == FR_OK ) { + const auto fil_size = f_size(&fil); + const auto seek_result = f_lseek(&fil, fil_size); + if( seek_result != FR_OK ) { + f_close(&fil); + // TODO: Error, indicate somehow. + } else { + // TODO: Indicate success. + } + } else { + // TODO: Error, indicate somehow. + } +} + +namespace ui { + +void TPMSView::on_show() { + Console::on_show(); + + auto& message_map = context().message_map(); + message_map.register_handler(Message::ID::TPMSPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->log(this->model.on_packet(*message)); + } + ); +} + +void TPMSView::on_hide() { + auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::TPMSPacket); + + Console::on_hide(); +} + +void TPMSView::log(const ManchesterFormatted& formatted) { + writeln(formatted.data.substr(0, 240 / 8)); +} + +} /* namespace ui */ diff --git a/firmware/application/app_tpms.hpp b/firmware/application/app_tpms.hpp index 3a07ef626..f1d431be4 100644 --- a/firmware/application/app_tpms.hpp +++ b/firmware/application/app_tpms.hpp @@ -22,7 +22,6 @@ #ifndef __APP_TPMS_H__ #define __APP_TPMS_H__ -#include "receiver_model.hpp" #include "ui_console.hpp" #include "message.hpp" @@ -30,106 +29,30 @@ #include "ff.h" -#include -// #include "lpc43xx_cpp.hpp" -// using namespace lpc43xx; - -// TODO: SERIOUSLY!? Including this, just to use to_string_hex?! Refactor!!!1 -#include "ui_widget.hpp" - class TPMSModel { public: - TPMSModel() { - receiver_model.set_baseband_configuration({ - .mode = 5, - .sampling_rate = 2457600, - .decimation_factor = 4, - }); - receiver_model.set_baseband_bandwidth(1750000); + TPMSModel(); + ~TPMSModel(); - open_file(); - } - - ~TPMSModel() { - f_close(&fil); - } - - ManchesterFormatted on_packet(const TPMSPacketMessage& message) { - const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); - const auto hex_formatted = format_manchester(decoder); - - if( !f_error(&fil) ) { - rtc::RTC datetime; - rtcGetTime(&RTCD1, &datetime); - std::string timestamp = - ui::to_string_dec_uint(datetime.year(), 4) + - ui::to_string_dec_uint(datetime.month(), 2, '0') + - ui::to_string_dec_uint(datetime.day(), 2, '0') + - ui::to_string_dec_uint(datetime.hour(), 2, '0') + - ui::to_string_dec_uint(datetime.minute(), 2, '0') + - ui::to_string_dec_uint(datetime.second(), 2, '0'); - - const auto tuning_frequency = receiver_model.tuning_frequency(); - // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! - const auto tuning_frequency_str = ui::to_string_dec_uint(tuning_frequency, 10); - - std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; - f_puts(log.c_str(), &fil); - f_sync(&fil); - } - - return hex_formatted; - } + ManchesterFormatted on_packet(const TPMSPacketMessage& message); private: FIL fil; - void open_file() { - const auto open_result = f_open(&fil, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); - if( open_result == FR_OK ) { - const auto fil_size = f_size(&fil); - const auto seek_result = f_lseek(&fil, fil_size); - if( seek_result != FR_OK ) { - f_close(&fil); - // TODO: Error, indicate somehow. - } else { - // TODO: Indicate success. - } - } else { - // TODO: Error, indicate somehow. - } - } + void open_file(); }; namespace ui { class TPMSView : public Console { public: - void on_show() override { - Console::on_show(); - - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::TPMSPacket, - [this](Message* const p) { - const auto message = static_cast(p); - this->log(this->model.on_packet(*message)); - } - ); - } - - void on_hide() override { - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::TPMSPacket); - - Console::on_hide(); - } + void on_show() override; + void on_hide() override; private: TPMSModel model; - void log(const ManchesterFormatted& formatted) { - writeln(formatted.data.substr(0, 240 / 8)); - } + void log(const ManchesterFormatted& formatted); }; } /* namespace ui */ From 11e8456da038b785ed02f196e747bfd84f5a9260 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 21:59:47 -0800 Subject: [PATCH 038/452] Move app_ert.hpp code to .cpp. --- firmware/application/Makefile | 1 + firmware/application/app_ert.cpp | 84 ++++++++++++++++++++++++++++++++ firmware/application/app_ert.hpp | 57 ++-------------------- 3 files changed, 90 insertions(+), 52 deletions(-) create mode 100644 firmware/application/app_ert.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 8702a5625..e0c778b6f 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -171,6 +171,7 @@ CPPSRC = main.cpp \ ais_baseband.cpp \ app_ais.cpp \ app_tpms.cpp \ + app_ert.cpp \ sd_card.cpp \ manchester.cpp \ ../common/utility.cpp \ diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp new file mode 100644 index 000000000..30ef47363 --- /dev/null +++ b/firmware/application/app_ert.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "app_ert.hpp" + +#include "portapack.hpp" +using namespace portapack; + +#include "manchester.hpp" + +ERTModel::ERTModel() { + receiver_model.set_baseband_configuration({ + .mode = 6, + .sampling_rate = 4194304, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); +} + +std::string ERTModel::on_packet(const ERTPacketMessage& message) { + std::string s; + + if( message.packet.preamble == 0x555516a3 ) { + s += "IDM\n"; + } + if( message.packet.preamble == 0x1f2a60 ) { + s += "SCM\n"; + } + + const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); + + const auto hex_formatted = format_manchester(decoder); + s += hex_formatted.data; + s += "\n"; + s += hex_formatted.errors; + s += "\n"; + + return s; +} + +namespace ui { + +void ERTView::on_show() { + Console::on_show(); + + auto& message_map = context().message_map(); + message_map.register_handler(Message::ID::ERTPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->log(this->model.on_packet(*message)); + } + ); +} + +void ERTView::on_hide() { + auto& message_map = context().message_map(); + message_map.unregister_handler(Message::ID::ERTPacket); + + Console::on_hide(); +} + +void ERTView::log(const std::string& s) { + write(s); +} + +} /* namespace ui */ diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index 5b5e01bb2..05f0eba76 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -22,7 +22,6 @@ #ifndef __APP_ERT_H__ #define __APP_ERT_H__ -#include "receiver_model.hpp" #include "ui_console.hpp" #include "message.hpp" @@ -30,68 +29,22 @@ class ERTModel { public: - ERTModel() { - receiver_model.set_baseband_configuration({ - .mode = 6, - .sampling_rate = 4194304, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); - } + ERTModel(); - std::string on_packet(const ERTPacketMessage& message) { - std::string s; - - if( message.packet.preamble == 0x555516a3 ) { - s += "IDM\n"; - } - if( message.packet.preamble == 0x1f2a60 ) { - s += "SCM\n"; - } - - const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); - - const auto hex_formatted = format_manchester(decoder); - s += hex_formatted.data; - s += "\n"; - s += hex_formatted.errors; - s += "\n"; - - return s; - } - -private: + std::string on_packet(const ERTPacketMessage& message); }; namespace ui { class ERTView : public Console { public: - void on_show() override { - Console::on_show(); - - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::ERTPacket, - [this](Message* const p) { - const auto message = static_cast(p); - this->log(this->model.on_packet(*message)); - } - ); - } - - void on_hide() override { - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::ERTPacket); - - Console::on_hide(); - } + void on_show() override; + void on_hide() override; private: ERTModel model; - void log(const std::string& s) { - write(s); - } + void log(const std::string& s); }; } /* namespace ui */ From d15afc9f7d36f838de8a0af058cc74a283c80da7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 22:04:04 -0800 Subject: [PATCH 039/452] Move app_analog_audio.hpp code to .cpp. --- firmware/application/Makefile | 1 + firmware/application/app_analog_audio.cpp | 36 +++++++++++++++++++++++ firmware/application/app_analog_audio.hpp | 10 +------ 3 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 firmware/application/app_analog_audio.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index e0c778b6f..d44e74374 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -168,6 +168,7 @@ CPPSRC = main.cpp \ ui_spectrum.cpp \ receiver_model.cpp \ spectrum_color_lut.cpp \ + app_analog_audio.cpp \ ais_baseband.cpp \ app_ais.cpp \ app_tpms.cpp \ diff --git a/firmware/application/app_analog_audio.cpp b/firmware/application/app_analog_audio.cpp new file mode 100644 index 000000000..185ce7807 --- /dev/null +++ b/firmware/application/app_analog_audio.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "app_analog_audio.hpp" + +#include "portapack.hpp" +using namespace portapack; + +#include "utility.hpp" + +AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { + receiver_model.set_baseband_configuration({ + .mode = toUType(mode), + .sampling_rate = 3072000, + .decimation_factor = 4, + }); + receiver_model.set_baseband_bandwidth(1750000); +} diff --git a/firmware/application/app_analog_audio.hpp b/firmware/application/app_analog_audio.hpp index 4a620f2c6..1303a05e8 100644 --- a/firmware/application/app_analog_audio.hpp +++ b/firmware/application/app_analog_audio.hpp @@ -24,18 +24,10 @@ #include "receiver_model.hpp" #include "ui_spectrum.hpp" -#include "utility.hpp" class AnalogAudioModel { public: - AnalogAudioModel(ReceiverModel::Mode mode) { - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 3072000, - .decimation_factor = 4, - }); - receiver_model.set_baseband_bandwidth(1750000); - } + AnalogAudioModel(ReceiverModel::Mode mode); }; namespace ui { From 29f2d0e50af0726e63c81390c4b78310b4c10181 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 22:07:17 -0800 Subject: [PATCH 040/452] Move app_spectrum_analysis.hpp code to .cpp. --- firmware/application/Makefile | 1 + .../application/app_spectrum_analysis.cpp | 34 +++++++++++++++++++ .../application/app_spectrum_analysis.hpp | 9 +---- 3 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 firmware/application/app_spectrum_analysis.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index d44e74374..f8507d83c 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -173,6 +173,7 @@ CPPSRC = main.cpp \ app_ais.cpp \ app_tpms.cpp \ app_ert.cpp \ + app_spectrum_analysis.cpp \ sd_card.cpp \ manchester.cpp \ ../common/utility.cpp \ diff --git a/firmware/application/app_spectrum_analysis.cpp b/firmware/application/app_spectrum_analysis.cpp new file mode 100644 index 000000000..6da566653 --- /dev/null +++ b/firmware/application/app_spectrum_analysis.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "app_spectrum_analysis.hpp" + +#include "portapack.hpp" +using namespace portapack; + +SpectrumAnalysisModel::SpectrumAnalysisModel() { + receiver_model.set_baseband_configuration({ + .mode = 4, + .sampling_rate = 20000000, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(12000000); +} diff --git a/firmware/application/app_spectrum_analysis.hpp b/firmware/application/app_spectrum_analysis.hpp index b3217db40..d725c198c 100644 --- a/firmware/application/app_spectrum_analysis.hpp +++ b/firmware/application/app_spectrum_analysis.hpp @@ -27,14 +27,7 @@ class SpectrumAnalysisModel { public: - SpectrumAnalysisModel() { - receiver_model.set_baseband_configuration({ - .mode = 4, - .sampling_rate = 20000000, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(12000000); - } + SpectrumAnalysisModel(); }; namespace ui { From 57aed55cc71c56d756ec59fc0608e713dbad9599 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 1 Dec 2015 22:39:27 -0800 Subject: [PATCH 041/452] Extract LogFile, add (dumb) logging to ERT, AIS apps. --- firmware/application/Makefile | 1 + firmware/application/app_ais.cpp | 11 ++++++- firmware/application/app_ais.hpp | 4 +++ firmware/application/app_ert.cpp | 7 ++++ firmware/application/app_ert.hpp | 4 +++ firmware/application/app_tpms.cpp | 27 ++------------- firmware/application/app_tpms.hpp | 8 ++--- firmware/application/log_file.cpp | 55 +++++++++++++++++++++++++++++++ firmware/application/log_file.hpp | 42 +++++++++++++++++++++++ 9 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 firmware/application/log_file.cpp create mode 100644 firmware/application/log_file.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index f8507d83c..3ecf44e23 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -175,6 +175,7 @@ CPPSRC = main.cpp \ app_ert.cpp \ app_spectrum_analysis.cpp \ sd_card.cpp \ + log_file.cpp \ manchester.cpp \ ../common/utility.cpp \ ../common/chibios_cpp.cpp \ diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 118323ad0..dbee7c742 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -31,10 +31,19 @@ AISModel::AISModel() { .decimation_factor = 4, }); receiver_model.set_baseband_bandwidth(1750000); + + log_file.open_for_append("ais.txt"); } baseband::ais::decoded_packet AISModel::on_packet(const AISPacketMessage& message) { - return baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); + const auto result = baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); + + if( log_file.is_ready() ) { + std::string entry = result.first + "/" + result.second + "\r\n"; + log_file.write(entry); + } + + return result; } namespace ui { diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 606aee873..19b4d0187 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -24,6 +24,7 @@ #include "ui_console.hpp" #include "message.hpp" +#include "log_file.hpp" #include "ais_baseband.hpp" @@ -32,6 +33,9 @@ public: AISModel(); baseband::ais::decoded_packet on_packet(const AISPacketMessage& message); + +private: + LogFile log_file; }; namespace ui { diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 30ef47363..9a4facb69 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -33,6 +33,8 @@ ERTModel::ERTModel() { .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); + + log_file.open_for_append("ert.txt"); } std::string ERTModel::on_packet(const ERTPacketMessage& message) { @@ -53,6 +55,11 @@ std::string ERTModel::on_packet(const ERTPacketMessage& message) { s += hex_formatted.errors; s += "\n"; + if( log_file.is_ready() ) { + std::string entry = hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; + log_file.write(entry); + } + return s; } diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index 05f0eba76..8bb461385 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -24,6 +24,7 @@ #include "ui_console.hpp" #include "message.hpp" +#include "log_file.hpp" #include @@ -32,6 +33,9 @@ public: ERTModel(); std::string on_packet(const ERTPacketMessage& message); + +private: + LogFile log_file; }; namespace ui { diff --git a/firmware/application/app_tpms.cpp b/firmware/application/app_tpms.cpp index 598cabcea..67da089de 100644 --- a/firmware/application/app_tpms.cpp +++ b/firmware/application/app_tpms.cpp @@ -39,18 +39,14 @@ TPMSModel::TPMSModel() { }); receiver_model.set_baseband_bandwidth(1750000); - open_file(); -} - -TPMSModel::~TPMSModel() { - f_close(&fil); + log_file.open_for_append("tpms.txt"); } ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); const auto hex_formatted = format_manchester(decoder); - if( !f_error(&fil) ) { + if( log_file.is_ready() ) { rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); std::string timestamp = @@ -66,29 +62,12 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { const auto tuning_frequency_str = ui::to_string_dec_uint(tuning_frequency, 10); std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; - f_puts(log.c_str(), &fil); - f_sync(&fil); + log_file.write(log); } return hex_formatted; } -void TPMSModel::open_file() { - const auto open_result = f_open(&fil, "tpms.txt", FA_WRITE | FA_OPEN_ALWAYS); - if( open_result == FR_OK ) { - const auto fil_size = f_size(&fil); - const auto seek_result = f_lseek(&fil, fil_size); - if( seek_result != FR_OK ) { - f_close(&fil); - // TODO: Error, indicate somehow. - } else { - // TODO: Indicate success. - } - } else { - // TODO: Error, indicate somehow. - } -} - namespace ui { void TPMSView::on_show() { diff --git a/firmware/application/app_tpms.hpp b/firmware/application/app_tpms.hpp index f1d431be4..962129f08 100644 --- a/firmware/application/app_tpms.hpp +++ b/firmware/application/app_tpms.hpp @@ -26,20 +26,16 @@ #include "message.hpp" #include "manchester.hpp" - -#include "ff.h" +#include "log_file.hpp" class TPMSModel { public: TPMSModel(); - ~TPMSModel(); ManchesterFormatted on_packet(const TPMSPacketMessage& message); private: - FIL fil; - - void open_file(); + LogFile log_file; }; namespace ui { diff --git a/firmware/application/log_file.cpp b/firmware/application/log_file.cpp new file mode 100644 index 000000000..82b2a0460 --- /dev/null +++ b/firmware/application/log_file.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "log_file.hpp" + +LogFile::~LogFile() { + close(); +} + +bool LogFile::open_for_append(const std::string file_path) { + const auto open_result = f_open(&f, file_path.c_str(), FA_WRITE | FA_OPEN_ALWAYS); + if( open_result == FR_OK ) { + const auto seek_result = f_lseek(&f, f_size(&f)); + if( seek_result == FR_OK ) { + return true; + } else { + close(); + } + } + + return false; +} + +bool LogFile::close() { + f_close(&f); + return true; +} + +bool LogFile::is_ready() { + return !f_error(&f); +} + +bool LogFile::write(const std::string message) { + const auto puts_result = f_puts(message.c_str(), &f); + const auto sync_result = f_sync(&f); + return (puts_result >= 0) && (sync_result == FR_OK); +} diff --git a/firmware/application/log_file.hpp b/firmware/application/log_file.hpp new file mode 100644 index 000000000..19887d000 --- /dev/null +++ b/firmware/application/log_file.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __LOG_FILE_H__ +#define __LOG_FILE_H__ + +#include + +#include "ff.h" + +class LogFile { +public: + ~LogFile(); + + bool open_for_append(const std::string file_path); + bool close(); + bool is_ready(); + bool write(const std::string message); + +private: + FIL f; +}; + +#endif/*__LOG_FILE_H__*/ From 4baf2a06f249e51857dee0d6749e9df9e9745677 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 2 Dec 2015 09:31:14 -0800 Subject: [PATCH 042/452] Move ais_baseband code to app_ais. --- firmware/application/app_ais.cpp | 329 ++++++++++++++++++++++++++++++ firmware/application/app_ais.hpp | 11 +- firmware/common/ais_baseband.cpp | 333 ------------------------------- firmware/common/ais_baseband.hpp | 4 - 4 files changed, 339 insertions(+), 338 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index dbee7c742..8efd196df 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -24,6 +24,335 @@ #include "portapack.hpp" using namespace portapack; +#include "field_reader.hpp" +#include "crc.hpp" + +// TODO: Move string formatting elsewhere!!! +#include "ui_widget.hpp" + +namespace baseband { +namespace ais { + +decoded_packet packet_decode(const std::bitset<1024>& data, const size_t data_length); + +struct BitRemap { + size_t operator()(const size_t bit_index) const { + return bit_index ^ 7; + } +}; + +struct CRCBitRemap { + size_t operator()(const size_t bit_index) const { + return bit_index; + } +}; + +using FieldReader = ::FieldReader, BitRemap>; +using CRCFieldReader = ::FieldReader, CRCBitRemap>; + +struct PacketLengthRange { + constexpr PacketLengthRange( + ) : min_bytes { 0 }, + max_bytes { 0 } + { + } + + constexpr PacketLengthRange( + const uint16_t min_bits, + const uint16_t max_bits + ) : min_bytes { static_cast(min_bits / 8U) }, + max_bytes { static_cast(max_bits / 8U) } + { + // static_assert((min_bits & 7) == 0, "minimum bits not a multiple of 8"); + // static_assert((max_bits & 7) == 0, "minimum bits not a multiple of 8"); + } + + bool contains(const size_t bit_count) const { + return !is_above(bit_count) && !is_below(bit_count); + } + + bool is_above(const size_t bit_count) const { + return (min() > bit_count); + } + + bool is_below(const size_t bit_count) const { + return (max() < bit_count); + } + + size_t min() const { + return min_bytes * 8; + } + + size_t max() const { + return max_bytes * 8; + } + +private: + const uint8_t min_bytes; + const uint8_t max_bytes; +}; + +static constexpr std::array packet_length_range { { + { 0, 0 }, // 0 + { 168, 168 }, // 1 + { 168, 168 }, // 2 + { 168, 168 }, // 3 + { 168, 168 }, // 4 + { 424, 424 }, // 5 + { 0, 0 }, // 6 + { 0, 0 }, // 7 + { 0, 1008 }, // 8 + { 0, 0 }, // 9 + { 0, 0 }, // 10 + { 0, 0 }, // 11 + { 0, 0 }, // 12 + { 0, 0 }, // 13 + { 0, 0 }, // 14 + { 0, 0 }, // 15 + { 0, 0 }, // 16 + { 0, 0 }, // 17 + { 168, 168 }, // 18 + { 0, 0 }, // 19 + { 72, 160 }, // 20 + { 272, 360 }, // 21 + { 168, 168 }, // 22 + { 160, 160 }, // 23 + { 160, 168 }, // 24 + { 0, 168 }, // 25 + { 0, 0 }, // 26 + { 0, 0 }, // 27 + { 0, 0 }, // 28 + { 0, 0 }, // 29 + { 0, 0 }, // 30 + { 0, 0 }, // 31 +} }; + +struct PacketLengthValidator { + bool operator()(const uint_fast8_t message_id, const size_t length) { + return packet_length_range[message_id].contains(length); + } +}; + +struct PacketTooLong { + bool operator()(const uint_fast8_t message_id, const size_t length) { + return packet_length_range[message_id].is_below(length); + } +}; + +struct CRCCheck { + bool operator()(const std::bitset<1024>& payload, const size_t data_length) { + CRCFieldReader field_crc { payload }; + CRC ais_fcs { 0x1021 }; + + uint16_t crc_calculated = 0xffff; + + for(size_t i=0; i(field.read(start_bit, 27) << 5) / 32; +} + +static int32_t ais_longitude_normalized( + const FieldReader& field, + const size_t start_bit +) { + // Shifting and dividing is to sign-extend the source field. + // TODO: There's probably a more elegant way to do it. + return static_cast(field.read(start_bit, 28) << 4) / 16; +} + +static std::string ais_format_latlon_normalized(const int32_t normalized) { + const int32_t t = (normalized * 5) / 3; + const int32_t degrees = t / (100 * 10000); + const int32_t fraction = std::abs(t) % (100 * 10000); + return ui::to_string_dec_int(degrees) + "." + ui::to_string_dec_int(fraction, 6, '0'); +} + +static std::string ais_format_latitude( + const FieldReader& field, + const size_t start_bit +) { + const auto value = static_cast(field.read(start_bit, 27) << 5) / 32; + return ais_format_latlon_normalized(value); +} + +static std::string ais_format_longitude( + const FieldReader& field, + const size_t start_bit +) { + const auto value = static_cast(field.read(start_bit, 28) << 4) / 16; + return ais_format_latlon_normalized(value); +} + +struct ais_datetime { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +}; + +static ais_datetime ais_get_datetime( + const FieldReader& field, + const size_t start_bit +) { + return { + static_cast(field.read(start_bit + 0, 14)), + static_cast(field.read(start_bit + 14, 4)), + static_cast(field.read(start_bit + 18, 5)), + static_cast(field.read(start_bit + 23, 5)), + static_cast(field.read(start_bit + 28, 6)), + static_cast(field.read(start_bit + 34, 6)), + }; +} + +static std::string ais_format_datetime( + const FieldReader& field, + const size_t start_bit +) { + const auto datetime = ais_get_datetime(field, start_bit); + return ui::to_string_dec_uint(datetime.year, 4) + "/" + + ui::to_string_dec_uint(datetime.month, 2, '0') + "/" + + ui::to_string_dec_uint(datetime.day, 2, '0') + " " + + ui::to_string_dec_uint(datetime.hour, 2, '0') + ":" + + ui::to_string_dec_uint(datetime.minute, 2, '0') + ":" + + ui::to_string_dec_uint(datetime.second, 2, '0'); +} + +static char ais_char_to_ascii(const uint8_t c) { + return (c ^ 32) + 32; +} + +static std::string ais_read_text( + const FieldReader& field, + const size_t start_bit, + const size_t character_count +) { + std::string result; + const size_t character_length = 6; + const size_t end_bit = start_bit + character_count * character_length; + for(size_t i=start_bit; i& payload, const size_t payload_length) { + // TODO: Unstuff here, not in baseband! + + // Subtract end flag (8 bits) - one unstuffing bit (occurs during end flag). + const size_t data_and_fcs_length = payload_length - 7; + + if( data_and_fcs_length < 38 ) { + return { "short " + ui::to_string_dec_uint(data_and_fcs_length, 3), "" }; + } + + const size_t extra_bits = data_and_fcs_length & 7; + if( extra_bits != 0 ) { + return { "extra bits " + ui::to_string_dec_uint(data_and_fcs_length, 3), "" }; + } + + FieldReader field { payload }; + + const auto message_id = field.read(0, 6); + + const size_t data_length = data_and_fcs_length - 16; + PacketLengthValidator packet_length_valid; + if( !packet_length_valid(message_id, data_length) ) { + return { "bad length " + ui::to_string_dec_uint(data_length, 3), "" }; + } + + CRCCheck crc_ok; + if( !crc_ok(payload, data_length) ) { + return { "crc", "" }; + } + + const auto source_id = field.read(8, 30); + std::string result { ui::to_string_dec_uint(message_id, 2) + " " + ui::to_string_dec_uint(source_id, 10) }; + + switch(message_id) { + case 1: + case 2: + case 3: + { + const auto navigational_status = field.read(38, 4); + result += " " + ais_format_navigational_status(navigational_status); + result += " " + ais_format_latlon_normalized(ais_latitude_normalized(field, 89)); + result += " " + ais_format_latlon_normalized(ais_longitude_normalized(field, 61)); + } + break; + + case 4: + { + result += " " + ais_format_datetime(field, 38); + result += " " + ais_format_latlon_normalized(ais_latitude_normalized(field, 107)); + result += " " + ais_format_latlon_normalized(ais_longitude_normalized(field, 79)); + } + break; + + case 5: + { + const auto call_sign = ais_read_text(field, 70, 7); + const auto name = ais_read_text(field, 112, 20); + const auto destination = ais_read_text(field, 302, 20); + result += " \"" + call_sign + "\" \"" + name + "\" \"" + destination + "\""; + } + break; + + case 21: + { + const auto name = ais_read_text(field, 43, 20); + result += " \"" + name + "\" " + ais_format_latitude(field, 192) + " " + ais_format_longitude(field, 164); + } + break; + + default: + break; + } + + return { "OK", result }; +} + +} /* namespace ais */ +} /* namespace baseband */ + AISModel::AISModel() { receiver_model.set_baseband_configuration({ .mode = 3, diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 19b4d0187..5e5e315b6 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -26,7 +26,16 @@ #include "message.hpp" #include "log_file.hpp" -#include "ais_baseband.hpp" +#include +#include + +namespace baseband { +namespace ais { + +using decoded_packet = std::pair; + +} /* namespace ais */ +} /* namespace baseband */ class AISModel { public: diff --git a/firmware/common/ais_baseband.cpp b/firmware/common/ais_baseband.cpp index dcd414918..d137a6a55 100644 --- a/firmware/common/ais_baseband.cpp +++ b/firmware/common/ais_baseband.cpp @@ -20,336 +20,3 @@ */ #include "ais_baseband.hpp" - -#include -#include -#include -#include - -#include "field_reader.hpp" -#include "crc.hpp" - -// TODO: Move string formatting elsewhere!!! -#include "ui_widget.hpp" - -namespace baseband { - -namespace ais { - -struct BitRemap { - size_t operator()(const size_t bit_index) const { - return bit_index ^ 7; - } -}; - -struct CRCBitRemap { - size_t operator()(const size_t bit_index) const { - return bit_index; - } -}; - -using FieldReader = ::FieldReader, BitRemap>; -using CRCFieldReader = ::FieldReader, CRCBitRemap>; - -struct PacketLengthRange { - constexpr PacketLengthRange( - ) : min_bytes { 0 }, - max_bytes { 0 } - { - } - - constexpr PacketLengthRange( - const uint16_t min_bits, - const uint16_t max_bits - ) : min_bytes { static_cast(min_bits / 8U) }, - max_bytes { static_cast(max_bits / 8U) } - { - // static_assert((min_bits & 7) == 0, "minimum bits not a multiple of 8"); - // static_assert((max_bits & 7) == 0, "minimum bits not a multiple of 8"); - } - - bool contains(const size_t bit_count) const { - return !is_above(bit_count) && !is_below(bit_count); - } - - bool is_above(const size_t bit_count) const { - return (min() > bit_count); - } - - bool is_below(const size_t bit_count) const { - return (max() < bit_count); - } - - size_t min() const { - return min_bytes * 8; - } - - size_t max() const { - return max_bytes * 8; - } - -private: - const uint8_t min_bytes; - const uint8_t max_bytes; -}; - -static constexpr std::array packet_length_range { { - { 0, 0 }, // 0 - { 168, 168 }, // 1 - { 168, 168 }, // 2 - { 168, 168 }, // 3 - { 168, 168 }, // 4 - { 424, 424 }, // 5 - { 0, 0 }, // 6 - { 0, 0 }, // 7 - { 0, 1008 }, // 8 - { 0, 0 }, // 9 - { 0, 0 }, // 10 - { 0, 0 }, // 11 - { 0, 0 }, // 12 - { 0, 0 }, // 13 - { 0, 0 }, // 14 - { 0, 0 }, // 15 - { 0, 0 }, // 16 - { 0, 0 }, // 17 - { 168, 168 }, // 18 - { 0, 0 }, // 19 - { 72, 160 }, // 20 - { 272, 360 }, // 21 - { 168, 168 }, // 22 - { 160, 160 }, // 23 - { 160, 168 }, // 24 - { 0, 168 }, // 25 - { 0, 0 }, // 26 - { 0, 0 }, // 27 - { 0, 0 }, // 28 - { 0, 0 }, // 29 - { 0, 0 }, // 30 - { 0, 0 }, // 31 -} }; - -struct PacketLengthValidator { - bool operator()(const uint_fast8_t message_id, const size_t length) { - return packet_length_range[message_id].contains(length); - } -}; - -struct PacketTooLong { - bool operator()(const uint_fast8_t message_id, const size_t length) { - return packet_length_range[message_id].is_below(length); - } -}; - -struct CRCCheck { - bool operator()(const std::bitset<1024>& payload, const size_t data_length) { - CRCFieldReader field_crc { payload }; - CRC ais_fcs { 0x1021 }; - - uint16_t crc_calculated = 0xffff; - - for(size_t i=0; i(field.read(start_bit, 27) << 5) / 32; -} - -static int32_t ais_longitude_normalized( - const FieldReader& field, - const size_t start_bit -) { - // Shifting and dividing is to sign-extend the source field. - // TODO: There's probably a more elegant way to do it. - return static_cast(field.read(start_bit, 28) << 4) / 16; -} - -static std::string ais_format_latlon_normalized(const int32_t normalized) { - const int32_t t = (normalized * 5) / 3; - const int32_t degrees = t / (100 * 10000); - const int32_t fraction = std::abs(t) % (100 * 10000); - return ui::to_string_dec_int(degrees) + "." + ui::to_string_dec_int(fraction, 6, '0'); -} - -static std::string ais_format_latitude( - const FieldReader& field, - const size_t start_bit -) { - const auto value = static_cast(field.read(start_bit, 27) << 5) / 32; - return ais_format_latlon_normalized(value); -} - -static std::string ais_format_longitude( - const FieldReader& field, - const size_t start_bit -) { - const auto value = static_cast(field.read(start_bit, 28) << 4) / 16; - return ais_format_latlon_normalized(value); -} - -struct ais_datetime { - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; -}; - -static ais_datetime ais_get_datetime( - const FieldReader& field, - const size_t start_bit -) { - return { - static_cast(field.read(start_bit + 0, 14)), - static_cast(field.read(start_bit + 14, 4)), - static_cast(field.read(start_bit + 18, 5)), - static_cast(field.read(start_bit + 23, 5)), - static_cast(field.read(start_bit + 28, 6)), - static_cast(field.read(start_bit + 34, 6)), - }; -} - -static std::string ais_format_datetime( - const FieldReader& field, - const size_t start_bit -) { - const auto datetime = ais_get_datetime(field, start_bit); - return ui::to_string_dec_uint(datetime.year, 4) + "/" + - ui::to_string_dec_uint(datetime.month, 2, '0') + "/" + - ui::to_string_dec_uint(datetime.day, 2, '0') + " " + - ui::to_string_dec_uint(datetime.hour, 2, '0') + ":" + - ui::to_string_dec_uint(datetime.minute, 2, '0') + ":" + - ui::to_string_dec_uint(datetime.second, 2, '0'); -} - -static char ais_char_to_ascii(const uint8_t c) { - return (c ^ 32) + 32; -} - -static std::string ais_read_text( - const FieldReader& field, - const size_t start_bit, - const size_t character_count -) { - std::string result; - const size_t character_length = 6; - const size_t end_bit = start_bit + character_count * character_length; - for(size_t i=start_bit; i& payload, const size_t payload_length) { - // TODO: Unstuff here, not in baseband! - - // Subtract end flag (8 bits) - one unstuffing bit (occurs during end flag). - const size_t data_and_fcs_length = payload_length - 7; - - if( data_and_fcs_length < 38 ) { - return { "short " + ui::to_string_dec_uint(data_and_fcs_length, 3), "" }; - } - - const size_t extra_bits = data_and_fcs_length & 7; - if( extra_bits != 0 ) { - return { "extra bits " + ui::to_string_dec_uint(data_and_fcs_length, 3), "" }; - } - - FieldReader field { payload }; - - const auto message_id = field.read(0, 6); - - const size_t data_length = data_and_fcs_length - 16; - PacketLengthValidator packet_length_valid; - if( !packet_length_valid(message_id, data_length) ) { - return { "bad length " + ui::to_string_dec_uint(data_length, 3), "" }; - } - - CRCCheck crc_ok; - if( !crc_ok(payload, data_length) ) { - return { "crc", "" }; - } - - const auto source_id = field.read(8, 30); - std::string result { ui::to_string_dec_uint(message_id, 2) + " " + ui::to_string_dec_uint(source_id, 10) }; - - switch(message_id) { - case 1: - case 2: - case 3: - { - const auto navigational_status = field.read(38, 4); - result += " " + ais_format_navigational_status(navigational_status); - result += " " + ais_format_latlon_normalized(ais_latitude_normalized(field, 89)); - result += " " + ais_format_latlon_normalized(ais_longitude_normalized(field, 61)); - } - break; - - case 4: - { - result += " " + ais_format_datetime(field, 38); - result += " " + ais_format_latlon_normalized(ais_latitude_normalized(field, 107)); - result += " " + ais_format_latlon_normalized(ais_longitude_normalized(field, 79)); - } - break; - - case 5: - { - const auto call_sign = ais_read_text(field, 70, 7); - const auto name = ais_read_text(field, 112, 20); - const auto destination = ais_read_text(field, 302, 20); - result += " \"" + call_sign + "\" \"" + name + "\" \"" + destination + "\""; - } - break; - - case 21: - { - const auto name = ais_read_text(field, 43, 20); - result += " \"" + name + "\" " + ais_format_latitude(field, 192) + " " + ais_format_longitude(field, 164); - } - break; - - default: - break; - } - - return { "OK", result }; -} - -} /* namespace ais */ -} /* namespace baseband */ diff --git a/firmware/common/ais_baseband.hpp b/firmware/common/ais_baseband.hpp index 2be4753b0..c693d610d 100644 --- a/firmware/common/ais_baseband.hpp +++ b/firmware/common/ais_baseband.hpp @@ -57,10 +57,6 @@ constexpr std::array, 32> rrc_taps_76k8_4t_p { { { 1.7970187432e-03f, -7.4434953528e-04f }, { 4.6850211151e-03f, -9.3190864122e-04f }, } }; -using decoded_packet = std::pair; - -decoded_packet packet_decode(const std::bitset<1024>& data, const size_t data_length); - } /* namespace ais */ } /* namespace baseband */ From b8ee19f8e67238c49ad285ec17a9dd697b1ee1bd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 2 Dec 2015 12:16:39 -0800 Subject: [PATCH 043/452] AIS: Large refactor to separate packet decode from UI/log formatting. --- firmware/application/app_ais.cpp | 277 ++++++++++++++----------------- firmware/application/app_ais.hpp | 61 ++++++- 2 files changed, 184 insertions(+), 154 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 8efd196df..c18b00f62 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -24,7 +24,6 @@ #include "portapack.hpp" using namespace portapack; -#include "field_reader.hpp" #include "crc.hpp" // TODO: Move string formatting elsewhere!!! @@ -33,21 +32,12 @@ using namespace portapack; namespace baseband { namespace ais { -decoded_packet packet_decode(const std::bitset<1024>& data, const size_t data_length); - -struct BitRemap { - size_t operator()(const size_t bit_index) const { - return bit_index ^ 7; - } -}; - struct CRCBitRemap { size_t operator()(const size_t bit_index) const { return bit_index; } }; -using FieldReader = ::FieldReader, BitRemap>; using CRCFieldReader = ::FieldReader, CRCBitRemap>; struct PacketLengthRange { @@ -158,75 +148,16 @@ struct CRCCheck { } }; -static int32_t ais_latitude_normalized( - const FieldReader& field, - const size_t start_bit -) { - // Shifting and dividing is to sign-extend the source field. - // TODO: There's probably a more elegant way to do it. - return static_cast(field.read(start_bit, 27) << 5) / 32; -} - -static int32_t ais_longitude_normalized( - const FieldReader& field, - const size_t start_bit -) { - // Shifting and dividing is to sign-extend the source field. - // TODO: There's probably a more elegant way to do it. - return static_cast(field.read(start_bit, 28) << 4) / 16; -} - -static std::string ais_format_latlon_normalized(const int32_t normalized) { +static std::string format_latlon_normalized(const int32_t normalized) { const int32_t t = (normalized * 5) / 3; const int32_t degrees = t / (100 * 10000); const int32_t fraction = std::abs(t) % (100 * 10000); return ui::to_string_dec_int(degrees) + "." + ui::to_string_dec_int(fraction, 6, '0'); } -static std::string ais_format_latitude( - const FieldReader& field, - const size_t start_bit +static std::string format_datetime( + const DateTime& datetime ) { - const auto value = static_cast(field.read(start_bit, 27) << 5) / 32; - return ais_format_latlon_normalized(value); -} - -static std::string ais_format_longitude( - const FieldReader& field, - const size_t start_bit -) { - const auto value = static_cast(field.read(start_bit, 28) << 4) / 16; - return ais_format_latlon_normalized(value); -} - -struct ais_datetime { - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; -}; - -static ais_datetime ais_get_datetime( - const FieldReader& field, - const size_t start_bit -) { - return { - static_cast(field.read(start_bit + 0, 14)), - static_cast(field.read(start_bit + 14, 4)), - static_cast(field.read(start_bit + 18, 5)), - static_cast(field.read(start_bit + 23, 5)), - static_cast(field.read(start_bit + 28, 6)), - static_cast(field.read(start_bit + 34, 6)), - }; -} - -static std::string ais_format_datetime( - const FieldReader& field, - const size_t start_bit -) { - const auto datetime = ais_get_datetime(field, start_bit); return ui::to_string_dec_uint(datetime.year, 4) + "/" + ui::to_string_dec_uint(datetime.month, 2, '0') + "/" + ui::to_string_dec_uint(datetime.day, 2, '0') + " " + @@ -235,26 +166,7 @@ static std::string ais_format_datetime( ui::to_string_dec_uint(datetime.second, 2, '0'); } -static char ais_char_to_ascii(const uint8_t c) { - return (c ^ 32) + 32; -} - -static std::string ais_read_text( - const FieldReader& field, - const size_t start_bit, - const size_t character_count -) { - std::string result; - const size_t character_length = 6; - const size_t end_bit = start_bit + character_count * character_length; - for(size_t i=start_bit; i& payload, const size_t payload_length) { - // TODO: Unstuff here, not in baseband! +static char char_to_ascii(const uint8_t c) { + return (c ^ 32) + 32; +} +size_t Packet::length() const { + return payload_length_; +} + +bool Packet::is_valid() const { // Subtract end flag (8 bits) - one unstuffing bit (occurs during end flag). - const size_t data_and_fcs_length = payload_length - 7; + const size_t data_and_fcs_length = payload_length_ - 7; if( data_and_fcs_length < 38 ) { - return { "short " + ui::to_string_dec_uint(data_and_fcs_length, 3), "" }; + return false; } const size_t extra_bits = data_and_fcs_length & 7; if( extra_bits != 0 ) { - return { "extra bits " + ui::to_string_dec_uint(data_and_fcs_length, 3), "" }; + return false; } - FieldReader field { payload }; - - const auto message_id = field.read(0, 6); - const size_t data_length = data_and_fcs_length - 16; PacketLengthValidator packet_length_valid; - if( !packet_length_valid(message_id, data_length) ) { - return { "bad length " + ui::to_string_dec_uint(data_length, 3), "" }; + if( !packet_length_valid(message_id(), data_length) ) { + return false; } CRCCheck crc_ok; - if( !crc_ok(payload, data_length) ) { - return { "crc", "" }; + if( !crc_ok(payload_, data_length) ) { + return false; } - const auto source_id = field.read(8, 30); - std::string result { ui::to_string_dec_uint(message_id, 2) + " " + ui::to_string_dec_uint(source_id, 10) }; + return true; +} - switch(message_id) { - case 1: - case 2: - case 3: - { - const auto navigational_status = field.read(38, 4); - result += " " + ais_format_navigational_status(navigational_status); - result += " " + ais_format_latlon_normalized(ais_latitude_normalized(field, 89)); - result += " " + ais_format_latlon_normalized(ais_longitude_normalized(field, 61)); - } - break; +uint32_t Packet::message_id() const { + return field_.read(0, 6); +} - case 4: - { - result += " " + ais_format_datetime(field, 38); - result += " " + ais_format_latlon_normalized(ais_latitude_normalized(field, 107)); - result += " " + ais_format_latlon_normalized(ais_longitude_normalized(field, 79)); - } - break; +uint32_t Packet::source_id() const { + return field_.read(8, 30); +} - case 5: - { - const auto call_sign = ais_read_text(field, 70, 7); - const auto name = ais_read_text(field, 112, 20); - const auto destination = ais_read_text(field, 302, 20); - result += " \"" + call_sign + "\" \"" + name + "\" \"" + destination + "\""; - } - break; +uint32_t Packet::read(const size_t start_bit, const size_t length) const { + return field_.read(start_bit, length); +} - case 21: - { - const auto name = ais_read_text(field, 43, 20); - result += " \"" + name + "\" " + ais_format_latitude(field, 192) + " " + ais_format_longitude(field, 164); - } - break; +std::string Packet::text( + const size_t start_bit, + const size_t character_count +) const { + std::string result; + const size_t character_length = 6; + const size_t end_bit = start_bit + character_count * character_length; + for(size_t i=start_bit; i(field_.read(start_bit + 0, 14)), + static_cast(field_.read(start_bit + 14, 4)), + static_cast(field_.read(start_bit + 18, 5)), + static_cast(field_.read(start_bit + 23, 5)), + static_cast(field_.read(start_bit + 28, 6)), + static_cast(field_.read(start_bit + 34, 6)), + }; +} + +Latitude Packet::latitude(const size_t start_bit) const { + // Shifting and dividing is to sign-extend the source field. + // TODO: There's probably a more elegant way to do it. + return static_cast(field_.read(start_bit, 27) << 5) / 32; +} + +Longitude Packet::longitude(const size_t start_bit) const { + // Shifting and dividing is to sign-extend the source field. + // TODO: There's probably a more elegant way to do it. + return static_cast(field_.read(start_bit, 28) << 4) / 16; } } /* namespace ais */ @@ -364,15 +284,27 @@ AISModel::AISModel() { log_file.open_for_append("ais.txt"); } -baseband::ais::decoded_packet AISModel::on_packet(const AISPacketMessage& message) { - const auto result = baseband::ais::packet_decode(message.packet.payload, message.packet.bits_received); +bool AISModel::on_packet(const baseband::ais::Packet& packet) { + // TODO: Unstuff here, not in baseband! + + if( !packet.is_valid() ) { + return false; + } if( log_file.is_ready() ) { - std::string entry = result.first + "/" + result.second + "\r\n"; + std::string entry; + entry.reserve((packet.length() + 3) / 4); + + for(size_t i=0; i= 10) ? ('W' + nibble) : ('0' + nibble); + } + + entry += "\r\n"; log_file.write(entry); } - return result; + return true; } namespace ui { @@ -384,7 +316,10 @@ void AISView::on_show() { message_map.register_handler(Message::ID::AISPacket, [this](Message* const p) { const auto message = static_cast(p); - this->log(this->model.on_packet(*message)); + const baseband::ais::Packet packet { message->packet.payload, message->packet.bits_received }; + if( this->model.on_packet(packet) ) { + this->log(packet); + } } ); } @@ -396,10 +331,50 @@ void AISView::on_hide() { Console::on_hide(); } -void AISView::log(const baseband::ais::decoded_packet decoded) { - if( decoded.first == "OK" ) { - writeln(decoded.second); +void AISView::log(const baseband::ais::Packet& packet) { + std::string result { ui::to_string_dec_uint(packet.message_id(), 2) + " " + ui::to_string_dec_uint(packet.source_id(), 10) }; + + switch(packet.message_id()) { + case 1: + case 2: + case 3: + { + const auto navigational_status = packet.read(38, 4); + result += " " + baseband::ais::format_navigational_status(navigational_status); + result += " " + baseband::ais::format_latlon_normalized(packet.latitude(89)); + result += " " + baseband::ais::format_latlon_normalized(packet.longitude(61)); + } + break; + + case 4: + { + result += " " + baseband::ais::format_datetime(packet.datetime(38)); + result += " " + baseband::ais::format_latlon_normalized(packet.latitude(107)); + result += " " + baseband::ais::format_latlon_normalized(packet.longitude(79)); + } + break; + + case 5: + { + const auto call_sign = packet.text(70, 7); + const auto name = packet.text(112, 20); + const auto destination = packet.text(302, 20); + result += " \"" + call_sign + "\" \"" + name + "\" \"" + destination + "\""; + } + break; + + case 21: + { + const auto name = packet.text(43, 20); + result += " \"" + name + "\" " + baseband::ais::format_latlon_normalized(packet.latitude(192)) + " " + baseband::ais::format_latlon_normalized(packet.longitude(164)); + } + break; + + default: + break; } + + writeln(result); } } /* namespace ui */ diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 5e5e315b6..ffca34437 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -25,14 +25,69 @@ #include "ui_console.hpp" #include "message.hpp" #include "log_file.hpp" +#include "field_reader.hpp" +#include +#include #include +#include #include namespace baseband { namespace ais { -using decoded_packet = std::pair; +struct BitRemap { + size_t operator()(const size_t bit_index) const { + return bit_index ^ 7; + } +}; + +using FieldReader = ::FieldReader, BitRemap>; + +struct DateTime { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +}; + +using Latitude = int32_t; +using Longitude = int32_t; + +class Packet { +public: + constexpr Packet( + const std::bitset<1024>& payload, + const size_t payload_length + ) : payload_ { payload }, + payload_length_ { payload_length }, + field_ { payload_ } + { + } + + size_t length() const; + + bool is_valid() const; + + uint32_t message_id() const; + uint32_t source_id() const; + + uint32_t read(const size_t start_bit, const size_t length) const; + + std::string text(const size_t start_bit, const size_t character_count) const; + + DateTime datetime(const size_t start_bit) const; + + Latitude latitude(const size_t start_bit) const; + Longitude longitude(const size_t start_bit) const; + +private: + const std::bitset<1024> payload_; + const size_t payload_length_; + const FieldReader field_; +}; } /* namespace ais */ } /* namespace baseband */ @@ -41,7 +96,7 @@ class AISModel { public: AISModel(); - baseband::ais::decoded_packet on_packet(const AISPacketMessage& message); + bool on_packet(const baseband::ais::Packet& packet); private: LogFile log_file; @@ -57,7 +112,7 @@ public: private: AISModel model; - void log(const baseband::ais::decoded_packet decoded); + void log(const baseband::ais::Packet& packet); }; } /* namespace ui */ From d8c59e2ce296acf8e9deaaca1e0715ce03d89b7f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 2 Dec 2015 13:23:29 -0800 Subject: [PATCH 044/452] Zero pad years < 1000 to four digits. --- firmware/application/app_ais.cpp | 2 +- firmware/application/app_tpms.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index c18b00f62..89b33ac28 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -158,7 +158,7 @@ static std::string format_latlon_normalized(const int32_t normalized) { static std::string format_datetime( const DateTime& datetime ) { - return ui::to_string_dec_uint(datetime.year, 4) + "/" + + return ui::to_string_dec_uint(datetime.year, 4, '0') + "/" + ui::to_string_dec_uint(datetime.month, 2, '0') + "/" + ui::to_string_dec_uint(datetime.day, 2, '0') + " " + ui::to_string_dec_uint(datetime.hour, 2, '0') + ":" + diff --git a/firmware/application/app_tpms.cpp b/firmware/application/app_tpms.cpp index 67da089de..d159cecfb 100644 --- a/firmware/application/app_tpms.cpp +++ b/firmware/application/app_tpms.cpp @@ -50,7 +50,7 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); std::string timestamp = - ui::to_string_dec_uint(datetime.year(), 4) + + ui::to_string_dec_uint(datetime.year(), 4, '0') + ui::to_string_dec_uint(datetime.month(), 2, '0') + ui::to_string_dec_uint(datetime.day(), 2, '0') + ui::to_string_dec_uint(datetime.hour(), 2, '0') + From 76845c4335320d87b012eb12ebbb63a5301ea2a9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 2 Dec 2015 13:38:17 -0800 Subject: [PATCH 045/452] Extract to_string_* functions from ui_widget. --- firmware/application/Makefile | 1 + firmware/application/app_ais.cpp | 19 ++- firmware/application/app_tpms.cpp | 17 ++- firmware/application/manchester.cpp | 7 +- firmware/application/string_format.cpp | 114 ++++++++++++++++++ firmware/application/string_format.hpp | 34 ++++++ .../application/ui_baseband_stats_view.cpp | 2 + firmware/application/ui_debug.cpp | 1 + firmware/application/ui_receiver.cpp | 2 + firmware/application/ui_spectrum.hpp | 2 + firmware/common/ui_widget.cpp | 95 +-------------- firmware/common/ui_widget.hpp | 6 - 12 files changed, 178 insertions(+), 122 deletions(-) create mode 100644 firmware/application/string_format.cpp create mode 100644 firmware/application/string_format.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 3ecf44e23..403056dd9 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -177,6 +177,7 @@ CPPSRC = main.cpp \ sd_card.cpp \ log_file.cpp \ manchester.cpp \ + string_format.cpp \ ../common/utility.cpp \ ../common/chibios_cpp.cpp \ ../common/debug.cpp \ diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 89b33ac28..a4da213eb 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -26,8 +26,7 @@ using namespace portapack; #include "crc.hpp" -// TODO: Move string formatting elsewhere!!! -#include "ui_widget.hpp" +#include "string_format.hpp" namespace baseband { namespace ais { @@ -152,18 +151,18 @@ static std::string format_latlon_normalized(const int32_t normalized) { const int32_t t = (normalized * 5) / 3; const int32_t degrees = t / (100 * 10000); const int32_t fraction = std::abs(t) % (100 * 10000); - return ui::to_string_dec_int(degrees) + "." + ui::to_string_dec_int(fraction, 6, '0'); + return to_string_dec_int(degrees) + "." + to_string_dec_int(fraction, 6, '0'); } static std::string format_datetime( const DateTime& datetime ) { - return ui::to_string_dec_uint(datetime.year, 4, '0') + "/" + - ui::to_string_dec_uint(datetime.month, 2, '0') + "/" + - ui::to_string_dec_uint(datetime.day, 2, '0') + " " + - ui::to_string_dec_uint(datetime.hour, 2, '0') + ":" + - ui::to_string_dec_uint(datetime.minute, 2, '0') + ":" + - ui::to_string_dec_uint(datetime.second, 2, '0'); + return to_string_dec_uint(datetime.year, 4, '0') + "/" + + to_string_dec_uint(datetime.month, 2, '0') + "/" + + to_string_dec_uint(datetime.day, 2, '0') + " " + + to_string_dec_uint(datetime.hour, 2, '0') + ":" + + to_string_dec_uint(datetime.minute, 2, '0') + ":" + + to_string_dec_uint(datetime.second, 2, '0'); } static std::string format_navigational_status(const unsigned int value) { @@ -332,7 +331,7 @@ void AISView::on_hide() { } void AISView::log(const baseband::ais::Packet& packet) { - std::string result { ui::to_string_dec_uint(packet.message_id(), 2) + " " + ui::to_string_dec_uint(packet.source_id(), 10) }; + std::string result { to_string_dec_uint(packet.message_id(), 2) + " " + to_string_dec_uint(packet.source_id(), 10) }; switch(packet.message_id()) { case 1: diff --git a/firmware/application/app_tpms.cpp b/firmware/application/app_tpms.cpp index d159cecfb..db74c108b 100644 --- a/firmware/application/app_tpms.cpp +++ b/firmware/application/app_tpms.cpp @@ -28,8 +28,7 @@ using namespace portapack; // #include "lpc43xx_cpp.hpp" // using namespace lpc43xx; -// TODO: SERIOUSLY!? Including this, just to use to_string_hex?! Refactor!!!1 -#include "ui_widget.hpp" +#include "string_format.hpp" TPMSModel::TPMSModel() { receiver_model.set_baseband_configuration({ @@ -50,16 +49,16 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); std::string timestamp = - ui::to_string_dec_uint(datetime.year(), 4, '0') + - ui::to_string_dec_uint(datetime.month(), 2, '0') + - ui::to_string_dec_uint(datetime.day(), 2, '0') + - ui::to_string_dec_uint(datetime.hour(), 2, '0') + - ui::to_string_dec_uint(datetime.minute(), 2, '0') + - ui::to_string_dec_uint(datetime.second(), 2, '0'); + to_string_dec_uint(datetime.year(), 4, '0') + + to_string_dec_uint(datetime.month(), 2, '0') + + to_string_dec_uint(datetime.day(), 2, '0') + + to_string_dec_uint(datetime.hour(), 2, '0') + + to_string_dec_uint(datetime.minute(), 2, '0') + + to_string_dec_uint(datetime.second(), 2, '0'); const auto tuning_frequency = receiver_model.tuning_frequency(); // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! - const auto tuning_frequency_str = ui::to_string_dec_uint(tuning_frequency, 10); + const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; log_file.write(log); diff --git a/firmware/application/manchester.cpp b/firmware/application/manchester.cpp index 877fc03b7..8a9aa7241 100644 --- a/firmware/application/manchester.cpp +++ b/firmware/application/manchester.cpp @@ -21,8 +21,7 @@ #include "manchester.hpp" -// TODO: SERIOUSLY!? Including this, just to use to_string_hex?! Refactor!!!1 -#include "ui_widget.hpp" +#include "string_format.hpp" ManchesterDecoder::DecodedSymbol ManchesterDecoder::operator[](const size_t index) const { const size_t encoded_index = index * 2; @@ -63,8 +62,8 @@ ManchesterFormatted format_manchester( error |= symbol.error; if( (i & 3) == 3 ) { - hex_data += ui::to_string_hex(data & 0xf, 1); - hex_error += ui::to_string_hex(error & 0xf, 1); + hex_data += to_string_hex(data & 0xf, 1); + hex_error += to_string_hex(error & 0xf, 1); } } diff --git a/firmware/application/string_format.cpp b/firmware/application/string_format.cpp new file mode 100644 index 000000000..be5f988c0 --- /dev/null +++ b/firmware/application/string_format.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "string_format.hpp" + +static char* to_string_dec_uint_internal( + char* p, + uint32_t n +) { + *p = 0; + auto q = p; + + do { + const uint32_t d = n % 10; + const char c = d + 48; + *(--q) = c; + n /= 10; + } while( n != 0 ); + + return q; +} + +static char* to_string_dec_uint_pad_internal( + char* const term, + const uint32_t n, + const int32_t l, + const char fill +) { + auto q = to_string_dec_uint_internal(term, n); + + if( fill ) { + while( (term - q) < l ) { + *(--q) = fill; + } + } + + return q; +} + +std::string to_string_dec_uint( + const uint32_t n, + const int32_t l, + const char fill +) { + char p[16]; + auto term = p + sizeof(p) - 1; + auto q = to_string_dec_uint_pad_internal(term, n, l, fill); + + // Right justify. + while( (term - q) < l ) { + *(--q) = ' '; + } + + return q; +} + +std::string to_string_dec_int( + const int32_t n, + const int32_t l, + const char fill +) { + const size_t negative = (n < 0) ? 1 : 0; + uint32_t n_abs = negative ? -n : n; + + char p[16]; + auto term = p + sizeof(p) - 1; + auto q = to_string_dec_uint_pad_internal(term, n_abs, l - negative, fill); + + // Add sign. + if( negative ) { + *(--q) = '-'; + } + + // Right justify. + while( (term - q) < l ) { + *(--q) = ' '; + } + + return q; +} + +static void to_string_hex_internal(char* p, const uint32_t n, const int32_t l) { + const uint32_t d = n & 0xf; + p[l] = (d > 9) ? (d + 87) : (d + 48); + if( l > 0 ) { + to_string_hex_internal(p, n >> 4, l - 1); + } +} + +std::string to_string_hex(const uint32_t n, const int32_t l) { + char p[16]; + to_string_hex_internal(p, n, l - 1); + p[l] = 0; + return p; +} + diff --git a/firmware/application/string_format.hpp b/firmware/application/string_format.hpp new file mode 100644 index 000000000..0eba017f5 --- /dev/null +++ b/firmware/application/string_format.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __STRING_FORMAT_H__ +#define __STRING_FORMAT_H__ + +#include +#include + +// TODO: Allow l=0 to not fill/justify? Already using this way in ui_spectrum.hpp... + +std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = 0); +std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0); +std::string to_string_hex(const uint32_t n, const int32_t l = 0); + +#endif/*__STRING_FORMAT_H__*/ diff --git a/firmware/application/ui_baseband_stats_view.cpp b/firmware/application/ui_baseband_stats_view.cpp index fcf0816ee..76cccb5a9 100644 --- a/firmware/application/ui_baseband_stats_view.cpp +++ b/firmware/application/ui_baseband_stats_view.cpp @@ -27,6 +27,8 @@ #include "hackrf_hal.hpp" using namespace hackrf::one; +#include "string_format.hpp" + namespace ui { /* BasebandStatsView *****************************************************/ diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 28d99abf3..4441268d3 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -24,6 +24,7 @@ #include "ch.h" #include "radio.hpp" +#include "string_format.hpp" namespace ui { diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 9af664762..421442e13 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -24,6 +24,8 @@ #include "portapack.hpp" using namespace portapack; +#include "string_format.hpp" + #include "app_analog_audio.hpp" #include "app_ais.hpp" #include "app_tpms.hpp" diff --git a/firmware/application/ui_spectrum.hpp b/firmware/application/ui_spectrum.hpp index 6a10088f4..fe2fab913 100644 --- a/firmware/application/ui_spectrum.hpp +++ b/firmware/application/ui_spectrum.hpp @@ -35,6 +35,8 @@ using namespace portapack; #include #include +#include "string_format.hpp" + namespace ui { namespace spectrum { diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 79ddafe14..d2b040dbf 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -26,6 +26,8 @@ #include #include +#include "string_format.hpp" + namespace ui { static bool ui_dirty = true; @@ -42,99 +44,6 @@ bool is_dirty() { return ui_dirty; } -constexpr size_t to_string_max_length = 16; - -static char* to_string_dec_uint_internal( - char* p, - uint32_t n -) { - *p = 0; - auto q = p; - - do { - const uint32_t d = n % 10; - const char c = d + 48; - *(--q) = c; - n /= 10; - } while( n != 0 ); - - return q; -} - -static char* to_string_dec_uint_pad_internal( - char* const term, - const uint32_t n, - const int32_t l, - const char fill -) { - auto q = to_string_dec_uint_internal(term, n); - - if( fill ) { - while( (term - q) < l ) { - *(--q) = fill; - } - } - - return q; -} - -std::string to_string_dec_uint( - const uint32_t n, - const int32_t l, - const char fill -) { - char p[16]; - auto term = p + sizeof(p) - 1; - auto q = to_string_dec_uint_pad_internal(term, n, l, fill); - - // Right justify. - while( (term - q) < l ) { - *(--q) = ' '; - } - - return q; -} - -std::string to_string_dec_int( - const int32_t n, - const int32_t l, - const char fill -) { - const size_t negative = (n < 0) ? 1 : 0; - uint32_t n_abs = negative ? -n : n; - - char p[16]; - auto term = p + sizeof(p) - 1; - auto q = to_string_dec_uint_pad_internal(term, n_abs, l - negative, fill); - - // Add sign. - if( negative ) { - *(--q) = '-'; - } - - // Right justify. - while( (term - q) < l ) { - *(--q) = ' '; - } - - return q; -} - -static void to_string_hex_internal(char* p, const uint32_t n, const int32_t l) { - const uint32_t d = n & 0xf; - p[l] = (d > 9) ? (d + 87) : (d + 48); - if( l > 0 ) { - to_string_hex_internal(p, n >> 4, l - 1); - } -} - -std::string to_string_hex(const uint32_t n, const int32_t l) { - char p[16]; - to_string_hex_internal(p, n, l - 1); - p[l] = 0; - return p; -} - /* Widget ****************************************************************/ Point Widget::screen_pos() { diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index f54bc6778..2426e409e 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -41,12 +41,6 @@ void dirty_set(); void dirty_clear(); bool is_dirty(); -// TODO: Move these somewhere else! -// TODO: Allow l=0 to not fill/justify? Already using this way in ui_spectrum.hpp... -std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = 0); -std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0); -std::string to_string_hex(const uint32_t n, const int32_t l = 0); - class Context { public: FocusManager& focus_manager() { From bfcd25d85725ffcdb3dc08184cf6e878481727a3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 2 Dec 2015 14:05:25 -0800 Subject: [PATCH 046/452] LogFile puts timestamp before entry, CRLF after. --- firmware/application/app_ais.cpp | 3 +-- firmware/application/app_ert.cpp | 18 ++++++++---------- firmware/application/app_tpms.cpp | 18 ++---------------- firmware/application/log_file.cpp | 19 +++++++++++++++++++ firmware/application/log_file.hpp | 5 ++++- 5 files changed, 34 insertions(+), 29 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index a4da213eb..09f81a5da 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -299,8 +299,7 @@ bool AISModel::on_packet(const baseband::ais::Packet& packet) { entry += (nibble >= 10) ? ('W' + nibble) : ('0' + nibble); } - entry += "\r\n"; - log_file.write(entry); + log_file.write_entry(entry); } return true; diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 9a4facb69..951104869 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -38,29 +38,27 @@ ERTModel::ERTModel() { } std::string ERTModel::on_packet(const ERTPacketMessage& message) { - std::string s; + std::string entry; if( message.packet.preamble == 0x555516a3 ) { - s += "IDM\n"; + entry += "IDM "; } if( message.packet.preamble == 0x1f2a60 ) { - s += "SCM\n"; + entry += "SCM "; } const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); const auto hex_formatted = format_manchester(decoder); - s += hex_formatted.data; - s += "\n"; - s += hex_formatted.errors; - s += "\n"; + entry += hex_formatted.data; + entry += "/"; + entry += hex_formatted.errors; if( log_file.is_ready() ) { - std::string entry = hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; - log_file.write(entry); + log_file.write_entry(entry); } - return s; + return entry; } namespace ui { diff --git a/firmware/application/app_tpms.cpp b/firmware/application/app_tpms.cpp index db74c108b..3df0a0e50 100644 --- a/firmware/application/app_tpms.cpp +++ b/firmware/application/app_tpms.cpp @@ -24,10 +24,6 @@ #include "portapack.hpp" using namespace portapack; -#include -// #include "lpc43xx_cpp.hpp" -// using namespace lpc43xx; - #include "string_format.hpp" TPMSModel::TPMSModel() { @@ -46,22 +42,12 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { const auto hex_formatted = format_manchester(decoder); if( log_file.is_ready() ) { - rtc::RTC datetime; - rtcGetTime(&RTCD1, &datetime); - std::string timestamp = - to_string_dec_uint(datetime.year(), 4, '0') + - to_string_dec_uint(datetime.month(), 2, '0') + - to_string_dec_uint(datetime.day(), 2, '0') + - to_string_dec_uint(datetime.hour(), 2, '0') + - to_string_dec_uint(datetime.minute(), 2, '0') + - to_string_dec_uint(datetime.second(), 2, '0'); - const auto tuning_frequency = receiver_model.tuning_frequency(); // TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue! const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); - std::string log = timestamp + " " + tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors + "\r\n"; - log_file.write(log); + std::string entry = tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors; + log_file.write_entry(entry); } return hex_formatted; diff --git a/firmware/application/log_file.cpp b/firmware/application/log_file.cpp index 82b2a0460..3225ea45e 100644 --- a/firmware/application/log_file.cpp +++ b/firmware/application/log_file.cpp @@ -21,6 +21,11 @@ #include "log_file.hpp" +#include "string_format.hpp" + +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + LogFile::~LogFile() { close(); } @@ -48,6 +53,20 @@ bool LogFile::is_ready() { return !f_error(&f); } +bool LogFile::write_entry(const std::string entry) { + rtc::RTC datetime; + rtcGetTime(&RTCD1, &datetime); + std::string timestamp = + to_string_dec_uint(datetime.year(), 4, '0') + + to_string_dec_uint(datetime.month(), 2, '0') + + to_string_dec_uint(datetime.day(), 2, '0') + + to_string_dec_uint(datetime.hour(), 2, '0') + + to_string_dec_uint(datetime.minute(), 2, '0') + + to_string_dec_uint(datetime.second(), 2, '0'); + + return write(timestamp + " " + entry + "\r\n"); +} + bool LogFile::write(const std::string message) { const auto puts_result = f_puts(message.c_str(), &f); const auto sync_result = f_sync(&f); diff --git a/firmware/application/log_file.hpp b/firmware/application/log_file.hpp index 19887d000..2e4708dda 100644 --- a/firmware/application/log_file.hpp +++ b/firmware/application/log_file.hpp @@ -33,10 +33,13 @@ public: bool open_for_append(const std::string file_path); bool close(); bool is_ready(); - bool write(const std::string message); + + bool write_entry(const std::string entry); private: FIL f; + + bool write(const std::string message); }; #endif/*__LOG_FILE_H__*/ From ad22eab3d28bd4470607aa7541a48b83cb26c2be Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 2 Dec 2015 14:12:35 -0800 Subject: [PATCH 047/452] Fix ERT console lack of CRLF. --- firmware/application/app_ert.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 951104869..ae21df4be 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -83,7 +83,7 @@ void ERTView::on_hide() { } void ERTView::log(const std::string& s) { - write(s); + writeln(s); } } /* namespace ui */ From 0909cdb31ec1b296dc5115ff8275e4a86eb63d73 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 2 Dec 2015 22:39:05 -0800 Subject: [PATCH 048/452] AIS: Add MMSI type. --- firmware/application/app_ais.cpp | 6 +++++- firmware/application/app_ais.hpp | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 09f81a5da..df5b36f1d 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -224,7 +224,11 @@ uint32_t Packet::message_id() const { return field_.read(0, 6); } -uint32_t Packet::source_id() const { +MMSI Packet::user_id() const { + return field_.read(8, 30); +} + +MMSI Packet::source_id() const { return field_.read(8, 30); } diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index ffca34437..b5739ce2c 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -56,6 +56,8 @@ struct DateTime { using Latitude = int32_t; using Longitude = int32_t; +using MMSI = uint32_t; + class Packet { public: constexpr Packet( @@ -72,7 +74,8 @@ public: bool is_valid() const; uint32_t message_id() const; - uint32_t source_id() const; + MMSI user_id() const; + MMSI source_id() const; uint32_t read(const size_t start_bit, const size_t length) const; From bb3cb6f0802fe2beef05edc64c376898e19fa541 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 3 Dec 2015 14:04:20 -0800 Subject: [PATCH 049/452] Push packet timestamping earlier in packet handling. Ideally, it'd get pushed back into baseband, and baseband would correct for the length of the packet (based on preamble/access code match timestamp minus preamble/access code duration) to give the exact time the packet started. --- firmware/application/app_ais.cpp | 10 ++++++++-- firmware/application/app_ais.hpp | 8 ++++++++ firmware/application/app_ert.cpp | 8 +++++++- firmware/application/app_tpms.cpp | 8 +++++++- firmware/application/log_file.cpp | 4 +--- firmware/application/log_file.hpp | 5 ++++- 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index df5b36f1d..1afbb06f2 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -220,6 +220,10 @@ bool Packet::is_valid() const { return true; } +rtc::RTC Packet::received_at() const { + return received_at_; +} + uint32_t Packet::message_id() const { return field_.read(0, 6); } @@ -303,7 +307,7 @@ bool AISModel::on_packet(const baseband::ais::Packet& packet) { entry += (nibble >= 10) ? ('W' + nibble) : ('0' + nibble); } - log_file.write_entry(entry); + log_file.write_entry(packet.received_at(), entry); } return true; @@ -318,7 +322,9 @@ void AISView::on_show() { message_map.register_handler(Message::ID::AISPacket, [this](Message* const p) { const auto message = static_cast(p); - const baseband::ais::Packet packet { message->packet.payload, message->packet.bits_received }; + rtc::RTC datetime; + rtcGetTime(&RTCD1, &datetime); + const baseband::ais::Packet packet { datetime, message->packet.payload, message->packet.bits_received }; if( this->model.on_packet(packet) ) { this->log(packet); } diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index b5739ce2c..1bd7c763d 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -27,6 +27,9 @@ #include "log_file.hpp" #include "field_reader.hpp" +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + #include #include #include @@ -61,10 +64,12 @@ using MMSI = uint32_t; class Packet { public: constexpr Packet( + const rtc::RTC& received_at, const std::bitset<1024>& payload, const size_t payload_length ) : payload_ { payload }, payload_length_ { payload_length }, + received_at_ { received_at }, field_ { payload_ } { } @@ -73,6 +78,8 @@ public: bool is_valid() const; + rtc::RTC received_at() const; + uint32_t message_id() const; MMSI user_id() const; MMSI source_id() const; @@ -89,6 +96,7 @@ public: private: const std::bitset<1024> payload_; const size_t payload_length_; + const rtc::RTC received_at_; const FieldReader field_; }; diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index ae21df4be..755bbcfed 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -26,6 +26,9 @@ using namespace portapack; #include "manchester.hpp" +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + ERTModel::ERTModel() { receiver_model.set_baseband_configuration({ .mode = 6, @@ -38,6 +41,9 @@ ERTModel::ERTModel() { } std::string ERTModel::on_packet(const ERTPacketMessage& message) { + rtc::RTC received_at; + rtcGetTime(&RTCD1, &received_at); + std::string entry; if( message.packet.preamble == 0x555516a3 ) { @@ -55,7 +61,7 @@ std::string ERTModel::on_packet(const ERTPacketMessage& message) { entry += hex_formatted.errors; if( log_file.is_ready() ) { - log_file.write_entry(entry); + log_file.write_entry(received_at, entry); } return entry; diff --git a/firmware/application/app_tpms.cpp b/firmware/application/app_tpms.cpp index 3df0a0e50..a02aaf3c5 100644 --- a/firmware/application/app_tpms.cpp +++ b/firmware/application/app_tpms.cpp @@ -26,6 +26,9 @@ using namespace portapack; #include "string_format.hpp" +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + TPMSModel::TPMSModel() { receiver_model.set_baseband_configuration({ .mode = 5, @@ -38,6 +41,9 @@ TPMSModel::TPMSModel() { } ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { + rtc::RTC received_at; + rtcGetTime(&RTCD1, &received_at); + const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); const auto hex_formatted = format_manchester(decoder); @@ -47,7 +53,7 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); std::string entry = tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors; - log_file.write_entry(entry); + log_file.write_entry(received_at, entry); } return hex_formatted; diff --git a/firmware/application/log_file.cpp b/firmware/application/log_file.cpp index 3225ea45e..a32149f15 100644 --- a/firmware/application/log_file.cpp +++ b/firmware/application/log_file.cpp @@ -53,9 +53,7 @@ bool LogFile::is_ready() { return !f_error(&f); } -bool LogFile::write_entry(const std::string entry) { - rtc::RTC datetime; - rtcGetTime(&RTCD1, &datetime); +bool LogFile::write_entry(const rtc::RTC& datetime, const std::string entry) { std::string timestamp = to_string_dec_uint(datetime.year(), 4, '0') + to_string_dec_uint(datetime.month(), 2, '0') + diff --git a/firmware/application/log_file.hpp b/firmware/application/log_file.hpp index 2e4708dda..cf7dcf4dc 100644 --- a/firmware/application/log_file.hpp +++ b/firmware/application/log_file.hpp @@ -26,6 +26,9 @@ #include "ff.h" +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + class LogFile { public: ~LogFile(); @@ -34,7 +37,7 @@ public: bool close(); bool is_ready(); - bool write_entry(const std::string entry); + bool write_entry(const rtc::RTC& datetime, const std::string entry); private: FIL f; From 0cad2847f8c086d0bbf95329142a2cbb179f6d42 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 3 Dec 2015 14:08:06 -0800 Subject: [PATCH 050/452] LogFile pass references to reduce code size a bit. Apparently the compiler isn't optimizing away copies in places I thought it would. --- firmware/application/log_file.cpp | 6 +++--- firmware/application/log_file.hpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/application/log_file.cpp b/firmware/application/log_file.cpp index a32149f15..7bcfefbbf 100644 --- a/firmware/application/log_file.cpp +++ b/firmware/application/log_file.cpp @@ -30,7 +30,7 @@ LogFile::~LogFile() { close(); } -bool LogFile::open_for_append(const std::string file_path) { +bool LogFile::open_for_append(const std::string& file_path) { const auto open_result = f_open(&f, file_path.c_str(), FA_WRITE | FA_OPEN_ALWAYS); if( open_result == FR_OK ) { const auto seek_result = f_lseek(&f, f_size(&f)); @@ -53,7 +53,7 @@ bool LogFile::is_ready() { return !f_error(&f); } -bool LogFile::write_entry(const rtc::RTC& datetime, const std::string entry) { +bool LogFile::write_entry(const rtc::RTC& datetime, const std::string& entry) { std::string timestamp = to_string_dec_uint(datetime.year(), 4, '0') + to_string_dec_uint(datetime.month(), 2, '0') + @@ -65,7 +65,7 @@ bool LogFile::write_entry(const rtc::RTC& datetime, const std::string entry) { return write(timestamp + " " + entry + "\r\n"); } -bool LogFile::write(const std::string message) { +bool LogFile::write(const std::string& message) { const auto puts_result = f_puts(message.c_str(), &f); const auto sync_result = f_sync(&f); return (puts_result >= 0) && (sync_result == FR_OK); diff --git a/firmware/application/log_file.hpp b/firmware/application/log_file.hpp index cf7dcf4dc..3f7024c35 100644 --- a/firmware/application/log_file.hpp +++ b/firmware/application/log_file.hpp @@ -33,16 +33,16 @@ class LogFile { public: ~LogFile(); - bool open_for_append(const std::string file_path); + bool open_for_append(const std::string& file_path); bool close(); bool is_ready(); - bool write_entry(const rtc::RTC& datetime, const std::string entry); + bool write_entry(const rtc::RTC& datetime, const std::string& entry); private: FIL f; - bool write(const std::string message); + bool write(const std::string& message); }; #endif/*__LOG_FILE_H__*/ From 3644bfd983921af53861fa8d8f12e5e7d7e13185 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 3 Dec 2015 20:34:02 -0800 Subject: [PATCH 051/452] AISView displays list of most recent packets -- MMSI and name or call sign. Formerly scrolling console of packets. --- firmware/application/app_ais.cpp | 86 ++++++++++++++++++++++---------- firmware/application/app_ais.hpp | 32 +++++++++++- 2 files changed, 92 insertions(+), 26 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 1afbb06f2..cf624e3cb 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -28,6 +28,8 @@ using namespace portapack; #include "string_format.hpp" +#include + namespace baseband { namespace ais { @@ -316,7 +318,7 @@ bool AISModel::on_packet(const baseband::ais::Packet& packet) { namespace ui { void AISView::on_show() { - Console::on_show(); + View::on_show(); auto& message_map = context().message_map(); message_map.register_handler(Message::ID::AISPacket, @@ -336,53 +338,87 @@ void AISView::on_hide() { auto& message_map = context().message_map(); message_map.unregister_handler(Message::ID::AISPacket); - Console::on_hide(); + View::on_hide(); } void AISView::log(const baseband::ais::Packet& packet) { - std::string result { to_string_dec_uint(packet.message_id(), 2) + " " + to_string_dec_uint(packet.source_id(), 10) }; + const auto source_id = packet.source_id(); + auto matching_recent = std::find_if(recent.begin(), recent.end(), + [source_id](const AISView::RecentEntry& entry) { return entry.mmsi == source_id; } + ); + if( matching_recent != recent.end() ) { + // Found within. Move to front of list, increment counter. + recent.push_front(*matching_recent); + recent.erase(matching_recent); + } else { + recent.emplace_front(source_id); + while(recent.size() > 64) { + recent.pop_back(); + } + } + + auto& entry = recent.front(); + entry.received_count++; switch(packet.message_id()) { case 1: case 2: case 3: - { - const auto navigational_status = packet.read(38, 4); - result += " " + baseband::ais::format_navigational_status(navigational_status); - result += " " + baseband::ais::format_latlon_normalized(packet.latitude(89)); - result += " " + baseband::ais::format_latlon_normalized(packet.longitude(61)); - } + entry.navigational_status = packet.read(38, 4); + entry.last_position.timestamp = packet.received_at(); + entry.last_position.latitude = packet.latitude(89); + entry.last_position.longitude = packet.longitude(61); break; case 4: - { - result += " " + baseband::ais::format_datetime(packet.datetime(38)); - result += " " + baseband::ais::format_latlon_normalized(packet.latitude(107)); - result += " " + baseband::ais::format_latlon_normalized(packet.longitude(79)); - } + // packet.datetime(38) + entry.last_position.timestamp = packet.received_at(); + entry.last_position.latitude = packet.latitude(107); + entry.last_position.longitude = packet.longitude(79); break; case 5: - { - const auto call_sign = packet.text(70, 7); - const auto name = packet.text(112, 20); - const auto destination = packet.text(302, 20); - result += " \"" + call_sign + "\" \"" + name + "\" \"" + destination + "\""; - } + entry.call_sign = packet.text(70, 7); + entry.name = packet.text(112, 20); + entry.destination = packet.text(302, 20); break; case 21: - { - const auto name = packet.text(43, 20); - result += " \"" + name + "\" " + baseband::ais::format_latlon_normalized(packet.latitude(192)) + " " + baseband::ais::format_latlon_normalized(packet.longitude(164)); - } + entry.name = packet.text(43, 20); + entry.last_position.timestamp = packet.received_at(); + entry.last_position.latitude = packet.latitude(192); + entry.last_position.longitude = packet.longitude(164); break; default: break; } - writeln(result); + set_dirty(); +} + +void AISView::paint(Painter& painter) { + const auto r = screen_rect(); + const auto& s = style(); + + auto p = r.pos; + for(const auto entry : recent) { + std::string line = to_string_dec_uint(entry.mmsi, 10) + " "; + if( !entry.name.empty() ) { + line += entry.name; + } else { + line += entry.call_sign; + } + + line.resize(r.width() / 8, ' '); + + painter.draw_string(p, s, line); + p.y += s.font.line_height(); + + if( p.y >= r.bottom() ) { + break; + } + } } } /* namespace ui */ diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 1bd7c763d..9b85066d7 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -34,6 +34,7 @@ using namespace lpc43xx; #include #include #include +#include #include namespace baseband { @@ -115,14 +116,43 @@ private: namespace ui { -class AISView : public Console { +class AISView : public View { public: void on_show() override; void on_hide() override; + void paint(Painter& painter) override; + private: AISModel model; + struct Position { + rtc::RTC timestamp { }; + baseband::ais::Latitude latitude { 0 }; + baseband::ais::Longitude longitude { 0 }; + }; + + struct RecentEntry { + baseband::ais::MMSI mmsi; + std::string name; + std::string call_sign; + std::string destination; + Position last_position; + size_t received_count; + int8_t navigational_status; + + RecentEntry( + const baseband::ais::MMSI& mmsi + ) : mmsi { mmsi }, + last_position { }, + received_count { 0 }, + navigational_status { -1 } + { + } + }; + + std::list recent; + void log(const baseband::ais::Packet& packet); }; From 2a2e65abad168d1c220827ac2dcb38a8414a9981 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 3 Dec 2015 20:34:30 -0800 Subject: [PATCH 052/452] Reserve length of AIS packet text std::string. --- firmware/application/app_ais.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index cf624e3cb..fa96ed180 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -247,6 +247,8 @@ std::string Packet::text( const size_t character_count ) const { std::string result; + result.reserve(character_count); + const size_t character_length = 6; const size_t end_bit = start_bit + character_count * character_length; for(size_t i=start_bit; i Date: Thu, 3 Dec 2015 20:53:14 -0800 Subject: [PATCH 053/452] ui::OptionsField match option value by ==, not >=. I think I used >= to match baseband filter bandwidth, but then the options would all have to be in increasing order to do the right thing, which is not what another developer would expect! --- firmware/common/ui_widget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index d2b040dbf..16c2829a9 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -397,7 +397,7 @@ void OptionsField::set_selected_index(const size_t new_index) { void OptionsField::set_by_value(value_t v) { size_t new_index { 0 }; for(const auto& option : options) { - if( option.second >= v ) { + if( option.second == v ) { set_selected_index(new_index); break; } From fbd077e91da593ff97375842bc44dd3fa65a4ad1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 3 Dec 2015 20:54:18 -0800 Subject: [PATCH 054/452] Restore receiver mode when View is displayed. Needs refactor because on_modulation_changed() doesn't change the modulation so much as the "app" or receiver mode. --- firmware/application/ui_receiver.cpp | 13 +++++++++++++ firmware/application/ui_receiver.hpp | 3 +++ 2 files changed, 16 insertions(+) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 421442e13..78682d142 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -498,6 +498,19 @@ ReceiverView::~ReceiverView() { receiver_model.disable(); } +void ReceiverView::on_show() { + View::on_show(); + + // TODO: Separate concepts of baseband "modulation" and receiver "mode". + on_modulation_changed(static_cast(receiver_model.modulation())); +} + +void ReceiverView::on_hide() { + on_modulation_changed(static_cast(-1)); + + View::on_hide(); +} + void ReceiverView::focus() { button_done.focus(); } diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index af948c3c7..e2cbf1f7d 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -362,6 +362,9 @@ public: ReceiverView(NavigationView& nav, ReceiverModel& receiver_model); ~ReceiverView(); + void on_show() override; + void on_hide() override; + void focus() override; private: From 4205793b5409ba5dde805bf459e581d169694b5a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 3 Dec 2015 20:58:17 -0800 Subject: [PATCH 055/452] Clean up narrowing conversion warning. --- firmware/baseband/proc_ert.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/proc_ert.hpp b/firmware/baseband/proc_ert.hpp index bc5fcc93b..fa38d286a 100644 --- a/firmware/baseband/proc_ert.hpp +++ b/firmware/baseband/proc_ert.hpp @@ -57,11 +57,11 @@ public: private: const uint32_t baseband_sampling_rate = 4194304; const size_t decimation = 1; - const uint32_t symbol_rate = 32768; + const float symbol_rate = 32768; const uint32_t channel_sampling_rate = baseband_sampling_rate / decimation; const size_t samples_per_symbol = channel_sampling_rate / symbol_rate; - const uint32_t clock_recovery_rate = symbol_rate * 2; + const float clock_recovery_rate = symbol_rate * 2; // ChannelDecimator decimator { ChannelDecimator::DecimationFactor::By2, false }; From 64b9bfa35fbeac754feb4503bfde71b07e20cf9f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 3 Dec 2015 22:09:06 -0800 Subject: [PATCH 056/452] Make MMSI-formatting function. Only render nine digits, left zero pad. --- firmware/application/app_ais.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index fa96ed180..dbfeacce3 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -156,6 +156,12 @@ static std::string format_latlon_normalized(const int32_t normalized) { return to_string_dec_int(degrees) + "." + to_string_dec_int(fraction, 6, '0'); } +static std::string format_mmsi( + const MMSI& mmsi +) { + return to_string_dec_uint(mmsi, 9, '0'); +} + static std::string format_datetime( const DateTime& datetime ) { @@ -405,7 +411,7 @@ void AISView::paint(Painter& painter) { auto p = r.pos; for(const auto entry : recent) { - std::string line = to_string_dec_uint(entry.mmsi, 10) + " "; + std::string line = baseband::ais::format_mmsi(entry.mmsi) + " "; if( !entry.name.empty() ) { line += entry.name; } else { From 1c191bcd4f93074180cd5a6a14f20288c758e4b3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 5 Dec 2015 14:22:35 -0800 Subject: [PATCH 057/452] Rename AISView::log to on_packet. --- firmware/application/app_ais.cpp | 4 ++-- firmware/application/app_ais.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index dbfeacce3..f57cd2d0f 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -336,7 +336,7 @@ void AISView::on_show() { rtcGetTime(&RTCD1, &datetime); const baseband::ais::Packet packet { datetime, message->packet.payload, message->packet.bits_received }; if( this->model.on_packet(packet) ) { - this->log(packet); + this->on_packet(packet); } } ); @@ -349,7 +349,7 @@ void AISView::on_hide() { View::on_hide(); } -void AISView::log(const baseband::ais::Packet& packet) { +void AISView::on_packet(const baseband::ais::Packet& packet) { const auto source_id = packet.source_id(); auto matching_recent = std::find_if(recent.begin(), recent.end(), [source_id](const AISView::RecentEntry& entry) { return entry.mmsi == source_id; } diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 9b85066d7..6f8a99f2c 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -152,8 +152,8 @@ private: }; std::list recent; + void on_packet(const baseband::ais::Packet& packet); - void log(const baseband::ais::Packet& packet); }; } /* namespace ui */ From 27684069c5d013ff2736287e0628b65a700d6575 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 5 Dec 2015 14:23:53 -0800 Subject: [PATCH 058/452] Track when AISView has focus. --- firmware/application/app_ais.cpp | 10 ++++++++++ firmware/application/app_ais.hpp | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index f57cd2d0f..fc013d8d3 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -405,6 +405,16 @@ void AISView::on_packet(const baseband::ais::Packet& packet) { set_dirty(); } +void AISView::on_focus() { + has_focus = true; + set_dirty(); +} + +void AISView::on_blur() { + has_focus = false; + set_dirty(); +} + void AISView::paint(Painter& painter) { const auto r = screen_rect(); const auto& s = style(); diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 6f8a99f2c..254a8008f 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -118,14 +118,23 @@ namespace ui { class AISView : public View { public: + AISView() { + flags.focusable = true; + } + void on_show() override; void on_hide() override; void paint(Painter& painter) override; + void on_focus() override; + void on_blur() override; + private: AISModel model; + bool has_focus = false; + struct Position { rtc::RTC timestamp { }; baseband::ais::Latitude latitude { 0 }; From 9791d64b502eab1a9788b5695f822b2a0efd0f1c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 5 Dec 2015 14:24:41 -0800 Subject: [PATCH 059/452] AISView RecentEntry UI selection by encoder. --- firmware/application/app_ais.cpp | 43 +++++++++++++++++++++++++++++++- firmware/application/app_ais.hpp | 15 ++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index fc013d8d3..ebdbc486d 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -415,6 +415,11 @@ void AISView::on_blur() { set_dirty(); } +bool AISView::on_encoder(const EncoderEvent event) { + advance(event); + return true; +} + void AISView::paint(Painter& painter) { const auto r = screen_rect(); const auto& s = style(); @@ -430,7 +435,12 @@ void AISView::paint(Painter& painter) { line.resize(r.width() / 8, ' '); - painter.draw_string(p, s, line); + if( has_focus && (selected_key == entry.mmsi) ) { + painter.draw_string(p, s.invert(), line); + } else { + painter.draw_string(p, s, line); + } + p.y += s.font.line_height(); if( p.y >= r.bottom() ) { @@ -439,4 +449,35 @@ void AISView::paint(Painter& painter) { } } +AISView::RecentEntries::iterator AISView::selected_entry() { + const auto key = selected_key; + return std::find_if(std::begin(recent), std::end(recent), [key](const RecentEntry& e) { return e.mmsi == key; }); +} + +void AISView::advance(const int32_t amount) { + auto selected = selected_entry(); + if( selected == std::end(recent) ) { + if( recent.empty() ) { + selected_key = invalid_key; + } else { + selected_key = recent.front().mmsi; + } + } else { + if( amount < 0 ) { + if( selected != std::begin(recent) ) { + std::advance(selected, -1); + } + } + if( amount > 0 ) { + std::advance(selected, 1); + if( selected == std::end(recent) ) { + return; + } + } + selected_key = selected->mmsi; + } + + set_dirty(); +} + } /* namespace ui */ diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 254a8008f..0bc828771 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -37,6 +37,8 @@ using namespace lpc43xx; #include #include +#include + namespace baseband { namespace ais { @@ -130,9 +132,15 @@ public: void on_focus() override; void on_blur() override; + bool on_encoder(const EncoderEvent event) override; + private: AISModel model; + using EntryKey = baseband::ais::MMSI; + EntryKey selected_key; + const EntryKey invalid_key = 0xffffffff; + bool has_focus = false; struct Position { @@ -160,9 +168,14 @@ private: } }; - std::list recent; + using RecentEntries = std::list; + RecentEntries recent; + void on_packet(const baseband::ais::Packet& packet); + RecentEntries::iterator selected_entry(); + + void advance(const int32_t amount); }; } /* namespace ui */ From 8fce9378cc4d9d10a2910ad12041a03a0c46a723 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 5 Dec 2015 19:52:12 -0800 Subject: [PATCH 060/452] Extract entry list truncation. --- firmware/application/app_ais.cpp | 10 +++++++--- firmware/application/app_ais.hpp | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index ebdbc486d..75213c5ae 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -349,6 +349,12 @@ void AISView::on_hide() { View::on_hide(); } +void AISView::truncate_entries() { + while(recent.size() > 64) { + recent.pop_back(); + } +} + void AISView::on_packet(const baseband::ais::Packet& packet) { const auto source_id = packet.source_id(); auto matching_recent = std::find_if(recent.begin(), recent.end(), @@ -360,9 +366,7 @@ void AISView::on_packet(const baseband::ais::Packet& packet) { recent.erase(matching_recent); } else { recent.emplace_front(source_id); - while(recent.size() > 64) { - recent.pop_back(); - } + truncate_entries(); } auto& entry = recent.front(); diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 0bc828771..6979770a9 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -173,6 +173,8 @@ private: void on_packet(const baseband::ais::Packet& packet); + void truncate_entries(); + RecentEntries::iterator selected_entry(); void advance(const int32_t amount); From c4ad2ffe1be0295593cfe4725a3497a53acb9444 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 5 Dec 2015 20:15:30 -0800 Subject: [PATCH 061/452] Extract AIS RecentEntry painting into separate method. Small steps in a larger refactor, and better selected-item-scrolls-off-the-bottom behavior. --- firmware/application/app_ais.cpp | 46 ++++++++++++++++++++------------ firmware/application/app_ais.hpp | 7 +++++ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 75213c5ae..a0b5e2044 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -424,30 +424,42 @@ bool AISView::on_encoder(const EncoderEvent event) { return true; } +bool AISView::draw_entry( + const RecentEntry& entry, + const Rect& target_rect, + Painter& painter, + const Style& s +) { + std::string line = baseband::ais::format_mmsi(entry.mmsi) + " "; + if( !entry.name.empty() ) { + line += entry.name; + } else { + line += entry.call_sign; + } + + line.resize(target_rect.width() / 8, ' '); + + const bool is_selected_key = (selected_key == entry.mmsi); + if( has_focus && is_selected_key ) { + painter.draw_string(target_rect.pos, s.invert(), line); + } else { + painter.draw_string(target_rect.pos, s, line); + } + + return is_selected_key; +} + void AISView::paint(Painter& painter) { const auto r = screen_rect(); const auto& s = style(); - auto p = r.pos; + Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; for(const auto entry : recent) { - std::string line = baseband::ais::format_mmsi(entry.mmsi) + " "; - if( !entry.name.empty() ) { - line += entry.name; - } else { - line += entry.call_sign; - } + draw_entry(entry, target_rect, painter, s); - line.resize(r.width() / 8, ' '); + target_rect.pos.y += target_rect.height(); - if( has_focus && (selected_key == entry.mmsi) ) { - painter.draw_string(p, s.invert(), line); - } else { - painter.draw_string(p, s, line); - } - - p.y += s.font.line_height(); - - if( p.y >= r.bottom() ) { + if( target_rect.pos.y >= r.bottom() ) { break; } } diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 6979770a9..48cb49f83 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -173,6 +173,13 @@ private: void on_packet(const baseband::ais::Packet& packet); + bool draw_entry( + const RecentEntry& entry, + const Rect& target_rect, + Painter& painter, + const Style& s + ); + void truncate_entries(); RecentEntries::iterator selected_entry(); From 0f23736253e46c6cf7eceb95e2a255b90928fb25 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 5 Dec 2015 20:25:05 -0800 Subject: [PATCH 062/452] Whoops, don't match selected_key inside draw_entry. --- firmware/application/app_ais.cpp | 16 +++++----------- firmware/application/app_ais.hpp | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index a0b5e2044..1b2df09f9 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -424,7 +424,7 @@ bool AISView::on_encoder(const EncoderEvent event) { return true; } -bool AISView::draw_entry( +void AISView::draw_entry( const RecentEntry& entry, const Rect& target_rect, Painter& painter, @@ -438,15 +438,7 @@ bool AISView::draw_entry( } line.resize(target_rect.width() / 8, ' '); - - const bool is_selected_key = (selected_key == entry.mmsi); - if( has_focus && is_selected_key ) { - painter.draw_string(target_rect.pos, s.invert(), line); - } else { - painter.draw_string(target_rect.pos, s, line); - } - - return is_selected_key; + painter.draw_string(target_rect.pos, s, line); } void AISView::paint(Painter& painter) { @@ -455,7 +447,9 @@ void AISView::paint(Painter& painter) { Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; for(const auto entry : recent) { - draw_entry(entry, target_rect, painter, s); + const auto is_selected_key = (selected_key == entry.mmsi); + const auto& draw_style = (has_focus && is_selected_key) ? s.invert() : s; + draw_entry(entry, target_rect, painter, draw_style); target_rect.pos.y += target_rect.height(); diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 48cb49f83..3f5c096f5 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -173,7 +173,7 @@ private: void on_packet(const baseband::ais::Packet& packet); - bool draw_entry( + void draw_entry( const RecentEntry& entry, const Rect& target_rect, Painter& painter, From 85ac3fa4ac86489455dd9c7afa11a8f7a3da49f8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 6 Dec 2015 09:50:53 -0800 Subject: [PATCH 063/452] Show selected item at bottom of visible list even if it should be off-screen. Not convinced this is the most intuitive approach, but it's better than before. --- firmware/application/app_ais.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 1b2df09f9..2188539d7 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -446,14 +446,21 @@ void AISView::paint(Painter& painter) { const auto& s = style(); Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; + bool found_selected_item = false; for(const auto entry : recent) { + const auto next_y = target_rect.pos.y + target_rect.height(); + const auto last_visible_entry = (next_y >= r.bottom()); + const auto is_selected_key = (selected_key == entry.mmsi); - const auto& draw_style = (has_focus && is_selected_key) ? s.invert() : s; - draw_entry(entry, target_rect, painter, draw_style); + found_selected_item |= is_selected_key; - target_rect.pos.y += target_rect.height(); + if( !last_visible_entry || (last_visible_entry && found_selected_item) ) { + const auto& draw_style = (has_focus && is_selected_key) ? s.invert() : s; + draw_entry(entry, target_rect, painter, draw_style); + target_rect.pos.y += target_rect.height(); + } - if( target_rect.pos.y >= r.bottom() ) { + if( last_visible_entry && found_selected_item ) { break; } } From 5cfd44a546c3f3f45308eab7e86a70d58104ac2c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 6 Dec 2015 15:22:52 -0800 Subject: [PATCH 064/452] Manchester decoded symbol operator| for accessing bit value. --- firmware/application/manchester.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/firmware/application/manchester.hpp b/firmware/application/manchester.hpp index 5e965c854..93d902170 100644 --- a/firmware/application/manchester.hpp +++ b/firmware/application/manchester.hpp @@ -54,6 +54,11 @@ private: const size_t sense; }; +template +T operator|(const T& l, const ManchesterDecoder::DecodedSymbol& r) { + return l | r.value; +} + struct ManchesterFormatted { const std::string data; const std::string errors; From 51026609ce0fbfe131329ddddc479eabf66a9a46 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 6 Dec 2015 15:31:17 -0800 Subject: [PATCH 065/452] ert::Packet parser. --- firmware/application/app_ert.cpp | 42 +++++++++++++++++++ firmware/application/app_ert.hpp | 71 ++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 755bbcfed..fe0174373 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -29,6 +29,48 @@ using namespace portapack; #include "lpc43xx_cpp.hpp" using namespace lpc43xx; +namespace ert { + +size_t Packet::length() const { + return payload_length_; +} + +bool Packet::is_valid() const { + return true; +} + +rtc::RTC Packet::received_at() const { + return received_at_; +} + +Packet::Type Packet::type() const { + return type_; +} + +ID Packet::id() const { + if( type() == Packet::Type::SCM ) { + const auto msb = reader_.read(0, 2); + const auto lsb = reader_.read(35, 24); + return (msb << 24) | lsb; + } + if( type() == Packet::Type::IDM ) { + return reader_.read(5 * 8, 32); + } + return invalid_id; +} + +Consumption Packet::consumption() const { + if( type() == Packet::Type::SCM ) { + return reader_.read(11, 24); + } + if( type() == Packet::Type::IDM ) { + return reader_.read(25 * 8, 32); + } + return invalid_consumption; +} + +} /* namespace ert */ + ERTModel::ERTModel() { receiver_model.set_baseband_configuration({ .mode = 6, diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index 8bb461385..ebc268640 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -25,8 +25,79 @@ #include "ui_console.hpp" #include "message.hpp" #include "log_file.hpp" +#include "manchester.hpp" +#include "field_reader.hpp" +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + +#include #include +#include + +namespace ert { + +struct BitRemap { + size_t operator()(const size_t bit_index) const { + return bit_index; + } +}; + +using ID = uint32_t; +using Consumption = uint32_t; + +class Packet { +public: + enum Type { + Unknown = 0, + IDM = 1, + SCM = 2, + }; + + Packet( + const rtc::RTC& received_at, + const uint64_t preamble, + const std::bitset<1024>& payload, + const size_t payload_length + ) : payload_ { payload }, + payload_length_ { payload_length }, + received_at_ { received_at }, + decoder_ { payload_, payload_length_ }, + reader_ { decoder_ }, + type_ { Type::Unknown } + { + if( preamble == 0x1f2a60 ) { + type_ = Type::SCM; + } else if( preamble == 0x555516a3 ) { + type_ = Type::IDM; + } + } + + size_t length() const; + + bool is_valid() const; + + rtc::RTC received_at() const; + + Type type() const; + ID id() const; + Consumption consumption() const; + +private: + using Reader = FieldReader; + + const std::bitset<1024> payload_; + const size_t payload_length_; + const rtc::RTC received_at_; + const ManchesterDecoder decoder_; + const Reader reader_; + Type type_; + + const ID invalid_id = 0; + const Consumption invalid_consumption = 0; +}; + +} /* namespace ert */ class ERTModel { public: From 2a55030d4ebb0aaa4b0c8eddd004b9b12d2e5de8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 6 Dec 2015 15:32:21 -0800 Subject: [PATCH 066/452] Use ert::Packet for basic packet decoding. --- firmware/application/app_ert.cpp | 61 +++++++++++++++++--------------- firmware/application/app_ert.hpp | 4 +-- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index fe0174373..785f133c2 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -29,6 +29,8 @@ using namespace portapack; #include "lpc43xx_cpp.hpp" using namespace lpc43xx; +#include "string_format.hpp" + namespace ert { size_t Packet::length() const { @@ -82,31 +84,8 @@ ERTModel::ERTModel() { log_file.open_for_append("ert.txt"); } -std::string ERTModel::on_packet(const ERTPacketMessage& message) { - rtc::RTC received_at; - rtcGetTime(&RTCD1, &received_at); - - std::string entry; - - if( message.packet.preamble == 0x555516a3 ) { - entry += "IDM "; - } - if( message.packet.preamble == 0x1f2a60 ) { - entry += "SCM "; - } - - const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received); - - const auto hex_formatted = format_manchester(decoder); - entry += hex_formatted.data; - entry += "/"; - entry += hex_formatted.errors; - - if( log_file.is_ready() ) { - log_file.write_entry(received_at, entry); - } - - return entry; +bool ERTModel::on_packet(const ert::Packet&) { + return true; } namespace ui { @@ -118,7 +97,12 @@ void ERTView::on_show() { message_map.register_handler(Message::ID::ERTPacket, [this](Message* const p) { const auto message = static_cast(p); - this->log(this->model.on_packet(*message)); + rtc::RTC datetime; + rtcGetTime(&RTCD1, &datetime); + const ert::Packet packet { datetime, message->packet.preamble, message->packet.payload, message->packet.bits_received }; + if( this->model.on_packet(packet) ) { + this->on_packet(packet); + } } ); } @@ -130,8 +114,29 @@ void ERTView::on_hide() { Console::on_hide(); } -void ERTView::log(const std::string& s) { - writeln(s); +void ERTView::on_packet(const ert::Packet& packet) { + std::string msg; + switch(packet.type()) { + case ert::Packet::Type::SCM: + msg += "SCM "; + msg += to_string_dec_uint(packet.id(), 10); + msg += " "; + msg += to_string_dec_uint(packet.consumption(), 10); + break; + + case ert::Packet::Type::IDM: + msg += "IDM "; + msg += to_string_dec_uint(packet.id(), 10); + msg += " "; + msg += to_string_dec_uint(packet.consumption(), 10); + break; + + default: + msg += "???"; + break; + } + + writeln(msg); } } /* namespace ui */ diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index ebc268640..8ca08d19f 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -103,7 +103,7 @@ class ERTModel { public: ERTModel(); - std::string on_packet(const ERTPacketMessage& message); + bool on_packet(const ert::Packet& packet); private: LogFile log_file; @@ -119,7 +119,7 @@ public: private: ERTModel model; - void log(const std::string& s); + void on_packet(const ert::Packet& packet); }; } /* namespace ui */ From 9e004d47549980bd32191f632f90c5c04392ae90 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 6 Dec 2015 15:36:23 -0800 Subject: [PATCH 067/452] Move ERT packet type determination earlier. It'll eventually move into baseband. --- firmware/application/app_ert.cpp | 9 ++++++++- firmware/application/app_ert.hpp | 11 +++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 785f133c2..39e2632cb 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -99,7 +99,14 @@ void ERTView::on_show() { const auto message = static_cast(p); rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); - const ert::Packet packet { datetime, message->packet.preamble, message->packet.payload, message->packet.bits_received }; + ert::Packet::Type packet_type = ert::Packet::Type::Unknown; + if( message->packet.preamble == 0x1f2a60 ) { + packet_type = ert::Packet::Type::SCM; + } else if( message->packet.preamble == 0x555516a3 ) { + packet_type = ert::Packet::Type::IDM; + } + + const ert::Packet packet { datetime, packet_type, message->packet.payload, message->packet.bits_received }; if( this->model.on_packet(packet) ) { this->on_packet(packet); } diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index 8ca08d19f..4230483e3 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -56,7 +56,7 @@ public: Packet( const rtc::RTC& received_at, - const uint64_t preamble, + const Type type, const std::bitset<1024>& payload, const size_t payload_length ) : payload_ { payload }, @@ -64,13 +64,8 @@ public: received_at_ { received_at }, decoder_ { payload_, payload_length_ }, reader_ { decoder_ }, - type_ { Type::Unknown } + type_ { type } { - if( preamble == 0x1f2a60 ) { - type_ = Type::SCM; - } else if( preamble == 0x555516a3 ) { - type_ = Type::IDM; - } } size_t length() const; @@ -91,7 +86,7 @@ private: const rtc::RTC received_at_; const ManchesterDecoder decoder_; const Reader reader_; - Type type_; + const Type type_; const ID invalid_id = 0; const Consumption invalid_consumption = 0; From b9643dc9884bdc339dcd3056c49d1e3d6d81e186 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 6 Dec 2015 15:47:04 -0800 Subject: [PATCH 068/452] Clean up ERT packet type notation. Still not great, but at least repeated code is reduced. --- firmware/application/app_ert.cpp | 23 ++++++++--------------- firmware/application/app_ert.hpp | 12 +++--------- firmware/baseband/proc_ert.cpp | 4 ++-- firmware/common/message.hpp | 8 +++++++- 4 files changed, 20 insertions(+), 27 deletions(-) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 39e2632cb..3a0c75a63 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -45,27 +45,27 @@ rtc::RTC Packet::received_at() const { return received_at_; } -Packet::Type Packet::type() const { +ERTPacket::Type Packet::type() const { return type_; } ID Packet::id() const { - if( type() == Packet::Type::SCM ) { + if( type() == ERTPacket::Type::SCM ) { const auto msb = reader_.read(0, 2); const auto lsb = reader_.read(35, 24); return (msb << 24) | lsb; } - if( type() == Packet::Type::IDM ) { + if( type() == ERTPacket::Type::IDM ) { return reader_.read(5 * 8, 32); } return invalid_id; } Consumption Packet::consumption() const { - if( type() == Packet::Type::SCM ) { + if( type() == ERTPacket::Type::SCM ) { return reader_.read(11, 24); } - if( type() == Packet::Type::IDM ) { + if( type() == ERTPacket::Type::IDM ) { return reader_.read(25 * 8, 32); } return invalid_consumption; @@ -99,14 +99,7 @@ void ERTView::on_show() { const auto message = static_cast(p); rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); - ert::Packet::Type packet_type = ert::Packet::Type::Unknown; - if( message->packet.preamble == 0x1f2a60 ) { - packet_type = ert::Packet::Type::SCM; - } else if( message->packet.preamble == 0x555516a3 ) { - packet_type = ert::Packet::Type::IDM; - } - - const ert::Packet packet { datetime, packet_type, message->packet.payload, message->packet.bits_received }; + const ert::Packet packet { datetime, message->packet.type, message->packet.payload, message->packet.bits_received }; if( this->model.on_packet(packet) ) { this->on_packet(packet); } @@ -124,14 +117,14 @@ void ERTView::on_hide() { void ERTView::on_packet(const ert::Packet& packet) { std::string msg; switch(packet.type()) { - case ert::Packet::Type::SCM: + case ERTPacket::Type::SCM: msg += "SCM "; msg += to_string_dec_uint(packet.id(), 10); msg += " "; msg += to_string_dec_uint(packet.consumption(), 10); break; - case ert::Packet::Type::IDM: + case ERTPacket::Type::IDM: msg += "IDM "; msg += to_string_dec_uint(packet.id(), 10); msg += " "; diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index 4230483e3..53b0e533e 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -48,15 +48,9 @@ using Consumption = uint32_t; class Packet { public: - enum Type { - Unknown = 0, - IDM = 1, - SCM = 2, - }; - Packet( const rtc::RTC& received_at, - const Type type, + const ERTPacket::Type type, const std::bitset<1024>& payload, const size_t payload_length ) : payload_ { payload }, @@ -74,7 +68,7 @@ public: rtc::RTC received_at() const; - Type type() const; + ERTPacket::Type type() const; ID id() const; Consumption consumption() const; @@ -86,7 +80,7 @@ private: const rtc::RTC received_at_; const ManchesterDecoder decoder_; const Reader reader_; - const Type type_; + const ERTPacket::Type type_; const ID invalid_id = 0; const Consumption invalid_consumption = 0; diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index f27396c2e..97fd63073 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -99,7 +99,7 @@ void ERTProcessor::scm_handler( const size_t bits_received ) { ERTPacketMessage message; - message.packet.preamble = 0x1f2a60; + message.packet.type = ERTPacket::Type::SCM; message.packet.payload = payload; message.packet.bits_received = bits_received; shared_memory.application_queue.push(message); @@ -110,7 +110,7 @@ void ERTProcessor::idm_handler( const size_t bits_received ) { ERTPacketMessage message; - message.packet.preamble = 0x555516a3; + message.packet.type = ERTPacket::Type::IDM; message.packet.payload = payload; message.packet.bits_received = bits_received; shared_memory.application_queue.push(message); diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index d5c0101bf..995d0730b 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -242,7 +242,13 @@ public: }; struct ERTPacket { - uint64_t preamble { 0 }; + enum class Type : uint32_t { + Unknown = 0, + IDM = 1, + SCM = 2, + }; + + Type type { Type::Unknown }; std::bitset<1024> payload; size_t bits_received { 0 }; }; From 2d0052fb14c741aac3a6ac687b48dff0ef95de64 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 7 Dec 2015 09:58:08 -0800 Subject: [PATCH 069/452] Generalize ERT offset tracking a little. --- firmware/baseband/proc_ert.cpp | 6 +++--- firmware/baseband/proc_ert.hpp | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index 97fd63073..b9daa9527 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -51,9 +51,9 @@ void ERTProcessor::execute(buffer_c8_t buffer) { average_i += src->real(); average_q += src->imag(); average_count++; - if( average_count == 2048 ) { - offset_i = static_cast(average_i) / 2048.0f; - offset_q = static_cast(average_q) / 2048.0f; + if( average_count == average_window ) { + offset_i = static_cast(average_i) / average_window; + offset_q = static_cast(average_q) / average_window; average_i = 0; average_q = 0; average_count = 0; diff --git a/firmware/baseband/proc_ert.hpp b/firmware/baseband/proc_ert.hpp index fa38d286a..0bb3d0c3c 100644 --- a/firmware/baseband/proc_ert.hpp +++ b/firmware/baseband/proc_ert.hpp @@ -96,6 +96,7 @@ private: float sum_period[3]; float manchester[3]; + const size_t average_window { 2048 }; int32_t average_i { 0 }; int32_t average_q { 0 }; size_t average_count { 0 }; From 1c01f547176746d5dc282086685aa1b8cee04223 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 7 Dec 2015 09:59:41 -0800 Subject: [PATCH 070/452] Widen ERT baseband filter to 2.5MHz. It appears this will not negatively impact the noise floor vs. benefit of receiving additional channels (0.2MHz spacing). --- firmware/application/app_ert.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 3a0c75a63..a6cbde5e4 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -79,7 +79,7 @@ ERTModel::ERTModel() { .sampling_rate = 4194304, .decimation_factor = 1, }); - receiver_model.set_baseband_bandwidth(1750000); + receiver_model.set_baseband_bandwidth(2500000); log_file.open_for_append("ert.txt"); } From b9ea7fa7866263596f5fcf93c6c2c1a778554d62 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 7 Dec 2015 11:38:35 -0800 Subject: [PATCH 071/452] ERT CRC checking for SCM packets. IDM coming as soon as I can address packet truncation... --- firmware/application/app_ert.cpp | 17 +++++++++++++++++ firmware/application/app_ert.hpp | 2 ++ 2 files changed, 19 insertions(+) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index a6cbde5e4..6a08888a3 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -29,6 +29,7 @@ using namespace portapack; #include "lpc43xx_cpp.hpp" using namespace lpc43xx; +#include "crc.hpp" #include "string_format.hpp" namespace ert { @@ -71,6 +72,21 @@ Consumption Packet::consumption() const { return invalid_consumption; } +bool Packet::crc_ok() const { + if( type() == ERTPacket::Type::SCM ) { + CRC ert_bch { 0x6f63 }; + size_t start_bit = 5; + auto crc_calculated = ert_bch.calculate_byte(0x0000, reader_.read(0, start_bit)); + for(size_t i=start_bit; i; From bd33e652eae071591ecc5c830520e9cf32feb6a2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 7 Dec 2015 12:35:05 -0800 Subject: [PATCH 072/452] Abstract packet type/implementation details. --- firmware/application/app_ais.cpp | 17 +++++---- firmware/application/app_ais.hpp | 14 +++---- firmware/application/app_ert.cpp | 4 +- firmware/application/app_ert.hpp | 12 +++--- firmware/application/app_tpms.cpp | 2 +- firmware/application/manchester.cpp | 8 ++-- firmware/application/manchester.hpp | 11 +++--- firmware/baseband/packet_builder.hpp | 21 +++++----- firmware/baseband/proc_ais.cpp | 6 +-- firmware/baseband/proc_ais.hpp | 9 ++--- firmware/baseband/proc_ert.cpp | 12 ++---- firmware/baseband/proc_ert.hpp | 18 ++++----- firmware/baseband/proc_tpms.cpp | 6 +-- firmware/baseband/proc_tpms.hpp | 9 ++--- firmware/common/message.hpp | 13 +++---- firmware/common/packet.hpp | 57 ++++++++++++++++++++++++++++ 16 files changed, 129 insertions(+), 90 deletions(-) create mode 100644 firmware/common/packet.hpp diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 2188539d7..3633b6512 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -39,7 +39,7 @@ struct CRCBitRemap { } }; -using CRCFieldReader = ::FieldReader, CRCBitRemap>; +using CRCFieldReader = ::FieldReader<::Packet, CRCBitRemap>; struct PacketLengthRange { constexpr PacketLengthRange( @@ -131,8 +131,11 @@ struct PacketTooLong { }; struct CRCCheck { - bool operator()(const std::bitset<1024>& payload, const size_t data_length) { - CRCFieldReader field_crc { payload }; + bool operator()(const ::Packet& packet) { + const size_t data_and_fcs_length = packet.size() - 7; + const size_t data_length = data_and_fcs_length - 16; + + CRCFieldReader field_crc { packet }; CRC ais_fcs { 0x1021 }; uint16_t crc_calculated = 0xffff; @@ -198,12 +201,12 @@ static char char_to_ascii(const uint8_t c) { } size_t Packet::length() const { - return payload_length_; + return packet_.size(); } bool Packet::is_valid() const { // Subtract end flag (8 bits) - one unstuffing bit (occurs during end flag). - const size_t data_and_fcs_length = payload_length_ - 7; + const size_t data_and_fcs_length = length() - 7; if( data_and_fcs_length < 38 ) { return false; @@ -221,7 +224,7 @@ bool Packet::is_valid() const { } CRCCheck crc_ok; - if( !crc_ok(payload_, data_length) ) { + if( !crc_ok(packet_) ) { return false; } @@ -334,7 +337,7 @@ void AISView::on_show() { const auto message = static_cast(p); rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); - const baseband::ais::Packet packet { datetime, message->packet.payload, message->packet.bits_received }; + const baseband::ais::Packet packet { datetime, message->packet.packet }; if( this->model.on_packet(packet) ) { this->on_packet(packet); } diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 3f5c096f5..f31e62c83 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -26,6 +26,7 @@ #include "message.hpp" #include "log_file.hpp" #include "field_reader.hpp" +#include "packet.hpp" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -48,7 +49,7 @@ struct BitRemap { } }; -using FieldReader = ::FieldReader, BitRemap>; +using FieldReader = ::FieldReader<::Packet, BitRemap>; struct DateTime { uint16_t year; @@ -68,12 +69,10 @@ class Packet { public: constexpr Packet( const rtc::RTC& received_at, - const std::bitset<1024>& payload, - const size_t payload_length - ) : payload_ { payload }, - payload_length_ { payload_length }, + const ::Packet& packet + ) : packet_ { packet }, received_at_ { received_at }, - field_ { payload_ } + field_ { packet_ } { } @@ -97,8 +96,7 @@ public: Longitude longitude(const size_t start_bit) const; private: - const std::bitset<1024> payload_; - const size_t payload_length_; + const ::Packet packet_; const rtc::RTC received_at_; const FieldReader field_; }; diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 6a08888a3..28d915758 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -35,7 +35,7 @@ using namespace lpc43xx; namespace ert { size_t Packet::length() const { - return payload_length_; + return packet_.size(); } bool Packet::is_valid() const { @@ -115,7 +115,7 @@ void ERTView::on_show() { const auto message = static_cast(p); rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); - const ert::Packet packet { datetime, message->packet.type, message->packet.payload, message->packet.bits_received }; + const ert::Packet packet { datetime, message->packet.type, message->packet.packet }; if( this->model.on_packet(packet) ) { this->on_packet(packet); } diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index 8c0880cb2..756e600f5 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -27,6 +27,7 @@ #include "log_file.hpp" #include "manchester.hpp" #include "field_reader.hpp" +#include "packet.hpp" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -51,12 +52,10 @@ public: Packet( const rtc::RTC& received_at, const ERTPacket::Type type, - const std::bitset<1024>& payload, - const size_t payload_length - ) : payload_ { payload }, - payload_length_ { payload_length }, + const ::Packet& packet + ) : packet_ { packet }, received_at_ { received_at }, - decoder_ { payload_, payload_length_ }, + decoder_ { packet_ }, reader_ { decoder_ }, type_ { type } { @@ -77,8 +76,7 @@ public: private: using Reader = FieldReader; - const std::bitset<1024> payload_; - const size_t payload_length_; + const ::Packet packet_; const rtc::RTC received_at_; const ManchesterDecoder decoder_; const Reader reader_; diff --git a/firmware/application/app_tpms.cpp b/firmware/application/app_tpms.cpp index a02aaf3c5..b88b6fa4b 100644 --- a/firmware/application/app_tpms.cpp +++ b/firmware/application/app_tpms.cpp @@ -44,7 +44,7 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { rtc::RTC received_at; rtcGetTime(&RTCD1, &received_at); - const ManchesterDecoder decoder(message.packet.payload, message.packet.bits_received, 1); + const ManchesterDecoder decoder(message.packet.packet, 1); const auto hex_formatted = format_manchester(decoder); if( log_file.is_ready() ) { diff --git a/firmware/application/manchester.cpp b/firmware/application/manchester.cpp index 8a9aa7241..3862faccb 100644 --- a/firmware/application/manchester.cpp +++ b/firmware/application/manchester.cpp @@ -25,9 +25,9 @@ ManchesterDecoder::DecodedSymbol ManchesterDecoder::operator[](const size_t index) const { const size_t encoded_index = index * 2; - if( (encoded_index + 1) < count ) { - const auto value = encoded[encoded_index + sense]; - const auto error = encoded[encoded_index + 0] == encoded[encoded_index + 1]; + if( (encoded_index + 1) < packet.size() ) { + const auto value = packet[encoded_index + sense]; + const auto error = packet[encoded_index + 0] == packet[encoded_index + 1]; return { value, error }; } else { return { 0, 1 }; @@ -35,7 +35,7 @@ ManchesterDecoder::DecodedSymbol ManchesterDecoder::operator[](const size_t inde } size_t ManchesterDecoder::symbols_count() const { - return count / 2; + return packet.size() / 2; } ManchesterFormatted format_manchester( diff --git a/firmware/application/manchester.hpp b/firmware/application/manchester.hpp index 93d902170..77262c465 100644 --- a/firmware/application/manchester.hpp +++ b/firmware/application/manchester.hpp @@ -27,6 +27,8 @@ #include #include +#include "packet.hpp" + class ManchesterDecoder { public: struct DecodedSymbol { @@ -35,11 +37,9 @@ public: }; constexpr ManchesterDecoder( - const std::bitset<1024>& encoded, - const size_t count, + const ::Packet& packet, const size_t sense = 0 - ) : encoded { encoded }, - count { count }, + ) : packet { packet }, sense { sense } { } @@ -49,8 +49,7 @@ public: size_t symbols_count() const; private: - const std::bitset<1024>& encoded; - const size_t count; + const ::Packet& packet; const size_t sense; }; diff --git a/firmware/baseband/packet_builder.hpp b/firmware/baseband/packet_builder.hpp index 3d756a7cf..66892f63a 100644 --- a/firmware/baseband/packet_builder.hpp +++ b/firmware/baseband/packet_builder.hpp @@ -28,6 +28,7 @@ #include #include "bit_pattern.hpp" +#include "packet.hpp" struct NeverMatch { bool operator()(const BitHistory&, const size_t) const { @@ -46,8 +47,7 @@ struct FixedLength { template class PacketBuilder { public: - using PayloadType = std::bitset<1024>; - using PayloadHandlerFunc = std::function; + using PayloadHandlerFunc = std::function; PacketBuilder( const PreambleMatcher preamble_matcher, @@ -78,18 +78,18 @@ public: switch(state) { case State::Preamble: - if( preamble(bit_history, bits_received) ) { + if( preamble(bit_history, packet.size()) ) { state = State::Payload; } break; case State::Payload: - if( !unstuff(bit_history, bits_received) ) { - payload[bits_received++] = symbol; + if( !unstuff(bit_history, packet.size()) ) { + packet.add(symbol); } - if( end(bit_history, bits_received) ) { - payload_handler(payload, bits_received); + if( end(bit_history, packet.size()) ) { + payload_handler(packet); reset_state(); } else { if( packet_truncated() ) { @@ -111,7 +111,7 @@ private: }; bool packet_truncated() const { - return bits_received >= payload.size(); + return packet.size() >= packet.capacity(); } const PayloadHandlerFunc payload_handler; @@ -121,12 +121,11 @@ private: UnstuffMatcher unstuff; EndMatcher end; - size_t bits_received { 0 }; State state { State::Preamble }; - PayloadType payload; + ::Packet packet; void reset_state() { - bits_received = 0; + packet.clear(); state = State::Preamble; } }; diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index 72bc5a160..c0ba0efb2 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -60,11 +60,9 @@ void AISProcessor::consume_symbol( } void AISProcessor::payload_handler( - const std::bitset<1024>& payload, - const size_t bits_received + const ::Packet& packet ) { AISPacketMessage message; - message.packet.payload = payload; - message.packet.bits_received = bits_received; + message.packet.packet = packet; shared_memory.application_queue.push(message); } diff --git a/firmware/baseband/proc_ais.hpp b/firmware/baseband/proc_ais.hpp index e52983f6a..c8a407e08 100644 --- a/firmware/baseband/proc_ais.hpp +++ b/firmware/baseband/proc_ais.hpp @@ -30,6 +30,7 @@ #include "clock_recovery.hpp" #include "symbol_coding.hpp" #include "packet_builder.hpp" +#include "packet.hpp" #include "message.hpp" @@ -41,8 +42,6 @@ class AISProcessor : public BasebandProcessor { public: - using payload_t = std::bitset<1024>; - void execute(buffer_c8_t buffer) override; private: @@ -58,13 +57,13 @@ private: { 0b0101010101111110, 16, 1 }, { 0b111110, 6 }, { 0b01111110, 8 }, - [this](const payload_t& payload, const size_t bits_received) { - this->payload_handler(payload, bits_received); + [this](const ::Packet& packet) { + this->payload_handler(packet); } }; void consume_symbol(const float symbol); - void payload_handler(const payload_t& payload, const size_t bits_received); + void payload_handler(const ::Packet& packet); }; #endif/*__PROC_AIS_H__*/ diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index b9daa9527..f3d683869 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -95,23 +95,19 @@ void ERTProcessor::consume_symbol( } void ERTProcessor::scm_handler( - const std::bitset<1024>& payload, - const size_t bits_received + const ::Packet& packet ) { ERTPacketMessage message; message.packet.type = ERTPacket::Type::SCM; - message.packet.payload = payload; - message.packet.bits_received = bits_received; + message.packet.packet = packet; shared_memory.application_queue.push(message); } void ERTProcessor::idm_handler( - const std::bitset<1024>& payload, - const size_t bits_received + const ::Packet& packet ) { ERTPacketMessage message; message.packet.type = ERTPacket::Type::IDM; - message.packet.payload = payload; - message.packet.bits_received = bits_received; + message.packet.packet = packet; shared_memory.application_queue.push(message); } diff --git a/firmware/baseband/proc_ert.hpp b/firmware/baseband/proc_ert.hpp index 0bb3d0c3c..e5b2654ea 100644 --- a/firmware/baseband/proc_ert.hpp +++ b/firmware/baseband/proc_ert.hpp @@ -29,6 +29,7 @@ #include "clock_recovery.hpp" #include "symbol_coding.hpp" #include "packet_builder.hpp" +#include "packet.hpp" #include "message.hpp" @@ -45,13 +46,10 @@ constexpr size_t scm_payload_length_max { 150 }; constexpr uint64_t idm_preamble_and_sync_manchester { 0b0110011001100110011001100110011001010110011010011001100101011010 }; constexpr size_t idm_preamble_and_sync_length { 64 - 16 }; -// TODO: Should be 1408, but need to widen pathway to application processor... -constexpr size_t idm_payload_length_max { 960 }; +constexpr size_t idm_payload_length_max { 1408 }; class ERTProcessor : public BasebandProcessor { public: - using payload_t = std::bitset<1024>; - void execute(buffer_c8_t buffer) override; private: @@ -74,8 +72,8 @@ private: { scm_preamble_and_sync_manchester, scm_preamble_and_sync_length, 1 }, { }, { scm_payload_length_max }, - [this](const payload_t& payload, const size_t bits_received) { - this->scm_handler(payload, bits_received); + [this](const ::Packet& packet) { + this->scm_handler(packet); } }; @@ -83,14 +81,14 @@ private: { idm_preamble_and_sync_manchester, idm_preamble_and_sync_length, 1 }, { }, { idm_payload_length_max }, - [this](const payload_t& payload, const size_t bits_received) { - this->idm_handler(payload, bits_received); + [this](const ::Packet& packet) { + this->idm_handler(packet); } }; void consume_symbol(const float symbol); - void scm_handler(const payload_t& payload, const size_t bits_received); - void idm_handler(const payload_t& payload, const size_t bits_received); + void scm_handler(const ::Packet& packet); + void idm_handler(const ::Packet& packet); float sum_half_period[2]; float sum_period[3]; diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index 90f441e99..a6f18c73c 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -58,11 +58,9 @@ void TPMSProcessor::consume_symbol( } void TPMSProcessor::payload_handler( - const std::bitset<1024>& payload, - const size_t bits_received + const ::Packet& packet ) { TPMSPacketMessage message; - message.packet.payload = payload; - message.packet.bits_received = bits_received; + message.packet.packet = packet; shared_memory.application_queue.push(message); } diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index dc10259a9..1e531186a 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -30,6 +30,7 @@ #include "clock_recovery.hpp" #include "symbol_coding.hpp" #include "packet_builder.hpp" +#include "packet.hpp" #include "message.hpp" @@ -49,8 +50,6 @@ constexpr std::array, 8> rect_taps_153k6_1t_p { { class TPMSProcessor : public BasebandProcessor { public: - using payload_t = std::bitset<1024>; - void execute(buffer_c8_t buffer) override; private: @@ -65,13 +64,13 @@ private: { 0b010101010101010101010101010110, 30, 1 }, { }, { 256 }, - [this](const payload_t& payload, const size_t bits_received) { - this->payload_handler(payload, bits_received); + [this](const ::Packet& packet) { + this->payload_handler(packet); } }; void consume_symbol(const float symbol); - void payload_handler(const payload_t& payload, const size_t bits_received); + void payload_handler(const ::Packet& packet); }; #endif/*__PROC_TPMS_H__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 995d0730b..b88f8acae 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -27,6 +27,8 @@ #include #include +#include "packet.hpp" + #include "utility.hpp" #include "ch.h" @@ -201,11 +203,8 @@ public: ChannelSpectrum spectrum; }; -#include - struct AISPacket { - std::bitset<1024> payload; - size_t bits_received { 0 }; + ::Packet packet; }; class AISPacketMessage : public Message { @@ -219,8 +218,7 @@ public: }; struct TPMSPacket { - std::bitset<1024> payload; - size_t bits_received { 0 }; + ::Packet packet; }; class TPMSPacketMessage : public Message { @@ -249,8 +247,7 @@ struct ERTPacket { }; Type type { Type::Unknown }; - std::bitset<1024> payload; - size_t bits_received { 0 }; + ::Packet packet; }; class ERTPacketMessage : public Message { diff --git a/firmware/common/packet.hpp b/firmware/common/packet.hpp new file mode 100644 index 000000000..816a4727a --- /dev/null +++ b/firmware/common/packet.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PACKET_H__ +#define __PACKET_H__ + +#include +#include + +class Packet { +public: + void add(const bool symbol) { + if( count < capacity() ) { + data[count++] = symbol; + } + } + + uint_fast8_t operator[](const size_t index) const { + return (index < size()) ? data[index] : 0; + } + + size_t size() const { + return count; + } + + size_t capacity() const { + return data.size(); + } + + void clear() { + count = 0; + } + +private: + std::bitset<1408> data; + size_t count { 0 }; +}; + +#endif/*__PACKET_H__*/ From a2df8ea599714237567b2cfd81da1b6c52d4ed6a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 7 Dec 2015 15:29:43 -0800 Subject: [PATCH 073/452] Simplify excessively idiomatic C-ism. --- firmware/common/crc.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/crc.hpp b/firmware/common/crc.hpp index 0b825dc22..ded1934a7 100644 --- a/firmware/common/crc.hpp +++ b/firmware/common/crc.hpp @@ -59,7 +59,7 @@ public: */ T remainder = crc_in; remainder ^= data << (width() - 8); - for(size_t bit=8; bit>0; --bit) { + for(size_t bit=0; bit<8; bit++) { if( remainder & top_bit() ) { remainder = (remainder << 1) ^ polynomial; } else { From f1b45d4e7f875d069380defbfd8560cb63ea3ee9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 7 Dec 2015 15:31:01 -0800 Subject: [PATCH 074/452] Reinstate logging of ERT packets. --- firmware/application/app_ert.cpp | 11 ++++++++++- firmware/application/app_ert.hpp | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 28d915758..5996c0a02 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -72,6 +72,10 @@ Consumption Packet::consumption() const { return invalid_consumption; } +ManchesterFormatted Packet::symbols_formatted() const { + return format_manchester(decoder_); +} + bool Packet::crc_ok() const { if( type() == ERTPacket::Type::SCM ) { CRC ert_bch { 0x6f63 }; @@ -100,7 +104,12 @@ ERTModel::ERTModel() { log_file.open_for_append("ert.txt"); } -bool ERTModel::on_packet(const ert::Packet&) { +bool ERTModel::on_packet(const ert::Packet& packet) { + if( log_file.is_ready() ) { + const auto formatted = packet.symbols_formatted(); + log_file.write_entry(packet.received_at(), formatted.data + "/" + formatted.errors); + } + return true; } diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index 756e600f5..1e473daaa 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -71,6 +71,8 @@ public: ID id() const; Consumption consumption() const; + ManchesterFormatted symbols_formatted() const; + bool crc_ok() const; private: From ee1eadce5b53bf478d7cb52a4e01e7564297dd06 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 7 Dec 2015 15:31:42 -0800 Subject: [PATCH 075/452] Fix incorrect ERT packet length(). Was returning number of symbols before Manchester decoding. Oops. --- firmware/application/app_ert.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 5996c0a02..0000716f7 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -35,7 +35,7 @@ using namespace lpc43xx; namespace ert { size_t Packet::length() const { - return packet_.size(); + return decoder_.symbols_count(); } bool Packet::is_valid() const { From b61ed7dce258d310a5f8c8deec3a5e09e4026c3e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 7 Dec 2015 15:32:26 -0800 Subject: [PATCH 076/452] Clean up ERT CRC code, add IDM CRC checking. --- firmware/application/app_ert.cpp | 35 +++++++++++++++++++++++--------- firmware/application/app_ert.hpp | 3 +++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 0000716f7..96417703b 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -77,18 +77,32 @@ ManchesterFormatted Packet::symbols_formatted() const { } bool Packet::crc_ok() const { - if( type() == ERTPacket::Type::SCM ) { - CRC ert_bch { 0x6f63 }; - size_t start_bit = 5; - auto crc_calculated = ert_bch.calculate_byte(0x0000, reader_.read(0, start_bit)); - for(size_t i=start_bit; i ert_bch { 0x6f63 }; + size_t start_bit = 5; + auto crc_calculated = ert_bch.calculate_byte(0x0000, reader_.read(0, start_bit)); + for(size_t i=start_bit; i ert_crc_ccitt { 0x1021 }; + uint16_t crc_calculated = 0xffff; + for(size_t i=0; i Date: Mon, 7 Dec 2015 15:35:24 -0800 Subject: [PATCH 077/452] Only show ERT packets that pass CRC check. --- firmware/application/app_ert.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 96417703b..f1d4aa050 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -124,7 +124,7 @@ bool ERTModel::on_packet(const ert::Packet& packet) { log_file.write_entry(packet.received_at(), formatted.data + "/" + formatted.errors); } - return true; + return packet.crc_ok(); } namespace ui { @@ -161,7 +161,6 @@ void ERTView::on_packet(const ert::Packet& packet) { msg += to_string_dec_uint(packet.id(), 10); msg += " "; msg += to_string_dec_uint(packet.consumption(), 10); - msg += packet.crc_ok() ? " *" : " x"; break; case ERTPacket::Type::IDM: @@ -169,7 +168,6 @@ void ERTView::on_packet(const ert::Packet& packet) { msg += to_string_dec_uint(packet.id(), 10); msg += " "; msg += to_string_dec_uint(packet.consumption(), 10); - msg += packet.crc_ok() ? " *" : " x"; break; default: From 7cded79b59a1c04c327e11d17e488e475a7ae09b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 10:35:54 -0800 Subject: [PATCH 078/452] Clean up CRC class/interface, make more like boost::crc_basic. --- firmware/application/app_ais.cpp | 19 +++---- firmware/application/app_ert.cpp | 15 ++--- firmware/common/crc.hpp | 95 ++++++++++++++++---------------- 3 files changed, 62 insertions(+), 67 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 3633b6512..a7711818e 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -132,23 +132,18 @@ struct PacketTooLong { struct CRCCheck { bool operator()(const ::Packet& packet) { + const size_t fcs_length = 16; const size_t data_and_fcs_length = packet.size() - 7; - const size_t data_length = data_and_fcs_length - 16; + const size_t data_length = data_and_fcs_length - fcs_length; CRCFieldReader field_crc { packet }; - CRC ais_fcs { 0x1021 }; + CRC ais_fcs { 0x1021, 0xffff, 0xffff }; - uint16_t crc_calculated = 0xffff; - - for(size_t i=0; i ert_bch { 0x6f63 }; size_t start_bit = 5; - auto crc_calculated = ert_bch.calculate_byte(0x0000, reader_.read(0, start_bit)); + ert_bch.process_byte(reader_.read(0, start_bit)); for(size_t i=start_bit; i ert_crc_ccitt { 0x1021 }; - uint16_t crc_calculated = 0xffff; + CRC ert_crc_ccitt { 0x1021, 0xffff, 0x1d0f }; for(size_t i=0; i #include +/* Inspired by + * http://www.barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code + * + * ...then munged into a shape resembling boost::crc_basic. + * http://www.boost.org/doc/libs/release/libs/crc/ + */ + template class CRC { public: constexpr CRC( - const T polynomial/*, - const T initial*/ - ) : polynomial { polynomial }/*, - initial { initial }*/ + const T truncated_polynomial, + const T initial_remainder = 0, + const T final_xor_value = 0 + ) : truncated_polynomial { truncated_polynomial }, + initial_remainder { initial_remainder }, + final_xor_value { final_xor_value }, + remainder { initial_remainder } { - // CRC LSB must always be 1 } -/* - template - T calculate(const U& bits, const size_t length) { - if( length > bits.size() ) { - // Exception. - return 0; - } - T crc = 0; - - for(size_t i=0; i Date: Tue, 8 Dec 2015 11:14:00 -0800 Subject: [PATCH 079/452] AIS Packet refactor, consolidating duplicate packet length code. --- firmware/application/app_ais.cpp | 54 ++++++++++++++------------------ firmware/application/app_ais.hpp | 7 +++++ 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index a7711818e..b222e6119 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -130,23 +130,6 @@ struct PacketTooLong { } }; -struct CRCCheck { - bool operator()(const ::Packet& packet) { - const size_t fcs_length = 16; - const size_t data_and_fcs_length = packet.size() - 7; - const size_t data_length = data_and_fcs_length - fcs_length; - - CRCFieldReader field_crc { packet }; - CRC ais_fcs { 0x1021, 0xffff, 0xffff }; - - for(size_t i=0; i(field_.read(start_bit, 28) << 4) / 16; } +bool Packet::crc_ok() const { + CRCFieldReader field_crc { packet_ }; + CRC ais_fcs { 0x1021, 0xffff, 0xffff }; + + for(size_t i=0; i Date: Tue, 8 Dec 2015 13:38:40 -0800 Subject: [PATCH 080/452] AIS: More simplifying of packet length/validation code. --- firmware/application/app_ais.cpp | 30 +++++++++++++++--------------- firmware/application/app_ais.hpp | 2 ++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index b222e6119..b71463b20 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -183,21 +183,7 @@ size_t Packet::length() const { } bool Packet::is_valid() const { - if( data_and_fcs_length() < 38 ) { - return false; - } - - const size_t extra_bits = data_and_fcs_length() & 7; - if( extra_bits != 0 ) { - return false; - } - - PacketLengthValidator packet_length_valid; - if( !packet_length_valid(message_id(), data_length()) ) { - return false; - } - - return crc_ok(); + return length_valid() && crc_ok(); } rtc::RTC Packet::received_at() const { @@ -279,6 +265,20 @@ size_t Packet::data_length() const { return data_and_fcs_length() - fcs_length; } +bool Packet::length_valid() const { + const size_t extra_bits = data_and_fcs_length() & 7; + if( extra_bits != 0 ) { + return false; + } + + const PacketLengthValidator packet_length_valid; + if( !packet_length_valid(message_id(), data_length()) ) { + return false; + } + + return true; +} + } /* namespace ais */ } /* namespace baseband */ diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 12e5d60f1..74284f6f6 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -106,6 +106,8 @@ private: size_t data_and_fcs_length() const; size_t data_length() const; + + bool length_valid() const; }; } /* namespace ais */ From 31fdf026f252e3ed1efaa95a15f81c973b7b49da Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 13:47:52 -0800 Subject: [PATCH 081/452] constexpr a bunch of stuff. --- firmware/application/app_ais.cpp | 18 +++++++++--------- firmware/application/app_ais.hpp | 2 +- firmware/application/app_ert.hpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index b71463b20..6f2b3a30a 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -34,7 +34,7 @@ namespace baseband { namespace ais { struct CRCBitRemap { - size_t operator()(const size_t bit_index) const { + constexpr size_t operator()(const size_t& bit_index) const { return bit_index; } }; @@ -58,23 +58,23 @@ struct PacketLengthRange { // static_assert((max_bits & 7) == 0, "minimum bits not a multiple of 8"); } - bool contains(const size_t bit_count) const { + constexpr bool contains(const size_t bit_count) const { return !is_above(bit_count) && !is_below(bit_count); } - bool is_above(const size_t bit_count) const { + constexpr bool is_above(const size_t bit_count) const { return (min() > bit_count); } - bool is_below(const size_t bit_count) const { + constexpr bool is_below(const size_t bit_count) const { return (max() < bit_count); } - size_t min() const { + constexpr size_t min() const { return min_bytes * 8; } - size_t max() const { + constexpr size_t max() const { return max_bytes * 8; } @@ -119,13 +119,13 @@ static constexpr std::array packet_length_range { { } }; struct PacketLengthValidator { - bool operator()(const uint_fast8_t message_id, const size_t length) { + constexpr bool operator()(const uint_fast8_t message_id, const size_t length) const { return packet_length_range[message_id].contains(length); } }; struct PacketTooLong { - bool operator()(const uint_fast8_t message_id, const size_t length) { + constexpr bool operator()(const uint_fast8_t message_id, const size_t length) const { return packet_length_range[message_id].is_below(length); } }; @@ -174,7 +174,7 @@ static std::string format_navigational_status(const unsigned int value) { } } -static char char_to_ascii(const uint8_t c) { +static constexpr char char_to_ascii(const uint8_t c) { return (c ^ 32) + 32; } diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 74284f6f6..160aec45c 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -44,7 +44,7 @@ namespace baseband { namespace ais { struct BitRemap { - size_t operator()(const size_t bit_index) const { + constexpr size_t operator()(const size_t bit_index) const { return bit_index ^ 7; } }; diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index 9d0a29b0b..0053dbce7 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -39,7 +39,7 @@ using namespace lpc43xx; namespace ert { struct BitRemap { - size_t operator()(const size_t bit_index) const { + constexpr size_t operator()(const size_t bit_index) const { return bit_index; } }; From 90a7327cd5c49434d25eeb758191e26a177b863a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 14:15:15 -0800 Subject: [PATCH 082/452] Clean up FieldReader and BitRemap types. --- firmware/application/app_ais.cpp | 8 +------- firmware/application/app_ais.hpp | 12 +++--------- firmware/application/app_ert.hpp | 8 +------- firmware/common/field_reader.hpp | 15 +++++++++++++++ 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 6f2b3a30a..5c387e5bd 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -33,13 +33,7 @@ using namespace portapack; namespace baseband { namespace ais { -struct CRCBitRemap { - constexpr size_t operator()(const size_t& bit_index) const { - return bit_index; - } -}; - -using CRCFieldReader = ::FieldReader<::Packet, CRCBitRemap>; +using CRCFieldReader = ::FieldReader<::Packet, BitRemapNone>; struct PacketLengthRange { constexpr PacketLengthRange( diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 160aec45c..8cba0dacb 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -43,14 +43,6 @@ using namespace lpc43xx; namespace baseband { namespace ais { -struct BitRemap { - constexpr size_t operator()(const size_t bit_index) const { - return bit_index ^ 7; - } -}; - -using FieldReader = ::FieldReader<::Packet, BitRemap>; - struct DateTime { uint16_t year; uint8_t month; @@ -98,9 +90,11 @@ public: bool crc_ok() const; private: + using Reader = FieldReader<::Packet, BitRemapByteReverse>; + const ::Packet packet_; const rtc::RTC received_at_; - const FieldReader field_; + const Reader field_; const size_t fcs_length = 16; diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index 0053dbce7..bb78254fe 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -38,12 +38,6 @@ using namespace lpc43xx; namespace ert { -struct BitRemap { - constexpr size_t operator()(const size_t bit_index) const { - return bit_index; - } -}; - using ID = uint32_t; using Consumption = uint32_t; @@ -76,7 +70,7 @@ public: bool crc_ok() const; private: - using Reader = FieldReader; + using Reader = FieldReader; const ::Packet packet_; const rtc::RTC received_at_; diff --git a/firmware/common/field_reader.hpp b/firmware/common/field_reader.hpp index 4a1e05d6f..03d0a24d0 100644 --- a/firmware/common/field_reader.hpp +++ b/firmware/common/field_reader.hpp @@ -25,6 +25,18 @@ #include #include +struct BitRemapNone { + constexpr size_t operator()(const size_t& bit_index) const { + return bit_index; + } +}; + +struct BitRemapByteReverse { + constexpr size_t operator()(const size_t bit_index) const { + return bit_index ^ 7; + } +}; + template class FieldReader { public: @@ -34,6 +46,9 @@ public: { } + /* The "start_bit" winds up being the MSB of the returned field value. */ + /* The BitRemap functor determines which bits are read from the source + * packet. */ uint32_t read(const size_t start_bit, const size_t length) const { uint32_t value = 0; for(size_t i=start_bit; i<(start_bit + length); i++) { From 280acfd227384ef3a15829983920f79ad09237ac Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 14:16:36 -0800 Subject: [PATCH 083/452] First commit of AIS data scroller. It's weird and buggy right now, but I think I can make it work sensibly. --- firmware/application/app_ais.cpp | 42 ++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index 5c387e5bd..b39608798 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -432,23 +432,35 @@ void AISView::paint(Painter& painter) { const auto& s = style(); Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; - bool found_selected_item = false; - for(const auto entry : recent) { - const auto next_y = target_rect.pos.y + target_rect.height(); - const auto last_visible_entry = (next_y >= r.bottom()); + const size_t visible_item_count = r.height() / s.font.line_height(); + auto selected = selected_entry(); + if( selected == std::end(recent) ) { + selected = std::begin(recent); + } + + RecentEntries::iterator start = selected; + RecentEntries::iterator end = selected; + size_t i = 0; + + // Move start iterator toward first entry. + while( (start != std::begin(recent)) && (i < visible_item_count / 2) ) { + std::advance(start, -1); + i++; + } + + // Move end iterator toward last entry. + while( (end != std::end(recent)) && (i < visible_item_count) ) { + std::advance(end, 1); + i++; + } + + for(auto p = start; p != end; p++) { + const auto& entry = *p; const auto is_selected_key = (selected_key == entry.mmsi); - found_selected_item |= is_selected_key; - - if( !last_visible_entry || (last_visible_entry && found_selected_item) ) { - const auto& draw_style = (has_focus && is_selected_key) ? s.invert() : s; - draw_entry(entry, target_rect, painter, draw_style); - target_rect.pos.y += target_rect.height(); - } - - if( last_visible_entry && found_selected_item ) { - break; - } + const auto& draw_style = (has_focus && is_selected_key) ? s.invert() : s; + draw_entry(entry, target_rect, painter, draw_style); + target_rect.pos.y += target_rect.height(); } } From d0d97e92cb73aa0a0a1cf0fbf9d4912c3dee876a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 15:15:51 -0800 Subject: [PATCH 084/452] Rename ::Packet to baseband::Packet. Remove IPC packet types. --- firmware/application/app_ais.cpp | 4 +-- firmware/application/app_ais.hpp | 8 ++--- firmware/application/app_ert.cpp | 20 +++++------ firmware/application/app_ert.hpp | 12 +++---- firmware/application/app_tpms.cpp | 2 +- firmware/application/manchester.hpp | 6 ++-- firmware/baseband/packet_builder.hpp | 6 ++-- firmware/baseband/proc_ais.cpp | 4 +-- firmware/baseband/proc_ais.hpp | 6 ++-- firmware/baseband/proc_ert.cpp | 12 +++---- firmware/baseband/proc_ert.hpp | 10 +++--- firmware/baseband/proc_tpms.cpp | 4 +-- firmware/baseband/proc_tpms.hpp | 6 ++-- .../{packet.hpp => baseband_packet.hpp} | 10 ++++-- firmware/common/message.hpp | 35 +++++++------------ 15 files changed, 69 insertions(+), 76 deletions(-) rename firmware/common/{packet.hpp => baseband_packet.hpp} (89%) diff --git a/firmware/application/app_ais.cpp b/firmware/application/app_ais.cpp index b39608798..ca2545e7a 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/app_ais.cpp @@ -33,7 +33,7 @@ using namespace portapack; namespace baseband { namespace ais { -using CRCFieldReader = ::FieldReader<::Packet, BitRemapNone>; +using CRCFieldReader = ::FieldReader; struct PacketLengthRange { constexpr PacketLengthRange( @@ -320,7 +320,7 @@ void AISView::on_show() { const auto message = static_cast(p); rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); - const baseband::ais::Packet packet { datetime, message->packet.packet }; + const baseband::ais::Packet packet { datetime, message->packet }; if( this->model.on_packet(packet) ) { this->on_packet(packet); } diff --git a/firmware/application/app_ais.hpp b/firmware/application/app_ais.hpp index 8cba0dacb..3f2cad3f3 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/app_ais.hpp @@ -26,7 +26,7 @@ #include "message.hpp" #include "log_file.hpp" #include "field_reader.hpp" -#include "packet.hpp" +#include "baseband_packet.hpp" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -61,7 +61,7 @@ class Packet { public: constexpr Packet( const rtc::RTC& received_at, - const ::Packet& packet + const baseband::Packet& packet ) : packet_ { packet }, received_at_ { received_at }, field_ { packet_ } @@ -90,9 +90,9 @@ public: bool crc_ok() const; private: - using Reader = FieldReader<::Packet, BitRemapByteReverse>; + using Reader = FieldReader; - const ::Packet packet_; + const baseband::Packet packet_; const rtc::RTC received_at_; const Reader field_; diff --git a/firmware/application/app_ert.cpp b/firmware/application/app_ert.cpp index 970e8588f..28c17b541 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/app_ert.cpp @@ -46,27 +46,27 @@ rtc::RTC Packet::received_at() const { return received_at_; } -ERTPacket::Type Packet::type() const { +ERTPacketMessage::Type Packet::type() const { return type_; } ID Packet::id() const { - if( type() == ERTPacket::Type::SCM ) { + if( type() == ERTPacketMessage::Type::SCM ) { const auto msb = reader_.read(0, 2); const auto lsb = reader_.read(35, 24); return (msb << 24) | lsb; } - if( type() == ERTPacket::Type::IDM ) { + if( type() == ERTPacketMessage::Type::IDM ) { return reader_.read(5 * 8, 32); } return invalid_id; } Consumption Packet::consumption() const { - if( type() == ERTPacket::Type::SCM ) { + if( type() == ERTPacketMessage::Type::SCM ) { return reader_.read(11, 24); } - if( type() == ERTPacket::Type::IDM ) { + if( type() == ERTPacketMessage::Type::IDM ) { return reader_.read(25 * 8, 32); } return invalid_consumption; @@ -78,8 +78,8 @@ ManchesterFormatted Packet::symbols_formatted() const { bool Packet::crc_ok() const { switch(type()) { - case ERTPacket::Type::SCM: return crc_ok_scm(); - case ERTPacket::Type::IDM: return crc_ok_idm(); + case ERTPacketMessage::Type::SCM: return crc_ok_scm(); + case ERTPacketMessage::Type::IDM: return crc_ok_idm(); default: return false; } } @@ -135,7 +135,7 @@ void ERTView::on_show() { const auto message = static_cast(p); rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); - const ert::Packet packet { datetime, message->packet.type, message->packet.packet }; + const ert::Packet packet { datetime, message->type, message->packet }; if( this->model.on_packet(packet) ) { this->on_packet(packet); } @@ -153,14 +153,14 @@ void ERTView::on_hide() { void ERTView::on_packet(const ert::Packet& packet) { std::string msg; switch(packet.type()) { - case ERTPacket::Type::SCM: + case ERTPacketMessage::Type::SCM: msg += "SCM "; msg += to_string_dec_uint(packet.id(), 10); msg += " "; msg += to_string_dec_uint(packet.consumption(), 10); break; - case ERTPacket::Type::IDM: + case ERTPacketMessage::Type::IDM: msg += "IDM "; msg += to_string_dec_uint(packet.id(), 10); msg += " "; diff --git a/firmware/application/app_ert.hpp b/firmware/application/app_ert.hpp index bb78254fe..e35c7d3aa 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/app_ert.hpp @@ -27,7 +27,7 @@ #include "log_file.hpp" #include "manchester.hpp" #include "field_reader.hpp" -#include "packet.hpp" +#include "baseband_packet.hpp" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -45,8 +45,8 @@ class Packet { public: Packet( const rtc::RTC& received_at, - const ERTPacket::Type type, - const ::Packet& packet + const ERTPacketMessage::Type type, + const baseband::Packet& packet ) : packet_ { packet }, received_at_ { received_at }, decoder_ { packet_ }, @@ -61,7 +61,7 @@ public: rtc::RTC received_at() const; - ERTPacket::Type type() const; + ERTPacketMessage::Type type() const; ID id() const; Consumption consumption() const; @@ -72,11 +72,11 @@ public: private: using Reader = FieldReader; - const ::Packet packet_; + const baseband::Packet packet_; const rtc::RTC received_at_; const ManchesterDecoder decoder_; const Reader reader_; - const ERTPacket::Type type_; + const ERTPacketMessage::Type type_; const ID invalid_id = 0; const Consumption invalid_consumption = 0; diff --git a/firmware/application/app_tpms.cpp b/firmware/application/app_tpms.cpp index b88b6fa4b..25d1cacff 100644 --- a/firmware/application/app_tpms.cpp +++ b/firmware/application/app_tpms.cpp @@ -44,7 +44,7 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { rtc::RTC received_at; rtcGetTime(&RTCD1, &received_at); - const ManchesterDecoder decoder(message.packet.packet, 1); + const ManchesterDecoder decoder(message.packet, 1); const auto hex_formatted = format_manchester(decoder); if( log_file.is_ready() ) { diff --git a/firmware/application/manchester.hpp b/firmware/application/manchester.hpp index 77262c465..50cae73f2 100644 --- a/firmware/application/manchester.hpp +++ b/firmware/application/manchester.hpp @@ -27,7 +27,7 @@ #include #include -#include "packet.hpp" +#include "baseband_packet.hpp" class ManchesterDecoder { public: @@ -37,7 +37,7 @@ public: }; constexpr ManchesterDecoder( - const ::Packet& packet, + const baseband::Packet& packet, const size_t sense = 0 ) : packet { packet }, sense { sense } @@ -49,7 +49,7 @@ public: size_t symbols_count() const; private: - const ::Packet& packet; + const baseband::Packet& packet; const size_t sense; }; diff --git a/firmware/baseband/packet_builder.hpp b/firmware/baseband/packet_builder.hpp index 66892f63a..168f242e8 100644 --- a/firmware/baseband/packet_builder.hpp +++ b/firmware/baseband/packet_builder.hpp @@ -28,7 +28,7 @@ #include #include "bit_pattern.hpp" -#include "packet.hpp" +#include "baseband_packet.hpp" struct NeverMatch { bool operator()(const BitHistory&, const size_t) const { @@ -47,7 +47,7 @@ struct FixedLength { template class PacketBuilder { public: - using PayloadHandlerFunc = std::function; + using PayloadHandlerFunc = std::function; PacketBuilder( const PreambleMatcher preamble_matcher, @@ -122,7 +122,7 @@ private: EndMatcher end; State state { State::Preamble }; - ::Packet packet; + baseband::Packet packet; void reset_state() { packet.clear(); diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index c0ba0efb2..b411dc3da 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -60,9 +60,9 @@ void AISProcessor::consume_symbol( } void AISProcessor::payload_handler( - const ::Packet& packet + const baseband::Packet& packet ) { AISPacketMessage message; - message.packet.packet = packet; + message.packet = packet; shared_memory.application_queue.push(message); } diff --git a/firmware/baseband/proc_ais.hpp b/firmware/baseband/proc_ais.hpp index c8a407e08..94de70e0c 100644 --- a/firmware/baseband/proc_ais.hpp +++ b/firmware/baseband/proc_ais.hpp @@ -30,7 +30,7 @@ #include "clock_recovery.hpp" #include "symbol_coding.hpp" #include "packet_builder.hpp" -#include "packet.hpp" +#include "baseband_packet.hpp" #include "message.hpp" @@ -57,13 +57,13 @@ private: { 0b0101010101111110, 16, 1 }, { 0b111110, 6 }, { 0b01111110, 8 }, - [this](const ::Packet& packet) { + [this](const baseband::Packet& packet) { this->payload_handler(packet); } }; void consume_symbol(const float symbol); - void payload_handler(const ::Packet& packet); + void payload_handler(const baseband::Packet& packet); }; #endif/*__PROC_AIS_H__*/ diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index f3d683869..36f3d55ce 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -95,19 +95,19 @@ void ERTProcessor::consume_symbol( } void ERTProcessor::scm_handler( - const ::Packet& packet + const baseband::Packet& packet ) { ERTPacketMessage message; - message.packet.type = ERTPacket::Type::SCM; - message.packet.packet = packet; + message.type = ERTPacketMessage::Type::SCM; + message.packet = packet; shared_memory.application_queue.push(message); } void ERTProcessor::idm_handler( - const ::Packet& packet + const baseband::Packet& packet ) { ERTPacketMessage message; - message.packet.type = ERTPacket::Type::IDM; - message.packet.packet = packet; + message.type = ERTPacketMessage::Type::IDM; + message.packet = packet; shared_memory.application_queue.push(message); } diff --git a/firmware/baseband/proc_ert.hpp b/firmware/baseband/proc_ert.hpp index e5b2654ea..9663a1f36 100644 --- a/firmware/baseband/proc_ert.hpp +++ b/firmware/baseband/proc_ert.hpp @@ -29,7 +29,7 @@ #include "clock_recovery.hpp" #include "symbol_coding.hpp" #include "packet_builder.hpp" -#include "packet.hpp" +#include "baseband_packet.hpp" #include "message.hpp" @@ -72,7 +72,7 @@ private: { scm_preamble_and_sync_manchester, scm_preamble_and_sync_length, 1 }, { }, { scm_payload_length_max }, - [this](const ::Packet& packet) { + [this](const baseband::Packet& packet) { this->scm_handler(packet); } }; @@ -81,14 +81,14 @@ private: { idm_preamble_and_sync_manchester, idm_preamble_and_sync_length, 1 }, { }, { idm_payload_length_max }, - [this](const ::Packet& packet) { + [this](const baseband::Packet& packet) { this->idm_handler(packet); } }; void consume_symbol(const float symbol); - void scm_handler(const ::Packet& packet); - void idm_handler(const ::Packet& packet); + void scm_handler(const baseband::Packet& packet); + void idm_handler(const baseband::Packet& packet); float sum_half_period[2]; float sum_period[3]; diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index a6f18c73c..17eebafb6 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -58,9 +58,9 @@ void TPMSProcessor::consume_symbol( } void TPMSProcessor::payload_handler( - const ::Packet& packet + const baseband::Packet& packet ) { TPMSPacketMessage message; - message.packet.packet = packet; + message.packet = packet; shared_memory.application_queue.push(message); } diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index 1e531186a..fd7e1d20d 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -30,7 +30,7 @@ #include "clock_recovery.hpp" #include "symbol_coding.hpp" #include "packet_builder.hpp" -#include "packet.hpp" +#include "baseband_packet.hpp" #include "message.hpp" @@ -64,13 +64,13 @@ private: { 0b010101010101010101010101010110, 30, 1 }, { }, { 256 }, - [this](const ::Packet& packet) { + [this](const baseband::Packet& packet) { this->payload_handler(packet); } }; void consume_symbol(const float symbol); - void payload_handler(const ::Packet& packet); + void payload_handler(const baseband::Packet& packet); }; #endif/*__PROC_TPMS_H__*/ diff --git a/firmware/common/packet.hpp b/firmware/common/baseband_packet.hpp similarity index 89% rename from firmware/common/packet.hpp rename to firmware/common/baseband_packet.hpp index 816a4727a..4285828c5 100644 --- a/firmware/common/packet.hpp +++ b/firmware/common/baseband_packet.hpp @@ -19,12 +19,14 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __PACKET_H__ -#define __PACKET_H__ +#ifndef __BASEBAND_PACKET_H__ +#define __BASEBAND_PACKET_H__ #include #include +namespace baseband { + class Packet { public: void add(const bool symbol) { @@ -54,4 +56,6 @@ private: size_t count { 0 }; }; -#endif/*__PACKET_H__*/ +} /* namespace baseband */ + +#endif/*__BASEBAND_PACKET_H__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index b88f8acae..fd232befd 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -27,7 +27,7 @@ #include #include -#include "packet.hpp" +#include "baseband_packet.hpp" #include "utility.hpp" @@ -203,10 +203,6 @@ public: ChannelSpectrum spectrum; }; -struct AISPacket { - ::Packet packet; -}; - class AISPacketMessage : public Message { public: constexpr AISPacketMessage( @@ -214,11 +210,7 @@ public: { } - AISPacket packet; -}; - -struct TPMSPacket { - ::Packet packet; + baseband::Packet packet; }; class TPMSPacketMessage : public Message { @@ -228,7 +220,7 @@ public: { } - TPMSPacket packet; + baseband::Packet packet; }; class ShutdownMessage : public Message { @@ -239,17 +231,6 @@ public: } }; -struct ERTPacket { - enum class Type : uint32_t { - Unknown = 0, - IDM = 1, - SCM = 2, - }; - - Type type { Type::Unknown }; - ::Packet packet; -}; - class ERTPacketMessage : public Message { public: constexpr ERTPacketMessage( @@ -257,7 +238,15 @@ public: { } - ERTPacket packet; + enum class Type : uint32_t { + Unknown = 0, + IDM = 1, + SCM = 2, + }; + + Type type { Type::Unknown }; + + baseband::Packet packet; }; class MessageHandlerMap { From 218d81fc60128d2f1a581d70cd72e772a3f37149 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 15:28:33 -0800 Subject: [PATCH 085/452] Rename all the app .cpp/.hpp to have app name first. Larger refactoring of filenames and namespaces imminent! --- firmware/application/Makefile | 10 +++++----- firmware/application/{app_ais.cpp => ais_app.cpp} | 2 +- firmware/application/{app_ais.hpp => ais_app.hpp} | 6 +++--- .../{app_analog_audio.cpp => analog_audio_app.cpp} | 2 +- .../{app_analog_audio.hpp => analog_audio_app.hpp} | 6 +++--- firmware/application/{app_ert.cpp => ert_app.cpp} | 2 +- firmware/application/{app_ert.hpp => ert_app.hpp} | 6 +++--- ...spectrum_analysis.cpp => spectrum_analysis_app.cpp} | 2 +- ...spectrum_analysis.hpp => spectrum_analysis_app.hpp} | 6 +++--- firmware/application/{app_tpms.cpp => tpms_app.cpp} | 2 +- firmware/application/{app_tpms.hpp => tpms_app.hpp} | 6 +++--- firmware/application/ui_receiver.cpp | 10 +++++----- 12 files changed, 30 insertions(+), 30 deletions(-) rename firmware/application/{app_ais.cpp => ais_app.cpp} (99%) rename firmware/application/{app_ais.hpp => ais_app.hpp} (98%) rename firmware/application/{app_analog_audio.cpp => analog_audio_app.cpp} (97%) rename firmware/application/{app_analog_audio.hpp => analog_audio_app.hpp} (92%) rename firmware/application/{app_ert.cpp => ert_app.cpp} (99%) rename firmware/application/{app_ert.hpp => ert_app.hpp} (97%) rename firmware/application/{app_spectrum_analysis.cpp => spectrum_analysis_app.cpp} (96%) rename firmware/application/{app_spectrum_analysis.hpp => spectrum_analysis_app.hpp} (90%) rename firmware/application/{app_tpms.cpp => tpms_app.cpp} (99%) rename firmware/application/{app_tpms.hpp => tpms_app.hpp} (94%) diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 403056dd9..6b75b8a3b 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -168,12 +168,12 @@ CPPSRC = main.cpp \ ui_spectrum.cpp \ receiver_model.cpp \ spectrum_color_lut.cpp \ - app_analog_audio.cpp \ + analog_audio_app.cpp \ ais_baseband.cpp \ - app_ais.cpp \ - app_tpms.cpp \ - app_ert.cpp \ - app_spectrum_analysis.cpp \ + ais_app.cpp \ + tpms_app.cpp \ + ert_app.cpp \ + spectrum_analysis_app.cpp \ sd_card.cpp \ log_file.cpp \ manchester.cpp \ diff --git a/firmware/application/app_ais.cpp b/firmware/application/ais_app.cpp similarity index 99% rename from firmware/application/app_ais.cpp rename to firmware/application/ais_app.cpp index ca2545e7a..4abeeb60a 100644 --- a/firmware/application/app_ais.cpp +++ b/firmware/application/ais_app.cpp @@ -19,7 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#include "app_ais.hpp" +#include "ais_app.hpp" #include "portapack.hpp" using namespace portapack; diff --git a/firmware/application/app_ais.hpp b/firmware/application/ais_app.hpp similarity index 98% rename from firmware/application/app_ais.hpp rename to firmware/application/ais_app.hpp index 3f2cad3f3..1143366b3 100644 --- a/firmware/application/app_ais.hpp +++ b/firmware/application/ais_app.hpp @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __APP_AIS_H__ -#define __APP_AIS_H__ +#ifndef __AIS_APP_H__ +#define __AIS_APP_H__ #include "ui_console.hpp" #include "message.hpp" @@ -190,4 +190,4 @@ private: } /* namespace ui */ -#endif/*__APP_AIS_H__*/ +#endif/*__AIS_APP_H__*/ diff --git a/firmware/application/app_analog_audio.cpp b/firmware/application/analog_audio_app.cpp similarity index 97% rename from firmware/application/app_analog_audio.cpp rename to firmware/application/analog_audio_app.cpp index 185ce7807..f5ec76cff 100644 --- a/firmware/application/app_analog_audio.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -19,7 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#include "app_analog_audio.hpp" +#include "analog_audio_app.hpp" #include "portapack.hpp" using namespace portapack; diff --git a/firmware/application/app_analog_audio.hpp b/firmware/application/analog_audio_app.hpp similarity index 92% rename from firmware/application/app_analog_audio.hpp rename to firmware/application/analog_audio_app.hpp index 1303a05e8..20703094e 100644 --- a/firmware/application/app_analog_audio.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __APP_ANALOG_AUDIO_H__ -#define __APP_ANALOG_AUDIO_H__ +#ifndef __ANALOG_AUDIO_APP_H__ +#define __ANALOG_AUDIO_APP_H__ #include "receiver_model.hpp" #include "ui_spectrum.hpp" @@ -46,4 +46,4 @@ private: } /* namespace ui */ -#endif/*__APP_ANALOG_AUDIO_H__*/ +#endif/*__ANALOG_AUDIO_APP_H__*/ diff --git a/firmware/application/app_ert.cpp b/firmware/application/ert_app.cpp similarity index 99% rename from firmware/application/app_ert.cpp rename to firmware/application/ert_app.cpp index 28c17b541..8fb1e9924 100644 --- a/firmware/application/app_ert.cpp +++ b/firmware/application/ert_app.cpp @@ -19,7 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#include "app_ert.hpp" +#include "ert_app.hpp" #include "portapack.hpp" using namespace portapack; diff --git a/firmware/application/app_ert.hpp b/firmware/application/ert_app.hpp similarity index 97% rename from firmware/application/app_ert.hpp rename to firmware/application/ert_app.hpp index e35c7d3aa..301475ea5 100644 --- a/firmware/application/app_ert.hpp +++ b/firmware/application/ert_app.hpp @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __APP_ERT_H__ -#define __APP_ERT_H__ +#ifndef __ERT_APP_H__ +#define __ERT_APP_H__ #include "ui_console.hpp" #include "message.hpp" @@ -112,4 +112,4 @@ private: } /* namespace ui */ -#endif/*__APP_ERT_H__*/ +#endif/*__ERT_APP_H__*/ diff --git a/firmware/application/app_spectrum_analysis.cpp b/firmware/application/spectrum_analysis_app.cpp similarity index 96% rename from firmware/application/app_spectrum_analysis.cpp rename to firmware/application/spectrum_analysis_app.cpp index 6da566653..de3a14b0c 100644 --- a/firmware/application/app_spectrum_analysis.cpp +++ b/firmware/application/spectrum_analysis_app.cpp @@ -19,7 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#include "app_spectrum_analysis.hpp" +#include "spectrum_analysis_app.hpp" #include "portapack.hpp" using namespace portapack; diff --git a/firmware/application/app_spectrum_analysis.hpp b/firmware/application/spectrum_analysis_app.hpp similarity index 90% rename from firmware/application/app_spectrum_analysis.hpp rename to firmware/application/spectrum_analysis_app.hpp index d725c198c..9e8196af9 100644 --- a/firmware/application/app_spectrum_analysis.hpp +++ b/firmware/application/spectrum_analysis_app.hpp @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __APP_SPECTRUM_ANALYSIS_H__ -#define __APP_SPECTRUM_ANALYSIS_H__ +#ifndef __SPECTRUM_ANALYSIS_APP_H__ +#define __SPECTRUM_ANALYSIS_APP_H__ #include "receiver_model.hpp" #include "ui_spectrum.hpp" @@ -41,4 +41,4 @@ private: } /* namespace ui */ -#endif/*__APP_SPECTRUM_ANALYSIS_H__*/ +#endif/*__SPECTRUM_ANALYSIS_APP_H__*/ diff --git a/firmware/application/app_tpms.cpp b/firmware/application/tpms_app.cpp similarity index 99% rename from firmware/application/app_tpms.cpp rename to firmware/application/tpms_app.cpp index 25d1cacff..3ac2ba85e 100644 --- a/firmware/application/app_tpms.cpp +++ b/firmware/application/tpms_app.cpp @@ -19,7 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#include "app_tpms.hpp" +#include "tpms_app.hpp" #include "portapack.hpp" using namespace portapack; diff --git a/firmware/application/app_tpms.hpp b/firmware/application/tpms_app.hpp similarity index 94% rename from firmware/application/app_tpms.hpp rename to firmware/application/tpms_app.hpp index 962129f08..37fb2542b 100644 --- a/firmware/application/app_tpms.hpp +++ b/firmware/application/tpms_app.hpp @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __APP_TPMS_H__ -#define __APP_TPMS_H__ +#ifndef __TPMS_APP_H__ +#define __TPMS_APP_H__ #include "ui_console.hpp" #include "message.hpp" @@ -53,4 +53,4 @@ private: } /* namespace ui */ -#endif/*__APP_TPMS_H__*/ +#endif/*__TPMS_APP_H__*/ diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 78682d142..d540b2103 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -26,11 +26,11 @@ using namespace portapack; #include "string_format.hpp" -#include "app_analog_audio.hpp" -#include "app_ais.hpp" -#include "app_tpms.hpp" -#include "app_ert.hpp" -#include "app_spectrum_analysis.hpp" +#include "analog_audio_app.hpp" +#include "ais_app.hpp" +#include "tpms_app.hpp" +#include "ert_app.hpp" +#include "spectrum_analysis_app.hpp" namespace ui { From 37d7d5b273bf673c88bbaa458f88271985100468 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 15:49:20 -0800 Subject: [PATCH 086/452] Separate AIS packet and formatting code from app code. --- firmware/application/Makefile | 1 + firmware/application/ais_app.cpp | 220 ++------------------------- firmware/application/ais_app.hpp | 75 +-------- firmware/application/ais_packet.cpp | 228 ++++++++++++++++++++++++++++ firmware/application/ais_packet.hpp | 102 +++++++++++++ 5 files changed, 345 insertions(+), 281 deletions(-) create mode 100644 firmware/application/ais_packet.cpp create mode 100644 firmware/application/ais_packet.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 6b75b8a3b..4642a7d01 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -170,6 +170,7 @@ CPPSRC = main.cpp \ spectrum_color_lut.cpp \ analog_audio_app.cpp \ ais_baseband.cpp \ + ais_packet.cpp \ ais_app.cpp \ tpms_app.cpp \ ert_app.cpp \ diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 4abeeb60a..91559976f 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -21,124 +21,31 @@ #include "ais_app.hpp" +#include "string_format.hpp" + #include "portapack.hpp" using namespace portapack; -#include "crc.hpp" - -#include "string_format.hpp" - #include -namespace baseband { namespace ais { +namespace format { -using CRCFieldReader = ::FieldReader; - -struct PacketLengthRange { - constexpr PacketLengthRange( - ) : min_bytes { 0 }, - max_bytes { 0 } - { - } - - constexpr PacketLengthRange( - const uint16_t min_bits, - const uint16_t max_bits - ) : min_bytes { static_cast(min_bits / 8U) }, - max_bytes { static_cast(max_bits / 8U) } - { - // static_assert((min_bits & 7) == 0, "minimum bits not a multiple of 8"); - // static_assert((max_bits & 7) == 0, "minimum bits not a multiple of 8"); - } - - constexpr bool contains(const size_t bit_count) const { - return !is_above(bit_count) && !is_below(bit_count); - } - - constexpr bool is_above(const size_t bit_count) const { - return (min() > bit_count); - } - - constexpr bool is_below(const size_t bit_count) const { - return (max() < bit_count); - } - - constexpr size_t min() const { - return min_bytes * 8; - } - - constexpr size_t max() const { - return max_bytes * 8; - } - -private: - const uint8_t min_bytes; - const uint8_t max_bytes; -}; - -static constexpr std::array packet_length_range { { - { 0, 0 }, // 0 - { 168, 168 }, // 1 - { 168, 168 }, // 2 - { 168, 168 }, // 3 - { 168, 168 }, // 4 - { 424, 424 }, // 5 - { 0, 0 }, // 6 - { 0, 0 }, // 7 - { 0, 1008 }, // 8 - { 0, 0 }, // 9 - { 0, 0 }, // 10 - { 0, 0 }, // 11 - { 0, 0 }, // 12 - { 0, 0 }, // 13 - { 0, 0 }, // 14 - { 0, 0 }, // 15 - { 0, 0 }, // 16 - { 0, 0 }, // 17 - { 168, 168 }, // 18 - { 0, 0 }, // 19 - { 72, 160 }, // 20 - { 272, 360 }, // 21 - { 168, 168 }, // 22 - { 160, 160 }, // 23 - { 160, 168 }, // 24 - { 0, 168 }, // 25 - { 0, 0 }, // 26 - { 0, 0 }, // 27 - { 0, 0 }, // 28 - { 0, 0 }, // 29 - { 0, 0 }, // 30 - { 0, 0 }, // 31 -} }; - -struct PacketLengthValidator { - constexpr bool operator()(const uint_fast8_t message_id, const size_t length) const { - return packet_length_range[message_id].contains(length); - } -}; - -struct PacketTooLong { - constexpr bool operator()(const uint_fast8_t message_id, const size_t length) const { - return packet_length_range[message_id].is_below(length); - } -}; - -static std::string format_latlon_normalized(const int32_t normalized) { +static std::string latlon_normalized(const int32_t normalized) { const int32_t t = (normalized * 5) / 3; const int32_t degrees = t / (100 * 10000); const int32_t fraction = std::abs(t) % (100 * 10000); return to_string_dec_int(degrees) + "." + to_string_dec_int(fraction, 6, '0'); } -static std::string format_mmsi( - const MMSI& mmsi +static std::string mmsi( + const baseband::ais::MMSI& mmsi ) { return to_string_dec_uint(mmsi, 9, '0'); } -static std::string format_datetime( - const DateTime& datetime +static std::string datetime( + const baseband::ais::DateTime& datetime ) { return to_string_dec_uint(datetime.year, 4, '0') + "/" + to_string_dec_uint(datetime.month, 2, '0') + "/" + @@ -148,7 +55,7 @@ static std::string format_datetime( to_string_dec_uint(datetime.second, 2, '0'); } -static std::string format_navigational_status(const unsigned int value) { +static std::string navigational_status(const unsigned int value) { switch(value) { case 0: return "under way w/engine"; case 1: return "at anchor"; @@ -168,113 +75,8 @@ static std::string format_navigational_status(const unsigned int value) { } } -static constexpr char char_to_ascii(const uint8_t c) { - return (c ^ 32) + 32; -} - -size_t Packet::length() const { - return packet_.size(); -} - -bool Packet::is_valid() const { - return length_valid() && crc_ok(); -} - -rtc::RTC Packet::received_at() const { - return received_at_; -} - -uint32_t Packet::message_id() const { - return field_.read(0, 6); -} - -MMSI Packet::user_id() const { - return field_.read(8, 30); -} - -MMSI Packet::source_id() const { - return field_.read(8, 30); -} - -uint32_t Packet::read(const size_t start_bit, const size_t length) const { - return field_.read(start_bit, length); -} - -std::string Packet::text( - const size_t start_bit, - const size_t character_count -) const { - std::string result; - result.reserve(character_count); - - const size_t character_length = 6; - const size_t end_bit = start_bit + character_count * character_length; - for(size_t i=start_bit; i(field_.read(start_bit + 0, 14)), - static_cast(field_.read(start_bit + 14, 4)), - static_cast(field_.read(start_bit + 18, 5)), - static_cast(field_.read(start_bit + 23, 5)), - static_cast(field_.read(start_bit + 28, 6)), - static_cast(field_.read(start_bit + 34, 6)), - }; -} - -Latitude Packet::latitude(const size_t start_bit) const { - // Shifting and dividing is to sign-extend the source field. - // TODO: There's probably a more elegant way to do it. - return static_cast(field_.read(start_bit, 27) << 5) / 32; -} - -Longitude Packet::longitude(const size_t start_bit) const { - // Shifting and dividing is to sign-extend the source field. - // TODO: There's probably a more elegant way to do it. - return static_cast(field_.read(start_bit, 28) << 4) / 16; -} - -bool Packet::crc_ok() const { - CRCFieldReader field_crc { packet_ }; - CRC ais_fcs { 0x1021, 0xffff, 0xffff }; - - for(size_t i=0; i #include #include -#include #include #include #include -namespace baseband { -namespace ais { - -struct DateTime { - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; -}; - -using Latitude = int32_t; -using Longitude = int32_t; - -using MMSI = uint32_t; - -class Packet { -public: - constexpr Packet( - const rtc::RTC& received_at, - const baseband::Packet& packet - ) : packet_ { packet }, - received_at_ { received_at }, - field_ { packet_ } - { - } - - size_t length() const; - - bool is_valid() const; - - rtc::RTC received_at() const; - - uint32_t message_id() const; - MMSI user_id() const; - MMSI source_id() const; - - uint32_t read(const size_t start_bit, const size_t length) const; - - std::string text(const size_t start_bit, const size_t character_count) const; - - DateTime datetime(const size_t start_bit) const; - - Latitude latitude(const size_t start_bit) const; - Longitude longitude(const size_t start_bit) const; - - bool crc_ok() const; - -private: - using Reader = FieldReader; - - const baseband::Packet packet_; - const rtc::RTC received_at_; - const Reader field_; - - const size_t fcs_length = 16; - - size_t data_and_fcs_length() const; - size_t data_length() const; - - bool length_valid() const; -}; - -} /* namespace ais */ -} /* namespace baseband */ - class AISModel { public: AISModel(); diff --git a/firmware/application/ais_packet.cpp b/firmware/application/ais_packet.cpp new file mode 100644 index 000000000..62bb98e22 --- /dev/null +++ b/firmware/application/ais_packet.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "ais_packet.hpp" + +#include "crc.hpp" + +#include + +namespace baseband { +namespace ais { + +using CRCFieldReader = ::FieldReader; + +struct PacketLengthRange { + constexpr PacketLengthRange( + ) : min_bytes { 0 }, + max_bytes { 0 } + { + } + + constexpr PacketLengthRange( + const uint16_t min_bits, + const uint16_t max_bits + ) : min_bytes { static_cast(min_bits / 8U) }, + max_bytes { static_cast(max_bits / 8U) } + { + // static_assert((min_bits & 7) == 0, "minimum bits not a multiple of 8"); + // static_assert((max_bits & 7) == 0, "minimum bits not a multiple of 8"); + } + + constexpr bool contains(const size_t bit_count) const { + return !is_above(bit_count) && !is_below(bit_count); + } + + constexpr bool is_above(const size_t bit_count) const { + return (min() > bit_count); + } + + constexpr bool is_below(const size_t bit_count) const { + return (max() < bit_count); + } + + constexpr size_t min() const { + return min_bytes * 8; + } + + constexpr size_t max() const { + return max_bytes * 8; + } + +private: + const uint8_t min_bytes; + const uint8_t max_bytes; +}; + +static constexpr std::array packet_length_range { { + { 0, 0 }, // 0 + { 168, 168 }, // 1 + { 168, 168 }, // 2 + { 168, 168 }, // 3 + { 168, 168 }, // 4 + { 424, 424 }, // 5 + { 0, 0 }, // 6 + { 0, 0 }, // 7 + { 0, 1008 }, // 8 + { 0, 0 }, // 9 + { 0, 0 }, // 10 + { 0, 0 }, // 11 + { 0, 0 }, // 12 + { 0, 0 }, // 13 + { 0, 0 }, // 14 + { 0, 0 }, // 15 + { 0, 0 }, // 16 + { 0, 0 }, // 17 + { 168, 168 }, // 18 + { 0, 0 }, // 19 + { 72, 160 }, // 20 + { 272, 360 }, // 21 + { 168, 168 }, // 22 + { 160, 160 }, // 23 + { 160, 168 }, // 24 + { 0, 168 }, // 25 + { 0, 0 }, // 26 + { 0, 0 }, // 27 + { 0, 0 }, // 28 + { 0, 0 }, // 29 + { 0, 0 }, // 30 + { 0, 0 }, // 31 +} }; + +struct PacketLengthValidator { + constexpr bool operator()(const uint_fast8_t message_id, const size_t length) const { + return packet_length_range[message_id].contains(length); + } +}; + +struct PacketTooLong { + constexpr bool operator()(const uint_fast8_t message_id, const size_t length) const { + return packet_length_range[message_id].is_below(length); + } +}; + +static constexpr char char_to_ascii(const uint8_t c) { + return (c ^ 32) + 32; +} + +size_t Packet::length() const { + return packet_.size(); +} + +bool Packet::is_valid() const { + return length_valid() && crc_ok(); +} + +rtc::RTC Packet::received_at() const { + return received_at_; +} + +uint32_t Packet::message_id() const { + return field_.read(0, 6); +} + +MMSI Packet::user_id() const { + return field_.read(8, 30); +} + +MMSI Packet::source_id() const { + return field_.read(8, 30); +} + +uint32_t Packet::read(const size_t start_bit, const size_t length) const { + return field_.read(start_bit, length); +} + +std::string Packet::text( + const size_t start_bit, + const size_t character_count +) const { + std::string result; + result.reserve(character_count); + + const size_t character_length = 6; + const size_t end_bit = start_bit + character_count * character_length; + for(size_t i=start_bit; i(field_.read(start_bit + 0, 14)), + static_cast(field_.read(start_bit + 14, 4)), + static_cast(field_.read(start_bit + 18, 5)), + static_cast(field_.read(start_bit + 23, 5)), + static_cast(field_.read(start_bit + 28, 6)), + static_cast(field_.read(start_bit + 34, 6)), + }; +} + +Latitude Packet::latitude(const size_t start_bit) const { + // Shifting and dividing is to sign-extend the source field. + // TODO: There's probably a more elegant way to do it. + return static_cast(field_.read(start_bit, 27) << 5) / 32; +} + +Longitude Packet::longitude(const size_t start_bit) const { + // Shifting and dividing is to sign-extend the source field. + // TODO: There's probably a more elegant way to do it. + return static_cast(field_.read(start_bit, 28) << 4) / 16; +} + +bool Packet::crc_ok() const { + CRCFieldReader field_crc { packet_ }; + CRC ais_fcs { 0x1021, 0xffff, 0xffff }; + + for(size_t i=0; i +#include +#include + +namespace baseband { +namespace ais { + +struct DateTime { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +}; + +using Latitude = int32_t; +using Longitude = int32_t; + +using MMSI = uint32_t; + +class Packet { +public: + constexpr Packet( + const rtc::RTC& received_at, + const baseband::Packet& packet + ) : packet_ { packet }, + received_at_ { received_at }, + field_ { packet_ } + { + } + + size_t length() const; + + bool is_valid() const; + + rtc::RTC received_at() const; + + uint32_t message_id() const; + MMSI user_id() const; + MMSI source_id() const; + + uint32_t read(const size_t start_bit, const size_t length) const; + + std::string text(const size_t start_bit, const size_t character_count) const; + + DateTime datetime(const size_t start_bit) const; + + Latitude latitude(const size_t start_bit) const; + Longitude longitude(const size_t start_bit) const; + + bool crc_ok() const; + +private: + using Reader = FieldReader; + + const baseband::Packet packet_; + const rtc::RTC received_at_; + const Reader field_; + + const size_t fcs_length = 16; + + size_t data_and_fcs_length() const; + size_t data_length() const; + + bool length_valid() const; +}; + +} /* namespace ais */ +} /* namespace baseband */ + +#endif/*__AIS_PACKET_H__*/ From 3e0acc998850e3ee19c641312cd4a05535ef094b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 15:53:17 -0800 Subject: [PATCH 087/452] AIS-related namespace cleanup. --- firmware/application/ais_app.cpp | 10 +++++----- firmware/application/ais_app.hpp | 14 +++++++------- firmware/application/ais_packet.cpp | 2 -- firmware/application/ais_packet.hpp | 2 -- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 91559976f..1aaa0e38f 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -39,13 +39,13 @@ static std::string latlon_normalized(const int32_t normalized) { } static std::string mmsi( - const baseband::ais::MMSI& mmsi + const ais::MMSI& mmsi ) { return to_string_dec_uint(mmsi, 9, '0'); } static std::string datetime( - const baseband::ais::DateTime& datetime + const ais::DateTime& datetime ) { return to_string_dec_uint(datetime.year, 4, '0') + "/" + to_string_dec_uint(datetime.month, 2, '0') + "/" + @@ -89,7 +89,7 @@ AISModel::AISModel() { log_file.open_for_append("ais.txt"); } -bool AISModel::on_packet(const baseband::ais::Packet& packet) { +bool AISModel::on_packet(const ais::Packet& packet) { // TODO: Unstuff here, not in baseband! if( !packet.is_valid() ) { @@ -122,7 +122,7 @@ void AISView::on_show() { const auto message = static_cast(p); rtc::RTC datetime; rtcGetTime(&RTCD1, &datetime); - const baseband::ais::Packet packet { datetime, message->packet }; + const ais::Packet packet { datetime, message->packet }; if( this->model.on_packet(packet) ) { this->on_packet(packet); } @@ -143,7 +143,7 @@ void AISView::truncate_entries() { } } -void AISView::on_packet(const baseband::ais::Packet& packet) { +void AISView::on_packet(const ais::Packet& packet) { const auto source_id = packet.source_id(); auto matching_recent = std::find_if(recent.begin(), recent.end(), [source_id](const AISView::RecentEntry& entry) { return entry.mmsi == source_id; } diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 8261db71f..9f51ebbda 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -42,7 +42,7 @@ class AISModel { public: AISModel(); - bool on_packet(const baseband::ais::Packet& packet); + bool on_packet(const ais::Packet& packet); private: LogFile log_file; @@ -69,7 +69,7 @@ public: private: AISModel model; - using EntryKey = baseband::ais::MMSI; + using EntryKey = ais::MMSI; EntryKey selected_key; const EntryKey invalid_key = 0xffffffff; @@ -77,12 +77,12 @@ private: struct Position { rtc::RTC timestamp { }; - baseband::ais::Latitude latitude { 0 }; - baseband::ais::Longitude longitude { 0 }; + ais::Latitude latitude { 0 }; + ais::Longitude longitude { 0 }; }; struct RecentEntry { - baseband::ais::MMSI mmsi; + ais::MMSI mmsi; std::string name; std::string call_sign; std::string destination; @@ -91,7 +91,7 @@ private: int8_t navigational_status; RecentEntry( - const baseband::ais::MMSI& mmsi + const ais::MMSI& mmsi ) : mmsi { mmsi }, last_position { }, received_count { 0 }, @@ -103,7 +103,7 @@ private: using RecentEntries = std::list; RecentEntries recent; - void on_packet(const baseband::ais::Packet& packet); + void on_packet(const ais::Packet& packet); void draw_entry( const RecentEntry& entry, diff --git a/firmware/application/ais_packet.cpp b/firmware/application/ais_packet.cpp index 62bb98e22..c212936d8 100644 --- a/firmware/application/ais_packet.cpp +++ b/firmware/application/ais_packet.cpp @@ -25,7 +25,6 @@ #include -namespace baseband { namespace ais { using CRCFieldReader = ::FieldReader; @@ -225,4 +224,3 @@ bool Packet::length_valid() const { } } /* namespace ais */ -} /* namespace baseband */ diff --git a/firmware/application/ais_packet.hpp b/firmware/application/ais_packet.hpp index c6ed84ee0..ac23b3b98 100644 --- a/firmware/application/ais_packet.hpp +++ b/firmware/application/ais_packet.hpp @@ -32,7 +32,6 @@ using namespace lpc43xx; #include #include -namespace baseband { namespace ais { struct DateTime { @@ -97,6 +96,5 @@ private: }; } /* namespace ais */ -} /* namespace baseband */ #endif/*__AIS_PACKET_H__*/ From 644d3837ff4cd9edd8e17722cbadb54b7847aa8f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 15:54:35 -0800 Subject: [PATCH 088/452] Consolidate AIS Packet types. --- firmware/application/ais_packet.cpp | 4 +--- firmware/application/ais_packet.hpp | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/firmware/application/ais_packet.cpp b/firmware/application/ais_packet.cpp index c212936d8..7999a111b 100644 --- a/firmware/application/ais_packet.cpp +++ b/firmware/application/ais_packet.cpp @@ -27,8 +27,6 @@ namespace ais { -using CRCFieldReader = ::FieldReader; - struct PacketLengthRange { constexpr PacketLengthRange( ) : min_bytes { 0 }, @@ -190,7 +188,7 @@ Longitude Packet::longitude(const size_t start_bit) const { } bool Packet::crc_ok() const { - CRCFieldReader field_crc { packet_ }; + CRCReader field_crc { packet_ }; CRC ais_fcs { 0x1021, 0xffff, 0xffff }; for(size_t i=0; i; + using CRCReader = FieldReader; const baseband::Packet packet_; const rtc::RTC received_at_; From 2e81d1f5b7565ce69823123ad7de29f77030c498 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 16:04:48 -0800 Subject: [PATCH 089/452] Separate ERT packet and UI code. --- firmware/application/Makefile | 1 + firmware/application/ert_app.cpp | 72 ---------------------- firmware/application/ert_app.hpp | 58 +---------------- firmware/application/ert_packet.cpp | 96 +++++++++++++++++++++++++++++ firmware/application/ert_packet.hpp | 87 ++++++++++++++++++++++++++ 5 files changed, 185 insertions(+), 129 deletions(-) create mode 100644 firmware/application/ert_packet.cpp create mode 100644 firmware/application/ert_packet.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 4642a7d01..cf6ab3dc7 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -174,6 +174,7 @@ CPPSRC = main.cpp \ ais_app.cpp \ tpms_app.cpp \ ert_app.cpp \ + ert_packet.cpp \ spectrum_analysis_app.cpp \ sd_card.cpp \ log_file.cpp \ diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 8fb1e9924..cf91c9bd7 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -32,78 +32,6 @@ using namespace lpc43xx; #include "crc.hpp" #include "string_format.hpp" -namespace ert { - -size_t Packet::length() const { - return decoder_.symbols_count(); -} - -bool Packet::is_valid() const { - return true; -} - -rtc::RTC Packet::received_at() const { - return received_at_; -} - -ERTPacketMessage::Type Packet::type() const { - return type_; -} - -ID Packet::id() const { - if( type() == ERTPacketMessage::Type::SCM ) { - const auto msb = reader_.read(0, 2); - const auto lsb = reader_.read(35, 24); - return (msb << 24) | lsb; - } - if( type() == ERTPacketMessage::Type::IDM ) { - return reader_.read(5 * 8, 32); - } - return invalid_id; -} - -Consumption Packet::consumption() const { - if( type() == ERTPacketMessage::Type::SCM ) { - return reader_.read(11, 24); - } - if( type() == ERTPacketMessage::Type::IDM ) { - return reader_.read(25 * 8, 32); - } - return invalid_consumption; -} - -ManchesterFormatted Packet::symbols_formatted() const { - return format_manchester(decoder_); -} - -bool Packet::crc_ok() const { - switch(type()) { - case ERTPacketMessage::Type::SCM: return crc_ok_scm(); - case ERTPacketMessage::Type::IDM: return crc_ok_idm(); - default: return false; - } -} - -bool Packet::crc_ok_scm() const { - CRC ert_bch { 0x6f63 }; - size_t start_bit = 5; - ert_bch.process_byte(reader_.read(0, start_bit)); - for(size_t i=start_bit; i ert_crc_ccitt { 0x1021, 0xffff, 0x1d0f }; - for(size_t i=0; i #include #include -namespace ert { - -using ID = uint32_t; -using Consumption = uint32_t; - -class Packet { -public: - Packet( - const rtc::RTC& received_at, - const ERTPacketMessage::Type type, - const baseband::Packet& packet - ) : packet_ { packet }, - received_at_ { received_at }, - decoder_ { packet_ }, - reader_ { decoder_ }, - type_ { type } - { - } - - size_t length() const; - - bool is_valid() const; - - rtc::RTC received_at() const; - - ERTPacketMessage::Type type() const; - ID id() const; - Consumption consumption() const; - - ManchesterFormatted symbols_formatted() const; - - bool crc_ok() const; - -private: - using Reader = FieldReader; - - const baseband::Packet packet_; - const rtc::RTC received_at_; - const ManchesterDecoder decoder_; - const Reader reader_; - const ERTPacketMessage::Type type_; - - const ID invalid_id = 0; - const Consumption invalid_consumption = 0; - - bool crc_ok_idm() const; - bool crc_ok_scm() const; -}; - -} /* namespace ert */ - class ERTModel { public: ERTModel(); diff --git a/firmware/application/ert_packet.cpp b/firmware/application/ert_packet.cpp new file mode 100644 index 000000000..7cec5fa79 --- /dev/null +++ b/firmware/application/ert_packet.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "ert_packet.hpp" + +#include "crc.hpp" + +namespace ert { + +size_t Packet::length() const { + return decoder_.symbols_count(); +} + +bool Packet::is_valid() const { + return true; +} + +rtc::RTC Packet::received_at() const { + return received_at_; +} + +ERTPacketMessage::Type Packet::type() const { + return type_; +} + +ID Packet::id() const { + if( type() == ERTPacketMessage::Type::SCM ) { + const auto msb = reader_.read(0, 2); + const auto lsb = reader_.read(35, 24); + return (msb << 24) | lsb; + } + if( type() == ERTPacketMessage::Type::IDM ) { + return reader_.read(5 * 8, 32); + } + return invalid_id; +} + +Consumption Packet::consumption() const { + if( type() == ERTPacketMessage::Type::SCM ) { + return reader_.read(11, 24); + } + if( type() == ERTPacketMessage::Type::IDM ) { + return reader_.read(25 * 8, 32); + } + return invalid_consumption; +} + +ManchesterFormatted Packet::symbols_formatted() const { + return format_manchester(decoder_); +} + +bool Packet::crc_ok() const { + switch(type()) { + case ERTPacketMessage::Type::SCM: return crc_ok_scm(); + case ERTPacketMessage::Type::IDM: return crc_ok_idm(); + default: return false; + } +} + +bool Packet::crc_ok_scm() const { + CRC ert_bch { 0x6f63 }; + size_t start_bit = 5; + ert_bch.process_byte(reader_.read(0, start_bit)); + for(size_t i=start_bit; i ert_crc_ccitt { 0x1021, 0xffff, 0x1d0f }; + for(size_t i=0; i +#include + +#include "field_reader.hpp" +#include "baseband_packet.hpp" +#include "manchester.hpp" +#include "message.hpp" + +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + +namespace ert { + +using ID = uint32_t; +using Consumption = uint32_t; + +class Packet { +public: + Packet( + const rtc::RTC& received_at, + const ERTPacketMessage::Type type, + const baseband::Packet& packet + ) : packet_ { packet }, + received_at_ { received_at }, + decoder_ { packet_ }, + reader_ { decoder_ }, + type_ { type } + { + } + + size_t length() const; + + bool is_valid() const; + + rtc::RTC received_at() const; + + ERTPacketMessage::Type type() const; + ID id() const; + Consumption consumption() const; + + ManchesterFormatted symbols_formatted() const; + + bool crc_ok() const; + +private: + using Reader = FieldReader; + + const baseband::Packet packet_; + const rtc::RTC received_at_; + const ManchesterDecoder decoder_; + const Reader reader_; + const ERTPacketMessage::Type type_; + + const ID invalid_id = 0; + const Consumption invalid_consumption = 0; + + bool crc_ok_idm() const; + bool crc_ok_scm() const; +}; + +} /* namespace ert */ + +#endif/*__ERT_PACKET_H__*/ From 7de187e267458d5436d21b002306c3bdf2bb36fb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 16:08:20 -0800 Subject: [PATCH 090/452] Move ERT, AIS packet code to common/. --- firmware/application/Makefile | 4 ++-- firmware/{application => common}/ais_packet.cpp | 0 firmware/{application => common}/ais_packet.hpp | 0 firmware/{application => common}/ert_packet.cpp | 0 firmware/{application => common}/ert_packet.hpp | 0 5 files changed, 2 insertions(+), 2 deletions(-) rename firmware/{application => common}/ais_packet.cpp (100%) rename firmware/{application => common}/ais_packet.hpp (100%) rename firmware/{application => common}/ert_packet.cpp (100%) rename firmware/{application => common}/ert_packet.hpp (100%) diff --git a/firmware/application/Makefile b/firmware/application/Makefile index cf6ab3dc7..5149b13c4 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -170,11 +170,11 @@ CPPSRC = main.cpp \ spectrum_color_lut.cpp \ analog_audio_app.cpp \ ais_baseband.cpp \ - ais_packet.cpp \ + ../commom/ais_packet.cpp \ ais_app.cpp \ tpms_app.cpp \ ert_app.cpp \ - ert_packet.cpp \ + ../common/ert_packet.cpp \ spectrum_analysis_app.cpp \ sd_card.cpp \ log_file.cpp \ diff --git a/firmware/application/ais_packet.cpp b/firmware/common/ais_packet.cpp similarity index 100% rename from firmware/application/ais_packet.cpp rename to firmware/common/ais_packet.cpp diff --git a/firmware/application/ais_packet.hpp b/firmware/common/ais_packet.hpp similarity index 100% rename from firmware/application/ais_packet.hpp rename to firmware/common/ais_packet.hpp diff --git a/firmware/application/ert_packet.cpp b/firmware/common/ert_packet.cpp similarity index 100% rename from firmware/application/ert_packet.cpp rename to firmware/common/ert_packet.cpp diff --git a/firmware/application/ert_packet.hpp b/firmware/common/ert_packet.hpp similarity index 100% rename from firmware/application/ert_packet.hpp rename to firmware/common/ert_packet.hpp From eb1402764ec42578c6d6ded27c4b860d03d61752 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 8 Dec 2015 16:19:27 -0800 Subject: [PATCH 091/452] Move ERT packet type to its rightful place. No longer mixed up with Message types. --- firmware/application/ert_app.cpp | 4 ++-- firmware/baseband/proc_ert.cpp | 4 ++-- firmware/common/ert_packet.cpp | 16 ++++++++-------- firmware/common/ert_packet.hpp | 13 +++++++++---- firmware/common/message.hpp | 9 ++------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index cf91c9bd7..1b4c4c83a 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -81,14 +81,14 @@ void ERTView::on_hide() { void ERTView::on_packet(const ert::Packet& packet) { std::string msg; switch(packet.type()) { - case ERTPacketMessage::Type::SCM: + case ert::Packet::Type::SCM: msg += "SCM "; msg += to_string_dec_uint(packet.id(), 10); msg += " "; msg += to_string_dec_uint(packet.consumption(), 10); break; - case ERTPacketMessage::Type::IDM: + case ert::Packet::Type::IDM: msg += "IDM "; msg += to_string_dec_uint(packet.id(), 10); msg += " "; diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index 36f3d55ce..c7c070741 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -98,7 +98,7 @@ void ERTProcessor::scm_handler( const baseband::Packet& packet ) { ERTPacketMessage message; - message.type = ERTPacketMessage::Type::SCM; + message.type = ert::Packet::Type::SCM; message.packet = packet; shared_memory.application_queue.push(message); } @@ -107,7 +107,7 @@ void ERTProcessor::idm_handler( const baseband::Packet& packet ) { ERTPacketMessage message; - message.type = ERTPacketMessage::Type::IDM; + message.type = ert::Packet::Type::IDM; message.packet = packet; shared_memory.application_queue.push(message); } diff --git a/firmware/common/ert_packet.cpp b/firmware/common/ert_packet.cpp index 7cec5fa79..e5c477f9c 100644 --- a/firmware/common/ert_packet.cpp +++ b/firmware/common/ert_packet.cpp @@ -37,27 +37,27 @@ rtc::RTC Packet::received_at() const { return received_at_; } -ERTPacketMessage::Type Packet::type() const { +Packet::Type Packet::type() const { return type_; } ID Packet::id() const { - if( type() == ERTPacketMessage::Type::SCM ) { + if( type() == Type::SCM ) { const auto msb = reader_.read(0, 2); const auto lsb = reader_.read(35, 24); return (msb << 24) | lsb; } - if( type() == ERTPacketMessage::Type::IDM ) { + if( type() == Type::IDM ) { return reader_.read(5 * 8, 32); } return invalid_id; } Consumption Packet::consumption() const { - if( type() == ERTPacketMessage::Type::SCM ) { + if( type() == Type::SCM ) { return reader_.read(11, 24); } - if( type() == ERTPacketMessage::Type::IDM ) { + if( type() == Type::IDM ) { return reader_.read(25 * 8, 32); } return invalid_consumption; @@ -69,9 +69,9 @@ ManchesterFormatted Packet::symbols_formatted() const { bool Packet::crc_ok() const { switch(type()) { - case ERTPacketMessage::Type::SCM: return crc_ok_scm(); - case ERTPacketMessage::Type::IDM: return crc_ok_idm(); - default: return false; + case Type::SCM: return crc_ok_scm(); + case Type::IDM: return crc_ok_idm(); + default: return false; } } diff --git a/firmware/common/ert_packet.hpp b/firmware/common/ert_packet.hpp index d7489571b..eaaa1763d 100644 --- a/firmware/common/ert_packet.hpp +++ b/firmware/common/ert_packet.hpp @@ -28,7 +28,6 @@ #include "field_reader.hpp" #include "baseband_packet.hpp" #include "manchester.hpp" -#include "message.hpp" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -40,9 +39,15 @@ using Consumption = uint32_t; class Packet { public: + enum class Type : uint32_t { + Unknown = 0, + IDM = 1, + SCM = 2, + }; + Packet( const rtc::RTC& received_at, - const ERTPacketMessage::Type type, + const Type type, const baseband::Packet& packet ) : packet_ { packet }, received_at_ { received_at }, @@ -58,7 +63,7 @@ public: rtc::RTC received_at() const; - ERTPacketMessage::Type type() const; + Type type() const; ID id() const; Consumption consumption() const; @@ -73,7 +78,7 @@ private: const rtc::RTC received_at_; const ManchesterDecoder decoder_; const Reader reader_; - const ERTPacketMessage::Type type_; + const Type type_; const ID invalid_id = 0; const Consumption invalid_consumption = 0; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index fd232befd..d0628ffe5 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -28,6 +28,7 @@ #include #include "baseband_packet.hpp" +#include "ert_packet.hpp" #include "utility.hpp" @@ -238,13 +239,7 @@ public: { } - enum class Type : uint32_t { - Unknown = 0, - IDM = 1, - SCM = 2, - }; - - Type type { Type::Unknown }; + ert::Packet::Type type { ert::Packet::Type::Unknown }; baseband::Packet packet; }; From 4d52f73f6ac44190d8b336f35cb12592f8060ac2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 11:28:18 -0800 Subject: [PATCH 092/452] Move Manchester to common/. --- firmware/{application => common}/manchester.cpp | 0 firmware/{application => common}/manchester.hpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename firmware/{application => common}/manchester.cpp (100%) rename firmware/{application => common}/manchester.hpp (100%) diff --git a/firmware/application/manchester.cpp b/firmware/common/manchester.cpp similarity index 100% rename from firmware/application/manchester.cpp rename to firmware/common/manchester.cpp diff --git a/firmware/application/manchester.hpp b/firmware/common/manchester.hpp similarity index 100% rename from firmware/application/manchester.hpp rename to firmware/common/manchester.hpp From 3bed016128349dded091e50c87d8ed79d75e7212 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 11:56:16 -0800 Subject: [PATCH 093/452] BasebandProcessor interface change to pass references, not copies. --- firmware/baseband/baseband_processor.cpp | 14 +++++++------- firmware/baseband/baseband_processor.hpp | 16 ++++++++-------- firmware/baseband/main.cpp | 2 +- firmware/baseband/proc_ais.cpp | 2 +- firmware/baseband/proc_ais.hpp | 2 +- firmware/baseband/proc_am_audio.cpp | 2 +- firmware/baseband/proc_am_audio.hpp | 2 +- firmware/baseband/proc_ert.cpp | 2 +- firmware/baseband/proc_ert.hpp | 2 +- firmware/baseband/proc_nfm_audio.cpp | 2 +- firmware/baseband/proc_nfm_audio.hpp | 2 +- firmware/baseband/proc_tpms.cpp | 2 +- firmware/baseband/proc_tpms.hpp | 2 +- firmware/baseband/proc_wfm_audio.cpp | 2 +- firmware/baseband/proc_wfm_audio.hpp | 2 +- firmware/baseband/proc_wideband_spectrum.cpp | 2 +- firmware/baseband/proc_wideband_spectrum.hpp | 2 +- 17 files changed, 30 insertions(+), 30 deletions(-) diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index 83e6d857e..2b57b8ec8 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -59,7 +59,7 @@ void BasebandProcessor::update_spectrum() { } } -void BasebandProcessor::feed_channel_stats(const buffer_c16_t channel) { +void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { channel_stats.feed( channel, [this](const ChannelStatistics statistics) { @@ -69,7 +69,7 @@ void BasebandProcessor::feed_channel_stats(const buffer_c16_t channel) { } void BasebandProcessor::feed_channel_spectrum( - const buffer_c16_t channel, + const buffer_c16_t& channel, const uint32_t filter_pass_frequency, const uint32_t filter_stop_frequency ) { @@ -83,7 +83,7 @@ void BasebandProcessor::feed_channel_spectrum( ); } -void BasebandProcessor::fill_audio_buffer(const buffer_s16_t audio) { +void BasebandProcessor::fill_audio_buffer(const buffer_s16_t& audio) { auto audio_buffer = audio::dma::tx_empty_buffer();; for(size_t i=0; i, 256> channel_spectrum; @@ -67,10 +67,10 @@ private: AudioStatsCollector audio_stats; AudioStatisticsMessage audio_stats_message; - void post_channel_stats_message(const ChannelStatistics statistics); - void post_channel_spectrum_message(const buffer_c16_t data); - void feed_audio_stats(const buffer_s16_t audio); - void post_audio_stats_message(const AudioStatistics statistics); + void post_channel_stats_message(const ChannelStatistics& statistics); + void post_channel_spectrum_message(const buffer_c16_t& data); + void feed_audio_stats(const buffer_s16_t& audio); + void post_audio_stats_message(const AudioStatistics& statistics); }; #endif/*__BASEBAND_PROCESSOR_H__*/ diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 70a9d43eb..4999e0672 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -135,7 +135,7 @@ private: while(true) { // TODO: Place correct sampling rate into buffer returned here: const auto buffer_tmp = baseband::dma::wait_for_rx_buffer(); - const buffer_c8_t buffer { + buffer_c8_t buffer { buffer_tmp.p, buffer_tmp.count, baseband_configuration.sampling_rate }; diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index b411dc3da..fa61004b1 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -26,7 +26,7 @@ #include "i2s.hpp" using namespace lpc43xx; -void AISProcessor::execute(buffer_c8_t buffer) { +void AISProcessor::execute(buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ auto decimator_out = decimator.execute(buffer); diff --git a/firmware/baseband/proc_ais.hpp b/firmware/baseband/proc_ais.hpp index 94de70e0c..67e3c7d28 100644 --- a/firmware/baseband/proc_ais.hpp +++ b/firmware/baseband/proc_ais.hpp @@ -42,7 +42,7 @@ class AISProcessor : public BasebandProcessor { public: - void execute(buffer_c8_t buffer) override; + void execute(buffer_c8_t& buffer) override; private: ChannelDecimator decimator { ChannelDecimator::DecimationFactor::By32 }; diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 7a688a088..4899f8021 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -23,7 +23,7 @@ #include -void NarrowbandAMAudio::execute(buffer_c8_t buffer) { +void NarrowbandAMAudio::execute(buffer_c8_t& buffer) { auto decimator_out = decimator.execute(buffer); const buffer_c16_t work_baseband_buffer { diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 6c0d91e59..d6f6ce11f 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -38,7 +38,7 @@ public: channel_filter.configure(channel_filter_taps.taps, 2); } - void execute(buffer_c8_t buffer) override; + void execute(buffer_c8_t& buffer) override; private: ChannelDecimator decimator; diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index c7c070741..34d6e0e83 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -41,7 +41,7 @@ float ERTProcessor::abs(const complex8_t& v) { return std::sqrt(r2_i2); } -void ERTProcessor::execute(buffer_c8_t buffer) { +void ERTProcessor::execute(buffer_c8_t& buffer) { /* 4.194304MHz, 2048 samples */ // auto decimator_out = decimator.execute(buffer); diff --git a/firmware/baseband/proc_ert.hpp b/firmware/baseband/proc_ert.hpp index 9663a1f36..09fea85cf 100644 --- a/firmware/baseband/proc_ert.hpp +++ b/firmware/baseband/proc_ert.hpp @@ -50,7 +50,7 @@ constexpr size_t idm_payload_length_max { 1408 }; class ERTProcessor : public BasebandProcessor { public: - void execute(buffer_c8_t buffer) override; + void execute(buffer_c8_t& buffer) override; private: const uint32_t baseband_sampling_rate = 4194304; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index e9b70cf9b..c18894168 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -24,7 +24,7 @@ #include #include -void NarrowbandFMAudio::execute(buffer_c8_t buffer) { +void NarrowbandFMAudio::execute(buffer_c8_t& buffer) { /* Called every 2048/3072000 second -- 1500Hz. */ auto decimator_out = decimator.execute(buffer); diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index f35533873..ede1c6ccd 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -39,7 +39,7 @@ public: channel_filter.configure(channel_filter_taps.taps, 2); } - void execute(buffer_c8_t buffer) override; + void execute(buffer_c8_t& buffer) override; private: ChannelDecimator decimator; diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index 17eebafb6..c8431b2c8 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -26,7 +26,7 @@ #include "i2s.hpp" using namespace lpc43xx; -void TPMSProcessor::execute(buffer_c8_t buffer) { +void TPMSProcessor::execute(buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ auto decimator_out = decimator.execute(buffer); diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index fd7e1d20d..79fa4ae18 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -50,7 +50,7 @@ constexpr std::array, 8> rect_taps_153k6_1t_p { { class TPMSProcessor : public BasebandProcessor { public: - void execute(buffer_c8_t buffer) override; + void execute(buffer_c8_t& buffer) override; private: ChannelDecimator decimator { ChannelDecimator::DecimationFactor::By16 }; diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 5f4a09ccd..d01ab1697 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -23,7 +23,7 @@ #include -void WidebandFMAudio::execute(buffer_c8_t buffer) { +void WidebandFMAudio::execute(buffer_c8_t& buffer) { auto decimator_out = decimator.execute(buffer); const buffer_s16_t work_audio_buffer { diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 3a0eb65c0..d638f46a8 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -37,7 +37,7 @@ public: decimator.set_decimation_factor(ChannelDecimator::DecimationFactor::By4); } - void execute(buffer_c8_t buffer) override; + void execute(buffer_c8_t& buffer) override; private: ChannelDecimator decimator; diff --git a/firmware/baseband/proc_wideband_spectrum.cpp b/firmware/baseband/proc_wideband_spectrum.cpp index 32ae65b97..d6beb0516 100644 --- a/firmware/baseband/proc_wideband_spectrum.cpp +++ b/firmware/baseband/proc_wideband_spectrum.cpp @@ -33,7 +33,7 @@ using namespace lpc43xx; #include -void WidebandSpectrum::execute(buffer_c8_t buffer) { +void WidebandSpectrum::execute(buffer_c8_t& buffer) { // 2048 complex8_t samples per buffer. // 102.4us per buffer. 20480 instruction cycles per buffer. diff --git a/firmware/baseband/proc_wideband_spectrum.hpp b/firmware/baseband/proc_wideband_spectrum.hpp index bbbe04eab..f142588ed 100644 --- a/firmware/baseband/proc_wideband_spectrum.hpp +++ b/firmware/baseband/proc_wideband_spectrum.hpp @@ -30,7 +30,7 @@ class WidebandSpectrum : public BasebandProcessor { public: - void execute(buffer_c8_t buffer) override; + void execute(buffer_c8_t& buffer) override; private: size_t sample_count = 0; From 98abc4bba8a0bbf1d7ec8279df86b9c6a27861fa Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 11:57:57 -0800 Subject: [PATCH 094/452] Create baseband statistics messages on stack. Code size shrank ~200 bytes with this change. --- firmware/baseband/baseband_processor.cpp | 2 ++ firmware/baseband/baseband_processor.hpp | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index 2b57b8ec8..cdf476ae2 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -94,6 +94,7 @@ void BasebandProcessor::fill_audio_buffer(const buffer_s16_t& audio) { } void BasebandProcessor::post_channel_stats_message(const ChannelStatistics& statistics) { + ChannelStatisticsMessage channel_stats_message; channel_stats_message.statistics = statistics; shared_memory.application_queue.push(channel_stats_message); } @@ -117,6 +118,7 @@ void BasebandProcessor::feed_audio_stats(const buffer_s16_t& audio) { } void BasebandProcessor::post_audio_stats_message(const AudioStatistics& statistics) { + AudioStatisticsMessage audio_stats_message; audio_stats_message.statistics = statistics; shared_memory.application_queue.push(audio_stats_message); } diff --git a/firmware/baseband/baseband_processor.hpp b/firmware/baseband/baseband_processor.hpp index 6d61aec04..32e4ea329 100644 --- a/firmware/baseband/baseband_processor.hpp +++ b/firmware/baseband/baseband_processor.hpp @@ -62,10 +62,7 @@ private: BlockDecimator<256> channel_spectrum_decimator { 4 }; ChannelStatsCollector channel_stats; - ChannelStatisticsMessage channel_stats_message; - AudioStatsCollector audio_stats; - AudioStatisticsMessage audio_stats_message; void post_channel_stats_message(const ChannelStatistics& statistics); void post_channel_spectrum_message(const buffer_c16_t& data); From 14f24d8584537d9fdc04c0a9895116925003bf53 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 12:04:43 -0800 Subject: [PATCH 095/452] Move BasebandProcessor message.push() from dedicated methods to existing lambdas. --- firmware/baseband/baseband_processor.cpp | 22 +++++++--------------- firmware/baseband/baseband_processor.hpp | 2 -- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index cdf476ae2..020e4b54c 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -62,8 +62,10 @@ void BasebandProcessor::update_spectrum() { void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { channel_stats.feed( channel, - [this](const ChannelStatistics statistics) { - this->post_channel_stats_message(statistics); + [](const ChannelStatistics statistics) { + ChannelStatisticsMessage channel_stats_message; + channel_stats_message.statistics = statistics; + shared_memory.application_queue.push(channel_stats_message); } ); } @@ -93,12 +95,6 @@ void BasebandProcessor::fill_audio_buffer(const buffer_s16_t& audio) { feed_audio_stats(audio); } -void BasebandProcessor::post_channel_stats_message(const ChannelStatistics& statistics) { - ChannelStatisticsMessage channel_stats_message; - channel_stats_message.statistics = statistics; - shared_memory.application_queue.push(channel_stats_message); -} - void BasebandProcessor::post_channel_spectrum_message(const buffer_c16_t& data) { if( !channel_spectrum_request_update ) { fft_swap(data, channel_spectrum); @@ -112,13 +108,9 @@ void BasebandProcessor::feed_audio_stats(const buffer_s16_t& audio) { audio_stats.feed( audio, [this](const AudioStatistics statistics) { - this->post_audio_stats_message(statistics); + AudioStatisticsMessage audio_stats_message; + audio_stats_message.statistics = statistics; + shared_memory.application_queue.push(audio_stats_message); } ); } - -void BasebandProcessor::post_audio_stats_message(const AudioStatistics& statistics) { - AudioStatisticsMessage audio_stats_message; - audio_stats_message.statistics = statistics; - shared_memory.application_queue.push(audio_stats_message); -} diff --git a/firmware/baseband/baseband_processor.hpp b/firmware/baseband/baseband_processor.hpp index 32e4ea329..26fa1dac8 100644 --- a/firmware/baseband/baseband_processor.hpp +++ b/firmware/baseband/baseband_processor.hpp @@ -64,10 +64,8 @@ private: ChannelStatsCollector channel_stats; AudioStatsCollector audio_stats; - void post_channel_stats_message(const ChannelStatistics& statistics); void post_channel_spectrum_message(const buffer_c16_t& data); void feed_audio_stats(const buffer_s16_t& audio); - void post_audio_stats_message(const AudioStatistics& statistics); }; #endif/*__BASEBAND_PROCESSOR_H__*/ From 77aceaaf568596d22a190311516244ffd7734e38 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 12:17:40 -0800 Subject: [PATCH 096/452] More BasebandProcessor pass by reference. --- firmware/baseband/baseband_processor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index 020e4b54c..19531938d 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -62,7 +62,7 @@ void BasebandProcessor::update_spectrum() { void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { channel_stats.feed( channel, - [](const ChannelStatistics statistics) { + [](const ChannelStatistics& statistics) { ChannelStatisticsMessage channel_stats_message; channel_stats_message.statistics = statistics; shared_memory.application_queue.push(channel_stats_message); @@ -79,7 +79,7 @@ void BasebandProcessor::feed_channel_spectrum( channel_filter_stop_frequency = filter_stop_frequency; channel_spectrum_decimator.feed( channel, - [this](const buffer_c16_t data) { + [this](const buffer_c16_t& data) { this->post_channel_spectrum_message(data); } ); @@ -107,7 +107,7 @@ void BasebandProcessor::post_channel_spectrum_message(const buffer_c16_t& data) void BasebandProcessor::feed_audio_stats(const buffer_s16_t& audio) { audio_stats.feed( audio, - [this](const AudioStatistics statistics) { + [this](const AudioStatistics& statistics) { AudioStatisticsMessage audio_stats_message; audio_stats_message.statistics = statistics; shared_memory.application_queue.push(audio_stats_message); From 3ed77af0c1ed26e7aefda735cea819d97b40062a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 12:25:11 -0800 Subject: [PATCH 097/452] BasebandProcessor: Streamline construction of some messages. --- firmware/baseband/baseband_processor.cpp | 6 ++---- firmware/common/message.hpp | 7 +++++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index 19531938d..b6b10d07e 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -63,8 +63,7 @@ void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { channel_stats.feed( channel, [](const ChannelStatistics& statistics) { - ChannelStatisticsMessage channel_stats_message; - channel_stats_message.statistics = statistics; + ChannelStatisticsMessage channel_stats_message { statistics }; shared_memory.application_queue.push(channel_stats_message); } ); @@ -108,8 +107,7 @@ void BasebandProcessor::feed_audio_stats(const buffer_s16_t& audio) { audio_stats.feed( audio, [this](const AudioStatistics& statistics) { - AudioStatisticsMessage audio_stats_message; - audio_stats_message.statistics = statistics; + AudioStatisticsMessage audio_stats_message { statistics }; shared_memory.application_queue.push(audio_stats_message); } ); diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index d0628ffe5..82bf0f265 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -117,7 +117,9 @@ struct ChannelStatistics { class ChannelStatisticsMessage : public Message { public: constexpr ChannelStatisticsMessage( - ) : Message { ID::ChannelStatistics } + const ChannelStatistics& statistics + ) : Message { ID::ChannelStatistics }, + statistics { statistics } { } @@ -150,8 +152,9 @@ struct AudioStatistics { class AudioStatisticsMessage : public Message { public: constexpr AudioStatisticsMessage( + const AudioStatistics& statistics ) : Message { ID::AudioStatistics }, - statistics { } + statistics { statistics } { } From ef315f0d92ecd8ef27051fe27a7fb45cad06cdd3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 12:36:12 -0800 Subject: [PATCH 098/452] Const/pass-by-reference a bunch more baseband stuff. --- firmware/baseband/audio_stats_collector.hpp | 4 ++-- firmware/baseband/baseband_processor.hpp | 2 +- firmware/baseband/baseband_stats_collector.hpp | 2 +- firmware/baseband/block_decimator.hpp | 2 +- firmware/baseband/channel_decimator.cpp | 6 +++--- firmware/baseband/channel_decimator.hpp | 8 ++++---- firmware/baseband/channel_stats_collector.hpp | 2 +- firmware/baseband/proc_ais.cpp | 2 +- firmware/baseband/proc_ais.hpp | 2 +- firmware/baseband/proc_am_audio.cpp | 2 +- firmware/baseband/proc_am_audio.hpp | 2 +- firmware/baseband/proc_ert.cpp | 2 +- firmware/baseband/proc_ert.hpp | 2 +- firmware/baseband/proc_nfm_audio.cpp | 2 +- firmware/baseband/proc_nfm_audio.hpp | 2 +- firmware/baseband/proc_tpms.cpp | 2 +- firmware/baseband/proc_tpms.hpp | 2 +- firmware/baseband/proc_wfm_audio.cpp | 2 +- firmware/baseband/proc_wfm_audio.hpp | 2 +- firmware/baseband/proc_wideband_spectrum.cpp | 2 +- firmware/baseband/proc_wideband_spectrum.hpp | 2 +- firmware/baseband/rssi_stats_collector.hpp | 2 +- 22 files changed, 28 insertions(+), 28 deletions(-) diff --git a/firmware/baseband/audio_stats_collector.hpp b/firmware/baseband/audio_stats_collector.hpp index 189fff802..15405673a 100644 --- a/firmware/baseband/audio_stats_collector.hpp +++ b/firmware/baseband/audio_stats_collector.hpp @@ -32,7 +32,7 @@ class AudioStatsCollector { public: template - void feed(buffer_s16_t src, Callback callback) { + void feed(const buffer_s16_t& src, Callback callback) { consume_audio_buffer(src); if( update_stats(src.count, src.sampling_rate) ) { @@ -55,7 +55,7 @@ private: AudioStatistics statistics; - void consume_audio_buffer(buffer_s16_t src) { + void consume_audio_buffer(const buffer_s16_t& src) { auto src_p = src.p; const auto src_end = &src.p[src.count]; while(src_p < src_end) { diff --git a/firmware/baseband/baseband_processor.hpp b/firmware/baseband/baseband_processor.hpp index 26fa1dac8..127854504 100644 --- a/firmware/baseband/baseband_processor.hpp +++ b/firmware/baseband/baseband_processor.hpp @@ -37,7 +37,7 @@ class BasebandProcessor { public: virtual ~BasebandProcessor() = default; - virtual void execute(buffer_c8_t& buffer) = 0; + virtual void execute(const buffer_c8_t& buffer) = 0; void update_spectrum(); diff --git a/firmware/baseband/baseband_stats_collector.hpp b/firmware/baseband/baseband_stats_collector.hpp index a44c2936d..d214d61f7 100644 --- a/firmware/baseband/baseband_stats_collector.hpp +++ b/firmware/baseband/baseband_stats_collector.hpp @@ -46,7 +46,7 @@ public: } template - void process(buffer_c8_t buffer, Callback callback) { + void process(const buffer_c8_t& buffer, Callback callback) { samples += buffer.count; const size_t report_samples = buffer.sampling_rate * report_interval; diff --git a/firmware/baseband/block_decimator.hpp b/firmware/baseband/block_decimator.hpp index dbca0ebd9..1f7710efc 100644 --- a/firmware/baseband/block_decimator.hpp +++ b/firmware/baseband/block_decimator.hpp @@ -65,7 +65,7 @@ public: } template - void feed(const buffer_c16_t src, BlockCallback callback) { + void feed(const buffer_c16_t& src, BlockCallback callback) { /* NOTE: Input block size must be >= factor */ set_input_sampling_rate(src.sampling_rate); diff --git a/firmware/baseband/channel_decimator.cpp b/firmware/baseband/channel_decimator.cpp index 80bd136b9..59dbd7ea7 100644 --- a/firmware/baseband/channel_decimator.cpp +++ b/firmware/baseband/channel_decimator.cpp @@ -21,7 +21,7 @@ #include "channel_decimator.hpp" -buffer_c16_t ChannelDecimator::execute_decimation(buffer_c8_t buffer) { +buffer_c16_t ChannelDecimator::execute_decimation(const buffer_c8_t& buffer) { const buffer_c16_t work_baseband_buffer { work_baseband.data(), work_baseband.size() @@ -80,8 +80,8 @@ buffer_c16_t ChannelDecimator::execute_decimation(buffer_c8_t buffer) { } buffer_c16_t ChannelDecimator::execute_stage_0( - buffer_c8_t buffer, - buffer_c16_t work_baseband_buffer + const buffer_c8_t& buffer, + const buffer_c16_t& work_baseband_buffer ) { if( fs_over_4_downconvert ) { return translate.execute(buffer, work_baseband_buffer); diff --git a/firmware/baseband/channel_decimator.hpp b/firmware/baseband/channel_decimator.hpp index 10a650332..956964b07 100644 --- a/firmware/baseband/channel_decimator.hpp +++ b/firmware/baseband/channel_decimator.hpp @@ -57,7 +57,7 @@ public: decimation_factor = f; } - buffer_c16_t execute(buffer_c8_t buffer) { + buffer_c16_t execute(const buffer_c8_t& buffer) { auto decimated = execute_decimation(buffer); return decimated; @@ -76,11 +76,11 @@ private: DecimationFactor decimation_factor; const bool fs_over_4_downconvert; - buffer_c16_t execute_decimation(buffer_c8_t buffer); + buffer_c16_t execute_decimation(const buffer_c8_t& buffer); buffer_c16_t execute_stage_0( - buffer_c8_t buffer, - buffer_c16_t work_baseband_buffer + const buffer_c8_t& buffer, + const buffer_c16_t& work_baseband_buffer ); }; diff --git a/firmware/baseband/channel_stats_collector.hpp b/firmware/baseband/channel_stats_collector.hpp index 8c91ac5b4..d03f03a16 100644 --- a/firmware/baseband/channel_stats_collector.hpp +++ b/firmware/baseband/channel_stats_collector.hpp @@ -34,7 +34,7 @@ class ChannelStatsCollector { public: template - void feed(buffer_c16_t src, Callback callback) { + void feed(const buffer_c16_t& src, Callback callback) { auto src_p = src.p; while(src_p < &src.p[src.count]) { const uint32_t sample = *__SIMD32(src_p)++; diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index fa61004b1..903a7e2f8 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -26,7 +26,7 @@ #include "i2s.hpp" using namespace lpc43xx; -void AISProcessor::execute(buffer_c8_t& buffer) { +void AISProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ auto decimator_out = decimator.execute(buffer); diff --git a/firmware/baseband/proc_ais.hpp b/firmware/baseband/proc_ais.hpp index 67e3c7d28..16bf42b45 100644 --- a/firmware/baseband/proc_ais.hpp +++ b/firmware/baseband/proc_ais.hpp @@ -42,7 +42,7 @@ class AISProcessor : public BasebandProcessor { public: - void execute(buffer_c8_t& buffer) override; + void execute(const buffer_c8_t& buffer) override; private: ChannelDecimator decimator { ChannelDecimator::DecimationFactor::By32 }; diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 4899f8021..5bb374e99 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -23,7 +23,7 @@ #include -void NarrowbandAMAudio::execute(buffer_c8_t& buffer) { +void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { auto decimator_out = decimator.execute(buffer); const buffer_c16_t work_baseband_buffer { diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index d6f6ce11f..dfa6d5ec0 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -38,7 +38,7 @@ public: channel_filter.configure(channel_filter_taps.taps, 2); } - void execute(buffer_c8_t& buffer) override; + void execute(const buffer_c8_t& buffer) override; private: ChannelDecimator decimator; diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index 34d6e0e83..5ef5d4967 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -41,7 +41,7 @@ float ERTProcessor::abs(const complex8_t& v) { return std::sqrt(r2_i2); } -void ERTProcessor::execute(buffer_c8_t& buffer) { +void ERTProcessor::execute(const buffer_c8_t& buffer) { /* 4.194304MHz, 2048 samples */ // auto decimator_out = decimator.execute(buffer); diff --git a/firmware/baseband/proc_ert.hpp b/firmware/baseband/proc_ert.hpp index 09fea85cf..439180d1c 100644 --- a/firmware/baseband/proc_ert.hpp +++ b/firmware/baseband/proc_ert.hpp @@ -50,7 +50,7 @@ constexpr size_t idm_payload_length_max { 1408 }; class ERTProcessor : public BasebandProcessor { public: - void execute(buffer_c8_t& buffer) override; + void execute(const buffer_c8_t& buffer) override; private: const uint32_t baseband_sampling_rate = 4194304; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index c18894168..4ac7539ec 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -24,7 +24,7 @@ #include #include -void NarrowbandFMAudio::execute(buffer_c8_t& buffer) { +void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { /* Called every 2048/3072000 second -- 1500Hz. */ auto decimator_out = decimator.execute(buffer); diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index ede1c6ccd..b4112dde2 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -39,7 +39,7 @@ public: channel_filter.configure(channel_filter_taps.taps, 2); } - void execute(buffer_c8_t& buffer) override; + void execute(const buffer_c8_t& buffer) override; private: ChannelDecimator decimator; diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index c8431b2c8..314a05e7b 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -26,7 +26,7 @@ #include "i2s.hpp" using namespace lpc43xx; -void TPMSProcessor::execute(buffer_c8_t& buffer) { +void TPMSProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ auto decimator_out = decimator.execute(buffer); diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index 79fa4ae18..541ee0e06 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -50,7 +50,7 @@ constexpr std::array, 8> rect_taps_153k6_1t_p { { class TPMSProcessor : public BasebandProcessor { public: - void execute(buffer_c8_t& buffer) override; + void execute(const buffer_c8_t& buffer) override; private: ChannelDecimator decimator { ChannelDecimator::DecimationFactor::By16 }; diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index d01ab1697..a708a9ac0 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -23,7 +23,7 @@ #include -void WidebandFMAudio::execute(buffer_c8_t& buffer) { +void WidebandFMAudio::execute(const buffer_c8_t& buffer) { auto decimator_out = decimator.execute(buffer); const buffer_s16_t work_audio_buffer { diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index d638f46a8..b4aa41bd5 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -37,7 +37,7 @@ public: decimator.set_decimation_factor(ChannelDecimator::DecimationFactor::By4); } - void execute(buffer_c8_t& buffer) override; + void execute(const buffer_c8_t& buffer) override; private: ChannelDecimator decimator; diff --git a/firmware/baseband/proc_wideband_spectrum.cpp b/firmware/baseband/proc_wideband_spectrum.cpp index d6beb0516..12fe1b7d8 100644 --- a/firmware/baseband/proc_wideband_spectrum.cpp +++ b/firmware/baseband/proc_wideband_spectrum.cpp @@ -33,7 +33,7 @@ using namespace lpc43xx; #include -void WidebandSpectrum::execute(buffer_c8_t& buffer) { +void WidebandSpectrum::execute(const buffer_c8_t& buffer) { // 2048 complex8_t samples per buffer. // 102.4us per buffer. 20480 instruction cycles per buffer. diff --git a/firmware/baseband/proc_wideband_spectrum.hpp b/firmware/baseband/proc_wideband_spectrum.hpp index f142588ed..b21f6b3e2 100644 --- a/firmware/baseband/proc_wideband_spectrum.hpp +++ b/firmware/baseband/proc_wideband_spectrum.hpp @@ -30,7 +30,7 @@ class WidebandSpectrum : public BasebandProcessor { public: - void execute(buffer_c8_t& buffer) override; + void execute(const buffer_c8_t& buffer) override; private: size_t sample_count = 0; diff --git a/firmware/baseband/rssi_stats_collector.hpp b/firmware/baseband/rssi_stats_collector.hpp index 6ab945bf1..7a1cd4940 100644 --- a/firmware/baseband/rssi_stats_collector.hpp +++ b/firmware/baseband/rssi_stats_collector.hpp @@ -31,7 +31,7 @@ class RSSIStatisticsCollector { public: template - void process(rf::rssi::buffer_t buffer, Callback callback) { + void process(const rf::rssi::buffer_t& buffer, Callback callback) { auto p = buffer.p; if( p == nullptr ) { return; From f36988506248fc866fcea3a3fa8e6a8d57d60766 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 13:21:27 -0800 Subject: [PATCH 099/452] Extract processor factory function. A small code size reduction. I tried using std::unique_ptr, but code bloated between 150 and 400 bytes! --- firmware/baseband/main.cpp | 48 ++++++++++++-------------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 4999e0672..bd2c458ab 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -321,6 +321,19 @@ private: static constexpr auto direction = baseband::Direction::Receive; +static BasebandProcessor* create_processor(const int32_t mode) { + switch(mode) { + case 0: return new NarrowbandAMAudio(); + case 1: return new NarrowbandFMAudio(); + case 2: return new WidebandFMAudio(); + case 3: return new AISProcessor(); + case 4: return new WidebandSpectrum(); + case 5: return new TPMSProcessor(); + case 6: return new ERTProcessor(); + default: return nullptr; + } +} + int main(void) { init(); @@ -345,39 +358,8 @@ int main(void) { auto old_p = baseband_thread.baseband_processor; baseband_thread.baseband_processor = nullptr; delete old_p; - - switch(message->configuration.mode) { - case 0: - baseband_thread.baseband_processor = new NarrowbandAMAudio(); - break; - - case 1: - baseband_thread.baseband_processor = new NarrowbandFMAudio(); - break; - - case 2: - baseband_thread.baseband_processor = new WidebandFMAudio(); - break; - - case 3: - baseband_thread.baseband_processor = new AISProcessor(); - break; - - case 4: - baseband_thread.baseband_processor = new WidebandSpectrum(); - break; - - case 5: - baseband_thread.baseband_processor = new TPMSProcessor(); - break; - - case 6: - baseband_thread.baseband_processor = new ERTProcessor(); - break; - - default: - break; - } + + baseband_thread.baseband_processor = create_processor(message->configuration.mode); if( baseband_thread.baseband_processor ) { if( direction == baseband::Direction::Receive ) { From 83bf2a9a3646fef72839391c501d746e16c40def Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 14:40:34 -0800 Subject: [PATCH 100/452] Tweak BasebandConfiguration constructors to avoid surprise type conversions. --- firmware/application/receiver_model.cpp | 6 +----- firmware/common/message.hpp | 9 +++++++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 709fbd9b2..f068f24d5 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -126,11 +126,7 @@ void ReceiverModel::enable() { void ReceiverModel::disable() { /* TODO: This is a dumb hack to stop baseband from working so hard. */ BasebandConfigurationMessage message { - .configuration = { - .mode = -1, - .sampling_rate = 0, - .decimation_factor = 1, - } + .configuration = { }, }; shared_memory.baseband_queue.push(message); diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 82bf0f265..a1c2e78ca 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -167,14 +167,19 @@ struct BasebandConfiguration { size_t decimation_factor; constexpr BasebandConfiguration( - int32_t mode = -1, - uint32_t sampling_rate = 0, + int32_t mode, + uint32_t sampling_rate, size_t decimation_factor = 1 ) : mode { mode }, sampling_rate { sampling_rate }, decimation_factor { decimation_factor } { } + + constexpr BasebandConfiguration( + ) : BasebandConfiguration { -1, 0, 1 } + { + } }; class BasebandConfigurationMessage : public Message { From 82f367dfeaa5eb6c46210458957d0b029399301f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 14:41:07 -0800 Subject: [PATCH 101/452] Move code into BasebandThread. --- firmware/baseband/main.cpp | 89 +++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index bd2c458ab..66ce0320b 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -102,6 +102,8 @@ private: const char* const name; }; +static constexpr auto direction = baseband::Direction::Receive; + class BasebandThread : public ThreadBase { public: BasebandThread( @@ -116,6 +118,23 @@ public: ); } + void set_configuration(const BasebandConfiguration& new_configuration) { + if( new_configuration.mode != baseband_configuration.mode ) { + disable(); + + // TODO: Timing problem around disabling DMA and nulling and deleting old processor + auto old_p = baseband_processor; + baseband_processor = nullptr; + delete old_p; + + baseband_processor = create_processor(new_configuration.mode); + + enable(); + } + + baseband_configuration = new_configuration; + } + Thread* thread_main { nullptr }; Thread* thread_rssi { nullptr }; BasebandProcessor* baseband_processor { nullptr }; @@ -151,6 +170,36 @@ private: ); } } + + BasebandProcessor* create_processor(const int32_t mode) { + switch(mode) { + case 0: return new NarrowbandAMAudio(); + case 1: return new NarrowbandFMAudio(); + case 2: return new WidebandFMAudio(); + case 3: return new AISProcessor(); + case 4: return new WidebandSpectrum(); + case 5: return new TPMSProcessor(); + case 6: return new ERTProcessor(); + default: return nullptr; + } + } + + void disable() { + if( baseband_processor ) { + i2s::i2s0::tx_mute(); + baseband::dma::disable(); + rf::rssi::stop(); + } + } + + void enable() { + if( baseband_processor ) { + if( direction == baseband::Direction::Receive ) { + rf::rssi::start(); + } + baseband::dma::enable(direction); + } + } }; class RSSIThread : public ThreadBase { @@ -319,21 +368,6 @@ private: } }; -static constexpr auto direction = baseband::Direction::Receive; - -static BasebandProcessor* create_processor(const int32_t mode) { - switch(mode) { - case 0: return new NarrowbandAMAudio(); - case 1: return new NarrowbandFMAudio(); - case 2: return new WidebandFMAudio(); - case 3: return new AISProcessor(); - case 4: return new WidebandSpectrum(); - case 5: return new TPMSProcessor(); - case 6: return new ERTProcessor(); - default: return nullptr; - } -} - int main(void) { init(); @@ -346,30 +380,7 @@ int main(void) { message_handlers.register_handler(Message::ID::BasebandConfiguration, [&message_handlers](const Message* const p) { auto message = reinterpret_cast(p); - if( message->configuration.mode != baseband_thread.baseband_configuration.mode ) { - - if( baseband_thread.baseband_processor ) { - i2s::i2s0::tx_mute(); - baseband::dma::disable(); - rf::rssi::stop(); - } - - // TODO: Timing problem around disabling DMA and nulling and deleting old processor - auto old_p = baseband_thread.baseband_processor; - baseband_thread.baseband_processor = nullptr; - delete old_p; - - baseband_thread.baseband_processor = create_processor(message->configuration.mode); - - if( baseband_thread.baseband_processor ) { - if( direction == baseband::Direction::Receive ) { - rf::rssi::start(); - } - baseband::dma::enable(direction); - } - } - - baseband_thread.baseband_configuration = message->configuration; + baseband_thread.set_configuration(message->configuration); } ); From a7afc58cf83ea0dbb29dea07d4434d5d5844ddbf Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 15:13:07 -0800 Subject: [PATCH 102/452] More consistent use of pass-by-ref, const in baseband code. --- firmware/baseband/baseband_processor.cpp | 4 ++-- firmware/baseband/main.cpp | 4 ++-- firmware/baseband/proc_ais.cpp | 3 +-- firmware/baseband/proc_ert.cpp | 8 ++------ firmware/baseband/proc_tpms.cpp | 3 +-- firmware/common/message.hpp | 20 ++++++++++++++------ 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index b6b10d07e..0f6a8fc03 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -63,7 +63,7 @@ void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { channel_stats.feed( channel, [](const ChannelStatistics& statistics) { - ChannelStatisticsMessage channel_stats_message { statistics }; + const ChannelStatisticsMessage channel_stats_message { statistics }; shared_memory.application_queue.push(channel_stats_message); } ); @@ -107,7 +107,7 @@ void BasebandProcessor::feed_audio_stats(const buffer_s16_t& audio) { audio_stats.feed( audio, [this](const AudioStatistics& statistics) { - AudioStatisticsMessage audio_stats_message { statistics }; + const AudioStatisticsMessage audio_stats_message { statistics }; shared_memory.application_queue.push(audio_stats_message); } ); diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 66ce0320b..fb3d2c39a 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -163,7 +163,7 @@ private: } stats.process(buffer, - [](const BasebandStatistics statistics) { + [](const BasebandStatistics& statistics) { const BasebandStatisticsMessage message { statistics }; shared_memory.application_queue.push(message); } @@ -233,7 +233,7 @@ private: stats.process( buffer, - [](const RSSIStatistics statistics) { + [](const RSSIStatistics& statistics) { const RSSIStatisticsMessage message { statistics }; shared_memory.application_queue.push(message); } diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index 903a7e2f8..7cb0f3cb0 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -62,7 +62,6 @@ void AISProcessor::consume_symbol( void AISProcessor::payload_handler( const baseband::Packet& packet ) { - AISPacketMessage message; - message.packet = packet; + const AISPacketMessage message { packet }; shared_memory.application_queue.push(message); } diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index 5ef5d4967..c2b08f476 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -97,17 +97,13 @@ void ERTProcessor::consume_symbol( void ERTProcessor::scm_handler( const baseband::Packet& packet ) { - ERTPacketMessage message; - message.type = ert::Packet::Type::SCM; - message.packet = packet; + const ERTPacketMessage message { ert::Packet::Type::SCM, packet }; shared_memory.application_queue.push(message); } void ERTProcessor::idm_handler( const baseband::Packet& packet ) { - ERTPacketMessage message; - message.type = ert::Packet::Type::IDM; - message.packet = packet; + const ERTPacketMessage message { ert::Packet::Type::IDM, packet }; shared_memory.application_queue.push(message); } diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index 314a05e7b..b9e111222 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -60,7 +60,6 @@ void TPMSProcessor::consume_symbol( void TPMSProcessor::payload_handler( const baseband::Packet& packet ) { - TPMSPacketMessage message; - message.packet = packet; + const TPMSPacketMessage message { packet }; shared_memory.application_queue.push(message); } diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index a1c2e78ca..cbd05969d 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -185,9 +185,9 @@ struct BasebandConfiguration { class BasebandConfigurationMessage : public Message { public: constexpr BasebandConfigurationMessage( - BasebandConfiguration configuration + const BasebandConfiguration& configuration ) : Message { ID::BasebandConfiguration }, - configuration(configuration) + configuration { configuration } { } @@ -215,7 +215,9 @@ public: class AISPacketMessage : public Message { public: constexpr AISPacketMessage( - ) : Message { ID::AISPacket } + const baseband::Packet& packet + ) : Message { ID::AISPacket }, + packet { packet } { } @@ -225,7 +227,9 @@ public: class TPMSPacketMessage : public Message { public: constexpr TPMSPacketMessage( - ) : Message { ID::TPMSPacket } + const baseband::Packet& packet + ) : Message { ID::TPMSPacket }, + packet { packet } { } @@ -243,11 +247,15 @@ public: class ERTPacketMessage : public Message { public: constexpr ERTPacketMessage( - ) : Message { ID::ERTPacket } + const ert::Packet::Type type, + const baseband::Packet& packet + ) : Message { ID::ERTPacket }, + type { type }, + packet { packet } { } - ert::Packet::Type type { ert::Packet::Type::Unknown }; + ert::Packet::Type type; baseband::Packet packet; }; From e8cf0b8de7021d59d7a884890ddd95e24099a16a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 15:22:20 -0800 Subject: [PATCH 103/452] Clean up baseband/main.cpp #includes. --- firmware/baseband/main.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index fb3d2c39a..f5b0e1eb2 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -40,17 +40,9 @@ #include "touch_dma.hpp" -#include "dsp_decimate.hpp" -#include "dsp_demodulate.hpp" -#include "dsp_fir_taps.hpp" -#include "dsp_iir.hpp" -#include "dsp_iir_config.hpp" -#include "dsp_squelch.hpp" - #include "baseband_stats_collector.hpp" #include "rssi_stats_collector.hpp" -#include "channel_decimator.hpp" #include "baseband_processor.hpp" #include "proc_am_audio.hpp" #include "proc_nfm_audio.hpp" @@ -60,9 +52,6 @@ #include "proc_tpms.hpp" #include "proc_ert.hpp" -#include "clock_recovery.hpp" -#include "packet_builder.hpp" - #include "message_queue.hpp" #include "utility.hpp" @@ -77,8 +66,6 @@ #include #include #include -#include -#include class ThreadBase { public: From 2808efac4c1b6fea40fe4fe9b65f16283e2e5294 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 15:27:33 -0800 Subject: [PATCH 104/452] Remove unused lambda captures. --- firmware/baseband/baseband_processor.cpp | 2 +- firmware/baseband/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index 0f6a8fc03..620e965ed 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -106,7 +106,7 @@ void BasebandProcessor::post_channel_spectrum_message(const buffer_c16_t& data) void BasebandProcessor::feed_audio_stats(const buffer_s16_t& audio) { audio_stats.feed( audio, - [this](const AudioStatistics& statistics) { + [](const AudioStatistics& statistics) { const AudioStatisticsMessage audio_stats_message { statistics }; shared_memory.application_queue.push(audio_stats_message); } diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index f5b0e1eb2..d6995dbaa 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -365,7 +365,7 @@ int main(void) { auto& message_handlers = event_dispatcher.message_handlers(); message_handlers.register_handler(Message::ID::BasebandConfiguration, - [&message_handlers](const Message* const p) { + [](const Message* const p) { auto message = reinterpret_cast(p); baseband_thread.set_configuration(message->configuration); } From e998014e575f29c12590117a0477cd4c7a8e74ba Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 15:53:54 -0800 Subject: [PATCH 105/452] Extract BasebandThread, ThreadBase to separate files. --- firmware/baseband/Makefile | 1 + firmware/baseband/baseband_thread.cpp | 122 +++++++++++++++++++++++ firmware/baseband/baseband_thread.hpp | 64 ++++++++++++ firmware/baseband/main.cpp | 135 +------------------------- firmware/baseband/thread_base.hpp | 49 ++++++++++ 5 files changed, 239 insertions(+), 132 deletions(-) create mode 100644 firmware/baseband/baseband_thread.cpp create mode 100644 firmware/baseband/baseband_thread.hpp create mode 100644 firmware/baseband/thread_base.hpp diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 8e930720b..182c19b3b 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -129,6 +129,7 @@ CPPSRC = main.cpp \ gpdma.cpp \ baseband_dma.cpp \ portapack_shared_memory.cpp \ + baseband_thread.cpp \ baseband_processor.cpp \ channel_decimator.cpp \ dsp_decimate.cpp \ diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp new file mode 100644 index 000000000..0ca0fed48 --- /dev/null +++ b/firmware/baseband/baseband_thread.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "baseband_thread.hpp" + +#include "dsp_types.hpp" + +#include "baseband_stats_collector.hpp" +#include "baseband_dma.hpp" + +#include "rssi.hpp" +#include "i2s.hpp" + +#include "proc_am_audio.hpp" +#include "proc_nfm_audio.hpp" +#include "proc_wfm_audio.hpp" +#include "proc_ais.hpp" +#include "proc_wideband_spectrum.hpp" +#include "proc_tpms.hpp" +#include "proc_ert.hpp" + +#include "portapack_shared_memory.hpp" + +Thread* BasebandThread::start(const tprio_t priority) { + return chThdCreateStatic(wa, sizeof(wa), + priority, ThreadBase::fn, + this + ); +} + +void BasebandThread::set_configuration(const BasebandConfiguration& new_configuration) { + if( new_configuration.mode != baseband_configuration.mode ) { + disable(); + + // TODO: Timing problem around disabling DMA and nulling and deleting old processor + auto old_p = baseband_processor; + baseband_processor = nullptr; + delete old_p; + + baseband_processor = create_processor(new_configuration.mode); + + enable(); + } + + baseband_configuration = new_configuration; +} + +void BasebandThread::run() { + BasebandStatsCollector stats { + chSysGetIdleThread(), + thread_main, + thread_rssi, + chThdSelf() + }; + + while(true) { + // TODO: Place correct sampling rate into buffer returned here: + const auto buffer_tmp = baseband::dma::wait_for_rx_buffer(); + buffer_c8_t buffer { + buffer_tmp.p, buffer_tmp.count, baseband_configuration.sampling_rate + }; + + if( baseband_processor ) { + baseband_processor->execute(buffer); + } + + stats.process(buffer, + [](const BasebandStatistics& statistics) { + const BasebandStatisticsMessage message { statistics }; + shared_memory.application_queue.push(message); + } + ); + } +} + +BasebandProcessor* BasebandThread::create_processor(const int32_t mode) { + switch(mode) { + case 0: return new NarrowbandAMAudio(); + case 1: return new NarrowbandFMAudio(); + case 2: return new WidebandFMAudio(); + case 3: return new AISProcessor(); + case 4: return new WidebandSpectrum(); + case 5: return new TPMSProcessor(); + case 6: return new ERTProcessor(); + default: return nullptr; + } +} + +void BasebandThread::disable() { + if( baseband_processor ) { + i2s::i2s0::tx_mute(); + baseband::dma::disable(); + rf::rssi::stop(); + } +} + +void BasebandThread::enable() { + if( baseband_processor ) { + if( direction() == baseband::Direction::Receive ) { + rf::rssi::start(); + } + baseband::dma::enable(direction()); + } +} diff --git a/firmware/baseband/baseband_thread.hpp b/firmware/baseband/baseband_thread.hpp new file mode 100644 index 000000000..8bb4894ab --- /dev/null +++ b/firmware/baseband/baseband_thread.hpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __BASEBAND_THREAD_H__ +#define __BASEBAND_THREAD_H__ + +#include "thread_base.hpp" +#include "message.hpp" +#include "baseband_processor.hpp" + +#include + +class BasebandThread : public ThreadBase { +public: + BasebandThread( + ) : ThreadBase { "baseband" } + { + } + + Thread* start(const tprio_t priority); + + void set_configuration(const BasebandConfiguration& new_configuration); + + // This getter should die, it's just here to leak information to code that + // isn't in the right place to begin with. + baseband::Direction direction() const { + return baseband::Direction::Receive; + } + + Thread* thread_main { nullptr }; + Thread* thread_rssi { nullptr }; + BasebandProcessor* baseband_processor { nullptr }; + BasebandConfiguration baseband_configuration; + +private: + WORKING_AREA(wa, 2048); + + void run() override; + + BasebandProcessor* create_processor(const int32_t mode); + + void disable(); + void enable(); +}; + +#endif/*__BASEBAND_THREAD_H__*/ diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index d6995dbaa..6e7516546 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -40,17 +40,10 @@ #include "touch_dma.hpp" -#include "baseband_stats_collector.hpp" #include "rssi_stats_collector.hpp" +#include "baseband_thread.hpp" #include "baseband_processor.hpp" -#include "proc_am_audio.hpp" -#include "proc_nfm_audio.hpp" -#include "proc_wfm_audio.hpp" -#include "proc_ais.hpp" -#include "proc_wideband_spectrum.hpp" -#include "proc_tpms.hpp" -#include "proc_ert.hpp" #include "message_queue.hpp" @@ -67,128 +60,6 @@ #include #include -class ThreadBase { -public: - constexpr ThreadBase( - const char* const name - ) : name { name } - { - } - - static msg_t fn(void* arg) { - auto obj = static_cast(arg); - chRegSetThreadName(obj->name); - obj->run(); - - return 0; - } - - virtual void run() = 0; - -private: - const char* const name; -}; - -static constexpr auto direction = baseband::Direction::Receive; - -class BasebandThread : public ThreadBase { -public: - BasebandThread( - ) : ThreadBase { "baseband" } - { - } - - Thread* start(const tprio_t priority) { - return chThdCreateStatic(wa, sizeof(wa), - priority, ThreadBase::fn, - this - ); - } - - void set_configuration(const BasebandConfiguration& new_configuration) { - if( new_configuration.mode != baseband_configuration.mode ) { - disable(); - - // TODO: Timing problem around disabling DMA and nulling and deleting old processor - auto old_p = baseband_processor; - baseband_processor = nullptr; - delete old_p; - - baseband_processor = create_processor(new_configuration.mode); - - enable(); - } - - baseband_configuration = new_configuration; - } - - Thread* thread_main { nullptr }; - Thread* thread_rssi { nullptr }; - BasebandProcessor* baseband_processor { nullptr }; - BasebandConfiguration baseband_configuration; - -private: - WORKING_AREA(wa, 2048); - - void run() override { - BasebandStatsCollector stats { - chSysGetIdleThread(), - thread_main, - thread_rssi, - chThdSelf() - }; - - while(true) { - // TODO: Place correct sampling rate into buffer returned here: - const auto buffer_tmp = baseband::dma::wait_for_rx_buffer(); - buffer_c8_t buffer { - buffer_tmp.p, buffer_tmp.count, baseband_configuration.sampling_rate - }; - - if( baseband_processor ) { - baseband_processor->execute(buffer); - } - - stats.process(buffer, - [](const BasebandStatistics& statistics) { - const BasebandStatisticsMessage message { statistics }; - shared_memory.application_queue.push(message); - } - ); - } - } - - BasebandProcessor* create_processor(const int32_t mode) { - switch(mode) { - case 0: return new NarrowbandAMAudio(); - case 1: return new NarrowbandFMAudio(); - case 2: return new WidebandFMAudio(); - case 3: return new AISProcessor(); - case 4: return new WidebandSpectrum(); - case 5: return new TPMSProcessor(); - case 6: return new ERTProcessor(); - default: return nullptr; - } - } - - void disable() { - if( baseband_processor ) { - i2s::i2s0::tx_mute(); - baseband::dma::disable(); - rf::rssi::stop(); - } - } - - void enable() { - if( baseband_processor ) { - if( direction == baseband::Direction::Receive ) { - rf::rssi::start(); - } - baseband::dma::enable(direction); - } - } -}; - class RSSIThread : public ThreadBase { public: RSSIThread( @@ -379,7 +250,7 @@ int main(void) { /* TODO: Ensure DMAs are configured to point at first LLI in chain. */ - if( direction == baseband::Direction::Receive ) { + if( baseband_thread.direction() == baseband::Direction::Receive ) { rf::rssi::dma::allocate(4, 400); } @@ -390,7 +261,7 @@ int main(void) { new std::array(); baseband::dma::configure( baseband_buffer->data(), - direction + baseband_thread.direction() ); //baseband::dma::allocate(4, 2048); diff --git a/firmware/baseband/thread_base.hpp b/firmware/baseband/thread_base.hpp new file mode 100644 index 000000000..3db73d146 --- /dev/null +++ b/firmware/baseband/thread_base.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __THREAD_BASE_H__ +#define __THREAD_BASE_H__ + +#include + +class ThreadBase { +public: + constexpr ThreadBase( + const char* const name + ) : name { name } + { + } + + static msg_t fn(void* arg) { + auto obj = static_cast(arg); + chRegSetThreadName(obj->name); + obj->run(); + + return 0; + } + + virtual void run() = 0; + +private: + const char* const name; +}; + +#endif/*__THREAD_BASE_H__*/ From ded33ebabdcfb447b996982bcf733043117c6562 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 16:03:22 -0800 Subject: [PATCH 106/452] Extract RSSIThread to separate files. --- firmware/baseband/Makefile | 1 + firmware/baseband/main.cpp | 43 +----------------------- firmware/baseband/rssi_thread.cpp | 56 +++++++++++++++++++++++++++++++ firmware/baseband/rssi_thread.hpp | 48 ++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 firmware/baseband/rssi_thread.cpp create mode 100644 firmware/baseband/rssi_thread.hpp diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 182c19b3b..caf93066b 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -150,6 +150,7 @@ CPPSRC = main.cpp \ fxpt_atan2.cpp \ rssi.cpp \ rssi_dma.cpp \ + rssi_thread.cpp \ audio.cpp \ audio_dma.cpp \ touch_dma.cpp \ diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 6e7516546..97895fcfe 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -40,9 +40,8 @@ #include "touch_dma.hpp" -#include "rssi_stats_collector.hpp" - #include "baseband_thread.hpp" +#include "rssi_thread.hpp" #include "baseband_processor.hpp" #include "message_queue.hpp" @@ -60,46 +59,6 @@ #include #include -class RSSIThread : public ThreadBase { -public: - RSSIThread( - ) : ThreadBase { "rssi" } - { - } - - Thread* start(const tprio_t priority) { - return chThdCreateStatic(wa, sizeof(wa), - priority, ThreadBase::fn, - this - ); - } - - uint32_t sampling_rate { 400000 }; - -private: - WORKING_AREA(wa, 128); - - void run() override { - RSSIStatisticsCollector stats; - - while(true) { - // TODO: Place correct sampling rate into buffer returned here: - const auto buffer_tmp = rf::rssi::dma::wait_for_buffer(); - const rf::rssi::buffer_t buffer { - buffer_tmp.p, buffer_tmp.count, sampling_rate - }; - - stats.process( - buffer, - [](const RSSIStatistics& statistics) { - const RSSIStatisticsMessage message { statistics }; - shared_memory.application_queue.push(message); - } - ); - } - } -}; - extern "C" { void __late_init(void) { diff --git a/firmware/baseband/rssi_thread.cpp b/firmware/baseband/rssi_thread.cpp new file mode 100644 index 000000000..b084c4948 --- /dev/null +++ b/firmware/baseband/rssi_thread.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "rssi_thread.hpp" + +#include "rssi.hpp" +#include "rssi_dma.hpp" +#include "rssi_stats_collector.hpp" + +#include "message.hpp" +#include "portapack_shared_memory.hpp" + +Thread* RSSIThread::start(const tprio_t priority) { + return chThdCreateStatic(wa, sizeof(wa), + priority, ThreadBase::fn, + this + ); +} + +void RSSIThread::run() { + RSSIStatisticsCollector stats; + + while(true) { + // TODO: Place correct sampling rate into buffer returned here: + const auto buffer_tmp = rf::rssi::dma::wait_for_buffer(); + const rf::rssi::buffer_t buffer { + buffer_tmp.p, buffer_tmp.count, sampling_rate + }; + + stats.process( + buffer, + [](const RSSIStatistics& statistics) { + const RSSIStatisticsMessage message { statistics }; + shared_memory.application_queue.push(message); + } + ); + } +} diff --git a/firmware/baseband/rssi_thread.hpp b/firmware/baseband/rssi_thread.hpp new file mode 100644 index 000000000..d7224ddb4 --- /dev/null +++ b/firmware/baseband/rssi_thread.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __RSSI_THREAD_H__ +#define __RSSI_THREAD_H__ + +#include "thread_base.hpp" + +#include + +#include + +class RSSIThread : public ThreadBase { +public: + RSSIThread( + ) : ThreadBase { "rssi" } + { + } + + Thread* start(const tprio_t priority); + + uint32_t sampling_rate { 400000 }; + +private: + WORKING_AREA(wa, 128); + + void run() override; +}; + +#endif/*__RSSI_THREAD_H__*/ From 255c568f9e6ed38044a455929b071b02cf00c652 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 16:13:52 -0800 Subject: [PATCH 107/452] Make some Baseband/RSSIThread members private/const. --- firmware/baseband/baseband_thread.hpp | 3 ++- firmware/baseband/rssi_thread.hpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/baseband_thread.hpp b/firmware/baseband/baseband_thread.hpp index 8bb4894ab..f21d53ee9 100644 --- a/firmware/baseband/baseband_thread.hpp +++ b/firmware/baseband/baseband_thread.hpp @@ -48,11 +48,12 @@ public: Thread* thread_main { nullptr }; Thread* thread_rssi { nullptr }; BasebandProcessor* baseband_processor { nullptr }; - BasebandConfiguration baseband_configuration; private: WORKING_AREA(wa, 2048); + BasebandConfiguration baseband_configuration; + void run() override; BasebandProcessor* create_processor(const int32_t mode); diff --git a/firmware/baseband/rssi_thread.hpp b/firmware/baseband/rssi_thread.hpp index d7224ddb4..f3fde10ae 100644 --- a/firmware/baseband/rssi_thread.hpp +++ b/firmware/baseband/rssi_thread.hpp @@ -37,12 +37,12 @@ public: Thread* start(const tprio_t priority); - uint32_t sampling_rate { 400000 }; - private: WORKING_AREA(wa, 128); void run() override; + + const uint32_t sampling_rate { 400000 }; }; #endif/*__RSSI_THREAD_H__*/ From 13e4b41c1e72b3aa0a5d99f60e7c50f9e130f84f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 16:15:18 -0800 Subject: [PATCH 108/452] Trivial clean-up. --- firmware/baseband/main.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 97895fcfe..c003b648c 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -106,13 +106,8 @@ static void init() { rf::rssi::init(); touch::dma::init(); - const auto thread_main = chThdSelf(); - - const auto thread_rssi = rssi_thread.start(NORMALPRIO + 10); - - baseband_thread.thread_main = thread_main; - baseband_thread.thread_rssi = thread_rssi; - + baseband_thread.thread_main = chThdSelf(); + baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); baseband_thread.start(NORMALPRIO + 20); } From ed25f65e8b6fbcaba627f1dbd3bb16d79f01ddb2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 16:29:50 -0800 Subject: [PATCH 109/452] Move BasebandThread init into main(). --- firmware/baseband/main.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index c003b648c..d5e6fb876 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -105,10 +105,6 @@ static void init() { rf::rssi::init(); touch::dma::init(); - - baseband_thread.thread_main = chThdSelf(); - baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); - baseband_thread.start(NORMALPRIO + 20); } static void shutdown() { @@ -203,6 +199,9 @@ int main(void) { ); /* TODO: Ensure DMAs are configured to point at first LLI in chain. */ + baseband_thread.thread_main = chThdSelf(); + baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); + baseband_thread.start(NORMALPRIO + 20); if( baseband_thread.direction() == baseband::Direction::Receive ) { rf::rssi::dma::allocate(4, 400); From 818790e734a483647dcea0019e61e5c9182eb80c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 16:32:00 -0800 Subject: [PATCH 110/452] Move init/configure details into RSSI/BasebandThread classes. --- firmware/baseband/baseband_thread.cpp | 14 ++++++++++++++ firmware/baseband/main.cpp | 21 +-------------------- firmware/baseband/rssi_thread.cpp | 5 +++++ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp index 0ca0fed48..f654bda73 100644 --- a/firmware/baseband/baseband_thread.cpp +++ b/firmware/baseband/baseband_thread.cpp @@ -23,6 +23,7 @@ #include "dsp_types.hpp" +#include "baseband.hpp" #include "baseband_stats_collector.hpp" #include "baseband_dma.hpp" @@ -39,6 +40,8 @@ #include "portapack_shared_memory.hpp" +#include + Thread* BasebandThread::start(const tprio_t priority) { return chThdCreateStatic(wa, sizeof(wa), priority, ThreadBase::fn, @@ -64,6 +67,15 @@ void BasebandThread::set_configuration(const BasebandConfiguration& new_configur } void BasebandThread::run() { + baseband::dma::init(); + + const auto baseband_buffer = new std::array(); + baseband::dma::configure( + baseband_buffer->data(), + direction() + ); + //baseband::dma::allocate(4, 2048); + BasebandStatsCollector stats { chSysGetIdleThread(), thread_main, @@ -89,6 +101,8 @@ void BasebandThread::run() { } ); } + + delete baseband_buffer; } BasebandProcessor* BasebandThread::create_processor(const int32_t mode) { diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index d5e6fb876..44275bd18 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -29,15 +29,10 @@ #include "gpdma.hpp" -#include "baseband_dma.hpp" - #include "event_m4.hpp" #include "irq_ipc_m4.hpp" -#include "rssi.hpp" -#include "rssi_dma.hpp" - #include "touch_dma.hpp" #include "baseband_thread.hpp" @@ -101,9 +96,6 @@ static void init() { gpdma::controller.enable(); nvicEnableVector(DMA_IRQn, CORTEX_PRIORITY_MASK(LPC_DMA_IRQ_PRIORITY)); - baseband::dma::init(); - - rf::rssi::init(); touch::dma::init(); } @@ -199,25 +191,14 @@ int main(void) { ); /* TODO: Ensure DMAs are configured to point at first LLI in chain. */ + baseband_thread.thread_main = chThdSelf(); baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); baseband_thread.start(NORMALPRIO + 20); - if( baseband_thread.direction() == baseband::Direction::Receive ) { - rf::rssi::dma::allocate(4, 400); - } - touch::dma::allocate(); touch::dma::enable(); - const auto baseband_buffer = - new std::array(); - baseband::dma::configure( - baseband_buffer->data(), - baseband_thread.direction() - ); - //baseband::dma::allocate(4, 2048); - event_dispatcher.run(); shutdown(); diff --git a/firmware/baseband/rssi_thread.cpp b/firmware/baseband/rssi_thread.cpp index b084c4948..d7b5f99ca 100644 --- a/firmware/baseband/rssi_thread.cpp +++ b/firmware/baseband/rssi_thread.cpp @@ -36,6 +36,9 @@ Thread* RSSIThread::start(const tprio_t priority) { } void RSSIThread::run() { + rf::rssi::init(); + rf::rssi::dma::allocate(4, 400); + RSSIStatisticsCollector stats; while(true) { @@ -53,4 +56,6 @@ void RSSIThread::run() { } ); } + + rf::rssi::dma::free(); } From 6328efb70b075fec76b46a0268388d83e80483b7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 17:10:28 -0800 Subject: [PATCH 111/452] Move more baseband main() code into EventDispatcher. EventDispatcher might be ripe for a refactor or rename. --- firmware/baseband/main.cpp | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 44275bd18..1edf47137 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -125,6 +125,23 @@ public: } void run() { + message_map.register_handler(Message::ID::BasebandConfiguration, + [](const Message* const p) { + auto message = reinterpret_cast(p); + baseband_thread.set_configuration(message->configuration); + } + ); + + message_map.register_handler(Message::ID::Shutdown, + [this](const Message* const) { + this->request_stop(); + } + ); + + baseband_thread.thread_main = chThdSelf(); + baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); + baseband_thread.start(NORMALPRIO + 20); + while(is_running) { const auto events = wait(); dispatch(events); @@ -175,26 +192,8 @@ int main(void) { m0apptxevent_interrupt_enable(); EventDispatcher event_dispatcher; - auto& message_handlers = event_dispatcher.message_handlers(); - - message_handlers.register_handler(Message::ID::BasebandConfiguration, - [](const Message* const p) { - auto message = reinterpret_cast(p); - baseband_thread.set_configuration(message->configuration); - } - ); - - message_handlers.register_handler(Message::ID::Shutdown, - [&event_dispatcher](const Message* const) { - event_dispatcher.request_stop(); - } - ); /* TODO: Ensure DMAs are configured to point at first LLI in chain. */ - - baseband_thread.thread_main = chThdSelf(); - baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); - baseband_thread.start(NORMALPRIO + 20); touch::dma::allocate(); touch::dma::enable(); From 4b3fa25cef7301d3e3d28793237dfc7cbc5cece5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 17:19:18 -0800 Subject: [PATCH 112/452] Move sending of ShutdownMessage into shutdown(). Crazy, I know. --- firmware/baseband/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 1edf47137..2a8e567cb 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -109,6 +109,9 @@ static void shutdown() { chSysDisable(); systick_stop(); + + ShutdownMessage shutdown_message; + shared_memory.application_queue.push(shutdown_message); } static void halt() { @@ -202,9 +205,6 @@ int main(void) { shutdown(); - ShutdownMessage shutdown_message; - shared_memory.application_queue.push(shutdown_message); - halt(); return 0; From 95fe57c9aafd7d3463076f2fe1beb0ecb84068af Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 17:20:10 -0800 Subject: [PATCH 113/452] Consolidate EventDispatcher client code. --- firmware/baseband/main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 2a8e567cb..e601d2dfc 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -194,13 +194,12 @@ int main(void) { events_initialize(chThdSelf()); m0apptxevent_interrupt_enable(); - EventDispatcher event_dispatcher; - /* TODO: Ensure DMAs are configured to point at first LLI in chain. */ touch::dma::allocate(); touch::dma::enable(); + EventDispatcher event_dispatcher; event_dispatcher.run(); shutdown(); From f3979a1d65adde11edd0da844155344b3929fef4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 17:25:55 -0800 Subject: [PATCH 114/452] Move event initialization code into EventDispatcher. --- firmware/baseband/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index e601d2dfc..95536bbeb 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -141,6 +141,9 @@ public: } ); + events_initialize(chThdSelf()); + m0apptxevent_interrupt_enable(); + baseband_thread.thread_main = chThdSelf(); baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); baseband_thread.start(NORMALPRIO + 20); @@ -191,9 +194,6 @@ private: int main(void) { init(); - events_initialize(chThdSelf()); - m0apptxevent_interrupt_enable(); - /* TODO: Ensure DMAs are configured to point at first LLI in chain. */ touch::dma::allocate(); From f90e5bab6be340540d970f4cd429e64eec89e703 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 17:29:16 -0800 Subject: [PATCH 115/452] Push more init/shutdown code out of main(). --- firmware/baseband/main.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 95536bbeb..036e0cd8a 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -97,6 +97,15 @@ static void init() { nvicEnableVector(DMA_IRQn, CORTEX_PRIORITY_MASK(LPC_DMA_IRQ_PRIORITY)); touch::dma::init(); + touch::dma::allocate(); + touch::dma::enable(); +} + +static void halt() { + port_disable(); + while(true) { + port_wait_for_interrupt(); + } } static void shutdown() { @@ -112,13 +121,8 @@ static void shutdown() { ShutdownMessage shutdown_message; shared_memory.application_queue.push(shutdown_message); -} -static void halt() { - port_disable(); - while(true) { - port_wait_for_interrupt(); - } + halt(); } class EventDispatcher { @@ -152,6 +156,8 @@ public: const auto events = wait(); dispatch(events); } + + shutdown(); } void request_stop() { @@ -196,15 +202,8 @@ int main(void) { /* TODO: Ensure DMAs are configured to point at first LLI in chain. */ - touch::dma::allocate(); - touch::dma::enable(); - EventDispatcher event_dispatcher; event_dispatcher.run(); - shutdown(); - - halt(); - return 0; } From d895a54078c1f9e6276a1dbd8a3750b7798d8fb9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 17:33:44 -0800 Subject: [PATCH 116/452] Almost finished moving around baseband init/shutdown code. --- firmware/baseband/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 036e0cd8a..4055b281a 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -112,8 +112,6 @@ static void shutdown() { // TODO: Is this complete? nvicDisableVector(DMA_IRQn); - - m0apptxevent_interrupt_disable(); chSysDisable(); @@ -157,7 +155,7 @@ public: dispatch(events); } - shutdown(); + m0apptxevent_interrupt_disable(); } void request_stop() { @@ -205,5 +203,7 @@ int main(void) { EventDispatcher event_dispatcher; event_dispatcher.run(); + shutdown(); + return 0; } From ca7e0f1e200a4d08e1ee627e4406fca7043519c7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 18:28:19 -0800 Subject: [PATCH 117/452] Remove #include of ChibiOS test.h. Would be appropriate if writing a test case project. Someday... --- firmware/application/main.cpp | 1 - firmware/baseband/main.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 25102c4dc..a30bba256 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -20,7 +20,6 @@ */ #include "ch.h" -#include "test.h" #include "portapack.hpp" #include "portapack_shared_memory.hpp" diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 4055b281a..cb0cb3656 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -20,7 +20,6 @@ */ #include "ch.h" -#include "test.h" #include "lpc43xx_cpp.hpp" From a3bab9126da162f9ebfd93be57e415cee512861c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 20:13:27 -0800 Subject: [PATCH 118/452] Remove commented, dead code. --- firmware/baseband/baseband_dma.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/firmware/baseband/baseband_dma.cpp b/firmware/baseband/baseband_dma.cpp index 520365d12..f3002b282 100644 --- a/firmware/baseband/baseband_dma.cpp +++ b/firmware/baseband/baseband_dma.cpp @@ -99,16 +99,12 @@ constexpr size_t msg_count = transfers_per_buffer - 1; static std::array lli_loop; static constexpr auto& gpdma_channel_sgpio = gpdma::channels[portapack::sgpio_gpdma_channel_number]; -//static Mailbox mailbox; -//static std::array messages; static Semaphore semaphore; static volatile const gpdma::channel::LLI* next_lli = nullptr; static void transfer_complete() { next_lli = gpdma_channel_sgpio.next_lli(); - /* TODO: Is Mailbox the proper synchronization mechanism for this? */ - //chMBPostI(&mailbox, 0); chSemSignalI(&semaphore); } @@ -117,7 +113,6 @@ static void dma_error() { } void init() { - //chMBInit(&mailbox, messages.data(), messages.size()); chSemInit(&semaphore, 0); gpdma_channel_sgpio.set_handlers(transfer_complete, dma_error); @@ -144,7 +139,6 @@ void enable(const baseband::Direction direction) { const auto gpdma_config = config(direction); gpdma_channel_sgpio.configure(lli_loop[0], gpdma_config); - //chMBReset(&mailbox); chSemReset(&semaphore, 0); gpdma_channel_sgpio.enable(); @@ -159,8 +153,6 @@ void disable() { } baseband::buffer_t wait_for_rx_buffer() { - //msg_t msg; - //const auto status = chMBFetch(&mailbox, &msg, TIME_INFINITE); const auto status = chSemWait(&semaphore); if( status == RDY_OK ) { const auto next = next_lli; From 211d1d19ea7ea83ddf1b1792472bdc83c8bc0ef5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 21:01:44 -0800 Subject: [PATCH 119/452] Move Thread WORKING_AREAs out of classes. Limited where and how you could instantiate the classes. --- firmware/baseband/baseband_thread.cpp | 4 +++- firmware/baseband/baseband_thread.hpp | 2 -- firmware/baseband/main.cpp | 5 ++--- firmware/baseband/rssi_thread.cpp | 4 +++- firmware/baseband/rssi_thread.hpp | 2 -- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp index f654bda73..606d09254 100644 --- a/firmware/baseband/baseband_thread.cpp +++ b/firmware/baseband/baseband_thread.cpp @@ -42,8 +42,10 @@ #include +WORKING_AREA(baseband_thread_wa, 2048); + Thread* BasebandThread::start(const tprio_t priority) { - return chThdCreateStatic(wa, sizeof(wa), + return chThdCreateStatic(baseband_thread_wa, sizeof(baseband_thread_wa), priority, ThreadBase::fn, this ); diff --git a/firmware/baseband/baseband_thread.hpp b/firmware/baseband/baseband_thread.hpp index f21d53ee9..e19882346 100644 --- a/firmware/baseband/baseband_thread.hpp +++ b/firmware/baseband/baseband_thread.hpp @@ -50,8 +50,6 @@ public: BasebandProcessor* baseband_processor { nullptr }; private: - WORKING_AREA(wa, 2048); - BasebandConfiguration baseband_configuration; void run() override; diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index cb0cb3656..6705f8af7 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -74,9 +74,6 @@ void __late_init(void) { } -static BasebandThread baseband_thread; -static RSSIThread rssi_thread; - static void init() { i2s::i2s0::configure( audio::i2s0_config_tx, @@ -163,6 +160,8 @@ public: private: MessageHandlerMap message_map; + BasebandThread baseband_thread; + RSSIThread rssi_thread; bool is_running = true; diff --git a/firmware/baseband/rssi_thread.cpp b/firmware/baseband/rssi_thread.cpp index d7b5f99ca..0bf153342 100644 --- a/firmware/baseband/rssi_thread.cpp +++ b/firmware/baseband/rssi_thread.cpp @@ -28,8 +28,10 @@ #include "message.hpp" #include "portapack_shared_memory.hpp" +WORKING_AREA(rssi_thread_wa, 128); + Thread* RSSIThread::start(const tprio_t priority) { - return chThdCreateStatic(wa, sizeof(wa), + return chThdCreateStatic(rssi_thread_wa, sizeof(rssi_thread_wa), priority, ThreadBase::fn, this ); diff --git a/firmware/baseband/rssi_thread.hpp b/firmware/baseband/rssi_thread.hpp index f3fde10ae..0a00ef8e9 100644 --- a/firmware/baseband/rssi_thread.hpp +++ b/firmware/baseband/rssi_thread.hpp @@ -38,8 +38,6 @@ public: Thread* start(const tprio_t priority); private: - WORKING_AREA(wa, 128); - void run() override; const uint32_t sampling_rate { 400000 }; From 75b1cc25ff68b27adf60ab0971c03d8f06ab415e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 10 Dec 2015 21:21:42 -0800 Subject: [PATCH 120/452] Missing lambda capture. --- firmware/baseband/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 6705f8af7..9f8ea3080 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -127,9 +127,9 @@ public: void run() { message_map.register_handler(Message::ID::BasebandConfiguration, - [](const Message* const p) { + [this](const Message* const p) { auto message = reinterpret_cast(p); - baseband_thread.set_configuration(message->configuration); + this->baseband_thread.set_configuration(message->configuration); } ); From 088f60f2bc7f0ad0147376c0b62929a779142d14 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 11 Dec 2015 12:26:45 -0800 Subject: [PATCH 121/452] Extract spectrum collector from BasebandProcessor. Code size improvement, and less confused classes. :-) --- firmware/baseband/Makefile | 1 + firmware/baseband/baseband_processor.cpp | 49 ------------ firmware/baseband/baseband_processor.hpp | 18 +---- firmware/baseband/baseband_thread.cpp | 6 ++ firmware/baseband/baseband_thread.hpp | 2 + firmware/baseband/main.cpp | 5 +- firmware/baseband/proc_am_audio.cpp | 2 +- firmware/baseband/proc_am_audio.hpp | 6 ++ firmware/baseband/proc_nfm_audio.cpp | 2 +- firmware/baseband/proc_nfm_audio.hpp | 6 ++ firmware/baseband/proc_wideband_spectrum.cpp | 28 +++---- firmware/baseband/proc_wideband_spectrum.hpp | 7 +- firmware/baseband/spectrum_collector.cpp | 79 ++++++++++++++++++++ firmware/baseband/spectrum_collector.hpp | 61 +++++++++++++++ firmware/common/complex.hpp | 7 ++ 15 files changed, 193 insertions(+), 86 deletions(-) create mode 100644 firmware/baseband/spectrum_collector.cpp create mode 100644 firmware/baseband/spectrum_collector.hpp diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index caf93066b..baec06534 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -137,6 +137,7 @@ CPPSRC = main.cpp \ matched_filter.cpp \ proc_am_audio.cpp \ proc_nfm_audio.cpp \ + spectrum_collector.cpp \ proc_wfm_audio.cpp \ proc_ais.cpp \ proc_wideband_spectrum.cpp \ diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index 620e965ed..9c05de3e2 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -34,31 +34,6 @@ #include #include -void BasebandProcessor::update_spectrum() { - // Called from idle thread (after EVT_MASK_SPECTRUM is flagged) - if( channel_spectrum_request_update ) { - /* Decimated buffer is full. Compute spectrum. */ - channel_spectrum_request_update = false; - fft_c_preswapped(channel_spectrum); - - ChannelSpectrumMessage spectrum_message; - for(size_t i=0; i .magnitude, or something more (less!) accurate. */ - spectrum_message.spectrum.db_count = spectrum_message.spectrum.db.size(); - spectrum_message.spectrum.sampling_rate = channel_spectrum_sampling_rate; - spectrum_message.spectrum.channel_filter_pass_frequency = channel_filter_pass_frequency; - spectrum_message.spectrum.channel_filter_stop_frequency = channel_filter_stop_frequency; - shared_memory.application_queue.push(spectrum_message); - } -} - void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { channel_stats.feed( channel, @@ -69,21 +44,6 @@ void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { ); } -void BasebandProcessor::feed_channel_spectrum( - const buffer_c16_t& channel, - const uint32_t filter_pass_frequency, - const uint32_t filter_stop_frequency -) { - channel_filter_pass_frequency = filter_pass_frequency; - channel_filter_stop_frequency = filter_stop_frequency; - channel_spectrum_decimator.feed( - channel, - [this](const buffer_c16_t& data) { - this->post_channel_spectrum_message(data); - } - ); -} - void BasebandProcessor::fill_audio_buffer(const buffer_s16_t& audio) { auto audio_buffer = audio::dma::tx_empty_buffer();; for(size_t i=0; i, 256> channel_spectrum; - uint32_t channel_spectrum_sampling_rate { 0 }; - uint32_t channel_filter_pass_frequency { 0 }; - uint32_t channel_filter_stop_frequency { 0 }; - private: - BlockDecimator<256> channel_spectrum_decimator { 4 }; - ChannelStatsCollector channel_stats; AudioStatsCollector audio_stats; - void post_channel_spectrum_message(const buffer_c16_t& data); void feed_audio_stats(const buffer_s16_t& audio); }; diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp index 606d09254..b23170c35 100644 --- a/firmware/baseband/baseband_thread.cpp +++ b/firmware/baseband/baseband_thread.cpp @@ -68,6 +68,12 @@ void BasebandThread::set_configuration(const BasebandConfiguration& new_configur baseband_configuration = new_configuration; } +void BasebandThread::on_update_spectrum() { + if( baseband_processor ) { + baseband_processor->on_update_spectrum(); + } +} + void BasebandThread::run() { baseband::dma::init(); diff --git a/firmware/baseband/baseband_thread.hpp b/firmware/baseband/baseband_thread.hpp index e19882346..814dcd51e 100644 --- a/firmware/baseband/baseband_thread.hpp +++ b/firmware/baseband/baseband_thread.hpp @@ -39,6 +39,8 @@ public: void set_configuration(const BasebandConfiguration& new_configuration); + void on_update_spectrum(); + // This getter should die, it's just here to leak information to code that // isn't in the right place to begin with. baseband::Direction direction() const { diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 9f8ea3080..16c8c5d3a 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -187,9 +187,8 @@ private: } void handle_spectrum() { - if( baseband_thread.baseband_processor ) { - baseband_thread.baseband_processor->update_spectrum(); - } + // TODO: Send this via another message?! + baseband_thread.on_update_spectrum(); } }; diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 5bb374e99..b2d480c7c 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -38,7 +38,7 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { // TODO: Feed channel_stats post-decimation data? feed_channel_stats(channel); - feed_channel_spectrum( + channel_spectrum.feed( channel, decimator_out.sampling_rate * channel_filter_taps.pass_frequency_normalized, decimator_out.sampling_rate * channel_filter_taps.stop_frequency_normalized diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index dfa6d5ec0..283f0f7c5 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -31,6 +31,8 @@ #include "dsp_iir.hpp" #include "dsp_iir_config.hpp" +#include "spectrum_collector.hpp" + class NarrowbandAMAudio : public BasebandProcessor { public: NarrowbandAMAudio() { @@ -40,12 +42,16 @@ public: void execute(const buffer_c8_t& buffer) override; + void on_update_spectrum() override { channel_spectrum.update(); } + private: ChannelDecimator decimator; const fir_taps_real<64>& channel_filter_taps = taps_64_lp_031_070_tfilter; dsp::decimate::FIRAndDecimateComplex channel_filter; dsp::demodulate::AM demod; IIRBiquadFilter audio_hpf { audio_hpf_config }; + + SpectrumCollector channel_spectrum; }; #endif/*__PROC_AM_AUDIO_H__*/ diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 4ac7539ec..80a400d7f 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -41,7 +41,7 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { // TODO: Feed channel_stats post-decimation data? feed_channel_stats(channel); - feed_channel_spectrum( + channel_spectrum.feed( channel, decimator_out.sampling_rate * channel_filter_taps.pass_frequency_normalized, decimator_out.sampling_rate * channel_filter_taps.stop_frequency_normalized diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index b4112dde2..7c47f3539 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -32,6 +32,8 @@ #include "dsp_iir_config.hpp" #include "dsp_squelch.hpp" +#include "spectrum_collector.hpp" + class NarrowbandFMAudio : public BasebandProcessor { public: NarrowbandFMAudio() { @@ -41,6 +43,8 @@ public: void execute(const buffer_c8_t& buffer) override; + void on_update_spectrum() override { channel_spectrum.update(); } + private: ChannelDecimator decimator; const fir_taps_real<64>& channel_filter_taps = taps_64_lp_042_078_tfilter; @@ -49,6 +53,8 @@ private: IIRBiquadFilter audio_hpf { audio_hpf_config }; FMSquelch squelch; + + SpectrumCollector channel_spectrum; }; #endif/*__PROC_NFM_AUDIO_H__*/ diff --git a/firmware/baseband/proc_wideband_spectrum.cpp b/firmware/baseband/proc_wideband_spectrum.cpp index 12fe1b7d8..25ee7e48b 100644 --- a/firmware/baseband/proc_wideband_spectrum.cpp +++ b/firmware/baseband/proc_wideband_spectrum.cpp @@ -43,24 +43,24 @@ void WidebandSpectrum::execute(const buffer_c8_t& buffer) { std::fill(spectrum.begin(), spectrum.end(), 0); } - if( (phase & 7) == 0 ) { + for(size_t i=0; i #include @@ -32,10 +33,14 @@ class WidebandSpectrum : public BasebandProcessor { public: void execute(const buffer_c8_t& buffer) override; + void on_update_spectrum() override { channel_spectrum.update(); } + private: size_t sample_count = 0; - std::array, 256> spectrum; + SpectrumCollector channel_spectrum { 1 }; + + std::array spectrum; }; #endif/*__PROC_WIDEBAND_SPECTRUM_H__*/ diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp new file mode 100644 index 000000000..7c55126c4 --- /dev/null +++ b/firmware/baseband/spectrum_collector.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "spectrum_collector.hpp" + +#include "dsp_fft.hpp" + +#include "utility.hpp" +#include "event_m4.hpp" +#include "portapack_shared_memory.hpp" + +#include + +void SpectrumCollector::update() { + // Called from idle thread (after EVT_MASK_SPECTRUM is flagged) + if( channel_spectrum_request_update ) { + /* Decimated buffer is full. Compute spectrum. */ + channel_spectrum_request_update = false; + fft_c_preswapped(channel_spectrum); + + ChannelSpectrumMessage spectrum_message; + for(size_t i=0; i .magnitude, or something more (less!) accurate. */ + spectrum_message.spectrum.db_count = spectrum_message.spectrum.db.size(); + spectrum_message.spectrum.sampling_rate = channel_spectrum_sampling_rate; + spectrum_message.spectrum.channel_filter_pass_frequency = channel_filter_pass_frequency; + spectrum_message.spectrum.channel_filter_stop_frequency = channel_filter_stop_frequency; + shared_memory.application_queue.push(spectrum_message); + } +} + +void SpectrumCollector::feed( + const buffer_c16_t& channel, + const uint32_t filter_pass_frequency, + const uint32_t filter_stop_frequency +) { + channel_filter_pass_frequency = filter_pass_frequency; + channel_filter_stop_frequency = filter_stop_frequency; + channel_spectrum_decimator.feed( + channel, + [this](const buffer_c16_t& data) { + this->post_message(data); + } + ); +} + +void SpectrumCollector::post_message(const buffer_c16_t& data) { + if( !channel_spectrum_request_update ) { + fft_swap(data, channel_spectrum); + channel_spectrum_sampling_rate = data.sampling_rate; + channel_spectrum_request_update = true; + events_flag(EVT_MASK_SPECTRUM); + } +} diff --git a/firmware/baseband/spectrum_collector.hpp b/firmware/baseband/spectrum_collector.hpp new file mode 100644 index 000000000..a072b5299 --- /dev/null +++ b/firmware/baseband/spectrum_collector.hpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __SPECTRUM_COLLECTOR_H__ +#define __SPECTRUM_COLLECTOR_H__ + +#include "dsp_types.hpp" +#include "complex.hpp" + +#include "block_decimator.hpp" + +#include +#include + +class SpectrumCollector { +public: + constexpr SpectrumCollector( + const size_t decimation_factor = 4 + ) : channel_spectrum_decimator { decimation_factor } + { + } + + void update(); + + void feed( + const buffer_c16_t& channel, + const uint32_t filter_pass_frequency, + const uint32_t filter_stop_frequency + ); + +private: + BlockDecimator<256> channel_spectrum_decimator; + + volatile bool channel_spectrum_request_update { false }; + std::array, 256> channel_spectrum; + uint32_t channel_spectrum_sampling_rate { 0 }; + uint32_t channel_filter_pass_frequency { 0 }; + uint32_t channel_filter_stop_frequency { 0 }; + + void post_message(const buffer_c16_t& data); +}; + +#endif/*__SPECTRUM_COLLECTOR_H__*/ diff --git a/firmware/common/complex.hpp b/firmware/common/complex.hpp index b2cfc1dec..06d787bd8 100644 --- a/firmware/common/complex.hpp +++ b/firmware/common/complex.hpp @@ -101,6 +101,13 @@ public: void real(int16_t v) { _v[0] = v; } void imag(int16_t v) { _v[1] = v; } + template + complex& operator+=(const complex& other) { + _v[0] += other.real(); + _v[1] += other.imag(); + return *this; + } + constexpr uint32_t __rep() const { return _rep; } From d1637db2fc8f290a4e15a53f02571bc9ad1a7a1e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 11 Dec 2015 17:17:12 -0800 Subject: [PATCH 122/452] Reorder methods in source file to indicate call order. --- firmware/baseband/spectrum_collector.cpp | 48 ++++++++++++------------ firmware/baseband/spectrum_collector.hpp | 4 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index 7c55126c4..364cb44b1 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -29,6 +29,30 @@ #include +void SpectrumCollector::feed( + const buffer_c16_t& channel, + const uint32_t filter_pass_frequency, + const uint32_t filter_stop_frequency +) { + channel_filter_pass_frequency = filter_pass_frequency; + channel_filter_stop_frequency = filter_stop_frequency; + channel_spectrum_decimator.feed( + channel, + [this](const buffer_c16_t& data) { + this->post_message(data); + } + ); +} + +void SpectrumCollector::post_message(const buffer_c16_t& data) { + if( !channel_spectrum_request_update ) { + fft_swap(data, channel_spectrum); + channel_spectrum_sampling_rate = data.sampling_rate; + channel_spectrum_request_update = true; + events_flag(EVT_MASK_SPECTRUM); + } +} + void SpectrumCollector::update() { // Called from idle thread (after EVT_MASK_SPECTRUM is flagged) if( channel_spectrum_request_update ) { @@ -53,27 +77,3 @@ void SpectrumCollector::update() { shared_memory.application_queue.push(spectrum_message); } } - -void SpectrumCollector::feed( - const buffer_c16_t& channel, - const uint32_t filter_pass_frequency, - const uint32_t filter_stop_frequency -) { - channel_filter_pass_frequency = filter_pass_frequency; - channel_filter_stop_frequency = filter_stop_frequency; - channel_spectrum_decimator.feed( - channel, - [this](const buffer_c16_t& data) { - this->post_message(data); - } - ); -} - -void SpectrumCollector::post_message(const buffer_c16_t& data) { - if( !channel_spectrum_request_update ) { - fft_swap(data, channel_spectrum); - channel_spectrum_sampling_rate = data.sampling_rate; - channel_spectrum_request_update = true; - events_flag(EVT_MASK_SPECTRUM); - } -} diff --git a/firmware/baseband/spectrum_collector.hpp b/firmware/baseband/spectrum_collector.hpp index a072b5299..203f337ac 100644 --- a/firmware/baseband/spectrum_collector.hpp +++ b/firmware/baseband/spectrum_collector.hpp @@ -38,14 +38,14 @@ public: { } - void update(); - void feed( const buffer_c16_t& channel, const uint32_t filter_pass_frequency, const uint32_t filter_stop_frequency ); + void update(); + private: BlockDecimator<256> channel_spectrum_decimator; From c825a027b20c48a416f6c3ad5b77c5110082a852 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 11 Dec 2015 17:29:58 -0800 Subject: [PATCH 123/452] Comments regarding threading concerns, future refactoring. --- firmware/baseband/spectrum_collector.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index 364cb44b1..e344a0f59 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -29,11 +29,17 @@ #include +/* 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 SpectrumCollector::feed( const buffer_c16_t& channel, const uint32_t filter_pass_frequency, const uint32_t filter_stop_frequency ) { + // Called from baseband processing thread. channel_filter_pass_frequency = filter_pass_frequency; channel_filter_stop_frequency = filter_stop_frequency; channel_spectrum_decimator.feed( @@ -45,6 +51,7 @@ void SpectrumCollector::feed( } void SpectrumCollector::post_message(const buffer_c16_t& data) { + // Called from baseband processing thread. if( !channel_spectrum_request_update ) { fft_swap(data, channel_spectrum); channel_spectrum_sampling_rate = data.sampling_rate; From b058d609eb83b2d60d165cb5113c5a25af2670dd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 12 Dec 2015 11:37:30 -0800 Subject: [PATCH 124/452] Move packet timestamping into baseband. Now reads the RTC peripheral at the end of each received packet. TODO: Improve resolution to milliseconds or better. TODO: Work back from end of packet to compute timestamp for beginning of packet. TODO: Reuse ChibiOS RTC code, which isn't used now because ChibiOS on M0 core is responsible for RTC configuration, and including ChibiOS RTC API on M4 will also try to initialize/manage the peripheral. --- firmware/application/ais_app.cpp | 4 +-- firmware/application/ert_app.cpp | 7 +---- firmware/application/tpms_app.cpp | 8 +---- firmware/baseband/packet_builder.hpp | 1 + firmware/common/ais_packet.cpp | 4 +-- firmware/common/ais_packet.hpp | 8 +---- firmware/common/baseband_packet.hpp | 11 +++++++ firmware/common/buffer.hpp | 45 +++++++++++++++++++++++++--- firmware/common/ert_packet.cpp | 4 +-- firmware/common/ert_packet.hpp | 8 +---- 10 files changed, 62 insertions(+), 38 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 1aaa0e38f..0487a8bdc 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -120,9 +120,7 @@ void AISView::on_show() { message_map.register_handler(Message::ID::AISPacket, [this](Message* const p) { const auto message = static_cast(p); - rtc::RTC datetime; - rtcGetTime(&RTCD1, &datetime); - const ais::Packet packet { datetime, message->packet }; + const ais::Packet packet { message->packet }; if( this->model.on_packet(packet) ) { this->on_packet(packet); } diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 1b4c4c83a..596831e3e 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -26,9 +26,6 @@ using namespace portapack; #include "manchester.hpp" -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - #include "crc.hpp" #include "string_format.hpp" @@ -61,9 +58,7 @@ void ERTView::on_show() { message_map.register_handler(Message::ID::ERTPacket, [this](Message* const p) { const auto message = static_cast(p); - rtc::RTC datetime; - rtcGetTime(&RTCD1, &datetime); - const ert::Packet packet { datetime, message->type, message->packet }; + const ert::Packet packet { message->type, message->packet }; if( this->model.on_packet(packet) ) { this->on_packet(packet); } diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 3ac2ba85e..155c8aa9f 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -26,9 +26,6 @@ using namespace portapack; #include "string_format.hpp" -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - TPMSModel::TPMSModel() { receiver_model.set_baseband_configuration({ .mode = 5, @@ -41,9 +38,6 @@ TPMSModel::TPMSModel() { } ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { - rtc::RTC received_at; - rtcGetTime(&RTCD1, &received_at); - const ManchesterDecoder decoder(message.packet, 1); const auto hex_formatted = format_manchester(decoder); @@ -53,7 +47,7 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); std::string entry = tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors; - log_file.write_entry(received_at, entry); + log_file.write_entry(message.packet.timestamp(), entry); } return hex_formatted; diff --git a/firmware/baseband/packet_builder.hpp b/firmware/baseband/packet_builder.hpp index 168f242e8..d32d129d0 100644 --- a/firmware/baseband/packet_builder.hpp +++ b/firmware/baseband/packet_builder.hpp @@ -89,6 +89,7 @@ public: } if( end(bit_history, packet.size()) ) { + packet.set_timestamp(Timestamp::now()); payload_handler(packet); reset_state(); } else { diff --git a/firmware/common/ais_packet.cpp b/firmware/common/ais_packet.cpp index 7999a111b..9dcf76588 100644 --- a/firmware/common/ais_packet.cpp +++ b/firmware/common/ais_packet.cpp @@ -128,8 +128,8 @@ bool Packet::is_valid() const { return length_valid() && crc_ok(); } -rtc::RTC Packet::received_at() const { - return received_at_; +Timestamp Packet::received_at() const { + return packet_.timestamp(); } uint32_t Packet::message_id() const { diff --git a/firmware/common/ais_packet.hpp b/firmware/common/ais_packet.hpp index 25ecc9360..90e80873f 100644 --- a/firmware/common/ais_packet.hpp +++ b/firmware/common/ais_packet.hpp @@ -25,9 +25,6 @@ #include "baseband_packet.hpp" #include "field_reader.hpp" -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - #include #include #include @@ -51,10 +48,8 @@ using MMSI = uint32_t; class Packet { public: constexpr Packet( - const rtc::RTC& received_at, const baseband::Packet& packet ) : packet_ { packet }, - received_at_ { received_at }, field_ { packet_ } { } @@ -63,7 +58,7 @@ public: bool is_valid() const; - rtc::RTC received_at() const; + Timestamp received_at() const; uint32_t message_id() const; MMSI user_id() const; @@ -85,7 +80,6 @@ private: using CRCReader = FieldReader; const baseband::Packet packet_; - const rtc::RTC received_at_; const Reader field_; const size_t fcs_length = 16; diff --git a/firmware/common/baseband_packet.hpp b/firmware/common/baseband_packet.hpp index 4285828c5..f5bf161c4 100644 --- a/firmware/common/baseband_packet.hpp +++ b/firmware/common/baseband_packet.hpp @@ -22,6 +22,8 @@ #ifndef __BASEBAND_PACKET_H__ #define __BASEBAND_PACKET_H__ +#include "baseband.hpp" + #include #include @@ -29,6 +31,14 @@ namespace baseband { class Packet { public: + void set_timestamp(const Timestamp& value) { + timestamp_ = value; + } + + Timestamp timestamp() const { + return timestamp_; + } + void add(const bool symbol) { if( count < capacity() ) { data[count++] = symbol; @@ -53,6 +63,7 @@ public: private: std::bitset<1408> data; + Timestamp timestamp_ { }; size_t count { 0 }; }; diff --git a/firmware/common/buffer.hpp b/firmware/common/buffer.hpp index be1846dd8..da7e70a78 100644 --- a/firmware/common/buffer.hpp +++ b/firmware/common/buffer.hpp @@ -25,16 +25,50 @@ #include #include +/* LPC43xx RTC structure. Avoiding using the ChibiOS-defined structure because + * it pulls in all sorts of dependencies and initialization and other stuff that + * the M0 needs to remain in control of. + * + * But yes, this is a hack, and something better is needed. It's too tangled of + * a knot to tackle at the moment, though... + */ +#if defined(LPC43XX_M4) +#include "lpc43xx_m4.h" + +struct Timestamp { + uint32_t tv_date { 0 }; + uint32_t tv_time { 0 }; + + static Timestamp now() { + // Code stolen from LPC43xx rtc_lld.c + Timestamp timestamp; + do { + timestamp.tv_time = LPC_RTC->CTIME0; + timestamp.tv_date = LPC_RTC->CTIME1; + } while( (timestamp.tv_time != LPC_RTC->CTIME0) || (timestamp.tv_date != LPC_RTC->CTIME1) ); + return timestamp; + } +}; +#endif + +#if defined(LPC43XX_M0) +#include "lpc43xx_cpp.hpp" + +using Timestamp = lpc43xx::rtc::RTC; +#endif + template struct buffer_t { T* const p; const size_t count; const uint32_t sampling_rate; + const Timestamp timestamp; constexpr buffer_t( ) : p { nullptr }, count { 0 }, - sampling_rate { 0 } + sampling_rate { 0 }, + timestamp { } { } @@ -42,17 +76,20 @@ struct buffer_t { const buffer_t& other ) : p { other.p }, count { other.count }, - sampling_rate { other.sampling_rate } + sampling_rate { other.sampling_rate }, + timestamp { other.timestamp } { } constexpr buffer_t( T* const p, const size_t count, - const uint32_t sampling_rate = 0 + const uint32_t sampling_rate = 0, + const Timestamp timestamp = { } ) : p { p }, count { count }, - sampling_rate { sampling_rate } + sampling_rate { sampling_rate }, + timestamp { timestamp } { } }; diff --git a/firmware/common/ert_packet.cpp b/firmware/common/ert_packet.cpp index e5c477f9c..da2a61241 100644 --- a/firmware/common/ert_packet.cpp +++ b/firmware/common/ert_packet.cpp @@ -33,8 +33,8 @@ bool Packet::is_valid() const { return true; } -rtc::RTC Packet::received_at() const { - return received_at_; +Timestamp Packet::received_at() const { + return packet_.timestamp(); } Packet::Type Packet::type() const { diff --git a/firmware/common/ert_packet.hpp b/firmware/common/ert_packet.hpp index eaaa1763d..f0bb3a132 100644 --- a/firmware/common/ert_packet.hpp +++ b/firmware/common/ert_packet.hpp @@ -29,9 +29,6 @@ #include "baseband_packet.hpp" #include "manchester.hpp" -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - namespace ert { using ID = uint32_t; @@ -46,11 +43,9 @@ public: }; Packet( - const rtc::RTC& received_at, const Type type, const baseband::Packet& packet ) : packet_ { packet }, - received_at_ { received_at }, decoder_ { packet_ }, reader_ { decoder_ }, type_ { type } @@ -61,7 +56,7 @@ public: bool is_valid() const; - rtc::RTC received_at() const; + Timestamp received_at() const; Type type() const; ID id() const; @@ -75,7 +70,6 @@ private: using Reader = FieldReader; const baseband::Packet packet_; - const rtc::RTC received_at_; const ManchesterDecoder decoder_; const Reader reader_; const Type type_; From 9170c66bc0d04cf2013fbf35f4c4bbc706b2b666 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 12 Dec 2015 11:37:59 -0800 Subject: [PATCH 125/452] Remove unused function declaration. --- firmware/common/baseband.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/firmware/common/baseband.hpp b/firmware/common/baseband.hpp index 50ce8da75..dfeef046a 100644 --- a/firmware/common/baseband.hpp +++ b/firmware/common/baseband.hpp @@ -35,8 +35,6 @@ enum class Direction { Transmit = 1, }; -buffer_t wait_for_rx_buffer(); - } /* namespace baseband */ #endif/*__BASEBAND_H__*/ From a6fbd1c5ef2eabd9d98e7c452e600517a632590b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 11:48:39 -0800 Subject: [PATCH 126/452] Make DebugRFFCView into generic RegistersView. --- firmware/application/ui_debug.cpp | 17 ----------------- firmware/application/ui_debug.hpp | 29 ++++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 4441268d3..a46e9c84a 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -102,23 +102,6 @@ void DebugRFFC5072RegistersWidget::draw_values( } } -DebugRFFC5072View::DebugRFFC5072View(NavigationView& nav) { - add_children({ { - &text_title, - &widget_registers, - &button_update, - &button_done, - } }); - - button_update.on_select = [this](Button&){ - this->widget_registers.update(); - }; - button_done.on_select = [&nav](Button&){ nav.pop(); }; -} - -void DebugRFFC5072View::focus() { - button_done.focus(); -} DebugMenuView::DebugMenuView(NavigationView& nav) { add_items<7>({ { diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 92fa0c47b..babab07e9 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -89,6 +89,8 @@ public: void paint(Painter& painter) override; + static constexpr const char* name = "RFFC5072"; + private: static constexpr size_t registers_count { 31 }; @@ -115,19 +117,34 @@ private: void draw_values(Painter& painter, const rffc507x::RegisterMap registers); }; -class DebugRFFC5072View : public View { +template +class RegistersView : public View { public: - DebugRFFC5072View(NavigationView& nav); + RegistersView(NavigationView& nav) { + add_children({ { + &text_title, + &widget_registers, + &button_update, + &button_done, + } }); - void focus() override; + button_update.on_select = [this](Button&){ + this->widget_registers.update(); + }; + button_done.on_select = [&nav](Button&){ nav.pop(); }; + } + + void focus() { + button_done.focus(); + } private: Text text_title { { 88, 16, 40, 16 }, - "RFFC5072", + RegistersWidget::name, }; - DebugRFFC5072RegistersWidget widget_registers { + RegistersWidget widget_registers { { 32, 48, 176, 128 } }; @@ -142,6 +159,8 @@ private: }; }; +using DebugRFFC5072View = RegistersView; + class DebugMenuView : public MenuView { public: DebugMenuView(NavigationView& nav); From c7d49eb190ce212092fc9f9ea72e606bd75cddcb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 11:50:06 -0800 Subject: [PATCH 127/452] Expose MAX2837 registers, show registers in debug view. --- firmware/application/max2837.cpp | 4 +++ firmware/application/max2837.hpp | 2 ++ firmware/application/radio.cpp | 3 +- firmware/application/radio.hpp | 2 ++ firmware/application/ui_debug.cpp | 49 ++++++++++++++++++++++++++++++- firmware/application/ui_debug.hpp | 36 +++++++++++++++++++++++ 6 files changed, 93 insertions(+), 3 deletions(-) diff --git a/firmware/application/max2837.cpp b/firmware/application/max2837.cpp index bf040a8f5..ca446a0ee 100644 --- a/firmware/application/max2837.cpp +++ b/firmware/application/max2837.cpp @@ -251,4 +251,8 @@ reg_t MAX2837::temp_sense() { return value; } +RegisterMap MAX2837::registers() { + return _map; +} + } diff --git a/firmware/application/max2837.hpp b/firmware/application/max2837.hpp index e3e8ce9b6..6f21b34e8 100644 --- a/firmware/application/max2837.hpp +++ b/firmware/application/max2837.hpp @@ -880,6 +880,8 @@ public: reg_t temp_sense(); + RegisterMap registers(); + private: spi::arbiter::Target& _target; diff --git a/firmware/application/radio.cpp b/firmware/application/radio.cpp index dcb6bfa7e..dbb29eac7 100644 --- a/firmware/application/radio.cpp +++ b/firmware/application/radio.cpp @@ -22,7 +22,6 @@ #include "radio.hpp" #include "rf_path.hpp" -#include "max2837.hpp" #include "max5864.hpp" #include "baseband_cpld.hpp" #include "baseband_sgpio.hpp" @@ -88,7 +87,7 @@ static spi::arbiter::Target ssp1_target_max5864 { static rf::path::Path rf_path; rffc507x::RFFC507x first_if; -static max2837::MAX2837 second_if { ssp1_target_max2837 }; +max2837::MAX2837 second_if { ssp1_target_max2837 }; static max5864::MAX5864 baseband_codec { ssp1_target_max5864 }; static baseband::CPLD baseband_cpld; static baseband::SGPIO baseband_sgpio; diff --git a/firmware/application/radio.hpp b/firmware/application/radio.hpp index 442968aad..c796963dd 100644 --- a/firmware/application/radio.hpp +++ b/firmware/application/radio.hpp @@ -28,6 +28,7 @@ #include #include "rffc507x.hpp" +#include "max2837.hpp" namespace radio { @@ -47,6 +48,7 @@ void streaming_disable(); void disable(); extern rffc507x::RFFC507x first_if; +extern max2837::MAX2837 second_if; } /* namespace radio */ diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index a46e9c84a..8e81d6bfc 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -55,6 +55,53 @@ void DebugMemoryView::focus() { button_done.focus(); } +void DebugMAX2837RegistersWidget::update() { + set_dirty(); +} + +void DebugMAX2837RegistersWidget::paint(Painter& painter) { + draw_legend(painter); + + const auto registers = radio::second_if.registers(); + draw_values(painter, registers); +} + +void DebugMAX2837RegistersWidget::draw_legend(Painter& painter) { + for(size_t i=0; i((i / registers_per_row) * row_height) + }; + + const auto text = to_string_hex(i, legend_length); + painter.draw_string( + screen_pos() + offset, + style(), + text + ); + } +} + +void DebugMAX2837RegistersWidget::draw_values( + Painter& painter, + const max2837::RegisterMap registers +) { + for(size_t i=0; i(legend_width + 8 + (i % registers_per_row) * (value_width + 8)), + static_cast((i / registers_per_row) * row_height) + }; + + const uint16_t value = registers.w[i]; + + const auto text = to_string_hex(value, value_length); + painter.draw_string( + screen_pos() + offset, + style(), + text + ); + } +} + void DebugRFFC5072RegistersWidget::update() { set_dirty(); } @@ -109,7 +156,7 @@ DebugMenuView::DebugMenuView(NavigationView& nav) { { "Radio State", [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "SD Card", [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "RFFC5072", [&nav](){ nav.push(new DebugRFFC5072View { nav }); } }, - { "MAX2837", [&nav](){ nav.push(new NotImplementedView { nav }); } }, + { "MAX2837", [&nav](){ nav.push(new DebugMAX2837View { nav }); } }, { "Si5351C", [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "WM8731", [&nav](){ nav.push(new NotImplementedView { nav }); } }, } }); diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index babab07e9..ccba0f269 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -29,6 +29,7 @@ #include "ui_navigation.hpp" #include "rffc507x.hpp" +#include "max2837.hpp" namespace ui { @@ -117,6 +118,40 @@ private: void draw_values(Painter& painter, const rffc507x::RegisterMap registers); }; +class DebugMAX2837RegistersWidget : public Widget { +public: + constexpr DebugMAX2837RegistersWidget( + Rect parent_rect + ) : Widget { parent_rect } + { + } + + void update(); + + void paint(Painter& painter) override; + + static constexpr const char* const name = "MAX2837"; + +private: + static constexpr size_t registers_count = 32; + + static constexpr size_t legend_length = 2; + static constexpr Dim legend_width = legend_length * 8; + + static constexpr size_t value_length = 3; + static constexpr Dim value_width = value_length * 8; + + static constexpr size_t registers_per_row = 4; + static constexpr size_t registers_row_length = (registers_per_row * (value_length + 1)) - 1; + static constexpr Dim registers_row_width = registers_row_length * 8; + + static constexpr size_t rows = registers_count / registers_per_row; + static constexpr Dim row_height = 16; + + void draw_legend(Painter& painter); + void draw_values(Painter& painter, const max2837::RegisterMap registers); +}; + template class RegistersView : public View { public: @@ -160,6 +195,7 @@ private: }; using DebugRFFC5072View = RegistersView; +using DebugMAX2837View = RegistersView; class DebugMenuView : public MenuView { public: From 32108a82299df8300f632adc6772e26d3b3e0368 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 11:50:31 -0800 Subject: [PATCH 128/452] Field for register set name was too narrow. --- firmware/application/ui_debug.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index ccba0f269..16906ccdd 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -175,7 +175,7 @@ public: private: Text text_title { - { 88, 16, 40, 16 }, + { 88, 16, 64, 16 }, RegistersWidget::name, }; From 5df1665994e7d33492e9cd9c881f37518175bb68 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 11:50:55 -0800 Subject: [PATCH 129/452] Class divider comments. --- firmware/application/ui_debug.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 8e81d6bfc..98d52e912 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -28,6 +28,8 @@ namespace ui { +/* DebugMemoryView *******************************************************/ + DebugMemoryView::DebugMemoryView(NavigationView& nav) { add_children({ { &text_title, @@ -55,6 +57,8 @@ void DebugMemoryView::focus() { button_done.focus(); } +/* DebugMAX2837RegistersWidget *******************************************/ + void DebugMAX2837RegistersWidget::update() { set_dirty(); } @@ -102,6 +106,8 @@ void DebugMAX2837RegistersWidget::draw_values( } } +/* DebugRFFC5072RegistersWidget ******************************************/ + void DebugRFFC5072RegistersWidget::update() { set_dirty(); } @@ -149,6 +155,7 @@ void DebugRFFC5072RegistersWidget::draw_values( } } +/* DebugMenuView *********************************************************/ DebugMenuView::DebugMenuView(NavigationView& nav) { add_items<7>({ { From 74aa2112f44819d741809fdb0352cfba9590de22 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 12:34:51 -0800 Subject: [PATCH 130/452] Add Si5351C register view, make more space in all register views. --- firmware/application/portapack.cpp | 1 - firmware/application/portapack.hpp | 3 ++ firmware/application/ui_debug.cpp | 50 +++++++++++++++++++++++++++++- firmware/application/ui_debug.hpp | 42 +++++++++++++++++++++++-- 4 files changed, 91 insertions(+), 5 deletions(-) diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 67ee181f4..1491fe6a4 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -27,7 +27,6 @@ #include "hackrf_gpio.hpp" using namespace hackrf::one; -#include "si5351.hpp" #include "clock_manager.hpp" #include "i2c_pp.hpp" diff --git a/firmware/application/portapack.hpp b/firmware/application/portapack.hpp index 939442de4..ae424f36d 100644 --- a/firmware/application/portapack.hpp +++ b/firmware/application/portapack.hpp @@ -25,6 +25,7 @@ #include "spi_pp.hpp" #include "wm8731.hpp" +#include "si5351.hpp" #include "lcd_ili9341.hpp" #include "radio.hpp" @@ -40,6 +41,8 @@ extern SPI ssp1; extern wolfson::wm8731::WM8731 audio_codec; +extern si5351::Si5351 clock_generator; + extern ReceiverModel receiver_model; void init(); diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 98d52e912..fd7b9ecd6 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -155,6 +155,54 @@ void DebugRFFC5072RegistersWidget::draw_values( } } +/* DebugSi5351CRegistersWidget ******************************************/ + +void DebugSi5351CRegistersWidget::update() { + set_dirty(); +} + +void DebugSi5351CRegistersWidget::paint(Painter& painter) { + draw_legend(painter); + + draw_values(painter, portapack::clock_generator); +} + +void DebugSi5351CRegistersWidget::draw_legend(Painter& painter) { + for(size_t i=0; i((i / registers_per_row) * row_height) + }; + + const auto text = to_string_hex(i, legend_length); + painter.draw_string( + screen_pos() + offset, + style(), + text + ); + } +} + +void DebugSi5351CRegistersWidget::draw_values( + Painter& painter, + si5351::Si5351& device +) { + for(size_t i=0; i(legend_width + 8 + (i % registers_per_row) * (value_width + 8)), + static_cast((i / registers_per_row) * row_height) + }; + + const auto value = device.read_register(i); + + const auto text = to_string_hex(value, value_length); + painter.draw_string( + screen_pos() + offset, + style(), + text + ); + } +} + /* DebugMenuView *********************************************************/ DebugMenuView::DebugMenuView(NavigationView& nav) { @@ -164,7 +212,7 @@ DebugMenuView::DebugMenuView(NavigationView& nav) { { "SD Card", [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "RFFC5072", [&nav](){ nav.push(new DebugRFFC5072View { nav }); } }, { "MAX2837", [&nav](){ nav.push(new DebugMAX2837View { nav }); } }, - { "Si5351C", [&nav](){ nav.push(new NotImplementedView { nav }); } }, + { "Si5351C", [&nav](){ nav.push(new DebugSi5351CView { nav }); } }, { "WM8731", [&nav](){ nav.push(new NotImplementedView { nav }); } }, } }); on_left = [&nav](){ nav.pop(); }; diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 16906ccdd..68871b3cf 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -30,6 +30,7 @@ #include "rffc507x.hpp" #include "max2837.hpp" +#include "portapack.hpp" namespace ui { @@ -152,6 +153,40 @@ private: void draw_values(Painter& painter, const max2837::RegisterMap registers); }; +class DebugSi5351CRegistersWidget : public Widget { +public: + constexpr DebugSi5351CRegistersWidget( + Rect parent_rect + ) : Widget { parent_rect } + { + } + + void update(); + + void paint(Painter& painter) override; + + static constexpr const char* const name = "Si5351C"; + +private: + static constexpr size_t registers_count = 96; + + static constexpr size_t legend_length = 2; + static constexpr Dim legend_width = legend_length * 8; + + static constexpr size_t value_length = 2; + static constexpr Dim value_width = value_length * 8; + + static constexpr size_t registers_per_row = 8; + static constexpr size_t registers_row_length = (registers_per_row * (value_length + 1)) - 1; + static constexpr Dim registers_row_width = registers_row_length * 8; + + static constexpr size_t rows = registers_count / registers_per_row; + static constexpr Dim row_height = 16; + + void draw_legend(Painter& painter); + void draw_values(Painter& painter, si5351::Si5351& device); +}; + template class RegistersView : public View { public: @@ -180,22 +215,23 @@ private: }; RegistersWidget widget_registers { - { 32, 48, 176, 128 } + { 0, 48, 240, 192 } }; Button button_update { - { 16, 192, 96, 24 }, + { 16, 256, 96, 24 }, "Update" }; Button button_done { - { 128, 192, 96, 24 }, + { 128, 256, 96, 24 }, "Done" }; }; using DebugRFFC5072View = RegistersView; using DebugMAX2837View = RegistersView; +using DebugSi5351CView = RegistersView; class DebugMenuView : public MenuView { public: From 041e2118419b960ad6640f663bb42e319d3771a1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 13:18:05 -0800 Subject: [PATCH 131/452] Expose register read functions. --- firmware/application/max2837.hpp | 2 +- firmware/application/rffc507x.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/max2837.hpp b/firmware/application/max2837.hpp index 6f21b34e8..de300cb18 100644 --- a/firmware/application/max2837.hpp +++ b/firmware/application/max2837.hpp @@ -881,6 +881,7 @@ public: reg_t temp_sense(); RegisterMap registers(); + reg_t read(const address_t reg_num); private: spi::arbiter::Target& _target; @@ -891,7 +892,6 @@ private: void flush_one(const Register reg); void write(const address_t reg_num, const reg_t value); - reg_t read(const address_t reg_num); void write(const Register reg, const reg_t value); reg_t read(const Register reg); diff --git a/firmware/application/rffc507x.hpp b/firmware/application/rffc507x.hpp index 72fdd6b9b..27d2ee673 100644 --- a/firmware/application/rffc507x.hpp +++ b/firmware/application/rffc507x.hpp @@ -810,6 +810,7 @@ public: void set_frequency(const rf::Frequency lo_frequency); RegisterMap registers(); + reg_t read(const address_t reg_num); private: spi::SPI _bus; @@ -818,7 +819,6 @@ private: DirtyRegisters _dirty; void write(const address_t reg_num, const reg_t value); - reg_t read(const address_t reg_num); void write(const Register reg, const reg_t value); reg_t read(const Register reg); From 2fe1285c11c748b93019708a610e6f6c0ac57c7a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 13:18:37 -0800 Subject: [PATCH 132/452] Un-inline register read/write functions. --- firmware/application/max2837.cpp | 8 ++++---- firmware/application/rffc507x.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/application/max2837.cpp b/firmware/application/max2837.cpp index ca446a0ee..98a1850c7 100644 --- a/firmware/application/max2837.cpp +++ b/firmware/application/max2837.cpp @@ -149,22 +149,22 @@ void MAX2837::flush_one(const Register reg) { _dirty.clear(reg_num); } -inline void MAX2837::write(const address_t reg_num, const reg_t value) { +void MAX2837::write(const address_t reg_num, const reg_t value) { uint16_t t = (0U << 15) | (reg_num << 10) | (value & 0x3ffU); _target.transfer(&t, 1); } -inline reg_t MAX2837::read(const address_t reg_num) { +reg_t MAX2837::read(const address_t reg_num) { uint16_t t = (1U << 15) | (reg_num << 10); _target.transfer(&t, 1U); return t & 0x3ffU; } -inline void MAX2837::write(const Register reg, const reg_t value) { +void MAX2837::write(const Register reg, const reg_t value) { write(toUType(reg), value); } -inline reg_t MAX2837::read(const Register reg) { +reg_t MAX2837::read(const Register reg) { return read(toUType(reg)); } diff --git a/firmware/application/rffc507x.cpp b/firmware/application/rffc507x.cpp index 1ac3fec31..30921cc56 100644 --- a/firmware/application/rffc507x.cpp +++ b/firmware/application/rffc507x.cpp @@ -183,23 +183,23 @@ void RFFC507x::flush() { } } -inline void RFFC507x::write(const address_t reg_num, const spi::reg_t value) { +void RFFC507x::write(const address_t reg_num, const spi::reg_t value) { _bus.write(reg_num, value); } -inline spi::reg_t RFFC507x::read(const address_t reg_num) { +spi::reg_t RFFC507x::read(const address_t reg_num) { return _bus.read(reg_num); } -inline void RFFC507x::write(const Register reg, const spi::reg_t value) { +void RFFC507x::write(const Register reg, const spi::reg_t value) { write(toUType(reg), value); } -inline spi::reg_t RFFC507x::read(const Register reg) { +spi::reg_t RFFC507x::read(const Register reg) { return read(toUType(reg)); } -inline void RFFC507x::flush_one(const Register reg) { +void RFFC507x::flush_one(const Register reg) { const auto reg_num = toUType(reg); write(reg_num, _map.w[reg_num]); _dirty.clear(reg_num); From 94805285e2ad07abecf945e39fdef39355e1c6f6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 13:20:22 -0800 Subject: [PATCH 133/452] Remove RegisterMap accessors. --- firmware/application/max2837.cpp | 4 ---- firmware/application/max2837.hpp | 1 - firmware/application/rffc507x.cpp | 4 ---- firmware/application/rffc507x.hpp | 1 - 4 files changed, 10 deletions(-) diff --git a/firmware/application/max2837.cpp b/firmware/application/max2837.cpp index 98a1850c7..f932cbaa0 100644 --- a/firmware/application/max2837.cpp +++ b/firmware/application/max2837.cpp @@ -251,8 +251,4 @@ reg_t MAX2837::temp_sense() { return value; } -RegisterMap MAX2837::registers() { - return _map; -} - } diff --git a/firmware/application/max2837.hpp b/firmware/application/max2837.hpp index de300cb18..d6733bce6 100644 --- a/firmware/application/max2837.hpp +++ b/firmware/application/max2837.hpp @@ -880,7 +880,6 @@ public: reg_t temp_sense(); - RegisterMap registers(); reg_t read(const address_t reg_num); private: diff --git a/firmware/application/rffc507x.cpp b/firmware/application/rffc507x.cpp index 30921cc56..b001aee4f 100644 --- a/firmware/application/rffc507x.cpp +++ b/firmware/application/rffc507x.cpp @@ -272,10 +272,6 @@ spi::reg_t RFFC507x::readback(const Readback readback) { return read(Register::READBACK); } -RegisterMap RFFC507x::registers() { - return _map; -} - #if 0 /* Test of RFFC507x reset over temperature */ while(true) { diff --git a/firmware/application/rffc507x.hpp b/firmware/application/rffc507x.hpp index 27d2ee673..4850f1474 100644 --- a/firmware/application/rffc507x.hpp +++ b/firmware/application/rffc507x.hpp @@ -809,7 +809,6 @@ public: void set_mixer_current(const uint8_t value); void set_frequency(const rf::Frequency lo_frequency); - RegisterMap registers(); reg_t read(const address_t reg_num); private: From a0fbfcf6a2569645322c1c6d92b483a69b2125c5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 13:22:09 -0800 Subject: [PATCH 134/452] Consolidate code and improve reuse between RegistersWidgets. --- firmware/application/ui_debug.cpp | 129 +++-------------------- firmware/application/ui_debug.hpp | 168 ++++++++++++++---------------- 2 files changed, 95 insertions(+), 202 deletions(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index fd7b9ecd6..4c35b489d 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -57,26 +57,25 @@ void DebugMemoryView::focus() { button_done.focus(); } -/* DebugMAX2837RegistersWidget *******************************************/ +/* RegistersWidget *******************************************************/ -void DebugMAX2837RegistersWidget::update() { +void RegistersWidget::update() { set_dirty(); } -void DebugMAX2837RegistersWidget::paint(Painter& painter) { +void RegistersWidget::paint(Painter& painter) { draw_legend(painter); - const auto registers = radio::second_if.registers(); - draw_values(painter, registers); + draw_values(painter); } -void DebugMAX2837RegistersWidget::draw_legend(Painter& painter) { - for(size_t i=0; i((i / registers_per_row) * row_height) + 0, static_cast((i / config.registers_per_row) * row_height) }; - const auto text = to_string_hex(i, legend_length); + const auto text = to_string_hex(i, config.legend_length); painter.draw_string( screen_pos() + offset, style(), @@ -85,116 +84,18 @@ void DebugMAX2837RegistersWidget::draw_legend(Painter& painter) { } } -void DebugMAX2837RegistersWidget::draw_values( - Painter& painter, - const max2837::RegisterMap registers +void RegistersWidget::draw_values( + Painter& painter ) { - for(size_t i=0; i(legend_width + 8 + (i % registers_per_row) * (value_width + 8)), - static_cast((i / registers_per_row) * row_height) + static_cast(config.legend_width() + 8 + (i % config.registers_per_row) * (config.value_width() + 8)), + static_cast((i / config.registers_per_row) * row_height) }; - const uint16_t value = registers.w[i]; + const auto value = read(i); - const auto text = to_string_hex(value, value_length); - painter.draw_string( - screen_pos() + offset, - style(), - text - ); - } -} - -/* DebugRFFC5072RegistersWidget ******************************************/ - -void DebugRFFC5072RegistersWidget::update() { - set_dirty(); -} - -void DebugRFFC5072RegistersWidget::paint(Painter& painter) { - draw_legend(painter); - - const auto registers = radio::first_if.registers(); - draw_values(painter, registers); -} - -void DebugRFFC5072RegistersWidget::draw_legend(Painter& painter) { - for(size_t i=0; i((i / registers_per_row) * row_height) - }; - - const auto text = to_string_hex(i, legend_length); - painter.draw_string( - screen_pos() + offset, - style(), - text - ); - } -} - -void DebugRFFC5072RegistersWidget::draw_values( - Painter& painter, - const rffc507x::RegisterMap registers -) { - for(size_t i=0; i(legend_width + 8 + (i % registers_per_row) * (value_width + 8)), - static_cast((i / registers_per_row) * row_height) - }; - - const uint16_t value = registers.w[i]; - - const auto text = to_string_hex(value, value_length); - painter.draw_string( - screen_pos() + offset, - style(), - text - ); - } -} - -/* DebugSi5351CRegistersWidget ******************************************/ - -void DebugSi5351CRegistersWidget::update() { - set_dirty(); -} - -void DebugSi5351CRegistersWidget::paint(Painter& painter) { - draw_legend(painter); - - draw_values(painter, portapack::clock_generator); -} - -void DebugSi5351CRegistersWidget::draw_legend(Painter& painter) { - for(size_t i=0; i((i / registers_per_row) * row_height) - }; - - const auto text = to_string_hex(i, legend_length); - painter.draw_string( - screen_pos() + offset, - style(), - text - ); - } -} - -void DebugSi5351CRegistersWidget::draw_values( - Painter& painter, - si5351::Si5351& device -) { - for(size_t i=0; i(legend_width + 8 + (i % registers_per_row) * (value_width + 8)), - static_cast((i / registers_per_row) * row_height) - }; - - const auto value = device.read_register(i); - - const auto text = to_string_hex(value, value_length); + const auto text = to_string_hex(value, config.value_length); painter.draw_string( screen_pos() + offset, style(), diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 68871b3cf..3b7624d66 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -79,112 +79,100 @@ private: }; }; -class DebugRFFC5072RegistersWidget : public Widget { +struct RegistersWidgetConfig { + const char* const name; + size_t registers_count; + size_t legend_length; + size_t value_length; + size_t registers_per_row; + + constexpr Dim legend_width() const { + return legend_length * 8; + } + + constexpr Dim value_width() const { + return value_length * 8; + } + + constexpr size_t registers_row_length() const { + return (registers_per_row * (value_length + 1)) - 1; + } + + constexpr Dim registers_row_width() const { + return registers_row_length() * 8; + } + + constexpr size_t rows() const { + return registers_count / registers_per_row; + } +}; + +class RegistersWidget : public Widget { +public: + constexpr RegistersWidget( + Rect parent_rect, + const RegistersWidgetConfig& config + ) : Widget { parent_rect }, + config(config) + { + } + + std::string name() const { + return config.name; + } + + virtual uint32_t read(const size_t register_number) = 0; + + void update(); + + void paint(Painter& painter) override; + +private: + const RegistersWidgetConfig config; + + static constexpr Dim row_height = 16; + + void draw_legend(Painter& painter); + void draw_values(Painter& painter); +}; + +class DebugRFFC5072RegistersWidget : public RegistersWidget { public: constexpr DebugRFFC5072RegistersWidget( Rect parent_rect - ) : Widget { parent_rect } + ) : RegistersWidget { parent_rect, { "RFFC5072", 31, 2, 4, 4 } } { } - void update(); - - void paint(Painter& painter) override; - - static constexpr const char* name = "RFFC5072"; - -private: - static constexpr size_t registers_count { 31 }; - - static constexpr size_t legend_length { 2 }; - static constexpr Dim legend_width { legend_length * 8 }; - - static constexpr size_t value_length { 4 }; - static constexpr Dim value_width { value_length * 8 }; - - static constexpr size_t registers_per_row { 4 }; - static constexpr size_t registers_row_length { - (registers_per_row * (value_length + 1)) - 1 - }; - static constexpr Dim registers_row_width { - registers_row_length * 8 - }; - - static constexpr size_t rows { - registers_count / registers_per_row - }; - static constexpr Dim row_height { 16 }; - - void draw_legend(Painter& painter); - void draw_values(Painter& painter, const rffc507x::RegisterMap registers); + uint32_t read(const size_t register_number) override { + return radio::first_if.read(register_number); + } }; -class DebugMAX2837RegistersWidget : public Widget { +class DebugMAX2837RegistersWidget : public RegistersWidget { public: constexpr DebugMAX2837RegistersWidget( Rect parent_rect - ) : Widget { parent_rect } + ) : RegistersWidget { parent_rect, { "MAX2837", 32, 2, 3, 4 } } { } - void update(); - - void paint(Painter& painter) override; - - static constexpr const char* const name = "MAX2837"; - -private: - static constexpr size_t registers_count = 32; - - static constexpr size_t legend_length = 2; - static constexpr Dim legend_width = legend_length * 8; - - static constexpr size_t value_length = 3; - static constexpr Dim value_width = value_length * 8; - - static constexpr size_t registers_per_row = 4; - static constexpr size_t registers_row_length = (registers_per_row * (value_length + 1)) - 1; - static constexpr Dim registers_row_width = registers_row_length * 8; - - static constexpr size_t rows = registers_count / registers_per_row; - static constexpr Dim row_height = 16; - - void draw_legend(Painter& painter); - void draw_values(Painter& painter, const max2837::RegisterMap registers); + uint32_t read(const size_t register_number) override { + return radio::second_if.read(register_number); + } }; -class DebugSi5351CRegistersWidget : public Widget { +class DebugSi5351CRegistersWidget : public RegistersWidget { public: constexpr DebugSi5351CRegistersWidget( Rect parent_rect - ) : Widget { parent_rect } + ) : RegistersWidget { parent_rect, { "Si5351C", 96, 2, 2, 8 } } { } - void update(); - - void paint(Painter& painter) override; - - static constexpr const char* const name = "Si5351C"; - -private: - static constexpr size_t registers_count = 96; - - static constexpr size_t legend_length = 2; - static constexpr Dim legend_width = legend_length * 8; - - static constexpr size_t value_length = 2; - static constexpr Dim value_width = value_length * 8; - - static constexpr size_t registers_per_row = 8; - static constexpr size_t registers_row_length = (registers_per_row * (value_length + 1)) - 1; - static constexpr Dim registers_row_width = registers_row_length * 8; - - static constexpr size_t rows = registers_count / registers_per_row; - static constexpr Dim row_height = 16; - - void draw_legend(Painter& painter); - void draw_values(Painter& painter, si5351::Si5351& device); + uint32_t read(const size_t register_number) override { + return portapack::clock_generator.read_register(register_number); + } }; template @@ -202,6 +190,13 @@ public: this->widget_registers.update(); }; button_done.on_select = [&nav](Button&){ nav.pop(); }; + + const auto title = widget_registers.name(); + text_title.set_parent_rect({ + static_cast((240 - title.size() * 8) / 2), 16, + static_cast(title.size() * 8), 16 + }); + text_title.set(title); } void focus() { @@ -209,10 +204,7 @@ public: } private: - Text text_title { - { 88, 16, 64, 16 }, - RegistersWidget::name, - }; + Text text_title; RegistersWidget widget_registers { { 0, 48, 240, 192 } From a1aa6ecdbf0497a847fd801a5af65096b0e6c465 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 13 Dec 2015 21:28:39 -0800 Subject: [PATCH 135/452] Eliminate per-device Views and RegisterWidgets, virtual methods. Nice code size improvement, despite supporting three device register sets instead of just one. --- firmware/application/ui_debug.cpp | 17 +++++-- firmware/application/ui_debug.hpp | 85 ++++++++----------------------- 2 files changed, 35 insertions(+), 67 deletions(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 4c35b489d..a07bea91c 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -93,7 +93,7 @@ void RegistersWidget::draw_values( static_cast((i / config.registers_per_row) * row_height) }; - const auto value = read(i); + const auto value = reader(i); const auto text = to_string_hex(value, config.value_length); painter.draw_string( @@ -111,9 +111,18 @@ DebugMenuView::DebugMenuView(NavigationView& nav) { { "Memory", [&nav](){ nav.push(new DebugMemoryView { nav }); } }, { "Radio State", [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "SD Card", [&nav](){ nav.push(new NotImplementedView { nav }); } }, - { "RFFC5072", [&nav](){ nav.push(new DebugRFFC5072View { nav }); } }, - { "MAX2837", [&nav](){ nav.push(new DebugMAX2837View { nav }); } }, - { "Si5351C", [&nav](){ nav.push(new DebugSi5351CView { nav }); } }, + { "RFFC5072", [&nav](){ nav.push(new RegistersView { + nav, "RFFC5072", { 31, 2, 4, 4 }, + [](const size_t register_number) { return radio::first_if.read(register_number); } + }); } }, + { "MAX2837", [&nav](){ nav.push(new RegistersView { + nav, "MAX2837", { 32, 2, 3, 4 }, + [](const size_t register_number) { return radio::second_if.read(register_number); } + }); } }, + { "Si5351C", [&nav](){ nav.push(new RegistersView { + nav, "Si5351C", { 96, 2, 2, 8 }, + [](const size_t register_number) { return portapack::clock_generator.read_register(register_number); } + }); } }, { "WM8731", [&nav](){ nav.push(new NotImplementedView { nav }); } }, } }); on_left = [&nav](){ nav.pop(); }; diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 3b7624d66..420f3162a 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -32,6 +32,9 @@ #include "max2837.hpp" #include "portapack.hpp" +#include +#include + namespace ui { class DebugMemoryView : public View { @@ -80,7 +83,6 @@ private: }; struct RegistersWidgetConfig { - const char* const name; size_t registers_count; size_t legend_length; size_t value_length; @@ -109,26 +111,22 @@ struct RegistersWidgetConfig { class RegistersWidget : public Widget { public: - constexpr RegistersWidget( - Rect parent_rect, - const RegistersWidgetConfig& config - ) : Widget { parent_rect }, - config(config) + RegistersWidget( + RegistersWidgetConfig&& config, + std::function&& reader + ) : Widget { }, + config(std::move(config)), + reader(std::move(reader)) { } - std::string name() const { - return config.name; - } - - virtual uint32_t read(const size_t register_number) = 0; - void update(); void paint(Painter& painter) override; private: const RegistersWidgetConfig config; + const std::function reader; static constexpr Dim row_height = 16; @@ -136,62 +134,29 @@ private: void draw_values(Painter& painter); }; -class DebugRFFC5072RegistersWidget : public RegistersWidget { -public: - constexpr DebugRFFC5072RegistersWidget( - Rect parent_rect - ) : RegistersWidget { parent_rect, { "RFFC5072", 31, 2, 4, 4 } } - { - } - - uint32_t read(const size_t register_number) override { - return radio::first_if.read(register_number); - } -}; - -class DebugMAX2837RegistersWidget : public RegistersWidget { -public: - constexpr DebugMAX2837RegistersWidget( - Rect parent_rect - ) : RegistersWidget { parent_rect, { "MAX2837", 32, 2, 3, 4 } } - { - } - - uint32_t read(const size_t register_number) override { - return radio::second_if.read(register_number); - } -}; - -class DebugSi5351CRegistersWidget : public RegistersWidget { -public: - constexpr DebugSi5351CRegistersWidget( - Rect parent_rect - ) : RegistersWidget { parent_rect, { "Si5351C", 96, 2, 2, 8 } } - { - } - - uint32_t read(const size_t register_number) override { - return portapack::clock_generator.read_register(register_number); - } -}; - -template class RegistersView : public View { public: - RegistersView(NavigationView& nav) { + RegistersView( + NavigationView& nav, + const std::string& title, + RegistersWidgetConfig&& config, + std::function&& reader + ) : registers_widget { std::move(config), std::move(reader) } + { add_children({ { &text_title, - &widget_registers, + ®isters_widget, &button_update, &button_done, } }); button_update.on_select = [this](Button&){ - this->widget_registers.update(); + this->registers_widget.update(); }; button_done.on_select = [&nav](Button&){ nav.pop(); }; - const auto title = widget_registers.name(); + registers_widget.set_parent_rect({ 0, 48, 240, 192 }); + text_title.set_parent_rect({ static_cast((240 - title.size() * 8) / 2), 16, static_cast(title.size() * 8), 16 @@ -206,9 +171,7 @@ public: private: Text text_title; - RegistersWidget widget_registers { - { 0, 48, 240, 192 } - }; + RegistersWidget registers_widget; Button button_update { { 16, 256, 96, 24 }, @@ -221,10 +184,6 @@ private: }; }; -using DebugRFFC5072View = RegistersView; -using DebugMAX2837View = RegistersView; -using DebugSi5351CView = RegistersView; - class DebugMenuView : public MenuView { public: DebugMenuView(NavigationView& nav); From 97f29f83365194e870c9c53edc3617f4adecc4c6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 10:22:42 -0800 Subject: [PATCH 136/452] Clean up UI navigation push constructor scheme. --- firmware/application/ui_debug.cpp | 26 +++++++++++++------------- firmware/application/ui_navigation.cpp | 18 +++++++++--------- firmware/application/ui_navigation.hpp | 11 ++++++++++- firmware/application/ui_receiver.cpp | 3 +-- firmware/application/ui_setup.cpp | 6 +++--- 5 files changed, 36 insertions(+), 28 deletions(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index a07bea91c..154208541 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -108,22 +108,22 @@ void RegistersWidget::draw_values( DebugMenuView::DebugMenuView(NavigationView& nav) { add_items<7>({ { - { "Memory", [&nav](){ nav.push(new DebugMemoryView { nav }); } }, - { "Radio State", [&nav](){ nav.push(new NotImplementedView { nav }); } }, - { "SD Card", [&nav](){ nav.push(new NotImplementedView { nav }); } }, - { "RFFC5072", [&nav](){ nav.push(new RegistersView { - nav, "RFFC5072", { 31, 2, 4, 4 }, + { "Memory", [&nav](){ nav.push(nav); } }, + { "Radio State", [&nav](){ nav.push(nav); } }, + { "SD Card", [&nav](){ nav.push(nav); } }, + { "RFFC5072", [&nav](){ nav.push( + nav, "RFFC5072", RegistersWidgetConfig { 31, 2, 4, 4 }, [](const size_t register_number) { return radio::first_if.read(register_number); } - }); } }, - { "MAX2837", [&nav](){ nav.push(new RegistersView { - nav, "MAX2837", { 32, 2, 3, 4 }, + ); } }, + { "MAX2837", [&nav](){ nav.push( + nav, "MAX2837", RegistersWidgetConfig { 32, 2, 3, 4 }, [](const size_t register_number) { return radio::second_if.read(register_number); } - }); } }, - { "Si5351C", [&nav](){ nav.push(new RegistersView { - nav, "Si5351C", { 96, 2, 2, 8 }, + ); } }, + { "Si5351C", [&nav](){ nav.push( + nav, "Si5351C", RegistersWidgetConfig { 96, 2, 2, 8 }, [](const size_t register_number) { return portapack::clock_generator.read_register(register_number); } - }); } }, - { "WM8731", [&nav](){ nav.push(new NotImplementedView { nav }); } }, + ); } }, + { "WM8731", [&nav](){ nav.push(nav); } }, } }); on_left = [&nav](){ nav.pop(); }; } diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index f603c3cc0..afa1bc731 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -48,7 +48,7 @@ NavigationView::NavigationView() { } -void NavigationView::push(View* new_view) { +void NavigationView::push_view(View* new_view) { // TODO: Trap nullptr? // TODO: Trap push of object already on stack? view_stack.push_back(new_view); @@ -96,13 +96,13 @@ void NavigationView::focus() { SystemMenuView::SystemMenuView(NavigationView& nav) { add_items<7>({ { - { "Receiver", [&nav](){ nav.push(new ReceiverView { nav, portapack::receiver_model }); } }, - { "Capture", [&nav](){ nav.push(new NotImplementedView { nav }); } }, - { "Analyze", [&nav](){ nav.push(new NotImplementedView { nav }); } }, - { "Setup", [&nav](){ nav.push(new SetupMenuView { nav }); } }, - { "About", [&nav](){ nav.push(new AboutView { nav }); } }, - { "Debug", [&nav](){ nav.push(new DebugMenuView { nav }); } }, - { "HackRF", [&nav](){ nav.push(new HackRFFirmwareView { nav }); } }, + { "Receiver", [&nav](){ nav.push(nav, portapack::receiver_model); } }, + { "Capture", [&nav](){ nav.push(nav); } }, + { "Analyze", [&nav](){ nav.push(nav); } }, + { "Setup", [&nav](){ nav.push(nav); } }, + { "About", [&nav](){ nav.push(nav); } }, + { "Debug", [&nav](){ nav.push(nav); } }, + { "HackRF", [&nav](){ nav.push(nav); } }, } }); } @@ -138,7 +138,7 @@ SystemView::SystemView( // Initial view. // TODO: Restore from non-volatile memory? - navigation_view.push(new SystemMenuView { navigation_view }); + navigation_view.push(navigation_view); } Context& SystemView::context() const { diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 7307aed92..0e12438e5 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -33,6 +33,7 @@ #include "ui_sd_card_status_view.hpp" #include +#include namespace ui { @@ -56,7 +57,13 @@ public: NavigationView(const NavigationView&) = delete; NavigationView(NavigationView&&) = delete; - void push(View* new_view); + template + T* push(Args&&... args) { + const auto new_view = new T(std::forward(args)...); + push_view(new_view); + return reinterpret_cast(new_view); + } + void pop(); void focus() override; @@ -66,6 +73,8 @@ private: Widget* view() const; void set_view(Widget* const new_view); + + void push_view(View* new_view); }; class SystemMenuView : public MenuView { diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index d540b2103..176dee47b 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -423,12 +423,11 @@ ReceiverView::ReceiverView( }; field_frequency.on_edit = [this, &nav]() { // TODO: Provide separate modal method/scheme? - auto new_view = new FrequencyKeypadView { nav, this->receiver_model.tuning_frequency() }; + auto new_view = nav.push(nav, this->receiver_model.tuning_frequency()); new_view->on_changed = [this](rf::Frequency f) { this->on_tuning_frequency_changed(f); this->field_frequency.set_value(f); }; - nav.push(new_view); }; field_frequency.on_show_options = [this]() { this->on_show_options_frequency(); diff --git a/firmware/application/ui_setup.cpp b/firmware/application/ui_setup.cpp index 178bac1a5..e7a93f982 100644 --- a/firmware/application/ui_setup.cpp +++ b/firmware/application/ui_setup.cpp @@ -159,9 +159,9 @@ void AboutView::focus() { SetupMenuView::SetupMenuView(NavigationView& nav) { add_items<3>({ { - { "Date/Time", [&nav](){ nav.push(new SetDateTimeView { nav }); } }, - { "Frequency Correction", [&nav](){ nav.push(new SetFrequencyCorrectionView { nav }); } }, - { "Touch", [&nav](){ nav.push(new NotImplementedView { nav }); } }, + { "Date/Time", [&nav](){ nav.push(nav); } }, + { "Frequency Correction", [&nav](){ nav.push(nav); } }, + { "Touch", [&nav](){ nav.push(nav); } }, } }); on_left = [&nav](){ nav.pop(); }; } From 18c4672ba26b38c94a04027283fabfbed2c0ebeb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 10:52:08 -0800 Subject: [PATCH 137/452] Clean up navigation stack alloc/delete sequence. --- firmware/application/ui_navigation.cpp | 44 ++++++++++++-------------- firmware/application/ui_navigation.hpp | 3 +- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index afa1bc731..3f6a0a380 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -49,43 +49,41 @@ NavigationView::NavigationView() } void NavigationView::push_view(View* new_view) { - // TODO: Trap nullptr? - // TODO: Trap push of object already on stack? + free_view(); + view_stack.push_back(new_view); - set_view(new_view); + + update_view(); } void NavigationView::pop() { // Can't pop last item from stack. if( view_stack.size() > 1 ) { - const auto old_view = view_stack.back(); + free_view(); + + delete view_stack.back(); view_stack.pop_back(); - const auto new_view = view_stack.back(); - set_view(new_view); - delete old_view; + + update_view(); } } +void NavigationView::free_view() { + remove_child(view()); +} + +void NavigationView::update_view() { + const auto new_view = view_stack.back(); + add_child(new_view); + new_view->set_parent_rect({ {0, 0}, size() }); + focus(); + set_dirty(); +} + Widget* NavigationView::view() const { return children_.empty() ? nullptr : children_[0]; } -void NavigationView::set_view(Widget* const new_view) { - const auto old_view = view(); - if( old_view ) { - remove_child(old_view); - } - - // TODO: Allow new_view == nullptr?! - if( new_view ) { - add_child(new_view); - new_view->set_parent_rect({ {0, 0}, size() }); - focus(); - } - - set_dirty(); -} - void NavigationView::focus() { if( view() ) { view()->focus(); diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 0e12438e5..4d4cd2adf 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -72,8 +72,9 @@ private: std::vector view_stack; Widget* view() const; - void set_view(Widget* const new_view); + void free_view(); + void update_view(); void push_view(View* new_view); }; From 969d9bd0709787f57fcca5232964ef6d9265c066 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 11:11:49 -0800 Subject: [PATCH 138/452] Use std::unique_ptr inside NavigationView. --- firmware/application/ui_navigation.cpp | 10 ++++++---- firmware/application/ui_navigation.hpp | 8 +++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 3f6a0a380..d988792aa 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -48,12 +48,15 @@ NavigationView::NavigationView() { } -void NavigationView::push_view(View* new_view) { +View* NavigationView::push_view(std::unique_ptr new_view) { free_view(); - view_stack.push_back(new_view); + const auto p = new_view.get(); + view_stack.emplace_back(std::move(new_view)); update_view(); + + return p; } void NavigationView::pop() { @@ -61,7 +64,6 @@ void NavigationView::pop() { if( view_stack.size() > 1 ) { free_view(); - delete view_stack.back(); view_stack.pop_back(); update_view(); @@ -73,7 +75,7 @@ void NavigationView::free_view() { } void NavigationView::update_view() { - const auto new_view = view_stack.back(); + const auto new_view = view_stack.back().get(); add_child(new_view); new_view->set_parent_rect({ {0, 0}, size() }); focus(); diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 4d4cd2adf..a43a83446 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -59,9 +59,7 @@ public: template T* push(Args&&... args) { - const auto new_view = new T(std::forward(args)...); - push_view(new_view); - return reinterpret_cast(new_view); + return reinterpret_cast(push_view(std::unique_ptr(new T(std::forward(args)...)))); } void pop(); @@ -69,13 +67,13 @@ public: void focus() override; private: - std::vector view_stack; + std::vector> view_stack; Widget* view() const; void free_view(); void update_view(); - void push_view(View* new_view); + View* push_view(std::unique_ptr new_view); }; class SystemMenuView : public MenuView { From 0828c66b8a85350427d8c94a9cbdcf11695f3cdc Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 11:12:12 -0800 Subject: [PATCH 139/452] Move default constructor to .hpp. --- firmware/application/ui_navigation.cpp | 4 ---- firmware/application/ui_navigation.hpp | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index d988792aa..335b835b0 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -44,10 +44,6 @@ SystemStatusView::SystemStatusView() { /* Navigation ************************************************************/ -NavigationView::NavigationView() -{ -} - View* NavigationView::push_view(std::unique_ptr new_view) { free_view(); diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index a43a83446..94bc9f319 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -52,7 +52,7 @@ private: class NavigationView : public View { public: - NavigationView(); + NavigationView() { } NavigationView(const NavigationView&) = delete; NavigationView(NavigationView&&) = delete; From a340cbb74bf25a6dc69e7a39615dde32bb534a0a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 11:18:59 -0800 Subject: [PATCH 140/452] Make NavigationView an implicit first argument to any instance pushed onto nav stack. --- firmware/application/ui_debug.cpp | 14 +++++++------- firmware/application/ui_navigation.cpp | 16 ++++++++-------- firmware/application/ui_navigation.hpp | 2 +- firmware/application/ui_receiver.cpp | 2 +- firmware/application/ui_setup.cpp | 6 +++--- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 154208541..5d9efd9ce 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -108,22 +108,22 @@ void RegistersWidget::draw_values( DebugMenuView::DebugMenuView(NavigationView& nav) { add_items<7>({ { - { "Memory", [&nav](){ nav.push(nav); } }, - { "Radio State", [&nav](){ nav.push(nav); } }, - { "SD Card", [&nav](){ nav.push(nav); } }, + { "Memory", [&nav](){ nav.push(); } }, + { "Radio State", [&nav](){ nav.push(); } }, + { "SD Card", [&nav](){ nav.push(); } }, { "RFFC5072", [&nav](){ nav.push( - nav, "RFFC5072", RegistersWidgetConfig { 31, 2, 4, 4 }, + "RFFC5072", RegistersWidgetConfig { 31, 2, 4, 4 }, [](const size_t register_number) { return radio::first_if.read(register_number); } ); } }, { "MAX2837", [&nav](){ nav.push( - nav, "MAX2837", RegistersWidgetConfig { 32, 2, 3, 4 }, + "MAX2837", RegistersWidgetConfig { 32, 2, 3, 4 }, [](const size_t register_number) { return radio::second_if.read(register_number); } ); } }, { "Si5351C", [&nav](){ nav.push( - nav, "Si5351C", RegistersWidgetConfig { 96, 2, 2, 8 }, + "Si5351C", RegistersWidgetConfig { 96, 2, 2, 8 }, [](const size_t register_number) { return portapack::clock_generator.read_register(register_number); } ); } }, - { "WM8731", [&nav](){ nav.push(nav); } }, + { "WM8731", [&nav](){ nav.push(); } }, } }); on_left = [&nav](){ nav.pop(); }; } diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 335b835b0..617bed0ec 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -92,13 +92,13 @@ void NavigationView::focus() { SystemMenuView::SystemMenuView(NavigationView& nav) { add_items<7>({ { - { "Receiver", [&nav](){ nav.push(nav, portapack::receiver_model); } }, - { "Capture", [&nav](){ nav.push(nav); } }, - { "Analyze", [&nav](){ nav.push(nav); } }, - { "Setup", [&nav](){ nav.push(nav); } }, - { "About", [&nav](){ nav.push(nav); } }, - { "Debug", [&nav](){ nav.push(nav); } }, - { "HackRF", [&nav](){ nav.push(nav); } }, + { "Receiver", [&nav](){ nav.push(portapack::receiver_model); } }, + { "Capture", [&nav](){ nav.push(); } }, + { "Analyze", [&nav](){ nav.push(); } }, + { "Setup", [&nav](){ nav.push(); } }, + { "About", [&nav](){ nav.push(); } }, + { "Debug", [&nav](){ nav.push(); } }, + { "HackRF", [&nav](){ nav.push(); } }, } }); } @@ -134,7 +134,7 @@ SystemView::SystemView( // Initial view. // TODO: Restore from non-volatile memory? - navigation_view.push(navigation_view); + navigation_view.push(); } Context& SystemView::context() const { diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 94bc9f319..273af6568 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -59,7 +59,7 @@ public: template T* push(Args&&... args) { - return reinterpret_cast(push_view(std::unique_ptr(new T(std::forward(args)...)))); + return reinterpret_cast(push_view(std::unique_ptr(new T(*this, std::forward(args)...)))); } void pop(); diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 176dee47b..a9264ea94 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -423,7 +423,7 @@ ReceiverView::ReceiverView( }; field_frequency.on_edit = [this, &nav]() { // TODO: Provide separate modal method/scheme? - auto new_view = nav.push(nav, this->receiver_model.tuning_frequency()); + auto new_view = nav.push(this->receiver_model.tuning_frequency()); new_view->on_changed = [this](rf::Frequency f) { this->on_tuning_frequency_changed(f); this->field_frequency.set_value(f); diff --git a/firmware/application/ui_setup.cpp b/firmware/application/ui_setup.cpp index e7a93f982..b61c87cbc 100644 --- a/firmware/application/ui_setup.cpp +++ b/firmware/application/ui_setup.cpp @@ -159,9 +159,9 @@ void AboutView::focus() { SetupMenuView::SetupMenuView(NavigationView& nav) { add_items<3>({ { - { "Date/Time", [&nav](){ nav.push(nav); } }, - { "Frequency Correction", [&nav](){ nav.push(nav); } }, - { "Touch", [&nav](){ nav.push(nav); } }, + { "Date/Time", [&nav](){ nav.push(); } }, + { "Frequency Correction", [&nav](){ nav.push(); } }, + { "Touch", [&nav](){ nav.push(); } }, } }); on_left = [&nav](){ nav.pop(); }; } From 2ee072aa7bc194b869cab77ad10c10f732fe02db Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 11:24:48 -0800 Subject: [PATCH 141/452] Invert register number column colors in RegistersWidget. --- firmware/application/ui_debug.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 5d9efd9ce..c18f59090 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -78,7 +78,7 @@ void RegistersWidget::draw_legend(Painter& painter) { const auto text = to_string_hex(i, config.legend_length); painter.draw_string( screen_pos() + offset, - style(), + style().invert(), text ); } From 56c316715639aa6276df004b819355ea6bf3757a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 11:30:24 -0800 Subject: [PATCH 142/452] Move RegistersWidget/Views methods to .cpp. --- firmware/application/ui_debug.cpp | 43 +++++++++++++++++++++++++++++++ firmware/application/ui_debug.hpp | 33 +++--------------------- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index c18f59090..0fd4b55f5 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -59,6 +59,15 @@ void DebugMemoryView::focus() { /* RegistersWidget *******************************************************/ +RegistersWidget::RegistersWidget( + RegistersWidgetConfig&& config, + std::function&& reader +) : Widget { }, + config(std::move(config)), + reader(std::move(reader)) +{ +} + void RegistersWidget::update() { set_dirty(); } @@ -104,6 +113,40 @@ void RegistersWidget::draw_values( } } +/* RegistersView *********************************************************/ + +RegistersView::RegistersView( + NavigationView& nav, + const std::string& title, + RegistersWidgetConfig&& config, + std::function&& reader +) : registers_widget { std::move(config), std::move(reader) } +{ + add_children({ { + &text_title, + ®isters_widget, + &button_update, + &button_done, + } }); + + button_update.on_select = [this](Button&){ + this->registers_widget.update(); + }; + button_done.on_select = [&nav](Button&){ nav.pop(); }; + + registers_widget.set_parent_rect({ 0, 48, 240, 192 }); + + text_title.set_parent_rect({ + static_cast((240 - title.size() * 8) / 2), 16, + static_cast(title.size() * 8), 16 + }); + text_title.set(title); +} + +void RegistersView::focus() { + button_done.focus(); +} + /* DebugMenuView *********************************************************/ DebugMenuView::DebugMenuView(NavigationView& nav) { diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 420f3162a..46920c9ef 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -114,11 +114,7 @@ public: RegistersWidget( RegistersWidgetConfig&& config, std::function&& reader - ) : Widget { }, - config(std::move(config)), - reader(std::move(reader)) - { - } + ); void update(); @@ -141,32 +137,9 @@ public: const std::string& title, RegistersWidgetConfig&& config, std::function&& reader - ) : registers_widget { std::move(config), std::move(reader) } - { - add_children({ { - &text_title, - ®isters_widget, - &button_update, - &button_done, - } }); + ); - button_update.on_select = [this](Button&){ - this->registers_widget.update(); - }; - button_done.on_select = [&nav](Button&){ nav.pop(); }; - - registers_widget.set_parent_rect({ 0, 48, 240, 192 }); - - text_title.set_parent_rect({ - static_cast((240 - title.size() * 8) / 2), 16, - static_cast(title.size() * 8), 16 - }); - text_title.set(title); - } - - void focus() { - button_done.focus(); - } + void focus(); private: Text text_title; From ee3a77f32cb306ede15e559acd3aba4fd0ef3deb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 11:47:43 -0800 Subject: [PATCH 143/452] Center RegistersWidget painting. --- firmware/application/ui_debug.cpp | 12 +++++++----- firmware/application/ui_debug.hpp | 8 ++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 0fd4b55f5..a3469405b 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -73,15 +73,16 @@ void RegistersWidget::update() { } void RegistersWidget::paint(Painter& painter) { - draw_legend(painter); + const Coord left = (size().w - config.row_width()) / 2; - draw_values(painter); + draw_legend(left, painter); + draw_values(left, painter); } -void RegistersWidget::draw_legend(Painter& painter) { +void RegistersWidget::draw_legend(const Coord left, Painter& painter) { for(size_t i=0; i((i / config.registers_per_row) * row_height) + left, static_cast((i / config.registers_per_row) * row_height) }; const auto text = to_string_hex(i, config.legend_length); @@ -94,11 +95,12 @@ void RegistersWidget::draw_legend(Painter& painter) { } void RegistersWidget::draw_values( + const Coord left, Painter& painter ) { for(size_t i=0; i(config.legend_width() + 8 + (i % config.registers_per_row) * (config.value_width() + 8)), + static_cast(left + config.legend_width() + 8 + (i % config.registers_per_row) * (config.value_width() + 8)), static_cast((i / config.registers_per_row) * row_height) }; diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 46920c9ef..6ed9b4e9f 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -104,6 +104,10 @@ struct RegistersWidgetConfig { return registers_row_length() * 8; } + constexpr Dim row_width() const { + return legend_width() + 8 + registers_row_width(); + } + constexpr size_t rows() const { return registers_count / registers_per_row; } @@ -126,8 +130,8 @@ private: static constexpr Dim row_height = 16; - void draw_legend(Painter& painter); - void draw_values(Painter& painter); + void draw_legend(const Coord left, Painter& painter); + void draw_values(const Coord left, Painter& painter); }; class RegistersView : public View { From 24d60a11e34203f7b1c2f0634735216a50b2e3c0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 12:09:01 -0800 Subject: [PATCH 144/452] Add WM8731.read() for cached values. --- firmware/common/wm8731.cpp | 4 ++++ firmware/common/wm8731.hpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/firmware/common/wm8731.cpp b/firmware/common/wm8731.cpp index 6ecd06651..15e7e6daf 100644 --- a/firmware/common/wm8731.cpp +++ b/firmware/common/wm8731.cpp @@ -36,5 +36,9 @@ void WM8731::write(const address_t reg_address, const reg_t value) { bus.transmit(bus_address, values.data(), values.size()); } +reg_t WM8731::read(const address_t reg_address) { + return map.w[reg_address]; +} + } /* namespace wm8731 */ } /* namespace wolfson */ diff --git a/firmware/common/wm8731.hpp b/firmware/common/wm8731.hpp index 4a0e1f984..ab0833902 100644 --- a/firmware/common/wm8731.hpp +++ b/firmware/common/wm8731.hpp @@ -394,6 +394,8 @@ public: // write(Register::AnalogAudioPathControl); // } + reg_t read(const address_t reg_address); + private: I2C& bus; const I2C::address_t bus_address; From 4ce27f51d419b82e8af9281a254b10cd3ea2933c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 12:09:31 -0800 Subject: [PATCH 145/452] Add WM8731 registers view. --- firmware/application/ui_debug.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index a3469405b..7e955b03d 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -168,7 +168,10 @@ DebugMenuView::DebugMenuView(NavigationView& nav) { "Si5351C", RegistersWidgetConfig { 96, 2, 2, 8 }, [](const size_t register_number) { return portapack::clock_generator.read_register(register_number); } ); } }, - { "WM8731", [&nav](){ nav.push(); } }, + { "WM8731", [&nav](){ nav.push( + "WM8731", RegistersWidgetConfig { wolfson::wm8731::reg_count, 1, 3, 4 }, + [](const size_t register_number) { return portapack::audio_codec.read(register_number); } + ); } }, } }); on_left = [&nav](){ nav.pop(); }; } From fa3eaf082020b300fd0e46057828344f7d33877f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 12:26:41 -0800 Subject: [PATCH 146/452] Disable audio codec wait-for-zero-crossing volume change mode. This may explain (now unreproduceable) issue where UI volume changes weren't always changing the gain on the audio codec. --- firmware/common/wm8731.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/wm8731.hpp b/firmware/common/wm8731.hpp index ab0833902..88e9440a4 100644 --- a/firmware/common/wm8731.hpp +++ b/firmware/common/wm8731.hpp @@ -374,7 +374,7 @@ public: write(LeftHeadphoneOut { .lhpvol = static_cast(n), - .lzcen = 1, + .lzcen = 0, .lrhpboth = 1, .reserved0 = 0, }); From 552bba47ea15182d0315f4a5718506ddae7f29de Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 13:57:45 -0800 Subject: [PATCH 147/452] Move a lot of WM8731 functions to .cpp. --- firmware/common/wm8731.cpp | 120 +++++++++++++++++++++++++++++++++ firmware/common/wm8731.hpp | 131 ++++--------------------------------- 2 files changed, 134 insertions(+), 117 deletions(-) diff --git a/firmware/common/wm8731.cpp b/firmware/common/wm8731.cpp index 15e7e6daf..85ba55334 100644 --- a/firmware/common/wm8731.cpp +++ b/firmware/common/wm8731.cpp @@ -27,6 +27,76 @@ namespace wolfson { namespace wm8731 { +void WM8731::init() { + reset(); + + write(PowerDownControl { + .lineinpd = 1, + .micpd = 0, + .adcpd = 0, + .dacpd = 0, + .outpd = 0, + .oscpd = 1, + .clkoutpd = 1, + .poweroff = 0, + .reserved0 = 0, + }); + + // write(SamplingControl { + // .usb_normal = 0, + // .bosr = 0, + // .sr = 0, + // .clkidiv2 = 0, + // .clkodiv2 = 0, + // .reserved0 = 0, + // }); + + write(DigitalAudioInterfaceFormat { + .format = 2, + .iwl = 0, + .lrp = 0, + .lrswap = 0, + .ms = 0, + .bclkinv = 0, + .reserved0 = 0, + }); + + write(DigitalAudioPathControl { + .adchpd = 0, + .deemp = 0, + .dacmu = 0, + .hpor = 0, + .reserved0 = 0, + }); + + write(AnalogAudioPathControl { + .micboost = 1, // Enable 20dB boost + .mutemic = 0, // Disable mute (unmute) + .insel = 1, // Microphone input to ADC + .bypass = 0, + .dacsel = 1, + .sidetone = 0, + .sideatt = 0, + .reserved0 = 0, + }); + + write(ActiveControl { + .active = 1, + .reserved0 = 0, + }); + + set_line_in_volume(0.0_dB); + headphone_mute(); +} + +void WM8731::reset() { + write(0x0f, 0); +} + +void WM8731::write(const Register reg) { + write(toUType(reg), map.w[toUType(reg)]); +} + void WM8731::write(const address_t reg_address, const reg_t value) { const uint16_t word = (reg_address << 9) | value; const std::array values { @@ -40,5 +110,55 @@ reg_t WM8731::read(const address_t reg_address) { return map.w[reg_address]; } +void WM8731::write(const LeftLineIn value) { + map.r.left_line_in = value; + write(Register::LeftLineIn); +} + +void WM8731::write(const RightLineIn value) { + map.r.right_line_in = value; + write(Register::RightLineIn); +} + +void WM8731::write(const LeftHeadphoneOut value) { + map.r.left_headphone_out = value; + write(Register::LeftHeadphoneOut); +} + +void WM8731::write(const RightHeadphoneOut value) { + map.r.right_headphone_out = value; + write(Register::RightHeadphoneOut); +} + +void WM8731::write(const AnalogAudioPathControl value) { + map.r.analog_audio_path_control = value; + write(Register::AnalogAudioPathControl); +} + +void WM8731::write(const DigitalAudioPathControl value) { + map.r.digital_audio_path_control = value; + write(Register::DigitalAudioPathControl); +} + +void WM8731::write(const PowerDownControl value) { + map.r.power_down_control = value; + write(Register::PowerDownControl); +} + +void WM8731::write(const DigitalAudioInterfaceFormat value) { + map.r.digital_audio_interface_format = value; + write(Register::DigitalAudioInterfaceFormat); +} + +void WM8731::write(const SamplingControl value) { + map.r.sampling_control = value; + write(Register::SamplingControl); +} + +void WM8731::write(const ActiveControl value) { + map.r.active_control = value; + write(Register::ActiveControl); +} + } /* namespace wm8731 */ } /* namespace wolfson */ diff --git a/firmware/common/wm8731.hpp b/firmware/common/wm8731.hpp index 88e9440a4..6a1fa05e3 100644 --- a/firmware/common/wm8731.hpp +++ b/firmware/common/wm8731.hpp @@ -289,71 +289,9 @@ public: { } - void init() { - reset(); + void init(); - write(PowerDownControl { - .lineinpd = 1, - .micpd = 0, - .adcpd = 0, - .dacpd = 0, - .outpd = 0, - .oscpd = 1, - .clkoutpd = 1, - .poweroff = 0, - .reserved0 = 0, - }); - - // write(SamplingControl { - // .usb_normal = 0, - // .bosr = 0, - // .sr = 0, - // .clkidiv2 = 0, - // .clkodiv2 = 0, - // .reserved0 = 0, - // }); - - write(DigitalAudioInterfaceFormat { - .format = 2, - .iwl = 0, - .lrp = 0, - .lrswap = 0, - .ms = 0, - .bclkinv = 0, - .reserved0 = 0, - }); - - write(DigitalAudioPathControl { - .adchpd = 0, - .deemp = 0, - .dacmu = 0, - .hpor = 0, - .reserved0 = 0, - }); - - write(AnalogAudioPathControl { - .micboost = 1, // Enable 20dB boost - .mutemic = 0, // Disable mute (unmute) - .insel = 1, // Microphone input to ADC - .bypass = 0, - .dacsel = 1, - .sidetone = 0, - .sideatt = 0, - .reserved0 = 0, - }); - - write(ActiveControl { - .active = 1, - .reserved0 = 0, - }); - - set_line_in_volume(0.0_dB); - headphone_mute(); - } - - void reset() { - write(0x0f, 0); - } + void reset(); void set_line_in_volume(const volume_t volume) { const auto normalized = line_in_gain_range.normalize(volume); @@ -401,61 +339,20 @@ private: const I2C::address_t bus_address; RegisterMap map { default_after_reset }; - void write(const Register reg) { - write(toUType(reg), map.w[toUType(reg)]); - } - + void write(const Register reg); + void write(const address_t reg_address, const reg_t value); - void write(const LeftLineIn value) { - map.r.left_line_in = value; - write(Register::LeftLineIn); - } - - void write(const RightLineIn value) { - map.r.right_line_in = value; - write(Register::RightLineIn); - } - - void write(const LeftHeadphoneOut value) { - map.r.left_headphone_out = value; - write(Register::LeftHeadphoneOut); - } - - void write(const RightHeadphoneOut value) { - map.r.right_headphone_out = value; - write(Register::RightHeadphoneOut); - } - - void write(const AnalogAudioPathControl value) { - map.r.analog_audio_path_control = value; - write(Register::AnalogAudioPathControl); - } - - void write(const DigitalAudioPathControl value) { - map.r.digital_audio_path_control = value; - write(Register::DigitalAudioPathControl); - } - - void write(const PowerDownControl value) { - map.r.power_down_control = value; - write(Register::PowerDownControl); - } - - void write(const DigitalAudioInterfaceFormat value) { - map.r.digital_audio_interface_format = value; - write(Register::DigitalAudioInterfaceFormat); - } - - void write(const SamplingControl value) { - map.r.sampling_control = value; - write(Register::SamplingControl); - } - - void write(const ActiveControl value) { - map.r.active_control = value; - write(Register::ActiveControl); - } + void write(const LeftLineIn value); + void write(const RightLineIn value); + void write(const LeftHeadphoneOut value); + void write(const RightHeadphoneOut value); + void write(const AnalogAudioPathControl value); + void write(const DigitalAudioPathControl value); + void write(const PowerDownControl value); + void write(const DigitalAudioInterfaceFormat value); + void write(const SamplingControl value); + void write(const ActiveControl value); }; } /* namespace wm8731 */ From f204a58d2463cbc9ba7f0bde713747ec8cb67f5f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 14 Dec 2015 14:03:17 -0800 Subject: [PATCH 148/452] WM8731 header clean-up. --- firmware/common/wm8731.cpp | 4 +--- firmware/common/wm8731.hpp | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/firmware/common/wm8731.cpp b/firmware/common/wm8731.cpp index 85ba55334..f5c454c36 100644 --- a/firmware/common/wm8731.cpp +++ b/firmware/common/wm8731.cpp @@ -19,10 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#include -#include - #include "wm8731.hpp" +#include "utility.hpp" namespace wolfson { namespace wm8731 { diff --git a/firmware/common/wm8731.hpp b/firmware/common/wm8731.hpp index 6a1fa05e3..a81e819cc 100644 --- a/firmware/common/wm8731.hpp +++ b/firmware/common/wm8731.hpp @@ -23,11 +23,10 @@ #define __WM8731_H__ #include +#include #include "i2c_pp.hpp" -#include "wm8731.hpp" -#include "utility.hpp" #include "volume.hpp" namespace wolfson { From 7a4604e24e08a6ba976dfff3230ff8e8f91c55e4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 16 Dec 2015 19:33:30 -0800 Subject: [PATCH 149/452] Move code out of ui_spectrum.hpp. --- firmware/application/ui_spectrum.cpp | 254 ++++++++++++++++++++++++++- firmware/application/ui_spectrum.hpp | 248 +++----------------------- 2 files changed, 273 insertions(+), 229 deletions(-) diff --git a/firmware/application/ui_spectrum.cpp b/firmware/application/ui_spectrum.cpp index b0a81b071..d450b4b62 100644 --- a/firmware/application/ui_spectrum.cpp +++ b/firmware/application/ui_spectrum.cpp @@ -21,6 +21,258 @@ #include "ui_spectrum.hpp" -namespace ui { +#include "spectrum_color_lut.hpp" +#include "portapack.hpp" +using namespace portapack; + +#include "string_format.hpp" + +#include +#include + +namespace ui { +namespace spectrum { + +/* FrequencyScale ********************************************************/ + +void FrequencyScale::on_show() { + clear(); +} + +void FrequencyScale::set_spectrum_sampling_rate(const uint32_t new_sampling_rate, const size_t new_spectrum_bins) { + if( (spectrum_sampling_rate != new_sampling_rate) || + (spectrum_bins != new_spectrum_bins) ) { + spectrum_sampling_rate = new_sampling_rate; + spectrum_bins = new_spectrum_bins; + set_dirty(); + } +} + +void FrequencyScale::set_channel_filter( + const uint32_t pass_frequency, + const uint32_t stop_frequency +) { + if( (channel_filter_pass_frequency != pass_frequency) || + (channel_filter_stop_frequency != stop_frequency) ) { + channel_filter_pass_frequency = pass_frequency; + channel_filter_stop_frequency = stop_frequency; + set_dirty(); + } +} + +void FrequencyScale::paint(Painter& painter) { + const auto r = screen_rect(); + + clear_background(painter, r); + + if( !spectrum_sampling_rate || !spectrum_bins ) { + // Can't draw without non-zero scale. + return; + } + + draw_filter_ranges(painter, r); + draw_frequency_ticks(painter, r); +} + +void FrequencyScale::clear() { + spectrum_sampling_rate = 0; + spectrum_bins = 0; + set_dirty(); +} + +void FrequencyScale::clear_background(Painter& painter, const Rect r) { + painter.fill_rectangle(r, Color::black()); +} + +void FrequencyScale::draw_frequency_ticks(Painter& painter, const Rect r) { + const auto x_center = r.width() / 2; + + const Rect tick { + static_cast(r.left() + x_center), r.top(), + 1, r.height() + }; + painter.fill_rectangle(tick, Color::white()); + + constexpr uint32_t tick_count_max = 4; + float rough_tick_interval = float(spectrum_sampling_rate) / tick_count_max; + size_t magnitude = 1; + size_t magnitude_n = 0; + while(rough_tick_interval >= 10.0f) { + rough_tick_interval /= 10; + magnitude *= 10; + magnitude_n += 1; + } + const size_t tick_interval = std::ceil(rough_tick_interval); + + size_t tick_offset = tick_interval; + while((tick_offset * magnitude) < spectrum_sampling_rate / 2) { + const Dim pixel_offset = tick_offset * magnitude * spectrum_bins / spectrum_sampling_rate; + + const std::string zero_pad = + ((magnitude_n % 3) == 0) ? "" : + ((magnitude_n % 3) == 1) ? "0" : "00"; + const std::string unit = + (magnitude_n >= 6) ? "M" : + (magnitude_n >= 3) ? "k" : ""; + const std::string label = to_string_dec_uint(tick_offset) + zero_pad + unit; + + const Coord offset_low = static_cast(r.left() + x_center - pixel_offset); + const Rect tick_low { offset_low, r.top(), 1, r.height() }; + painter.fill_rectangle(tick_low, Color::white()); + painter.draw_string({ static_cast(offset_low + 2), r.top() }, style(), label ); + + const Coord offset_high = static_cast(r.left() + x_center + pixel_offset); + const Rect tick_high { offset_high, r.top(), 1, r.height() }; + painter.fill_rectangle(tick_high, Color::white()); + painter.draw_string({ static_cast(offset_high + 2), r.top() }, style(), label ); + + tick_offset += tick_interval; + } +} + +void FrequencyScale::draw_filter_ranges(Painter& painter, const Rect r) { + if( channel_filter_pass_frequency ) { + const auto x_center = r.width() / 2; + + const auto pass_offset = channel_filter_pass_frequency * spectrum_bins / spectrum_sampling_rate; + const auto stop_offset = channel_filter_stop_frequency * spectrum_bins / spectrum_sampling_rate; + + const auto pass_x_lo = x_center - pass_offset; + const auto pass_x_hi = x_center + pass_offset; + + if( channel_filter_stop_frequency ) { + const auto stop_x_lo = x_center - stop_offset; + const auto stop_x_hi = x_center + stop_offset; + + const Rect r_stop_lo { + static_cast(r.left() + stop_x_lo), static_cast(r.bottom() - filter_band_height), + static_cast(pass_x_lo - stop_x_lo), filter_band_height + }; + painter.fill_rectangle( + r_stop_lo, + Color::yellow() + ); + + const Rect r_stop_hi { + static_cast(r.left() + pass_x_hi), static_cast(r.bottom() - filter_band_height), + static_cast(stop_x_hi - pass_x_hi), filter_band_height + }; + painter.fill_rectangle( + r_stop_hi, + Color::yellow() + ); + } + + const Rect r_pass { + static_cast(r.left() + pass_x_lo), static_cast(r.bottom() - filter_band_height), + static_cast(pass_x_hi - pass_x_lo), filter_band_height + }; + painter.fill_rectangle( + r_pass, + Color::green() + ); + } +} + +/* WaterfallView *********************************************************/ + +void WaterfallView::on_show() { + clear(); + + const auto screen_r = screen_rect(); + display.scroll_set_area(screen_r.top(), screen_r.bottom()); +} + +void WaterfallView::on_hide() { + /* TODO: Clear region to eliminate brief flash of content at un-shifted + * position? + */ + display.scroll_disable(); +} + +void WaterfallView::paint(Painter& painter) { + // Do nothing. + (void)painter; +} + +void WaterfallView::on_channel_spectrum( + const ChannelSpectrum& spectrum +) { + /* TODO: static_assert that message.spectrum.db.size() >= pixel_row.size() */ + + std::array pixel_row; + for(size_t i=0; i<120; i++) { + const auto pixel_color = spectrum_rgb3_lut[spectrum.db[256 - 120 + i]]; + pixel_row[i] = pixel_color; + } + + for(size_t i=120; i<240; i++) { + const auto pixel_color = spectrum_rgb3_lut[spectrum.db[i - 120]]; + pixel_row[i] = pixel_color; + } + + const auto draw_y = display.scroll(1); + + display.draw_pixels( + { { 0, draw_y }, { pixel_row.size(), 1 } }, + pixel_row + ); +} + +void WaterfallView::clear() { + display.fill_rectangle( + screen_rect(), + Color::black() + ); +} + +/* WaterfallWidget *******************************************************/ + +WaterfallWidget::WaterfallWidget() { + add_children({ + &waterfall_view, + &frequency_scale, + }); +} + +void WaterfallWidget::on_show() { + context().message_map().register_handler(Message::ID::ChannelSpectrum, + [this](const Message* const p) { + this->on_channel_spectrum(reinterpret_cast(p)->spectrum); + } + ); +} + +void WaterfallWidget::on_hide() { + context().message_map().unregister_handler(Message::ID::ChannelSpectrum); +} + +void WaterfallWidget::set_parent_rect(const Rect new_parent_rect) { + constexpr Dim scale_height = 20; + + View::set_parent_rect(new_parent_rect); + frequency_scale.set_parent_rect({ 0, 0, new_parent_rect.width(), scale_height }); + waterfall_view.set_parent_rect({ + 0, scale_height, + new_parent_rect.width(), + static_cast(new_parent_rect.height() - scale_height) + }); +} + +void WaterfallWidget::paint(Painter& painter) { + // TODO: + (void)painter; +} + +void WaterfallWidget::on_channel_spectrum(const ChannelSpectrum& spectrum) { + waterfall_view.on_channel_spectrum(spectrum); + frequency_scale.set_spectrum_sampling_rate(spectrum.sampling_rate, spectrum.db_count); + frequency_scale.set_channel_filter( + spectrum.channel_filter_pass_frequency, + spectrum.channel_filter_stop_frequency + ); +} + +} /* namespace spectrum */ } /* namespace ui */ diff --git a/firmware/application/ui_spectrum.hpp b/firmware/application/ui_spectrum.hpp index fe2fab913..21c4479e9 100644 --- a/firmware/application/ui_spectrum.hpp +++ b/firmware/application/ui_spectrum.hpp @@ -24,62 +24,23 @@ #include "ui.hpp" #include "ui_widget.hpp" -#include "spectrum_color_lut.hpp" - -#include "portapack.hpp" -using namespace portapack; #include "message.hpp" #include -#include -#include - -#include "string_format.hpp" +#include namespace ui { namespace spectrum { class FrequencyScale : public Widget { public: - void on_show() override { - clear(); - } + void on_show() override; - void set_spectrum_sampling_rate(const uint32_t new_sampling_rate, const size_t new_spectrum_bins) { - if( (spectrum_sampling_rate != new_sampling_rate) || - (spectrum_bins != new_spectrum_bins) ) { - spectrum_sampling_rate = new_sampling_rate; - spectrum_bins = new_spectrum_bins; - set_dirty(); - } - } + void set_spectrum_sampling_rate(const uint32_t new_sampling_rate, const size_t new_spectrum_bins); + void set_channel_filter(const uint32_t pass_frequency, const uint32_t stop_frequency); - void set_channel_filter( - const uint32_t pass_frequency, - const uint32_t stop_frequency - ) { - if( (channel_filter_pass_frequency != pass_frequency) || - (channel_filter_stop_frequency != stop_frequency) ) { - channel_filter_pass_frequency = pass_frequency; - channel_filter_stop_frequency = stop_frequency; - set_dirty(); - } - } - - void paint(Painter& painter) override { - const auto r = screen_rect(); - - clear_background(painter, r); - - if( !spectrum_sampling_rate || !spectrum_bins ) { - // Can't draw without non-zero scale. - return; - } - - draw_filter_ranges(painter, r); - draw_frequency_ticks(painter, r); - } + void paint(Painter& painter) override; private: static constexpr Dim filter_band_height = 4; @@ -89,211 +50,42 @@ private: uint32_t channel_filter_pass_frequency { 0 }; uint32_t channel_filter_stop_frequency { 0 }; - void clear() { - spectrum_sampling_rate = 0; - spectrum_bins = 0; - set_dirty(); - } + void clear(); + void clear_background(Painter& painter, const Rect r); - void clear_background(Painter& painter, const Rect r) { - painter.fill_rectangle(r, Color::black()); - } - - void draw_frequency_ticks(Painter& painter, const Rect r) { - const auto x_center = r.width() / 2; - - const Rect tick { - static_cast(r.left() + x_center), r.top(), - 1, r.height() - }; - painter.fill_rectangle(tick, Color::white()); - - constexpr uint32_t tick_count_max = 4; - float rough_tick_interval = float(spectrum_sampling_rate) / tick_count_max; - size_t magnitude = 1; - size_t magnitude_n = 0; - while(rough_tick_interval >= 10.0f) { - rough_tick_interval /= 10; - magnitude *= 10; - magnitude_n += 1; - } - const size_t tick_interval = std::ceil(rough_tick_interval); - - size_t tick_offset = tick_interval; - while((tick_offset * magnitude) < spectrum_sampling_rate / 2) { - const Dim pixel_offset = tick_offset * magnitude * spectrum_bins / spectrum_sampling_rate; - - const std::string zero_pad = - ((magnitude_n % 3) == 0) ? "" : - ((magnitude_n % 3) == 1) ? "0" : "00"; - const std::string unit = - (magnitude_n >= 6) ? "M" : - (magnitude_n >= 3) ? "k" : ""; - const std::string label = to_string_dec_uint(tick_offset) + zero_pad + unit; - - const Coord offset_low = static_cast(r.left() + x_center - pixel_offset); - const Rect tick_low { offset_low, r.top(), 1, r.height() }; - painter.fill_rectangle(tick_low, Color::white()); - painter.draw_string({ static_cast(offset_low + 2), r.top() }, style(), label ); - - const Coord offset_high = static_cast(r.left() + x_center + pixel_offset); - const Rect tick_high { offset_high, r.top(), 1, r.height() }; - painter.fill_rectangle(tick_high, Color::white()); - painter.draw_string({ static_cast(offset_high + 2), r.top() }, style(), label ); - - tick_offset += tick_interval; - } - } - - void draw_filter_ranges(Painter& painter, const Rect r) { - if( channel_filter_pass_frequency ) { - const auto x_center = r.width() / 2; - - const auto pass_offset = channel_filter_pass_frequency * spectrum_bins / spectrum_sampling_rate; - const auto stop_offset = channel_filter_stop_frequency * spectrum_bins / spectrum_sampling_rate; - - const auto pass_x_lo = x_center - pass_offset; - const auto pass_x_hi = x_center + pass_offset; - - if( channel_filter_stop_frequency ) { - const auto stop_x_lo = x_center - stop_offset; - const auto stop_x_hi = x_center + stop_offset; - - const Rect r_stop_lo { - static_cast(r.left() + stop_x_lo), static_cast(r.bottom() - filter_band_height), - static_cast(pass_x_lo - stop_x_lo), filter_band_height - }; - painter.fill_rectangle( - r_stop_lo, - Color::yellow() - ); - - const Rect r_stop_hi { - static_cast(r.left() + pass_x_hi), static_cast(r.bottom() - filter_band_height), - static_cast(stop_x_hi - pass_x_hi), filter_band_height - }; - painter.fill_rectangle( - r_stop_hi, - Color::yellow() - ); - } - - const Rect r_pass { - static_cast(r.left() + pass_x_lo), static_cast(r.bottom() - filter_band_height), - static_cast(pass_x_hi - pass_x_lo), filter_band_height - }; - painter.fill_rectangle( - r_pass, - Color::green() - ); - } - } + void draw_frequency_ticks(Painter& painter, const Rect r); + void draw_filter_ranges(Painter& painter, const Rect r); }; class WaterfallView : public Widget { public: - void on_show() override { - clear(); + void on_show() override; + void on_hide() override; - const auto screen_r = screen_rect(); - display.scroll_set_area(screen_r.top(), screen_r.bottom()); - } + void paint(Painter& painter) override; - void on_hide() override { - /* TODO: Clear region to eliminate brief flash of content at un-shifted - * position? - */ - display.scroll_disable(); - } - - void paint(Painter& painter) override { - // Do nothing. - (void)painter; - } - - void on_channel_spectrum( - const ChannelSpectrum& spectrum - ) { - /* TODO: static_assert that message.spectrum.db.size() >= pixel_row.size() */ - - std::array pixel_row; - for(size_t i=0; i<120; i++) { - const auto pixel_color = spectrum_rgb3_lut[spectrum.db[256 - 120 + i]]; - pixel_row[i] = pixel_color; - } - - for(size_t i=120; i<240; i++) { - const auto pixel_color = spectrum_rgb3_lut[spectrum.db[i - 120]]; - pixel_row[i] = pixel_color; - } - - const auto draw_y = display.scroll(1); - - display.draw_pixels( - { { 0, draw_y }, { pixel_row.size(), 1 } }, - pixel_row - ); - } + void on_channel_spectrum(const ChannelSpectrum& spectrum); private: - void clear() { - display.fill_rectangle( - screen_rect(), - Color::black() - ); - } + void clear(); }; class WaterfallWidget : public View { public: - WaterfallWidget() { - add_children({ - &waterfall_view, - &frequency_scale, - }); - } + WaterfallWidget(); - void on_show() override { - context().message_map().register_handler(Message::ID::ChannelSpectrum, - [this](const Message* const p) { - this->on_channel_spectrum(reinterpret_cast(p)->spectrum); - } - ); - } + void on_show() override; + void on_hide() override; - void on_hide() override { - context().message_map().unregister_handler(Message::ID::ChannelSpectrum); - } + void set_parent_rect(const Rect new_parent_rect) override; - void set_parent_rect(const Rect new_parent_rect) override { - constexpr Dim scale_height = 20; - - View::set_parent_rect(new_parent_rect); - frequency_scale.set_parent_rect({ 0, 0, new_parent_rect.width(), scale_height }); - waterfall_view.set_parent_rect({ - 0, scale_height, - new_parent_rect.width(), - static_cast(new_parent_rect.height() - scale_height) - }); - } - - void paint(Painter& painter) override { - // TODO: - (void)painter; - } + void paint(Painter& painter) override; private: WaterfallView waterfall_view; FrequencyScale frequency_scale; - void on_channel_spectrum(const ChannelSpectrum& spectrum) { - waterfall_view.on_channel_spectrum(spectrum); - frequency_scale.set_spectrum_sampling_rate(spectrum.sampling_rate, spectrum.db_count); - frequency_scale.set_channel_filter( - spectrum.channel_filter_pass_frequency, - spectrum.channel_filter_stop_frequency - ); - } + void on_channel_spectrum(const ChannelSpectrum& spectrum); }; } /* namespace spectrum */ From 5408eb104274c38b6d0f971274f3fccafb09ce15 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 16 Dec 2015 21:21:45 -0800 Subject: [PATCH 150/452] Nuke duplicate peripheral pointer constants for C++ Turns out the reinterpret_cast idiom is no longer kosher in the standard. --- .../os/hal/platforms/LPC43xx/lpc43xx.inc | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/lpc43xx.inc b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/lpc43xx.inc index 26a7d07e9..fb09b7826 100644 --- a/firmware/chibios-portapack/os/hal/platforms/LPC43xx/lpc43xx.inc +++ b/firmware/chibios-portapack/os/hal/platforms/LPC43xx/lpc43xx.inc @@ -1372,43 +1372,6 @@ typedef struct { // ------------------------------------------------------------------------------------------------ -#ifdef __cplusplus - -#define LPC_PERIPHERAL(_t, _i) constexpr auto const LPC_ ## _i = reinterpret_cast(LPC_ ## _i ## _BASE) - -LPC_PERIPHERAL(GPDMA, GPDMA); -LPC_PERIPHERAL(SPIFI, SPIFI); -LPC_PERIPHERAL(SDMMC, SDMMC); -LPC_PERIPHERAL(CREG, CREG); -LPC_PERIPHERAL(RTC, RTC); -LPC_PERIPHERAL(CGU, CGU); -LPC_PERIPHERAL(CCU1, CCU1); -LPC_PERIPHERAL(CCU2, CCU2); -LPC_PERIPHERAL(RGU, RGU); -LPC_PERIPHERAL(USART, USART0); -LPC_PERIPHERAL(UART, UART1); -LPC_PERIPHERAL(SSPx, SSP0); -LPC_PERIPHERAL(TIMER, TIMER0); -LPC_PERIPHERAL(TIMER, TIMER1); -LPC_PERIPHERAL(SCU, SCU); -LPC_PERIPHERAL(GPIO_INT, GPIO_INT); -LPC_PERIPHERAL(I2Cx, I2C0); -LPC_PERIPHERAL(I2S, I2S0); -LPC_PERIPHERAL(I2S, I2S1); -LPC_PERIPHERAL(RITIMER, RITIMER); -LPC_PERIPHERAL(USART, USART2); -LPC_PERIPHERAL(USART, USART3); -LPC_PERIPHERAL(TIMER, TIMER2); -LPC_PERIPHERAL(TIMER, TIMER3); -LPC_PERIPHERAL(SSPx, SSP1); -LPC_PERIPHERAL(I2Cx, I2C1); -LPC_PERIPHERAL(ADCx, ADC0); -LPC_PERIPHERAL(ADCx, ADC1); -LPC_PERIPHERAL(GPIO, GPIO); -LPC_PERIPHERAL(SGPIO, SGPIO); - -#else - #define LPC_GPDMA ((LPC_GPDMA_Type *) LPC_GPDMA_BASE) #define LPC_SPIFI ((LPC_SPIFI_Type *) LPC_SPIFI_BASE) #define LPC_SDMMC ((LPC_SDMMC_Type *) LPC_SDMMC_BASE) @@ -1439,7 +1402,6 @@ LPC_PERIPHERAL(SGPIO, SGPIO); #define LPC_ADC1 ((LPC_ADCx_Type *) LPC_ADC1_BASE) #define LPC_GPIO ((LPC_GPIO_Type *) LPC_GPIO_BASE) #define LPC_SGPIO ((LPC_SGPIO_Type *) LPC_SGPIO_BASE) -#endif #ifdef __cplusplus } From d34499d92088b66374ba51f922ecbc5be02fad0e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 16 Dec 2015 22:29:29 -0800 Subject: [PATCH 151/452] Remove ui::BasebandBandwidthField. --- firmware/application/ui_receiver.cpp | 29 ---------------------------- firmware/application/ui_receiver.hpp | 5 ----- 2 files changed, 34 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index a9264ea94..c3f87513d 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -34,35 +34,6 @@ using namespace portapack; namespace ui { -/* BasebandBandwidthField ************************************************/ - -BasebandBandwidthField::BasebandBandwidthField( - Point parent_pos -) : OptionsField { - parent_pos, - 4, - { - { " 1M8", 1750000 }, - { " 2M5", 2500000 }, - { " 3M5", 3500000 }, - { " 5M ", 5000000 }, - { " 5M5", 5500000 }, - { " 6M ", 6000000 }, - { " 7M ", 7000000 }, - { " 8M ", 8000000 }, - { " 9M ", 9000000 }, - { "10M ", 10000000 }, - { "12M ", 12000000 }, - { "14M ", 14000000 }, - { "15M ", 15000000 }, - { "20M ", 20000000 }, - { "24M ", 24000000 }, - { "28M ", 28000000 }, - } - } -{ -} - /* FrequencyField ********************************************************/ FrequencyField::FrequencyField( diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index e2cbf1f7d..4a321d37f 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -44,11 +44,6 @@ namespace ui { -class BasebandBandwidthField : public OptionsField { -public: - BasebandBandwidthField(Point parent_pos); -}; - class FrequencyField : public Widget { public: std::function on_change; From 750506b33e06fadd5a604eb85c71dd2a0672d52d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 16 Dec 2015 22:35:26 -0800 Subject: [PATCH 152/452] Move more code from .hpp to .cpp. --- firmware/common/ui_widget.cpp | 57 ++++++++++++++++++++++++++++++++++ firmware/common/ui_widget.hpp | 58 ++++------------------------------- 2 files changed, 63 insertions(+), 52 deletions(-) diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 16c2829a9..7732a5028 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -249,6 +249,14 @@ Widget* View::initial_focus() { /* Rectangle *************************************************************/ +Rectangle::Rectangle( + Rect parent_rect, + Color c +) : Widget { parent_rect }, + color { c } +{ +} + void Rectangle::set_color(const Color c) { color = c; set_dirty(); @@ -263,6 +271,20 @@ void Rectangle::paint(Painter& painter) { /* Text ******************************************************************/ +Text::Text( + Rect parent_rect, + std::string text +) : Widget { parent_rect }, + text { text } +{ +} + +Text::Text( + Rect parent_rect +) : Text { parent_rect, { } } +{ +} + void Text::set(const std::string value) { text = value; set_dirty(); @@ -278,6 +300,15 @@ void Text::paint(Painter& painter) { /* Button ****************************************************************/ + Button::Button( + Rect parent_rect, + std::string text +) : Widget { parent_rect }, + text_ { text } +{ + flags.focusable = true; +} + void Button::set_text(const std::string value) { text_ = value; set_dirty(); @@ -378,6 +409,17 @@ bool Button::on_touch(const TouchEvent event) { /* OptionsField **********************************************************/ +OptionsField::OptionsField( + Point parent_pos, + size_t length, + options_t options +) : Widget { { parent_pos, { static_cast(8 * length), 16 } } }, + length_ { length }, + options { options } +{ + flags.focusable = true; +} + size_t OptionsField::selected_index() const { return selected_index_; } @@ -432,6 +474,21 @@ bool OptionsField::on_touch(const TouchEvent event) { /* NumberField ***********************************************************/ +NumberField::NumberField( + Point parent_pos, + size_t length, + range_t range, + int32_t step, + char fill_char +) : Widget { { parent_pos, { static_cast(8 * length), 16 } } }, + range { range }, + step { step }, + length_ { length }, + fill_char { fill_char } +{ + flags.focusable = true; +} + int32_t NumberField::value() const { return value_; } diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 2426e409e..a974631a5 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -171,13 +171,7 @@ protected: class Rectangle : public Widget { public: - constexpr Rectangle( - const Rect parent_rect, - const Color c - ) : Widget { parent_rect }, - color { c } - { - } + Rectangle(Rect parent_rect, Color c); void paint(Painter& painter) override; @@ -193,19 +187,8 @@ public: ) : text { "" } { } - Text( - Rect parent_rect, - std::string text - ) : Widget { parent_rect }, - text { text } - { - } - - Text( - Rect parent_rect - ) : Text { parent_rect, { } } - { - } + Text(Rect parent_rect, std::string text); + Text(Rect parent_rect); void set(const std::string value); @@ -219,14 +202,7 @@ class Button : public Widget { public: std::function on_select; - Button( - Rect parent_rect, - std::string text - ) : Widget { parent_rect }, - text_ { text } - { - flags.focusable = true; - } + Button(Rect parent_rect, std::string text); Button( ) : Button { { }, { } } @@ -254,16 +230,7 @@ public: std::function on_change; - OptionsField( - Point parent_pos, - size_t length, - options_t options - ) : Widget { { parent_pos, { static_cast(8 * length), 16 } } }, - length_ { length }, - options { options } - { - flags.focusable = true; - } + OptionsField(Point parent_pos, size_t length, options_t options); size_t selected_index() const; void set_selected_index(const size_t new_index); @@ -287,20 +254,7 @@ public: using range_t = std::pair; - NumberField( - Point parent_pos, - size_t length, - range_t range, - int32_t step, - char fill_char - ) : Widget { { parent_pos, { static_cast(8 * length), 16 } } }, - range { range }, - step { step }, - length_ { length }, - fill_char { fill_char } - { - flags.focusable = true; - } + NumberField(Point parent_pos, size_t length, range_t range, int32_t step, char fill_char); NumberField(const NumberField&) = delete; NumberField(NumberField&&) = delete; From 86edf01defb9f54dd864dce3837874f963dd8c05 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 16 Dec 2015 22:36:51 -0800 Subject: [PATCH 153/452] Quick and dirty temperature logger, debug view of temp vs. time. --- firmware/application/Makefile | 1 + firmware/application/main.cpp | 2 + firmware/application/portapack.cpp | 2 + firmware/application/portapack.hpp | 3 + firmware/application/temperature_logger.cpp | 65 +++++++++++++++++++++ firmware/application/temperature_logger.hpp | 51 ++++++++++++++++ firmware/application/ui_debug.cpp | 55 ++++++++++++++++- firmware/application/ui_debug.hpp | 30 ++++++++++ 8 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 firmware/application/temperature_logger.cpp create mode 100644 firmware/application/temperature_logger.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 5149b13c4..bd488ea74 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -180,6 +180,7 @@ CPPSRC = main.cpp \ log_file.cpp \ manchester.cpp \ string_format.cpp \ + temperature_logger.cpp \ ../common/utility.cpp \ ../common/chibios_cpp.cpp \ ../common/debug.cpp \ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index a30bba256..21a5874ea 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -129,6 +129,8 @@ private: void handle_rtc_tick() { sd_card::poll_inserted(); + + portapack::temperature_logger.second_tick(); } static ui::Widget* touch_widget(ui::Widget* const w, ui::TouchEvent event) { diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 1491fe6a4..e9460c508 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -65,6 +65,8 @@ ReceiverModel receiver_model { clock_manager }; +TemperatureLogger temperature_logger; + class Power { public: void init() { diff --git a/firmware/application/portapack.hpp b/firmware/application/portapack.hpp index ae424f36d..cbe0b6657 100644 --- a/firmware/application/portapack.hpp +++ b/firmware/application/portapack.hpp @@ -29,6 +29,7 @@ #include "lcd_ili9341.hpp" #include "radio.hpp" +#include "temperature_logger.hpp" namespace portapack { @@ -45,6 +46,8 @@ extern si5351::Si5351 clock_generator; extern ReceiverModel receiver_model; +extern TemperatureLogger temperature_logger; + void init(); void shutdown(); diff --git a/firmware/application/temperature_logger.cpp b/firmware/application/temperature_logger.cpp new file mode 100644 index 000000000..b2317ab93 --- /dev/null +++ b/firmware/application/temperature_logger.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "temperature_logger.hpp" + +#include "radio.hpp" + +#include + +void TemperatureLogger::second_tick() { + sample_phase++; + if( sample_phase >= sample_interval ) { + push_sample(read_sample()); + } +} + +size_t TemperatureLogger::size() const { + return std::min(samples.size(), samples_count); +} + +std::vector TemperatureLogger::history() const { + std::vector result; + + const auto n = size(); + result.resize(n); + + // Copy the last N samples from the buffer, since new samples are added at the end. + std::copy(samples.cend() - n, samples.cend(), result.data()); + + return result; +} + +TemperatureLogger::sample_t TemperatureLogger::read_sample() { + // MAX2837 does not return a valid temperature if in "shutdown" mode. + return radio::second_if.temp_sense() & 0x1f; +} + +void TemperatureLogger::push_sample(const TemperatureLogger::sample_t sample) { + // Started out building a pseudo-FIFO, then got lazy. + + // Shift samples: samples[1:] -> samples[0:-1] + // New sample goes into samples[-1] + std::copy(samples.cbegin() + 1, samples.cend(), samples.begin()); + samples.back() = sample; + samples_count++; + sample_phase = 0; +} diff --git a/firmware/application/temperature_logger.hpp b/firmware/application/temperature_logger.hpp new file mode 100644 index 000000000..5095c3383 --- /dev/null +++ b/firmware/application/temperature_logger.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __TEMPERATURE_LOGGER_H__ +#define __TEMPERATURE_LOGGER_H__ + +#include +#include +#include +#include + +class TemperatureLogger { +public: + using sample_t = uint8_t; + + void second_tick(); + + size_t size() const; + + std::vector history() const; + +private: + std::array samples; + + static constexpr size_t sample_interval = 5; + size_t sample_phase = 0; + size_t samples_count = 0; + + sample_t read_sample(); + void push_sample(const sample_t sample); +}; + +#endif/*__TEMPERATURE_LOGGER_H__*/ diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 7e955b03d..1622287fe 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -57,6 +57,50 @@ void DebugMemoryView::focus() { button_done.focus(); } +/* TemperatureWidget *****************************************************/ + +void TemperatureWidget::paint(Painter& painter) { + const auto history = portapack::temperature_logger.history(); + + const auto rect = screen_rect(); + + for(size_t i=0; i(rect.right() - (history.size() - i) * 1), + static_cast(rect.bottom() - bar_height), + 1, bar_height + }; + painter.fill_rectangle(bar_rect, Color::green()); + } + + if( !history.empty() ) { + const int32_t temp = -45 + history.back() * 5; + const size_t temp_len = 3; + painter.draw_string( + { static_cast(rect.right() - (temp_len * 8)), rect.top() }, + style(), + to_string_dec_int(temp, temp_len) + ); + } +} + +/* TemperatureView *******************************************************/ + +TemperatureView::TemperatureView(NavigationView& nav) { + add_children({ { + &temperature_widget, + &button_done, + } }); + + button_done.on_select = [&nav](Button&){ nav.pop(); }; +} + +void TemperatureView::focus() { + button_done.focus(); +} + /* RegistersWidget *******************************************************/ RegistersWidget::RegistersWidget( @@ -80,6 +124,8 @@ void RegistersWidget::paint(Painter& painter) { } void RegistersWidget::draw_legend(const Coord left, Painter& painter) { + const auto pos = screen_pos(); + for(size_t i=0; i((i / config.registers_per_row) * row_height) @@ -87,7 +133,7 @@ void RegistersWidget::draw_legend(const Coord left, Painter& painter) { const auto text = to_string_hex(i, config.legend_length); painter.draw_string( - screen_pos() + offset, + pos + offset, style().invert(), text ); @@ -98,6 +144,8 @@ void RegistersWidget::draw_values( const Coord left, Painter& painter ) { + const auto pos = screen_pos(); + for(size_t i=0; i(left + config.legend_width() + 8 + (i % config.registers_per_row) * (config.value_width() + 8)), @@ -108,7 +156,7 @@ void RegistersWidget::draw_values( const auto text = to_string_hex(value, config.value_length); painter.draw_string( - screen_pos() + offset, + pos + offset, style(), text ); @@ -152,7 +200,7 @@ void RegistersView::focus() { /* DebugMenuView *********************************************************/ DebugMenuView::DebugMenuView(NavigationView& nav) { - add_items<7>({ { + add_items<8>({ { { "Memory", [&nav](){ nav.push(); } }, { "Radio State", [&nav](){ nav.push(); } }, { "SD Card", [&nav](){ nav.push(); } }, @@ -172,6 +220,7 @@ DebugMenuView::DebugMenuView(NavigationView& nav) { "WM8731", RegistersWidgetConfig { wolfson::wm8731::reg_count, 1, 3, 4 }, [](const size_t register_number) { return portapack::audio_codec.read(register_number); } ); } }, + { "Temperature", [&nav](){ nav.push(); } }, } }); on_left = [&nav](){ nav.pop(); }; } diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 6ed9b4e9f..cfd7f7ad6 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -82,6 +82,36 @@ private: }; }; +class TemperatureWidget : public Widget { +public: + explicit constexpr TemperatureWidget( + Rect parent_rect + ) : Widget { parent_rect } + { + } + + void paint(Painter& painter) override; + +private: +}; + +class TemperatureView : public View { +public: + explicit TemperatureView(NavigationView& nav); + + void focus() override; + +private: + TemperatureWidget temperature_widget { + { 0, 16, 240, 192 }, + }; + + Button button_done { + { 72, 256, 96, 24 }, + "Done" + }; +}; + struct RegistersWidgetConfig { size_t registers_count; size_t legend_length; From 3151100e503cdcf8bf9ae2c58cee0b3eec9dd0f1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 16 Dec 2015 22:37:55 -0800 Subject: [PATCH 154/452] Correct aesthetic typo in MAX2837 register defaults. --- firmware/application/max2837.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/max2837.hpp b/firmware/application/max2837.hpp index d6733bce6..d4666c35b 100644 --- a/firmware/application/max2837.hpp +++ b/firmware/application/max2837.hpp @@ -576,7 +576,7 @@ constexpr RegisterMap initial_register_values { Register_Type { .LNAtune = 0, .LNAde_Q = 1, .L = 0b000, - .iqerr_trim = 0b0000, + .iqerr_trim = 0b00000, .RESERVED0 = 0, }, .lpf_1 = { /* 2 */ From b65cd72a68e832b002114093b8986ae73d8694ff Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 17 Dec 2015 10:12:03 -0800 Subject: [PATCH 155/452] Remove some pointless GCC-isms. --- firmware/common/volume.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/common/volume.hpp b/firmware/common/volume.hpp index 97c432d88..8ef85557a 100644 --- a/firmware/common/volume.hpp +++ b/firmware/common/volume.hpp @@ -27,15 +27,15 @@ class volume_t { public: constexpr volume_t operator-() const { - return { .cb = -cb }; + return { -cb }; } constexpr volume_t operator+(const volume_t& other) const { - return { .cb = cb + other.cb }; + return { cb + other.cb }; } constexpr volume_t operator-(const volume_t& other) const { - return { .cb = cb - other.cb }; + return { cb - other.cb }; } volume_t& operator+=(const volume_t& other) { @@ -52,11 +52,11 @@ public: } static constexpr volume_t centibel(const int cb) { - return { .cb = cb }; + return { cb }; } static constexpr volume_t decibel(const int db) { - return { .cb = db * 10 }; + return { db * 10 }; } int32_t centibel() const { From 17d405ccec4edd76ef347dc70f6cdcf888ddd0be Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 17 Dec 2015 10:30:40 -0800 Subject: [PATCH 156/452] Weird syntax burp on my part. --- firmware/application/ui_receiver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index c3f87513d..176673ee9 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -345,7 +345,7 @@ void RadioGainOptionsView::on_agc_changed(bool v) { LNAGainField::LNAGainField( Point parent_pos ) : NumberField { - { parent_pos }, 2, + parent_pos, 2, { max2837::lna::gain_db_min, max2837::lna::gain_db_max }, max2837::lna::gain_db_step, ' ', From 146a06b0d1527da13695dd90e03f2d90b2a71cb5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 17 Dec 2015 12:12:22 -0800 Subject: [PATCH 157/452] Method to read TemperatureLogger record capacity. --- firmware/application/temperature_logger.cpp | 6 +++++- firmware/application/temperature_logger.hpp | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/firmware/application/temperature_logger.cpp b/firmware/application/temperature_logger.cpp index b2317ab93..474c3dd03 100644 --- a/firmware/application/temperature_logger.cpp +++ b/firmware/application/temperature_logger.cpp @@ -33,7 +33,11 @@ void TemperatureLogger::second_tick() { } size_t TemperatureLogger::size() const { - return std::min(samples.size(), samples_count); + return std::min(capacity(), samples_count); +} + +size_t TemperatureLogger::capacity() const { + return samples.size(); } std::vector TemperatureLogger::history() const { diff --git a/firmware/application/temperature_logger.hpp b/firmware/application/temperature_logger.hpp index 5095c3383..51f8e451a 100644 --- a/firmware/application/temperature_logger.hpp +++ b/firmware/application/temperature_logger.hpp @@ -34,7 +34,8 @@ public: void second_tick(); size_t size() const; - + size_t capacity() const; + std::vector history() const; private: From c92138f4b3f9e5716dbae41594389ed0bf0d802c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 17 Dec 2015 12:14:28 -0800 Subject: [PATCH 158/452] Extract calculation of temperature from raw sensor value. --- firmware/application/ui_debug.cpp | 6 +++++- firmware/application/ui_debug.hpp | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 1622287fe..b4355e45b 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -76,7 +76,7 @@ void TemperatureWidget::paint(Painter& painter) { } if( !history.empty() ) { - const int32_t temp = -45 + history.back() * 5; + const int32_t temp = temperature(history.back()); const size_t temp_len = 3; painter.draw_string( { static_cast(rect.right() - (temp_len * 8)), rect.top() }, @@ -86,6 +86,10 @@ void TemperatureWidget::paint(Painter& painter) { } } +int32_t TemperatureWidget::temperature(const int32_t sensor_value) { + return -45 + sensor_value * 5 +} + /* TemperatureView *******************************************************/ TemperatureView::TemperatureView(NavigationView& nav) { diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index cfd7f7ad6..2c83b6a87 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -93,6 +93,7 @@ public: void paint(Painter& painter) override; private: + int32_t temperature(const uint32_t sensor_value); }; class TemperatureView : public View { From c3116eac6350b2a6c4b721320295df662455734c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 17 Dec 2015 12:16:26 -0800 Subject: [PATCH 159/452] Use reference to temperature logger, more concise. --- firmware/application/ui_debug.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index b4355e45b..fe64e7395 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -60,10 +60,11 @@ void DebugMemoryView::focus() { /* TemperatureWidget *****************************************************/ void TemperatureWidget::paint(Painter& painter) { - const auto history = portapack::temperature_logger.history(); + const auto logger = portapack::temperature_logger; const auto rect = screen_rect(); + const auto history = logger.history(); for(size_t i=0; i Date: Thu, 17 Dec 2015 12:18:25 -0800 Subject: [PATCH 160/452] Center temperature graph in view. --- firmware/application/ui_debug.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index fe64e7395..aaf6e25e4 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -64,15 +64,17 @@ void TemperatureWidget::paint(Painter& painter) { const auto rect = screen_rect(); + const Dim bar_width = 1; + const Dim margin_x = (rect.width() - (logger.capacity() * bar_width)) / 2; + const Coord rightmost_x = rect.right() - margin_x; + const auto history = logger.history(); for(size_t i=0; i(rect.right() - (history.size() - i) * 1), - static_cast(rect.bottom() - bar_height), - 1, bar_height - }; + const Coord x = rightmost_x - (history.size() - i) * bar_width; + const Coord y = rect.bottom() - bar_height; + const Rect bar_rect { x, y, bar_width, bar_height }; painter.fill_rectangle(bar_rect, Color::green()); } From 1146d1fa061c224de3449d2471401a9c1a31d294 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 17 Dec 2015 20:36:58 -0800 Subject: [PATCH 161/452] Clean up temperature sensor rendering. --- firmware/application/ui_debug.cpp | 71 +++++++++++++++++++++++-------- firmware/application/ui_debug.hpp | 22 ++++++++-- 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index aaf6e25e4..fff640c9d 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -63,40 +63,77 @@ void TemperatureWidget::paint(Painter& painter) { const auto logger = portapack::temperature_logger; const auto rect = screen_rect(); + const Color color_background { 0, 0, 64 }; + const Color color_foreground = Color::green(); + const Color color_reticle { 128, 128, 128 }; - const Dim bar_width = 1; - const Dim margin_x = (rect.width() - (logger.capacity() * bar_width)) / 2; - const Coord rightmost_x = rect.right() - margin_x; + const Dim graph_width = logger.capacity() * bar_width; + const Dim graph_height = rect.height() - 16; + const Rect graph_rect { + rect.left() + (rect.width() - graph_width) / 2, rect.top() + 8, + graph_width, rect.height() + }; + const Rect frame_rect { + graph_rect.left() - 1, graph_rect.top() - 1, + graph_rect.width() + 2, graph_rect.height() + 2 + }; + painter.draw_rectangle(frame_rect, color_reticle); + painter.fill_rectangle(graph_rect, color_background); const auto history = logger.history(); for(size_t i=0; i(rect.right() - (temp_len * 8)), rect.top() }, - style(), - to_string_dec_int(temp, temp_len) - ); + const auto sample = history.back(); + const auto temp = temperature(sample); + const auto last_y = screen_y(temp, graph_rect); + const Coord x = graph_rect.right() + 8; + const Coord y = last_y - 8; + + painter.draw_string({ x, y }, style(), temperature_str(temp)); + } + + const auto display_temp_max = display_temp_min + (graph_rect.height() / display_temp_scale); + for(auto temp=display_temp_min; temp<=display_temp_max; temp+=10) { + const int32_t tick_length = 6; + const auto tick_x = graph_rect.left() - tick_length; + const auto tick_y = screen_y(temp, graph_rect); + painter.fill_rectangle({ tick_x, tick_y, tick_length, 1 }, color_reticle); + const auto text_x = graph_rect.left() - temp_len * 8 - 8; + const auto text_y = tick_y - 8; + painter.draw_string({ text_x, text_y }, style(), temperature_str(temp)); } } -int32_t TemperatureWidget::temperature(const int32_t sensor_value) { - return -45 + sensor_value * 5 +TemperatureWidget::temperature_t TemperatureWidget::temperature(const sample_t sensor_value) const { + return -45 + sensor_value * 5; +} + +std::string TemperatureWidget::temperature_str(const temperature_t temperature) const { + return to_string_dec_int(temperature, temp_len - 1) + "C"; +} + +Coord TemperatureWidget::screen_y( + const temperature_t temperature, + const Rect& rect +) const { + const Coord y_raw = rect.bottom() - ((temperature - display_temp_min) * display_temp_scale); + const auto y_limit = std::min(rect.bottom(), std::max(rect.top(), y_raw)); + return y_limit; } /* TemperatureView *******************************************************/ TemperatureView::TemperatureView(NavigationView& nav) { add_children({ { + &text_title, &temperature_widget, &button_done, } }); diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index 2c83b6a87..b693650ad 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -93,7 +93,18 @@ public: void paint(Painter& painter) override; private: - int32_t temperature(const uint32_t sensor_value); + using sample_t = uint32_t; + using temperature_t = int32_t; + + temperature_t temperature(const sample_t sensor_value) const; + Coord screen_y(const temperature_t temperature, const Rect& screen_rect) const; + + std::string temperature_str(const temperature_t temperature) const; + + static constexpr temperature_t display_temp_min = 0; + static constexpr temperature_t display_temp_scale = 3; + static constexpr Dim bar_width = 1; + static constexpr size_t temp_len = 3; }; class TemperatureView : public View { @@ -103,12 +114,17 @@ public: void focus() override; private: + Text text_title { + { 76, 16, 240, 16 }, + "Temperature", + }; + TemperatureWidget temperature_widget { - { 0, 16, 240, 192 }, + { 0, 40, 240, 180 }, }; Button button_done { - { 72, 256, 96, 24 }, + { 72, 264, 96, 24 }, "Done" }; }; From b38338efc03cd5de79b7c4b066a94bc2fbe0c306 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 17 Dec 2015 20:59:21 -0800 Subject: [PATCH 162/452] Keep MAX2837 in standby so temperature can be read. I think this won't significantly impact power consumption. --- firmware/application/max2837.cpp | 2 ++ firmware/application/radio.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/firmware/application/max2837.cpp b/firmware/application/max2837.cpp index f932cbaa0..7456a1bc4 100644 --- a/firmware/application/max2837.cpp +++ b/firmware/application/max2837.cpp @@ -124,6 +124,8 @@ void MAX2837::init() { _dirty.set(); flush(); + + set_mode(Mode::Standby); } void MAX2837::set_mode(const Mode mode) { diff --git a/firmware/application/radio.cpp b/firmware/application/radio.cpp index dbb29eac7..974636638 100644 --- a/firmware/application/radio.cpp +++ b/firmware/application/radio.cpp @@ -167,7 +167,7 @@ void streaming_disable() { void disable() { baseband_sgpio.streaming_disable(); baseband_codec.set_mode(max5864::Mode::Shutdown); - second_if.set_mode(max2837::Mode::Shutdown); + second_if.set_mode(max2837::Mode::Standby); first_if.disable(); set_rf_amp(false); } From bddd26d5571bf984e50ccc59b245d646b90b2c52 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 20 Dec 2015 13:31:00 -0800 Subject: [PATCH 163/452] Perform frequency-domain windowing of spectrum. Reduces sidelobes a bit, improves apparent resolution. Avoids windowing (more RAM and CPU) in baseband. --- firmware/baseband/spectrum_collector.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index e344a0f59..dacf45ab6 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -69,7 +69,10 @@ void SpectrumCollector::update() { ChannelSpectrumMessage spectrum_message; for(size_t i=0; i Date: Sun, 20 Dec 2015 13:33:08 -0800 Subject: [PATCH 164/452] Fix inaccurate comment. --- firmware/baseband/channel_decimator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/baseband/channel_decimator.cpp b/firmware/baseband/channel_decimator.cpp index 59dbd7ea7..c8a7cf5c8 100644 --- a/firmware/baseband/channel_decimator.cpp +++ b/firmware/baseband/channel_decimator.cpp @@ -47,7 +47,7 @@ buffer_c16_t ChannelDecimator::execute_decimation(const buffer_c8_t& buffer) { /* 1.536MHz complex[1024], [-32768, 32512] * -> 3rd order CIC: -0.1dB @ 0.028fs, -1dB @ 0.088fs, -60dB @ 0.468fs * -0.1dB @ 43kHz, -1dB @ 136kHz, -60dB @ 723kHz - * -> gain of 8 + * -> gain of 1 * -> decimation by 2 * -> 768kHz complex[512], [-8192, 8128] */ auto cic_1_out = cic_1.execute(stage_0_out, work_baseband_buffer); From b8726b6ecf46dfc04c755c13507289512446ae60 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 24 Dec 2015 10:36:26 -0800 Subject: [PATCH 165/452] Un-bitfield PinConfig, GCC 5 didn't like it. And GCC 4.9 was very touchy about it. Attempts to fix by other means broke MAX2837 register readback (but not writing?). It suggests there might be a deeper issue -- setup/hold timing? --- firmware/common/gpio.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/common/gpio.hpp b/firmware/common/gpio.hpp index 21a08d6b4..0f02d6ec3 100644 --- a/firmware/common/gpio.hpp +++ b/firmware/common/gpio.hpp @@ -28,12 +28,12 @@ #include "hal.h" struct PinConfig { - const uint32_t mode : 3; - const uint32_t pd : 1; - const uint32_t pu : 1; - const uint32_t fast : 1; - const uint32_t input : 1; - const uint32_t ifilt : 1; + const uint32_t mode; + const uint32_t pd; + const uint32_t pu; + const uint32_t fast; + const uint32_t input; + const uint32_t ifilt; constexpr operator uint16_t() { return From dc86db5b87945a2bd7a710f1a0a79faff7ccd316 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 10:12:40 -0800 Subject: [PATCH 166/452] Reminder to my future self to not over-optimize complex conjugate multiply. --- firmware/common/utility_m4.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/firmware/common/utility_m4.hpp b/firmware/common/utility_m4.hpp index e7d98e90f..2516f12a1 100644 --- a/firmware/common/utility_m4.hpp +++ b/firmware/common/utility_m4.hpp @@ -40,6 +40,9 @@ static inline complex32_t multiply_conjugate_s16_s32(const complex16_t::rep_type // multiply: (a + bj) * (c + dj) = (ac - bd) + (bc + ad)j // conjugate-multiply: (ac + bd) + (bc - ad)j //return { a.real() * b.real() + a.imag() * b.imag(), a.imag() * b.real() - a.real() * b.imag() }; + // NOTE: Did not use combination of SMUAD and SMUSDX because of non-saturating arithmetic. + // const int32_t r = __SMUAD(a, b); + // const int32_t i = __SMUSDX(b, a); const int32_t rr = __SMULBB(a, b); const int32_t ii = __SMULTT(a, b); const int32_t r = __QADD(rr, ii); From ccc34028695671a0e62ebe8497bb21c0b0577841 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 10:14:35 -0800 Subject: [PATCH 167/452] Add complex32_t type. --- firmware/common/dsp_types.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/common/dsp_types.hpp b/firmware/common/dsp_types.hpp index 56fbe3d7e..b4d34843c 100644 --- a/firmware/common/dsp_types.hpp +++ b/firmware/common/dsp_types.hpp @@ -30,5 +30,6 @@ using buffer_c8_t = buffer_t; using buffer_c16_t = buffer_t; using buffer_s16_t = buffer_t; +using buffer_c32_t = buffer_t; #endif/*__DSP_TYPES_H__*/ From 49215c3ae6f141ec5312fd686f9ffd5721c8592c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 15:49:47 -0800 Subject: [PATCH 168/452] Remove garbage DSP filter code. --- firmware/baseband/dsp_decimate.cpp | 70 ------------------- firmware/baseband/dsp_decimate.hpp | 105 ----------------------------- 2 files changed, 175 deletions(-) diff --git a/firmware/baseband/dsp_decimate.cpp b/firmware/baseband/dsp_decimate.cpp index bb06d33c0..eef3f857a 100644 --- a/firmware/baseband/dsp_decimate.cpp +++ b/firmware/baseband/dsp_decimate.cpp @@ -385,76 +385,6 @@ buffer_s16_t DecimateBy2CIC4Real::execute( return { dst.p, src.count / 2, src.sampling_rate / 2 }; } -#if 0 -buffer_c16_t DecimateBy2HBF5Complex::execute( - buffer_c16_t const src, - buffer_c16_t const dst -) { - auto src_p = src.p; - auto dst_p = dst.p; - int32_t n = src.count; - for(; n>0; n-=2) { - /* TODO: Probably a lot of room to optimize... */ - z[0] = z[2]; - //z[1] = z[3]; - z[2] = z[4]; - //z[3] = z[5]; - z[4] = z[6]; - z[5] = z[7]; - z[6] = z[8]; - z[7] = z[9]; - z[8] = z[10]; - z[9] = *(src_p++); - z[10] = *(src_p++); - int32_t t_real { z[5].real * 256 }; - int32_t t_imag { z[5].imag * 256 }; - t_real += (z[ 0].real + z[10].real) * 3; - t_imag += (z[ 0].imag + z[10].imag) * 3; - t_real -= (z[ 2].real + z[ 8].real) * 25; - t_imag -= (z[ 2].imag + z[ 8].imag) * 25; - t_real += (z[ 4].real + z[ 6].real) * 150; - t_imag += (z[ 4].imag + z[ 6].imag) * 150; - *(dst_p++) = { t_real / 256, t_imag / 256 }; - } - - return { dst.p, src.count / 2, src.sampling_rate / 2 }; -} - -buffer_c16_t DecimateBy2HBF7Complex::execute( - buffer_c16_t const src, - buffer_c16_t const dst -) { - auto src_p = src.p; - auto dst_p = dst.p; - int32_t n = src.count; - for(; n>0; n-=2) { - /* TODO: Probably a lot of room to optimize... */ - z[0] = z[2]; - //z[1] = z[3]; - z[2] = z[4]; - //z[3] = z[5]; - z[4] = z[6]; - z[5] = z[7]; - z[6] = z[8]; - z[7] = z[9]; - z[8] = z[10]; - z[9] = *(src_p++); - z[10] = *(src_p++); - - int32_t t_real { z[5].real * 512 }; - int32_t t_imag { z[5].imag * 512 }; - t_real += (z[ 0].real + z[10].real) * 7; - t_imag += (z[ 0].imag + z[10].imag) * 7; - t_real -= (z[ 2].real + z[ 8].real) * 53; - t_imag -= (z[ 2].imag + z[ 8].imag) * 53; - t_real += (z[ 4].real + z[ 6].real) * 302; - t_imag += (z[ 4].imag + z[ 6].imag) * 302; - *(dst_p++) = { t_real / 512, t_imag / 512 }; - } - - return { dst.p, src.count / 2, src.sampling_rate / 2 }; -} -#endif } /* namespace decimate */ } /* namespace dsp */ diff --git a/firmware/baseband/dsp_decimate.hpp b/firmware/baseband/dsp_decimate.hpp index f57c5e2fe..4b392cada 100644 --- a/firmware/baseband/dsp_decimate.hpp +++ b/firmware/baseband/dsp_decimate.hpp @@ -142,112 +142,7 @@ public: private: int16_t z[5]; }; -#if 0 -class DecimateBy2HBF5Complex { -public: - buffer_c16_t execute( - buffer_c16_t const src, - buffer_c16_t const dst - ); -private: - complex16_t z[11]; -}; - -class DecimateBy2HBF7Complex { -public: - buffer_c16_t execute( - buffer_c16_t const src, - buffer_c16_t const dst - ); - -private: - complex16_t z[11]; -}; -#endif -/* From http://www.dspguru.com/book/export/html/3 - -Here are several basic techniques to fake circular buffers: - -Split the calculation: You can split any FIR calculation into its "pre-wrap" -and "post-wrap" parts. By splitting the calculation into these two parts, you -essentially can do the circular logic only once, rather than once per tap. -(See fir_double_z in FirAlgs.c above.) - -Duplicate the delay line: For a FIR with N taps, use a delay line of size 2N. -Copy each sample to its proper location, as well as at location-plus-N. -Therefore, the FIR calculation's MAC loop can be done on a flat buffer of N -points, starting anywhere within the first set of N points. The second set of -N delayed samples provides the "wrap around" comparable to a true circular -buffer. (See fir_double_z in FirAlgs.c above.) - -Duplicate the coefficients: This is similar to the above, except that the -duplication occurs in terms of the coefficients, not the delay line. -Compared to the previous method, this has a calculation advantage of not -having to store each incoming sample twice, and it also has a memory -advantage when the same coefficient set will be used on multiple delay lines. -(See fir_double_h in FirAlgs.c above.) - -Use block processing: In block processing, you use a delay line which is a -multiple of the number of taps. You therefore only have to move the data -once per block to implement the delay-line mechanism. When the block size -becomes "large", the overhead of a moving the delay line once per block -becomes negligible. -*/ - -#if 0 -template -class FIRAndDecimateBy2Complex { -public: - FIR64AndDecimateBy2Complex( - const std::array& taps - ) : taps { taps } - { - } - - buffer_c16_t execute( - buffer_c16_t const src, - buffer_c16_t const dst - ) { - /* int16_t input (sample count "n" must be multiple of 4) - * -> int16_t output, decimated by 2. - * taps are normalized to 1 << 16 == 1.0. - */ - - return { dst.p, src.count / 2 }; - } - -private: - std::array z; - const std::array& taps; - - complex process_one(const size_t start_offset) { - const auto split = &z[start_offset]; - const auto end = &z[z.size()]; - auto tap = &taps[0]; - - complex t { 0, 0 }; - - auto p = split; - while(p < end) { - const auto t = *(tap++); - const auto c = *(p++); - t.real += c.real * t; - t.imag += c.imag * t; - } - - p = &z[0]; - while(p < split) { - const auto t = *(tap++); - const auto c = *(p++); - t.real += c.real * t; - t.imag += c.imag * t; - } - - return { t.real / 65536, t.imag / 65536 }; - } -}; -#endif } /* namespace decimate */ } /* namespace dsp */ From 4910bacfa2aedc8a6e88fa10577b138a5650f93d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 15:50:19 -0800 Subject: [PATCH 169/452] Un-comment angle_precise(). Not used, but no reason to comment out. --- firmware/baseband/dsp_demodulate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/dsp_demodulate.cpp b/firmware/baseband/dsp_demodulate.cpp index 4ee6ed688..bc11e990c 100644 --- a/firmware/baseband/dsp_demodulate.cpp +++ b/firmware/baseband/dsp_demodulate.cpp @@ -72,11 +72,11 @@ static inline float angle_approx_0deg27(const complex32_t t) { const auto x = static_cast(t.imag()) / static_cast(t.real()); return x / (1.0f + 0.28086f * x * x); } -/* + static inline float angle_precise(const complex32_t t) { return atan2f(t.imag(), t.real()); } -*/ + buffer_s16_t FM::execute( buffer_c16_t src, buffer_s16_t dst From 4ee038553036466bd079d49011a9fd17a1602cbb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 15:51:20 -0800 Subject: [PATCH 170/452] Add FM class default constructor. For classes that configure FM demodulation at runtime. --- firmware/baseband/dsp_demodulate.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/firmware/baseband/dsp_demodulate.hpp b/firmware/baseband/dsp_demodulate.hpp index c5f871e14..51c9504d3 100644 --- a/firmware/baseband/dsp_demodulate.hpp +++ b/firmware/baseband/dsp_demodulate.hpp @@ -37,6 +37,12 @@ public: class FM { public: + constexpr FM( + ) : z_ { 0 }, + k { 0 } + { + } + /* * angle: -pi to pi. output range: -32768 to 32767. * Maximum delta-theta (output of atan2) at maximum deviation frequency: From ef7aeaafa9bedb2e3166101c9d104bfe5db7a05d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 15:56:51 -0800 Subject: [PATCH 171/452] Tweak (and document!) audio HPF IIR. --- firmware/baseband/dsp_iir_config.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index e20a51fce..961900c14 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -24,9 +24,10 @@ #include "dsp_iir.hpp" +// scipy.signal.butter(2, 300 / 24000.0, 'highpass', analog=False) constexpr iir_biquad_config_t audio_hpf_config { - { 0.93346032f, -1.86687724f, 0.93346032f }, - { 1.0f , -1.97730264f, 0.97773668f } + { 0.97261390f, -1.94522780f, 0.97261390f, }, + { 1.00000000f, -1.94447766f, 0.94597794f, } }; constexpr iir_biquad_config_t non_audio_hpf_config { From 7ec1a1f85bd5313944b83d2f0fef1a77db5d7066 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 16:24:43 -0800 Subject: [PATCH 172/452] Move comment about FM squelch IIR filter. --- firmware/baseband/dsp_iir_config.hpp | 1 + firmware/baseband/dsp_squelch.hpp | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index 961900c14..d238c6d23 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -30,6 +30,7 @@ constexpr iir_biquad_config_t audio_hpf_config { { 1.00000000f, -1.94447766f, 0.94597794f, } }; +// scipy.signal.iirdesign(wp=8000 / 24000.0, ws= 4000 / 24000.0, gpass=1, gstop=18, ftype='ellip') constexpr iir_biquad_config_t non_audio_hpf_config { { 0.51891061f, -0.95714180f, 0.51891061f }, { 1.0f , -0.79878302f, 0.43960231f } diff --git a/firmware/baseband/dsp_squelch.hpp b/firmware/baseband/dsp_squelch.hpp index 06cb2cdd7..37cf68a30 100644 --- a/firmware/baseband/dsp_squelch.hpp +++ b/firmware/baseband/dsp_squelch.hpp @@ -37,8 +37,6 @@ private: static constexpr size_t N = 32; static constexpr int16_t threshold = 3072; - // nyquist = 48000 / 2.0 - // scipy.signal.iirdesign(wp=8000 / nyquist, ws= 4000 / nyquist, gpass=1, gstop=18, ftype='ellip') IIRBiquadFilter non_audio_hpf { non_audio_hpf_config }; }; From 8453741252655499d20fe358080bed72233bc1f1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 16:33:26 -0800 Subject: [PATCH 173/452] Saturate IIR filter output to int16_t. --- firmware/baseband/dsp_iir.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/dsp_iir.hpp b/firmware/baseband/dsp_iir.hpp index 8fb12f055..895cb3122 100644 --- a/firmware/baseband/dsp_iir.hpp +++ b/firmware/baseband/dsp_iir.hpp @@ -45,7 +45,9 @@ public: void execute(buffer_s16_t buffer_in, buffer_s16_t buffer_out) { // TODO: Assert that buffer_out.count == buffer_in.count. for(size_t i=0; i Date: Mon, 28 Dec 2015 16:49:31 -0800 Subject: [PATCH 174/452] Improve argument and retval types for my M4 SIMD intrinsics. --- .../os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/firmware/chibios-portapack/os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h b/firmware/chibios-portapack/os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h index 592ed3de8..bfbcda282 100644 --- a/firmware/chibios-portapack/os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h +++ b/firmware/chibios-portapack/os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h @@ -134,34 +134,34 @@ typedef enum IRQn { /* Overload of __SXTB16() to add ROR argument, since using __ROR() as an * argument to the existing __SXTB16() doesn't produce optimum/sane code. */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t rm, uint32_t ror) +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SXTB16(uint32_t rm, uint32_t ror) { - uint32_t rd; + int32_t rd; __ASM volatile ("sxtb16 %0, %1, ror %2" : "=r" (rd) : "r" (rm), "I" (ror)); return rd; } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTH(uint32_t rm, uint32_t ror) +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SXTH(uint32_t rm, uint32_t ror) { - uint32_t rd; + int32_t rd; __ASM volatile ("sxth %0, %1, ror %2" : "=r" (rd) : "r" (rm), "I" (ror)); return rd; } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLATB(uint32_t rm, uint32_t rs, uint32_t rn) { - uint32_t rd; +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SMLATB(uint32_t rm, uint32_t rs, uint32_t rn) { + int32_t rd; __ASM volatile ("smlatb %0, %1, %2, %3" : "=r" (rd) : "r" (rm), "r" (rs), "r" (rn)); return rd; } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLABB(uint32_t rm, uint32_t rs, uint32_t rn) { - uint32_t rd; +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SMLABB(uint32_t rm, uint32_t rs, uint32_t rn) { + int32_t rd; __ASM volatile("smlabb %0, %1, %2, %3" : "=r" (rd) : "r" (rm), "r" (rs), "r" (rn)); return rd; } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAH(uint32_t rn, uint32_t rm, uint32_t ror) { - uint32_t rd; +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SXTAH(uint32_t rn, uint32_t rm, uint32_t ror) { + int32_t rd; __ASM volatile("sxtah %0, %1, %2, ror %3" : "=r" (rd) : "r" (rn), "r" (rm), "I" (ror)); return rd; } @@ -172,37 +172,37 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __BFI(uint32_t rd, u return rd; } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMULBB(uint32_t op1, uint32_t op2) { - uint32_t result; +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SMULBB(uint32_t op1, uint32_t op2) { + int32_t result; __ASM volatile ("smulbb %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return result; } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMULBT(uint32_t op1, uint32_t op2) { - uint32_t result; +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SMULBT(uint32_t op1, uint32_t op2) { + int32_t result; __ASM volatile ("smulbt %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return result; } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMULTB(uint32_t op1, uint32_t op2) { - uint32_t result; +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SMULTB(uint32_t op1, uint32_t op2) { + int32_t result; __ASM volatile ("smultb %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return result; } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMULTT(uint32_t op1, uint32_t op2) { - uint32_t result; +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SMULTT(uint32_t op1, uint32_t op2) { + int32_t result; __ASM volatile ("smultt %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); return result; } #undef __SMLALD -__attribute__( ( always_inline ) ) static inline uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +__attribute__( ( always_inline ) ) static inline int64_t __SMLALD (uint32_t op1, uint32_t op2, int64_t acc) { union llreg_u{ uint32_t w32[2]; - uint64_t w64; + int64_t w64; } llr; llr.w64 = acc; @@ -213,11 +213,11 @@ __attribute__( ( always_inline ) ) static inline uint64_t __SMLALD (uint32_t op1 #undef __SMLALDX -__attribute__( ( always_inline ) ) static inline uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +__attribute__( ( always_inline ) ) static inline int64_t __SMLALDX (uint32_t op1, uint32_t op2, int64_t acc) { union llreg_u{ uint32_t w32[2]; - uint64_t w64; + int64_t w64; } llr; llr.w64 = acc; @@ -228,11 +228,11 @@ __attribute__( ( always_inline ) ) static inline uint64_t __SMLALDX (uint32_t op #undef __SMLSLD -__attribute__( ( always_inline ) ) static inline uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +__attribute__( ( always_inline ) ) static inline int64_t __SMLSLD (uint32_t op1, uint32_t op2, int64_t acc) { union llreg_u{ uint32_t w32[2]; - uint64_t w64; + int64_t w64; } llr; llr.w64 = acc; From 9505d367c3ce249c9d786ced7bfbe6180536b39a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 16:50:01 -0800 Subject: [PATCH 175/452] Add SMMULR "intrinsic". --- .../os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/firmware/chibios-portapack/os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h b/firmware/chibios-portapack/os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h index bfbcda282..25f569079 100644 --- a/firmware/chibios-portapack/os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h +++ b/firmware/chibios-portapack/os/hal/platforms/LPC43xx_M4/lpc43xx_m4.h @@ -241,6 +241,14 @@ __attribute__( ( always_inline ) ) static inline int64_t __SMLSLD (uint32_t op1, return(llr.w64); } +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __SMMULR (int32_t op1, int32_t op2) +{ + uint32_t result; + + __ASM volatile ("smmulr %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + #endif /* __cplusplus */ #endif /* __LPC43XX_M4_H */ From f74e6690cbee4fc6bc66286b26332b722397cf72 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 16:51:34 -0800 Subject: [PATCH 176/452] Utilize class types for member variables -- slightly more generic. --- firmware/common/complex.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/common/complex.hpp b/firmware/common/complex.hpp index 06d787bd8..645a9b439 100644 --- a/firmware/common/complex.hpp +++ b/firmware/common/complex.hpp @@ -66,8 +66,8 @@ public: private: union { - int8_t _v[2]; - uint16_t _rep; + value_type _v[2]; + rep_type _rep; }; }; @@ -121,8 +121,8 @@ public: private: union { - int16_t _v[2]; - uint32_t _rep; + value_type _v[2]; + rep_type _rep; }; }; From 87c97721283a08627f8a8c55c619a0bdc66c6396 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Dec 2015 16:52:10 -0800 Subject: [PATCH 177/452] More M4 instruction wrappers, with vector typed arguments. --- firmware/common/simd.hpp | 108 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 firmware/common/simd.hpp diff --git a/firmware/common/simd.hpp b/firmware/common/simd.hpp new file mode 100644 index 000000000..0d65b8dd5 --- /dev/null +++ b/firmware/common/simd.hpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __SIMD_H__ +#define __SIMD_H__ + +#if defined(LPC43XX_M4) + +#include + +#include + +struct vec4_s8 { + union { + int8_t v[4]; + uint32_t w; + }; +}; + +struct vec2_s16 { + constexpr vec2_s16( + ) : v { 0, 0 } + { + } + + constexpr vec2_s16( + const int16_t v0, + const int16_t v1 + ) : v { v0, v1 } + { + } + + constexpr vec2_s16( + const vec2_s16& other + ) : w { other.w } + { + } + + vec2_s16& operator=(const vec2_s16& other) { + w = other.w; + return *this; + } + + union { + int16_t v[2]; + uint32_t w; + }; +}; + +static inline vec4_s8 rev16(const vec4_s8 v) { + vec4_s8 result; + result.w = __REV16(v.w); + return result; +} + +static inline vec4_s8 pkhbt(const vec4_s8 v1, const vec4_s8 v2, const size_t sh = 0) { + vec4_s8 result; + result.w = __PKHBT(v1.w, v2.w, sh); + return result; +} + +static inline vec2_s16 pkhbt(const vec2_s16 v1, const vec2_s16 v2, const size_t sh = 0) { + vec2_s16 result; + result.w = __PKHBT(v1.w, v2.w, sh); + return result; +} + +static inline vec2_s16 pkhtb(const vec2_s16 v1, const vec2_s16 v2, const size_t sh = 0) { + vec2_s16 result; + result.w = __PKHTB(v1.w, v2.w, sh); + return result; +} + +static inline vec2_s16 sxtb16(const vec4_s8 v, const size_t sh = 0) { + vec2_s16 result; + result.w = __SXTB16(v.w, sh); + return result; +} + +static inline int32_t smlsd(const vec2_s16 v1, const vec2_s16 v2, const int32_t accum) { + return __SMLSD(v1.w, v2.w, accum); +} + +static inline int32_t smlad(const vec2_s16 v1, const vec2_s16 v2, const int32_t accum) { + return __SMLAD(v1.w, v2.w, accum); +} + +#endif /* defined(LPC43XX_M4) */ + +#endif/*__SIMD_H__*/ From 549e5b9ddc68f075b2995e50766ba697bca88cd5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 29 Dec 2015 10:48:29 -0800 Subject: [PATCH 178/452] Unrolled FIR filters for more flexible baseband filtering (using IFIR technique). --- firmware/baseband/dsp_decimate.cpp | 278 +++++++++++++++++++++++++++++ firmware/baseband/dsp_decimate.hpp | 60 +++++++ 2 files changed, 338 insertions(+) diff --git a/firmware/baseband/dsp_decimate.cpp b/firmware/baseband/dsp_decimate.cpp index eef3f857a..5698b33df 100644 --- a/firmware/baseband/dsp_decimate.cpp +++ b/firmware/baseband/dsp_decimate.cpp @@ -26,6 +26,284 @@ namespace dsp { namespace decimate { +static inline complex32_t mac_fs4_shift( + const vec2_s16* const z, + const vec2_s16* const t, + const size_t index, + const complex32_t accum +) { + /* Accumulate sample * tap results for samples already in z buffer. + * Multiply using swap/negation to achieve Fs/4 shift. + * For iterations where samples are shifting out of z buffer (being discarded). + * Expect negated tap t[2] to accomodate instruction set limitations. + */ + const bool negated_t2 = index & 1; + const auto q1_i0 = z[index*2 + 0]; + const auto i1_q0 = z[index*2 + 1]; + const auto t1_t0 = t[index]; + const auto real = negated_t2 ? smlsd(q1_i0, t1_t0, accum.real()) : smlad(q1_i0, t1_t0, accum.real()); + const auto imag = negated_t2 ? smlad(i1_q0, t1_t0, accum.imag()) : smlsd(i1_q0, t1_t0, accum.imag()); + return { real, imag }; +} + +static inline complex32_t mac_shift( + const vec2_s16* const z, + const vec2_s16* const t, + const size_t index, + const complex32_t accum +) { + /* Accumulate sample * tap results for samples already in z buffer. + * For iterations where samples are shifting out of z buffer (being discarded). + * real += i1 * t1 + i0 * t0 + * imag += q1 * t1 + q0 * t0 + */ + const auto i1_i0 = z[index*2 + 0]; + const auto q1_q0 = z[index*2 + 1]; + const auto t1_t0 = t[index]; + const auto real = smlad(i1_i0, t1_t0, accum.real()); + const auto imag = smlad(q1_q0, t1_t0, accum.imag()); + return { real, imag }; +} + +static inline complex32_t mac_fs4_shift_and_store( + vec2_s16* const z, + const vec2_s16* const t, + const size_t decimation_factor, + const size_t index, + const complex32_t accum +) { + /* Accumulate sample * tap results for samples already in z buffer. + * Place new samples into z buffer. + * Expect negated tap t[2] to accomodate instruction set limitations. + */ + const bool negated_t2 = index & 1; + const auto q1_i0 = z[decimation_factor + index*2 + 0]; + const auto i1_q0 = z[decimation_factor + index*2 + 1]; + const auto t1_t0 = t[decimation_factor / 2 + index]; + z[index*2 + 0] = q1_i0; + const auto real = negated_t2 ? smlsd(q1_i0, t1_t0, accum.real()) : smlad(q1_i0, t1_t0, accum.real()); + z[index*2 + 1] = i1_q0; + const auto imag = negated_t2 ? smlad(i1_q0, t1_t0, accum.imag()) : smlsd(i1_q0, t1_t0, accum.imag()); + return { real, imag }; +} + +static inline complex32_t mac_shift_and_store( + vec2_s16* const z, + const vec2_s16* const t, + const size_t decimation_factor, + const size_t index, + const complex32_t accum +) { + /* Accumulate sample * tap results for samples already in z buffer. + * Place new samples into z buffer. + * Expect negated tap t[2] to accomodate instruction set limitations. + */ + const auto i1_i0 = z[decimation_factor + index*2 + 0]; + const auto q1_q0 = z[decimation_factor + index*2 + 1]; + const auto t1_t0 = t[decimation_factor / 2 + index]; + z[index*2 + 0] = i1_i0; + const auto real = smlad(i1_i0, t1_t0, accum.real()); + z[index*2 + 1] = q1_q0; + const auto imag = smlad(q1_q0, t1_t0, accum.imag()); + return { real, imag }; +} + +static inline complex32_t mac_fs4_shift_and_store_new_c8_samples( + vec2_s16* const z, + const vec2_s16* const t, + const vec4_s8* const in, + const size_t decimation_factor, + const size_t index, + const size_t length, + const complex32_t accum +) { + /* Accumulate sample * tap results for new samples. + * Place new samples into z buffer. + * Expect negated tap t[2] to accomodate instruction set limitations. + */ + const bool negated_t2 = index & 1; + const auto q1_i1_q0_i0 = in[index]; + const auto t1_t0 = t[(length - decimation_factor) / 2 + index]; + const auto i1_q1_i0_q0 = rev16(q1_i1_q0_i0); + const auto i1_q1_q0_i0 = pkhbt(q1_i1_q0_i0, i1_q1_i0_q0); + const auto q1_i0 = sxtb16(i1_q1_q0_i0); + const auto i1_q0 = sxtb16(i1_q1_q0_i0, 8); + z[length - decimation_factor * 2 + index*2 + 0] = q1_i0; + const auto real = negated_t2 ? smlsd(q1_i0, t1_t0, accum.real()) : smlad(q1_i0, t1_t0, accum.real()); + z[length - decimation_factor * 2 + index*2 + 1] = i1_q0; + const auto imag = negated_t2 ? smlad(i1_q0, t1_t0, accum.imag()) : smlsd(i1_q0, t1_t0, accum.imag()); + return { real, imag }; +} + +static inline complex32_t mac_shift_and_store_new_c16_samples( + vec2_s16* const z, + const vec2_s16* const t, + const vec2_s16* const in, + const size_t decimation_factor, + const size_t index, + const size_t length, + const complex32_t accum +) { + /* Accumulate sample * tap results for new samples. + * Place new samples into z buffer. + * Expect negated tap t[2] to accomodate instruction set limitations. + */ + const auto q0_i0 = in[index*2+0]; + const auto q1_i1 = in[index*2+1]; + const auto i1_i0 = pkhbt(q0_i0, q1_i1, 16); + const auto q1_q0 = pkhtb(q1_i1, q0_i0, 16); + const auto t1_t0 = t[(length - decimation_factor) / 2 + index]; + z[length - decimation_factor * 2 + index*2 + 0] = i1_i0; + const auto real = smlad(i1_i0, t1_t0, accum.real()); + z[length - decimation_factor * 2 + index*2 + 1] = q1_q0; + const auto imag = smlad(q1_q0, t1_t0, accum.imag()); + return { real, imag }; +} + +static inline uint32_t scale_round_and_pack( + const complex32_t value, + const int32_t scale_factor +) { + /* Multiply 32-bit components of the complex by a scale factor, + * into int64_ts, then round to nearest LSB (1 << 32), saturate to 16 bits, + * and pack into a complex. + */ + const auto scaled_real = __SMMULR(value.real(), scale_factor); + const auto saturated_real = __SSAT(scaled_real, 16); + + const auto scaled_imag = __SMMULR(value.imag(), scale_factor); + const auto saturated_imag = __SSAT(scaled_imag, 16); + + return __PKHBT(saturated_real, saturated_imag, 16); +} + +// FIRC8xR16x24FS4Decim8 ////////////////////////////////////////////////// + +FIRC8xR16x24FS4Decim8::FIRC8xR16x24FS4Decim8() { + z_.fill({}); +} + +void FIRC8xR16x24FS4Decim8::configure( + const std::array& taps, + const int32_t scale, + const Shift shift +) { + const int negate_factor = (shift == Shift::Up) ? -1 : 1; + for(size_t i=0; i(__builtin_assume_aligned(z_.data(), 4)); + const vec2_s16* const t = static_cast(__builtin_assume_aligned(taps_.data(), 4)); + uint32_t* const d = static_cast(__builtin_assume_aligned(dst.p, 4)); + + const auto k = output_scale; + + const size_t count = src.count / decimation_factor; + for(size_t i=0; i(__builtin_assume_aligned(&src.p[i * decimation_factor], 4)); + + complex32_t accum; + + // Oldest samples are discarded. + accum = mac_fs4_shift(z, t, 0, accum); + accum = mac_fs4_shift(z, t, 1, accum); + accum = mac_fs4_shift(z, t, 2, accum); + accum = mac_fs4_shift(z, t, 3, accum); + + // Middle samples are shifted earlier in the "z" delay buffer. + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 0, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 1, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 2, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 3, accum); + + // Newest samples come from "in" buffer, are copied to "z" delay buffer. + accum = mac_fs4_shift_and_store_new_c8_samples(z, t, in, decimation_factor, 0, taps_count, accum); + accum = mac_fs4_shift_and_store_new_c8_samples(z, t, in, decimation_factor, 1, taps_count, accum); + accum = mac_fs4_shift_and_store_new_c8_samples(z, t, in, decimation_factor, 2, taps_count, accum); + accum = mac_fs4_shift_and_store_new_c8_samples(z, t, in, decimation_factor, 3, taps_count, accum); + + d[i] = scale_round_and_pack(accum, k); + } + + return { + dst.p, + count, + src.sampling_rate / decimation_factor + }; +} + +// FIRC16xR16x32Decim8 //////////////////////////////////////////////////// + +FIRC16xR16x32Decim8::FIRC16xR16x32Decim8() { + z_.fill({}); +} + +void FIRC16xR16x32Decim8::configure( + const std::array& taps, + const int32_t scale +) { + std::copy(taps.cbegin(), taps.cend(), taps_.begin()); + output_scale = scale; +} + +buffer_c16_t FIRC16xR16x32Decim8::execute( + buffer_c16_t src, + buffer_c16_t dst +) { + vec2_s16* const z = static_cast(__builtin_assume_aligned(z_.data(), 4)); + const vec2_s16* const t = static_cast(__builtin_assume_aligned(taps_.data(), 4)); + uint32_t* const d = static_cast(__builtin_assume_aligned(dst.p, 4)); + + const auto k = output_scale; + + const size_t count = src.count / decimation_factor; + for(size_t i=0; i(__builtin_assume_aligned(&src.p[i * decimation_factor], 4)); + + complex32_t accum; + + // Oldest samples are discarded. + accum = mac_shift(z, t, 0, accum); + accum = mac_shift(z, t, 1, accum); + accum = mac_shift(z, t, 2, accum); + accum = mac_shift(z, t, 3, accum); + + // Middle samples are shifted earlier in the "z" delay buffer. + accum = mac_shift_and_store(z, t, decimation_factor, 0, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 1, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 2, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 3, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 4, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 5, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 6, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 7, accum); + + // Newest samples come from "in" buffer, are copied to "z" delay buffer. + accum = mac_shift_and_store_new_c16_samples(z, t, in, decimation_factor, 0, taps_count, accum); + accum = mac_shift_and_store_new_c16_samples(z, t, in, decimation_factor, 1, taps_count, accum); + accum = mac_shift_and_store_new_c16_samples(z, t, in, decimation_factor, 2, taps_count, accum); + accum = mac_shift_and_store_new_c16_samples(z, t, in, decimation_factor, 3, taps_count, accum); + + d[i] = scale_round_and_pack(accum, k); + } + + return { + dst.p, + count, + src.sampling_rate / decimation_factor + }; +} + buffer_c16_t Complex8DecimateBy2CIC3::execute(buffer_c8_t src, buffer_c16_t dst) { /* Decimates by two using a non-recursive third-order CIC filter. */ diff --git a/firmware/baseband/dsp_decimate.hpp b/firmware/baseband/dsp_decimate.hpp index 4b392cada..5079f2597 100644 --- a/firmware/baseband/dsp_decimate.hpp +++ b/firmware/baseband/dsp_decimate.hpp @@ -31,6 +31,8 @@ #include "dsp_types.hpp" +#include "simd.hpp" + namespace dsp { namespace decimate { @@ -90,6 +92,64 @@ private: const std::array& taps; }; +class FIRC8xR16x24FS4Decim8 { +public: + static constexpr size_t taps_count = 24; + static constexpr size_t decimation_factor = 8; + + using sample_t = complex8_t; + using tap_t = int16_t; + + enum class Shift : bool { + Down = true, + Up = false + }; + + FIRC8xR16x24FS4Decim8(); + + void configure( + const std::array& taps, + const int32_t scale, + const Shift shift = Shift::Down + ); + + buffer_c16_t execute( + buffer_c8_t src, + buffer_c16_t dst + ); + +private: + std::array z_; + std::array taps_; + int32_t output_scale = 0; +}; + +class FIRC16xR16x32Decim8 { +public: + static constexpr size_t taps_count = 32; + static constexpr size_t decimation_factor = 8; + + using sample_t = complex16_t; + using tap_t = int16_t; + + FIRC16xR16x32Decim8(); + + void configure( + const std::array& taps, + const int32_t scale + ); + + buffer_c16_t execute( + buffer_c16_t src, + buffer_c16_t dst + ); + +private: + std::array z_; + std::array taps_; + int32_t output_scale = 0; +}; + class FIRAndDecimateComplex { public: using sample_t = complex16_t; From df593c2f0f66f4b81b21c49782904fc3da18b1b9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 29 Dec 2015 10:55:55 -0800 Subject: [PATCH 179/452] Run codec at 1 x baseband sample rate. Do not use CPLD decimator. Codec performance appears to be unaffected by <8MHz sample rate. Saves a bit of power, eliminates dependency on CPLD decimation feature. --- firmware/application/ais_app.cpp | 2 +- firmware/application/analog_audio_app.cpp | 2 +- firmware/application/receiver_model.hpp | 2 +- firmware/application/tpms_app.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 0487a8bdc..13bf711da 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -82,7 +82,7 @@ AISModel::AISModel() { receiver_model.set_baseband_configuration({ .mode = 3, .sampling_rate = 2457600, - .decimation_factor = 4, + .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index f5ec76cff..e27ef1c66 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -30,7 +30,7 @@ AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { receiver_model.set_baseband_configuration({ .mode = toUType(mode), .sampling_rate = 3072000, - .decimation_factor = 4, + .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); } diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index c2479c97a..818a21a60 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -93,7 +93,7 @@ private: BasebandConfiguration baseband_configuration { .mode = 1, /* TODO: Enum! */ .sampling_rate = 3072000, - .decimation_factor = 4, + .decimation_factor = 1, }; volume_t headphone_volume_ { -43.0_dB }; ClockManager& clock_manager; diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 155c8aa9f..85a849c8c 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -30,7 +30,7 @@ TPMSModel::TPMSModel() { receiver_model.set_baseband_configuration({ .mode = 5, .sampling_rate = 2457600, - .decimation_factor = 4, + .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); From bbfcca8ec099ef8e478989f8d012270696498102 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 29 Dec 2015 10:58:53 -0800 Subject: [PATCH 180/452] Rebake of AM, NFM demodulators -- more flexible filtering/configuration. Also make SpectrumCollector dynamically configurable. Add deemphasis filter to NFM. --- firmware/baseband/dsp_iir_config.hpp | 6 + firmware/baseband/proc_am_audio.cpp | 82 ++++++--- firmware/baseband/proc_am_audio.hpp | 19 ++- firmware/baseband/proc_nfm_audio.cpp | 168 ++++++++++++++++--- firmware/baseband/proc_nfm_audio.hpp | 25 ++- firmware/baseband/proc_wideband_spectrum.hpp | 2 +- firmware/baseband/spectrum_collector.cpp | 6 + firmware/baseband/spectrum_collector.hpp | 5 +- 8 files changed, 249 insertions(+), 64 deletions(-) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index d238c6d23..ad9b81f91 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -34,6 +34,12 @@ constexpr iir_biquad_config_t audio_hpf_config { constexpr iir_biquad_config_t non_audio_hpf_config { { 0.51891061f, -0.95714180f, 0.51891061f }, { 1.0f , -0.79878302f, 0.43960231f } + +// scipy.signal.butter(1, 300 / 24000.0, 'lowpass', analog=False) +// NOTE: Technically, order-1 filter, b[2] = a[2] = 0. +constexpr iir_biquad_config_t audio_deemph_300_6_config { + { 0.01925927f, 0.01925927f, 0.00000000f, }, + { 1.00000000f, -0.96148145f, 0.00000000f, }, }; #endif/*__DSP_IIR_CONFIG_H__*/ diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index b2d480c7c..34fb55412 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -21,39 +21,77 @@ #include "proc_am_audio.hpp" -#include +// DSB AM 6K00A3E emission type /////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=3000, stop=339000, decim=8, fout=384000 +static constexpr std::array taps_6k0_decim_0 { { + 39, 104, 224, 412, 674, 1008, 1400, 1821, + 2234, 2594, 2863, 3006, 3006, 2863, 2594, 2234, + 1821, 1400, 1008, 674, 412, 224, 104, 39, +} }; + +// IFIR prototype filter: fs=384000, pass=3000, stop=45000, decim=8, fout=48000 +static constexpr std::array taps_6k0_decim_1 { { + -26, -63, -123, -195, -263, -295, -253, -99, + 199, 651, 1242, 1927, 2633, 3273, 3760, 4023, + 4023, 3760, 3273, 2633, 1927, 1242, 651, 199, + -99, -253, -295, -263, -195, -123, -63, -26, +} }; + +// Channel filter: fs=48000, pass=3000, stop=6700, decim=1, fout=48000 +static constexpr std::array taps_6k0_channel { { + 95, 178, 247, 208, -21, -474, -1080, -1640, + -1857, -1411, -83, 2134, 4978, 7946, 10413, 11815, + 11815, 10413, 7946, 4978, 2134, -83, -1411, -1857, + -1640, -1080, -474, -21, 208, 247, 178, 95, +} }; + +NarrowbandAMAudio::NarrowbandAMAudio() { + constexpr size_t baseband_fs = 3072000; + + constexpr size_t decim_0_input_fs = baseband_fs; + constexpr size_t decim_0_decimation_factor = 8; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; + + constexpr size_t decim_1_input_fs = decim_0_output_fs; + constexpr size_t decim_1_decimation_factor = 8; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; + + constexpr size_t channel_filter_input_fs = decim_1_output_fs; + constexpr size_t channel_filter_decimation_factor = 1; + constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; + + decim_0.configure(taps_6k0_decim_0, 33554432); + decim_1.configure(taps_6k0_decim_1, 131072); + channel_filter.configure(taps_6k0_channel, 1); + channel_filter_pass_f = 3000; + channel_filter_stop_f = 6700; + + channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); +} void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { - auto decimator_out = decimator.execute(buffer); - - const buffer_c16_t work_baseband_buffer { - (complex16_t*)decimator_out.p, - sizeof(*decimator_out.p) * decimator_out.count + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() }; - /* 96kHz complex[64] - * -> FIR filter, 48kHz int16_t[32] */ - auto channel = channel_filter.execute(decimator_out, work_baseband_buffer); + const auto decim_0_out = decim_0.execute(buffer, dst_buffer); + const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); + const auto channel_out = channel_filter.execute(decim_1_out, dst_buffer); // TODO: Feed channel_stats post-decimation data? - feed_channel_stats(channel); - channel_spectrum.feed( - channel, - decimator_out.sampling_rate * channel_filter_taps.pass_frequency_normalized, - decimator_out.sampling_rate * channel_filter_taps.stop_frequency_normalized - ); + feed_channel_stats(channel_out); + channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); const buffer_s16_t work_audio_buffer { - (int16_t*)decimator_out.p, - sizeof(*decimator_out.p) * decimator_out.count + (int16_t*)dst.data(), + sizeof(*dst.data()) * dst.size() }; - /* 48kHz complex[32] - * -> AM demodulation - * -> 48kHz int16_t[32] */ - auto audio = demod.execute(channel, work_audio_buffer); + auto audio = demod.execute(channel_out, work_audio_buffer); audio_hpf.execute_in_place(audio); + fill_audio_buffer(audio); } diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 283f0f7c5..4779384b1 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -33,22 +33,27 @@ #include "spectrum_collector.hpp" +#include +#include + class NarrowbandAMAudio : public BasebandProcessor { public: - NarrowbandAMAudio() { - decimator.set_decimation_factor(ChannelDecimator::DecimationFactor::By32); - channel_filter.configure(channel_filter_taps.taps, 2); - } - + NarrowbandAMAudio(); + void execute(const buffer_c8_t& buffer) override; void on_update_spectrum() override { channel_spectrum.update(); } private: - ChannelDecimator decimator; - const fir_taps_real<64>& channel_filter_taps = taps_64_lp_031_070_tfilter; + std::array dst; + dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; + dsp::decimate::FIRC16xR16x32Decim8 decim_1; dsp::decimate::FIRAndDecimateComplex channel_filter; + uint32_t channel_filter_pass_f; + uint32_t channel_filter_stop_f; + dsp::demodulate::AM demod; + IIRBiquadFilter audio_hpf { audio_hpf_config }; SpectrumCollector channel_spectrum; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 80a400d7f..fe20a03ea 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -24,44 +24,163 @@ #include #include +// NBFM 16K0F3E emission type ///////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=8000, stop=344000, decim=8, fout=384000 +static constexpr std::array taps_16k0_decim_0 { { + 1, 67, 165, 340, 599, 944, 1361, 1820, + 2278, 2684, 2988, 3152, 3152, 2988, 2684, 2278, + 1820, 1361, 944, 599, 340, 165, 67, 1, +} }; + +// IFIR prototype filter: fs=384000, pass=8000, stop=40000, decim=8, fout=48000 +static constexpr std::array taps_16k0_decim_1 { { + -26, -125, -180, -275, -342, -359, -286, -90, + 250, 733, 1337, 2011, 2688, 3289, 3740, 3982, + 3982, 3740, 3289, 2688, 2011, 1337, 733, 250, + -90, -286, -359, -342, -275, -180, -125, -26, +} }; + +// Channel filter: fs=48000, pass=8000, stop=12400, decim=1, fout=48000 +static constexpr std::array taps_16k0_channel { { + -73, -285, -376, -8, 609, 538, -584, -1387, + -148, 2173, 1959, -2146, -5267, -297, 12915, 24737, + 24737, 12915, -297, -5267, -2146, 1959, 2173, -148, + -1387, -584, 538, 609, -8, -376, -285, -73, +} }; + +// NBFM 11K0F3E emission type ///////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=5500, stop=341500, decim=8, fout=384000 +static constexpr std::array taps_11k0_decim_0 { { + 38, 102, 220, 406, 668, 1004, 1397, 1822, + 2238, 2603, 2875, 3020, 3020, 2875, 2603, 2238, + 1822, 1397, 1004, 668, 406, 220, 102, 38, +} }; + +// IFIR prototype filter: fs=384000, pass=5500, stop=42500, decim=8, fout=48000 +static constexpr std::array taps_11k0_decim_1 { { + -42, -87, -157, -234, -298, -318, -255, -75, + 246, 713, 1306, 1976, 2656, 3265, 3724, 3971, + 3971, 3724, 3265, 2656, 1976, 1306, 713, 246, + -75, -255, -318, -298, -234, -157, -87, -42, +} }; + +// Channel filter: fs=48000, pass=5500, stop=8900, decim=1, fout=48000 +static constexpr std::array taps_11k0_channel { { + -68, -345, -675, -867, -582, 247, 1222, 1562, + 634, -1379, -3219, -3068, 310, 6510, 13331, 17795, + 17795, 13331, 6510, 310, -3068, -3219, -1379, 634, + 1562, 1222, 247, -582, -867, -675, -345, -68, +} }; + +/// NBFM 8K50F3E emission type //////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=4250, stop=340250, decim=8, fout=384000 +static constexpr std::array taps_4k25_decim_0 { { + 38, 103, 222, 409, 671, 1006, 1399, 1821, + 2236, 2599, 2868, 3012, 3012, 2868, 2599, 2236, + 1821, 1399, 1006, 671, 409, 222, 103, 38, +} }; + +// IFIR prototype filter: fs=384000, pass=4250, stop=43750, decim=8, fout=48000 +static constexpr std::array taps_4k25_decim_1 { { + -33, -74, -139, -214, -280, -306, -254, -87, + 222, 682, 1274, 1951, 2644, 3268, 3741, 3996, + 3996, 3741, 3268, 2644, 1951, 1274, 682, 222, + -87, -254, -306, -280, -214, -139, -74, -33, +} }; + +// Channel filter: fs=48000, pass=4250, stop=7900, decim=1, fout=48000 +static constexpr std::array taps_4k25_channel { { + -58, -14, 153, 484, 871, 1063, 770, -141, + -1440, -2488, -2435, -614, 3035, 7771, 12226, 14927, + 14927, 12226, 7771, 3035, -614, -2435, -2488, -1440, + -141, 770, 1063, 871, 484, 153, -14, -58, +} }; + +NarrowbandFMAudio::NarrowbandFMAudio() { + set_mode(Mode::Deviation2K5Narrow); +} + +void NarrowbandFMAudio::set_mode(const Mode mode) { + constexpr size_t baseband_fs = 3072000; + + constexpr size_t decim_0_input_fs = baseband_fs; + constexpr size_t decim_0_decimation_factor = 8; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; + + constexpr size_t decim_1_input_fs = decim_0_output_fs; + constexpr size_t decim_1_decimation_factor = 8; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; + + constexpr size_t channel_filter_input_fs = decim_1_output_fs; + constexpr size_t channel_filter_decimation_factor = 1; + constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; + + constexpr size_t demod_input_fs = channel_filter_output_fs; + + switch(mode) { + default: + case Mode::Deviation5K: + decim_0.configure(taps_16k0_decim_0, 33554432); + decim_1.configure(taps_16k0_decim_1, 131072); + channel_filter.configure(taps_16k0_channel, channel_filter_decimation_factor); + demod.configure(demod_input_fs, 5000); + channel_filter_pass_f = 8000; + channel_filter_stop_f = 12400; + break; + + case Mode::Deviation2K5Wide: + decim_0.configure(taps_11k0_decim_0, 33554432); + decim_1.configure(taps_11k0_decim_1, 131072); + channel_filter.configure(taps_11k0_channel, channel_filter_decimation_factor); + demod.configure(demod_input_fs, 2500); + channel_filter_pass_f = 5500; + channel_filter_stop_f = 8900; + break; + + case Mode::Deviation2K5Narrow: + decim_0.configure(taps_4k25_decim_0, 33554432); + decim_1.configure(taps_4k25_decim_1, 131072); + channel_filter.configure(taps_4k25_channel, channel_filter_decimation_factor); + demod.configure(demod_input_fs, 2500); + channel_filter_pass_f = 4250; + channel_filter_stop_f = 7900; + break; + } + + channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); +} + void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { - /* Called every 2048/3072000 second -- 1500Hz. */ - - auto decimator_out = decimator.execute(buffer); - - const buffer_c16_t work_baseband_buffer { - (complex16_t*)decimator_out.p, - sizeof(*decimator_out.p) * decimator_out.count + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() }; - /* 96kHz complex[64] - * -> FIR filter, <6kHz (0.063fs) pass, gain 1.0 - * -> 48kHz int16_t[32] */ - auto channel = channel_filter.execute(decimator_out, work_baseband_buffer); + const auto decim_0_out = decim_0.execute(buffer, dst_buffer); + const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); + const auto channel_out = channel_filter.execute(decim_1_out, dst_buffer); - // TODO: Feed channel_stats post-decimation data? - feed_channel_stats(channel); - channel_spectrum.feed( - channel, - decimator_out.sampling_rate * channel_filter_taps.pass_frequency_normalized, - decimator_out.sampling_rate * channel_filter_taps.stop_frequency_normalized - ); + feed_channel_stats(channel_out); + channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); const buffer_s16_t work_audio_buffer { - (int16_t*)decimator_out.p, - sizeof(*decimator_out.p) * decimator_out.count + (int16_t*)dst.data(), + sizeof(*dst.data()) * dst.size() }; - /* 48kHz complex[32] - * -> FM demodulation - * -> 48kHz int16_t[32] */ - auto audio = demod.execute(channel, work_audio_buffer); + auto audio = demod.execute(channel_out, work_audio_buffer); static uint64_t audio_present_history = 0; const auto audio_present_now = squelch.execute(audio); audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0); const bool audio_present = (audio_present_history != 0); + audio_hpf.execute_in_place(audio); + audio_deemph.execute_in_place(audio); + if( !audio_present ) { // Zero audio buffer. for(size_t i=0; i& channel_filter_taps = taps_64_lp_042_078_tfilter; + std::array dst; + dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; + dsp::decimate::FIRC16xR16x32Decim8 decim_1; + dsp::decimate::FIRAndDecimateComplex channel_filter; - dsp::demodulate::FM demod { 48000, 7500 }; + uint32_t channel_filter_pass_f = 0; + uint32_t channel_filter_stop_f = 0; + + dsp::demodulate::FM demod; IIRBiquadFilter audio_hpf { audio_hpf_config }; + IIRBiquadFilter audio_deemph { audio_deemph_300_6_config }; FMSquelch squelch; SpectrumCollector channel_spectrum; diff --git a/firmware/baseband/proc_wideband_spectrum.hpp b/firmware/baseband/proc_wideband_spectrum.hpp index 283f40e30..b8311c694 100644 --- a/firmware/baseband/proc_wideband_spectrum.hpp +++ b/firmware/baseband/proc_wideband_spectrum.hpp @@ -38,7 +38,7 @@ public: private: size_t sample_count = 0; - SpectrumCollector channel_spectrum { 1 }; + SpectrumCollector channel_spectrum; std::array spectrum; }; diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index dacf45ab6..2c604b2b5 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -29,6 +29,12 @@ #include +void SpectrumCollector::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. diff --git a/firmware/baseband/spectrum_collector.hpp b/firmware/baseband/spectrum_collector.hpp index 203f337ac..52ef1d0e3 100644 --- a/firmware/baseband/spectrum_collector.hpp +++ b/firmware/baseband/spectrum_collector.hpp @@ -33,11 +33,12 @@ class SpectrumCollector { public: constexpr SpectrumCollector( - const size_t decimation_factor = 4 - ) : channel_spectrum_decimator { decimation_factor } + ) : channel_spectrum_decimator { 1 } { } + void set_decimation_factor(const size_t decimation_factor); + void feed( const buffer_c16_t& channel, const uint32_t filter_pass_frequency, From 3db0820b5438085fb1438a5d2f9628230a2960b4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 29 Dec 2015 11:24:23 -0800 Subject: [PATCH 181/452] Remove LOCATE_IN_RAM from DMA IRQ handler Not needed for M4, was causing code to be located in data RAM, and veneers to jump between code and data RAM. Reclaimed a few hundred bytes of code RAM. --- firmware/common/gpdma.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/firmware/common/gpdma.cpp b/firmware/common/gpdma.cpp index b320af913..cdd7a9a36 100644 --- a/firmware/common/gpdma.cpp +++ b/firmware/common/gpdma.cpp @@ -69,7 +69,6 @@ void Channel::configure( extern "C" { -LOCATE_IN_RAM CH_IRQ_HANDLER(DMA_IRQHandler) { CH_IRQ_PROLOGUE(); From 7de80edcd3eeea755817e4c6144dd967b150b8ca Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 30 Dec 2015 12:19:42 -0800 Subject: [PATCH 182/452] Move baseband FIR filter defs to common file. They will likely be shared with multiple decimators/demodulators. Also added normalized filter pass/stop values to each set of taps. --- firmware/baseband/dsp_fir_taps.hpp | 222 ++++++++++++++------------- firmware/baseband/proc_am_audio.cpp | 35 +---- firmware/baseband/proc_nfm_audio.cpp | 105 ++----------- 3 files changed, 132 insertions(+), 230 deletions(-) diff --git a/firmware/baseband/dsp_fir_taps.hpp b/firmware/baseband/dsp_fir_taps.hpp index 9839a9def..68ea1ea86 100644 --- a/firmware/baseband/dsp_fir_taps.hpp +++ b/firmware/baseband/dsp_fir_taps.hpp @@ -34,149 +34,151 @@ struct fir_taps_real { std::array taps; }; -/* 3kHz/6.7kHz @ 96kHz. sum(abs(taps)): 89429 */ -constexpr fir_taps_real<64> taps_64_lp_031_070_tfilter { - .pass_frequency_normalized = 0.031f, - .stop_frequency_normalized = 0.070f, +// NBFM 16K0F3E emission type ///////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=8000, stop=344000, decim=8, fout=384000 +constexpr fir_taps_real<24> taps_16k0_decim_0 { + .pass_frequency_normalized = 8000.0f / 3072000.0f, + .stop_frequency_normalized = 344000.0f / 3072000.0f, .taps = { { - 56, 58, 81, 100, 113, 112, 92, 49, - -21, -120, -244, -389, -543, -692, -819, -903, - -923, -861, -698, -424, -34, 469, 1073, 1756, - 2492, 3243, 3972, 4639, 5204, 5634, 5903, 5995, - 5903, 5634, 5204, 4639, 3972, 3243, 2492, 1756, - 1073, 469, -34, -424, -698, -861, -923, -903, - -819, -692, -543, -389, -244, -120, -21, 49, - 92, 112, 113, 100, 81, 58, 56, 0, + 1, 67, 165, 340, 599, 944, 1361, 1820, + 2278, 2684, 2988, 3152, 3152, 2988, 2684, 2278, + 1820, 1361, 944, 599, 340, 165, 67, 1, } }, }; -/* 4kHz/7.5kHz @ 96kHz. sum(abs(taps)): 96783 */ -constexpr fir_taps_real<64> taps_64_lp_042_078_tfilter { - .pass_frequency_normalized = 0.042f, - .stop_frequency_normalized = 0.078f, +// IFIR prototype filter: fs=384000, pass=8000, stop=40000, decim=8, fout=48000 +constexpr fir_taps_real<32> taps_16k0_decim_1 { + .pass_frequency_normalized = 8000.0f / 384000.0f, + .stop_frequency_normalized = 40000.0f / 384000.0f, .taps = { { - -19, 39, 72, 126, 197, 278, 360, 432, - 478, 485, 438, 327, 152, -82, -359, -651, - -922, -1132, -1236, -1192, -968, -545, 81, 892, - 1852, 2906, 3984, 5012, 5910, 6609, 7053, 7205, - 7053, 6609, 5910, 5012, 3984, 2906, 1852, 892, - 81, -545, -968, -1192, -1236, -1132, -922, -651, - -359, -82, 152, 327, 438, 485, 478, 432, - 360, 278, 197, 126, 72, 39, -19, 0, + -26, -125, -180, -275, -342, -359, -286, -90, + 250, 733, 1337, 2011, 2688, 3289, 3740, 3982, + 3982, 3740, 3289, 2688, 2011, 1337, 733, 250, + -90, -286, -359, -342, -275, -180, -125, -26, } }, }; -/* 5kHz/8.5kHz @ 96kHz. sum(abs(taps)): 101312 */ -constexpr fir_taps_real<64> taps_64_lp_052_089_tfilter { - .pass_frequency_normalized = 0.052f, - .stop_frequency_normalized = 0.089f, +// Channel filter: fs=48000, pass=8000, stop=12400, decim=1, fout=48000 +constexpr fir_taps_real<32> taps_16k0_channel { + .pass_frequency_normalized = 8000.0f / 48000.0f, + .stop_frequency_normalized = 12400.0f / 48000.0f, .taps = { { - -65, -88, -129, -163, -178, -160, -100, 9, - 160, 340, 523, 675, 758, 738, 591, 313, - -76, -533, -987, -1355, -1544, -1472, -1077, -335, - 738, 2078, 3579, 5104, 6502, 7627, 8355, 8608, - 8355, 7627, 6502, 5104, 3579, 2078, 738, -335, - -1077, -1472, -1544, -1355, -987, -533, -76, 313, - 591, 738, 758, 675, 523, 340, 160, 9, - -100, -160, -178, -163, -129, -88, -65, 0, + -73, -285, -376, -8, 609, 538, -584, -1387, + -148, 2173, 1959, -2146, -5267, -297, 12915, 24737, + 24737, 12915, -297, -5267, -2146, 1959, 2173, -148, + -1387, -584, 538, 609, -8, -376, -285, -73, } }, }; -/* 6kHz/9.6kHz @ 96kHz. sum(abs(taps)): 105088 */ -constexpr fir_taps_real<64> taps_64_lp_063_100_tfilter { - .pass_frequency_normalized = 0.063f, - .stop_frequency_normalized = 0.100f, +// NBFM 11K0F3E emission type ///////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=5500, stop=341500, decim=8, fout=384000 +constexpr fir_taps_real<24> taps_11k0_decim_0 { + .pass_frequency_normalized = 5500.0f / 3072000.0f, + .stop_frequency_normalized = 341500.0f / 3072000.0f, .taps = { { - 43, 21, -2, -54, -138, -245, -360, -453, - -493, -451, -309, -73, 227, 535, 776, 876, - 773, 443, -86, -730, -1357, -1801, -1898, -1515, - -585, 869, 2729, 4794, 6805, 8490, 9611, 10004, - 9611, 8490, 6805, 4794, 2729, 869, -585, -1515, - -1898, -1801, -1357, -730, -86, 443, 773, 876, - 776, 535, 227, -73, -309, -451, -493, -453, - -360, -245, -138, -54, -2, 21, 43, 0, + 38, 102, 220, 406, 668, 1004, 1397, 1822, + 2238, 2603, 2875, 3020, 3020, 2875, 2603, 2238, + 1822, 1397, 1004, 668, 406, 220, 102, 38, } }, }; -/* 7kHz/10.4kHz @ 96kHz: sum(abs(taps)): 110157 */ -constexpr fir_taps_real<64> taps_64_lp_073_108_tfilter { - .pass_frequency_normalized = 0.073f, - .stop_frequency_normalized = 0.108f, +// IFIR prototype filter: fs=384000, pass=5500, stop=42500, decim=8, fout=48000 +constexpr fir_taps_real<32> taps_11k0_decim_1 { + .pass_frequency_normalized = 5500.0f / 384000.0f, + .stop_frequency_normalized = 42500.0f / 384000.0f, .taps = { { - 79, 145, 241, 334, 396, 394, 306, 130, - -109, -360, -550, -611, -494, -197, 229, 677, - 1011, 1096, 846, 257, -570, -1436, -2078, -2225, - -1670, -327, 1726, 4245, 6861, 9146, 10704, 11257, - 10704, 9146, 6861, 4245, 1726, -327, -1670, -2225, - -2078, -1436, -570, 257, 846, 1096, 1011, 677, - 229, -197, -494, -611, -550, -360, -109, 130, - 306, 394, 396, 334, 241, 145, 79, 0, + -42, -87, -157, -234, -298, -318, -255, -75, + 246, 713, 1306, 1976, 2656, 3265, 3724, 3971, + 3971, 3724, 3265, 2656, 1976, 1306, 713, 246, + -75, -255, -318, -298, -234, -157, -87, -42, } }, }; -/* 8kHz/11.5kHz @ 96kHz. sum(abs(taps)): 112092 */ -constexpr fir_taps_real<64> taps_64_lp_083_120_tfilter { - .pass_frequency_normalized = 0.083f, - .stop_frequency_normalized = 0.120f, +// Channel filter: fs=48000, pass=5500, stop=8900, decim=1, fout=48000 +constexpr fir_taps_real<32> taps_11k0_channel { + .pass_frequency_normalized = 5500.0f / 48000.0f, + .stop_frequency_normalized = 8900.0f / 48000.0f, .taps = { { - -63, -72, -71, -21, 89, 248, 417, 537, - 548, 407, 124, -237, -563, -723, -621, -238, - 337, 919, 1274, 1201, 617, -382, -1514, -2364, - -2499, -1600, 414, 3328, 6651, 9727, 11899, 12682, - 11899, 9727, 6651, 3328, 414, -1600, -2499, -2364, - -1514, -382, 617, 1201, 1274, 919, 337, -238, - -621, -723, -563, -237, 124, 407, 548, 537, - 417, 248, 89, -21, -71, -72, -63, 0, + -68, -345, -675, -867, -582, 247, 1222, 1562, + 634, -1379, -3219, -3068, 310, 6510, 13331, 17795, + 17795, 13331, 6510, 310, -3068, -3219, -1379, 634, + 1562, 1222, 247, -582, -867, -675, -345, -68, } }, }; -/* 9kHz/12.4kHz @ 96kHz. sum(abs(taps)): 116249 */ -constexpr fir_taps_real<64> taps_64_lp_094_129_tfilter { - .pass_frequency_normalized = 0.094f, - .stop_frequency_normalized = 0.129f, +/// NBFM 8K50F3E emission type //////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=4250, stop=340250, decim=8, fout=384000 +constexpr fir_taps_real<24> taps_4k25_decim_0 { + .pass_frequency_normalized = 4250.0f / 3072000.0f, + .stop_frequency_normalized = 340250.0f / 3072000.0f, .taps = { { - 5, -93, -198, -335, -449, -478, -378, -144, - 166, 444, 563, 440, 82, -395, -788, -892, - -589, 73, 859, 1421, 1431, 734, -530, -1919, - -2798, -2555, -837, 2274, 6220, 10103, 12941, 13981, - 12941, 10103, 6220, 2274, -837, -2555, -2798, -1919, - -530, 734, 1431, 1421, 859, 73, -589, -892, - -788, -395, 82, 440, 563, 444, 166, -144, - -378, -478, -449, -335, -198, -93, 5, 0, + 38, 103, 222, 409, 671, 1006, 1399, 1821, + 2236, 2599, 2868, 3012, 3012, 2868, 2599, 2236, + 1821, 1399, 1006, 671, 409, 222, 103, 38, } }, }; -/* 10kHz/13.4kHz @ 96kHz. sum(abs(taps)): 118511 */ -constexpr fir_taps_real<64> taps_64_lp_104_140_tfilter { - .pass_frequency_normalized = 0.104f, - .stop_frequency_normalized = 0.140f, +// IFIR prototype filter: fs=384000, pass=4250, stop=43750, decim=8, fout=48000 +constexpr fir_taps_real<32> taps_4k25_decim_1 { + .pass_frequency_normalized = 4250.0f / 384000.0f, + .stop_frequency_normalized = 43750.0f / 384000.0f, .taps = { { - 89, 159, 220, 208, 84, -147, -412, -597, - -588, -345, 58, 441, 595, 391, -128, -730, - -1080, -914, -198, 793, 1558, 1594, 678, -942, - -2546, -3187, -2084, 992, 5515, 10321, 13985, 15353, - 13985, 10321, 5515, 992, -2084, -3187, -2546, -942, - 678, 1594, 1558, 793, -198, -914, -1080, -730, - -128, 391, 595, 441, 58, -345, -588, -597, - -412, -147, 84, 208, 220, 159, 89, 0, + -33, -74, -139, -214, -280, -306, -254, -87, + 222, 682, 1274, 1951, 2644, 3268, 3741, 3996, + 3996, 3741, 3268, 2644, 1951, 1274, 682, 222, + -87, -254, -306, -280, -214, -139, -74, -33, } }, }; -/* Wideband FM channel filter - * 103kHz/128kHz @ 768kHz - */ -constexpr fir_taps_real<64> taps_64_lp_130_169_tfilter { - .pass_frequency_normalized = 0.130f, - .stop_frequency_normalized = 0.169f, +// Channel filter: fs=48000, pass=4250, stop=7900, decim=1, fout=48000 +constexpr fir_taps_real<32> taps_4k25_channel { + .pass_frequency_normalized = 4250.0f / 48000.0f, + .stop_frequency_normalized = 7900.0f / 48000.0f, .taps = { { - 100, 127, 62, -157, -470, -707, -678, -332, - 165, 494, 400, -85, -610, -729, -253, 535, - 1026, 734, -263, -1264, -1398, -332, 1316, 2259, - 1447, -988, -3474, -3769, -385, 6230, 13607, 18450, - 18450, 13607, 6230, -385, -3769, -3474, -988, 1447, - 2259, 1316, -332, -1398, -1264, -263, 734, 1026, - 535, -253, -729, -610, -85, 400, 494, 165, - -332, -678, -707, -470, -157, 62, 127, 100, + -58, -14, 153, 484, 871, 1063, 770, -141, + -1440, -2488, -2435, -614, 3035, 7771, 12226, 14927, + 14927, 12226, 7771, 3035, -614, -2435, -2488, -1440, + -141, 770, 1063, 871, 484, 153, -14, -58, + } }, +}; + +// DSB AM 6K00A3E emission type /////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=3000, stop=339000, decim=8, fout=384000 +constexpr fir_taps_real<24> taps_6k0_decim_0 { + .pass_frequency_normalized = 3000.0f / 3072000.0f, + .stop_frequency_normalized = 339000.0f / 3072000.0f, + .taps = { { + 39, 104, 224, 412, 674, 1008, 1400, 1821, + 2234, 2594, 2863, 3006, 3006, 2863, 2594, 2234, + 1821, 1400, 1008, 674, 412, 224, 104, 39, + } }, +}; + +// IFIR prototype filter: fs=384000, pass=3000, stop=45000, decim=8, fout=48000 +constexpr fir_taps_real<32> taps_6k0_decim_1 { + .pass_frequency_normalized = 3000.0f / 384000.0f, + .stop_frequency_normalized = 45000.0f / 384000.0f, + .taps = { { + -26, -63, -123, -195, -263, -295, -253, -99, + 199, 651, 1242, 1927, 2633, 3273, 3760, 4023, + 4023, 3760, 3273, 2633, 1927, 1242, 651, 199, + -99, -253, -295, -263, -195, -123, -63, -26, + } }, +}; + +// Channel filter: fs=48000, pass=3000, stop=6700, decim=1, fout=48000 +constexpr fir_taps_real<32> taps_6k0_channel { + .pass_frequency_normalized = 3000.0f / 48000.0f, + .stop_frequency_normalized = 6700.0f / 48000.0f, + .taps = { { + 95, 178, 247, 208, -21, -474, -1080, -1640, + -1857, -1411, -83, 2134, 4978, 7946, 10413, 11815, + 11815, 10413, 7946, 4978, 2134, -83, -1411, -1857, + -1640, -1080, -474, -21, 208, 247, 178, 95, } }, }; diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 34fb55412..8d8489686 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -21,31 +21,6 @@ #include "proc_am_audio.hpp" -// DSB AM 6K00A3E emission type /////////////////////////////////////////// - -// IFIR image-reject filter: fs=3072000, pass=3000, stop=339000, decim=8, fout=384000 -static constexpr std::array taps_6k0_decim_0 { { - 39, 104, 224, 412, 674, 1008, 1400, 1821, - 2234, 2594, 2863, 3006, 3006, 2863, 2594, 2234, - 1821, 1400, 1008, 674, 412, 224, 104, 39, -} }; - -// IFIR prototype filter: fs=384000, pass=3000, stop=45000, decim=8, fout=48000 -static constexpr std::array taps_6k0_decim_1 { { - -26, -63, -123, -195, -263, -295, -253, -99, - 199, 651, 1242, 1927, 2633, 3273, 3760, 4023, - 4023, 3760, 3273, 2633, 1927, 1242, 651, 199, - -99, -253, -295, -263, -195, -123, -63, -26, -} }; - -// Channel filter: fs=48000, pass=3000, stop=6700, decim=1, fout=48000 -static constexpr std::array taps_6k0_channel { { - 95, 178, 247, 208, -21, -474, -1080, -1640, - -1857, -1411, -83, 2134, 4978, 7946, 10413, 11815, - 11815, 10413, 7946, 4978, 2134, -83, -1411, -1857, - -1640, -1080, -474, -21, 208, 247, 178, 95, -} }; - NarrowbandAMAudio::NarrowbandAMAudio() { constexpr size_t baseband_fs = 3072000; @@ -61,11 +36,11 @@ NarrowbandAMAudio::NarrowbandAMAudio() { constexpr size_t channel_filter_decimation_factor = 1; constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; - decim_0.configure(taps_6k0_decim_0, 33554432); - decim_1.configure(taps_6k0_decim_1, 131072); - channel_filter.configure(taps_6k0_channel, 1); - channel_filter_pass_f = 3000; - channel_filter_stop_f = 6700; + decim_0.configure(taps_6k0_decim_0.taps, 33554432); + decim_1.configure(taps_6k0_decim_1.taps, 131072); + channel_filter.configure(taps_6k0_channel.taps, 1); + channel_filter_pass_f = taps_6k0_channel.pass_frequency_normalized * channel_filter_input_fs; + channel_filter_stop_f = taps_6k0_channel.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); } diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index fe20a03ea..ecd17a134 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -24,81 +24,6 @@ #include #include -// NBFM 16K0F3E emission type ///////////////////////////////////////////// - -// IFIR image-reject filter: fs=3072000, pass=8000, stop=344000, decim=8, fout=384000 -static constexpr std::array taps_16k0_decim_0 { { - 1, 67, 165, 340, 599, 944, 1361, 1820, - 2278, 2684, 2988, 3152, 3152, 2988, 2684, 2278, - 1820, 1361, 944, 599, 340, 165, 67, 1, -} }; - -// IFIR prototype filter: fs=384000, pass=8000, stop=40000, decim=8, fout=48000 -static constexpr std::array taps_16k0_decim_1 { { - -26, -125, -180, -275, -342, -359, -286, -90, - 250, 733, 1337, 2011, 2688, 3289, 3740, 3982, - 3982, 3740, 3289, 2688, 2011, 1337, 733, 250, - -90, -286, -359, -342, -275, -180, -125, -26, -} }; - -// Channel filter: fs=48000, pass=8000, stop=12400, decim=1, fout=48000 -static constexpr std::array taps_16k0_channel { { - -73, -285, -376, -8, 609, 538, -584, -1387, - -148, 2173, 1959, -2146, -5267, -297, 12915, 24737, - 24737, 12915, -297, -5267, -2146, 1959, 2173, -148, - -1387, -584, 538, 609, -8, -376, -285, -73, -} }; - -// NBFM 11K0F3E emission type ///////////////////////////////////////////// - -// IFIR image-reject filter: fs=3072000, pass=5500, stop=341500, decim=8, fout=384000 -static constexpr std::array taps_11k0_decim_0 { { - 38, 102, 220, 406, 668, 1004, 1397, 1822, - 2238, 2603, 2875, 3020, 3020, 2875, 2603, 2238, - 1822, 1397, 1004, 668, 406, 220, 102, 38, -} }; - -// IFIR prototype filter: fs=384000, pass=5500, stop=42500, decim=8, fout=48000 -static constexpr std::array taps_11k0_decim_1 { { - -42, -87, -157, -234, -298, -318, -255, -75, - 246, 713, 1306, 1976, 2656, 3265, 3724, 3971, - 3971, 3724, 3265, 2656, 1976, 1306, 713, 246, - -75, -255, -318, -298, -234, -157, -87, -42, -} }; - -// Channel filter: fs=48000, pass=5500, stop=8900, decim=1, fout=48000 -static constexpr std::array taps_11k0_channel { { - -68, -345, -675, -867, -582, 247, 1222, 1562, - 634, -1379, -3219, -3068, 310, 6510, 13331, 17795, - 17795, 13331, 6510, 310, -3068, -3219, -1379, 634, - 1562, 1222, 247, -582, -867, -675, -345, -68, -} }; - -/// NBFM 8K50F3E emission type //////////////////////////////////////////// - -// IFIR image-reject filter: fs=3072000, pass=4250, stop=340250, decim=8, fout=384000 -static constexpr std::array taps_4k25_decim_0 { { - 38, 103, 222, 409, 671, 1006, 1399, 1821, - 2236, 2599, 2868, 3012, 3012, 2868, 2599, 2236, - 1821, 1399, 1006, 671, 409, 222, 103, 38, -} }; - -// IFIR prototype filter: fs=384000, pass=4250, stop=43750, decim=8, fout=48000 -static constexpr std::array taps_4k25_decim_1 { { - -33, -74, -139, -214, -280, -306, -254, -87, - 222, 682, 1274, 1951, 2644, 3268, 3741, 3996, - 3996, 3741, 3268, 2644, 1951, 1274, 682, 222, - -87, -254, -306, -280, -214, -139, -74, -33, -} }; - -// Channel filter: fs=48000, pass=4250, stop=7900, decim=1, fout=48000 -static constexpr std::array taps_4k25_channel { { - -58, -14, 153, 484, 871, 1063, 770, -141, - -1440, -2488, -2435, -614, 3035, 7771, 12226, 14927, - 14927, 12226, 7771, 3035, -614, -2435, -2488, -1440, - -141, 770, 1063, 871, 484, 153, -14, -58, -} }; - NarrowbandFMAudio::NarrowbandFMAudio() { set_mode(Mode::Deviation2K5Narrow); } @@ -123,30 +48,30 @@ void NarrowbandFMAudio::set_mode(const Mode mode) { switch(mode) { default: case Mode::Deviation5K: - decim_0.configure(taps_16k0_decim_0, 33554432); - decim_1.configure(taps_16k0_decim_1, 131072); - channel_filter.configure(taps_16k0_channel, channel_filter_decimation_factor); + decim_0.configure(taps_16k0_decim_0.taps, 33554432); + decim_1.configure(taps_16k0_decim_1.taps, 131072); + channel_filter.configure(taps_16k0_channel.taps, channel_filter_decimation_factor); demod.configure(demod_input_fs, 5000); - channel_filter_pass_f = 8000; - channel_filter_stop_f = 12400; + channel_filter_pass_f = taps_16k0_channel.pass_frequency_normalized * channel_filter_input_fs; + channel_filter_stop_f = taps_16k0_channel.stop_frequency_normalized * channel_filter_input_fs; break; case Mode::Deviation2K5Wide: - decim_0.configure(taps_11k0_decim_0, 33554432); - decim_1.configure(taps_11k0_decim_1, 131072); - channel_filter.configure(taps_11k0_channel, channel_filter_decimation_factor); + decim_0.configure(taps_11k0_decim_0.taps, 33554432); + decim_1.configure(taps_11k0_decim_1.taps, 131072); + channel_filter.configure(taps_11k0_channel.taps, channel_filter_decimation_factor); demod.configure(demod_input_fs, 2500); - channel_filter_pass_f = 5500; - channel_filter_stop_f = 8900; + channel_filter_pass_f = taps_11k0_channel.pass_frequency_normalized * channel_filter_input_fs; + channel_filter_stop_f = taps_11k0_channel.stop_frequency_normalized * channel_filter_input_fs; break; case Mode::Deviation2K5Narrow: - decim_0.configure(taps_4k25_decim_0, 33554432); - decim_1.configure(taps_4k25_decim_1, 131072); - channel_filter.configure(taps_4k25_channel, channel_filter_decimation_factor); + decim_0.configure(taps_4k25_decim_0.taps, 33554432); + decim_1.configure(taps_4k25_decim_1.taps, 131072); + channel_filter.configure(taps_4k25_channel.taps, channel_filter_decimation_factor); demod.configure(demod_input_fs, 2500); - channel_filter_pass_f = 4250; - channel_filter_stop_f = 7900; + channel_filter_pass_f = taps_4k25_channel.pass_frequency_normalized * channel_filter_input_fs; + channel_filter_stop_f = taps_4k25_channel.stop_frequency_normalized * channel_filter_input_fs; break; } From 09623431902745f3f3fa0f6a12e865a52dd65599 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 30 Dec 2015 12:20:25 -0800 Subject: [PATCH 183/452] Use decimation variable, not hard-coded value. Break in form from NBFM code. --- firmware/baseband/proc_am_audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 8d8489686..603155e40 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -38,7 +38,7 @@ NarrowbandAMAudio::NarrowbandAMAudio() { decim_0.configure(taps_6k0_decim_0.taps, 33554432); decim_1.configure(taps_6k0_decim_1.taps, 131072); - channel_filter.configure(taps_6k0_channel.taps, 1); + channel_filter.configure(taps_6k0_channel.taps, channel_filter_decimation_factor); channel_filter_pass_f = taps_6k0_channel.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = taps_6k0_channel.stop_frequency_normalized * channel_filter_input_fs; From ef37bbd8519e94f88812f3b3fd9e5b719b79ef84 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 31 Dec 2015 10:08:41 -0800 Subject: [PATCH 184/452] Small FM squelch simplification. --- firmware/baseband/dsp_squelch.cpp | 2 +- firmware/baseband/dsp_squelch.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/dsp_squelch.cpp b/firmware/baseband/dsp_squelch.cpp index 4cfe651ae..8047b388b 100644 --- a/firmware/baseband/dsp_squelch.cpp +++ b/firmware/baseband/dsp_squelch.cpp @@ -41,5 +41,5 @@ bool FMSquelch::execute(buffer_s16_t audio) { } } - return (max_squared < (threshold * threshold)); + return (max_squared < threshold_squared); } diff --git a/firmware/baseband/dsp_squelch.hpp b/firmware/baseband/dsp_squelch.hpp index 37cf68a30..8d1923c6c 100644 --- a/firmware/baseband/dsp_squelch.hpp +++ b/firmware/baseband/dsp_squelch.hpp @@ -35,7 +35,7 @@ public: private: static constexpr size_t N = 32; - static constexpr int16_t threshold = 3072; + static constexpr uint32_t threshold_squared = 8192 * 8192; IIRBiquadFilter non_audio_hpf { non_audio_hpf_config }; }; From 9fb22dfd1f4092f1693d89eaf1db160b4ec8cfa8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 31 Dec 2015 10:09:42 -0800 Subject: [PATCH 185/452] Reduce type size for int16_t squared values. --- firmware/baseband/dsp_squelch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/dsp_squelch.cpp b/firmware/baseband/dsp_squelch.cpp index 8047b388b..d9d39591d 100644 --- a/firmware/baseband/dsp_squelch.cpp +++ b/firmware/baseband/dsp_squelch.cpp @@ -33,9 +33,9 @@ bool FMSquelch::execute(buffer_s16_t audio) { }; non_audio_hpf.execute(audio, squelch_energy); - uint64_t max_squared = 0; + uint32_t max_squared = 0; for(const auto sample : squelch_energy_buffer) { - const uint64_t sample_squared = sample * sample; + const uint32_t sample_squared = sample * sample; if( sample_squared > max_squared ) { max_squared = sample_squared; } From 316d5d433b5ba8c08aedb7166f36ff2f81ed7778 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 31 Dec 2015 10:52:28 -0800 Subject: [PATCH 186/452] Move IIR code into .cpp file. A few hundred more text section bytes saved. --- firmware/baseband/Makefile | 1 + firmware/baseband/dsp_iir.cpp | 50 +++++++++++++++++++++++++++++++++++ firmware/baseband/dsp_iir.hpp | 27 +++---------------- 3 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 firmware/baseband/dsp_iir.cpp diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index baec06534..2970d145d 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -148,6 +148,7 @@ CPPSRC = main.cpp \ packet_builder.cpp \ dsp_fft.cpp \ dsp_fir_taps.cpp \ + dsp_iir.cpp \ fxpt_atan2.cpp \ rssi.cpp \ rssi_dma.cpp \ diff --git a/firmware/baseband/dsp_iir.cpp b/firmware/baseband/dsp_iir.cpp new file mode 100644 index 000000000..e8367a76e --- /dev/null +++ b/firmware/baseband/dsp_iir.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "dsp_iir.hpp" + +#include + +void IIRBiquadFilter::execute(buffer_s16_t buffer_in, buffer_s16_t buffer_out) { + // TODO: Assert that buffer_out.count == buffer_in.count. + for(size_t i=0; i x { { 0.0f, 0.0f, 0.0f } }; std::array y { { 0.0f, 0.0f, 0.0f } }; - float execute_sample(const float in) { - x[0] = x[1]; - x[1] = x[2]; - x[2] = in; - - y[0] = y[1]; - y[1] = y[2]; - y[2] = config.b[0] * x[2] + config.b[1] * x[1] + config.b[2] * x[0] - - config.a[1] * y[1] - config.a[2] * y[0]; - - return y[2]; - } + float execute_sample(const float in); }; #endif/*__DSP_IIR_H__*/ From ff05833b02275a223d3468087a8df1b1de016647 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 1 Jan 2016 13:20:02 -0800 Subject: [PATCH 187/452] Use new decimation filters in AIS processor. --- firmware/baseband/proc_ais.cpp | 16 +++++++++++++++- firmware/baseband/proc_ais.hpp | 8 ++++++-- firmware/common/ais_baseband.hpp | 30 +++++++++++------------------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index 7cb0f3cb0..3db550ad5 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -26,10 +26,24 @@ #include "i2s.hpp" using namespace lpc43xx; +#include "dsp_fir_taps.hpp" + +AISProcessor::AISProcessor() { + decim_0.configure(taps_11k0_decim_0.taps, 33554432); + decim_1.configure(taps_11k0_decim_1.taps, 131072); +} + void AISProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ - auto decimator_out = decimator.execute(buffer); + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + + const auto decim_0_out = decim_0.execute(buffer, dst_buffer); + const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); + const auto decimator_out = decim_1_out; /* 76.8kHz, 64 samples */ feed_channel_stats(decimator_out); diff --git a/firmware/baseband/proc_ais.hpp b/firmware/baseband/proc_ais.hpp index 16bf42b45..59812efb4 100644 --- a/firmware/baseband/proc_ais.hpp +++ b/firmware/baseband/proc_ais.hpp @@ -42,11 +42,15 @@ class AISProcessor : public BasebandProcessor { public: + AISProcessor(); + void execute(const buffer_c8_t& buffer) override; private: - ChannelDecimator decimator { ChannelDecimator::DecimationFactor::By32 }; - dsp::matched_filter::MatchedFilter mf { baseband::ais::rrc_taps_76k8_4t_p, 4 }; + std::array dst; + dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; + dsp::decimate::FIRC16xR16x32Decim8 decim_1; + dsp::matched_filter::MatchedFilter mf { baseband::ais::rrc_taps_38k4_4t_p, 2 }; clock_recovery::ClockRecovery clock_recovery { 19200, 9600, { 0.0555f }, diff --git a/firmware/common/ais_baseband.hpp b/firmware/common/ais_baseband.hpp index c693d610d..1d7a2aa69 100644 --- a/firmware/common/ais_baseband.hpp +++ b/firmware/common/ais_baseband.hpp @@ -36,25 +36,17 @@ namespace ais { // cleaning up ISI. // Translate+RRC filter -// sample=76.8k, deviation=2400, b=0.5, symbol=9600 -// Length: 32 taps, 4 symbols, 1 cycle of sinusoid -constexpr std::array, 32> rrc_taps_76k8_4t_p { { - { 5.3368736990e-03f, 0.0000000000e+00f }, { 4.6850211151e-03f, 9.3190864122e-04f }, - { 1.7970187432e-03f, 7.4434953528e-04f }, { -2.5478608559e-03f, -1.7024261963e-03f }, - { -6.6710920858e-03f, -6.6710920858e-03f }, { -8.6960320791e-03f, -1.3014531722e-02f }, - { -7.5474785839e-03f, -1.8221225159e-02f }, { -3.8115552023e-03f, -1.9161981995e-02f }, - { -8.1697309033e-19f, -1.3342183083e-02f }, { 3.6940784220e-05f, -1.8571386338e-04f }, - { -7.5474785839e-03f, 1.8221225159e-02f }, { -2.4954265902e-02f, 3.7346698152e-02f }, - { -5.1450054092e-02f, 5.1450054092e-02f }, { -8.3018814119e-02f, 5.5471398140e-02f }, - { -1.1321218147e-01f, 4.6894020990e-02f }, { -1.3498960022e-01f, 2.6851100952e-02f }, - { -1.4292666316e-01f, 1.7503468055e-17f }, { -1.3498960022e-01f, -2.6851100952e-02f }, - { -1.1321218147e-01f, -4.6894020990e-02f }, { -8.3018814119e-02f, -5.5471398140e-02f }, - { -5.1450054092e-02f, -5.1450054092e-02f }, { -2.4954265902e-02f, -3.7346698152e-02f }, - { -7.5474785839e-03f, -1.8221225159e-02f }, { 3.6940784220e-05f, 1.8571386338e-04f }, - { 2.4509192710e-18f, 1.3342183083e-02f }, { -3.8115552023e-03f, 1.9161981995e-02f }, - { -7.5474785839e-03f, 1.8221225159e-02f }, { -8.6960320791e-03f, 1.3014531722e-02f }, - { -6.6710920858e-03f, 6.6710920858e-03f }, { -2.5478608559e-03f, 1.7024261963e-03f }, - { 1.7970187432e-03f, -7.4434953528e-04f }, { 4.6850211151e-03f, -9.3190864122e-04f }, +// sample=38.4k, deviation=2400, b=0.5, symbol=9600 +// Length: 16 taps, 4 symbols, 1 cycles of sinusoid +constexpr std::array, 16> rrc_taps_38k4_4t_p { { + { 1.0619794019e-02f, 0.0000000000e+00f }, { 3.5758705854e-03f, 1.4811740938e-03f }, + { -1.3274742629e-02f, -1.3274742629e-02f }, { -1.5018657262e-02f, -3.6258246051e-02f }, + { 0.0000000000e+00f, -2.6549484581e-02f }, { -1.5018657262e-02f, 3.6258246051e-02f }, + { -1.0237997393e-01f, 1.0237997393e-01f }, { -2.2527985355e-01f, 9.3313970669e-02f }, + { -2.8440842032e-01f, 0.0000000000e+00f }, { -2.2527985355e-01f, -9.3313970669e-02f }, + { -1.0237997393e-01f, -1.0237997393e-01f }, { -1.5018657262e-02f, -3.6258246051e-02f }, + { 0.0000000000e+00f, 2.6549484581e-02f }, { -1.5018657262e-02f, 3.6258246051e-02f }, + { -1.3274742629e-02f, 1.3274742629e-02f }, { 3.5758705854e-03f, -1.4811740938e-03f }, } }; } /* namespace ais */ From 9a0fb2cab77ea9f37c8258bb6324df617dde817c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 1 Jan 2016 20:53:11 -0800 Subject: [PATCH 188/452] Rename IIR filter for 300Hz high-pass. --- firmware/baseband/dsp_iir_config.hpp | 2 +- firmware/baseband/proc_am_audio.hpp | 2 +- firmware/baseband/proc_nfm_audio.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index ad9b81f91..171a8969c 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -25,7 +25,7 @@ #include "dsp_iir.hpp" // scipy.signal.butter(2, 300 / 24000.0, 'highpass', analog=False) -constexpr iir_biquad_config_t audio_hpf_config { +constexpr iir_biquad_config_t audio_hpf_300hz_config { { 0.97261390f, -1.94522780f, 0.97261390f, }, { 1.00000000f, -1.94447766f, 0.94597794f, } }; diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 4779384b1..bdceaa516 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -54,7 +54,7 @@ private: dsp::demodulate::AM demod; - IIRBiquadFilter audio_hpf { audio_hpf_config }; + IIRBiquadFilter audio_hpf { audio_hpf_300hz_config }; SpectrumCollector channel_spectrum; }; diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 3e1d22056..9ad71feae 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -61,7 +61,7 @@ private: dsp::demodulate::FM demod; - IIRBiquadFilter audio_hpf { audio_hpf_config }; + IIRBiquadFilter audio_hpf { audio_hpf_300hz_config }; IIRBiquadFilter audio_deemph { audio_deemph_300_6_config }; FMSquelch squelch; From 2e90edbf390b5ba3d49b70ecb039165ab8df2622 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 1 Jan 2016 20:55:00 -0800 Subject: [PATCH 189/452] Add 30Hz high-pass IIR filter for wideband FM. --- firmware/baseband/dsp_iir_config.hpp | 6 ++++++ firmware/baseband/proc_wfm_audio.hpp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index 171a8969c..7e99ed03f 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -24,6 +24,12 @@ #include "dsp_iir.hpp" +// scipy.signal.butter(2, 30 / 24000.0, 'highpass', analog=False) +constexpr iir_biquad_config_t audio_hpf_30hz_config { + { 0.99722705f, -1.99445410f, 0.99722705f, }, + { 1.00000000f, -1.99444641f, 0.99446179f, } +}; + // scipy.signal.butter(2, 300 / 24000.0, 'highpass', analog=False) constexpr iir_biquad_config_t audio_hpf_300hz_config { { 0.97261390f, -1.94522780f, 0.97261390f, }, diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index b4aa41bd5..6b0fed885 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -49,7 +49,7 @@ private: const fir_taps_real<64>& audio_filter_taps = taps_64_lp_156_198; dsp::decimate::FIR64AndDecimateBy2Real audio_filter { audio_filter_taps.taps }; - IIRBiquadFilter audio_hpf { audio_hpf_config }; + IIRBiquadFilter audio_hpf { audio_hpf_30hz_config }; }; #endif/*__PROC_WFM_AUDIO_H__*/ From 0e049394397feee5417d25bc6e5fda06805aeb02 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 1 Jan 2016 20:56:30 -0800 Subject: [PATCH 190/452] Broadcast FM de-emphasis using 75us time constant. --- firmware/baseband/dsp_iir_config.hpp | 8 ++++++++ firmware/baseband/proc_wfm_audio.cpp | 2 ++ firmware/baseband/proc_wfm_audio.hpp | 1 + 3 files changed, 11 insertions(+) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index 7e99ed03f..371521c4d 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -48,4 +48,12 @@ constexpr iir_biquad_config_t audio_deemph_300_6_config { { 1.00000000f, -0.96148145f, 0.00000000f, }, }; +// 75us RC time constant, used in broadcast FM in Americas, South Korea +// scipy.signal.butter(1, 2122 / 24000.0, 'lowpass', analog=False) +// NOTE: Technically, order-1 filter, b[2] = a[2] = 0. +constexpr iir_biquad_config_t audio_deemph_2122_6_config { + { 0.12264116f, 0.12264116f, 0.00000000f, }, + { 1.00000000f, -0.75471767f, 0.00000000f, }, +}; + #endif/*__DSP_IIR_CONFIG_H__*/ diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index a708a9ac0..d1bc8fe93 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -68,5 +68,7 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { /* -> 48kHz int16_t[32] */ audio_hpf.execute_in_place(audio); + audio_deemph.execute_in_place(audio); + fill_audio_buffer(audio); } diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 6b0fed885..91965cc72 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -50,6 +50,7 @@ private: dsp::decimate::FIR64AndDecimateBy2Real audio_filter { audio_filter_taps.taps }; IIRBiquadFilter audio_hpf { audio_hpf_30hz_config }; + IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config }; }; #endif/*__PROC_WFM_AUDIO_H__*/ From 096ebe47d8f4e17f366272221983d0ac1cfc88e9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 2 Jan 2016 10:24:49 -0800 Subject: [PATCH 191/452] Turn almost-zeros in TPMS matched filter to actual zeros. --- firmware/baseband/proc_tpms.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index 541ee0e06..45a655fa7 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -42,10 +42,10 @@ // sample=153.6k, deviation=38400, symbol=19200 // Length: 8 taps, 1 symbols, 2 cycles of sinusoid constexpr std::array, 8> rect_taps_153k6_1t_p { { - { 1.2500000000e-01f, 0.0000000000e+00f }, { 7.6540424947e-18f, 1.2500000000e-01f }, - { -1.2500000000e-01f, 1.5308084989e-17f }, { -2.2962127484e-17f, -1.2500000000e-01f }, - { 1.2500000000e-01f, -3.0616169979e-17f }, { 3.8270212473e-17f, 1.2500000000e-01f }, - { -1.2500000000e-01f, 4.5924254968e-17f }, { -5.3578297463e-17f, -1.2500000000e-01f }, + { 1.2500000000e-01f, 0.0000000000e+00f }, { 0.0000000000e+00f, 1.2500000000e-01f }, + { -1.2500000000e-01f, 0.0000000000e+00f }, { 0.0000000000e+00f, -1.2500000000e-01f }, + { 1.2500000000e-01f, 0.0000000000e+00f }, { 0.0000000000e+00f, 1.2500000000e-01f }, + { -1.2500000000e-01f, 0.0000000000e+00f }, { 0.0000000000e+00f, -1.2500000000e-01f }, } }; class TPMSProcessor : public BasebandProcessor { From a02bfe55d0b9fbcac2a35006855b1f5a863c0c4a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 2 Jan 2016 10:34:17 -0800 Subject: [PATCH 192/452] Decimators for wider IFIR output bandwidth. --- firmware/baseband/dsp_decimate.cpp | 119 +++++++++++++++++++++++++++++ firmware/baseband/dsp_decimate.hpp | 58 ++++++++++++++ 2 files changed, 177 insertions(+) diff --git a/firmware/baseband/dsp_decimate.cpp b/firmware/baseband/dsp_decimate.cpp index 5698b33df..c8a70898d 100644 --- a/firmware/baseband/dsp_decimate.cpp +++ b/firmware/baseband/dsp_decimate.cpp @@ -177,6 +177,71 @@ static inline uint32_t scale_round_and_pack( return __PKHBT(saturated_real, saturated_imag, 16); } +// FIRC8xR16x24FS4Decim4 ////////////////////////////////////////////////// + +FIRC8xR16x24FS4Decim4::FIRC8xR16x24FS4Decim4() { + z_.fill({}); +} + +void FIRC8xR16x24FS4Decim4::configure( + const std::array& taps, + const int32_t scale, + const Shift shift +) { + const int negate_factor = (shift == Shift::Up) ? -1 : 1; + for(size_t i=0; i(__builtin_assume_aligned(z_.data(), 4)); + const vec2_s16* const t = static_cast(__builtin_assume_aligned(taps_.data(), 4)); + uint32_t* const d = static_cast(__builtin_assume_aligned(dst.p, 4)); + + const auto k = output_scale; + + const size_t count = src.count / decimation_factor; + for(size_t i=0; i(__builtin_assume_aligned(&src.p[i * decimation_factor], 4)); + + complex32_t accum; + + // Oldest samples are discarded. + accum = mac_fs4_shift(z, t, 0, accum); + accum = mac_fs4_shift(z, t, 1, accum); + + // Middle samples are shifted earlier in the "z" delay buffer. + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 0, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 1, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 2, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 3, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 4, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 5, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 6, accum); + accum = mac_fs4_shift_and_store(z, t, decimation_factor, 7, accum); + + // Newest samples come from "in" buffer, are copied to "z" delay buffer. + accum = mac_fs4_shift_and_store_new_c8_samples(z, t, in, decimation_factor, 0, taps_count, accum); + accum = mac_fs4_shift_and_store_new_c8_samples(z, t, in, decimation_factor, 1, taps_count, accum); + + d[i] = scale_round_and_pack(accum, k); + } + + return { + dst.p, + count, + src.sampling_rate / decimation_factor + }; +} + // FIRC8xR16x24FS4Decim8 ////////////////////////////////////////////////// FIRC8xR16x24FS4Decim8::FIRC8xR16x24FS4Decim8() { @@ -242,6 +307,60 @@ buffer_c16_t FIRC8xR16x24FS4Decim8::execute( }; } +// FIRC16xR16x16Decim2 //////////////////////////////////////////////////// + +FIRC16xR16x16Decim2::FIRC16xR16x16Decim2() { + z_.fill({}); +} + +void FIRC16xR16x16Decim2::configure( + const std::array& taps, + const int32_t scale +) { + std::copy(taps.cbegin(), taps.cend(), taps_.begin()); + output_scale = scale; +} + +buffer_c16_t FIRC16xR16x16Decim2::execute( + buffer_c16_t src, + buffer_c16_t dst +) { + vec2_s16* const z = static_cast(__builtin_assume_aligned(z_.data(), 4)); + const vec2_s16* const t = static_cast(__builtin_assume_aligned(taps_.data(), 4)); + uint32_t* const d = static_cast(__builtin_assume_aligned(dst.p, 4)); + + const auto k = output_scale; + + const size_t count = src.count / decimation_factor; + for(size_t i=0; i(__builtin_assume_aligned(&src.p[i * decimation_factor], 4)); + + complex32_t accum; + + // Oldest samples are discarded. + accum = mac_shift(z, t, 0, accum); + + // Middle samples are shifted earlier in the "z" delay buffer. + accum = mac_shift_and_store(z, t, decimation_factor, 0, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 1, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 2, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 3, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 4, accum); + accum = mac_shift_and_store(z, t, decimation_factor, 5, accum); + + // Newest samples come from "in" buffer, are copied to "z" delay buffer. + accum = mac_shift_and_store_new_c16_samples(z, t, in, decimation_factor, 0, taps_count, accum); + + d[i] = scale_round_and_pack(accum, k); + } + + return { + dst.p, + count, + src.sampling_rate / decimation_factor + }; +} + // FIRC16xR16x32Decim8 //////////////////////////////////////////////////// FIRC16xR16x32Decim8::FIRC16xR16x32Decim8() { diff --git a/firmware/baseband/dsp_decimate.hpp b/firmware/baseband/dsp_decimate.hpp index 5079f2597..97f027030 100644 --- a/firmware/baseband/dsp_decimate.hpp +++ b/firmware/baseband/dsp_decimate.hpp @@ -92,6 +92,38 @@ private: const std::array& taps; }; +class FIRC8xR16x24FS4Decim4 { +public: + static constexpr size_t taps_count = 24; + static constexpr size_t decimation_factor = 4; + + using sample_t = complex8_t; + using tap_t = int16_t; + + enum class Shift : bool { + Down = true, + Up = false + }; + + FIRC8xR16x24FS4Decim4(); + + void configure( + const std::array& taps, + const int32_t scale, + const Shift shift = Shift::Down + ); + + buffer_c16_t execute( + buffer_c8_t src, + buffer_c16_t dst + ); + +private: + std::array z_; + std::array taps_; + int32_t output_scale = 0; +}; + class FIRC8xR16x24FS4Decim8 { public: static constexpr size_t taps_count = 24; @@ -124,6 +156,32 @@ private: int32_t output_scale = 0; }; +class FIRC16xR16x16Decim2 { +public: + static constexpr size_t taps_count = 16; + static constexpr size_t decimation_factor = 2; + + using sample_t = complex16_t; + using tap_t = int16_t; + + FIRC16xR16x16Decim2(); + + void configure( + const std::array& taps, + const int32_t scale + ); + + buffer_c16_t execute( + buffer_c16_t src, + buffer_c16_t dst + ); + +private: + std::array z_; + std::array taps_; + int32_t output_scale = 0; +}; + class FIRC16xR16x32Decim8 { public: static constexpr size_t taps_count = 32; From e720bfb05468581ccadd39b15cae3f66655c5e55 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 2 Jan 2016 10:35:23 -0800 Subject: [PATCH 193/452] Use IFIR decimation for broadcast FM receiver. --- firmware/baseband/dsp_decimate.cpp | 6 ++++ firmware/baseband/dsp_decimate.hpp | 8 ++---- firmware/baseband/dsp_fir_taps.hpp | 21 ++++++++++++++ firmware/baseband/proc_wfm_audio.cpp | 41 +++++++++++++++++++++------- firmware/baseband/proc_wfm_audio.hpp | 14 ++++------ 5 files changed, 67 insertions(+), 23 deletions(-) diff --git a/firmware/baseband/dsp_decimate.cpp b/firmware/baseband/dsp_decimate.cpp index c8a70898d..6bc2c9b3c 100644 --- a/firmware/baseband/dsp_decimate.cpp +++ b/firmware/baseband/dsp_decimate.cpp @@ -618,6 +618,12 @@ buffer_c16_t DecimateBy2CIC3::execute( return { dst.p, src.count / 2, src.sampling_rate / 2 }; } +void FIR64AndDecimateBy2Real::configure( + const std::array& new_taps +) { + std::copy(new_taps.cbegin(), new_taps.cend(), taps.begin()); +} + buffer_s16_t FIR64AndDecimateBy2Real::execute( buffer_s16_t src, buffer_s16_t dst diff --git a/firmware/baseband/dsp_decimate.hpp b/firmware/baseband/dsp_decimate.hpp index 97f027030..6922999b6 100644 --- a/firmware/baseband/dsp_decimate.hpp +++ b/firmware/baseband/dsp_decimate.hpp @@ -76,11 +76,9 @@ class FIR64AndDecimateBy2Real { public: static constexpr size_t taps_count = 64; - FIR64AndDecimateBy2Real( + void configure( const std::array& taps - ) : taps(taps) - { - } + ); buffer_s16_t execute( buffer_s16_t src, @@ -89,7 +87,7 @@ public: private: std::array z; - const std::array& taps; + std::array taps; }; class FIRC8xR16x24FS4Decim4 { diff --git a/firmware/baseband/dsp_fir_taps.hpp b/firmware/baseband/dsp_fir_taps.hpp index 68ea1ea86..8b7b6feac 100644 --- a/firmware/baseband/dsp_fir_taps.hpp +++ b/firmware/baseband/dsp_fir_taps.hpp @@ -182,6 +182,27 @@ constexpr fir_taps_real<32> taps_6k0_channel { } }, }; +// WFM 200KF8E emission type ////////////////////////////////////////////// + +constexpr fir_taps_real<24> taps_200k_wfm_decim_0 = { + .pass_frequency_normalized = 100000.0f / 3072000.0f, + .stop_frequency_normalized = 484000.0f / 3072000.0f, + .taps = { { + 48, -18, -151, -364, -557, -548, -139, 789, + 2187, 3800, 5230, 6071, 6071, 5230, 3800, 2187, + 789, -139, -548, -557, -364, -151, -18, 48, + } }, +}; + +constexpr fir_taps_real<16> taps_200k_wfm_decim_1 = { + .pass_frequency_normalized = 100000.0f / 768000.0f, + .stop_frequency_normalized = 284000.0f / 768000.0f, + .taps = { { + -67, -123, 388, 622, -1342, -2185, 4599, 14486, + 14486, 4599, -2185, -1342, 622, 388, -123, -67, + } }, +}; + /* Wideband audio filter */ /* 96kHz int16_t input * -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index d1bc8fe93..9f0639cc1 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -23,8 +23,34 @@ #include +WidebandFMAudio::WidebandFMAudio() { + constexpr size_t baseband_fs = 3072000; + + constexpr size_t decim_0_input_fs = baseband_fs; + constexpr size_t decim_0_decimation_factor = 4; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; + + constexpr size_t decim_1_input_fs = decim_0_output_fs; + constexpr size_t decim_1_decimation_factor = 2; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; + + constexpr size_t demod_input_fs = decim_1_output_fs; + + decim_0.configure(taps_200k_wfm_decim_0.taps, 33554432); + decim_1.configure(taps_200k_wfm_decim_1.taps, 131072); + demod.configure(demod_input_fs, 75000); + audio_filter.configure(taps_64_lp_156_198.taps); +} + void WidebandFMAudio::execute(const buffer_c8_t& buffer) { - auto decimator_out = decimator.execute(buffer); + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + + const auto decim_0_out = decim_0.execute(buffer, dst_buffer); + const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); + const auto decimator_out = decim_1_out; const buffer_s16_t work_audio_buffer { (int16_t*)decimator_out.p, @@ -37,29 +63,24 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { feed_channel_stats(channel); //feed_channel_spectrum(channel); - /* 768kHz complex[512] + /* 384kHz complex[256] * -> FM demodulation - * -> 768kHz int16_t[512] */ + * -> 384kHz int16_t[256] */ /* TODO: To improve adjacent channel rejection, implement complex channel filter: * pass < +/- 100kHz, stop > +/- 200kHz */ auto audio_oversampled = demod.execute(decimator_out, work_audio_buffer); - /* 768kHz int16_t[512] - * -> 4th order CIC decimation by 2, gain of 1 - * -> 384kHz int16_t[256] */ - auto audio_8fs = audio_dec_1.execute(audio_oversampled, work_audio_buffer); - /* 384kHz int16_t[256] * -> 4th order CIC decimation by 2, gain of 1 * -> 192kHz int16_t[128] */ - auto audio_4fs = audio_dec_2.execute(audio_8fs, work_audio_buffer); + auto audio_4fs = audio_dec_1.execute(audio_oversampled, work_audio_buffer); /* 192kHz int16_t[128] * -> 4th order CIC decimation by 2, gain of 1 * -> 96kHz int16_t[64] */ - auto audio_2fs = audio_dec_3.execute(audio_4fs, work_audio_buffer); + auto audio_2fs = audio_dec_2.execute(audio_4fs, work_audio_buffer); /* 96kHz int16_t[64] * -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop, gain of 1 diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 91965cc72..b45cc7178 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -33,21 +33,19 @@ class WidebandFMAudio : public BasebandProcessor { public: - WidebandFMAudio() { - decimator.set_decimation_factor(ChannelDecimator::DecimationFactor::By4); - } + WidebandFMAudio(); void execute(const buffer_c8_t& buffer) override; private: - ChannelDecimator decimator; + std::array dst; + dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; + dsp::decimate::FIRC16xR16x16Decim2 decim_1; - dsp::demodulate::FM demod { 768000, 75000 }; + dsp::demodulate::FM demod; dsp::decimate::DecimateBy2CIC4Real audio_dec_1; dsp::decimate::DecimateBy2CIC4Real audio_dec_2; - dsp::decimate::DecimateBy2CIC4Real audio_dec_3; - const fir_taps_real<64>& audio_filter_taps = taps_64_lp_156_198; - dsp::decimate::FIR64AndDecimateBy2Real audio_filter { audio_filter_taps.taps }; + dsp::decimate::FIR64AndDecimateBy2Real audio_filter; IIRBiquadFilter audio_hpf { audio_hpf_30hz_config }; IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config }; From 410d4d7fc394497eaeb1386022711a5d5d25a37c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 2 Jan 2016 10:42:40 -0800 Subject: [PATCH 194/452] Use IFIR decimator for TPMS. --- firmware/baseband/proc_tpms.cpp | 35 ++++++++++++++++++++++++++++++++- firmware/baseband/proc_tpms.hpp | 27 ++++++++++++++++--------- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index b9e111222..1e8d378a0 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -26,10 +26,43 @@ #include "i2s.hpp" using namespace lpc43xx; +#include "dsp_fir_taps.hpp" + +static constexpr fir_taps_real<24> taps_200k_decim_0 = { + .pass_frequency_normalized = 100000.0f / 2457600.0f, + .stop_frequency_normalized = 407200.0f / 2457600.0f, + .taps = { { + 90, 94, 4, -240, -570, -776, -563, 309, + 1861, 3808, 5618, 6710, 6710, 5618, 3808, 1861, + 309, -563, -776, -570, -240, 4, 94, 90, + } }, +}; + +static constexpr fir_taps_real<16> taps_200k_decim_1 = { + .pass_frequency_normalized = 100000.0f / 614400.0f, + .stop_frequency_normalized = 207200.0f / 614400.0f, + .taps = { { + -132, -256, 545, 834, -1507, -2401, 4666, 14583, + 14583, 4666, -2401, -1507, 834, 545, -256, -132, + } }, +}; + +TPMSProcessor::TPMSProcessor() { + decim_0.configure(taps_200k_decim_0.taps, 33554432); + decim_1.configure(taps_200k_decim_1.taps, 131072); +} + void TPMSProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ - auto decimator_out = decimator.execute(buffer); + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + + const auto decim_0_out = decim_0.execute(buffer, dst_buffer); + const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); + const auto decimator_out = decim_1_out; /* 76.8kHz, 64 samples */ feed_channel_stats(decimator_out); diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index 45a655fa7..10b902489 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -39,22 +39,31 @@ #include // Translate+rectangular filter -// sample=153.6k, deviation=38400, symbol=19200 -// Length: 8 taps, 1 symbols, 2 cycles of sinusoid -constexpr std::array, 8> rect_taps_153k6_1t_p { { - { 1.2500000000e-01f, 0.0000000000e+00f }, { 0.0000000000e+00f, 1.2500000000e-01f }, - { -1.2500000000e-01f, 0.0000000000e+00f }, { 0.0000000000e+00f, -1.2500000000e-01f }, - { 1.2500000000e-01f, 0.0000000000e+00f }, { 0.0000000000e+00f, 1.2500000000e-01f }, - { -1.2500000000e-01f, 0.0000000000e+00f }, { 0.0000000000e+00f, -1.2500000000e-01f }, +// sample=307.2k, deviation=38400, symbol=19200 +// Length: 16 taps, 1 symbols, 2 cycles of sinusoid +constexpr std::array, 16> rect_taps_307k2_1t_p { { + { 6.2500000000e-02f, 0.0000000000e+00f }, { 4.4194173824e-02f, 4.4194173824e-02f }, + { 0.0000000000e+00f, 6.2500000000e-02f }, { -4.4194173824e-02f, 4.4194173824e-02f }, + { -6.2500000000e-02f, 0.0000000000e+00f }, { -4.4194173824e-02f, -4.4194173824e-02f }, + { 0.0000000000e+00f, -6.2500000000e-02f }, { 4.4194173824e-02f, -4.4194173824e-02f }, + { 6.2500000000e-02f, 0.0000000000e+00f }, { 4.4194173824e-02f, 4.4194173824e-02f }, + { 0.0000000000e+00f, 6.2500000000e-02f }, { -4.4194173824e-02f, 4.4194173824e-02f }, + { -6.2500000000e-02f, 0.0000000000e+00f }, { -4.4194173824e-02f, -4.4194173824e-02f }, + { 0.0000000000e+00f, -6.2500000000e-02f }, { 4.4194173824e-02f, -4.4194173824e-02f }, } }; class TPMSProcessor : public BasebandProcessor { public: + TPMSProcessor(); + void execute(const buffer_c8_t& buffer) override; private: - ChannelDecimator decimator { ChannelDecimator::DecimationFactor::By16 }; - dsp::matched_filter::MatchedFilter mf { rect_taps_153k6_1t_p, 4 }; + std::array dst; + dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; + dsp::decimate::FIRC16xR16x16Decim2 decim_1; + + dsp::matched_filter::MatchedFilter mf { rect_taps_307k2_1t_p, 8 }; clock_recovery::ClockRecovery clock_recovery { 38400, 19200, { 0.0555f }, From e7be7c5121d21413b4c343af5084e10d2736d7bd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 2 Jan 2016 10:49:37 -0800 Subject: [PATCH 195/452] Comments about IFIR filter taps design parameters. --- firmware/baseband/dsp_fir_taps.hpp | 2 ++ firmware/baseband/proc_tpms.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/firmware/baseband/dsp_fir_taps.hpp b/firmware/baseband/dsp_fir_taps.hpp index 8b7b6feac..c043cab93 100644 --- a/firmware/baseband/dsp_fir_taps.hpp +++ b/firmware/baseband/dsp_fir_taps.hpp @@ -184,6 +184,7 @@ constexpr fir_taps_real<32> taps_6k0_channel { // WFM 200KF8E emission type ////////////////////////////////////////////// +// IFIR image-reject filter: fs=3072000, pass=100000, stop=484000, decim=4, fout=768000 constexpr fir_taps_real<24> taps_200k_wfm_decim_0 = { .pass_frequency_normalized = 100000.0f / 3072000.0f, .stop_frequency_normalized = 484000.0f / 3072000.0f, @@ -194,6 +195,7 @@ constexpr fir_taps_real<24> taps_200k_wfm_decim_0 = { } }, }; +// IFIR prototype filter: fs=768000, pass=100000, stop=284000, decim=2, fout=384000 constexpr fir_taps_real<16> taps_200k_wfm_decim_1 = { .pass_frequency_normalized = 100000.0f / 768000.0f, .stop_frequency_normalized = 284000.0f / 768000.0f, diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index 1e8d378a0..e7f8257a8 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -28,6 +28,7 @@ using namespace lpc43xx; #include "dsp_fir_taps.hpp" +// IFIR image-reject filter: fs=2457600, pass=100000, stop=407200, decim=4, fout=614400 static constexpr fir_taps_real<24> taps_200k_decim_0 = { .pass_frequency_normalized = 100000.0f / 2457600.0f, .stop_frequency_normalized = 407200.0f / 2457600.0f, @@ -38,6 +39,7 @@ static constexpr fir_taps_real<24> taps_200k_decim_0 = { } }, }; +// IFIR prototype filter: fs=614400, pass=100000, stop=207200, decim=2, fout=307200 static constexpr fir_taps_real<16> taps_200k_decim_1 = { .pass_frequency_normalized = 100000.0f / 614400.0f, .stop_frequency_normalized = 207200.0f / 614400.0f, From fea5dd536fba176afc07ba875be9e9fa4ec1226b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 2 Jan 2016 10:57:47 -0800 Subject: [PATCH 196/452] Move baseband working buffers from member variables to stack. It's temporary, after all... --- firmware/baseband/baseband_thread.cpp | 2 +- firmware/baseband/proc_ais.cpp | 1 + firmware/baseband/proc_ais.hpp | 1 - firmware/baseband/proc_am_audio.cpp | 1 + firmware/baseband/proc_am_audio.hpp | 1 - firmware/baseband/proc_nfm_audio.cpp | 1 + firmware/baseband/proc_nfm_audio.hpp | 1 - firmware/baseband/proc_tpms.cpp | 1 + firmware/baseband/proc_tpms.hpp | 1 - firmware/baseband/proc_wfm_audio.cpp | 1 + firmware/baseband/proc_wfm_audio.hpp | 1 - 11 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp index b23170c35..ce0ff0b88 100644 --- a/firmware/baseband/baseband_thread.cpp +++ b/firmware/baseband/baseband_thread.cpp @@ -42,7 +42,7 @@ #include -WORKING_AREA(baseband_thread_wa, 2048); +WORKING_AREA(baseband_thread_wa, 4096); Thread* BasebandThread::start(const tprio_t priority) { return chThdCreateStatic(baseband_thread_wa, sizeof(baseband_thread_wa), diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index 3db550ad5..41108ff7a 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -36,6 +36,7 @@ AISProcessor::AISProcessor() { void AISProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ + std::array dst; const buffer_c16_t dst_buffer { dst.data(), dst.size() diff --git a/firmware/baseband/proc_ais.hpp b/firmware/baseband/proc_ais.hpp index 59812efb4..6f8be94d6 100644 --- a/firmware/baseband/proc_ais.hpp +++ b/firmware/baseband/proc_ais.hpp @@ -47,7 +47,6 @@ public: void execute(const buffer_c8_t& buffer) override; private: - std::array dst; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC16xR16x32Decim8 decim_1; dsp::matched_filter::MatchedFilter mf { baseband::ais::rrc_taps_38k4_4t_p, 2 }; diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 603155e40..518ad25f1 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -46,6 +46,7 @@ NarrowbandAMAudio::NarrowbandAMAudio() { } void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { + std::array dst; const buffer_c16_t dst_buffer { dst.data(), dst.size() diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index bdceaa516..6acc2a27f 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -45,7 +45,6 @@ public: void on_update_spectrum() override { channel_spectrum.update(); } private: - std::array dst; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC16xR16x32Decim8 decim_1; dsp::decimate::FIRAndDecimateComplex channel_filter; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index ecd17a134..4b8cb6c46 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -79,6 +79,7 @@ void NarrowbandFMAudio::set_mode(const Mode mode) { } void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { + std::array dst; const buffer_c16_t dst_buffer { dst.data(), dst.size() diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 9ad71feae..d0471d30f 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -51,7 +51,6 @@ public: void on_update_spectrum() override { channel_spectrum.update(); } private: - std::array dst; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC16xR16x32Decim8 decim_1; diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index e7f8257a8..99b58b574 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -57,6 +57,7 @@ TPMSProcessor::TPMSProcessor() { void TPMSProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ + std::array dst; const buffer_c16_t dst_buffer { dst.data(), dst.size() diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index 10b902489..0164a28c7 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -59,7 +59,6 @@ public: void execute(const buffer_c8_t& buffer) override; private: - std::array dst; dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; dsp::decimate::FIRC16xR16x16Decim2 decim_1; diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 9f0639cc1..65923dddc 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -43,6 +43,7 @@ WidebandFMAudio::WidebandFMAudio() { } void WidebandFMAudio::execute(const buffer_c8_t& buffer) { + std::array dst; const buffer_c16_t dst_buffer { dst.data(), dst.size() diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index b45cc7178..6d6a6d0cb 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -38,7 +38,6 @@ public: void execute(const buffer_c8_t& buffer) override; private: - std::array dst; dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; dsp::decimate::FIRC16xR16x16Decim2 decim_1; From 07cd99d85dcae806773f0242526a87d7e33cbbed Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 2 Jan 2016 22:54:09 -0800 Subject: [PATCH 197/452] Removing baseband MessageHandlerMap. It's a bit heavy (362 bytes smaller with switch/case implementation), hard to access to add/remove handlers, doesn't bubble events like I'd like. (I'm going to bubble events to the baseband processor shortly.) --- firmware/baseband/main.cpp | 48 +++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 16c8c5d3a..4f0196212 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -121,24 +121,7 @@ static void shutdown() { class EventDispatcher { public: - MessageHandlerMap& message_handlers() { - return message_map; - } - void run() { - message_map.register_handler(Message::ID::BasebandConfiguration, - [this](const Message* const p) { - auto message = reinterpret_cast(p); - this->baseband_thread.set_configuration(message->configuration); - } - ); - - message_map.register_handler(Message::ID::Shutdown, - [this](const Message* const) { - this->request_stop(); - } - ); - events_initialize(chThdSelf()); m0apptxevent_interrupt_enable(); @@ -159,7 +142,6 @@ public: } private: - MessageHandlerMap message_map; BasebandThread baseband_thread; RSSIThread rssi_thread; @@ -182,10 +164,38 @@ private: void handle_baseband_queue() { std::array message_buffer; while(Message* const message = shared_memory.baseband_queue.pop(message_buffer)) { - message_map.send(message); + on_message(message); } } + void on_message(const Message* const message) { + switch(message->id) { + case Message::ID::BasebandConfiguration: + on_message_baseband_configuration(*reinterpret_cast(message)); + break; + + case Message::ID::Shutdown: + on_message_shutdown(*reinterpret_cast(message)); + break; + + default: + on_message_default(message); + break; + } + } + + void on_message_baseband_configuration(const BasebandConfigurationMessage& message) { + baseband_thread.set_configuration(message.configuration); + } + + void on_message_shutdown(const ShutdownMessage&) { + request_stop(); + } + + void on_message_default(const Message* const) { + // TODO: Pass to active baseband processor. + } + void handle_spectrum() { // TODO: Send this via another message?! baseband_thread.on_update_spectrum(); From fd612dc20750e1006f26bd3a1c3b4587fa2308a5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 2 Jan 2016 22:59:31 -0800 Subject: [PATCH 198/452] Baseband: Pass unhandled messages to baseband thread, processor. --- firmware/baseband/baseband_processor.hpp | 1 + firmware/baseband/baseband_thread.cpp | 6 ++++++ firmware/baseband/baseband_thread.hpp | 1 + firmware/baseband/main.cpp | 4 ++-- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/baseband_processor.hpp b/firmware/baseband/baseband_processor.hpp index 82a79a0e7..48b23b7ba 100644 --- a/firmware/baseband/baseband_processor.hpp +++ b/firmware/baseband/baseband_processor.hpp @@ -38,6 +38,7 @@ public: virtual void execute(const buffer_c8_t& buffer) = 0; + virtual void on_message(const Message* const) { }; virtual void on_update_spectrum() { }; protected: diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp index ce0ff0b88..1035d2dc3 100644 --- a/firmware/baseband/baseband_thread.cpp +++ b/firmware/baseband/baseband_thread.cpp @@ -68,6 +68,12 @@ void BasebandThread::set_configuration(const BasebandConfiguration& new_configur baseband_configuration = new_configuration; } +void BasebandThread::on_message(const Message* const message) { + if( baseband_processor ) { + baseband_processor->on_message(message); + } +} + void BasebandThread::on_update_spectrum() { if( baseband_processor ) { baseband_processor->on_update_spectrum(); diff --git a/firmware/baseband/baseband_thread.hpp b/firmware/baseband/baseband_thread.hpp index 814dcd51e..4c16a54d5 100644 --- a/firmware/baseband/baseband_thread.hpp +++ b/firmware/baseband/baseband_thread.hpp @@ -39,6 +39,7 @@ public: void set_configuration(const BasebandConfiguration& new_configuration); + void on_message(const Message* const message); void on_update_spectrum(); // This getter should die, it's just here to leak information to code that diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 4f0196212..79df6ce1c 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -192,8 +192,8 @@ private: request_stop(); } - void on_message_default(const Message* const) { - // TODO: Pass to active baseband processor. + void on_message_default(const Message* const message) { + baseband_thread.on_message(message); } void handle_spectrum() { From c9f9d97d0768383df58d8c3de04ae8794ba3cc0d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 11:49:01 -0800 Subject: [PATCH 199/452] Move BasebandConfiguration message handling into baseband thread. --- firmware/baseband/baseband_thread.cpp | 8 ++++++-- firmware/baseband/baseband_thread.hpp | 4 ++-- firmware/baseband/main.cpp | 8 -------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp index 1035d2dc3..84b23bed6 100644 --- a/firmware/baseband/baseband_thread.cpp +++ b/firmware/baseband/baseband_thread.cpp @@ -69,8 +69,12 @@ void BasebandThread::set_configuration(const BasebandConfiguration& new_configur } void BasebandThread::on_message(const Message* const message) { - if( baseband_processor ) { - baseband_processor->on_message(message); + if( message->id == Message::ID::BasebandConfiguration ) { + set_configuration(reinterpret_cast(message)->configuration); + } else { + if( baseband_processor ) { + baseband_processor->on_message(message); + } } } diff --git a/firmware/baseband/baseband_thread.hpp b/firmware/baseband/baseband_thread.hpp index 4c16a54d5..c1c5d9041 100644 --- a/firmware/baseband/baseband_thread.hpp +++ b/firmware/baseband/baseband_thread.hpp @@ -37,8 +37,6 @@ public: Thread* start(const tprio_t priority); - void set_configuration(const BasebandConfiguration& new_configuration); - void on_message(const Message* const message); void on_update_spectrum(); @@ -61,6 +59,8 @@ private: void disable(); void enable(); + + void set_configuration(const BasebandConfiguration& new_configuration); }; #endif/*__BASEBAND_THREAD_H__*/ diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 79df6ce1c..3e18808a4 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -170,10 +170,6 @@ private: void on_message(const Message* const message) { switch(message->id) { - case Message::ID::BasebandConfiguration: - on_message_baseband_configuration(*reinterpret_cast(message)); - break; - case Message::ID::Shutdown: on_message_shutdown(*reinterpret_cast(message)); break; @@ -184,10 +180,6 @@ private: } } - void on_message_baseband_configuration(const BasebandConfigurationMessage& message) { - baseband_thread.set_configuration(message.configuration); - } - void on_message_shutdown(const ShutdownMessage&) { request_stop(); } From 39ca6fec6216a4a3ea1be7834e8ade1784577389 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 12:05:47 -0800 Subject: [PATCH 200/452] Transform update spectrum event into message. --- firmware/baseband/baseband_thread.cpp | 6 ------ firmware/baseband/baseband_thread.hpp | 1 - firmware/baseband/main.cpp | 4 ++-- firmware/baseband/proc_am_audio.cpp | 6 ++++++ firmware/baseband/proc_am_audio.hpp | 4 ++-- firmware/baseband/proc_nfm_audio.cpp | 6 ++++++ firmware/baseband/proc_nfm_audio.hpp | 2 +- firmware/baseband/proc_wideband_spectrum.cpp | 6 ++++++ firmware/baseband/proc_wideband_spectrum.hpp | 2 +- firmware/common/message.hpp | 9 +++++++++ 10 files changed, 33 insertions(+), 13 deletions(-) diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp index 84b23bed6..223a762e5 100644 --- a/firmware/baseband/baseband_thread.cpp +++ b/firmware/baseband/baseband_thread.cpp @@ -78,12 +78,6 @@ void BasebandThread::on_message(const Message* const message) { } } -void BasebandThread::on_update_spectrum() { - if( baseband_processor ) { - baseband_processor->on_update_spectrum(); - } -} - void BasebandThread::run() { baseband::dma::init(); diff --git a/firmware/baseband/baseband_thread.hpp b/firmware/baseband/baseband_thread.hpp index c1c5d9041..81d35433a 100644 --- a/firmware/baseband/baseband_thread.hpp +++ b/firmware/baseband/baseband_thread.hpp @@ -38,7 +38,6 @@ public: Thread* start(const tprio_t priority); void on_message(const Message* const message); - void on_update_spectrum(); // This getter should die, it's just here to leak information to code that // isn't in the right place to begin with. diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 3e18808a4..3814aa282 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -189,8 +189,8 @@ private: } void handle_spectrum() { - // TODO: Send this via another message?! - baseband_thread.on_update_spectrum(); + const UpdateSpectrumMessage message; + baseband_thread.on_message(&message); } }; diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 518ad25f1..c2da853bb 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -71,3 +71,9 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { fill_audio_buffer(audio); } + +void NarrowbandAMAudio::on_message(const Message* const message) { + if( message->id == Message::ID::UpdateSpectrum ) { + channel_spectrum.update(); + } +} diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 6acc2a27f..e664b0af8 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -41,8 +41,8 @@ public: NarrowbandAMAudio(); void execute(const buffer_c8_t& buffer) override; - - void on_update_spectrum() override { channel_spectrum.update(); } + + void on_message(const Message* const message) override; private: dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 4b8cb6c46..98c8f70c1 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -116,3 +116,9 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { fill_audio_buffer(audio); } + +void NarrowbandFMAudio::on_message(const Message* const message) { + if( message->id == Message::ID::UpdateSpectrum ) { + channel_spectrum.update(); + } +} diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index d0471d30f..4619a010f 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -48,7 +48,7 @@ public: void execute(const buffer_c8_t& buffer) override; - void on_update_spectrum() override { channel_spectrum.update(); } + void on_message(const Message* const message) override; private: dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; diff --git a/firmware/baseband/proc_wideband_spectrum.cpp b/firmware/baseband/proc_wideband_spectrum.cpp index 25ee7e48b..077342872 100644 --- a/firmware/baseband/proc_wideband_spectrum.cpp +++ b/firmware/baseband/proc_wideband_spectrum.cpp @@ -67,3 +67,9 @@ void WidebandSpectrum::execute(const buffer_c8_t& buffer) { i2s::i2s0::tx_mute(); } + +void WidebandSpectrum::on_message(const Message* const message) { + if( message->id == Message::ID::UpdateSpectrum ) { + channel_spectrum.update(); + } +} diff --git a/firmware/baseband/proc_wideband_spectrum.hpp b/firmware/baseband/proc_wideband_spectrum.hpp index b8311c694..24ac10b09 100644 --- a/firmware/baseband/proc_wideband_spectrum.hpp +++ b/firmware/baseband/proc_wideband_spectrum.hpp @@ -33,7 +33,7 @@ class WidebandSpectrum : public BasebandProcessor { public: void execute(const buffer_c8_t& buffer) override; - void on_update_spectrum() override { channel_spectrum.update(); } + void on_message(const Message* const message) override; private: size_t sample_count = 0; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index cbd05969d..dc76459d6 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -50,6 +50,7 @@ public: Shutdown = 8, AISPacket = 7, ERTPacket = 9, + UpdateSpectrum = 10, MAX }; @@ -260,6 +261,14 @@ public: baseband::Packet packet; }; +class UpdateSpectrumMessage : public Message { +public: + constexpr UpdateSpectrumMessage( + ) : Message { ID::UpdateSpectrum } + { + } +}; + class MessageHandlerMap { public: using MessageHandler = std::function; From c179b9e1cdec561939ddeb4f8a57d00e0dc06c7e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 12:45:15 -0800 Subject: [PATCH 201/452] Move FIR filter configs to common/, so M0 can use it. Planning to pass from M0 to M4 so M4 doesn't need to keep all these different filter configs in text section. --- firmware/{baseband => common}/dsp_fir_taps.cpp | 0 firmware/{baseband => common}/dsp_fir_taps.hpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename firmware/{baseband => common}/dsp_fir_taps.cpp (100%) rename firmware/{baseband => common}/dsp_fir_taps.hpp (100%) diff --git a/firmware/baseband/dsp_fir_taps.cpp b/firmware/common/dsp_fir_taps.cpp similarity index 100% rename from firmware/baseband/dsp_fir_taps.cpp rename to firmware/common/dsp_fir_taps.cpp diff --git a/firmware/baseband/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp similarity index 100% rename from firmware/baseband/dsp_fir_taps.hpp rename to firmware/common/dsp_fir_taps.hpp From a5012427d89406b3d964dfcdca5da2e6d522febe Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 12:45:34 -0800 Subject: [PATCH 202/452] Remove little bit of dead code. --- firmware/baseband/proc_wideband_spectrum.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/firmware/baseband/proc_wideband_spectrum.hpp b/firmware/baseband/proc_wideband_spectrum.hpp index 24ac10b09..c8401e32e 100644 --- a/firmware/baseband/proc_wideband_spectrum.hpp +++ b/firmware/baseband/proc_wideband_spectrum.hpp @@ -36,8 +36,6 @@ public: void on_message(const Message* const message) override; private: - size_t sample_count = 0; - SpectrumCollector channel_spectrum; std::array spectrum; From 0497dbf62f19cc50d23a15d1bec9a13aad4ccd58 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 12:46:21 -0800 Subject: [PATCH 203/452] NBFM configuration message. Allows changing NBFM filter configurations from M0. --- firmware/common/message.hpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index dc76459d6..d332a0917 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -29,6 +29,7 @@ #include "baseband_packet.hpp" #include "ert_packet.hpp" +#include "dsp_fir_taps.hpp" #include "utility.hpp" @@ -51,6 +52,7 @@ public: AISPacket = 7, ERTPacket = 9, UpdateSpectrum = 10, + NBFMConfigure = 11, MAX }; @@ -269,6 +271,27 @@ public: } }; +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 deviation + ) : Message { ID::NBFMConfigure }, + decim_0_filter { decim_0_filter }, + decim_1_filter { decim_1_filter }, + channel_filter { channel_filter }, + deviation { deviation } + { + } + + 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 deviation; +}; + class MessageHandlerMap { public: using MessageHandler = std::function; From 7496c2aced25e27a56b93a75342b278598076123 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 12:47:22 -0800 Subject: [PATCH 204/452] Send NBFM configuration message from M0 to M4. --- firmware/application/analog_audio_app.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index e27ef1c66..7ef3102ad 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -22,6 +22,7 @@ #include "analog_audio_app.hpp" #include "portapack.hpp" +#include "portapack_shared_memory.hpp" using namespace portapack; #include "utility.hpp" @@ -33,4 +34,14 @@ AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); + + if( mode == ReceiverModel::Mode::NarrowbandFMAudio ) { + const NBFMConfigureMessage message { + taps_4k25_decim_0, + taps_4k25_decim_1, + taps_4k25_channel, + 2500, + }; + shared_memory.baseband_queue.push(message); + } } From 317ec53638aea3503b6f41e5b75f6e9dbe0b1963 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 12:49:00 -0800 Subject: [PATCH 205/452] Handle NBFM configuration message on M4 processor side. --- firmware/baseband/proc_nfm_audio.cpp | 95 ++++++++++++---------------- firmware/baseband/proc_nfm_audio.hpp | 17 ++--- 2 files changed, 46 insertions(+), 66 deletions(-) diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 98c8f70c1..5f4204407 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -24,61 +24,11 @@ #include #include -NarrowbandFMAudio::NarrowbandFMAudio() { - set_mode(Mode::Deviation2K5Narrow); -} - -void NarrowbandFMAudio::set_mode(const Mode mode) { - constexpr size_t baseband_fs = 3072000; - - constexpr size_t decim_0_input_fs = baseband_fs; - constexpr size_t decim_0_decimation_factor = 8; - constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; - - constexpr size_t decim_1_input_fs = decim_0_output_fs; - constexpr size_t decim_1_decimation_factor = 8; - constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; - - constexpr size_t channel_filter_input_fs = decim_1_output_fs; - constexpr size_t channel_filter_decimation_factor = 1; - constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; - - constexpr size_t demod_input_fs = channel_filter_output_fs; - - switch(mode) { - default: - case Mode::Deviation5K: - decim_0.configure(taps_16k0_decim_0.taps, 33554432); - decim_1.configure(taps_16k0_decim_1.taps, 131072); - channel_filter.configure(taps_16k0_channel.taps, channel_filter_decimation_factor); - demod.configure(demod_input_fs, 5000); - channel_filter_pass_f = taps_16k0_channel.pass_frequency_normalized * channel_filter_input_fs; - channel_filter_stop_f = taps_16k0_channel.stop_frequency_normalized * channel_filter_input_fs; - break; - - case Mode::Deviation2K5Wide: - decim_0.configure(taps_11k0_decim_0.taps, 33554432); - decim_1.configure(taps_11k0_decim_1.taps, 131072); - channel_filter.configure(taps_11k0_channel.taps, channel_filter_decimation_factor); - demod.configure(demod_input_fs, 2500); - channel_filter_pass_f = taps_11k0_channel.pass_frequency_normalized * channel_filter_input_fs; - channel_filter_stop_f = taps_11k0_channel.stop_frequency_normalized * channel_filter_input_fs; - break; - - case Mode::Deviation2K5Narrow: - decim_0.configure(taps_4k25_decim_0.taps, 33554432); - decim_1.configure(taps_4k25_decim_1.taps, 131072); - channel_filter.configure(taps_4k25_channel.taps, channel_filter_decimation_factor); - demod.configure(demod_input_fs, 2500); - channel_filter_pass_f = taps_4k25_channel.pass_frequency_normalized * channel_filter_input_fs; - channel_filter_stop_f = taps_4k25_channel.stop_frequency_normalized * channel_filter_input_fs; - break; +void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { + if( !configured ) { + return; } - channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); -} - -void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { std::array dst; const buffer_c16_t dst_buffer { dst.data(), @@ -118,7 +68,44 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { } void NarrowbandFMAudio::on_message(const Message* const message) { - if( message->id == Message::ID::UpdateSpectrum ) { + switch(message->id) { + case Message::ID::UpdateSpectrum: channel_spectrum.update(); + break; + + case Message::ID::NBFMConfigure: + configure(*reinterpret_cast(message)); + break; + + default: + break; } } + +void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { + constexpr size_t baseband_fs = 3072000; + + constexpr size_t decim_0_input_fs = baseband_fs; + constexpr size_t decim_0_decimation_factor = 8; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; + + constexpr size_t decim_1_input_fs = decim_0_output_fs; + constexpr size_t decim_1_decimation_factor = 8; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; + + constexpr size_t channel_filter_input_fs = decim_1_output_fs; + constexpr size_t channel_filter_decimation_factor = 1; + constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; + + constexpr size_t demod_input_fs = channel_filter_output_fs; + + decim_0.configure(message.decim_0_filter.taps, 33554432); + decim_1.configure(message.decim_1_filter.taps, 131072); + channel_filter.configure(message.channel_filter.taps, channel_filter_decimation_factor); + demod.configure(demod_input_fs, message.deviation); + channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; + channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; + channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); + + configured = true; +} diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 4619a010f..1dd3782f9 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -24,28 +24,18 @@ #include "baseband_processor.hpp" -#include "channel_decimator.hpp" #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" -#include "dsp_fir_taps.hpp" #include "dsp_iir.hpp" #include "dsp_iir_config.hpp" #include "dsp_squelch.hpp" +#include "message.hpp" + #include "spectrum_collector.hpp" class NarrowbandFMAudio : public BasebandProcessor { public: - enum class Mode { - Deviation5K = 0, - Deviation2K5Wide = 1, - Deviation2K5Narrow = 2, - }; - - NarrowbandFMAudio(); - - void set_mode(const Mode mode); - void execute(const buffer_c8_t& buffer) override; void on_message(const Message* const message) override; @@ -65,6 +55,9 @@ private: FMSquelch squelch; SpectrumCollector channel_spectrum; + + bool configured { false }; + void configure(const NBFMConfigureMessage& message); }; #endif/*__PROC_NFM_AUDIO_H__*/ From f2f7032615b497d10ca2c7e810fdd05d1b9af839 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 13:38:55 -0800 Subject: [PATCH 206/452] Wideband FM configuration messages from M0. --- firmware/application/analog_audio_app.cpp | 40 +++++++++++++---- firmware/application/analog_audio_app.hpp | 4 ++ firmware/baseband/proc_wfm_audio.cpp | 55 +++++++++++++++-------- firmware/baseband/proc_wfm_audio.hpp | 7 ++- firmware/common/message.hpp | 22 +++++++++ 5 files changed, 99 insertions(+), 29 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 7ef3102ad..0b048acfe 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -35,13 +35,37 @@ AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { }); receiver_model.set_baseband_bandwidth(1750000); - if( mode == ReceiverModel::Mode::NarrowbandFMAudio ) { - const NBFMConfigureMessage message { - taps_4k25_decim_0, - taps_4k25_decim_1, - taps_4k25_channel, - 2500, - }; - shared_memory.baseband_queue.push(message); + switch(mode) { + case ReceiverModel::Mode::NarrowbandFMAudio: + configure_nbfm(); + break; + + case ReceiverModel::Mode::WidebandFMAudio: + configure_wfm(); + break; + + default: + break; } + +} + +void AnalogAudioModel::configure_nbfm() { + const NBFMConfigureMessage message { + taps_4k25_decim_0, + taps_4k25_decim_1, + taps_4k25_channel, + 2500, + }; + shared_memory.baseband_queue.push(message); +} + +void AnalogAudioModel::configure_wfm() { + const WFMConfigureMessage message { + taps_200k_wfm_decim_0, + taps_200k_wfm_decim_1, + taps_64_lp_156_198, + 75000, + }; + shared_memory.baseband_queue.push(message); } diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 20703094e..80047fa24 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -28,6 +28,10 @@ class AnalogAudioModel { public: AnalogAudioModel(ReceiverModel::Mode mode); + +private: + void configure_nbfm(); + void configure_wfm(); }; namespace ui { diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 65923dddc..485fa6206 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -23,26 +23,11 @@ #include -WidebandFMAudio::WidebandFMAudio() { - constexpr size_t baseband_fs = 3072000; - - constexpr size_t decim_0_input_fs = baseband_fs; - constexpr size_t decim_0_decimation_factor = 4; - constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; - - constexpr size_t decim_1_input_fs = decim_0_output_fs; - constexpr size_t decim_1_decimation_factor = 2; - constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; - - constexpr size_t demod_input_fs = decim_1_output_fs; - - decim_0.configure(taps_200k_wfm_decim_0.taps, 33554432); - decim_1.configure(taps_200k_wfm_decim_1.taps, 131072); - demod.configure(demod_input_fs, 75000); - audio_filter.configure(taps_64_lp_156_198.taps); -} - void WidebandFMAudio::execute(const buffer_c8_t& buffer) { + if( !configured ) { + return; + } + std::array dst; const buffer_c16_t dst_buffer { dst.data(), @@ -94,3 +79,35 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { fill_audio_buffer(audio); } + +void WidebandFMAudio::on_message(const Message* const message) { + switch(message->id) { + case Message::ID::WFMConfigure: + configure(*reinterpret_cast(message)); + break; + + default: + break; + } +} + +void WidebandFMAudio::configure(const WFMConfigureMessage& message) { + constexpr size_t baseband_fs = 3072000; + + constexpr size_t decim_0_input_fs = baseband_fs; + constexpr size_t decim_0_decimation_factor = 4; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; + + constexpr size_t decim_1_input_fs = decim_0_output_fs; + constexpr size_t decim_1_decimation_factor = 2; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; + + constexpr size_t demod_input_fs = decim_1_output_fs; + + decim_0.configure(message.decim_0_filter.taps, 33554432); + decim_1.configure(message.decim_1_filter.taps, 131072); + demod.configure(demod_input_fs, message.deviation); + audio_filter.configure(message.audio_filter.taps); + + configured = true; +} diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 6d6a6d0cb..79b7969dc 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -33,10 +33,10 @@ class WidebandFMAudio : public BasebandProcessor { public: - WidebandFMAudio(); - void execute(const buffer_c8_t& buffer) override; + void on_message(const Message* const message) override; + private: dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; dsp::decimate::FIRC16xR16x16Decim2 decim_1; @@ -48,6 +48,9 @@ private: IIRBiquadFilter audio_hpf { audio_hpf_30hz_config }; IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config }; + + bool configured { false }; + void configure(const WFMConfigureMessage& message); }; #endif/*__PROC_WFM_AUDIO_H__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index d332a0917..fdb67bbd4 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -53,6 +53,7 @@ public: ERTPacket = 9, UpdateSpectrum = 10, NBFMConfigure = 11, + WFMConfigure = 12, MAX }; @@ -292,6 +293,27 @@ public: const size_t deviation; }; +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 + ) : Message { ID::WFMConfigure }, + decim_0_filter { decim_0_filter }, + decim_1_filter { decim_1_filter }, + audio_filter { audio_filter }, + deviation { deviation } + { + } + + 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; +}; + class MessageHandlerMap { public: using MessageHandler = std::function; From b5aa2b205fa71a6e8b25ea95b00260e14525b8be Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 14:31:39 -0800 Subject: [PATCH 207/452] Implement AMConfigureMessage from M0 to M4. --- firmware/application/analog_audio_app.cpp | 13 +++++ firmware/application/analog_audio_app.hpp | 1 + firmware/baseband/proc_am_audio.cpp | 64 ++++++++++++++--------- firmware/baseband/proc_am_audio.hpp | 5 +- firmware/common/message.hpp | 19 +++++++ 5 files changed, 75 insertions(+), 27 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 0b048acfe..ec50f4d52 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -44,6 +44,10 @@ AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { configure_wfm(); break; + case ReceiverModel::Mode::AMAudio: + configure_am(); + break; + default: break; } @@ -69,3 +73,12 @@ void AnalogAudioModel::configure_wfm() { }; shared_memory.baseband_queue.push(message); } + +void AnalogAudioModel::configure_am() { + const AMConfigureMessage message { + taps_6k0_decim_0, + taps_6k0_decim_1, + taps_6k0_channel, + }; + shared_memory.baseband_queue.push(message); +} diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 80047fa24..7c840ced4 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -32,6 +32,7 @@ public: private: void configure_nbfm(); void configure_wfm(); + void configure_am(); }; namespace ui { diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index c2da853bb..c6fc3212c 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -21,31 +21,11 @@ #include "proc_am_audio.hpp" -NarrowbandAMAudio::NarrowbandAMAudio() { - constexpr size_t baseband_fs = 3072000; - - constexpr size_t decim_0_input_fs = baseband_fs; - constexpr size_t decim_0_decimation_factor = 8; - constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; - - constexpr size_t decim_1_input_fs = decim_0_output_fs; - constexpr size_t decim_1_decimation_factor = 8; - constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; - - constexpr size_t channel_filter_input_fs = decim_1_output_fs; - constexpr size_t channel_filter_decimation_factor = 1; - constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; - - decim_0.configure(taps_6k0_decim_0.taps, 33554432); - decim_1.configure(taps_6k0_decim_1.taps, 131072); - channel_filter.configure(taps_6k0_channel.taps, channel_filter_decimation_factor); - channel_filter_pass_f = taps_6k0_channel.pass_frequency_normalized * channel_filter_input_fs; - channel_filter_stop_f = taps_6k0_channel.stop_frequency_normalized * channel_filter_input_fs; - - channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); -} - void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { + if( !configured ) { + return; + } + std::array dst; const buffer_c16_t dst_buffer { dst.data(), @@ -73,7 +53,41 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { } void NarrowbandAMAudio::on_message(const Message* const message) { - if( message->id == Message::ID::UpdateSpectrum ) { + switch(message->id) { + case Message::ID::UpdateSpectrum: channel_spectrum.update(); + break; + + case Message::ID::AMConfigure: + configure(*reinterpret_cast(message)); + break; + + default: + break; } } + +void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { + constexpr size_t baseband_fs = 3072000; + + constexpr size_t decim_0_input_fs = baseband_fs; + constexpr size_t decim_0_decimation_factor = 8; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; + + constexpr size_t decim_1_input_fs = decim_0_output_fs; + constexpr size_t decim_1_decimation_factor = 8; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; + + constexpr size_t channel_filter_input_fs = decim_1_output_fs; + constexpr size_t channel_filter_decimation_factor = 1; + constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; + + decim_0.configure(message.decim_0_filter.taps, 33554432); + decim_1.configure(message.decim_1_filter.taps, 131072); + channel_filter.configure(message.channel_filter.taps, channel_filter_decimation_factor); + channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; + channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; + channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); + + configured = true; +} diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index e664b0af8..f70885132 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -38,8 +38,6 @@ class NarrowbandAMAudio : public BasebandProcessor { public: - NarrowbandAMAudio(); - void execute(const buffer_c8_t& buffer) override; void on_message(const Message* const message) override; @@ -56,6 +54,9 @@ private: IIRBiquadFilter audio_hpf { audio_hpf_300hz_config }; SpectrumCollector channel_spectrum; + + bool configured { false }; + void configure(const AMConfigureMessage& message); }; #endif/*__PROC_AM_AUDIO_H__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index fdb67bbd4..6e0e8fee2 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -54,6 +54,7 @@ public: UpdateSpectrum = 10, NBFMConfigure = 11, WFMConfigure = 12, + AMConfigure = 13, MAX }; @@ -314,6 +315,24 @@ public: const size_t deviation; }; +class AMConfigureMessage : public Message { +public: + constexpr AMConfigureMessage( + const fir_taps_real<24>& decim_0_filter, + const fir_taps_real<32>& decim_1_filter, + const fir_taps_real<32>& channel_filter + ) : Message { ID::AMConfigure }, + decim_0_filter { decim_0_filter }, + decim_1_filter { decim_1_filter }, + channel_filter { channel_filter } + { + } + + const fir_taps_real<24> decim_0_filter; + const fir_taps_real<32> decim_1_filter; + const fir_taps_real<32> channel_filter; +}; + class MessageHandlerMap { public: using MessageHandler = std::function; From 422f6c69604b9fd35cce92f8efb33f9a63fd769f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 16:21:17 -0800 Subject: [PATCH 208/452] Don't pass by reference in message constructors. --- firmware/common/message.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 6e0e8fee2..9a7dc0ae1 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -276,9 +276,9 @@ public: 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 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 deviation ) : Message { ID::NBFMConfigure }, decim_0_filter { decim_0_filter }, @@ -297,9 +297,9 @@ public: 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 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 ) : Message { ID::WFMConfigure }, decim_0_filter { decim_0_filter }, @@ -318,9 +318,9 @@ public: class AMConfigureMessage : public Message { public: constexpr AMConfigureMessage( - const fir_taps_real<24>& decim_0_filter, - const fir_taps_real<32>& decim_1_filter, - const fir_taps_real<32>& channel_filter + const fir_taps_real<24> decim_0_filter, + const fir_taps_real<32> decim_1_filter, + const fir_taps_real<32> channel_filter ) : Message { ID::AMConfigure }, decim_0_filter { decim_0_filter }, decim_1_filter { decim_1_filter }, From 62ee26e763efbbe715db3064f2ef94fd0e0454ec Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 16:28:09 -0800 Subject: [PATCH 209/452] OK... Nuke list initializations. --- firmware/common/message.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 9a7dc0ae1..e247b27cb 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -281,9 +281,9 @@ public: const fir_taps_real<32> channel_filter, const size_t deviation ) : Message { ID::NBFMConfigure }, - decim_0_filter { decim_0_filter }, - decim_1_filter { decim_1_filter }, - channel_filter { channel_filter }, + decim_0_filter(decim_0_filter), + decim_1_filter(decim_1_filter), + channel_filter(channel_filter), deviation { deviation } { } @@ -302,9 +302,9 @@ public: const fir_taps_real<64> audio_filter, const size_t deviation ) : Message { ID::WFMConfigure }, - decim_0_filter { decim_0_filter }, - decim_1_filter { decim_1_filter }, - audio_filter { audio_filter }, + decim_0_filter(decim_0_filter), + decim_1_filter(decim_1_filter), + audio_filter(audio_filter), deviation { deviation } { } @@ -322,9 +322,9 @@ public: const fir_taps_real<32> decim_1_filter, const fir_taps_real<32> channel_filter ) : Message { ID::AMConfigure }, - decim_0_filter { decim_0_filter }, - decim_1_filter { decim_1_filter }, - channel_filter { channel_filter } + decim_0_filter(decim_0_filter), + decim_1_filter(decim_1_filter), + channel_filter(channel_filter) { } From 3f299c74c65d1debf6d77b69160c8ba6f801cd23 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 16:32:45 -0800 Subject: [PATCH 210/452] More old GCC fussiness fixes. --- firmware/baseband/dsp_iir_config.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index 371521c4d..8ddee3b69 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -26,14 +26,14 @@ // scipy.signal.butter(2, 30 / 24000.0, 'highpass', analog=False) constexpr iir_biquad_config_t audio_hpf_30hz_config { - { 0.99722705f, -1.99445410f, 0.99722705f, }, - { 1.00000000f, -1.99444641f, 0.99446179f, } + { 0.99722705f, -1.99445410f, 0.99722705f }, + { 1.00000000f, -1.99444641f, 0.99446179f } }; // scipy.signal.butter(2, 300 / 24000.0, 'highpass', analog=False) constexpr iir_biquad_config_t audio_hpf_300hz_config { - { 0.97261390f, -1.94522780f, 0.97261390f, }, - { 1.00000000f, -1.94447766f, 0.94597794f, } + { 0.97261390f, -1.94522780f, 0.97261390f }, + { 1.00000000f, -1.94447766f, 0.94597794f } }; // scipy.signal.iirdesign(wp=8000 / 24000.0, ws= 4000 / 24000.0, gpass=1, gstop=18, ftype='ellip') @@ -44,16 +44,16 @@ constexpr iir_biquad_config_t non_audio_hpf_config { // scipy.signal.butter(1, 300 / 24000.0, 'lowpass', analog=False) // NOTE: Technically, order-1 filter, b[2] = a[2] = 0. constexpr iir_biquad_config_t audio_deemph_300_6_config { - { 0.01925927f, 0.01925927f, 0.00000000f, }, - { 1.00000000f, -0.96148145f, 0.00000000f, }, + { 0.01925927f, 0.01925927f, 0.00000000f }, + { 1.00000000f, -0.96148145f, 0.00000000f } }; // 75us RC time constant, used in broadcast FM in Americas, South Korea // scipy.signal.butter(1, 2122 / 24000.0, 'lowpass', analog=False) // NOTE: Technically, order-1 filter, b[2] = a[2] = 0. constexpr iir_biquad_config_t audio_deemph_2122_6_config { - { 0.12264116f, 0.12264116f, 0.00000000f, }, - { 1.00000000f, -0.75471767f, 0.00000000f, }, + { 0.12264116f, 0.12264116f, 0.00000000f }, + { 1.00000000f, -0.75471767f, 0.00000000f } }; #endif/*__DSP_IIR_CONFIG_H__*/ From 28be223ace91d6bac55dc468789ffa0de57904c4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 16:37:47 -0800 Subject: [PATCH 211/452] Fix for merge-breakage. Argh. --- firmware/baseband/dsp_iir_config.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index 8ddee3b69..096acd995 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -40,6 +40,7 @@ constexpr iir_biquad_config_t audio_hpf_300hz_config { constexpr iir_biquad_config_t non_audio_hpf_config { { 0.51891061f, -0.95714180f, 0.51891061f }, { 1.0f , -0.79878302f, 0.43960231f } +}; // scipy.signal.butter(1, 300 / 24000.0, 'lowpass', analog=False) // NOTE: Technically, order-1 filter, b[2] = a[2] = 0. From 10bce4b845442586a8d23db3ad087e33b27788fa Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 16:58:08 -0800 Subject: [PATCH 212/452] Clean up #includes. --- firmware/baseband/proc_am_audio.cpp | 2 ++ firmware/baseband/proc_am_audio.hpp | 3 --- firmware/baseband/proc_nfm_audio.hpp | 2 -- firmware/baseband/proc_wfm_audio.hpp | 2 -- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index c6fc3212c..ce11aaf14 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -21,6 +21,8 @@ #include "proc_am_audio.hpp" +#include + void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { if( !configured ) { return; diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index f70885132..172fab616 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -24,17 +24,14 @@ #include "baseband_processor.hpp" -#include "channel_decimator.hpp" #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" -#include "dsp_fir_taps.hpp" #include "dsp_iir.hpp" #include "dsp_iir_config.hpp" #include "spectrum_collector.hpp" #include -#include class NarrowbandAMAudio : public BasebandProcessor { public: diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 1dd3782f9..87e056935 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -30,8 +30,6 @@ #include "dsp_iir_config.hpp" #include "dsp_squelch.hpp" -#include "message.hpp" - #include "spectrum_collector.hpp" class NarrowbandFMAudio : public BasebandProcessor { diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 79b7969dc..9ef62fc8d 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -24,10 +24,8 @@ #include "baseband_processor.hpp" -#include "channel_decimator.hpp" #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" -#include "dsp_fir_taps.hpp" #include "dsp_iir.hpp" #include "dsp_iir_config.hpp" From 86cf967464f067134e586b3df27c3b9d2797c8f8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 16:58:36 -0800 Subject: [PATCH 213/452] Simplify FM demodulator class. Remove duplicate code. --- firmware/baseband/dsp_demodulate.hpp | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/firmware/baseband/dsp_demodulate.hpp b/firmware/baseband/dsp_demodulate.hpp index 51c9504d3..6e84fb8b3 100644 --- a/firmware/baseband/dsp_demodulate.hpp +++ b/firmware/baseband/dsp_demodulate.hpp @@ -37,37 +37,23 @@ public: class FM { public: - constexpr FM( - ) : z_ { 0 }, - k { 0 } - { - } - - /* - * angle: -pi to pi. output range: -32768 to 32767. - * Maximum delta-theta (output of atan2) at maximum deviation frequency: - * delta_theta_max = 2 * pi * deviation / sampling_rate - */ - constexpr FM( - const float sampling_rate, - const float deviation_hz - ) : z_ { 0 }, - k { static_cast(32767.0f / (2.0 * pi * deviation_hz / sampling_rate)) } - { - } - buffer_s16_t execute( buffer_c16_t src, buffer_s16_t dst ); void configure(const float sampling_rate, const float deviation_hz) { + /* + * angle: -pi to pi. output range: -32768 to 32767. + * Maximum delta-theta (output of atan2) at maximum deviation frequency: + * delta_theta_max = 2 * pi * deviation / sampling_rate + */ k = static_cast(32767.0f / (2.0 * pi * deviation_hz / sampling_rate)); } private: - complex16_t::rep_type z_; - float k; + complex16_t::rep_type z_ { 0 }; + float k { 0 }; }; } /* namespace demodulate */ From 8adaddac5ffb90514fd337754dcc988ad62222ae Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 17:03:16 -0800 Subject: [PATCH 214/452] Make FM squelch runtime-configurable. --- firmware/baseband/dsp_squelch.cpp | 4 ++++ firmware/baseband/dsp_squelch.hpp | 4 +++- firmware/baseband/proc_nfm_audio.cpp | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/dsp_squelch.cpp b/firmware/baseband/dsp_squelch.cpp index d9d39591d..6420a0877 100644 --- a/firmware/baseband/dsp_squelch.cpp +++ b/firmware/baseband/dsp_squelch.cpp @@ -43,3 +43,7 @@ bool FMSquelch::execute(buffer_s16_t audio) { return (max_squared < threshold_squared); } + +void FMSquelch::set_threshold(const uint32_t new_value) { + threshold_squared = new_value * new_value; +} diff --git a/firmware/baseband/dsp_squelch.hpp b/firmware/baseband/dsp_squelch.hpp index 8d1923c6c..cd8e841d1 100644 --- a/firmware/baseband/dsp_squelch.hpp +++ b/firmware/baseband/dsp_squelch.hpp @@ -33,9 +33,11 @@ class FMSquelch { public: bool execute(buffer_s16_t audio); + void set_threshold(const uint32_t new_value); + private: static constexpr size_t N = 32; - static constexpr uint32_t threshold_squared = 8192 * 8192; + uint32_t threshold_squared { 0 }; IIRBiquadFilter non_audio_hpf { non_audio_hpf_config }; }; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 5f4204407..7742f65f1 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -106,6 +106,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); + squelch.set_threshold(8192); configured = true; } From 78992c2f8d4c9c97ffb326263fe1f32f8cf6cde1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 17:05:00 -0800 Subject: [PATCH 215/452] Adjust default FM squelch threshold. --- firmware/baseband/proc_nfm_audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 7742f65f1..4468af000 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -106,7 +106,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); - squelch.set_threshold(8192); + squelch.set_threshold(6144); configured = true; } From 65dd385c94daa8349af4581863dbbcff629885ff Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 17:47:08 -0800 Subject: [PATCH 216/452] Little FFT loop indexing tweak. --- firmware/common/dsp_fft.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/common/dsp_fft.hpp b/firmware/common/dsp_fft.hpp index 3dce015a3..35532de16 100644 --- a/firmware/common/dsp_fft.hpp +++ b/firmware/common/dsp_fft.hpp @@ -112,7 +112,8 @@ void fft_c_preswapped(std::array& data) { static_assert(power_of_two(N), "only defined for N == power of two"); /* Provide data to this function, pre-swapped. */ - for(size_t mmax = 1; N > mmax; mmax <<= 1) { + for(size_t k = 0; k < log_2(N); k++) { + const size_t mmax = 1 << k; const float theta = -pi / mmax; const float wtemp = sin_f32(0.5f * theta); const T wp { From 54e59cc22431463f848d53d78d1f2b1a90b8d3d6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 20:08:26 -0800 Subject: [PATCH 217/452] Hard-code K=8 FFT twiddle constants for now. So low on baseband RAM! This eliminates the sin_f32() function and table, which is only used in the FFT, for the moment. --- firmware/common/dsp_fft.hpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/firmware/common/dsp_fft.hpp b/firmware/common/dsp_fft.hpp index 35532de16..f61218d0a 100644 --- a/firmware/common/dsp_fft.hpp +++ b/firmware/common/dsp_fft.hpp @@ -31,7 +31,6 @@ #include "dsp_types.hpp" #include "complex.hpp" -#include "sine_table.hpp" #include "hal.h" namespace std { @@ -110,16 +109,24 @@ void fft_swap_in_place(std::array& data) { template void fft_c_preswapped(std::array& data) { static_assert(power_of_two(N), "only defined for N == power of two"); + constexpr auto K = log_2(N); + + static_assert(N == 256, "lame that I've hard-coded a table for K=8"); + static constexpr std::array, K> wp_table { { + { -2.00000000000000000000000000000000f, 0.00000000000000000000000000000000f }, + { -1.00000000000000000000000000000000f, -1.00000000000000000000000000000000f }, + { -0.29289321881345242726268907063059f, -0.70710678118654746171500846685376f }, + { -0.07612046748871323376128827931097f, -0.38268343236508978177923268049199f }, + { -0.01921471959676954860407604996908f, -0.19509032201612824808378832130984f }, + { -0.00481527332780311376897453001789f, -0.09801714032956060362877792613290f }, + { -0.00120454379482760713659939000308f, -0.04906767432741801493456534899451f }, + { -0.00030118130379577984830768988544f, -0.02454122852291228812360301958506f }, + } }; /* Provide data to this function, pre-swapped. */ for(size_t k = 0; k < log_2(N); k++) { const size_t mmax = 1 << k; - const float theta = -pi / mmax; - const float wtemp = sin_f32(0.5f * theta); - const T wp { - -2.0f * wtemp * wtemp, - sin_f32(theta) - }; + const auto wp = wp_table[k]; T w { 1.0f, 0.0f }; for(size_t m = 0; m < mmax; ++m) { for(size_t i = m; i < N; i += mmax * 2) { From 963b6e257a447e7a5cca9c3050bad6defb88f647 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 20:25:31 -0800 Subject: [PATCH 218/452] FFT twiddles can be used for all K <= table length. Change assert to allow FFTs < 8. --- firmware/common/dsp_fft.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/firmware/common/dsp_fft.hpp b/firmware/common/dsp_fft.hpp index f61218d0a..7d4c61e1c 100644 --- a/firmware/common/dsp_fft.hpp +++ b/firmware/common/dsp_fft.hpp @@ -111,8 +111,9 @@ void fft_c_preswapped(std::array& data) { static_assert(power_of_two(N), "only defined for N == power of two"); constexpr auto K = log_2(N); - static_assert(N == 256, "lame that I've hard-coded a table for K=8"); - static constexpr std::array, K> wp_table { { + constexpr size_t K_max = 8; + static_assert(K <= K_max, "No FFT twiddle factors for K > 8"); + static constexpr std::array, K_max> wp_table { { { -2.00000000000000000000000000000000f, 0.00000000000000000000000000000000f }, { -1.00000000000000000000000000000000f, -1.00000000000000000000000000000000f }, { -0.29289321881345242726268907063059f, -0.70710678118654746171500846685376f }, From 5547782f5a0d9dcf6cacb9fe29cd78db35c3f259 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 21:02:44 -0800 Subject: [PATCH 219/452] Improve FFT twiddle factor precisions using Python SymPy. Python math, numpy, scipy produce values with significant rounding errors. --- firmware/common/dsp_fft.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/common/dsp_fft.hpp b/firmware/common/dsp_fft.hpp index 7d4c61e1c..a360721ac 100644 --- a/firmware/common/dsp_fft.hpp +++ b/firmware/common/dsp_fft.hpp @@ -114,14 +114,14 @@ void fft_c_preswapped(std::array& data) { constexpr size_t K_max = 8; static_assert(K <= K_max, "No FFT twiddle factors for K > 8"); static constexpr std::array, K_max> wp_table { { - { -2.00000000000000000000000000000000f, 0.00000000000000000000000000000000f }, - { -1.00000000000000000000000000000000f, -1.00000000000000000000000000000000f }, - { -0.29289321881345242726268907063059f, -0.70710678118654746171500846685376f }, - { -0.07612046748871323376128827931097f, -0.38268343236508978177923268049199f }, - { -0.01921471959676954860407604996908f, -0.19509032201612824808378832130984f }, - { -0.00481527332780311376897453001789f, -0.09801714032956060362877792613290f }, - { -0.00120454379482760713659939000308f, -0.04906767432741801493456534899451f }, - { -0.00030118130379577984830768988544f, -0.02454122852291228812360301958506f }, + { -2.0f, 0.0f }, + { -1.0f, -1.0f }, + { -0.2928932188134524756f, -0.7071067811865475244f }, + { -0.076120467488713243872f, -0.38268343236508977173f }, + { -0.019214719596769550874f, -0.19509032201612826785f }, + { -0.0048152733278031137552f, -0.098017140329560601994f }, + { -0.0012045437948276072852f, -0.049067674327418014255f }, + { -0.00030118130379577988423f, -0.024541228522912288032f }, } }; /* Provide data to this function, pre-swapped. */ From d9017530c638622964f183f681c9cc25e1a75e7b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 22:31:44 -0800 Subject: [PATCH 220/452] Moved baseband temporary buffers back into class member variables. Significant performance hit when declaring on stack. C++ wants to initialize std::array or even raw array with element constructors, was resulting in ~7% CPU utilization, for a buffer that was immediately written over anyway. --- firmware/baseband/proc_ais.cpp | 6 ------ firmware/baseband/proc_ais.hpp | 6 ++++++ firmware/baseband/proc_am_audio.cpp | 11 ----------- firmware/baseband/proc_am_audio.hpp | 10 ++++++++++ firmware/baseband/proc_nfm_audio.cpp | 11 ----------- firmware/baseband/proc_nfm_audio.hpp | 10 ++++++++++ firmware/baseband/proc_tpms.cpp | 6 ------ firmware/baseband/proc_tpms.hpp | 6 ++++++ firmware/baseband/proc_wfm_audio.cpp | 11 ----------- firmware/baseband/proc_wfm_audio.hpp | 10 ++++++++++ 10 files changed, 42 insertions(+), 45 deletions(-) diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index 41108ff7a..b12e8ba88 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -36,12 +36,6 @@ AISProcessor::AISProcessor() { void AISProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ - std::array dst; - const buffer_c16_t dst_buffer { - dst.data(), - dst.size() - }; - const auto decim_0_out = decim_0.execute(buffer, dst_buffer); const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); const auto decimator_out = decim_1_out; diff --git a/firmware/baseband/proc_ais.hpp b/firmware/baseband/proc_ais.hpp index 6f8be94d6..966d739aa 100644 --- a/firmware/baseband/proc_ais.hpp +++ b/firmware/baseband/proc_ais.hpp @@ -47,6 +47,12 @@ public: void execute(const buffer_c8_t& buffer) override; private: + std::array dst; + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC16xR16x32Decim8 decim_1; dsp::matched_filter::MatchedFilter mf { baseband::ais::rrc_taps_38k4_4t_p, 2 }; diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index ce11aaf14..dd51c7464 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -28,12 +28,6 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { return; } - std::array dst; - const buffer_c16_t dst_buffer { - dst.data(), - dst.size() - }; - const auto decim_0_out = decim_0.execute(buffer, dst_buffer); const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); const auto channel_out = channel_filter.execute(decim_1_out, dst_buffer); @@ -42,11 +36,6 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { feed_channel_stats(channel_out); channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); - const buffer_s16_t work_audio_buffer { - (int16_t*)dst.data(), - sizeof(*dst.data()) * dst.size() - }; - auto audio = demod.execute(channel_out, work_audio_buffer); audio_hpf.execute_in_place(audio); diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 172fab616..1ab7890f3 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -40,6 +40,16 @@ public: void on_message(const Message* const message) override; private: + std::array dst; + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + const buffer_s16_t work_audio_buffer { + (int16_t*)dst.data(), + sizeof(*dst.data()) * dst.size() + }; + dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC16xR16x32Decim8 decim_1; dsp::decimate::FIRAndDecimateComplex channel_filter; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 4468af000..8424f0d80 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -29,12 +29,6 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { return; } - std::array dst; - const buffer_c16_t dst_buffer { - dst.data(), - dst.size() - }; - const auto decim_0_out = decim_0.execute(buffer, dst_buffer); const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); const auto channel_out = channel_filter.execute(decim_1_out, dst_buffer); @@ -42,11 +36,6 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { feed_channel_stats(channel_out); channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); - const buffer_s16_t work_audio_buffer { - (int16_t*)dst.data(), - sizeof(*dst.data()) * dst.size() - }; - auto audio = demod.execute(channel_out, work_audio_buffer); static uint64_t audio_present_history = 0; diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 87e056935..aa444c206 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -39,6 +39,16 @@ public: void on_message(const Message* const message) override; private: + std::array dst; + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + const buffer_s16_t work_audio_buffer { + (int16_t*)dst.data(), + sizeof(*dst.data()) * dst.size() + }; + dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC16xR16x32Decim8 decim_1; diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index 99b58b574..6ae7da998 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -57,12 +57,6 @@ TPMSProcessor::TPMSProcessor() { void TPMSProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ - std::array dst; - const buffer_c16_t dst_buffer { - dst.data(), - dst.size() - }; - const auto decim_0_out = decim_0.execute(buffer, dst_buffer); const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); const auto decimator_out = decim_1_out; diff --git a/firmware/baseband/proc_tpms.hpp b/firmware/baseband/proc_tpms.hpp index 0164a28c7..0c42beb73 100644 --- a/firmware/baseband/proc_tpms.hpp +++ b/firmware/baseband/proc_tpms.hpp @@ -59,6 +59,12 @@ public: void execute(const buffer_c8_t& buffer) override; private: + std::array dst; + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; dsp::decimate::FIRC16xR16x16Decim2 decim_1; diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 485fa6206..617102996 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -28,21 +28,10 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { return; } - std::array dst; - const buffer_c16_t dst_buffer { - dst.data(), - dst.size() - }; - const auto decim_0_out = decim_0.execute(buffer, dst_buffer); const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); const auto decimator_out = decim_1_out; - const buffer_s16_t work_audio_buffer { - (int16_t*)decimator_out.p, - sizeof(*decimator_out.p) * decimator_out.count - }; - auto channel = decimator_out; // TODO: Feed channel_stats post-decimation data? diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 9ef62fc8d..6c149328c 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -36,6 +36,16 @@ public: void on_message(const Message* const message) override; private: + std::array dst; + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + const buffer_s16_t work_audio_buffer { + (int16_t*)dst.data(), + sizeof(dst) / sizeof(int16_t) + }; + dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; dsp::decimate::FIRC16xR16x16Decim2 decim_1; From b03da8d6931288721feb9c33e0d0111abb586b54 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 22:42:40 -0800 Subject: [PATCH 221/452] Fix calculation of work_audio_buffer item count. --- firmware/baseband/proc_am_audio.hpp | 2 +- firmware/baseband/proc_nfm_audio.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 1ab7890f3..46fbbee52 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -47,7 +47,7 @@ private: }; const buffer_s16_t work_audio_buffer { (int16_t*)dst.data(), - sizeof(*dst.data()) * dst.size() + sizeof(dst) / sizeof(int16_t) }; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index aa444c206..a4c65576f 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -46,7 +46,7 @@ private: }; const buffer_s16_t work_audio_buffer { (int16_t*)dst.data(), - sizeof(*dst.data()) * dst.size() + sizeof(dst) / sizeof(int16_t) }; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; From b0855b3c4d508b6527f5bfb99d5767a0eef4abc6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 3 Jan 2016 23:09:06 -0800 Subject: [PATCH 222/452] Pass buffers by reference to save significant text section code size. 752 bytes! --- firmware/baseband/dsp_decimate.cpp | 36 +++++++++++++-------------- firmware/baseband/dsp_decimate.hpp | 40 +++++++++++++++--------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/firmware/baseband/dsp_decimate.cpp b/firmware/baseband/dsp_decimate.cpp index 6bc2c9b3c..b3dd91749 100644 --- a/firmware/baseband/dsp_decimate.cpp +++ b/firmware/baseband/dsp_decimate.cpp @@ -199,8 +199,8 @@ void FIRC8xR16x24FS4Decim4::configure( } buffer_c16_t FIRC8xR16x24FS4Decim4::execute( - buffer_c8_t src, - buffer_c16_t dst + const buffer_c8_t& src, + const buffer_c16_t& dst ) { vec2_s16* const z = static_cast(__builtin_assume_aligned(z_.data(), 4)); const vec2_s16* const t = static_cast(__builtin_assume_aligned(taps_.data(), 4)); @@ -264,8 +264,8 @@ void FIRC8xR16x24FS4Decim8::configure( } buffer_c16_t FIRC8xR16x24FS4Decim8::execute( - buffer_c8_t src, - buffer_c16_t dst + const buffer_c8_t& src, + const buffer_c16_t& dst ) { vec2_s16* const z = static_cast(__builtin_assume_aligned(z_.data(), 4)); const vec2_s16* const t = static_cast(__builtin_assume_aligned(taps_.data(), 4)); @@ -322,8 +322,8 @@ void FIRC16xR16x16Decim2::configure( } buffer_c16_t FIRC16xR16x16Decim2::execute( - buffer_c16_t src, - buffer_c16_t dst + const buffer_c16_t& src, + const buffer_c16_t& dst ) { vec2_s16* const z = static_cast(__builtin_assume_aligned(z_.data(), 4)); const vec2_s16* const t = static_cast(__builtin_assume_aligned(taps_.data(), 4)); @@ -376,8 +376,8 @@ void FIRC16xR16x32Decim8::configure( } buffer_c16_t FIRC16xR16x32Decim8::execute( - buffer_c16_t src, - buffer_c16_t dst + const buffer_c16_t& src, + const buffer_c16_t& dst ) { vec2_s16* const z = static_cast(__builtin_assume_aligned(z_.data(), 4)); const vec2_s16* const t = static_cast(__builtin_assume_aligned(taps_.data(), 4)); @@ -423,7 +423,7 @@ buffer_c16_t FIRC16xR16x32Decim8::execute( }; } -buffer_c16_t Complex8DecimateBy2CIC3::execute(buffer_c8_t src, buffer_c16_t dst) { +buffer_c16_t Complex8DecimateBy2CIC3::execute(const buffer_c8_t& src, const buffer_c16_t& dst) { /* Decimates by two using a non-recursive third-order CIC filter. */ @@ -480,7 +480,7 @@ buffer_c16_t Complex8DecimateBy2CIC3::execute(buffer_c8_t src, buffer_c16_t dst) return { dst.p, src.count / 2, src.sampling_rate / 2 }; } -buffer_c16_t TranslateByFSOver4AndDecimateBy2CIC3::execute(buffer_c8_t src, buffer_c16_t dst) { +buffer_c16_t TranslateByFSOver4AndDecimateBy2CIC3::execute(const buffer_c8_t& src, const buffer_c16_t& dst) { /* Translates incoming complex samples by -fs/4, * decimates by two using a non-recursive third-order CIC filter. */ @@ -565,8 +565,8 @@ buffer_c16_t TranslateByFSOver4AndDecimateBy2CIC3::execute(buffer_c8_t src, buff } buffer_c16_t DecimateBy2CIC3::execute( - buffer_c16_t src, - buffer_c16_t dst + const buffer_c16_t& src, + const buffer_c16_t& dst ) { /* Complex non-recursive 3rd-order CIC filter (taps 1,3,3,1). * Gain of 8. @@ -625,8 +625,8 @@ void FIR64AndDecimateBy2Real::configure( } buffer_s16_t FIR64AndDecimateBy2Real::execute( - buffer_s16_t src, - buffer_s16_t dst + const buffer_s16_t& src, + const buffer_s16_t& dst ) { /* int16_t input (sample count "n" must be multiple of 4) * -> int16_t output, decimated by 2. @@ -658,8 +658,8 @@ buffer_s16_t FIR64AndDecimateBy2Real::execute( } buffer_c16_t FIRAndDecimateComplex::execute( - buffer_c16_t src, - buffer_c16_t dst + const buffer_c16_t& src, + const buffer_c16_t& dst ) { /* int16_t input (sample count "n" must be multiple of decimation_factor) * -> int16_t output, decimated by decimation_factor. @@ -768,8 +768,8 @@ buffer_c16_t FIRAndDecimateComplex::execute( } buffer_s16_t DecimateBy2CIC4Real::execute( - buffer_s16_t src, - buffer_s16_t dst + const buffer_s16_t& src, + const buffer_s16_t& dst ) { auto src_p = src.p; auto dst_p = dst.p; diff --git a/firmware/baseband/dsp_decimate.hpp b/firmware/baseband/dsp_decimate.hpp index 6922999b6..ac5c927fc 100644 --- a/firmware/baseband/dsp_decimate.hpp +++ b/firmware/baseband/dsp_decimate.hpp @@ -39,8 +39,8 @@ namespace decimate { class Complex8DecimateBy2CIC3 { public: buffer_c16_t execute( - buffer_c8_t src, - buffer_c16_t dst + const buffer_c8_t& src, + const buffer_c16_t& dst ); private: @@ -51,8 +51,8 @@ private: class TranslateByFSOver4AndDecimateBy2CIC3 { public: buffer_c16_t execute( - buffer_c8_t src, - buffer_c16_t dst + const buffer_c8_t& src, + const buffer_c16_t& dst ); private: @@ -63,8 +63,8 @@ private: class DecimateBy2CIC3 { public: buffer_c16_t execute( - buffer_c16_t src, - buffer_c16_t dst + const buffer_c16_t& src, + const buffer_c16_t& dst ); private: @@ -81,8 +81,8 @@ public: ); buffer_s16_t execute( - buffer_s16_t src, - buffer_s16_t dst + const buffer_s16_t& src, + const buffer_s16_t& dst ); private: @@ -112,8 +112,8 @@ public: ); buffer_c16_t execute( - buffer_c8_t src, - buffer_c16_t dst + const buffer_c8_t& src, + const buffer_c16_t& dst ); private: @@ -144,8 +144,8 @@ public: ); buffer_c16_t execute( - buffer_c8_t src, - buffer_c16_t dst + const buffer_c8_t& src, + const buffer_c16_t& dst ); private: @@ -170,8 +170,8 @@ public: ); buffer_c16_t execute( - buffer_c16_t src, - buffer_c16_t dst + const buffer_c16_t& src, + const buffer_c16_t& dst ); private: @@ -196,8 +196,8 @@ public: ); buffer_c16_t execute( - buffer_c16_t src, - buffer_c16_t dst + const buffer_c16_t& src, + const buffer_c16_t& dst ); private: @@ -235,8 +235,8 @@ public: } buffer_c16_t execute( - buffer_c16_t src, - buffer_c16_t dst + const buffer_c16_t& src, + const buffer_c16_t& dst ); private: @@ -251,8 +251,8 @@ private: class DecimateBy2CIC4Real { public: buffer_s16_t execute( - buffer_s16_t src, - buffer_s16_t dst + const buffer_s16_t& src, + const buffer_s16_t& dst ); private: From 8fb3ffaedc3e5165999fbaacae437e033465d83d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 09:01:51 -0800 Subject: [PATCH 223/452] Reorder squelch code to group things a bit more logically. --- firmware/baseband/proc_nfm_audio.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 8424f0d80..87217851b 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -38,14 +38,16 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { auto audio = demod.execute(channel_out, work_audio_buffer); - static uint64_t audio_present_history = 0; + // Yes, evaluate squelch here, but do audio filtering regardless to keep glitches + // out of the filters. Zero out audio *after* filtering, based on squelch status. const auto audio_present_now = squelch.execute(audio); - audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0); - const bool audio_present = (audio_present_history != 0); audio_hpf.execute_in_place(audio); audio_deemph.execute_in_place(audio); + static uint64_t audio_present_history = 0; + audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0); + const bool audio_present = (audio_present_history != 0); if( !audio_present ) { // Zero audio buffer. for(size_t i=0; i Date: Mon, 4 Jan 2016 09:06:17 -0800 Subject: [PATCH 224/452] Add mute_audio() function to baseband processor. --- firmware/baseband/baseband_processor.cpp | 4 ++++ firmware/baseband/baseband_processor.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index 9c05de3e2..cfef43b22 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -54,6 +54,10 @@ void BasebandProcessor::fill_audio_buffer(const buffer_s16_t& audio) { feed_audio_stats(audio); } +void BasebandProcessor::mute_audio() { + i2s::i2s0::tx_mute(); +} + void BasebandProcessor::feed_audio_stats(const buffer_s16_t& audio) { audio_stats.feed( audio, diff --git a/firmware/baseband/baseband_processor.hpp b/firmware/baseband/baseband_processor.hpp index 48b23b7ba..99df8703b 100644 --- a/firmware/baseband/baseband_processor.hpp +++ b/firmware/baseband/baseband_processor.hpp @@ -45,6 +45,7 @@ protected: void feed_channel_stats(const buffer_c16_t& channel); void fill_audio_buffer(const buffer_s16_t& audio); + void mute_audio(); private: ChannelStatsCollector channel_stats; From 222b878629d39ea2576ea54f090898baf7e2372c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 09:07:07 -0800 Subject: [PATCH 225/452] Use BasebandProcessor::mute_audio(), remove I2S #include dependencies. --- firmware/baseband/proc_ais.cpp | 5 +---- firmware/baseband/proc_ert.cpp | 5 +---- firmware/baseband/proc_nfm_audio.cpp | 12 +++++------- firmware/baseband/proc_tpms.cpp | 5 +---- firmware/baseband/proc_wideband_spectrum.cpp | 5 +---- 5 files changed, 9 insertions(+), 23 deletions(-) diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index b12e8ba88..295bd8e15 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -23,9 +23,6 @@ #include "portapack_shared_memory.hpp" -#include "i2s.hpp" -using namespace lpc43xx; - #include "dsp_fir_taps.hpp" AISProcessor::AISProcessor() { @@ -56,7 +53,7 @@ void AISProcessor::execute(const buffer_c8_t& buffer) { } } - i2s::i2s0::tx_mute(); + mute_audio(); } void AISProcessor::consume_symbol( diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index c2b08f476..5708e8ed5 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -23,9 +23,6 @@ #include "portapack_shared_memory.hpp" -#include "i2s.hpp" -using namespace lpc43xx; - float ERTProcessor::abs(const complex8_t& v) { // const int16_t r = v.real() - offset_i; // const int16_t i = v.imag() - offset_q; @@ -83,7 +80,7 @@ void ERTProcessor::execute(const buffer_c8_t& buffer) { clock_recovery(data); } - i2s::i2s0::tx_mute(); + mute_audio(); } void ERTProcessor::consume_symbol( diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 87217851b..749d754b1 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -48,14 +48,12 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { static uint64_t audio_present_history = 0; audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0); const bool audio_present = (audio_present_history != 0); - if( !audio_present ) { - // Zero audio buffer. - for(size_t i=0; i @@ -65,7 +62,7 @@ void WidebandSpectrum::execute(const buffer_c8_t& buffer) { phase++; } - i2s::i2s0::tx_mute(); + mute_audio(); } void WidebandSpectrum::on_message(const Message* const message) { From c5b234d9f682586dddf2211f7b0cd9ad2567d4ce Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 09:13:17 -0800 Subject: [PATCH 226/452] Remove BasebandProcessor virtual method replaced by message. --- firmware/baseband/baseband_processor.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/firmware/baseband/baseband_processor.hpp b/firmware/baseband/baseband_processor.hpp index 99df8703b..707a3ef84 100644 --- a/firmware/baseband/baseband_processor.hpp +++ b/firmware/baseband/baseband_processor.hpp @@ -39,7 +39,6 @@ public: virtual void execute(const buffer_c8_t& buffer) = 0; virtual void on_message(const Message* const) { }; - virtual void on_update_spectrum() { }; protected: void feed_channel_stats(const buffer_c16_t& channel); From 168bd02deae7b0953b3c93087f46cab963086a8f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 09:25:43 -0800 Subject: [PATCH 227/452] Move AudioStatsCollector code into .cpp. --- firmware/baseband/Makefile | 1 + firmware/baseband/audio_stats_collector.cpp | 60 +++++++++++++++++++++ firmware/baseband/audio_stats_collector.hpp | 39 ++------------ 3 files changed, 64 insertions(+), 36 deletions(-) create mode 100644 firmware/baseband/audio_stats_collector.cpp diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 2970d145d..4d167f9a9 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -155,6 +155,7 @@ CPPSRC = main.cpp \ rssi_thread.cpp \ audio.cpp \ audio_dma.cpp \ + audio_stats_collector.cpp \ touch_dma.cpp \ ../common/utility.cpp \ ../common/chibios_cpp.cpp \ diff --git a/firmware/baseband/audio_stats_collector.cpp b/firmware/baseband/audio_stats_collector.cpp new file mode 100644 index 000000000..a82e8f40e --- /dev/null +++ b/firmware/baseband/audio_stats_collector.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "audio_stats_collector.hpp" + +#include "utility.hpp" + +void AudioStatsCollector::consume_audio_buffer(const buffer_s16_t& src) { + auto src_p = src.p; + const auto src_end = &src.p[src.count]; + while(src_p < src_end) { + const auto sample = *(src_p++); + const uint64_t sample_squared = sample * sample; + squared_sum += sample_squared; + if( sample_squared > max_squared ) { + max_squared = sample_squared; + } + } +} + +bool AudioStatsCollector::update_stats(const size_t sample_count, const size_t sampling_rate) { + count += sample_count; + + const size_t samples_per_update = sampling_rate * update_interval; + + if( count >= samples_per_update ) { + const float squared_sum_f = squared_sum; + const float max_squared_f = max_squared; + const float squared_avg_f = squared_sum_f / count; + statistics.rms_db = complex16_mag_squared_to_dbv_norm(squared_avg_f); + statistics.max_db = complex16_mag_squared_to_dbv_norm(max_squared_f); + statistics.count = count; + + squared_sum = 0; + max_squared = 0; + count = 0; + + return true; + } else { + return false; + } +} diff --git a/firmware/baseband/audio_stats_collector.hpp b/firmware/baseband/audio_stats_collector.hpp index 15405673a..1193fd0d0 100644 --- a/firmware/baseband/audio_stats_collector.hpp +++ b/firmware/baseband/audio_stats_collector.hpp @@ -22,9 +22,8 @@ #ifndef __AUDIO_STATS_COLLECTOR_H__ #define __AUDIO_STATS_COLLECTOR_H__ -#include "buffer.hpp" +#include "dsp_types.hpp" #include "message.hpp" -#include "utility.hpp" #include #include @@ -55,41 +54,9 @@ private: AudioStatistics statistics; - void consume_audio_buffer(const buffer_s16_t& src) { - auto src_p = src.p; - const auto src_end = &src.p[src.count]; - while(src_p < src_end) { - const auto sample = *(src_p++); - const uint64_t sample_squared = sample * sample; - squared_sum += sample_squared; - if( sample_squared > max_squared ) { - max_squared = sample_squared; - } - } - } + void consume_audio_buffer(const buffer_s16_t& src); - bool update_stats(const size_t sample_count, const size_t sampling_rate) { - count += sample_count; - - const size_t samples_per_update = sampling_rate * update_interval; - - if( count >= samples_per_update ) { - const float squared_sum_f = squared_sum; - const float max_squared_f = max_squared; - const float squared_avg_f = squared_sum_f / count; - statistics.rms_db = complex16_mag_squared_to_dbv_norm(squared_avg_f); - statistics.max_db = complex16_mag_squared_to_dbv_norm(max_squared_f); - statistics.count = count; - - squared_sum = 0; - max_squared = 0; - count = 0; - - return true; - } else { - return false; - } - } + bool update_stats(const size_t sample_count, const size_t sampling_rate); }; #endif/*__AUDIO_STATS_COLLECTOR_H__*/ From cd17f414b7572fd9fee14c519ff7519c6cdc1a2b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 09:49:48 -0800 Subject: [PATCH 228/452] ChannelDecimator now unused, remove from Makefile, remove commented code. --- firmware/baseband/Makefile | 1 - firmware/baseband/proc_ert.hpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 4d167f9a9..ca7ecee3f 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -131,7 +131,6 @@ CPPSRC = main.cpp \ portapack_shared_memory.cpp \ baseband_thread.cpp \ baseband_processor.cpp \ - channel_decimator.cpp \ dsp_decimate.cpp \ dsp_demodulate.cpp \ matched_filter.cpp \ diff --git a/firmware/baseband/proc_ert.hpp b/firmware/baseband/proc_ert.hpp index 439180d1c..9c0663c95 100644 --- a/firmware/baseband/proc_ert.hpp +++ b/firmware/baseband/proc_ert.hpp @@ -61,8 +61,6 @@ private: const size_t samples_per_symbol = channel_sampling_rate / symbol_rate; const float clock_recovery_rate = symbol_rate * 2; - // ChannelDecimator decimator { ChannelDecimator::DecimationFactor::By2, false }; - clock_recovery::ClockRecovery clock_recovery { clock_recovery_rate, symbol_rate, { 1.0f / 18.0f }, [this](const float symbol) { this->consume_symbol(symbol); } From 778e2d2381e7669f02f946f8679f4e85607f0b2e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 10:12:18 -0800 Subject: [PATCH 229/452] A little code consolidation -- M0APP IRQ. --- firmware/baseband/Makefile | 1 - firmware/baseband/event_m4.cpp | 19 +++++++++++ firmware/baseband/irq_ipc_m4.cpp | 54 -------------------------------- firmware/baseband/irq_ipc_m4.hpp | 28 ----------------- firmware/baseband/main.cpp | 6 ++-- firmware/common/lpc43xx_cpp.hpp | 10 ++++++ 6 files changed, 31 insertions(+), 87 deletions(-) delete mode 100644 firmware/baseband/irq_ipc_m4.cpp delete mode 100644 firmware/baseband/irq_ipc_m4.hpp diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index ca7ecee3f..5695723ba 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -125,7 +125,6 @@ CSRC = $(PORTSRC) \ CPPSRC = main.cpp \ message_queue.cpp \ event_m4.cpp \ - irq_ipc_m4.cpp \ gpdma.cpp \ baseband_dma.cpp \ portapack_shared_memory.cpp \ diff --git a/firmware/baseband/event_m4.cpp b/firmware/baseband/event_m4.cpp index 50b0c0b77..ca0038e72 100644 --- a/firmware/baseband/event_m4.cpp +++ b/firmware/baseband/event_m4.cpp @@ -21,6 +21,9 @@ #include "event_m4.hpp" +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + #include "ch.h" Thread* thread_event_loop = nullptr; @@ -28,3 +31,19 @@ Thread* thread_event_loop = nullptr; void events_initialize(Thread* const event_loop_thread) { thread_event_loop = event_loop_thread; } + +extern "C" { + +CH_IRQ_HANDLER(MAPP_IRQHandler) { + CH_IRQ_PROLOGUE(); + + chSysLockFromIsr(); + events_flag_isr(EVT_MASK_BASEBAND); + chSysUnlockFromIsr(); + + creg::m0apptxevent::clear(); + + CH_IRQ_EPILOGUE(); +} + +} diff --git a/firmware/baseband/irq_ipc_m4.cpp b/firmware/baseband/irq_ipc_m4.cpp deleted file mode 100644 index 07a753352..000000000 --- a/firmware/baseband/irq_ipc_m4.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "irq_ipc_m4.hpp" - -#include "ch.h" -#include "hal.h" - -#include "event_m4.hpp" - -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - -void m0apptxevent_interrupt_enable() { - nvicEnableVector(M0CORE_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_M0APPTXEVENT_IRQ_PRIORITY)); -} - -void m0apptxevent_interrupt_disable() { - nvicDisableVector(M0CORE_IRQn); -} - -extern "C" { - -CH_IRQ_HANDLER(MAPP_IRQHandler) { - CH_IRQ_PROLOGUE(); - - chSysLockFromIsr(); - events_flag_isr(EVT_MASK_BASEBAND); - chSysUnlockFromIsr(); - - creg::m0apptxevent::clear(); - - CH_IRQ_EPILOGUE(); -} - -} diff --git a/firmware/baseband/irq_ipc_m4.hpp b/firmware/baseband/irq_ipc_m4.hpp deleted file mode 100644 index 61328685d..000000000 --- a/firmware/baseband/irq_ipc_m4.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __IRQ_IPC_M4_H__ -#define __IRQ_IPC_M4_H__ - -void m0apptxevent_interrupt_enable(); -void m0apptxevent_interrupt_disable(); - -#endif/*__IRQ_IPC_M4_H__*/ diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 3814aa282..fcf9de579 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -30,8 +30,6 @@ #include "event_m4.hpp" -#include "irq_ipc_m4.hpp" - #include "touch_dma.hpp" #include "baseband_thread.hpp" @@ -123,7 +121,7 @@ class EventDispatcher { public: void run() { events_initialize(chThdSelf()); - m0apptxevent_interrupt_enable(); + lpc43xx::creg::m0apptxevent::enable(); baseband_thread.thread_main = chThdSelf(); baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); @@ -134,7 +132,7 @@ public: dispatch(events); } - m0apptxevent_interrupt_disable(); + lpc43xx::creg::m0apptxevent::disable(); } void request_stop() { diff --git a/firmware/common/lpc43xx_cpp.hpp b/firmware/common/lpc43xx_cpp.hpp index abdb0d629..f1578192d 100644 --- a/firmware/common/lpc43xx_cpp.hpp +++ b/firmware/common/lpc43xx_cpp.hpp @@ -57,6 +57,16 @@ inline void clear() { namespace m0apptxevent { +#if defined(LPC43XX_M4) +inline void enable() { + nvicEnableVector(M0CORE_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_M0APPTXEVENT_IRQ_PRIORITY)); +} + +inline void disable() { + nvicDisableVector(M0CORE_IRQn); +} +#endif + #if defined(LPC43XX_M0) inline void assert() { __SEV(); From 05a1c224261763116e77376adc51fe471d43f003 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 11:00:17 -0800 Subject: [PATCH 230/452] More tweaks to pass buffers by reference. 144 bytes less code! --- firmware/baseband/dsp_demodulate.cpp | 8 ++++---- firmware/baseband/dsp_demodulate.hpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/baseband/dsp_demodulate.cpp b/firmware/baseband/dsp_demodulate.cpp index bc11e990c..42f04b01c 100644 --- a/firmware/baseband/dsp_demodulate.cpp +++ b/firmware/baseband/dsp_demodulate.cpp @@ -31,8 +31,8 @@ namespace dsp { namespace demodulate { buffer_s16_t AM::execute( - buffer_c16_t src, - buffer_s16_t dst + const buffer_c16_t& src, + const buffer_s16_t& dst ) { /* Intermediate maximum value: 46341 (when input is -32768,-32768). */ /* Normalized to maximum 32767 for int16_t representation. */ @@ -78,8 +78,8 @@ static inline float angle_precise(const complex32_t t) { } buffer_s16_t FM::execute( - buffer_c16_t src, - buffer_s16_t dst + const buffer_c16_t& src, + const buffer_s16_t& dst ) { auto z = z_; diff --git a/firmware/baseband/dsp_demodulate.hpp b/firmware/baseband/dsp_demodulate.hpp index 6e84fb8b3..0f1d4bf84 100644 --- a/firmware/baseband/dsp_demodulate.hpp +++ b/firmware/baseband/dsp_demodulate.hpp @@ -30,16 +30,16 @@ namespace demodulate { class AM { public: buffer_s16_t execute( - buffer_c16_t src, - buffer_s16_t dst + const buffer_c16_t& src, + const buffer_s16_t& dst ); }; class FM { public: buffer_s16_t execute( - buffer_c16_t src, - buffer_s16_t dst + const buffer_c16_t& src, + const buffer_s16_t& dst ); void configure(const float sampling_rate, const float deviation_hz) { From 359fb6f3c6eeb2bbdc50e1cb319bb13631b5053e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 11:04:28 -0800 Subject: [PATCH 231/452] ...and more pass-by-reference. Another 176 bytes! --- firmware/baseband/dsp_iir.cpp | 4 ++-- firmware/baseband/dsp_iir.hpp | 4 ++-- firmware/baseband/dsp_squelch.cpp | 2 +- firmware/baseband/dsp_squelch.hpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/baseband/dsp_iir.cpp b/firmware/baseband/dsp_iir.cpp index e8367a76e..8fde51ef6 100644 --- a/firmware/baseband/dsp_iir.cpp +++ b/firmware/baseband/dsp_iir.cpp @@ -23,7 +23,7 @@ #include -void IIRBiquadFilter::execute(buffer_s16_t buffer_in, buffer_s16_t buffer_out) { +void IIRBiquadFilter::execute(const buffer_s16_t& buffer_in, const buffer_s16_t& buffer_out) { // TODO: Assert that buffer_out.count == buffer_in.count. for(size_t i=0; i #include -bool FMSquelch::execute(buffer_s16_t audio) { +bool FMSquelch::execute(const buffer_s16_t& audio) { // TODO: No hard-coded array size. std::array squelch_energy_buffer; const buffer_s16_t squelch_energy { diff --git a/firmware/baseband/dsp_squelch.hpp b/firmware/baseband/dsp_squelch.hpp index cd8e841d1..1a1607d7a 100644 --- a/firmware/baseband/dsp_squelch.hpp +++ b/firmware/baseband/dsp_squelch.hpp @@ -31,7 +31,7 @@ class FMSquelch { public: - bool execute(buffer_s16_t audio); + bool execute(const buffer_s16_t& audio); void set_threshold(const uint32_t new_value); From e6f69c90f24ee4125d1ebe653d3f76841a235f67 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 11:20:28 -0800 Subject: [PATCH 232/452] Reduce inlining of FIR configuration due to templating. 80 bytes! --- firmware/baseband/dsp_decimate.cpp | 12 ++++++++++++ firmware/baseband/dsp_decimate.hpp | 12 +++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/firmware/baseband/dsp_decimate.cpp b/firmware/baseband/dsp_decimate.cpp index b3dd91749..5c5ba40e7 100644 --- a/firmware/baseband/dsp_decimate.cpp +++ b/firmware/baseband/dsp_decimate.cpp @@ -657,6 +657,18 @@ buffer_s16_t FIR64AndDecimateBy2Real::execute( return { dst.p, src.count / 2, src.sampling_rate / 2 }; } +void FIRAndDecimateComplex::configure( + const int16_t* const taps, + const size_t taps_count, + const size_t decimation_factor +) { + samples_ = std::make_unique(taps_count); + taps_reversed_ = std::make_unique(taps_count); + taps_count_ = taps_count; + decimation_factor_ = decimation_factor; + std::reverse_copy(&taps[0], &taps[taps_count], &taps_reversed_[0]); +} + buffer_c16_t FIRAndDecimateComplex::execute( const buffer_c16_t& src, const buffer_c16_t& dst diff --git a/firmware/baseband/dsp_decimate.hpp b/firmware/baseband/dsp_decimate.hpp index ac5c927fc..d3f41555b 100644 --- a/firmware/baseband/dsp_decimate.hpp +++ b/firmware/baseband/dsp_decimate.hpp @@ -227,11 +227,7 @@ public: const T& taps, const size_t decimation_factor ) { - samples_ = std::make_unique(taps.size()); - taps_reversed_ = std::make_unique(taps.size()); - taps_count_ = taps.size(); - decimation_factor_ = decimation_factor; - std::reverse_copy(taps.cbegin(), taps.cend(), &taps_reversed_[0]); + configure(taps.data(), taps.size(), decimation_factor); } buffer_c16_t execute( @@ -246,6 +242,12 @@ private: std::unique_ptr taps_reversed_; size_t taps_count_; size_t decimation_factor_; + + void configure( + const int16_t* const taps, + const size_t taps_count, + const size_t decimation_factor + ); }; class DecimateBy2CIC4Real { From cd3a5afdb1c41225a7c9e982aa310dd57700b4e9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 11:32:47 -0800 Subject: [PATCH 233/452] More templating elimination (MatchedFilter), some #include clean-up. 592 bytes! --- firmware/baseband/matched_filter.cpp | 17 +++++++++++++++++ firmware/baseband/matched_filter.hpp | 19 +++++++------------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/firmware/baseband/matched_filter.cpp b/firmware/baseband/matched_filter.cpp index 5040349a6..511410dfd 100644 --- a/firmware/baseband/matched_filter.cpp +++ b/firmware/baseband/matched_filter.cpp @@ -21,9 +21,26 @@ #include "matched_filter.hpp" +#include +#include + +#include "utility.hpp" + namespace dsp { namespace matched_filter { +void MatchedFilter::configure( + const tap_t* const taps, + const size_t taps_count, + const size_t decimation_factor +) { + samples_ = std::make_unique(taps_count); + taps_reversed_ = std::make_unique(taps_count); + taps_count_ = taps_count; + decimation_factor_ = decimation_factor; + std::reverse_copy(&taps[0], &taps[taps_count], &taps_reversed_[0]); +} + bool MatchedFilter::execute_once( const sample_t input ) { diff --git a/firmware/baseband/matched_filter.hpp b/firmware/baseband/matched_filter.hpp index 741f50180..d3ee30bef 100644 --- a/firmware/baseband/matched_filter.hpp +++ b/firmware/baseband/matched_filter.hpp @@ -22,17 +22,10 @@ #ifndef __MATCHED_FILTER_H__ #define __MATCHED_FILTER_H__ -#include "utility.hpp" - #include - #include -#include #include -#include -#include - namespace dsp { namespace matched_filter { @@ -61,11 +54,7 @@ public: const T& taps, size_t decimation_factor ) { - samples_ = std::make_unique(taps.size()); - taps_reversed_ = std::make_unique(taps.size()); - taps_count_ = taps.size(); - decimation_factor_ = decimation_factor; - std::reverse_copy(taps.cbegin(), taps.cend(), &taps_reversed_[0]); + configure(taps.data(), taps.size(), decimation_factor); } bool execute_once(const sample_t input); @@ -93,6 +82,12 @@ private: bool is_new_decimation_cycle() const { return (decimation_phase == 0); } + + void configure( + const tap_t* const taps, + const size_t taps_count, + const size_t decimation_factor + ); }; } /* namespace matched_filter */ From 6d3cdb9bbfe81b89b772678e44fa990d628e34d3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 11:45:33 -0800 Subject: [PATCH 234/452] Separate template/callback code from method code. ...for more small reductions in code size. --- firmware/baseband/audio_stats_collector.cpp | 10 ++++++++++ firmware/baseband/audio_stats_collector.hpp | 9 +++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/firmware/baseband/audio_stats_collector.cpp b/firmware/baseband/audio_stats_collector.cpp index a82e8f40e..c728ed355 100644 --- a/firmware/baseband/audio_stats_collector.cpp +++ b/firmware/baseband/audio_stats_collector.cpp @@ -58,3 +58,13 @@ bool AudioStatsCollector::update_stats(const size_t sample_count, const size_t s return false; } } + +bool AudioStatsCollector::feed(const buffer_s16_t& src) { + consume_audio_buffer(src); + + return update_stats(src.count, src.sampling_rate); +} + +bool AudioStatsCollector::mute(const size_t sample_count, const size_t sampling_rate) { + return update_stats(sample_count, sampling_rate); +} diff --git a/firmware/baseband/audio_stats_collector.hpp b/firmware/baseband/audio_stats_collector.hpp index 1193fd0d0..467bc3377 100644 --- a/firmware/baseband/audio_stats_collector.hpp +++ b/firmware/baseband/audio_stats_collector.hpp @@ -32,16 +32,14 @@ class AudioStatsCollector { public: template void feed(const buffer_s16_t& src, Callback callback) { - consume_audio_buffer(src); - - if( update_stats(src.count, src.sampling_rate) ) { + if( feed(src) ) { callback(statistics); } } template void mute(const size_t sample_count, const size_t sampling_rate, Callback callback) { - if( update_stats(sample_count, sampling_rate) ) { + if( mute(sample_count, sampling_rate) ) { callback(statistics); } } @@ -57,6 +55,9 @@ private: void consume_audio_buffer(const buffer_s16_t& src); bool update_stats(const size_t sample_count, const size_t sampling_rate); + + bool feed(const buffer_s16_t& src); + bool mute(const size_t sample_count, const size_t sampling_rate); }; #endif/*__AUDIO_STATS_COLLECTOR_H__*/ From b42d3cc9d508da6cbb7c0f779925998b96e3b206 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 11:49:39 -0800 Subject: [PATCH 235/452] Move BasebandStatsCollector code into .cpp, as much as possible. Still have template for callback, but hopefully will mitigate bloat when BasebandStatsCollector is used in multiple places. --- firmware/baseband/Makefile | 1 + .../baseband/baseband_stats_collector.cpp | 59 +++++++++++++++++++ .../baseband/baseband_stats_collector.hpp | 35 ++--------- 3 files changed, 65 insertions(+), 30 deletions(-) create mode 100644 firmware/baseband/baseband_stats_collector.cpp diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 5695723ba..1d9ccf516 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -130,6 +130,7 @@ CPPSRC = main.cpp \ portapack_shared_memory.cpp \ baseband_thread.cpp \ baseband_processor.cpp \ + baseband_stats_collector.cpp \ dsp_decimate.cpp \ dsp_demodulate.cpp \ matched_filter.cpp \ diff --git a/firmware/baseband/baseband_stats_collector.cpp b/firmware/baseband/baseband_stats_collector.cpp new file mode 100644 index 000000000..91a1bcf33 --- /dev/null +++ b/firmware/baseband/baseband_stats_collector.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "baseband_stats_collector.hpp" + +#include "utility_m4.hpp" + +bool BasebandStatsCollector::process(const buffer_c8_t& buffer) { + samples += buffer.count; + + const size_t report_samples = buffer.sampling_rate * report_interval; + const auto report_delta = samples - samples_last_report; + return report_delta >= report_samples; +} + +BasebandStatistics BasebandStatsCollector::capture_statistics() { + BasebandStatistics statistics; + + const auto idle_ticks = thread_idle->total_ticks; + statistics.idle_ticks = (idle_ticks - last_idle_ticks); + last_idle_ticks = idle_ticks; + + const auto main_ticks = thread_main->total_ticks; + statistics.main_ticks = (main_ticks - last_main_ticks); + last_main_ticks = main_ticks; + + const auto rssi_ticks = thread_rssi->total_ticks; + statistics.rssi_ticks = (rssi_ticks - last_rssi_ticks); + last_rssi_ticks = rssi_ticks; + + const auto baseband_ticks = thread_baseband->total_ticks; + statistics.baseband_ticks = (baseband_ticks - last_baseband_ticks); + last_baseband_ticks = baseband_ticks; + + statistics.saturation = m4_flag_saturation(); + clear_m4_flag_saturation(); + + samples_last_report = samples; + + return statistics; +} diff --git a/firmware/baseband/baseband_stats_collector.hpp b/firmware/baseband/baseband_stats_collector.hpp index d214d61f7..b628a8b2b 100644 --- a/firmware/baseband/baseband_stats_collector.hpp +++ b/firmware/baseband/baseband_stats_collector.hpp @@ -26,7 +26,6 @@ #include "dsp_types.hpp" #include "message.hpp" -#include "utility_m4.hpp" #include #include @@ -47,35 +46,8 @@ public: template void process(const buffer_c8_t& buffer, Callback callback) { - samples += buffer.count; - - const size_t report_samples = buffer.sampling_rate * report_interval; - const auto report_delta = samples - samples_last_report; - if( report_delta >= report_samples ) { - BasebandStatistics statistics; - - const auto idle_ticks = thread_idle->total_ticks; - statistics.idle_ticks = (idle_ticks - last_idle_ticks); - last_idle_ticks = idle_ticks; - - const auto main_ticks = thread_main->total_ticks; - statistics.main_ticks = (main_ticks - last_main_ticks); - last_main_ticks = main_ticks; - - const auto rssi_ticks = thread_rssi->total_ticks; - statistics.rssi_ticks = (rssi_ticks - last_rssi_ticks); - last_rssi_ticks = rssi_ticks; - - const auto baseband_ticks = thread_baseband->total_ticks; - statistics.baseband_ticks = (baseband_ticks - last_baseband_ticks); - last_baseband_ticks = baseband_ticks; - - statistics.saturation = m4_flag_saturation(); - clear_m4_flag_saturation(); - - callback(statistics); - - samples_last_report = samples; + if( process(buffer) ) { + callback(capture_statistics()); } } @@ -91,6 +63,9 @@ private: uint32_t last_rssi_ticks { 0 }; const Thread* const thread_baseband; uint32_t last_baseband_ticks { 0 }; + + bool process(const buffer_c8_t& buffer); + BasebandStatistics capture_statistics(); }; #endif/*__BASEBAND_STATS_COLLECTOR_H__*/ From a27489eb21fe28f116a434d14388604aeb6adfd2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 12:00:52 -0800 Subject: [PATCH 236/452] Consolidating M4-specific saturation flag code. --- firmware/baseband/baseband_stats_collector.cpp | 6 +++--- firmware/common/lpc43xx_cpp.hpp | 15 +++++++++++++++ firmware/common/utility_m4.hpp | 9 --------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/firmware/baseband/baseband_stats_collector.cpp b/firmware/baseband/baseband_stats_collector.cpp index 91a1bcf33..8eec12c5e 100644 --- a/firmware/baseband/baseband_stats_collector.cpp +++ b/firmware/baseband/baseband_stats_collector.cpp @@ -21,7 +21,7 @@ #include "baseband_stats_collector.hpp" -#include "utility_m4.hpp" +#include "lpc43xx_cpp.hpp" bool BasebandStatsCollector::process(const buffer_c8_t& buffer) { samples += buffer.count; @@ -50,8 +50,8 @@ BasebandStatistics BasebandStatsCollector::capture_statistics() { statistics.baseband_ticks = (baseband_ticks - last_baseband_ticks); last_baseband_ticks = baseband_ticks; - statistics.saturation = m4_flag_saturation(); - clear_m4_flag_saturation(); + statistics.saturation = lpc43xx::m4::flag_saturation(); + lpc43xx::m4::clear_flag_saturation(); samples_last_report = samples; diff --git a/firmware/common/lpc43xx_cpp.hpp b/firmware/common/lpc43xx_cpp.hpp index f1578192d..d2917f9b6 100644 --- a/firmware/common/lpc43xx_cpp.hpp +++ b/firmware/common/lpc43xx_cpp.hpp @@ -30,6 +30,21 @@ namespace lpc43xx { +#if defined(LPC43XX_M4) +namespace m4 { + +static inline bool flag_saturation() { + return __get_APSR() & (1U << 27); +} + +static inline void clear_flag_saturation() { + uint32_t flags = 1; + __asm volatile ("MSR APSR_nzcvqg, %0" : : "r" (flags)); +} + +} /* namespace m4 */ +#endif + namespace creg { static_assert(offsetof(LPC_CREG_Type, CREG0) == 0x004, "CREG0 offset wrong"); diff --git a/firmware/common/utility_m4.hpp b/firmware/common/utility_m4.hpp index 2516f12a1..c0868081d 100644 --- a/firmware/common/utility_m4.hpp +++ b/firmware/common/utility_m4.hpp @@ -26,15 +26,6 @@ #include -static inline bool m4_flag_saturation() { - return __get_APSR() & (1U << 27); -} - -static inline void clear_m4_flag_saturation() { - uint32_t flags = 1; - __asm volatile ("MSR APSR_nzcvqg, %0" : : "r" (flags)); -} - static inline complex32_t multiply_conjugate_s16_s32(const complex16_t::rep_type a, const complex16_t::rep_type b) { // conjugate: conj(a + bj) = a - bj // multiply: (a + bj) * (c + dj) = (ac - bd) + (bc + ad)j From b058c0fe009380a93dc362c8bb5add514fc3c902 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 12:07:30 -0800 Subject: [PATCH 237/452] Consolidate M0-specific code. --- firmware/application/irq_ipc.cpp | 4 ---- firmware/application/irq_ipc.hpp | 2 -- firmware/application/main.cpp | 2 +- firmware/common/lpc43xx_cpp.hpp | 10 ++++++++++ 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/firmware/application/irq_ipc.cpp b/firmware/application/irq_ipc.cpp index a4c7504bf..5ee5a97e3 100644 --- a/firmware/application/irq_ipc.cpp +++ b/firmware/application/irq_ipc.cpp @@ -29,10 +29,6 @@ #include "lpc43xx_cpp.hpp" using namespace lpc43xx; -void m4txevent_interrupt_enable() { - nvicEnableVector(M4CORE_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_M4TXEVENT_IRQ_PRIORITY)); -} - extern "C" { CH_IRQ_HANDLER(M4Core_IRQHandler) { diff --git a/firmware/application/irq_ipc.hpp b/firmware/application/irq_ipc.hpp index 70d59d15e..de768c80f 100644 --- a/firmware/application/irq_ipc.hpp +++ b/firmware/application/irq_ipc.hpp @@ -22,6 +22,4 @@ #ifndef __IRQ_IPC_H__ #define __IRQ_IPC_H__ -void m4txevent_interrupt_enable(); - #endif/*__IRQ_IPC_H__*/ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 21a5874ea..b40fff241 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -259,7 +259,7 @@ int main(void) { controls_init(); lcd_frame_sync_configure(); rtc_interrupt_enable(); - m4txevent_interrupt_enable(); + lpc43xx::creg::m4txevent::enable(); event_dispatcher.run(); diff --git a/firmware/common/lpc43xx_cpp.hpp b/firmware/common/lpc43xx_cpp.hpp index d2917f9b6..92ca64ec1 100644 --- a/firmware/common/lpc43xx_cpp.hpp +++ b/firmware/common/lpc43xx_cpp.hpp @@ -58,6 +58,16 @@ static_assert(offsetof(LPC_CREG_Type, USB1FLADJ) == 0x600, "USB1FLADJ offset wro namespace m4txevent { +#if defined(LPC43XX_M0) +inline void enable() { + nvicEnableVector(M4CORE_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_M4TXEVENT_IRQ_PRIORITY)); +} + +inline void disable() { + nvicDisableVector(M4CORE_IRQn); +} +#endif + #if defined(LPC43XX_M4) inline void assert() { __SEV(); From 69b258cc2b311393b07927e79ad85555b5f1ddcb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 12:15:10 -0800 Subject: [PATCH 238/452] Consolidate event handler code, including IRQ. --- firmware/application/Makefile | 1 - firmware/application/irq_ipc.cpp | 46 -------------------------------- firmware/application/irq_ipc.hpp | 25 ----------------- firmware/application/main.cpp | 17 +++++++++++- 4 files changed, 16 insertions(+), 73 deletions(-) delete mode 100644 firmware/application/irq_ipc.cpp delete mode 100644 firmware/application/irq_ipc.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index bd488ea74..ab0e616c2 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -118,7 +118,6 @@ CSRC = $(PORTSRC) \ # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. CPPSRC = main.cpp \ - irq_ipc.cpp \ irq_lcd_frame.cpp \ irq_controls.cpp \ irq_rtc.cpp \ diff --git a/firmware/application/irq_ipc.cpp b/firmware/application/irq_ipc.cpp deleted file mode 100644 index 5ee5a97e3..000000000 --- a/firmware/application/irq_ipc.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "irq_ipc.hpp" - -#include "event.hpp" - -#include "ch.h" -#include "hal.h" - -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - -extern "C" { - -CH_IRQ_HANDLER(M4Core_IRQHandler) { - CH_IRQ_PROLOGUE(); - - chSysLockFromIsr(); - events_flag_isr(EVT_MASK_APPLICATION); - chSysUnlockFromIsr(); - - creg::m4txevent::clear(); - - CH_IRQ_EPILOGUE(); -} - -} diff --git a/firmware/application/irq_ipc.hpp b/firmware/application/irq_ipc.hpp deleted file mode 100644 index de768c80f..000000000 --- a/firmware/application/irq_ipc.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __IRQ_IPC_H__ -#define __IRQ_IPC_H__ - -#endif/*__IRQ_IPC_H__*/ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index b40fff241..e5bcde2d6 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -33,7 +33,6 @@ #include "ui_painter.hpp" #include "ui_navigation.hpp" -#include "irq_ipc.hpp" #include "irq_lcd_frame.hpp" #include "irq_controls.hpp" #include "irq_rtc.hpp" @@ -55,6 +54,22 @@ using namespace lpc43xx; #include +extern "C" { + +CH_IRQ_HANDLER(M4Core_IRQHandler) { + CH_IRQ_PROLOGUE(); + + chSysLockFromIsr(); + events_flag_isr(EVT_MASK_APPLICATION); + chSysUnlockFromIsr(); + + creg::m4txevent::clear(); + + CH_IRQ_EPILOGUE(); +} + +} + class EventDispatcher { public: EventDispatcher( From 0fe5409357e1df3051a7e2397ac2b0574ffa780a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 12:15:35 -0800 Subject: [PATCH 239/452] Move M4TXEVENT interrupt control into event handler run(). --- firmware/application/main.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index e5bcde2d6..752da0354 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -86,10 +86,14 @@ public: } void run() { + creg::m4txevent::enable(); + while(is_running) { const auto events = wait(); dispatch(events); } + + creg::m4txevent::disable(); } void request_stop() { @@ -274,7 +278,6 @@ int main(void) { controls_init(); lcd_frame_sync_configure(); rtc_interrupt_enable(); - lpc43xx::creg::m4txevent::enable(); event_dispatcher.run(); From 229c1e9a3c9c89a4d0b2f9a02a2783debb77b8fb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 12:44:28 -0800 Subject: [PATCH 240/452] Move M4 MAPP IRQ handler to be with the event handler class. event.[ch]pp and event_m4.[ch]pp are looking almost the same now... --- firmware/baseband/event_m4.cpp | 19 ------------------- firmware/baseband/main.cpp | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/firmware/baseband/event_m4.cpp b/firmware/baseband/event_m4.cpp index ca0038e72..50b0c0b77 100644 --- a/firmware/baseband/event_m4.cpp +++ b/firmware/baseband/event_m4.cpp @@ -21,9 +21,6 @@ #include "event_m4.hpp" -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - #include "ch.h" Thread* thread_event_loop = nullptr; @@ -31,19 +28,3 @@ Thread* thread_event_loop = nullptr; void events_initialize(Thread* const event_loop_thread) { thread_event_loop = event_loop_thread; } - -extern "C" { - -CH_IRQ_HANDLER(MAPP_IRQHandler) { - CH_IRQ_PROLOGUE(); - - chSysLockFromIsr(); - events_flag_isr(EVT_MASK_BASEBAND); - chSysUnlockFromIsr(); - - creg::m0apptxevent::clear(); - - CH_IRQ_EPILOGUE(); -} - -} diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index fcf9de579..8a8852b59 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -117,6 +117,22 @@ static void shutdown() { halt(); } +extern "C" { + +CH_IRQ_HANDLER(MAPP_IRQHandler) { + CH_IRQ_PROLOGUE(); + + chSysLockFromIsr(); + events_flag_isr(EVT_MASK_BASEBAND); + chSysUnlockFromIsr(); + + creg::m0apptxevent::clear(); + + CH_IRQ_EPILOGUE(); +} + +} + class EventDispatcher { public: void run() { From c1e5577669ca59ee86e82cf2007121de4f193446 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 12:54:05 -0800 Subject: [PATCH 241/452] Eliminate duplicate code between event_m4.hpp, event.hpp. event.* is common code, _m0 and _m4 contain specific event mask definitions. --- .../event_m4.cpp => application/event_m0.hpp} | 18 +++++++++++------- firmware/application/irq_controls.cpp | 2 +- firmware/application/irq_lcd_frame.cpp | 2 +- firmware/application/irq_rtc.cpp | 2 +- firmware/application/main.cpp | 2 +- firmware/baseband/Makefile | 2 +- firmware/baseband/event_m4.hpp | 18 +----------------- firmware/{application => common}/event.cpp | 2 +- firmware/{application => common}/event.hpp | 9 +-------- 9 files changed, 19 insertions(+), 38 deletions(-) rename firmware/{baseband/event_m4.cpp => application/event_m0.hpp} (62%) rename firmware/{application => common}/event.cpp (93%) rename firmware/{application => common}/event.hpp (76%) diff --git a/firmware/baseband/event_m4.cpp b/firmware/application/event_m0.hpp similarity index 62% rename from firmware/baseband/event_m4.cpp rename to firmware/application/event_m0.hpp index 50b0c0b77..f2cb5e41d 100644 --- a/firmware/baseband/event_m4.cpp +++ b/firmware/application/event_m0.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. * * This file is part of PortaPack. * @@ -19,12 +19,16 @@ * Boston, MA 02110-1301, USA. */ -#include "event_m4.hpp" +#ifndef __EVENT_M0_H__ +#define __EVENT_M0_H__ -#include "ch.h" +#include "event.hpp" -Thread* thread_event_loop = nullptr; +constexpr auto EVT_MASK_RTC_TICK = EVENT_MASK(0); +constexpr auto EVT_MASK_LCD_FRAME_SYNC = EVENT_MASK(1); +constexpr auto EVT_MASK_SWITCHES = EVENT_MASK(3); +constexpr auto EVT_MASK_ENCODER = EVENT_MASK(4); +constexpr auto EVT_MASK_TOUCH = EVENT_MASK(5); +constexpr auto EVT_MASK_APPLICATION = EVENT_MASK(6); -void events_initialize(Thread* const event_loop_thread) { - thread_event_loop = event_loop_thread; -} +#endif/*__EVENT_M0_H__*/ diff --git a/firmware/application/irq_controls.cpp b/firmware/application/irq_controls.cpp index ddf8f154d..bba6f54d2 100644 --- a/firmware/application/irq_controls.cpp +++ b/firmware/application/irq_controls.cpp @@ -24,7 +24,7 @@ #include "ch.h" #include "hal.h" -#include "event.hpp" +#include "event_m0.hpp" #include "touch.hpp" #include "touch_adc.hpp" diff --git a/firmware/application/irq_lcd_frame.cpp b/firmware/application/irq_lcd_frame.cpp index 65498ad45..6ea2ed2df 100644 --- a/firmware/application/irq_lcd_frame.cpp +++ b/firmware/application/irq_lcd_frame.cpp @@ -21,7 +21,7 @@ #include "irq_lcd_frame.hpp" -#include "event.hpp" +#include "event_m0.hpp" #include "ch.h" #include "hal.h" diff --git a/firmware/application/irq_rtc.cpp b/firmware/application/irq_rtc.cpp index f393d0f45..9a7243201 100644 --- a/firmware/application/irq_rtc.cpp +++ b/firmware/application/irq_rtc.cpp @@ -26,7 +26,7 @@ #include "lpc43xx_cpp.hpp" using namespace lpc43xx; -#include "event.hpp" +#include "event_m0.hpp" void rtc_interrupt_enable() { rtc::interrupt::enable_second_inc(); diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 752da0354..8d8453bd6 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -37,7 +37,7 @@ #include "irq_controls.hpp" #include "irq_rtc.hpp" -#include "event.hpp" +#include "event_m0.hpp" #include "m4_startup.hpp" #include "spi_image.hpp" diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 1d9ccf516..27608c439 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -124,7 +124,7 @@ CSRC = $(PORTSRC) \ # setting. CPPSRC = main.cpp \ message_queue.cpp \ - event_m4.cpp \ + event.cpp \ gpdma.cpp \ baseband_dma.cpp \ portapack_shared_memory.cpp \ diff --git a/firmware/baseband/event_m4.hpp b/firmware/baseband/event_m4.hpp index be113ca89..03277443c 100644 --- a/firmware/baseband/event_m4.hpp +++ b/firmware/baseband/event_m4.hpp @@ -22,25 +22,9 @@ #ifndef __EVENT_M4_H__ #define __EVENT_M4_H__ -#include "ch.h" +#include "event.hpp" constexpr auto EVT_MASK_BASEBAND = EVENT_MASK(0); constexpr auto EVT_MASK_SPECTRUM = EVENT_MASK(1); -void events_initialize(Thread* const event_loop_thread); - -extern Thread* thread_event_loop; - -inline void events_flag(const eventmask_t events) { - if( thread_event_loop ) { - chEvtSignal(thread_event_loop, events); - } -} - -inline void events_flag_isr(const eventmask_t events) { - if( thread_event_loop ) { - chEvtSignalI(thread_event_loop, events); - } -} - #endif/*__EVENT_M4_H__*/ diff --git a/firmware/application/event.cpp b/firmware/common/event.cpp similarity index 93% rename from firmware/application/event.cpp rename to firmware/common/event.cpp index 5133c0c2c..28f1151d1 100644 --- a/firmware/application/event.cpp +++ b/firmware/common/event.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. * * This file is part of PortaPack. * diff --git a/firmware/application/event.hpp b/firmware/common/event.hpp similarity index 76% rename from firmware/application/event.hpp rename to firmware/common/event.hpp index fbf40d0a4..d05a0a325 100644 --- a/firmware/application/event.hpp +++ b/firmware/common/event.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. * * This file is part of PortaPack. * @@ -24,13 +24,6 @@ #include "ch.h" -constexpr auto EVT_MASK_RTC_TICK = EVENT_MASK(0); -constexpr auto EVT_MASK_LCD_FRAME_SYNC = EVENT_MASK(1); -constexpr auto EVT_MASK_SWITCHES = EVENT_MASK(3); -constexpr auto EVT_MASK_ENCODER = EVENT_MASK(4); -constexpr auto EVT_MASK_TOUCH = EVENT_MASK(5); -constexpr auto EVT_MASK_APPLICATION = EVENT_MASK(6); - void events_initialize(Thread* const event_loop_thread); extern Thread* thread_event_loop; From 73671ca5f6e220e9d4a81b52f11fd4968e4dc2f8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 15:41:49 -0800 Subject: [PATCH 242/452] Update sample rate and buffer size comments in execute() methods. --- firmware/baseband/proc_ais.cpp | 2 +- firmware/baseband/proc_tpms.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index 295bd8e15..237586588 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -37,7 +37,7 @@ void AISProcessor::execute(const buffer_c8_t& buffer) { const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); const auto decimator_out = decim_1_out; - /* 76.8kHz, 64 samples */ + /* 38.4kHz, 32 samples */ feed_channel_stats(decimator_out); /* No spectrum display while AIS decoding. feed_channel_spectrum( diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index 5a3e96541..efaf10920 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -58,7 +58,7 @@ void TPMSProcessor::execute(const buffer_c8_t& buffer) { const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); const auto decimator_out = decim_1_out; - /* 76.8kHz, 64 samples */ + /* 307.2kHz, 256 samples */ feed_channel_stats(decimator_out); /* No spectrum display while FSK decoding. feed_channel_spectrum( From 36021689f9a4c13017609d8d4ce069af05769b1e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 4 Jan 2016 15:42:19 -0800 Subject: [PATCH 243/452] Remove commented, dead code. --- firmware/baseband/proc_ais.cpp | 7 ------- firmware/baseband/proc_ert.cpp | 1 - firmware/baseband/proc_tpms.cpp | 7 ------- 3 files changed, 15 deletions(-) diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index 237586588..9caa9bb1d 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -39,13 +39,6 @@ void AISProcessor::execute(const buffer_c8_t& buffer) { /* 38.4kHz, 32 samples */ feed_channel_stats(decimator_out); - /* No spectrum display while AIS decoding. - feed_channel_spectrum( - channel, - decimator_out.sampling_rate * channel_filter_taps.pass_frequency_normalized, - decimator_out.sampling_rate * channel_filter_taps.stop_frequency_normalized - ); - */ for(size_t i=0; i Date: Mon, 4 Jan 2016 17:27:18 -0800 Subject: [PATCH 244/452] Add wideband FM spectrum waterfall. --- firmware/baseband/proc_wfm_audio.cpp | 19 ++++++++++++++++++- firmware/baseband/proc_wfm_audio.hpp | 8 ++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 617102996..5ad961d81 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -36,7 +36,12 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { // TODO: Feed channel_stats post-decimation data? feed_channel_stats(channel); - //feed_channel_spectrum(channel); + + spectrum_samples += channel.count; + if( spectrum_samples >= spectrum_interval_samples ) { + spectrum_samples -= spectrum_interval_samples; + channel_spectrum.feed(channel, channel_filter_pass_f, channel_filter_stop_f); + } /* 384kHz complex[256] * -> FM demodulation @@ -71,6 +76,10 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { void WidebandFMAudio::on_message(const Message* const message) { switch(message->id) { + case Message::ID::UpdateSpectrum: + channel_spectrum.update(); + break; + case Message::ID::WFMConfigure: configure(*reinterpret_cast(message)); break; @@ -93,10 +102,18 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) { constexpr size_t demod_input_fs = decim_1_output_fs; + constexpr auto spectrum_rate_hz = 50.0f; + spectrum_interval_samples = decim_1_output_fs / spectrum_rate_hz; + spectrum_samples = 0; + decim_0.configure(message.decim_0_filter.taps, 33554432); decim_1.configure(message.decim_1_filter.taps, 131072); + channel_filter_pass_f = message.decim_1_filter.pass_frequency_normalized * decim_1_input_fs; + channel_filter_stop_f = message.decim_1_filter.stop_frequency_normalized * decim_1_input_fs; demod.configure(demod_input_fs, message.deviation); audio_filter.configure(message.audio_filter.taps); + channel_spectrum.set_decimation_factor(1); + configured = true; } diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 6c149328c..4b1374937 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -29,6 +29,8 @@ #include "dsp_iir.hpp" #include "dsp_iir_config.hpp" +#include "spectrum_collector.hpp" + class WidebandFMAudio : public BasebandProcessor { public: void execute(const buffer_c8_t& buffer) override; @@ -48,6 +50,8 @@ private: dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; dsp::decimate::FIRC16xR16x16Decim2 decim_1; + uint32_t channel_filter_pass_f = 0; + uint32_t channel_filter_stop_f = 0; dsp::demodulate::FM demod; dsp::decimate::DecimateBy2CIC4Real audio_dec_1; @@ -57,6 +61,10 @@ private: IIRBiquadFilter audio_hpf { audio_hpf_30hz_config }; IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config }; + SpectrumCollector channel_spectrum; + size_t spectrum_interval_samples = 0; + size_t spectrum_samples = 0; + bool configured { false }; void configure(const WFMConfigureMessage& message); }; From 794925442eebb208f0b73935bc34f1fdec0cf9e9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 5 Jan 2016 21:04:35 -0800 Subject: [PATCH 245/452] Try to fix dumb S3 URLs. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index da50f6cf4..a742355b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ script: - popd addons: + s3_region: "us-west-2" artifacts: paths: - $(ls firmware/portapack-h1-firmware-*.tar.bz2 | tr "\n" ":") From ea8c186fcf037c5df4017e61c3b8059fe255fc77 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 5 Jan 2016 21:29:40 -0800 Subject: [PATCH 246/452] Revert "Try to fix dumb S3 URLs." This reverts commit 794925442eebb208f0b73935bc34f1fdec0cf9e9. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a742355b1..da50f6cf4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,6 @@ script: - popd addons: - s3_region: "us-west-2" artifacts: paths: - $(ls firmware/portapack-h1-firmware-*.tar.bz2 | tr "\n" ":") From b05923eab6e3aa918b84700d30c77cc81375cdd9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 6 Jan 2016 10:58:42 -0800 Subject: [PATCH 247/452] Change FIFO is_full() to make more sense. --- firmware/common/fifo.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/fifo.hpp b/firmware/common/fifo.hpp index f7a490c7f..0834d20ff 100644 --- a/firmware/common/fifo.hpp +++ b/firmware/common/fifo.hpp @@ -59,7 +59,7 @@ public: } bool is_full() const { - return len() > mask(); + return unused() == 0; } /* bool in(const T& val) { From 4059e9cebe8bf98c15dbad403cce2b4561560c4a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 6 Jan 2016 11:01:02 -0800 Subject: [PATCH 248/452] Reintroduce FIFO in/out for templated FIFO element type. --- firmware/common/fifo.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/common/fifo.hpp b/firmware/common/fifo.hpp index 0834d20ff..c7441eae9 100644 --- a/firmware/common/fifo.hpp +++ b/firmware/common/fifo.hpp @@ -61,7 +61,7 @@ public: bool is_full() const { return unused() == 0; } -/* + bool in(const T& val) { const bool is_not_full = !is_full(); if( is_not_full ) { @@ -71,7 +71,7 @@ public: } return is_not_full; } -*/ + size_t in(const T* const buf, size_t len) { const size_t l = unused(); if( len > l ) { @@ -93,7 +93,7 @@ public: _in += len + recsize(); return len; } -/* + bool out(T& val) { if( is_empty() ) { return false; @@ -105,7 +105,7 @@ public: return true; } -*/ + size_t out(T* const buf, size_t len) { len = out_peek(buf, len); _out += len; From 2cd28fcc0c8073695ab38b9c30e7530750ca8837 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 6 Jan 2016 11:04:25 -0800 Subject: [PATCH 249/452] Make FIFO::in() more consistent with other functions. --- firmware/common/fifo.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/firmware/common/fifo.hpp b/firmware/common/fifo.hpp index c7441eae9..83ee06deb 100644 --- a/firmware/common/fifo.hpp +++ b/firmware/common/fifo.hpp @@ -63,13 +63,15 @@ public: } bool in(const T& val) { - const bool is_not_full = !is_full(); - if( is_not_full ) { - _data[_in & mask()] = val; - smp_wmb(); - _in++; + if( is_full() ) { + return false; } - return is_not_full; + + _data[_in & mask()] = val; + smp_wmb(); + _in += 1; + + return true; } size_t in(const T* const buf, size_t len) { From aaa1bc3a0920226a17bc1707119c857ad4390a04 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 6 Jan 2016 11:34:41 -0800 Subject: [PATCH 250/452] Transmit ChannelSpectrum data through separate FIFO. Allows handling of data during LCD "vertical retrace", independent of other baseband->application messages. A bit kludgy still... --- firmware/application/ui_spectrum.cpp | 11 +++++++--- firmware/baseband/spectrum_collector.cpp | 18 ++++++++-------- firmware/baseband/spectrum_collector.hpp | 3 +++ firmware/common/message.hpp | 26 +++++++++++++++--------- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/firmware/application/ui_spectrum.cpp b/firmware/application/ui_spectrum.cpp index d450b4b62..824df9ff9 100644 --- a/firmware/application/ui_spectrum.cpp +++ b/firmware/application/ui_spectrum.cpp @@ -237,15 +237,20 @@ WaterfallWidget::WaterfallWidget() { } void WaterfallWidget::on_show() { - context().message_map().register_handler(Message::ID::ChannelSpectrum, + context().message_map().register_handler(Message::ID::FIFONotify, [this](const Message* const p) { - this->on_channel_spectrum(reinterpret_cast(p)->spectrum); + const auto message = reinterpret_cast(p); + auto fifo = reinterpret_cast(message->fifo); + ChannelSpectrum channel_spectrum; + if( fifo->out(channel_spectrum) ) { + this->on_channel_spectrum(channel_spectrum); + } } ); } void WaterfallWidget::on_hide() { - context().message_map().unregister_handler(Message::ID::ChannelSpectrum); + context().message_map().unregister_handler(Message::ID::FIFONotify); } void WaterfallWidget::set_parent_rect(const Rect new_parent_rect) { diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index 2c604b2b5..37660df67 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -73,8 +73,8 @@ void SpectrumCollector::update() { channel_spectrum_request_update = false; fft_c_preswapped(channel_spectrum); - ChannelSpectrumMessage spectrum_message; - for(size_t i=0; i .magnitude, or something more (less!) accurate. */ - spectrum_message.spectrum.db_count = spectrum_message.spectrum.db.size(); - spectrum_message.spectrum.sampling_rate = channel_spectrum_sampling_rate; - spectrum_message.spectrum.channel_filter_pass_frequency = channel_filter_pass_frequency; - spectrum_message.spectrum.channel_filter_stop_frequency = channel_filter_stop_frequency; - shared_memory.application_queue.push(spectrum_message); + spectrum.db_count = spectrum.db.size(); + spectrum.sampling_rate = channel_spectrum_sampling_rate; + spectrum.channel_filter_pass_frequency = channel_filter_pass_frequency; + spectrum.channel_filter_stop_frequency = channel_filter_stop_frequency; + fifo.in(spectrum); + FIFONotifyMessage message { &fifo }; + shared_memory.application_queue.push(message); } } diff --git a/firmware/baseband/spectrum_collector.hpp b/firmware/baseband/spectrum_collector.hpp index 52ef1d0e3..3e5910228 100644 --- a/firmware/baseband/spectrum_collector.hpp +++ b/firmware/baseband/spectrum_collector.hpp @@ -30,6 +30,8 @@ #include #include +#include "message.hpp" + class SpectrumCollector { public: constexpr SpectrumCollector( @@ -49,6 +51,7 @@ public: private: BlockDecimator<256> channel_spectrum_decimator; + ChannelSpectrumFIFO fifo; volatile bool channel_spectrum_request_update { false }; std::array, 256> channel_spectrum; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index e247b27cb..26d2cc1a0 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -30,6 +30,7 @@ #include "baseband_packet.hpp" #include "ert_packet.hpp" #include "dsp_fir_taps.hpp" +#include "fifo.hpp" #include "utility.hpp" @@ -44,7 +45,7 @@ public: RSSIStatistics = 0, BasebandStatistics = 1, ChannelStatistics = 2, - ChannelSpectrum = 3, + AudioStatistics = 4, BasebandConfiguration = 5, TPMSPacket = 6, @@ -55,6 +56,7 @@ public: NBFMConfigure = 11, WFMConfigure = 12, AMConfigure = 13, + FIFONotify = 14, MAX }; @@ -207,15 +209,7 @@ struct ChannelSpectrum { uint32_t channel_filter_stop_frequency { 0 }; }; -class ChannelSpectrumMessage : public Message { -public: - constexpr ChannelSpectrumMessage( - ) : Message { ID::ChannelSpectrum } - { - } - - ChannelSpectrum spectrum; -}; +using ChannelSpectrumFIFO = FIFO; class AISPacketMessage : public Message { public: @@ -333,6 +327,18 @@ public: const fir_taps_real<32> channel_filter; }; +class FIFONotifyMessage : public Message { +public: + constexpr FIFONotifyMessage( + void* const fifo + ) : Message { ID::FIFONotify }, + fifo { fifo } + { + } + + void* const fifo; +}; + class MessageHandlerMap { public: using MessageHandler = std::function; From ba33cc737d4a8d815ae76eafe5eec65b36276b57 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 6 Jan 2016 11:36:57 -0800 Subject: [PATCH 251/452] Transmit DisplayFrameSync message, handle in WaterfallSpectrum. More kludginess, especially around initialization and timing. But it addresses the flickering lines of pixels at the bottom of the waterfall scroll area! --- firmware/application/main.cpp | 2 ++ firmware/application/ui_spectrum.cpp | 15 +++++++++++---- firmware/application/ui_spectrum.hpp | 1 + firmware/common/message.hpp | 10 +++++++++- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 8d8453bd6..cdbc1e207 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -197,6 +197,8 @@ private: } void handle_lcd_frame_sync() { + DisplayFrameSyncMessage message; + context.message_map().send(&message); painter.paint_widget_tree(top_widget); } diff --git a/firmware/application/ui_spectrum.cpp b/firmware/application/ui_spectrum.cpp index 824df9ff9..afb43e94c 100644 --- a/firmware/application/ui_spectrum.cpp +++ b/firmware/application/ui_spectrum.cpp @@ -240,16 +240,23 @@ void WaterfallWidget::on_show() { context().message_map().register_handler(Message::ID::FIFONotify, [this](const Message* const p) { const auto message = reinterpret_cast(p); - auto fifo = reinterpret_cast(message->fifo); - ChannelSpectrum channel_spectrum; - if( fifo->out(channel_spectrum) ) { - this->on_channel_spectrum(channel_spectrum); + this->fifo = reinterpret_cast(message->fifo); + } + ); + context().message_map().register_handler(Message::ID::DisplayFrameSync, + [this](const Message* const p) { + if( this->fifo ) { + ChannelSpectrum channel_spectrum; + while( fifo->out(channel_spectrum) ) { + this->on_channel_spectrum(channel_spectrum); + } } } ); } void WaterfallWidget::on_hide() { + context().message_map().unregister_handler(Message::ID::DisplayFrameSync); context().message_map().unregister_handler(Message::ID::FIFONotify); } diff --git a/firmware/application/ui_spectrum.hpp b/firmware/application/ui_spectrum.hpp index 21c4479e9..2d166bbf2 100644 --- a/firmware/application/ui_spectrum.hpp +++ b/firmware/application/ui_spectrum.hpp @@ -84,6 +84,7 @@ public: private: WaterfallView waterfall_view; FrequencyScale frequency_scale; + ChannelSpectrumFIFO* fifo; void on_channel_spectrum(const ChannelSpectrum& spectrum); }; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 26d2cc1a0..3f3b6f8c7 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -45,7 +45,7 @@ public: RSSIStatistics = 0, BasebandStatistics = 1, ChannelStatistics = 2, - + DisplayFrameSync = 3, AudioStatistics = 4, BasebandConfiguration = 5, TPMSPacket = 6, @@ -133,6 +133,14 @@ public: ChannelStatistics statistics; }; +class DisplayFrameSyncMessage : public Message { +public: + constexpr DisplayFrameSyncMessage( + ) : Message { ID::DisplayFrameSync } + { + } +}; + struct AudioStatistics { int32_t rms_db; int32_t max_db; From 7710b2d1fac387ff5d513acfe4fadee7174cf2ac Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 6 Jan 2016 12:10:30 -0800 Subject: [PATCH 252/452] ChannelSpectrumConfig message subsumes FIFONotify. Separate channel spectrum config from spectrum data. This will permit sending config info only when necessary. Use type information of ChannelSpectrum to statically define number of FFT bins elsewhere. TODO: Posting configuration message way too often. Fixing that is the next step. --- firmware/application/ui_spectrum.cpp | 29 ++++++++---------- firmware/application/ui_spectrum.hpp | 4 +-- firmware/baseband/spectrum_collector.cpp | 18 ++++++----- firmware/baseband/spectrum_collector.hpp | 1 + firmware/common/message.hpp | 39 +++++++++++++----------- 5 files changed, 49 insertions(+), 42 deletions(-) diff --git a/firmware/application/ui_spectrum.cpp b/firmware/application/ui_spectrum.cpp index afb43e94c..0cdfedbe5 100644 --- a/firmware/application/ui_spectrum.cpp +++ b/firmware/application/ui_spectrum.cpp @@ -40,11 +40,9 @@ void FrequencyScale::on_show() { clear(); } -void FrequencyScale::set_spectrum_sampling_rate(const uint32_t new_sampling_rate, const size_t new_spectrum_bins) { - if( (spectrum_sampling_rate != new_sampling_rate) || - (spectrum_bins != new_spectrum_bins) ) { +void FrequencyScale::set_spectrum_sampling_rate(const uint32_t new_sampling_rate) { + if( (spectrum_sampling_rate != new_sampling_rate) ) { spectrum_sampling_rate = new_sampling_rate; - spectrum_bins = new_spectrum_bins; set_dirty(); } } @@ -66,7 +64,7 @@ void FrequencyScale::paint(Painter& painter) { clear_background(painter, r); - if( !spectrum_sampling_rate || !spectrum_bins ) { + if( !spectrum_sampling_rate ) { // Can't draw without non-zero scale. return; } @@ -77,7 +75,6 @@ void FrequencyScale::paint(Painter& painter) { void FrequencyScale::clear() { spectrum_sampling_rate = 0; - spectrum_bins = 0; set_dirty(); } @@ -237,14 +234,19 @@ WaterfallWidget::WaterfallWidget() { } void WaterfallWidget::on_show() { - context().message_map().register_handler(Message::ID::FIFONotify, + context().message_map().register_handler(Message::ID::ChannelSpectrumConfig, [this](const Message* const p) { - const auto message = reinterpret_cast(p); - this->fifo = reinterpret_cast(message->fifo); + const auto message = *reinterpret_cast(p); + frequency_scale.set_spectrum_sampling_rate(message.sampling_rate); + frequency_scale.set_channel_filter( + message.channel_filter_pass_frequency, + message.channel_filter_stop_frequency + ); + this->fifo = message.fifo; } ); context().message_map().register_handler(Message::ID::DisplayFrameSync, - [this](const Message* const p) { + [this](const Message* const) { if( this->fifo ) { ChannelSpectrum channel_spectrum; while( fifo->out(channel_spectrum) ) { @@ -257,7 +259,7 @@ void WaterfallWidget::on_show() { void WaterfallWidget::on_hide() { context().message_map().unregister_handler(Message::ID::DisplayFrameSync); - context().message_map().unregister_handler(Message::ID::FIFONotify); + context().message_map().unregister_handler(Message::ID::ChannelSpectrumConfig); } void WaterfallWidget::set_parent_rect(const Rect new_parent_rect) { @@ -279,11 +281,6 @@ void WaterfallWidget::paint(Painter& painter) { void WaterfallWidget::on_channel_spectrum(const ChannelSpectrum& spectrum) { waterfall_view.on_channel_spectrum(spectrum); - frequency_scale.set_spectrum_sampling_rate(spectrum.sampling_rate, spectrum.db_count); - frequency_scale.set_channel_filter( - spectrum.channel_filter_pass_frequency, - spectrum.channel_filter_stop_frequency - ); } } /* namespace spectrum */ diff --git a/firmware/application/ui_spectrum.hpp b/firmware/application/ui_spectrum.hpp index 2d166bbf2..cfce3c8f6 100644 --- a/firmware/application/ui_spectrum.hpp +++ b/firmware/application/ui_spectrum.hpp @@ -37,7 +37,7 @@ class FrequencyScale : public Widget { public: void on_show() override; - void set_spectrum_sampling_rate(const uint32_t new_sampling_rate, const size_t new_spectrum_bins); + void set_spectrum_sampling_rate(const uint32_t new_sampling_rate); void set_channel_filter(const uint32_t pass_frequency, const uint32_t stop_frequency); void paint(Painter& painter) override; @@ -46,7 +46,7 @@ private: static constexpr Dim filter_band_height = 4; uint32_t spectrum_sampling_rate { 0 }; - size_t spectrum_bins { 0 }; + const size_t spectrum_bins = std::tuple_size::value; uint32_t channel_filter_pass_frequency { 0 }; uint32_t channel_filter_stop_frequency { 0 }; diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index 37660df67..ca3fc1dd1 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -48,6 +48,7 @@ void SpectrumCollector::feed( // Called from baseband processing thread. channel_filter_pass_frequency = filter_pass_frequency; channel_filter_stop_frequency = filter_stop_frequency; + post_configuration_message(); channel_spectrum_decimator.feed( channel, [this](const buffer_c16_t& data) { @@ -66,6 +67,16 @@ void SpectrumCollector::post_message(const buffer_c16_t& data) { } } +void SpectrumCollector::post_configuration_message() { + ChannelSpectrumConfigMessage message { + channel_spectrum_sampling_rate, + channel_filter_pass_frequency, + channel_filter_stop_frequency, + &fifo + }; + shared_memory.application_queue.push(message); +} + void SpectrumCollector::update() { // Called from idle thread (after EVT_MASK_SPECTRUM is flagged) if( channel_spectrum_request_update ) { @@ -85,13 +96,6 @@ void SpectrumCollector::update() { spectrum.db[i] = std::max(0U, std::min(255U, v)); } - /* TODO: Rename .db -> .magnitude, or something more (less!) accurate. */ - spectrum.db_count = spectrum.db.size(); - spectrum.sampling_rate = channel_spectrum_sampling_rate; - spectrum.channel_filter_pass_frequency = channel_filter_pass_frequency; - spectrum.channel_filter_stop_frequency = channel_filter_stop_frequency; fifo.in(spectrum); - FIFONotifyMessage message { &fifo }; - shared_memory.application_queue.push(message); } } diff --git a/firmware/baseband/spectrum_collector.hpp b/firmware/baseband/spectrum_collector.hpp index 3e5910228..164937a41 100644 --- a/firmware/baseband/spectrum_collector.hpp +++ b/firmware/baseband/spectrum_collector.hpp @@ -60,6 +60,7 @@ private: uint32_t channel_filter_stop_frequency { 0 }; void post_message(const buffer_c16_t& data); + void post_configuration_message(); }; #endif/*__SPECTRUM_COLLECTOR_H__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 3f3b6f8c7..6885ddb98 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -56,7 +56,7 @@ public: NBFMConfigure = 11, WFMConfigure = 12, AMConfigure = 13, - FIFONotify = 14, + ChannelSpectrumConfig = 14, MAX }; @@ -211,14 +211,31 @@ public: struct ChannelSpectrum { std::array db { { 0 } }; - size_t db_count { 256 }; - uint32_t sampling_rate { 0 }; - uint32_t channel_filter_pass_frequency { 0 }; - uint32_t channel_filter_stop_frequency { 0 }; }; using ChannelSpectrumFIFO = FIFO; +class ChannelSpectrumConfigMessage : public Message { +public: + constexpr ChannelSpectrumConfigMessage( + uint32_t sampling_rate, + uint32_t channel_filter_pass_frequency, + uint32_t channel_filter_stop_frequency, + ChannelSpectrumFIFO* fifo + ) : Message { ID::ChannelSpectrumConfig }, + sampling_rate { sampling_rate }, + channel_filter_pass_frequency { channel_filter_pass_frequency }, + channel_filter_stop_frequency { channel_filter_stop_frequency }, + fifo { fifo } + { + } + + uint32_t sampling_rate { 0 }; + uint32_t channel_filter_pass_frequency { 0 }; + uint32_t channel_filter_stop_frequency { 0 }; + ChannelSpectrumFIFO* fifo { nullptr }; +}; + class AISPacketMessage : public Message { public: constexpr AISPacketMessage( @@ -335,18 +352,6 @@ public: const fir_taps_real<32> channel_filter; }; -class FIFONotifyMessage : public Message { -public: - constexpr FIFONotifyMessage( - void* const fifo - ) : Message { ID::FIFONotify }, - fifo { fifo } - { - } - - void* const fifo; -}; - class MessageHandlerMap { public: using MessageHandler = std::function; From 8fba47b7d8692acb150238064e0554cd476b58ee Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 7 Jan 2016 10:53:27 -0800 Subject: [PATCH 253/452] FIFO in and out indices should be volatile. Later code revealed that the receiving core never notices (reads anew) the _in member variable when waiting for the FIFO to be empty (_in == _out). --- firmware/common/fifo.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/common/fifo.hpp b/firmware/common/fifo.hpp index 83ee06deb..66c9c811c 100644 --- a/firmware/common/fifo.hpp +++ b/firmware/common/fifo.hpp @@ -201,8 +201,8 @@ private: } T _data[size()]; - size_t _in; - size_t _out; + volatile size_t _in; + volatile size_t _out; }; #endif/*__FIFO_H__*/ From c3167ac27c975aa7c6f69e91eb595b085cf4ec78 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 9 Jan 2016 12:17:17 -0800 Subject: [PATCH 254/452] Missing #includes. --- firmware/application/ui_audio.hpp | 2 ++ firmware/application/ui_channel.hpp | 2 ++ firmware/application/ui_rssi.hpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/firmware/application/ui_audio.hpp b/firmware/application/ui_audio.hpp index 0ec2e6a58..cecacc7ac 100644 --- a/firmware/application/ui_audio.hpp +++ b/firmware/application/ui_audio.hpp @@ -26,6 +26,8 @@ #include "ui_widget.hpp" #include "ui_painter.hpp" +#include "message.hpp" + #include namespace ui { diff --git a/firmware/application/ui_channel.hpp b/firmware/application/ui_channel.hpp index 34457de24..97ac61c8b 100644 --- a/firmware/application/ui_channel.hpp +++ b/firmware/application/ui_channel.hpp @@ -26,6 +26,8 @@ #include "ui_widget.hpp" #include "ui_painter.hpp" +#include "message.hpp" + #include namespace ui { diff --git a/firmware/application/ui_rssi.hpp b/firmware/application/ui_rssi.hpp index 503353b73..b8f8259e0 100644 --- a/firmware/application/ui_rssi.hpp +++ b/firmware/application/ui_rssi.hpp @@ -26,6 +26,8 @@ #include "ui_widget.hpp" #include "ui_painter.hpp" +#include "message.hpp" + #include namespace ui { From 365c2ef9469cfe95c3e2396d2e72ca9400d79ae1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 9 Jan 2016 12:20:57 -0800 Subject: [PATCH 255/452] Handle baseband::dma::wait_for_rx_buffer() returning empty buffer. Was technically OK before, because sample count was zero. But seems silly (and vaguely dangerous) to call all that code with a nullptr. --- firmware/baseband/baseband_thread.cpp | 26 ++++++++++++++------------ firmware/common/buffer.hpp | 4 ++++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp index 223a762e5..d1a2e30c8 100644 --- a/firmware/baseband/baseband_thread.cpp +++ b/firmware/baseband/baseband_thread.cpp @@ -98,20 +98,22 @@ void BasebandThread::run() { while(true) { // TODO: Place correct sampling rate into buffer returned here: const auto buffer_tmp = baseband::dma::wait_for_rx_buffer(); - buffer_c8_t buffer { - buffer_tmp.p, buffer_tmp.count, baseband_configuration.sampling_rate - }; + if( buffer_tmp ) { + buffer_c8_t buffer { + buffer_tmp.p, buffer_tmp.count, baseband_configuration.sampling_rate + }; - if( baseband_processor ) { - baseband_processor->execute(buffer); - } - - stats.process(buffer, - [](const BasebandStatistics& statistics) { - const BasebandStatisticsMessage message { statistics }; - shared_memory.application_queue.push(message); + if( baseband_processor ) { + baseband_processor->execute(buffer); } - ); + + stats.process(buffer, + [](const BasebandStatistics& statistics) { + const BasebandStatisticsMessage message { statistics }; + shared_memory.application_queue.push(message); + } + ); + } } delete baseband_buffer; diff --git a/firmware/common/buffer.hpp b/firmware/common/buffer.hpp index da7e70a78..2b3d71707 100644 --- a/firmware/common/buffer.hpp +++ b/firmware/common/buffer.hpp @@ -92,6 +92,10 @@ struct buffer_t { timestamp { timestamp } { } + + operator bool() const { + return (p != nullptr); + } }; #endif/*__BUFFER_H__*/ From 43d6098c48efb834fd9242261a9176d2a180acfa Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 9 Jan 2016 17:57:37 -0800 Subject: [PATCH 256/452] Move baseband_sgpio.* to common/. It'll soon be used by M4 code, not M0. SGPIO baseband streaming needs to be tightly controlled by... the baseband! --- firmware/{application => common}/baseband_sgpio.cpp | 0 firmware/{application => common}/baseband_sgpio.hpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename firmware/{application => common}/baseband_sgpio.cpp (100%) rename firmware/{application => common}/baseband_sgpio.hpp (100%) diff --git a/firmware/application/baseband_sgpio.cpp b/firmware/common/baseband_sgpio.cpp similarity index 100% rename from firmware/application/baseband_sgpio.cpp rename to firmware/common/baseband_sgpio.cpp diff --git a/firmware/application/baseband_sgpio.hpp b/firmware/common/baseband_sgpio.hpp similarity index 100% rename from firmware/application/baseband_sgpio.hpp rename to firmware/common/baseband_sgpio.hpp From c75c167c250e3b6b11bff3bec3d14ff03464fc66 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 10:11:16 -0800 Subject: [PATCH 257/452] Rename GPDMA channel disable_force() to disable(). There was nothing particularly forceful about the disable_force() code. Whether it's a "forced" operation depends on what happens before and after (HALT and ACTIVE flags are involved in a smooth disabling of the channel). --- firmware/baseband/audio_dma.cpp | 4 ++-- firmware/baseband/baseband_dma.cpp | 2 +- firmware/baseband/rssi_dma.cpp | 2 +- firmware/baseband/touch_dma.cpp | 2 +- firmware/common/gpdma.cpp | 2 +- firmware/common/gpdma.hpp | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/firmware/baseband/audio_dma.cpp b/firmware/baseband/audio_dma.cpp index 6fa6439bc..60e85096e 100644 --- a/firmware/baseband/audio_dma.cpp +++ b/firmware/baseband/audio_dma.cpp @@ -208,8 +208,8 @@ void enable() { } void disable() { - gpdma_channel_i2s0_tx.disable_force(); - gpdma_channel_i2s0_rx.disable_force(); + gpdma_channel_i2s0_tx.disable(); + gpdma_channel_i2s0_rx.disable(); } buffer_t tx_empty_buffer() { diff --git a/firmware/baseband/baseband_dma.cpp b/firmware/baseband/baseband_dma.cpp index f3002b282..7467f5510 100644 --- a/firmware/baseband/baseband_dma.cpp +++ b/firmware/baseband/baseband_dma.cpp @@ -149,7 +149,7 @@ bool is_enabled() { } void disable() { - gpdma_channel_sgpio.disable_force(); + gpdma_channel_sgpio.disable(); } baseband::buffer_t wait_for_rx_buffer() { diff --git a/firmware/baseband/rssi_dma.cpp b/firmware/baseband/rssi_dma.cpp index 5b060604a..91f3b4965 100644 --- a/firmware/baseband/rssi_dma.cpp +++ b/firmware/baseband/rssi_dma.cpp @@ -157,7 +157,7 @@ bool is_enabled() { } void disable() { - gpdma_channel.disable_force(); + gpdma_channel.disable(); } rf::rssi::buffer_t wait_for_buffer() { diff --git a/firmware/baseband/touch_dma.cpp b/firmware/baseband/touch_dma.cpp index aa120ff30..ce66617a1 100644 --- a/firmware/baseband/touch_dma.cpp +++ b/firmware/baseband/touch_dma.cpp @@ -122,7 +122,7 @@ bool is_enabled() { } void disable() { - gpdma_channel.disable_force(); + gpdma_channel.disable(); } } /* namespace dma */ diff --git a/firmware/common/gpdma.cpp b/firmware/common/gpdma.cpp index cdd7a9a36..034a62481 100644 --- a/firmware/common/gpdma.cpp +++ b/firmware/common/gpdma.cpp @@ -54,7 +54,7 @@ void Channel::configure( const LLI& first_lli, const uint32_t config ) const { - disable_force(); + disable(); clear_interrupts(); LPC_GPDMA_Channel_Type* const channel = &LPC_GPDMA->CH[number]; diff --git a/firmware/common/gpdma.hpp b/firmware/common/gpdma.hpp index b97dde14a..c403569bd 100644 --- a/firmware/common/gpdma.hpp +++ b/firmware/common/gpdma.hpp @@ -313,7 +313,7 @@ public: return LPC_GPDMA->CH[number].CONFIG & (1U << 0); } - void disable_force() const { + void disable() const { LPC_GPDMA->CH[number].CONFIG &= ~(1U << 0); } @@ -349,7 +349,7 @@ public: void disable() const { for(const auto& channel : channels) { - channel.disable_force(); + channel.disable(); } LPC_GPDMA->CONFIG &= ~(1U << 0); } From 8fde4972b41529f35e85073180f94e1112330501 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 10:15:25 -0800 Subject: [PATCH 258/452] Methods to peek and skip messages in queue. Allows receiver to not consume a message until after it's handled. And that enables the transmitter to block until the queue is empty, knowing that when unblocked, all messages in queue have been handled. --- firmware/common/fifo.hpp | 20 ++++++++++++++++++++ firmware/common/message_queue.hpp | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/firmware/common/fifo.hpp b/firmware/common/fifo.hpp index 66c9c811c..f217e67eb 100644 --- a/firmware/common/fifo.hpp +++ b/firmware/common/fifo.hpp @@ -114,6 +114,26 @@ public: return len; } + bool skip() { + if( is_empty() ) { + return false; + } + + size_t len = peek_n(); + _out += len + recsize(); + return true; + } + + size_t peek_r(void* const buf, size_t len) { + if( is_empty() ) { + return 0; + } + + size_t n; + len = out_copy_r((T*)buf, len, &n); + return len; + } + size_t out_r(void* const buf, size_t len) { if( is_empty() ) { return 0; diff --git a/firmware/common/message_queue.hpp b/firmware/common/message_queue.hpp index 94745f3ee..c4430a237 100644 --- a/firmware/common/message_queue.hpp +++ b/firmware/common/message_queue.hpp @@ -47,6 +47,25 @@ public: return push(&message, sizeof(message)); } + template + bool push_and_wait(const T& message) { + const bool result = push(message); + if( result ) { + // TODO: More graceful method of waiting for empty? Maybe sleep for a bit? + while( !is_empty() ); + } + return result; + } + + Message* peek(std::array& buf) { + Message* const p = reinterpret_cast(buf.data()); + return fifo.peek_r(buf.data(), buf.size()) ? p : nullptr; + } + + bool skip() { + return fifo.skip(); + } + Message* pop(std::array& buf) { Message* const p = reinterpret_cast(buf.data()); return fifo.out_r(buf.data(), buf.size()) ? p : nullptr; From 0647f26707236598c424d43307340e3531506313 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 10:23:39 -0800 Subject: [PATCH 259/452] Move SGPIO configuration and control to baseband firmware. Addresses long-standing and annoying bug where SGPIO DMA channel would not disable -- and not configure cleanly next time it was needed. My theory is that the DMA channel couldn't disable until it got a request from the peripheral, and sometimes the peripheral was disabled before that last request. Anyway, the baseband firmware should control the SGPIO, methinks, despite the impact on baseband code size. --- firmware/application/Makefile | 1 - firmware/application/radio.cpp | 13 ------------- firmware/application/radio.hpp | 2 -- firmware/application/receiver_model.cpp | 4 ---- firmware/baseband/Makefile | 1 + firmware/baseband/baseband_thread.cpp | 7 +++++++ 6 files changed, 8 insertions(+), 20 deletions(-) diff --git a/firmware/application/Makefile b/firmware/application/Makefile index ab0e616c2..ce6da9dce 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -135,7 +135,6 @@ CPPSRC = main.cpp \ wm8731.cpp \ radio.cpp \ baseband_cpld.cpp \ - baseband_sgpio.cpp \ tuning.cpp \ rf_path.cpp \ rffc507x.cpp \ diff --git a/firmware/application/radio.cpp b/firmware/application/radio.cpp index 974636638..cdaced346 100644 --- a/firmware/application/radio.cpp +++ b/firmware/application/radio.cpp @@ -24,7 +24,6 @@ #include "rf_path.hpp" #include "max5864.hpp" #include "baseband_cpld.hpp" -#include "baseband_sgpio.hpp" #include "portapack_shared_memory.hpp" #include "tuning.hpp" @@ -90,7 +89,6 @@ rffc507x::RFFC507x first_if; max2837::MAX2837 second_if { ssp1_target_max2837 }; static max5864::MAX5864 baseband_codec { ssp1_target_max5864 }; static baseband::CPLD baseband_cpld; -static baseband::SGPIO baseband_sgpio; static rf::Direction direction { rf::Direction::Receive }; @@ -100,7 +98,6 @@ void init() { second_if.init(); baseband_codec.init(); baseband_cpld.init(); - baseband_sgpio.init(); } void set_direction(const rf::Direction new_direction) { @@ -112,7 +109,6 @@ void set_direction(const rf::Direction new_direction) { rf_path.set_direction(direction); baseband_codec.set_mode((direction == rf::Direction::Transmit) ? max5864::Mode::Transmit : max5864::Mode::Receive); - baseband_sgpio.configure((direction == rf::Direction::Transmit) ? baseband::Direction::Transmit : baseband::Direction::Receive); } bool set_tuning_frequency(const rf::Frequency frequency) { @@ -156,16 +152,7 @@ void set_baseband_decimation_by(const size_t n) { baseband_cpld.set_decimation_by(n); } -void streaming_enable() { - baseband_sgpio.streaming_enable(); -} - -void streaming_disable() { - baseband_sgpio.streaming_disable(); -} - void disable() { - baseband_sgpio.streaming_disable(); baseband_codec.set_mode(max5864::Mode::Shutdown); second_if.set_mode(max2837::Mode::Standby); first_if.disable(); diff --git a/firmware/application/radio.hpp b/firmware/application/radio.hpp index c796963dd..0513c17c7 100644 --- a/firmware/application/radio.hpp +++ b/firmware/application/radio.hpp @@ -43,8 +43,6 @@ void set_sampling_frequency(const uint32_t frequency); void set_baseband_filter_bandwidth(const uint32_t bandwidth_minimum); void set_baseband_decimation_by(const size_t n); -void streaming_enable(); -void streaming_disable(); void disable(); extern rffc507x::RFFC507x first_if; diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index f068f24d5..6d44e7ec2 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -118,7 +118,6 @@ void ReceiverModel::enable() { update_vga(); update_baseband_bandwidth(); update_baseband_configuration(); - radio::streaming_enable(); update_headphone_volume(); } @@ -168,7 +167,6 @@ void ReceiverModel::set_baseband_configuration(const BasebandConfiguration confi } void ReceiverModel::update_baseband_configuration() { - radio::streaming_disable(); clock_manager.set_sampling_frequency(sampling_rate() * baseband_oversampling()); update_tuning_frequency(); @@ -176,8 +174,6 @@ void ReceiverModel::update_baseband_configuration() { BasebandConfigurationMessage message { baseband_configuration }; shared_memory.baseband_queue.push(message); - - radio::streaming_enable(); } void ReceiverModel::update_headphone_volume() { diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 27608c439..6f107e3ad 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -127,6 +127,7 @@ CPPSRC = main.cpp \ event.cpp \ gpdma.cpp \ baseband_dma.cpp \ + baseband_sgpio.cpp \ portapack_shared_memory.cpp \ baseband_thread.cpp \ baseband_processor.cpp \ diff --git a/firmware/baseband/baseband_thread.cpp b/firmware/baseband/baseband_thread.cpp index d1a2e30c8..92b968f5e 100644 --- a/firmware/baseband/baseband_thread.cpp +++ b/firmware/baseband/baseband_thread.cpp @@ -25,6 +25,7 @@ #include "baseband.hpp" #include "baseband_stats_collector.hpp" +#include "baseband_sgpio.hpp" #include "baseband_dma.hpp" #include "rssi.hpp" @@ -42,6 +43,8 @@ #include +static baseband::SGPIO baseband_sgpio; + WORKING_AREA(baseband_thread_wa, 4096); Thread* BasebandThread::start(const tprio_t priority) { @@ -79,6 +82,7 @@ void BasebandThread::on_message(const Message* const message) { } void BasebandThread::run() { + baseband_sgpio.init(); baseband::dma::init(); const auto baseband_buffer = new std::array(); @@ -136,6 +140,7 @@ void BasebandThread::disable() { if( baseband_processor ) { i2s::i2s0::tx_mute(); baseband::dma::disable(); + baseband_sgpio.streaming_disable(); rf::rssi::stop(); } } @@ -145,6 +150,8 @@ void BasebandThread::enable() { if( direction() == baseband::Direction::Receive ) { rf::rssi::start(); } + baseband_sgpio.configure(direction()); baseband::dma::enable(direction()); + baseband_sgpio.streaming_enable(); } } From d821afc60d7d1afd2529fda0e983d6d77546cb4b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 10:42:20 -0800 Subject: [PATCH 260/452] Spectrum streaming control, spectrum attributes back in each frame. TODO: This feels kinda complex, and there's some repeated Processor code that needs to be refactored into a base class. --- firmware/application/ui_spectrum.cpp | 23 ++++++++++++++---- firmware/baseband/proc_am_audio.cpp | 12 ++++++++++ firmware/baseband/proc_am_audio.hpp | 2 ++ firmware/baseband/proc_nfm_audio.cpp | 12 ++++++++++ firmware/baseband/proc_nfm_audio.hpp | 2 ++ firmware/baseband/proc_wfm_audio.cpp | 12 ++++++++++ firmware/baseband/proc_wfm_audio.hpp | 2 ++ firmware/baseband/spectrum_collector.cpp | 30 +++++++++++++----------- firmware/baseband/spectrum_collector.hpp | 5 +++- firmware/common/message.hpp | 30 +++++++++++++++++------- 10 files changed, 101 insertions(+), 29 deletions(-) diff --git a/firmware/application/ui_spectrum.cpp b/firmware/application/ui_spectrum.cpp index 0cdfedbe5..748382106 100644 --- a/firmware/application/ui_spectrum.cpp +++ b/firmware/application/ui_spectrum.cpp @@ -24,6 +24,7 @@ #include "spectrum_color_lut.hpp" #include "portapack.hpp" +#include "portapack_shared_memory.hpp" using namespace portapack; #include "string_format.hpp" @@ -237,11 +238,6 @@ void WaterfallWidget::on_show() { context().message_map().register_handler(Message::ID::ChannelSpectrumConfig, [this](const Message* const p) { const auto message = *reinterpret_cast(p); - frequency_scale.set_spectrum_sampling_rate(message.sampling_rate); - frequency_scale.set_channel_filter( - message.channel_filter_pass_frequency, - message.channel_filter_stop_frequency - ); this->fifo = message.fifo; } ); @@ -255,9 +251,21 @@ void WaterfallWidget::on_show() { } } ); + + shared_memory.baseband_queue.push_and_wait( + SpectrumStreamingConfigMessage { + SpectrumStreamingConfigMessage::Mode::Running + } + ); } void WaterfallWidget::on_hide() { + shared_memory.baseband_queue.push_and_wait( + SpectrumStreamingConfigMessage { + SpectrumStreamingConfigMessage::Mode::Stopped + } + ); + context().message_map().unregister_handler(Message::ID::DisplayFrameSync); context().message_map().unregister_handler(Message::ID::ChannelSpectrumConfig); } @@ -281,6 +289,11 @@ void WaterfallWidget::paint(Painter& painter) { void WaterfallWidget::on_channel_spectrum(const ChannelSpectrum& spectrum) { waterfall_view.on_channel_spectrum(spectrum); + frequency_scale.set_spectrum_sampling_rate(spectrum.sampling_rate); + frequency_scale.set_channel_filter( + spectrum.channel_filter_pass_frequency, + spectrum.channel_filter_stop_frequency + ); } } /* namespace spectrum */ diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index dd51c7464..561cefbeb 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -53,6 +53,10 @@ void NarrowbandAMAudio::on_message(const Message* const message) { configure(*reinterpret_cast(message)); break; + case Message::ID::SpectrumStreamingConfig: + streaming_config(*reinterpret_cast(message)); + break; + default: break; } @@ -82,3 +86,11 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { configured = true; } + +void NarrowbandAMAudio::streaming_config(const SpectrumStreamingConfigMessage& message) { + if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) { + channel_spectrum.start(); + } else { + channel_spectrum.stop(); + } +} diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 46fbbee52..9c819c677 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -64,6 +64,8 @@ private: bool configured { false }; void configure(const AMConfigureMessage& message); + + void streaming_config(const SpectrumStreamingConfigMessage& message); }; #endif/*__PROC_AM_AUDIO_H__*/ diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 749d754b1..093d92b49 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -66,6 +66,10 @@ void NarrowbandFMAudio::on_message(const Message* const message) { configure(*reinterpret_cast(message)); break; + case Message::ID::SpectrumStreamingConfig: + streaming_config(*reinterpret_cast(message)); + break; + default: break; } @@ -99,3 +103,11 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { configured = true; } + +void NarrowbandFMAudio::streaming_config(const SpectrumStreamingConfigMessage& message) { + if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) { + channel_spectrum.start(); + } else { + channel_spectrum.stop(); + } +} diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index a4c65576f..79fabbd89 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -66,6 +66,8 @@ private: bool configured { false }; void configure(const NBFMConfigureMessage& message); + + void streaming_config(const SpectrumStreamingConfigMessage& message); }; #endif/*__PROC_NFM_AUDIO_H__*/ diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 5ad961d81..d903462e2 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -84,6 +84,10 @@ void WidebandFMAudio::on_message(const Message* const message) { configure(*reinterpret_cast(message)); break; + case Message::ID::SpectrumStreamingConfig: + streaming_config(*reinterpret_cast(message)); + break; + default: break; } @@ -117,3 +121,11 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) { configured = true; } + +void WidebandFMAudio::streaming_config(const SpectrumStreamingConfigMessage& message) { + if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) { + channel_spectrum.start(); + } else { + channel_spectrum.stop(); + } +} diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 4b1374937..ee4a38f4f 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -67,6 +67,8 @@ private: bool configured { false }; void configure(const WFMConfigureMessage& message); + + void streaming_config(const SpectrumStreamingConfigMessage& message); }; #endif/*__PROC_WFM_AUDIO_H__*/ diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index ca3fc1dd1..7a70b69e7 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -29,6 +29,16 @@ #include +void SpectrumCollector::start() { + streaming = true; + ChannelSpectrumConfigMessage message { &fifo }; + shared_memory.application_queue.push(message); +} + +void SpectrumCollector::stop() { + streaming = false; +} + void SpectrumCollector::set_decimation_factor( const size_t decimation_factor ) { @@ -48,7 +58,7 @@ void SpectrumCollector::feed( // Called from baseband processing thread. channel_filter_pass_frequency = filter_pass_frequency; channel_filter_stop_frequency = filter_stop_frequency; - post_configuration_message(); + channel_spectrum_decimator.feed( channel, [this](const buffer_c16_t& data) { @@ -59,7 +69,7 @@ void SpectrumCollector::feed( void SpectrumCollector::post_message(const buffer_c16_t& data) { // Called from baseband processing thread. - if( !channel_spectrum_request_update ) { + if( streaming && !channel_spectrum_request_update ) { fft_swap(data, channel_spectrum); channel_spectrum_sampling_rate = data.sampling_rate; channel_spectrum_request_update = true; @@ -67,24 +77,17 @@ void SpectrumCollector::post_message(const buffer_c16_t& data) { } } -void SpectrumCollector::post_configuration_message() { - ChannelSpectrumConfigMessage message { - channel_spectrum_sampling_rate, - channel_filter_pass_frequency, - channel_filter_stop_frequency, - &fifo - }; - shared_memory.application_queue.push(message); -} - void SpectrumCollector::update() { // Called from idle thread (after EVT_MASK_SPECTRUM is flagged) - if( channel_spectrum_request_update ) { + if( streaming && channel_spectrum_request_update ) { /* Decimated buffer is full. Compute spectrum. */ channel_spectrum_request_update = false; fft_c_preswapped(channel_spectrum); ChannelSpectrum spectrum; + spectrum.sampling_rate = channel_spectrum_sampling_rate; + spectrum.channel_filter_pass_frequency = channel_filter_pass_frequency; + spectrum.channel_filter_stop_frequency = channel_filter_stop_frequency; for(size_t i=0; i, 256> channel_spectrum; uint32_t channel_spectrum_sampling_rate { 0 }; uint32_t channel_filter_pass_frequency { 0 }; uint32_t channel_filter_stop_frequency { 0 }; void post_message(const buffer_c16_t& data); - void post_configuration_message(); }; #endif/*__SPECTRUM_COLLECTOR_H__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 6885ddb98..66eebbc5a 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -57,6 +57,7 @@ public: WFMConfigure = 12, AMConfigure = 13, ChannelSpectrumConfig = 14, + SpectrumStreamingConfig = 15, MAX }; @@ -209,8 +210,28 @@ public: BasebandConfiguration configuration; }; +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 }; +}; + struct ChannelSpectrum { std::array db { { 0 } }; + uint32_t sampling_rate { 0 }; + uint32_t channel_filter_pass_frequency { 0 }; + uint32_t channel_filter_stop_frequency { 0 }; }; using ChannelSpectrumFIFO = FIFO; @@ -218,21 +239,12 @@ using ChannelSpectrumFIFO = FIFO; class ChannelSpectrumConfigMessage : public Message { public: constexpr ChannelSpectrumConfigMessage( - uint32_t sampling_rate, - uint32_t channel_filter_pass_frequency, - uint32_t channel_filter_stop_frequency, ChannelSpectrumFIFO* fifo ) : Message { ID::ChannelSpectrumConfig }, - sampling_rate { sampling_rate }, - channel_filter_pass_frequency { channel_filter_pass_frequency }, - channel_filter_stop_frequency { channel_filter_stop_frequency }, fifo { fifo } { } - uint32_t sampling_rate { 0 }; - uint32_t channel_filter_pass_frequency { 0 }; - uint32_t channel_filter_stop_frequency { 0 }; ChannelSpectrumFIFO* fifo { nullptr }; }; From 62e5ec1dbb3b942b2d910c5c18c5d507e807b958 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 10:45:22 -0800 Subject: [PATCH 261/452] Postpone clearing channel_spectrum_request_update until finished with data in array. There was potential for new samples to be copied into array as the FFT and post-processing were occuring. --- firmware/baseband/spectrum_collector.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index 7a70b69e7..16162272a 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -81,7 +81,6 @@ void SpectrumCollector::update() { // Called from idle thread (after EVT_MASK_SPECTRUM is flagged) if( streaming && channel_spectrum_request_update ) { /* Decimated buffer is full. Compute spectrum. */ - channel_spectrum_request_update = false; fft_c_preswapped(channel_spectrum); ChannelSpectrum spectrum; @@ -100,4 +99,6 @@ void SpectrumCollector::update() { } fifo.in(spectrum); } + + channel_spectrum_request_update = false; } From 136ba895ef2f1e94c89aecd476222bea95f8c5af Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 11:00:09 -0800 Subject: [PATCH 262/452] Clear spectrum FIFO when streaming is stopped. --- firmware/baseband/spectrum_collector.cpp | 1 + firmware/common/fifo.hpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index 16162272a..fc2241aca 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -37,6 +37,7 @@ void SpectrumCollector::start() { void SpectrumCollector::stop() { streaming = false; + fifo.reset_in(); } void SpectrumCollector::set_decimation_factor( diff --git a/firmware/common/fifo.hpp b/firmware/common/fifo.hpp index f217e67eb..86c06a733 100644 --- a/firmware/common/fifo.hpp +++ b/firmware/common/fifo.hpp @@ -42,6 +42,10 @@ public: _in = _out = 0; } + void reset_in() { + _in = _out; + } + void reset_out() { _out = _in; } From d9bfaaf805f710eb7b4bfb31afef55c99c9c601d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 11:01:54 -0800 Subject: [PATCH 263/452] Stop baseband streaming when switching radio configuration. Probably unnecessary, but feeling paranoid about changing sample rates while there's a processor actively handling samples, and potentially maxing out the M4 core. --- firmware/application/receiver_model.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 6d44e7ec2..52ba61d55 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -167,6 +167,14 @@ void ReceiverModel::set_baseband_configuration(const BasebandConfiguration confi } void ReceiverModel::update_baseband_configuration() { + // TODO: Move more low-level radio control stuff to M4. It'll enable tighter + // synchronization for things like wideband (sweeping) spectrum analysis, and + // protocols that need quick RX/TX turn-around. + + // Disabling baseband while changing sampling rates seems like a good idea... + shared_memory.baseband_queue.push_and_wait(BasebandConfigurationMessage { + .configuration = { }, + }); clock_manager.set_sampling_frequency(sampling_rate() * baseband_oversampling()); update_tuning_frequency(); From 146caaab6f58fa9ccd4f8b065107d6803368ea27 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 11:10:13 -0800 Subject: [PATCH 264/452] Consolidate baseband disable code. --- firmware/application/receiver_model.cpp | 19 ++++++++++--------- firmware/application/receiver_model.hpp | 2 ++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 52ba61d55..0162632de 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -122,13 +122,16 @@ void ReceiverModel::enable() { update_headphone_volume(); } -void ReceiverModel::disable() { - /* TODO: This is a dumb hack to stop baseband from working so hard. */ - BasebandConfigurationMessage message { - .configuration = { }, - }; - shared_memory.baseband_queue.push(message); +void ReceiverModel::baseband_disable() { + shared_memory.baseband_queue.push_and_wait( + BasebandConfigurationMessage { + .configuration = { }, + } + ); +} +void ReceiverModel::disable() { + baseband_disable(); radio::disable(); } @@ -172,9 +175,7 @@ void ReceiverModel::update_baseband_configuration() { // protocols that need quick RX/TX turn-around. // Disabling baseband while changing sampling rates seems like a good idea... - shared_memory.baseband_queue.push_and_wait(BasebandConfigurationMessage { - .configuration = { }, - }); + baseband_disable(); clock_manager.set_sampling_frequency(sampling_rate() * baseband_oversampling()); update_tuning_frequency(); diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index 818a21a60..aeeac7e41 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -107,6 +107,8 @@ private: void update_vga(); void update_baseband_configuration(); void update_headphone_volume(); + + void baseband_disable(); }; #endif/*__RECEIVER_MODEL_H__*/ From d6f797540df9d289140c4110065cda3a3dc1e5e6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 11:15:37 -0800 Subject: [PATCH 265/452] Remove baseband message from queue after it is processed. Application code can now wait on queue empty and know the baseband's state. --- firmware/baseband/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index 8a8852b59..d74dd148c 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -177,8 +177,9 @@ private: void handle_baseband_queue() { std::array message_buffer; - while(Message* const message = shared_memory.baseband_queue.pop(message_buffer)) { + while(Message* const message = shared_memory.baseband_queue.peek(message_buffer)) { on_message(message); + shared_memory.baseband_queue.skip(); } } From 4ea84301c66c44e1d0784ef91223d8598327da58 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 11:33:44 -0800 Subject: [PATCH 266/452] For non-audio modes, don't bother muting audio. It's assumed base class will start with audio muted. --- firmware/baseband/proc_ais.cpp | 2 -- firmware/baseband/proc_ert.cpp | 2 -- firmware/baseband/proc_tpms.cpp | 2 -- firmware/baseband/proc_wideband_spectrum.cpp | 2 -- 4 files changed, 8 deletions(-) diff --git a/firmware/baseband/proc_ais.cpp b/firmware/baseband/proc_ais.cpp index 9caa9bb1d..80452dd02 100644 --- a/firmware/baseband/proc_ais.cpp +++ b/firmware/baseband/proc_ais.cpp @@ -45,8 +45,6 @@ void AISProcessor::execute(const buffer_c8_t& buffer) { clock_recovery(mf.get_output()); } } - - mute_audio(); } void AISProcessor::consume_symbol( diff --git a/firmware/baseband/proc_ert.cpp b/firmware/baseband/proc_ert.cpp index 20e9764b2..e6ae439c5 100644 --- a/firmware/baseband/proc_ert.cpp +++ b/firmware/baseband/proc_ert.cpp @@ -78,8 +78,6 @@ void ERTProcessor::execute(const buffer_c8_t& buffer) { clock_recovery(data); } - - mute_audio(); } void ERTProcessor::consume_symbol( diff --git a/firmware/baseband/proc_tpms.cpp b/firmware/baseband/proc_tpms.cpp index 0906de719..d9b2375aa 100644 --- a/firmware/baseband/proc_tpms.cpp +++ b/firmware/baseband/proc_tpms.cpp @@ -66,8 +66,6 @@ void TPMSProcessor::execute(const buffer_c8_t& buffer) { clock_recovery(mf.get_output()); } } - - mute_audio(); } void TPMSProcessor::consume_symbol( diff --git a/firmware/baseband/proc_wideband_spectrum.cpp b/firmware/baseband/proc_wideband_spectrum.cpp index e8b624957..feb29f695 100644 --- a/firmware/baseband/proc_wideband_spectrum.cpp +++ b/firmware/baseband/proc_wideband_spectrum.cpp @@ -61,8 +61,6 @@ void WidebandSpectrum::execute(const buffer_c8_t& buffer) { } else { phase++; } - - mute_audio(); } void WidebandSpectrum::on_message(const Message* const message) { From eb5b2d7d301a141e75e15730149fc8fd5e9ab156 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 11:34:06 -0800 Subject: [PATCH 267/452] Fix broken audio stats when audio is muted. --- firmware/baseband/baseband_processor.cpp | 8 +++++++- firmware/baseband/baseband_processor.hpp | 2 +- firmware/baseband/proc_nfm_audio.cpp | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index cfef43b22..d17869204 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -54,8 +54,14 @@ void BasebandProcessor::fill_audio_buffer(const buffer_s16_t& audio) { feed_audio_stats(audio); } -void BasebandProcessor::mute_audio() { +void BasebandProcessor::mute_audio(const buffer_s16_t& audio) { i2s::i2s0::tx_mute(); + + for(size_t i=0; i Date: Sun, 10 Jan 2016 20:06:58 -0800 Subject: [PATCH 268/452] Unconst IIR configuration and filter. --- firmware/baseband/dsp_iir.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/dsp_iir.hpp b/firmware/baseband/dsp_iir.hpp index 2a04a66d0..5c36f5227 100644 --- a/firmware/baseband/dsp_iir.hpp +++ b/firmware/baseband/dsp_iir.hpp @@ -27,8 +27,8 @@ #include "dsp_types.hpp" struct iir_biquad_config_t { - const std::array b; - const std::array a; + std::array b; + std::array a; }; class IIRBiquadFilter { @@ -46,7 +46,7 @@ public: void execute_in_place(const buffer_s16_t& buffer); private: - const iir_biquad_config_t config; + iir_biquad_config_t config; std::array x { { 0.0f, 0.0f, 0.0f } }; std::array y { { 0.0f, 0.0f, 0.0f } }; From 497adda390aa107e68d1f1215cd2d62bac6eec38 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 20:11:05 -0800 Subject: [PATCH 269/452] IIR default constructor passes no audio. Debugging mechanism -- filter must be configured to pass audio. --- firmware/baseband/dsp_iir.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/firmware/baseband/dsp_iir.hpp b/firmware/baseband/dsp_iir.hpp index 5c36f5227..a34a51223 100644 --- a/firmware/baseband/dsp_iir.hpp +++ b/firmware/baseband/dsp_iir.hpp @@ -31,9 +31,18 @@ struct iir_biquad_config_t { std::array a; }; +constexpr iir_biquad_config_t iir_no_pass { + { { 0.0f, 0.0f, 0.0f } }, + { { 0.0f, 0.0f, 0.0f } }, +}; + class IIRBiquadFilter { public: // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt + constexpr IIRBiquadFilter( + ) : IIRBiquadFilter(iir_no_pass) + { + } // Assume all coefficients are normalized so that a0=1.0 constexpr IIRBiquadFilter( From 6f00687d889e2465ad1e07d71f50d132a78dd402 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 20:11:27 -0800 Subject: [PATCH 270/452] Add configure() for IIR filter. --- firmware/baseband/dsp_iir.cpp | 4 ++++ firmware/baseband/dsp_iir.hpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/firmware/baseband/dsp_iir.cpp b/firmware/baseband/dsp_iir.cpp index 8fde51ef6..209c43d5b 100644 --- a/firmware/baseband/dsp_iir.cpp +++ b/firmware/baseband/dsp_iir.cpp @@ -23,6 +23,10 @@ #include +void IIRBiquadFilter::configure(const iir_biquad_config_t& new_config) { + config = new_config; +} + void IIRBiquadFilter::execute(const buffer_s16_t& buffer_in, const buffer_s16_t& buffer_out) { // TODO: Assert that buffer_out.count == buffer_in.count. for(size_t i=0; i Date: Sun, 10 Jan 2016 20:14:26 -0800 Subject: [PATCH 271/452] Rename squelch algorithm variable for clarity. Helps to understand meaning of threshold. --- firmware/baseband/dsp_squelch.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/baseband/dsp_squelch.cpp b/firmware/baseband/dsp_squelch.cpp index 2ef331af5..c4c18cca1 100644 --- a/firmware/baseband/dsp_squelch.cpp +++ b/firmware/baseband/dsp_squelch.cpp @@ -33,15 +33,15 @@ bool FMSquelch::execute(const buffer_s16_t& audio) { }; non_audio_hpf.execute(audio, squelch_energy); - uint32_t max_squared = 0; + uint32_t non_audio_max_squared = 0; for(const auto sample : squelch_energy_buffer) { const uint32_t sample_squared = sample * sample; - if( sample_squared > max_squared ) { - max_squared = sample_squared; + if( sample_squared > non_audio_max_squared ) { + non_audio_max_squared = sample_squared; } } - return (max_squared < threshold_squared); + return (non_audio_max_squared < threshold_squared); } void FMSquelch::set_threshold(const uint32_t new_value) { From 5dac0bbe496ad9662ff43e77cfb081050797124f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 20:16:21 -0800 Subject: [PATCH 272/452] Squelch special case when threshold == 0, do not squelch. --- firmware/baseband/dsp_squelch.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/firmware/baseband/dsp_squelch.cpp b/firmware/baseband/dsp_squelch.cpp index c4c18cca1..72f026e0c 100644 --- a/firmware/baseband/dsp_squelch.cpp +++ b/firmware/baseband/dsp_squelch.cpp @@ -25,6 +25,10 @@ #include bool FMSquelch::execute(const buffer_s16_t& audio) { + if( threshold_squared == 0 ) { + return true; + } + // TODO: No hard-coded array size. std::array squelch_energy_buffer; const buffer_s16_t squelch_energy { From 13d260f936144f54228b6101857a12e90277cc44 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 20:18:12 -0800 Subject: [PATCH 273/452] Add IIR passthrough filter config. --- firmware/baseband/dsp_iir.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/firmware/baseband/dsp_iir.hpp b/firmware/baseband/dsp_iir.hpp index 97adb605f..1e06a737d 100644 --- a/firmware/baseband/dsp_iir.hpp +++ b/firmware/baseband/dsp_iir.hpp @@ -31,6 +31,11 @@ struct iir_biquad_config_t { std::array a; }; +constexpr iir_biquad_config_t iir_passthrough { + { { 1.0f, 0.0f, 0.0f } }, + { { 0.0f, 0.0f, 0.0f } }, +}; + constexpr iir_biquad_config_t iir_no_pass { { { 0.0f, 0.0f, 0.0f } }, { { 0.0f, 0.0f, 0.0f } }, From 364217a2b526f56b9ea82ab3df651266ebfcaf6b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 20:20:07 -0800 Subject: [PATCH 274/452] Rename IIR filter config variables. --- firmware/baseband/dsp_iir.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/dsp_iir.hpp b/firmware/baseband/dsp_iir.hpp index 1e06a737d..6821c9626 100644 --- a/firmware/baseband/dsp_iir.hpp +++ b/firmware/baseband/dsp_iir.hpp @@ -31,12 +31,12 @@ struct iir_biquad_config_t { std::array a; }; -constexpr iir_biquad_config_t iir_passthrough { +constexpr iir_biquad_config_t iir_config_passthrough { { { 1.0f, 0.0f, 0.0f } }, { { 0.0f, 0.0f, 0.0f } }, }; -constexpr iir_biquad_config_t iir_no_pass { +constexpr iir_biquad_config_t iir_config_no_pass { { { 0.0f, 0.0f, 0.0f } }, { { 0.0f, 0.0f, 0.0f } }, }; @@ -45,7 +45,7 @@ class IIRBiquadFilter { public: // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt constexpr IIRBiquadFilter( - ) : IIRBiquadFilter(iir_no_pass) + ) : IIRBiquadFilter(iir_config_no_pass) { } From 877a66ca786889be49826b2d0b94ebdc3574be91 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 10 Jan 2016 20:25:24 -0800 Subject: [PATCH 275/452] Create AudioOutput singleton, from extracted BasebandProcessor code. --- firmware/baseband/Makefile | 1 + firmware/baseband/audio_output.cpp | 86 ++++++++++++++++++++++++ firmware/baseband/audio_output.hpp | 57 ++++++++++++++++ firmware/baseband/baseband_processor.cpp | 39 ----------- firmware/baseband/baseband_processor.hpp | 12 +--- firmware/baseband/proc_am_audio.cpp | 8 ++- firmware/baseband/proc_am_audio.hpp | 4 -- firmware/baseband/proc_nfm_audio.cpp | 22 ++---- firmware/baseband/proc_nfm_audio.hpp | 7 -- firmware/baseband/proc_wfm_audio.cpp | 9 +-- firmware/baseband/proc_wfm_audio.hpp | 5 -- 11 files changed, 160 insertions(+), 90 deletions(-) create mode 100644 firmware/baseband/audio_output.cpp create mode 100644 firmware/baseband/audio_output.hpp diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 6f107e3ad..26c974c92 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -154,6 +154,7 @@ CPPSRC = main.cpp \ rssi_dma.cpp \ rssi_thread.cpp \ audio.cpp \ + audio_output.cpp \ audio_dma.cpp \ audio_stats_collector.cpp \ touch_dma.cpp \ diff --git a/firmware/baseband/audio_output.cpp b/firmware/baseband/audio_output.cpp new file mode 100644 index 000000000..824e21d6b --- /dev/null +++ b/firmware/baseband/audio_output.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "audio_output.hpp" + +#include "portapack_shared_memory.hpp" + +#include "audio_dma.hpp" + +#include "message.hpp" + +#include +#include + +void AudioOutput::configure( + const iir_biquad_config_t& hpf_config, + const iir_biquad_config_t& deemph_config, + const uint32_t squelch_threshold +) { + hpf.configure(hpf_config); + deemph.configure(deemph_config); + squelch.set_threshold(squelch_threshold); +} + +void AudioOutput::write( + const buffer_s16_t& audio +) { + const auto audio_present_now = squelch.execute(audio); + + hpf.execute_in_place(audio); + deemph.execute_in_place(audio); + + static uint64_t audio_present_history = 0; + audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0); + const bool audio_present = (audio_present_history != 0); + + if( audio_present ) { + i2s::i2s0::tx_unmute(); + } else { + i2s::i2s0::tx_mute(); + for(size_t i=0; i + +class AudioOutput { +public: + void configure( + const iir_biquad_config_t& hpf_config, + const iir_biquad_config_t& deemph_config = iir_config_passthrough, + const uint32_t squelch_threshold = 0 + ); + + void write(const buffer_s16_t& audio); + +private: + IIRBiquadFilter hpf; + IIRBiquadFilter deemph; + FMSquelch squelch; + + AudioStatsCollector audio_stats; + + void fill_audio_buffer(const buffer_s16_t& audio); + void feed_audio_stats(const buffer_s16_t& audio); +}; + +extern AudioOutput audio_output; + +#endif/*__AUDIO_OUTPUT_H__*/ diff --git a/firmware/baseband/baseband_processor.cpp b/firmware/baseband/baseband_processor.cpp index d17869204..4113dec5b 100644 --- a/firmware/baseband/baseband_processor.cpp +++ b/firmware/baseband/baseband_processor.cpp @@ -23,16 +23,7 @@ #include "portapack_shared_memory.hpp" -#include "dsp_fft.hpp" - -#include "audio_dma.hpp" - #include "message.hpp" -#include "event_m4.hpp" -#include "utility.hpp" - -#include -#include void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { channel_stats.feed( @@ -43,33 +34,3 @@ void BasebandProcessor::feed_channel_stats(const buffer_c16_t& channel) { } ); } - -void BasebandProcessor::fill_audio_buffer(const buffer_s16_t& audio) { - auto audio_buffer = audio::dma::tx_empty_buffer();; - for(size_t i=0; i -#include -#include +#include "message.hpp" class BasebandProcessor { public: @@ -43,14 +39,8 @@ public: protected: void feed_channel_stats(const buffer_c16_t& channel); - void fill_audio_buffer(const buffer_s16_t& audio); - void mute_audio(const buffer_s16_t& audio); - private: ChannelStatsCollector channel_stats; - AudioStatsCollector audio_stats; - - void feed_audio_stats(const buffer_s16_t& audio); }; #endif/*__BASEBAND_PROCESSOR_H__*/ diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 561cefbeb..2e70cf311 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -21,6 +21,9 @@ #include "proc_am_audio.hpp" +#include "dsp_iir_config.hpp" +#include "audio_output.hpp" + #include void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { @@ -38,9 +41,7 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { auto audio = demod.execute(channel_out, work_audio_buffer); - audio_hpf.execute_in_place(audio); - - fill_audio_buffer(audio); + audio_output.write(audio); } void NarrowbandAMAudio::on_message(const Message* const message) { @@ -83,6 +84,7 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); + audio_output.configure(audio_hpf_300hz_config); configured = true; } diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 9c819c677..21a146aa1 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -26,8 +26,6 @@ #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" -#include "dsp_iir.hpp" -#include "dsp_iir_config.hpp" #include "spectrum_collector.hpp" @@ -58,8 +56,6 @@ private: dsp::demodulate::AM demod; - IIRBiquadFilter audio_hpf { audio_hpf_300hz_config }; - SpectrumCollector channel_spectrum; bool configured { false }; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 6cb3696df..573042fb1 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -21,6 +21,9 @@ #include "proc_nfm_audio.hpp" +#include "dsp_iir_config.hpp" +#include "audio_output.hpp" + #include #include @@ -38,22 +41,7 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { auto audio = demod.execute(channel_out, work_audio_buffer); - // Yes, evaluate squelch here, but do audio filtering regardless to keep glitches - // out of the filters. Zero out audio *after* filtering, based on squelch status. - const auto audio_present_now = squelch.execute(audio); - - audio_hpf.execute_in_place(audio); - audio_deemph.execute_in_place(audio); - - static uint64_t audio_present_history = 0; - audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0); - const bool audio_present = (audio_present_history != 0); - - if( audio_present ) { - fill_audio_buffer(audio); - } else { - mute_audio(audio); - } + audio_output.write(audio); } void NarrowbandFMAudio::on_message(const Message* const message) { @@ -99,7 +87,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); - squelch.set_threshold(6144); + audio_output.configure(audio_hpf_300hz_config, audio_deemph_300_6_config, 6144); configured = true; } diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 79fabbd89..f52b89741 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -26,9 +26,6 @@ #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" -#include "dsp_iir.hpp" -#include "dsp_iir_config.hpp" -#include "dsp_squelch.hpp" #include "spectrum_collector.hpp" @@ -58,10 +55,6 @@ private: dsp::demodulate::FM demod; - IIRBiquadFilter audio_hpf { audio_hpf_300hz_config }; - IIRBiquadFilter audio_deemph { audio_deemph_300_6_config }; - FMSquelch squelch; - SpectrumCollector channel_spectrum; bool configured { false }; diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index d903462e2..98bddf6e1 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -21,6 +21,9 @@ #include "proc_wfm_audio.hpp" +#include "dsp_iir_config.hpp" +#include "audio_output.hpp" + #include void WidebandFMAudio::execute(const buffer_c8_t& buffer) { @@ -68,10 +71,7 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { auto audio = audio_filter.execute(audio_2fs, work_audio_buffer); /* -> 48kHz int16_t[32] */ - audio_hpf.execute_in_place(audio); - audio_deemph.execute_in_place(audio); - - fill_audio_buffer(audio); + audio_output.write(audio); } void WidebandFMAudio::on_message(const Message* const message) { @@ -116,6 +116,7 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) { channel_filter_stop_f = message.decim_1_filter.stop_frequency_normalized * decim_1_input_fs; demod.configure(demod_input_fs, message.deviation); audio_filter.configure(message.audio_filter.taps); + audio_output.configure(audio_hpf_30hz_config, audio_deemph_2122_6_config); channel_spectrum.set_decimation_factor(1); diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index ee4a38f4f..499932929 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -26,8 +26,6 @@ #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" -#include "dsp_iir.hpp" -#include "dsp_iir_config.hpp" #include "spectrum_collector.hpp" @@ -58,9 +56,6 @@ private: dsp::decimate::DecimateBy2CIC4Real audio_dec_2; dsp::decimate::FIR64AndDecimateBy2Real audio_filter; - IIRBiquadFilter audio_hpf { audio_hpf_30hz_config }; - IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config }; - SpectrumCollector channel_spectrum; size_t spectrum_interval_samples = 0; size_t spectrum_samples = 0; From 5a532f34a7774a6747795e4846d998f13d442fee Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 11 Jan 2016 09:35:58 -0800 Subject: [PATCH 276/452] Remove extra buffer structs/copies. --- firmware/baseband/proc_wfm_audio.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 98bddf6e1..d86197860 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -32,10 +32,7 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { } const auto decim_0_out = decim_0.execute(buffer, dst_buffer); - const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); - const auto decimator_out = decim_1_out; - - auto channel = decimator_out; + const auto channel = decim_1.execute(decim_0_out, dst_buffer); // TODO: Feed channel_stats post-decimation data? feed_channel_stats(channel); @@ -53,7 +50,7 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { * pass < +/- 100kHz, stop > +/- 200kHz */ - auto audio_oversampled = demod.execute(decimator_out, work_audio_buffer); + auto audio_oversampled = demod.execute(channel, work_audio_buffer); /* 384kHz int16_t[256] * -> 4th order CIC decimation by 2, gain of 1 From 64966d4539f20fb5b9ce5434a63494bc1fab992d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 11 Jan 2016 11:17:33 -0800 Subject: [PATCH 277/452] Fix NaNs coming out of angle_approx_0deg27(). Used in FM demodulator, was causing downstream problems when using the floating point values directly. --- firmware/baseband/dsp_demodulate.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/dsp_demodulate.cpp b/firmware/baseband/dsp_demodulate.cpp index 42f04b01c..67d24ca2a 100644 --- a/firmware/baseband/dsp_demodulate.cpp +++ b/firmware/baseband/dsp_demodulate.cpp @@ -69,8 +69,12 @@ static inline float angle_approx_4deg0(const complex32_t t) { } */ static inline float angle_approx_0deg27(const complex32_t t) { - const auto x = static_cast(t.imag()) / static_cast(t.real()); - return x / (1.0f + 0.28086f * x * x); + if( t.real() ) { + const auto x = static_cast(t.imag()) / static_cast(t.real()); + return x / (1.0f + 0.28086f * x * x); + } else { + return (t.imag() < 0) ? -1.5707963268f : 1.5707963268f; + } } static inline float angle_precise(const complex32_t t) { From e169a46367dbe07934f29f419b325fdd6e7a41eb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 11 Jan 2016 11:38:33 -0800 Subject: [PATCH 278/452] Un-static squelch history. --- firmware/baseband/audio_output.cpp | 1 - firmware/baseband/audio_output.hpp | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/audio_output.cpp b/firmware/baseband/audio_output.cpp index 824e21d6b..426c19ee7 100644 --- a/firmware/baseband/audio_output.cpp +++ b/firmware/baseband/audio_output.cpp @@ -48,7 +48,6 @@ void AudioOutput::write( hpf.execute_in_place(audio); deemph.execute_in_place(audio); - static uint64_t audio_present_history = 0; audio_present_history = (audio_present_history << 1) | (audio_present_now ? 1 : 0); const bool audio_present = (audio_present_history != 0); diff --git a/firmware/baseband/audio_output.hpp b/firmware/baseband/audio_output.hpp index b4b594879..1aec0478c 100644 --- a/firmware/baseband/audio_output.hpp +++ b/firmware/baseband/audio_output.hpp @@ -48,6 +48,8 @@ private: AudioStatsCollector audio_stats; + uint64_t audio_present_history = 0; + void fill_audio_buffer(const buffer_s16_t& audio); void feed_audio_stats(const buffer_s16_t& audio); }; From 5e917ebb2ca44000104c10929c947c16a4fb6791 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 11 Jan 2016 15:44:42 -0800 Subject: [PATCH 279/452] Cache IIR filter state because compiler *sometimes* doesn't want to. --- firmware/baseband/dsp_iir.cpp | 33 +++++++++++++++++++-------------- firmware/baseband/dsp_iir.hpp | 2 -- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/firmware/baseband/dsp_iir.cpp b/firmware/baseband/dsp_iir.cpp index 209c43d5b..9c8655bc3 100644 --- a/firmware/baseband/dsp_iir.cpp +++ b/firmware/baseband/dsp_iir.cpp @@ -28,27 +28,32 @@ void IIRBiquadFilter::configure(const iir_biquad_config_t& new_config) { } void IIRBiquadFilter::execute(const buffer_s16_t& buffer_in, const buffer_s16_t& buffer_out) { + const auto a_ = config.a; + const auto b_ = config.b; + + auto x_ = x; + auto y_ = y; + // TODO: Assert that buffer_out.count == buffer_in.count. for(size_t i=0; i x { { 0.0f, 0.0f, 0.0f } }; std::array y { { 0.0f, 0.0f, 0.0f } }; - - float execute_sample(const float in); }; #endif/*__DSP_IIR_H__*/ From b9f124850bf69b0303a2085a2ac0f019ac947ca6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 11 Jan 2016 16:10:48 -0800 Subject: [PATCH 280/452] Add buffer_t type alias. --- firmware/common/dsp_types.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/common/dsp_types.hpp b/firmware/common/dsp_types.hpp index b4d34843c..b27e6b408 100644 --- a/firmware/common/dsp_types.hpp +++ b/firmware/common/dsp_types.hpp @@ -31,5 +31,6 @@ using buffer_c8_t = buffer_t; using buffer_c16_t = buffer_t; using buffer_s16_t = buffer_t; using buffer_c32_t = buffer_t; +using buffer_f32_t = buffer_t; #endif/*__DSP_TYPES_H__*/ From 55e3a70fde6ea20e940b45ff6425cac3501f5f06 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 11 Jan 2016 16:15:42 -0800 Subject: [PATCH 281/452] Change baseband audio processing pipeline to all floats. --- firmware/baseband/audio_output.cpp | 25 +++++++++++--- firmware/baseband/audio_output.hpp | 7 ++-- firmware/baseband/audio_stats_collector.cpp | 13 +++---- firmware/baseband/audio_stats_collector.hpp | 10 +++--- firmware/baseband/dsp_demodulate.cpp | 38 +++++++++++++++------ firmware/baseband/dsp_demodulate.hpp | 9 +++-- firmware/baseband/dsp_iir.cpp | 8 ++--- firmware/baseband/dsp_iir.hpp | 4 +-- firmware/baseband/dsp_squelch.cpp | 14 ++++---- firmware/baseband/dsp_squelch.hpp | 6 ++-- firmware/baseband/proc_am_audio.hpp | 6 ++-- firmware/baseband/proc_nfm_audio.hpp | 6 ++-- 12 files changed, 90 insertions(+), 56 deletions(-) diff --git a/firmware/baseband/audio_output.cpp b/firmware/baseband/audio_output.cpp index 426c19ee7..f23f88712 100644 --- a/firmware/baseband/audio_output.cpp +++ b/firmware/baseband/audio_output.cpp @@ -29,11 +29,12 @@ #include #include +#include void AudioOutput::configure( const iir_biquad_config_t& hpf_config, const iir_biquad_config_t& deemph_config, - const uint32_t squelch_threshold + const float squelch_threshold ) { hpf.configure(hpf_config); deemph.configure(deemph_config); @@ -42,6 +43,20 @@ void AudioOutput::configure( void AudioOutput::write( const buffer_s16_t& audio +) { + std::array audio_f; + for(size_t i=0; i max_squared ) { max_squared = sample_squared; @@ -42,11 +42,8 @@ bool AudioStatsCollector::update_stats(const size_t sample_count, const size_t s const size_t samples_per_update = sampling_rate * update_interval; if( count >= samples_per_update ) { - const float squared_sum_f = squared_sum; - const float max_squared_f = max_squared; - const float squared_avg_f = squared_sum_f / count; - statistics.rms_db = complex16_mag_squared_to_dbv_norm(squared_avg_f); - statistics.max_db = complex16_mag_squared_to_dbv_norm(max_squared_f); + statistics.rms_db = complex16_mag_squared_to_dbv_norm(squared_sum / count); + statistics.max_db = complex16_mag_squared_to_dbv_norm(max_squared); statistics.count = count; squared_sum = 0; @@ -59,7 +56,7 @@ bool AudioStatsCollector::update_stats(const size_t sample_count, const size_t s } } -bool AudioStatsCollector::feed(const buffer_s16_t& src) { +bool AudioStatsCollector::feed(const buffer_f32_t& src) { consume_audio_buffer(src); return update_stats(src.count, src.sampling_rate); diff --git a/firmware/baseband/audio_stats_collector.hpp b/firmware/baseband/audio_stats_collector.hpp index 467bc3377..10e17edc6 100644 --- a/firmware/baseband/audio_stats_collector.hpp +++ b/firmware/baseband/audio_stats_collector.hpp @@ -31,7 +31,7 @@ class AudioStatsCollector { public: template - void feed(const buffer_s16_t& src, Callback callback) { + void feed(const buffer_f32_t& src, Callback callback) { if( feed(src) ) { callback(statistics); } @@ -46,17 +46,17 @@ public: private: static constexpr float update_interval { 0.1f }; - uint64_t squared_sum { 0 }; - uint32_t max_squared { 0 }; + float squared_sum { 0 }; + float max_squared { 0 }; size_t count { 0 }; AudioStatistics statistics; - void consume_audio_buffer(const buffer_s16_t& src); + void consume_audio_buffer(const buffer_f32_t& src); bool update_stats(const size_t sample_count, const size_t sampling_rate); - bool feed(const buffer_s16_t& src); + bool feed(const buffer_f32_t& src); bool mute(const size_t sample_count, const size_t sampling_rate); }; diff --git a/firmware/baseband/dsp_demodulate.cpp b/firmware/baseband/dsp_demodulate.cpp index 67d24ca2a..b6cbc45ef 100644 --- a/firmware/baseband/dsp_demodulate.cpp +++ b/firmware/baseband/dsp_demodulate.cpp @@ -30,9 +30,9 @@ namespace dsp { namespace demodulate { -buffer_s16_t AM::execute( +buffer_f32_t AM::execute( const buffer_c16_t& src, - const buffer_s16_t& dst + const buffer_f32_t& dst ) { /* Intermediate maximum value: 46341 (when input is -32768,-32768). */ /* Normalized to maximum 32767 for int16_t representation. */ @@ -49,15 +49,8 @@ buffer_s16_t AM::execute( const uint32_t sample1 = *__SIMD32(src_p)++; const uint32_t mag_sq0 = __SMUAD(sample0, sample0); const uint32_t mag_sq1 = __SMUAD(sample1, sample1); - const int32_t mag0_int = __builtin_sqrtf(mag_sq0); - const int32_t mag0_sat = __SSAT(mag0_int, 16); - const int32_t mag1_int = __builtin_sqrtf(mag_sq1); - const int32_t mag1_sat = __SSAT(mag1_int, 16); - *__SIMD32(dst_p)++ = __PKHBT( - mag0_sat, - mag1_sat, - 16 - ); + *(dst_p++) = __builtin_sqrtf(mag_sq0); + *(dst_p++) = __builtin_sqrtf(mag_sq1); } return { dst.p, src.count, src.sampling_rate }; @@ -81,6 +74,29 @@ static inline float angle_precise(const complex32_t t) { return atan2f(t.imag(), t.real()); } +buffer_f32_t FM::execute( + const buffer_c16_t& src, + const buffer_f32_t& dst +) { + auto z = z_; + + const auto src_p = src.p; + const auto src_end = &src.p[src.count]; + auto dst_p = dst.p; + while(src_p < src_end) { + const auto s0 = *__SIMD32(src_p)++; + const auto s1 = *__SIMD32(src_p)++; + const auto t0 = multiply_conjugate_s16_s32(s0, z); + const auto t1 = multiply_conjugate_s16_s32(s1, s0); + z = s1; + *(dst_p++) = angle_approx_0deg27(t0) * k; + *(dst_p++) = angle_approx_0deg27(t1) * k; + } + z_ = z; + + return { dst.p, src.count, src.sampling_rate }; +} + buffer_s16_t FM::execute( const buffer_c16_t& src, const buffer_s16_t& dst diff --git a/firmware/baseband/dsp_demodulate.hpp b/firmware/baseband/dsp_demodulate.hpp index 0f1d4bf84..c93d3b196 100644 --- a/firmware/baseband/dsp_demodulate.hpp +++ b/firmware/baseband/dsp_demodulate.hpp @@ -29,14 +29,19 @@ namespace demodulate { class AM { public: - buffer_s16_t execute( + buffer_f32_t execute( const buffer_c16_t& src, - const buffer_s16_t& dst + const buffer_f32_t& dst ); }; class FM { public: + buffer_f32_t execute( + const buffer_c16_t& src, + const buffer_f32_t& dst + ); + buffer_s16_t execute( const buffer_c16_t& src, const buffer_s16_t& dst diff --git a/firmware/baseband/dsp_iir.cpp b/firmware/baseband/dsp_iir.cpp index 9c8655bc3..443183ba4 100644 --- a/firmware/baseband/dsp_iir.cpp +++ b/firmware/baseband/dsp_iir.cpp @@ -27,7 +27,7 @@ void IIRBiquadFilter::configure(const iir_biquad_config_t& new_config) { config = new_config; } -void IIRBiquadFilter::execute(const buffer_s16_t& buffer_in, const buffer_s16_t& buffer_out) { +void IIRBiquadFilter::execute(const buffer_f32_t& buffer_in, const buffer_f32_t& buffer_out) { const auto a_ = config.a; const auto b_ = config.b; @@ -45,15 +45,13 @@ void IIRBiquadFilter::execute(const buffer_s16_t& buffer_in, const buffer_s16_t& y_[2] = b_[0] * x_[2] + b_[1] * x_[1] + b_[2] * x_[0] - a_[1] * y_[1] - a_[2] * y_[0]; - const int32_t output_sample = y_[2]; - const int32_t output_sample_saturated = __SSAT(output_sample, 16); - buffer_out.p[i] = output_sample_saturated; + buffer_out.p[i] = y_[2]; } x = x_; y = y_; } -void IIRBiquadFilter::execute_in_place(const buffer_s16_t& buffer) { +void IIRBiquadFilter::execute_in_place(const buffer_f32_t& buffer) { execute(buffer, buffer); } diff --git a/firmware/baseband/dsp_iir.hpp b/firmware/baseband/dsp_iir.hpp index df8813ce9..0ecc996a0 100644 --- a/firmware/baseband/dsp_iir.hpp +++ b/firmware/baseband/dsp_iir.hpp @@ -58,8 +58,8 @@ public: void configure(const iir_biquad_config_t& new_config); - void execute(const buffer_s16_t& buffer_in, const buffer_s16_t& buffer_out); - void execute_in_place(const buffer_s16_t& buffer); + void execute(const buffer_f32_t& buffer_in, const buffer_f32_t& buffer_out); + void execute_in_place(const buffer_f32_t& buffer); private: iir_biquad_config_t config; diff --git a/firmware/baseband/dsp_squelch.cpp b/firmware/baseband/dsp_squelch.cpp index 72f026e0c..b4a2d3a48 100644 --- a/firmware/baseband/dsp_squelch.cpp +++ b/firmware/baseband/dsp_squelch.cpp @@ -24,22 +24,22 @@ #include #include -bool FMSquelch::execute(const buffer_s16_t& audio) { - if( threshold_squared == 0 ) { +bool FMSquelch::execute(const buffer_f32_t& audio) { + if( threshold_squared == 0.0f ) { return true; } // TODO: No hard-coded array size. - std::array squelch_energy_buffer; - const buffer_s16_t squelch_energy { + std::array squelch_energy_buffer; + const buffer_f32_t squelch_energy { squelch_energy_buffer.data(), squelch_energy_buffer.size() }; non_audio_hpf.execute(audio, squelch_energy); - uint32_t non_audio_max_squared = 0; + float non_audio_max_squared = 0; for(const auto sample : squelch_energy_buffer) { - const uint32_t sample_squared = sample * sample; + const float sample_squared = sample * sample; if( sample_squared > non_audio_max_squared ) { non_audio_max_squared = sample_squared; } @@ -48,6 +48,6 @@ bool FMSquelch::execute(const buffer_s16_t& audio) { return (non_audio_max_squared < threshold_squared); } -void FMSquelch::set_threshold(const uint32_t new_value) { +void FMSquelch::set_threshold(const float new_value) { threshold_squared = new_value * new_value; } diff --git a/firmware/baseband/dsp_squelch.hpp b/firmware/baseband/dsp_squelch.hpp index 1a1607d7a..4701b9acd 100644 --- a/firmware/baseband/dsp_squelch.hpp +++ b/firmware/baseband/dsp_squelch.hpp @@ -31,13 +31,13 @@ class FMSquelch { public: - bool execute(const buffer_s16_t& audio); + bool execute(const buffer_f32_t& audio); - void set_threshold(const uint32_t new_value); + void set_threshold(const float new_value); private: static constexpr size_t N = 32; - uint32_t threshold_squared { 0 }; + float threshold_squared { 0.0f }; IIRBiquadFilter non_audio_hpf { non_audio_hpf_config }; }; diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 21a146aa1..79f7d8187 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -43,9 +43,9 @@ private: dst.data(), dst.size() }; - const buffer_s16_t work_audio_buffer { - (int16_t*)dst.data(), - sizeof(dst) / sizeof(int16_t) + const buffer_f32_t work_audio_buffer { + (float*)dst.data(), + sizeof(dst) / sizeof(float) }; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index f52b89741..3db9e11f0 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -41,9 +41,9 @@ private: dst.data(), dst.size() }; - const buffer_s16_t work_audio_buffer { - (int16_t*)dst.data(), - sizeof(dst) / sizeof(int16_t) + const buffer_f32_t work_audio_buffer { + (float*)dst.data(), + sizeof(dst) / sizeof(float) }; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; From 1f3c182b7f4ef4eb8fbaeaddecf76c63724a0374 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 11 Jan 2016 16:31:49 -0800 Subject: [PATCH 282/452] Add missing message handler for wideband spectrum. Spectrum processing was not enabled, and hence wideband spectrum was not being displayed. --- firmware/baseband/proc_wideband_spectrum.cpp | 19 ++++++++++++++++++- firmware/baseband/proc_wideband_spectrum.hpp | 4 ++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/firmware/baseband/proc_wideband_spectrum.cpp b/firmware/baseband/proc_wideband_spectrum.cpp index feb29f695..e91121154 100644 --- a/firmware/baseband/proc_wideband_spectrum.cpp +++ b/firmware/baseband/proc_wideband_spectrum.cpp @@ -64,7 +64,24 @@ void WidebandSpectrum::execute(const buffer_c8_t& buffer) { } void WidebandSpectrum::on_message(const Message* const message) { - if( message->id == Message::ID::UpdateSpectrum ) { + switch(message->id) { + case Message::ID::UpdateSpectrum: channel_spectrum.update(); + break; + + case Message::ID::SpectrumStreamingConfig: + streaming_config(*reinterpret_cast(message)); + break; + + default: + break; + } +} + +void WidebandSpectrum::streaming_config(const SpectrumStreamingConfigMessage& message) { + if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) { + channel_spectrum.start(); + } else { + channel_spectrum.stop(); } } diff --git a/firmware/baseband/proc_wideband_spectrum.hpp b/firmware/baseband/proc_wideband_spectrum.hpp index c8401e32e..72179633c 100644 --- a/firmware/baseband/proc_wideband_spectrum.hpp +++ b/firmware/baseband/proc_wideband_spectrum.hpp @@ -25,6 +25,8 @@ #include "baseband_processor.hpp" #include "spectrum_collector.hpp" +#include "message.hpp" + #include #include #include @@ -39,6 +41,8 @@ private: SpectrumCollector channel_spectrum; std::array spectrum; + + void streaming_config(const SpectrumStreamingConfigMessage& message); }; #endif/*__PROC_WIDEBAND_SPECTRUM_H__*/ From a577bc9664c920984eee0cad4c263bde6d1c01b3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 11 Jan 2016 17:18:24 -0800 Subject: [PATCH 283/452] Refactor naughty static variable hiding in WidebandSpectrum. --- firmware/baseband/proc_wideband_spectrum.cpp | 2 -- firmware/baseband/proc_wideband_spectrum.hpp | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/firmware/baseband/proc_wideband_spectrum.cpp b/firmware/baseband/proc_wideband_spectrum.cpp index e91121154..a5b6cd8a2 100644 --- a/firmware/baseband/proc_wideband_spectrum.cpp +++ b/firmware/baseband/proc_wideband_spectrum.cpp @@ -34,8 +34,6 @@ void WidebandSpectrum::execute(const buffer_c8_t& buffer) { // 2048 complex8_t samples per buffer. // 102.4us per buffer. 20480 instruction cycles per buffer. - static int phase = 0; - if( phase == 0 ) { std::fill(spectrum.begin(), spectrum.end(), 0); } diff --git a/firmware/baseband/proc_wideband_spectrum.hpp b/firmware/baseband/proc_wideband_spectrum.hpp index 72179633c..3aff0d3e5 100644 --- a/firmware/baseband/proc_wideband_spectrum.hpp +++ b/firmware/baseband/proc_wideband_spectrum.hpp @@ -43,6 +43,7 @@ private: std::array spectrum; void streaming_config(const SpectrumStreamingConfigMessage& message); + size_t phase = 0; }; #endif/*__PROC_WIDEBAND_SPECTRUM_H__*/ From b993e3d73ea6f01c08fc4b5b7185acd440d6f533 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 12 Jan 2016 10:32:00 -0800 Subject: [PATCH 284/452] Consolidate spectrum collector message handling. --- firmware/baseband/proc_am_audio.cpp | 15 ++----------- firmware/baseband/proc_am_audio.hpp | 2 -- firmware/baseband/proc_nfm_audio.cpp | 15 ++----------- firmware/baseband/proc_nfm_audio.hpp | 2 -- firmware/baseband/proc_wfm_audio.cpp | 15 ++----------- firmware/baseband/proc_wfm_audio.hpp | 2 -- firmware/baseband/proc_wideband_spectrum.cpp | 13 +---------- firmware/baseband/proc_wideband_spectrum.hpp | 1 - firmware/baseband/spectrum_collector.cpp | 23 ++++++++++++++++++++ firmware/baseband/spectrum_collector.hpp | 11 ++++++---- 10 files changed, 37 insertions(+), 62 deletions(-) diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 2e70cf311..06314ee0f 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -47,17 +47,14 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { void NarrowbandAMAudio::on_message(const Message* const message) { switch(message->id) { case Message::ID::UpdateSpectrum: - channel_spectrum.update(); + case Message::ID::SpectrumStreamingConfig: + channel_spectrum.on_message(message); break; case Message::ID::AMConfigure: configure(*reinterpret_cast(message)); break; - case Message::ID::SpectrumStreamingConfig: - streaming_config(*reinterpret_cast(message)); - break; - default: break; } @@ -88,11 +85,3 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { configured = true; } - -void NarrowbandAMAudio::streaming_config(const SpectrumStreamingConfigMessage& message) { - if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) { - channel_spectrum.start(); - } else { - channel_spectrum.stop(); - } -} diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 79f7d8187..1471263d5 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -60,8 +60,6 @@ private: bool configured { false }; void configure(const AMConfigureMessage& message); - - void streaming_config(const SpectrumStreamingConfigMessage& message); }; #endif/*__PROC_AM_AUDIO_H__*/ diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 573042fb1..906617cd3 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -47,17 +47,14 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { void NarrowbandFMAudio::on_message(const Message* const message) { switch(message->id) { case Message::ID::UpdateSpectrum: - channel_spectrum.update(); + case Message::ID::SpectrumStreamingConfig: + channel_spectrum.on_message(message); break; case Message::ID::NBFMConfigure: configure(*reinterpret_cast(message)); break; - case Message::ID::SpectrumStreamingConfig: - streaming_config(*reinterpret_cast(message)); - break; - default: break; } @@ -91,11 +88,3 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { configured = true; } - -void NarrowbandFMAudio::streaming_config(const SpectrumStreamingConfigMessage& message) { - if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) { - channel_spectrum.start(); - } else { - channel_spectrum.stop(); - } -} diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 3db9e11f0..14c2033c7 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -59,8 +59,6 @@ private: bool configured { false }; void configure(const NBFMConfigureMessage& message); - - void streaming_config(const SpectrumStreamingConfigMessage& message); }; #endif/*__PROC_NFM_AUDIO_H__*/ diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index d86197860..33526af8f 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -74,17 +74,14 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) { void WidebandFMAudio::on_message(const Message* const message) { switch(message->id) { case Message::ID::UpdateSpectrum: - channel_spectrum.update(); + case Message::ID::SpectrumStreamingConfig: + channel_spectrum.on_message(message); break; case Message::ID::WFMConfigure: configure(*reinterpret_cast(message)); break; - case Message::ID::SpectrumStreamingConfig: - streaming_config(*reinterpret_cast(message)); - break; - default: break; } @@ -119,11 +116,3 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) { configured = true; } - -void WidebandFMAudio::streaming_config(const SpectrumStreamingConfigMessage& message) { - if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) { - channel_spectrum.start(); - } else { - channel_spectrum.stop(); - } -} diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 499932929..22282189b 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -62,8 +62,6 @@ private: bool configured { false }; void configure(const WFMConfigureMessage& message); - - void streaming_config(const SpectrumStreamingConfigMessage& message); }; #endif/*__PROC_WFM_AUDIO_H__*/ diff --git a/firmware/baseband/proc_wideband_spectrum.cpp b/firmware/baseband/proc_wideband_spectrum.cpp index a5b6cd8a2..399cf6265 100644 --- a/firmware/baseband/proc_wideband_spectrum.cpp +++ b/firmware/baseband/proc_wideband_spectrum.cpp @@ -64,22 +64,11 @@ void WidebandSpectrum::execute(const buffer_c8_t& buffer) { void WidebandSpectrum::on_message(const Message* const message) { switch(message->id) { case Message::ID::UpdateSpectrum: - channel_spectrum.update(); - break; - case Message::ID::SpectrumStreamingConfig: - streaming_config(*reinterpret_cast(message)); + channel_spectrum.on_message(message); break; default: break; } } - -void WidebandSpectrum::streaming_config(const SpectrumStreamingConfigMessage& message) { - if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) { - channel_spectrum.start(); - } else { - channel_spectrum.stop(); - } -} diff --git a/firmware/baseband/proc_wideband_spectrum.hpp b/firmware/baseband/proc_wideband_spectrum.hpp index 3aff0d3e5..5a8757352 100644 --- a/firmware/baseband/proc_wideband_spectrum.hpp +++ b/firmware/baseband/proc_wideband_spectrum.hpp @@ -42,7 +42,6 @@ private: std::array spectrum; - void streaming_config(const SpectrumStreamingConfigMessage& message); size_t phase = 0; }; diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index fc2241aca..7a262ba66 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -29,6 +29,29 @@ #include +void SpectrumCollector::on_message(const Message* const message) { + switch(message->id) { + case Message::ID::UpdateSpectrum: + update(); + break; + + case Message::ID::SpectrumStreamingConfig: + set_state(*reinterpret_cast(message)); + break; + + default: + break; + } +} + +void SpectrumCollector::set_state(const SpectrumStreamingConfigMessage& message) { + if( message.mode == SpectrumStreamingConfigMessage::Mode::Running ) { + start(); + } else { + stop(); + } +} + void SpectrumCollector::start() { streaming = true; ChannelSpectrumConfigMessage message { &fifo }; diff --git a/firmware/baseband/spectrum_collector.hpp b/firmware/baseband/spectrum_collector.hpp index 2f5d51806..4c2cd5420 100644 --- a/firmware/baseband/spectrum_collector.hpp +++ b/firmware/baseband/spectrum_collector.hpp @@ -39,8 +39,7 @@ public: { } - void start(); - void stop(); + void on_message(const Message* const message); void set_decimation_factor(const size_t decimation_factor); @@ -50,8 +49,6 @@ public: const uint32_t filter_stop_frequency ); - void update(); - private: BlockDecimator<256> channel_spectrum_decimator; ChannelSpectrumFIFO fifo; @@ -64,6 +61,12 @@ private: uint32_t channel_filter_stop_frequency { 0 }; void post_message(const buffer_c16_t& data); + + void set_state(const SpectrumStreamingConfigMessage& message); + void start(); + void stop(); + + void update(); }; #endif/*__SPECTRUM_COLLECTOR_H__*/ From e73a9f98a1cf3ff2933a11a52506aa738095deb0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 12 Jan 2016 21:49:29 -0800 Subject: [PATCH 285/452] Move EventDispatcher code into event_*.hpp. More code redistribution coming shortly... --- firmware/application/Makefile | 1 + firmware/application/event_m0.cpp | 43 +++++++ firmware/application/event_m0.hpp | 200 ++++++++++++++++++++++++++++++ firmware/application/main.cpp | 191 ---------------------------- firmware/baseband/Makefile | 1 + firmware/baseband/event_m4.cpp | 43 +++++++ firmware/baseband/event_m4.hpp | 90 ++++++++++++++ firmware/baseband/main.cpp | 92 -------------- 8 files changed, 378 insertions(+), 283 deletions(-) create mode 100644 firmware/application/event_m0.cpp create mode 100644 firmware/baseband/event_m4.cpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index ce6da9dce..41c8e7616 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -122,6 +122,7 @@ CPPSRC = main.cpp \ irq_controls.cpp \ irq_rtc.cpp \ event.cpp \ + event_m0.cpp \ message_queue.cpp \ hackrf_hal.cpp \ portapack.cpp \ diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp new file mode 100644 index 000000000..0d8946feb --- /dev/null +++ b/firmware/application/event_m0.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "event_m0.hpp" + +#include "ch.h" + +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + +extern "C" { + +CH_IRQ_HANDLER(M4Core_IRQHandler) { + CH_IRQ_PROLOGUE(); + + chSysLockFromIsr(); + events_flag_isr(EVT_MASK_APPLICATION); + chSysUnlockFromIsr(); + + creg::m4txevent::clear(); + + CH_IRQ_EPILOGUE(); +} + +} diff --git a/firmware/application/event_m0.hpp b/firmware/application/event_m0.hpp index f2cb5e41d..890fdcb93 100644 --- a/firmware/application/event_m0.hpp +++ b/firmware/application/event_m0.hpp @@ -24,6 +24,31 @@ #include "event.hpp" +#include "portapack.hpp" +#include "portapack_shared_memory.hpp" + +#include "ui_widget.hpp" +#include "ui_painter.hpp" + +#include "touch.hpp" + +#include "irq_lcd_frame.hpp" +#include "irq_controls.hpp" +#include "irq_rtc.hpp" + +#include "message.hpp" +#include "message_queue.hpp" + +#include "sd_card.hpp" + +#include "ch.h" + +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + +#include +#include + constexpr auto EVT_MASK_RTC_TICK = EVENT_MASK(0); constexpr auto EVT_MASK_LCD_FRAME_SYNC = EVENT_MASK(1); constexpr auto EVT_MASK_SWITCHES = EVENT_MASK(3); @@ -31,4 +56,179 @@ constexpr auto EVT_MASK_ENCODER = EVENT_MASK(4); constexpr auto EVT_MASK_TOUCH = EVENT_MASK(5); constexpr auto EVT_MASK_APPLICATION = EVENT_MASK(6); +class EventDispatcher { +public: + EventDispatcher( + ui::Widget* const top_widget, + ui::Painter& painter, + ui::Context& context + ) : top_widget { top_widget }, + painter(painter), + context(context) + { + touch_manager.on_event = [this](const ui::TouchEvent event) { + this->on_touch_event(event); + }; + } + + void run() { + creg::m4txevent::enable(); + + while(is_running) { + const auto events = wait(); + dispatch(events); + } + + creg::m4txevent::disable(); + } + + void request_stop() { + is_running = false; + } + +private: + touch::Manager touch_manager; + ui::Widget* const top_widget; + ui::Painter& painter; + ui::Context& context; + uint32_t encoder_last = 0; + bool is_running = true; + bool sd_card_present = false; + + eventmask_t wait() { + return chEvtWaitAny(ALL_EVENTS); + } + + void dispatch(const eventmask_t events) { + if( events & EVT_MASK_APPLICATION ) { + handle_application_queue(); + } + + if( events & EVT_MASK_RTC_TICK ) { + handle_rtc_tick(); + } + + if( events & EVT_MASK_LCD_FRAME_SYNC ) { + handle_lcd_frame_sync(); + } + + if( events & EVT_MASK_SWITCHES ) { + handle_switches(); + } + + if( events & EVT_MASK_ENCODER ) { + handle_encoder(); + } + + if( events & EVT_MASK_TOUCH ) { + handle_touch(); + } + } + + void handle_application_queue() { + std::array message_buffer; + while(Message* const message = shared_memory.application_queue.pop(message_buffer)) { + context.message_map().send(message); + } + } + + void handle_rtc_tick() { + sd_card::poll_inserted(); + + portapack::temperature_logger.second_tick(); + } + + static ui::Widget* touch_widget(ui::Widget* const w, ui::TouchEvent event) { + if( !w->hidden() ) { + // To achieve reverse depth ordering (last object drawn is + // considered "top"), descend first. + for(const auto child : w->children()) { + const auto touched_widget = touch_widget(child, event); + if( touched_widget ) { + return touched_widget; + } + } + + const auto r = w->screen_rect(); + if( r.contains(event.point) ) { + if( w->on_touch(event) ) { + // This widget responded. Return it up the call stack. + return w; + } + } + } + return nullptr; + } + + ui::Widget* captured_widget { nullptr }; + + void on_touch_event(ui::TouchEvent event) { + /* TODO: Capture widget receiving the Start event, send Move and + * End events to the same widget. + */ + /* Capture Start widget. + * If touch is over Start widget at Move event, then the widget + * should be highlighted. If the touch is not over the Start + * widget at Move event, widget should un-highlight. + * If touch is over Start widget at End event, then the widget + * action should occur. + */ + if( event.type == ui::TouchEvent::Type::Start ) { + captured_widget = touch_widget(this->top_widget, event); + } + + if( captured_widget ) { + captured_widget->on_touch(event); + } + } + + void handle_lcd_frame_sync() { + DisplayFrameSyncMessage message; + context.message_map().send(&message); + painter.paint_widget_tree(top_widget); + } + + void handle_switches() { + const auto switches_state = get_switches_state(); + for(size_t i=0; i(i); + if( !event_bubble_key(event) ) { + context.focus_manager().update(top_widget, event); + } + } + } + } + + void handle_encoder() { + const uint32_t encoder_now = get_encoder_position(); + const int32_t delta = static_cast(encoder_now - encoder_last); + encoder_last = encoder_now; + const auto event = static_cast(delta); + event_bubble_encoder(event); + } + + void handle_touch() { + touch_manager.feed(get_touch_frame()); + } + + bool event_bubble_key(const ui::KeyEvent event) { + auto target = context.focus_manager().focus_widget(); + while( (target != nullptr) && !target->on_key(event) ) { + target = target->parent(); + } + + /* Return true if event was consumed. */ + return (target != nullptr); + } + + void event_bubble_encoder(const ui::EncoderEvent event) { + auto target = context.focus_manager().focus_widget(); + while( (target != nullptr) && !target->on_encoder(event) ) { + target = target->parent(); + } + } +}; + #endif/*__EVENT_M0_H__*/ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index cdbc1e207..2746beeb7 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -54,197 +54,6 @@ using namespace lpc43xx; #include -extern "C" { - -CH_IRQ_HANDLER(M4Core_IRQHandler) { - CH_IRQ_PROLOGUE(); - - chSysLockFromIsr(); - events_flag_isr(EVT_MASK_APPLICATION); - chSysUnlockFromIsr(); - - creg::m4txevent::clear(); - - CH_IRQ_EPILOGUE(); -} - -} - -class EventDispatcher { -public: - EventDispatcher( - ui::Widget* const top_widget, - ui::Painter& painter, - ui::Context& context - ) : top_widget { top_widget }, - painter(painter), - context(context) - { - touch_manager.on_event = [this](const ui::TouchEvent event) { - this->on_touch_event(event); - }; - } - - void run() { - creg::m4txevent::enable(); - - while(is_running) { - const auto events = wait(); - dispatch(events); - } - - creg::m4txevent::disable(); - } - - void request_stop() { - is_running = false; - } - -private: - touch::Manager touch_manager; - ui::Widget* const top_widget; - ui::Painter& painter; - ui::Context& context; - uint32_t encoder_last = 0; - bool is_running = true; - bool sd_card_present = false; - - eventmask_t wait() { - return chEvtWaitAny(ALL_EVENTS); - } - - void dispatch(const eventmask_t events) { - if( events & EVT_MASK_APPLICATION ) { - handle_application_queue(); - } - - if( events & EVT_MASK_RTC_TICK ) { - handle_rtc_tick(); - } - - if( events & EVT_MASK_LCD_FRAME_SYNC ) { - handle_lcd_frame_sync(); - } - - if( events & EVT_MASK_SWITCHES ) { - handle_switches(); - } - - if( events & EVT_MASK_ENCODER ) { - handle_encoder(); - } - - if( events & EVT_MASK_TOUCH ) { - handle_touch(); - } - } - - void handle_application_queue() { - std::array message_buffer; - while(Message* const message = shared_memory.application_queue.pop(message_buffer)) { - context.message_map().send(message); - } - } - - void handle_rtc_tick() { - sd_card::poll_inserted(); - - portapack::temperature_logger.second_tick(); - } - - static ui::Widget* touch_widget(ui::Widget* const w, ui::TouchEvent event) { - if( !w->hidden() ) { - // To achieve reverse depth ordering (last object drawn is - // considered "top"), descend first. - for(const auto child : w->children()) { - const auto touched_widget = touch_widget(child, event); - if( touched_widget ) { - return touched_widget; - } - } - - const auto r = w->screen_rect(); - if( r.contains(event.point) ) { - if( w->on_touch(event) ) { - // This widget responded. Return it up the call stack. - return w; - } - } - } - return nullptr; - } - - ui::Widget* captured_widget { nullptr }; - - void on_touch_event(ui::TouchEvent event) { - /* TODO: Capture widget receiving the Start event, send Move and - * End events to the same widget. - */ - /* Capture Start widget. - * If touch is over Start widget at Move event, then the widget - * should be highlighted. If the touch is not over the Start - * widget at Move event, widget should un-highlight. - * If touch is over Start widget at End event, then the widget - * action should occur. - */ - if( event.type == ui::TouchEvent::Type::Start ) { - captured_widget = touch_widget(this->top_widget, event); - } - - if( captured_widget ) { - captured_widget->on_touch(event); - } - } - - void handle_lcd_frame_sync() { - DisplayFrameSyncMessage message; - context.message_map().send(&message); - painter.paint_widget_tree(top_widget); - } - - void handle_switches() { - const auto switches_state = get_switches_state(); - for(size_t i=0; i(i); - if( !event_bubble_key(event) ) { - context.focus_manager().update(top_widget, event); - } - } - } - } - - void handle_encoder() { - const uint32_t encoder_now = get_encoder_position(); - const int32_t delta = static_cast(encoder_now - encoder_last); - encoder_last = encoder_now; - const auto event = static_cast(delta); - event_bubble_encoder(event); - } - - void handle_touch() { - touch_manager.feed(get_touch_frame()); - } - - bool event_bubble_key(const ui::KeyEvent event) { - auto target = context.focus_manager().focus_widget(); - while( (target != nullptr) && !target->on_key(event) ) { - target = target->parent(); - } - - /* Return true if event was consumed. */ - return (target != nullptr); - } - - void event_bubble_encoder(const ui::EncoderEvent event) { - auto target = context.focus_manager().focus_widget(); - while( (target != nullptr) && !target->on_encoder(event) ) { - target = target->parent(); - } - } -}; - int main(void) { portapack::init(); diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 26c974c92..413ed0ded 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -125,6 +125,7 @@ CSRC = $(PORTSRC) \ CPPSRC = main.cpp \ message_queue.cpp \ event.cpp \ + event_m4.cpp \ gpdma.cpp \ baseband_dma.cpp \ baseband_sgpio.cpp \ diff --git a/firmware/baseband/event_m4.cpp b/firmware/baseband/event_m4.cpp new file mode 100644 index 000000000..ae72c8426 --- /dev/null +++ b/firmware/baseband/event_m4.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "event_m4.hpp" + +#include "ch.h" + +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + +extern "C" { + +CH_IRQ_HANDLER(MAPP_IRQHandler) { + CH_IRQ_PROLOGUE(); + + chSysLockFromIsr(); + events_flag_isr(EVT_MASK_BASEBAND); + chSysUnlockFromIsr(); + + creg::m0apptxevent::clear(); + + CH_IRQ_EPILOGUE(); +} + +} diff --git a/firmware/baseband/event_m4.hpp b/firmware/baseband/event_m4.hpp index 03277443c..b257c158f 100644 --- a/firmware/baseband/event_m4.hpp +++ b/firmware/baseband/event_m4.hpp @@ -24,7 +24,97 @@ #include "event.hpp" +#include "portapack_shared_memory.hpp" + +#include "baseband_thread.hpp" +#include "rssi_thread.hpp" + +#include "message.hpp" +#include "message_queue.hpp" + +#include "ch.h" + +#include "lpc43xx_cpp.hpp" + +#include + constexpr auto EVT_MASK_BASEBAND = EVENT_MASK(0); constexpr auto EVT_MASK_SPECTRUM = EVENT_MASK(1); +class EventDispatcher { +public: + void run() { + events_initialize(chThdSelf()); + lpc43xx::creg::m0apptxevent::enable(); + + baseband_thread.thread_main = chThdSelf(); + baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); + baseband_thread.start(NORMALPRIO + 20); + + while(is_running) { + const auto events = wait(); + dispatch(events); + } + + lpc43xx::creg::m0apptxevent::disable(); + } + + void request_stop() { + is_running = false; + } + +private: + BasebandThread baseband_thread; + RSSIThread rssi_thread; + + bool is_running = true; + + eventmask_t wait() { + return chEvtWaitAny(ALL_EVENTS); + } + + void dispatch(const eventmask_t events) { + if( events & EVT_MASK_BASEBAND ) { + handle_baseband_queue(); + } + + if( events & EVT_MASK_SPECTRUM ) { + handle_spectrum(); + } + } + + void handle_baseband_queue() { + std::array message_buffer; + while(Message* const message = shared_memory.baseband_queue.peek(message_buffer)) { + on_message(message); + shared_memory.baseband_queue.skip(); + } + } + + void on_message(const Message* const message) { + switch(message->id) { + case Message::ID::Shutdown: + on_message_shutdown(*reinterpret_cast(message)); + break; + + default: + on_message_default(message); + break; + } + } + + void on_message_shutdown(const ShutdownMessage&) { + request_stop(); + } + + void on_message_default(const Message* const message) { + baseband_thread.on_message(message); + } + + void handle_spectrum() { + const UpdateSpectrumMessage message; + baseband_thread.on_message(&message); + } +}; + #endif/*__EVENT_M4_H__*/ diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index d74dd148c..d6a895a77 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -117,98 +117,6 @@ static void shutdown() { halt(); } -extern "C" { - -CH_IRQ_HANDLER(MAPP_IRQHandler) { - CH_IRQ_PROLOGUE(); - - chSysLockFromIsr(); - events_flag_isr(EVT_MASK_BASEBAND); - chSysUnlockFromIsr(); - - creg::m0apptxevent::clear(); - - CH_IRQ_EPILOGUE(); -} - -} - -class EventDispatcher { -public: - void run() { - events_initialize(chThdSelf()); - lpc43xx::creg::m0apptxevent::enable(); - - baseband_thread.thread_main = chThdSelf(); - baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); - baseband_thread.start(NORMALPRIO + 20); - - while(is_running) { - const auto events = wait(); - dispatch(events); - } - - lpc43xx::creg::m0apptxevent::disable(); - } - - void request_stop() { - is_running = false; - } - -private: - BasebandThread baseband_thread; - RSSIThread rssi_thread; - - bool is_running = true; - - eventmask_t wait() { - return chEvtWaitAny(ALL_EVENTS); - } - - void dispatch(const eventmask_t events) { - if( events & EVT_MASK_BASEBAND ) { - handle_baseband_queue(); - } - - if( events & EVT_MASK_SPECTRUM ) { - handle_spectrum(); - } - } - - void handle_baseband_queue() { - std::array message_buffer; - while(Message* const message = shared_memory.baseband_queue.peek(message_buffer)) { - on_message(message); - shared_memory.baseband_queue.skip(); - } - } - - void on_message(const Message* const message) { - switch(message->id) { - case Message::ID::Shutdown: - on_message_shutdown(*reinterpret_cast(message)); - break; - - default: - on_message_default(message); - break; - } - } - - void on_message_shutdown(const ShutdownMessage&) { - request_stop(); - } - - void on_message_default(const Message* const message) { - baseband_thread.on_message(message); - } - - void handle_spectrum() { - const UpdateSpectrumMessage message; - baseband_thread.on_message(&message); - } -}; - int main(void) { init(); From 731cea1b961f4bcb70a09104610450b0319ba340 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 12 Jan 2016 22:00:42 -0800 Subject: [PATCH 286/452] Move event.* code into event_m[04].*. Slightly more duplication of code now. Need a base class... --- firmware/application/event_m0.cpp | 4 +++- firmware/application/event_m0.hpp | 15 +++++++++++++++ firmware/application/irq_controls.cpp | 2 +- firmware/application/irq_lcd_frame.cpp | 2 +- firmware/application/irq_rtc.cpp | 2 +- firmware/application/main.cpp | 1 - firmware/baseband/event_m4.cpp | 4 +++- firmware/baseband/event_m4.hpp | 16 +++++++++++++++- firmware/baseband/spectrum_collector.cpp | 4 +++- firmware/common/event.cpp | 6 ------ firmware/common/event.hpp | 16 ---------------- 11 files changed, 42 insertions(+), 30 deletions(-) diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index 0d8946feb..384887496 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -32,7 +32,7 @@ CH_IRQ_HANDLER(M4Core_IRQHandler) { CH_IRQ_PROLOGUE(); chSysLockFromIsr(); - events_flag_isr(EVT_MASK_APPLICATION); + EventDispatcher::events_flag_isr(EVT_MASK_APPLICATION); chSysUnlockFromIsr(); creg::m4txevent::clear(); @@ -41,3 +41,5 @@ CH_IRQ_HANDLER(M4Core_IRQHandler) { } } + +Thread* EventDispatcher::thread_event_loop = nullptr; diff --git a/firmware/application/event_m0.hpp b/firmware/application/event_m0.hpp index 890fdcb93..41e74f7bb 100644 --- a/firmware/application/event_m0.hpp +++ b/firmware/application/event_m0.hpp @@ -66,6 +66,7 @@ public: painter(painter), context(context) { + thread_event_loop = chThdSelf(); touch_manager.on_event = [this](const ui::TouchEvent event) { this->on_touch_event(event); }; @@ -86,7 +87,21 @@ public: is_running = false; } + static inline void events_flag(const eventmask_t events) { + if( thread_event_loop ) { + chEvtSignal(thread_event_loop, events); + } + } + + static inline void events_flag_isr(const eventmask_t events) { + if( thread_event_loop ) { + chEvtSignalI(thread_event_loop, events); + } + } + private: + static Thread* thread_event_loop; + touch::Manager touch_manager; ui::Widget* const top_widget; ui::Painter& painter; diff --git a/firmware/application/irq_controls.cpp b/firmware/application/irq_controls.cpp index bba6f54d2..5a789721d 100644 --- a/firmware/application/irq_controls.cpp +++ b/firmware/application/irq_controls.cpp @@ -165,7 +165,7 @@ void timer0_callback(GPTDriver* const) { /* Signal event loop */ if( event_mask ) { chSysLockFromIsr(); - events_flag_isr(event_mask); + EventDispatcher::events_flag_isr(event_mask); chSysUnlockFromIsr(); } diff --git a/firmware/application/irq_lcd_frame.cpp b/firmware/application/irq_lcd_frame.cpp index 6ea2ed2df..585feb1f0 100644 --- a/firmware/application/irq_lcd_frame.cpp +++ b/firmware/application/irq_lcd_frame.cpp @@ -54,7 +54,7 @@ CH_IRQ_HANDLER(PIN_INT4_IRQHandler) { CH_IRQ_PROLOGUE(); chSysLockFromIsr(); - events_flag_isr(EVT_MASK_LCD_FRAME_SYNC); + EventDispatcher::events_flag_isr(EVT_MASK_LCD_FRAME_SYNC); chSysUnlockFromIsr(); LPC_GPIO_INT->IST = (1U << 4); diff --git a/firmware/application/irq_rtc.cpp b/firmware/application/irq_rtc.cpp index 9a7243201..332f1b3e9 100644 --- a/firmware/application/irq_rtc.cpp +++ b/firmware/application/irq_rtc.cpp @@ -39,7 +39,7 @@ CH_IRQ_HANDLER(RTC_IRQHandler) { CH_IRQ_PROLOGUE(); chSysLockFromIsr(); - events_flag_isr(EVT_MASK_RTC_TICK); + EventDispatcher::events_flag_isr(EVT_MASK_RTC_TICK); chSysUnlockFromIsr(); rtc::interrupt::clear_all(); diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 2746beeb7..788a44522 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -66,7 +66,6 @@ int main(void) { sdcStart(&SDCD1, nullptr); - events_initialize(chThdSelf()); init_message_queues(); ui::Context context; diff --git a/firmware/baseband/event_m4.cpp b/firmware/baseband/event_m4.cpp index ae72c8426..00f8bf1e8 100644 --- a/firmware/baseband/event_m4.cpp +++ b/firmware/baseband/event_m4.cpp @@ -32,7 +32,7 @@ CH_IRQ_HANDLER(MAPP_IRQHandler) { CH_IRQ_PROLOGUE(); chSysLockFromIsr(); - events_flag_isr(EVT_MASK_BASEBAND); + EventDispatcher::events_flag_isr(EVT_MASK_BASEBAND); chSysUnlockFromIsr(); creg::m0apptxevent::clear(); @@ -41,3 +41,5 @@ CH_IRQ_HANDLER(MAPP_IRQHandler) { } } + +Thread* EventDispatcher::thread_event_loop = nullptr; diff --git a/firmware/baseband/event_m4.hpp b/firmware/baseband/event_m4.hpp index b257c158f..e330226a4 100644 --- a/firmware/baseband/event_m4.hpp +++ b/firmware/baseband/event_m4.hpp @@ -44,7 +44,7 @@ constexpr auto EVT_MASK_SPECTRUM = EVENT_MASK(1); class EventDispatcher { public: void run() { - events_initialize(chThdSelf()); + thread_event_loop = chThdSelf(); lpc43xx::creg::m0apptxevent::enable(); baseband_thread.thread_main = chThdSelf(); @@ -63,7 +63,21 @@ public: is_running = false; } + static inline void events_flag(const eventmask_t events) { + if( thread_event_loop ) { + chEvtSignal(thread_event_loop, events); + } + } + + static inline void events_flag_isr(const eventmask_t events) { + if( thread_event_loop ) { + chEvtSignalI(thread_event_loop, events); + } + } + private: + static Thread* thread_event_loop; + BasebandThread baseband_thread; RSSIThread rssi_thread; diff --git a/firmware/baseband/spectrum_collector.cpp b/firmware/baseband/spectrum_collector.cpp index 7a262ba66..2b661c9a8 100644 --- a/firmware/baseband/spectrum_collector.cpp +++ b/firmware/baseband/spectrum_collector.cpp @@ -27,6 +27,8 @@ #include "event_m4.hpp" #include "portapack_shared_memory.hpp" +#include "event_m4.hpp" + #include void SpectrumCollector::on_message(const Message* const message) { @@ -97,7 +99,7 @@ void SpectrumCollector::post_message(const buffer_c16_t& data) { fft_swap(data, channel_spectrum); channel_spectrum_sampling_rate = data.sampling_rate; channel_spectrum_request_update = true; - events_flag(EVT_MASK_SPECTRUM); + EventDispatcher::events_flag(EVT_MASK_SPECTRUM); } } diff --git a/firmware/common/event.cpp b/firmware/common/event.cpp index 28f1151d1..eee675cdf 100644 --- a/firmware/common/event.cpp +++ b/firmware/common/event.cpp @@ -22,9 +22,3 @@ #include "event.hpp" #include "ch.h" - -Thread* thread_event_loop = nullptr; - -void events_initialize(Thread* const event_loop_thread) { - thread_event_loop = event_loop_thread; -} diff --git a/firmware/common/event.hpp b/firmware/common/event.hpp index d05a0a325..a6432674c 100644 --- a/firmware/common/event.hpp +++ b/firmware/common/event.hpp @@ -24,20 +24,4 @@ #include "ch.h" -void events_initialize(Thread* const event_loop_thread); - -extern Thread* thread_event_loop; - -inline void events_flag(const eventmask_t events) { - if( thread_event_loop ) { - chEvtSignal(thread_event_loop, events); - } -} - -inline void events_flag_isr(const eventmask_t events) { - if( thread_event_loop ) { - chEvtSignalI(thread_event_loop, events); - } -} - #endif/*__EVENT_H__*/ From f06d5989db93fdde36fc550b8c6de2f779a23112 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 12 Jan 2016 22:20:13 -0800 Subject: [PATCH 287/452] Move EventDispatcher code out of .hpp. --- firmware/application/event_m0.cpp | 174 ++++++++++++++++++++++++++++ firmware/application/event_m0.hpp | 181 +++--------------------------- firmware/baseband/event_m4.cpp | 74 ++++++++++++ firmware/baseband/event_m4.hpp | 77 ++----------- 4 files changed, 272 insertions(+), 234 deletions(-) diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index 384887496..609589c17 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -21,11 +21,23 @@ #include "event_m0.hpp" +#include "portapack.hpp" +#include "portapack_shared_memory.hpp" + +#include "sd_card.hpp" + +#include "message.hpp" +#include "message_queue.hpp" + +#include "irq_controls.hpp" + #include "ch.h" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; +#include + extern "C" { CH_IRQ_HANDLER(M4Core_IRQHandler) { @@ -43,3 +55,165 @@ CH_IRQ_HANDLER(M4Core_IRQHandler) { } Thread* EventDispatcher::thread_event_loop = nullptr; + +EventDispatcher::EventDispatcher( + ui::Widget* const top_widget, + ui::Painter& painter, + ui::Context& context +) : top_widget { top_widget }, + painter(painter), + context(context) +{ + thread_event_loop = chThdSelf(); + touch_manager.on_event = [this](const ui::TouchEvent event) { + this->on_touch_event(event); + }; +} + +void EventDispatcher::run() { + creg::m4txevent::enable(); + + while(is_running) { + const auto events = wait(); + dispatch(events); + } + + creg::m4txevent::disable(); +} + +void EventDispatcher::request_stop() { + is_running = false; +} + +eventmask_t EventDispatcher::wait() { + return chEvtWaitAny(ALL_EVENTS); +} + +void EventDispatcher::dispatch(const eventmask_t events) { + if( events & EVT_MASK_APPLICATION ) { + handle_application_queue(); + } + + if( events & EVT_MASK_RTC_TICK ) { + handle_rtc_tick(); + } + + if( events & EVT_MASK_LCD_FRAME_SYNC ) { + handle_lcd_frame_sync(); + } + + if( events & EVT_MASK_SWITCHES ) { + handle_switches(); + } + + if( events & EVT_MASK_ENCODER ) { + handle_encoder(); + } + + if( events & EVT_MASK_TOUCH ) { + handle_touch(); + } +} + +void EventDispatcher::handle_application_queue() { + std::array message_buffer; + while(Message* const message = shared_memory.application_queue.pop(message_buffer)) { + context.message_map().send(message); + } +} + +void EventDispatcher::handle_rtc_tick() { + sd_card::poll_inserted(); + + portapack::temperature_logger.second_tick(); +} + +ui::Widget* EventDispatcher::touch_widget(ui::Widget* const w, ui::TouchEvent event) { + if( !w->hidden() ) { + // To achieve reverse depth ordering (last object drawn is + // considered "top"), descend first. + for(const auto child : w->children()) { + const auto touched_widget = touch_widget(child, event); + if( touched_widget ) { + return touched_widget; + } + } + + const auto r = w->screen_rect(); + if( r.contains(event.point) ) { + if( w->on_touch(event) ) { + // This widget responded. Return it up the call stack. + return w; + } + } + } + return nullptr; +} + +void EventDispatcher::on_touch_event(ui::TouchEvent event) { + /* TODO: Capture widget receiving the Start event, send Move and + * End events to the same widget. + */ + /* Capture Start widget. + * If touch is over Start widget at Move event, then the widget + * should be highlighted. If the touch is not over the Start + * widget at Move event, widget should un-highlight. + * If touch is over Start widget at End event, then the widget + * action should occur. + */ + if( event.type == ui::TouchEvent::Type::Start ) { + captured_widget = touch_widget(this->top_widget, event); + } + + if( captured_widget ) { + captured_widget->on_touch(event); + } +} + +void EventDispatcher::handle_lcd_frame_sync() { + DisplayFrameSyncMessage message; + context.message_map().send(&message); + painter.paint_widget_tree(top_widget); +} + +void EventDispatcher::handle_switches() { + const auto switches_state = get_switches_state(); + for(size_t i=0; i(i); + if( !event_bubble_key(event) ) { + context.focus_manager().update(top_widget, event); + } + } + } +} + +void EventDispatcher::handle_encoder() { + const uint32_t encoder_now = get_encoder_position(); + const int32_t delta = static_cast(encoder_now - encoder_last); + encoder_last = encoder_now; + const auto event = static_cast(delta); + event_bubble_encoder(event); +} + +void EventDispatcher::handle_touch() { + touch_manager.feed(get_touch_frame()); +} + +bool EventDispatcher::event_bubble_key(const ui::KeyEvent event) { + auto target = context.focus_manager().focus_widget(); + while( (target != nullptr) && !target->on_key(event) ) { + target = target->parent(); + } + + /* Return true if event was consumed. */ + return (target != nullptr); +} + +void EventDispatcher::event_bubble_encoder(const ui::EncoderEvent event) { + auto target = context.focus_manager().focus_widget(); + while( (target != nullptr) && !target->on_encoder(event) ) { + target = target->parent(); + } +} \ No newline at end of file diff --git a/firmware/application/event_m0.hpp b/firmware/application/event_m0.hpp index 41e74f7bb..342ed0986 100644 --- a/firmware/application/event_m0.hpp +++ b/firmware/application/event_m0.hpp @@ -24,30 +24,14 @@ #include "event.hpp" -#include "portapack.hpp" -#include "portapack_shared_memory.hpp" - #include "ui_widget.hpp" #include "ui_painter.hpp" #include "touch.hpp" -#include "irq_lcd_frame.hpp" -#include "irq_controls.hpp" -#include "irq_rtc.hpp" - -#include "message.hpp" -#include "message_queue.hpp" - -#include "sd_card.hpp" - #include "ch.h" -#include "lpc43xx_cpp.hpp" -using namespace lpc43xx; - #include -#include constexpr auto EVT_MASK_RTC_TICK = EVENT_MASK(0); constexpr auto EVT_MASK_LCD_FRAME_SYNC = EVENT_MASK(1); @@ -62,30 +46,10 @@ public: ui::Widget* const top_widget, ui::Painter& painter, ui::Context& context - ) : top_widget { top_widget }, - painter(painter), - context(context) - { - thread_event_loop = chThdSelf(); - touch_manager.on_event = [this](const ui::TouchEvent event) { - this->on_touch_event(event); - }; - } + ); - void run() { - creg::m4txevent::enable(); - - while(is_running) { - const auto events = wait(); - dispatch(events); - } - - creg::m4txevent::disable(); - } - - void request_stop() { - is_running = false; - } + void run(); + void request_stop(); static inline void events_flag(const eventmask_t events) { if( thread_event_loop ) { @@ -110,140 +74,25 @@ private: bool is_running = true; bool sd_card_present = false; - eventmask_t wait() { - return chEvtWaitAny(ALL_EVENTS); - } + eventmask_t wait(); + void dispatch(const eventmask_t events); - void dispatch(const eventmask_t events) { - if( events & EVT_MASK_APPLICATION ) { - handle_application_queue(); - } + void handle_application_queue(); + void handle_rtc_tick(); - if( events & EVT_MASK_RTC_TICK ) { - handle_rtc_tick(); - } - - if( events & EVT_MASK_LCD_FRAME_SYNC ) { - handle_lcd_frame_sync(); - } - - if( events & EVT_MASK_SWITCHES ) { - handle_switches(); - } - - if( events & EVT_MASK_ENCODER ) { - handle_encoder(); - } - - if( events & EVT_MASK_TOUCH ) { - handle_touch(); - } - } - - void handle_application_queue() { - std::array message_buffer; - while(Message* const message = shared_memory.application_queue.pop(message_buffer)) { - context.message_map().send(message); - } - } - - void handle_rtc_tick() { - sd_card::poll_inserted(); - - portapack::temperature_logger.second_tick(); - } - - static ui::Widget* touch_widget(ui::Widget* const w, ui::TouchEvent event) { - if( !w->hidden() ) { - // To achieve reverse depth ordering (last object drawn is - // considered "top"), descend first. - for(const auto child : w->children()) { - const auto touched_widget = touch_widget(child, event); - if( touched_widget ) { - return touched_widget; - } - } - - const auto r = w->screen_rect(); - if( r.contains(event.point) ) { - if( w->on_touch(event) ) { - // This widget responded. Return it up the call stack. - return w; - } - } - } - return nullptr; - } + static ui::Widget* touch_widget(ui::Widget* const w, ui::TouchEvent event); ui::Widget* captured_widget { nullptr }; - void on_touch_event(ui::TouchEvent event) { - /* TODO: Capture widget receiving the Start event, send Move and - * End events to the same widget. - */ - /* Capture Start widget. - * If touch is over Start widget at Move event, then the widget - * should be highlighted. If the touch is not over the Start - * widget at Move event, widget should un-highlight. - * If touch is over Start widget at End event, then the widget - * action should occur. - */ - if( event.type == ui::TouchEvent::Type::Start ) { - captured_widget = touch_widget(this->top_widget, event); - } + void on_touch_event(ui::TouchEvent event); - if( captured_widget ) { - captured_widget->on_touch(event); - } - } + void handle_lcd_frame_sync(); + void handle_switches(); + void handle_encoder(); + void handle_touch(); - void handle_lcd_frame_sync() { - DisplayFrameSyncMessage message; - context.message_map().send(&message); - painter.paint_widget_tree(top_widget); - } - - void handle_switches() { - const auto switches_state = get_switches_state(); - for(size_t i=0; i(i); - if( !event_bubble_key(event) ) { - context.focus_manager().update(top_widget, event); - } - } - } - } - - void handle_encoder() { - const uint32_t encoder_now = get_encoder_position(); - const int32_t delta = static_cast(encoder_now - encoder_last); - encoder_last = encoder_now; - const auto event = static_cast(delta); - event_bubble_encoder(event); - } - - void handle_touch() { - touch_manager.feed(get_touch_frame()); - } - - bool event_bubble_key(const ui::KeyEvent event) { - auto target = context.focus_manager().focus_widget(); - while( (target != nullptr) && !target->on_key(event) ) { - target = target->parent(); - } - - /* Return true if event was consumed. */ - return (target != nullptr); - } - - void event_bubble_encoder(const ui::EncoderEvent event) { - auto target = context.focus_manager().focus_widget(); - while( (target != nullptr) && !target->on_encoder(event) ) { - target = target->parent(); - } - } + bool event_bubble_key(const ui::KeyEvent event); + void event_bubble_encoder(const ui::EncoderEvent event); }; #endif/*__EVENT_M0_H__*/ diff --git a/firmware/baseband/event_m4.cpp b/firmware/baseband/event_m4.cpp index 00f8bf1e8..0e90cd150 100644 --- a/firmware/baseband/event_m4.cpp +++ b/firmware/baseband/event_m4.cpp @@ -21,11 +21,18 @@ #include "event_m4.hpp" +#include "portapack_shared_memory.hpp" + +#include "message_queue.hpp" + #include "ch.h" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; +#include +#include + extern "C" { CH_IRQ_HANDLER(MAPP_IRQHandler) { @@ -43,3 +50,70 @@ CH_IRQ_HANDLER(MAPP_IRQHandler) { } Thread* EventDispatcher::thread_event_loop = nullptr; + +void EventDispatcher::run() { + thread_event_loop = chThdSelf(); + lpc43xx::creg::m0apptxevent::enable(); + + baseband_thread.thread_main = chThdSelf(); + baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); + baseband_thread.start(NORMALPRIO + 20); + + while(is_running) { + const auto events = wait(); + dispatch(events); + } + + lpc43xx::creg::m0apptxevent::disable(); +} + +void EventDispatcher::request_stop() { + is_running = false; +} + +eventmask_t EventDispatcher::wait() { + return chEvtWaitAny(ALL_EVENTS); +} + +void EventDispatcher::dispatch(const eventmask_t events) { + if( events & EVT_MASK_BASEBAND ) { + handle_baseband_queue(); + } + + if( events & EVT_MASK_SPECTRUM ) { + handle_spectrum(); + } +} + +void EventDispatcher::handle_baseband_queue() { + std::array message_buffer; + while(Message* const message = shared_memory.baseband_queue.peek(message_buffer)) { + on_message(message); + shared_memory.baseband_queue.skip(); + } +} + +void EventDispatcher::on_message(const Message* const message) { + switch(message->id) { + case Message::ID::Shutdown: + on_message_shutdown(*reinterpret_cast(message)); + break; + + default: + on_message_default(message); + break; + } +} + +void EventDispatcher::on_message_shutdown(const ShutdownMessage&) { + request_stop(); +} + +void EventDispatcher::on_message_default(const Message* const message) { + baseband_thread.on_message(message); +} + +void EventDispatcher::handle_spectrum() { + const UpdateSpectrumMessage message; + baseband_thread.on_message(&message); +} diff --git a/firmware/baseband/event_m4.hpp b/firmware/baseband/event_m4.hpp index e330226a4..ad9871d15 100644 --- a/firmware/baseband/event_m4.hpp +++ b/firmware/baseband/event_m4.hpp @@ -24,44 +24,20 @@ #include "event.hpp" -#include "portapack_shared_memory.hpp" - #include "baseband_thread.hpp" #include "rssi_thread.hpp" #include "message.hpp" -#include "message_queue.hpp" #include "ch.h" -#include "lpc43xx_cpp.hpp" - -#include - constexpr auto EVT_MASK_BASEBAND = EVENT_MASK(0); constexpr auto EVT_MASK_SPECTRUM = EVENT_MASK(1); class EventDispatcher { public: - void run() { - thread_event_loop = chThdSelf(); - lpc43xx::creg::m0apptxevent::enable(); - - baseband_thread.thread_main = chThdSelf(); - baseband_thread.thread_rssi = rssi_thread.start(NORMALPRIO + 10); - baseband_thread.start(NORMALPRIO + 20); - - while(is_running) { - const auto events = wait(); - dispatch(events); - } - - lpc43xx::creg::m0apptxevent::disable(); - } - - void request_stop() { - is_running = false; - } + void run(); + void request_stop(); static inline void events_flag(const eventmask_t events) { if( thread_event_loop ) { @@ -83,52 +59,17 @@ private: bool is_running = true; - eventmask_t wait() { - return chEvtWaitAny(ALL_EVENTS); - } + eventmask_t wait(); - void dispatch(const eventmask_t events) { - if( events & EVT_MASK_BASEBAND ) { - handle_baseband_queue(); - } + void dispatch(const eventmask_t events); - if( events & EVT_MASK_SPECTRUM ) { - handle_spectrum(); - } - } + void handle_baseband_queue(); - void handle_baseband_queue() { - std::array message_buffer; - while(Message* const message = shared_memory.baseband_queue.peek(message_buffer)) { - on_message(message); - shared_memory.baseband_queue.skip(); - } - } + void on_message(const Message* const message); + void on_message_shutdown(const ShutdownMessage&); + void on_message_default(const Message* const message); - void on_message(const Message* const message) { - switch(message->id) { - case Message::ID::Shutdown: - on_message_shutdown(*reinterpret_cast(message)); - break; - - default: - on_message_default(message); - break; - } - } - - void on_message_shutdown(const ShutdownMessage&) { - request_stop(); - } - - void on_message_default(const Message* const message) { - baseband_thread.on_message(message); - } - - void handle_spectrum() { - const UpdateSpectrumMessage message; - baseband_thread.on_message(&message); - } + void handle_spectrum(); }; #endif/*__EVENT_M4_H__*/ From 4b2157a938dec11e49c7c0980392a4dc9d04e109 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 11:43:21 -0800 Subject: [PATCH 288/452] Push AIS list item draw style into render method. --- firmware/application/ais_app.cpp | 10 ++++++---- firmware/application/ais_app.hpp | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 13bf711da..cd2854ddc 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -214,8 +214,11 @@ void AISView::draw_entry( const RecentEntry& entry, const Rect& target_rect, Painter& painter, - const Style& s + const Style& style, + const bool is_selected ) { + const auto& draw_style = is_selected ? style.invert() : style; + std::string line = ais::format::mmsi(entry.mmsi) + " "; if( !entry.name.empty() ) { line += entry.name; @@ -224,7 +227,7 @@ void AISView::draw_entry( } line.resize(target_rect.width() / 8, ' '); - painter.draw_string(target_rect.pos, s, line); + painter.draw_string(target_rect.pos, draw_style, line); } void AISView::paint(Painter& painter) { @@ -258,8 +261,7 @@ void AISView::paint(Painter& painter) { for(auto p = start; p != end; p++) { const auto& entry = *p; const auto is_selected_key = (selected_key == entry.mmsi); - const auto& draw_style = (has_focus && is_selected_key) ? s.invert() : s; - draw_entry(entry, target_rect, painter, draw_style); + draw_entry(entry, target_rect, painter, s, (has_focus && is_selected_key)); target_rect.pos.y += target_rect.height(); } } diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 9f51ebbda..a941321c5 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -109,7 +109,8 @@ private: const RecentEntry& entry, const Rect& target_rect, Painter& painter, - const Style& s + const Style& style, + const bool is_selected ); void truncate_entries(); From a29b76ac382b5dc637855fb8e912f474f485914d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 11:52:39 -0800 Subject: [PATCH 289/452] Pull AIS record types out of AISView. --- firmware/application/ais_app.cpp | 6 ++-- firmware/application/ais_app.hpp | 54 ++++++++++++++++---------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index cd2854ddc..9f0de16f6 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -144,7 +144,7 @@ void AISView::truncate_entries() { void AISView::on_packet(const ais::Packet& packet) { const auto source_id = packet.source_id(); auto matching_recent = std::find_if(recent.begin(), recent.end(), - [source_id](const AISView::RecentEntry& entry) { return entry.mmsi == source_id; } + [source_id](const AISRecentEntry& entry) { return entry.mmsi == source_id; } ); if( matching_recent != recent.end() ) { // Found within. Move to front of list, increment counter. @@ -211,7 +211,7 @@ bool AISView::on_encoder(const EncoderEvent event) { } void AISView::draw_entry( - const RecentEntry& entry, + const AISRecentEntry& entry, const Rect& target_rect, Painter& painter, const Style& style, @@ -268,7 +268,7 @@ void AISView::paint(Painter& painter) { AISView::RecentEntries::iterator AISView::selected_entry() { const auto key = selected_key; - return std::find_if(std::begin(recent), std::end(recent), [key](const RecentEntry& e) { return e.mmsi == key; }); + return std::find_if(std::begin(recent), std::end(recent), [key](const AISRecentEntry& e) { return e.mmsi == key; }); } void AISView::advance(const int32_t amount) { diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index a941321c5..68ac70d0b 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -38,6 +38,31 @@ using namespace lpc43xx; #include +struct AISPosition { + rtc::RTC timestamp { }; + ais::Latitude latitude { 0 }; + ais::Longitude longitude { 0 }; +}; + +struct AISRecentEntry { + ais::MMSI mmsi; + std::string name; + std::string call_sign; + std::string destination; + AISPosition last_position; + size_t received_count; + int8_t navigational_status; + + AISRecentEntry( + const ais::MMSI& mmsi + ) : mmsi { mmsi }, + last_position { }, + received_count { 0 }, + navigational_status { -1 } + { + } +}; + class AISModel { public: AISModel(); @@ -75,38 +100,13 @@ private: bool has_focus = false; - struct Position { - rtc::RTC timestamp { }; - ais::Latitude latitude { 0 }; - ais::Longitude longitude { 0 }; - }; - - struct RecentEntry { - ais::MMSI mmsi; - std::string name; - std::string call_sign; - std::string destination; - Position last_position; - size_t received_count; - int8_t navigational_status; - - RecentEntry( - const ais::MMSI& mmsi - ) : mmsi { mmsi }, - last_position { }, - received_count { 0 }, - navigational_status { -1 } - { - } - }; - - using RecentEntries = std::list; + using RecentEntries = std::list; RecentEntries recent; void on_packet(const ais::Packet& packet); void draw_entry( - const RecentEntry& entry, + const AISRecentEntry& entry, const Rect& target_rect, Painter& painter, const Style& style, From d380ffe52b9ca32aa3e501483cd526d19cd2b70a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 11:56:23 -0800 Subject: [PATCH 290/452] Extract AIS record renderer from AISView. --- firmware/application/ais_app.cpp | 4 ++-- firmware/application/ais_app.hpp | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 9f0de16f6..bf4e21117 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -210,7 +210,7 @@ bool AISView::on_encoder(const EncoderEvent event) { return true; } -void AISView::draw_entry( +static void ais_list_item_draw( const AISRecentEntry& entry, const Rect& target_rect, Painter& painter, @@ -261,7 +261,7 @@ void AISView::paint(Painter& painter) { for(auto p = start; p != end; p++) { const auto& entry = *p; const auto is_selected_key = (selected_key == entry.mmsi); - draw_entry(entry, target_rect, painter, s, (has_focus && is_selected_key)); + ais_list_item_draw(entry, target_rect, painter, s, (has_focus && is_selected_key)); target_rect.pos.y += target_rect.height(); } } diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 68ac70d0b..4a11efaf6 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -105,14 +105,6 @@ private: void on_packet(const ais::Packet& packet); - void draw_entry( - const AISRecentEntry& entry, - const Rect& target_rect, - Painter& painter, - const Style& style, - const bool is_selected - ); - void truncate_entries(); RecentEntries::iterator selected_entry(); From 9cab3c9978d93ef91c8fb33e6e03e564800aa150 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 15:46:04 -0800 Subject: [PATCH 291/452] Remove message_map from Context. It doesn't belong in a display/rendering context object, it has much broader significance, mostly distributing messages via the M4->M0 IPC mechanism. --- firmware/application/ais_app.cpp | 8 ++++---- firmware/application/ert_app.cpp | 8 ++++---- firmware/application/event_m0.cpp | 5 +++-- firmware/application/event_m0.hpp | 7 +++++++ firmware/application/main.cpp | 3 +-- firmware/application/tpms_app.cpp | 8 ++++---- firmware/application/ui_audio.cpp | 6 ++++-- firmware/application/ui_baseband_stats_view.cpp | 6 ++++-- firmware/application/ui_channel.cpp | 6 ++++-- firmware/application/ui_rssi.cpp | 6 ++++-- firmware/application/ui_spectrum.cpp | 10 ++++++---- firmware/common/ui_widget.hpp | 7 ------- 12 files changed, 45 insertions(+), 35 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index bf4e21117..a96b1fdf6 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -21,6 +21,8 @@ #include "ais_app.hpp" +#include "event_m0.hpp" + #include "string_format.hpp" #include "portapack.hpp" @@ -116,8 +118,7 @@ namespace ui { void AISView::on_show() { View::on_show(); - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::AISPacket, + EventDispatcher::message_map().register_handler(Message::ID::AISPacket, [this](Message* const p) { const auto message = static_cast(p); const ais::Packet packet { message->packet }; @@ -129,8 +130,7 @@ void AISView::on_show() { } void AISView::on_hide() { - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::AISPacket); + EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); View::on_hide(); } diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 596831e3e..c17c2ac8e 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -21,6 +21,8 @@ #include "ert_app.hpp" +#include "event_m0.hpp" + #include "portapack.hpp" using namespace portapack; @@ -54,8 +56,7 @@ namespace ui { void ERTView::on_show() { Console::on_show(); - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::ERTPacket, + EventDispatcher::message_map().register_handler(Message::ID::ERTPacket, [this](Message* const p) { const auto message = static_cast(p); const ert::Packet packet { message->type, message->packet }; @@ -67,8 +68,7 @@ void ERTView::on_show() { } void ERTView::on_hide() { - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::ERTPacket); + EventDispatcher::message_map().unregister_handler(Message::ID::ERTPacket); Console::on_hide(); } diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index 609589c17..6e8897710 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -54,6 +54,7 @@ CH_IRQ_HANDLER(M4Core_IRQHandler) { } +MessageHandlerMap EventDispatcher::message_map_; Thread* EventDispatcher::thread_event_loop = nullptr; EventDispatcher::EventDispatcher( @@ -118,7 +119,7 @@ void EventDispatcher::dispatch(const eventmask_t events) { void EventDispatcher::handle_application_queue() { std::array message_buffer; while(Message* const message = shared_memory.application_queue.pop(message_buffer)) { - context.message_map().send(message); + message_map().send(message); } } @@ -172,7 +173,7 @@ void EventDispatcher::on_touch_event(ui::TouchEvent event) { void EventDispatcher::handle_lcd_frame_sync() { DisplayFrameSyncMessage message; - context.message_map().send(&message); + message_map().send(&message); painter.paint_widget_tree(top_widget); } diff --git a/firmware/application/event_m0.hpp b/firmware/application/event_m0.hpp index 342ed0986..1409ceb7a 100644 --- a/firmware/application/event_m0.hpp +++ b/firmware/application/event_m0.hpp @@ -27,6 +27,8 @@ #include "ui_widget.hpp" #include "ui_painter.hpp" +#include "message.hpp" + #include "touch.hpp" #include "ch.h" @@ -63,7 +65,12 @@ public: } } + static MessageHandlerMap& message_map() { + return message_map_; + } + private: + static MessageHandlerMap message_map_; static Thread* thread_event_loop; touch::Manager touch_manager; diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 788a44522..d9900426c 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -76,8 +76,7 @@ int main(void) { ui::Painter painter; EventDispatcher event_dispatcher { &system_view, painter, context }; - auto& message_handlers = context.message_map(); - message_handlers.register_handler(Message::ID::Shutdown, + EventDispatcher::message_map().register_handler(Message::ID::Shutdown, [&event_dispatcher](const Message* const) { event_dispatcher.request_stop(); } diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 85a849c8c..39af6c076 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -21,6 +21,8 @@ #include "tpms_app.hpp" +#include "event_m0.hpp" + #include "portapack.hpp" using namespace portapack; @@ -58,8 +60,7 @@ namespace ui { void TPMSView::on_show() { Console::on_show(); - auto& message_map = context().message_map(); - message_map.register_handler(Message::ID::TPMSPacket, + EventDispatcher::message_map().register_handler(Message::ID::TPMSPacket, [this](Message* const p) { const auto message = static_cast(p); this->log(this->model.on_packet(*message)); @@ -68,8 +69,7 @@ void TPMSView::on_show() { } void TPMSView::on_hide() { - auto& message_map = context().message_map(); - message_map.unregister_handler(Message::ID::TPMSPacket); + EventDispatcher::message_map().unregister_handler(Message::ID::TPMSPacket); Console::on_hide(); } diff --git a/firmware/application/ui_audio.cpp b/firmware/application/ui_audio.cpp index 0dd698e2b..b85e0dd99 100644 --- a/firmware/application/ui_audio.cpp +++ b/firmware/application/ui_audio.cpp @@ -21,12 +21,14 @@ #include "ui_audio.hpp" +#include "event_m0.hpp" + #include namespace ui { void Audio::on_show() { - context().message_map().register_handler(Message::ID::AudioStatistics, + EventDispatcher::message_map().register_handler(Message::ID::AudioStatistics, [this](const Message* const p) { this->on_statistics_update(static_cast(p)->statistics); } @@ -34,7 +36,7 @@ void Audio::on_show() { } void Audio::on_hide() { - context().message_map().unregister_handler(Message::ID::AudioStatistics); + EventDispatcher::message_map().unregister_handler(Message::ID::AudioStatistics); } void Audio::paint(Painter& painter) { diff --git a/firmware/application/ui_baseband_stats_view.cpp b/firmware/application/ui_baseband_stats_view.cpp index 76cccb5a9..0d576e819 100644 --- a/firmware/application/ui_baseband_stats_view.cpp +++ b/firmware/application/ui_baseband_stats_view.cpp @@ -21,6 +21,8 @@ #include "ui_baseband_stats_view.hpp" +#include "event_m0.hpp" + #include #include @@ -40,7 +42,7 @@ BasebandStatsView::BasebandStatsView() { } void BasebandStatsView::on_show() { - context().message_map().register_handler(Message::ID::BasebandStatistics, + EventDispatcher::message_map().register_handler(Message::ID::BasebandStatistics, [this](const Message* const p) { this->on_statistics_update(static_cast(p)->statistics); } @@ -48,7 +50,7 @@ void BasebandStatsView::on_show() { } void BasebandStatsView::on_hide() { - context().message_map().unregister_handler(Message::ID::BasebandStatistics); + EventDispatcher::message_map().unregister_handler(Message::ID::BasebandStatistics); } diff --git a/firmware/application/ui_channel.cpp b/firmware/application/ui_channel.cpp index a5c8a568d..cdcb8d736 100644 --- a/firmware/application/ui_channel.cpp +++ b/firmware/application/ui_channel.cpp @@ -21,12 +21,14 @@ #include "ui_channel.hpp" +#include "event_m0.hpp" + #include namespace ui { void Channel::on_show() { - context().message_map().register_handler(Message::ID::ChannelStatistics, + EventDispatcher::message_map().register_handler(Message::ID::ChannelStatistics, [this](const Message* const p) { this->on_statistics_update(static_cast(p)->statistics); } @@ -34,7 +36,7 @@ void Channel::on_show() { } void Channel::on_hide() { - context().message_map().unregister_handler(Message::ID::ChannelStatistics); + EventDispatcher::message_map().unregister_handler(Message::ID::ChannelStatistics); } void Channel::paint(Painter& painter) { diff --git a/firmware/application/ui_rssi.cpp b/firmware/application/ui_rssi.cpp index 7cbba2a14..629b66d41 100644 --- a/firmware/application/ui_rssi.cpp +++ b/firmware/application/ui_rssi.cpp @@ -21,12 +21,14 @@ #include "ui_rssi.hpp" +#include "event_m0.hpp" + #include namespace ui { void RSSI::on_show() { - context().message_map().register_handler(Message::ID::RSSIStatistics, + EventDispatcher::message_map().register_handler(Message::ID::RSSIStatistics, [this](const Message* const p) { this->on_statistics_update(static_cast(p)->statistics); } @@ -34,7 +36,7 @@ void RSSI::on_show() { } void RSSI::on_hide() { - context().message_map().unregister_handler(Message::ID::RSSIStatistics); + EventDispatcher::message_map().unregister_handler(Message::ID::RSSIStatistics); } void RSSI::paint(Painter& painter) { diff --git a/firmware/application/ui_spectrum.cpp b/firmware/application/ui_spectrum.cpp index 748382106..addd2079d 100644 --- a/firmware/application/ui_spectrum.cpp +++ b/firmware/application/ui_spectrum.cpp @@ -21,6 +21,8 @@ #include "ui_spectrum.hpp" +#include "event_m0.hpp" + #include "spectrum_color_lut.hpp" #include "portapack.hpp" @@ -235,13 +237,13 @@ WaterfallWidget::WaterfallWidget() { } void WaterfallWidget::on_show() { - context().message_map().register_handler(Message::ID::ChannelSpectrumConfig, + EventDispatcher::message_map().register_handler(Message::ID::ChannelSpectrumConfig, [this](const Message* const p) { const auto message = *reinterpret_cast(p); this->fifo = message.fifo; } ); - context().message_map().register_handler(Message::ID::DisplayFrameSync, + EventDispatcher::message_map().register_handler(Message::ID::DisplayFrameSync, [this](const Message* const) { if( this->fifo ) { ChannelSpectrum channel_spectrum; @@ -266,8 +268,8 @@ void WaterfallWidget::on_hide() { } ); - context().message_map().unregister_handler(Message::ID::DisplayFrameSync); - context().message_map().unregister_handler(Message::ID::ChannelSpectrumConfig); + EventDispatcher::message_map().unregister_handler(Message::ID::DisplayFrameSync); + EventDispatcher::message_map().unregister_handler(Message::ID::ChannelSpectrumConfig); } void WaterfallWidget::set_parent_rect(const Rect new_parent_rect) { diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index a974631a5..f2e18364e 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -29,8 +29,6 @@ #include "utility.hpp" -#include "message.hpp" - #include #include #include @@ -47,13 +45,8 @@ public: return focus_manager_; } - MessageHandlerMap& message_map() { - return message_map_; - } - private: FocusManager focus_manager_; - MessageHandlerMap message_map_; }; class Widget { From f8a063312c52a0d2ea78df499e792362486ef916 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 16:32:56 -0800 Subject: [PATCH 292/452] AISModel receive packets from baseband, notifies AISView. Use Signal class to distribute packets to multiple listeners. --- firmware/application/ais_app.cpp | 34 +++++++++++++------------------- firmware/application/ais_app.hpp | 19 +++++++++++++++--- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index a96b1fdf6..b8d84565c 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -89,6 +89,18 @@ AISModel::AISModel() { receiver_model.set_baseband_bandwidth(1750000); log_file.open_for_append("ais.txt"); + + EventDispatcher::message_map().register_handler(Message::ID::AISPacket, + [this](Message* const p) { + const auto message = static_cast(p); + const ais::Packet packet { message->packet }; + this->on_packet(packet); + } + ); +} + +AISModel::~AISModel() { + EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); } bool AISModel::on_packet(const ais::Packet& packet) { @@ -110,31 +122,13 @@ bool AISModel::on_packet(const ais::Packet& packet) { log_file.write_entry(packet.received_at(), entry); } + packet_signal.emit(packet); + return true; } namespace ui { -void AISView::on_show() { - View::on_show(); - - EventDispatcher::message_map().register_handler(Message::ID::AISPacket, - [this](Message* const p) { - const auto message = static_cast(p); - const ais::Packet packet { message->packet }; - if( this->model.on_packet(packet) ) { - this->on_packet(packet); - } - } - ); -} - -void AISView::on_hide() { - EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); - - View::on_hide(); -} - void AISView::truncate_entries() { while(recent.size() > 64) { recent.pop_back(); diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 4a11efaf6..65bd9e26d 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -25,8 +25,12 @@ #include "ui_widget.hpp" #include "log_file.hpp" +#include "message.hpp" + #include "ais_packet.hpp" +#include "signal.hpp" + #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -66,11 +70,14 @@ struct AISRecentEntry { class AISModel { public: AISModel(); + ~AISModel(); - bool on_packet(const ais::Packet& packet); + Signal packet_signal; private: LogFile log_file; + + bool on_packet(const ais::Packet& packet); }; namespace ui { @@ -79,10 +86,15 @@ class AISView : public View { public: AISView() { flags.focusable = true; + + packet_signal_token = model.packet_signal += [this](const ais::Packet& packet) { + this->on_packet(packet); + }; } - void on_show() override; - void on_hide() override; + ~AISView() { + model.packet_signal -= packet_signal_token; + } void paint(Painter& painter) override; @@ -93,6 +105,7 @@ public: private: AISModel model; + SignalToken packet_signal_token; using EntryKey = ais::MMSI; EntryKey selected_key; From 94b73d782597ba456780afe673df61827a3a528e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 16:44:01 -0800 Subject: [PATCH 293/452] AISView constructors out of header. --- firmware/application/ais_app.cpp | 12 ++++++++++++ firmware/application/ais_app.hpp | 15 +++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index b8d84565c..21778def0 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -129,6 +129,18 @@ bool AISModel::on_packet(const ais::Packet& packet) { namespace ui { +AISView::AISView() { + flags.focusable = true; + + packet_signal_token = model.packet_signal += [this](const ais::Packet& packet) { + this->on_packet(packet); + }; +} + +AISView::~AISView() { + model.packet_signal -= packet_signal_token; +} + void AISView::truncate_entries() { while(recent.size() > 64) { recent.pop_back(); diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 65bd9e26d..f532eeaa3 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -84,18 +84,9 @@ namespace ui { class AISView : public View { public: - AISView() { - flags.focusable = true; - - packet_signal_token = model.packet_signal += [this](const ais::Packet& packet) { - this->on_packet(packet); - }; - } - - ~AISView() { - model.packet_signal -= packet_signal_token; - } - + AISView(); + ~AISView(); + void paint(Painter& painter) override; void on_focus() override; From 8c34e116af4b8fc82c7df72456d4c355178596a6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 17:00:53 -0800 Subject: [PATCH 294/452] Remove Signal use, register message handler in View. Changed my mind from earlier commit... --- firmware/application/ais_app.cpp | 33 +++++++++++--------------------- firmware/application/ais_app.hpp | 12 ++---------- 2 files changed, 13 insertions(+), 32 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 21778def0..6c8109c54 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -89,27 +89,11 @@ AISModel::AISModel() { receiver_model.set_baseband_bandwidth(1750000); log_file.open_for_append("ais.txt"); - - EventDispatcher::message_map().register_handler(Message::ID::AISPacket, - [this](Message* const p) { - const auto message = static_cast(p); - const ais::Packet packet { message->packet }; - this->on_packet(packet); - } - ); -} - -AISModel::~AISModel() { - EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); } bool AISModel::on_packet(const ais::Packet& packet) { // TODO: Unstuff here, not in baseband! - if( !packet.is_valid() ) { - return false; - } - if( log_file.is_ready() ) { std::string entry; entry.reserve((packet.length() + 3) / 4); @@ -122,8 +106,6 @@ bool AISModel::on_packet(const ais::Packet& packet) { log_file.write_entry(packet.received_at(), entry); } - packet_signal.emit(packet); - return true; } @@ -132,13 +114,20 @@ namespace ui { AISView::AISView() { flags.focusable = true; - packet_signal_token = model.packet_signal += [this](const ais::Packet& packet) { - this->on_packet(packet); - }; + EventDispatcher::message_map().register_handler(Message::ID::AISPacket, + [this](Message* const p) { + const auto message = static_cast(p); + const ais::Packet packet { message->packet }; + if( packet.is_valid() ) { + this->model.on_packet(packet); + this->on_packet(packet); + } + } + ); } AISView::~AISView() { - model.packet_signal -= packet_signal_token; + EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); } void AISView::truncate_entries() { diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index f532eeaa3..e7e20052c 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -25,12 +25,8 @@ #include "ui_widget.hpp" #include "log_file.hpp" -#include "message.hpp" - #include "ais_packet.hpp" -#include "signal.hpp" - #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -70,14 +66,11 @@ struct AISRecentEntry { class AISModel { public: AISModel(); - ~AISModel(); - Signal packet_signal; + bool on_packet(const ais::Packet& packet); private: LogFile log_file; - - bool on_packet(const ais::Packet& packet); }; namespace ui { @@ -86,7 +79,7 @@ class AISView : public View { public: AISView(); ~AISView(); - + void paint(Painter& painter) override; void on_focus() override; @@ -96,7 +89,6 @@ public: private: AISModel model; - SignalToken packet_signal_token; using EntryKey = ais::MMSI; EntryKey selected_key; From 01741f3c7cb7b439a8d1effc7340d59f7584e31b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 17:05:19 -0800 Subject: [PATCH 295/452] Rename AISModel to AISLogger. That's really what it is. Also move receiver initialization to AISView. It'll eventually move further out to an AISApp, once I figure out what an App looks like... --- firmware/application/ais_app.cpp | 23 ++++++++++------------- firmware/application/ais_app.hpp | 8 ++++---- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 6c8109c54..3d71207d3 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -80,20 +80,12 @@ static std::string navigational_status(const unsigned int value) { } /* namespace format */ } /* namespace ais */ -AISModel::AISModel() { - receiver_model.set_baseband_configuration({ - .mode = 3, - .sampling_rate = 2457600, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); - +AISLogger::AISLogger() { log_file.open_for_append("ais.txt"); } -bool AISModel::on_packet(const ais::Packet& packet) { +void AISLogger::on_packet(const ais::Packet& packet) { // TODO: Unstuff here, not in baseband! - if( log_file.is_ready() ) { std::string entry; entry.reserve((packet.length() + 3) / 4); @@ -105,8 +97,6 @@ bool AISModel::on_packet(const ais::Packet& packet) { log_file.write_entry(packet.received_at(), entry); } - - return true; } namespace ui { @@ -119,11 +109,18 @@ AISView::AISView() { const auto message = static_cast(p); const ais::Packet packet { message->packet }; if( packet.is_valid() ) { - this->model.on_packet(packet); + this->logger.on_packet(packet); this->on_packet(packet); } } ); + + receiver_model.set_baseband_configuration({ + .mode = 3, + .sampling_rate = 2457600, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); } AISView::~AISView() { diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index e7e20052c..249be1306 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -63,11 +63,11 @@ struct AISRecentEntry { } }; -class AISModel { +class AISLogger { public: - AISModel(); + AISLogger(); - bool on_packet(const ais::Packet& packet); + void on_packet(const ais::Packet& packet); private: LogFile log_file; @@ -88,7 +88,7 @@ public: bool on_encoder(const EncoderEvent event) override; private: - AISModel model; + AISLogger logger; using EntryKey = ais::MMSI; EntryKey selected_key; From 2888257167baecf734cde1eb6617d54dfc8409c1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 18:01:38 -0800 Subject: [PATCH 296/452] Extract AISRecentEntries from AISView. --- firmware/application/ais_app.cpp | 106 ++++++++++++++++--------------- firmware/application/ais_app.hpp | 38 +++++++++-- 2 files changed, 88 insertions(+), 56 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 3d71207d3..455a33817 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -99,55 +99,21 @@ void AISLogger::on_packet(const ais::Packet& packet) { } } -namespace ui { - -AISView::AISView() { - flags.focusable = true; - - EventDispatcher::message_map().register_handler(Message::ID::AISPacket, - [this](Message* const p) { - const auto message = static_cast(p); - const ais::Packet packet { message->packet }; - if( packet.is_valid() ) { - this->logger.on_packet(packet); - this->on_packet(packet); - } - } - ); - - receiver_model.set_baseband_configuration({ - .mode = 3, - .sampling_rate = 2457600, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); -} - -AISView::~AISView() { - EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); -} - -void AISView::truncate_entries() { - while(recent.size() > 64) { - recent.pop_back(); - } -} - -void AISView::on_packet(const ais::Packet& packet) { +void AISRecentEntries::on_packet(const ais::Packet& packet) { const auto source_id = packet.source_id(); - auto matching_recent = std::find_if(recent.begin(), recent.end(), + auto matching_recent = std::find_if(entries.begin(), entries.end(), [source_id](const AISRecentEntry& entry) { return entry.mmsi == source_id; } ); - if( matching_recent != recent.end() ) { + if( matching_recent != entries.end() ) { // Found within. Move to front of list, increment counter. - recent.push_front(*matching_recent); - recent.erase(matching_recent); + entries.push_front(*matching_recent); + entries.erase(matching_recent); } else { - recent.emplace_front(source_id); + entries.emplace_front(source_id); truncate_entries(); } - auto& entry = recent.front(); + auto& entry = entries.front(); entry.received_count++; switch(packet.message_id()) { @@ -183,6 +149,51 @@ void AISView::on_packet(const ais::Packet& packet) { default: break; } +} + +AISRecentEntries::ContainerType::const_iterator AISRecentEntries::find(const ais::MMSI key) const { + return std::find_if( + begin(), end(), + [key](const AISRecentEntry& e) { return e.mmsi == key; } + ); +} + +void AISRecentEntries::truncate_entries() { + while(entries.size() > entries_max) { + entries.pop_back(); + } +} + +namespace ui { + +AISView::AISView() { + flags.focusable = true; + + EventDispatcher::message_map().register_handler(Message::ID::AISPacket, + [this](Message* const p) { + const auto message = static_cast(p); + const ais::Packet packet { message->packet }; + if( packet.is_valid() ) { + this->logger.on_packet(packet); + this->on_packet(packet); + } + } + ); + + receiver_model.set_baseband_configuration({ + .mode = 3, + .sampling_rate = 2457600, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); +} + +AISView::~AISView() { + EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); +} + +void AISView::on_packet(const ais::Packet& packet) { + recent.on_packet(packet); set_dirty(); } @@ -229,13 +240,13 @@ void AISView::paint(Painter& painter) { Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; const size_t visible_item_count = r.height() / s.font.line_height(); - auto selected = selected_entry(); + auto selected = recent.find(selected_key); if( selected == std::end(recent) ) { selected = std::begin(recent); } - RecentEntries::iterator start = selected; - RecentEntries::iterator end = selected; + auto start = selected; + auto end = selected; size_t i = 0; // Move start iterator toward first entry. @@ -258,13 +269,8 @@ void AISView::paint(Painter& painter) { } } -AISView::RecentEntries::iterator AISView::selected_entry() { - const auto key = selected_key; - return std::find_if(std::begin(recent), std::end(recent), [key](const AISRecentEntry& e) { return e.mmsi == key; }); -} - void AISView::advance(const int32_t amount) { - auto selected = selected_entry(); + auto selected = recent.find(selected_key); if( selected == std::end(recent) ) { if( recent.empty() ) { selected_key = invalid_key; diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 249be1306..df859b08c 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -63,6 +63,37 @@ struct AISRecentEntry { } }; +class AISRecentEntries { +public: + using ContainerType = std::list; + + void on_packet(const ais::Packet& packet); + + ContainerType::const_reference front() const { + return entries.front(); + } + + ContainerType::const_iterator find(const ais::MMSI key) const; + + ContainerType::const_iterator begin() const { + return entries.begin(); + } + + ContainerType::const_iterator end() const { + return entries.end(); + } + + bool empty() const { + return entries.empty(); + } + +private: + ContainerType entries; + const size_t entries_max = 64; + + void truncate_entries(); +}; + class AISLogger { public: AISLogger(); @@ -96,15 +127,10 @@ private: bool has_focus = false; - using RecentEntries = std::list; - RecentEntries recent; + AISRecentEntries recent; void on_packet(const ais::Packet& packet); - void truncate_entries(); - - RecentEntries::iterator selected_entry(); - void advance(const int32_t amount); }; From 3df003a678b0a730fdeb21cb8ff6e81031ecc68f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 18:04:04 -0800 Subject: [PATCH 297/452] Rename AISRecentEntries::find -> find_by_mmsi. --- firmware/application/ais_app.cpp | 6 +++--- firmware/application/ais_app.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 455a33817..8d86e3391 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -151,7 +151,7 @@ void AISRecentEntries::on_packet(const ais::Packet& packet) { } } -AISRecentEntries::ContainerType::const_iterator AISRecentEntries::find(const ais::MMSI key) const { +AISRecentEntries::ContainerType::const_iterator AISRecentEntries::find_by_mmsi(const ais::MMSI key) const { return std::find_if( begin(), end(), [key](const AISRecentEntry& e) { return e.mmsi == key; } @@ -240,7 +240,7 @@ void AISView::paint(Painter& painter) { Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; const size_t visible_item_count = r.height() / s.font.line_height(); - auto selected = recent.find(selected_key); + auto selected = recent.find_by_mmsi(selected_key); if( selected == std::end(recent) ) { selected = std::begin(recent); } @@ -270,7 +270,7 @@ void AISView::paint(Painter& painter) { } void AISView::advance(const int32_t amount) { - auto selected = recent.find(selected_key); + auto selected = recent.find_by_mmsi(selected_key); if( selected == std::end(recent) ) { if( recent.empty() ) { selected_key = invalid_key; diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index df859b08c..59af0e969 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -73,7 +73,7 @@ public: return entries.front(); } - ContainerType::const_iterator find(const ais::MMSI key) const; + ContainerType::const_iterator find_by_mmsi(const ais::MMSI key) const; ContainerType::const_iterator begin() const { return entries.begin(); From af8630a6f38a81f400153fc62b2cecd06f4ff5e6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 18:04:50 -0800 Subject: [PATCH 298/452] Dedupe code, call AISRecentEntries::find_by_mmsi(). --- firmware/application/ais_app.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 8d86e3391..a2238e26d 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -101,9 +101,7 @@ void AISLogger::on_packet(const ais::Packet& packet) { void AISRecentEntries::on_packet(const ais::Packet& packet) { const auto source_id = packet.source_id(); - auto matching_recent = std::find_if(entries.begin(), entries.end(), - [source_id](const AISRecentEntry& entry) { return entry.mmsi == source_id; } - ); + auto matching_recent = find_by_mmsi(source_id); if( matching_recent != entries.end() ) { // Found within. Move to front of list, increment counter. entries.push_front(*matching_recent); From 8efeb049ca9c9f04169f25e2fc2e2a4ad28d5afc Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 18:06:45 -0800 Subject: [PATCH 299/452] Use std::begin(), std::end() where appropriate. --- firmware/application/ais_app.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index a2238e26d..0ae143186 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -102,7 +102,7 @@ void AISLogger::on_packet(const ais::Packet& packet) { void AISRecentEntries::on_packet(const ais::Packet& packet) { const auto source_id = packet.source_id(); auto matching_recent = find_by_mmsi(source_id); - if( matching_recent != entries.end() ) { + if( matching_recent != std::end(entries) ) { // Found within. Move to front of list, increment counter. entries.push_front(*matching_recent); entries.erase(matching_recent); @@ -151,7 +151,7 @@ void AISRecentEntries::on_packet(const ais::Packet& packet) { AISRecentEntries::ContainerType::const_iterator AISRecentEntries::find_by_mmsi(const ais::MMSI key) const { return std::find_if( - begin(), end(), + std::begin(entries), std::end(entries), [key](const AISRecentEntry& e) { return e.mmsi == key; } ); } From 8a30003ab64b5fd75098668441f6e188c3808fd0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 22:27:30 -0800 Subject: [PATCH 300/452] Move entry update code into AISRecentEntry. --- firmware/application/ais_app.cpp | 75 +++++++++++++++++--------------- firmware/application/ais_app.hpp | 2 + 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 0ae143186..28ef4b0de 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -99,6 +99,44 @@ void AISLogger::on_packet(const ais::Packet& packet) { } } +void AISRecentEntry::update(const ais::Packet& packet) { + received_count++; + + switch(packet.message_id()) { + case 1: + case 2: + case 3: + navigational_status = packet.read(38, 4); + last_position.timestamp = packet.received_at(); + last_position.latitude = packet.latitude(89); + last_position.longitude = packet.longitude(61); + break; + + case 4: + // packet.datetime(38) + last_position.timestamp = packet.received_at(); + last_position.latitude = packet.latitude(107); + last_position.longitude = packet.longitude(79); + break; + + case 5: + call_sign = packet.text(70, 7); + name = packet.text(112, 20); + destination = packet.text(302, 20); + break; + + case 21: + name = packet.text(43, 20); + last_position.timestamp = packet.received_at(); + last_position.latitude = packet.latitude(192); + last_position.longitude = packet.longitude(164); + break; + + default: + break; + } +} + void AISRecentEntries::on_packet(const ais::Packet& packet) { const auto source_id = packet.source_id(); auto matching_recent = find_by_mmsi(source_id); @@ -111,42 +149,7 @@ void AISRecentEntries::on_packet(const ais::Packet& packet) { truncate_entries(); } - auto& entry = entries.front(); - entry.received_count++; - - switch(packet.message_id()) { - case 1: - case 2: - case 3: - entry.navigational_status = packet.read(38, 4); - entry.last_position.timestamp = packet.received_at(); - entry.last_position.latitude = packet.latitude(89); - entry.last_position.longitude = packet.longitude(61); - break; - - case 4: - // packet.datetime(38) - entry.last_position.timestamp = packet.received_at(); - entry.last_position.latitude = packet.latitude(107); - entry.last_position.longitude = packet.longitude(79); - break; - - case 5: - entry.call_sign = packet.text(70, 7); - entry.name = packet.text(112, 20); - entry.destination = packet.text(302, 20); - break; - - case 21: - entry.name = packet.text(43, 20); - entry.last_position.timestamp = packet.received_at(); - entry.last_position.latitude = packet.latitude(192); - entry.last_position.longitude = packet.longitude(164); - break; - - default: - break; - } + entries.front().update(packet); } AISRecentEntries::ContainerType::const_iterator AISRecentEntries::find_by_mmsi(const ais::MMSI key) const { diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 59af0e969..b80ca6bd5 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -61,6 +61,8 @@ struct AISRecentEntry { navigational_status { -1 } { } + + void update(const ais::Packet& packet); }; class AISRecentEntries { From 30ca545b524c1451c91cc540f08778c30d4771f0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 23:08:22 -0800 Subject: [PATCH 301/452] Expose current SD card status. --- firmware/application/sd_card.cpp | 17 ++++++++++++----- firmware/application/sd_card.hpp | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/firmware/application/sd_card.cpp b/firmware/application/sd_card.cpp index 4e9989ab5..78f8e2870 100644 --- a/firmware/application/sd_card.cpp +++ b/firmware/application/sd_card.cpp @@ -31,6 +31,8 @@ namespace { bool card_present = false; +Status status_ { Status::NotPresent }; + FATFS fs; FRESULT mount() { @@ -50,24 +52,29 @@ void poll_inserted() { if( card_present_now != card_present ) { card_present = card_present_now; - Status status { card_present ? Status::Present : Status::NotPresent }; + Status new_status { card_present ? Status::Present : Status::NotPresent }; if( card_present ) { if( sdcConnect(&SDCD1) == CH_SUCCESS ) { if( mount() == FR_OK ) { - status = Status::Mounted; + new_status = Status::Mounted; } else { - status = Status::MountError; + new_status = Status::MountError; } } else { - status = Status::ConnectError; + new_status = Status::ConnectError; } } else { sdcDisconnect(&SDCD1); } - status_signal.emit(status); + status_ = new_status; + status_signal.emit(status_); } } +Status status() { + return status_; +} + } /* namespace sd_card */ diff --git a/firmware/application/sd_card.hpp b/firmware/application/sd_card.hpp index fef7849aa..1989f4651 100644 --- a/firmware/application/sd_card.hpp +++ b/firmware/application/sd_card.hpp @@ -40,6 +40,7 @@ enum class Status : int32_t { extern Signal status_signal; void poll_inserted(); +Status status(); } /* namespace sd_card */ From bd07e4e7e5e5a797dc161be3165b954bc6ac6dad Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 13 Jan 2016 23:11:19 -0800 Subject: [PATCH 302/452] Modify LogFile to open/close file on SD card status. Previously, would only open on construction, which was only when the receiver mode changed, which wasn't all that useful. --- firmware/application/ais_app.cpp | 4 ---- firmware/application/ais_app.hpp | 4 +--- firmware/application/ert_app.cpp | 2 -- firmware/application/ert_app.hpp | 2 +- firmware/application/log_file.cpp | 23 ++++++++++++++++++++++- firmware/application/log_file.hpp | 10 +++++++++- firmware/application/tpms_app.cpp | 2 -- firmware/application/tpms_app.hpp | 2 +- 8 files changed, 34 insertions(+), 15 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 28ef4b0de..d45004ec8 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -80,10 +80,6 @@ static std::string navigational_status(const unsigned int value) { } /* namespace format */ } /* namespace ais */ -AISLogger::AISLogger() { - log_file.open_for_append("ais.txt"); -} - void AISLogger::on_packet(const ais::Packet& packet) { // TODO: Unstuff here, not in baseband! if( log_file.is_ready() ) { diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index b80ca6bd5..7b2728951 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -98,12 +98,10 @@ private: class AISLogger { public: - AISLogger(); - void on_packet(const ais::Packet& packet); private: - LogFile log_file; + LogFile log_file { "ais.txt" }; }; namespace ui { diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index c17c2ac8e..86d637fa5 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -38,8 +38,6 @@ ERTModel::ERTModel() { .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(2500000); - - log_file.open_for_append("ert.txt"); } bool ERTModel::on_packet(const ert::Packet& packet) { diff --git a/firmware/application/ert_app.hpp b/firmware/application/ert_app.hpp index c00474e02..173093fb7 100644 --- a/firmware/application/ert_app.hpp +++ b/firmware/application/ert_app.hpp @@ -38,7 +38,7 @@ public: bool on_packet(const ert::Packet& packet); private: - LogFile log_file; + LogFile log_file { "ert.txt" }; }; namespace ui { diff --git a/firmware/application/log_file.cpp b/firmware/application/log_file.cpp index 7bcfefbbf..8cf4c3c2b 100644 --- a/firmware/application/log_file.cpp +++ b/firmware/application/log_file.cpp @@ -26,11 +26,24 @@ #include "lpc43xx_cpp.hpp" using namespace lpc43xx; +LogFile::LogFile( + const std::string file_path +) : file_path { file_path } +{ + open(); + + sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { + this->on_sd_card_status(status); + }; +} + LogFile::~LogFile() { + sd_card::status_signal -= sd_card_status_signal_token; + close(); } -bool LogFile::open_for_append(const std::string& file_path) { +bool LogFile::open() { const auto open_result = f_open(&f, file_path.c_str(), FA_WRITE | FA_OPEN_ALWAYS); if( open_result == FR_OK ) { const auto seek_result = f_lseek(&f, f_size(&f)); @@ -70,3 +83,11 @@ bool LogFile::write(const std::string& message) { const auto sync_result = f_sync(&f); return (puts_result >= 0) && (sync_result == FR_OK); } + +void LogFile::on_sd_card_status(const sd_card::Status status) { + if( status == sd_card::Status::Mounted ) { + open(); + } else { + close(); + } +} diff --git a/firmware/application/log_file.hpp b/firmware/application/log_file.hpp index 3f7024c35..c0f3138cf 100644 --- a/firmware/application/log_file.hpp +++ b/firmware/application/log_file.hpp @@ -25,24 +25,32 @@ #include #include "ff.h" +#include "sd_card.hpp" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; class LogFile { public: + LogFile(const std::string file_path); ~LogFile(); - bool open_for_append(const std::string& file_path); + bool open(); bool close(); bool is_ready(); bool write_entry(const rtc::RTC& datetime, const std::string& entry); private: + const std::string file_path; + FIL f; + SignalToken sd_card_status_signal_token; + bool write(const std::string& message); + + void on_sd_card_status(const sd_card::Status status); }; #endif/*__LOG_FILE_H__*/ diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 39af6c076..c05b62448 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -35,8 +35,6 @@ TPMSModel::TPMSModel() { .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); - - log_file.open_for_append("tpms.txt"); } ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 37fb2542b..b1417a8ff 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -35,7 +35,7 @@ public: ManchesterFormatted on_packet(const TPMSPacketMessage& message); private: - LogFile log_file; + LogFile log_file { "tpms.txt" }; }; namespace ui { From fc16bc7867746b4c8795af688acee6410860639f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 14 Jan 2016 09:19:16 -0800 Subject: [PATCH 303/452] Rename AISView to AISRecentEntriesView. Coming soon, top-layer AISAppView. --- firmware/application/ais_app.cpp | 16 ++++++++-------- firmware/application/ais_app.hpp | 6 +++--- firmware/application/ui_receiver.cpp | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index d45004ec8..58604311c 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -163,7 +163,7 @@ void AISRecentEntries::truncate_entries() { namespace ui { -AISView::AISView() { +AISRecentEntriesView::AISRecentEntriesView() { flags.focusable = true; EventDispatcher::message_map().register_handler(Message::ID::AISPacket, @@ -185,27 +185,27 @@ AISView::AISView() { receiver_model.set_baseband_bandwidth(1750000); } -AISView::~AISView() { +AISRecentEntriesView::~AISRecentEntriesView() { EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); } -void AISView::on_packet(const ais::Packet& packet) { +void AISRecentEntriesView::on_packet(const ais::Packet& packet) { recent.on_packet(packet); set_dirty(); } -void AISView::on_focus() { +void AISRecentEntriesView::on_focus() { has_focus = true; set_dirty(); } -void AISView::on_blur() { +void AISRecentEntriesView::on_blur() { has_focus = false; set_dirty(); } -bool AISView::on_encoder(const EncoderEvent event) { +bool AISRecentEntriesView::on_encoder(const EncoderEvent event) { advance(event); return true; } @@ -230,7 +230,7 @@ static void ais_list_item_draw( painter.draw_string(target_rect.pos, draw_style, line); } -void AISView::paint(Painter& painter) { +void AISRecentEntriesView::paint(Painter& painter) { const auto r = screen_rect(); const auto& s = style(); @@ -266,7 +266,7 @@ void AISView::paint(Painter& painter) { } } -void AISView::advance(const int32_t amount) { +void AISRecentEntriesView::advance(const int32_t amount) { auto selected = recent.find_by_mmsi(selected_key); if( selected == std::end(recent) ) { if( recent.empty() ) { diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 7b2728951..43e567710 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -106,10 +106,10 @@ private: namespace ui { -class AISView : public View { +class AISRecentEntriesView : public View { public: - AISView(); - ~AISView(); + AISRecentEntriesView(); + ~AISRecentEntriesView(); void paint(Painter& painter) override; diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 176673ee9..2c17edfac 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -517,7 +517,7 @@ void ReceiverView::on_modulation_changed(ReceiverModel::Mode mode) { break; case ReceiverModel::Mode::AIS: - widget_content = std::make_unique(); + widget_content = std::make_unique(); break; case ReceiverModel::Mode::SpectrumAnalysis: From 1f2b28b2b875d736e64f43e2ef95767cc3ad7554 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 14 Jan 2016 09:30:23 -0800 Subject: [PATCH 304/452] Add AISAppView. --- firmware/application/ais_app.cpp | 11 +++++++++++ firmware/application/ais_app.hpp | 10 ++++++++++ firmware/application/ui_receiver.cpp | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 58604311c..b062621fe 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -292,4 +292,15 @@ void AISRecentEntriesView::advance(const int32_t amount) { set_dirty(); } +AISAppView::AISAppView() { + add_children({ { + &recent_entries_view, + } }); +} + +void AISAppView::set_parent_rect(const Rect new_parent_rect) { + View::set_parent_rect(new_parent_rect); + recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); +} + } /* namespace ui */ diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 43e567710..4f4251717 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -134,6 +134,16 @@ private: void advance(const int32_t amount); }; +class AISAppView : public View { +public: + AISAppView(); + + void set_parent_rect(const Rect new_parent_rect) override; + +private: + AISRecentEntriesView recent_entries_view; +}; + } /* namespace ui */ #endif/*__AIS_APP_H__*/ diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 2c17edfac..20dc46b99 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -517,7 +517,7 @@ void ReceiverView::on_modulation_changed(ReceiverModel::Mode mode) { break; case ReceiverModel::Mode::AIS: - widget_content = std::make_unique(); + widget_content = std::make_unique(); break; case ReceiverModel::Mode::SpectrumAnalysis: From 6e0aa79d4458422e5912598c70833db287b6b932 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 14 Jan 2016 09:41:58 -0800 Subject: [PATCH 305/452] Move app-level config to new AISAppView class. --- firmware/application/ais_app.cpp | 60 +++++++++++++++++--------------- firmware/application/ais_app.hpp | 19 +++++----- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index b062621fe..e6b591fb7 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -163,36 +163,11 @@ void AISRecentEntries::truncate_entries() { namespace ui { -AISRecentEntriesView::AISRecentEntriesView() { +AISRecentEntriesView::AISRecentEntriesView( + AISRecentEntries& recent +) : recent { recent } +{ flags.focusable = true; - - EventDispatcher::message_map().register_handler(Message::ID::AISPacket, - [this](Message* const p) { - const auto message = static_cast(p); - const ais::Packet packet { message->packet }; - if( packet.is_valid() ) { - this->logger.on_packet(packet); - this->on_packet(packet); - } - } - ); - - receiver_model.set_baseband_configuration({ - .mode = 3, - .sampling_rate = 2457600, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); -} - -AISRecentEntriesView::~AISRecentEntriesView() { - EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); -} - -void AISRecentEntriesView::on_packet(const ais::Packet& packet) { - recent.on_packet(packet); - - set_dirty(); } void AISRecentEntriesView::on_focus() { @@ -296,6 +271,27 @@ AISAppView::AISAppView() { add_children({ { &recent_entries_view, } }); + + EventDispatcher::message_map().register_handler(Message::ID::AISPacket, + [this](Message* const p) { + const auto message = static_cast(p); + const ais::Packet packet { message->packet }; + if( packet.is_valid() ) { + this->on_packet(packet); + } + } + ); + + receiver_model.set_baseband_configuration({ + .mode = 3, + .sampling_rate = 2457600, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); +} + +AISAppView::~AISAppView() { + EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); } void AISAppView::set_parent_rect(const Rect new_parent_rect) { @@ -303,4 +299,10 @@ void AISAppView::set_parent_rect(const Rect new_parent_rect) { recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); } +void AISAppView::on_packet(const ais::Packet& packet) { + logger.on_packet(packet); + recent.on_packet(packet); + recent_entries_view.set_dirty(); +} + } /* namespace ui */ diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 4f4251717..4c4159f3a 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -108,8 +108,7 @@ namespace ui { class AISRecentEntriesView : public View { public: - AISRecentEntriesView(); - ~AISRecentEntriesView(); + AISRecentEntriesView(AISRecentEntries& recent); void paint(Painter& painter) override; @@ -119,29 +118,31 @@ public: bool on_encoder(const EncoderEvent event) override; private: - AISLogger logger; - + AISRecentEntries& recent; + using EntryKey = ais::MMSI; EntryKey selected_key; const EntryKey invalid_key = 0xffffffff; bool has_focus = false; - AISRecentEntries recent; - - void on_packet(const ais::Packet& packet); - void advance(const int32_t amount); }; class AISAppView : public View { public: AISAppView(); + ~AISAppView(); void set_parent_rect(const Rect new_parent_rect) override; private: - AISRecentEntriesView recent_entries_view; + AISRecentEntries recent; + AISLogger logger; + + AISRecentEntriesView recent_entries_view { recent }; + + void on_packet(const ais::Packet& packet); }; } /* namespace ui */ From 9fd93b0af6de505061c59bc30ce84206bb8ed6cd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 14 Jan 2016 09:45:29 -0800 Subject: [PATCH 306/452] Remove redundant focus tracking code. --- firmware/application/ais_app.cpp | 12 +----------- firmware/application/ais_app.hpp | 5 ----- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index e6b591fb7..e69c6a007 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -170,16 +170,6 @@ AISRecentEntriesView::AISRecentEntriesView( flags.focusable = true; } -void AISRecentEntriesView::on_focus() { - has_focus = true; - set_dirty(); -} - -void AISRecentEntriesView::on_blur() { - has_focus = false; - set_dirty(); -} - bool AISRecentEntriesView::on_encoder(const EncoderEvent event) { advance(event); return true; @@ -236,7 +226,7 @@ void AISRecentEntriesView::paint(Painter& painter) { for(auto p = start; p != end; p++) { const auto& entry = *p; const auto is_selected_key = (selected_key == entry.mmsi); - ais_list_item_draw(entry, target_rect, painter, s, (has_focus && is_selected_key)); + ais_list_item_draw(entry, target_rect, painter, s, (has_focus() && is_selected_key)); target_rect.pos.y += target_rect.height(); } } diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 4c4159f3a..e40848e0f 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -112,9 +112,6 @@ public: void paint(Painter& painter) override; - void on_focus() override; - void on_blur() override; - bool on_encoder(const EncoderEvent event) override; private: @@ -124,8 +121,6 @@ private: EntryKey selected_key; const EntryKey invalid_key = 0xffffffff; - bool has_focus = false; - void advance(const int32_t amount); }; From f8d9cb318d71e33da3b319ba901bfdc59ba635d6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 14 Jan 2016 09:56:06 -0800 Subject: [PATCH 307/452] Prevent AISAppView painting. View is always filled with children, no need to clear background before painting children. --- firmware/application/ais_app.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index e40848e0f..162d06d69 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -131,6 +131,10 @@ public: void set_parent_rect(const Rect new_parent_rect) override; + // Prevent painting of region covered entirely by a child. + // TODO: Add flag to View that specifies view does not need to be cleared before painting. + void paint(Painter&) override { }; + private: AISRecentEntries recent; AISLogger logger; From b1707298b7c629143607a641c4a0b5b1c9028fe5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 14 Jan 2016 11:49:19 -0800 Subject: [PATCH 308/452] Extract weird range-of-entries algorithm out of view. --- firmware/application/ais_app.cpp | 40 +++++++++++++++++++------------- firmware/application/ais_app.hpp | 7 +++++- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index e69c6a007..83e8fc0aa 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -161,6 +161,28 @@ void AISRecentEntries::truncate_entries() { } } +AISRecentEntries::RangeType AISRecentEntries::range_around( + ContainerType::const_iterator item, const size_t count +) const { + auto start = item; + auto end = item; + size_t i = 0; + + // Move start iterator toward first entry. + while( (start != std::begin(entries)) && (i < count / 2) ) { + std::advance(start, -1); + i++; + } + + // Move end iterator toward last entry. + while( (end != std::end(entries)) && (i < count) ) { + std::advance(end, 1); + i++; + } + + return { start, end }; +} + namespace ui { AISRecentEntriesView::AISRecentEntriesView( @@ -207,23 +229,9 @@ void AISRecentEntriesView::paint(Painter& painter) { selected = std::begin(recent); } - auto start = selected; - auto end = selected; - size_t i = 0; + auto range = recent.range_around(selected, visible_item_count); - // Move start iterator toward first entry. - while( (start != std::begin(recent)) && (i < visible_item_count / 2) ) { - std::advance(start, -1); - i++; - } - - // Move end iterator toward last entry. - while( (end != std::end(recent)) && (i < visible_item_count) ) { - std::advance(end, 1); - i++; - } - - for(auto p = start; p != end; p++) { + for(auto p = range.first; p != range.second; p++) { const auto& entry = *p; const auto is_selected_key = (selected_key == entry.mmsi); ais_list_item_draw(entry, target_rect, painter, s, (has_focus() && is_selected_key)); diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 162d06d69..31f890a42 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -68,7 +68,8 @@ struct AISRecentEntry { class AISRecentEntries { public: using ContainerType = std::list; - + using RangeType = std::pair; + void on_packet(const ais::Packet& packet); ContainerType::const_reference front() const { @@ -89,6 +90,10 @@ public: return entries.empty(); } + RangeType range_around( + ContainerType::const_iterator, const size_t count + ) const; + private: ContainerType entries; const size_t entries_max = 64; From aa249cbad479f07a85cf760d69374c2be240ea82 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 14 Jan 2016 22:39:58 -0800 Subject: [PATCH 309/452] Add AIS detail view. --- firmware/application/ais_app.cpp | 57 ++++++++++++++++++++++++++++++++ firmware/application/ais_app.hpp | 30 +++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 83e8fc0aa..d56e894a5 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -197,6 +197,19 @@ bool AISRecentEntriesView::on_encoder(const EncoderEvent event) { return true; } +bool AISRecentEntriesView::on_key(const ui::KeyEvent event) { + if( event == ui::KeyEvent::Select ) { + if( on_select ) { + const auto selected = recent.find_by_mmsi(selected_key); + if( selected != std::end(recent) ) { + on_select(*selected); + return true; + } + } + } + return false; +} + static void ais_list_item_draw( const AISRecentEntry& entry, const Rect& target_rect, @@ -265,11 +278,34 @@ void AISRecentEntriesView::advance(const int32_t amount) { set_dirty(); } +AISRecentEntryDetailView::AISRecentEntryDetailView() { + add_children({ { + &button_done, + } }); + + button_done.on_select = [this](const ui::Button&) { + if( this->on_close ) { + this->on_close(); + } + }; +} + +void AISRecentEntryDetailView::focus() { + button_done.focus(); +} + +void AISRecentEntryDetailView::set_entry(const AISRecentEntry& new_entry) { + entry = new_entry; +} + AISAppView::AISAppView() { add_children({ { &recent_entries_view, + &recent_entry_detail_view, } }); + recent_entry_detail_view.hidden(true); + EventDispatcher::message_map().register_handler(Message::ID::AISPacket, [this](Message* const p) { const auto message = static_cast(p); @@ -286,6 +322,13 @@ AISAppView::AISAppView() { .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); + + recent_entries_view.on_select = [this](const AISRecentEntry& entry) { + this->on_show_detail(entry); + }; + recent_entry_detail_view.on_close = [this]() { + this->on_show_list(); + }; } AISAppView::~AISAppView() { @@ -295,6 +338,7 @@ AISAppView::~AISAppView() { void AISAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); + recent_entry_detail_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); } void AISAppView::on_packet(const ais::Packet& packet) { @@ -303,4 +347,17 @@ void AISAppView::on_packet(const ais::Packet& packet) { recent_entries_view.set_dirty(); } +void AISAppView::on_show_list() { + recent_entries_view.hidden(false); + recent_entry_detail_view.hidden(true); + recent_entries_view.focus(); +} + +void AISAppView::on_show_detail(const AISRecentEntry& entry) { + recent_entries_view.hidden(true); + recent_entry_detail_view.hidden(false); + recent_entry_detail_view.set_entry(entry); + recent_entry_detail_view.focus(); +} + } /* namespace ui */ diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 31f890a42..e9d8df92b 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -53,6 +53,11 @@ struct AISRecentEntry { size_t received_count; int8_t navigational_status; + AISRecentEntry( + ) : AISRecentEntry { 0 } + { + } + AISRecentEntry( const ais::MMSI& mmsi ) : mmsi { mmsi }, @@ -113,11 +118,14 @@ namespace ui { class AISRecentEntriesView : public View { public: + std::function on_select; + AISRecentEntriesView(AISRecentEntries& recent); void paint(Painter& painter) override; bool on_encoder(const EncoderEvent event) override; + bool on_key(const ui::KeyEvent event) override; private: AISRecentEntries& recent; @@ -129,6 +137,25 @@ private: void advance(const int32_t amount); }; +class AISRecentEntryDetailView : public View { +public: + std::function on_close; + + AISRecentEntryDetailView(); + + void set_entry(const AISRecentEntry& new_entry); + + void focus() override; + +private: + AISRecentEntry entry; + + Button button_done { + { 72, 192, 96, 24 }, + "Done" + }; +}; + class AISAppView : public View { public: AISAppView(); @@ -145,8 +172,11 @@ private: AISLogger logger; AISRecentEntriesView recent_entries_view { recent }; + AISRecentEntryDetailView recent_entry_detail_view; void on_packet(const ais::Packet& packet); + void on_show_list(); + void on_show_detail(const AISRecentEntry& entry); }; } /* namespace ui */ From 089ef25df99c57c94fa856ec964cfb8cebd71cbe Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 11:23:28 -0800 Subject: [PATCH 310/452] Draw AIS entry details. --- firmware/application/ais_app.cpp | 36 ++++++++++++++++++++++++++++++++ firmware/application/ais_app.hpp | 9 ++++++++ 2 files changed, 45 insertions(+) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index d56e894a5..13abac8e0 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -294,6 +294,42 @@ void AISRecentEntryDetailView::focus() { button_done.focus(); } +Rect AISRecentEntryDetailView::draw_field( + Painter& painter, + const Rect& draw_rect, + const Style& style, + const std::string& label, + const std::string& value +) { + const size_t label_length_max = 4; + + painter.draw_string(Point { draw_rect.left(), draw_rect.top() }, style, label); + + const auto length = value.length(); + painter.draw_string(Point { draw_rect.left() + (label_length_max + 1) * 8, draw_rect.top() }, style, value); + + return { draw_rect.left(), draw_rect.top() + draw_rect.height(), draw_rect.width(), draw_rect.height() }; +} + +void AISRecentEntryDetailView::paint(Painter& painter) { + View::paint(painter); + + const auto s = style(); + const auto rect = screen_rect(); + + auto field_rect = Rect { rect.left(), rect.top() + 16, rect.width(), 16 }; + + const size_t mmsi_length = 9; + field_rect = draw_field(painter, field_rect, s, "MMSI", to_string_dec_int(entry.mmsi, mmsi_length)); + field_rect = draw_field(painter, field_rect, s, "Name", entry.name); + field_rect = draw_field(painter, field_rect, s, "Call", entry.call_sign); + field_rect = draw_field(painter, field_rect, s, "Dest", entry.destination); + field_rect = draw_field(painter, field_rect, s, "Lat ", ais::format::latlon_normalized(entry.last_position.latitude) + "N"); + field_rect = draw_field(painter, field_rect, s, "Lon ", ais::format::latlon_normalized(entry.last_position.longitude) + "E"); + field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry.navigational_status)); + field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry.received_count, 10)); +} + void AISRecentEntryDetailView::set_entry(const AISRecentEntry& new_entry) { entry = new_entry; } diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index e9d8df92b..9c8ebe08d 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -146,6 +146,7 @@ public: void set_entry(const AISRecentEntry& new_entry); void focus() override; + void paint(Painter&) override; private: AISRecentEntry entry; @@ -154,6 +155,14 @@ private: { 72, 192, 96, 24 }, "Done" }; + + Rect draw_field( + Painter& painter, + const Rect& draw_rect, + const Style& style, + const std::string& label, + const std::string& value + ); }; class AISAppView : public View { From 19e3b273ad755c71553623da13497b9fa7d58d00 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 11:37:37 -0800 Subject: [PATCH 311/452] Expose current RecentEntry from detail view. --- firmware/application/ais_app.cpp | 20 ++++++++++---------- firmware/application/ais_app.hpp | 3 ++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 13abac8e0..3eae505b7 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -320,18 +320,18 @@ void AISRecentEntryDetailView::paint(Painter& painter) { auto field_rect = Rect { rect.left(), rect.top() + 16, rect.width(), 16 }; const size_t mmsi_length = 9; - field_rect = draw_field(painter, field_rect, s, "MMSI", to_string_dec_int(entry.mmsi, mmsi_length)); - field_rect = draw_field(painter, field_rect, s, "Name", entry.name); - field_rect = draw_field(painter, field_rect, s, "Call", entry.call_sign); - field_rect = draw_field(painter, field_rect, s, "Dest", entry.destination); - field_rect = draw_field(painter, field_rect, s, "Lat ", ais::format::latlon_normalized(entry.last_position.latitude) + "N"); - field_rect = draw_field(painter, field_rect, s, "Lon ", ais::format::latlon_normalized(entry.last_position.longitude) + "E"); - field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry.navigational_status)); - field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry.received_count, 10)); + field_rect = draw_field(painter, field_rect, s, "MMSI", to_string_dec_int(entry_.mmsi, mmsi_length)); + field_rect = draw_field(painter, field_rect, s, "Name", entry_.name); + field_rect = draw_field(painter, field_rect, s, "Call", entry_.call_sign); + field_rect = draw_field(painter, field_rect, s, "Dest", entry_.destination); + field_rect = draw_field(painter, field_rect, s, "Lat ", ais::format::latlon_normalized(entry_.last_position.latitude) + "N"); + field_rect = draw_field(painter, field_rect, s, "Lon ", ais::format::latlon_normalized(entry_.last_position.longitude) + "E"); + field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry_.navigational_status)); + field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry_.received_count, 10)); } -void AISRecentEntryDetailView::set_entry(const AISRecentEntry& new_entry) { - entry = new_entry; +void AISRecentEntryDetailView::set_entry(const AISRecentEntry& entry) { + entry_ = entry; } AISAppView::AISAppView() { diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 9c8ebe08d..8c0237ac8 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -144,12 +144,13 @@ public: AISRecentEntryDetailView(); void set_entry(const AISRecentEntry& new_entry); + const AISRecentEntry& entry() const { return entry_; }; void focus() override; void paint(Painter&) override; private: - AISRecentEntry entry; + AISRecentEntry entry_; Button button_done { { 72, 192, 96, 24 }, From c4f7d9bf5417af4b620f3a41ec3c0cf22335fac6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 11:38:09 -0800 Subject: [PATCH 312/452] Return updated AIS RecentEntry. --- firmware/application/ais_app.cpp | 7 +++++-- firmware/application/ais_app.hpp | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 3eae505b7..9f90012b0 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -133,7 +133,7 @@ void AISRecentEntry::update(const ais::Packet& packet) { } } -void AISRecentEntries::on_packet(const ais::Packet& packet) { +const AISRecentEntry& AISRecentEntries::on_packet(const ais::Packet& packet) { const auto source_id = packet.source_id(); auto matching_recent = find_by_mmsi(source_id); if( matching_recent != std::end(entries) ) { @@ -145,7 +145,10 @@ void AISRecentEntries::on_packet(const ais::Packet& packet) { truncate_entries(); } - entries.front().update(packet); + auto& entry = entries.front(); + entry.update(packet); + + return entry; } AISRecentEntries::ContainerType::const_iterator AISRecentEntries::find_by_mmsi(const ais::MMSI key) const { diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 8c0237ac8..4e5fe55e5 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -75,7 +75,7 @@ public: using ContainerType = std::list; using RangeType = std::pair; - void on_packet(const ais::Packet& packet); + const AISRecentEntry& on_packet(const ais::Packet& packet); ContainerType::const_reference front() const { return entries.front(); From e163ed7463e93e87ea46c50779b1c729fdfe9ce3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 11:38:49 -0800 Subject: [PATCH 313/452] Update recent entry detail when recent entry changes. This doesn't feel like the right implementation, but I'm feeling impatient today... --- firmware/application/ais_app.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 9f90012b0..8c1da60bf 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -382,8 +382,13 @@ void AISAppView::set_parent_rect(const Rect new_parent_rect) { void AISAppView::on_packet(const ais::Packet& packet) { logger.on_packet(packet); - recent.on_packet(packet); + const auto updated_entry = recent.on_packet(packet); recent_entries_view.set_dirty(); + + // TODO: Crude hack, should be a more formal listener arrangement... + if( updated_entry.mmsi == recent_entry_detail_view.entry().mmsi ) { + recent_entry_detail_view.set_entry(updated_entry); + } } void AISAppView::on_show_list() { From f292d5038a91fb81200857a22d8ead213375ba35 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 11:39:39 -0800 Subject: [PATCH 314/452] Set AISRecentEntryDetailView dirty when entry changes. --- firmware/application/ais_app.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 8c1da60bf..8c8aa3295 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -335,6 +335,7 @@ void AISRecentEntryDetailView::paint(Painter& painter) { void AISRecentEntryDetailView::set_entry(const AISRecentEntry& entry) { entry_ = entry; + set_dirty(); } AISAppView::AISAppView() { From 8603c567cac2aac042b7f367b07a3ca839169ccd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 13:25:17 -0800 Subject: [PATCH 315/452] Unjustify AIS RX packet count. --- firmware/application/ais_app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 8c8aa3295..1ddc3b9ce 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -330,7 +330,7 @@ void AISRecentEntryDetailView::paint(Painter& painter) { field_rect = draw_field(painter, field_rect, s, "Lat ", ais::format::latlon_normalized(entry_.last_position.latitude) + "N"); field_rect = draw_field(painter, field_rect, s, "Lon ", ais::format::latlon_normalized(entry_.last_position.longitude) + "E"); field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry_.navigational_status)); - field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry_.received_count, 10)); + field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry_.received_count)); } void AISRecentEntryDetailView::set_entry(const AISRecentEntry& entry) { From 70d349e1a730594fe5dad51b89bb57455a2610c2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 13:39:40 -0800 Subject: [PATCH 316/452] Change default AIS navigational status to "unknown". --- firmware/application/ais_app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 1ddc3b9ce..d33a92b33 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -73,7 +73,7 @@ static std::string navigational_status(const unsigned int value) { case 12: return "towing ahead/along"; case 14: return "SART/MOB/EPIRB"; case 15: return "undefined"; - default: return "unexpected"; + default: return "unknown"; } } From 1e92d416c7703f49a880e5dc7832d64b134819f1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 14:24:31 -0800 Subject: [PATCH 317/452] More AIS position report detail. --- firmware/application/ais_app.cpp | 56 ++++++++++++++++++++++++++++++++ firmware/application/ais_app.hpp | 4 +++ firmware/common/ais_packet.hpp | 4 +++ 3 files changed, 64 insertions(+) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index d33a92b33..19aa6ceac 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -77,6 +77,54 @@ static std::string navigational_status(const unsigned int value) { } } +static std::string rate_of_turn(const RateOfTurn value) { + switch(value) { + case -128: return "not available"; + case -127: return "left >5 deg/30sec"; + case 0: return "0 deg/min"; + case 127: return "right >5 deg/30sec"; + default: + { + std::string result = (value < 0) ? "left " : "right "; + const float value_deg_sqrt = value / 4.733f; + const int32_t value_deg = value_deg_sqrt * value_deg_sqrt; + result += to_string_dec_uint(value_deg); + result += " deg/min"; + return result; + } + } +} + +static std::string speed_over_ground(const SpeedOverGround value) { + if( value == 1023 ) { + return "not available"; + } else if( value == 1022 ) { + return ">= 102.2 knots"; + } else { + return to_string_dec_uint(value / 10) + "." + to_string_dec_uint(value % 10, 1) + " knots"; + } +} + +static std::string course_over_ground(const CourseOverGround value) { + if( value > 3600 ) { + return "invalid"; + } else if( value == 3600 ) { + return "not available"; + } else { + return to_string_dec_uint(value / 10) + "." + to_string_dec_uint(value % 10, 1) + " deg"; + } +} + +static std::string true_heading(const TrueHeading value) { + if( value == 511 ) { + return "not available"; + } else if( value > 359 ) { + return "invalid"; + } else { + return to_string_dec_uint(value) + " deg"; + } +} + } /* namespace format */ } /* namespace ais */ @@ -103,9 +151,13 @@ void AISRecentEntry::update(const ais::Packet& packet) { case 2: case 3: navigational_status = packet.read(38, 4); + last_position.rate_of_turn = packet.read(42, 8); + last_position.speed_over_ground = packet.read(50, 10); last_position.timestamp = packet.received_at(); last_position.latitude = packet.latitude(89); last_position.longitude = packet.longitude(61); + last_position.course_over_ground = packet.read(116, 12); + last_position.true_heading = packet.read(128, 9); break; case 4: @@ -331,6 +383,10 @@ void AISRecentEntryDetailView::paint(Painter& painter) { field_rect = draw_field(painter, field_rect, s, "Lon ", ais::format::latlon_normalized(entry_.last_position.longitude) + "E"); field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry_.navigational_status)); field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry_.received_count)); + field_rect = draw_field(painter, field_rect, s, "RoT ", ais::format::rate_of_turn(entry_.last_position.rate_of_turn)); + field_rect = draw_field(painter, field_rect, s, "SoG ", ais::format::speed_over_ground(entry_.last_position.speed_over_ground)); + field_rect = draw_field(painter, field_rect, s, "CoG ", ais::format::course_over_ground(entry_.last_position.course_over_ground)); + field_rect = draw_field(painter, field_rect, s, "Head", ais::format::true_heading(entry_.last_position.true_heading)); } void AISRecentEntryDetailView::set_entry(const AISRecentEntry& entry) { diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 4e5fe55e5..31576f2d5 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -42,6 +42,10 @@ struct AISPosition { rtc::RTC timestamp { }; ais::Latitude latitude { 0 }; ais::Longitude longitude { 0 }; + ais::RateOfTurn rate_of_turn { -128 }; + ais::SpeedOverGround speed_over_ground { 1023 }; + ais::CourseOverGround course_over_ground { 3600 }; + ais::TrueHeading true_heading { 511 }; }; struct AISRecentEntry { diff --git a/firmware/common/ais_packet.hpp b/firmware/common/ais_packet.hpp index 90e80873f..bb0fda4c8 100644 --- a/firmware/common/ais_packet.hpp +++ b/firmware/common/ais_packet.hpp @@ -42,6 +42,10 @@ struct DateTime { using Latitude = int32_t; using Longitude = int32_t; +using RateOfTurn = int8_t; +using SpeedOverGround = uint16_t; +using CourseOverGround = uint16_t; +using TrueHeading = uint16_t; using MMSI = uint32_t; From f3989050e8265c1330524bb652d261ee478ec831 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 15:25:32 -0800 Subject: [PATCH 318/452] Clean up AIS lat/lon types and formatting. --- firmware/application/ais_app.cpp | 37 ++++++++++++++++++----- firmware/application/ais_app.hpp | 4 +-- firmware/common/ais_packet.cpp | 4 +-- firmware/common/ais_packet.hpp | 50 ++++++++++++++++++++++++++++++-- 4 files changed, 82 insertions(+), 13 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 19aa6ceac..f88ba79e9 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -33,11 +33,34 @@ using namespace portapack; namespace ais { namespace format { -static std::string latlon_normalized(const int32_t normalized) { - const int32_t t = (normalized * 5) / 3; - const int32_t degrees = t / (100 * 10000); - const int32_t fraction = std::abs(t) % (100 * 10000); - return to_string_dec_int(degrees) + "." + to_string_dec_int(fraction, 6, '0'); +static std::string latlon_abs_normalized(const int32_t normalized) { + const uint32_t normalized_abs = std::abs(normalized); + const uint32_t t = (normalized_abs * 5) / 3; + const uint32_t degrees = t / (100 * 10000); + const uint32_t fraction = t % (100 * 10000); + return to_string_dec_uint(degrees) + "." + to_string_dec_uint(fraction, 6, '0'); +} + +static std::string latitude(const Latitude value) { + if( value.is_not_available() ) { + return "not available"; + } else if( value.is_valid() ) { + const auto normalized = value.normalized(); + return latlon_abs_normalized(normalized) + ((normalized < 0) ? "S" : "N"); + } else { + return "invalid"; + } +} + +static std::string longitude(const Longitude value) { + if( value.is_not_available() ) { + return "not available"; + } else if( value.is_valid() ) { + const auto normalized = value.normalized(); + return latlon_abs_normalized(normalized) + ((normalized < 0) ? "W" : "E"); + } else { + return "invalid"; + } } static std::string mmsi( @@ -379,8 +402,8 @@ void AISRecentEntryDetailView::paint(Painter& painter) { field_rect = draw_field(painter, field_rect, s, "Name", entry_.name); field_rect = draw_field(painter, field_rect, s, "Call", entry_.call_sign); field_rect = draw_field(painter, field_rect, s, "Dest", entry_.destination); - field_rect = draw_field(painter, field_rect, s, "Lat ", ais::format::latlon_normalized(entry_.last_position.latitude) + "N"); - field_rect = draw_field(painter, field_rect, s, "Lon ", ais::format::latlon_normalized(entry_.last_position.longitude) + "E"); + field_rect = draw_field(painter, field_rect, s, "Lat ", ais::format::latitude(entry_.last_position.latitude)); + field_rect = draw_field(painter, field_rect, s, "Lon ", ais::format::longitude(entry_.last_position.longitude)); field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry_.navigational_status)); field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry_.received_count)); field_rect = draw_field(painter, field_rect, s, "RoT ", ais::format::rate_of_turn(entry_.last_position.rate_of_turn)); diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 31576f2d5..ee7d991f8 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -40,8 +40,8 @@ using namespace lpc43xx; struct AISPosition { rtc::RTC timestamp { }; - ais::Latitude latitude { 0 }; - ais::Longitude longitude { 0 }; + ais::Latitude latitude; + ais::Longitude longitude; ais::RateOfTurn rate_of_turn { -128 }; ais::SpeedOverGround speed_over_ground { 1023 }; ais::CourseOverGround course_over_ground { 3600 }; diff --git a/firmware/common/ais_packet.cpp b/firmware/common/ais_packet.cpp index 9dcf76588..dcd7cddd9 100644 --- a/firmware/common/ais_packet.cpp +++ b/firmware/common/ais_packet.cpp @@ -178,13 +178,13 @@ DateTime Packet::datetime(const size_t start_bit) const { Latitude Packet::latitude(const size_t start_bit) const { // Shifting and dividing is to sign-extend the source field. // TODO: There's probably a more elegant way to do it. - return static_cast(field_.read(start_bit, 27) << 5) / 32; + return field_.read(start_bit, 27); } Longitude Packet::longitude(const size_t start_bit) const { // Shifting and dividing is to sign-extend the source field. // TODO: There's probably a more elegant way to do it. - return static_cast(field_.read(start_bit, 28) << 4) / 16; + return field_.read(start_bit, 28); } bool Packet::crc_ok() const { diff --git a/firmware/common/ais_packet.hpp b/firmware/common/ais_packet.hpp index bb0fda4c8..47bf902ef 100644 --- a/firmware/common/ais_packet.hpp +++ b/firmware/common/ais_packet.hpp @@ -40,8 +40,54 @@ struct DateTime { uint8_t second; }; -using Latitude = int32_t; -using Longitude = int32_t; +template +struct LatLonBase { + constexpr LatLonBase( + ) : LatLonBase { raw_not_available } + { + } + + constexpr LatLonBase( + const int32_t raw + ) : raw_ { raw } + { + } + + constexpr LatLonBase( + const LatLonBase& other + ) : raw_ { other.raw_ } + { + } + + int32_t normalized() const { + return static_cast(raw() << sign_extend_shift) / (1 << sign_extend_shift); + } + + int32_t raw() const { + return raw_; + } + + bool is_not_available() const { + return raw() == raw_not_available; + } + + bool is_valid() const { + return (normalized() >= raw_valid_min) && (normalized() <= raw_valid_max); + } + +private: + int32_t raw_; + + static constexpr size_t sign_extend_shift = 32 - FieldSize; + + static constexpr int32_t raw_not_available = NAValue; + static constexpr int32_t raw_valid_min = -DegMax * 60 * 10000; + static constexpr int32_t raw_valid_max = DegMax * 60 * 10000; +}; + +using Latitude = LatLonBase<27, 90, 0x3412140>; +using Longitude = LatLonBase<28, 180, 0x6791AC0>; + using RateOfTurn = int8_t; using SpeedOverGround = uint16_t; using CourseOverGround = uint16_t; From 5ddb99237e90cfa22ab9a852bf01bea12869fb4f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 15:26:04 -0800 Subject: [PATCH 319/452] Move AIS entry details "done" button down a bit. --- firmware/application/ais_app.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index ee7d991f8..3b5e3d2e6 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -157,7 +157,7 @@ private: AISRecentEntry entry_; Button button_done { - { 72, 192, 96, 24 }, + { 72, 216, 96, 24 }, "Done" }; From 8fa8a26298d0aa4751f45064506fbf9c989a9b1b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 15:31:32 -0800 Subject: [PATCH 320/452] Read SD card status in SDCardStatusView constructor. View was not showing correct status if card was present at boot. --- firmware/application/ui_sd_card_status_view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ui_sd_card_status_view.cpp b/firmware/application/ui_sd_card_status_view.cpp index 1c7698539..d790a7603 100644 --- a/firmware/application/ui_sd_card_status_view.cpp +++ b/firmware/application/ui_sd_card_status_view.cpp @@ -33,7 +33,7 @@ SDCardStatusView::SDCardStatusView() { &text_status, } }); - text_status.set("XX"); + on_status(sd_card::status()); } void SDCardStatusView::on_show() { From cb5f563b92c5a58c5b7427491b3fbc219b5b9f94 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 15:59:04 -0800 Subject: [PATCH 321/452] Push more common AIS lat/lon formatting into common function. --- firmware/application/ais_app.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index f88ba79e9..2c5d817d9 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -33,12 +33,13 @@ using namespace portapack; namespace ais { namespace format { -static std::string latlon_abs_normalized(const int32_t normalized) { +static std::string latlon_abs_normalized(const int32_t normalized, const char suffixes[2]) { + const auto suffix = suffixes[(normalized < 0) ? 0 : 1]; const uint32_t normalized_abs = std::abs(normalized); const uint32_t t = (normalized_abs * 5) / 3; const uint32_t degrees = t / (100 * 10000); const uint32_t fraction = t % (100 * 10000); - return to_string_dec_uint(degrees) + "." + to_string_dec_uint(fraction, 6, '0'); + return to_string_dec_uint(degrees) + "." + to_string_dec_uint(fraction, 6, '0') + suffix; } static std::string latitude(const Latitude value) { @@ -46,7 +47,7 @@ static std::string latitude(const Latitude value) { return "not available"; } else if( value.is_valid() ) { const auto normalized = value.normalized(); - return latlon_abs_normalized(normalized) + ((normalized < 0) ? "S" : "N"); + return latlon_abs_normalized(normalized, "SN"); } else { return "invalid"; } @@ -57,7 +58,7 @@ static std::string longitude(const Longitude value) { return "not available"; } else if( value.is_valid() ) { const auto normalized = value.normalized(); - return latlon_abs_normalized(normalized) + ((normalized < 0) ? "W" : "E"); + return latlon_abs_normalized(normalized, "WE"); } else { return "invalid"; } From 8fd8815e95cb1c518d2d0593e592cda4f1595b37 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 16:00:21 -0800 Subject: [PATCH 322/452] Remove irrelevant comments. --- firmware/application/ais_app.cpp | 1 - firmware/common/ais_packet.cpp | 4 ---- 2 files changed, 5 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 2c5d817d9..cf2669ddc 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -185,7 +185,6 @@ void AISRecentEntry::update(const ais::Packet& packet) { break; case 4: - // packet.datetime(38) last_position.timestamp = packet.received_at(); last_position.latitude = packet.latitude(107); last_position.longitude = packet.longitude(79); diff --git a/firmware/common/ais_packet.cpp b/firmware/common/ais_packet.cpp index dcd7cddd9..53159ff21 100644 --- a/firmware/common/ais_packet.cpp +++ b/firmware/common/ais_packet.cpp @@ -176,14 +176,10 @@ DateTime Packet::datetime(const size_t start_bit) const { } Latitude Packet::latitude(const size_t start_bit) const { - // Shifting and dividing is to sign-extend the source field. - // TODO: There's probably a more elegant way to do it. return field_.read(start_bit, 27); } Longitude Packet::longitude(const size_t start_bit) const { - // Shifting and dividing is to sign-extend the source field. - // TODO: There's probably a more elegant way to do it. return field_.read(start_bit, 28); } From b5ac76afc4bdded6f3949613ae5d6068dc633db6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 17:58:27 -0800 Subject: [PATCH 323/452] Tiny code clean-up. --- firmware/application/ais_app.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index cf2669ddc..82c3f06f2 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -46,8 +46,7 @@ static std::string latitude(const Latitude value) { if( value.is_not_available() ) { return "not available"; } else if( value.is_valid() ) { - const auto normalized = value.normalized(); - return latlon_abs_normalized(normalized, "SN"); + return latlon_abs_normalized(value.normalized(), "SN"); } else { return "invalid"; } @@ -57,8 +56,7 @@ static std::string longitude(const Longitude value) { if( value.is_not_available() ) { return "not available"; } else if( value.is_valid() ) { - const auto normalized = value.normalized(); - return latlon_abs_normalized(normalized, "WE"); + return latlon_abs_normalized(value.normalized(), "WE"); } else { return "invalid"; } From de98dfe10be7d1e465b8bc02c89afa922afe8c1f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 17:59:02 -0800 Subject: [PATCH 324/452] AUS consolidated lat/lon formatting. --- firmware/application/ais_app.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 82c3f06f2..ae20f25a0 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -62,6 +62,16 @@ static std::string longitude(const Longitude value) { } } +static std::string latlon(const Latitude latitude, const Longitude longitude) { + if( latitude.is_valid() && longitude.is_valid() ) { + return latlon_abs_normalized(latitude.normalized(), "SN") + " " + latlon_abs_normalized(longitude.normalized(), "WE"); + } else if( latitude.is_not_available() && longitude.is_not_available() ) { + return "not available"; + } else { + return "invalid"; + } +} + static std::string mmsi( const ais::MMSI& mmsi ) { @@ -400,8 +410,7 @@ void AISRecentEntryDetailView::paint(Painter& painter) { field_rect = draw_field(painter, field_rect, s, "Name", entry_.name); field_rect = draw_field(painter, field_rect, s, "Call", entry_.call_sign); field_rect = draw_field(painter, field_rect, s, "Dest", entry_.destination); - field_rect = draw_field(painter, field_rect, s, "Lat ", ais::format::latitude(entry_.last_position.latitude)); - field_rect = draw_field(painter, field_rect, s, "Lon ", ais::format::longitude(entry_.last_position.longitude)); + field_rect = draw_field(painter, field_rect, s, "Pos ", ais::format::latlon(entry_.last_position.latitude, entry_.last_position.longitude)); field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry_.navigational_status)); field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry_.received_count)); field_rect = draw_field(painter, field_rect, s, "RoT ", ais::format::rate_of_turn(entry_.last_position.rate_of_turn)); From 6ead63d02dce9dbeb130c96e2c513c0195a4edef Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 18:15:05 -0800 Subject: [PATCH 325/452] Extract timestamp formatting to string_format. --- firmware/application/log_file.cpp | 9 +-------- firmware/application/string_format.cpp | 8 ++++++++ firmware/application/string_format.hpp | 6 ++++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/firmware/application/log_file.cpp b/firmware/application/log_file.cpp index 8cf4c3c2b..43528aa4a 100644 --- a/firmware/application/log_file.cpp +++ b/firmware/application/log_file.cpp @@ -67,14 +67,7 @@ bool LogFile::is_ready() { } bool LogFile::write_entry(const rtc::RTC& datetime, const std::string& entry) { - std::string timestamp = - to_string_dec_uint(datetime.year(), 4, '0') + - to_string_dec_uint(datetime.month(), 2, '0') + - to_string_dec_uint(datetime.day(), 2, '0') + - to_string_dec_uint(datetime.hour(), 2, '0') + - to_string_dec_uint(datetime.minute(), 2, '0') + - to_string_dec_uint(datetime.second(), 2, '0'); - + std::string timestamp = to_string_timestamp(datetime); return write(timestamp + " " + entry + "\r\n"); } diff --git a/firmware/application/string_format.cpp b/firmware/application/string_format.cpp index be5f988c0..596cc47ce 100644 --- a/firmware/application/string_format.cpp +++ b/firmware/application/string_format.cpp @@ -112,3 +112,11 @@ std::string to_string_hex(const uint32_t n, const int32_t l) { return p; } +std::string to_string_timestamp(const rtc::RTC& value) { + return to_string_dec_uint(value.year(), 4, '0') + + to_string_dec_uint(value.month(), 2, '0') + + to_string_dec_uint(value.day(), 2, '0') + + to_string_dec_uint(value.hour(), 2, '0') + + to_string_dec_uint(value.minute(), 2, '0') + + to_string_dec_uint(value.second(), 2, '0'); +} diff --git a/firmware/application/string_format.hpp b/firmware/application/string_format.hpp index 0eba017f5..6f7584784 100644 --- a/firmware/application/string_format.hpp +++ b/firmware/application/string_format.hpp @@ -25,10 +25,16 @@ #include #include +// BARF! rtc::RTC is leaking everywhere. +#include "lpc43xx_cpp.hpp" +using namespace lpc43xx; + // TODO: Allow l=0 to not fill/justify? Already using this way in ui_spectrum.hpp... std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = 0); std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0); std::string to_string_hex(const uint32_t n, const int32_t l = 0); +std::string to_string_timestamp(const rtc::RTC& value); + #endif/*__STRING_FORMAT_H__*/ From 93aea5984767754309c9b7cc255211bb4df8b13a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 18:15:34 -0800 Subject: [PATCH 326/452] Add AIS last position timestamp to details view. --- firmware/application/ais_app.cpp | 1 + firmware/application/string_format.cpp | 9 +++++++++ firmware/application/string_format.hpp | 1 + 3 files changed, 11 insertions(+) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index ae20f25a0..a4a1fb7ea 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -410,6 +410,7 @@ void AISRecentEntryDetailView::paint(Painter& painter) { field_rect = draw_field(painter, field_rect, s, "Name", entry_.name); field_rect = draw_field(painter, field_rect, s, "Call", entry_.call_sign); field_rect = draw_field(painter, field_rect, s, "Dest", entry_.destination); + field_rect = draw_field(painter, field_rect, s, "Last", to_string_datetime(entry_.last_position.timestamp)); field_rect = draw_field(painter, field_rect, s, "Pos ", ais::format::latlon(entry_.last_position.latitude, entry_.last_position.longitude)); field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry_.navigational_status)); field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry_.received_count)); diff --git a/firmware/application/string_format.cpp b/firmware/application/string_format.cpp index 596cc47ce..5e151297f 100644 --- a/firmware/application/string_format.cpp +++ b/firmware/application/string_format.cpp @@ -112,6 +112,15 @@ std::string to_string_hex(const uint32_t n, const int32_t l) { return p; } +std::string to_string_datetime(const rtc::RTC& value) { + return to_string_dec_uint(value.year(), 4, '0') + "/" + + to_string_dec_uint(value.month(), 2, '0') + "/" + + to_string_dec_uint(value.day(), 2, '0') + " " + + to_string_dec_uint(value.hour(), 2, '0') + ":" + + to_string_dec_uint(value.minute(), 2, '0') + ":" + + to_string_dec_uint(value.second(), 2, '0'); +} + std::string to_string_timestamp(const rtc::RTC& value) { return to_string_dec_uint(value.year(), 4, '0') + to_string_dec_uint(value.month(), 2, '0') + diff --git a/firmware/application/string_format.hpp b/firmware/application/string_format.hpp index 6f7584784..b90030e2a 100644 --- a/firmware/application/string_format.hpp +++ b/firmware/application/string_format.hpp @@ -35,6 +35,7 @@ std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0); std::string to_string_hex(const uint32_t n, const int32_t l = 0); +std::string to_string_datetime(const rtc::RTC& value); std::string to_string_timestamp(const rtc::RTC& value); #endif/*__STRING_FORMAT_H__*/ From be44c211725e75ffe297bb897c1b6d6f0dce6c81 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 18:15:50 -0800 Subject: [PATCH 327/452] Move AIS received packet count to bottom of details view. --- firmware/application/ais_app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index a4a1fb7ea..6358ad8f2 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -413,11 +413,11 @@ void AISRecentEntryDetailView::paint(Painter& painter) { field_rect = draw_field(painter, field_rect, s, "Last", to_string_datetime(entry_.last_position.timestamp)); field_rect = draw_field(painter, field_rect, s, "Pos ", ais::format::latlon(entry_.last_position.latitude, entry_.last_position.longitude)); field_rect = draw_field(painter, field_rect, s, "Stat", ais::format::navigational_status(entry_.navigational_status)); - field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry_.received_count)); field_rect = draw_field(painter, field_rect, s, "RoT ", ais::format::rate_of_turn(entry_.last_position.rate_of_turn)); field_rect = draw_field(painter, field_rect, s, "SoG ", ais::format::speed_over_ground(entry_.last_position.speed_over_ground)); field_rect = draw_field(painter, field_rect, s, "CoG ", ais::format::course_over_ground(entry_.last_position.course_over_ground)); field_rect = draw_field(painter, field_rect, s, "Head", ais::format::true_heading(entry_.last_position.true_heading)); + field_rect = draw_field(painter, field_rect, s, "Rx #", to_string_dec_uint(entry_.received_count)); } void AISRecentEntryDetailView::set_entry(const AISRecentEntry& entry) { From 1d0de2240d9fe7e82bd0a810239f4a1b262e2de1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 15 Jan 2016 20:25:29 -0800 Subject: [PATCH 328/452] Protect/private some ThreadBase implementation details. --- firmware/baseband/thread_base.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/thread_base.hpp b/firmware/baseband/thread_base.hpp index 3db73d146..9b5e8a996 100644 --- a/firmware/baseband/thread_base.hpp +++ b/firmware/baseband/thread_base.hpp @@ -32,6 +32,7 @@ public: { } +protected: static msg_t fn(void* arg) { auto obj = static_cast(arg); chRegSetThreadName(obj->name); @@ -40,10 +41,10 @@ public: return 0; } - virtual void run() = 0; - private: const char* const name; + + virtual void run() = 0; }; #endif/*__THREAD_BASE_H__*/ From 58e6d2691039246fb2a3c04988c0ae39ddc3481b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 16 Jan 2016 13:56:23 -0800 Subject: [PATCH 329/452] Move AudioOutput back to inside audio processor classes. Was wasting precious RAM making it static. I lose 400 bytes of .text, not sure why, but I think the trade is worth it. --- firmware/baseband/audio_output.cpp | 2 -- firmware/baseband/audio_output.hpp | 2 -- firmware/baseband/proc_am_audio.hpp | 3 +++ firmware/baseband/proc_nfm_audio.hpp | 3 +++ firmware/baseband/proc_wfm_audio.hpp | 3 +++ 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/firmware/baseband/audio_output.cpp b/firmware/baseband/audio_output.cpp index f23f88712..6e29fa161 100644 --- a/firmware/baseband/audio_output.cpp +++ b/firmware/baseband/audio_output.cpp @@ -98,5 +98,3 @@ void AudioOutput::feed_audio_stats(const buffer_f32_t& audio) { } ); } - -AudioOutput audio_output; diff --git a/firmware/baseband/audio_output.hpp b/firmware/baseband/audio_output.hpp index 85ab438ef..df490d3c8 100644 --- a/firmware/baseband/audio_output.hpp +++ b/firmware/baseband/audio_output.hpp @@ -55,6 +55,4 @@ private: void feed_audio_stats(const buffer_f32_t& audio); }; -extern AudioOutput audio_output; - #endif/*__AUDIO_OUTPUT_H__*/ diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 1471263d5..5da5136d4 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -27,6 +27,7 @@ #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" +#include "audio_output.hpp" #include "spectrum_collector.hpp" #include @@ -56,6 +57,8 @@ private: dsp::demodulate::AM demod; + AudioOutput audio_output; + SpectrumCollector channel_spectrum; bool configured { false }; diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 14c2033c7..69ce6ee0f 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -27,6 +27,7 @@ #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" +#include "audio_output.hpp" #include "spectrum_collector.hpp" class NarrowbandFMAudio : public BasebandProcessor { @@ -55,6 +56,8 @@ private: dsp::demodulate::FM demod; + AudioOutput audio_output; + SpectrumCollector channel_spectrum; bool configured { false }; diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 22282189b..5c30c2e93 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -27,6 +27,7 @@ #include "dsp_decimate.hpp" #include "dsp_demodulate.hpp" +#include "audio_output.hpp" #include "spectrum_collector.hpp" class WidebandFMAudio : public BasebandProcessor { @@ -56,6 +57,8 @@ private: dsp::decimate::DecimateBy2CIC4Real audio_dec_2; dsp::decimate::FIR64AndDecimateBy2Real audio_filter; + AudioOutput audio_output; + SpectrumCollector channel_spectrum; size_t spectrum_interval_samples = 0; size_t spectrum_samples = 0; From 8d2a86a4995b888f4c124016b256efeb5902ce3e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 16 Jan 2016 14:10:22 -0800 Subject: [PATCH 330/452] Change baseband optimization from -O3 to -O2 Significant size benefit with negligable performance effect. --- firmware/baseband/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index 413ed0ded..b5a0679c7 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -27,7 +27,7 @@ # Compiler options here. ifeq ($(USE_OPT),) USE_OPT = -mthumb \ - -O3 -ggdb3 \ + -O2 -ggdb3 \ -ffunction-sections \ -fdata-sections \ -fno-builtin \ From 1aa391bac833b35e1a6ee75812f430cfb2621cbe Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 17 Jan 2016 14:08:49 -0800 Subject: [PATCH 331/452] Whoops. Revert to baseband -O3 compiler flag. Was running out of CPU in ERT mode. --- firmware/baseband/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index b5a0679c7..413ed0ded 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -27,7 +27,7 @@ # Compiler options here. ifeq ($(USE_OPT),) USE_OPT = -mthumb \ - -O2 -ggdb3 \ + -O3 -ggdb3 \ -ffunction-sections \ -fdata-sections \ -fno-builtin \ From fc7a7d753d5e29041a0bf85f4de5807f7131c00b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 17 Jan 2016 14:20:02 -0800 Subject: [PATCH 332/452] Extract general File class from LogFile. --- firmware/application/Makefile | 1 + firmware/application/file.cpp | 71 +++++++++++++++++++++++++++++++ firmware/application/file.hpp | 52 ++++++++++++++++++++++ firmware/application/log_file.cpp | 33 +++----------- firmware/application/log_file.hpp | 6 +-- 5 files changed, 132 insertions(+), 31 deletions(-) create mode 100644 firmware/application/file.cpp create mode 100644 firmware/application/file.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 41c8e7616..73b6cebc6 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -176,6 +176,7 @@ CPPSRC = main.cpp \ ../common/ert_packet.cpp \ spectrum_analysis_app.cpp \ sd_card.cpp \ + file.cpp \ log_file.cpp \ manchester.cpp \ string_format.cpp \ diff --git a/firmware/application/file.cpp b/firmware/application/file.cpp new file mode 100644 index 000000000..439c0a9c8 --- /dev/null +++ b/firmware/application/file.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "file.hpp" + +File::~File() { + close(); +} + +bool File::open_for_append(const std::string file_path) { + const auto open_result = f_open(&f, file_path.c_str(), FA_WRITE | FA_OPEN_ALWAYS); + if( open_result == FR_OK ) { + const auto seek_result = f_lseek(&f, f_size(&f)); + if( seek_result == FR_OK ) { + return true; + } else { + close(); + } + } + + return false; +} + +bool File::close() { + f_close(&f); + return true; +} + +bool File::is_ready() { + return f_error(&f) == 0; +} + +bool File::read(void* const data, const size_t bytes_to_read) { + UINT bytes_read = 0; + const auto result = f_read(&f, data, bytes_to_read, &bytes_read); + return (result == FR_OK) && (bytes_read == bytes_to_read); +} + +bool File::write(const void* const data, const size_t bytes_to_write) { + UINT bytes_written = 0; + const auto result = f_write(&f, data, bytes_to_write, &bytes_written); + return (result == FR_OK) && (bytes_written == bytes_to_write); +} + +bool File::puts(const std::string string) { + const auto result = f_puts(string.c_str(), &f); + return (result >= 0); +} + +bool File::sync() { + const auto result = f_sync(&f); + return (result == FR_OK); +} diff --git a/firmware/application/file.hpp b/firmware/application/file.hpp new file mode 100644 index 000000000..363bd866f --- /dev/null +++ b/firmware/application/file.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __FILE_H__ +#define __FILE_H__ + +#include "ff.h" + +#include +#include + +class File { +public: + ~File(); + + bool open_for_append(const std::string file_path); + bool close(); + + bool is_ready(); + + bool read(void* const data, const size_t bytes_to_read); + bool write(const void* const data, const size_t bytes_to_write); + + bool puts(const std::string string); + + bool sync(); + +private: + const std::string file_path; + + FIL f; +}; + +#endif/*__FILE_H__*/ diff --git a/firmware/application/log_file.cpp b/firmware/application/log_file.cpp index 43528aa4a..3b5f4f013 100644 --- a/firmware/application/log_file.cpp +++ b/firmware/application/log_file.cpp @@ -30,7 +30,7 @@ LogFile::LogFile( const std::string file_path ) : file_path { file_path } { - open(); + file.open_for_append(file_path); sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { this->on_sd_card_status(status); @@ -40,30 +40,11 @@ LogFile::LogFile( LogFile::~LogFile() { sd_card::status_signal -= sd_card_status_signal_token; - close(); -} - -bool LogFile::open() { - const auto open_result = f_open(&f, file_path.c_str(), FA_WRITE | FA_OPEN_ALWAYS); - if( open_result == FR_OK ) { - const auto seek_result = f_lseek(&f, f_size(&f)); - if( seek_result == FR_OK ) { - return true; - } else { - close(); - } - } - - return false; -} - -bool LogFile::close() { - f_close(&f); - return true; + file.close(); } bool LogFile::is_ready() { - return !f_error(&f); + return file.is_ready(); } bool LogFile::write_entry(const rtc::RTC& datetime, const std::string& entry) { @@ -72,15 +53,13 @@ bool LogFile::write_entry(const rtc::RTC& datetime, const std::string& entry) { } bool LogFile::write(const std::string& message) { - const auto puts_result = f_puts(message.c_str(), &f); - const auto sync_result = f_sync(&f); - return (puts_result >= 0) && (sync_result == FR_OK); + return file.puts(message) && file.sync(); } void LogFile::on_sd_card_status(const sd_card::Status status) { if( status == sd_card::Status::Mounted ) { - open(); + file.open_for_append(file_path); } else { - close(); + file.close(); } } diff --git a/firmware/application/log_file.hpp b/firmware/application/log_file.hpp index c0f3138cf..0ddf781cc 100644 --- a/firmware/application/log_file.hpp +++ b/firmware/application/log_file.hpp @@ -24,7 +24,7 @@ #include -#include "ff.h" +#include "file.hpp" #include "sd_card.hpp" #include "lpc43xx_cpp.hpp" @@ -35,8 +35,6 @@ public: LogFile(const std::string file_path); ~LogFile(); - bool open(); - bool close(); bool is_ready(); bool write_entry(const rtc::RTC& datetime, const std::string& entry); @@ -44,7 +42,7 @@ public: private: const std::string file_path; - FIL f; + File file; SignalToken sd_card_status_signal_token; From 5a864d8d44b4b102ab5881e94d102049729c7950 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 17 Jan 2016 15:56:29 -0800 Subject: [PATCH 333/452] Generalize RecentEntries find() method name. --- firmware/application/ais_app.cpp | 10 +++++----- firmware/application/ais_app.hpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 6358ad8f2..54b5550d1 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -218,7 +218,7 @@ void AISRecentEntry::update(const ais::Packet& packet) { const AISRecentEntry& AISRecentEntries::on_packet(const ais::Packet& packet) { const auto source_id = packet.source_id(); - auto matching_recent = find_by_mmsi(source_id); + auto matching_recent = find(source_id); if( matching_recent != std::end(entries) ) { // Found within. Move to front of list, increment counter. entries.push_front(*matching_recent); @@ -234,7 +234,7 @@ const AISRecentEntry& AISRecentEntries::on_packet(const ais::Packet& packet) { return entry; } -AISRecentEntries::ContainerType::const_iterator AISRecentEntries::find_by_mmsi(const ais::MMSI key) const { +AISRecentEntries::ContainerType::const_iterator AISRecentEntries::find(const ais::MMSI key) const { return std::find_if( std::begin(entries), std::end(entries), [key](const AISRecentEntry& e) { return e.mmsi == key; } @@ -286,7 +286,7 @@ bool AISRecentEntriesView::on_encoder(const EncoderEvent event) { bool AISRecentEntriesView::on_key(const ui::KeyEvent event) { if( event == ui::KeyEvent::Select ) { if( on_select ) { - const auto selected = recent.find_by_mmsi(selected_key); + const auto selected = recent.find(selected_key); if( selected != std::end(recent) ) { on_select(*selected); return true; @@ -323,7 +323,7 @@ void AISRecentEntriesView::paint(Painter& painter) { Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; const size_t visible_item_count = r.height() / s.font.line_height(); - auto selected = recent.find_by_mmsi(selected_key); + auto selected = recent.find(selected_key); if( selected == std::end(recent) ) { selected = std::begin(recent); } @@ -339,7 +339,7 @@ void AISRecentEntriesView::paint(Painter& painter) { } void AISRecentEntriesView::advance(const int32_t amount) { - auto selected = recent.find_by_mmsi(selected_key); + auto selected = recent.find(selected_key); if( selected == std::end(recent) ) { if( recent.empty() ) { selected_key = invalid_key; diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 3b5e3d2e6..b704d7ba4 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -85,7 +85,7 @@ public: return entries.front(); } - ContainerType::const_iterator find_by_mmsi(const ais::MMSI key) const; + ContainerType::const_iterator find(const ais::MMSI key) const; ContainerType::const_iterator begin() const { return entries.begin(); From 3ee6fd3d876fc66d1efda2a472f7bb5cfcbf6c55 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 17 Jan 2016 17:58:39 -0800 Subject: [PATCH 334/452] Generalize AISRecentEntries -> templated RecentEntries. Also access Entry unique key via key(). --- firmware/application/ais_app.cpp | 31 +++++++++++++++++-------------- firmware/application/ais_app.hpp | 30 +++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 54b5550d1..04c482a4a 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -216,15 +216,15 @@ void AISRecentEntry::update(const ais::Packet& packet) { } } -const AISRecentEntry& AISRecentEntries::on_packet(const ais::Packet& packet) { - const auto source_id = packet.source_id(); - auto matching_recent = find(source_id); +template +const Entry& RecentEntries::on_packet(const Key key, const Packet& packet) { + auto matching_recent = find(key); if( matching_recent != std::end(entries) ) { // Found within. Move to front of list, increment counter. entries.push_front(*matching_recent); entries.erase(matching_recent); } else { - entries.emplace_front(source_id); + entries.emplace_front(key); truncate_entries(); } @@ -234,21 +234,24 @@ const AISRecentEntry& AISRecentEntries::on_packet(const ais::Packet& packet) { return entry; } -AISRecentEntries::ContainerType::const_iterator AISRecentEntries::find(const ais::MMSI key) const { +template +typename RecentEntries::const_iterator RecentEntries::find(const Key key) const { return std::find_if( std::begin(entries), std::end(entries), - [key](const AISRecentEntry& e) { return e.mmsi == key; } + [key](const Entry& e) { return e.key() == key; } ); } -void AISRecentEntries::truncate_entries() { +template +void RecentEntries::truncate_entries() { while(entries.size() > entries_max) { entries.pop_back(); } } -AISRecentEntries::RangeType AISRecentEntries::range_around( - ContainerType::const_iterator item, const size_t count +template +typename RecentEntries::RangeType RecentEntries::range_around( + const_iterator item, const size_t count ) const { auto start = item; auto end = item; @@ -332,7 +335,7 @@ void AISRecentEntriesView::paint(Painter& painter) { for(auto p = range.first; p != range.second; p++) { const auto& entry = *p; - const auto is_selected_key = (selected_key == entry.mmsi); + const auto is_selected_key = (selected_key == entry.key()); ais_list_item_draw(entry, target_rect, painter, s, (has_focus() && is_selected_key)); target_rect.pos.y += target_rect.height(); } @@ -344,7 +347,7 @@ void AISRecentEntriesView::advance(const int32_t amount) { if( recent.empty() ) { selected_key = invalid_key; } else { - selected_key = recent.front().mmsi; + selected_key = recent.front().key(); } } else { if( amount < 0 ) { @@ -358,7 +361,7 @@ void AISRecentEntriesView::advance(const int32_t amount) { return; } } - selected_key = selected->mmsi; + selected_key = selected->key(); } set_dirty(); @@ -470,11 +473,11 @@ void AISAppView::set_parent_rect(const Rect new_parent_rect) { void AISAppView::on_packet(const ais::Packet& packet) { logger.on_packet(packet); - const auto updated_entry = recent.on_packet(packet); + const auto updated_entry = recent.on_packet(packet.source_id(), packet); recent_entries_view.set_dirty(); // TODO: Crude hack, should be a more formal listener arrangement... - if( updated_entry.mmsi == recent_entry_detail_view.entry().mmsi ) { + if( updated_entry.key() == recent_entry_detail_view.entry().key() ) { recent_entry_detail_view.set_entry(updated_entry); } } diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index b704d7ba4..c3973c0e0 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -49,6 +49,8 @@ struct AISPosition { }; struct AISRecentEntry { + using Key = ais::MMSI; + ais::MMSI mmsi; std::string name; std::string call_sign; @@ -71,27 +73,35 @@ struct AISRecentEntry { { } + Key key() const { + return mmsi; + } + void update(const ais::Packet& packet); }; -class AISRecentEntries { +template +class RecentEntries { public: - using ContainerType = std::list; - using RangeType = std::pair; + using Key = typename Entry::Key; + using ContainerType = std::list; + using const_reference = typename ContainerType::const_reference; + using const_iterator = typename ContainerType::const_iterator; + using RangeType = std::pair; - const AISRecentEntry& on_packet(const ais::Packet& packet); + const Entry& on_packet(const Key key, const Packet& packet); - ContainerType::const_reference front() const { + const_reference front() const { return entries.front(); } - ContainerType::const_iterator find(const ais::MMSI key) const; + const_iterator find(const Key key) const; - ContainerType::const_iterator begin() const { + const_iterator begin() const { return entries.begin(); } - ContainerType::const_iterator end() const { + const_iterator end() const { return entries.end(); } @@ -100,7 +110,7 @@ public: } RangeType range_around( - ContainerType::const_iterator, const size_t count + const_iterator, const size_t count ) const; private: @@ -110,6 +120,8 @@ private: void truncate_entries(); }; +using AISRecentEntries = RecentEntries; + class AISLogger { public: void on_packet(const ais::Packet& packet); From fb8e5b21df752c6c4a00c649d602e07dc66ad6c0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 17 Jan 2016 18:07:39 -0800 Subject: [PATCH 335/452] Use AIS MMSI string formatter, remove right-justification. --- firmware/application/ais_app.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 04c482a4a..28b2b9086 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -75,7 +75,7 @@ static std::string latlon(const Latitude latitude, const Longitude longitude) { static std::string mmsi( const ais::MMSI& mmsi ) { - return to_string_dec_uint(mmsi, 9, '0'); + return to_string_dec_uint(mmsi, 9); } static std::string datetime( @@ -408,8 +408,7 @@ void AISRecentEntryDetailView::paint(Painter& painter) { auto field_rect = Rect { rect.left(), rect.top() + 16, rect.width(), 16 }; - const size_t mmsi_length = 9; - field_rect = draw_field(painter, field_rect, s, "MMSI", to_string_dec_int(entry_.mmsi, mmsi_length)); + field_rect = draw_field(painter, field_rect, s, "MMSI", ais::format::mmsi(entry_.mmsi)); field_rect = draw_field(painter, field_rect, s, "Name", entry_.name); field_rect = draw_field(painter, field_rect, s, "Call", entry_.call_sign); field_rect = draw_field(painter, field_rect, s, "Dest", entry_.destination); From eda6e6a5be40fff70a8559bde50ee46bc4d966a6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 17 Jan 2016 19:08:08 -0800 Subject: [PATCH 336/452] Move AIS recent items list draw function back into class. --- firmware/application/ais_app.cpp | 4 ++-- firmware/application/ais_app.hpp | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 28b2b9086..872b986cc 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -299,7 +299,7 @@ bool AISRecentEntriesView::on_key(const ui::KeyEvent event) { return false; } -static void ais_list_item_draw( +void AISRecentEntriesView::draw( const AISRecentEntry& entry, const Rect& target_rect, Painter& painter, @@ -336,7 +336,7 @@ void AISRecentEntriesView::paint(Painter& painter) { for(auto p = range.first; p != range.second; p++) { const auto& entry = *p; const auto is_selected_key = (selected_key == entry.key()); - ais_list_item_draw(entry, target_rect, painter, s, (has_focus() && is_selected_key)); + draw(entry, target_rect, painter, s, (has_focus() && is_selected_key)); target_rect.pos.y += target_rect.height(); } } diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index c3973c0e0..9a5589428 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -151,6 +151,14 @@ private: const EntryKey invalid_key = 0xffffffff; void advance(const int32_t amount); + + void draw( + const AISRecentEntry& entry, + const Rect& target_rect, + Painter& painter, + const Style& style, + const bool is_selected + ); }; class AISRecentEntryDetailView : public View { From df3ce07c5c170ee2d3bdf56816d4b7374cc63610 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 17 Jan 2016 20:49:34 -0800 Subject: [PATCH 337/452] Template AISRecentEntriesView. More teasing apart, not sure where this will end... --- firmware/application/ais_app.cpp | 24 +++++++++++++++--------- firmware/application/ais_app.hpp | 21 ++++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 872b986cc..fa2ff7ca6 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -274,19 +274,22 @@ typename RecentEntries::RangeType RecentEntries::r namespace ui { -AISRecentEntriesView::AISRecentEntriesView( - AISRecentEntries& recent +template +RecentEntriesView::RecentEntriesView( + Entries& recent ) : recent { recent } { flags.focusable = true; } -bool AISRecentEntriesView::on_encoder(const EncoderEvent event) { +template +bool RecentEntriesView::on_encoder(const EncoderEvent event) { advance(event); return true; } -bool AISRecentEntriesView::on_key(const ui::KeyEvent event) { +template +bool RecentEntriesView::on_key(const ui::KeyEvent event) { if( event == ui::KeyEvent::Select ) { if( on_select ) { const auto selected = recent.find(selected_key); @@ -299,8 +302,9 @@ bool AISRecentEntriesView::on_key(const ui::KeyEvent event) { return false; } -void AISRecentEntriesView::draw( - const AISRecentEntry& entry, +template<> +void RecentEntriesView::draw( + const Entry& entry, const Rect& target_rect, Painter& painter, const Style& style, @@ -319,7 +323,8 @@ void AISRecentEntriesView::draw( painter.draw_string(target_rect.pos, draw_style, line); } -void AISRecentEntriesView::paint(Painter& painter) { +template +void RecentEntriesView::paint(Painter& painter) { const auto r = screen_rect(); const auto& s = style(); @@ -341,11 +346,12 @@ void AISRecentEntriesView::paint(Painter& painter) { } } -void AISRecentEntriesView::advance(const int32_t amount) { +template +void RecentEntriesView::advance(const int32_t amount) { auto selected = recent.find(selected_key); if( selected == std::end(recent) ) { if( recent.empty() ) { - selected_key = invalid_key; + selected_key = Entry::invalid_key; } else { selected_key = recent.front().key(); } diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 9a5589428..5dfd0f6bf 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -51,6 +51,8 @@ struct AISPosition { struct AISRecentEntry { using Key = ais::MMSI; + static constexpr Key invalid_key = 0xffffffff; + ais::MMSI mmsi; std::string name; std::string call_sign; @@ -83,6 +85,7 @@ struct AISRecentEntry { template class RecentEntries { public: + using EntryType = Entry; using Key = typename Entry::Key; using ContainerType = std::list; using const_reference = typename ContainerType::const_reference; @@ -132,11 +135,14 @@ private: namespace ui { -class AISRecentEntriesView : public View { +template +class RecentEntriesView : public View { public: - std::function on_select; + using Entry = typename Entries::EntryType; - AISRecentEntriesView(AISRecentEntries& recent); + std::function on_select; + + RecentEntriesView(Entries& recent); void paint(Painter& painter) override; @@ -144,16 +150,15 @@ public: bool on_key(const ui::KeyEvent event) override; private: - AISRecentEntries& recent; + Entries& recent; - using EntryKey = ais::MMSI; + using EntryKey = typename Entry::Key; EntryKey selected_key; - const EntryKey invalid_key = 0xffffffff; void advance(const int32_t amount); void draw( - const AISRecentEntry& entry, + const Entry& entry, const Rect& target_rect, Painter& painter, const Style& style, @@ -161,6 +166,8 @@ private: ); }; +using AISRecentEntriesView = RecentEntriesView; + class AISRecentEntryDetailView : public View { public: std::function on_close; From 05d7e0222f72f028ac9d6b1e8393d3ba74ef9242 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 17 Jan 2016 21:42:15 -0800 Subject: [PATCH 338/452] Extract RecentEntries stuff to separate files. --- firmware/application/Makefile | 1 + firmware/application/ais_app.cpp | 134 --------------- firmware/application/ais_app.hpp | 74 +------- firmware/application/recent_entries.cpp | 22 +++ firmware/application/recent_entries.hpp | 217 ++++++++++++++++++++++++ 5 files changed, 242 insertions(+), 206 deletions(-) create mode 100644 firmware/application/recent_entries.cpp create mode 100644 firmware/application/recent_entries.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 73b6cebc6..4aa171a48 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -165,6 +165,7 @@ CPPSRC = main.cpp \ ui_console.cpp \ ui_receiver.cpp \ ui_spectrum.cpp \ + recent_entries.cpp \ receiver_model.cpp \ spectrum_color_lut.cpp \ analog_audio_app.cpp \ diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index fa2ff7ca6..25b332998 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -216,92 +216,8 @@ void AISRecentEntry::update(const ais::Packet& packet) { } } -template -const Entry& RecentEntries::on_packet(const Key key, const Packet& packet) { - auto matching_recent = find(key); - if( matching_recent != std::end(entries) ) { - // Found within. Move to front of list, increment counter. - entries.push_front(*matching_recent); - entries.erase(matching_recent); - } else { - entries.emplace_front(key); - truncate_entries(); - } - - auto& entry = entries.front(); - entry.update(packet); - - return entry; -} - -template -typename RecentEntries::const_iterator RecentEntries::find(const Key key) const { - return std::find_if( - std::begin(entries), std::end(entries), - [key](const Entry& e) { return e.key() == key; } - ); -} - -template -void RecentEntries::truncate_entries() { - while(entries.size() > entries_max) { - entries.pop_back(); - } -} - -template -typename RecentEntries::RangeType RecentEntries::range_around( - const_iterator item, const size_t count -) const { - auto start = item; - auto end = item; - size_t i = 0; - - // Move start iterator toward first entry. - while( (start != std::begin(entries)) && (i < count / 2) ) { - std::advance(start, -1); - i++; - } - - // Move end iterator toward last entry. - while( (end != std::end(entries)) && (i < count) ) { - std::advance(end, 1); - i++; - } - - return { start, end }; -} - namespace ui { -template -RecentEntriesView::RecentEntriesView( - Entries& recent -) : recent { recent } -{ - flags.focusable = true; -} - -template -bool RecentEntriesView::on_encoder(const EncoderEvent event) { - advance(event); - return true; -} - -template -bool RecentEntriesView::on_key(const ui::KeyEvent event) { - if( event == ui::KeyEvent::Select ) { - if( on_select ) { - const auto selected = recent.find(selected_key); - if( selected != std::end(recent) ) { - on_select(*selected); - return true; - } - } - } - return false; -} - template<> void RecentEntriesView::draw( const Entry& entry, @@ -323,56 +239,6 @@ void RecentEntriesView::draw( painter.draw_string(target_rect.pos, draw_style, line); } -template -void RecentEntriesView::paint(Painter& painter) { - const auto r = screen_rect(); - const auto& s = style(); - - Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; - const size_t visible_item_count = r.height() / s.font.line_height(); - - auto selected = recent.find(selected_key); - if( selected == std::end(recent) ) { - selected = std::begin(recent); - } - - auto range = recent.range_around(selected, visible_item_count); - - for(auto p = range.first; p != range.second; p++) { - const auto& entry = *p; - const auto is_selected_key = (selected_key == entry.key()); - draw(entry, target_rect, painter, s, (has_focus() && is_selected_key)); - target_rect.pos.y += target_rect.height(); - } -} - -template -void RecentEntriesView::advance(const int32_t amount) { - auto selected = recent.find(selected_key); - if( selected == std::end(recent) ) { - if( recent.empty() ) { - selected_key = Entry::invalid_key; - } else { - selected_key = recent.front().key(); - } - } else { - if( amount < 0 ) { - if( selected != std::begin(recent) ) { - std::advance(selected, -1); - } - } - if( amount > 0 ) { - std::advance(selected, 1); - if( selected == std::end(recent) ) { - return; - } - } - selected_key = selected->key(); - } - - set_dirty(); -} - AISRecentEntryDetailView::AISRecentEntryDetailView() { add_children({ { &button_done, diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 5dfd0f6bf..2c7a435c4 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -38,6 +38,8 @@ using namespace lpc43xx; #include +#include "recent_entries.hpp" + struct AISPosition { rtc::RTC timestamp { }; ais::Latitude latitude; @@ -82,47 +84,6 @@ struct AISRecentEntry { void update(const ais::Packet& packet); }; -template -class RecentEntries { -public: - using EntryType = Entry; - using Key = typename Entry::Key; - using ContainerType = std::list; - using const_reference = typename ContainerType::const_reference; - using const_iterator = typename ContainerType::const_iterator; - using RangeType = std::pair; - - const Entry& on_packet(const Key key, const Packet& packet); - - const_reference front() const { - return entries.front(); - } - - const_iterator find(const Key key) const; - - const_iterator begin() const { - return entries.begin(); - } - - const_iterator end() const { - return entries.end(); - } - - bool empty() const { - return entries.empty(); - } - - RangeType range_around( - const_iterator, const size_t count - ) const; - -private: - ContainerType entries; - const size_t entries_max = 64; - - void truncate_entries(); -}; - using AISRecentEntries = RecentEntries; class AISLogger { @@ -135,37 +96,6 @@ private: namespace ui { -template -class RecentEntriesView : public View { -public: - using Entry = typename Entries::EntryType; - - std::function on_select; - - RecentEntriesView(Entries& recent); - - void paint(Painter& painter) override; - - bool on_encoder(const EncoderEvent event) override; - bool on_key(const ui::KeyEvent event) override; - -private: - Entries& recent; - - using EntryKey = typename Entry::Key; - EntryKey selected_key; - - void advance(const int32_t amount); - - void draw( - const Entry& entry, - const Rect& target_rect, - Painter& painter, - const Style& style, - const bool is_selected - ); -}; - using AISRecentEntriesView = RecentEntriesView; class AISRecentEntryDetailView : public View { diff --git a/firmware/application/recent_entries.cpp b/firmware/application/recent_entries.cpp new file mode 100644 index 000000000..bfb21aeef --- /dev/null +++ b/firmware/application/recent_entries.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "recent_entries.hpp" diff --git a/firmware/application/recent_entries.hpp b/firmware/application/recent_entries.hpp new file mode 100644 index 000000000..a04545863 --- /dev/null +++ b/firmware/application/recent_entries.hpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __RECENT_ENTRIES_H__ +#define __RECENT_ENTRIES_H__ + +#include "ui_widget.hpp" + +#include +#include +#include +#include +#include +#include +#include + +template +class RecentEntries { +public: + using EntryType = Entry; + using Key = typename Entry::Key; + using ContainerType = std::list; + using const_reference = typename ContainerType::const_reference; + using const_iterator = typename ContainerType::const_iterator; + using RangeType = std::pair; + + const Entry& on_packet(const Key key, const Packet& packet) { + auto matching_recent = find(key); + if( matching_recent != std::end(entries) ) { + // Found within. Move to front of list, increment counter. + entries.push_front(*matching_recent); + entries.erase(matching_recent); + } else { + entries.emplace_front(key); + truncate_entries(); + } + + auto& entry = entries.front(); + entry.update(packet); + + return entry; + } + + const_reference front() const { + return entries.front(); + } + + const_iterator find(const Key key) const { + return std::find_if( + std::begin(entries), std::end(entries), + [key](const Entry& e) { return e.key() == key; } + ); + } + + const_iterator begin() const { + return entries.begin(); + } + + const_iterator end() const { + return entries.end(); + } + + bool empty() const { + return entries.empty(); + } + + RangeType range_around( + const_iterator item, const size_t count + ) const { + auto start = item; + auto end = item; + size_t i = 0; + + // Move start iterator toward first entry. + while( (start != std::begin(entries)) && (i < count / 2) ) { + std::advance(start, -1); + i++; + } + + // Move end iterator toward last entry. + while( (end != std::end(entries)) && (i < count) ) { + std::advance(end, 1); + i++; + } + + return { start, end }; + } + +private: + ContainerType entries; + const size_t entries_max = 64; + + void truncate_entries() { + while(entries.size() > entries_max) { + entries.pop_back(); + } + } +}; + +namespace ui { + +template +class RecentEntriesView : public View { +public: + using Entry = typename Entries::EntryType; + + std::function on_select; + + RecentEntriesView( + Entries& recent + ) : recent { recent } + { + flags.focusable = true; + } + + void paint(Painter& painter) override { + const auto r = screen_rect(); + const auto& s = style(); + + Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; + const size_t visible_item_count = r.height() / s.font.line_height(); + + auto selected = recent.find(selected_key); + if( selected == std::end(recent) ) { + selected = std::begin(recent); + } + + auto range = recent.range_around(selected, visible_item_count); + + for(auto p = range.first; p != range.second; p++) { + const auto& entry = *p; + const auto is_selected_key = (selected_key == entry.key()); + draw(entry, target_rect, painter, s, (has_focus() && is_selected_key)); + target_rect.pos.y += target_rect.height(); + } + } + + bool on_encoder(const EncoderEvent event) override { + advance(event); + return true; + } + + bool on_key(const ui::KeyEvent event) override { + if( event == ui::KeyEvent::Select ) { + if( on_select ) { + const auto selected = recent.find(selected_key); + if( selected != std::end(recent) ) { + on_select(*selected); + return true; + } + } + } + return false; + } + +private: + Entries& recent; + + using EntryKey = typename Entry::Key; + EntryKey selected_key; + + void advance(const int32_t amount) { + auto selected = recent.find(selected_key); + if( selected == std::end(recent) ) { + if( recent.empty() ) { + selected_key = Entry::invalid_key; + } else { + selected_key = recent.front().key(); + } + } else { + if( amount < 0 ) { + if( selected != std::begin(recent) ) { + std::advance(selected, -1); + } + } + if( amount > 0 ) { + std::advance(selected, 1); + if( selected == std::end(recent) ) { + return; + } + } + selected_key = selected->key(); + } + + set_dirty(); + } + + void draw( + const Entry& entry, + const Rect& target_rect, + Painter& painter, + const Style& style, + const bool is_selected + ); +}; + +} /* namespace ui */ + +#endif/*__RECENT_ENTRIES_H__*/ From 6e5e48cc7c5290793b2a50981eda2a1507bf0b63 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 17 Jan 2016 21:56:06 -0800 Subject: [PATCH 339/452] Clear region below RecentEntries list. --- firmware/application/recent_entries.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/firmware/application/recent_entries.hpp b/firmware/application/recent_entries.hpp index a04545863..68c8c4a45 100644 --- a/firmware/application/recent_entries.hpp +++ b/firmware/application/recent_entries.hpp @@ -151,6 +151,11 @@ public: draw(entry, target_rect, painter, s, (has_focus() && is_selected_key)); target_rect.pos.y += target_rect.height(); } + + painter.fill_rectangle( + { target_rect.left(), target_rect.top(), target_rect.width(), r.bottom() - target_rect.top() }, + style().background + ); } bool on_encoder(const EncoderEvent event) override { From 1a280149e2a709a43bd00d27543b06c457f7ae0f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 18 Jan 2016 13:29:11 -0800 Subject: [PATCH 340/452] Rename TPMSView -> TPMSAppView. --- firmware/application/tpms_app.cpp | 6 +++--- firmware/application/tpms_app.hpp | 2 +- firmware/application/ui_receiver.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index c05b62448..9b02c388d 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -55,7 +55,7 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { namespace ui { -void TPMSView::on_show() { +void TPMSAppView::on_show() { Console::on_show(); EventDispatcher::message_map().register_handler(Message::ID::TPMSPacket, @@ -66,13 +66,13 @@ void TPMSView::on_show() { ); } -void TPMSView::on_hide() { +void TPMSAppView::on_hide() { EventDispatcher::message_map().unregister_handler(Message::ID::TPMSPacket); Console::on_hide(); } -void TPMSView::log(const ManchesterFormatted& formatted) { +void TPMSAppView::log(const ManchesterFormatted& formatted) { writeln(formatted.data.substr(0, 240 / 8)); } diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index b1417a8ff..f1ac771c2 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -40,7 +40,7 @@ private: namespace ui { -class TPMSView : public Console { +class TPMSAppView : public Console { public: void on_show() override; void on_hide() override; diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 20dc46b99..e281a88b6 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -525,7 +525,7 @@ void ReceiverView::on_modulation_changed(ReceiverModel::Mode mode) { break; case ReceiverModel::Mode::TPMS: - widget_content = std::make_unique(); + widget_content = std::make_unique(); break; case ReceiverModel::Mode::ERT: From be328c5f389f6d55cc0ad4aa5d8ea43700820fd2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 18 Jan 2016 13:41:19 -0800 Subject: [PATCH 341/452] Rearrange TPMS app/UI code. --- firmware/application/tpms_app.cpp | 31 +++++++++++++++++-------------- firmware/application/tpms_app.hpp | 12 +++++++----- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 9b02c388d..37534b4b4 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -28,15 +28,6 @@ using namespace portapack; #include "string_format.hpp" -TPMSModel::TPMSModel() { - receiver_model.set_baseband_configuration({ - .mode = 5, - .sampling_rate = 2457600, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); -} - ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { const ManchesterDecoder decoder(message.packet, 1); const auto hex_formatted = format_manchester(decoder); @@ -55,8 +46,10 @@ ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { namespace ui { -void TPMSAppView::on_show() { - Console::on_show(); +TPMSAppView::TPMSAppView() { + add_children({ { + &console, + } }); EventDispatcher::message_map().register_handler(Message::ID::TPMSPacket, [this](Message* const p) { @@ -64,16 +57,26 @@ void TPMSAppView::on_show() { this->log(this->model.on_packet(*message)); } ); + + receiver_model.set_baseband_configuration({ + .mode = 5, + .sampling_rate = 2457600, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); } -void TPMSAppView::on_hide() { +TPMSAppView::~TPMSAppView() { EventDispatcher::message_map().unregister_handler(Message::ID::TPMSPacket); +} - Console::on_hide(); +void TPMSAppView::set_parent_rect(const Rect new_parent_rect) { + View::set_parent_rect(new_parent_rect); + console.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); } void TPMSAppView::log(const ManchesterFormatted& formatted) { - writeln(formatted.data.substr(0, 240 / 8)); + console.writeln(formatted.data.substr(0, 240 / 8)); } } /* namespace ui */ diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index f1ac771c2..d4a36747a 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -30,8 +30,6 @@ class TPMSModel { public: - TPMSModel(); - ManchesterFormatted on_packet(const TPMSPacketMessage& message); private: @@ -40,14 +38,18 @@ private: namespace ui { -class TPMSAppView : public Console { +class TPMSAppView : public View { public: - void on_show() override; - void on_hide() override; + TPMSAppView(); + ~TPMSAppView(); + + void set_parent_rect(const Rect new_parent_rect) override; private: TPMSModel model; + Console console; + void log(const ManchesterFormatted& formatted); }; From 32818ee9ab58ba28f385ad3d9ea9310f4824f203 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 18 Jan 2016 13:54:07 -0800 Subject: [PATCH 342/452] Introduce tpms::Packet type. --- firmware/application/tpms_app.cpp | 4 ++-- firmware/application/tpms_app.hpp | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 37534b4b4..62dae6852 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -28,7 +28,7 @@ using namespace portapack; #include "string_format.hpp" -ManchesterFormatted TPMSModel::on_packet(const TPMSPacketMessage& message) { +tpms::Packet TPMSModel::on_packet(const TPMSPacketMessage& message) { const ManchesterDecoder decoder(message.packet, 1); const auto hex_formatted = format_manchester(decoder); @@ -75,7 +75,7 @@ void TPMSAppView::set_parent_rect(const Rect new_parent_rect) { console.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); } -void TPMSAppView::log(const ManchesterFormatted& formatted) { +void TPMSAppView::log(const tpms::Packet& formatted) { console.writeln(formatted.data.substr(0, 240 / 8)); } diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index d4a36747a..620d88c00 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -28,9 +28,15 @@ #include "manchester.hpp" #include "log_file.hpp" +namespace tpms { + +using Packet = ManchesterFormatted; + +} /* namespace tpms */ + class TPMSModel { public: - ManchesterFormatted on_packet(const TPMSPacketMessage& message); + tpms::Packet on_packet(const TPMSPacketMessage& message); private: LogFile log_file { "tpms.txt" }; @@ -50,7 +56,7 @@ private: Console console; - void log(const ManchesterFormatted& formatted); + void log(const tpms::Packet& formatted); }; } /* namespace ui */ From feec99ac6a670849ebaabf7e347355d8fd175ba6 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 18 Jan 2016 14:21:24 -0800 Subject: [PATCH 343/452] Move TPMS packet handling to TPMSAppView. Also rename TPMSModel to TPMSLogger, considering that's what it was *really* doing. --- firmware/application/tpms_app.cpp | 22 +++++++++++++--------- firmware/application/tpms_app.hpp | 11 ++++++----- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 62dae6852..a5bdac307 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -28,9 +28,8 @@ using namespace portapack; #include "string_format.hpp" -tpms::Packet TPMSModel::on_packet(const TPMSPacketMessage& message) { - const ManchesterDecoder decoder(message.packet, 1); - const auto hex_formatted = format_manchester(decoder); +void TPMSLogger::on_packet(const Timestamp& timestamp, const tpms::Packet& packet) { + const auto hex_formatted = format_manchester(packet); if( log_file.is_ready() ) { const auto tuning_frequency = receiver_model.tuning_frequency(); @@ -38,10 +37,8 @@ tpms::Packet TPMSModel::on_packet(const TPMSPacketMessage& message) { const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); std::string entry = tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors; - log_file.write_entry(message.packet.timestamp(), entry); + log_file.write_entry(timestamp, entry); } - - return hex_formatted; } namespace ui { @@ -54,7 +51,7 @@ TPMSAppView::TPMSAppView() { EventDispatcher::message_map().register_handler(Message::ID::TPMSPacket, [this](Message* const p) { const auto message = static_cast(p); - this->log(this->model.on_packet(*message)); + this->on_packet(message->packet); } ); @@ -75,8 +72,15 @@ void TPMSAppView::set_parent_rect(const Rect new_parent_rect) { console.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); } -void TPMSAppView::log(const tpms::Packet& formatted) { - console.writeln(formatted.data.substr(0, 240 / 8)); +void TPMSAppView::on_packet(const baseband::Packet& baseband_packet) { + const tpms::Packet tpms_packet { baseband_packet, 1 }; + this->logger.on_packet(baseband_packet.timestamp(), tpms_packet); + this->draw(tpms_packet); +} + +void TPMSAppView::draw(const tpms::Packet& packet) { + const auto hex_formatted = format_manchester(packet); + console.writeln(hex_formatted.data.substr(0, 240 / 8)); } } /* namespace ui */ diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 620d88c00..d4904e666 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -30,13 +30,13 @@ namespace tpms { -using Packet = ManchesterFormatted; +using Packet = ManchesterDecoder; } /* namespace tpms */ -class TPMSModel { +class TPMSLogger { public: - tpms::Packet on_packet(const TPMSPacketMessage& message); + void on_packet(const Timestamp& timestamp, const tpms::Packet& packet); private: LogFile log_file { "tpms.txt" }; @@ -52,11 +52,12 @@ public: void set_parent_rect(const Rect new_parent_rect) override; private: - TPMSModel model; + TPMSLogger logger; Console console; - void log(const tpms::Packet& formatted); + void on_packet(const baseband::Packet& packet); + void draw(const tpms::Packet& packet); }; } /* namespace ui */ From fbcf784959fa4bb5b01862539752c347634fc7d1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 18 Jan 2016 14:34:30 -0800 Subject: [PATCH 344/452] Make tpms::Packet into real type. --- firmware/application/tpms_app.cpp | 30 +++++++++++++++++++++--------- firmware/application/tpms_app.hpp | 22 +++++++++++++++++++--- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index a5bdac307..2809fa0df 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -28,8 +28,20 @@ using namespace portapack; #include "string_format.hpp" -void TPMSLogger::on_packet(const Timestamp& timestamp, const tpms::Packet& packet) { - const auto hex_formatted = format_manchester(packet); +namespace tpms { + +Timestamp Packet::received_at() const { + return packet_.timestamp(); +} + +ManchesterFormatted Packet::symbols_formatted() const { + return format_manchester(decoder_); +} + +} /* namespace tpms */ + +void TPMSLogger::on_packet(const tpms::Packet& packet) { + const auto hex_formatted = packet.symbols_formatted(); if( log_file.is_ready() ) { const auto tuning_frequency = receiver_model.tuning_frequency(); @@ -37,7 +49,7 @@ void TPMSLogger::on_packet(const Timestamp& timestamp, const tpms::Packet& packe const auto tuning_frequency_str = to_string_dec_uint(tuning_frequency, 10); std::string entry = tuning_frequency_str + " FSK 38.4 19.2 " + hex_formatted.data + "/" + hex_formatted.errors; - log_file.write_entry(timestamp, entry); + log_file.write_entry(packet.received_at(), entry); } } @@ -51,7 +63,8 @@ TPMSAppView::TPMSAppView() { EventDispatcher::message_map().register_handler(Message::ID::TPMSPacket, [this](Message* const p) { const auto message = static_cast(p); - this->on_packet(message->packet); + const tpms::Packet packet { message->packet }; + this->on_packet(packet); } ); @@ -72,14 +85,13 @@ void TPMSAppView::set_parent_rect(const Rect new_parent_rect) { console.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); } -void TPMSAppView::on_packet(const baseband::Packet& baseband_packet) { - const tpms::Packet tpms_packet { baseband_packet, 1 }; - this->logger.on_packet(baseband_packet.timestamp(), tpms_packet); - this->draw(tpms_packet); +void TPMSAppView::on_packet(const tpms::Packet& packet) { + this->logger.on_packet(packet); + this->draw(packet); } void TPMSAppView::draw(const tpms::Packet& packet) { - const auto hex_formatted = format_manchester(packet); + const auto hex_formatted = packet.symbols_formatted(); console.writeln(hex_formatted.data.substr(0, 240 / 8)); } diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index d4904e666..3a1571f16 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -30,13 +30,29 @@ namespace tpms { -using Packet = ManchesterDecoder; +class Packet { +public: + constexpr Packet( + const baseband::Packet& packet + ) : packet_ { packet }, + decoder_ { packet_, 1 } + { + } + + Timestamp received_at() const; + + ManchesterFormatted symbols_formatted() const; + +private: + const baseband::Packet packet_; + const ManchesterDecoder decoder_; +}; } /* namespace tpms */ class TPMSLogger { public: - void on_packet(const Timestamp& timestamp, const tpms::Packet& packet); + void on_packet(const tpms::Packet& packet); private: LogFile log_file { "tpms.txt" }; @@ -56,7 +72,7 @@ private: Console console; - void on_packet(const baseband::Packet& packet); + void on_packet(const tpms::Packet& packet); void draw(const tpms::Packet& packet); }; From dbea30b9e4fc12bfbbaf18b6a7ecbec664aa0fef Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 18 Jan 2016 20:43:54 -0800 Subject: [PATCH 345/452] Check TPMS CRCs for packets I know, don't display the rest. --- firmware/application/tpms_app.cpp | 50 +++++++++++++++++++++++++++++-- firmware/application/tpms_app.hpp | 12 ++++++-- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 2809fa0df..e13b7dcba 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -28,6 +28,8 @@ using namespace portapack; #include "string_format.hpp" +#include "crc.hpp" + namespace tpms { Timestamp Packet::received_at() const { @@ -38,6 +40,46 @@ ManchesterFormatted Packet::symbols_formatted() const { return format_manchester(decoder_); } +size_t Packet::crc_valid_length() const { + constexpr uint32_t checksum_bytes = 0b1111111; + constexpr uint32_t crc_72_bytes = 0b111111111; + constexpr uint32_t crc_80_bytes = 0b1111111110; + + std::array bytes; + for(size_t i=0; i crc_72 { 0x01, 0xff }; + CRC crc_80 { 0x01, 0xff }; + + for(size_t i=0; i 0 ) { + const size_t length_chars = packet_length * 2 / 8; + const auto hex_formatted = packet.symbols_formatted(); + console.writeln(hex_formatted.data.substr(0, length_chars)); + } } } /* namespace ui */ diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 3a1571f16..48104f4fd 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -23,8 +23,9 @@ #define __TPMS_APP_H__ #include "ui_console.hpp" -#include "message.hpp" +#include "field_reader.hpp" +#include "baseband_packet.hpp" #include "manchester.hpp" #include "log_file.hpp" @@ -35,7 +36,8 @@ public: constexpr Packet( const baseband::Packet& packet ) : packet_ { packet }, - decoder_ { packet_, 1 } + decoder_ { packet_, 1 }, + reader_ { decoder_ } { } @@ -43,9 +45,15 @@ public: ManchesterFormatted symbols_formatted() const; + size_t crc_valid_length() const; + private: + using Reader = FieldReader; + const baseband::Packet packet_; const ManchesterDecoder decoder_; + + const Reader reader_; }; } /* namespace tpms */ From 7ad9ad259666fec35a8574c249aeea03f1c0e407 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 18 Jan 2016 21:42:26 -0800 Subject: [PATCH 346/452] TPMS packets to IDs and values. --- firmware/application/tpms_app.cpp | 27 ++++++++--- firmware/application/tpms_app.hpp | 74 ++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index e13b7dcba..d264cba0d 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -40,6 +40,17 @@ ManchesterFormatted Packet::symbols_formatted() const { return format_manchester(decoder_); } +Optional Packet::reading() const { + const auto length = crc_valid_length(); + + switch(length) { + case 64: return Reading { reader_.read(0, 32), reader_.read(32, 8) }; + case 72: return Reading { reader_.read(0, 32), reader_.read(40, 8), reader_.read(48, 8), reader_.read(56, 8) }; + case 80: return Reading { reader_.read(8, 32), reader_.read(48, 8), reader_.read(56, 8), reader_.read(64, 8) }; + default: return { }; + } +} + size_t Packet::crc_valid_length() const { constexpr uint32_t checksum_bytes = 0b1111111; constexpr uint32_t crc_72_bytes = 0b111111111; @@ -133,11 +144,17 @@ void TPMSAppView::on_packet(const tpms::Packet& packet) { } void TPMSAppView::draw(const tpms::Packet& packet) { - const auto packet_length = packet.crc_valid_length(); - if( packet_length > 0 ) { - const size_t length_chars = packet_length * 2 / 8; - const auto hex_formatted = packet.symbols_formatted(); - console.writeln(hex_formatted.data.substr(0, length_chars)); + const auto reading_opt = packet.reading(); + if( reading_opt.is_valid() ) { + const auto reading = reading_opt.value(); + auto s = to_string_hex(reading.id(), 8) + " " + to_string_hex(reading.value_1(), 2); + if( reading.value_2().is_valid() ) { + s += " " + to_string_hex(reading.value_2().value(), 2); + } + if( reading.value_3().is_valid() ) { + s += " " + to_string_hex(reading.value_3().value(), 2); + } + console.writeln(s); } } diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 48104f4fd..40931b04b 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -31,6 +31,76 @@ namespace tpms { +template +class Optional { +public: + constexpr Optional() : value_ { }, valid_ { false } { }; + constexpr Optional(const T& value) : value_ { value }, valid_ { true } { }; + constexpr Optional(T&& value) : value_ { std::move(value) }, valid_ { true } { }; + + bool is_valid() const { return valid_; }; + T value() const { return value_; }; + +private: + const T value_; + const bool valid_; +}; + +class Reading { +public: + constexpr Reading( + ) : id_ { 0 }, + value_1_ { 0 }, + value_2_ { 0 }, + value_3_ { 0 } + { + } + + constexpr Reading( + uint32_t id, + uint16_t value_1 + ) : id_ { id }, + value_1_ { value_1 }, + value_2_ { }, + value_3_ { } + { + } + + constexpr Reading( + uint32_t id, + uint16_t value_1, + uint16_t value_2, + uint16_t value_3 + ) : id_ { id }, + value_1_ { value_1 }, + value_2_ { value_2 }, + value_3_ { value_3 } + { + } + + uint32_t id() const { + return id_; + } + + uint16_t value_1() const { + return value_1_; + } + + Optional value_2() const { + return value_2_; + } + + Optional value_3() const { + return value_3_; + } + +private: + uint32_t id_; + uint16_t value_1_; + Optional value_2_; + Optional value_3_; +}; + class Packet { public: constexpr Packet( @@ -45,7 +115,7 @@ public: ManchesterFormatted symbols_formatted() const; - size_t crc_valid_length() const; + Optional reading() const; private: using Reader = FieldReader; @@ -54,6 +124,8 @@ private: const ManchesterDecoder decoder_; const Reader reader_; + + size_t crc_valid_length() const; }; } /* namespace tpms */ From 9a41961aeb4a6a976041821ab1e7b89690547c13 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 18 Jan 2016 22:18:49 -0800 Subject: [PATCH 347/452] Store TPMS "packet type". For now, completely dumb CRC-OK packet length, since I only handle three packet types, which differ in length. --- firmware/application/tpms_app.cpp | 9 +++++---- firmware/application/tpms_app.hpp | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index d264cba0d..47e43fcb3 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -44,9 +44,9 @@ Optional Packet::reading() const { const auto length = crc_valid_length(); switch(length) { - case 64: return Reading { reader_.read(0, 32), reader_.read(32, 8) }; - case 72: return Reading { reader_.read(0, 32), reader_.read(40, 8), reader_.read(48, 8), reader_.read(56, 8) }; - case 80: return Reading { reader_.read(8, 32), reader_.read(48, 8), reader_.read(56, 8), reader_.read(64, 8) }; + case 64: return Reading { 64, reader_.read(0, 32), reader_.read(32, 8) }; + case 72: return Reading { 72, reader_.read(0, 32), reader_.read(40, 8), reader_.read(48, 8), reader_.read(56, 8) }; + case 80: return Reading { 80, reader_.read(8, 32), reader_.read(48, 8), reader_.read(56, 8), reader_.read(64, 8) }; default: return { }; } } @@ -147,7 +147,8 @@ void TPMSAppView::draw(const tpms::Packet& packet) { const auto reading_opt = packet.reading(); if( reading_opt.is_valid() ) { const auto reading = reading_opt.value(); - auto s = to_string_hex(reading.id(), 8) + " " + to_string_hex(reading.value_1(), 2); + auto s = to_string_dec_uint(reading.type(), 2) + " " + to_string_hex(reading.id(), 8); + s += " " + to_string_hex(reading.value_1(), 2); if( reading.value_2().is_valid() ) { s += " " + to_string_hex(reading.value_2().value(), 2); } diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 40931b04b..ad06d8df4 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -49,7 +49,8 @@ private: class Reading { public: constexpr Reading( - ) : id_ { 0 }, + ) : type_ { 0 }, + id_ { 0 }, value_1_ { 0 }, value_2_ { 0 }, value_3_ { 0 } @@ -57,9 +58,11 @@ public: } constexpr Reading( + uint32_t type, uint32_t id, uint16_t value_1 - ) : id_ { id }, + ) : type_ { type }, + id_ { id }, value_1_ { value_1 }, value_2_ { }, value_3_ { } @@ -67,17 +70,23 @@ public: } constexpr Reading( + uint32_t type, uint32_t id, uint16_t value_1, uint16_t value_2, uint16_t value_3 - ) : id_ { id }, + ) : type_ { type }, + id_ { id }, value_1_ { value_1 }, value_2_ { value_2 }, value_3_ { value_3 } { } + uint32_t type() const { + return type_; + } + uint32_t id() const { return id_; } @@ -95,6 +104,7 @@ public: } private: + uint32_t type_; uint32_t id_; uint16_t value_1_; Optional value_2_; From 5e6a76dfe7557dbf6b2f51cb472bfbf97b3c485f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 18 Jan 2016 22:28:33 -0800 Subject: [PATCH 348/452] Use a proper enum for TPMS signal type. --- firmware/application/tpms_app.cpp | 10 ++++++---- firmware/application/tpms_app.hpp | 17 ++++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 47e43fcb3..336a86b88 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -30,6 +30,8 @@ using namespace portapack; #include "crc.hpp" +#include "utility.hpp" + namespace tpms { Timestamp Packet::received_at() const { @@ -44,9 +46,9 @@ Optional Packet::reading() const { const auto length = crc_valid_length(); switch(length) { - case 64: return Reading { 64, reader_.read(0, 32), reader_.read(32, 8) }; - case 72: return Reading { 72, reader_.read(0, 32), reader_.read(40, 8), reader_.read(48, 8), reader_.read(56, 8) }; - case 80: return Reading { 80, reader_.read(8, 32), reader_.read(48, 8), reader_.read(56, 8), reader_.read(64, 8) }; + case 64: return Reading { Reading::Type::FLM_64, reader_.read(0, 32), reader_.read(32, 8) }; + case 72: return Reading { Reading::Type::FLM_72, reader_.read(0, 32), reader_.read(40, 8), reader_.read(48, 8), reader_.read(56, 8) }; + case 80: return Reading { Reading::Type::FLM_80, reader_.read(8, 32), reader_.read(48, 8), reader_.read(56, 8), reader_.read(64, 8) }; default: return { }; } } @@ -147,7 +149,7 @@ void TPMSAppView::draw(const tpms::Packet& packet) { const auto reading_opt = packet.reading(); if( reading_opt.is_valid() ) { const auto reading = reading_opt.value(); - auto s = to_string_dec_uint(reading.type(), 2) + " " + to_string_hex(reading.id(), 8); + auto s = to_string_dec_uint(toUType(reading.type()), 2) + " " + to_string_hex(reading.id(), 8); s += " " + to_string_hex(reading.value_1(), 2); if( reading.value_2().is_valid() ) { s += " " + to_string_hex(reading.value_2().value(), 2); diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index ad06d8df4..d0d477f7a 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -48,8 +48,15 @@ private: class Reading { public: + enum Type { + None = 0, + FLM_64 = 1, + FLM_72 = 2, + FLM_80 = 3, + }; + constexpr Reading( - ) : type_ { 0 }, + ) : type_ { Type::None }, id_ { 0 }, value_1_ { 0 }, value_2_ { 0 }, @@ -58,7 +65,7 @@ public: } constexpr Reading( - uint32_t type, + Type type, uint32_t id, uint16_t value_1 ) : type_ { type }, @@ -70,7 +77,7 @@ public: } constexpr Reading( - uint32_t type, + Type type, uint32_t id, uint16_t value_1, uint16_t value_2, @@ -83,7 +90,7 @@ public: { } - uint32_t type() const { + Type type() const { return type_; } @@ -104,7 +111,7 @@ public: } private: - uint32_t type_; + Type type_; uint32_t id_; uint16_t value_1_; Optional value_2_; From bd0ec913f50564263fdfb7d3e47151c86773ec39 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 20 Jan 2016 09:02:25 -0800 Subject: [PATCH 349/452] Invert TPMS Manchester decoding, fix dependent CRC/checksums. --- firmware/application/tpms_app.cpp | 6 +++--- firmware/application/tpms_app.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 336a86b88..b80763636 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -63,9 +63,9 @@ size_t Packet::crc_valid_length() const { bytes[i] = reader_.read(i * 8, 8); } - uint32_t checksum = 6; - CRC crc_72 { 0x01, 0xff }; - CRC crc_80 { 0x01, 0xff }; + uint32_t checksum = 0; + CRC crc_72 { 0x01, 0x00 }; + CRC crc_80 { 0x01, 0x00 }; for(size_t i=0; i Date: Fri, 22 Jan 2016 10:59:41 -0800 Subject: [PATCH 350/452] Introduce TPMS measurement types, change formatting. --- firmware/application/tpms_app.cpp | 41 +++++++--- firmware/application/tpms_app.hpp | 122 ++++++++++++++++++++++-------- 2 files changed, 120 insertions(+), 43 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index b80763636..10c358613 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -46,10 +46,32 @@ Optional Packet::reading() const { const auto length = crc_valid_length(); switch(length) { - case 64: return Reading { Reading::Type::FLM_64, reader_.read(0, 32), reader_.read(32, 8) }; - case 72: return Reading { Reading::Type::FLM_72, reader_.read(0, 32), reader_.read(40, 8), reader_.read(48, 8), reader_.read(56, 8) }; - case 80: return Reading { Reading::Type::FLM_80, reader_.read(8, 32), reader_.read(48, 8), reader_.read(56, 8), reader_.read(64, 8) }; - default: return { }; + case 64: + return Reading { + Reading::Type::FLM_64, + reader_.read(0, 32), + Pressure { static_cast(reader_.read(32, 8)) * 4 / 3 }, + Temperature { static_cast(reader_.read(40, 8) & 0x7f) - 50 } + }; + + case 72: + return Reading { + Reading::Type::FLM_72, + reader_.read(0, 32), + Pressure { static_cast(reader_.read(40, 8)) * 4 / 3 }, + Temperature { static_cast(reader_.read(48, 8)) - 50 } + }; + + case 80: + return Reading { + Reading::Type::FLM_80, + reader_.read(8, 32), + Pressure { static_cast(reader_.read(48, 8)) * 4 / 3 }, + Temperature { static_cast(reader_.read(56, 8)) - 50 } + }; + + default: + return { }; } } @@ -149,13 +171,12 @@ void TPMSAppView::draw(const tpms::Packet& packet) { const auto reading_opt = packet.reading(); if( reading_opt.is_valid() ) { const auto reading = reading_opt.value(); - auto s = to_string_dec_uint(toUType(reading.type()), 2) + " " + to_string_hex(reading.id(), 8); - s += " " + to_string_hex(reading.value_1(), 2); - if( reading.value_2().is_valid() ) { - s += " " + to_string_hex(reading.value_2().value(), 2); + auto s = to_string_dec_uint(toUType(reading.type()), 2) + " " + to_string_hex(reading.id().value(), 8); + if( reading.pressure().is_valid() ) { + s += " " + to_string_dec_int(reading.pressure().value().kilopascal(), 3); } - if( reading.value_3().is_valid() ) { - s += " " + to_string_hex(reading.value_3().value(), 2); + if( reading.temperature().is_valid() ) { + s += " " + to_string_dec_int(reading.temperature().value().celsius(), 3); } console.writeln(s); } diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index e8c39da1b..3158b701f 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -46,6 +46,77 @@ private: const bool valid_; }; +class TransponderID { +public: + constexpr TransponderID( + ) : id_ { 0 } + { + } + + constexpr TransponderID( + const uint32_t id + ) : id_ { id } + { + } + + uint32_t value() const { + return id_; + } + +private: + uint32_t id_; +}; + +class Pressure { +public: + constexpr Pressure( + ) : kpa_ { 0 } + { + } + + constexpr Pressure( + const int32_t kilopascal + ) : kpa_ { static_cast(kilopascal) } + { + } + + int16_t kilopascal() const { + return kpa_; + } + + int16_t psi() const { + return static_cast(kpa_) * 1000 / 6895; + } + +private: + int16_t kpa_; +}; + +class Temperature { +public: + constexpr Temperature( + ) : c_ { 0 } + { + } + + constexpr Temperature( + const int32_t celsius + ) : c_ { static_cast(celsius) } + { + } + + int16_t celsius() const { + return c_; + } + + int16_t fahrenheit() const { + return (c_ * 9 / 5) + 32; + } + +private: + int16_t c_; +}; + class Reading { public: enum Type { @@ -56,37 +127,27 @@ public: }; constexpr Reading( - ) : type_ { Type::None }, - id_ { 0 }, - value_1_ { 0 }, - value_2_ { 0 }, - value_3_ { 0 } + ) : type_ { Type::None } { } constexpr Reading( Type type, - uint32_t id, - uint16_t value_1 + TransponderID id ) : type_ { type }, - id_ { id }, - value_1_ { value_1 }, - value_2_ { }, - value_3_ { } + id_ { id } { } - + constexpr Reading( Type type, - uint32_t id, - uint16_t value_1, - uint16_t value_2, - uint16_t value_3 + TransponderID id, + Optional pressure = { }, + Optional temperature = { } ) : type_ { type }, id_ { id }, - value_1_ { value_1 }, - value_2_ { value_2 }, - value_3_ { value_3 } + pressure_ { pressure }, + temperature_ { temperature } { } @@ -94,28 +155,23 @@ public: return type_; } - uint32_t id() const { + TransponderID id() const { return id_; } - uint16_t value_1() const { - return value_1_; + Optional pressure() const { + return pressure_; } - Optional value_2() const { - return value_2_; - } - - Optional value_3() const { - return value_3_; + Optional temperature() const { + return temperature_; } private: - Type type_; - uint32_t id_; - uint16_t value_1_; - Optional value_2_; - Optional value_3_; + Type type_ { Type::None }; + TransponderID id_ { 0 }; + Optional pressure_ { }; + Optional temperature_ { }; }; class Packet { From 54fb85a9d0ecd6c4707c538cfd5ba54ec98dfe3f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Jan 2016 13:40:15 -0800 Subject: [PATCH 351/452] Un-const Optional class members. --- firmware/application/tpms_app.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 3158b701f..e22cda8df 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -42,8 +42,8 @@ public: T value() const { return value_; }; private: - const T value_; - const bool valid_; + T value_; + bool valid_; }; class TransponderID { From 13c0999c3cfe5b4bc9644acd4df855093f0cafe7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Jan 2016 13:41:01 -0800 Subject: [PATCH 352/452] Move Optional outside tpms namespace. --- firmware/application/tpms_app.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index e22cda8df..41d4b797d 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -29,7 +29,6 @@ #include "manchester.hpp" #include "log_file.hpp" -namespace tpms { template class Optional { @@ -46,6 +45,8 @@ private: bool valid_; }; +namespace tpms { + class TransponderID { public: constexpr TransponderID( From 02b3e891f755f15f7a34f6a17d6562d15a106d82 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Jan 2016 15:00:25 -0800 Subject: [PATCH 353/452] TPMS RecentEntriesView and related stuff. Replaces Console listing of raw records. --- firmware/application/tpms_app.cpp | 99 ++++++++++++++++++++++++++----- firmware/application/tpms_app.hpp | 53 +++++++++++++++-- 2 files changed, 133 insertions(+), 19 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 10c358613..732755756 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -34,6 +34,26 @@ using namespace portapack; namespace tpms { +namespace format { + +std::string type(Reading::Type type) { + return to_string_dec_uint(toUType(type), 2); +} + +std::string id(TransponderID id) { + return to_string_hex(id.value(), 8); +} + +std::string pressure(Pressure pressure) { + return to_string_dec_int(pressure.kilopascal(), 3); +} + +std::string temperature(Temperature temperature) { + return to_string_dec_int(temperature.celsius(), 3); +} + +} /* namespace format */ + Timestamp Packet::received_at() const { return packet_.timestamp(); } @@ -130,11 +150,66 @@ void TPMSLogger::on_packet(const tpms::Packet& packet) { } } +const TPMSRecentEntry::Key TPMSRecentEntry::invalid_key = { tpms::Reading::Type::None, 0 }; + +void TPMSRecentEntry::update(const tpms::Reading& reading) { + received_count++; + + if( reading.pressure().is_valid() ) { + last_pressure = reading.pressure(); + // pressures.emplace_back(reading.pressure().value()); + // while( pressures.size() > 20 ) { + // pressures.pop_front(); + // } + } + if( reading.temperature().is_valid() ) { + last_temperature = reading.temperature(); + // temperatures.emplace_back(reading.temperature().value()); + // while( temperatures.size() > 20 ) { + // temperatures.pop_front(); + // } + } +} + namespace ui { +template<> +void RecentEntriesView::draw( + const Entry& entry, + const Rect& target_rect, + Painter& painter, + const Style& style, + const bool is_selected +) { + const auto& draw_style = is_selected ? style.invert() : style; + + std::string line = tpms::format::type(entry.type) + " " + tpms::format::id(entry.id); + + if( entry.last_pressure.is_valid() ) { + line += " " + tpms::format::pressure(entry.last_pressure.value()); + } else { + line += " " " "; + } + + if( entry.last_temperature.is_valid() ) { + line += " " + tpms::format::temperature(entry.last_temperature.value()); + } else { + line += " " " "; + } + + if( entry.received_count > 999 ) { + line += " +++"; + } else { + line += " " + to_string_dec_uint(entry.received_count, 3); + } + + line.resize(target_rect.width() / 8, ' '); + painter.draw_string(target_rect.pos, draw_style, line); +} + TPMSAppView::TPMSAppView() { add_children({ { - &console, + &recent_entries_view, } }); EventDispatcher::message_map().register_handler(Message::ID::TPMSPacket, @@ -159,27 +234,23 @@ TPMSAppView::~TPMSAppView() { void TPMSAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); - console.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); + recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); } void TPMSAppView::on_packet(const tpms::Packet& packet) { - this->logger.on_packet(packet); - this->draw(packet); -} + logger.on_packet(packet); -void TPMSAppView::draw(const tpms::Packet& packet) { const auto reading_opt = packet.reading(); if( reading_opt.is_valid() ) { const auto reading = reading_opt.value(); - auto s = to_string_dec_uint(toUType(reading.type()), 2) + " " + to_string_hex(reading.id().value(), 8); - if( reading.pressure().is_valid() ) { - s += " " + to_string_dec_int(reading.pressure().value().kilopascal(), 3); - } - if( reading.temperature().is_valid() ) { - s += " " + to_string_dec_int(reading.temperature().value().celsius(), 3); - } - console.writeln(s); + const auto updated_entry = recent.on_packet({ reading.type(), reading.id() }, reading); + recent_entries_view.set_dirty(); } } +void TPMSAppView::on_show_list() { + recent_entries_view.hidden(false); + recent_entries_view.focus(); +} + } /* namespace ui */ diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 41d4b797d..368b88289 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -22,13 +22,12 @@ #ifndef __TPMS_APP_H__ #define __TPMS_APP_H__ -#include "ui_console.hpp" - #include "field_reader.hpp" #include "baseband_packet.hpp" #include "manchester.hpp" #include "log_file.hpp" +#include "recent_entries.hpp" template class Optional { @@ -60,7 +59,7 @@ public: { } - uint32_t value() const { + constexpr uint32_t value() const { return id_; } @@ -204,6 +203,43 @@ private: } /* namespace tpms */ +namespace std { + +constexpr bool operator==(const tpms::TransponderID& lhs, const tpms::TransponderID& rhs) { + return (lhs.value() == rhs.value()); +} + +} /* namespace std */ + +struct TPMSRecentEntry { + using Key = std::pair; + + static const Key invalid_key; + + tpms::Reading::Type type { tpms::Reading::Type::None }; + tpms::TransponderID id { 0 }; + + size_t received_count { 0 }; + + Optional last_pressure; + Optional last_temperature; + + TPMSRecentEntry( + const Key& key + ) : type { key.first }, + id { key.second } + { + } + + Key key() const { + return { type, id }; + } + + void update(const tpms::Reading& reading); +}; + +using TPMSRecentEntries = RecentEntries; + class TPMSLogger { public: void on_packet(const tpms::Packet& packet); @@ -214,6 +250,8 @@ private: namespace ui { +using TPMSRecentEntriesView = RecentEntriesView; + class TPMSAppView : public View { public: TPMSAppView(); @@ -221,13 +259,18 @@ public: void set_parent_rect(const Rect new_parent_rect) override; + // Prevent painting of region covered entirely by a child. + // TODO: Add flag to View that specifies view does not need to be cleared before painting. + void paint(Painter&) override { }; + private: + TPMSRecentEntries recent; TPMSLogger logger; - Console console; + TPMSRecentEntriesView recent_entries_view { recent }; void on_packet(const tpms::Packet& packet); - void draw(const tpms::Packet& packet); + void on_show_list(); }; } /* namespace ui */ From 10d4172d5c63b054a0035b1714fbbfa6cbfa4f5b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Jan 2016 23:24:20 -0800 Subject: [PATCH 354/452] RF antenna bias voltage control API. --- firmware/application/radio.cpp | 6 ++++++ firmware/application/radio.hpp | 1 + firmware/application/receiver_model.cpp | 14 ++++++++++++++ firmware/application/receiver_model.hpp | 5 +++++ firmware/application/rffc507x.cpp | 12 ++++++++++++ firmware/application/rffc507x.hpp | 3 ++- 6 files changed, 40 insertions(+), 1 deletion(-) diff --git a/firmware/application/radio.cpp b/firmware/application/radio.cpp index cdaced346..b58222c5c 100644 --- a/firmware/application/radio.cpp +++ b/firmware/application/radio.cpp @@ -152,7 +152,13 @@ void set_baseband_decimation_by(const size_t n) { baseband_cpld.set_decimation_by(n); } +void set_antenna_bias(const bool on) { + /* Pull MOSFET gate low to turn on antenna bias. */ + first_if.set_gpo1(on ? 0 : 1); +} + void disable() { + set_antenna_bias(false); baseband_codec.set_mode(max5864::Mode::Shutdown); second_if.set_mode(max2837::Mode::Standby); first_if.disable(); diff --git a/firmware/application/radio.hpp b/firmware/application/radio.hpp index 0513c17c7..715fd0d50 100644 --- a/firmware/application/radio.hpp +++ b/firmware/application/radio.hpp @@ -42,6 +42,7 @@ void set_vga_gain(const int_fast8_t db); void set_sampling_frequency(const uint32_t frequency); void set_baseband_filter_bandwidth(const uint32_t bandwidth_minimum); void set_baseband_decimation_by(const size_t n); +void set_antenna_bias(const bool on); void disable(); diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 0162632de..944ba4c1f 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -52,6 +52,15 @@ void ReceiverModel::set_reference_ppm_correction(int32_t v) { clock_manager.set_reference_ppb(v * 1000); } +bool ReceiverModel::antenna_bias() const { + return antenna_bias_; +} + +void ReceiverModel::set_antenna_bias(bool enabled) { + antenna_bias_ = enabled; + update_antenna_bias(); +} + bool ReceiverModel::rf_amp() const { return rf_amp_; } @@ -113,6 +122,7 @@ uint32_t ReceiverModel::baseband_oversampling() const { void ReceiverModel::enable() { radio::set_direction(rf::Direction::Receive); update_tuning_frequency(); + update_antenna_bias(); update_rf_amp(); update_lna(); update_vga(); @@ -148,6 +158,10 @@ void ReceiverModel::update_tuning_frequency() { radio::set_tuning_frequency(persistent_memory::tuned_frequency() + tuning_offset()); } +void ReceiverModel::update_antenna_bias() { + radio::set_antenna_bias(antenna_bias_); +} + void ReceiverModel::update_rf_amp() { radio::set_rf_amp(rf_amp_); } diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index aeeac7e41..e13d76cb0 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -58,6 +58,9 @@ public: int32_t reference_ppm_correction() const; void set_reference_ppm_correction(int32_t v); + bool antenna_bias() const; + void set_antenna_bias(bool enabled); + bool rf_amp() const; void set_rf_amp(bool enabled); @@ -87,6 +90,7 @@ public: private: rf::Frequency frequency_step_ { 25000 }; bool rf_amp_ { false }; + bool antenna_bias_ { false }; int32_t lna_gain_db_ { 32 }; uint32_t baseband_bandwidth_ { max2837::filter::bandwidth_minimum }; int32_t vga_gain_db_ { 32 }; @@ -101,6 +105,7 @@ private: int32_t tuning_offset(); void update_tuning_frequency(); + void update_antenna_bias(); void update_rf_amp(); void update_lna(); void update_baseband_bandwidth(); diff --git a/firmware/application/rffc507x.cpp b/firmware/application/rffc507x.cpp index b001aee4f..6d466ea0d 100644 --- a/firmware/application/rffc507x.cpp +++ b/firmware/application/rffc507x.cpp @@ -262,6 +262,18 @@ void RFFC507x::set_frequency(const rf::Frequency lo_frequency) { flush(); } +void RFFC507x::set_gpo1(const bool new_value) { + if( new_value ) { + _map.r.gpo.p2gpo |= 1; + _map.r.gpo.p1gpo |= 1; + } else { + _map.r.gpo.p2gpo &= ~1; + _map.r.gpo.p1gpo &= ~1; + } + + flush_one(Register::GPO); +} + spi::reg_t RFFC507x::readback(const Readback readback) { /* TODO: This clobbers the rest of the DEV_CTRL register * Time to implement bitfields for registers. diff --git a/firmware/application/rffc507x.hpp b/firmware/application/rffc507x.hpp index 4850f1474..016f0f11a 100644 --- a/firmware/application/rffc507x.hpp +++ b/firmware/application/rffc507x.hpp @@ -808,7 +808,8 @@ public: void set_mixer_current(const uint8_t value); void set_frequency(const rf::Frequency lo_frequency); - + void set_gpo1(const bool new_value); + reg_t read(const address_t reg_num); private: From 25fac90d4fc27f780f021323e8d76b813912be37 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 11:31:50 -0800 Subject: [PATCH 355/452] Improve radio state management re: antenna bias voltage. Responsibility for radio state is still rather muddy... --- firmware/application/receiver_model.cpp | 8 +++++++- firmware/application/receiver_model.hpp | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 944ba4c1f..4f4e4d1cd 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -120,6 +120,7 @@ uint32_t ReceiverModel::baseband_oversampling() const { } void ReceiverModel::enable() { + enabled_ = true; radio::set_direction(rf::Direction::Receive); update_tuning_frequency(); update_antenna_bias(); @@ -141,7 +142,12 @@ void ReceiverModel::baseband_disable() { } void ReceiverModel::disable() { + enabled_ = false; + update_antenna_bias(); baseband_disable(); + + // TODO: Responsibility for enabling/disabling the radio is muddy. + // Some happens in ReceiverModel, some inside radio namespace. radio::disable(); } @@ -159,7 +165,7 @@ void ReceiverModel::update_tuning_frequency() { } void ReceiverModel::update_antenna_bias() { - radio::set_antenna_bias(antenna_bias_); + radio::set_antenna_bias(antenna_bias_ && enabled_); } void ReceiverModel::update_rf_amp() { diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index e13d76cb0..ac3ce913e 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -89,6 +89,7 @@ public: private: rf::Frequency frequency_step_ { 25000 }; + bool enabled_ { false }; bool rf_amp_ { false }; bool antenna_bias_ { false }; int32_t lna_gain_db_ { 32 }; From 60b8b38652209add6147571ced1651bd33aff8a3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 11:32:10 -0800 Subject: [PATCH 356/452] UI to turn on antenna bias voltage. --- firmware/application/ui_setup.cpp | 29 ++++++++++++++++++- firmware/application/ui_setup.hpp | 47 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/firmware/application/ui_setup.cpp b/firmware/application/ui_setup.cpp index b61c87cbc..596d15340 100644 --- a/firmware/application/ui_setup.cpp +++ b/firmware/application/ui_setup.cpp @@ -25,6 +25,9 @@ #include "lpc43xx_cpp.hpp" using namespace lpc43xx; +#include "portapack.hpp" +using portapack::receiver_model; + namespace ui { SetDateTimeView::SetDateTimeView( @@ -141,6 +144,29 @@ SetFrequencyCorrectionModel SetFrequencyCorrectionView::form_collect() { }; } +AntennaBiasSetupView::AntennaBiasSetupView(NavigationView& nav) { + add_children({ { + &text_title, + &text_description_1, + &text_description_2, + &text_description_3, + &text_description_4, + &options_bias, + &button_done, + } }); + + options_bias.set_by_value(receiver_model.antenna_bias() ? 1 : 0); + options_bias.on_change = [this](size_t, OptionsField::value_t v) { + receiver_model.set_antenna_bias(v); + }; + + button_done.on_select = [&nav](Button&){ nav.pop(); }; +} + +void AntennaBiasSetupView::focus() { + button_done.focus(); +} + AboutView::AboutView(NavigationView& nav) { add_children({ { &text_title, @@ -158,9 +184,10 @@ void AboutView::focus() { } SetupMenuView::SetupMenuView(NavigationView& nav) { - add_items<3>({ { + add_items<4>({ { { "Date/Time", [&nav](){ nav.push(); } }, { "Frequency Correction", [&nav](){ nav.push(); } }, + { "Antenna Bias Voltage", [&nav](){ nav.push(); } }, { "Touch", [&nav](){ nav.push(); } }, } }); on_left = [&nav](){ nav.pop(); }; diff --git a/firmware/application/ui_setup.hpp b/firmware/application/ui_setup.hpp index 3b0bae081..c012d5fc6 100644 --- a/firmware/application/ui_setup.hpp +++ b/firmware/application/ui_setup.hpp @@ -176,6 +176,53 @@ private: SetFrequencyCorrectionModel form_collect(); }; +class AntennaBiasSetupView : public View { +public: + AntennaBiasSetupView(NavigationView& nav); + + void focus() override; + +private: + Text text_title { + { 5 * 8, 3 * 16, 20 * 8, 16 }, + "Antenna Bias Voltage" + }; + + Text text_description_1 { + { 24, 6 * 16, 24 * 8, 16 }, + "CAUTION: Ensure that all" + }; + + Text text_description_2 { + { 28, 7 * 16, 23 * 8, 16 }, + "devices attached to the" + }; + + Text text_description_3 { + { 8, 8 * 16, 28 * 8, 16 }, + "antenna connector can accept" + }; + + Text text_description_4 { + { 68, 9 * 16, 13 * 8, 16 }, + "a DC voltage!" + }; + + OptionsField options_bias { + { 100, 12 * 16 }, + 5, + { + { " Off ", 0 }, + { " On ", 1 }, + } + }; + + Button button_done { + { 72, 15 * 16, 96, 24 }, + "Done" + }; +}; + class AboutView : public View { public: AboutView(NavigationView& nav); From ce481c0b5a9da7bfec5a67dbd771d02e5b20afae Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 17:02:16 -0800 Subject: [PATCH 357/452] Clean up UI type static_casts. So disgusting, but not entirely gone yet... --- firmware/application/ui_console.cpp | 2 +- firmware/application/ui_debug.cpp | 10 ++++---- firmware/application/ui_menu.cpp | 2 +- firmware/application/ui_receiver.cpp | 4 ++-- firmware/application/ui_spectrum.cpp | 27 ++++++++++----------- firmware/common/ui.cpp | 6 ++--- firmware/common/ui.hpp | 36 ++++++++++++---------------- firmware/common/ui_painter.cpp | 10 ++++---- firmware/common/ui_widget.cpp | 10 ++------ 9 files changed, 45 insertions(+), 62 deletions(-) diff --git a/firmware/application/ui_console.cpp b/firmware/application/ui_console.cpp index 48c0daeb2..654822366 100644 --- a/firmware/application/ui_console.cpp +++ b/firmware/application/ui_console.cpp @@ -49,7 +49,7 @@ void Console::write(const std::string message) { crlf(); } const Point pos_glyph { - static_cast(rect.pos.x + pos.x), + rect.pos.x + pos.x, display.scroll_area_y(pos.y) }; display.draw_glyph(pos_glyph, glyph, s.foreground, s.background); diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index fff640c9d..7b91f8df5 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -172,7 +172,7 @@ void RegistersWidget::draw_legend(const Coord left, Painter& painter) { for(size_t i=0; i((i / config.registers_per_row) * row_height) + left, (i / config.registers_per_row) * row_height }; const auto text = to_string_hex(i, config.legend_length); @@ -192,8 +192,8 @@ void RegistersWidget::draw_values( for(size_t i=0; i(left + config.legend_width() + 8 + (i % config.registers_per_row) * (config.value_width() + 8)), - static_cast((i / config.registers_per_row) * row_height) + left + config.legend_width() + 8 + (i % config.registers_per_row) * (config.value_width() + 8), + (i / config.registers_per_row) * row_height }; const auto value = reader(i); @@ -231,8 +231,8 @@ RegistersView::RegistersView( registers_widget.set_parent_rect({ 0, 48, 240, 192 }); text_title.set_parent_rect({ - static_cast((240 - title.size() * 8) / 2), 16, - static_cast(title.size() * 8), 16 + (240 - title.size() * 8) / 2, 16, + title.size() * 8, 16 }); text_title.set(title); } diff --git a/firmware/application/ui_menu.cpp b/firmware/application/ui_menu.cpp index 45468c2de..7aa098d31 100644 --- a/firmware/application/ui_menu.cpp +++ b/firmware/application/ui_menu.cpp @@ -52,7 +52,7 @@ void MenuItemView::paint(Painter& painter) { ); painter.draw_string( - { static_cast(r.pos.x + 8), static_cast(r.pos.y + (r.size.h - font_height) / 2) }, + { r.pos.x + 8, r.pos.y + (r.size.h - font_height) / 2 }, paint_style, item.text ); diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index e281a88b6..f9b9f9b4b 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -167,8 +167,8 @@ FrequencyKeypadView::FrequencyKeypadView( }; button.on_select = button_fn; button.set_parent_rect({ - static_cast((n % 3) * button_w), - static_cast((n / 3) * button_h + button_h), + (n % 3) * button_w, + (n / 3) * button_h + button_h, button_w, button_h }); button.set_text(label); diff --git a/firmware/application/ui_spectrum.cpp b/firmware/application/ui_spectrum.cpp index addd2079d..4204e37a3 100644 --- a/firmware/application/ui_spectrum.cpp +++ b/firmware/application/ui_spectrum.cpp @@ -88,10 +88,7 @@ void FrequencyScale::clear_background(Painter& painter, const Rect r) { void FrequencyScale::draw_frequency_ticks(Painter& painter, const Rect r) { const auto x_center = r.width() / 2; - const Rect tick { - static_cast(r.left() + x_center), r.top(), - 1, r.height() - }; + const Rect tick { r.left() + x_center, r.top(), 1, r.height() }; painter.fill_rectangle(tick, Color::white()); constexpr uint32_t tick_count_max = 4; @@ -117,15 +114,15 @@ void FrequencyScale::draw_frequency_ticks(Painter& painter, const Rect r) { (magnitude_n >= 3) ? "k" : ""; const std::string label = to_string_dec_uint(tick_offset) + zero_pad + unit; - const Coord offset_low = static_cast(r.left() + x_center - pixel_offset); + const Coord offset_low = r.left() + x_center - pixel_offset; const Rect tick_low { offset_low, r.top(), 1, r.height() }; painter.fill_rectangle(tick_low, Color::white()); - painter.draw_string({ static_cast(offset_low + 2), r.top() }, style(), label ); + painter.draw_string({ offset_low + 2, r.top() }, style(), label ); - const Coord offset_high = static_cast(r.left() + x_center + pixel_offset); + const Coord offset_high = r.left() + x_center + pixel_offset; const Rect tick_high { offset_high, r.top(), 1, r.height() }; painter.fill_rectangle(tick_high, Color::white()); - painter.draw_string({ static_cast(offset_high + 2), r.top() }, style(), label ); + painter.draw_string({ offset_high + 2, r.top() }, style(), label ); tick_offset += tick_interval; } @@ -146,8 +143,8 @@ void FrequencyScale::draw_filter_ranges(Painter& painter, const Rect r) { const auto stop_x_hi = x_center + stop_offset; const Rect r_stop_lo { - static_cast(r.left() + stop_x_lo), static_cast(r.bottom() - filter_band_height), - static_cast(pass_x_lo - stop_x_lo), filter_band_height + r.left() + stop_x_lo, r.bottom() - filter_band_height, + pass_x_lo - stop_x_lo, filter_band_height }; painter.fill_rectangle( r_stop_lo, @@ -155,8 +152,8 @@ void FrequencyScale::draw_filter_ranges(Painter& painter, const Rect r) { ); const Rect r_stop_hi { - static_cast(r.left() + pass_x_hi), static_cast(r.bottom() - filter_band_height), - static_cast(stop_x_hi - pass_x_hi), filter_band_height + r.left() + pass_x_hi, r.bottom() - filter_band_height, + stop_x_hi - pass_x_hi, filter_band_height }; painter.fill_rectangle( r_stop_hi, @@ -165,8 +162,8 @@ void FrequencyScale::draw_filter_ranges(Painter& painter, const Rect r) { } const Rect r_pass { - static_cast(r.left() + pass_x_lo), static_cast(r.bottom() - filter_band_height), - static_cast(pass_x_hi - pass_x_lo), filter_band_height + r.left() + pass_x_lo, r.bottom() - filter_band_height, + pass_x_hi - pass_x_lo, filter_band_height }; painter.fill_rectangle( r_pass, @@ -280,7 +277,7 @@ void WaterfallWidget::set_parent_rect(const Rect new_parent_rect) { waterfall_view.set_parent_rect({ 0, scale_height, new_parent_rect.width(), - static_cast(new_parent_rect.height() - scale_height) + new_parent_rect.height() - scale_height }); } diff --git a/firmware/common/ui.cpp b/firmware/common/ui.cpp index e85c07c96..4fd400880 100644 --- a/firmware/common/ui.cpp +++ b/firmware/common/ui.cpp @@ -36,9 +36,7 @@ Rect Rect::intersect(const Rect& o) const { const auto y1 = std::max(top(), o.top()); const auto y2 = std::min(bottom(), o.bottom()); if( (x2 >= x1) && (y2 > y1) ) { - return { - x1, y1, - static_cast(x2 - x1), static_cast(y2 - y1) }; + return { x1, y1, x2 - x1, y2 - y1 }; } else { return { }; } @@ -54,7 +52,7 @@ Rect& Rect::operator+=(const Rect& p) { pos = { x1, y1 }; const auto x2 = std::max(right(), p.right()); const auto y2 = std::max(bottom(), p.bottom()); - size = { static_cast(x2 - x1), static_cast(y2 - y1) }; + size = { x2 - x1, y2 - y1 }; } return *this; } diff --git a/firmware/common/ui.hpp b/firmware/common/ui.hpp index 554b1f36d..cf62d137e 100644 --- a/firmware/common/ui.hpp +++ b/firmware/common/ui.hpp @@ -99,23 +99,23 @@ struct Point { } constexpr Point( - Coord x, - Coord y - ) : x { x }, - y { y } + int x, + int y + ) : x { static_cast(x) }, + y { static_cast(y) } { } Point operator-() const { - return { static_cast(-x), static_cast(-y) }; + return { -x, -y }; } Point operator+(const Point& p) const { - return { static_cast(x + p.x), static_cast(y + p.y) }; + return { x + p.x, y + p.y }; } Point operator-(const Point& p) const { - return { static_cast(x - p.x), static_cast(y - p.y) }; + return { x - p.x, y - p.y }; } Point& operator+=(const Point& p) { @@ -155,10 +155,7 @@ private: /* Clockwise rotate (in screen coordinates), with a gain in * magnitude of sqrt(2). */ - return { - static_cast(x - y), - static_cast(x + y) - }; + return { x - y, x + y }; } #endif }; @@ -174,10 +171,10 @@ struct Size { } constexpr Size( - Dim w, - Dim h - ) : w { w }, - h { h } + int w, + int h + ) : w { static_cast(w) }, + h { static_cast(h) } { } @@ -197,8 +194,8 @@ struct Rect { } constexpr Rect( - Coord x, Coord y, - Dim w, Dim h + int x, int y, + int w, int h ) : pos { x, y }, size { w, h } { @@ -237,10 +234,7 @@ struct Rect { } Point center() const { - return { - static_cast(pos.x + size.w / 2), - static_cast(pos.y + size.h / 2) - }; + return { pos.x + size.w / 2, pos.y + size.h / 2 }; } bool is_empty() const { diff --git a/firmware/common/ui_painter.cpp b/firmware/common/ui_painter.cpp index 1f772fa1c..3dbcf89b9 100644 --- a/firmware/common/ui_painter.cpp +++ b/firmware/common/ui_painter.cpp @@ -55,18 +55,18 @@ size_t Painter::draw_string(Point p, const Style& style, const std::string text) } void Painter::draw_hline(Point p, size_t width, const Color c) { - display.fill_rectangle({ p, { static_cast(width), 1 } }, c); + display.fill_rectangle({ p, { width, 1 } }, c); } void Painter::draw_vline(Point p, size_t height, const Color c) { - display.fill_rectangle({ p, { 1, static_cast(height) } }, c); + display.fill_rectangle({ p, { 1, height } }, c); } void Painter::draw_rectangle(const Rect r, const Color c) { draw_hline(r.pos, r.size.w, c); - draw_vline({ r.pos.x, static_cast(r.pos.y + 1) }, r.size.h - 2, c); - draw_vline({ static_cast(r.pos.x + r.size.w - 1), static_cast(r.pos.y + 1) }, r.size.h - 2, c); - draw_hline({ r.pos.x, static_cast(r.pos.y + r.size.h - 1) }, r.size.w, c); + draw_vline({ r.pos.x, r.pos.y + 1 }, r.size.h - 2, c); + draw_vline({ r.pos.x + r.size.w - 1, r.pos.y + 1 }, r.size.h - 2, c); + draw_hline({ r.pos.x, r.pos.y + r.size.h - 1 }, r.size.w, c); } void Painter::fill_rectangle(const Rect r, const Color c) { diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 7732a5028..8564514ea 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -326,19 +326,13 @@ void Button::paint(Painter& painter) { painter.draw_rectangle(r, style().foreground); painter.fill_rectangle( - { - static_cast(r.pos.x + 1), static_cast(r.pos.y + 1), - static_cast(r.size.w - 2), static_cast(r.size.h - 2) - }, + { r.pos.x + 1, r.pos.y + 1, r.size.w - 2, r.size.h - 2 }, paint_style.background ); const auto label_r = paint_style.font.size_of(text_); painter.draw_string( - { - static_cast(r.pos.x + (r.size.w - label_r.w) / 2), - static_cast(r.pos.y + (r.size.h - label_r.h) / 2) - }, + { r.pos.x + (r.size.w - label_r.w) / 2, r.pos.y + (r.size.h - label_r.h) / 2 }, paint_style, text_ ); From 14f18d5cf767fffdbb10f6714a63c886698f5400 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 17:53:16 -0800 Subject: [PATCH 358/452] Reduce use of unsigned integers when signed will do fine. --- firmware/application/ais_app.cpp | 2 +- firmware/application/ui_debug.cpp | 12 ++++++------ firmware/application/ui_debug.hpp | 26 +++++++++++++------------- firmware/application/ui_receiver.cpp | 2 +- firmware/application/ui_receiver.hpp | 16 ++++++++-------- firmware/application/ui_spectrum.cpp | 16 ++++++++-------- firmware/application/ui_spectrum.hpp | 14 +++++++------- firmware/common/ui.hpp | 13 +++++++------ firmware/common/ui_painter.cpp | 8 ++++---- firmware/common/ui_painter.hpp | 8 ++++---- 10 files changed, 59 insertions(+), 58 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 25b332998..d0f5ca259 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -262,7 +262,7 @@ Rect AISRecentEntryDetailView::draw_field( const std::string& label, const std::string& value ) { - const size_t label_length_max = 4; + const int label_length_max = 4; painter.draw_string(Point { draw_rect.left(), draw_rect.top() }, style, label); diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 7b91f8df5..243c555ef 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -67,8 +67,8 @@ void TemperatureWidget::paint(Painter& painter) { const Color color_foreground = Color::green(); const Color color_reticle { 128, 128, 128 }; - const Dim graph_width = logger.capacity() * bar_width; const Dim graph_height = rect.height() - 16; + const auto graph_width = static_cast(logger.capacity()) * bar_width; const Rect graph_rect { rect.left() + (rect.width() - graph_width) / 2, rect.top() + 8, graph_width, rect.height() @@ -124,7 +124,7 @@ Coord TemperatureWidget::screen_y( const temperature_t temperature, const Rect& rect ) const { - const Coord y_raw = rect.bottom() - ((temperature - display_temp_min) * display_temp_scale); + int y_raw = rect.bottom() - ((temperature - display_temp_min) * display_temp_scale); const auto y_limit = std::min(rect.bottom(), std::max(rect.top(), y_raw)); return y_limit; } @@ -170,7 +170,7 @@ void RegistersWidget::paint(Painter& painter) { void RegistersWidget::draw_legend(const Coord left, Painter& painter) { const auto pos = screen_pos(); - for(size_t i=0; i(title.size()) * 8) / 2, 16, + static_cast(title.size()) * 8, 16 }); text_title.set(title); } diff --git a/firmware/application/ui_debug.hpp b/firmware/application/ui_debug.hpp index b693650ad..c54d08712 100644 --- a/firmware/application/ui_debug.hpp +++ b/firmware/application/ui_debug.hpp @@ -103,8 +103,8 @@ private: static constexpr temperature_t display_temp_min = 0; static constexpr temperature_t display_temp_scale = 3; - static constexpr Dim bar_width = 1; - static constexpr size_t temp_len = 3; + static constexpr int bar_width = 1; + static constexpr int temp_len = 3; }; class TemperatureView : public View { @@ -130,32 +130,32 @@ private: }; struct RegistersWidgetConfig { - size_t registers_count; - size_t legend_length; - size_t value_length; - size_t registers_per_row; + int registers_count; + int legend_length; + int value_length; + int registers_per_row; - constexpr Dim legend_width() const { + constexpr int legend_width() const { return legend_length * 8; } - constexpr Dim value_width() const { + constexpr int value_width() const { return value_length * 8; } - constexpr size_t registers_row_length() const { + constexpr int registers_row_length() const { return (registers_per_row * (value_length + 1)) - 1; } - constexpr Dim registers_row_width() const { + constexpr int registers_row_width() const { return registers_row_length() * 8; } - constexpr Dim row_width() const { + constexpr int row_width() const { return legend_width() + 8 + registers_row_width(); } - constexpr size_t rows() const { + constexpr int rows() const { return registers_count / registers_per_row; } }; @@ -175,7 +175,7 @@ private: const RegistersWidgetConfig config; const std::function reader; - static constexpr Dim row_height = 16; + static constexpr int row_height = 16; void draw_legend(const Coord left, Painter& painter); void draw_values(const Coord left, Painter& painter); diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index f9b9f9b4b..11c03150f 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -159,7 +159,7 @@ FrequencyKeypadView::FrequencyKeypadView( const char* const key_caps = "123456789<0."; - size_t n = 0; + int n = 0; for(auto& button : buttons) { add_child(&button); const std::string label { diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 4a321d37f..fa0d575c5 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -204,16 +204,16 @@ public: void set_value(const rf::Frequency new_value); private: - static constexpr size_t button_w = 240 / 3; - static constexpr size_t button_h = 48; + static constexpr int button_w = 240 / 3; + static constexpr int button_h = 48; - static constexpr size_t mhz_digits = 4; - static constexpr size_t submhz_digits = 4; + static constexpr int mhz_digits = 4; + static constexpr int submhz_digits = 4; - static constexpr size_t mhz_mod = pow(10, mhz_digits); - static constexpr size_t submhz_base = pow(10, 6 - submhz_digits); - //static constexpr size_t submhz_mod = pow(10, submhz_digits); - static constexpr size_t text_digits = mhz_digits + 1 + submhz_digits; + static constexpr int mhz_mod = pow(10, mhz_digits); + static constexpr int submhz_base = pow(10, 6 - submhz_digits); + //static constexpr int submhz_mod = pow(10, submhz_digits); + static constexpr int text_digits = mhz_digits + 1 + submhz_digits; Text text_value { { 0, 0, text_digits * button_w, button_h } diff --git a/firmware/application/ui_spectrum.cpp b/firmware/application/ui_spectrum.cpp index 4204e37a3..27e7da43b 100644 --- a/firmware/application/ui_spectrum.cpp +++ b/firmware/application/ui_spectrum.cpp @@ -43,7 +43,7 @@ void FrequencyScale::on_show() { clear(); } -void FrequencyScale::set_spectrum_sampling_rate(const uint32_t new_sampling_rate) { +void FrequencyScale::set_spectrum_sampling_rate(const int new_sampling_rate) { if( (spectrum_sampling_rate != new_sampling_rate) ) { spectrum_sampling_rate = new_sampling_rate; set_dirty(); @@ -51,8 +51,8 @@ void FrequencyScale::set_spectrum_sampling_rate(const uint32_t new_sampling_rate } void FrequencyScale::set_channel_filter( - const uint32_t pass_frequency, - const uint32_t stop_frequency + const int pass_frequency, + const int stop_frequency ) { if( (channel_filter_pass_frequency != pass_frequency) || (channel_filter_stop_frequency != stop_frequency) ) { @@ -91,18 +91,18 @@ void FrequencyScale::draw_frequency_ticks(Painter& painter, const Rect r) { const Rect tick { r.left() + x_center, r.top(), 1, r.height() }; painter.fill_rectangle(tick, Color::white()); - constexpr uint32_t tick_count_max = 4; + constexpr int tick_count_max = 4; float rough_tick_interval = float(spectrum_sampling_rate) / tick_count_max; - size_t magnitude = 1; - size_t magnitude_n = 0; + int magnitude = 1; + int magnitude_n = 0; while(rough_tick_interval >= 10.0f) { rough_tick_interval /= 10; magnitude *= 10; magnitude_n += 1; } - const size_t tick_interval = std::ceil(rough_tick_interval); + const int tick_interval = std::ceil(rough_tick_interval); - size_t tick_offset = tick_interval; + auto tick_offset = tick_interval; while((tick_offset * magnitude) < spectrum_sampling_rate / 2) { const Dim pixel_offset = tick_offset * magnitude * spectrum_bins / spectrum_sampling_rate; diff --git a/firmware/application/ui_spectrum.hpp b/firmware/application/ui_spectrum.hpp index cfce3c8f6..0c9321df9 100644 --- a/firmware/application/ui_spectrum.hpp +++ b/firmware/application/ui_spectrum.hpp @@ -37,18 +37,18 @@ class FrequencyScale : public Widget { public: void on_show() override; - void set_spectrum_sampling_rate(const uint32_t new_sampling_rate); - void set_channel_filter(const uint32_t pass_frequency, const uint32_t stop_frequency); + void set_spectrum_sampling_rate(const int new_sampling_rate); + void set_channel_filter(const int pass_frequency, const int stop_frequency); void paint(Painter& painter) override; private: - static constexpr Dim filter_band_height = 4; + static constexpr int filter_band_height = 4; - uint32_t spectrum_sampling_rate { 0 }; - const size_t spectrum_bins = std::tuple_size::value; - uint32_t channel_filter_pass_frequency { 0 }; - uint32_t channel_filter_stop_frequency { 0 }; + int spectrum_sampling_rate { 0 }; + const int spectrum_bins = std::tuple_size::value; + int channel_filter_pass_frequency { 0 }; + int channel_filter_stop_frequency { 0 }; void clear(); void clear_background(Painter& painter, const Rect r); diff --git a/firmware/common/ui.hpp b/firmware/common/ui.hpp index cf62d137e..8ac914ae6 100644 --- a/firmware/common/ui.hpp +++ b/firmware/common/ui.hpp @@ -209,27 +209,28 @@ struct Rect { { } - Coord top() const { + + int top() const { return pos.y; } - Coord bottom() const { + int bottom() const { return pos.y + size.h; } - Coord left() const { + int left() const { return pos.x; } - Coord right() const { + int right() const { return pos.x + size.w; } - Dim width() const { + int width() const { return size.w; } - Dim height() const { + int height() const { return size.h; } diff --git a/firmware/common/ui_painter.cpp b/firmware/common/ui_painter.cpp index 3dbcf89b9..7409b8ebc 100644 --- a/firmware/common/ui_painter.cpp +++ b/firmware/common/ui_painter.cpp @@ -36,13 +36,13 @@ Style Style::invert() const { }; } -size_t Painter::draw_char(const Point p, const Style& style, const char c) { +int Painter::draw_char(const Point p, const Style& style, const char c) { const auto glyph = style.font.glyph(c); display.draw_glyph(p, glyph, style.foreground, style.background); return glyph.advance().x; } -size_t Painter::draw_string(Point p, const Style& style, const std::string text) { +int Painter::draw_string(Point p, const Style& style, const std::string text) { size_t width = 0; for(const auto c : text) { const auto glyph = style.font.glyph(c); @@ -54,11 +54,11 @@ size_t Painter::draw_string(Point p, const Style& style, const std::string text) return width; } -void Painter::draw_hline(Point p, size_t width, const Color c) { +void Painter::draw_hline(Point p, int width, const Color c) { display.fill_rectangle({ p, { width, 1 } }, c); } -void Painter::draw_vline(Point p, size_t height, const Color c) { +void Painter::draw_vline(Point p, int height, const Color c) { display.fill_rectangle({ p, { 1, height } }, c); } diff --git a/firmware/common/ui_painter.hpp b/firmware/common/ui_painter.hpp index 40e03edf1..7ac7b40a4 100644 --- a/firmware/common/ui_painter.hpp +++ b/firmware/common/ui_painter.hpp @@ -46,9 +46,9 @@ public: Painter(const Painter&) = delete; Painter(Painter&&) = delete; - size_t draw_char(const Point p, const Style& style, const char c); + int draw_char(const Point p, const Style& style, const char c); - size_t draw_string(Point p, const Style& style, const std::string text); + int draw_string(Point p, const Style& style, const std::string text); void draw_rectangle(const Rect r, const Color c); void fill_rectangle(const Rect r, const Color c); @@ -56,8 +56,8 @@ public: void paint_widget_tree(Widget* const w); private: - void draw_hline(Point p, size_t width, const Color c); - void draw_vline(Point p, size_t height, const Color c); + void draw_hline(Point p, int width, const Color c); + void draw_vline(Point p, int height, const Color c); void paint_widget(Widget* const w); }; From e4f55394078194e29faf9c517b85f886416ecbad Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 17:53:33 -0800 Subject: [PATCH 359/452] Remove unused variables. --- firmware/application/ais_app.cpp | 2 -- firmware/application/tpms_app.cpp | 2 +- firmware/application/ui_debug.cpp | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index d0f5ca259..5c51adbfe 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -265,8 +265,6 @@ Rect AISRecentEntryDetailView::draw_field( const int label_length_max = 4; painter.draw_string(Point { draw_rect.left(), draw_rect.top() }, style, label); - - const auto length = value.length(); painter.draw_string(Point { draw_rect.left() + (label_length_max + 1) * 8, draw_rect.top() }, style, value); return { draw_rect.left(), draw_rect.top() + draw_rect.height(), draw_rect.width(), draw_rect.height() }; diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 732755756..f738e2d5c 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -243,7 +243,7 @@ void TPMSAppView::on_packet(const tpms::Packet& packet) { const auto reading_opt = packet.reading(); if( reading_opt.is_valid() ) { const auto reading = reading_opt.value(); - const auto updated_entry = recent.on_packet({ reading.type(), reading.id() }, reading); + recent.on_packet({ reading.type(), reading.id() }, reading); recent_entries_view.set_dirty(); } } diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 243c555ef..7dde4ab39 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -67,7 +67,6 @@ void TemperatureWidget::paint(Painter& painter) { const Color color_foreground = Color::green(); const Color color_reticle { 128, 128, 128 }; - const Dim graph_height = rect.height() - 16; const auto graph_width = static_cast(logger.capacity()) * bar_width; const Rect graph_rect { rect.left() + (rect.width() - graph_width) / 2, rect.top() + 8, From cca8c6dc066520247df95bdbad1960738da167dd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 21:17:04 -0800 Subject: [PATCH 360/452] ERTModel -> ERTLogger, now ERTApp does setup. --- firmware/application/ert_app.cpp | 90 +++++++++++++++----------------- firmware/application/ert_app.hpp | 12 ++--- 2 files changed, 47 insertions(+), 55 deletions(-) diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 86d637fa5..680772e81 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -31,7 +31,24 @@ using namespace portapack; #include "crc.hpp" #include "string_format.hpp" -ERTModel::ERTModel() { +void ERTLogger::on_packet(const ert::Packet& packet) { + if( log_file.is_ready() ) { + const auto formatted = packet.symbols_formatted(); + log_file.write_entry(packet.received_at(), formatted.data + "/" + formatted.errors); + } +} + +namespace ui { + +ERTView::ERTView() { + EventDispatcher::message_map().register_handler(Message::ID::ERTPacket, + [this](Message* const p) { + const auto message = static_cast(p); + const ert::Packet packet { message->type, message->packet }; + this->on_packet(packet); + } + ); + receiver_model.set_baseband_configuration({ .mode = 6, .sampling_rate = 4194304, @@ -40,60 +57,37 @@ ERTModel::ERTModel() { receiver_model.set_baseband_bandwidth(2500000); } -bool ERTModel::on_packet(const ert::Packet& packet) { - if( log_file.is_ready() ) { - const auto formatted = packet.symbols_formatted(); - log_file.write_entry(packet.received_at(), formatted.data + "/" + formatted.errors); - } - - return packet.crc_ok(); -} - -namespace ui { - -void ERTView::on_show() { - Console::on_show(); - - EventDispatcher::message_map().register_handler(Message::ID::ERTPacket, - [this](Message* const p) { - const auto message = static_cast(p); - const ert::Packet packet { message->type, message->packet }; - if( this->model.on_packet(packet) ) { - this->on_packet(packet); - } - } - ); -} - -void ERTView::on_hide() { +ERTView::~ERTView() { EventDispatcher::message_map().unregister_handler(Message::ID::ERTPacket); - - Console::on_hide(); } void ERTView::on_packet(const ert::Packet& packet) { - std::string msg; - switch(packet.type()) { - case ert::Packet::Type::SCM: - msg += "SCM "; - msg += to_string_dec_uint(packet.id(), 10); - msg += " "; - msg += to_string_dec_uint(packet.consumption(), 10); - break; + logger.on_packet(packet); - case ert::Packet::Type::IDM: - msg += "IDM "; - msg += to_string_dec_uint(packet.id(), 10); - msg += " "; - msg += to_string_dec_uint(packet.consumption(), 10); - break; + if( packet.crc_ok() ) { + std::string msg; + switch(packet.type()) { + case ert::Packet::Type::SCM: + msg += "SCM "; + msg += to_string_dec_uint(packet.id(), 10); + msg += " "; + msg += to_string_dec_uint(packet.consumption(), 10); + break; - default: - msg += "???"; - break; + case ert::Packet::Type::IDM: + msg += "IDM "; + msg += to_string_dec_uint(packet.id(), 10); + msg += " "; + msg += to_string_dec_uint(packet.consumption(), 10); + break; + + default: + msg += "???"; + break; + } + + writeln(msg); } - - writeln(msg); } } /* namespace ui */ diff --git a/firmware/application/ert_app.hpp b/firmware/application/ert_app.hpp index 173093fb7..46c2d15a2 100644 --- a/firmware/application/ert_app.hpp +++ b/firmware/application/ert_app.hpp @@ -31,11 +31,9 @@ #include #include -class ERTModel { +class ERTLogger { public: - ERTModel(); - - bool on_packet(const ert::Packet& packet); + void on_packet(const ert::Packet& packet); private: LogFile log_file { "ert.txt" }; @@ -45,11 +43,11 @@ namespace ui { class ERTView : public Console { public: - void on_show() override; - void on_hide() override; + ERTView(); + ~ERTView(); private: - ERTModel model; + ERTLogger logger; void on_packet(const ert::Packet& packet); }; From 45ae222ab590cbff437ef1fa6a7680609d176d0b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 21:26:06 -0800 Subject: [PATCH 361/452] Extract Optional to own header. --- firmware/application/tpms_app.hpp | 15 +---------- firmware/common/optional.hpp | 42 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 firmware/common/optional.hpp diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 368b88289..a92f13ef4 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -29,20 +29,7 @@ #include "recent_entries.hpp" -template -class Optional { -public: - constexpr Optional() : value_ { }, valid_ { false } { }; - constexpr Optional(const T& value) : value_ { value }, valid_ { true } { }; - constexpr Optional(T&& value) : value_ { std::move(value) }, valid_ { true } { }; - - bool is_valid() const { return valid_; }; - T value() const { return value_; }; - -private: - T value_; - bool valid_; -}; +#include "optional.hpp" namespace tpms { diff --git a/firmware/common/optional.hpp b/firmware/common/optional.hpp new file mode 100644 index 000000000..a6ca3ecf6 --- /dev/null +++ b/firmware/common/optional.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __OPTIONAL_H__ +#define __OPTIONAL_H__ + +#include + +template +class Optional { +public: + constexpr Optional() : value_ { }, valid_ { false } { }; + constexpr Optional(const T& value) : value_ { value }, valid_ { true } { }; + constexpr Optional(T&& value) : value_ { std::move(value) }, valid_ { true } { }; + + bool is_valid() const { return valid_; }; + T value() const { return value_; }; + +private: + T value_; + bool valid_; +}; + +#endif/*__OPTIONAL_H__*/ From 45a8759d7ba95dfb53d4d03ed0db0b4185f46c13 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 21:29:27 -0800 Subject: [PATCH 362/452] Remove silly types on Temperature/Pressure getters. --- firmware/application/tpms_app.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index a92f13ef4..aa33de245 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -67,11 +67,11 @@ public: { } - int16_t kilopascal() const { + int kilopascal() const { return kpa_; } - int16_t psi() const { + int psi() const { return static_cast(kpa_) * 1000 / 6895; } @@ -92,11 +92,11 @@ public: { } - int16_t celsius() const { + int celsius() const { return c_; } - int16_t fahrenheit() const { + int fahrenheit() const { return (c_ * 9 / 5) + 32; } From 798b5eb97246b776adee3eb1af1eabbad37b8ade Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 21:37:22 -0800 Subject: [PATCH 363/452] Extract Temperature, Pressure into units header. --- firmware/application/tpms_app.hpp | 58 +++------------------- firmware/common/units.hpp | 81 +++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 52 deletions(-) create mode 100644 firmware/common/units.hpp diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index aa33de245..8484fb225 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -31,6 +31,10 @@ #include "optional.hpp" +#include "units.hpp" +using units::Temperature; +using units::Pressure; + namespace tpms { class TransponderID { @@ -54,56 +58,6 @@ private: uint32_t id_; }; -class Pressure { -public: - constexpr Pressure( - ) : kpa_ { 0 } - { - } - - constexpr Pressure( - const int32_t kilopascal - ) : kpa_ { static_cast(kilopascal) } - { - } - - int kilopascal() const { - return kpa_; - } - - int psi() const { - return static_cast(kpa_) * 1000 / 6895; - } - -private: - int16_t kpa_; -}; - -class Temperature { -public: - constexpr Temperature( - ) : c_ { 0 } - { - } - - constexpr Temperature( - const int32_t celsius - ) : c_ { static_cast(celsius) } - { - } - - int celsius() const { - return c_; - } - - int fahrenheit() const { - return (c_ * 9 / 5) + 32; - } - -private: - int16_t c_; -}; - class Reading { public: enum Type { @@ -208,8 +162,8 @@ struct TPMSRecentEntry { size_t received_count { 0 }; - Optional last_pressure; - Optional last_temperature; + Optional last_pressure; + Optional last_temperature; TPMSRecentEntry( const Key& key diff --git a/firmware/common/units.hpp b/firmware/common/units.hpp new file mode 100644 index 000000000..d3923426a --- /dev/null +++ b/firmware/common/units.hpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __UNITS_H__ +#define __UNITS_H__ + +#include + +namespace units { + +class Pressure { +public: + constexpr Pressure( + ) : kpa_ { 0 } + { + } + + constexpr Pressure( + const int kilopascal + ) : kpa_ { static_cast(kilopascal) } + { + } + + int kilopascal() const { + return kpa_; + } + + int psi() const { + return kpa_ * 1000 / 6895; + } + +private: + int16_t kpa_; +}; + +class Temperature { +public: + constexpr Temperature( + ) : c_ { 0 } + { + } + + constexpr Temperature( + const int celsius + ) : c_ { static_cast(celsius) } + { + } + + int celsius() const { + return c_; + } + + int fahrenheit() const { + return (c_ * 9 / 5) + 32; + } + +private: + int16_t c_; +}; + +} /* namespace units */ + +#endif/*__UNITS_H__*/ From 4d5697cda7b88ef2949af603a16aaebab18a2d66 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 21:38:33 -0800 Subject: [PATCH 364/452] Simplify TPMS units static_casts. --- firmware/application/tpms_app.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index f738e2d5c..3c5d6ccc6 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -70,24 +70,24 @@ Optional Packet::reading() const { return Reading { Reading::Type::FLM_64, reader_.read(0, 32), - Pressure { static_cast(reader_.read(32, 8)) * 4 / 3 }, - Temperature { static_cast(reader_.read(40, 8) & 0x7f) - 50 } + Pressure { static_cast(reader_.read(32, 8)) * 4 / 3 }, + Temperature { static_cast(reader_.read(40, 8) & 0x7f) - 50 } }; case 72: return Reading { Reading::Type::FLM_72, reader_.read(0, 32), - Pressure { static_cast(reader_.read(40, 8)) * 4 / 3 }, - Temperature { static_cast(reader_.read(48, 8)) - 50 } + Pressure { static_cast(reader_.read(40, 8)) * 4 / 3 }, + Temperature { static_cast(reader_.read(48, 8)) - 50 } }; case 80: return Reading { Reading::Type::FLM_80, reader_.read(8, 32), - Pressure { static_cast(reader_.read(48, 8)) * 4 / 3 }, - Temperature { static_cast(reader_.read(56, 8)) - 50 } + Pressure { static_cast(reader_.read(48, 8)) * 4 / 3 }, + Temperature { static_cast(reader_.read(56, 8)) - 50 } }; default: From d888c77661f8ac26137b312d3f835780d095c812 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 21:38:43 -0800 Subject: [PATCH 365/452] Remove TPMS commented code. --- firmware/application/tpms_app.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 3c5d6ccc6..08aeeb885 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -157,17 +157,9 @@ void TPMSRecentEntry::update(const tpms::Reading& reading) { if( reading.pressure().is_valid() ) { last_pressure = reading.pressure(); - // pressures.emplace_back(reading.pressure().value()); - // while( pressures.size() > 20 ) { - // pressures.pop_front(); - // } } if( reading.temperature().is_valid() ) { last_temperature = reading.temperature(); - // temperatures.emplace_back(reading.temperature().value()); - // while( temperatures.size() > 20 ) { - // temperatures.pop_front(); - // } } } From fedecbeca5d416dd478667eeb93ac55bc90dd300 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 21:46:41 -0800 Subject: [PATCH 366/452] Extract ERT formatting code to free functions. --- firmware/application/ert_app.cpp | 41 ++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 680772e81..385d857b8 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -31,6 +31,31 @@ using namespace portapack; #include "crc.hpp" #include "string_format.hpp" +namespace ert { + +namespace format { + +std::string type(Packet::Type value) { + switch(value) { + default: + case Packet::Type::Unknown: return "???"; + case Packet::Type::IDM: return "IDM"; + case Packet::Type::SCM: return "SCM"; + } +} + +std::string id(ID value) { + return to_string_dec_uint(value, 10); +} + +std::string consumption(Consumption value) { + return to_string_dec_uint(value, 10); +} + +} /* namespace format */ + +} /* namespace ert */ + void ERTLogger::on_packet(const ert::Packet& packet) { if( log_file.is_ready() ) { const auto formatted = packet.symbols_formatted(); @@ -65,24 +90,16 @@ void ERTView::on_packet(const ert::Packet& packet) { logger.on_packet(packet); if( packet.crc_ok() ) { - std::string msg; + std::string msg { ert::format::type(packet.type()) }; + switch(packet.type()) { case ert::Packet::Type::SCM: - msg += "SCM "; - msg += to_string_dec_uint(packet.id(), 10); - msg += " "; - msg += to_string_dec_uint(packet.consumption(), 10); - break; - case ert::Packet::Type::IDM: - msg += "IDM "; - msg += to_string_dec_uint(packet.id(), 10); - msg += " "; - msg += to_string_dec_uint(packet.consumption(), 10); + msg += " " + ert::format::id(packet.id()); + msg += " " + ert::format::consumption(packet.consumption()); break; default: - msg += "???"; break; } From 56218565c18c63b1f5aa8c4a13e1b403d2d5962f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 21:52:42 -0800 Subject: [PATCH 367/452] Use TPMS declared invalid_key as default initializer values. --- firmware/application/tpms_app.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 8484fb225..a79ebb1e0 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -157,8 +157,8 @@ struct TPMSRecentEntry { static const Key invalid_key; - tpms::Reading::Type type { tpms::Reading::Type::None }; - tpms::TransponderID id { 0 }; + tpms::Reading::Type type { invalid_key.first }; + tpms::TransponderID id { invalid_key.second }; size_t received_count { 0 }; From db2f78f0f84473c1a808f68f5038200f3251d92e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 23 Jan 2016 22:24:48 -0800 Subject: [PATCH 368/452] ERTAppView, recent entries tracking and display. --- firmware/application/ert_app.cpp | 64 ++++++++++++++++++++-------- firmware/application/ert_app.hpp | 49 ++++++++++++++++++--- firmware/application/ui_receiver.cpp | 2 +- 3 files changed, 92 insertions(+), 23 deletions(-) diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 385d857b8..0242baa28 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -63,9 +63,41 @@ void ERTLogger::on_packet(const ert::Packet& packet) { } } +void ERTRecentEntry::update(const ert::Packet& packet) { + received_count++; + + last_consumption = packet.consumption(); +} + namespace ui { -ERTView::ERTView() { +template<> +void RecentEntriesView::draw( + const Entry& entry, + const Rect& target_rect, + Painter& painter, + const Style& style, + const bool is_selected +) { + const auto& draw_style = is_selected ? style.invert() : style; + + std::string line = ert::format::id(entry.id) + " " + ert::format::consumption(entry.last_consumption); + + if( entry.received_count > 999 ) { + line += " +++"; + } else { + line += " " + to_string_dec_uint(entry.received_count, 3); + } + + line.resize(target_rect.width() / 8, ' '); + painter.draw_string(target_rect.pos, draw_style, line); +} + +ERTAppView::ERTAppView() { + add_children({ { + &recent_entries_view, + } }); + EventDispatcher::message_map().register_handler(Message::ID::ERTPacket, [this](Message* const p) { const auto message = static_cast(p); @@ -82,29 +114,27 @@ ERTView::ERTView() { receiver_model.set_baseband_bandwidth(2500000); } -ERTView::~ERTView() { +ERTAppView::~ERTAppView() { EventDispatcher::message_map().unregister_handler(Message::ID::ERTPacket); } -void ERTView::on_packet(const ert::Packet& packet) { +void ERTAppView::set_parent_rect(const Rect new_parent_rect) { + View::set_parent_rect(new_parent_rect); + recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); +} + +void ERTAppView::on_packet(const ert::Packet& packet) { logger.on_packet(packet); if( packet.crc_ok() ) { - std::string msg { ert::format::type(packet.type()) }; - - switch(packet.type()) { - case ert::Packet::Type::SCM: - case ert::Packet::Type::IDM: - msg += " " + ert::format::id(packet.id()); - msg += " " + ert::format::consumption(packet.consumption()); - break; - - default: - break; - } - - writeln(msg); + recent.on_packet(packet.id(), packet); + recent_entries_view.set_dirty(); } } +void ERTAppView::on_show_list() { + recent_entries_view.hidden(false); + recent_entries_view.focus(); +} + } /* namespace ui */ diff --git a/firmware/application/ert_app.hpp b/firmware/application/ert_app.hpp index 46c2d15a2..8614b0766 100644 --- a/firmware/application/ert_app.hpp +++ b/firmware/application/ert_app.hpp @@ -22,14 +22,39 @@ #ifndef __ERT_APP_H__ #define __ERT_APP_H__ -#include "ui_console.hpp" #include "log_file.hpp" #include "ert_packet.hpp" +#include "recent_entries.hpp" + #include #include -#include + +struct ERTRecentEntry { + using Key = ert::ID; + + // TODO: Is this the right choice of invalid key value? + static constexpr Key invalid_key = 0; + + ert::ID id { invalid_key }; + + size_t received_count { 0 }; + + ert::Consumption last_consumption; + + ERTRecentEntry( + const Key& key + ) : id { key } + { + } + + Key key() const { + return id; + } + + void update(const ert::Packet& packet); +}; class ERTLogger { public: @@ -39,17 +64,31 @@ private: LogFile log_file { "ert.txt" }; }; +using ERTRecentEntries = RecentEntries; + namespace ui { -class ERTView : public Console { +using ERTRecentEntriesView = RecentEntriesView; + +class ERTAppView : public View { public: - ERTView(); - ~ERTView(); + ERTAppView(); + ~ERTAppView(); + + void set_parent_rect(const Rect new_parent_rect) override; + + // Prevent painting of region covered entirely by a child. + // TODO: Add flag to View that specifies view does not need to be cleared before painting. + void paint(Painter&) override { }; private: + ERTRecentEntries recent; ERTLogger logger; + ERTRecentEntriesView recent_entries_view { recent }; + void on_packet(const ert::Packet& packet); + void on_show_list(); }; } /* namespace ui */ diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 11c03150f..82e7c4bdd 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -529,7 +529,7 @@ void ReceiverView::on_modulation_changed(ReceiverModel::Mode mode) { break; case ReceiverModel::Mode::ERT: - widget_content = std::make_unique(); + widget_content = std::make_unique(); break; default: From e04e72abe7543897543d29024f5d08a2a67ba342 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 24 Jan 2016 22:12:16 -0800 Subject: [PATCH 369/452] Remove unused ReceiverView() receiver_model arg. --- firmware/application/ui_navigation.cpp | 2 +- firmware/application/ui_receiver.cpp | 8 +++----- firmware/application/ui_receiver.hpp | 4 +--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 617bed0ec..90cacbbfa 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -92,7 +92,7 @@ void NavigationView::focus() { SystemMenuView::SystemMenuView(NavigationView& nav) { add_items<7>({ { - { "Receiver", [&nav](){ nav.push(portapack::receiver_model); } }, + { "Receiver", [&nav](){ nav.push(); } }, { "Capture", [&nav](){ nav.push(); } }, { "Analyze", [&nav](){ nav.push(); } }, { "Setup", [&nav](){ nav.push(); } }, diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 82e7c4bdd..ed13ae839 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -363,10 +363,8 @@ void LNAGainField::on_focus() { /* ReceiverView **********************************************************/ ReceiverView::ReceiverView( - NavigationView& nav, - ReceiverModel& receiver_model -) : receiver_model(receiver_model) -{ + NavigationView& nav +) { add_children({ { &rssi, &channel, @@ -394,7 +392,7 @@ ReceiverView::ReceiverView( }; field_frequency.on_edit = [this, &nav]() { // TODO: Provide separate modal method/scheme? - auto new_view = nav.push(this->receiver_model.tuning_frequency()); + auto new_view = nav.push(receiver_model.tuning_frequency()); new_view->on_changed = [this](rf::Frequency f) { this->on_tuning_frequency_changed(f); this->field_frequency.set_value(f); diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index fa0d575c5..922e1f73e 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -354,7 +354,7 @@ constexpr Style style_options_group { class ReceiverView : public View { public: - ReceiverView(NavigationView& nav, ReceiverModel& receiver_model); + ReceiverView(NavigationView& nav); ~ReceiverView(); void on_show() override; @@ -363,8 +363,6 @@ public: void focus() override; private: - ReceiverModel& receiver_model; - RSSI rssi { { 19 * 8, 0, 11 * 8, 4 }, }; From 5ecc6d0330baa5dcb207e514a25c6bd1946273aa Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 24 Jan 2016 22:38:36 -0800 Subject: [PATCH 370/452] Add Receiver sub-menu, Transponders item and sub-menu. --- firmware/application/ais_app.cpp | 2 +- firmware/application/ais_app.hpp | 4 +++- firmware/application/ert_app.cpp | 2 +- firmware/application/ert_app.hpp | 4 +++- firmware/application/tpms_app.cpp | 2 +- firmware/application/tpms_app.hpp | 4 +++- firmware/application/ui_navigation.cpp | 25 ++++++++++++++++++++++++- firmware/application/ui_navigation.hpp | 10 ++++++++++ firmware/application/ui_receiver.cpp | 12 ------------ firmware/application/ui_receiver.hpp | 3 --- 10 files changed, 46 insertions(+), 22 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 5c51adbfe..6c1f2e400 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -297,7 +297,7 @@ void AISRecentEntryDetailView::set_entry(const AISRecentEntry& entry) { set_dirty(); } -AISAppView::AISAppView() { +AISAppView::AISAppView(NavigationView&) { add_children({ { &recent_entries_view, &recent_entry_detail_view, diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 2c7a435c4..c0352bc3e 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -23,6 +23,8 @@ #define __AIS_APP_H__ #include "ui_widget.hpp" +#include "ui_navigation.hpp" + #include "log_file.hpp" #include "ais_packet.hpp" @@ -129,7 +131,7 @@ private: class AISAppView : public View { public: - AISAppView(); + AISAppView(NavigationView& nav); ~AISAppView(); void set_parent_rect(const Rect new_parent_rect) override; diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 0242baa28..203fa98f1 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -93,7 +93,7 @@ void RecentEntriesView::draw( painter.draw_string(target_rect.pos, draw_style, line); } -ERTAppView::ERTAppView() { +ERTAppView::ERTAppView(NavigationView&) { add_children({ { &recent_entries_view, } }); diff --git a/firmware/application/ert_app.hpp b/firmware/application/ert_app.hpp index 8614b0766..6100441a8 100644 --- a/firmware/application/ert_app.hpp +++ b/firmware/application/ert_app.hpp @@ -22,6 +22,8 @@ #ifndef __ERT_APP_H__ #define __ERT_APP_H__ +#include "ui_navigation.hpp" + #include "log_file.hpp" #include "ert_packet.hpp" @@ -72,7 +74,7 @@ using ERTRecentEntriesView = RecentEntriesView; class ERTAppView : public View { public: - ERTAppView(); + ERTAppView(NavigationView& nav); ~ERTAppView(); void set_parent_rect(const Rect new_parent_rect) override; diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 08aeeb885..74cf4c133 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -199,7 +199,7 @@ void RecentEntriesView::draw( painter.draw_string(target_rect.pos, draw_style, line); } -TPMSAppView::TPMSAppView() { +TPMSAppView::TPMSAppView(NavigationView&) { add_children({ { &recent_entries_view, } }); diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index a79ebb1e0..ce58d0ac8 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -22,6 +22,8 @@ #ifndef __TPMS_APP_H__ #define __TPMS_APP_H__ +#include "ui_navigation.hpp" + #include "field_reader.hpp" #include "baseband_packet.hpp" #include "manchester.hpp" @@ -195,7 +197,7 @@ using TPMSRecentEntriesView = RecentEntriesView; class TPMSAppView : public View { public: - TPMSAppView(); + TPMSAppView(NavigationView& nav); ~TPMSAppView(); void set_parent_rect(const Rect new_parent_rect) override; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 90cacbbfa..a92312b5c 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -28,6 +28,10 @@ #include "ui_debug.hpp" #include "ui_receiver.hpp" +#include "ais_app.hpp" +#include "ert_app.hpp" +#include "tpms_app.hpp" + #include "m4_startup.hpp" namespace ui { @@ -88,11 +92,30 @@ void NavigationView::focus() { } } +/* TransceiversMenuView **************************************************/ + +TranspondersMenuView::TranspondersMenuView(NavigationView& nav) { + add_items<3>({ { + { "AIS: Boats", [&nav](){ nav.push(); } }, + { "ERT: Utility Meters", [&nav](){ nav.push(); } }, + { "TPMS: Cars", [&nav](){ nav.push(); } }, + } }); +} + +/* ReceiverMenuView ******************************************************/ + +ReceiverMenuView::ReceiverMenuView(NavigationView& nav) { + add_items<2>({ { + { "Audio", [&nav](){ nav.push(); } }, + { "Transponders", [&nav](){ nav.push(); } }, + } }); +} + /* SystemMenuView ********************************************************/ SystemMenuView::SystemMenuView(NavigationView& nav) { add_items<7>({ { - { "Receiver", [&nav](){ nav.push(); } }, + { "Receiver", [&nav](){ nav.push(); } }, { "Capture", [&nav](){ nav.push(); } }, { "Analyze", [&nav](){ nav.push(); } }, { "Setup", [&nav](){ nav.push(); } }, diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 273af6568..ca15b11dd 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -76,6 +76,16 @@ private: View* push_view(std::unique_ptr new_view); }; +class TranspondersMenuView : public MenuView { +public: + TranspondersMenuView(NavigationView& nav); +}; + +class ReceiverMenuView : public MenuView { +public: + ReceiverMenuView(NavigationView& nav); +}; + class SystemMenuView : public MenuView { public: SystemMenuView(NavigationView& nav); diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index ed13ae839..a5f595846 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -514,22 +514,10 @@ void ReceiverView::on_modulation_changed(ReceiverModel::Mode mode) { widget_content = std::make_unique(mode); break; - case ReceiverModel::Mode::AIS: - widget_content = std::make_unique(); - break; - case ReceiverModel::Mode::SpectrumAnalysis: widget_content = std::make_unique(); break; - case ReceiverModel::Mode::TPMS: - widget_content = std::make_unique(); - break; - - case ReceiverModel::Mode::ERT: - widget_content = std::make_unique(); - break; - default: break; } diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 922e1f73e..131d26e44 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -407,9 +407,6 @@ private: { " AM ", toUType(ReceiverModel::Mode::AMAudio) }, { "NFM ", toUType(ReceiverModel::Mode::NarrowbandFMAudio) }, { "WFM ", toUType(ReceiverModel::Mode::WidebandFMAudio) }, - { "AIS ", toUType(ReceiverModel::Mode::AIS) }, - { "TPMS", toUType(ReceiverModel::Mode::TPMS) }, - { "ERT", toUType(ReceiverModel::Mode::ERT) }, { "SPEC", toUType(ReceiverModel::Mode::SpectrumAnalysis) }, } }; From 029a44e24c0fe355d482c90d2784b8aa474479a0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 24 Jan 2016 22:38:45 -0800 Subject: [PATCH 371/452] Missing header. --- firmware/application/tpms_app.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index ce58d0ac8..56e820ddb 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -22,6 +22,7 @@ #ifndef __TPMS_APP_H__ #define __TPMS_APP_H__ +#include "ui_widget.hpp" #include "ui_navigation.hpp" #include "field_reader.hpp" From 15800eea33a050b0f8f3235cc3d1844f205cc145 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 25 Jan 2016 11:13:19 -0800 Subject: [PATCH 372/452] Move nav back button outside of ReceiverView. --- firmware/application/ui_navigation.cpp | 25 +++++++++++++++++++++++++ firmware/application/ui_navigation.hpp | 15 ++++++++++++++- firmware/application/ui_receiver.cpp | 7 +------ firmware/application/ui_receiver.hpp | 5 ----- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index a92312b5c..d9f7a107b 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -40,14 +40,29 @@ namespace ui { SystemStatusView::SystemStatusView() { add_children({ { + &button_back, &portapack, &sd_card_status_view, } }); sd_card_status_view.set_parent_rect({ 28 * 8, 0 * 16, 2 * 8, 1 * 16 }); + + button_back.on_select = [this](Button&){ + if( this->on_back ) { + this->on_back(); + } + }; +} + +void SystemStatusView::set_back_visible(bool new_value) { + button_back.hidden(!new_value); } /* Navigation ************************************************************/ +bool NavigationView::is_top() const { + return view_stack.size() == 1; +} + View* NavigationView::push_view(std::unique_ptr new_view) { free_view(); @@ -80,6 +95,10 @@ void NavigationView::update_view() { new_view->set_parent_rect({ {0, 0}, size() }); focus(); set_dirty(); + + if( on_view_changed ) { + on_view_changed(); + } } Widget* NavigationView::view() const { @@ -148,12 +167,18 @@ SystemView::SystemView( { 0, 0 }, { parent_rect.width(), status_view_height } }); + status_view.on_back = [this]() { + this->navigation_view.pop(); + }; add_child(&navigation_view); navigation_view.set_parent_rect({ { 0, status_view_height }, { parent_rect.width(), static_cast(parent_rect.height() - status_view_height) } }); + navigation_view.on_view_changed = [this]() { + this->status_view.set_back_visible(!this->navigation_view.is_top()); + }; // Initial view. // TODO: Restore from non-volatile memory? diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index ca15b11dd..01ff26b6c 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -39,11 +39,20 @@ namespace ui { class SystemStatusView : public View { public: + std::function on_back; + SystemStatusView(); + void set_back_visible(bool new_value); + private: + Button button_back { + { 0 * 8, 0 * 16, 3 * 8, 16 }, + " < ", + }; + Text portapack { - { 0, 0, 9 * 8, 1 * 16 }, + { 3 * 8, 0, 9 * 8, 1 * 16 }, "PortaPack", }; @@ -52,11 +61,15 @@ private: class NavigationView : public View { public: + std::function on_view_changed; + NavigationView() { } NavigationView(const NavigationView&) = delete; NavigationView(NavigationView&&) = delete; + bool is_top() const; + template T* push(Args&&... args) { return reinterpret_cast(push_view(std::unique_ptr(new T(*this, std::forward(args)...)))); diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index a5f595846..d4996dbab 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -369,7 +369,6 @@ ReceiverView::ReceiverView( &rssi, &channel, &audio, - &button_done, &field_frequency, &field_lna, //&options_baseband_bandwidth, @@ -381,10 +380,6 @@ ReceiverView::ReceiverView( &view_rf_gain_options, } }); - button_done.on_select = [&nav](Button&){ - nav.pop(); - }; - field_frequency.set_value(receiver_model.tuning_frequency()); field_frequency.set_step(receiver_model.frequency_step()); field_frequency.on_change = [this](rf::Frequency f) { @@ -480,7 +475,7 @@ void ReceiverView::on_hide() { } void ReceiverView::focus() { - button_done.focus(); + field_frequency.focus(); } void ReceiverView::on_tuning_frequency_changed(rf::Frequency f) { diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 131d26e44..515118283 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -375,11 +375,6 @@ private: { 19 * 8, 10, 11 * 8, 4 }, }; - Button button_done { - { 0 * 8, 0 * 16, 3 * 8, 16 }, - " < ", - }; - FrequencyField field_frequency { { 0 * 8, 1 * 16 }, }; From 8b0e6e65c85122226e6fea42687d46e6fc9b1469 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 25 Jan 2016 11:22:39 -0800 Subject: [PATCH 373/452] Configure radio in AIS, ERT, TPMS apps. --- firmware/application/ais_app.cpp | 6 ++++++ firmware/application/ert_app.cpp | 6 ++++++ firmware/application/tpms_app.cpp | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 6c1f2e400..4c134ca0e 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -321,6 +321,11 @@ AISAppView::AISAppView(NavigationView&) { .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); + receiver_model.set_rf_amp(false); + receiver_model.set_lna(32); + receiver_model.set_vga(32); + receiver_model.set_tuning_frequency(162025000); + receiver_model.enable(); recent_entries_view.on_select = [this](const AISRecentEntry& entry) { this->on_show_detail(entry); @@ -331,6 +336,7 @@ AISAppView::AISAppView(NavigationView&) { } AISAppView::~AISAppView() { + receiver_model.disable(); EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); } diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 203fa98f1..ab4c4ba88 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -112,9 +112,15 @@ ERTAppView::ERTAppView(NavigationView&) { .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(2500000); + receiver_model.set_rf_amp(false); + receiver_model.set_lna(32); + receiver_model.set_vga(32); + receiver_model.set_tuning_frequency(911600000); + receiver_model.enable(); } ERTAppView::~ERTAppView() { + receiver_model.disable(); EventDispatcher::message_map().unregister_handler(Message::ID::ERTPacket); } diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 74cf4c133..6073e0516 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -218,9 +218,15 @@ TPMSAppView::TPMSAppView(NavigationView&) { .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); + receiver_model.set_rf_amp(false); + receiver_model.set_lna(32); + receiver_model.set_vga(32); + receiver_model.set_tuning_frequency(315000000); + receiver_model.enable(); } TPMSAppView::~TPMSAppView() { + receiver_model.disable(); EventDispatcher::message_map().unregister_handler(Message::ID::TPMSPacket); } From c1f7f2336737d962706e34ef482116adf4479b7a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 25 Jan 2016 11:47:59 -0800 Subject: [PATCH 374/452] Add AIS channel control. --- firmware/application/ais_app.cpp | 21 ++++++++++++++++++--- firmware/application/ais_app.hpp | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index 4c134ca0e..ef96ec09b 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -299,6 +299,8 @@ void AISRecentEntryDetailView::set_entry(const AISRecentEntry& entry) { AISAppView::AISAppView(NavigationView&) { add_children({ { + &label_channel, + &options_channel, &recent_entries_view, &recent_entry_detail_view, } }); @@ -315,6 +317,11 @@ AISAppView::AISAppView(NavigationView&) { } ); + options_channel.on_change = [this](size_t, OptionsField::value_t v) { + this->on_frequency_changed(v); + }; + options_channel.set_by_value(162025000); + receiver_model.set_baseband_configuration({ .mode = 3, .sampling_rate = 2457600, @@ -324,7 +331,6 @@ AISAppView::AISAppView(NavigationView&) { receiver_model.set_rf_amp(false); receiver_model.set_lna(32); receiver_model.set_vga(32); - receiver_model.set_tuning_frequency(162025000); receiver_model.enable(); recent_entries_view.on_select = [this](const AISRecentEntry& entry) { @@ -340,10 +346,15 @@ AISAppView::~AISAppView() { EventDispatcher::message_map().unregister_handler(Message::ID::AISPacket); } +void AISAppView::focus() { + options_channel.focus(); +} + void AISAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); - recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); - recent_entry_detail_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); + const Rect content_rect { 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height }; + recent_entries_view.set_parent_rect(content_rect); + recent_entry_detail_view.set_parent_rect(content_rect); } void AISAppView::on_packet(const ais::Packet& packet) { @@ -370,4 +381,8 @@ void AISAppView::on_show_detail(const AISRecentEntry& entry) { recent_entry_detail_view.focus(); } +void AISAppView::on_frequency_changed(const uint32_t new_frequency) { + receiver_model.set_tuning_frequency(new_frequency); +} + } /* namespace ui */ diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index c0352bc3e..8dd078bd0 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -140,6 +140,8 @@ public: // TODO: Add flag to View that specifies view does not need to be cleared before painting. void paint(Painter&) override { }; + void focus() override; + private: AISRecentEntries recent; AISLogger logger; @@ -147,9 +149,27 @@ private: AISRecentEntriesView recent_entries_view { recent }; AISRecentEntryDetailView recent_entry_detail_view; + static constexpr auto header_height = 1 * 16; + + Text label_channel { + { 0 * 8, 0 * 16, 2 * 8, 1 * 16 }, + "Ch" + }; + + OptionsField options_channel { + { 3 * 8, 0 * 16 }, + 3, + { + { "87B", 161975000 }, + { "88B", 162025000 }, + } + }; + void on_packet(const ais::Packet& packet); void on_show_list(); void on_show_detail(const AISRecentEntry& entry); + + void on_frequency_changed(const uint32_t new_frequency); }; } /* namespace ui */ From a13e19a907cafc340c7c480defe6437272edcce7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Jan 2016 13:00:36 -0800 Subject: [PATCH 375/452] Paint background of Text object before string. --- firmware/application/ais_app.cpp | 1 + firmware/common/ui_widget.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index ef96ec09b..c688ae3bf 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -299,6 +299,7 @@ void AISRecentEntryDetailView::set_entry(const AISRecentEntry& entry) { AISAppView::AISAppView(NavigationView&) { add_children({ { + &label_app_name, &label_channel, &options_channel, &recent_entries_view, diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 8564514ea..3cddbd408 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -291,9 +291,14 @@ void Text::set(const std::string value) { } void Text::paint(Painter& painter) { + const auto rect = screen_rect(); + const auto s = style(); + + painter.fill_rectangle(rect, s.background); + painter.draw_string( - screen_pos(), - style(), + rect.pos, + s, text ); } From 0efe2ea0ae22691e78c25f3e22f231bfcc4132f2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Jan 2016 13:01:16 -0800 Subject: [PATCH 376/452] Add virtual title() to View class. --- firmware/common/ui_widget.cpp | 4 ++++ firmware/common/ui_widget.hpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 3cddbd408..8053d9fd7 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -247,6 +247,10 @@ Widget* View::initial_focus() { return nullptr; } +std::string View::title() const { + return ""; +}; + /* Rectangle *************************************************************/ Rectangle::Rectangle( diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index f2e18364e..d292d8e2a 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -155,6 +155,8 @@ public: virtual Widget* initial_focus(); + virtual std::string title() const; + protected: std::vector children_; Rect dirty_screen_rect; From dc42525dcb04acaa9e6ef0d03a18fddca0f7a98b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Jan 2016 13:04:19 -0800 Subject: [PATCH 377/452] Oops, removed line that should've been in prior commit. --- firmware/application/ais_app.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index c688ae3bf..ef96ec09b 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -299,7 +299,6 @@ void AISRecentEntryDetailView::set_entry(const AISRecentEntry& entry) { AISAppView::AISAppView(NavigationView&) { add_children({ { - &label_app_name, &label_channel, &options_channel, &recent_entries_view, From 7fe8288737776435a4070e8b43a58678739aeec3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Jan 2016 13:04:44 -0800 Subject: [PATCH 378/452] Set Navigation title with View.title() if not empty. --- firmware/application/ui_navigation.cpp | 15 ++++++++++++--- firmware/application/ui_navigation.hpp | 11 +++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index d9f7a107b..e2c76b6c0 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -41,7 +41,7 @@ namespace ui { SystemStatusView::SystemStatusView() { add_children({ { &button_back, - &portapack, + &title, &sd_card_status_view, } }); sd_card_status_view.set_parent_rect({ 28 * 8, 0 * 16, 2 * 8, 1 * 16 }); @@ -57,6 +57,14 @@ void SystemStatusView::set_back_visible(bool new_value) { button_back.hidden(!new_value); } +void SystemStatusView::set_title(const std::string new_value) { + if( new_value.empty() ) { + title.set(default_title); + } else { + title.set(new_value); + } +} + /* Navigation ************************************************************/ bool NavigationView::is_top() const { @@ -97,7 +105,7 @@ void NavigationView::update_view() { set_dirty(); if( on_view_changed ) { - on_view_changed(); + on_view_changed(*new_view); } } @@ -176,8 +184,9 @@ SystemView::SystemView( { 0, status_view_height }, { parent_rect.width(), static_cast(parent_rect.height() - status_view_height) } }); - navigation_view.on_view_changed = [this]() { + navigation_view.on_view_changed = [this](const View& new_view) { this->status_view.set_back_visible(!this->navigation_view.is_top()); + this->status_view.set_title(new_view.title()); }; // Initial view. diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 01ff26b6c..5dab355b4 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -44,16 +44,19 @@ public: SystemStatusView(); void set_back_visible(bool new_value); + void set_title(const std::string new_value); private: + static constexpr auto default_title = "PortaPack"; + Button button_back { { 0 * 8, 0 * 16, 3 * 8, 16 }, " < ", }; - Text portapack { - { 3 * 8, 0, 9 * 8, 1 * 16 }, - "PortaPack", + Text title { + { 3 * 8, 0, 16 * 8, 1 * 16 }, + default_title, }; SDCardStatusView sd_card_status_view; @@ -61,7 +64,7 @@ private: class NavigationView : public View { public: - std::function on_view_changed; + std::function on_view_changed; NavigationView() { } From bd829d7d851ca3e504ac2fd3bbe9d7a0c558bca8 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Jan 2016 13:08:46 -0800 Subject: [PATCH 379/452] Add titles for transponder apps. --- firmware/application/ais_app.hpp | 2 ++ firmware/application/ert_app.hpp | 2 ++ firmware/application/tpms_app.hpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/firmware/application/ais_app.hpp b/firmware/application/ais_app.hpp index 8dd078bd0..73b005d30 100644 --- a/firmware/application/ais_app.hpp +++ b/firmware/application/ais_app.hpp @@ -142,6 +142,8 @@ public: void focus() override; + std::string title() const override { return "AIS"; }; + private: AISRecentEntries recent; AISLogger logger; diff --git a/firmware/application/ert_app.hpp b/firmware/application/ert_app.hpp index 6100441a8..996dad67c 100644 --- a/firmware/application/ert_app.hpp +++ b/firmware/application/ert_app.hpp @@ -83,6 +83,8 @@ public: // TODO: Add flag to View that specifies view does not need to be cleared before painting. void paint(Painter&) override { }; + std::string title() const override { return "ERT"; }; + private: ERTRecentEntries recent; ERTLogger logger; diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index 56e820ddb..ac3486cd3 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -207,6 +207,8 @@ public: // TODO: Add flag to View that specifies view does not need to be cleared before painting. void paint(Painter&) override { }; + std::string title() const override { return "TPMS"; }; + private: TPMSRecentEntries recent; TPMSLogger logger; From cac9f02c48284f365d41c63ea3bc31217597a33f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 26 Jan 2016 17:25:51 -0800 Subject: [PATCH 380/452] Add simple column headers to recents list views. --- firmware/application/ais_app.cpp | 9 +++++++++ firmware/application/ert_app.cpp | 9 +++++++++ firmware/application/recent_entries.hpp | 16 ++++++++++++++++ firmware/application/tpms_app.cpp | 9 +++++++++ 4 files changed, 43 insertions(+) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index ef96ec09b..e186d1fa6 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -218,6 +218,15 @@ void AISRecentEntry::update(const ais::Packet& packet) { namespace ui { +template<> +void RecentEntriesView::draw_header( + const Rect& target_rect, + Painter& painter, + const Style& style +) { + painter.draw_string(target_rect.pos, style, " MMSI |Name/Call "); +} + template<> void RecentEntriesView::draw( const Entry& entry, diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index ab4c4ba88..749824257 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -71,6 +71,15 @@ void ERTRecentEntry::update(const ert::Packet& packet) { namespace ui { +template<> +void RecentEntriesView::draw_header( + const Rect& target_rect, + Painter& painter, + const Style& style +) { + painter.draw_string(target_rect.pos, style, " ID | Consumpt |Cnt "); +} + template<> void RecentEntriesView::draw( const Entry& entry, diff --git a/firmware/application/recent_entries.hpp b/firmware/application/recent_entries.hpp index 68c8c4a45..87d647ecb 100644 --- a/firmware/application/recent_entries.hpp +++ b/firmware/application/recent_entries.hpp @@ -23,6 +23,7 @@ #define __RECENT_ENTRIES_H__ #include "ui_widget.hpp" +#include "ui_font_fixed_8x16.hpp" #include #include @@ -138,6 +139,15 @@ public: Rect target_rect { r.pos, { r.width(), s.font.line_height() }}; const size_t visible_item_count = r.height() / s.font.line_height(); + const Style style_header { + .font = font::fixed_8x16, + .background = Color::blue(), + .foreground = Color::white(), + }; + + draw_header(target_rect, painter, style_header); + target_rect.pos.y += target_rect.height(); + auto selected = recent.find(selected_key); if( selected == std::end(recent) ) { selected = std::begin(recent); @@ -208,6 +218,12 @@ private: set_dirty(); } + void draw_header( + const Rect& target_rect, + Painter& painter, + const Style& style + ); + void draw( const Entry& entry, const Rect& target_rect, diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 6073e0516..2ca0e06d5 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -165,6 +165,15 @@ void TPMSRecentEntry::update(const tpms::Reading& reading) { namespace ui { +template<> +void RecentEntriesView::draw_header( + const Rect& target_rect, + Painter& painter, + const Style& style +) { + painter.draw_string(target_rect.pos, style, "Tp| ID |kPa| C |Cnt "); +} + template<> void RecentEntriesView::draw( const Entry& entry, From cb403160b3a22696d65edba05515c008d80448b0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 09:02:17 -0800 Subject: [PATCH 381/452] Really dumb list view columns structures. --- firmware/application/ais_app.cpp | 17 ++++++++++++++++- firmware/application/ert_app.cpp | 18 +++++++++++++++++- firmware/application/tpms_app.cpp | 20 +++++++++++++++++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/firmware/application/ais_app.cpp b/firmware/application/ais_app.cpp index e186d1fa6..c3867e347 100644 --- a/firmware/application/ais_app.cpp +++ b/firmware/application/ais_app.cpp @@ -218,13 +218,28 @@ void AISRecentEntry::update(const ais::Packet& packet) { namespace ui { +static const std::array, 2> ais_columns { { + { "MMSI", 9 }, + { "Name/Call", 20 }, +} }; + template<> void RecentEntriesView::draw_header( const Rect& target_rect, Painter& painter, const Style& style ) { - painter.draw_string(target_rect.pos, style, " MMSI |Name/Call "); + auto x = 0; + for(const auto& column : ais_columns) { + const auto width = column.second; + auto text = column.first; + if( width > text.length() ) { + text.append(width - text.length(), ' '); + } + + painter.draw_string({ x, target_rect.pos.y }, style, text); + x += (width * 8) + 8; + } } template<> diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 749824257..0fb8b709c 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -71,13 +71,29 @@ void ERTRecentEntry::update(const ert::Packet& packet) { namespace ui { +static const std::array, 3> ert_columns { { + { "ID", 10 }, + { "Consumpt", 10 }, + { "Cnt", 3 }, +} }; + template<> void RecentEntriesView::draw_header( const Rect& target_rect, Painter& painter, const Style& style ) { - painter.draw_string(target_rect.pos, style, " ID | Consumpt |Cnt "); + auto x = 0; + for(const auto& column : ert_columns) { + const auto width = column.second; + auto text = column.first; + if( width > text.length() ) { + text.append(width - text.length(), ' '); + } + + painter.draw_string({ x, target_rect.pos.y }, style, text); + x += (width * 8) + 8; + } } template<> diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index 2ca0e06d5..a7e4e5eca 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -165,13 +165,31 @@ void TPMSRecentEntry::update(const tpms::Reading& reading) { namespace ui { +static const std::array, 5> tpms_columns { { + { "Tp", 2 }, + { "ID", 8 }, + { "kPa", 3 }, + { "C", 3 }, + { "Cnt", 3 }, +} }; + template<> void RecentEntriesView::draw_header( const Rect& target_rect, Painter& painter, const Style& style ) { - painter.draw_string(target_rect.pos, style, "Tp| ID |kPa| C |Cnt "); + auto x = 0; + for(const auto& column : tpms_columns) { + const auto width = column.second; + auto text = column.first; + if( width > text.length() ) { + text.append(width - text.length(), ' '); + } + + painter.draw_string({ x, target_rect.pos.y }, style, text); + x += (width * 8) + 8; + } } template<> From 07b8c6c6615ba82c27456d0deea6513c25af00d1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 10:18:44 -0800 Subject: [PATCH 382/452] Fix initial focus on ERT, TPMS apps. --- firmware/application/ert_app.cpp | 4 ++++ firmware/application/ert_app.hpp | 2 ++ firmware/application/tpms_app.cpp | 4 ++++ firmware/application/tpms_app.hpp | 2 ++ 4 files changed, 12 insertions(+) diff --git a/firmware/application/ert_app.cpp b/firmware/application/ert_app.cpp index 0fb8b709c..9ca5800da 100644 --- a/firmware/application/ert_app.cpp +++ b/firmware/application/ert_app.cpp @@ -149,6 +149,10 @@ ERTAppView::~ERTAppView() { EventDispatcher::message_map().unregister_handler(Message::ID::ERTPacket); } +void ERTAppView::focus() { + recent_entries_view.focus(); +} + void ERTAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); diff --git a/firmware/application/ert_app.hpp b/firmware/application/ert_app.hpp index 996dad67c..065f7f9bf 100644 --- a/firmware/application/ert_app.hpp +++ b/firmware/application/ert_app.hpp @@ -83,6 +83,8 @@ public: // TODO: Add flag to View that specifies view does not need to be cleared before painting. void paint(Painter&) override { }; + void focus() override; + std::string title() const override { return "ERT"; }; private: diff --git a/firmware/application/tpms_app.cpp b/firmware/application/tpms_app.cpp index a7e4e5eca..2cc05c084 100644 --- a/firmware/application/tpms_app.cpp +++ b/firmware/application/tpms_app.cpp @@ -257,6 +257,10 @@ TPMSAppView::~TPMSAppView() { EventDispatcher::message_map().unregister_handler(Message::ID::TPMSPacket); } +void TPMSAppView::focus() { + recent_entries_view.focus(); +} + void TPMSAppView::set_parent_rect(const Rect new_parent_rect) { View::set_parent_rect(new_parent_rect); recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() }); diff --git a/firmware/application/tpms_app.hpp b/firmware/application/tpms_app.hpp index ac3486cd3..0ecf48847 100644 --- a/firmware/application/tpms_app.hpp +++ b/firmware/application/tpms_app.hpp @@ -207,6 +207,8 @@ public: // TODO: Add flag to View that specifies view does not need to be cleared before painting. void paint(Painter&) override { }; + void focus() override; + std::string title() const override { return "TPMS"; }; private: From 60778c55915fc4b1e3b6c1d7ab6f215ce91206af Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 10:49:17 -0800 Subject: [PATCH 383/452] Another tweak to sane-ify transponder apps initial focus. --- firmware/application/recent_entries.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/firmware/application/recent_entries.hpp b/firmware/application/recent_entries.hpp index 87d647ecb..8fbbb71ad 100644 --- a/firmware/application/recent_entries.hpp +++ b/firmware/application/recent_entries.hpp @@ -186,11 +186,15 @@ public: return false; } + void on_focus() override { + advance(0); + } + private: Entries& recent; using EntryKey = typename Entry::Key; - EntryKey selected_key; + EntryKey selected_key = Entry::invalid_key; void advance(const int32_t amount) { auto selected = recent.find(selected_key); From 34434c088cd8e8905332cd0168ff1f093986320d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 11:01:50 -0800 Subject: [PATCH 384/452] Clean up audio receiver UI fields layout. --- firmware/application/ui_receiver.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 515118283..1c9c84cbc 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -364,23 +364,23 @@ public: private: RSSI rssi { - { 19 * 8, 0, 11 * 8, 4 }, + { 21 * 8, 0, 6 * 8, 4 }, }; Channel channel { - { 19 * 8, 5, 11 * 8, 4 }, + { 21 * 8, 5, 6 * 8, 4 }, }; Audio audio { - { 19 * 8, 10, 11 * 8, 4 }, + { 21 * 8, 10, 6 * 8, 4 }, }; FrequencyField field_frequency { - { 0 * 8, 1 * 16 }, + { 5 * 8, 0 * 16 }, }; LNAGainField field_lna { - { 13 * 8, 1 * 16 } + { 15 * 8, 0 * 16 } }; /* BasebandBandwidthField options_baseband_bandwidth { @@ -388,7 +388,7 @@ private: }; */ NumberField field_vga { - { 16 * 8, 1 * 16}, + { 18 * 8, 0 * 16}, 2, { max2837::vga::gain_db_min, max2837::vga::gain_db_max }, max2837::vga::gain_db_step, @@ -396,7 +396,7 @@ private: }; OptionsField options_modulation { - { 19 * 8, 1 * 16 }, + { 0 * 8, 0 * 16 }, 4, { { " AM ", toUType(ReceiverModel::Mode::AMAudio) }, @@ -425,7 +425,7 @@ private: }; NumberField field_volume { - { 28 * 8, 1 * 16 }, + { 28 * 8, 0 * 16 }, 2, { 0, 99 }, 1, @@ -433,12 +433,12 @@ private: }; FrequencyOptionsView view_frequency_options { - { 0 * 8, 2 * 16, 30 * 8, 1 * 16 }, + { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, &style_options_group }; RadioGainOptionsView view_rf_gain_options { - { 0 * 8, 2 * 16, 30 * 8, 1 * 16 }, + { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, &style_options_group }; From 87a6f931c9d99f99b57c8f8be6385431924f41da Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 11:03:37 -0800 Subject: [PATCH 385/452] Remove commented and unused code. --- firmware/application/ui_receiver.cpp | 22 ++-------------------- firmware/application/ui_receiver.hpp | 25 +------------------------ 2 files changed, 3 insertions(+), 44 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index d4996dbab..09b6540c8 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -371,10 +371,8 @@ ReceiverView::ReceiverView( &audio, &field_frequency, &field_lna, - //&options_baseband_bandwidth, &field_vga, &options_modulation, - //&options_baseband_oversampling, &field_volume, &view_frequency_options, &view_rf_gain_options, @@ -404,13 +402,7 @@ ReceiverView::ReceiverView( field_lna.on_show_options = [this]() { this->on_show_options_rf_gain(); }; - /* - options_baseband_bandwidth.set_by_value(receiver_model.baseband_bandwidth()); - options_baseband_bandwidth.on_change = [this](size_t n, OptionsField::value_t v) { - (void)n; - this->on_baseband_bandwidth_changed(v); - }; - */ + field_vga.set_value(receiver_model.vga()); field_vga.on_change = [this](int32_t v_db) { this->on_vga_changed(v_db); @@ -421,13 +413,7 @@ ReceiverView::ReceiverView( (void)n; this->on_modulation_changed(static_cast(v)); }; -/* - options_baseband_oversampling.set_by_value(receiver_model.baseband_oversampling()); - options_baseband_oversampling.on_change = [this](size_t n, OptionsField::value_t v) { - (void)n; - this->on_baseband_oversampling_changed(v); - }; -*/ + field_volume.set_value((receiver_model.headphone_volume() - wolfson::wm8731::headphone_gain_range.max).decibel() + 99); field_volume.on_change = [this](int32_t v) { this->on_headphone_volume_changed(v); @@ -555,8 +541,4 @@ void ReceiverView::on_headphone_volume_changed(int32_t v) { receiver_model.set_headphone_volume(new_volume); } -// void ReceiverView::on_baseband_oversampling_changed(int32_t v) { -// receiver_model.set_baseband_oversampling(v); -// } - } /* namespace ui */ diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 1c9c84cbc..e75ad075f 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -382,11 +382,7 @@ private: LNAGainField field_lna { { 15 * 8, 0 * 16 } }; - /* - BasebandBandwidthField options_baseband_bandwidth { - { 15 * 8, 1 * 16 }, - }; - */ + NumberField field_vga { { 18 * 8, 0 * 16}, 2, @@ -405,24 +401,6 @@ private: { "SPEC", toUType(ReceiverModel::Mode::SpectrumAnalysis) }, } }; -/* - OptionsField options_baseband_oversampling { - { 24 * 8, 1 * 16 }, - 1, - { - { "4", 4 }, - { "6", 6 }, - { "8", 8 }, - } - }; -*/ - NumberField field_vregmode { - { 24 * 8, 1 * 16 }, - 1, - { 0, 1 }, - 1, - ' ', - }; NumberField field_volume { { 28 * 8, 0 * 16 }, @@ -455,7 +433,6 @@ private: void on_frequency_step_changed(rf::Frequency f); void on_reference_ppm_correction_changed(int32_t v); void on_headphone_volume_changed(int32_t v); -// void on_baseband_oversampling_changed(int32_t v); void on_edit_frequency(); }; From c761d3aaa8352c2a4c0760706c5d29906f1bce78 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 11:48:22 -0800 Subject: [PATCH 386/452] Fix RSSI meter scaling, clean up limits code. --- firmware/application/ui_rssi.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/firmware/application/ui_rssi.cpp b/firmware/application/ui_rssi.cpp index 629b66d41..644c438ea 100644 --- a/firmware/application/ui_rssi.cpp +++ b/firmware/application/ui_rssi.cpp @@ -41,18 +41,19 @@ void RSSI::on_hide() { void RSSI::paint(Painter& painter) { const auto r = screen_rect(); - /* - constexpr int32_t rssi_min = 0.# * 256 / 3.3; - constexpr int32_t rssi_max = 2.5 * 256 / 3.3; - // (23 - 194) / 2 - */ - /* TODO: Clip maximum */ - constexpr int32_t raw_min = 23; + + constexpr int32_t rssi_sample_range = 256; + constexpr float rssi_voltage_min = 0.4; + constexpr float rssi_voltage_max = 2.2; + constexpr float adc_voltage_max = 3.3; + constexpr int32_t raw_min = rssi_sample_range * rssi_voltage_min / adc_voltage_max; + constexpr int32_t raw_max = rssi_sample_range * rssi_voltage_max / adc_voltage_max; + constexpr int32_t raw_delta = raw_max - raw_min; const int32_t x_0 = 0; - const int32_t x_min = std::max(x_0, (min_ - raw_min) / 2); - const int32_t x_avg = std::max(x_min, (avg_ - raw_min) / 2); - const int32_t x_max = std::max(x_avg + 1, (max_ - raw_min) / 2); const int32_t x_lim = r.width(); + const int32_t x_min = std::max(x_0, (min_ - raw_min) * x_lim / raw_delta); + const int32_t x_avg = std::max(x_min, (avg_ - raw_min) * x_lim / raw_delta); + const int32_t x_max = std::max(x_avg + 1, (max_ - raw_min) * x_lim / raw_delta); const Rect r0 { static_cast(r.left() + x_0), r.top(), From 018b54c71126285cf94c7fa69994f2f58bc14cad Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 12:09:36 -0800 Subject: [PATCH 387/452] Extract range_t to utility header. --- .../common/portapack_persistent_memory.cpp | 20 ++----------------- firmware/common/utility.hpp | 18 +++++++++++++++++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 6c44f0fdc..63ace6634 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -23,30 +23,14 @@ #include "hal.h" +#include "utility.hpp" + #include #include namespace portapack { namespace persistent_memory { -/* TODO: This is widely applicable. Factor this to somewhere useful. */ -template -struct range_t { - const T minimum; - const T maximum; - - const T& clip(const T& value) const { - return std::max(std::min(value, maximum), minimum); - } - - void reset_if_outside(T& value, const T& reset_value) const { - if( (value < minimum ) || - (value > maximum ) ) { - value = reset_value; - } - } -}; - using tuned_frequency_range_t = range_t; constexpr tuned_frequency_range_t tuned_frequency_range { rf::tuning_range.min, rf::tuning_range.max }; constexpr rf::Frequency tuned_frequency_reset_value { 858750000 }; diff --git a/firmware/common/utility.hpp b/firmware/common/utility.hpp index b1d00b65a..fc8a3b3cb 100644 --- a/firmware/common/utility.hpp +++ b/firmware/common/utility.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -70,6 +71,23 @@ inline float magnitude_squared(const std::complex c) { return r2 + i2; } +template +struct range_t { + const T minimum; + const T maximum; + + const T& clip(const T& value) const { + return std::max(std::min(value, maximum), minimum); + } + + void reset_if_outside(T& value, const T& reset_value) const { + if( (value < minimum ) || + (value > maximum ) ) { + value = reset_value; + } + } +}; + namespace std { /*! Stephan T Lavavej (STL!) implementation of make_unique, which has been accepted into the C++14 standard. From 6917a381061aec46c4700ece956d52c016d154f0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 12:50:33 -0800 Subject: [PATCH 388/452] Improve clipping of RSSI, baseband, audio bar graphs. --- firmware/application/ui_audio.cpp | 20 ++++++++++++-------- firmware/application/ui_channel.cpp | 17 ++++++++++------- firmware/application/ui_rssi.cpp | 27 +++++++++++++++------------ 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/firmware/application/ui_audio.cpp b/firmware/application/ui_audio.cpp index b85e0dd99..65fd3832e 100644 --- a/firmware/application/ui_audio.cpp +++ b/firmware/application/ui_audio.cpp @@ -23,6 +23,8 @@ #include "event_m0.hpp" +#include "utility.hpp" + #include namespace ui { @@ -42,15 +44,17 @@ void Audio::on_hide() { void Audio::paint(Painter& painter) { const auto r = screen_rect(); - const int32_t db_min = -r.width(); - const int32_t x_0 = 0; - const int32_t x_rms = std::max(x_0, rms_db_ - db_min); - const int32_t x_max = std::max(x_rms + 1, max_db_ - db_min); - const int32_t x_lim = r.width(); + constexpr int db_min = -96; + constexpr int db_max = 0; + constexpr int db_delta = db_max - db_min; + const range_t x_rms_range { 0, r.width() - 1 }; + const auto x_rms = x_rms_range.clip((rms_db_ - db_min) * r.width() / db_delta); + const range_t x_max_range { x_rms + 1, r.width() }; + const auto x_max = x_max_range.clip((max_db_ - db_min) * r.width() / db_delta); const Rect r0 { - static_cast(r.left() + x_0), r.top(), - static_cast(x_rms - x_0), r.height() + static_cast(r.left()), r.top(), + static_cast(x_rms), r.height() }; painter.fill_rectangle( r0, @@ -77,7 +81,7 @@ void Audio::paint(Painter& painter) { const Rect r3 { static_cast(r.left() + x_max), r.top(), - static_cast(x_lim - x_max), r.height() + static_cast(r.width() - x_max), r.height() }; painter.fill_rectangle( r3, diff --git a/firmware/application/ui_channel.cpp b/firmware/application/ui_channel.cpp index cdcb8d736..62f1b49a3 100644 --- a/firmware/application/ui_channel.cpp +++ b/firmware/application/ui_channel.cpp @@ -23,6 +23,8 @@ #include "event_m0.hpp" +#include "utility.hpp" + #include namespace ui { @@ -42,14 +44,15 @@ void Channel::on_hide() { void Channel::paint(Painter& painter) { const auto r = screen_rect(); - const int32_t db_min = -r.width(); - const int32_t x_0 = 0; - const int32_t x_max = std::max(x_0, max_db_ - db_min); - const int32_t x_lim = r.width(); + constexpr int db_min = -96; + constexpr int db_max = 0; + constexpr int db_delta = db_max - db_min; + const range_t x_max_range { 0, r.width() - 1 }; + const auto x_max = x_max_range.clip((max_db_ - db_min) * r.width() / db_delta); const Rect r0 { - static_cast(r.left() + x_0), r.top(), - static_cast(x_max - x_0), r.height() + static_cast(r.left()), r.top(), + static_cast(x_max), r.height() }; painter.fill_rectangle( r0, @@ -67,7 +70,7 @@ void Channel::paint(Painter& painter) { const Rect r2 { static_cast(r.left() + x_max + 1), r.top(), - static_cast(x_lim - (x_max + 1)), r.height() + static_cast(r.width() - (x_max + 1)), r.height() }; painter.fill_rectangle( r2, diff --git a/firmware/application/ui_rssi.cpp b/firmware/application/ui_rssi.cpp index 644c438ea..a56468634 100644 --- a/firmware/application/ui_rssi.cpp +++ b/firmware/application/ui_rssi.cpp @@ -23,6 +23,8 @@ #include "event_m0.hpp" +#include "utility.hpp" + #include namespace ui { @@ -42,22 +44,23 @@ void RSSI::on_hide() { void RSSI::paint(Painter& painter) { const auto r = screen_rect(); - constexpr int32_t rssi_sample_range = 256; + constexpr int rssi_sample_range = 256; constexpr float rssi_voltage_min = 0.4; constexpr float rssi_voltage_max = 2.2; constexpr float adc_voltage_max = 3.3; - constexpr int32_t raw_min = rssi_sample_range * rssi_voltage_min / adc_voltage_max; - constexpr int32_t raw_max = rssi_sample_range * rssi_voltage_max / adc_voltage_max; - constexpr int32_t raw_delta = raw_max - raw_min; - const int32_t x_0 = 0; - const int32_t x_lim = r.width(); - const int32_t x_min = std::max(x_0, (min_ - raw_min) * x_lim / raw_delta); - const int32_t x_avg = std::max(x_min, (avg_ - raw_min) * x_lim / raw_delta); - const int32_t x_max = std::max(x_avg + 1, (max_ - raw_min) * x_lim / raw_delta); + constexpr int raw_min = rssi_sample_range * rssi_voltage_min / adc_voltage_max; + constexpr int raw_max = rssi_sample_range * rssi_voltage_max / adc_voltage_max; + constexpr int raw_delta = raw_max - raw_min; + const range_t x_avg_range { 0, r.width() - 1 }; + const auto x_avg = x_avg_range.clip((avg_ - raw_min) * r.width() / raw_delta); + const range_t x_min_range { 0, x_avg }; + const auto x_min = x_min_range.clip((min_ - raw_min) * r.width() / raw_delta); + const range_t x_max_range { x_avg + 1, r.width() }; + const auto x_max = x_max_range.clip((max_ - raw_min) * r.width() / raw_delta); const Rect r0 { - static_cast(r.left() + x_0), r.top(), - static_cast(x_min - x_0), r.height() + static_cast(r.left()), r.top(), + static_cast(x_min), r.height() }; painter.fill_rectangle( r0, @@ -93,7 +96,7 @@ void RSSI::paint(Painter& painter) { const Rect r4 { static_cast(r.left() + x_max), r.top(), - static_cast(x_lim - x_max), r.height() + static_cast(r.width() - x_max), r.height() }; painter.fill_rectangle( r4, From 3b7bec542c5739354edd33440cc23fa7196286cb Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 14:20:15 -0800 Subject: [PATCH 389/452] Move and adjust variable controlling size of audio RX waterfall. Closes recently-opened gap between control UI and waterfall. --- firmware/application/ui_receiver.cpp | 1 - firmware/application/ui_receiver.hpp | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 09b6540c8..670268051 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -505,7 +505,6 @@ void ReceiverView::on_modulation_changed(ReceiverModel::Mode mode) { if( widget_content ) { add_child(widget_content.get()); - const ui::Dim header_height = 3 * 16; const ui::Rect rect { 0, header_height, parent_rect.width(), static_cast(parent_rect.height() - header_height) }; widget_content->set_parent_rect(rect); } diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index e75ad075f..91950834e 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -363,6 +363,8 @@ public: void focus() override; private: + static constexpr ui::Dim header_height = 2 * 16; + RSSI rssi { { 21 * 8, 0, 6 * 8, 4 }, }; From ca3b1a2c5a6c846492556e5aa70e48b853dadcab Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 14:25:08 -0800 Subject: [PATCH 390/452] Remove more commented code. --- firmware/application/ui_receiver.cpp | 31 ---------------------------- firmware/application/ui_receiver.hpp | 22 -------------------- 2 files changed, 53 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 670268051..f8bdf7488 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -98,25 +98,7 @@ bool FrequencyField::on_key(const ui::KeyEvent event) { } return false; } -/* -bool FrequencyField::on_key(const ui::KeyEvent event) override { - if( event == ui::KeyEvent::Select ) { - // NOTE: For testing sampling rate / decimation combinations - turbo = !turbo; - if( turbo ) { - clock_manager.set_sampling_frequency(18432000); - radio::set_baseband_decimation_by(6); - } else { - clock_manager.set_sampling_frequency(12288000); - radio::set_baseband_decimation_by(4); - } - return true; - } - - return false; -} -*/ bool FrequencyField::on_encoder(const EncoderEvent delta) { set_value(value() + (delta * step)); return true; @@ -310,19 +292,11 @@ RadioGainOptionsView::RadioGainOptionsView( add_children({ { &label_rf_amp, &field_rf_amp, - //&label_agc, - //&field_agc } }); field_rf_amp.on_change = [this](int32_t v) { this->on_rf_amp_changed(v); }; - /* - field_agc.set_value(receiver_model.agc()); - field_agc.on_change = [this](int32_t v) { - this->on_agc_changed(v); - }; - */ } void RadioGainOptionsView::set_rf_amp(int32_t v_db) { @@ -334,11 +308,6 @@ void RadioGainOptionsView::on_rf_amp_changed(bool enable) { on_change_rf_amp(enable); } } -/* -void RadioGainOptionsView::on_agc_changed(bool v) { - receiver_model.set_agc(v); -} -*/ /* LNAGainField **********************************************************/ diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 91950834e..78046e762 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -72,8 +72,6 @@ private: rf::Frequency value_; rf::Frequency step { 25000 }; - //bool turbo { false }; - rf::Frequency clamp_value(rf::Frequency value); }; @@ -113,13 +111,6 @@ public: } void add_digit(const char c) { - /* - if( justify == Justify::Right ) { - push_right(c); - } else { - insert_right(c); - } - */ insert_right(c); } @@ -212,7 +203,6 @@ private: static constexpr int mhz_mod = pow(10, mhz_digits); static constexpr int submhz_base = pow(10, 6 - submhz_digits); - //static constexpr int submhz_mod = pow(10, submhz_digits); static constexpr int text_digits = mhz_digits + 1 + submhz_digits; Text text_value { @@ -321,18 +311,6 @@ private: 1, ' ', }; - /* - Text label_agc { - { 6 * 8, 0 * 16, 3 * 8, 1 * 16 }, - "AGC" - }; - - NumberField field_agc { - { 10 * 8, 0 * 16}, - 1, - { 0, 1 } - }; - */ void on_rf_amp_changed(bool enable); }; From 7519b83379873ca31b959e3deff1306ce780b0d1 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 14:46:45 -0800 Subject: [PATCH 391/452] Make better use of range_t methods. --- firmware/application/max2837.cpp | 10 ++--- firmware/application/max2837.hpp | 12 +++--- firmware/application/rf_path.hpp | 43 +++---------------- firmware/application/rffc507x.cpp | 10 +---- firmware/application/tuning.cpp | 8 ++-- firmware/application/ui_receiver.cpp | 8 +--- .../common/portapack_persistent_memory.cpp | 6 +-- firmware/common/utility.hpp | 14 ++++++ 8 files changed, 39 insertions(+), 72 deletions(-) diff --git a/firmware/application/max2837.cpp b/firmware/application/max2837.cpp index 7456a1bc4..e1c759c2a 100644 --- a/firmware/application/max2837.cpp +++ b/firmware/application/max2837.cpp @@ -196,18 +196,16 @@ void MAX2837::set_lpf_rf_bandwidth(const uint32_t bandwidth_minimum) { bool MAX2837::set_frequency(const rf::Frequency lo_frequency) { /* TODO: This is a sad implementation. Refactor. */ - if( lo_frequency < lo::band[0].min ) { - return false; - } else if( lo_frequency < lo::band[0].max ) { + if( lo::band[0].contains(lo_frequency) ) { _map.r.syn_int_div.LOGEN_BSW = 0b00; /* 2300 - 2399.99MHz */ _map.r.rxrf_1.LNAband = 0; /* 2.3 - 2.5GHz */ - } else if( lo_frequency < lo::band[1].max ) { + } else if( lo::band[1].contains(lo_frequency) ) { _map.r.syn_int_div.LOGEN_BSW = 0b01; /* 2400 - 2499.99MHz */ _map.r.rxrf_1.LNAband = 0; /* 2.3 - 2.5GHz */ - } else if( lo_frequency < lo::band[2].max ) { + } else if( lo::band[2].contains(lo_frequency) ) { _map.r.syn_int_div.LOGEN_BSW = 0b10; /* 2500 - 2599.99MHz */ _map.r.rxrf_1.LNAband = 1; /* 2.5 - 2.7GHz */ - } else if( lo_frequency < lo::band[3].max ) { + } else if( lo::band[3].contains(lo_frequency) ) { _map.r.syn_int_div.LOGEN_BSW = 0b11; /* 2600 - 2700Hz */ _map.r.rxrf_1.LNAband = 1; /* 2.5 - 2.7GHz */ } else { diff --git a/firmware/application/max2837.hpp b/firmware/application/max2837.hpp index d4666c35b..43ffe8b2a 100644 --- a/firmware/application/max2837.hpp +++ b/firmware/application/max2837.hpp @@ -50,10 +50,10 @@ enum class Mode { namespace lo { constexpr std::array band { { - { .min = 2300000000, .max = 2400000000, }, - { .min = 2400000000, .max = 2500000000, }, - { .min = 2500000000, .max = 2600000000, }, - { .min = 2600000000, .max = 2700000000, }, + { 2300000000, 2400000000 }, + { 2400000000, 2500000000 }, + { 2500000000, 2600000000 }, + { 2600000000, 2700000000 }, } }; } /* namespace lo */ @@ -67,8 +67,8 @@ constexpr int8_t gain_db_max = 40; constexpr int8_t gain_db_step = 8; constexpr std::array band { { - { .min = 2300000000, .max = 2500000000, }, - { .min = 2500000000, .max = 2700000000, }, + { 2300000000, 2500000000 }, + { 2500000000, 2700000000 }, } }; } /* namespace lna */ diff --git a/firmware/application/rf_path.hpp b/firmware/application/rf_path.hpp index 97cbaa08b..84a0a0b3e 100644 --- a/firmware/application/rf_path.hpp +++ b/firmware/application/rf_path.hpp @@ -22,29 +22,14 @@ #ifndef __RF_PATH_H__ #define __RF_PATH_H__ +#include "utility.hpp" + #include namespace rf { using Frequency = int64_t; - -struct FrequencyRange { - Frequency min; - Frequency max; - /* TODO: static_assert low < high? */ - - bool below_range(const Frequency f) const { - return f < min; - } - - bool contains(const Frequency f) const { - return (f >= min) && (f < max); - } - - bool out_of_range(const Frequency f) const { - return !contains(f); - } -}; +using FrequencyRange = range_t; enum class Direction { /* Zero-based, used as index into table */ @@ -54,20 +39,9 @@ enum class Direction { namespace path { -constexpr FrequencyRange band_low { - .min = 0, - .max = 2150000000, -}; - -constexpr FrequencyRange band_high { - .min = 2750000000, - .max = 7250000000, -}; - -constexpr FrequencyRange band_mid { - .min = band_low.max, - .max = band_high.min, -}; +constexpr FrequencyRange band_low { 0, 2150000000 }; +constexpr FrequencyRange band_high { 2750000000, 7250000000 }; +constexpr FrequencyRange band_mid { band_low.maximum, band_high.minimum }; enum class Band { /* Zero-based, used as index into frequency_bands table */ @@ -94,10 +68,7 @@ private: } /* path */ -constexpr FrequencyRange tuning_range { - .min = path::band_low.min, - .max = path::band_high.max, -}; +constexpr FrequencyRange tuning_range { path::band_low.minimum, path::band_high.maximum }; } /* rf */ diff --git a/firmware/application/rffc507x.cpp b/firmware/application/rffc507x.cpp index 6d466ea0d..e15265e47 100644 --- a/firmware/application/rffc507x.cpp +++ b/firmware/application/rffc507x.cpp @@ -51,10 +51,7 @@ constexpr auto reference_frequency = rffc5072_reference_f; namespace vco { -constexpr rf::FrequencyRange range { - .min = 2700000000U, - .max = 5400000000U, -}; +constexpr rf::FrequencyRange range { 2700000000, 5400000000 }; } /* namespace vco */ @@ -66,10 +63,7 @@ constexpr size_t divider_log2_max = 5; constexpr size_t divider_min = 1U << divider_log2_min; constexpr size_t divider_max = 1U << divider_log2_max; -constexpr rf::FrequencyRange range { - .min = vco::range.min / divider_max, - .max = vco::range.max / divider_min, -}; +constexpr rf::FrequencyRange range { vco::range.minimum / divider_max, vco::range.maximum / divider_min }; size_t divider_log2(const rf::Frequency lo_frequency) { /* TODO: Error */ diff --git a/firmware/application/tuning.cpp b/firmware/application/tuning.cpp index b662fbc3d..2519fc82d 100644 --- a/firmware/application/tuning.cpp +++ b/firmware/application/tuning.cpp @@ -83,13 +83,11 @@ Config high_band(const rf::Frequency target_frequency) { Config create(const rf::Frequency target_frequency) { /* TODO: This is some lame code. */ - if( target_frequency < rf::path::band_low.min ) { - return { }; - } else if( target_frequency < rf::path::band_low.max ) { + if( rf::path::band_low.contains(target_frequency) ) { return low_band(target_frequency); - } else if( target_frequency < rf::path::band_mid.max ) { + } else if( rf::path::band_mid.contains(target_frequency) ) { return mid_band(target_frequency); - } else if( target_frequency < rf::path::band_high.max ) { + } else if( rf::path::band_high.contains(target_frequency) ) { return high_band(target_frequency); } else { return { }; diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index f8bdf7488..e45c720e7 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -118,13 +118,7 @@ void FrequencyField::on_focus() { } rf::Frequency FrequencyField::clamp_value(rf::Frequency value) { - if( value > range.max ) { - value = range.max; - } - if( value < range.min ) { - value = range.min; - } - return value; + return range.clip(value); } /* FrequencyKeypadView ***************************************************/ diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 63ace6634..de4ce64aa 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -31,8 +31,6 @@ namespace portapack { namespace persistent_memory { -using tuned_frequency_range_t = range_t; -constexpr tuned_frequency_range_t tuned_frequency_range { rf::tuning_range.min, rf::tuning_range.max }; constexpr rf::Frequency tuned_frequency_reset_value { 858750000 }; using ppb_range_t = range_t; @@ -50,12 +48,12 @@ static_assert(sizeof(data_t) <= 0x100, "Persistent memory structure too large fo static data_t* const data = reinterpret_cast(LPC_BACKUP_REG_BASE); rf::Frequency tuned_frequency() { - tuned_frequency_range.reset_if_outside(data->tuned_frequency, tuned_frequency_reset_value); + rf::tuning_range.reset_if_outside(data->tuned_frequency, tuned_frequency_reset_value); return data->tuned_frequency; } void set_tuned_frequency(const rf::Frequency new_value) { - data->tuned_frequency = tuned_frequency_range.clip(new_value); + data->tuned_frequency = rf::tuning_range.clip(new_value); } ppb_t correction_ppb() { diff --git a/firmware/common/utility.hpp b/firmware/common/utility.hpp index fc8a3b3cb..2a2dc9f4c 100644 --- a/firmware/common/utility.hpp +++ b/firmware/common/utility.hpp @@ -86,6 +86,20 @@ struct range_t { value = reset_value; } } + + bool below_range(const T& value) const { + return value < minimum; + } + + bool contains(const T& value) const { + // TODO: Subtle gotcha here! Range test doesn't include maximum! + return (value >= minimum) && (value < maximum); + } + + bool out_of_range(const T& value) const { + // TODO: Subtle gotcha here! Range test in contains() doesn't include maximum! + return !contains(value); + } }; namespace std { From 87dc5a055b09ca2071b6102bcd57687ec3d2f464 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 14:55:03 -0800 Subject: [PATCH 392/452] More application of range_t methods. --- firmware/application/max2837.cpp | 4 ++-- firmware/application/max2837.hpp | 6 ++---- firmware/application/ui_receiver.cpp | 2 +- firmware/application/ui_receiver.hpp | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/firmware/application/max2837.cpp b/firmware/application/max2837.cpp index e1c759c2a..33e4a8b60 100644 --- a/firmware/application/max2837.cpp +++ b/firmware/application/max2837.cpp @@ -40,7 +40,7 @@ constexpr std::array lookup_8db_steps { }; static uint_fast8_t gain_ordinal(const int8_t db) { - int8_t db_sat = std::min(std::max(gain_db_min, db), gain_db_max); + const auto db_sat = gain_db_range.clip(db); return lna::lookup_8db_steps[(db_sat >> 3) & 7]; } @@ -49,7 +49,7 @@ static uint_fast8_t gain_ordinal(const int8_t db) { namespace vga { static uint_fast8_t gain_ordinal(const int8_t db) { - int8_t db_sat = std::min(std::max(gain_db_min, db), gain_db_max); + const auto db_sat = gain_db_range.clip(db); return ((db_sat >> 1) & 0b11111) ^ 0b11111; } diff --git a/firmware/application/max2837.hpp b/firmware/application/max2837.hpp index 43ffe8b2a..6c91ae58d 100644 --- a/firmware/application/max2837.hpp +++ b/firmware/application/max2837.hpp @@ -62,8 +62,7 @@ constexpr std::array band { { namespace lna { -constexpr int8_t gain_db_min = 0; -constexpr int8_t gain_db_max = 40; +constexpr range_t gain_db_range { 0, 40 }; constexpr int8_t gain_db_step = 8; constexpr std::array band { { @@ -77,8 +76,7 @@ constexpr std::array band { { namespace vga { -constexpr int8_t gain_db_min = 0; -constexpr int8_t gain_db_max = 62; +constexpr range_t gain_db_range { 0, 62 }; constexpr int8_t gain_db_step = 2; } /* namespace vga */ diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index e45c720e7..87c26527e 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -309,7 +309,7 @@ LNAGainField::LNAGainField( Point parent_pos ) : NumberField { parent_pos, 2, - { max2837::lna::gain_db_min, max2837::lna::gain_db_max }, + { max2837::lna::gain_db_range.minimum, max2837::lna::gain_db_range.maximum }, max2837::lna::gain_db_step, ' ', } diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 78046e762..dac6a028f 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -366,7 +366,7 @@ private: NumberField field_vga { { 18 * 8, 0 * 16}, 2, - { max2837::vga::gain_db_min, max2837::vga::gain_db_max }, + { max2837::vga::gain_db_range.minimum, max2837::vga::gain_db_range.maximum }, max2837::vga::gain_db_step, ' ', }; From 7876eb087785a4adf8adbcb0502b7b065da2881d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 15:26:39 -0800 Subject: [PATCH 393/452] Remove PPM "Corr." label. --- firmware/application/ui_receiver.cpp | 1 - firmware/application/ui_receiver.hpp | 5 ----- 2 files changed, 6 deletions(-) diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 87c26527e..4263a84c1 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -248,7 +248,6 @@ FrequencyOptionsView::FrequencyOptionsView( add_children({ { &text_step, &options_step, - &text_correction, &field_ppm, &text_ppm, } }); diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index dac6a028f..7d6b9e360 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -271,11 +271,6 @@ private: void on_step_changed(rf::Frequency v); void on_reference_ppm_correction_changed(int32_t v); - Text text_correction { - { 17 * 8, 0 * 16, 5 * 8, 16 }, - "Corr.", - }; - NumberField field_ppm { { 23 * 8, 0 * 16 }, 3, From 234ac5c50bcde45e68e07417e629852cd03dc3d9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 16:04:23 -0800 Subject: [PATCH 394/452] Additional audio receiver step sizes. Requested in issue #52, pull request #56. Added with qualifications the smaller step sizes, and a couple of more VHF-/UHF-y step sizes. --- firmware/application/ui_receiver.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 7d6b9e360..6ab202363 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -259,6 +259,10 @@ private: { { " 100", 100 }, { " 1k ", 1000 }, + { " 3k ", 3000 }, /* Approximate SSB bandwidth */ + { " 5k ", 5000 }, + { " 6k3", 6250 }, + { " 9k ", 9000 }, /* channel spacing for LF, MF in some regions */ { " 10k ", 10000 }, { " 12k5", 12500 }, { " 25k ", 25000 }, From 10f6554a1b8dad5703e2749c620f75028fe7b093 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 20:17:35 -0800 Subject: [PATCH 395/452] Remove extra #include. --- firmware/application/tuning.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/firmware/application/tuning.cpp b/firmware/application/tuning.cpp index 2519fc82d..5edc48524 100644 --- a/firmware/application/tuning.cpp +++ b/firmware/application/tuning.cpp @@ -19,8 +19,6 @@ * Boston, MA 02110-1301, USA. */ -#include "ch.h" - #include "tuning.hpp" #include "utility.hpp" From 1caf6952d8a092b972c71b089c8349289483e240 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 20:20:34 -0800 Subject: [PATCH 396/452] Remove GCC-isms interfering with host-based testing. --- firmware/application/tuning.cpp | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/firmware/application/tuning.cpp b/firmware/application/tuning.cpp index 5edc48524..0ca8711b9 100644 --- a/firmware/application/tuning.cpp +++ b/firmware/application/tuning.cpp @@ -49,32 +49,19 @@ constexpr rf::Frequency high_band_second_lo_frequency(const rf::Frequency target Config low_band(const rf::Frequency target_frequency) { const rf::Frequency first_lo_frequency = target_frequency + low_band_second_lo_frequency(target_frequency); const rf::Frequency second_lo_frequency = first_lo_frequency - target_frequency; - return { - .first_lo_frequency = first_lo_frequency, - .second_lo_frequency = second_lo_frequency, - .rf_path_band = rf::path::Band::Low, - .baseband_q_invert = true, - }; + const bool baseband_q_invert = true; + return { first_lo_frequency, second_lo_frequency, rf::path::Band::Low, baseband_q_invert }; } Config mid_band(const rf::Frequency target_frequency) { - return { - .first_lo_frequency = 0, - .second_lo_frequency = target_frequency, - .rf_path_band = rf::path::Band::Mid, - .baseband_q_invert = false, - }; + return { 0, target_frequency, rf::path::Band::Mid, false }; } Config high_band(const rf::Frequency target_frequency) { const rf::Frequency first_lo_frequency = target_frequency - high_band_second_lo_frequency(target_frequency); const rf::Frequency second_lo_frequency = target_frequency - first_lo_frequency; - return { - .first_lo_frequency = first_lo_frequency, - .second_lo_frequency = second_lo_frequency, - .rf_path_band = rf::path::Band::High, - .baseband_q_invert = false, - }; + const bool baseband_q_invert = false; + return { first_lo_frequency, second_lo_frequency, rf::path::Band::High, baseband_q_invert }; } } /* namespace */ From 894d4b955c7d60b24cb9188b3a7cb7f68f42dc73 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 20:33:54 -0800 Subject: [PATCH 397/452] Unclever first attempt at display sleep. --- firmware/application/event_m0.cpp | 26 ++++++++++++++------------ firmware/application/event_m0.hpp | 8 ++++++++ firmware/application/main.cpp | 5 +++++ firmware/application/ui_navigation.cpp | 7 +++++++ firmware/application/ui_navigation.hpp | 5 +++++ firmware/common/message.hpp | 9 +++++++++ 6 files changed, 48 insertions(+), 12 deletions(-) diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index 6e8897710..df694bb5d 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -98,21 +98,23 @@ void EventDispatcher::dispatch(const eventmask_t events) { if( events & EVT_MASK_RTC_TICK ) { handle_rtc_tick(); } + + if( !display_sleep ) { + if( events & EVT_MASK_LCD_FRAME_SYNC ) { + handle_lcd_frame_sync(); + } - if( events & EVT_MASK_LCD_FRAME_SYNC ) { - handle_lcd_frame_sync(); - } + if( events & EVT_MASK_SWITCHES ) { + handle_switches(); + } - if( events & EVT_MASK_SWITCHES ) { - handle_switches(); - } + if( events & EVT_MASK_ENCODER ) { + handle_encoder(); + } - if( events & EVT_MASK_ENCODER ) { - handle_encoder(); - } - - if( events & EVT_MASK_TOUCH ) { - handle_touch(); + if( events & EVT_MASK_TOUCH ) { + handle_touch(); + } } } diff --git a/firmware/application/event_m0.hpp b/firmware/application/event_m0.hpp index 1409ceb7a..38eea5660 100644 --- a/firmware/application/event_m0.hpp +++ b/firmware/application/event_m0.hpp @@ -27,6 +27,8 @@ #include "ui_widget.hpp" #include "ui_painter.hpp" +#include "portapack.hpp" + #include "message.hpp" #include "touch.hpp" @@ -53,6 +55,11 @@ public: void run(); void request_stop(); + void set_display_sleep(bool new_value) { + portapack::io.lcd_backlight(false); + display_sleep = new_value; + }; + static inline void events_flag(const eventmask_t events) { if( thread_event_loop ) { chEvtSignal(thread_event_loop, events); @@ -80,6 +87,7 @@ private: uint32_t encoder_last = 0; bool is_running = true; bool sd_card_present = false; + bool display_sleep = false; eventmask_t wait(); void dispatch(const eventmask_t events); diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index d9900426c..a3674ab71 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -81,6 +81,11 @@ int main(void) { event_dispatcher.request_stop(); } ); + EventDispatcher::message_map().register_handler(Message::ID::DisplaySleep, + [&event_dispatcher](const Message* const) { + event_dispatcher.set_display_sleep(true); + } + ); m4_init(portapack::spi_flash::baseband, portapack::memory::map::m4_code); diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index e2c76b6c0..6a21d2150 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -22,6 +22,7 @@ #include "ui_navigation.hpp" #include "portapack.hpp" +#include "event_m0.hpp" #include "receiver_model.hpp" #include "ui_setup.hpp" @@ -42,6 +43,7 @@ SystemStatusView::SystemStatusView() { add_children({ { &button_back, &title, + &button_sleep, &sd_card_status_view, } }); sd_card_status_view.set_parent_rect({ 28 * 8, 0 * 16, 2 * 8, 1 * 16 }); @@ -51,6 +53,11 @@ SystemStatusView::SystemStatusView() { this->on_back(); } }; + + button_sleep.on_select = [this](Button&) { + DisplaySleepMessage message; + EventDispatcher::message_map().send(&message); + }; } void SystemStatusView::set_back_visible(bool new_value) { diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 5dab355b4..a0c0ce04d 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -59,6 +59,11 @@ private: default_title, }; + Button button_sleep { + { 25 * 8, 0, 2 * 8, 1 * 16 }, + "ZZ", + }; + SDCardStatusView sd_card_status_view; }; diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 66eebbc5a..5c823938c 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -58,6 +58,7 @@ public: AMConfigure = 13, ChannelSpectrumConfig = 14, SpectrumStreamingConfig = 15, + DisplaySleep = 16, MAX }; @@ -165,6 +166,14 @@ struct AudioStatistics { } }; +class DisplaySleepMessage : public Message { +public: + constexpr DisplaySleepMessage( + ) : Message { ID::DisplaySleep } + { + } +}; + class AudioStatisticsMessage : public Message { public: constexpr AudioStatisticsMessage( From b801366e4ef8a3d5d8920e5b8d1fa70f59a486f5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 27 Jan 2016 21:03:34 -0800 Subject: [PATCH 398/452] Recover from display sleep, use LCD sleep function. --- firmware/application/event_m0.cpp | 30 ++++++++++++++++++++++++++---- firmware/application/event_m0.hpp | 5 +---- firmware/common/lcd_ili9341.cpp | 30 ++++++++++++++++++++++++------ firmware/common/lcd_ili9341.hpp | 3 +++ 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index df694bb5d..dc5573979 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -86,6 +86,19 @@ void EventDispatcher::request_stop() { is_running = false; } +void EventDispatcher::set_display_sleep(const bool sleep) { + // TODO: Distribute display sleep message more broadly, shut down data generation + // on baseband side, since all that data is being discarded during sleep. + if( sleep ) { + portapack::io.lcd_backlight(false); + portapack::display.sleep(); + } else { + portapack::display.wake(); + portapack::io.lcd_backlight(true); + } + display_sleep = sleep; +}; + eventmask_t EventDispatcher::wait() { return chEvtWaitAny(ALL_EVENTS); } @@ -99,15 +112,15 @@ void EventDispatcher::dispatch(const eventmask_t events) { handle_rtc_tick(); } + if( events & EVT_MASK_SWITCHES ) { + handle_switches(); + } + if( !display_sleep ) { if( events & EVT_MASK_LCD_FRAME_SYNC ) { handle_lcd_frame_sync(); } - if( events & EVT_MASK_SWITCHES ) { - handle_switches(); - } - if( events & EVT_MASK_ENCODER ) { handle_encoder(); } @@ -181,6 +194,15 @@ void EventDispatcher::handle_lcd_frame_sync() { void EventDispatcher::handle_switches() { const auto switches_state = get_switches_state(); + + if( display_sleep ) { + // Swallow event, wake up display. + if( switches_state.any() ) { + set_display_sleep(false); + } + return; + } + for(size_t i=0; i Date: Wed, 27 Jan 2016 21:47:10 -0800 Subject: [PATCH 399/452] Fix flickering freq/gain options views. Was caused by invalidating ALL of the parent view, when only the overlapping views would need to be repainted. --- firmware/common/ui_widget.cpp | 12 +++++++++++- firmware/common/ui_widget.hpp | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 8053d9fd7..0b9cc01ca 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -95,7 +95,9 @@ void Widget::hidden(bool hide) { // If parent is hidden, either of these is a no-op. if( hide ) { - parent()->set_dirty(); + // TODO: Instead of dirtying parent entirely, dirty only children + // that overlap with this widget. + parent()->dirty_overlapping_children_in_rect(parent_rect); /* TODO: Notify self and all non-hidden children that they're * now effectively hidden? */ @@ -198,6 +200,14 @@ void Widget::visible(bool v) { } } +void Widget::dirty_overlapping_children_in_rect(const Rect& child_rect) { + for(auto child : children()) { + if( !child_rect.intersect(child->parent_rect).is_empty() ) { + child->set_dirty(); + } + } +} + /* View ******************************************************************/ void View::set_parent_rect(const Rect new_parent_rect) { diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index d292d8e2a..e1e886894 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -131,6 +131,8 @@ protected: .highlighted = false, .visible = false, }; + + void dirty_overlapping_children_in_rect(const Rect& child_rect); }; class View : public Widget { From a03a72474db8cfa3dd01104f3d76dcba4586915d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 15:17:05 -0800 Subject: [PATCH 400/452] Insert IDIVC into audio MCLK path, so it can be divided. --- firmware/application/clock_manager.cpp | 12 +++++++++++- firmware/application/clock_manager.hpp | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/firmware/application/clock_manager.cpp b/firmware/application/clock_manager.cpp index 86682b746..5ec51aecb 100644 --- a/firmware/application/clock_manager.cpp +++ b/firmware/application/clock_manager.cpp @@ -516,7 +516,17 @@ void ClockManager::start_audio_pll() { while( !cgu::pll0audio::is_locked() ); cgu::pll0audio::clock_enable(); - set_clock(LPC_CGU->BASE_AUDIO_CLK, cgu::CLK_SEL::PLL0AUDIO); + set_base_audio_clock_divider(1); + set_clock(LPC_CGU->BASE_AUDIO_CLK, cgu::CLK_SEL::IDIVC); +} + +void ClockManager::set_base_audio_clock_divider(const size_t divisor) { + LPC_CGU->IDIVC_CTRL = + (0 << 1) + | ((divisor - 1) << 2) + | (1 << 11) + | (toUType(cgu::CLK_SEL::PLL0AUDIO) << 24) + ; } void ClockManager::stop_audio_pll() { diff --git a/firmware/application/clock_manager.hpp b/firmware/application/clock_manager.hpp index 54a80a03d..f13985296 100644 --- a/firmware/application/clock_manager.hpp +++ b/firmware/application/clock_manager.hpp @@ -51,6 +51,8 @@ public: void start_audio_pll(); void stop_audio_pll(); + void set_base_audio_clock_divider(const size_t divisor); + void enable_codec_clocks(); void disable_codec_clocks(); From 0cf839bc939b808861cd6dd5682d5038008e6f01 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 15:21:33 -0800 Subject: [PATCH 401/452] Expose instance clock_manager in portapack.hpp. --- firmware/application/portapack.cpp | 4 +--- firmware/application/portapack.hpp | 2 ++ firmware/application/receiver_model.hpp | 8 -------- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index e9460c508..6621a5b85 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -61,9 +61,7 @@ ClockManager clock_manager { i2c0, clock_generator }; -ReceiverModel receiver_model { - clock_manager -}; +ReceiverModel receiver_model; TemperatureLogger temperature_logger; diff --git a/firmware/application/portapack.hpp b/firmware/application/portapack.hpp index cbe0b6657..886c4a436 100644 --- a/firmware/application/portapack.hpp +++ b/firmware/application/portapack.hpp @@ -29,6 +29,7 @@ #include "lcd_ili9341.hpp" #include "radio.hpp" +#include "clock_manager.hpp" #include "temperature_logger.hpp" namespace portapack { @@ -43,6 +44,7 @@ extern SPI ssp1; extern wolfson::wm8731::WM8731 audio_codec; extern si5351::Si5351 clock_generator; +extern ClockManager clock_manager; extern ReceiverModel receiver_model; diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index ac3ce913e..d76f46701 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -25,7 +25,6 @@ #include #include -#include "clock_manager.hpp" #include "message.hpp" #include "rf_path.hpp" #include "max2837.hpp" @@ -43,12 +42,6 @@ public: ERT = 6, }; - constexpr ReceiverModel( - ClockManager& clock_manager - ) : clock_manager(clock_manager) - { - } - rf::Frequency tuning_frequency() const; void set_tuning_frequency(rf::Frequency f); @@ -101,7 +94,6 @@ private: .decimation_factor = 1, }; volume_t headphone_volume_ { -43.0_dB }; - ClockManager& clock_manager; int32_t tuning_offset(); From a2a169352c2f92f02b7dd7aef84c14509d44583b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 15:24:31 -0800 Subject: [PATCH 402/452] Rename existing IIR configs to reflect fs=48k design. --- firmware/baseband/dsp_iir_config.hpp | 8 ++++---- firmware/baseband/proc_wfm_audio.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index 096acd995..588e6ce80 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -25,13 +25,13 @@ #include "dsp_iir.hpp" // scipy.signal.butter(2, 30 / 24000.0, 'highpass', analog=False) -constexpr iir_biquad_config_t audio_hpf_30hz_config { +constexpr iir_biquad_config_t audio_48k_hpf_30hz_config { { 0.99722705f, -1.99445410f, 0.99722705f }, { 1.00000000f, -1.99444641f, 0.99446179f } }; // scipy.signal.butter(2, 300 / 24000.0, 'highpass', analog=False) -constexpr iir_biquad_config_t audio_hpf_300hz_config { +constexpr iir_biquad_config_t audio_48k_hpf_300hz_config { { 0.97261390f, -1.94522780f, 0.97261390f }, { 1.00000000f, -1.94447766f, 0.94597794f } }; @@ -44,7 +44,7 @@ constexpr iir_biquad_config_t non_audio_hpf_config { // scipy.signal.butter(1, 300 / 24000.0, 'lowpass', analog=False) // NOTE: Technically, order-1 filter, b[2] = a[2] = 0. -constexpr iir_biquad_config_t audio_deemph_300_6_config { +constexpr iir_biquad_config_t audio_48k_deemph_300_6_config { { 0.01925927f, 0.01925927f, 0.00000000f }, { 1.00000000f, -0.96148145f, 0.00000000f } }; @@ -52,7 +52,7 @@ constexpr iir_biquad_config_t audio_deemph_300_6_config { // 75us RC time constant, used in broadcast FM in Americas, South Korea // scipy.signal.butter(1, 2122 / 24000.0, 'lowpass', analog=False) // NOTE: Technically, order-1 filter, b[2] = a[2] = 0. -constexpr iir_biquad_config_t audio_deemph_2122_6_config { +constexpr iir_biquad_config_t audio_48k_deemph_2122_6_config { { 0.12264116f, 0.12264116f, 0.00000000f }, { 1.00000000f, -0.75471767f, 0.00000000f } }; diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 33526af8f..963c14966 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -110,7 +110,7 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) { channel_filter_stop_f = message.decim_1_filter.stop_frequency_normalized * decim_1_input_fs; demod.configure(demod_input_fs, message.deviation); audio_filter.configure(message.audio_filter.taps); - audio_output.configure(audio_hpf_30hz_config, audio_deemph_2122_6_config); + audio_output.configure(audio_48k_hpf_30hz_config, audio_48k_deemph_2122_6_config); channel_spectrum.set_decimation_factor(1); From 0e436ded14bb8dff54716caef86928ba48a9d7be Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 15:32:32 -0800 Subject: [PATCH 403/452] Add IIR configs for lower audio sampling rates. --- firmware/baseband/dsp_iir_config.hpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/baseband/dsp_iir_config.hpp index 588e6ce80..320edb0b2 100644 --- a/firmware/baseband/dsp_iir_config.hpp +++ b/firmware/baseband/dsp_iir_config.hpp @@ -36,6 +36,18 @@ constexpr iir_biquad_config_t audio_48k_hpf_300hz_config { { 1.00000000f, -1.94447766f, 0.94597794f } }; +// scipy.signal.butter(2, 300 / 8000.0, 'highpass', analog=False) +constexpr iir_biquad_config_t audio_16k_hpf_300hz_config { + { 0.92006616f, -1.84013232f, 0.92006616f }, + { 1.00000000f, -1.83373266f, 0.84653197f } +}; + +// scipy.signal.butter(2, 300 / 4000.0, 'highpass', analog=False) +constexpr iir_biquad_config_t audio_8k_hpf_300hz_config { + { 0.84645925f, -1.69291851f, 0.84645925f }, + { 1.00000000f, -1.66920314f, 0.71663387f } +}; + // scipy.signal.iirdesign(wp=8000 / 24000.0, ws= 4000 / 24000.0, gpass=1, gstop=18, ftype='ellip') constexpr iir_biquad_config_t non_audio_hpf_config { { 0.51891061f, -0.95714180f, 0.51891061f }, @@ -49,6 +61,20 @@ constexpr iir_biquad_config_t audio_48k_deemph_300_6_config { { 1.00000000f, -0.96148145f, 0.00000000f } }; +// scipy.signal.butter(1, 300 / 8000.0, 'lowpass', analog=False) +// NOTE: Technically, order-1 filter, b[2] = a[2] = 0. +constexpr iir_biquad_config_t audio_16k_deemph_300_6_config { + { 0.05568894f, 0.05568894f, 0.00000000f }, + { 1.00000000f, -0.88862213f, 0.00000000f } +}; + +// scipy.signal.butter(1, 300 / 4000.0, 'lowpass', analog=False) +// NOTE: Technically, order-1 filter, b[2] = a[2] = 0. +constexpr iir_biquad_config_t audio_8k_deemph_300_6_config { + { 0.10583178f, 0.10583178f, 0.00000000f }, + { 1.00000000f, -0.78833643f, 0.00000000f } +}; + // 75us RC time constant, used in broadcast FM in Americas, South Korea // scipy.signal.butter(1, 2122 / 24000.0, 'lowpass', analog=False) // NOTE: Technically, order-1 filter, b[2] = a[2] = 0. From db642cac8d840e022a6e359167bceeea71f7a181 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 15:33:01 -0800 Subject: [PATCH 404/452] Change audio sampling rates on NBFM, AM modes. --- firmware/application/analog_audio_app.cpp | 3 +++ firmware/baseband/proc_am_audio.cpp | 11 +++++++---- firmware/baseband/proc_am_audio.hpp | 10 +++++++--- firmware/baseband/proc_nfm_audio.cpp | 13 ++++++++----- firmware/baseband/proc_nfm_audio.hpp | 10 +++++++--- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index ec50f4d52..8396a2d29 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -62,6 +62,7 @@ void AnalogAudioModel::configure_nbfm() { 2500, }; shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(3); } void AnalogAudioModel::configure_wfm() { @@ -72,6 +73,7 @@ void AnalogAudioModel::configure_wfm() { 75000, }; shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(1); } void AnalogAudioModel::configure_am() { @@ -81,4 +83,5 @@ void AnalogAudioModel::configure_am() { taps_6k0_channel, }; shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(6); } diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 06314ee0f..463a8e700 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -39,9 +39,12 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { feed_channel_stats(channel_out); channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); - auto audio = demod.execute(channel_out, work_audio_buffer); - - audio_output.write(audio); + channel_block_buffer.feed( + channel_out, [this](const buffer_c16_t buffer) { + auto audio = this->demod.execute(buffer, this->audio_buffer); + this->audio_output.write(audio); + } + ); } void NarrowbandAMAudio::on_message(const Message* const message) { @@ -81,7 +84,7 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); - audio_output.configure(audio_hpf_300hz_config); + audio_output.configure(audio_8k_hpf_300hz_config); configured = true; } diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 5da5136d4..ef1b442ac 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -44,9 +44,10 @@ private: dst.data(), dst.size() }; - const buffer_f32_t work_audio_buffer { - (float*)dst.data(), - sizeof(dst) / sizeof(float) + std::array audio; + const buffer_f32_t audio_buffer { + audio.data(), + audio.size() }; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; @@ -55,6 +56,9 @@ private: uint32_t channel_filter_pass_f; uint32_t channel_filter_stop_f; + static constexpr size_t post_channel_decimation_factor = 6; + BlockDecimator<32> channel_block_buffer { post_channel_decimation_factor }; + dsp::demodulate::AM demod; AudioOutput audio_output; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 906617cd3..755709395 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -39,9 +39,12 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { feed_channel_stats(channel_out); channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); - auto audio = demod.execute(channel_out, work_audio_buffer); - - audio_output.write(audio); + channel_block_buffer.feed( + channel_out, [this](const buffer_c16_t buffer) { + auto audio = this->demod.execute(buffer, this->audio_buffer); + this->audio_output.write(audio); + } + ); } void NarrowbandFMAudio::on_message(const Message* const message) { @@ -75,7 +78,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { constexpr size_t channel_filter_decimation_factor = 1; constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; - constexpr size_t demod_input_fs = channel_filter_output_fs; + constexpr size_t demod_input_fs = channel_filter_output_fs / post_channel_decimation_factor; decim_0.configure(message.decim_0_filter.taps, 33554432); decim_1.configure(message.decim_1_filter.taps, 131072); @@ -84,7 +87,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); - audio_output.configure(audio_hpf_300hz_config, audio_deemph_300_6_config, 6144); + audio_output.configure(audio_16k_hpf_300hz_config, audio_16k_deemph_300_6_config, 0); configured = true; } diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 69ce6ee0f..190b7f988 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -42,9 +42,10 @@ private: dst.data(), dst.size() }; - const buffer_f32_t work_audio_buffer { - (float*)dst.data(), - sizeof(dst) / sizeof(float) + std::array audio; + const buffer_f32_t audio_buffer { + audio.data(), + audio.size() }; dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; @@ -54,6 +55,9 @@ private: uint32_t channel_filter_pass_f = 0; uint32_t channel_filter_stop_f = 0; + static constexpr size_t post_channel_decimation_factor = 3; + BlockDecimator<32> channel_block_buffer { post_channel_decimation_factor }; + dsp::demodulate::FM demod; AudioOutput audio_output; From 01e14ecbcf816b93b48ecf46ead6d21869c954c7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 15:43:39 -0800 Subject: [PATCH 405/452] Move IIR struct and configs to common/. --- firmware/{baseband => common}/dsp_iir.cpp | 0 firmware/{baseband => common}/dsp_iir.hpp | 0 firmware/{baseband => common}/dsp_iir_config.hpp | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename firmware/{baseband => common}/dsp_iir.cpp (100%) rename firmware/{baseband => common}/dsp_iir.hpp (100%) rename firmware/{baseband => common}/dsp_iir_config.hpp (100%) diff --git a/firmware/baseband/dsp_iir.cpp b/firmware/common/dsp_iir.cpp similarity index 100% rename from firmware/baseband/dsp_iir.cpp rename to firmware/common/dsp_iir.cpp diff --git a/firmware/baseband/dsp_iir.hpp b/firmware/common/dsp_iir.hpp similarity index 100% rename from firmware/baseband/dsp_iir.hpp rename to firmware/common/dsp_iir.hpp diff --git a/firmware/baseband/dsp_iir_config.hpp b/firmware/common/dsp_iir_config.hpp similarity index 100% rename from firmware/baseband/dsp_iir_config.hpp rename to firmware/common/dsp_iir_config.hpp From 96898f82b2393dbeada54980754471ab81038181 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 15:57:20 -0800 Subject: [PATCH 406/452] Pass IIR configs from application to baseband. --- firmware/application/analog_audio_app.cpp | 8 ++++++ firmware/baseband/proc_am_audio.cpp | 3 +-- firmware/baseband/proc_nfm_audio.cpp | 3 +-- firmware/baseband/proc_wfm_audio.cpp | 3 +-- firmware/common/message.hpp | 30 +++++++++++++++++------ 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 8396a2d29..5884a2b01 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -25,6 +25,9 @@ #include "portapack_shared_memory.hpp" using namespace portapack; +#include "dsp_fir_taps.hpp" +#include "dsp_iir_config.hpp" + #include "utility.hpp" AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { @@ -60,6 +63,8 @@ void AnalogAudioModel::configure_nbfm() { taps_4k25_decim_1, taps_4k25_channel, 2500, + audio_16k_hpf_300hz_config, + audio_16k_deemph_300_6_config }; shared_memory.baseband_queue.push(message); clock_manager.set_base_audio_clock_divider(3); @@ -71,6 +76,8 @@ void AnalogAudioModel::configure_wfm() { taps_200k_wfm_decim_1, taps_64_lp_156_198, 75000, + audio_48k_hpf_30hz_config, + audio_48k_deemph_2122_6_config }; shared_memory.baseband_queue.push(message); clock_manager.set_base_audio_clock_divider(1); @@ -81,6 +88,7 @@ void AnalogAudioModel::configure_am() { taps_6k0_decim_0, taps_6k0_decim_1, taps_6k0_channel, + audio_8k_hpf_300hz_config }; shared_memory.baseband_queue.push(message); clock_manager.set_base_audio_clock_divider(6); diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 463a8e700..3ce9f2e5e 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -21,7 +21,6 @@ #include "proc_am_audio.hpp" -#include "dsp_iir_config.hpp" #include "audio_output.hpp" #include @@ -84,7 +83,7 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); - audio_output.configure(audio_8k_hpf_300hz_config); + audio_output.configure(message.audio_hpf_config); configured = true; } diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 755709395..8893fa30f 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -21,7 +21,6 @@ #include "proc_nfm_audio.hpp" -#include "dsp_iir_config.hpp" #include "audio_output.hpp" #include @@ -87,7 +86,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); - audio_output.configure(audio_16k_hpf_300hz_config, audio_16k_deemph_300_6_config, 0); + audio_output.configure(message.audio_hpf_config, message.audio_deemph_config, 0); configured = true; } diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index 963c14966..ae11abdb3 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -21,7 +21,6 @@ #include "proc_wfm_audio.hpp" -#include "dsp_iir_config.hpp" #include "audio_output.hpp" #include @@ -110,7 +109,7 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) { channel_filter_stop_f = message.decim_1_filter.stop_frequency_normalized * decim_1_input_fs; demod.configure(demod_input_fs, message.deviation); audio_filter.configure(message.audio_filter.taps); - audio_output.configure(audio_48k_hpf_30hz_config, audio_48k_deemph_2122_6_config); + audio_output.configure(message.audio_hpf_config, message.audio_deemph_config); channel_spectrum.set_decimation_factor(1); diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 5c823938c..576bc7fa5 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -30,6 +30,7 @@ #include "baseband_packet.hpp" #include "ert_packet.hpp" #include "dsp_fir_taps.hpp" +#include "dsp_iir.hpp" #include "fifo.hpp" #include "utility.hpp" @@ -38,7 +39,7 @@ class Message { public: - static constexpr size_t MAX_SIZE = 276; + static constexpr size_t MAX_SIZE = 288; enum class ID : uint32_t { /* Assign consecutive IDs. IDs are used to index array. */ @@ -319,12 +320,16 @@ public: 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 deviation + const size_t deviation, + const iir_biquad_config_t audio_hpf_config, + const iir_biquad_config_t audio_deemph_config ) : Message { ID::NBFMConfigure }, decim_0_filter(decim_0_filter), decim_1_filter(decim_1_filter), channel_filter(channel_filter), - deviation { deviation } + deviation { deviation }, + audio_hpf_config { audio_hpf_config }, + audio_deemph_config { audio_deemph_config } { } @@ -332,6 +337,8 @@ public: const fir_taps_real<32> decim_1_filter; const fir_taps_real<32> channel_filter; const size_t deviation; + const iir_biquad_config_t audio_hpf_config; + const iir_biquad_config_t audio_deemph_config; }; class WFMConfigureMessage : public Message { @@ -340,12 +347,16 @@ public: 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 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 } + deviation { deviation }, + audio_hpf_config { audio_hpf_config }, + audio_deemph_config { audio_deemph_config } { } @@ -353,6 +364,8 @@ public: 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 { @@ -360,17 +373,20 @@ public: constexpr AMConfigureMessage( const fir_taps_real<24> decim_0_filter, const fir_taps_real<32> decim_1_filter, - const fir_taps_real<32> channel_filter + const fir_taps_real<32> channel_filter, + const iir_biquad_config_t audio_hpf_config ) : Message { ID::AMConfigure }, decim_0_filter(decim_0_filter), decim_1_filter(decim_1_filter), - channel_filter(channel_filter) + channel_filter(channel_filter), + 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> channel_filter; + const iir_biquad_config_t audio_hpf_config; }; class MessageHandlerMap { From 7c65a2d65017e5f34274a63c2982f643af1ec0fa Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 16:11:00 -0800 Subject: [PATCH 407/452] Clean up baseband processor statics. --- firmware/baseband/proc_am_audio.cpp | 9 ++------- firmware/baseband/proc_am_audio.hpp | 5 ++++- firmware/baseband/proc_nfm_audio.cpp | 9 ++------- firmware/baseband/proc_nfm_audio.hpp | 5 ++++- firmware/baseband/proc_wfm_audio.cpp | 9 ++------- firmware/baseband/proc_wfm_audio.hpp | 3 +++ 6 files changed, 17 insertions(+), 23 deletions(-) diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 3ce9f2e5e..b3ff0ba9c 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -63,18 +63,13 @@ void NarrowbandAMAudio::on_message(const Message* const message) { } void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { - constexpr size_t baseband_fs = 3072000; - constexpr size_t decim_0_input_fs = baseband_fs; - constexpr size_t decim_0_decimation_factor = 8; - constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor; constexpr size_t decim_1_input_fs = decim_0_output_fs; - constexpr size_t decim_1_decimation_factor = 8; - constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; constexpr size_t channel_filter_input_fs = decim_1_output_fs; - constexpr size_t channel_filter_decimation_factor = 1; constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; decim_0.configure(message.decim_0_filter.taps, 33554432); diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index ef1b442ac..2035c40cc 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -39,6 +39,10 @@ public: void on_message(const Message* const message) override; private: + static constexpr size_t baseband_fs = 3072000; + static constexpr size_t channel_filter_decimation_factor = 1; + static constexpr size_t post_channel_decimation_factor = 6; + std::array dst; const buffer_c16_t dst_buffer { dst.data(), @@ -56,7 +60,6 @@ private: uint32_t channel_filter_pass_f; uint32_t channel_filter_stop_f; - static constexpr size_t post_channel_decimation_factor = 6; BlockDecimator<32> channel_block_buffer { post_channel_decimation_factor }; dsp::demodulate::AM demod; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 8893fa30f..60e56039e 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -63,18 +63,13 @@ void NarrowbandFMAudio::on_message(const Message* const message) { } void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { - constexpr size_t baseband_fs = 3072000; - constexpr size_t decim_0_input_fs = baseband_fs; - constexpr size_t decim_0_decimation_factor = 8; - constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor; constexpr size_t decim_1_input_fs = decim_0_output_fs; - constexpr size_t decim_1_decimation_factor = 8; - constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; constexpr size_t channel_filter_input_fs = decim_1_output_fs; - constexpr size_t channel_filter_decimation_factor = 1; constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; constexpr size_t demod_input_fs = channel_filter_output_fs / post_channel_decimation_factor; diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 190b7f988..0b2c806d6 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -37,6 +37,10 @@ public: void on_message(const Message* const message) override; private: + static constexpr size_t baseband_fs = 3072000; + static constexpr size_t channel_filter_decimation_factor = 1; + static constexpr size_t post_channel_decimation_factor = 3; + std::array dst; const buffer_c16_t dst_buffer { dst.data(), @@ -55,7 +59,6 @@ private: uint32_t channel_filter_pass_f = 0; uint32_t channel_filter_stop_f = 0; - static constexpr size_t post_channel_decimation_factor = 3; BlockDecimator<32> channel_block_buffer { post_channel_decimation_factor }; dsp::demodulate::FM demod; diff --git a/firmware/baseband/proc_wfm_audio.cpp b/firmware/baseband/proc_wfm_audio.cpp index ae11abdb3..4246a5559 100644 --- a/firmware/baseband/proc_wfm_audio.cpp +++ b/firmware/baseband/proc_wfm_audio.cpp @@ -87,19 +87,14 @@ void WidebandFMAudio::on_message(const Message* const message) { } void WidebandFMAudio::configure(const WFMConfigureMessage& message) { - constexpr size_t baseband_fs = 3072000; - constexpr size_t decim_0_input_fs = baseband_fs; - constexpr size_t decim_0_decimation_factor = 4; - constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor; constexpr size_t decim_1_input_fs = decim_0_output_fs; - constexpr size_t decim_1_decimation_factor = 2; - constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; constexpr size_t demod_input_fs = decim_1_output_fs; - constexpr auto spectrum_rate_hz = 50.0f; spectrum_interval_samples = decim_1_output_fs / spectrum_rate_hz; spectrum_samples = 0; diff --git a/firmware/baseband/proc_wfm_audio.hpp b/firmware/baseband/proc_wfm_audio.hpp index 5c30c2e93..15f5bf36c 100644 --- a/firmware/baseband/proc_wfm_audio.hpp +++ b/firmware/baseband/proc_wfm_audio.hpp @@ -37,6 +37,9 @@ public: void on_message(const Message* const message) override; private: + static constexpr size_t baseband_fs = 3072000; + static constexpr auto spectrum_rate_hz = 50.0f; + std::array dst; const buffer_c16_t dst_buffer { dst.data(), From d984532190a7c36bf870efc1ffa6d8e62ee4dc7b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 16:18:03 -0800 Subject: [PATCH 408/452] Converging AM, NBFM processors for eventual merging. --- firmware/baseband/proc_am_audio.hpp | 4 ++-- firmware/baseband/proc_nfm_audio.hpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 2035c40cc..877363f7a 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -57,8 +57,8 @@ private: dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC16xR16x32Decim8 decim_1; dsp::decimate::FIRAndDecimateComplex channel_filter; - uint32_t channel_filter_pass_f; - uint32_t channel_filter_stop_f; + uint32_t channel_filter_pass_f = 0; + uint32_t channel_filter_stop_f = 0; BlockDecimator<32> channel_block_buffer { post_channel_decimation_factor }; diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 0b2c806d6..08847a1f9 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -30,6 +30,8 @@ #include "audio_output.hpp" #include "spectrum_collector.hpp" +#include + class NarrowbandFMAudio : public BasebandProcessor { public: void execute(const buffer_c8_t& buffer) override; @@ -54,7 +56,6 @@ private: dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC16xR16x32Decim8 decim_1; - dsp::decimate::FIRAndDecimateComplex channel_filter; uint32_t channel_filter_pass_f = 0; uint32_t channel_filter_stop_f = 0; From 28e5b7e4afc41d52fda16e03cb1a16627a42ff86 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 17:06:22 -0800 Subject: [PATCH 409/452] Remove some filter constructors, reset Z on configure(). --- firmware/baseband/dsp_decimate.cpp | 20 ++++---------------- firmware/baseband/dsp_decimate.hpp | 8 -------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/firmware/baseband/dsp_decimate.cpp b/firmware/baseband/dsp_decimate.cpp index 5c5ba40e7..af5f12e39 100644 --- a/firmware/baseband/dsp_decimate.cpp +++ b/firmware/baseband/dsp_decimate.cpp @@ -179,10 +179,6 @@ static inline uint32_t scale_round_and_pack( // FIRC8xR16x24FS4Decim4 ////////////////////////////////////////////////// -FIRC8xR16x24FS4Decim4::FIRC8xR16x24FS4Decim4() { - z_.fill({}); -} - void FIRC8xR16x24FS4Decim4::configure( const std::array& taps, const int32_t scale, @@ -196,6 +192,7 @@ void FIRC8xR16x24FS4Decim4::configure( taps_[i+3] = taps[i+3] * negate_factor; } output_scale = scale; + z_.fill({}); } buffer_c16_t FIRC8xR16x24FS4Decim4::execute( @@ -244,10 +241,6 @@ buffer_c16_t FIRC8xR16x24FS4Decim4::execute( // FIRC8xR16x24FS4Decim8 ////////////////////////////////////////////////// -FIRC8xR16x24FS4Decim8::FIRC8xR16x24FS4Decim8() { - z_.fill({}); -} - void FIRC8xR16x24FS4Decim8::configure( const std::array& taps, const int32_t scale, @@ -261,6 +254,7 @@ void FIRC8xR16x24FS4Decim8::configure( taps_[i+3] = taps[i+3] * negate_factor; } output_scale = scale; + z_.fill({}); } buffer_c16_t FIRC8xR16x24FS4Decim8::execute( @@ -309,16 +303,13 @@ buffer_c16_t FIRC8xR16x24FS4Decim8::execute( // FIRC16xR16x16Decim2 //////////////////////////////////////////////////// -FIRC16xR16x16Decim2::FIRC16xR16x16Decim2() { - z_.fill({}); -} - void FIRC16xR16x16Decim2::configure( const std::array& taps, const int32_t scale ) { std::copy(taps.cbegin(), taps.cend(), taps_.begin()); output_scale = scale; + z_.fill({}); } buffer_c16_t FIRC16xR16x16Decim2::execute( @@ -363,16 +354,13 @@ buffer_c16_t FIRC16xR16x16Decim2::execute( // FIRC16xR16x32Decim8 //////////////////////////////////////////////////// -FIRC16xR16x32Decim8::FIRC16xR16x32Decim8() { - z_.fill({}); -} - void FIRC16xR16x32Decim8::configure( const std::array& taps, const int32_t scale ) { std::copy(taps.cbegin(), taps.cend(), taps_.begin()); output_scale = scale; + z_.fill({}); } buffer_c16_t FIRC16xR16x32Decim8::execute( diff --git a/firmware/baseband/dsp_decimate.hpp b/firmware/baseband/dsp_decimate.hpp index d3f41555b..0f4ca8453 100644 --- a/firmware/baseband/dsp_decimate.hpp +++ b/firmware/baseband/dsp_decimate.hpp @@ -103,8 +103,6 @@ public: Up = false }; - FIRC8xR16x24FS4Decim4(); - void configure( const std::array& taps, const int32_t scale, @@ -135,8 +133,6 @@ public: Up = false }; - FIRC8xR16x24FS4Decim8(); - void configure( const std::array& taps, const int32_t scale, @@ -162,8 +158,6 @@ public: using sample_t = complex16_t; using tap_t = int16_t; - FIRC16xR16x16Decim2(); - void configure( const std::array& taps, const int32_t scale @@ -188,8 +182,6 @@ public: using sample_t = complex16_t; using tap_t = int16_t; - FIRC16xR16x32Decim8(); - void configure( const std::array& taps, const int32_t scale From 65d224be14b9c6868974c9d22af53c264c93d798 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 18:31:03 -0800 Subject: [PATCH 410/452] Add IIR configs for fs=24kHz NBFM and fs=12kHz AM. --- firmware/common/dsp_iir_config.hpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/firmware/common/dsp_iir_config.hpp b/firmware/common/dsp_iir_config.hpp index 320edb0b2..50aca1d50 100644 --- a/firmware/common/dsp_iir_config.hpp +++ b/firmware/common/dsp_iir_config.hpp @@ -36,12 +36,24 @@ constexpr iir_biquad_config_t audio_48k_hpf_300hz_config { { 1.00000000f, -1.94447766f, 0.94597794f } }; +// scipy.signal.butter(2, 300 / 12000.0, 'highpass', analog=False) +constexpr iir_biquad_config_t audio_24k_hpf_300hz_config { + { 0.94597686f, -1.89195371f, 0.94597686f }, + { 1.00000000f, -1.88903308f, 0.89487434f } +}; + // scipy.signal.butter(2, 300 / 8000.0, 'highpass', analog=False) constexpr iir_biquad_config_t audio_16k_hpf_300hz_config { { 0.92006616f, -1.84013232f, 0.92006616f }, { 1.00000000f, -1.83373266f, 0.84653197f } }; +// scipy.signal.butter(2, 300 / 6000.0, 'highpass', analog=False) +constexpr iir_biquad_config_t audio_12k_hpf_300hz_config { + { 0.89485861f, -1.78971721f, 0.89485861f }, + { 1.00000000f, -1.77863178f, 0.80080265f } +}; + // scipy.signal.butter(2, 300 / 4000.0, 'highpass', analog=False) constexpr iir_biquad_config_t audio_8k_hpf_300hz_config { { 0.84645925f, -1.69291851f, 0.84645925f }, @@ -61,6 +73,13 @@ constexpr iir_biquad_config_t audio_48k_deemph_300_6_config { { 1.00000000f, -0.96148145f, 0.00000000f } }; +// scipy.signal.butter(1, 300 / 12000.0, 'lowpass', analog=False) +// NOTE: Technically, order-1 filter, b[2] = a[2] = 0. +constexpr iir_biquad_config_t audio_24k_deemph_300_6_config { + { 0.03780475f, 0.03780475f, 0.00000000f }, + { 1.00000000f, -0.92439049f, 0.00000000f } +}; + // scipy.signal.butter(1, 300 / 8000.0, 'lowpass', analog=False) // NOTE: Technically, order-1 filter, b[2] = a[2] = 0. constexpr iir_biquad_config_t audio_16k_deemph_300_6_config { @@ -68,6 +87,13 @@ constexpr iir_biquad_config_t audio_16k_deemph_300_6_config { { 1.00000000f, -0.88862213f, 0.00000000f } }; +// scipy.signal.butter(1, 300 / 6000.0, 'lowpass', analog=False) +// NOTE: Technically, order-1 filter, b[2] = a[2] = 0. +constexpr iir_biquad_config_t audio_12k_deemph_300_6_config { + { 0.07295966f, 0.07295966f, 0.00000000f }, + { 1.00000000f, -0.85408069f, 0.00000000f } +}; + // scipy.signal.butter(1, 300 / 4000.0, 'lowpass', analog=False) // NOTE: Technically, order-1 filter, b[2] = a[2] = 0. constexpr iir_biquad_config_t audio_8k_deemph_300_6_config { From aead1d8798d0dddbe4d2a4cf53fc0b57ebd97185 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 19:23:30 -0800 Subject: [PATCH 411/452] Change NBFM audio fs->24k, AM ->12k. Send channel decimation factor from application to baseband. --- firmware/application/analog_audio_app.cpp | 12 +++++++----- firmware/baseband/proc_am_audio.cpp | 4 ++-- firmware/baseband/proc_am_audio.hpp | 2 -- firmware/baseband/proc_nfm_audio.cpp | 6 +++--- firmware/baseband/proc_nfm_audio.hpp | 2 -- firmware/common/message.hpp | 6 ++++++ 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 5884a2b01..75ce47817 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -62,12 +62,13 @@ void AnalogAudioModel::configure_nbfm() { taps_4k25_decim_0, taps_4k25_decim_1, taps_4k25_channel, + 2, 2500, - audio_16k_hpf_300hz_config, - audio_16k_deemph_300_6_config + audio_24k_hpf_300hz_config, + audio_24k_deemph_300_6_config }; shared_memory.baseband_queue.push(message); - clock_manager.set_base_audio_clock_divider(3); + clock_manager.set_base_audio_clock_divider(2); } void AnalogAudioModel::configure_wfm() { @@ -88,8 +89,9 @@ void AnalogAudioModel::configure_am() { taps_6k0_decim_0, taps_6k0_decim_1, taps_6k0_channel, - audio_8k_hpf_300hz_config + 4, + audio_12k_hpf_300hz_config }; shared_memory.baseband_queue.push(message); - clock_manager.set_base_audio_clock_divider(6); + clock_manager.set_base_audio_clock_divider(4); } diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index b3ff0ba9c..65ad8e9e0 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -70,11 +70,11 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; constexpr size_t channel_filter_input_fs = decim_1_output_fs; - constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; + const size_t channel_filter_output_fs = channel_filter_input_fs / message.channel_decimation; decim_0.configure(message.decim_0_filter.taps, 33554432); decim_1.configure(message.decim_1_filter.taps, 131072); - channel_filter.configure(message.channel_filter.taps, channel_filter_decimation_factor); + channel_filter.configure(message.channel_filter.taps, message.channel_decimation); channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 877363f7a..e2e76e95d 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -40,8 +40,6 @@ public: private: static constexpr size_t baseband_fs = 3072000; - static constexpr size_t channel_filter_decimation_factor = 1; - static constexpr size_t post_channel_decimation_factor = 6; std::array dst; const buffer_c16_t dst_buffer { diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 60e56039e..3fd9f5e38 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -70,13 +70,13 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; constexpr size_t channel_filter_input_fs = decim_1_output_fs; - constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; + const size_t channel_filter_output_fs = channel_filter_input_fs / message.channel_decimation; - constexpr size_t demod_input_fs = channel_filter_output_fs / post_channel_decimation_factor; + const size_t demod_input_fs = channel_filter_output_fs; decim_0.configure(message.decim_0_filter.taps, 33554432); decim_1.configure(message.decim_1_filter.taps, 131072); - channel_filter.configure(message.channel_filter.taps, channel_filter_decimation_factor); + channel_filter.configure(message.channel_filter.taps, message.channel_decimation); demod.configure(demod_input_fs, message.deviation); channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 08847a1f9..6f0866946 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -40,8 +40,6 @@ public: private: static constexpr size_t baseband_fs = 3072000; - static constexpr size_t channel_filter_decimation_factor = 1; - static constexpr size_t post_channel_decimation_factor = 3; std::array dst; const buffer_c16_t dst_buffer { diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 576bc7fa5..1f902af04 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -320,6 +320,7 @@ public: 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 @@ -327,6 +328,7 @@ public: 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 } @@ -336,6 +338,7 @@ public: 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; @@ -374,11 +377,13 @@ public: 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 iir_biquad_config_t audio_hpf_config ) : Message { ID::AMConfigure }, decim_0_filter(decim_0_filter), decim_1_filter(decim_1_filter), channel_filter(channel_filter), + channel_decimation { channel_decimation }, audio_hpf_config { audio_hpf_config } { } @@ -386,6 +391,7 @@ public: 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 iir_biquad_config_t audio_hpf_config; }; From a55856588619d71626fc65df1301387b45547448 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 19:25:08 -0800 Subject: [PATCH 412/452] Further template BlockDecimator by element type, use for audio buffer. Appropriating for use as a buffer accumulator that will save up enough audio samples to put into an audio DMA buffer. --- firmware/baseband/audio_output.cpp | 11 +++++++++++ firmware/baseband/audio_output.hpp | 4 ++++ firmware/baseband/block_decimator.hpp | 6 +++--- firmware/baseband/proc_am_audio.cpp | 8 ++------ firmware/baseband/proc_am_audio.hpp | 2 -- firmware/baseband/proc_nfm_audio.cpp | 8 ++------ firmware/baseband/proc_nfm_audio.hpp | 2 -- firmware/baseband/spectrum_collector.hpp | 2 +- 8 files changed, 23 insertions(+), 20 deletions(-) diff --git a/firmware/baseband/audio_output.cpp b/firmware/baseband/audio_output.cpp index 6e29fa161..fa67eab26 100644 --- a/firmware/baseband/audio_output.cpp +++ b/firmware/baseband/audio_output.cpp @@ -57,6 +57,17 @@ void AudioOutput::write( void AudioOutput::write( const buffer_f32_t& audio +) { + block_buffer.feed( + audio, + [this](const buffer_f32_t& buffer) { + this->on_block(buffer); + } + ); +} + +void AudioOutput::on_block( + const buffer_f32_t& audio ) { const auto audio_present_now = squelch.execute(audio); diff --git a/firmware/baseband/audio_output.hpp b/firmware/baseband/audio_output.hpp index df490d3c8..0ebaa8cdd 100644 --- a/firmware/baseband/audio_output.hpp +++ b/firmware/baseband/audio_output.hpp @@ -27,6 +27,7 @@ #include "dsp_iir.hpp" #include "dsp_squelch.hpp" +#include "block_decimator.hpp" #include "audio_stats_collector.hpp" #include @@ -43,6 +44,8 @@ public: void write(const buffer_f32_t& audio); private: + BlockDecimator block_buffer { 1 }; + IIRBiquadFilter hpf; IIRBiquadFilter deemph; FMSquelch squelch; @@ -51,6 +54,7 @@ private: uint64_t audio_present_history = 0; + void on_block(const buffer_f32_t& audio); void fill_audio_buffer(const buffer_f32_t& audio); void feed_audio_stats(const buffer_f32_t& audio); }; diff --git a/firmware/baseband/block_decimator.hpp b/firmware/baseband/block_decimator.hpp index 1f7710efc..7782dc371 100644 --- a/firmware/baseband/block_decimator.hpp +++ b/firmware/baseband/block_decimator.hpp @@ -29,7 +29,7 @@ #include "dsp_types.hpp" #include "complex.hpp" -template +template class BlockDecimator { public: constexpr BlockDecimator( @@ -65,7 +65,7 @@ public: } template - void feed(const buffer_c16_t& src, BlockCallback callback) { + void feed(const buffer_t& src, BlockCallback callback) { /* NOTE: Input block size must be >= factor */ set_input_sampling_rate(src.sampling_rate); @@ -85,7 +85,7 @@ public: } private: - std::array buffer; + std::array buffer; uint32_t input_sampling_rate_ { 0 }; size_t factor_ { 1 }; size_t src_i { 0 }; diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 65ad8e9e0..c522eb6df 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -38,12 +38,8 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { feed_channel_stats(channel_out); channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); - channel_block_buffer.feed( - channel_out, [this](const buffer_c16_t buffer) { - auto audio = this->demod.execute(buffer, this->audio_buffer); - this->audio_output.write(audio); - } - ); + auto audio = demod.execute(channel_out, audio_buffer); + audio_output.write(audio); } void NarrowbandAMAudio::on_message(const Message* const message) { diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index e2e76e95d..43ec8c971 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -58,8 +58,6 @@ private: uint32_t channel_filter_pass_f = 0; uint32_t channel_filter_stop_f = 0; - BlockDecimator<32> channel_block_buffer { post_channel_decimation_factor }; - dsp::demodulate::AM demod; AudioOutput audio_output; diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 3fd9f5e38..3bc880434 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -38,12 +38,8 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) { feed_channel_stats(channel_out); channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); - channel_block_buffer.feed( - channel_out, [this](const buffer_c16_t buffer) { - auto audio = this->demod.execute(buffer, this->audio_buffer); - this->audio_output.write(audio); - } - ); + auto audio = demod.execute(channel_out, audio_buffer); + audio_output.write(audio); } void NarrowbandFMAudio::on_message(const Message* const message) { diff --git a/firmware/baseband/proc_nfm_audio.hpp b/firmware/baseband/proc_nfm_audio.hpp index 6f0866946..dbae4f5fd 100644 --- a/firmware/baseband/proc_nfm_audio.hpp +++ b/firmware/baseband/proc_nfm_audio.hpp @@ -58,8 +58,6 @@ private: uint32_t channel_filter_pass_f = 0; uint32_t channel_filter_stop_f = 0; - BlockDecimator<32> channel_block_buffer { post_channel_decimation_factor }; - dsp::demodulate::FM demod; AudioOutput audio_output; diff --git a/firmware/baseband/spectrum_collector.hpp b/firmware/baseband/spectrum_collector.hpp index 4c2cd5420..6c50120be 100644 --- a/firmware/baseband/spectrum_collector.hpp +++ b/firmware/baseband/spectrum_collector.hpp @@ -50,7 +50,7 @@ public: ); private: - BlockDecimator<256> channel_spectrum_decimator; + BlockDecimator channel_spectrum_decimator; ChannelSpectrumFIFO fifo; volatile bool channel_spectrum_request_update { false }; From 2fd8b1c4d40682e8c1b863116651277e51cd4d81 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 21:05:43 -0800 Subject: [PATCH 413/452] Bodge in preset control of NBFM bandwidth/deviation. --- firmware/application/analog_audio_app.cpp | 26 +++++++++++++++++------ firmware/application/analog_audio_app.hpp | 2 +- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 75ce47817..a820dc62d 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -40,7 +40,7 @@ AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { switch(mode) { case ReceiverModel::Mode::NarrowbandFMAudio: - configure_nbfm(); + configure_nbfm(2); break; case ReceiverModel::Mode::WidebandFMAudio: @@ -57,13 +57,27 @@ AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { } -void AnalogAudioModel::configure_nbfm() { +struct NBFMMode { + const fir_taps_real<24> decim_0; + const fir_taps_real<32> decim_1; + const fir_taps_real<32> channel; + const size_t deviation; +}; + +static constexpr std::array nbfm_mode_configs { { + { taps_4k25_decim_0, taps_4k25_decim_1, taps_4k25_channel, 2500 }, + { taps_11k0_decim_0, taps_11k0_decim_1, taps_11k0_channel, 2500 }, + { taps_16k0_decim_0, taps_16k0_decim_1, taps_16k0_channel, 5000 }, +} }; + +void AnalogAudioModel::configure_nbfm(const size_t index) { + const auto config = nbfm_mode_configs[index]; const NBFMConfigureMessage message { - taps_4k25_decim_0, - taps_4k25_decim_1, - taps_4k25_channel, + config.decim_0, + config.decim_1, + config.channel, 2, - 2500, + config.deviation, audio_24k_hpf_300hz_config, audio_24k_deemph_300_6_config }; diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 7c840ced4..f032f01f9 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -30,7 +30,7 @@ public: AnalogAudioModel(ReceiverModel::Mode mode); private: - void configure_nbfm(); + void configure_nbfm(const size_t index); void configure_wfm(); void configure_am(); }; From 220b7b0a6ac4269d8fecbbb895767d4bc7e63f09 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 22:27:18 -0800 Subject: [PATCH 414/452] Add SSB demodulator. --- firmware/baseband/dsp_demodulate.cpp | 17 +++++++++++++++++ firmware/baseband/dsp_demodulate.hpp | 8 ++++++++ 2 files changed, 25 insertions(+) diff --git a/firmware/baseband/dsp_demodulate.cpp b/firmware/baseband/dsp_demodulate.cpp index b6cbc45ef..6645f424b 100644 --- a/firmware/baseband/dsp_demodulate.cpp +++ b/firmware/baseband/dsp_demodulate.cpp @@ -55,6 +55,23 @@ buffer_f32_t AM::execute( return { dst.p, src.count, src.sampling_rate }; } + +buffer_f32_t SSB::execute( + const buffer_c16_t& src, + const buffer_f32_t& dst +) { + const complex16_t* src_p = src.p; + const auto src_end = &src.p[src.count]; + auto dst_p = dst.p; + while(src_p < src_end) { + *(dst_p++) = (src_p++)->real(); + *(dst_p++) = (src_p++)->real(); + *(dst_p++) = (src_p++)->real(); + *(dst_p++) = (src_p++)->real(); + } + + return { dst.p, src.count, src.sampling_rate }; +} /* static inline float angle_approx_4deg0(const complex32_t t) { const auto x = static_cast(t.imag()) / static_cast(t.real()); diff --git a/firmware/baseband/dsp_demodulate.hpp b/firmware/baseband/dsp_demodulate.hpp index c93d3b196..d7117b9d9 100644 --- a/firmware/baseband/dsp_demodulate.hpp +++ b/firmware/baseband/dsp_demodulate.hpp @@ -35,6 +35,14 @@ public: ); }; +class SSB { +public: + buffer_f32_t execute( + const buffer_c16_t& src, + const buffer_f32_t& dst + ); +}; + class FM { public: buffer_f32_t execute( From b9c2ba40537bf7b05a0927318e96f93e8b1229b2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 22:29:23 -0800 Subject: [PATCH 415/452] Add fir_taps_complex structure. --- firmware/common/dsp_fir_taps.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/firmware/common/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp index c043cab93..c83ad11ee 100644 --- a/firmware/common/dsp_fir_taps.hpp +++ b/firmware/common/dsp_fir_taps.hpp @@ -34,6 +34,13 @@ struct fir_taps_real { std::array taps; }; +template +struct fir_taps_complex { + float pass_frequency_normalized; + float stop_frequency_normalized; + std::array taps; +}; + // NBFM 16K0F3E emission type ///////////////////////////////////////////// // IFIR image-reject filter: fs=3072000, pass=8000, stop=344000, decim=8, fout=384000 From f82a22dd2c6e7d1d876c9f7d092cbb0f9a91d51b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 29 Jan 2016 22:29:52 -0800 Subject: [PATCH 416/452] USB channel filter. --- firmware/common/dsp_fir_taps.hpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/firmware/common/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp index c83ad11ee..b783b8f1f 100644 --- a/firmware/common/dsp_fir_taps.hpp +++ b/firmware/common/dsp_fir_taps.hpp @@ -189,6 +189,32 @@ constexpr fir_taps_real<32> taps_6k0_channel { } }, }; +// USB AM 2K80J3E emission type /////////////////////////////////////////// + +// IFIR prototype filter: fs=48000, pass=3000, stop=6700, decim=1, fout=48000 +constexpr fir_taps_complex<64> taps_2k8_usb_channel { + .pass_frequency_normalized = 3000.0f / 12000.0f, + .stop_frequency_normalized = 3300.0f / 12000.0f, + .taps = { { + { -146, 0 }, { -41, -45 }, { -1, 10 }, { -95, 69 }, + { -194, -41 }, { -91, -158 }, { 14, -43 }, { -150, 67 }, + { -299, -133 }, { -100, -307 }, { 50, -86 }, { -254, 54 }, + { -453, -329 }, { -62, -587 }, { 170, -189 }, { -334, 0 }, + { -580, -645 }, { 104, -986 }, { 418, -304 }, { -412, -88 }, + { -680, -1178 }, { 527, -1623 }, { 970, -432 }, { -441, -196 }, + { -698, -2149 }, { 1617, -2800 }, { 2384, -507 }, { -429, -311 }, + { -545, -5181 }, { 6925, -7691 }, { 14340, 0 }, { 10601, 11773 }, + { -1499, 14261 }, { -8373, 6083 }, { -5095, -1083 }, { -265, -459 }, + { -753, 2318 }, { -2954, 1315 }, { -2064, -919 }, { -149, -459 }, + { -531, 920 }, { -1669, 355 }, { -1100, -800 }, { -44, -419 }, + { -346, 384 }, { -992, 0 }, { -580, -645 }, { 35, -332 }, + { -205, 149 }, { -577, -123 }, { -280, -485 }, { 80, -247 }, + { -91, 40 }, { -294, -131 }, { -101, -312 }, { 82, -142 }, + { -44, 9 }, { -147, -107 }, { -21, -197 }, { 79, -88 }, + { 10, 0 }, { -41, -45 }, { 15, -145 }, { 0, 0 }, + } }, +}; + // WFM 200KF8E emission type ////////////////////////////////////////////// // IFIR image-reject filter: fs=3072000, pass=100000, stop=484000, decim=4, fout=768000 From b029bacd8c4015820e52fdaeb5d64683e3c4d836 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 17:21:48 -0800 Subject: [PATCH 417/452] Remove channel decimation from AMConfigureMessage. --- firmware/application/analog_audio_app.cpp | 1 - firmware/baseband/proc_am_audio.cpp | 4 ++-- firmware/baseband/proc_am_audio.hpp | 2 ++ firmware/common/message.hpp | 3 --- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index a820dc62d..affcdcd96 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -103,7 +103,6 @@ void AnalogAudioModel::configure_am() { taps_6k0_decim_0, taps_6k0_decim_1, taps_6k0_channel, - 4, audio_12k_hpf_300hz_config }; shared_memory.baseband_queue.push(message); diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index c522eb6df..9d8a2341c 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -66,11 +66,11 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; constexpr size_t channel_filter_input_fs = decim_1_output_fs; - const size_t channel_filter_output_fs = channel_filter_input_fs / message.channel_decimation; + const size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; decim_0.configure(message.decim_0_filter.taps, 33554432); decim_1.configure(message.decim_1_filter.taps, 131072); - channel_filter.configure(message.channel_filter.taps, message.channel_decimation); + channel_filter.configure(message.channel_filter.taps, channel_filter_decimation_factor); channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 43ec8c971..569b5a1de 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -40,6 +40,8 @@ public: private: static constexpr size_t baseband_fs = 3072000; + static constexpr size_t decim_2_decimation_factor = 4; + static constexpr size_t channel_filter_decimation_factor = 1; std::array dst; const buffer_c16_t dst_buffer { diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 1f902af04..1ee92fd5b 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -377,13 +377,11 @@ public: 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 iir_biquad_config_t audio_hpf_config ) : Message { ID::AMConfigure }, decim_0_filter(decim_0_filter), decim_1_filter(decim_1_filter), channel_filter(channel_filter), - channel_decimation { channel_decimation }, audio_hpf_config { audio_hpf_config } { } @@ -391,7 +389,6 @@ public: 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 iir_biquad_config_t audio_hpf_config; }; From 69deaafd1cbde995ea67aa0bb6da4e4cd8455868 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 17:22:38 -0800 Subject: [PATCH 418/452] Clean up formatting of USB FIR filter taps. --- firmware/common/dsp_fir_taps.hpp | 34 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/firmware/common/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp index b783b8f1f..dd9bda9ee 100644 --- a/firmware/common/dsp_fir_taps.hpp +++ b/firmware/common/dsp_fir_taps.hpp @@ -191,27 +191,27 @@ constexpr fir_taps_real<32> taps_6k0_channel { // USB AM 2K80J3E emission type /////////////////////////////////////////// -// IFIR prototype filter: fs=48000, pass=3000, stop=6700, decim=1, fout=48000 +// IFIR prototype filter: fs=12000, pass=3000, stop=3300, decim=1, fout=12000 constexpr fir_taps_complex<64> taps_2k8_usb_channel { .pass_frequency_normalized = 3000.0f / 12000.0f, .stop_frequency_normalized = 3300.0f / 12000.0f, .taps = { { - { -146, 0 }, { -41, -45 }, { -1, 10 }, { -95, 69 }, - { -194, -41 }, { -91, -158 }, { 14, -43 }, { -150, 67 }, - { -299, -133 }, { -100, -307 }, { 50, -86 }, { -254, 54 }, - { -453, -329 }, { -62, -587 }, { 170, -189 }, { -334, 0 }, - { -580, -645 }, { 104, -986 }, { 418, -304 }, { -412, -88 }, - { -680, -1178 }, { 527, -1623 }, { 970, -432 }, { -441, -196 }, - { -698, -2149 }, { 1617, -2800 }, { 2384, -507 }, { -429, -311 }, - { -545, -5181 }, { 6925, -7691 }, { 14340, 0 }, { 10601, 11773 }, - { -1499, 14261 }, { -8373, 6083 }, { -5095, -1083 }, { -265, -459 }, - { -753, 2318 }, { -2954, 1315 }, { -2064, -919 }, { -149, -459 }, - { -531, 920 }, { -1669, 355 }, { -1100, -800 }, { -44, -419 }, - { -346, 384 }, { -992, 0 }, { -580, -645 }, { 35, -332 }, - { -205, 149 }, { -577, -123 }, { -280, -485 }, { 80, -247 }, - { -91, 40 }, { -294, -131 }, { -101, -312 }, { 82, -142 }, - { -44, 9 }, { -147, -107 }, { -21, -197 }, { 79, -88 }, - { 10, 0 }, { -41, -45 }, { 15, -145 }, { 0, 0 }, + { -146, 0 }, { -41, -45 }, { -1, 10 }, { -95, 69 }, + { -194, -41 }, { -91, -158 }, { 14, -43 }, { -150, 67 }, + { -299, -133 }, { -100, -307 }, { 50, -86 }, { -254, 54 }, + { -453, -329 }, { -62, -587 }, { 170, -189 }, { -334, 0 }, + { -580, -645 }, { 104, -986 }, { 418, -304 }, { -412, -88 }, + { -680, -1178 }, { 527, -1623 }, { 970, -432 }, { -441, -196 }, + { -698, -2149 }, { 1617, -2800 }, { 2384, -507 }, { -429, -311 }, + { -545, -5181 }, { 6925, -7691 }, { 14340, 0 }, { 10601, 11773 }, + { -1499, 14261 }, { -8373, 6083 }, { -5095, -1083 }, { -265, -459 }, + { -753, 2318 }, { -2954, 1315 }, { -2064, -919 }, { -149, -459 }, + { -531, 920 }, { -1669, 355 }, { -1100, -800 }, { -44, -419 }, + { -346, 384 }, { -992, 0 }, { -580, -645 }, { 35, -332 }, + { -205, 149 }, { -577, -123 }, { -280, -485 }, { 80, -247 }, + { -91, 40 }, { -294, -131 }, { -101, -312 }, { 82, -142 }, + { -44, 9 }, { -147, -107 }, { -21, -197 }, { 79, -88 }, + { 10, 0 }, { -41, -45 }, { 15, -145 }, { 0, 0 }, } }, }; From 279e5c775d97ee738da5935e307a7c3960504c05 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 17:23:04 -0800 Subject: [PATCH 419/452] Add LSB filter taps. --- firmware/common/dsp_fir_taps.hpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/firmware/common/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp index dd9bda9ee..46c7ca2c2 100644 --- a/firmware/common/dsp_fir_taps.hpp +++ b/firmware/common/dsp_fir_taps.hpp @@ -215,6 +215,32 @@ constexpr fir_taps_complex<64> taps_2k8_usb_channel { } }, }; +// LSB AM 2K80J3E emission type /////////////////////////////////////////// + +// IFIR prototype filter: fs=12000, pass=3000, stop=3300, decim=1, fout=12000 +constexpr fir_taps_complex<64> taps_2k8_lsb_channel { + .pass_frequency_normalized = 3000.0f / 12000.0f, + .stop_frequency_normalized = 3300.0f / 12000.0f, + .taps = { { + { -146, 0 }, { -41, 45 }, { -1, -10 }, { -95, -69 }, + { -194, 41 }, { -91, 158 }, { 14, 43 }, { -150, -67 }, + { -299, 133 }, { -100, 307 }, { 50, 86 }, { -254, -54 }, + { -453, 329 }, { -62, 587 }, { 170, 189 }, { -334, 0 }, + { -580, 645 }, { 104, 986 }, { 418, 304 }, { -412, 88 }, + { -680, 1178 }, { 527, 1623 }, { 970, 432 }, { -441, 196 }, + { -698, 2149 }, { 1617, 2800 }, { 2384, 507 }, { -429, 311 }, + { -545, 5181 }, { 6925, 7691 }, { 14340, 0 }, { 10601, -11773 }, + { -1499, -14261 }, { -8373, -6083 }, { -5095, 1083 }, { -265, 459 }, + { -753, -2318 }, { -2954, -1315 }, { -2064, 919 }, { -149, 459 }, + { -531, -920 }, { -1669, -355 }, { -1100, 800 }, { -44, 419 }, + { -346, -384 }, { -992, 0 }, { -580, 645 }, { 35, 332 }, + { -205, -149 }, { -577, 123 }, { -280, 485 }, { 80, 247 }, + { -91, -40 }, { -294, 131 }, { -101, 312 }, { 82, 142 }, + { -44, -9 }, { -147, 107 }, { -21, 197 }, { 79, 88 }, + { 10, 0 }, { -41, 45 }, { 15, 145 }, { 0, 0 }, + } }, +}; + // WFM 200KF8E emission type ////////////////////////////////////////////// // IFIR image-reject filter: fs=3072000, pass=100000, stop=484000, decim=4, fout=768000 From 1915ff980ff8df5ea02df4320551dab07df7fbc5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 17:28:11 -0800 Subject: [PATCH 420/452] Add AM processor decim_2. --- firmware/application/analog_audio_app.cpp | 1 + firmware/baseband/proc_am_audio.cpp | 9 +++++++-- firmware/baseband/proc_am_audio.hpp | 1 + firmware/common/dsp_fir_taps.hpp | 2 +- firmware/common/message.hpp | 3 +++ 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index affcdcd96..60eaca4e3 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -102,6 +102,7 @@ void AnalogAudioModel::configure_am() { const AMConfigureMessage message { taps_6k0_decim_0, taps_6k0_decim_1, + taps_6k0_decim_2, taps_6k0_channel, audio_12k_hpf_300hz_config }; diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index 9d8a2341c..ad655f542 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -32,7 +32,8 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { const auto decim_0_out = decim_0.execute(buffer, dst_buffer); const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); - const auto channel_out = channel_filter.execute(decim_1_out, dst_buffer); + const auto decim_2_out = decim_2.execute(decim_1_out, dst_buffer); + const auto channel_out = channel_filter.execute(decim_2_out, dst_buffer); // TODO: Feed channel_stats post-decimation data? feed_channel_stats(channel_out); @@ -65,11 +66,15 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { constexpr size_t decim_1_input_fs = decim_0_output_fs; constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; - constexpr size_t channel_filter_input_fs = decim_1_output_fs; + constexpr size_t decim_2_input_fs = decim_1_output_fs; + constexpr size_t decim_2_output_fs = decim_2_input_fs / decim_2_decimation_factor; + + constexpr size_t channel_filter_input_fs = decim_2_output_fs; const size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor; decim_0.configure(message.decim_0_filter.taps, 33554432); decim_1.configure(message.decim_1_filter.taps, 131072); + decim_2.configure(message.decim_2_filter.taps, decim_2_decimation_factor); channel_filter.configure(message.channel_filter.taps, channel_filter_decimation_factor); channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 569b5a1de..07406aa2e 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -56,6 +56,7 @@ private: dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; dsp::decimate::FIRC16xR16x32Decim8 decim_1; + dsp::decimate::FIRAndDecimateComplex decim_2; dsp::decimate::FIRAndDecimateComplex channel_filter; uint32_t channel_filter_pass_f = 0; uint32_t channel_filter_stop_f = 0; diff --git a/firmware/common/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp index 46c7ca2c2..53c7fa5a9 100644 --- a/firmware/common/dsp_fir_taps.hpp +++ b/firmware/common/dsp_fir_taps.hpp @@ -178,7 +178,7 @@ constexpr fir_taps_real<32> taps_6k0_decim_1 { }; // Channel filter: fs=48000, pass=3000, stop=6700, decim=1, fout=48000 -constexpr fir_taps_real<32> taps_6k0_channel { +constexpr fir_taps_real<32> taps_6k0_decim_2 { .pass_frequency_normalized = 3000.0f / 48000.0f, .stop_frequency_normalized = 6700.0f / 48000.0f, .taps = { { diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 1ee92fd5b..dc3385ea9 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -376,11 +376,13 @@ public: 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_real<32> channel_filter, 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), audio_hpf_config { audio_hpf_config } { @@ -388,6 +390,7 @@ public: 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_real<32> channel_filter; const iir_biquad_config_t audio_hpf_config; }; From ad4d7a2e8ace8dc9474d7fc6c952f95ca4fbb0ee Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 17:30:03 -0800 Subject: [PATCH 421/452] Add SSB demodulator, switch between AM and SSB. --- firmware/baseband/proc_am_audio.cpp | 9 +++++++-- firmware/baseband/proc_am_audio.hpp | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index ad655f542..dc94b7b17 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -39,8 +39,13 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { feed_channel_stats(channel_out); channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); - auto audio = demod.execute(channel_out, audio_buffer); - audio_output.write(audio); + if( false ) { + auto audio = demod_am.execute(channel_out, audio_buffer); + audio_output.write(audio); + } else { + auto audio = demod_ssb.execute(channel_out, audio_buffer); + audio_output.write(audio); + } } void NarrowbandAMAudio::on_message(const Message* const message) { diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index 07406aa2e..a695df3da 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -61,7 +61,8 @@ private: uint32_t channel_filter_pass_f = 0; uint32_t channel_filter_stop_f = 0; - dsp::demodulate::AM demod; + dsp::demodulate::AM demod_am; + dsp::demodulate::SSB demod_ssb; AudioOutput audio_output; From f2dff168205f375949ecd4f574a056b11b306450 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 17:30:54 -0800 Subject: [PATCH 422/452] Use complex channel filter taps for AM/SSB. --- firmware/application/analog_audio_app.cpp | 2 +- firmware/baseband/dsp_decimate.cpp | 12 ------------ firmware/baseband/dsp_decimate.hpp | 11 +++++++++-- firmware/common/message.hpp | 6 +++--- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 60eaca4e3..082dbae4c 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -103,7 +103,7 @@ void AnalogAudioModel::configure_am() { taps_6k0_decim_0, taps_6k0_decim_1, taps_6k0_decim_2, - taps_6k0_channel, + taps_2k8_usb_channel, audio_12k_hpf_300hz_config }; shared_memory.baseband_queue.push(message); diff --git a/firmware/baseband/dsp_decimate.cpp b/firmware/baseband/dsp_decimate.cpp index af5f12e39..abd8e7d03 100644 --- a/firmware/baseband/dsp_decimate.cpp +++ b/firmware/baseband/dsp_decimate.cpp @@ -645,18 +645,6 @@ buffer_s16_t FIR64AndDecimateBy2Real::execute( return { dst.p, src.count / 2, src.sampling_rate / 2 }; } -void FIRAndDecimateComplex::configure( - const int16_t* const taps, - const size_t taps_count, - const size_t decimation_factor -) { - samples_ = std::make_unique(taps_count); - taps_reversed_ = std::make_unique(taps_count); - taps_count_ = taps_count; - decimation_factor_ = decimation_factor; - std::reverse_copy(&taps[0], &taps[taps_count], &taps_reversed_[0]); -} - buffer_c16_t FIRAndDecimateComplex::execute( const buffer_c16_t& src, const buffer_c16_t& dst diff --git a/firmware/baseband/dsp_decimate.hpp b/firmware/baseband/dsp_decimate.hpp index 0f4ca8453..1a9bf303c 100644 --- a/firmware/baseband/dsp_decimate.hpp +++ b/firmware/baseband/dsp_decimate.hpp @@ -235,11 +235,18 @@ private: size_t taps_count_; size_t decimation_factor_; + template void configure( - const int16_t* const taps, + const T* const taps, const size_t taps_count, const size_t decimation_factor - ); + ) { + samples_ = std::make_unique(taps_count); + taps_reversed_ = std::make_unique(taps_count); + taps_count_ = taps_count; + decimation_factor_ = decimation_factor; + std::reverse_copy(&taps[0], &taps[taps_count], &taps_reversed_[0]); + } }; class DecimateBy2CIC4Real { diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index dc3385ea9..79e512672 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -39,7 +39,7 @@ class Message { public: - static constexpr size_t MAX_SIZE = 288; + static constexpr size_t MAX_SIZE = 512; enum class ID : uint32_t { /* Assign consecutive IDs. IDs are used to index array. */ @@ -377,7 +377,7 @@ public: 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_real<32> channel_filter, + const fir_taps_complex<64> channel_filter, const iir_biquad_config_t audio_hpf_config ) : Message { ID::AMConfigure }, decim_0_filter(decim_0_filter), @@ -391,7 +391,7 @@ public: 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_real<32> channel_filter; + const fir_taps_complex<64> channel_filter; const iir_biquad_config_t audio_hpf_config; }; From e778be6472bac69bbac4aaa8fa1e131ee72eef08 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 18:02:28 -0800 Subject: [PATCH 423/452] Selection of AM/SSB from application side. --- firmware/application/analog_audio_app.cpp | 1 + firmware/baseband/proc_am_audio.cpp | 14 +++++++++----- firmware/baseband/proc_am_audio.hpp | 3 +++ firmware/common/message.hpp | 8 ++++++++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 082dbae4c..e333b7c20 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -104,6 +104,7 @@ void AnalogAudioModel::configure_am() { taps_6k0_decim_1, taps_6k0_decim_2, taps_2k8_usb_channel, + AMConfigureMessage::Modulation::SSB, audio_12k_hpf_300hz_config }; shared_memory.baseband_queue.push(message); diff --git a/firmware/baseband/proc_am_audio.cpp b/firmware/baseband/proc_am_audio.cpp index dc94b7b17..3a073db49 100644 --- a/firmware/baseband/proc_am_audio.cpp +++ b/firmware/baseband/proc_am_audio.cpp @@ -39,12 +39,15 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) { feed_channel_stats(channel_out); channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f); - if( false ) { - auto audio = demod_am.execute(channel_out, audio_buffer); - audio_output.write(audio); + auto audio = demodulate(channel_out); + audio_output.write(audio); +} + +buffer_f32_t NarrowbandAMAudio::demodulate(const buffer_c16_t& channel) { + if( modulation_ssb ) { + return demod_ssb.execute(channel, audio_buffer); } else { - auto audio = demod_ssb.execute(channel_out, audio_buffer); - audio_output.write(audio); + return demod_am.execute(channel, audio_buffer); } } @@ -84,6 +87,7 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); + modulation_ssb = (message.modulation == AMConfigureMessage::Modulation::SSB); audio_output.configure(message.audio_hpf_config); configured = true; diff --git a/firmware/baseband/proc_am_audio.hpp b/firmware/baseband/proc_am_audio.hpp index a695df3da..226720e26 100644 --- a/firmware/baseband/proc_am_audio.hpp +++ b/firmware/baseband/proc_am_audio.hpp @@ -61,6 +61,7 @@ private: uint32_t channel_filter_pass_f = 0; uint32_t channel_filter_stop_f = 0; + bool modulation_ssb = false; dsp::demodulate::AM demod_am; dsp::demodulate::SSB demod_ssb; @@ -70,6 +71,8 @@ private: bool configured { false }; void configure(const AMConfigureMessage& message); + + buffer_f32_t demodulate(const buffer_c16_t& channel); }; #endif/*__PROC_AM_AUDIO_H__*/ diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 79e512672..cf8454e5f 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -373,17 +373,24 @@ public: class AMConfigureMessage : public Message { public: + enum class Modulation : int32_t { + AM = 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 } { } @@ -392,6 +399,7 @@ public: 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; }; From a1e1677b8b57d75686282700a3d3bbe3640b4a0e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 18:17:29 -0800 Subject: [PATCH 424/452] Rename AM modulation mode "DSB". --- firmware/common/message.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index cf8454e5f..278d69ec4 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -374,7 +374,7 @@ public: class AMConfigureMessage : public Message { public: enum class Modulation : int32_t { - AM = 0, + DSB = 0, SSB = 1, }; From a97cd642acecee73f380648c8b9b6b13282757a2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 19:03:32 -0800 Subject: [PATCH 425/452] Multiple AM modes selection in application API. --- firmware/application/analog_audio_app.cpp | 20 ++++++++++++++++---- firmware/application/analog_audio_app.hpp | 2 +- firmware/common/dsp_fir_taps.hpp | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index e333b7c20..d5094c60b 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -48,7 +48,7 @@ AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { break; case ReceiverModel::Mode::AMAudio: - configure_am(); + configure_am(0); break; default: @@ -98,13 +98,25 @@ void AnalogAudioModel::configure_wfm() { clock_manager.set_base_audio_clock_divider(1); } -void AnalogAudioModel::configure_am() { +struct AMMode { + const fir_taps_complex<64> channel; + const AMConfigureMessage::Modulation modulation; +}; + +static constexpr std::array am_mode_configs { { + { taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, + { taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB }, + { taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB }, +} }; + +void AnalogAudioModel::configure_am(const size_t index) { + const auto config = am_mode_configs[index]; const AMConfigureMessage message { taps_6k0_decim_0, taps_6k0_decim_1, taps_6k0_decim_2, - taps_2k8_usb_channel, - AMConfigureMessage::Modulation::SSB, + config.channel, + config.modulation, audio_12k_hpf_300hz_config }; shared_memory.baseband_queue.push(message); diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index f032f01f9..a598a6b40 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -32,7 +32,7 @@ public: private: void configure_nbfm(const size_t index); void configure_wfm(); - void configure_am(); + void configure_am(const size_t index); }; namespace ui { diff --git a/firmware/common/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp index 53c7fa5a9..63944282e 100644 --- a/firmware/common/dsp_fir_taps.hpp +++ b/firmware/common/dsp_fir_taps.hpp @@ -189,6 +189,29 @@ constexpr fir_taps_real<32> taps_6k0_decim_2 { } }, }; +constexpr fir_taps_complex<64> taps_6k0_dsb_channel { + .pass_frequency_normalized = 3000.0f / 12000.0f, + .stop_frequency_normalized = 3300.0f / 12000.0f, + .taps = { { + { -70, 0 }, { -142, 0 }, { 121, 0 }, { 90, 0 }, + { -134, 0 }, { -136, 0 }, { 200, 0 }, { 170, 0 }, + { -278, 0 }, { -209, 0 }, { 378, 0 }, { 251, 0 }, + { -505, 0 }, { -294, 0 }, { 665, 0 }, { 336, 0 }, + { -868, 0 }, { -378, 0 }, { 1131, 0 }, { 417, 0 }, + { -1479, 0 }, { -453, 0 }, { 1965, 0 }, { 484, 0 }, + { -2698, 0 }, { -510, 0 }, { 3967, 0 }, { 528, 0 }, + { -6829, 0 }, { -540, 0 }, { 20819, 0 }, { 32767, 0 }, /* TODO: Saturated peak! Originally 33312. */ + { 20819, 0 }, { -540, 0 }, { -6829, 0 }, { 528, 0 }, + { 3967, 0 }, { -510, 0 }, { -2698, 0 }, { 484, 0 }, + { 1965, 0 }, { -453, 0 }, { -1479, 0 }, { 417, 0 }, + { 1131, 0 }, { -378, 0 }, { -868, 0 }, { 336, 0 }, + { 665, 0 }, { -294, 0 }, { -505, 0 }, { 251, 0 }, + { 378, 0 }, { -209, 0 }, { -278, 0 }, { 170, 0 }, + { 200, 0 }, { -136, 0 }, { -134, 0 }, { 90, 0 }, + { 121, 0 }, { -142, 0 }, { -70, 0 }, { 0, 0 }, + } }, +}; + // USB AM 2K80J3E emission type /////////////////////////////////////////// // IFIR prototype filter: fs=12000, pass=3000, stop=3300, decim=1, fout=12000 From a79aa3e5809915d8e007f6df92e308e947615b9b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 19:03:50 -0800 Subject: [PATCH 426/452] Correct DSB decim_2 FIR taps comment. --- firmware/common/dsp_fir_taps.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp index 63944282e..7ce8bd298 100644 --- a/firmware/common/dsp_fir_taps.hpp +++ b/firmware/common/dsp_fir_taps.hpp @@ -177,7 +177,7 @@ constexpr fir_taps_real<32> taps_6k0_decim_1 { } }, }; -// Channel filter: fs=48000, pass=3000, stop=6700, decim=1, fout=48000 +// IFIR prototype filter: fs=48000, pass=3000, stop=6700, decim=4, fout=12000 constexpr fir_taps_real<32> taps_6k0_decim_2 { .pass_frequency_normalized = 3000.0f / 48000.0f, .stop_frequency_normalized = 6700.0f / 48000.0f, From ccafc1e82c68dfda72d147edb7affe1f2732998f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 20:45:16 -0800 Subject: [PATCH 427/452] Fix DSB channel filter taps, don't saturate max tap value. --- firmware/common/dsp_fir_taps.hpp | 36 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/firmware/common/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp index 7ce8bd298..535809b86 100644 --- a/firmware/common/dsp_fir_taps.hpp +++ b/firmware/common/dsp_fir_taps.hpp @@ -189,26 +189,30 @@ constexpr fir_taps_real<32> taps_6k0_decim_2 { } }, }; +// Channel filter: fs=12000, pass=3000, stop=3300, decim=1, fout=12000 +/* NOTE: Slightly less than 1.0 gain (normalized to 65536) due to max(taps) being + * slightly larger than 32767 (33312). + */ constexpr fir_taps_complex<64> taps_6k0_dsb_channel { .pass_frequency_normalized = 3000.0f / 12000.0f, .stop_frequency_normalized = 3300.0f / 12000.0f, .taps = { { - { -70, 0 }, { -142, 0 }, { 121, 0 }, { 90, 0 }, - { -134, 0 }, { -136, 0 }, { 200, 0 }, { 170, 0 }, - { -278, 0 }, { -209, 0 }, { 378, 0 }, { 251, 0 }, - { -505, 0 }, { -294, 0 }, { 665, 0 }, { 336, 0 }, - { -868, 0 }, { -378, 0 }, { 1131, 0 }, { 417, 0 }, - { -1479, 0 }, { -453, 0 }, { 1965, 0 }, { 484, 0 }, - { -2698, 0 }, { -510, 0 }, { 3967, 0 }, { 528, 0 }, - { -6829, 0 }, { -540, 0 }, { 20819, 0 }, { 32767, 0 }, /* TODO: Saturated peak! Originally 33312. */ - { 20819, 0 }, { -540, 0 }, { -6829, 0 }, { 528, 0 }, - { 3967, 0 }, { -510, 0 }, { -2698, 0 }, { 484, 0 }, - { 1965, 0 }, { -453, 0 }, { -1479, 0 }, { 417, 0 }, - { 1131, 0 }, { -378, 0 }, { -868, 0 }, { 336, 0 }, - { 665, 0 }, { -294, 0 }, { -505, 0 }, { 251, 0 }, - { 378, 0 }, { -209, 0 }, { -278, 0 }, { 170, 0 }, - { 200, 0 }, { -136, 0 }, { -134, 0 }, { 90, 0 }, - { 121, 0 }, { -142, 0 }, { -70, 0 }, { 0, 0 }, + { -69, 0 }, { -140, 0 }, { 119, 0 }, { 89, 0 }, + { -132, 0 }, { -134, 0 }, { 197, 0 }, { 167, 0 }, + { -273, 0 }, { -206, 0 }, { 372, 0 }, { 247, 0 }, + { -497, 0 }, { -289, 0 }, { 654, 0 }, { 331, 0 }, + { -854, 0 }, { -372, 0 }, { 1112, 0 }, { 411, 0 }, + { -1455, 0 }, { -446, 0 }, { 1933, 0 }, { 476, 0 }, + { -2654, 0 }, { -501, 0 }, { 3902, 0 }, { 520, 0 }, + { -6717, 0 }, { -531, 0 }, { 20478, 0 }, { 32767, 0 }, + { 20478, 0 }, { -531, 0 }, { -6717, 0 }, { 520, 0 }, + { 3902, 0 }, { -501, 0 }, { -2654, 0 }, { 476, 0 }, + { 1933, 0 }, { -446, 0 }, { -1455, 0 }, { 411, 0 }, + { 1112, 0 }, { -372, 0 }, { -854, 0 }, { 331, 0 }, + { 654, 0 }, { -289, 0 }, { -497, 0 }, { 247, 0 }, + { 372, 0 }, { -206, 0 }, { -273, 0 }, { 167, 0 }, + { 197, 0 }, { -134, 0 }, { -132, 0 }, { 89, 0 }, + { 119, 0 }, { -140, 0 }, { -69, 0 }, { 0, 0 }, } }, }; From faf0fd6b914225861fecafb584f30e22b9c13b4f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 21:11:59 -0800 Subject: [PATCH 428/452] Remove some spurious comments. --- firmware/baseband/dsp_demodulate.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/firmware/baseband/dsp_demodulate.cpp b/firmware/baseband/dsp_demodulate.cpp index 6645f424b..b0eae2b5d 100644 --- a/firmware/baseband/dsp_demodulate.cpp +++ b/firmware/baseband/dsp_demodulate.cpp @@ -34,17 +34,10 @@ buffer_f32_t AM::execute( const buffer_c16_t& src, const buffer_f32_t& dst ) { - /* Intermediate maximum value: 46341 (when input is -32768,-32768). */ - /* Normalized to maximum 32767 for int16_t representation. */ - const auto src_p = src.p; const auto src_end = &src.p[src.count]; auto dst_p = dst.p; while(src_p < src_end) { - // const auto s = *(src_p++); - // const uint32_t r_sq = s.real() * s.real(); - // const uint32_t i_sq = s.imag() * s.imag(); - // const uint32_t mag_sq = r_sq + i_sq; const uint32_t sample0 = *__SIMD32(src_p)++; const uint32_t sample1 = *__SIMD32(src_p)++; const uint32_t mag_sq0 = __SMUAD(sample0, sample0); From f134e63f0577f9972445ca712362772c5f11855d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 30 Jan 2016 22:23:22 -0800 Subject: [PATCH 429/452] Initialize Spectrum FIFO pointer to nullptr. --- firmware/application/ui_spectrum.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/ui_spectrum.hpp b/firmware/application/ui_spectrum.hpp index 0c9321df9..8b0381f45 100644 --- a/firmware/application/ui_spectrum.hpp +++ b/firmware/application/ui_spectrum.hpp @@ -84,7 +84,7 @@ public: private: WaterfallView waterfall_view; FrequencyScale frequency_scale; - ChannelSpectrumFIFO* fifo; + ChannelSpectrumFIFO* fifo { nullptr }; void on_channel_spectrum(const ChannelSpectrum& spectrum); }; From 4d3294c2280b1d02ba643cdc47ffee4ee72db28f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 31 Jan 2016 09:13:44 -0800 Subject: [PATCH 430/452] Move ReceiverView code to AnalogAudioView. ReceiverView predated the "app" model, was serving as a shell for *all* radio activity, but became outmoded and redundant when non-audio modes were split out into separate apps. Some stuff is broken in this change, will be fixed imminently. --- firmware/application/Makefile | 1 - firmware/application/analog_audio_app.cpp | 251 ++++++++++++++++-- firmware/application/analog_audio_app.hpp | 113 +++++++- .../application/spectrum_analysis_app.cpp | 34 --- .../application/spectrum_analysis_app.hpp | 44 --- firmware/application/ui_navigation.cpp | 4 +- firmware/application/ui_receiver.cpp | 186 +------------ firmware/application/ui_receiver.hpp | 100 ------- 8 files changed, 331 insertions(+), 402 deletions(-) delete mode 100644 firmware/application/spectrum_analysis_app.cpp delete mode 100644 firmware/application/spectrum_analysis_app.hpp diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 4aa171a48..5b2262e6b 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -175,7 +175,6 @@ CPPSRC = main.cpp \ tpms_app.cpp \ ert_app.cpp \ ../common/ert_packet.cpp \ - spectrum_analysis_app.cpp \ sd_card.cpp \ file.cpp \ log_file.cpp \ diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index d5094c60b..47cfb8141 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -30,33 +30,6 @@ using namespace portapack; #include "utility.hpp" -AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) { - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 3072000, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); - - switch(mode) { - case ReceiverModel::Mode::NarrowbandFMAudio: - configure_nbfm(2); - break; - - case ReceiverModel::Mode::WidebandFMAudio: - configure_wfm(); - break; - - case ReceiverModel::Mode::AMAudio: - configure_am(0); - break; - - default: - break; - } - -} - struct NBFMMode { const fir_taps_real<24> decim_0; const fir_taps_real<32> decim_1; @@ -122,3 +95,227 @@ void AnalogAudioModel::configure_am(const size_t index) { shared_memory.baseband_queue.push(message); clock_manager.set_base_audio_clock_divider(4); } + +namespace ui { + +/* AnalogAudioView *******************************************************/ + +AnalogAudioView::AnalogAudioView( + NavigationView& nav +) { + add_children({ { + &rssi, + &channel, + &audio, + &field_frequency, + &field_lna, + &field_vga, + &options_modulation, + &field_volume, + &view_frequency_options, + &view_rf_gain_options, + &waterfall, + } }); + + field_frequency.set_value(receiver_model.tuning_frequency()); + field_frequency.set_step(receiver_model.frequency_step()); + field_frequency.on_change = [this](rf::Frequency f) { + this->on_tuning_frequency_changed(f); + }; + field_frequency.on_edit = [this, &nav]() { + // TODO: Provide separate modal method/scheme? + auto new_view = nav.push(receiver_model.tuning_frequency()); + new_view->on_changed = [this](rf::Frequency f) { + this->on_tuning_frequency_changed(f); + this->field_frequency.set_value(f); + }; + }; + + field_frequency.on_show_options = [this]() { + this->on_show_options_frequency(); + }; + + field_lna.set_value(receiver_model.lna()); + field_lna.on_change = [this](int32_t v) { + this->on_lna_changed(v); + }; + + field_lna.on_show_options = [this]() { + this->on_show_options_rf_gain(); + }; + + field_vga.set_value(receiver_model.vga()); + field_vga.on_change = [this](int32_t v_db) { + this->on_vga_changed(v_db); + }; + + options_modulation.set_by_value(1); + options_modulation.on_change = [this](size_t n, OptionsField::value_t v) { + (void)n; + this->on_modulation_changed(v); + }; + + field_volume.set_value((receiver_model.headphone_volume() - wolfson::wm8731::headphone_gain_range.max).decibel() + 99); + field_volume.on_change = [this](int32_t v) { + this->on_headphone_volume_changed(v); + }; + + view_frequency_options.hidden(true); + view_frequency_options.set_step(receiver_model.frequency_step()); + view_frequency_options.on_change_step = [this](rf::Frequency f) { + this->on_frequency_step_changed(f); + }; + view_frequency_options.set_reference_ppm_correction(receiver_model.reference_ppm_correction()); + view_frequency_options.on_change_reference_ppm_correction = [this](int32_t v) { + this->on_reference_ppm_correction_changed(v); + }; + + view_rf_gain_options.hidden(true); + view_rf_gain_options.set_rf_amp(receiver_model.rf_amp()); + view_rf_gain_options.on_change_rf_amp = [this](bool enable) { + this->on_rf_amp_changed(enable); + }; +} + +AnalogAudioView::~AnalogAudioView() { + // TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do + // both? + audio_codec.headphone_mute(); + + receiver_model.disable(); +} + +void AnalogAudioView::on_show() { + View::on_show(); + // TODO: Terrible kludge because widget system doesn't notify Waterfall that + // it's being shown or hidden. +} + +void AnalogAudioView::on_hide() { + // TODO: Terrible kludge because widget system doesn't notify Waterfall that + // it's being shown or hidden. + waterfall.on_hide(); + View::on_hide(); +} + +void AnalogAudioView::set_parent_rect(const Rect new_parent_rect) { + View::set_parent_rect(new_parent_rect); + + const ui::Rect waterfall_rect { 0, header_height, new_parent_rect.width(), static_cast(new_parent_rect.height() - header_height) }; + waterfall.set_parent_rect(waterfall_rect); +} + +void AnalogAudioView::focus() { + field_frequency.focus(); +} + +void AnalogAudioView::on_tuning_frequency_changed(rf::Frequency f) { + receiver_model.set_tuning_frequency(f); +} + +void AnalogAudioView::on_baseband_bandwidth_changed(uint32_t bandwidth_hz) { + receiver_model.set_baseband_bandwidth(bandwidth_hz); +} + +void AnalogAudioView::on_rf_amp_changed(bool v) { + receiver_model.set_rf_amp(v); +} + +void AnalogAudioView::on_lna_changed(int32_t v_db) { + receiver_model.set_lna(v_db); +} + +void AnalogAudioView::on_vga_changed(int32_t v_db) { + receiver_model.set_vga(v_db); +} + +void AnalogAudioView::on_modulation_changed(int32_t mode) { + // remove_child(widget_content.get()); + // widget_content.reset(); + + // TODO: Terrible kludge because widget system doesn't notify Waterfall that + // it's being shown or hidden. + waterfall.on_hide(); + + switch(mode) { + default: + case 1: + receiver_model.set_baseband_configuration({ + .mode = toUType(ReceiverModel::Mode::AMAudio), + .sampling_rate = 3072000, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); + receiver_model.enable(); + model.configure_am(0); + waterfall.on_show(); + break; + + case 2: + receiver_model.set_baseband_configuration({ + .mode = toUType(ReceiverModel::Mode::NarrowbandFMAudio), + .sampling_rate = 3072000, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); + receiver_model.enable(); + model.configure_nbfm(1); + waterfall.on_show(); + break; + + case 3: + receiver_model.set_baseband_configuration({ + .mode = toUType(ReceiverModel::Mode::WidebandFMAudio), + .sampling_rate = 3072000, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(1750000); + receiver_model.enable(); + model.configure_wfm(); + waterfall.on_show(); + break; + + case 4: + receiver_model.set_baseband_configuration({ + .mode = 4, + .sampling_rate = 20000000, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(12000000); + receiver_model.enable(); + waterfall.on_show(); + break; + } +} + +void AnalogAudioView::on_show_options_frequency() { + view_rf_gain_options.hidden(true); + field_lna.set_style(nullptr); + + view_frequency_options.hidden(false); + field_frequency.set_style(&view_frequency_options.style()); +} + +void AnalogAudioView::on_show_options_rf_gain() { + view_frequency_options.hidden(true); + field_frequency.set_style(nullptr); + + view_rf_gain_options.hidden(false); + field_lna.set_style(&view_frequency_options.style()); +} + +void AnalogAudioView::on_frequency_step_changed(rf::Frequency f) { + receiver_model.set_frequency_step(f); + field_frequency.set_step(f); +} + +void AnalogAudioView::on_reference_ppm_correction_changed(int32_t v) { + receiver_model.set_reference_ppm_correction(v); +} + +void AnalogAudioView::on_headphone_volume_changed(int32_t v) { + const auto new_volume = volume_t::decibel(v - 99) + wolfson::wm8731::headphone_gain_range.max; + receiver_model.set_headphone_volume(new_volume); +} + +} /* namespace ui */ diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index a598a6b40..7a1920dd9 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -23,13 +23,14 @@ #define __ANALOG_AUDIO_APP_H__ #include "receiver_model.hpp" + +#include "ui_receiver.hpp" #include "ui_spectrum.hpp" +#include "ui_font_fixed_8x16.hpp" + class AnalogAudioModel { public: - AnalogAudioModel(ReceiverModel::Mode mode); - -private: void configure_nbfm(const size_t index); void configure_wfm(); void configure_am(const size_t index); @@ -37,16 +38,110 @@ private: namespace ui { -class AnalogAudioView : public spectrum::WaterfallWidget { +constexpr Style style_options_group { + .font = font::fixed_8x16, + .background = Color::blue(), + .foreground = Color::white(), +}; + +class AnalogAudioView : public View { public: - AnalogAudioView( - ReceiverModel::Mode mode - ) : model { mode } - { - } + AnalogAudioView(NavigationView& nav); + ~AnalogAudioView(); + + void on_show() override; + void on_hide() override; + + void set_parent_rect(const Rect new_parent_rect) override; + + void focus() override; private: AnalogAudioModel model; + + static constexpr ui::Dim header_height = 2 * 16; + + RSSI rssi { + { 21 * 8, 0, 6 * 8, 4 }, + }; + + Channel channel { + { 21 * 8, 5, 6 * 8, 4 }, + }; + + Audio audio { + { 21 * 8, 10, 6 * 8, 4 }, + }; + + FrequencyField field_frequency { + { 5 * 8, 0 * 16 }, + }; + + LNAGainField field_lna { + { 15 * 8, 0 * 16 } + }; + + NumberField field_vga { + { 18 * 8, 0 * 16}, + 2, + { max2837::vga::gain_db_range.minimum, max2837::vga::gain_db_range.maximum }, + max2837::vga::gain_db_step, + ' ', + }; + + OptionsField options_modulation { + { 0 * 8, 0 * 16 }, + 4, + { + { " AM ", 1 }, + { "NFM ", 2 }, + { "WFM ", 3 }, + { "SPEC", 4 }, + } + }; + + NumberField field_volume { + { 28 * 8, 0 * 16 }, + 2, + { 0, 99 }, + 1, + ' ', + }; + + FrequencyOptionsView view_frequency_options { + { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, + &style_options_group + }; + + RadioGainOptionsView view_rf_gain_options { + { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, + &style_options_group + }; +/* + AmplitudeModulationOptionsView view_am_modulation_options { + { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, + &style_options_group + }; + + FrequencyModulationOptionsView view_fm_modulation_options { + { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, + &style_options_group + }; +*/ + spectrum::WaterfallWidget waterfall; + + void on_tuning_frequency_changed(rf::Frequency f); + void on_baseband_bandwidth_changed(uint32_t bandwidth_hz); + void on_rf_amp_changed(bool v); + void on_lna_changed(int32_t v_db); + void on_vga_changed(int32_t v_db); + void on_modulation_changed(int32_t v); + void on_show_options_frequency(); + void on_show_options_rf_gain(); + void on_frequency_step_changed(rf::Frequency f); + void on_reference_ppm_correction_changed(int32_t v); + void on_headphone_volume_changed(int32_t v); + void on_edit_frequency(); }; } /* namespace ui */ diff --git a/firmware/application/spectrum_analysis_app.cpp b/firmware/application/spectrum_analysis_app.cpp deleted file mode 100644 index de3a14b0c..000000000 --- a/firmware/application/spectrum_analysis_app.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "spectrum_analysis_app.hpp" - -#include "portapack.hpp" -using namespace portapack; - -SpectrumAnalysisModel::SpectrumAnalysisModel() { - receiver_model.set_baseband_configuration({ - .mode = 4, - .sampling_rate = 20000000, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(12000000); -} diff --git a/firmware/application/spectrum_analysis_app.hpp b/firmware/application/spectrum_analysis_app.hpp deleted file mode 100644 index 9e8196af9..000000000 --- a/firmware/application/spectrum_analysis_app.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __SPECTRUM_ANALYSIS_APP_H__ -#define __SPECTRUM_ANALYSIS_APP_H__ - -#include "receiver_model.hpp" -#include "ui_spectrum.hpp" - -class SpectrumAnalysisModel { -public: - SpectrumAnalysisModel(); -}; - -namespace ui { - -class SpectrumAnalysisView : public spectrum::WaterfallWidget { -public: - -private: - SpectrumAnalysisModel model; -}; - -} /* namespace ui */ - -#endif/*__SPECTRUM_ANALYSIS_APP_H__*/ diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 6a21d2150..364db9628 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -27,8 +27,8 @@ #include "ui_setup.hpp" #include "ui_debug.hpp" -#include "ui_receiver.hpp" +#include "analog_audio_app.hpp" #include "ais_app.hpp" #include "ert_app.hpp" #include "tpms_app.hpp" @@ -140,7 +140,7 @@ TranspondersMenuView::TranspondersMenuView(NavigationView& nav) { ReceiverMenuView::ReceiverMenuView(NavigationView& nav) { add_items<2>({ { - { "Audio", [&nav](){ nav.push(); } }, + { "Audio", [&nav](){ nav.push(); } }, { "Transponders", [&nav](){ nav.push(); } }, } }); } diff --git a/firmware/application/ui_receiver.cpp b/firmware/application/ui_receiver.cpp index 4263a84c1..f80db7429 100644 --- a/firmware/application/ui_receiver.cpp +++ b/firmware/application/ui_receiver.cpp @@ -26,11 +26,7 @@ using namespace portapack; #include "string_format.hpp" -#include "analog_audio_app.hpp" -#include "ais_app.hpp" -#include "tpms_app.hpp" -#include "ert_app.hpp" -#include "spectrum_analysis_app.hpp" +#include "max2837.hpp" namespace ui { @@ -322,184 +318,4 @@ void LNAGainField::on_focus() { } } -/* ReceiverView **********************************************************/ - -ReceiverView::ReceiverView( - NavigationView& nav -) { - add_children({ { - &rssi, - &channel, - &audio, - &field_frequency, - &field_lna, - &field_vga, - &options_modulation, - &field_volume, - &view_frequency_options, - &view_rf_gain_options, - } }); - - field_frequency.set_value(receiver_model.tuning_frequency()); - field_frequency.set_step(receiver_model.frequency_step()); - field_frequency.on_change = [this](rf::Frequency f) { - this->on_tuning_frequency_changed(f); - }; - field_frequency.on_edit = [this, &nav]() { - // TODO: Provide separate modal method/scheme? - auto new_view = nav.push(receiver_model.tuning_frequency()); - new_view->on_changed = [this](rf::Frequency f) { - this->on_tuning_frequency_changed(f); - this->field_frequency.set_value(f); - }; - }; - field_frequency.on_show_options = [this]() { - this->on_show_options_frequency(); - }; - - field_lna.set_value(receiver_model.lna()); - field_lna.on_change = [this](int32_t v) { - this->on_lna_changed(v); - }; - field_lna.on_show_options = [this]() { - this->on_show_options_rf_gain(); - }; - - field_vga.set_value(receiver_model.vga()); - field_vga.on_change = [this](int32_t v_db) { - this->on_vga_changed(v_db); - }; - - options_modulation.set_by_value(receiver_model.modulation()); - options_modulation.on_change = [this](size_t n, OptionsField::value_t v) { - (void)n; - this->on_modulation_changed(static_cast(v)); - }; - - field_volume.set_value((receiver_model.headphone_volume() - wolfson::wm8731::headphone_gain_range.max).decibel() + 99); - field_volume.on_change = [this](int32_t v) { - this->on_headphone_volume_changed(v); - }; - - view_frequency_options.hidden(true); - view_frequency_options.set_step(receiver_model.frequency_step()); - view_frequency_options.on_change_step = [this](rf::Frequency f) { - this->on_frequency_step_changed(f); - }; - view_frequency_options.set_reference_ppm_correction(receiver_model.reference_ppm_correction()); - view_frequency_options.on_change_reference_ppm_correction = [this](int32_t v) { - this->on_reference_ppm_correction_changed(v); - }; - - view_rf_gain_options.hidden(true); - view_rf_gain_options.set_rf_amp(receiver_model.rf_amp()); - view_rf_gain_options.on_change_rf_amp = [this](bool enable) { - this->on_rf_amp_changed(enable); - }; - - receiver_model.enable(); -} - -ReceiverView::~ReceiverView() { - - // TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do - // both? - audio_codec.headphone_mute(); - - receiver_model.disable(); -} - -void ReceiverView::on_show() { - View::on_show(); - - // TODO: Separate concepts of baseband "modulation" and receiver "mode". - on_modulation_changed(static_cast(receiver_model.modulation())); -} - -void ReceiverView::on_hide() { - on_modulation_changed(static_cast(-1)); - - View::on_hide(); -} - -void ReceiverView::focus() { - field_frequency.focus(); -} - -void ReceiverView::on_tuning_frequency_changed(rf::Frequency f) { - receiver_model.set_tuning_frequency(f); -} - -void ReceiverView::on_baseband_bandwidth_changed(uint32_t bandwidth_hz) { - receiver_model.set_baseband_bandwidth(bandwidth_hz); -} - -void ReceiverView::on_rf_amp_changed(bool v) { - receiver_model.set_rf_amp(v); -} - -void ReceiverView::on_lna_changed(int32_t v_db) { - receiver_model.set_lna(v_db); -} - -void ReceiverView::on_vga_changed(int32_t v_db) { - receiver_model.set_vga(v_db); -} - -void ReceiverView::on_modulation_changed(ReceiverModel::Mode mode) { - remove_child(widget_content.get()); - widget_content.reset(); - - switch(mode) { - case ReceiverModel::Mode::AMAudio: - case ReceiverModel::Mode::NarrowbandFMAudio: - case ReceiverModel::Mode::WidebandFMAudio: - widget_content = std::make_unique(mode); - break; - - case ReceiverModel::Mode::SpectrumAnalysis: - widget_content = std::make_unique(); - break; - - default: - break; - } - - if( widget_content ) { - add_child(widget_content.get()); - const ui::Rect rect { 0, header_height, parent_rect.width(), static_cast(parent_rect.height() - header_height) }; - widget_content->set_parent_rect(rect); - } -} - -void ReceiverView::on_show_options_frequency() { - view_rf_gain_options.hidden(true); - field_lna.set_style(nullptr); - - view_frequency_options.hidden(false); - field_frequency.set_style(&view_frequency_options.style()); -} - -void ReceiverView::on_show_options_rf_gain() { - view_frequency_options.hidden(true); - field_frequency.set_style(nullptr); - - view_rf_gain_options.hidden(false); - field_lna.set_style(&view_frequency_options.style()); -} - -void ReceiverView::on_frequency_step_changed(rf::Frequency f) { - receiver_model.set_frequency_step(f); - field_frequency.set_step(f); -} - -void ReceiverView::on_reference_ppm_correction_changed(int32_t v) { - receiver_model.set_reference_ppm_correction(v); -} - -void ReceiverView::on_headphone_volume_changed(int32_t v) { - const auto new_volume = volume_t::decibel(v - 99) + wolfson::wm8731::headphone_gain_range.max; - receiver_model.set_headphone_volume(new_volume); -} - } /* namespace ui */ diff --git a/firmware/application/ui_receiver.hpp b/firmware/application/ui_receiver.hpp index 6ab202363..fa74f970d 100644 --- a/firmware/application/ui_receiver.hpp +++ b/firmware/application/ui_receiver.hpp @@ -23,19 +23,11 @@ #define __UI_RECEIVER_H__ #include "ui.hpp" -#include "ui_font_fixed_8x16.hpp" #include "ui_navigation.hpp" #include "ui_painter.hpp" #include "ui_widget.hpp" -#include "utility.hpp" - -#include "max2837.hpp" #include "rf_path.hpp" -#include "volume.hpp" -#include "wm8731.hpp" - -#include "receiver_model.hpp" #include #include @@ -323,98 +315,6 @@ public: void on_focus() override; }; -constexpr Style style_options_group { - .font = font::fixed_8x16, - .background = Color::blue(), - .foreground = Color::white(), -}; - -class ReceiverView : public View { -public: - ReceiverView(NavigationView& nav); - ~ReceiverView(); - - void on_show() override; - void on_hide() override; - - void focus() override; - -private: - static constexpr ui::Dim header_height = 2 * 16; - - RSSI rssi { - { 21 * 8, 0, 6 * 8, 4 }, - }; - - Channel channel { - { 21 * 8, 5, 6 * 8, 4 }, - }; - - Audio audio { - { 21 * 8, 10, 6 * 8, 4 }, - }; - - FrequencyField field_frequency { - { 5 * 8, 0 * 16 }, - }; - - LNAGainField field_lna { - { 15 * 8, 0 * 16 } - }; - - NumberField field_vga { - { 18 * 8, 0 * 16}, - 2, - { max2837::vga::gain_db_range.minimum, max2837::vga::gain_db_range.maximum }, - max2837::vga::gain_db_step, - ' ', - }; - - OptionsField options_modulation { - { 0 * 8, 0 * 16 }, - 4, - { - { " AM ", toUType(ReceiverModel::Mode::AMAudio) }, - { "NFM ", toUType(ReceiverModel::Mode::NarrowbandFMAudio) }, - { "WFM ", toUType(ReceiverModel::Mode::WidebandFMAudio) }, - { "SPEC", toUType(ReceiverModel::Mode::SpectrumAnalysis) }, - } - }; - - NumberField field_volume { - { 28 * 8, 0 * 16 }, - 2, - { 0, 99 }, - 1, - ' ', - }; - - FrequencyOptionsView view_frequency_options { - { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, - &style_options_group - }; - - RadioGainOptionsView view_rf_gain_options { - { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, - &style_options_group - }; - - std::unique_ptr widget_content; - - void on_tuning_frequency_changed(rf::Frequency f); - void on_baseband_bandwidth_changed(uint32_t bandwidth_hz); - void on_rf_amp_changed(bool v); - void on_lna_changed(int32_t v_db); - void on_vga_changed(int32_t v_db); - void on_modulation_changed(ReceiverModel::Mode mode); - void on_show_options_frequency(); - void on_show_options_rf_gain(); - void on_frequency_step_changed(rf::Frequency f); - void on_reference_ppm_correction_changed(int32_t v); - void on_headphone_volume_changed(int32_t v); - void on_edit_frequency(); -}; - } /* namespace ui */ #endif/*__UI_RECEIVER_H__*/ From c5f8daa21022ed2cf1c1e1fe719247de218693f5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 1 Feb 2016 09:12:55 -0800 Subject: [PATCH 431/452] Restore use of ReceiverModel::Mode enum. --- firmware/application/analog_audio_app.cpp | 36 ++++++++++------------- firmware/application/analog_audio_app.hpp | 10 +++---- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 47cfb8141..3050da55c 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -149,10 +149,9 @@ AnalogAudioView::AnalogAudioView( this->on_vga_changed(v_db); }; - options_modulation.set_by_value(1); - options_modulation.on_change = [this](size_t n, OptionsField::value_t v) { - (void)n; - this->on_modulation_changed(v); + options_modulation.set_by_value(toUType(ReceiverModel::Mode::AMAudio)); + options_modulation.on_change = [this](size_t, OptionsField::value_t v) { + this->on_modulation_changed(static_cast(v)); }; field_volume.set_value((receiver_model.headphone_volume() - wolfson::wm8731::headphone_gain_range.max).decibel() + 99); @@ -229,63 +228,58 @@ void AnalogAudioView::on_vga_changed(int32_t v_db) { receiver_model.set_vga(v_db); } -void AnalogAudioView::on_modulation_changed(int32_t mode) { - // remove_child(widget_content.get()); - // widget_content.reset(); - +void AnalogAudioView::on_modulation_changed(const ReceiverModel::Mode mode) { // TODO: Terrible kludge because widget system doesn't notify Waterfall that // it's being shown or hidden. waterfall.on_hide(); switch(mode) { default: - case 1: + case ReceiverModel::Mode::AMAudio: receiver_model.set_baseband_configuration({ - .mode = toUType(ReceiverModel::Mode::AMAudio), + .mode = toUType(mode), .sampling_rate = 3072000, .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); receiver_model.enable(); model.configure_am(0); - waterfall.on_show(); break; - case 2: + case ReceiverModel::Mode::NarrowbandFMAudio: receiver_model.set_baseband_configuration({ - .mode = toUType(ReceiverModel::Mode::NarrowbandFMAudio), + .mode = toUType(mode), .sampling_rate = 3072000, .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); receiver_model.enable(); - model.configure_nbfm(1); - waterfall.on_show(); + model.configure_nbfm(0); break; - case 3: + case ReceiverModel::Mode::WidebandFMAudio: receiver_model.set_baseband_configuration({ - .mode = toUType(ReceiverModel::Mode::WidebandFMAudio), + .mode = toUType(mode), .sampling_rate = 3072000, .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(1750000); receiver_model.enable(); model.configure_wfm(); - waterfall.on_show(); break; - case 4: + case ReceiverModel::Mode::SpectrumAnalysis: receiver_model.set_baseband_configuration({ - .mode = 4, + .mode = toUType(mode), .sampling_rate = 20000000, .decimation_factor = 1, }); receiver_model.set_baseband_bandwidth(12000000); receiver_model.enable(); - waterfall.on_show(); break; } + + waterfall.on_show(); } void AnalogAudioView::on_show_options_frequency() { diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 7a1920dd9..8c52ba22f 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -93,10 +93,10 @@ private: { 0 * 8, 0 * 16 }, 4, { - { " AM ", 1 }, - { "NFM ", 2 }, - { "WFM ", 3 }, - { "SPEC", 4 }, + { " AM ", toUType(ReceiverModel::Mode::AMAudio) }, + { "NFM ", toUType(ReceiverModel::Mode::NarrowbandFMAudio) }, + { "WFM ", toUType(ReceiverModel::Mode::WidebandFMAudio) }, + { "SPEC", toUType(ReceiverModel::Mode::SpectrumAnalysis) }, } }; @@ -135,7 +135,7 @@ private: void on_rf_amp_changed(bool v); void on_lna_changed(int32_t v_db); void on_vga_changed(int32_t v_db); - void on_modulation_changed(int32_t v); + void on_modulation_changed(const ReceiverModel::Mode mode); void on_show_options_frequency(); void on_show_options_rf_gain(); void on_frequency_step_changed(rf::Frequency f); From afffdba150bcbeefb280dab609a66693848977d4 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 1 Feb 2016 09:13:17 -0800 Subject: [PATCH 432/452] AnalogAudioView::on_show() is a no-op, remove. --- firmware/application/analog_audio_app.cpp | 6 ------ firmware/application/analog_audio_app.hpp | 1 - 2 files changed, 7 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 3050da55c..38c250907 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -184,12 +184,6 @@ AnalogAudioView::~AnalogAudioView() { receiver_model.disable(); } -void AnalogAudioView::on_show() { - View::on_show(); - // TODO: Terrible kludge because widget system doesn't notify Waterfall that - // it's being shown or hidden. -} - void AnalogAudioView::on_hide() { // TODO: Terrible kludge because widget system doesn't notify Waterfall that // it's being shown or hidden. diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 8c52ba22f..ef16585c7 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -49,7 +49,6 @@ public: AnalogAudioView(NavigationView& nav); ~AnalogAudioView(); - void on_show() override; void on_hide() override; void set_parent_rect(const Rect new_parent_rect) override; From ee67948a639a4b4675993e9ac03496e8e5402d93 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 1 Feb 2016 09:17:32 -0800 Subject: [PATCH 433/452] Simplify AnalogAudioView mode switching. --- firmware/application/analog_audio_app.cpp | 37 ++++++----------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 38c250907..8de5d2159 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -227,49 +227,30 @@ void AnalogAudioView::on_modulation_changed(const ReceiverModel::Mode mode) { // it's being shown or hidden. waterfall.on_hide(); + const auto is_wideband_spectrum_mode = (mode == ReceiverModel::Mode::SpectrumAnalysis); + receiver_model.set_baseband_configuration({ + .mode = toUType(mode), + .sampling_rate = is_wideband_spectrum_mode ? 20000000U : 3072000U, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000); + receiver_model.enable(); + switch(mode) { default: case ReceiverModel::Mode::AMAudio: - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 3072000, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); - receiver_model.enable(); model.configure_am(0); break; case ReceiverModel::Mode::NarrowbandFMAudio: - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 3072000, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); - receiver_model.enable(); model.configure_nbfm(0); break; case ReceiverModel::Mode::WidebandFMAudio: - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 3072000, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(1750000); - receiver_model.enable(); model.configure_wfm(); break; case ReceiverModel::Mode::SpectrumAnalysis: - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = 20000000, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(12000000); - receiver_model.enable(); break; } From cbaa04ff078ddfd55666fcfe62598701d60d3529 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 11:02:07 -0800 Subject: [PATCH 434/452] Reorganize analog audio configs structures. --- firmware/application/analog_audio_app.cpp | 101 +++++++++++++--------- firmware/application/analog_audio_app.hpp | 39 +++++++-- 2 files changed, 90 insertions(+), 50 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 8de5d2159..b7b382954 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -25,32 +25,30 @@ #include "portapack_shared_memory.hpp" using namespace portapack; -#include "dsp_fir_taps.hpp" -#include "dsp_iir_config.hpp" - #include "utility.hpp" -struct NBFMMode { - const fir_taps_real<24> decim_0; - const fir_taps_real<32> decim_1; - const fir_taps_real<32> channel; - const size_t deviation; -}; +#include "dsp_iir_config.hpp" -static constexpr std::array nbfm_mode_configs { { - { taps_4k25_decim_0, taps_4k25_decim_1, taps_4k25_channel, 2500 }, - { taps_11k0_decim_0, taps_11k0_decim_1, taps_11k0_channel, 2500 }, - { taps_16k0_decim_0, taps_16k0_decim_1, taps_16k0_channel, 5000 }, -} }; +void AMConfig::apply() const { + const AMConfigureMessage message { + taps_6k0_decim_0, + taps_6k0_decim_1, + taps_6k0_decim_2, + channel, + modulation, + audio_12k_hpf_300hz_config + }; + shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(4); +} -void AnalogAudioModel::configure_nbfm(const size_t index) { - const auto config = nbfm_mode_configs[index]; +void NBFMConfig::apply() const { const NBFMConfigureMessage message { - config.decim_0, - config.decim_1, - config.channel, + decim_0, + decim_1, + channel, 2, - config.deviation, + deviation, audio_24k_hpf_300hz_config, audio_24k_deemph_300_6_config }; @@ -58,7 +56,7 @@ void AnalogAudioModel::configure_nbfm(const size_t index) { clock_manager.set_base_audio_clock_divider(2); } -void AnalogAudioModel::configure_wfm() { +void WFMConfig::apply() const { const WFMConfigureMessage message { taps_200k_wfm_decim_0, taps_200k_wfm_decim_1, @@ -71,30 +69,21 @@ void AnalogAudioModel::configure_wfm() { clock_manager.set_base_audio_clock_divider(1); } -struct AMMode { - const fir_taps_complex<64> channel; - const AMConfigureMessage::Modulation modulation; -}; - -static constexpr std::array am_mode_configs { { +static constexpr std::array am_configs { { { taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, { taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB }, { taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB }, } }; -void AnalogAudioModel::configure_am(const size_t index) { - const auto config = am_mode_configs[index]; - const AMConfigureMessage message { - taps_6k0_decim_0, - taps_6k0_decim_1, - taps_6k0_decim_2, - config.channel, - config.modulation, - audio_12k_hpf_300hz_config - }; - shared_memory.baseband_queue.push(message); - clock_manager.set_base_audio_clock_divider(4); -} +static constexpr std::array nbfm_configs { { + { taps_4k25_decim_0, taps_4k25_decim_1, taps_4k25_channel, 2500 }, + { taps_11k0_decim_0, taps_11k0_decim_1, taps_11k0_channel, 2500 }, + { taps_16k0_decim_0, taps_16k0_decim_1, taps_16k0_channel, 5000 }, +} }; + +static constexpr std::array wfm_configs { { + { }, +} }; namespace ui { @@ -239,15 +228,15 @@ void AnalogAudioView::on_modulation_changed(const ReceiverModel::Mode mode) { switch(mode) { default: case ReceiverModel::Mode::AMAudio: - model.configure_am(0); + update_am_config(); break; case ReceiverModel::Mode::NarrowbandFMAudio: - model.configure_nbfm(0); + update_nbfm_config(); break; case ReceiverModel::Mode::WidebandFMAudio: - model.configure_wfm(); + update_wfm_config(); break; case ReceiverModel::Mode::SpectrumAnalysis: @@ -287,4 +276,30 @@ void AnalogAudioView::on_headphone_volume_changed(int32_t v) { receiver_model.set_headphone_volume(new_volume); } +void AnalogAudioView::on_am_config_index_changed(size_t n) { + if( n < am_configs.size() ) { + am_config_index = n; + update_am_config(); + } +} + +void AnalogAudioView::on_nbfm_config_index_changed(size_t n) { + if( n < nbfm_configs.size() ) { + nbfm_config_index = n; + update_nbfm_config(); + } +} + +void AnalogAudioView::update_am_config() { + am_configs[am_config_index].apply(); +} + +void AnalogAudioView::update_nbfm_config() { + nbfm_configs[nbfm_config_index].apply(); +} + +void AnalogAudioView::update_wfm_config() { + wfm_configs[wfm_config_index].apply(); +} + } /* namespace ui */ diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index ef16585c7..f303bb0e3 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -29,11 +29,27 @@ #include "ui_font_fixed_8x16.hpp" -class AnalogAudioModel { -public: - void configure_nbfm(const size_t index); - void configure_wfm(); - void configure_am(const size_t index); +#include "dsp_fir_taps.hpp" +#include "dsp_iir.hpp" + +struct AMConfig { + const fir_taps_complex<64> channel; + const AMConfigureMessage::Modulation modulation; + + void apply() const; +}; + +struct NBFMConfig { + const fir_taps_real<24> decim_0; + const fir_taps_real<32> decim_1; + const fir_taps_real<32> channel; + const size_t deviation; + + void apply() const; +}; + +struct WFMConfig { + void apply() const; }; namespace ui { @@ -56,8 +72,6 @@ public: void focus() override; private: - AnalogAudioModel model; - static constexpr ui::Dim header_height = 2 * 16; RSSI rssi { @@ -129,6 +143,10 @@ private: */ spectrum::WaterfallWidget waterfall; + size_t am_config_index = 0; + size_t nbfm_config_index = 0; + static constexpr size_t wfm_config_index = 0; + void on_tuning_frequency_changed(rf::Frequency f); void on_baseband_bandwidth_changed(uint32_t bandwidth_hz); void on_rf_amp_changed(bool v); @@ -141,6 +159,13 @@ private: void on_reference_ppm_correction_changed(int32_t v); void on_headphone_volume_changed(int32_t v); void on_edit_frequency(); + + void on_am_config_index_changed(size_t n); + void on_nbfm_config_index_changed(size_t n); + + void update_am_config(); + void update_nbfm_config(); + void update_wfm_config(); }; } /* namespace ui */ From fece0a5e1bab005698014f9a5173d680e2df8f5f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 13:39:02 -0800 Subject: [PATCH 435/452] Move modulation configuration into ReceiverModel. --- firmware/application/analog_audio_app.cpp | 122 +++---------------- firmware/application/analog_audio_app.hpp | 32 +---- firmware/application/receiver_model.cpp | 139 +++++++++++++++++++++- firmware/application/receiver_model.hpp | 12 ++ 4 files changed, 168 insertions(+), 137 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index b7b382954..cf680ca60 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -27,64 +27,6 @@ using namespace portapack; #include "utility.hpp" -#include "dsp_iir_config.hpp" - -void AMConfig::apply() const { - const AMConfigureMessage message { - taps_6k0_decim_0, - taps_6k0_decim_1, - taps_6k0_decim_2, - channel, - modulation, - audio_12k_hpf_300hz_config - }; - shared_memory.baseband_queue.push(message); - clock_manager.set_base_audio_clock_divider(4); -} - -void NBFMConfig::apply() const { - const NBFMConfigureMessage message { - decim_0, - decim_1, - channel, - 2, - deviation, - audio_24k_hpf_300hz_config, - audio_24k_deemph_300_6_config - }; - shared_memory.baseband_queue.push(message); - clock_manager.set_base_audio_clock_divider(2); -} - -void WFMConfig::apply() const { - const WFMConfigureMessage message { - taps_200k_wfm_decim_0, - taps_200k_wfm_decim_1, - taps_64_lp_156_198, - 75000, - audio_48k_hpf_30hz_config, - audio_48k_deemph_2122_6_config - }; - shared_memory.baseband_queue.push(message); - clock_manager.set_base_audio_clock_divider(1); -} - -static constexpr std::array am_configs { { - { taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, - { taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB }, - { taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB }, -} }; - -static constexpr std::array nbfm_configs { { - { taps_4k25_decim_0, taps_4k25_decim_1, taps_4k25_channel, 2500 }, - { taps_11k0_decim_0, taps_11k0_decim_1, taps_11k0_channel, 2500 }, - { taps_16k0_decim_0, taps_16k0_decim_1, taps_16k0_channel, 5000 }, -} }; - -static constexpr std::array wfm_configs { { - { }, -} }; - namespace ui { /* AnalogAudioView *******************************************************/ @@ -163,6 +105,8 @@ AnalogAudioView::AnalogAudioView( view_rf_gain_options.on_change_rf_amp = [this](bool enable) { this->on_rf_amp_changed(enable); }; + + update_modulation(static_cast(receiver_model.modulation())); } AnalogAudioView::~AnalogAudioView() { @@ -211,39 +155,12 @@ void AnalogAudioView::on_vga_changed(int32_t v_db) { receiver_model.set_vga(v_db); } -void AnalogAudioView::on_modulation_changed(const ReceiverModel::Mode mode) { +void AnalogAudioView::on_modulation_changed(const ReceiverModel::Mode modulation) { // TODO: Terrible kludge because widget system doesn't notify Waterfall that // it's being shown or hidden. waterfall.on_hide(); - - const auto is_wideband_spectrum_mode = (mode == ReceiverModel::Mode::SpectrumAnalysis); - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = is_wideband_spectrum_mode ? 20000000U : 3072000U, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000); - receiver_model.enable(); - - switch(mode) { - default: - case ReceiverModel::Mode::AMAudio: - update_am_config(); - break; - - case ReceiverModel::Mode::NarrowbandFMAudio: - update_nbfm_config(); - break; - - case ReceiverModel::Mode::WidebandFMAudio: - update_wfm_config(); - break; - - case ReceiverModel::Mode::SpectrumAnalysis: - break; - } - - waterfall.on_show(); + update_modulation(modulation); + waterfall.on_show(); } void AnalogAudioView::on_show_options_frequency() { @@ -277,29 +194,22 @@ void AnalogAudioView::on_headphone_volume_changed(int32_t v) { } void AnalogAudioView::on_am_config_index_changed(size_t n) { - if( n < am_configs.size() ) { - am_config_index = n; - update_am_config(); - } + receiver_model.set_am_configuration(n); } void AnalogAudioView::on_nbfm_config_index_changed(size_t n) { - if( n < nbfm_configs.size() ) { - nbfm_config_index = n; - update_nbfm_config(); - } + receiver_model.set_nbfm_configuration(n); } -void AnalogAudioView::update_am_config() { - am_configs[am_config_index].apply(); -} - -void AnalogAudioView::update_nbfm_config() { - nbfm_configs[nbfm_config_index].apply(); -} - -void AnalogAudioView::update_wfm_config() { - wfm_configs[wfm_config_index].apply(); +void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { + const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis); + receiver_model.set_baseband_configuration({ + .mode = toUType(modulation), + .sampling_rate = is_wideband_spectrum_mode ? 20000000U : 3072000U, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000); + receiver_model.enable(); } } /* namespace ui */ diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index f303bb0e3..1aa691fa2 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -29,29 +29,6 @@ #include "ui_font_fixed_8x16.hpp" -#include "dsp_fir_taps.hpp" -#include "dsp_iir.hpp" - -struct AMConfig { - const fir_taps_complex<64> channel; - const AMConfigureMessage::Modulation modulation; - - void apply() const; -}; - -struct NBFMConfig { - const fir_taps_real<24> decim_0; - const fir_taps_real<32> decim_1; - const fir_taps_real<32> channel; - const size_t deviation; - - void apply() const; -}; - -struct WFMConfig { - void apply() const; -}; - namespace ui { constexpr Style style_options_group { @@ -143,16 +120,13 @@ private: */ spectrum::WaterfallWidget waterfall; - size_t am_config_index = 0; - size_t nbfm_config_index = 0; - static constexpr size_t wfm_config_index = 0; void on_tuning_frequency_changed(rf::Frequency f); void on_baseband_bandwidth_changed(uint32_t bandwidth_hz); void on_rf_amp_changed(bool v); void on_lna_changed(int32_t v_db); void on_vga_changed(int32_t v_db); - void on_modulation_changed(const ReceiverModel::Mode mode); + void on_modulation_changed(const ReceiverModel::Mode modulation); void on_show_options_frequency(); void on_show_options_rf_gain(); void on_frequency_step_changed(rf::Frequency f); @@ -163,9 +137,7 @@ private: void on_am_config_index_changed(size_t n); void on_nbfm_config_index_changed(size_t n); - void update_am_config(); - void update_nbfm_config(); - void update_wfm_config(); + void update_modulation(const ReceiverModel::Mode modulation); }; } /* namespace ui */ diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 4f4e4d1cd..dd6554c65 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -26,6 +26,90 @@ #include "portapack.hpp" using namespace portapack; +#include "dsp_fir_taps.hpp" +#include "dsp_iir.hpp" +#include "dsp_iir_config.hpp" + +namespace { + +struct AMConfig { + const fir_taps_complex<64> channel; + const AMConfigureMessage::Modulation modulation; + + void apply() const; +}; + +struct NBFMConfig { + const fir_taps_real<24> decim_0; + const fir_taps_real<32> decim_1; + const fir_taps_real<32> channel; + const size_t deviation; + + void apply() const; +}; + +struct WFMConfig { + void apply() const; +}; + +void AMConfig::apply() const { + const AMConfigureMessage message { + taps_6k0_decim_0, + taps_6k0_decim_1, + taps_6k0_decim_2, + channel, + modulation, + audio_12k_hpf_300hz_config + }; + shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(4); +} + +void NBFMConfig::apply() const { + const NBFMConfigureMessage message { + decim_0, + decim_1, + channel, + 2, + deviation, + audio_24k_hpf_300hz_config, + audio_24k_deemph_300_6_config + }; + shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(2); +} + +void WFMConfig::apply() const { + const WFMConfigureMessage message { + taps_200k_wfm_decim_0, + taps_200k_wfm_decim_1, + taps_64_lp_156_198, + 75000, + audio_48k_hpf_30hz_config, + audio_48k_deemph_2122_6_config + }; + shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(1); +} + +static constexpr std::array am_configs { { + { taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, + { taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB }, + { taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB }, +} }; + +static constexpr std::array nbfm_configs { { + { taps_4k25_decim_0, taps_4k25_decim_1, taps_4k25_channel, 2500 }, + { taps_11k0_decim_0, taps_11k0_decim_1, taps_11k0_channel, 2500 }, + { taps_16k0_decim_0, taps_16k0_decim_1, taps_16k0_channel, 5000 }, +} }; + +static constexpr std::array wfm_configs { { + { }, +} }; + +} /* namespace */ + rf::Frequency ReceiverModel::tuning_frequency() const { return persistent_memory::tuned_frequency(); } @@ -129,7 +213,7 @@ void ReceiverModel::enable() { update_vga(); update_baseband_bandwidth(); update_baseband_configuration(); - + update_modulation_configuration(); update_headphone_volume(); } @@ -189,6 +273,27 @@ void ReceiverModel::set_baseband_configuration(const BasebandConfiguration confi update_baseband_configuration(); } +void ReceiverModel::set_am_configuration(const size_t n) { + if( n < am_configs.size() ) { + am_config_index = n; + update_modulation_configuration(); + } +} + +void ReceiverModel::set_nbfm_configuration(const size_t n) { + if( n < nbfm_configs.size() ) { + nbfm_config_index = n; + update_modulation_configuration(); + } +} + +void ReceiverModel::set_wfm_configuration(const size_t n) { + if( n < wfm_configs.size() ) { + wfm_config_index = n; + update_modulation_configuration(); + } +} + void ReceiverModel::update_baseband_configuration() { // TODO: Move more low-level radio control stuff to M4. It'll enable tighter // synchronization for things like wideband (sweeping) spectrum analysis, and @@ -211,3 +316,35 @@ void ReceiverModel::update_headphone_volume() { audio_codec.set_headphone_volume(headphone_volume_); } + +void ReceiverModel::update_modulation_configuration() { + switch(static_cast(modulation())) { + default: + case Mode::AMAudio: + update_am_configuration(); + break; + + case Mode::NarrowbandFMAudio: + update_nbfm_configuration(); + break; + + case Mode::WidebandFMAudio: + update_wfm_configuration(); + break; + + case Mode::SpectrumAnalysis: + break; + } +} + +void ReceiverModel::update_am_configuration() { + am_configs[am_config_index].apply(); +} + +void ReceiverModel::update_nbfm_configuration() { + nbfm_configs[nbfm_config_index].apply(); +} + +void ReceiverModel::update_wfm_configuration() { + wfm_configs[wfm_config_index].apply(); +} diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index d76f46701..3c1749c62 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -80,6 +80,10 @@ public: void set_baseband_configuration(const BasebandConfiguration config); + void set_am_configuration(const size_t n); + void set_nbfm_configuration(const size_t n); + void set_wfm_configuration(const size_t n); + private: rf::Frequency frequency_step_ { 25000 }; bool enabled_ { false }; @@ -93,6 +97,9 @@ private: .sampling_rate = 3072000, .decimation_factor = 1, }; + size_t am_config_index = 0; + size_t nbfm_config_index = 0; + size_t wfm_config_index = 0; volume_t headphone_volume_ { -43.0_dB }; int32_t tuning_offset(); @@ -106,6 +113,11 @@ private: void update_baseband_configuration(); void update_headphone_volume(); + void update_modulation_configuration(); + void update_am_configuration(); + void update_nbfm_configuration(); + void update_wfm_configuration(); + void baseband_disable(); }; From be8c1307e2c31e9d17d2a08ba7457a52aa97a471 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 13:41:11 -0800 Subject: [PATCH 436/452] Add OptionsField event for on_focus. TODO: So poorly named! Should be on_focus, but requires sweeping changes. Ugh. --- firmware/common/ui_widget.cpp | 6 ++++++ firmware/common/ui_widget.hpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 0b9cc01ca..6a184576e 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -473,6 +473,12 @@ void OptionsField::paint(Painter& painter) { } } +void OptionsField::on_focus() { + if( on_show_options ) { + on_show_options(); + } +} + bool OptionsField::on_encoder(const EncoderEvent delta) { set_selected_index(selected_index() + delta); return true; diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index e1e886894..ddecaae26 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -226,6 +226,7 @@ public: using options_t = std::vector; std::function on_change; + std::function on_show_options; OptionsField(Point parent_pos, size_t length, options_t options); @@ -236,6 +237,7 @@ public: void paint(Painter& painter) override; + void on_focus() override; bool on_encoder(const EncoderEvent delta) override; bool on_touch(const TouchEvent event) override; From 3f86a7c4ae84c0bb4bf9ee9ea2ff0b8a4d2e92ee Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 13:42:00 -0800 Subject: [PATCH 437/452] Add AM/NBFM configuration options views. --- firmware/application/analog_audio_app.cpp | 91 +++++++++++++++++++++++ firmware/application/analog_audio_app.hpp | 56 ++++++++++++-- 2 files changed, 142 insertions(+), 5 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index cf680ca60..d7cd6c4c2 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -29,6 +29,46 @@ using namespace portapack; namespace ui { +/* AMOptionsView *********************************************************/ + +AMOptionsView::AMOptionsView( + const Rect parent_rect, const Style* const style +) : View { parent_rect } +{ + set_style(style); + + add_children({ { + &label_config, + &options_config, + } }); + + options_config.on_change = [this](size_t n, OptionsField::value_t) { + if( on_config_changed ) { + this->on_config_changed(n); + } + }; +} + +/* NBFMOptionsView *******************************************************/ + +NBFMOptionsView::NBFMOptionsView( + const Rect parent_rect, const Style* const style +) : View { parent_rect } +{ + set_style(style); + + add_children({ { + &label_config, + &options_config, + } }); + + options_config.on_change = [this](size_t n, OptionsField::value_t) { + if( on_config_changed ) { + this->on_config_changed(n); + } + }; +} + /* AnalogAudioView *******************************************************/ AnalogAudioView::AnalogAudioView( @@ -45,6 +85,8 @@ AnalogAudioView::AnalogAudioView( &field_volume, &view_frequency_options, &view_rf_gain_options, + &view_am_options, + &view_nbfm_options, &waterfall, } }); @@ -84,6 +126,9 @@ AnalogAudioView::AnalogAudioView( options_modulation.on_change = [this](size_t, OptionsField::value_t v) { this->on_modulation_changed(static_cast(v)); }; + options_modulation.on_show_options = [this]() { + this->on_show_options_modulation(); + }; field_volume.set_value((receiver_model.headphone_volume() - wolfson::wm8731::headphone_gain_range.max).decibel() + 99); field_volume.on_change = [this](int32_t v) { @@ -106,6 +151,16 @@ AnalogAudioView::AnalogAudioView( this->on_rf_amp_changed(enable); }; + view_am_options.hidden(true); + view_am_options.on_config_changed = [this](size_t n) { + this->on_am_config_index_changed(n); + }; + + view_nbfm_options.hidden(true); + view_nbfm_options.on_config_changed = [this](size_t n) { + this->on_nbfm_config_index_changed(n); + }; + update_modulation(static_cast(receiver_model.modulation())); } @@ -160,25 +215,61 @@ void AnalogAudioView::on_modulation_changed(const ReceiverModel::Mode modulation // it's being shown or hidden. waterfall.on_hide(); update_modulation(modulation); + on_show_options_modulation(); waterfall.on_show(); } void AnalogAudioView::on_show_options_frequency() { + // TODO: This approach of managing options views is error-prone and unsustainable! view_rf_gain_options.hidden(true); + view_am_options.hidden(true); + view_nbfm_options.hidden(true); + field_lna.set_style(nullptr); + options_modulation.set_style(nullptr); view_frequency_options.hidden(false); field_frequency.set_style(&view_frequency_options.style()); } void AnalogAudioView::on_show_options_rf_gain() { + // TODO: This approach of managing options views is error-prone and unsustainable! view_frequency_options.hidden(true); + view_am_options.hidden(true); + view_nbfm_options.hidden(true); + field_frequency.set_style(nullptr); + options_modulation.set_style(nullptr); view_rf_gain_options.hidden(false); field_lna.set_style(&view_frequency_options.style()); } +void AnalogAudioView::on_show_options_modulation() { + // TODO: This approach of managing options views is error-prone and unsustainable! + view_frequency_options.hidden(true); + view_rf_gain_options.hidden(true); + + const auto modulation = static_cast(receiver_model.modulation()); + if( modulation != ReceiverModel::Mode::AMAudio ) { + view_am_options.hidden(true); + } + if( modulation != ReceiverModel::Mode::NarrowbandFMAudio ) { + view_nbfm_options.hidden(true); + } + + field_frequency.set_style(nullptr); + field_lna.set_style(nullptr); + + if( modulation == ReceiverModel::Mode::AMAudio ) { + view_am_options.hidden(false); + } + if( modulation == ReceiverModel::Mode::NarrowbandFMAudio ) { + view_nbfm_options.hidden(false); + } + options_modulation.set_style(&view_frequency_options.style()); +} + void AnalogAudioView::on_frequency_step_changed(rf::Frequency f) { receiver_model.set_frequency_step(f); field_frequency.set_step(f); diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 1aa691fa2..7ff0efc3d 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -37,6 +37,52 @@ constexpr Style style_options_group { .foreground = Color::white(), }; +class AMOptionsView : public View { +public: + std::function on_config_changed; + + AMOptionsView(const Rect parent_rect, const Style* const style); + +private: + Text label_config { + { 0 * 8, 0 * 16, 2 * 8, 1 * 16 }, + "BW", + }; + + OptionsField options_config { + { 3 * 8, 0 * 16 }, + 4, + { + { "DSB ", 0 }, + { "USB ", 0 }, + { "LSB ", 0 }, + } + }; +}; + +class NBFMOptionsView : public View { +public: + std::function on_config_changed; + + NBFMOptionsView(const Rect parent_rect, const Style* const style); + +private: + Text label_config { + { 0 * 8, 0 * 16, 2 * 8, 1 * 16 }, + "BW", + }; + + OptionsField options_config { + { 3 * 8, 0 * 16 }, + 4, + { + { " 8k5", 0 }, + { "11k ", 0 }, + { "16k ", 0 }, + } + }; +}; + class AnalogAudioView : public View { public: AnalogAudioView(NavigationView& nav); @@ -107,20 +153,19 @@ private: { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, &style_options_group }; -/* - AmplitudeModulationOptionsView view_am_modulation_options { + + AMOptionsView view_am_options { { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, &style_options_group }; - FrequencyModulationOptionsView view_fm_modulation_options { + NBFMOptionsView view_nbfm_options { { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, &style_options_group }; -*/ + spectrum::WaterfallWidget waterfall; - void on_tuning_frequency_changed(rf::Frequency f); void on_baseband_bandwidth_changed(uint32_t bandwidth_hz); void on_rf_amp_changed(bool v); @@ -129,6 +174,7 @@ private: void on_modulation_changed(const ReceiverModel::Mode modulation); void on_show_options_frequency(); void on_show_options_rf_gain(); + void on_show_options_modulation(); void on_frequency_step_changed(rf::Frequency f); void on_reference_ppm_correction_changed(int32_t v); void on_headphone_volume_changed(int32_t v); From d82cbcb1c4aacfb86e90cf206371b1809fbec1cf Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 14:26:00 -0800 Subject: [PATCH 438/452] Rework modulation options views handling. Still not pretty, but a bit simpler. I think... --- firmware/application/analog_audio_app.cpp | 126 ++++++++++++---------- firmware/application/analog_audio_app.hpp | 23 +--- 2 files changed, 71 insertions(+), 78 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index d7cd6c4c2..51f34f799 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -83,10 +83,6 @@ AnalogAudioView::AnalogAudioView( &field_vga, &options_modulation, &field_volume, - &view_frequency_options, - &view_rf_gain_options, - &view_am_options, - &view_nbfm_options, &waterfall, } }); @@ -135,32 +131,6 @@ AnalogAudioView::AnalogAudioView( this->on_headphone_volume_changed(v); }; - view_frequency_options.hidden(true); - view_frequency_options.set_step(receiver_model.frequency_step()); - view_frequency_options.on_change_step = [this](rf::Frequency f) { - this->on_frequency_step_changed(f); - }; - view_frequency_options.set_reference_ppm_correction(receiver_model.reference_ppm_correction()); - view_frequency_options.on_change_reference_ppm_correction = [this](int32_t v) { - this->on_reference_ppm_correction_changed(v); - }; - - view_rf_gain_options.hidden(true); - view_rf_gain_options.set_rf_amp(receiver_model.rf_amp()); - view_rf_gain_options.on_change_rf_amp = [this](bool enable) { - this->on_rf_amp_changed(enable); - }; - - view_am_options.hidden(true); - view_am_options.on_config_changed = [this](size_t n) { - this->on_am_config_index_changed(n); - }; - - view_nbfm_options.hidden(true); - view_nbfm_options.on_config_changed = [this](size_t n) { - this->on_nbfm_config_index_changed(n); - }; - update_modulation(static_cast(receiver_model.modulation())); } @@ -219,55 +189,93 @@ void AnalogAudioView::on_modulation_changed(const ReceiverModel::Mode modulation waterfall.on_show(); } -void AnalogAudioView::on_show_options_frequency() { - // TODO: This approach of managing options views is error-prone and unsustainable! - view_rf_gain_options.hidden(true); - view_am_options.hidden(true); - view_nbfm_options.hidden(true); +void AnalogAudioView::remove_options_widget() { + if( options_widget ) { + remove_child(options_widget.get()); + options_widget.reset(); + } field_lna.set_style(nullptr); options_modulation.set_style(nullptr); + field_frequency.set_style(nullptr); +} - view_frequency_options.hidden(false); - field_frequency.set_style(&view_frequency_options.style()); +void AnalogAudioView::set_options_widget(std::unique_ptr new_widget) { + if( new_widget ) { + options_widget = std::move(new_widget); + add_child(options_widget.get()); + } +} + +void AnalogAudioView::on_show_options_frequency() { + // TODO: This approach of managing options views is error-prone and unsustainable! + remove_options_widget(); + + field_frequency.set_style(&style_options_group); + + auto widget = std::make_unique( + Rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, + &style_options_group + ); + + widget->set_step(receiver_model.frequency_step()); + widget->on_change_step = [this](rf::Frequency f) { + this->on_frequency_step_changed(f); + }; + widget->set_reference_ppm_correction(receiver_model.reference_ppm_correction()); + widget->on_change_reference_ppm_correction = [this](int32_t v) { + this->on_reference_ppm_correction_changed(v); + }; + + set_options_widget(std::move(widget)); } void AnalogAudioView::on_show_options_rf_gain() { // TODO: This approach of managing options views is error-prone and unsustainable! - view_frequency_options.hidden(true); - view_am_options.hidden(true); - view_nbfm_options.hidden(true); + remove_options_widget(); - field_frequency.set_style(nullptr); - options_modulation.set_style(nullptr); + field_lna.set_style(&style_options_group); - view_rf_gain_options.hidden(false); - field_lna.set_style(&view_frequency_options.style()); + auto widget = std::make_unique( + Rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, + &style_options_group + ); + + widget->set_rf_amp(receiver_model.rf_amp()); + widget->on_change_rf_amp = [this](bool enable) { + this->on_rf_amp_changed(enable); + }; + + set_options_widget(std::move(widget)); } void AnalogAudioView::on_show_options_modulation() { // TODO: This approach of managing options views is error-prone and unsustainable! - view_frequency_options.hidden(true); - view_rf_gain_options.hidden(true); + remove_options_widget(); const auto modulation = static_cast(receiver_model.modulation()); - if( modulation != ReceiverModel::Mode::AMAudio ) { - view_am_options.hidden(true); - } - if( modulation != ReceiverModel::Mode::NarrowbandFMAudio ) { - view_nbfm_options.hidden(true); - } - - field_frequency.set_style(nullptr); - field_lna.set_style(nullptr); - if( modulation == ReceiverModel::Mode::AMAudio ) { - view_am_options.hidden(false); + options_modulation.set_style(&style_options_group); + auto widget = std::make_unique( + Rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, + &style_options_group + ); + widget->on_config_changed = [this](size_t n) { + this->on_am_config_index_changed(n); + }; + set_options_widget(std::move(widget)); } if( modulation == ReceiverModel::Mode::NarrowbandFMAudio ) { - view_nbfm_options.hidden(false); + options_modulation.set_style(&style_options_group); + auto widget = std::make_unique( + Rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, + &style_options_group + ); + widget->on_config_changed = [this](size_t n) { + this->on_nbfm_config_index_changed(n); + }; + set_options_widget(std::move(widget)); } - options_modulation.set_style(&view_frequency_options.style()); } void AnalogAudioView::on_frequency_step_changed(rf::Frequency f) { diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index 7ff0efc3d..a67dfc98f 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -144,26 +144,8 @@ private: ' ', }; - FrequencyOptionsView view_frequency_options { - { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, - &style_options_group - }; + std::unique_ptr options_widget; - RadioGainOptionsView view_rf_gain_options { - { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, - &style_options_group - }; - - AMOptionsView view_am_options { - { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, - &style_options_group - }; - - NBFMOptionsView view_nbfm_options { - { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, - &style_options_group - }; - spectrum::WaterfallWidget waterfall; void on_tuning_frequency_changed(rf::Frequency f); @@ -183,6 +165,9 @@ private: void on_am_config_index_changed(size_t n); void on_nbfm_config_index_changed(size_t n); + void remove_options_widget(); + void set_options_widget(std::unique_ptr new_widget); + void update_modulation(const ReceiverModel::Mode modulation); }; From 1cf38387c1dbb456c1b23bab8d162b73cd108c89 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 15:01:04 -0800 Subject: [PATCH 439/452] Initialize modulation from ReceiverModel. --- firmware/application/analog_audio_app.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index 51f34f799..f36532ec7 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -118,7 +118,8 @@ AnalogAudioView::AnalogAudioView( this->on_vga_changed(v_db); }; - options_modulation.set_by_value(toUType(ReceiverModel::Mode::AMAudio)); + const auto modulation = receiver_model.modulation(); + options_modulation.set_by_value(modulation); options_modulation.on_change = [this](size_t, OptionsField::value_t v) { this->on_modulation_changed(static_cast(v)); }; @@ -131,7 +132,7 @@ AnalogAudioView::AnalogAudioView( this->on_headphone_volume_changed(v); }; - update_modulation(static_cast(receiver_model.modulation())); + update_modulation(static_cast(modulation)); } AnalogAudioView::~AnalogAudioView() { From 10c7c57fd1b80faf95010feb875f3d636fce5d7d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 15:19:43 -0800 Subject: [PATCH 440/452] Expose modulation configuration indices. --- firmware/application/receiver_model.cpp | 12 ++++++++++++ firmware/application/receiver_model.hpp | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index dd6554c65..7947a652c 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -337,14 +337,26 @@ void ReceiverModel::update_modulation_configuration() { } } +size_t ReceiverModel::am_configuration() const { + return am_config_index; +} + void ReceiverModel::update_am_configuration() { am_configs[am_config_index].apply(); } +size_t ReceiverModel::nbfm_configuration() const { + return nbfm_config_index; +} + void ReceiverModel::update_nbfm_configuration() { nbfm_configs[nbfm_config_index].apply(); } +size_t ReceiverModel::wfm_configuration() const { + return wfm_config_index; +} + void ReceiverModel::update_wfm_configuration() { wfm_configs[wfm_config_index].apply(); } diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index 3c1749c62..4b21c87bb 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -80,8 +80,13 @@ public: void set_baseband_configuration(const BasebandConfiguration config); + size_t am_configuration() const; void set_am_configuration(const size_t n); + + size_t nbfm_configuration() const; void set_nbfm_configuration(const size_t n); + + size_t wfm_configuration() const; void set_wfm_configuration(const size_t n); private: From d9be5677e3665299dedf2759b47bfff974ba0a4b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 15:20:14 -0800 Subject: [PATCH 441/452] Simplify handling of modulation config changes via UI. --- firmware/application/analog_audio_app.cpp | 24 ++++------------------- firmware/application/analog_audio_app.hpp | 7 ------- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index f36532ec7..fcd9cda18 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -42,10 +42,9 @@ AMOptionsView::AMOptionsView( &options_config, } }); + options_config.set_selected_index(receiver_model.am_configuration()); options_config.on_change = [this](size_t n, OptionsField::value_t) { - if( on_config_changed ) { - this->on_config_changed(n); - } + receiver_model.set_am_configuration(n); }; } @@ -62,10 +61,9 @@ NBFMOptionsView::NBFMOptionsView( &options_config, } }); + options_config.set_selected_index(receiver_model.nbfm_configuration()); options_config.on_change = [this](size_t n, OptionsField::value_t) { - if( on_config_changed ) { - this->on_config_changed(n); - } + receiver_model.set_nbfm_configuration(n); }; } @@ -261,9 +259,6 @@ void AnalogAudioView::on_show_options_modulation() { Rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, &style_options_group ); - widget->on_config_changed = [this](size_t n) { - this->on_am_config_index_changed(n); - }; set_options_widget(std::move(widget)); } if( modulation == ReceiverModel::Mode::NarrowbandFMAudio ) { @@ -272,9 +267,6 @@ void AnalogAudioView::on_show_options_modulation() { Rect { 0 * 8, 1 * 16, 30 * 8, 1 * 16 }, &style_options_group ); - widget->on_config_changed = [this](size_t n) { - this->on_nbfm_config_index_changed(n); - }; set_options_widget(std::move(widget)); } } @@ -293,14 +285,6 @@ void AnalogAudioView::on_headphone_volume_changed(int32_t v) { receiver_model.set_headphone_volume(new_volume); } -void AnalogAudioView::on_am_config_index_changed(size_t n) { - receiver_model.set_am_configuration(n); -} - -void AnalogAudioView::on_nbfm_config_index_changed(size_t n) { - receiver_model.set_nbfm_configuration(n); -} - void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis); receiver_model.set_baseband_configuration({ diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index a67dfc98f..e3bd24a4a 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -39,8 +39,6 @@ constexpr Style style_options_group { class AMOptionsView : public View { public: - std::function on_config_changed; - AMOptionsView(const Rect parent_rect, const Style* const style); private: @@ -62,8 +60,6 @@ private: class NBFMOptionsView : public View { public: - std::function on_config_changed; - NBFMOptionsView(const Rect parent_rect, const Style* const style); private: @@ -162,9 +158,6 @@ private: void on_headphone_volume_changed(int32_t v); void on_edit_frequency(); - void on_am_config_index_changed(size_t n); - void on_nbfm_config_index_changed(size_t n); - void remove_options_widget(); void set_options_widget(std::unique_ptr new_widget); From ab2c5b256f244cdd2a8fefb46fd4bb83db36b9e0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 16:08:18 -0800 Subject: [PATCH 442/452] Reinstate and slightly tweak NBFM squelch. --- firmware/baseband/proc_nfm_audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/baseband/proc_nfm_audio.cpp b/firmware/baseband/proc_nfm_audio.cpp index 3bc880434..2a0349acf 100644 --- a/firmware/baseband/proc_nfm_audio.cpp +++ b/firmware/baseband/proc_nfm_audio.cpp @@ -77,7 +77,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) { channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs; channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs; channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2))); - audio_output.configure(message.audio_hpf_config, message.audio_deemph_config, 0); + audio_output.configure(message.audio_hpf_config, message.audio_deemph_config, 12288); configured = true; } From ceef8d32d3b5da9a4faf7b98cad7ae677c63a600 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 2 Feb 2016 16:15:14 -0800 Subject: [PATCH 443/452] Use more accurate arctan for NBFM demodulation. --- firmware/baseband/dsp_demodulate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/baseband/dsp_demodulate.cpp b/firmware/baseband/dsp_demodulate.cpp index b0eae2b5d..1c59c1743 100644 --- a/firmware/baseband/dsp_demodulate.cpp +++ b/firmware/baseband/dsp_demodulate.cpp @@ -99,8 +99,8 @@ buffer_f32_t FM::execute( const auto t0 = multiply_conjugate_s16_s32(s0, z); const auto t1 = multiply_conjugate_s16_s32(s1, s0); z = s1; - *(dst_p++) = angle_approx_0deg27(t0) * k; - *(dst_p++) = angle_approx_0deg27(t1) * k; + *(dst_p++) = angle_precise(t0) * k; + *(dst_p++) = angle_precise(t1) * k; } z_ = z; From 5d0b5d427a24a18088dca9bad89c72f430de389d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 Feb 2016 10:33:54 -0800 Subject: [PATCH 444/452] Extract draw_bitmap from draw_glyph. --- firmware/common/lcd_ili9341.cpp | 25 +++++++++++++++++-------- firmware/common/lcd_ili9341.hpp | 8 ++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/firmware/common/lcd_ili9341.cpp b/firmware/common/lcd_ili9341.cpp index cad5747b5..0f0dd319d 100644 --- a/firmware/common/lcd_ili9341.cpp +++ b/firmware/common/lcd_ili9341.cpp @@ -299,20 +299,29 @@ void ILI9341::draw_pixels( io.lcd_write_pixels(colors, count); } +void ILI9341::draw_bitmap( + const ui::Point p, + const ui::Size size, + const uint8_t* const pixels, + const ui::Color foreground, + const ui::Color background +) { + lcd_start_ram_write(p, size); + + const size_t count = size.w * size.h; + for(size_t i=0; i> 3] & (1U << (i & 0x7)); + io.lcd_write_pixel(pixel ? foreground : background); + } +} + void ILI9341::draw_glyph( const ui::Point p, const ui::Glyph& glyph, const ui::Color foreground, const ui::Color background ) { - lcd_start_ram_write(p, glyph.size()); - - const size_t count = glyph.w() * glyph.h(); - const auto pixels = glyph.pixels(); - for(size_t i=0; i> 3] & (1U << (i & 0x7)); - io.lcd_write_pixel(pixel ? foreground : background); - } + draw_bitmap(p, glyph.size(), glyph.pixels(), foreground, background); } void ILI9341::scroll_set_area( diff --git a/firmware/common/lcd_ili9341.hpp b/firmware/common/lcd_ili9341.hpp index 3b688f837..7c5cda381 100644 --- a/firmware/common/lcd_ili9341.hpp +++ b/firmware/common/lcd_ili9341.hpp @@ -65,6 +65,14 @@ public: draw_pixels(r, colors.data(), colors.size()); } + void draw_bitmap( + const ui::Point p, + const ui::Size size, + const uint8_t* const data, + const ui::Color foreground, + const ui::Color background + ); + void draw_glyph( const ui::Point p, const ui::Glyph& glyph, From e2a82061d4bc27818fcc6102f53cbf933e62a28a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 Feb 2016 10:34:17 -0800 Subject: [PATCH 445/452] Update SD card status when view is shown. --- firmware/application/ui_sd_card_status_view.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/ui_sd_card_status_view.cpp b/firmware/application/ui_sd_card_status_view.cpp index d790a7603..5a254c876 100644 --- a/firmware/application/ui_sd_card_status_view.cpp +++ b/firmware/application/ui_sd_card_status_view.cpp @@ -32,14 +32,14 @@ SDCardStatusView::SDCardStatusView() { add_children({ { &text_status, } }); - - on_status(sd_card::status()); } void SDCardStatusView::on_show() { sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { this->on_status(status); }; + + on_status(sd_card::status()); } void SDCardStatusView::on_hide() { From deade67fd8806b2fac801676107c504d4de49c7c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 Feb 2016 13:23:23 -0800 Subject: [PATCH 446/452] Add ui::Bitmap for two-color images. --- firmware/common/ui.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/firmware/common/ui.hpp b/firmware/common/ui.hpp index 8ac914ae6..0a44efb6d 100644 --- a/firmware/common/ui.hpp +++ b/firmware/common/ui.hpp @@ -257,6 +257,11 @@ struct Rect { } }; +struct Bitmap { + const Size size; + const uint8_t* const data; +}; + enum class KeyEvent { /* Ordinals map to bit positions reported by CPLD */ Right = 0, From 76013a656c2cbfde66a201d71c3311e1b1a30d1b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 Feb 2016 13:23:46 -0800 Subject: [PATCH 447/452] Add Painter.draw_bitmap for Bitmap types. --- firmware/common/ui_painter.cpp | 4 ++++ firmware/common/ui_painter.hpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/firmware/common/ui_painter.cpp b/firmware/common/ui_painter.cpp index 7409b8ebc..2b54e1948 100644 --- a/firmware/common/ui_painter.cpp +++ b/firmware/common/ui_painter.cpp @@ -54,6 +54,10 @@ int Painter::draw_string(Point p, const Style& style, const std::string text) { return width; } +void Painter::draw_bitmap(const Point p, const Bitmap& bitmap, const Color foreground, const Color background) { + display.draw_bitmap(p, bitmap.size, bitmap.data, foreground, background); +} + void Painter::draw_hline(Point p, int width, const Color c) { display.fill_rectangle({ p, { width, 1 } }, c); } diff --git a/firmware/common/ui_painter.hpp b/firmware/common/ui_painter.hpp index 7ac7b40a4..98d6d36e7 100644 --- a/firmware/common/ui_painter.hpp +++ b/firmware/common/ui_painter.hpp @@ -50,6 +50,8 @@ public: int draw_string(Point p, const Style& style, const std::string text); + void draw_bitmap(const Point p, const Bitmap& bitmap, const Color background, const Color foreground); + void draw_rectangle(const Rect r, const Color c); void fill_rectangle(const Rect r, const Color c); From e57659d4cf0fb3dfae601f5290fc58336fca1ed7 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 Feb 2016 13:24:38 -0800 Subject: [PATCH 448/452] Convert SD card view to show icon/color for status. --- .../application/ui_sd_card_status_view.cpp | 131 ++++++++++++------ .../application/ui_sd_card_status_view.hpp | 9 +- 2 files changed, 94 insertions(+), 46 deletions(-) diff --git a/firmware/application/ui_sd_card_status_view.cpp b/firmware/application/ui_sd_card_status_view.cpp index 5a254c876..95b82fecb 100644 --- a/firmware/application/ui_sd_card_status_view.cpp +++ b/firmware/application/ui_sd_card_status_view.cpp @@ -28,58 +28,111 @@ namespace ui { /* SDCardStatusView *****************************************************/ -SDCardStatusView::SDCardStatusView() { - add_children({ { - &text_status, - } }); +namespace detail { + +static constexpr uint8_t bitmap_sd_card_ok_data[] = { + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xf0, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_sd_card_ok { + { 16, 16 }, bitmap_sd_card_ok_data +}; + +static constexpr uint8_t bitmap_sd_card_unknown_data[] = { + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xf0, 0x1f, + 0x38, 0x1c, 0x98, 0x19, 0xf8, 0x19, 0xf8, 0x1c, + 0x78, 0x1e, 0x78, 0x1e, 0xf8, 0x1f, 0x78, 0x1e, + 0xf8, 0x1f, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_sd_card_unknown { + { 16, 16 }, bitmap_sd_card_unknown_data +}; + +static constexpr uint8_t bitmap_sd_card_error_data[] = { + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0xf0, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1b, 0xf8, 0x19, 0xf8, 0x1c, + 0xf8, 0x1e, 0xf8, 0x1c, 0xf8, 0x19, 0xf8, 0x1b, + 0xf8, 0x1f, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_sd_card_error { + { 16, 16 }, bitmap_sd_card_error_data +}; + +const Bitmap& bitmap_sd_card(const sd_card::Status status) { + switch(status) { + case sd_card::Status::IOError: + case sd_card::Status::MountError: + case sd_card::Status::ConnectError: + return bitmap_sd_card_error; + + case sd_card::Status::NotPresent: + return bitmap_sd_card_unknown; + + case sd_card::Status::Present: + return bitmap_sd_card_unknown; + + case sd_card::Status::Mounted: + return bitmap_sd_card_ok; + + default: + return bitmap_sd_card_unknown; + } } +static constexpr Color color_sd_card_error = Color::red(); +static constexpr Color color_sd_card_unknown = Color::yellow(); +static constexpr Color color_sd_card_ok = Color::green(); + +const Color color_sd_card(const sd_card::Status status) { + switch(status) { + case sd_card::Status::IOError: + case sd_card::Status::MountError: + case sd_card::Status::ConnectError: + return color_sd_card_error; + + case sd_card::Status::NotPresent: + return color_sd_card_unknown; + + case sd_card::Status::Present: + return color_sd_card_unknown; + + case sd_card::Status::Mounted: + return color_sd_card_ok; + + default: + return color_sd_card_unknown; + } +} + +} /* namespace detail */ + void SDCardStatusView::on_show() { sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { this->on_status(status); }; - - on_status(sd_card::status()); } void SDCardStatusView::on_hide() { sd_card::status_signal -= sd_card_status_signal_token; } -void SDCardStatusView::on_status(const sd_card::Status status) { - std::string msg("??"); +void SDCardStatusView::paint(Painter& painter) { + const auto status = sd_card::status(); + painter.draw_bitmap( + screen_pos(), + detail::bitmap_sd_card(status), + detail::color_sd_card(status), + style().background + ); +} - switch(status) { - case sd_card::Status::IOError: - msg = "IO"; - break; - - case sd_card::Status::MountError: - msg = "MT"; - break; - - case sd_card::Status::ConnectError: - msg = "CN"; - break; - - case sd_card::Status::NotPresent: - msg = "XX"; - break; - - case sd_card::Status::Present: - msg = "OO"; - break; - - case sd_card::Status::Mounted: - msg = "OK"; - break; - - default: - msg = "--"; - break; - } - - text_status.set(msg); +void SDCardStatusView::on_status(const sd_card::Status) { + set_dirty(); } } /* namespace ui */ diff --git a/firmware/application/ui_sd_card_status_view.hpp b/firmware/application/ui_sd_card_status_view.hpp index dd542f3c2..7c4262606 100644 --- a/firmware/application/ui_sd_card_status_view.hpp +++ b/firmware/application/ui_sd_card_status_view.hpp @@ -29,17 +29,12 @@ namespace ui { class SDCardStatusView : public View { public: - SDCardStatusView(); - void on_show() override; void on_hide() override; -private: - Text text_status { - { 0 * 8, 0, 2 * 8, 1 * 16 }, - "", - }; + void paint(Painter& painter) override; +private: SignalToken sd_card_status_signal_token; void on_status(const sd_card::Status status); From 84824a504f7a913abc067a22e8c10dc97f103270 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 Feb 2016 15:48:50 -0800 Subject: [PATCH 449/452] Add UI Image and ImageButton classes. --- firmware/common/ui_widget.cpp | 93 +++++++++++++++++++++++++++++++++++ firmware/common/ui_widget.hpp | 37 ++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 6a184576e..bc1883603 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -420,6 +420,99 @@ bool Button::on_touch(const TouchEvent event) { #endif } +/* Image *****************************************************************/ + +Image::Image( +) : Image { { }, nullptr, Color::white(), Color::black() } +{ +} + +Image::Image( + const Rect parent_rect, + const Bitmap* bitmap, + const Color foreground, + const Color background +) : Widget { parent_rect }, + bitmap_ { bitmap }, + foreground_ { foreground }, + background_ { background } +{ +} + +void Image::set_bitmap(const Bitmap* bitmap) { + bitmap_ = bitmap; + set_dirty(); +} + +void Image::set_foreground(const Color color) { + foreground_ = color; + set_dirty(); +} + +void Image::set_background(const Color color) { + background_ = color; + set_dirty(); +} + +void Image::paint(Painter& painter) { + if( bitmap_ ) { + // Code also handles ImageButton behavior. + const bool selected = (has_focus() || flags.highlighted); + painter.draw_bitmap( + screen_pos(), + *bitmap_, + selected ? background_ : foreground_, + selected ? foreground_ : background_ + ); + } +} + +/* ImageButton ***********************************************************/ + +// TODO: Virtually all this code is duplicated from Button. Base class? + +ImageButton::ImageButton( + const Rect parent_rect, + const Bitmap* bitmap, + const Color foreground, + const Color background +) : Image { parent_rect, bitmap, foreground, background } +{ + flags.focusable = true; +} + +bool ImageButton::on_key(const KeyEvent key) { + if( key == KeyEvent::Select ) { + if( on_select ) { + on_select(*this); + return true; + } + } + + return false; +} + +bool ImageButton::on_touch(const TouchEvent event) { + switch(event.type) { + case TouchEvent::Type::Start: + flags.highlighted = true; + set_dirty(); + return true; + + + case TouchEvent::Type::End: + flags.highlighted = false; + set_dirty(); + if( on_select ) { + on_select(*this); + } + return true; + + default: + return false; + } +} + /* OptionsField **********************************************************/ OptionsField::OptionsField( diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index ddecaae26..80d3de46d 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -218,6 +218,43 @@ private: std::string text_; }; +class Image : public Widget { +public: + Image(); + Image( + const Rect parent_rect, + const Bitmap* bitmap, + const Color foreground, + const Color background + ); + + void set_bitmap(const Bitmap* bitmap); + void set_foreground(const Color color); + void set_background(const Color color); + + void paint(Painter& painter) override; + +private: + const Bitmap* bitmap_; + Color foreground_; + Color background_; +}; + +class ImageButton : public Image { +public: + std::function on_select; + + ImageButton( + const Rect parent_rect, + const Bitmap* bitmap, + const Color foreground, + const Color background + ); + + bool on_key(const KeyEvent key) override; + bool on_touch(const TouchEvent event) override; +}; + class OptionsField : public Widget { public: using name_t = std::string; From dd6d56cff8f7db2981ae237b59118419d46cf99f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 Feb 2016 15:50:14 -0800 Subject: [PATCH 450/452] SD card status view inherits from new Image class. --- firmware/application/ui_navigation.cpp | 1 - firmware/application/ui_navigation.hpp | 4 +++- firmware/application/ui_sd_card_status_view.cpp | 17 +++++++++++------ firmware/application/ui_sd_card_status_view.hpp | 4 +++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 364db9628..fc7248c3b 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -46,7 +46,6 @@ SystemStatusView::SystemStatusView() { &button_sleep, &sd_card_status_view, } }); - sd_card_status_view.set_parent_rect({ 28 * 8, 0 * 16, 2 * 8, 1 * 16 }); button_back.on_select = [this](Button&){ if( this->on_back ) { diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index a0c0ce04d..14beadc92 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -64,7 +64,9 @@ private: "ZZ", }; - SDCardStatusView sd_card_status_view; + SDCardStatusView sd_card_status_view { + { 28 * 8, 0 * 16, 2 * 8, 1 * 16 } + }; }; class NavigationView : public View { diff --git a/firmware/application/ui_sd_card_status_view.cpp b/firmware/application/ui_sd_card_status_view.cpp index 95b82fecb..46a077208 100644 --- a/firmware/application/ui_sd_card_status_view.cpp +++ b/firmware/application/ui_sd_card_status_view.cpp @@ -111,6 +111,12 @@ const Color color_sd_card(const sd_card::Status status) { } /* namespace detail */ +SDCardStatusView::SDCardStatusView( + const Rect parent_rect +) : Image { parent_rect, &detail::bitmap_sd_card_unknown, detail::color_sd_card_unknown, Color::black() } +{ +} + void SDCardStatusView::on_show() { sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { this->on_status(status); @@ -123,15 +129,14 @@ void SDCardStatusView::on_hide() { void SDCardStatusView::paint(Painter& painter) { const auto status = sd_card::status(); - painter.draw_bitmap( - screen_pos(), - detail::bitmap_sd_card(status), - detail::color_sd_card(status), - style().background - ); + set_bitmap(&detail::bitmap_sd_card(status)); + set_foreground(detail::color_sd_card(status)); + + Image::paint(painter); } void SDCardStatusView::on_status(const sd_card::Status) { + // Don't update image properties here, they might change. Wait until paint. set_dirty(); } diff --git a/firmware/application/ui_sd_card_status_view.hpp b/firmware/application/ui_sd_card_status_view.hpp index 7c4262606..31388cfab 100644 --- a/firmware/application/ui_sd_card_status_view.hpp +++ b/firmware/application/ui_sd_card_status_view.hpp @@ -27,8 +27,10 @@ namespace ui { -class SDCardStatusView : public View { +class SDCardStatusView : public Image { public: + SDCardStatusView(const Rect parent_rect); + void on_show() override; void on_hide() override; From 5d4e59271ab08816cd4fe4c3703edae7bda0d690 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 Feb 2016 16:04:23 -0800 Subject: [PATCH 451/452] Switch display sleep button to ImageButton. --- firmware/application/ui_navigation.cpp | 2 +- firmware/application/ui_navigation.hpp | 29 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index fc7248c3b..dfa252317 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -53,7 +53,7 @@ SystemStatusView::SystemStatusView() { } }; - button_sleep.on_select = [this](Button&) { + button_sleep.on_select = [this](ImageButton&) { DisplaySleepMessage message; EventDispatcher::message_map().send(&message); }; diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 14beadc92..48c409902 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -37,6 +37,29 @@ namespace ui { +static constexpr uint8_t bitmap_sleep_data[] = { + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x04, + 0x00, 0x08, + 0x00, 0x18, + 0x00, 0x18, + 0x00, 0x38, + 0x00, 0x3c, + 0x00, 0x3c, + 0x00, 0x3e, + 0x84, 0x1f, + 0xf8, 0x1f, + 0xf0, 0x0f, + 0xc0, 0x03, + 0x00, 0x00, + 0x00, 0x00, +}; + +static constexpr Bitmap bitmap_sleep { + { 16, 16 }, bitmap_sleep_data +}; + class SystemStatusView : public View { public: std::function on_back; @@ -59,9 +82,11 @@ private: default_title, }; - Button button_sleep { + ImageButton button_sleep { { 25 * 8, 0, 2 * 8, 1 * 16 }, - "ZZ", + &bitmap_sleep, + Color::white(), + Color::black() }; SDCardStatusView sd_card_status_view { From 1d2dd4e19d6c67891526fe544ad41d18dff9cb0b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 Feb 2016 17:59:46 -0800 Subject: [PATCH 452/452] Old GCC on Travis-CI was cheesed off by my new syntax. --- firmware/common/message.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 278d69ec4..c29eb11ec 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -330,8 +330,8 @@ public: channel_filter(channel_filter), channel_decimation { channel_decimation }, deviation { deviation }, - audio_hpf_config { audio_hpf_config }, - audio_deemph_config { audio_deemph_config } + audio_hpf_config(audio_hpf_config), + audio_deemph_config(audio_deemph_config) { } @@ -358,8 +358,8 @@ public: decim_1_filter(decim_1_filter), audio_filter(audio_filter), deviation { deviation }, - audio_hpf_config { audio_hpf_config }, - audio_deemph_config { audio_deemph_config } + audio_hpf_config(audio_hpf_config), + audio_deemph_config(audio_deemph_config) { } @@ -391,7 +391,7 @@ public: decim_2_filter(decim_2_filter), channel_filter(channel_filter), modulation { modulation }, - audio_hpf_config { audio_hpf_config } + audio_hpf_config(audio_hpf_config) { }