diff --git a/firmware/application/apps/ble_app.cpp b/firmware/application/apps/ble_app.cpp index 9cf9d579..36185634 100644 --- a/firmware/application/apps/ble_app.cpp +++ b/firmware/application/apps/ble_app.cpp @@ -43,6 +43,17 @@ std::string pad_string_with_spaces(int snakes) { return paddedStr; } +uint64_t copy_mac_address_to_uint64(const uint8_t* macAddress) { + uint64_t result = 0; + + // Copy each byte of the MAC address to the corresponding byte in the uint64_t. + for (int i = 0; i < 6; ++i) { + result |= static_cast(macAddress[i]) << ((5 - i) * 8); + } + + return result; +} + namespace ui { template <> void RecentEntriesTable::draw( @@ -50,13 +61,7 @@ void RecentEntriesTable::draw( const Rect& target_rect, Painter& painter, const Style& style) { - std::string line = to_string_hex(entry.macAddress & 0xFF, 2); - - line += ":" + to_string_hex((entry.macAddress >> 8) & 0xFF, 2); - line += ":" + to_string_hex((entry.macAddress >> 16) & 0xFF, 2); - line += ":" + to_string_hex((entry.macAddress >> 24) & 0xFF, 2); - line += ":" + to_string_hex((entry.macAddress >> 32) & 0xFF, 2); - line += ":" + to_string_hex((entry.macAddress >> 40), 2); + std::string line = to_string_mac_address(entry.packetData.macAddress, 6); // Handle spacing for negative sign. uint8_t db_spacing = entry.dbValue > 0 ? 7 : 6; @@ -126,13 +131,6 @@ void BleRecentEntryDetailView::paint(Painter& painter) { length[currentPacket] = entry_.packetData.data[currentByte++]; type[currentPacket] = entry_.packetData.data[currentByte++]; - // This should never happen, but in here just in case. - // Break because we can't trust rest of data. - // if (length[currentPacket] > entry_.packetData.dataLen) - // { - // break; - // } - // Subtract 1 because type is part of the length. for (i = 0; i < length[currentPacket] - 1; i++) { data[currentPacket][i] = entry_.packetData.data[currentByte++]; @@ -211,9 +209,11 @@ BLERxView::BLERxView(NavigationView& nav) &field_rf_amp, &field_lna, &field_vga, - &options_region, + &options_channel, &field_frequency, &check_log, + &label_sort, + &options_sort, &recent_entries_view, &recent_entry_detail_view}); @@ -232,14 +232,36 @@ BLERxView::BLERxView(NavigationView& nav) logging = v; }; - options_region.on_change = [this](size_t, int32_t i) { + options_channel.on_change = [this](size_t, int32_t i) { field_frequency.set_value(get_freq_by_channel_number(i)); channel_number = i; baseband::set_btle(channel_number); }; - options_region.set_selected_index(0, true); + options_sort.on_change = [this](size_t, int32_t i) { + switch (i) { + case 0: + sortEntriesBy( + recent, [](const BleRecentEntry& entry) { return entry.macAddress; }, true); + break; + case 1: + sortEntriesBy( + recent, [](const BleRecentEntry& entry) { return entry.dbValue; }, true); + break; + case 2: + sortEntriesBy( + recent, [](const BleRecentEntry& entry) { return entry.timestamp; }, false); + break; + default: + break; + } + + recent_entries_view.set_dirty(); + }; + + options_channel.set_selected_index(0, true); + options_sort.set_selected_index(0, true); logger = std::make_unique(); @@ -299,18 +321,13 @@ void BLERxView::on_data(BlePacketData* packet) { // str_console += to_string_dec_uint(value); - str_console += " Len: "; + str_console += " Len:"; str_console += to_string_dec_uint(packet->size); str_console += "\n"; - str_console += "Mac"; - str_console += ":" + to_string_hex(packet->macAddress[0], 2); - str_console += ":" + to_string_hex(packet->macAddress[1], 2); - str_console += ":" + to_string_hex(packet->macAddress[2], 2); - str_console += ":" + to_string_hex(packet->macAddress[3], 2); - str_console += ":" + to_string_hex(packet->macAddress[4], 2); - str_console += ":" + to_string_hex(packet->macAddress[5], 2); + str_console += "Mac:"; + str_console += to_string_mac_address(packet->macAddress, 6); str_console += "\n"; str_console += "Data:"; @@ -323,15 +340,15 @@ void BLERxView::on_data(BlePacketData* packet) { str_console += "\n"; + uint64_t macAddressEncoded = copy_mac_address_to_uint64(packet->macAddress); + // Start of Packet stuffing. - uint64_t macAddressEncoded = 0; - - memcpy(&macAddressEncoded, packet->macAddress, sizeof(uint64_t)); - // Masking off the top 2 bytes to avoid invalid keys. auto& entry = ::on_packet(recent, macAddressEncoded & 0xFFFFFFFFFFFF); entry.dbValue = packet->max_dB; + entry.timestamp = to_string_timestamp(rtc_time::now()); + entry.packetData.type = packet->type; entry.packetData.size = packet->size; entry.packetData.dataLen = packet->dataLen; @@ -348,6 +365,24 @@ void BLERxView::on_data(BlePacketData* packet) { } // entry.update(packet); + + switch (options_sort.selected_index()) { + case 0: + sortEntriesBy( + recent, [](const BleRecentEntry& entry) { return entry.macAddress; }, true); + break; + case 1: + sortEntriesBy( + recent, [](const BleRecentEntry& entry) { return entry.dbValue; }, true); + break; + case 2: + sortEntriesBy( + recent, [](const BleRecentEntry& entry) { return entry.timestamp; }, false); + break; + default: + break; + } + recent_entries_view.set_dirty(); // TODO: Crude hack, should be a more formal listener arrangement... diff --git a/firmware/application/apps/ble_app.hpp b/firmware/application/apps/ble_app.hpp index 6f3031b5..6d516afc 100644 --- a/firmware/application/apps/ble_app.hpp +++ b/firmware/application/apps/ble_app.hpp @@ -76,6 +76,7 @@ struct BleRecentEntry { uint64_t macAddress; int dbValue; BlePacketData packetData; + std::string timestamp; BleRecentEntry() : BleRecentEntry{0} { @@ -85,7 +86,8 @@ struct BleRecentEntry { const uint64_t macAddress) : macAddress{macAddress}, dbValue{}, - packetData{} { + packetData{}, + timestamp{} { } Key key() const { @@ -165,6 +167,17 @@ class BLERxView : public View { static constexpr auto header_height = 12 + 2 * 16; + OptionsField options_channel{ + {0 * 8, 0 * 8}, + 5, + {{"Ch.37 ", 37}, + {"Ch.38", 38}, + {"Ch.39", 39}}}; + + RxFrequencyField field_frequency{ + {6 * 8, 0 * 16}, + nav_}; + RFAmpField field_rf_amp{ {16 * 8, 0 * 16}}; @@ -180,26 +193,25 @@ class BLERxView : public View { Channel channel{ {24 * 8, 5, 6 * 8, 4}}; - RxFrequencyField field_frequency{ - {6 * 8, 0 * 16}, - nav_}; + Checkbox check_log{ + {0 * 8, 3 * 8}, + 3, + "Log", + true}; - OptionsField options_region{ - {0 * 8, 0 * 8}, - 5, - {{"Ch.37 ", 37}, - {"Ch.38", 38}, - {"Ch.39", 39}}}; + Labels label_sort{ + {{6 * 8, 3 * 8}, "Sort:", Color::light_grey()}}; + + OptionsField options_sort{ + {12 * 8, 3 * 8}, + 6, + {{"MAC", 0}, + {"dB", 1}, + {"Recent", 2}}}; Console console{ {0, 4 * 16, 240, 240}}; - Checkbox check_log{ - {0 * 8, 1 * 16}, - 3, - "LOG", - false}; - std::string str_log{""}; bool logging{false}; diff --git a/firmware/application/recent_entries.hpp b/firmware/application/recent_entries.hpp index 195e27b4..8dc022ab 100644 --- a/firmware/application/recent_entries.hpp +++ b/firmware/application/recent_entries.hpp @@ -88,6 +88,13 @@ static std::pair +void sortEntriesBy(ContainerType& entries, KeySelector keySelector, SortOrder ascending) { + entries.sort([keySelector, ascending](const auto& a, const auto& b) { + return ascending ? keySelector(a) < keySelector(b) : keySelector(a) > keySelector(b); + }); +} + namespace ui { using RecentEntriesColumn = std::pair; diff --git a/firmware/application/string_format.cpp b/firmware/application/string_format.cpp index 2f971c5a..c1654146 100644 --- a/firmware/application/string_format.cpp +++ b/firmware/application/string_format.cpp @@ -311,6 +311,18 @@ std::string to_string_file_size(uint32_t file_size) { return to_string_dec_uint(file_size) + suffix[suffix_index]; } +std::string to_string_mac_address(const uint8_t* macAddress, uint8_t length) { + std::string string; + + string += to_string_hex(macAddress[0], 2); + + for (int i = 1; i < length; i++) { + string += ":" + to_string_hex(macAddress[i], 2); + } + + return string; +} + std::string unit_auto_scale(double n, const uint32_t base_unit, uint32_t precision) { const uint32_t powers_of_ten[5] = {1, 10, 100, 1000, 10000}; std::string string{""}; diff --git a/firmware/application/string_format.hpp b/firmware/application/string_format.hpp index 72c326c6..eba45a8e 100644 --- a/firmware/application/string_format.hpp +++ b/firmware/application/string_format.hpp @@ -76,6 +76,9 @@ std::string to_string_FAT_timestamp(const FATTimestamp& timestamp); // Gets a human readable file size string. std::string to_string_file_size(uint32_t file_size); +// Converts Mac Address to string. +std::string to_string_mac_address(const uint8_t* macAddress, uint8_t length); + /* Scales 'n' to be a value less than 1000. 'base_unit' is the index of the unit from * 'unit_prefix' that 'n' is in initially. 3 is the index of the '1s' unit. */ std::string unit_auto_scale(double n, const uint32_t base_unit, uint32_t precision);