Merge remote-tracking branch 'upstream/master'

Base class for text entry
This commit is contained in:
furrtek
2017-06-21 03:25:27 +01:00
131 changed files with 19385 additions and 5412 deletions
+20 -9
View File
@@ -72,8 +72,11 @@ set(USE_FPU no)
# Project, sources and paths
#
set(CPLD_SVF_PATH ${HARDWARE_PATH}/portapack_h1/cpld/output_files/portapack_h1_cpld.svf)
set(CPLD_DATA_CPP ${CMAKE_CURRENT_BINARY_DIR}/portapack_cpld_data.cpp)
set(CPLD_20150901_SVF_PATH ${HARDWARE_PATH}/portapack_h1/cpld/20150901/output_files/portapack_h1_cpld.svf)
set(CPLD_20150901_DATA_CPP ${CMAKE_CURRENT_BINARY_DIR}/portapack_cpld_20150901_data.cpp)
set(CPLD_20170522_SVF_PATH ${HARDWARE_PATH}/portapack_h1/cpld/20170522/output_files/portapack_h1_cpld.svf)
set(CPLD_20170522_DATA_CPP ${CMAKE_CURRENT_BINARY_DIR}/portapack_cpld_20170522_data.cpp)
set(HACKRF_CPLD_DATA_HPP ${CMAKE_CURRENT_BINARY_DIR}/hackrf_cpld_data.hpp)
set(HACKRF_CPLD_DATA_CPP ${CMAKE_CURRENT_BINARY_DIR}/hackrf_cpld_data.cpp)
@@ -123,8 +126,9 @@ set(CPPSRC
clock_manager.cpp
si5351.cpp
${COMMON}/wm8731.cpp
${COMMON}/ak4951.cpp
radio.cpp
baseband_cpld.cpp
${COMMON}/baseband_cpld.cpp
tuning.cpp
rf_path.cpp
rffc507x.cpp
@@ -242,8 +246,9 @@ set(CPPSRC
${COMMON}/cpld_xilinx.cpp
${COMMON}/jtag.cpp
${COMMON}/jtag_tap.cpp
cpld_update.cpp
${CPLD_DATA_CPP}
${COMMON}/cpld_update.cpp
${CPLD_20150901_DATA_CPP}
${CPLD_20170522_DATA_CPP}
${HACKRF_CPLD_DATA_CPP}
)
@@ -362,14 +367,20 @@ include(${RULESPATH}/rules.cmake)
##############################################################################
add_custom_command(
OUTPUT ${CPLD_DATA_CPP}
COMMAND ${EXTRACT_CPLD_DATA} ${CPLD_SVF_PATH} >${CPLD_DATA_CPP}
DEPENDS ${EXTRACT_CPLD_DATA} ${CPLD_SVF_PATH}
OUTPUT ${CPLD_20150901_DATA_CPP}
COMMAND ${EXTRACT_CPLD_DATA} ${CPLD_20150901_SVF_PATH} rev_20150901 >${CPLD_20150901_DATA_CPP}
DEPENDS ${EXTRACT_CPLD_DATA} ${CPLD_20150901_SVF_PATH}
)
add_custom_command(
OUTPUT ${CPLD_20170522_DATA_CPP}
COMMAND ${EXTRACT_CPLD_DATA} ${CPLD_20170522_SVF_PATH} rev_20170522 >${CPLD_20170522_DATA_CPP}
DEPENDS ${EXTRACT_CPLD_DATA} ${CPLD_20170522_SVF_PATH}
)
add_custom_command(
OUTPUT ${HACKRF_CPLD_DATA_HPP} ${HACKRF_CPLD_DATA_CPP}
COMMAND ${EXTRACT_SVF_DATA_XC2C64A} ${HACKRF_CPLD_SVF_PATH} hackrf::one::cpld::verify_blocks ${HACKRF_CPLD_DATA_HPP} ${HACKRF_CPLD_DATA_CPP}
COMMAND ${EXTRACT_SVF_DATA_XC2C64A} ${HACKRF_CPLD_SVF_PATH} hackrf::one::cpld::verify_blocks ${HACKRF_CPLD_DATA_CPP}
DEPENDS ${EXTRACT_SVF_DATA_XC2C64A} ${HACKRF_CPLD_SVF_PATH}
)
+40 -29
View File
@@ -23,11 +23,9 @@
#include "audio.hpp"
#include "portapack.hpp"
using portapack::i2c0;
using portapack::clock_manager;
#include "wm8731.hpp"
using wolfson::wm8731::WM8731;
#include "portapack_hal.hpp"
#include "i2s.hpp"
using namespace lpc43xx;
@@ -98,24 +96,10 @@ constexpr i2s::ConfigDMA i2s0_config_dma {
},
};
constexpr uint8_t wm8731_i2c_address = 0x1a;
WM8731 audio_codec { i2c0, wm8731_i2c_address };
static audio::Codec* audio_codec = nullptr;
} /* namespace */
namespace input {
void start() {
i2s::i2s0::rx_start();
}
void stop() {
i2s::i2s0::rx_stop();
}
} /* namespace input */
namespace output {
void start() {
@@ -130,53 +114,80 @@ void stop() {
void mute() {
i2s::i2s0::tx_mute();
audio_codec.headphone_mute();
audio_codec->headphone_disable();
}
void unmute() {
i2s::i2s0::tx_unmute();
audio_codec->headphone_enable();
}
} /* namespace output */
namespace input {
void start() {
audio_codec->microphone_enable();
i2s::i2s0::rx_start();
}
void stop() {
i2s::i2s0::rx_stop();
audio_codec->microphone_disable();
}
} /* namespace input */
namespace headphone {
volume_range_t volume_range() {
return wolfson::wm8731::headphone_gain_range;
return audio_codec->headphone_gain_range();
}
void set_volume(const volume_t volume) {
audio_codec.set_headphone_volume(volume);
audio_codec->set_headphone_volume(volume);
}
} /* namespace headphone */
namespace debug {
int reg_count() {
return wolfson::wm8731::reg_count;
size_t reg_count() {
return audio_codec->reg_count();
}
uint16_t reg_read(const int register_number) {
return audio_codec.read(register_number);
uint32_t reg_read(const size_t register_number) {
return audio_codec->reg_read(register_number);
}
std::string codec_name() {
return audio_codec->name();
}
size_t reg_bits() {
return audio_codec->reg_bits();
}
} /* namespace debug */
void init() {
void init(audio::Codec* const codec) {
audio_codec = codec;
clock_manager.start_audio_pll();
audio_codec.init();
audio_codec->init();
i2s::i2s0::configure(
i2s0_config_tx,
i2s0_config_rx,
i2s0_config_dma
);
// Set pin mode, since it's likely GPIO (as left after CPLD JTAG interactions).
portapack::pin_i2s0_rx_sda.mode(3);
}
void shutdown() {
audio_codec.reset();
audio_codec->reset();
output::stop();
}
+30 -3
View File
@@ -26,9 +26,34 @@
#include "volume.hpp"
#include <cstdint>
#include <cstddef>
#include <string>
namespace audio {
class Codec {
public:
virtual ~Codec() { }
virtual std::string name() const = 0;
virtual bool reset() = 0;
virtual void init() = 0;
virtual void headphone_enable() = 0;
virtual void headphone_disable() = 0;
virtual volume_range_t headphone_gain_range() const = 0;
virtual void set_headphone_volume(const volume_t volume) = 0;
virtual void microphone_enable() = 0;
virtual void microphone_disable() = 0;
virtual size_t reg_count() const = 0;
virtual size_t reg_bits() const = 0;
virtual uint32_t reg_read(const size_t register_number) = 0;
};
namespace output {
void start();
@@ -56,12 +81,14 @@ void set_volume(const volume_t volume);
namespace debug {
int reg_count();
uint16_t reg_read(const int register_number);
size_t reg_count();
uint32_t reg_read(const size_t register_number);
std::string codec_name();
size_t reg_bits();
} /* namespace debug */
void init();
void init(audio::Codec* const codec);
void shutdown();
enum class Rate {
-38
View File
@@ -1,38 +0,0 @@
/*
* 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 "baseband_cpld.hpp"
#include "hackrf_gpio.hpp"
using namespace hackrf::one;
namespace baseband {
void CPLD::init() {
set_invert(false);
gpio_baseband_invert.output();
}
void CPLD::set_invert(const bool invert) {
gpio_baseband_invert.write(invert);
}
}
-40
View File
@@ -1,40 +0,0 @@
/*
* 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 __BASEBAND_CPLD_H__
#define __BASEBAND_CPLD_H__
#include <cstdint>
namespace baseband {
class CPLD {
public:
void init();
void set_invert(const bool invert);
private:
};
}
#endif/*__BASEBAND_CPLD_H__*/
-122
View File
@@ -1,122 +0,0 @@
/*
* 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 "cpld_update.hpp"
#include "hackrf_gpio.hpp"
#include "portapack_hal.hpp"
#include "jtag_target_gpio.hpp"
#include "cpld_max5.hpp"
#include "cpld_xilinx.hpp"
#include "portapack_cpld_data.hpp"
#include "hackrf_cpld_data.hpp"
bool cpld_update_if_necessary() {
jtag::GPIOTarget target {
portapack::gpio_cpld_tck,
portapack::gpio_cpld_tms,
portapack::gpio_cpld_tdi,
portapack::gpio_cpld_tdo
};
jtag::JTAG jtag { target };
cpld::max5::CPLD cpld { jtag };
/* Unknown state */
cpld.reset();
cpld.run_test_idle();
/* Run-Test/Idle */
if( !cpld.idcode_ok() ) {
return false;
}
/* Enter ISP:
* Ensures that the I/O pins transition smoothly from user mode to ISP
* mode. All pins are tri-stated.
*/
cpld.enter_isp();
/* If silicon ID doesn't match, there's a serious problem. Leave CPLD
* in passive state.
*/
if( !cpld.silicon_id_ok() ) {
return false;
}
/* Verify CPLD contents against current bitstream. */
auto ok = cpld.verify(
portapack::cpld::block_0,
portapack::cpld::block_1
);
/* CPLD verifies incorrectly. Erase and program with current bitstream. */
if( !ok ) {
ok = cpld.program(
portapack::cpld::block_0,
portapack::cpld::block_1
);
}
/* If programming OK, reset CPLD to user mode. Otherwise leave it in
* passive (ISP) state.
*/
if( ok ) {
cpld.exit_isp();
}
return ok;
}
static jtag::GPIOTarget jtag_target_hackrf() {
return {
hackrf::one::gpio_cpld_tck,
hackrf::one::gpio_cpld_tms,
hackrf::one::gpio_cpld_tdi,
hackrf::one::gpio_cpld_tdo,
};
}
bool cpld_hackrf_load_sram() {
auto jtag_target_hackrf_cpld = jtag_target_hackrf();
cpld::xilinx::XC2C64A hackrf_cpld { jtag_target_hackrf_cpld };
hackrf_cpld.write_sram(hackrf::one::cpld::verify_blocks);
const auto ok = hackrf_cpld.verify_sram(hackrf::one::cpld::verify_blocks);
return ok;
}
bool cpld_hackrf_verify_eeprom() {
auto jtag_target_hackrf_cpld = jtag_target_hackrf();
cpld::xilinx::XC2C64A hackrf_cpld { jtag_target_hackrf_cpld };
const auto ok = hackrf_cpld.verify_eeprom(hackrf::one::cpld::verify_blocks);
return ok;
}
void cpld_hackrf_init_from_eeprom() {
auto jtag_target_hackrf_cpld = jtag_target_hackrf();
cpld::xilinx::XC2C64A hackrf_cpld { jtag_target_hackrf_cpld };
hackrf_cpld.init_from_eeprom();
}
-31
View File
@@ -1,31 +0,0 @@
/*
* 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 __CPLD_UPDATE_H__
#define __CPLD_UPDATE_H__
bool cpld_update_if_necessary();
bool cpld_hackrf_load_sram();
bool cpld_hackrf_verify_eeprom();
void cpld_hackrf_init_from_eeprom();
#endif/*__CPLD_UPDATE_H__*/
+16 -13
View File
@@ -5,7 +5,7 @@
/ FatFs - FAT file system module configuration file
/---------------------------------------------------------------------------*/
#define _FFCONF 80186 /* Revision ID */
#define _FFCONF 68300 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
@@ -76,7 +76,7 @@
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
/ 1 - ASCII (No support of extended character. Non-LFN cfg. only)
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
@@ -151,7 +151,7 @@
/---------------------------------------------------------------------------*/
#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
/* Number of volumes (logical drives) to be used. (1-10) */
#define _STR_VOLUME_ID 0
@@ -175,11 +175,11 @@
#define _MIN_SS 512
#define _MAX_SS 512
/* These options configure the range of sector size to be supported. (512, 1024,
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
/ 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
/ disk_ioctl() function. */
/ to variable sector size and GET_SECTOR_SIZE command needs to be implemented to
/ the disk_ioctl() function. */
#define _USE_TRIM 0
@@ -207,15 +207,15 @@
#define _FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS bytes.
/ At the tiny configuration, size of file object (FIL) is shrinked _MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the file system object (FATFS) is used for the file data transfer. */
#define _FS_EXFAT 0
/* This option switches support of exFAT file system in addition to the traditional
/ FAT file system. (0:Disable or 1:Enable) To enable exFAT, also LFN must be enabled.
/ Note that enabling exFAT discards C89 compatibility. */
/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#define _FS_NORTC 0
@@ -228,7 +228,7 @@
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to get current time form real-time clock. _NORTC_MON,
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
@@ -261,8 +261,11 @@
/
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.c. */
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/* #include <windows.h> // O/S definitions */
/*--- End of configuration options ---*/
+11 -11
View File
@@ -130,23 +130,23 @@ static void event_loop() {
}
int main(void) {
portapack::init();
if( portapack::init() ) {
portapack::display.init();
portapack::io.init();
portapack::display.init();
sdcStart(&SDCD1, nullptr);
sdcStart(&SDCD1, nullptr);
controls_init();
lcd_frame_sync_configure();
rtc_interrupt_enable();
controls_init();
lcd_frame_sync_configure();
rtc_interrupt_enable();
event_loop();
event_loop();
sdcDisconnect(&SDCD1);
sdcStop(&SDCD1);
sdcDisconnect(&SDCD1);
sdcStop(&SDCD1);
portapack::shutdown();
}
portapack::shutdown();
m4_init(portapack::spi_flash::image_tag_hackrf, portapack::memory::map::m4_code_hackrf);
m0_halt();
+79 -19
View File
@@ -21,6 +21,8 @@
#include "portapack.hpp"
#include "portapack_hal.hpp"
#include "portapack_dma.hpp"
#include "portapack_cpld_data.hpp"
#include "portapack_persistent_memory.hpp"
#include "hackrf_hal.hpp"
@@ -32,8 +34,16 @@ using namespace hackrf::one;
#include "touch_adc.hpp"
#include "audio.hpp"
#include "wm8731.hpp"
using wolfson::wm8731::WM8731;
#include "ak4951.hpp"
using asahi_kasei::ak4951::AK4951;
#include "cpld_update.hpp"
#include "optional.hpp"
namespace portapack {
portapack::IO io {
@@ -60,6 +70,9 @@ ClockManager clock_manager {
i2c0, clock_generator
};
WM8731 audio_codec_wm8731 { i2c0, 0x1a };
AK4951 audio_codec_ak4951 { i2c0, 0x12 };
ReceiverModel receiver_model;
TemperatureLogger temperature_logger;
@@ -106,7 +119,53 @@ private:
static Power power;
void init() {
enum class PortaPackModel {
R1_20150901,
R2_20170522,
};
static PortaPackModel portapack_model() {
static Optional<PortaPackModel> model;
if( !model.is_valid() ) {
if( audio_codec_wm8731.detected() ) {
model = PortaPackModel::R1_20150901;
} else {
model = PortaPackModel::R2_20170522;
}
}
return model.value();
}
static audio::Codec* portapack_audio_codec() {
return (portapack_model() == PortaPackModel::R2_20170522)
? static_cast<audio::Codec*>(&audio_codec_ak4951)
: static_cast<audio::Codec*>(&audio_codec_wm8731)
;
}
static const portapack::cpld::Config& portapack_cpld_config() {
return (portapack_model() == PortaPackModel::R2_20170522)
? portapack::cpld::rev_20170522::config
: portapack::cpld::rev_20150901::config
;
}
static void shutdown_base() {
clock_manager.shutdown();
power.shutdown();
// TODO: Wait a bit for supplies to discharge?
chSysDisable();
systick_stop();
hackrf::one::reset();
}
bool init() {
for(const auto& pin : pins) {
pin.init();
}
@@ -147,7 +206,18 @@ void init() {
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
clock_manager.run_at_full_speed();
audio::init();
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
shutdown_base();
return false;
}
if( !hackrf::cpld::load_sram() ) {
chSysHalt();
}
portapack::io.init();
audio::init(portapack_audio_codec());
clock_manager.enable_first_if_clock();
clock_manager.enable_second_if_clock();
@@ -156,33 +226,23 @@ void init() {
touch::adc::init();
if( !cpld_update_if_necessary() ) {
chSysHalt();
}
LPC_CREG->DMAMUX = portapack::gpdma_mux;
gpdma::controller.enable();
if( !cpld_hackrf_load_sram() ) {
chSysHalt();
}
return true;
}
void shutdown() {
gpdma::controller.disable();
display.shutdown();
radio::disable();
audio::shutdown();
cpld_hackrf_init_from_eeprom();
hackrf::cpld::init_from_eeprom();
clock_manager.shutdown();
power.shutdown();
// TODO: Wait a bit for supplies to discharge?
chSysDisable();
systick_stop();
hackrf::one::reset();
shutdown_base();
}
extern "C" {
+1 -1
View File
@@ -53,7 +53,7 @@ extern uint8_t bl_tick_counter;
extern TemperatureLogger temperature_logger;
void init();
bool init();
void shutdown();
} /* namespace portapack */
+2 -4
View File
@@ -132,8 +132,6 @@ AboutView::AboutView(
NavigationView& nav
)
{
//uint8_t p, c;
add_children({
&text_cpld_hackrf,
&text_cpld_hackrf_status,
@@ -150,13 +148,13 @@ AboutView::AboutView(
add_child(&text);
}
if( cpld_hackrf_verify_eeprom() ) {
if( hackrf::cpld::verify_eeprom() ) {
text_cpld_hackrf_status.set(" OK");
} else {
text_cpld_hackrf_status.set("BAD");
}
button_ok.on_select = [this,&nav](Button&){
button_ok.on_select = [&nav](Button&){
nav.pop();
};
}
+1 -1
View File
@@ -136,7 +136,7 @@ ADSBTxView::ADSBTxView(NavigationView& nav) {
generate_frame();
};
button_callsign.on_select = [this, &nav](Button&) {
text_entry(nav, &callsign, 9);
text_prompt(nav, &callsign, 9);
};
field_altitude.set_value(11000);
+2 -57
View File
@@ -26,11 +26,8 @@
#include "hackrf_hal.hpp"
#include "portapack_shared_memory.hpp"
#include <cstring>
#include <algorithm>
using namespace hackrf::one;
namespace ui {
void AlphanumView::paint(Painter&) {
@@ -41,23 +38,14 @@ AlphanumView::AlphanumView(
NavigationView& nav,
std::string * str,
size_t max_length
) : _max_length(max_length),
_str(str)
) : TextEntryView(nav, str, max_length)
{
size_t n;
// Trim from right
_str->erase(std::find_if(_str->rbegin(), _str->rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), _str->end());
cursor_pos = _str->length();
_str->resize(_max_length, 0);
add_children({
&text_input,
&button_mode,
&text_raw,
&field_raw,
&button_ok
&field_raw
});
const auto button_fn = [this](Button& button) {
@@ -97,22 +85,6 @@ AlphanumView::AlphanumView(
update_text();
}
void AlphanumView::draw_cursor() {
Point draw_pos;
draw_pos = {text_input.screen_rect().location().x() + 8 + std::min((Coord)cursor_pos, (Coord)28) * 8,
text_input.screen_rect().location().y() + 16};
portapack::display.fill_rectangle(
{{text_input.screen_rect().location().x(), draw_pos.y()}, {text_input.screen_rect().size().width(), 4}},
Color::black()
);
portapack::display.fill_rectangle(
{draw_pos, {8, 4}},
Color::white()
);
}
void AlphanumView::set_mode(const uint32_t new_mode) {
size_t n = 0;
@@ -137,10 +109,6 @@ void AlphanumView::set_mode(const uint32_t new_mode) {
button_mode.set_text(key_sets[0].first);
}
void AlphanumView::focus() {
button_ok.focus();
}
void AlphanumView::on_button(Button& button) {
const auto c = button.text()[0];
@@ -152,27 +120,4 @@ void AlphanumView::on_button(Button& button) {
update_text();
}
void AlphanumView::char_add(const char c) {
if (cursor_pos >= _max_length) return;
_str->replace(cursor_pos, 1, 1, c);
cursor_pos++;
}
void AlphanumView::char_delete() {
if (!cursor_pos) return;
cursor_pos--;
_str->replace(cursor_pos, 1, 1, 0);
}
void AlphanumView::update_text() {
if (cursor_pos <= 28)
text_input.set(' ' + *_str + std::string(_max_length - _str->length(), ' '));
else
text_input.set('<' + _str->substr(cursor_pos - 28, 28));
draw_cursor();
}
}
+3 -20
View File
@@ -26,16 +26,13 @@
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_painter.hpp"
#include "ui_textentry.hpp"
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "ui_font_fixed_8x16.hpp"
namespace ui {
class AlphanumView : public View {
class AlphanumView : public TextEntryView {
public:
std::function<void(std::string*)> on_changed { };
AlphanumView(NavigationView& nav, std::string * str, size_t max_length);
AlphanumView(const AlphanumView&) = delete;
@@ -44,9 +41,6 @@ public:
AlphanumView& operator=(AlphanumView&&) = delete;
void paint(Painter& painter) override;
void focus() override;
std::string title() const override { return "Text entry"; };
private:
const char * const keys_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ' .<";
@@ -59,21 +53,10 @@ private:
{ "Digit", keys_digit }
};
size_t _max_length { };
uint32_t cursor_pos { 0 };
uint32_t mode = 0; // Uppercase
std::string * _str { };
uint32_t mode = 0; // Uppercase
void char_add(const char c);
void char_delete();
void set_mode(const uint32_t new_mode);
void draw_cursor();
void on_button(Button& button);
void update_text();
Text text_input {
{ 0, 0, 240, 16 }
};
std::array<Button, 30> buttons { };
+18 -18
View File
@@ -173,12 +173,12 @@ void RegistersWidget::paint(Painter& painter) {
void RegistersWidget::draw_legend(const Coord left, Painter& painter) {
const auto pos = screen_pos();
for(int i=0; i<config.registers_count; i+=config.registers_per_row) {
for(int i=0; i<config.registers_count; i+=config.registers_per_row()) {
const Point offset {
left, (i / config.registers_per_row) * row_height
left, (i / config.registers_per_row()) * row_height
};
const auto text = to_string_hex(i, config.legend_length);
const auto text = to_string_hex(i, config.legend_length());
painter.draw_string(
pos + offset,
style().invert(),
@@ -195,13 +195,13 @@ void RegistersWidget::draw_values(
for(int i=0; i<config.registers_count; i++) {
const Point offset = {
left + config.legend_width() + 8 + (i % config.registers_per_row) * (config.value_width() + 8),
(i / config.registers_per_row) * row_height
left + config.legend_width() + 8 + (i % config.registers_per_row()) * (config.value_width() + 8),
(i / config.registers_per_row()) * row_height
};
const auto value = reader(i);
const auto text = to_string_hex(value, config.value_length);
const auto text = to_string_hex(value, config.value_length());
painter.draw_string(
pos + offset,
style(),
@@ -247,37 +247,37 @@ void RegistersView::focus() {
/* DebugPeripheralsMenuView **********************************************/
DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) {
add_items<4>({ {
{ "RFFC5072", ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
"RFFC5072", RegistersWidgetConfig { 31, 2, 4, 4 },
add_items({
{ "RFFC5072", ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
"RFFC5072", RegistersWidgetConfig { 31, 16 },
[](const size_t register_number) { return radio::debug::first_if::register_read(register_number); }
); } },
{ "MAX2837", ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
"MAX2837", RegistersWidgetConfig { 32, 2, 3, 4 },
{ "MAX2837", ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
"MAX2837", RegistersWidgetConfig { 32, 10 },
[](const size_t register_number) { return radio::debug::second_if::register_read(register_number); }
); } },
{ "Si5351C", ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
"Si5351C", RegistersWidgetConfig { 96, 2, 2, 8 },
{ "Si5351C", ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
"Si5351C", RegistersWidgetConfig { 96, 8 },
[](const size_t register_number) { return portapack::clock_generator.read_register(register_number); }
); } },
{ "WM8731",ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
"WM8731", RegistersWidgetConfig { audio::debug::reg_count(), 1, 3, 4 },
{ audio::debug::codec_name(), ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
audio::debug::codec_name(), RegistersWidgetConfig { audio::debug::reg_count(), audio::debug::reg_bits() },
[](const size_t register_number) { return audio::debug::reg_read(register_number); }
); } },
} });
});
on_left = [&nav](){ nav.pop(); };
}
/* DebugMenuView *********************************************************/
DebugMenuView::DebugMenuView(NavigationView& nav) {
add_items<4>({ {
add_items({
{ "Memory", ui::Color::white(), nullptr, [&nav](){ nav.push<DebugMemoryView>(); } },
{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } },
//{ "SD Card", ui::Color::white(), nullptr, [&nav](){ nav.push<SDCardDebugView>(); } },
{ "Peripherals", ui::Color::white(), nullptr, [&nav](){ nav.push<DebugPeripheralsMenuView>(); } },
{ "Temperature", ui::Color::white(), nullptr, [&nav](){ nav.push<TemperatureView>(); } },
} });
});
on_left = [&nav](){ nav.pop(); };
}
+17 -7
View File
@@ -131,20 +131,30 @@ private:
struct RegistersWidgetConfig {
int registers_count;
int legend_length;
int value_length;
int registers_per_row;
int register_bits;
constexpr int legend_length() const {
return (registers_count >= 0x10) ? 2 : 1;
}
constexpr int legend_width() const {
return legend_length * 8;
return legend_length() * 8;
}
constexpr int value_length() const {
return (register_bits + 3) / 4;
}
constexpr int value_width() const {
return value_length * 8;
return value_length() * 8;
}
constexpr int registers_per_row() const {
return (value_length() >= 3) ? 4 : 8;
}
constexpr int registers_row_length() const {
return (registers_per_row * (value_length + 1)) - 1;
return (registers_per_row() * (value_length() + 1)) - 1;
}
constexpr int registers_row_width() const {
@@ -156,7 +166,7 @@ struct RegistersWidgetConfig {
}
constexpr int rows() const {
return registers_count / registers_per_row;
return registers_count / registers_per_row();
}
};
+2 -4
View File
@@ -25,14 +25,12 @@
#include "portapack.hpp"
#include "event_m0.hpp"
//#include <cstring>
using namespace portapack;
namespace ui {
void FrequencySaveView::on_save_name() {
text_entry(nav_, &desc_buffer, 7, [this](std::string * buffer) {
text_prompt(nav_, &desc_buffer, 7, [this](std::string * buffer) {
database.entries.push_back({ value_, "", *buffer, (int32_t)options_category.selected_index_value() });
nav_.pop();
});
@@ -209,7 +207,7 @@ void FreqManView::on_edit_freq(rf::Frequency f) {
}
void FreqManView::on_edit_desc(NavigationView& nav) {
text_entry(nav, &desc_buffer, 28, [this](std::string * buffer) {
text_prompt(nav, &desc_buffer, 28, [this](std::string * buffer) {
database.entries[menu_view.highlighted()].description = *buffer;
//setup_list();
});
+6 -49
View File
@@ -26,7 +26,7 @@
#include "hackrf_hal.hpp"
#include "portapack_shared_memory.hpp"
#include <cstring>
#include <algorithm>
using namespace portapack;
@@ -40,24 +40,15 @@ HandWriteView::HandWriteView(
NavigationView& nav,
std::string * str,
size_t max_length
) : _max_length(max_length),
_str(str)
) : TextEntryView(nav, str, max_length)
{
size_t n;
// Trim from right
_str->erase(std::find_if(_str->rbegin(), _str->rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), _str->end());
cursor_pos = _str->length();
_str->resize(_max_length, 0);
// Handwriting alphabet definition here
handwriting = &handwriting_unistroke;
add_children({
&text_input,
&button_case,
&button_ok
&button_case
});
const auto button_fn = [this](Button& button) {
@@ -224,9 +215,8 @@ void HandWriteView::guess_letter() {
char_add('A' + symbol - 1);
clear_zone(Color::green(), true); // Green flash
} else {
if (cursor_pos) {
cursor_pos--;
_str->replace(cursor_pos, 1, 1, 0);
if (_cursor_pos) {
char_delete();
clear_zone(Color::yellow(), true); // Yellow flash
} else {
clear_zone(Color::red(), true); // Red flash
@@ -257,26 +247,7 @@ void HandWriteView::sample_pen() {
int16_t diff_x, diff_y;
uint8_t dir, dir_ud, dir_lr, stroke_prev;
// Blink cursor
if (!(sample_skip & 15)) {
Point draw_pos;
draw_pos = {text_input.screen_rect().location().x() + 8 + std::min((Coord)cursor_pos, (Coord)28) * 8,
text_input.screen_rect().location().y() + 16 - 4};
if (cursor) {
display.fill_rectangle(
{draw_pos, {text_input.screen_rect().size().width() - draw_pos.x(), 4}},
Color::black()
);
} else {
display.fill_rectangle(
{draw_pos, {8, 4}},
Color::white()
);
}
cursor = !cursor;
}
draw_cursor();
if (flash_timer) {
if (flash_timer == 1) clear_zone(Color::black(), false);
@@ -385,18 +356,4 @@ void HandWriteView::on_button(Button& button) {
update_text();
}
void HandWriteView::char_add(const char c) {
if (cursor_pos >= _max_length) return;
_str->replace(cursor_pos, 1, 1, c);
cursor_pos++;
}
void HandWriteView::update_text() {
if (cursor_pos <= 28)
text_input.set(' ' + *_str + std::string(_max_length - _str->length(), ' '));
else
text_input.set('<' + _str->substr(cursor_pos - 28, 28));
}
}
+5 -19
View File
@@ -26,58 +26,44 @@
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_painter.hpp"
#include "ui_navigation.hpp"
#include "ui_textentry.hpp"
#include "unistroke.hpp"
namespace ui {
class HandWriteView : public View {
class HandWriteView : public TextEntryView {
public:
std::function<void(std::string*)> on_changed { };
HandWriteView(NavigationView& nav, std::string * str, size_t max_length);
HandWriteView(const HandWriteView&) = delete;
HandWriteView(HandWriteView&&) = delete;
HandWriteView& operator=(const HandWriteView&) = delete;
HandWriteView& operator=(HandWriteView&&) = delete;
void paint(Painter& painter) override;
void on_show() override;
bool on_touch(const TouchEvent event) override;
std::string title() const override { return "Text entry"; };
private:
const char special_chars[5] = {'\'', '.', '?', '!', '='};
const char special_chars[5] = { '\'', '.', '?', '!', '=' };
const HandWriting * handwriting { };
Painter * _painter { };
size_t _max_length;
uint8_t dir_cnt { 0 };
uint8_t dir_prev { 0 };
uint8_t flash_timer { 0 };
uint32_t cursor_pos { 0 };
bool cursor { false };
bool tracing { false };
uint8_t stroke_index { 0 };
uint8_t sample_skip { 0 }, move_wait { 0 };
uint8_t stroke_list[8];
Point start_pos { }, current_pos { }, last_pos { };
bool _lowercase = false;
std::string * _str { };
void sample_pen();
void add_stroke(uint8_t dir);
void guess_letter();
void clear_zone(const Color color, const bool flash);
void char_add(const char c);
void on_button(Button& button);
void update_text();
Text text_input {
{ 8, 0, 232, 16 }
};
std::array<Button, 10> num_buttons { };
std::array<Button, 5> special_buttons { };
+2 -2
View File
@@ -186,7 +186,7 @@ void LCRView::start_tx(const bool scan) {
}
void LCRView::on_button_setam(NavigationView& nav, Button& button) {
text_entry(nav, &litteral[button.id], 7);
text_prompt(nav, &litteral[button.id], 7);
}
LCRView::LCRView(NavigationView& nav) {
@@ -263,7 +263,7 @@ LCRView::LCRView(NavigationView& nav) {
button_scan.set_style(&style_val);
button_setrgsb.on_select = [this,&nav](Button&) {
text_entry(nav, &rgsb, 4);
text_prompt(nav, &rgsb, 4);
};
button_txsetup.on_select = [&nav](Button&) {
+7 -1
View File
@@ -138,11 +138,17 @@ void MenuView::clear() {
}
}
void MenuView::add_item(const MenuItem item) {
void MenuView::add_item(MenuItem item) {
add_child(new MenuItemView { item, keep_highlight_ });
update_items();
}
void MenuView::add_items(std::initializer_list<MenuItem> items) {
for(auto item : items) {
add_item(item);
}
}
void MenuView::update_items() {
size_t i = 0;
int32_t y_pos;
+3 -9
View File
@@ -51,7 +51,7 @@ public:
MenuItemView(
MenuItem item,
bool keep_highlight
) : item(item),
) : item { item },
keep_highlight_ { keep_highlight }
{
}
@@ -75,15 +75,9 @@ public:
~MenuView();
void add_item(const MenuItem item);
void add_item(MenuItem item);
void add_items(std::initializer_list<MenuItem> items);
void clear();
template<size_t N>
void add_items(const std::array<MenuItem, N>& items) {
for (const auto& item : items) {
add_item(item);
}
}
MenuItemView* item_view(size_t index) const;
+1 -1
View File
@@ -71,7 +71,7 @@ static msg_t ookthread_fn(void * arg) {
}
void MorseView::on_set_text(NavigationView& nav) {
text_entry(nav, &buffer, 28);
text_prompt(nav, &buffer, 28);
}
void MorseView::focus() {
+8 -8
View File
@@ -281,7 +281,7 @@ void NavigationView::focus() {
/* ReceiversMenuView *****************************************************/
ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
add_items<9>({ {
add_items({
{ "ADS-B: Planes", ui::Color::grey(), &bitmap_icon_adsb, [&nav](){ nav.push<NotImplementedView>(); }, },
{ "AIS: Boats", ui::Color::green(), &bitmap_icon_ais, [&nav](){ nav.push<AISAppView>(); } },
{ "APRS", ui::Color::grey(), &bitmap_icon_aprs, [&nav](){ nav.push<NotImplementedView>(); } },
@@ -291,14 +291,14 @@ ReceiversMenuView::ReceiversMenuView(NavigationView& nav) {
{ "SIGFOX", ui::Color::grey(), &bitmap_icon_fox, [&nav](){ nav.push<NotImplementedView>(); } }, // SIGFRXView
{ "SSTV", ui::Color::grey(), &bitmap_icon_sstv, [&nav](){ nav.push<NotImplementedView>(); } },
{ "TPMS: Cars", ui::Color::green(), &bitmap_icon_tpms, [&nav](){ nav.push<TPMSAppView>(); } },
} });
});
on_left = [&nav](){ nav.pop(); };
}
/* TransmittersMenuView **************************************************/
TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
add_items<16>({ {
add_items({
{ "ADS-B Mode S", ui::Color::orange(), &bitmap_icon_adsb, [&nav](){ nav.push<ADSBTxView>(); } },
{ "APRS", ui::Color::grey(), &bitmap_icon_aprs, [&nav](){ nav.push<APRSTXView>(); } },
{ "BHT Xy/EP", ui::Color::green(), &bitmap_icon_bht, [&nav](){ nav.push<BHTView>(); } },
@@ -315,20 +315,20 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) {
{ "SSTV", ui::Color::green(), &bitmap_icon_sstv, [&nav](){ nav.push<SSTVTXView>(); } },
{ "TEDI/LCR AFSK", ui::Color::yellow(), &bitmap_icon_lcr, [&nav](){ nav.push<LCRView>(); } },
{ "Whistle", ui::Color::green(), &bitmap_icon_whistle, [&nav](){ nav.push<WhistleView>(); } },
} });
});
on_left = [&nav](){ nav.pop(); };
}
/* UtilitiesMenuView *****************************************************/
UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) {
add_items<5>({ {
add_items({
{ "Frequency manager", ui::Color::green(), &bitmap_icon_freqman, [&nav](){ nav.push<FreqManView>(); } },
{ "CW generator", ui::Color::green(), &bitmap_icon_cwgen, [&nav](){ nav.push<CWTXView>(); } },
{ "Whip antenna length", ui::Color::yellow(),nullptr, [&nav](){ nav.push<WhipCalcView>(); } },
{ "Notepad", ui::Color::grey(), &bitmap_icon_notepad, [&nav](){ nav.push<NotImplementedView>(); } },
{ "Wipe SD card", ui::Color::red(), nullptr, [&nav](){ nav.push<WipeSDView>(); } },
} });
});
on_left = [&nav](){ nav.pop(); };
}
@@ -345,7 +345,7 @@ void SystemMenuView::hackrf_mode(NavigationView& nav) {
}
SystemMenuView::SystemMenuView(NavigationView& nav) {
add_items<10>({ {
add_items({
{ "Play dead", ui::Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push<PlayDeadView>(); } },
{ "Receivers", ui::Color::cyan(), &bitmap_icon_receivers, [&nav](){ nav.push<ReceiversMenuView>(); } },
{ "Transmitters", ui::Color::green(), nullptr, [&nav](){ nav.push<TransmittersMenuView>(); } },
@@ -357,7 +357,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) {
//{ "Debug", ui::Color::white(), nullptr, [&nav](){ nav.push<DebugMenuView>(); } },
{ "HackRF mode", ui::Color::white(), &bitmap_icon_hackrf, [this, &nav](){ hackrf_mode(nav); } },
{ "About", ui::Color::white(), nullptr, [&nav](){ nav.push<AboutView>(); } }
} });
});
set_highlighted(1); // Startup selection is "Receivers"
}
+1 -1
View File
@@ -124,7 +124,7 @@ void POCSAGTXView::paint(Painter&) {
}
void POCSAGTXView::on_set_text(NavigationView& nav) {
text_entry(nav, &buffer, 16);
text_prompt(nav, &buffer, 16);
}
POCSAGTXView::POCSAGTXView(
+2 -2
View File
@@ -136,11 +136,11 @@ RDSView::RDSView(NavigationView& nav) {
options_coverage.set_selected_index(0); // Local
button_editpsn.on_select = [this, &nav](Button&) {
text_entry(nav, &PSN, 8);
text_prompt(nav, &PSN, 8);
};
button_editradiotext.on_select = [this, &nav](Button&){
text_entry(nav, &RadioText, 24);
text_prompt(nav, &RadioText, 24);
};
}
+2 -2
View File
@@ -445,7 +445,7 @@ void ModInfoView::focus() {
}*/
SetupMenuView::SetupMenuView(NavigationView& nav) {
add_items<6>({ {
add_items({
{ "UI", ui::Color::white(), nullptr, [&nav](){ nav.push<SetUIView>(); } },
//{ "SD card modules", ui::Color::white(), [&nav](){ nav.push<ModInfoView>(); } },
{ "Date/Time", ui::Color::white(), nullptr, [&nav](){ nav.push<SetDateTimeView>(); } },
@@ -453,7 +453,7 @@ SetupMenuView::SetupMenuView(NavigationView& nav) {
{ "Antenna Bias Voltage", ui::Color::white(), nullptr, [&nav](){ nav.push<AntennaBiasSetupView>(); } },
{ "Touch screen", ui::Color::white(), nullptr, [&nav](){ nav.push<TouchCalibrationView>(); } },
{ "Play dead", ui::Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push<SetPlayDeadView>(); } }
} });
});
on_left = [&nav](){ nav.pop(); };
}
+75 -2
View File
@@ -22,11 +22,15 @@
#include "ui_textentry.hpp"
#include "portapack_persistent_memory.hpp"
#include "ui_handwrite.hpp"
#include "ui_alphanum.hpp"
using namespace portapack;
namespace ui {
void text_entry(NavigationView& nav, std::string * str, const size_t max_length, const std::function<void(std::string *)> on_done) {
if (portapack::persistent_memory::ui_config_textentry() == 0) {
void text_prompt(NavigationView& nav, std::string * str, const size_t max_length, const std::function<void(std::string *)> on_done) {
if (persistent_memory::ui_config_textentry() == 0) {
auto te_view = nav.push<AlphanumView>(str, max_length);
te_view->on_changed = [on_done](std::string * value) {
if (on_done)
@@ -41,4 +45,73 @@ void text_entry(NavigationView& nav, std::string * str, const size_t max_length,
}
}
void TextEntryView::update_text() {
if (_cursor_pos <= 28)
text_input.set(' ' + *_str + std::string(_max_length - _str->length(), ' '));
else
text_input.set('<' + _str->substr(_cursor_pos - 28, 28));
draw_cursor();
}
void TextEntryView::char_delete() {
if (!_cursor_pos) return;
_cursor_pos--;
_str->replace(_cursor_pos, 1, 1, 0);
}
void TextEntryView::char_add(const char c) {
if (_cursor_pos >= _max_length) return;
_str->replace(_cursor_pos, 1, 1, c);
_cursor_pos++;
}
void TextEntryView::draw_cursor() {
Point draw_pos;
draw_pos = { text_input.screen_rect().location().x() + 8 + std::min((Coord)_cursor_pos, (Coord)28) * 8,
text_input.screen_rect().location().y() + 16 };
display.fill_rectangle(
{ { text_input.screen_rect().location().x(), draw_pos.y() }, { text_input.screen_rect().size().width(), 4 } },
Color::black()
);
display.fill_rectangle(
{ draw_pos, { 8, 4 } },
Color::white()
);
}
void TextEntryView::focus() {
button_ok.focus();
}
TextEntryView::TextEntryView(
NavigationView& nav,
std::string * str,
size_t max_length
) : _str(str),
_max_length(max_length)
{
// Trim from right
_str->erase(std::find_if(_str->rbegin(), _str->rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), _str->end());
_cursor_pos = _str->length();
_str->resize(_max_length, 0);
add_children({
&text_input,
&button_ok
});
button_ok.on_select = [this, &nav](Button&) {
if (on_changed)
on_changed(_str);
nav.pop();
};
}
} /* namespace ui */
+35 -3
View File
@@ -25,12 +25,44 @@
#include "ui.hpp"
#include "ui_navigation.hpp"
#include "ui_handwrite.hpp"
#include "ui_alphanum.hpp"
namespace ui {
void text_entry(NavigationView& nav, std::string * str, size_t max_length, const std::function<void(std::string*)> on_done = nullptr);
class TextEntryView : public View {
public:
std::function<void(std::string*)> on_changed { };
void focus() override;
std::string title() const override { return "Text entry"; };
protected:
TextEntryView(NavigationView& nav, std::string * str, size_t max_length);
TextEntryView(const TextEntryView&) = delete;
TextEntryView(TextEntryView&&) = delete;
TextEntryView& operator=(const TextEntryView&) = delete;
TextEntryView& operator=(TextEntryView&&) = delete;
void char_add(const char c);
void char_delete();
void draw_cursor();
void update_text();
std::string * _str;
size_t _max_length;
uint32_t _cursor_pos { 0 };
Text text_input {
{ 0, 0, 240, 16 }
};
Button button_ok {
{ 10 * 8, 33 * 8, 9 * 8, 32 },
"OK"
};
};
void text_prompt(NavigationView& nav, std::string * str, size_t max_length, const std::function<void(std::string*)> on_done = nullptr);
} /* namespace ui */