mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-06-19 20:34:25 -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
28 changed files with 2272 additions and 1143 deletions
|
@ -172,6 +172,9 @@ CPPSRC = main.cpp \
|
||||||
ui_receiver.cpp \
|
ui_receiver.cpp \
|
||||||
ui_spectrum.cpp \
|
ui_spectrum.cpp \
|
||||||
ui_loadmodule.cpp \
|
ui_loadmodule.cpp \
|
||||||
|
ui_afskrx.cpp \
|
||||||
|
ui_sigfrx.cpp \
|
||||||
|
ui_xylos.cpp \
|
||||||
receiver_model.cpp \
|
receiver_model.cpp \
|
||||||
transmitter_model.cpp \
|
transmitter_model.cpp \
|
||||||
spectrum_color_lut.cpp \
|
spectrum_color_lut.cpp \
|
||||||
|
|
|
@ -19,8 +19,13 @@
|
||||||
* Boston, MA 02110-1301, USA.
|
* 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: 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: LCD backlight PWM
|
||||||
//TODO: BUG: Crash after TX stop
|
//TODO: BUG: Crash after TX stop
|
||||||
//TODO: Check bw setting in LCR TX
|
//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[16] = {0xce,0x87,0x2b,0x2c,0x9e,0x74,0xe8,0x1c,0x1c,0xe9,0xfc,0xc2,0x40,0xc3,0x32,0xd5,};
|
||||||
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_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();
|
make_frame();
|
||||||
|
|
||||||
shared_memory.afsk_samples_per_bit = 228000/portapack::persistent_memory::afsk_bitrate();
|
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_mark = portapack::persistent_memory::afsk_mark_freq()*(0x40000*256)/2280;
|
||||||
shared_memory.afsk_phase_inc_space = portapack::persistent_memory::afsk_space_freq()*(0x10000*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;
|
shared_memory.afsk_fmmod = portapack::persistent_memory::afsk_bw() * 8;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
#include "ui_whistle.hpp"
|
#include "ui_whistle.hpp"
|
||||||
#include "ui_jammer.hpp"
|
#include "ui_jammer.hpp"
|
||||||
#include "ui_loadmodule.hpp"
|
#include "ui_loadmodule.hpp"
|
||||||
|
#include "ui_afskrx.hpp"
|
||||||
|
#include "ui_xylos.hpp"
|
||||||
|
#include "ui_sigfrx.hpp"
|
||||||
|
|
||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
#include "m4_startup.hpp"
|
#include "m4_startup.hpp"
|
||||||
|
@ -108,16 +111,19 @@ void NavigationView::focus() {
|
||||||
/* SystemMenuView ********************************************************/
|
/* SystemMenuView ********************************************************/
|
||||||
|
|
||||||
SystemMenuView::SystemMenuView(NavigationView& nav) {
|
SystemMenuView::SystemMenuView(NavigationView& nav) {
|
||||||
add_items<11>({ {
|
add_items<10>({ {
|
||||||
{ "Play dead", ui::Color::red(), [&nav](){ nav.push(new PlayDeadView { nav, false }); } },
|
{ "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 }); } },
|
//{ "Nordic/BTLE RX", ui::Color::cyan(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||||
{ "Jammer", ui::Color::white(), [&nav](){ nav.push(new JammerView { nav, transmitter_model }); } },
|
{ "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 }); } },
|
//{ "Encoder TX", ui::Color::green(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||||
{ "Whistle", ui::Color::purple(), [&nav](){ nav.push(new WhistleView { nav, transmitter_model }); } },
|
{ "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 }); } },
|
//{ "SIGFOX RX", ui::Color::orange(), [&nav](){ nav.push(new SIGFRXView { nav, receiver_model }); } },
|
||||||
{ "TEDI/LCR TX", ui::Color::orange(), [&nav](){ nav.push(new LCRView { nav, transmitter_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 }); } },
|
{ "Setup", ui::Color::white(), [&nav](){ nav.push(new SetupMenuView { nav }); } },
|
||||||
{ "About", ui::Color::white(), [&nav](){ nav.push(new AboutView { nav }); } },
|
{ "About", ui::Color::white(), [&nav](){ nav.push(new AboutView { nav }); } },
|
||||||
{ "Debug", ui::Color::white(), [&nav](){ nav.push(new DebugMenuView { nav }); } },
|
{ "Debug", ui::Color::white(), [&nav](){ nav.push(new DebugMenuView { nav }); } },
|
||||||
|
@ -161,6 +167,8 @@ SystemView::SystemView(
|
||||||
//if (persistent_memory::playing_dead() == 0x59)
|
//if (persistent_memory::playing_dead() == 0x59)
|
||||||
// navigation_view.push(new PlayDeadView { navigation_view, true });
|
// navigation_view.push(new PlayDeadView { navigation_view, true });
|
||||||
//else
|
//else
|
||||||
|
// navigation_view.push(new BMPView { navigation_view });
|
||||||
|
|
||||||
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) {
|
void BMPView::paint(Painter& painter) {
|
||||||
uint32_t pixel_data;
|
portapack::display.drawBMP({(240-185)/2, 0}, splash_bmp);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PlayDeadView **********************************************************/
|
/* 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 \
|
matched_filter.cpp \
|
||||||
proc_jammer.cpp \
|
proc_jammer.cpp \
|
||||||
proc_fsk_lcr.cpp \
|
proc_fsk_lcr.cpp \
|
||||||
|
proc_xylos.cpp \
|
||||||
dsp_squelch.cpp \
|
dsp_squelch.cpp \
|
||||||
clock_recovery.cpp \
|
clock_recovery.cpp \
|
||||||
packet_builder.cpp \
|
packet_builder.cpp \
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "baseband_processor.hpp"
|
#include "baseband_processor.hpp"
|
||||||
#include "proc_fsk_lcr.hpp"
|
#include "proc_fsk_lcr.hpp"
|
||||||
#include "proc_jammer.hpp"
|
#include "proc_jammer.hpp"
|
||||||
|
#include "proc_xylos.hpp"
|
||||||
|
|
||||||
#include "clock_recovery.hpp"
|
#include "clock_recovery.hpp"
|
||||||
#include "packet_builder.hpp"
|
#include "packet_builder.hpp"
|
||||||
|
@ -512,6 +513,11 @@ int main(void) {
|
||||||
direction = baseband::Direction::Transmit;
|
direction = baseband::Direction::Transmit;
|
||||||
baseband_thread.baseband_processor = new JammerProcessor();
|
baseband_thread.baseband_processor = new JammerProcessor();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 19:
|
||||||
|
direction = baseband::Direction::Transmit;
|
||||||
|
baseband_thread.baseband_processor = new XylosProcessor();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "proc_fsk_lcr.hpp"
|
#include "proc_fsk_lcr.hpp"
|
||||||
#include "portapack_shared_memory.hpp"
|
#include "portapack_shared_memory.hpp"
|
||||||
|
#include "sine_table.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ void LCRFSKProcessor::execute(buffer_c8_t buffer) {
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//sample = sine_table_f32[(aphase & 0x00FF0000)>>16];
|
sample = (sine_table_f32[(aphase & 0x03FF0000)>>18]*255);
|
||||||
|
|
||||||
//FM
|
//FM
|
||||||
frq = sample * shared_memory.afsk_fmmod;
|
frq = sample * shared_memory.afsk_fmmod;
|
||||||
|
@ -84,8 +85,8 @@ void LCRFSKProcessor::execute(buffer_c8_t buffer) {
|
||||||
phase = (phase + frq);
|
phase = (phase + frq);
|
||||||
sphase = phase + (256<<16);
|
sphase = phase + (256<<16);
|
||||||
|
|
||||||
//re = sine_table_f32[(sphase & 0x00FF0000)>>16];
|
re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127);
|
||||||
//im = sine_table_f32[(phase & 0x00FF0000)>>16];
|
im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127);
|
||||||
|
|
||||||
buffer.p[i] = {(int8_t)re,(int8_t)im};
|
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 (ir > 15) ir = 0;
|
||||||
if (shared_memory.jammer_ranges[ir].active == true) break;
|
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;
|
message.freq = shared_memory.jammer_ranges[ir].center;
|
||||||
shared_memory.application_queue.push(message);
|
shared_memory.application_queue.push(message);
|
||||||
|
@ -89,7 +89,7 @@ void JammerProcessor::execute(buffer_c8_t buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
aphase += 8830;
|
aphase += 8830;
|
||||||
sample = sine_table_f32[(aphase & 0x00FF0000)>>16];
|
sample = sine_table_f32[(aphase & 0x03FF0000)>>18]*256;
|
||||||
|
|
||||||
//FM
|
//FM
|
||||||
frq = sample * jammer_bw; // Bandwidth
|
frq = sample * jammer_bw; // Bandwidth
|
||||||
|
@ -97,8 +97,8 @@ void JammerProcessor::execute(buffer_c8_t buffer) {
|
||||||
phase = (phase + frq);
|
phase = (phase + frq);
|
||||||
sphase = phase + (256<<16);
|
sphase = phase + (256<<16);
|
||||||
|
|
||||||
re = sine_table_f32[(sphase & 0x00FF0000)>>16];
|
re = sine_table_f32[(sphase & 0x03FF0000)>>18]*127;
|
||||||
im = sine_table_f32[(phase & 0x00FF0000)>>16];
|
im = sine_table_f32[(phase & 0x03FF0000)>>18]*127;
|
||||||
|
|
||||||
buffer.p[i] = {(int8_t)re,(int8_t)im};
|
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_ais.cpp \
|
||||||
proc_wideband_spectrum.cpp \
|
proc_wideband_spectrum.cpp \
|
||||||
proc_tpms.cpp \
|
proc_tpms.cpp \
|
||||||
|
proc_afskrx.cpp \
|
||||||
|
proc_sigfrx.cpp \
|
||||||
dsp_squelch.cpp \
|
dsp_squelch.cpp \
|
||||||
clock_recovery.cpp \
|
clock_recovery.cpp \
|
||||||
packet_builder.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 */
|
/* Wideband audio filter */
|
||||||
/* 96kHz int16_t input
|
/* 96kHz int16_t input
|
||||||
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop
|
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop
|
||||||
|
|
|
@ -57,9 +57,11 @@
|
||||||
#include "proc_am_audio.hpp"
|
#include "proc_am_audio.hpp"
|
||||||
#include "proc_nfm_audio.hpp"
|
#include "proc_nfm_audio.hpp"
|
||||||
#include "proc_wfm_audio.hpp"
|
#include "proc_wfm_audio.hpp"
|
||||||
#include "proc_ais.hpp"
|
//#include "proc_ais.hpp"
|
||||||
#include "proc_wideband_spectrum.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 "clock_recovery.hpp"
|
||||||
#include "packet_builder.hpp"
|
#include "packet_builder.hpp"
|
||||||
|
@ -356,7 +358,7 @@ void ram_loop_fn(void) {
|
||||||
void wait_for_switch(void) {
|
void wait_for_switch(void) {
|
||||||
memcpy(&ram_loop[0], reinterpret_cast<char*>(&ram_loop_fn), 32);
|
memcpy(&ram_loop[0], reinterpret_cast<char*>(&ram_loop_fn), 32);
|
||||||
loop_ptr = reinterpret_cast<fn_ptr>(&ram_loop[0]);
|
loop_ptr = reinterpret_cast<fn_ptr>(&ram_loop[0]);
|
||||||
ReadyForSwitchMessage message { true };
|
ReadyForSwitchMessage message;
|
||||||
shared_memory.application_queue.push(message);
|
shared_memory.application_queue.push(message);
|
||||||
(*loop_ptr)();
|
(*loop_ptr)();
|
||||||
return;
|
return;
|
||||||
|
@ -402,19 +404,29 @@ int main(void) {
|
||||||
baseband_thread.baseband_processor = new WidebandFMAudio();
|
baseband_thread.baseband_processor = new WidebandFMAudio();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
/*case 3:
|
||||||
direction = baseband::Direction::Receive;
|
direction = baseband::Direction::Receive;
|
||||||
baseband_thread.baseband_processor = new AISProcessor();
|
baseband_thread.baseband_processor = new AISProcessor();
|
||||||
break;
|
break;*/
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
direction = baseband::Direction::Receive;
|
direction = baseband::Direction::Receive;
|
||||||
baseband_thread.baseband_processor = new WidebandSpectrum();
|
baseband_thread.baseband_processor = new WidebandSpectrum();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
/*case 5:
|
||||||
direction = baseband::Direction::Receive;
|
direction = baseband::Direction::Receive;
|
||||||
baseband_thread.baseband_processor = new TPMSProcessor();
|
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;
|
break;
|
||||||
|
|
||||||
case 0xFF:
|
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);
|
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) {
|
void ILI9341::draw_line(const ui::Point start, const ui::Point end, const ui::Color color) {
|
||||||
int x0 = start.x;
|
int x0 = start.x;
|
||||||
int y0 = start.y;
|
int y0 = start.y;
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
);
|
);
|
||||||
|
|
||||||
void draw_pixel(const ui::Point p, const ui::Color color);
|
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);
|
void render_line(const ui::Point p, const uint8_t count, const ui::Color* line_buffer);
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
SDCardStatus = 10,
|
SDCardStatus = 10,
|
||||||
Retune = 11,
|
Retune = 11,
|
||||||
ReadyForSwitch = 12,
|
ReadyForSwitch = 12,
|
||||||
|
AFSKData = 13,
|
||||||
MAX
|
MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -236,6 +237,16 @@ public:
|
||||||
TPMSPacket packet;
|
TPMSPacket packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AFSKDataMessage : public Message {
|
||||||
|
public:
|
||||||
|
constexpr AFSKDataMessage(
|
||||||
|
) : Message { ID::AFSKData }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t data[128] = {0};
|
||||||
|
};
|
||||||
|
|
||||||
class ShutdownMessage : public Message {
|
class ShutdownMessage : public Message {
|
||||||
public:
|
public:
|
||||||
constexpr ShutdownMessage(
|
constexpr ShutdownMessage(
|
||||||
|
@ -269,12 +280,9 @@ public:
|
||||||
class ReadyForSwitchMessage : public Message {
|
class ReadyForSwitchMessage : public Message {
|
||||||
public:
|
public:
|
||||||
ReadyForSwitchMessage(
|
ReadyForSwitchMessage(
|
||||||
bool ok
|
|
||||||
) : Message { ID::ReadyForSwitch }
|
) : Message { ID::ReadyForSwitch }
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool ok = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RetuneMessage : public Message {
|
class RetuneMessage : public Message {
|
||||||
|
|
|
@ -59,6 +59,9 @@ struct SharedMemory {
|
||||||
bool afsk_transmit_done;
|
bool afsk_transmit_done;
|
||||||
|
|
||||||
JammerRange jammer_ranges[16];
|
JammerRange jammer_ranges[16];
|
||||||
|
|
||||||
|
char xylosdata[21];
|
||||||
|
bool xylos_transmit_done;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SharedMemory& shared_memory;
|
extern SharedMemory& shared_memory;
|
||||||
|
|
|
@ -433,7 +433,6 @@ bool Checkbox::on_key(const KeyEvent key) {
|
||||||
|
|
||||||
if( on_select ) {
|
if( on_select ) {
|
||||||
on_select(*this);
|
on_select(*this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue