mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-24 06:49:24 -05:00
Play dead actually works, fixed 7bit AFSK, AFSK repeat, started whistle mode
This commit is contained in:
parent
07754727ed
commit
9a7657fb38
@ -112,7 +112,8 @@ CSRC = $(PORTSRC) \
|
||||
$(HALSRC) \
|
||||
$(PLATFORMSRC) \
|
||||
$(BOARDSRC) \
|
||||
$(FATFSSRC)
|
||||
$(FATFSSRC) \
|
||||
$(CHIBIOS)/os/various/evtimer.c
|
||||
|
||||
|
||||
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
|
||||
@ -162,6 +163,7 @@ CPPSRC = main.cpp \
|
||||
ui_debug.cpp \
|
||||
ui_rds.cpp \
|
||||
ui_lcr.cpp \
|
||||
ui_whistle.cpp \
|
||||
ui_afsksetup.cpp \
|
||||
ui_console.cpp \
|
||||
ui_receiver.cpp \
|
||||
|
@ -33,6 +33,10 @@ void m4txevent_interrupt_enable() {
|
||||
nvicEnableVector(M4CORE_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_M4TXEVENT_IRQ_PRIORITY));
|
||||
}
|
||||
|
||||
void m4txevent_interrupt_disable() {
|
||||
nvicDisableVector(M4CORE_IRQn);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
CH_IRQ_HANDLER(M4Core_IRQHandler) {
|
||||
|
@ -33,6 +33,8 @@
|
||||
* cause an exception and effectively halt the M4. But that feels gross.
|
||||
*/
|
||||
void m4_init(const portapack::spi_flash::region_t from, void* const to) {
|
||||
//m4txevent_interrupt_disable();
|
||||
|
||||
/* Initialize M4 code RAM */
|
||||
std::memcpy(to, from.base_address(), from.size);
|
||||
|
||||
|
@ -19,6 +19,26 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
//Reims ANFR 822519
|
||||
//TODO: UC/LC update buttons in keyboard view
|
||||
//TODO: Dynamically load baseband code depending on mode (disable M4 & interrupts, load, reset)
|
||||
//TODO: Bodet :)
|
||||
//TODO: Whistler
|
||||
//TODO: Setup: Play dead by default ? Enable/disable ?
|
||||
//TODO: Hide statusview when playing dead
|
||||
//TODO: Persistent playdead !
|
||||
//TODO: LCR EC=A,J,N
|
||||
//TODO: LCR full message former (see norm)
|
||||
//TODO: See if receive still works
|
||||
//TODO: LCR repeats
|
||||
//TODO: LCR shared memory semaphore for doing/done
|
||||
//TODO: LCR address scan
|
||||
//TODO: LCR text showing status in LCRView
|
||||
//TODO: AFSK NRZI
|
||||
//TODO: AFSK volume
|
||||
//TODO: AFSK channel bandwidth
|
||||
//TODO: TX power
|
||||
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
@ -506,15 +526,15 @@ int main(void) {
|
||||
};
|
||||
ui::Painter painter;
|
||||
|
||||
context.message_map[Message::ID::FSKPacket] = [](const Message* const p) {
|
||||
const auto message = static_cast<const FSKPacketMessage*>(p);
|
||||
(void)message;
|
||||
};
|
||||
context.message_map[Message::ID::FSKPacket] = [](const Message* const p) {
|
||||
const auto message = static_cast<const FSKPacketMessage*>(p);
|
||||
(void)message;
|
||||
};
|
||||
|
||||
context.message_map[Message::ID::TXDone] = [](const Message* const p) {
|
||||
const auto message = static_cast<const TXDoneMessage*>(p);
|
||||
(void)message;
|
||||
};
|
||||
context.message_map[Message::ID::TXDone] = [](const Message* const p) {
|
||||
const auto message = static_cast<const TXDoneMessage*>(p);
|
||||
(void)message;
|
||||
};
|
||||
|
||||
EventDispatcher event_dispatcher { &system_view, painter, context };
|
||||
|
||||
|
@ -249,7 +249,7 @@ char hexify(char in) {
|
||||
return in + 0x30;
|
||||
}
|
||||
|
||||
DebugLCRView::DebugLCRView(NavigationView& nav, char* lcrstring, uint8_t checksum) {
|
||||
DebugLCRView::DebugLCRView(NavigationView& nav, char * lcrstring, uint8_t checksum) {
|
||||
char cstr[15] = "Checksum: 0x ";
|
||||
|
||||
add_children({ {
|
||||
@ -265,10 +265,10 @@ DebugLCRView::DebugLCRView(NavigationView& nav, char* lcrstring, uint8_t checksu
|
||||
std::string b = std::string(lcrstring);
|
||||
|
||||
text_lcr1.set(b.substr(8+(0*26),26));
|
||||
if (strlen(b > 34)) text_lcr2.set(b.substr(8+(1*26),26));
|
||||
if (strlen(b > 34+26)) text_lcr3.set(b.substr(8+(2*26),26));
|
||||
if (strlen(b > 34+26+26)) text_lcr4.set(b.substr(8+(3*26),26));
|
||||
if (strlen(b > 34+26+26+26)) text_lcr5.set(b.substr(8+(4*26),26));
|
||||
if (strlen(lcrstring) > 34) text_lcr2.set(b.substr(8+(1*26),26));
|
||||
if (strlen(lcrstring) > 34+26) text_lcr3.set(b.substr(8+(2*26),26));
|
||||
if (strlen(lcrstring) > 34+26+26) text_lcr4.set(b.substr(8+(3*26),26));
|
||||
if (strlen(lcrstring) > 34+26+26+26) text_lcr5.set(b.substr(8+(4*26),26));
|
||||
|
||||
cstr[12] = hexify(checksum >> 4);
|
||||
cstr[13] = hexify(checksum & 15);
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "rffc507x.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
char hexify(char in);
|
||||
|
||||
class BasebandStatsView : public View {
|
||||
public:
|
||||
|
@ -39,12 +39,6 @@
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
|
||||
//TODO: Repeats
|
||||
//TODO: Shared memory semaphore for doing/done
|
||||
//TODO: Scan
|
||||
//TODO: Text showing status in LCRView
|
||||
//TODO: Checkboxes for AMs
|
||||
|
||||
using namespace hackrf::one;
|
||||
|
||||
namespace ui {
|
||||
@ -107,7 +101,7 @@ void LCRView::make_frame() {
|
||||
strcat(lcrframe, litteral[4]);
|
||||
strcat(lcrframe, "\" CL=0 ");
|
||||
}
|
||||
strcat(lcrframe, "EC=A SAB=0"); //TODO: EC=A,J,N
|
||||
strcat(lcrframe, "EC=A SAB=0");
|
||||
|
||||
memcpy(lcrstring, lcrframe, 256);
|
||||
|
||||
@ -124,12 +118,12 @@ void LCRView::make_frame() {
|
||||
|
||||
strcat(lcrframe, eom);
|
||||
|
||||
if (persistent_memory::afsk_config() & 2)
|
||||
//if (persistent_memory::afsk_config() & 2)
|
||||
pm = 0; // Even parity
|
||||
else
|
||||
pm = 1; // Odd parity
|
||||
//else
|
||||
// pm = 1; // Odd parity
|
||||
|
||||
if (persistent_memory::afsk_config() & 1) {
|
||||
//if (persistent_memory::afsk_config() & 1) {
|
||||
// LSB first
|
||||
for (dp=0;dp<strlen(lcrframe);dp++) {
|
||||
pp = pm;
|
||||
@ -137,15 +131,11 @@ void LCRView::make_frame() {
|
||||
cur_byte = lcrframe[dp];
|
||||
for (cp=0;cp<7;cp++) {
|
||||
if ((cur_byte>>cp)&1) pp++;
|
||||
new_byte |= ((cur_byte>>cp)&1)<<(6-cp);
|
||||
new_byte |= (((cur_byte>>cp)&1)<<(7-cp));
|
||||
}
|
||||
// 8/7 bit
|
||||
if (persistent_memory::afsk_config() & 4)
|
||||
lcrframe_f[dp] = new_byte;
|
||||
else
|
||||
lcrframe_f[dp] = (new_byte<<1)|(pp&1);
|
||||
lcrframe_f[dp] = new_byte|(pp&1);
|
||||
}
|
||||
} else {
|
||||
/*} else {
|
||||
// MSB first
|
||||
for (dp=0;dp<strlen(lcrframe);dp++) {
|
||||
pp = pm;
|
||||
@ -153,16 +143,16 @@ void LCRView::make_frame() {
|
||||
for (cp=0;cp<7;cp++) {
|
||||
if ((cur_byte>>cp)&1) pp++;
|
||||
}
|
||||
// 8/7 bit
|
||||
if (persistent_memory::afsk_config() & 4)
|
||||
lcrframe_f[dp] = cur_byte;
|
||||
else
|
||||
lcrframe_f[dp] = (cur_byte<<1)|(pp&1);
|
||||
lcrframe_f[dp] = (cur_byte<<1)|(pp&1);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
lcrframe_f[dp] = 0;
|
||||
}
|
||||
|
||||
void LCRView::paint(Painter& painter) {
|
||||
uint8_t i;
|
||||
|
||||
static constexpr Style style_orange {
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::black(),
|
||||
@ -174,43 +164,14 @@ void LCRView::paint(Painter& painter) {
|
||||
static_cast<Coord>(72)
|
||||
};
|
||||
|
||||
painter.draw_string(
|
||||
screen_pos() + offset,
|
||||
style_orange,
|
||||
litteral[0]
|
||||
);
|
||||
|
||||
offset.y += 40;
|
||||
|
||||
painter.draw_string(
|
||||
screen_pos() + offset,
|
||||
style_orange,
|
||||
litteral[1]
|
||||
);
|
||||
|
||||
offset.y += 40;
|
||||
|
||||
painter.draw_string(
|
||||
screen_pos() + offset,
|
||||
style_orange,
|
||||
litteral[2]
|
||||
);
|
||||
|
||||
offset.y += 40;
|
||||
|
||||
painter.draw_string(
|
||||
screen_pos() + offset,
|
||||
style_orange,
|
||||
litteral[3]
|
||||
);
|
||||
|
||||
offset.y += 40;
|
||||
|
||||
painter.draw_string(
|
||||
screen_pos() + offset,
|
||||
style_orange,
|
||||
litteral[4]
|
||||
);
|
||||
for (i = 0; i < 5; i++) {
|
||||
painter.draw_string(
|
||||
screen_pos() + offset,
|
||||
style_orange,
|
||||
litteral[i]
|
||||
);
|
||||
offset.y += 40;
|
||||
}
|
||||
}
|
||||
|
||||
LCRView::LCRView(
|
||||
@ -315,7 +276,6 @@ LCRView::LCRView(
|
||||
|
||||
button_transmit.on_select = [this,&transmitter_model](Button&){
|
||||
uint16_t c;
|
||||
ui::Context context;
|
||||
|
||||
make_frame();
|
||||
|
||||
@ -323,18 +283,25 @@ LCRView::LCRView(
|
||||
shared_memory.afsk_phase_inc_mark = persistent_memory::afsk_mark_freq()*(65536*1024)/2280;
|
||||
shared_memory.afsk_phase_inc_space = persistent_memory::afsk_space_freq()*(65536*1024)/2280;
|
||||
|
||||
for (c = 0; c < 256; c++) {
|
||||
shared_memory.lcrdata[c] = this->lcrframe[c];
|
||||
}
|
||||
memset(shared_memory.lcrdata, 0, 256);
|
||||
memcpy(shared_memory.lcrdata, lcrframe_f, 256);
|
||||
|
||||
shared_memory.afsk_transmit_done = false;
|
||||
shared_memory.afsk_repeat = 5; // DEFAULT
|
||||
|
||||
/*context.message_map[Message::ID::TXDone] = [this](const Message* const p) {
|
||||
text_status.set("Sent ! ");
|
||||
};*/
|
||||
context().message_map[Message::ID::TXDone] = [this, &transmitter_model](const Message* const p) {
|
||||
const auto message = static_cast<const TXDoneMessage*>(p);
|
||||
if (message->n > 0) {
|
||||
char str[8] = "0/5... ";
|
||||
str[0] = hexify(5-message->n);
|
||||
text_status.set(str);
|
||||
} else {
|
||||
text_status.set("Done ! ");
|
||||
transmitter_model.disable();
|
||||
}
|
||||
};
|
||||
|
||||
text_status.set("Send...");
|
||||
text_status.set("0/5... ");
|
||||
|
||||
transmitter_model.enable();
|
||||
};
|
||||
|
@ -66,7 +66,7 @@ private:
|
||||
TransmitterModel& transmitter_model;
|
||||
|
||||
Text text_status {
|
||||
{ 172, 196, 64, 16 },
|
||||
{ 168, 196, 64, 16 },
|
||||
"Ready"
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_rds.hpp"
|
||||
#include "ui_lcr.hpp"
|
||||
#include "ui_whistle.hpp"
|
||||
|
||||
#include "portapack.hpp"
|
||||
#include "m4_startup.hpp"
|
||||
@ -102,11 +103,11 @@ void NavigationView::focus() {
|
||||
|
||||
SystemMenuView::SystemMenuView(NavigationView& nav) {
|
||||
add_items<10>({ {
|
||||
{ "Play dead", ui::Color::red(), [&nav](){ nav.push(new PlayDeadView { nav }); } },
|
||||
{ "Play dead", ui::Color::red(), [&nav](){ nav.push(new PlayDeadView { nav, false }); } },
|
||||
{ "Receiver", ui::Color::white(), [&nav](){ nav.push(new ReceiverView { nav, receiver_model }); } },
|
||||
{ "Capture", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||
{ "Analyze", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||
{ "RDS TX", ui::Color::orange(), [&nav](){ nav.push(new RDSView { nav, transmitter_model }); } },
|
||||
{ "Whistle", ui::Color::white(), [&nav](){ nav.push(new WhistleView { nav, transmitter_model }); } },
|
||||
{ "RDS TX", ui::Color::yellow(), [&nav](){ nav.push(new RDSView { nav, transmitter_model }); } },
|
||||
{ "LCR TX", ui::Color::orange(), [&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 }); } },
|
||||
@ -147,7 +148,10 @@ SystemView::SystemView(
|
||||
|
||||
// Initial view.
|
||||
// TODO: Restore from non-volatile memory?
|
||||
navigation_view.push(new BMPView { navigation_view }); //SystemMenuView
|
||||
if (persistent_memory::playing_dead())
|
||||
navigation_view.push(new PlayDeadView { navigation_view, true });
|
||||
else
|
||||
navigation_view.push(new BMPView { navigation_view });
|
||||
}
|
||||
|
||||
Context& SystemView::context() const {
|
||||
@ -226,7 +230,10 @@ void PlayDeadView::focus() {
|
||||
button_done.focus();
|
||||
}
|
||||
|
||||
PlayDeadView::PlayDeadView(NavigationView& nav) {
|
||||
PlayDeadView::PlayDeadView(NavigationView& nav, bool booting) {
|
||||
_booting = booting;
|
||||
persistent_memory::set_playing_dead(1);
|
||||
|
||||
add_children({ {
|
||||
&text_playdead1,
|
||||
&text_playdead2,
|
||||
@ -238,10 +245,17 @@ PlayDeadView::PlayDeadView(NavigationView& nav) {
|
||||
};
|
||||
|
||||
button_done.on_select = [this,&nav](Button&){
|
||||
if (sequence == persistent_memory::playdead_sequence())
|
||||
nav.pop();
|
||||
else
|
||||
if (sequence == persistent_memory::playdead_sequence()) {
|
||||
persistent_memory::set_playing_dead(0);
|
||||
if (_booting) {
|
||||
nav.pop();
|
||||
nav.push(new SystemMenuView { nav });
|
||||
} else {
|
||||
nav.pop();
|
||||
}
|
||||
} else {
|
||||
sequence = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -106,10 +106,11 @@ private:
|
||||
|
||||
class PlayDeadView : public View {
|
||||
public:
|
||||
PlayDeadView(NavigationView& nav);
|
||||
PlayDeadView(NavigationView& nav, bool booting);
|
||||
void focus() override;
|
||||
|
||||
private:
|
||||
bool _booting;
|
||||
uint32_t sequence = 0;
|
||||
Text text_playdead1 {
|
||||
{ 6 * 8, 7 * 16, 14 * 8, 16 },
|
||||
|
@ -66,36 +66,33 @@ AlphanumView::AlphanumView(
|
||||
this->on_button(button);
|
||||
};
|
||||
|
||||
const char* const key_caps = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ. !<";
|
||||
|
||||
size_t n = 0;
|
||||
for(auto& button : buttons) {
|
||||
add_child(&button);
|
||||
const std::string label {
|
||||
key_caps[n]
|
||||
};
|
||||
button.on_select = button_fn;
|
||||
button.set_parent_rect({
|
||||
static_cast<Coord>((n % 5) * button_w),
|
||||
static_cast<Coord>((n / 5) * button_h + 18),
|
||||
button_w, button_h
|
||||
});
|
||||
button.set_text(label);
|
||||
if ((n < 10) || (n == 39))
|
||||
button.set_style(&style_num);
|
||||
else
|
||||
button.set_style(&style_alpha);
|
||||
n++;
|
||||
}
|
||||
set_uppercase();
|
||||
|
||||
add_child(&button_lowercase);
|
||||
button_lowercase.on_select = [this, &nav, txt, max_len](Button&) {
|
||||
if (_lowercase == true) {
|
||||
_lowercase = false;
|
||||
button_lowercase.set_text("LC");
|
||||
button_lowercase.set_text("UC");
|
||||
set_uppercase();
|
||||
} else {
|
||||
_lowercase = true;
|
||||
button_lowercase.set_text("UC");
|
||||
button_lowercase.set_text("LC");
|
||||
set_lowercase();
|
||||
}
|
||||
};
|
||||
|
||||
@ -109,6 +106,35 @@ AlphanumView::AlphanumView(
|
||||
update_text();
|
||||
}
|
||||
|
||||
void AlphanumView::set_uppercase() {
|
||||
const char* const key_caps = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ. !<";
|
||||
|
||||
size_t n = 0;
|
||||
for(auto& button : buttons) {
|
||||
add_child(&button);
|
||||
const std::string label {
|
||||
key_caps[n]
|
||||
};
|
||||
button.set_text(label);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AlphanumView::set_lowercase() {
|
||||
const char* const key_caps = "0123456789abcdefghijklmnopqrstuvwxyz. !<";
|
||||
|
||||
size_t n = 0;
|
||||
for(auto& button : buttons) {
|
||||
add_child(&button);
|
||||
const std::string label {
|
||||
key_caps[n]
|
||||
};
|
||||
button.set_text(label);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
void AlphanumView::focus() {
|
||||
button_done.focus();
|
||||
}
|
||||
@ -122,10 +148,7 @@ void AlphanumView::on_button(Button& button) {
|
||||
if( s == "<" ) {
|
||||
char_delete();
|
||||
} else {
|
||||
if (_lowercase == true)
|
||||
char_add(s[0] + 32);
|
||||
else
|
||||
char_add(s[0]);
|
||||
char_add(s[0]);
|
||||
}
|
||||
update_text();
|
||||
}
|
||||
|
@ -55,11 +55,14 @@ public:
|
||||
|
||||
private:
|
||||
uint8_t _max_len;
|
||||
bool _lowercase;
|
||||
bool _lowercase = false;
|
||||
static constexpr size_t button_w = 240 / 5;
|
||||
static constexpr size_t button_h = 28;
|
||||
char txtinput[9];
|
||||
|
||||
|
||||
void set_lowercase();
|
||||
void set_uppercase();
|
||||
|
||||
Text text_input {
|
||||
{ 88, 0, 240, 16 }
|
||||
};
|
||||
@ -68,7 +71,7 @@ private:
|
||||
|
||||
Button button_lowercase {
|
||||
{ 88+64+16, 270, 32, 24 },
|
||||
"LC"
|
||||
"UC"
|
||||
};
|
||||
|
||||
Button button_done {
|
||||
|
@ -269,7 +269,7 @@ void FrequencyKeypadView::field_toggle() {
|
||||
|
||||
void FrequencyKeypadView::update_text() {
|
||||
const auto s = mhz.as_string() + "." + submhz.as_string();
|
||||
text_value.set(s);
|
||||
text_value.set(s.c_str());
|
||||
}
|
||||
|
||||
/* FrequencyOptionsView **************************************************/
|
||||
|
133
firmware/application/ui_whistle.cpp
Normal file
133
firmware/application/ui_whistle.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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_whistle.hpp"
|
||||
#include "ui_receiver.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 WhistleView::focus() {
|
||||
button_transmit.focus();
|
||||
}
|
||||
|
||||
WhistleView::~WhistleView() {
|
||||
transmitter_model.disable();
|
||||
}
|
||||
|
||||
void WhistleView::paint(Painter& painter) {
|
||||
|
||||
}
|
||||
|
||||
void WhistleView::whistle_th(void *arg) {
|
||||
Mailbox* mbox = (Mailbox *)arg;
|
||||
chMBPost(mbox, 1, TIME_INFINITE);
|
||||
}
|
||||
|
||||
Button WhistleView::button_scan = {
|
||||
{ 76, 270, 72, 32 },
|
||||
"SCAN"
|
||||
};
|
||||
|
||||
WhistleView::WhistleView(
|
||||
NavigationView& nav,
|
||||
TransmitterModel& transmitter_model
|
||||
) : transmitter_model(transmitter_model)
|
||||
{
|
||||
Mailbox mbox;
|
||||
msg_t mbox_buffer[3];
|
||||
chMBInit(&mbox, mbox_buffer, 3);
|
||||
|
||||
transmitter_model.set_modulation(17);
|
||||
transmitter_model.set_tuning_frequency(persistent_memory::tuned_frequency());
|
||||
|
||||
add_children({ {
|
||||
&button_scan,
|
||||
&button_transmit,
|
||||
&button_exit
|
||||
} });
|
||||
|
||||
button_transmit.on_select = [this,&transmitter_model](Button&){
|
||||
/*uint16_t c;
|
||||
ui::Context context;
|
||||
|
||||
make_frame();
|
||||
|
||||
shared_memory.afsk_samples_per_bit = 228000/persistent_memory::afsk_bitrate();
|
||||
shared_memory.afsk_phase_inc_mark = persistent_memory::afsk_mark_freq()*(65536*1024)/2280;
|
||||
shared_memory.afsk_phase_inc_space = persistent_memory::afsk_space_freq()*(65536*1024)/2280;
|
||||
|
||||
for (c = 0; c < 256; c++) {
|
||||
shared_memory.lcrdata[c] = this->lcrframe[c];
|
||||
}
|
||||
|
||||
shared_memory.afsk_transmit_done = false;
|
||||
shared_memory.afsk_repeat = 5; // DEFAULT
|
||||
|
||||
text_status.set("Send...");
|
||||
|
||||
transmitter_model.enable();*/
|
||||
};
|
||||
|
||||
button_exit.on_select = [&nav](Button&){
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
static VirtualTimer vt1;
|
||||
msg_t msg, result;
|
||||
|
||||
/*static EvTimer evt;
|
||||
static EventListener el0;
|
||||
|
||||
evtInit(&evt, MS2ST(2000));
|
||||
evtStart(&evt);
|
||||
chEvtRegister(&evt.et_es, &el0, 0);*/
|
||||
|
||||
//chVTSet(&vt1, MS2ST(2000), whistle_th, (void *)&mbox);
|
||||
|
||||
while(1) {
|
||||
/*result = chMBFetch(&mbox, &msg, TIME_INFINITE);
|
||||
if(result == RDY_OK) {
|
||||
if(msg & 1)
|
||||
button_scan.set_text("POUET");
|
||||
}*/
|
||||
chThdSleepMilliseconds(500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
93
firmware/application/ui_whistle.hpp
Normal file
93
firmware/application/ui_whistle.hpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 WhistleView : public View {
|
||||
public:
|
||||
WhistleView(NavigationView& nav, TransmitterModel& transmitter_model);
|
||||
~WhistleView();
|
||||
|
||||
void focus() override;
|
||||
void paint(Painter& painter) override;
|
||||
static void whistle_th(void *p);
|
||||
|
||||
private:
|
||||
typedef struct rstchs {
|
||||
rf::Frequency out[3];
|
||||
rf::Frequency in;
|
||||
} rstchs;
|
||||
rstchs whistle_chs[14] = {
|
||||
{{ 467650000, 467700000, 467750000 }, 457700000},
|
||||
{{ 467750000, 467825000, 467875000 }, 457825000},
|
||||
{{ 467875000, 467925000, 467975000 }, 457925000},
|
||||
{{ 467950000, 468000000, 468050000 }, 457800000},
|
||||
{{ 467625000, 467675000, 467725000 }, 457675000},
|
||||
{{ 467700000, 467750000, 467800000 }, 457750000},
|
||||
{{ 467750000, 467800000, 467850000 }, 457800000},
|
||||
{{ 467825000, 467875000, 467925000 }, 457875000},
|
||||
{{ 467900000, 467950000, 468000000 }, 457950000},
|
||||
{{ 468025000, 468075000, 468125000 }, 458075000},
|
||||
{{ 468100000, 468150000, 468200000 }, 458150000},
|
||||
{{ 468075000, 468125000, 468175000 }, 458125000},
|
||||
{{ 468175000, 468225000, 468275000 }, 458225000},
|
||||
{{ 468225000, 468275000, 468325000 }, 458275000}
|
||||
};
|
||||
rf::Frequency f;
|
||||
TransmitterModel& transmitter_model;
|
||||
|
||||
Text text_status {
|
||||
{ 172, 196, 64, 16 },
|
||||
"Ready"
|
||||
};
|
||||
|
||||
Checkbox checkbox_am_a {
|
||||
{ 16, 68 },
|
||||
""
|
||||
};
|
||||
|
||||
Button button_transmit {
|
||||
{ 24, 270, 48, 32 },
|
||||
"TX"
|
||||
};
|
||||
|
||||
static Button button_scan;
|
||||
|
||||
Button button_exit {
|
||||
{ 176, 270, 48, 32 },
|
||||
"Exit"
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
@ -678,6 +678,7 @@ static int32_t waveform_biphase[] = {
|
||||
-157,-160,-163,-166,-167,-168,-168,-167
|
||||
};
|
||||
|
||||
/*
|
||||
class RDSProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(buffer_c8_t buffer) override {
|
||||
@ -758,7 +759,7 @@ private:
|
||||
uint32_t phase, sphase;
|
||||
int32_t sig, frq, frq_im, rdsc;
|
||||
int32_t k;
|
||||
};
|
||||
};*/
|
||||
|
||||
class LCRFSKProcessor : public BasebandProcessor {
|
||||
public:
|
||||
@ -779,22 +780,25 @@ public:
|
||||
bit_pos = 0;
|
||||
byte_pos = 0;
|
||||
cur_byte = shared_memory.lcrdata[0];
|
||||
if( message.is_free() ) {
|
||||
message.n = shared_memory.afsk_repeat;
|
||||
shared_memory.application_queue.push(&message);
|
||||
}
|
||||
} else {
|
||||
shared_memory.afsk_transmit_done = true; // TODO: Remove, unused
|
||||
//shared_memory.application_queue.push(&message);
|
||||
if( message.is_free() ) {
|
||||
message.n = 0;
|
||||
shared_memory.afsk_transmit_done = true;
|
||||
shared_memory.application_queue.push(&message);
|
||||
}
|
||||
cur_byte = 0;
|
||||
}
|
||||
}
|
||||
//cur_byte = (0x55<<1); //DEBUG
|
||||
|
||||
//SdddddddpD
|
||||
//0dddddddp1
|
||||
|
||||
gbyte = 0;
|
||||
gbyte = cur_byte << 1;
|
||||
gbyte |= 1;
|
||||
|
||||
cur_bit = gbyte >> (9-bit_pos) & 1;
|
||||
cur_bit = (gbyte >> (9-bit_pos)) & 1;
|
||||
|
||||
if (bit_pos == 9) {
|
||||
bit_pos = 0;
|
||||
@ -822,7 +826,7 @@ public:
|
||||
sample = sintab[(aphase & 0x03FF0000)>>16];
|
||||
|
||||
//FM
|
||||
frq = sample * 850; //TODO: Put in config (channel bandwidth)
|
||||
frq = sample * 500;
|
||||
|
||||
phase = (phase + frq);
|
||||
sphase = phase + (256<<16);
|
||||
@ -837,8 +841,8 @@ public:
|
||||
private:
|
||||
int8_t re, im;
|
||||
uint8_t s;
|
||||
uint8_t bit_pos, byte_pos;
|
||||
uint8_t cur_byte = 0;
|
||||
uint8_t bit_pos, byte_pos = 0;
|
||||
char cur_byte = 0;
|
||||
uint16_t gbyte;
|
||||
uint8_t cur_bit = 0;
|
||||
uint32_t sample_count;
|
||||
@ -847,6 +851,44 @@ private:
|
||||
TXDoneMessage message;
|
||||
};
|
||||
|
||||
class ToneProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(buffer_c8_t buffer) override {
|
||||
|
||||
for (size_t i = 0; i<buffer.count; i++) {
|
||||
|
||||
//Sample generation 2.28M/10 = 228kHz
|
||||
if (s >= 9) {
|
||||
s = 0;
|
||||
aphase += 353205; // DEBUG
|
||||
sample = sintab[(aphase & 0x03FF0000)>>16];
|
||||
} else {
|
||||
s++;
|
||||
}
|
||||
|
||||
sample = sintab[(aphase & 0x03FF0000)>>16];
|
||||
|
||||
//FM
|
||||
frq = sample * 500; // DEBUG
|
||||
|
||||
phase = (phase + frq);
|
||||
sphase = phase + (256<<16);
|
||||
|
||||
re = sintab[(sphase & 0x03FF0000)>>16];
|
||||
im = sintab[(phase & 0x03FF0000)>>16];
|
||||
|
||||
buffer.p[i] = {(int8_t)re,(int8_t)im};
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int8_t re, im;
|
||||
uint8_t s;
|
||||
uint32_t sample_count;
|
||||
uint32_t aphase, phase, sphase;
|
||||
int32_t sample, sig, frq;
|
||||
};
|
||||
|
||||
static BasebandProcessor* baseband_processor { nullptr };
|
||||
static BasebandConfiguration baseband_configuration;
|
||||
|
||||
@ -1107,15 +1149,20 @@ int main(void) {
|
||||
baseband_processor = new FSKProcessor(message_handlers);
|
||||
break;
|
||||
|
||||
case 15:
|
||||
/*case 15:
|
||||
direction = baseband::Direction::Transmit;
|
||||
baseband_processor = new RDSProcessor();
|
||||
break;
|
||||
break;*/
|
||||
|
||||
case 16:
|
||||
direction = baseband::Direction::Transmit;
|
||||
baseband_processor = new LCRFSKProcessor();
|
||||
break;
|
||||
|
||||
case 17:
|
||||
direction = baseband::Direction::Transmit;
|
||||
baseband_processor = new ToneProcessor();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -258,6 +258,8 @@ public:
|
||||
) : Message { ID::TXDone }
|
||||
{
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
};
|
||||
|
||||
class MessageHandlerMap {
|
||||
|
@ -77,7 +77,7 @@ struct data_t {
|
||||
uint32_t afsk_config;
|
||||
|
||||
// Play dead unlock
|
||||
bool playing_dead;
|
||||
uint32_t playing_dead;
|
||||
uint32_t playdead_sequence;
|
||||
};
|
||||
|
||||
@ -138,11 +138,11 @@ void set_afsk_config(const uint32_t new_value) {
|
||||
data->afsk_config = new_value;
|
||||
}
|
||||
|
||||
bool playing_dead() {
|
||||
uint32_t playing_dead() {
|
||||
return data->playing_dead;
|
||||
}
|
||||
|
||||
void set_playing_dead(const bool new_value) {
|
||||
void set_playing_dead(const uint32_t new_value) {
|
||||
data->playing_dead = new_value;
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,8 @@ void set_afsk_bitrate(const int32_t new_value);
|
||||
uint32_t afsk_config();
|
||||
void set_afsk_config(const uint32_t new_value);
|
||||
|
||||
bool playing_dead();
|
||||
void set_playing_dead(const bool new_value);
|
||||
uint32_t playing_dead();
|
||||
void set_playing_dead(const uint32_t new_value);
|
||||
|
||||
uint32_t playdead_sequence();
|
||||
void set_playdead_sequence(const uint32_t new_value);
|
||||
|
@ -43,7 +43,7 @@ struct SharedMemory {
|
||||
|
||||
uint32_t rdsdata[16];
|
||||
|
||||
char lcrdata[256];
|
||||
uint8_t lcrdata[256];
|
||||
uint32_t afsk_samples_per_bit;
|
||||
uint32_t afsk_phase_inc_mark;
|
||||
uint32_t afsk_phase_inc_space;
|
||||
|
@ -483,6 +483,11 @@ void Button::set_text(const std::string value) {
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void Button::set_text(const int value) { //std::string
|
||||
text_ = value;
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void Button::set_style(const Style* new_style) {
|
||||
if( new_style != style_ ) {
|
||||
style_ = new_style;
|
||||
|
@ -270,6 +270,7 @@ public:
|
||||
}
|
||||
|
||||
void set_text(const std::string value);
|
||||
void set_text(const int value);
|
||||
void set_style(const Style* new_style);
|
||||
std::string text() const;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user