RadioSet: Forgot yet another set of source files, it's TermView
This commit is contained in:
parent
34c09e6b1d
commit
38e5f51511
485
ExternalApps/RadioSet/main/Source/TermView.cpp
Normal file
485
ExternalApps/RadioSet/main/Source/TermView.cpp
Normal file
@ -0,0 +1,485 @@
|
||||
#include "TermView.h"
|
||||
|
||||
#include <tt_kernel.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "Str.h"
|
||||
#include "Utils.h"
|
||||
|
||||
extern lv_font_t lv_font_unscii_8;
|
||||
extern lv_font_t lv_font_ptmono_12;
|
||||
|
||||
class Message {
|
||||
public:
|
||||
uint8_t* data;
|
||||
size_t size;
|
||||
|
||||
Message(const uint8_t* packetData, const size_t packetSize) {
|
||||
size = packetSize;
|
||||
data = new uint8_t[size];
|
||||
memcpy(data, packetData, size);
|
||||
}
|
||||
|
||||
virtual lv_obj_t* makeMessageBox(lv_obj_t* parent) = 0;
|
||||
|
||||
virtual void refresh() = 0;
|
||||
|
||||
virtual ~Message() {
|
||||
delete[] data;
|
||||
}
|
||||
};
|
||||
|
||||
class RxMessage : public Message {
|
||||
public:
|
||||
RadioHandle radio;
|
||||
float rssi;
|
||||
float snr;
|
||||
lv_obj_t* msgBox = nullptr;
|
||||
|
||||
RxMessage(RadioHandle radio, const RadioRxPacket* packet)
|
||||
: Message(packet->data, packet->size)
|
||||
, radio(radio) {
|
||||
rssi = packet->rssi;
|
||||
snr = packet->snr;
|
||||
}
|
||||
|
||||
static void applyStyle(lv_obj_t* obj) {
|
||||
static lv_style_t style;
|
||||
static bool init = false;
|
||||
if (!init) {
|
||||
lv_style_init(&style);
|
||||
lv_style_set_border_color(&style, lv_color_make(0x0A, 0x5C, 0x36));
|
||||
lv_style_set_border_side(&style, LV_BORDER_SIDE_LEFT);
|
||||
lv_style_set_border_width(&style, 5);
|
||||
lv_style_set_pad_all(&style, 1);
|
||||
lv_style_set_margin_bottom(&style, 2);
|
||||
lv_style_set_radius(&style, 0);
|
||||
}
|
||||
|
||||
lv_obj_add_style(obj, &style, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
virtual lv_obj_t* makeMessageBox(lv_obj_t* parent) {
|
||||
char timebuffer[32] = {0};
|
||||
Str info;
|
||||
Str message;
|
||||
bool is_txt = false;
|
||||
|
||||
auto* msg_container = lv_obj_create(parent);
|
||||
lv_obj_set_flex_flow(msg_container, LV_FLEX_FLOW_COLUMN);
|
||||
//lv_obj_set_flex_grow(msg_container, 0);
|
||||
lv_obj_set_style_pad_all(msg_container, 1, 0);
|
||||
//lv_obj_add_flag(msg_container, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
lv_obj_t* msg_label = lv_label_create(msg_container);
|
||||
is_txt = isPrintable(data, size);
|
||||
if (is_txt) {
|
||||
message.set((const char*)data, ((const char*)data + size));
|
||||
} else {
|
||||
hexdump(message, data, size);
|
||||
}
|
||||
|
||||
lv_label_set_text(msg_label, message.c_str());
|
||||
lv_obj_set_width(msg_label, lv_pct(100));
|
||||
lv_label_set_long_mode(msg_label, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(msg_label, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_obj_set_style_pad_all(msg_label, 0, 0);
|
||||
lv_obj_set_style_text_font(msg_label, &lv_font_ptmono_12, 0);
|
||||
|
||||
lv_obj_t* msg_info = lv_label_create(msg_container);
|
||||
|
||||
// Get time
|
||||
time_t now = time(nullptr);
|
||||
struct tm* tm_info = localtime(&now);
|
||||
strftime(timebuffer, sizeof(timebuffer), "%H:%M:%S", tm_info);
|
||||
|
||||
info.append("RX/");
|
||||
|
||||
// Get device name and modulation
|
||||
auto modulation = MODULATION_NONE;
|
||||
if (radio) {
|
||||
info.append(tt_hal_radio_get_name(radio));
|
||||
modulation = tt_hal_radio_get_modulation(radio);
|
||||
info.append(" ");
|
||||
} else {
|
||||
info.append("?");
|
||||
}
|
||||
|
||||
info.append(toString(modulation));
|
||||
info.append(is_txt ? "/TXT " : "/BIN ");
|
||||
|
||||
info.append(timebuffer);
|
||||
info.appendf(" SI:%.2f SN:%.2f PS:%d", rssi, snr, size);
|
||||
|
||||
lv_label_set_text(msg_info, info.c_str());
|
||||
lv_obj_set_width(msg_info, lv_pct(100));
|
||||
lv_label_set_long_mode(msg_info, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(msg_info, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_obj_set_style_pad_all(msg_info, 0, 0);
|
||||
lv_obj_set_style_text_font(msg_info, &lv_font_unscii_8, 0);
|
||||
|
||||
lv_obj_set_width(msg_container, lv_pct(100));
|
||||
|
||||
lv_obj_update_layout(msg_label);
|
||||
lv_obj_update_layout(msg_info);
|
||||
lv_obj_set_height(msg_container, LV_SIZE_CONTENT);
|
||||
|
||||
applyStyle(msg_container);
|
||||
|
||||
msgBox = msg_container;
|
||||
//clownvomit(msg_container);
|
||||
return msg_container;
|
||||
}
|
||||
|
||||
virtual void refresh() {}
|
||||
|
||||
virtual ~RxMessage() {
|
||||
if (msgBox) {
|
||||
lv_obj_del(msgBox);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TxMessage : public Message {
|
||||
public:
|
||||
RadioHandle radio;
|
||||
RadioTxState lastState;
|
||||
uint32_t address;
|
||||
lv_obj_t* msgBox = nullptr;
|
||||
lv_obj_t* statusLabel = nullptr;
|
||||
|
||||
TxMessage(RadioHandle radio, const RadioTxPacket* packet)
|
||||
: Message(packet->data, packet->size)
|
||||
, radio(radio) {
|
||||
address = packet->address;
|
||||
}
|
||||
|
||||
static void updateStatusFor(RadioTxId id, RadioTxState state, void* ctx) {
|
||||
static_cast<TxMessage*>(ctx)->updateStatus(id, state);
|
||||
}
|
||||
|
||||
static void applyStyle(lv_obj_t* obj) {
|
||||
static lv_style_t style;
|
||||
static bool init = false;
|
||||
if (!init) {
|
||||
lv_style_init(&style);
|
||||
lv_style_set_border_color(&style, lv_color_make(0xFF, 0xBF, 0x00));
|
||||
lv_style_set_border_side(&style, LV_BORDER_SIDE_LEFT);
|
||||
lv_style_set_border_width(&style, 5);
|
||||
lv_style_set_pad_all(&style, 1);
|
||||
lv_style_set_margin_bottom(&style, 2);
|
||||
lv_style_set_radius(&style, 0);
|
||||
}
|
||||
|
||||
lv_obj_add_style(obj, &style, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
virtual lv_obj_t* makeMessageBox(lv_obj_t* parent) {
|
||||
char timebuffer[32] = {0};
|
||||
Str info;
|
||||
Str message;
|
||||
|
||||
auto* msg_container = lv_obj_create(parent);
|
||||
static lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
static lv_coord_t row_dsc[] = {LV_GRID_CONTENT, /* row 0 – label 0 */
|
||||
LV_GRID_CONTENT, /* row 1 – labels 1+2 */
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
lv_obj_set_grid_dsc_array(msg_container, col_dsc, row_dsc);
|
||||
lv_obj_set_style_pad_all(msg_container, 1, 0);
|
||||
|
||||
lv_obj_t* msg_label = lv_label_create(msg_container);
|
||||
if (isPrintable(data, size)) {
|
||||
message.set((const char*)data, ((const char*)data + size));
|
||||
} else {
|
||||
hexdump(message, data, size);
|
||||
}
|
||||
|
||||
lv_label_set_text(msg_label, message.c_str());
|
||||
lv_obj_set_width(msg_label, lv_pct(100));
|
||||
lv_label_set_long_mode(msg_label, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(msg_label, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_obj_set_style_pad_all(msg_label, 0, 0);
|
||||
lv_obj_set_style_text_font(msg_label, &lv_font_ptmono_12, 0);
|
||||
|
||||
lv_obj_t* msg_info = lv_label_create(msg_container);
|
||||
|
||||
// Get time
|
||||
time_t now = time(nullptr);
|
||||
struct tm* tm_info = localtime(&now);
|
||||
strftime(timebuffer, sizeof(timebuffer), "%H:%M:%S", tm_info);
|
||||
|
||||
info.append("TX/");
|
||||
|
||||
// Get device name and modulation
|
||||
auto modulation = MODULATION_NONE;
|
||||
if (radio) {
|
||||
info.append(tt_hal_radio_get_name(radio));
|
||||
modulation = tt_hal_radio_get_modulation(radio);
|
||||
info.append(" ");
|
||||
} else {
|
||||
info.append("?");
|
||||
}
|
||||
bool is_txt = isPrintable(data, size);
|
||||
info.append(toString(modulation));
|
||||
info.append(is_txt ? "/TXT " : "/BIN ");
|
||||
|
||||
info.append(timebuffer);
|
||||
info.appendf(" PS:%d", size);
|
||||
|
||||
lv_label_set_text(msg_info, info.c_str());
|
||||
lv_obj_set_width(msg_info, LV_SIZE_CONTENT);
|
||||
lv_label_set_long_mode(msg_info, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(msg_info, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_obj_set_style_pad_all(msg_info, 0, 0);
|
||||
lv_obj_set_style_text_font(msg_info, &lv_font_unscii_8, 0);
|
||||
|
||||
statusLabel = lv_label_create(msg_container);
|
||||
lv_label_set_text(statusLabel, "NEW");
|
||||
lv_obj_set_width(statusLabel, LV_SIZE_CONTENT);
|
||||
lv_label_set_long_mode(statusLabel, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(statusLabel, LV_TEXT_ALIGN_RIGHT, 0);
|
||||
lv_obj_set_style_pad_all(statusLabel, 0, 0);
|
||||
lv_obj_set_style_text_font(statusLabel, &lv_font_unscii_8, 0);
|
||||
|
||||
lv_obj_update_layout(msg_label);
|
||||
lv_obj_update_layout(msg_info);
|
||||
lv_obj_update_layout(statusLabel);
|
||||
|
||||
/* attach items (child index, column, row, column-span, row-span) */
|
||||
lv_obj_set_grid_cell(msg_label, LV_GRID_ALIGN_STRETCH, 0, 1,
|
||||
LV_GRID_ALIGN_CENTER, 0, 1);
|
||||
lv_obj_set_grid_cell(msg_info, LV_GRID_ALIGN_START, 0, 1,
|
||||
LV_GRID_ALIGN_CENTER, 1, 1);
|
||||
lv_obj_set_grid_cell(statusLabel, LV_GRID_ALIGN_END, 0, 1,
|
||||
LV_GRID_ALIGN_CENTER, 1, 1);
|
||||
|
||||
lv_obj_set_width(msg_container, lv_pct(100));
|
||||
lv_obj_set_height(msg_container, LV_SIZE_CONTENT);
|
||||
|
||||
applyStyle(msg_container);
|
||||
|
||||
msgBox = msg_container;
|
||||
return msg_container;
|
||||
}
|
||||
|
||||
void updateStatus(RadioTxId id, RadioTxState state) {
|
||||
lastState = state;
|
||||
}
|
||||
|
||||
virtual void refresh() {
|
||||
const auto* status_txt = toString(lastState);
|
||||
if (statusLabel) {
|
||||
auto indicatorColor = lv_color_make(0xFF, 0x00, 0x00);
|
||||
|
||||
switch (lastState) {
|
||||
case RADIO_TX_QUEUED:
|
||||
// Dark Amber
|
||||
indicatorColor = lv_color_make(0xD5, 0x36, 0x00);
|
||||
break;
|
||||
case RADIO_TX_PENDING_TRANSMIT:
|
||||
// Light Amber
|
||||
indicatorColor = lv_color_make(0xFF, 0xD2, 0x2B);
|
||||
break;
|
||||
case RADIO_TX_TRANSMITTED:
|
||||
// Green
|
||||
indicatorColor = lv_color_make(0x8F, 0xCE, 0x00);
|
||||
break;
|
||||
case RADIO_TX_TIMEOUT:
|
||||
// Purple
|
||||
indicatorColor = lv_color_make(0xC9, 0x00, 0x76);
|
||||
break;
|
||||
case RADIO_TX_ERROR:
|
||||
// Full Red
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lv_obj_set_style_bg_opa(statusLabel, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_bg_color(statusLabel, indicatorColor, 0);
|
||||
lv_obj_set_style_text_color(statusLabel, lv_color_make(0x00, 0x00, 0x00), 0);
|
||||
lv_obj_set_style_pad_all(statusLabel, 1, 0);
|
||||
lv_label_set_text(statusLabel, status_txt);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~TxMessage() {
|
||||
if (msgBox) {
|
||||
lv_obj_del(msgBox);
|
||||
}
|
||||
}
|
||||
};
|
||||
void TermView::initUi(lv_obj_t* parent) {
|
||||
|
||||
mainPanel = lv_obj_create(parent);
|
||||
lv_obj_set_size(mainPanel, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_flex_flow(mainPanel, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_align(mainPanel, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_border_width(mainPanel, 0, 0);
|
||||
lv_obj_set_style_pad_all(mainPanel, 0, 0);
|
||||
|
||||
messageList = lv_obj_create(mainPanel);
|
||||
lv_obj_set_size(messageList, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_flex_flow(messageList, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_align(messageList, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_border_width(messageList, 0, 0);
|
||||
lv_obj_set_style_pad_all(messageList, 0, 0);
|
||||
make_scrollable(messageList);
|
||||
|
||||
// Input panel
|
||||
auto* input_panel = lv_obj_create(mainPanel);
|
||||
lv_obj_set_flex_flow(input_panel, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_size(input_panel, lv_pct(100), LV_SIZE_CONTENT);
|
||||
lv_obj_align(input_panel, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
lv_obj_set_flex_align(input_panel, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_set_style_pad_all(input_panel, 5, 0);
|
||||
|
||||
// Input field
|
||||
inputField = lv_textarea_create(input_panel);
|
||||
lv_obj_set_flex_grow(inputField, 1);
|
||||
lv_obj_set_height(inputField, LV_PCT(100));
|
||||
lv_textarea_set_placeholder_text(inputField, "Type a message...");
|
||||
lv_textarea_set_one_line(inputField, true);
|
||||
|
||||
// Send button
|
||||
sendButton = lv_btn_create(input_panel);
|
||||
lv_obj_set_size(sendButton, 50, LV_SIZE_CONTENT);
|
||||
//lv_obj_add_event_cb(send_btn, onSendClicked, LV_EVENT_CLICKED, this);
|
||||
|
||||
auto* btn_label = lv_label_create(sendButton);
|
||||
lv_label_set_text(btn_label, "SEND");
|
||||
lv_obj_center(btn_label);
|
||||
|
||||
lv_obj_set_flex_grow(messageList, 1);
|
||||
lv_obj_set_flex_grow(input_panel, 0);
|
||||
|
||||
lv_obj_add_event_cb(sendButton, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
auto* self = (TermView*)lv_event_get_user_data(e);
|
||||
self->sendMessage();
|
||||
}, LV_EVENT_SHORT_CLICKED, (void*)this);
|
||||
|
||||
renderMessagesTimer = lv_timer_create([](lv_timer_t* timer) {
|
||||
auto self = reinterpret_cast<TermView*>(lv_timer_get_user_data(timer));
|
||||
self->updateMessages();
|
||||
}, 500, this);
|
||||
}
|
||||
|
||||
void TermView::setVisible(bool visible) {
|
||||
if (visible) {
|
||||
lv_obj_clear_flag(mainPanel, LV_OBJ_FLAG_HIDDEN);
|
||||
} else {
|
||||
lv_obj_add_flag(mainPanel, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
void TermView::addRadio(RadioHandle radio) {
|
||||
auto sub_id = tt_hal_radio_subscribe_receive(radio, [](DeviceId id, const RadioRxPacket* packet, void* ctx) {
|
||||
auto* self = (TermView*)ctx;
|
||||
self->pushRxMessage(id, packet);
|
||||
}, this);
|
||||
|
||||
radios.pushBack(RadioItem{
|
||||
.handle = radio,
|
||||
.rxSubId = sub_id
|
||||
});
|
||||
|
||||
// TODO: Remove once radio select dropdown is there
|
||||
selectedRadio = radio;
|
||||
}
|
||||
|
||||
void TermView::cleanupRadios() {
|
||||
for (auto iter = radios.begin(); iter != radios.end(); iter++) {
|
||||
tt_hal_radio_unsubscribe_receive(iter->handle, iter->rxSubId);
|
||||
}
|
||||
}
|
||||
|
||||
void TermView::sendMessage() {
|
||||
auto* message = lv_textarea_get_text(inputField);
|
||||
auto txPacket = RadioTxPacket {
|
||||
.data = (uint8_t*)message, // I am NOT allocating for this
|
||||
.size = strlen(message),
|
||||
.address = 0
|
||||
};
|
||||
|
||||
auto* txBox = new TxMessage(selectedRadio, &txPacket);
|
||||
tt_mutex_lock(mutex, portMAX_DELAY);
|
||||
inMsgQueue.pushBack(txBox);
|
||||
signalHasMsgs = true;
|
||||
tt_mutex_unlock(mutex);
|
||||
|
||||
tt_hal_radio_transmit(selectedRadio, txPacket, TxMessage::updateStatusFor, txBox);
|
||||
}
|
||||
|
||||
void TermView::pushRxMessage(DeviceId device, const RadioRxPacket* packet) {
|
||||
auto radio = getRadioForDeviceId(device);
|
||||
tt_mutex_lock(mutex, portMAX_DELAY);
|
||||
|
||||
auto* rxBox = new RxMessage(radio, packet);
|
||||
inMsgQueue.pushBack(rxBox);
|
||||
signalHasMsgs = true;
|
||||
tt_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
void TermView::run() {
|
||||
while(!getSignalStop()) {
|
||||
while(!getSignalHasMsg() && !getSignalStop()) {
|
||||
tt_kernel_delay_millis(100);
|
||||
}
|
||||
|
||||
if (getSignalStop()) {
|
||||
break;
|
||||
}
|
||||
|
||||
tt_mutex_lock(lvglMutex, portMAX_DELAY);
|
||||
while (!inMsgQueue.empty()) {
|
||||
auto* message = inMsgQueue.front();
|
||||
inMsgQueue.popFront();
|
||||
|
||||
if (messages.size() >= MESSAGE_LIMIT) {
|
||||
delete messages.back();
|
||||
messages.popBack();
|
||||
}
|
||||
|
||||
message->makeMessageBox(messageList);
|
||||
messages.pushFront(message);
|
||||
}
|
||||
|
||||
lv_obj_update_layout(messageList);
|
||||
tt_mutex_unlock(lvglMutex);
|
||||
clearSignalHasMsg();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TermView::updateMessages() {
|
||||
bool at_bottom = (lv_obj_get_scroll_bottom(messageList) <= 0);
|
||||
bool focused = lv_obj_has_state(messageList, LV_STATE_FOCUSED);
|
||||
|
||||
tt_mutex_lock(lvglMutex, portMAX_DELAY);
|
||||
while (!inMsgQueue.empty()) {
|
||||
auto* message = inMsgQueue.front();
|
||||
inMsgQueue.popFront();
|
||||
|
||||
if (messages.size() >= MESSAGE_LIMIT) {
|
||||
delete messages.back();
|
||||
messages.popBack();
|
||||
}
|
||||
|
||||
message->makeMessageBox(messageList);
|
||||
messages.pushFront(message);
|
||||
}
|
||||
|
||||
lv_obj_update_layout(messageList);
|
||||
tt_mutex_unlock(lvglMutex);
|
||||
// demorgan spinning in his grave for his teachings are for naught
|
||||
//if (!(!at_bottom || focused)) {
|
||||
if (at_bottom) {
|
||||
lv_obj_scroll_to_y(messageList, LV_COORD_MAX, LV_ANIM_ON);
|
||||
}
|
||||
|
||||
for (auto iter = messages.begin(); iter != messages.end(); iter++) {
|
||||
(*iter)->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
110
ExternalApps/RadioSet/main/Source/TermView.h
Normal file
110
ExternalApps/RadioSet/main/Source/TermView.h
Normal file
@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <tt_hal_radio.h>
|
||||
#include <tt_mutex.h>
|
||||
#include <tt_thread.h>
|
||||
|
||||
#include "LinkedList.h"
|
||||
#include "Dequeue.h"
|
||||
|
||||
class Message;
|
||||
|
||||
class TermView {
|
||||
static size_t constexpr MESSAGE_LIMIT = 64;
|
||||
|
||||
struct RadioItem {
|
||||
RadioHandle handle;
|
||||
RadioRxSubscriptionId rxSubId;
|
||||
};
|
||||
|
||||
ThreadHandle thread;
|
||||
MutexHandle lvglMutex;
|
||||
MutexHandle mutex;
|
||||
bool signalStop = false;
|
||||
bool signalHasMsgs = false;
|
||||
|
||||
LinkedList<RadioItem> radios;
|
||||
RadioHandle selectedRadio = nullptr;
|
||||
Dequeue<Message*> inMsgQueue;
|
||||
LinkedList<Message*> messages;
|
||||
lv_obj_t* mainPanel = nullptr;
|
||||
lv_obj_t* messageList = nullptr;
|
||||
lv_obj_t* inputField = nullptr;
|
||||
lv_obj_t* sendButton = nullptr;
|
||||
lv_timer_t* renderMessagesTimer = nullptr;
|
||||
|
||||
static int32_t threadMain(void* context) {
|
||||
static_cast<TermView*>(context)->run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void initUi(lv_obj_t* parent);
|
||||
void cleanupRadios();
|
||||
|
||||
void setSignalStop() {
|
||||
tt_mutex_lock(mutex, portMAX_DELAY);
|
||||
signalStop = true;
|
||||
tt_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
bool getSignalStop() {
|
||||
//tt_mutex_lock(mutex, portMAX_DELAY);
|
||||
auto s = signalStop;
|
||||
//tt_mutex_unlock(mutex);
|
||||
return s;
|
||||
}
|
||||
|
||||
void setSignalHasMsg() {
|
||||
tt_mutex_lock(mutex, portMAX_DELAY);
|
||||
signalHasMsgs = true;
|
||||
tt_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
void clearSignalHasMsg() {
|
||||
tt_mutex_lock(mutex, portMAX_DELAY);
|
||||
signalHasMsgs = false;
|
||||
tt_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
bool getSignalHasMsg() {
|
||||
tt_mutex_lock(mutex, portMAX_DELAY);
|
||||
auto s = signalHasMsgs;
|
||||
tt_mutex_unlock(mutex);
|
||||
return s;
|
||||
}
|
||||
|
||||
void run();
|
||||
|
||||
RadioHandle getRadioForDeviceId(DeviceId devid) {
|
||||
for (auto iter = radios.begin(); iter != radios.end(); iter++) {
|
||||
if (tt_hal_radio_get_device_id(iter->handle) == devid) {
|
||||
return iter->handle;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
TermView(MutexHandle lvglMutex, lv_obj_t* parent)
|
||||
: lvglMutex(lvglMutex) {
|
||||
initUi(parent);
|
||||
thread = tt_thread_alloc_ext("RadioTerm.TermView", 2*4096, threadMain, this);
|
||||
mutex = tt_mutex_alloc(MUTEX_TYPE_RECURSIVE);
|
||||
//tt_thread_start(thread);
|
||||
}
|
||||
|
||||
virtual ~TermView() {
|
||||
setSignalStop();
|
||||
tt_thread_join(thread, portMAX_DELAY);
|
||||
tt_thread_free(thread);
|
||||
cleanupRadios();
|
||||
}
|
||||
|
||||
void setVisible(bool visible);
|
||||
void addRadio(RadioHandle radio);
|
||||
void sendMessage();
|
||||
void updateMessages();
|
||||
|
||||
void pushRxMessage(DeviceId device, const RadioRxPacket* packet);
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user