Dynamic baseband module loading from SD card

This commit is contained in:
furrtek
2015-11-20 07:59:09 +01:00
parent 835d581e6c
commit 5f60b004f7
82 changed files with 8041 additions and 580 deletions

View File

@@ -149,6 +149,7 @@ CPPSRC = main.cpp \
encoder.cpp \
lcd_ili9341.cpp \
ui.cpp \
ui_alphanum.cpp \
ui_text.cpp \
ui_widget.cpp \
ui_painter.cpp \
@@ -170,6 +171,7 @@ CPPSRC = main.cpp \
ui_console.cpp \
ui_receiver.cpp \
ui_spectrum.cpp \
ui_loadmodule.cpp \
receiver_model.cpp \
transmitter_model.cpp \
spectrum_color_lut.cpp \

View File

@@ -22,12 +22,14 @@
#include "m4_startup.hpp"
#include "hal.h"
#include "lpc43xx_cpp.hpp"
#include "message.hpp"
#include "portapack_shared_memory.hpp"
#include <cstring>
char * modhash;
/* TODO: OK, this is cool, but how do I put the M4 to sleep so I can switch to
* a different image? Other than asking the old image to sleep while the M0
* makes changes?
@@ -37,6 +39,7 @@
*/
void m4_init(const portapack::spi_flash::region_t from, const portapack::memory::region_t to) {
/* Initialize M4 code RAM */
// DEBUG
std::memcpy(reinterpret_cast<void*>(to.base()), from.base(), from.size);
/* M4 core is assumed to be sleeping with interrupts off, so we can mess
@@ -48,6 +51,58 @@ void m4_init(const portapack::spi_flash::region_t from, const portapack::memory:
LPC_RGU->RESET_CTRL[0] = (1 << 13);
}
int m4_load_image(void) {
uint32_t mod_size;
UINT bw;
uint8_t i;
char md5sum[16];
FILINFO modinfo;
FIL modfile;
DIR rootdir;
FRESULT res;
// Scan SD card root directory for files with the right md5 fingerprint at the right location
f_opendir(&rootdir, "/");
for (;;) {
res = f_readdir(&rootdir, &modinfo);
if (res != FR_OK || modinfo.fname[0] == 0) break;
if (!(modinfo.fattrib & AM_DIR)) {
f_open(&modfile, modinfo.fname, FA_OPEN_EXISTING | FA_READ);
f_lseek(&modfile, 26);
f_read(&modfile, &md5sum, 16, &bw);
for (i = 0; i < 16; i++) {
if (md5sum[i] != modhash[i]) break;
}
if (i == 16) {
f_lseek(&modfile, 6);
f_read(&modfile, &mod_size, 4, &bw);
f_lseek(&modfile, 256);
f_read(&modfile, reinterpret_cast<void*>(portapack::memory::map::m4_code.base()), mod_size, &bw);
LPC_RGU->RESET_CTRL[0] = (1 << 13);
f_close(&modfile);
return 1;
}
f_close(&modfile);
}
}
return 0;
}
void m4_switch(const char * hash) {
modhash = const_cast<char*>(hash);
// Ask M4 to enter loop in RAM
BasebandConfiguration baseband_switch {
.mode = 0xFF,
.sampling_rate = 0,
.decimation_factor = 1,
};
BasebandConfigurationMessage message { baseband_switch };
shared_memory.baseband_queue.push(message);
}
void m4_request_shutdown() {
ShutdownMessage shutdown_message;
shared_memory.baseband_queue.push(shutdown_message);

View File

@@ -24,10 +24,14 @@
#include <cstddef>
#include "ff.h"
#include "memory_map.hpp"
#include "spi_image.hpp"
#include "ui_navigation.hpp"
void m4_init(const portapack::spi_flash::region_t from, const portapack::memory::region_t to);
void m4_request_shutdown();
void m4_switch(const char * hash);
int m4_load_image(void);
#endif/*__M4_STARTUP_H__*/

View File

@@ -19,8 +19,12 @@
* Boston, MA 02110-1301, USA.
*/
//Reims ANFR 822519
//TODO: UC/LC update buttons in keyboard view
//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: LCD backlight PWM
//TODO: BUG: Crash after TX stop
//TODO: Check bw setting in LCR TX
//TODO: BUG: Crash after PSN entry in RDS TX
//TODO: Dynamically load baseband code depending on mode (disable M4 & interrupts, load, reset)
//TODO: Bodet :)
//TODO: Whistler
@@ -29,14 +33,8 @@
//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"

View File

@@ -0,0 +1,2 @@
const char md5_baseband[16] = {0xca,0x05,0xc3,0xbf,0x78,0x10,0xad,0xac,0x2a,0x2b,0x31,0x19,0xf9,0xe8,0x91,0x26,};
const char md5_baseband_tx[16] = {0xe7,0x28,0x33,0x67,0x45,0x37,0x1e,0x13,0x3c,0x85,0xb5,0x91,0x51,0xaa,0xed,0x4f,};

View File

@@ -0,0 +1,173 @@
/*
* 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_alphanum.hpp"
#include "ch.h"
#include "ff.h"
#include "portapack.hpp"
#include "radio.hpp"
#include "hackrf_hal.hpp"
#include "portapack_shared_memory.hpp"
#include <cstring>
using namespace hackrf::one;
namespace ui {
AlphanumView::AlphanumView(
NavigationView& nav,
char txt[],
uint8_t max_len
) {
_max_len = max_len;
_lowercase = false;
static constexpr Style style_alpha {
.font = font::fixed_8x16,
.background = Color::red(),
.foreground = Color::black(),
};
static constexpr Style style_num {
.font = font::fixed_8x16,
.background = Color::yellow(),
.foreground = Color::black(),
};
txtidx = 0;
memcpy(txtinput, txt, max_len+1);
add_child(&text_input);
const auto button_fn = [this](Button& button) {
this->on_button(button);
};
size_t n = 0;
for(auto& button : buttons) {
add_child(&button);
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
});
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("UC");
set_uppercase();
} else {
_lowercase = true;
button_lowercase.set_text("LC");
set_lowercase();
}
};
add_child(&button_done);
button_done.on_select = [this, &nav, txt, max_len](Button&) {
memcpy(txt, txtinput, max_len+1);
on_changed(this->value());
nav.pop();
};
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();
}
char * AlphanumView::value() {
return txtinput;
}
void AlphanumView::on_button(Button& button) {
const auto s = button.text();
if( s == "<" ) {
char_delete();
} else {
char_add(s[0]);
}
update_text();
}
void AlphanumView::char_add(const char c) {
if (txtidx < _max_len) {
txtinput[txtidx] = c;
txtidx++;
}
}
void AlphanumView::char_delete() {
if (txtidx) {
txtidx--;
txtinput[txtidx] = ' ';
}
}
void AlphanumView::update_text() {
text_input.set(txtinput);
}
}

View File

@@ -0,0 +1,83 @@
/*
* 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 AlphanumView : public View {
public:
std::function<void(char *)> on_changed;
AlphanumView(NavigationView& nav, char txt[], uint8_t max_len);
void focus() override;
char * value();
uint8_t txtidx;
void char_add(const char c);
void char_delete();
private:
uint8_t _max_len;
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 }
};
std::array<Button, 40> buttons;
Button button_lowercase {
{ 88+64+16, 270, 32, 24 },
"UC"
};
Button button_done {
{ 88, 270, 64, 24 },
"Done"
};
void on_button(Button& button);
void update_text();
};
} /* namespace ui */

View File

@@ -144,10 +144,30 @@ void DebugSDView::paint(Painter& painter) {
DebugSDView::DebugSDView(NavigationView& nav) {
add_children({ {
&text_title,
&text_modules,
&button_makefile,
&button_done
} });
FIL fdst;
char buffer[256];
uint8_t mods_version, mods_count;
UINT bw;
const auto open_result = f_open(&fdst, "ppmods.bin", FA_OPEN_EXISTING | FA_READ);
if (open_result == FR_OK) {
f_read(&fdst, &mods_version, 1, &bw);
if (mods_version == 1) {
f_read(&fdst, &mods_count, 1, &bw);
f_read(&fdst, buffer, 8, &bw);
f_read(&fdst, buffer, 16, &bw);
buffer[16] = 0;
text_modules.set(buffer);
} else {
text_modules.set("Bad version");
}
}
button_makefile.on_select = [this](Button&){
FATFS fs; /* Work area (file system object) for logical drives */
FIL fdst; /* File objects */

View File

@@ -155,7 +155,12 @@ public:
private:
Text text_title {
{ 32, 16, 128, 16 },
"SD card debug",
"SD card debug"
};
Text text_modules {
{ 8, 32, 28 * 8, 16 },
"TESTTESTTESTTESTTESTTESTTEST"
};
Button button_makefile {

View File

@@ -192,7 +192,8 @@ LCRView::LCRView(
memset(litteral, 0, 5*8);
memset(rgsb, 0, 5);
strcpy(rgsb, RGSB_list[0]);
strcpy(rgsb, RGSB_list[29]);
button_setrgsb.set_text(rgsb);
add_children({ {
&text_recap,
@@ -282,10 +283,10 @@ LCRView::LCRView(
make_frame();
shared_memory.afsk_samples_per_bit = 228000/portapack::persistent_memory::afsk_bitrate();
shared_memory.afsk_phase_inc_mark = portapack::persistent_memory::afsk_mark_freq()*(65536*1024)/2280;
shared_memory.afsk_phase_inc_space = portapack::persistent_memory::afsk_space_freq()*(65536*1024)/2280;
shared_memory.afsk_phase_inc_mark = portapack::persistent_memory::afsk_mark_freq()*(0x10000*256)/2280;
shared_memory.afsk_phase_inc_space = portapack::persistent_memory::afsk_space_freq()*(0x10000*256)/2280;
shared_memory.afsk_fmmod = portapack::persistent_memory::afsk_bw()*33;
shared_memory.afsk_fmmod = portapack::persistent_memory::afsk_bw() * 8;
memset(shared_memory.lcrdata, 0, 256);
memcpy(shared_memory.lcrdata, lcrframe_f, 256);
@@ -297,8 +298,10 @@ LCRView::LCRView(
[this,&transmitter_model](Message* const p) {
const auto message = static_cast<const TXDoneMessage*>(p);
if (message->n > 0) {
char str[8] = "0... ";
str[0] = hexify(message->n);
char str[8];
strcpy(str, to_string_dec_int(message->n).c_str());
strcat(str, "/");
strcat(str, to_string_dec_int(shared_memory.afsk_repeat).c_str());
text_status.set(str);
} else {
text_status.set("Done ! ");
@@ -307,7 +310,10 @@ LCRView::LCRView(
}
);
text_status.set("0... ");
char str[8];
strcpy(str, "0/");
strcat(str, to_string_dec_int(shared_memory.afsk_repeat).c_str());
text_status.set(str);
transmitter_model.enable();
};

View File

@@ -0,0 +1,89 @@
/*
* 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_loadmodule.hpp"
#include "ch.h"
#include "ff.h"
#include "hackrf_gpio.hpp"
#include "portapack.hpp"
#include "hackrf_hal.hpp"
#include <cstring>
#include <stdio.h>
using namespace hackrf::one;
namespace ui {
void LoadModuleView::focus() {
button_ok.focus();
}
void LoadModuleView::paint(Painter& painter) {
}
void LoadModuleView::on_hide() {
auto& message_map = context().message_map();
message_map.unregister_handler(Message::ID::ReadyForSwitch);
}
void LoadModuleView::on_show() {
auto& message_map = context().message_map();
message_map.register_handler(Message::ID::ReadyForSwitch,
[this](Message* const p) {
const auto message = static_cast<const ReadyForSwitchMessage*>(p);
if (m4_load_image()) {
text_info.set("Module loaded :)");
_mod_loaded = true;
} else {
text_info.set("Module not found :(");
_mod_loaded = false;
}
}
);
m4_switch(_hash);
}
LoadModuleView::LoadModuleView(
NavigationView& nav,
const char * hash,
View* new_view
)
{
add_children({ {
&text_info,
&button_ok
} });
_hash = hash;
button_ok.on_select = [this,&nav,new_view](Button&){
nav.pop();
if (_mod_loaded == true) nav.push(new_view);
};
}
} /* namespace ui */

View File

@@ -0,0 +1,56 @@
/*
* 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 "m4_startup.hpp"
#include "ui_font_fixed_8x16.hpp"
namespace ui {
class LoadModuleView : public View {
public:
LoadModuleView(NavigationView& nav, const char * hash, View* new_view);
void on_show() override;
void on_hide() override;
void focus() override;
void paint(Painter& painter) override;
private:
const char * _hash;
bool _mod_loaded = false;
Text text_info {
{ 8, 64, 224, 16 },
"Searching module..."
};
Button button_ok {
{ 88, 128, 64, 32 },
"OK"
};
};
} /* namespace ui */

View File

@@ -35,10 +35,14 @@
#include "ui_lcr.hpp"
#include "ui_whistle.hpp"
#include "ui_jammer.hpp"
#include "ui_loadmodule.hpp"
#include "portapack.hpp"
#include "m4_startup.hpp"
#include "spi_image.hpp"
#include "modules.h"
using namespace portapack;
namespace ui {
@@ -104,17 +108,20 @@ void NavigationView::focus() {
/* SystemMenuView ********************************************************/
SystemMenuView::SystemMenuView(NavigationView& nav) {
add_items<10>({ {
{ "Play dead", ui::Color::red(), [&nav](){ nav.push(new PlayDeadView { nav, false }); } },
{ "Receiver", ui::Color::white(), [&nav](){ nav.push(new ReceiverView { nav, receiver_model }); } },
{ "Jammer", ui::Color::white(), [&nav](){ nav.push(new JammerView { 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 }); } },
{ "Debug", ui::Color::white(), [&nav](){ nav.push(new DebugMenuView { nav }); } },
{ "HackRF", ui::Color::white(), [&nav](){ nav.push(new HackRFFirmwareView { nav }); } },
add_items<11>({ {
{ "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 } }); } },
//{ "Nordic/BTLE RX", ui::Color::cyan(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
{ "Jammer", ui::Color::white(), [&nav](){ nav.push(new JammerView { nav, transmitter_model }); } },
{ "Audio file TX", ui::Color::white(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
//{ "Encoder TX", ui::Color::green(), [&nav](){ nav.push(new NotImplementedView { nav }); } },
{ "Whistle", ui::Color::purple(), [&nav](){ nav.push(new WhistleView { nav, transmitter_model }); } },
{ "RDS TX", ui::Color::yellow(), [&nav](){ nav.push(new RDSView { nav, transmitter_model }); } },
{ "TEDI/LCR TX", ui::Color::orange(), [&nav](){ nav.push(new LCRView { nav, transmitter_model }); } },
{ "Setup", ui::Color::white(), [&nav](){ nav.push(new SetupMenuView { nav }); } },
{ "About", ui::Color::white(), [&nav](){ nav.push(new AboutView { nav }); } },
{ "Debug", ui::Color::white(), [&nav](){ nav.push(new DebugMenuView { nav }); } },
{ "HackRF", ui::Color::white(), [&nav](){ nav.push(new HackRFFirmwareView { nav }); } },
} });
}

View File

@@ -36,140 +36,6 @@
using namespace hackrf::one;
namespace ui {
AlphanumView::AlphanumView(
NavigationView& nav,
char txt[],
uint8_t max_len
) {
_max_len = max_len;
_lowercase = false;
static constexpr Style style_alpha {
.font = font::fixed_8x16,
.background = Color::red(),
.foreground = Color::black(),
};
static constexpr Style style_num {
.font = font::fixed_8x16,
.background = Color::yellow(),
.foreground = Color::black(),
};
txtidx = 0;
memcpy(txtinput, txt, max_len+1);
add_child(&text_input);
const auto button_fn = [this](Button& button) {
this->on_button(button);
};
size_t n = 0;
for(auto& button : buttons) {
add_child(&button);
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
});
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("UC");
set_uppercase();
} else {
_lowercase = true;
button_lowercase.set_text("LC");
set_lowercase();
}
};
add_child(&button_done);
button_done.on_select = [this, &nav, txt, max_len](Button&) {
memcpy(txt, txtinput, max_len+1);
on_changed(this->value());
nav.pop();
};
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();
}
char * AlphanumView::value() {
return txtinput;
}
void AlphanumView::on_button(Button& button) {
const auto s = button.text();
if( s == "<" ) {
char_delete();
} else {
char_add(s[0]);
}
update_text();
}
void AlphanumView::char_add(const char c) {
if (txtidx < _max_len) {
txtinput[txtidx] = c;
txtidx++;
}
}
void AlphanumView::char_delete() {
if (txtidx) {
txtidx--;
txtinput[txtidx] = ' ';
}
}
void AlphanumView::update_text() {
text_input.set(txtinput);
}
void RDSView::focus() {
button_setpsn.focus();

View File

@@ -24,12 +24,13 @@
#include "ui_spectrum.hpp"
#include "ui_console.hpp"
#include "ff.h"
#include "portapack.hpp"
using namespace portapack;
#include "ais_baseband.hpp"
#include "ff.h"
#include "m4_startup.hpp"
namespace ui {