mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Xylos (CCIR tones) TX, jammer update, SD card mod load
Xylos TX (CCIR tones) ;) Jammer update, still buggy and inefficient SD card module loader update
This commit is contained in:
parent
5a5a4c3525
commit
802ac496e9
@ -172,6 +172,9 @@ CPPSRC = main.cpp \
|
||||
ui_receiver.cpp \
|
||||
ui_spectrum.cpp \
|
||||
ui_loadmodule.cpp \
|
||||
ui_afskrx.cpp \
|
||||
ui_sigfrx.cpp \
|
||||
ui_xylos.cpp \
|
||||
receiver_model.cpp \
|
||||
transmitter_model.cpp \
|
||||
spectrum_color_lut.cpp \
|
||||
|
@ -19,8 +19,13 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
//TODO: check jammer bandwidths
|
||||
//TODO: GSM channel detector
|
||||
//TODO: wait_for_switch() in baseband-tx !
|
||||
//TODO: AFSK receiver
|
||||
//TODO: SIGFOX RX/TX
|
||||
//TODO: Reset baseband if module not found (instead of lockup in RAM loop)
|
||||
//TODO: Module name/filename in modules.hpp to indicate requirement in case it's not found
|
||||
//TODO: Module name/filename in modules.hpp to indicate requirement in case it's not found ui_loadmodule
|
||||
//TODO: LCD backlight PWM
|
||||
//TODO: BUG: Crash after TX stop
|
||||
//TODO: Check bw setting in LCR TX
|
||||
|
@ -1,2 +1,2 @@
|
||||
const char md5_baseband[16] = {0xca,0x05,0xc3,0xbf,0x78,0x10,0xad,0xac,0x2a,0x2b,0x31,0x19,0xf9,0xe8,0x91,0x26,};
|
||||
const char md5_baseband_tx[16] = {0xe7,0x28,0x33,0x67,0x45,0x37,0x1e,0x13,0x3c,0x85,0xb5,0x91,0x51,0xaa,0xed,0x4f,};
|
||||
const char md5_baseband[16] = {0xce,0x87,0x2b,0x2c,0x9e,0x74,0xe8,0x1c,0x1c,0xe9,0xfc,0xc2,0x40,0xc3,0x32,0xd5,};
|
||||
const char md5_baseband_tx[16] = {0x1b,0xef,0x34,0x50,0x45,0xd7,0xae,0x7c,0xb5,0x4f,0x0c,0x5a,0x80,0xa0,0xbc,0x05,};
|
||||
|
File diff suppressed because it is too large
Load Diff
144
firmware/application/ui_afskrx.cpp
Normal file
144
firmware/application/ui_afskrx.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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 "ui_afskrx.hpp"
|
||||
|
||||
#include "ui_spectrum.hpp"
|
||||
#include "ui_console.hpp"
|
||||
|
||||
#include "ff.h"
|
||||
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
#include "ui_receiver.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
AFSKRXView::AFSKRXView(
|
||||
NavigationView& nav,
|
||||
ReceiverModel& receiver_model
|
||||
) : receiver_model(receiver_model)
|
||||
{
|
||||
add_children({ {
|
||||
&button_done,
|
||||
&text_rx
|
||||
} } );
|
||||
|
||||
button_done.on_select = [&nav](Button&){
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
receiver_model.set_baseband_configuration({
|
||||
.mode = 6,
|
||||
.sampling_rate = 3072000,
|
||||
.decimation_factor = 4,
|
||||
});
|
||||
receiver_model.set_baseband_bandwidth(1750000);
|
||||
}
|
||||
|
||||
AFSKRXView::~AFSKRXView() {
|
||||
receiver_model.disable();
|
||||
}
|
||||
|
||||
void AFSKRXView::on_show() {
|
||||
auto& message_map = context().message_map();
|
||||
message_map.register_handler(Message::ID::AFSKData,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const AFSKDataMessage*>(p);
|
||||
this->on_data_afsk(*message);
|
||||
}
|
||||
);
|
||||
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
void AFSKRXView::on_hide() {
|
||||
auto& message_map = context().message_map();
|
||||
message_map.unregister_handler(Message::ID::AFSKData);
|
||||
}
|
||||
|
||||
void AFSKRXView::on_data_afsk(const AFSKDataMessage& message) {
|
||||
Coord oy,ny;
|
||||
|
||||
//text_rx.set(to_string_dec_int(abs(message.data), 8, '0'));
|
||||
|
||||
portapack::display.fill_rectangle({0,160-64,240,128},{32,32,32});
|
||||
|
||||
oy = 160;
|
||||
for (int c=0;c<128;c++) {
|
||||
ny = 160-(message.data[c]>>10);
|
||||
portapack::display.draw_line({static_cast<Coord>(c),oy},{static_cast<Coord>(c+1),ny},{255,127,0});
|
||||
oy = ny;
|
||||
}
|
||||
|
||||
/*auto payload = message.packet.payload;
|
||||
auto payload_length = message.packet.bits_received;
|
||||
|
||||
std::string hex_data;
|
||||
std::string hex_error;
|
||||
uint8_t byte_data = 0;
|
||||
uint8_t byte_error = 0;
|
||||
for(size_t i=0; i<payload_length; i+=2) {
|
||||
const auto bit_data = payload[i+1];
|
||||
const auto bit_error = (payload[i+0] == payload[i+1]);
|
||||
|
||||
byte_data <<= 1;
|
||||
byte_data |= bit_data ? 1 : 0;
|
||||
|
||||
byte_error <<= 1;
|
||||
byte_error |= bit_error ? 1 : 0;
|
||||
|
||||
if( ((i >> 1) & 7) == 7 ) {
|
||||
hex_data += to_string_hex(byte_data, 2);
|
||||
hex_error += to_string_hex(byte_error, 2);
|
||||
}
|
||||
}
|
||||
|
||||
auto console = reinterpret_cast<Console*>(widget_content.get());
|
||||
console->writeln(hex_data.substr(0, 240 / 8));
|
||||
|
||||
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_data + "/" + hex_error + "\r\n";
|
||||
f_puts(log.c_str(), &fil_tpms);
|
||||
f_sync(&fil_tpms);
|
||||
}*/
|
||||
}
|
||||
|
||||
void AFSKRXView::focus() {
|
||||
button_done.focus();
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
76
firmware/application/ui_afskrx.hpp
Normal file
76
firmware/application/ui_afskrx.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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 __UI_AFSKRX_H__
|
||||
#define __UI_AFSKRX_H__
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_font_fixed_8x16.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_painter.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_console.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "receiver_model.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
namespace ui {
|
||||
|
||||
class AFSKRXView : public View {
|
||||
public:
|
||||
AFSKRXView(NavigationView& nav, ReceiverModel& receiver_model);
|
||||
~AFSKRXView();
|
||||
|
||||
void focus() override;
|
||||
|
||||
void on_show() override;
|
||||
void on_hide() override;
|
||||
|
||||
private:
|
||||
ReceiverModel& receiver_model;
|
||||
|
||||
std::unique_ptr<Widget> widget_content;
|
||||
|
||||
Button button_done {
|
||||
{ 4 * 8, 0 * 16, 3 * 8, 16 },
|
||||
" < "
|
||||
};
|
||||
|
||||
Text text_rx {
|
||||
{ 1 * 8, 2 * 16, 28 * 8, 16 },
|
||||
"Ready..."
|
||||
};
|
||||
|
||||
void on_tuning_frequency_changed(rf::Frequency f);
|
||||
void on_edit_frequency();
|
||||
|
||||
void on_data_afsk(const AFSKDataMessage& message);
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_RECEIVER_H__*/
|
@ -283,8 +283,8 @@ LCRView::LCRView(
|
||||
make_frame();
|
||||
|
||||
shared_memory.afsk_samples_per_bit = 228000/portapack::persistent_memory::afsk_bitrate();
|
||||
shared_memory.afsk_phase_inc_mark = portapack::persistent_memory::afsk_mark_freq()*(0x10000*256)/2280;
|
||||
shared_memory.afsk_phase_inc_space = portapack::persistent_memory::afsk_space_freq()*(0x10000*256)/2280;
|
||||
shared_memory.afsk_phase_inc_mark = portapack::persistent_memory::afsk_mark_freq()*(0x40000*256)/2280;
|
||||
shared_memory.afsk_phase_inc_space = portapack::persistent_memory::afsk_space_freq()*(0x40000*256)/2280;
|
||||
|
||||
shared_memory.afsk_fmmod = portapack::persistent_memory::afsk_bw() * 8;
|
||||
|
||||
|
@ -36,6 +36,9 @@
|
||||
#include "ui_whistle.hpp"
|
||||
#include "ui_jammer.hpp"
|
||||
#include "ui_loadmodule.hpp"
|
||||
#include "ui_afskrx.hpp"
|
||||
#include "ui_xylos.hpp"
|
||||
#include "ui_sigfrx.hpp"
|
||||
|
||||
#include "portapack.hpp"
|
||||
#include "m4_startup.hpp"
|
||||
@ -108,16 +111,19 @@ void NavigationView::focus() {
|
||||
/* SystemMenuView ********************************************************/
|
||||
|
||||
SystemMenuView::SystemMenuView(NavigationView& nav) {
|
||||
add_items<11>({ {
|
||||
add_items<10>({ {
|
||||
{ "Play dead", ui::Color::red(), [&nav](){ nav.push(new PlayDeadView { nav, false }); } },
|
||||
{ "Receiver", ui::Color::cyan(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband, new ReceiverView { nav, receiver_model } }); } },
|
||||
{ "Receiver", ui::Color::cyan(), [&nav](){ nav.push(new ReceiverView { nav, receiver_model }); } },
|
||||
//{ "Nordic/BTLE RX", ui::Color::cyan(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||
{ "Jammer", ui::Color::white(), [&nav](){ nav.push(new JammerView { nav, transmitter_model }); } },
|
||||
{ "Audio file TX", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||
//{ "Audio file TX", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||
//{ "Encoder TX", ui::Color::green(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||
{ "Whistle", ui::Color::purple(), [&nav](){ nav.push(new WhistleView { nav, transmitter_model }); } },
|
||||
{ "RDS TX", ui::Color::yellow(), [&nav](){ nav.push(new RDSView { nav, transmitter_model }); } },
|
||||
{ "TEDI/LCR TX", ui::Color::orange(), [&nav](){ nav.push(new LCRView { nav, transmitter_model }); } },
|
||||
//{ "SIGFOX RX", ui::Color::orange(), [&nav](){ nav.push(new SIGFRXView { nav, receiver_model }); } },
|
||||
//{ "RDS TX", ui::Color::yellow(), [&nav](){ nav.push(new LoadModuleView { nav, md5_baseband_tx, new RDSView { nav, transmitter_model }}; } },
|
||||
{ "Xylos TX", ui::Color::orange(), [&nav](){ nav.push(new XylosView { nav, transmitter_model }); } },
|
||||
//{ "AFSK RX", ui::Color::cyan(), [&nav](){ nav.push(new AFSKRXView { nav, receiver_model }); } },
|
||||
{ "TEDI/LCR TX", ui::Color::yellow(), [&nav](){ nav.push(new LCRView { nav, transmitter_model }); } },
|
||||
{ "Setup", ui::Color::white(), [&nav](){ nav.push(new SetupMenuView { nav }); } },
|
||||
{ "About", ui::Color::white(), [&nav](){ nav.push(new AboutView { nav }); } },
|
||||
{ "Debug", ui::Color::white(), [&nav](){ nav.push(new DebugMenuView { nav }); } },
|
||||
@ -161,6 +167,8 @@ SystemView::SystemView(
|
||||
//if (persistent_memory::playing_dead() == 0x59)
|
||||
// navigation_view.push(new PlayDeadView { navigation_view, true });
|
||||
//else
|
||||
// navigation_view.push(new BMPView { navigation_view });
|
||||
|
||||
navigation_view.push(new BMPView { navigation_view });
|
||||
}
|
||||
|
||||
@ -187,51 +195,7 @@ BMPView::BMPView(NavigationView& nav) {
|
||||
}
|
||||
|
||||
void BMPView::paint(Painter& painter) {
|
||||
uint32_t pixel_data;
|
||||
uint8_t p, by, c, count;
|
||||
ui::Color linebuffer[185];
|
||||
ui::Coord px = 0, py = 302;
|
||||
ui::Color palette[16];
|
||||
|
||||
// RLE_4 BMP loader with hardcoded size and no delta :(
|
||||
|
||||
pixel_data = splash_bmp[0x0A];
|
||||
p = 0;
|
||||
for (c = 0x36; c < (0x36+(16*4)); c+=4) {
|
||||
palette[p++] = ui::Color(splash_bmp[c+2], splash_bmp[c+1], splash_bmp[c]);
|
||||
}
|
||||
|
||||
do {
|
||||
by = splash_bmp[pixel_data++];
|
||||
if (by) {
|
||||
count = by;
|
||||
by = splash_bmp[pixel_data++];
|
||||
for (c = 0; c < count; c+=2) {
|
||||
linebuffer[px++] = palette[by >> 4];
|
||||
if (px < 185) linebuffer[px++] = palette[by & 15];
|
||||
}
|
||||
if (pixel_data & 1) pixel_data++;
|
||||
} else {
|
||||
by = splash_bmp[pixel_data++];
|
||||
if (by == 0) {
|
||||
portapack::display.render_line({27, py}, 185, linebuffer);
|
||||
py--;
|
||||
px = 0;
|
||||
} else if (by == 1) {
|
||||
break;
|
||||
} else if (by == 2) {
|
||||
// Delta
|
||||
} else {
|
||||
count = by;
|
||||
for (c = 0; c < count; c+=2) {
|
||||
by = splash_bmp[pixel_data++];
|
||||
linebuffer[px++] = palette[by >> 4];
|
||||
if (px < 185) linebuffer[px++] = palette[by & 15];
|
||||
}
|
||||
if (pixel_data & 1) pixel_data++;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
portapack::display.drawBMP({(240-185)/2, 0}, splash_bmp);
|
||||
}
|
||||
|
||||
/* PlayDeadView **********************************************************/
|
||||
|
246
firmware/application/ui_xylos.cpp
Normal file
246
firmware/application/ui_xylos.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* 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_xylos.hpp"
|
||||
|
||||
#include "ch.h"
|
||||
#include "evtimer.h"
|
||||
|
||||
#include "ff.h"
|
||||
#include "hackrf_gpio.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "radio.hpp"
|
||||
|
||||
#include "hackrf_hal.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace hackrf::one;
|
||||
|
||||
namespace ui {
|
||||
|
||||
void XylosView::focus() {
|
||||
city_code.focus();
|
||||
}
|
||||
|
||||
XylosView::~XylosView() {
|
||||
transmitter_model.disable();
|
||||
}
|
||||
|
||||
void XylosView::paint(Painter& painter) {
|
||||
|
||||
}
|
||||
|
||||
void XylosView::upd_message() {
|
||||
uint8_t c;
|
||||
|
||||
ccirmessage[0] = '0';
|
||||
ccirmessage[1] = '0';
|
||||
ccirmessage[2] = '0';
|
||||
ccirmessage[3] = '0';
|
||||
|
||||
ccirmessage[4] = (city_code.value() / 10) + 0x30;
|
||||
ccirmessage[5] = (city_code.value() % 10) + 0x30;
|
||||
ccirmessage[6] = family_code.value() + 0x30;
|
||||
if (checkbox_wcsubfamily.value() == false)
|
||||
ccirmessage[7] = subfamily_code.value() + 0x30;
|
||||
else
|
||||
ccirmessage[7] = 'A';
|
||||
if (checkbox_wcid.value() == false) {
|
||||
ccirmessage[8] = (receiver_code.value() / 10) + 0x30;
|
||||
ccirmessage[9] = (receiver_code.value() % 10) + 0x30;
|
||||
} else {
|
||||
ccirmessage[8] = 'A';
|
||||
ccirmessage[9] = 'A';
|
||||
}
|
||||
|
||||
ccirmessage[10] = 'B';
|
||||
|
||||
ccirmessage[11] = options_ra.selected_index() + 0x30;
|
||||
ccirmessage[12] = options_rb.selected_index() + 0x30;
|
||||
ccirmessage[13] = options_rc.selected_index() + 0x30;
|
||||
ccirmessage[14] = '0';
|
||||
|
||||
ccirmessage[15] = 'B';
|
||||
|
||||
ccirmessage[16] = '0';
|
||||
ccirmessage[17] = '0';
|
||||
ccirmessage[18] = '0';
|
||||
ccirmessage[19] = '0';
|
||||
|
||||
// Stuffing
|
||||
for (c=1; c<20; c++) {
|
||||
if (ccirmessage[c] == ccirmessage[c-1]) ccirmessage[c] = 'E';
|
||||
}
|
||||
|
||||
ccirmessage[20] = 0;
|
||||
|
||||
text_debug.set(ccirmessage);
|
||||
}
|
||||
|
||||
XylosView::XylosView(
|
||||
NavigationView& nav,
|
||||
TransmitterModel& transmitter_model
|
||||
) : transmitter_model(transmitter_model)
|
||||
{
|
||||
static constexpr Style style_val {
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::green(),
|
||||
.foreground = Color::black(),
|
||||
};
|
||||
|
||||
static constexpr Style style_cancel {
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::red(),
|
||||
.foreground = Color::black(),
|
||||
};
|
||||
|
||||
transmitter_model.set_modulation(19);
|
||||
|
||||
add_children({ {
|
||||
&text_title,
|
||||
&text_city,
|
||||
&city_code,
|
||||
&text_family,
|
||||
&family_code,
|
||||
&text_subfamily,
|
||||
&subfamily_code,
|
||||
&checkbox_wcsubfamily,
|
||||
&text_receiver,
|
||||
&receiver_code,
|
||||
&checkbox_wcid,
|
||||
&text_freq,
|
||||
&options_freq,
|
||||
&text_ra,
|
||||
&options_ra,
|
||||
&text_rb,
|
||||
&options_rb,
|
||||
&text_rc,
|
||||
&options_rc,
|
||||
&text_progress,
|
||||
&text_debug,
|
||||
&button_transmit,
|
||||
&button_exit
|
||||
} });
|
||||
|
||||
city_code.set_value(18);
|
||||
family_code.set_value(1);
|
||||
subfamily_code.set_value(1);
|
||||
receiver_code.set_value(1);
|
||||
options_freq.set_selected_index(5);
|
||||
|
||||
checkbox_wcsubfamily.set_value(true);
|
||||
checkbox_wcid.set_value(true);
|
||||
|
||||
city_code.on_change = [this](int32_t v) {
|
||||
(void)v;
|
||||
XylosView::upd_message();
|
||||
};
|
||||
family_code.on_change = [this](int32_t v) {
|
||||
(void)v;
|
||||
XylosView::upd_message();
|
||||
};
|
||||
subfamily_code.on_change = [this](int32_t v) {
|
||||
(void)v;
|
||||
XylosView::upd_message();
|
||||
};
|
||||
receiver_code.on_change = [this](int32_t v) {
|
||||
(void)v;
|
||||
XylosView::upd_message();
|
||||
};
|
||||
checkbox_wcsubfamily.on_select = [this](Checkbox&) {
|
||||
XylosView::upd_message();
|
||||
};
|
||||
checkbox_wcid.on_select = [this](Checkbox&) {
|
||||
XylosView::upd_message();
|
||||
};
|
||||
options_ra.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
(void)v;
|
||||
XylosView::upd_message();
|
||||
};
|
||||
options_rb.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
(void)v;
|
||||
XylosView::upd_message();
|
||||
};
|
||||
options_rc.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
(void)v;
|
||||
XylosView::upd_message();
|
||||
};
|
||||
|
||||
button_transmit.set_style(&style_val);
|
||||
|
||||
button_transmit.on_select = [this,&transmitter_model](Button&) {
|
||||
if (txing == false) {
|
||||
upd_message();
|
||||
|
||||
auto& message_map = context().message_map();
|
||||
|
||||
message_map.unregister_handler(Message::ID::TXDone);
|
||||
|
||||
message_map.register_handler(Message::ID::TXDone,
|
||||
[this,&transmitter_model](Message* const p) {
|
||||
uint8_t c;
|
||||
char progress[21];
|
||||
const auto message = static_cast<const TXDoneMessage*>(p);
|
||||
if (message->n == 25) {
|
||||
transmitter_model.disable();
|
||||
for (c=0;c<20;c++)
|
||||
progress[c] = ' ';
|
||||
progress[20] = 0;
|
||||
text_progress.set(progress);
|
||||
txing = false;
|
||||
button_transmit.set_style(&style_val);
|
||||
button_transmit.set_text("START");
|
||||
} else {
|
||||
for (c=0;c<message->n;c++)
|
||||
progress[c] = ' ';
|
||||
progress[c] = '.';
|
||||
progress[++c] = 0;
|
||||
text_progress.set(progress);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
shared_memory.xylos_transmit_done = false;
|
||||
memcpy(shared_memory.xylosdata, ccirmessage, 21);
|
||||
|
||||
transmitter_model.set_tuning_frequency(87700000); //xylos_freqs[options_freq.selected_index()]);
|
||||
|
||||
txing = true;
|
||||
button_transmit.set_style(&style_cancel);
|
||||
button_transmit.set_text("Wait");
|
||||
transmitter_model.enable();
|
||||
}
|
||||
};
|
||||
|
||||
button_exit.on_select = [&nav](Button&){
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
191
firmware/application/ui_xylos.hpp
Normal file
191
firmware/application/ui_xylos.hpp
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_painter.hpp"
|
||||
#include "ui_menu.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_font_fixed_8x16.hpp"
|
||||
#include "clock_manager.hpp"
|
||||
#include "message.hpp"
|
||||
#include "rf_path.hpp"
|
||||
#include "max2837.hpp"
|
||||
#include "volume.hpp"
|
||||
#include "transmitter_model.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class XylosView : public View {
|
||||
public:
|
||||
XylosView(NavigationView& nav, TransmitterModel& transmitter_model);
|
||||
~XylosView();
|
||||
|
||||
void upd_message();
|
||||
void focus() override;
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
private:
|
||||
bool txing = false;
|
||||
const rf::Frequency xylos_freqs[6] = { 31325000, 31387500, 31437500, 31475000, 31687500, 31975000 };
|
||||
char ccirmessage[21];
|
||||
|
||||
TransmitterModel& transmitter_model;
|
||||
|
||||
Text text_title {
|
||||
{ 1 * 8, 1 * 16, 11, 16 },
|
||||
"BH Xylos TX"
|
||||
};
|
||||
|
||||
Text text_city {
|
||||
{ 4 * 8, 3 * 16, 11 * 8, 16 },
|
||||
"Code ville:"
|
||||
};
|
||||
NumberField city_code {
|
||||
{ 16 * 8, 3 * 16 },
|
||||
2,
|
||||
{ 0, 99 },
|
||||
1,
|
||||
' '
|
||||
};
|
||||
|
||||
Text text_family {
|
||||
{ 7 * 8, 4 * 16, 8 * 8, 16 },
|
||||
"Famille:"
|
||||
};
|
||||
NumberField family_code {
|
||||
{ 16 * 8, 4 * 16 },
|
||||
2,
|
||||
{ 0, 9 },
|
||||
1,
|
||||
' '
|
||||
};
|
||||
|
||||
Text text_subfamily {
|
||||
{ 2 * 8, 5 * 16 + 4, 13 * 8, 16 },
|
||||
"Sous-famille:"
|
||||
};
|
||||
NumberField subfamily_code {
|
||||
{ 16 * 8, 5 * 16 + 4 },
|
||||
2,
|
||||
{ 0, 9 },
|
||||
1,
|
||||
' '
|
||||
};
|
||||
Checkbox checkbox_wcsubfamily {
|
||||
{ 20 * 8, 5 * 16},
|
||||
"Toutes"
|
||||
};
|
||||
|
||||
Text text_receiver {
|
||||
{ 2 * 8, 7 * 16 + 6, 13 * 8, 16 },
|
||||
"ID recepteur:"
|
||||
};
|
||||
NumberField receiver_code {
|
||||
{ 16 * 8, 7 * 16 + 6 },
|
||||
2,
|
||||
{ 0, 99 },
|
||||
1,
|
||||
' '
|
||||
};
|
||||
Checkbox checkbox_wcid {
|
||||
{ 20 * 8, 7 * 16 + 4},
|
||||
"Tous"
|
||||
};
|
||||
|
||||
Text text_freq {
|
||||
{ 5 * 8, 9 * 16, 10 * 8, 16 },
|
||||
"Frequence:"
|
||||
};
|
||||
OptionsField options_freq {
|
||||
{ 16 * 8, 9 * 16 },
|
||||
6,
|
||||
{
|
||||
{ "31.3250", 0 },
|
||||
{ "31.3875", 1 },
|
||||
{ "31.4375", 2 },
|
||||
{ "31.4750", 3 },
|
||||
{ "31.6875", 4 },
|
||||
{ "31.9750", 5 }
|
||||
}
|
||||
};
|
||||
|
||||
Text text_ra {
|
||||
{ 12, 11 * 16, 8 * 8, 16 },
|
||||
"Relais 1"
|
||||
};
|
||||
OptionsField options_ra {
|
||||
{ 16, 12 * 16 },
|
||||
3,
|
||||
{
|
||||
{ "Ignorer", 0 },
|
||||
{ " OFF ", 1 },
|
||||
{ " ON ", 2 }
|
||||
}
|
||||
};
|
||||
Text text_rb {
|
||||
{ 88, 11 * 16, 8 * 8, 16 },
|
||||
"Relais 2"
|
||||
};
|
||||
OptionsField options_rb {
|
||||
{ 92, 12 * 16 },
|
||||
3,
|
||||
{
|
||||
{ "Ignorer", 0 },
|
||||
{ " OFF ", 1 },
|
||||
{ " ON ", 2 }
|
||||
}
|
||||
};
|
||||
Text text_rc {
|
||||
{ 164, 11 * 16, 8 * 8, 16 },
|
||||
"Relais 3"
|
||||
};
|
||||
OptionsField options_rc {
|
||||
{ 168, 12 * 16 },
|
||||
3,
|
||||
{
|
||||
{ "Ignorer", 0 },
|
||||
{ " OFF ", 1 },
|
||||
{ " ON ", 2 }
|
||||
}
|
||||
};
|
||||
|
||||
Text text_progress {
|
||||
{ 5 * 8, 13 * 16, 20 * 8, 16 },
|
||||
" "
|
||||
};
|
||||
Text text_debug {
|
||||
{ 5 * 8, 14 * 16, 20 * 8, 16 },
|
||||
"--------------------"
|
||||
};
|
||||
|
||||
Button button_transmit {
|
||||
{ 2 * 8, 16 * 16, 64, 32 },
|
||||
"START"
|
||||
};
|
||||
|
||||
Button button_exit {
|
||||
{ 21 * 8, 16 * 16, 64, 32 },
|
||||
"Exit"
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
Binary file not shown.
@ -136,6 +136,7 @@ CPPSRC = main.cpp \
|
||||
matched_filter.cpp \
|
||||
proc_jammer.cpp \
|
||||
proc_fsk_lcr.cpp \
|
||||
proc_xylos.cpp \
|
||||
dsp_squelch.cpp \
|
||||
clock_recovery.cpp \
|
||||
packet_builder.cpp \
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "baseband_processor.hpp"
|
||||
#include "proc_fsk_lcr.hpp"
|
||||
#include "proc_jammer.hpp"
|
||||
#include "proc_xylos.hpp"
|
||||
|
||||
#include "clock_recovery.hpp"
|
||||
#include "packet_builder.hpp"
|
||||
@ -512,6 +513,11 @@ int main(void) {
|
||||
direction = baseband::Direction::Transmit;
|
||||
baseband_thread.baseband_processor = new JammerProcessor();
|
||||
break;
|
||||
|
||||
case 19:
|
||||
direction = baseband::Direction::Transmit;
|
||||
baseband_thread.baseband_processor = new XylosProcessor();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "proc_fsk_lcr.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "sine_table.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@ -76,7 +77,7 @@ void LCRFSKProcessor::execute(buffer_c8_t buffer) {
|
||||
s++;
|
||||
}
|
||||
|
||||
//sample = sine_table_f32[(aphase & 0x00FF0000)>>16];
|
||||
sample = (sine_table_f32[(aphase & 0x03FF0000)>>18]*255);
|
||||
|
||||
//FM
|
||||
frq = sample * shared_memory.afsk_fmmod;
|
||||
@ -84,8 +85,8 @@ void LCRFSKProcessor::execute(buffer_c8_t buffer) {
|
||||
phase = (phase + frq);
|
||||
sphase = phase + (256<<16);
|
||||
|
||||
//re = sine_table_f32[(sphase & 0x00FF0000)>>16];
|
||||
//im = sine_table_f32[(phase & 0x00FF0000)>>16];
|
||||
re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127);
|
||||
im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127);
|
||||
|
||||
buffer.p[i] = {(int8_t)re,(int8_t)im};
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ void JammerProcessor::execute(buffer_c8_t buffer) {
|
||||
if (ir > 15) ir = 0;
|
||||
if (shared_memory.jammer_ranges[ir].active == true) break;
|
||||
}
|
||||
jammer_bw = shared_memory.jammer_ranges[ir].width / 4;
|
||||
jammer_bw = shared_memory.jammer_ranges[ir].width / 2;
|
||||
|
||||
message.freq = shared_memory.jammer_ranges[ir].center;
|
||||
shared_memory.application_queue.push(message);
|
||||
@ -89,7 +89,7 @@ void JammerProcessor::execute(buffer_c8_t buffer) {
|
||||
}
|
||||
|
||||
aphase += 8830;
|
||||
sample = sine_table_f32[(aphase & 0x00FF0000)>>16];
|
||||
sample = sine_table_f32[(aphase & 0x03FF0000)>>18]*256;
|
||||
|
||||
//FM
|
||||
frq = sample * jammer_bw; // Bandwidth
|
||||
@ -97,8 +97,8 @@ void JammerProcessor::execute(buffer_c8_t buffer) {
|
||||
phase = (phase + frq);
|
||||
sphase = phase + (256<<16);
|
||||
|
||||
re = sine_table_f32[(sphase & 0x00FF0000)>>16];
|
||||
im = sine_table_f32[(phase & 0x00FF0000)>>16];
|
||||
re = sine_table_f32[(sphase & 0x03FF0000)>>18]*127;
|
||||
im = sine_table_f32[(phase & 0x03FF0000)>>18]*127;
|
||||
|
||||
buffer.p[i] = {(int8_t)re,(int8_t)im};
|
||||
}
|
||||
|
75
firmware/baseband-tx/proc_xylos.cpp
Normal file
75
firmware/baseband-tx/proc_xylos.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 "proc_xylos.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "sine_table.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
void XylosProcessor::execute(buffer_c8_t buffer) {
|
||||
|
||||
for (size_t i = 0; i<buffer.count; i++) {
|
||||
//Sample generation 2.28M/10 = 228kHz
|
||||
if (s >= 9) {
|
||||
s = 0;
|
||||
|
||||
if (sample_count >= CCIR_TONELENGTH) {
|
||||
if (shared_memory.xylos_transmit_done == false) {
|
||||
message.n = byte_pos; // Progress
|
||||
shared_memory.application_queue.push(message);
|
||||
digit = shared_memory.xylosdata[byte_pos++];
|
||||
}
|
||||
|
||||
if (!digit) {
|
||||
message.n = 25; // Done code
|
||||
shared_memory.xylos_transmit_done = true;
|
||||
shared_memory.application_queue.push(message);
|
||||
digit = 0;
|
||||
}
|
||||
|
||||
if (digit > '9') digit -= 7;
|
||||
digit -= 0x30;
|
||||
|
||||
sample_count = 0;
|
||||
} else {
|
||||
sample_count++;
|
||||
}
|
||||
|
||||
aphase += ccir_phases[digit];
|
||||
} else {
|
||||
s++;
|
||||
}
|
||||
|
||||
sample = (sine_table_f32[(aphase & 0x03FF0000)>>18]*255);
|
||||
|
||||
//FM
|
||||
frq = sample * 160; // 20kHz wide (?)
|
||||
|
||||
phase = (phase + frq);
|
||||
sphase = phase + (256<<16);
|
||||
|
||||
re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127);
|
||||
im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127);
|
||||
|
||||
buffer.p[i] = {(int8_t)re,(int8_t)im};
|
||||
}
|
||||
}
|
64
firmware/baseband-tx/proc_xylos.hpp
Normal file
64
firmware/baseband-tx/proc_xylos.hpp
Normal file
@ -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 __PROC_XYLOS_H__
|
||||
#define __PROC_XYLOS_H__
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
|
||||
#define CCIR_TONELENGTH 22800
|
||||
#define PHASEV 294.34
|
||||
|
||||
class XylosProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(buffer_c8_t buffer) override;
|
||||
|
||||
private:
|
||||
uint32_t ccir_phases[16] = {
|
||||
1981*PHASEV,
|
||||
1124*PHASEV,
|
||||
1197*PHASEV,
|
||||
1275*PHASEV,
|
||||
1358*PHASEV,
|
||||
1446*PHASEV,
|
||||
1540*PHASEV,
|
||||
1640*PHASEV,
|
||||
1747*PHASEV,
|
||||
1860*PHASEV,
|
||||
2400*PHASEV,
|
||||
930*PHASEV,
|
||||
2247*PHASEV,
|
||||
991*PHASEV,
|
||||
2110*PHASEV,
|
||||
1055*PHASEV
|
||||
};
|
||||
|
||||
int8_t re, im;
|
||||
uint8_t s;
|
||||
uint8_t byte_pos = 0;
|
||||
uint8_t digit = 0;
|
||||
uint32_t sample_count = CCIR_TONELENGTH;
|
||||
uint32_t aphase, phase, sphase;
|
||||
int32_t sample, frq;
|
||||
TXDoneMessage message;
|
||||
};
|
||||
|
||||
#endif
|
Binary file not shown.
@ -140,6 +140,8 @@ CPPSRC = main.cpp \
|
||||
proc_ais.cpp \
|
||||
proc_wideband_spectrum.cpp \
|
||||
proc_tpms.cpp \
|
||||
proc_afskrx.cpp \
|
||||
proc_sigfrx.cpp \
|
||||
dsp_squelch.cpp \
|
||||
clock_recovery.cpp \
|
||||
packet_builder.cpp \
|
||||
|
@ -180,6 +180,79 @@ constexpr fir_taps_real<64> taps_64_lp_130_169_tfilter {
|
||||
} },
|
||||
};
|
||||
|
||||
// 41kHz/70kHz @ 192kHz
|
||||
// http://t-filter.appspot.com
|
||||
constexpr fir_taps_real<64> taps_64_lp_410_700_tfilter {
|
||||
.pass_frequency_normalized = 0.213f,
|
||||
.stop_frequency_normalized = 0.364f,
|
||||
.taps = { {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
3,
|
||||
-3,
|
||||
-7,
|
||||
12,
|
||||
10,
|
||||
-35,
|
||||
-3,
|
||||
79,
|
||||
-37,
|
||||
-138,
|
||||
146,
|
||||
180,
|
||||
-361,
|
||||
-126,
|
||||
688,
|
||||
-149,
|
||||
-1062,
|
||||
800,
|
||||
1308,
|
||||
-1991,
|
||||
-1092,
|
||||
3963,
|
||||
-286,
|
||||
-7710,
|
||||
6211,
|
||||
32368,
|
||||
32368,
|
||||
6211,
|
||||
-7710,
|
||||
-286,
|
||||
3963,
|
||||
-1092,
|
||||
-1991,
|
||||
1308,
|
||||
800,
|
||||
-1062,
|
||||
-149,
|
||||
688,
|
||||
-126,
|
||||
-361,
|
||||
180,
|
||||
146,
|
||||
-138,
|
||||
-37,
|
||||
79,
|
||||
-3,
|
||||
-35,
|
||||
10,
|
||||
12,
|
||||
-7,
|
||||
-3,
|
||||
3,
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
} },
|
||||
};
|
||||
|
||||
/* Wideband audio filter */
|
||||
/* 96kHz int16_t input
|
||||
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop
|
||||
|
@ -57,9 +57,11 @@
|
||||
#include "proc_am_audio.hpp"
|
||||
#include "proc_nfm_audio.hpp"
|
||||
#include "proc_wfm_audio.hpp"
|
||||
#include "proc_ais.hpp"
|
||||
//#include "proc_ais.hpp"
|
||||
#include "proc_wideband_spectrum.hpp"
|
||||
#include "proc_tpms.hpp"
|
||||
//#include "proc_tpms.hpp"
|
||||
#include "proc_afskrx.hpp"
|
||||
#include "proc_sigfrx.hpp"
|
||||
|
||||
#include "clock_recovery.hpp"
|
||||
#include "packet_builder.hpp"
|
||||
@ -356,7 +358,7 @@ void ram_loop_fn(void) {
|
||||
void wait_for_switch(void) {
|
||||
memcpy(&ram_loop[0], reinterpret_cast<char*>(&ram_loop_fn), 32);
|
||||
loop_ptr = reinterpret_cast<fn_ptr>(&ram_loop[0]);
|
||||
ReadyForSwitchMessage message { true };
|
||||
ReadyForSwitchMessage message;
|
||||
shared_memory.application_queue.push(message);
|
||||
(*loop_ptr)();
|
||||
return;
|
||||
@ -402,19 +404,29 @@ int main(void) {
|
||||
baseband_thread.baseband_processor = new WidebandFMAudio();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/*case 3:
|
||||
direction = baseband::Direction::Receive;
|
||||
baseband_thread.baseband_processor = new AISProcessor();
|
||||
break;
|
||||
break;*/
|
||||
|
||||
case 4:
|
||||
direction = baseband::Direction::Receive;
|
||||
baseband_thread.baseband_processor = new WidebandSpectrum();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
/*case 5:
|
||||
direction = baseband::Direction::Receive;
|
||||
baseband_thread.baseband_processor = new TPMSProcessor();
|
||||
break;*/
|
||||
|
||||
case 6:
|
||||
direction = baseband::Direction::Receive;
|
||||
baseband_thread.baseband_processor = new AFSKRXProcessor();
|
||||
break;
|
||||
|
||||
case 7:
|
||||
direction = baseband::Direction::Receive;
|
||||
baseband_thread.baseband_processor = new SIGFRXProcessor();
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
|
122
firmware/baseband/proc_afskrx.cpp
Normal file
122
firmware/baseband/proc_afskrx.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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_afskrx.hpp"
|
||||
#include "sine_table.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
|
||||
using namespace lpc43xx;
|
||||
|
||||
void AFSKRXProcessor::execute(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
|
||||
};
|
||||
|
||||
/* 96kHz complex<int16_t>[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 buffer_s16_t work_audio_buffer {
|
||||
(int16_t*)decimator_out.p,
|
||||
sizeof(*decimator_out.p) * decimator_out.count
|
||||
};
|
||||
|
||||
/* 48kHz complex<int16_t>[32]
|
||||
* -> FM demodulation
|
||||
* -> 48kHz int16_t[32] */
|
||||
auto audio = demod.execute(channel, 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);
|
||||
*/
|
||||
//if( !audio_present ) {
|
||||
// Zero audio buffer.
|
||||
/*for(size_t i=0; i<audio.count; i++) {
|
||||
if ((i % 3) > 1)
|
||||
audio.p[i] = 4096;
|
||||
else
|
||||
audio.p[i] = -4096;
|
||||
}*/
|
||||
//}
|
||||
|
||||
audio_hpf.execute_in_place(audio);
|
||||
|
||||
for(size_t i=0; i<audio.count; i++) {
|
||||
if (spur > 10) {
|
||||
if (audio.p[i] > 2000)
|
||||
sign = 1;
|
||||
if (audio.p[i] < -2000)
|
||||
sign = 0;
|
||||
spur = 0;
|
||||
} else {
|
||||
spur++;
|
||||
}
|
||||
if (sign != prev_sign) {
|
||||
if (freq_timer < 15) // 48
|
||||
bit = 0;
|
||||
else
|
||||
bit++;
|
||||
freq_timer = 0;
|
||||
}
|
||||
prev_sign = sign;
|
||||
if (freq_timer < 1000) freq_timer++; // TODO: Limit in a more intelligent way
|
||||
}
|
||||
|
||||
if (bit_timer >= 40) {
|
||||
bit_timer = 0;
|
||||
// Check bit state here !
|
||||
} else {
|
||||
bit_timer++;
|
||||
}
|
||||
|
||||
if (sc >= 600) {
|
||||
sc = 0;
|
||||
AFSKDataMessage message;
|
||||
memcpy(message.data,aud,128*2);
|
||||
shared_memory.application_queue.push(message);
|
||||
audc = 0;
|
||||
} else {
|
||||
sc++;
|
||||
}
|
||||
|
||||
if (audc < 4) {
|
||||
memcpy(aud+(audc*32),audio.p,32*2);
|
||||
audc++;
|
||||
}
|
||||
|
||||
fill_audio_buffer(audio);
|
||||
}
|
||||
|
||||
void AFSKRXProcessor::data_handler(
|
||||
const double data
|
||||
) {
|
||||
/*AFSKDataMessage message;
|
||||
message.data = 'T';
|
||||
shared_memory.application_queue.push(message);*/
|
||||
}
|
68
firmware/baseband/proc_afskrx.hpp
Normal file
68
firmware/baseband/proc_afskrx.hpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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_AFSKRX_H__
|
||||
#define __PROC_AFSKRX_H__
|
||||
|
||||
#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 <cstdint>
|
||||
#include <cstddef>
|
||||
#include <bitset>
|
||||
|
||||
class AFSKRXProcessor : public BasebandProcessor {
|
||||
public:
|
||||
AFSKRXProcessor() {
|
||||
decimator.set_decimation_factor(ChannelDecimator::DecimationFactor::By32);
|
||||
channel_filter.configure(channel_filter_taps.taps, 2);
|
||||
}
|
||||
|
||||
void execute(buffer_c8_t buffer) override;
|
||||
|
||||
private:
|
||||
ChannelDecimator decimator;
|
||||
const fir_taps_real<64>& channel_filter_taps = taps_64_lp_042_078_tfilter;
|
||||
dsp::decimate::FIRAndDecimateComplex channel_filter;
|
||||
dsp::demodulate::FM demod { 48000, 5000 };
|
||||
|
||||
IIRBiquadFilter audio_hpf { audio_hpf_config };
|
||||
//FMSquelch squelch;
|
||||
|
||||
uint16_t bit_timer = 0, freq_timer = 0;
|
||||
uint16_t sc;
|
||||
uint8_t audc, spur, sign, prev_sign, bit = 0;
|
||||
|
||||
int16_t aud[128];
|
||||
|
||||
void data_handler(const double data);
|
||||
};
|
||||
|
||||
#endif/*__PROC_TPMS_H__*/
|
@ -246,6 +246,70 @@ void ILI9341::render_line(const ui::Point p, const uint8_t count, const ui::Colo
|
||||
io.lcd_write_pixels(line_buffer, count);
|
||||
}
|
||||
|
||||
void ILI9341::drawBMP(const ui::Point p, const uint8_t * bitmap) {
|
||||
uint32_t pixel_data, pal_data;
|
||||
uint8_t pal, by, c, count;
|
||||
ui::Color linebuffer[240];
|
||||
ui::Coord px = 0, py;
|
||||
ui::Color palette[16];
|
||||
uint32_t bmpwidth, bmpheight;
|
||||
|
||||
// RLE_4 BMP loader with hardcoded size and no delta :(
|
||||
|
||||
if (bitmap[0x1E] != 2) return; // Bad compression type
|
||||
bmpwidth = static_cast<int32_t>(
|
||||
(bitmap[0x12]) |
|
||||
(bitmap[0x13] << 8) |
|
||||
(bitmap[0x14] << 16)|
|
||||
(bitmap[0x15] << 24) );
|
||||
bmpheight = static_cast<int32_t>(
|
||||
(bitmap[0x16]) |
|
||||
(bitmap[0x17] << 8) |
|
||||
(bitmap[0x18] << 16)|
|
||||
(bitmap[0x19] << 24) );
|
||||
|
||||
pal_data = bitmap[0x0E] + 0x0E;
|
||||
|
||||
pixel_data = bitmap[0x0A];
|
||||
pal = 0;
|
||||
for (c = 0; c < (16*4); c+=4) {
|
||||
palette[pal++] = ui::Color(bitmap[c+2+pal_data], bitmap[c+1+pal_data], bitmap[c+pal_data]);
|
||||
}
|
||||
|
||||
py = bmpheight + 16;
|
||||
do {
|
||||
by = bitmap[pixel_data++];
|
||||
if (by) {
|
||||
count = by;
|
||||
by = bitmap[pixel_data++];
|
||||
for (c = 0; c < count; c+=2) {
|
||||
linebuffer[px++] = palette[by >> 4];
|
||||
if (px < bmpwidth) linebuffer[px++] = palette[by & 15];
|
||||
}
|
||||
if (pixel_data & 1) pixel_data++;
|
||||
} else {
|
||||
by = bitmap[pixel_data++];
|
||||
if (by == 0) {
|
||||
render_line({p.x, p.y + py}, bmpwidth, linebuffer);
|
||||
py--;
|
||||
px = 0;
|
||||
} else if (by == 1) {
|
||||
break;
|
||||
} else if (by == 2) {
|
||||
// Delta
|
||||
} else {
|
||||
count = by;
|
||||
for (c = 0; c < count; c+=2) {
|
||||
by = bitmap[pixel_data++];
|
||||
linebuffer[px++] = palette[by >> 4];
|
||||
if (px < bmpwidth) linebuffer[px++] = palette[by & 15];
|
||||
}
|
||||
if (pixel_data & 1) pixel_data++;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
void ILI9341::draw_line(const ui::Point start, const ui::Point end, const ui::Color color) {
|
||||
int x0 = start.x;
|
||||
int y0 = start.y;
|
||||
|
@ -54,6 +54,7 @@ public:
|
||||
);
|
||||
|
||||
void draw_pixel(const ui::Point p, const ui::Color color);
|
||||
void drawBMP(const ui::Point p, const uint8_t * bitmap);
|
||||
void render_line(const ui::Point p, const uint8_t count, const ui::Color* line_buffer);
|
||||
|
||||
template<size_t N>
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
SDCardStatus = 10,
|
||||
Retune = 11,
|
||||
ReadyForSwitch = 12,
|
||||
AFSKData = 13,
|
||||
MAX
|
||||
};
|
||||
|
||||
@ -236,6 +237,16 @@ public:
|
||||
TPMSPacket packet;
|
||||
};
|
||||
|
||||
class AFSKDataMessage : public Message {
|
||||
public:
|
||||
constexpr AFSKDataMessage(
|
||||
) : Message { ID::AFSKData }
|
||||
{
|
||||
}
|
||||
|
||||
int16_t data[128] = {0};
|
||||
};
|
||||
|
||||
class ShutdownMessage : public Message {
|
||||
public:
|
||||
constexpr ShutdownMessage(
|
||||
@ -269,12 +280,9 @@ public:
|
||||
class ReadyForSwitchMessage : public Message {
|
||||
public:
|
||||
ReadyForSwitchMessage(
|
||||
bool ok
|
||||
) : Message { ID::ReadyForSwitch }
|
||||
{
|
||||
}
|
||||
|
||||
const bool ok = false;
|
||||
};
|
||||
|
||||
class RetuneMessage : public Message {
|
||||
|
@ -59,6 +59,9 @@ struct SharedMemory {
|
||||
bool afsk_transmit_done;
|
||||
|
||||
JammerRange jammer_ranges[16];
|
||||
|
||||
char xylosdata[21];
|
||||
bool xylos_transmit_done;
|
||||
};
|
||||
|
||||
extern SharedMemory& shared_memory;
|
||||
|
@ -433,7 +433,6 @@ bool Checkbox::on_key(const KeyEvent key) {
|
||||
|
||||
if( on_select ) {
|
||||
on_select(*this);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user