Play dead actually works, fixed 7bit AFSK, AFSK repeat, started whistle mode

This commit is contained in:
furrtek 2015-09-10 20:36:39 +02:00
parent 07754727ed
commit 9a7657fb38
22 changed files with 447 additions and 128 deletions

View File

@ -112,7 +112,8 @@ CSRC = $(PORTSRC) \
$(HALSRC) \ $(HALSRC) \
$(PLATFORMSRC) \ $(PLATFORMSRC) \
$(BOARDSRC) \ $(BOARDSRC) \
$(FATFSSRC) $(FATFSSRC) \
$(CHIBIOS)/os/various/evtimer.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global # 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_debug.cpp \
ui_rds.cpp \ ui_rds.cpp \
ui_lcr.cpp \ ui_lcr.cpp \
ui_whistle.cpp \
ui_afsksetup.cpp \ ui_afsksetup.cpp \
ui_console.cpp \ ui_console.cpp \
ui_receiver.cpp \ ui_receiver.cpp \

View File

@ -33,6 +33,10 @@ void m4txevent_interrupt_enable() {
nvicEnableVector(M4CORE_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_M4TXEVENT_IRQ_PRIORITY)); nvicEnableVector(M4CORE_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_M4TXEVENT_IRQ_PRIORITY));
} }
void m4txevent_interrupt_disable() {
nvicDisableVector(M4CORE_IRQn);
}
extern "C" { extern "C" {
CH_IRQ_HANDLER(M4Core_IRQHandler) { CH_IRQ_HANDLER(M4Core_IRQHandler) {

View File

@ -33,6 +33,8 @@
* cause an exception and effectively halt the M4. But that feels gross. * 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) { void m4_init(const portapack::spi_flash::region_t from, void* const to) {
//m4txevent_interrupt_disable();
/* Initialize M4 code RAM */ /* Initialize M4 code RAM */
std::memcpy(to, from.base_address(), from.size); std::memcpy(to, from.base_address(), from.size);

View File

@ -19,6 +19,26 @@
* Boston, MA 02110-1301, USA. * 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 "ch.h"
#include "test.h" #include "test.h"
@ -506,15 +526,15 @@ int main(void) {
}; };
ui::Painter painter; ui::Painter painter;
context.message_map[Message::ID::FSKPacket] = [](const Message* const p) { context.message_map[Message::ID::FSKPacket] = [](const Message* const p) {
const auto message = static_cast<const FSKPacketMessage*>(p); const auto message = static_cast<const FSKPacketMessage*>(p);
(void)message; (void)message;
}; };
context.message_map[Message::ID::TXDone] = [](const Message* const p) { context.message_map[Message::ID::TXDone] = [](const Message* const p) {
const auto message = static_cast<const TXDoneMessage*>(p); const auto message = static_cast<const TXDoneMessage*>(p);
(void)message; (void)message;
}; };
EventDispatcher event_dispatcher { &system_view, painter, context }; EventDispatcher event_dispatcher { &system_view, painter, context };

View File

@ -249,7 +249,7 @@ char hexify(char in) {
return in + 0x30; 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 "; char cstr[15] = "Checksum: 0x ";
add_children({ { add_children({ {
@ -265,10 +265,10 @@ DebugLCRView::DebugLCRView(NavigationView& nav, char* lcrstring, uint8_t checksu
std::string b = std::string(lcrstring); std::string b = std::string(lcrstring);
text_lcr1.set(b.substr(8+(0*26),26)); text_lcr1.set(b.substr(8+(0*26),26));
if (strlen(b > 34)) text_lcr2.set(b.substr(8+(1*26),26)); if (strlen(lcrstring) > 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(lcrstring) > 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(lcrstring) > 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+26+26+26) text_lcr5.set(b.substr(8+(4*26),26));
cstr[12] = hexify(checksum >> 4); cstr[12] = hexify(checksum >> 4);
cstr[13] = hexify(checksum & 15); cstr[13] = hexify(checksum & 15);

View File

@ -32,6 +32,8 @@
namespace ui { namespace ui {
char hexify(char in);
class BasebandStatsView : public View { class BasebandStatsView : public View {
public: public:
BasebandStatsView(); BasebandStatsView();

View File

@ -39,12 +39,6 @@
#include <cstring> #include <cstring>
#include <stdio.h> #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; using namespace hackrf::one;
namespace ui { namespace ui {
@ -107,7 +101,7 @@ void LCRView::make_frame() {
strcat(lcrframe, litteral[4]); strcat(lcrframe, litteral[4]);
strcat(lcrframe, "\" CL=0 "); 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); memcpy(lcrstring, lcrframe, 256);
@ -124,12 +118,12 @@ void LCRView::make_frame() {
strcat(lcrframe, eom); strcat(lcrframe, eom);
if (persistent_memory::afsk_config() & 2) //if (persistent_memory::afsk_config() & 2)
pm = 0; // Even parity pm = 0; // Even parity
else //else
pm = 1; // Odd parity // pm = 1; // Odd parity
if (persistent_memory::afsk_config() & 1) { //if (persistent_memory::afsk_config() & 1) {
// LSB first // LSB first
for (dp=0;dp<strlen(lcrframe);dp++) { for (dp=0;dp<strlen(lcrframe);dp++) {
pp = pm; pp = pm;
@ -137,15 +131,11 @@ void LCRView::make_frame() {
cur_byte = lcrframe[dp]; cur_byte = lcrframe[dp];
for (cp=0;cp<7;cp++) { for (cp=0;cp<7;cp++) {
if ((cur_byte>>cp)&1) pp++; 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 lcrframe_f[dp] = new_byte|(pp&1);
if (persistent_memory::afsk_config() & 4)
lcrframe_f[dp] = new_byte;
else
lcrframe_f[dp] = (new_byte<<1)|(pp&1);
} }
} else { /*} else {
// MSB first // MSB first
for (dp=0;dp<strlen(lcrframe);dp++) { for (dp=0;dp<strlen(lcrframe);dp++) {
pp = pm; pp = pm;
@ -153,16 +143,16 @@ void LCRView::make_frame() {
for (cp=0;cp<7;cp++) { for (cp=0;cp<7;cp++) {
if ((cur_byte>>cp)&1) pp++; 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) { void LCRView::paint(Painter& painter) {
uint8_t i;
static constexpr Style style_orange { static constexpr Style style_orange {
.font = font::fixed_8x16, .font = font::fixed_8x16,
.background = Color::black(), .background = Color::black(),
@ -174,43 +164,14 @@ void LCRView::paint(Painter& painter) {
static_cast<Coord>(72) static_cast<Coord>(72)
}; };
for (i = 0; i < 5; i++) {
painter.draw_string( painter.draw_string(
screen_pos() + offset, screen_pos() + offset,
style_orange, style_orange,
litteral[0] litteral[i]
); );
offset.y += 40; 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]
);
} }
LCRView::LCRView( LCRView::LCRView(
@ -315,7 +276,6 @@ LCRView::LCRView(
button_transmit.on_select = [this,&transmitter_model](Button&){ button_transmit.on_select = [this,&transmitter_model](Button&){
uint16_t c; uint16_t c;
ui::Context context;
make_frame(); 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_mark = persistent_memory::afsk_mark_freq()*(65536*1024)/2280;
shared_memory.afsk_phase_inc_space = persistent_memory::afsk_space_freq()*(65536*1024)/2280; shared_memory.afsk_phase_inc_space = persistent_memory::afsk_space_freq()*(65536*1024)/2280;
for (c = 0; c < 256; c++) { memset(shared_memory.lcrdata, 0, 256);
shared_memory.lcrdata[c] = this->lcrframe[c]; memcpy(shared_memory.lcrdata, lcrframe_f, 256);
}
shared_memory.afsk_transmit_done = false; shared_memory.afsk_transmit_done = false;
shared_memory.afsk_repeat = 5; // DEFAULT shared_memory.afsk_repeat = 5; // DEFAULT
/*context.message_map[Message::ID::TXDone] = [this](const Message* const p) { context().message_map[Message::ID::TXDone] = [this, &transmitter_model](const Message* const p) {
text_status.set("Sent ! "); 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(); transmitter_model.enable();
}; };

View File

@ -66,7 +66,7 @@ private:
TransmitterModel& transmitter_model; TransmitterModel& transmitter_model;
Text text_status { Text text_status {
{ 172, 196, 64, 16 }, { 168, 196, 64, 16 },
"Ready" "Ready"
}; };

View File

@ -32,6 +32,7 @@
#include "ui_receiver.hpp" #include "ui_receiver.hpp"
#include "ui_rds.hpp" #include "ui_rds.hpp"
#include "ui_lcr.hpp" #include "ui_lcr.hpp"
#include "ui_whistle.hpp"
#include "portapack.hpp" #include "portapack.hpp"
#include "m4_startup.hpp" #include "m4_startup.hpp"
@ -102,11 +103,11 @@ void NavigationView::focus() {
SystemMenuView::SystemMenuView(NavigationView& nav) { SystemMenuView::SystemMenuView(NavigationView& nav) {
add_items<10>({ { 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 }); } }, { "Receiver", ui::Color::white(), [&nav](){ nav.push(new ReceiverView { nav, receiver_model }); } },
{ "Capture", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "Capture", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
{ "Analyze", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } }, { "Whistle", ui::Color::white(), [&nav](){ nav.push(new WhistleView { nav, transmitter_model }); } },
{ "RDS TX", ui::Color::orange(), [&nav](){ nav.push(new RDSView { 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 }); } }, { "LCR TX", ui::Color::orange(), [&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 }); } },
@ -147,7 +148,10 @@ SystemView::SystemView(
// Initial view. // Initial view.
// TODO: Restore from non-volatile memory? // 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 { Context& SystemView::context() const {
@ -226,7 +230,10 @@ void PlayDeadView::focus() {
button_done.focus(); button_done.focus();
} }
PlayDeadView::PlayDeadView(NavigationView& nav) { PlayDeadView::PlayDeadView(NavigationView& nav, bool booting) {
_booting = booting;
persistent_memory::set_playing_dead(1);
add_children({ { add_children({ {
&text_playdead1, &text_playdead1,
&text_playdead2, &text_playdead2,
@ -238,10 +245,17 @@ PlayDeadView::PlayDeadView(NavigationView& nav) {
}; };
button_done.on_select = [this,&nav](Button&){ button_done.on_select = [this,&nav](Button&){
if (sequence == persistent_memory::playdead_sequence()) if (sequence == persistent_memory::playdead_sequence()) {
persistent_memory::set_playing_dead(0);
if (_booting) {
nav.pop(); nav.pop();
else nav.push(new SystemMenuView { nav });
} else {
nav.pop();
}
} else {
sequence = 0; sequence = 0;
}
}; };
} }

View File

@ -106,10 +106,11 @@ private:
class PlayDeadView : public View { class PlayDeadView : public View {
public: public:
PlayDeadView(NavigationView& nav); PlayDeadView(NavigationView& nav, bool booting);
void focus() override; void focus() override;
private: private:
bool _booting;
uint32_t sequence = 0; uint32_t sequence = 0;
Text text_playdead1 { Text text_playdead1 {
{ 6 * 8, 7 * 16, 14 * 8, 16 }, { 6 * 8, 7 * 16, 14 * 8, 16 },

View File

@ -66,36 +66,33 @@ AlphanumView::AlphanumView(
this->on_button(button); this->on_button(button);
}; };
const char* const key_caps = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ. !<";
size_t n = 0; size_t n = 0;
for(auto& button : buttons) { for(auto& button : buttons) {
add_child(&button); add_child(&button);
const std::string label {
key_caps[n]
};
button.on_select = button_fn; button.on_select = button_fn;
button.set_parent_rect({ button.set_parent_rect({
static_cast<Coord>((n % 5) * button_w), static_cast<Coord>((n % 5) * button_w),
static_cast<Coord>((n / 5) * button_h + 18), static_cast<Coord>((n / 5) * button_h + 18),
button_w, button_h button_w, button_h
}); });
button.set_text(label);
if ((n < 10) || (n == 39)) if ((n < 10) || (n == 39))
button.set_style(&style_num); button.set_style(&style_num);
else else
button.set_style(&style_alpha); button.set_style(&style_alpha);
n++; n++;
} }
set_uppercase();
add_child(&button_lowercase); add_child(&button_lowercase);
button_lowercase.on_select = [this, &nav, txt, max_len](Button&) { button_lowercase.on_select = [this, &nav, txt, max_len](Button&) {
if (_lowercase == true) { if (_lowercase == true) {
_lowercase = false; _lowercase = false;
button_lowercase.set_text("LC"); button_lowercase.set_text("UC");
set_uppercase();
} else { } else {
_lowercase = true; _lowercase = true;
button_lowercase.set_text("UC"); button_lowercase.set_text("LC");
set_lowercase();
} }
}; };
@ -109,6 +106,35 @@ AlphanumView::AlphanumView(
update_text(); 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() { void AlphanumView::focus() {
button_done.focus(); button_done.focus();
} }
@ -122,9 +148,6 @@ void AlphanumView::on_button(Button& button) {
if( s == "<" ) { if( s == "<" ) {
char_delete(); char_delete();
} else { } else {
if (_lowercase == true)
char_add(s[0] + 32);
else
char_add(s[0]); char_add(s[0]);
} }
update_text(); update_text();

View File

@ -55,11 +55,14 @@ public:
private: private:
uint8_t _max_len; uint8_t _max_len;
bool _lowercase; bool _lowercase = false;
static constexpr size_t button_w = 240 / 5; static constexpr size_t button_w = 240 / 5;
static constexpr size_t button_h = 28; static constexpr size_t button_h = 28;
char txtinput[9]; char txtinput[9];
void set_lowercase();
void set_uppercase();
Text text_input { Text text_input {
{ 88, 0, 240, 16 } { 88, 0, 240, 16 }
}; };
@ -68,7 +71,7 @@ private:
Button button_lowercase { Button button_lowercase {
{ 88+64+16, 270, 32, 24 }, { 88+64+16, 270, 32, 24 },
"LC" "UC"
}; };
Button button_done { Button button_done {

View File

@ -269,7 +269,7 @@ void FrequencyKeypadView::field_toggle() {
void FrequencyKeypadView::update_text() { void FrequencyKeypadView::update_text() {
const auto s = mhz.as_string() + "." + submhz.as_string(); const auto s = mhz.as_string() + "." + submhz.as_string();
text_value.set(s); text_value.set(s.c_str());
} }
/* FrequencyOptionsView **************************************************/ /* FrequencyOptionsView **************************************************/

View 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 */

View 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 */

View File

@ -678,6 +678,7 @@ static int32_t waveform_biphase[] = {
-157,-160,-163,-166,-167,-168,-168,-167 -157,-160,-163,-166,-167,-168,-168,-167
}; };
/*
class RDSProcessor : public BasebandProcessor { class RDSProcessor : public BasebandProcessor {
public: public:
void execute(buffer_c8_t buffer) override { void execute(buffer_c8_t buffer) override {
@ -758,7 +759,7 @@ private:
uint32_t phase, sphase; uint32_t phase, sphase;
int32_t sig, frq, frq_im, rdsc; int32_t sig, frq, frq_im, rdsc;
int32_t k; int32_t k;
}; };*/
class LCRFSKProcessor : public BasebandProcessor { class LCRFSKProcessor : public BasebandProcessor {
public: public:
@ -779,22 +780,25 @@ public:
bit_pos = 0; bit_pos = 0;
byte_pos = 0; byte_pos = 0;
cur_byte = shared_memory.lcrdata[0]; cur_byte = shared_memory.lcrdata[0];
if( message.is_free() ) {
message.n = shared_memory.afsk_repeat;
shared_memory.application_queue.push(&message);
}
} else { } else {
shared_memory.afsk_transmit_done = true; // TODO: Remove, unused if( message.is_free() ) {
//shared_memory.application_queue.push(&message); message.n = 0;
shared_memory.afsk_transmit_done = true;
shared_memory.application_queue.push(&message);
}
cur_byte = 0; cur_byte = 0;
} }
} }
//cur_byte = (0x55<<1); //DEBUG
//SdddddddpD
//0dddddddp1
gbyte = 0; gbyte = 0;
gbyte = cur_byte << 1; gbyte = cur_byte << 1;
gbyte |= 1; gbyte |= 1;
cur_bit = gbyte >> (9-bit_pos) & 1; cur_bit = (gbyte >> (9-bit_pos)) & 1;
if (bit_pos == 9) { if (bit_pos == 9) {
bit_pos = 0; bit_pos = 0;
@ -822,7 +826,7 @@ public:
sample = sintab[(aphase & 0x03FF0000)>>16]; sample = sintab[(aphase & 0x03FF0000)>>16];
//FM //FM
frq = sample * 850; //TODO: Put in config (channel bandwidth) frq = sample * 500;
phase = (phase + frq); phase = (phase + frq);
sphase = phase + (256<<16); sphase = phase + (256<<16);
@ -837,8 +841,8 @@ public:
private: private:
int8_t re, im; int8_t re, im;
uint8_t s; uint8_t s;
uint8_t bit_pos, byte_pos; uint8_t bit_pos, byte_pos = 0;
uint8_t cur_byte = 0; char cur_byte = 0;
uint16_t gbyte; uint16_t gbyte;
uint8_t cur_bit = 0; uint8_t cur_bit = 0;
uint32_t sample_count; uint32_t sample_count;
@ -847,6 +851,44 @@ private:
TXDoneMessage message; 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 BasebandProcessor* baseband_processor { nullptr };
static BasebandConfiguration baseband_configuration; static BasebandConfiguration baseband_configuration;
@ -1107,16 +1149,21 @@ int main(void) {
baseband_processor = new FSKProcessor(message_handlers); baseband_processor = new FSKProcessor(message_handlers);
break; break;
case 15: /*case 15:
direction = baseband::Direction::Transmit; direction = baseband::Direction::Transmit;
baseband_processor = new RDSProcessor(); baseband_processor = new RDSProcessor();
break; break;*/
case 16: case 16:
direction = baseband::Direction::Transmit; direction = baseband::Direction::Transmit;
baseband_processor = new LCRFSKProcessor(); baseband_processor = new LCRFSKProcessor();
break; break;
case 17:
direction = baseband::Direction::Transmit;
baseband_processor = new ToneProcessor();
break;
default: default:
break; break;
} }

View File

@ -258,6 +258,8 @@ public:
) : Message { ID::TXDone } ) : Message { ID::TXDone }
{ {
} }
int n = 0;
}; };
class MessageHandlerMap { class MessageHandlerMap {

View File

@ -77,7 +77,7 @@ struct data_t {
uint32_t afsk_config; uint32_t afsk_config;
// Play dead unlock // Play dead unlock
bool playing_dead; uint32_t playing_dead;
uint32_t playdead_sequence; uint32_t playdead_sequence;
}; };
@ -138,11 +138,11 @@ void set_afsk_config(const uint32_t new_value) {
data->afsk_config = new_value; data->afsk_config = new_value;
} }
bool playing_dead() { uint32_t playing_dead() {
return data->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; data->playing_dead = new_value;
} }

View File

@ -49,8 +49,8 @@ void set_afsk_bitrate(const int32_t new_value);
uint32_t afsk_config(); uint32_t afsk_config();
void set_afsk_config(const uint32_t new_value); void set_afsk_config(const uint32_t new_value);
bool playing_dead(); uint32_t playing_dead();
void set_playing_dead(const bool new_value); void set_playing_dead(const uint32_t new_value);
uint32_t playdead_sequence(); uint32_t playdead_sequence();
void set_playdead_sequence(const uint32_t new_value); void set_playdead_sequence(const uint32_t new_value);

View File

@ -43,7 +43,7 @@ struct SharedMemory {
uint32_t rdsdata[16]; uint32_t rdsdata[16];
char lcrdata[256]; uint8_t lcrdata[256];
uint32_t afsk_samples_per_bit; uint32_t afsk_samples_per_bit;
uint32_t afsk_phase_inc_mark; uint32_t afsk_phase_inc_mark;
uint32_t afsk_phase_inc_space; uint32_t afsk_phase_inc_space;

View File

@ -483,6 +483,11 @@ void Button::set_text(const std::string value) {
set_dirty(); set_dirty();
} }
void Button::set_text(const int value) { //std::string
text_ = value;
set_dirty();
}
void Button::set_style(const Style* new_style) { void Button::set_style(const Style* new_style) {
if( new_style != style_ ) { if( new_style != style_ ) {
style_ = new_style; style_ = new_style;

View File

@ -270,6 +270,7 @@ public:
} }
void set_text(const std::string value); void set_text(const std::string value);
void set_text(const int value);
void set_style(const Style* new_style); void set_style(const Style* new_style);
std::string text() const; std::string text() const;