mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-20 04:54:45 -07:00
nrfupd and animation assets upd
This commit is contained in:
@@ -32,8 +32,8 @@ Thank you to all the supporters!
|
||||
- Renamed some FAPs to fix ordering in Applications, delete your `/ext/apps` folder to get rid of duplicates
|
||||
- Removed: [VB Lab Migration Assistant (By GMMan)](https://github.com/GMMan/flipperzero-vb-migrate) `Req: Vital Bracelet` (due to fap error)
|
||||
- Updated: [Dice (By Ka3u6y6a)](https://github.com/Ka3u6y6a/flipper-zero-dice)
|
||||
- Updated: [NRF24 Scanner (By vad7)](https://github.com/vad7/nrf24scan)
|
||||
- Updated: [Wii EC Analyser (By csBlueChip)](https://github.com/csBlueChip/FlipperZero_WiiEC)
|
||||
- Updated: [NRF24 Scanner v1.5 (By vad7)](https://github.com/vad7/nrf24scan)
|
||||
|
||||
## Install from Release
|
||||
FLASH STOCK FIRST BEFORE UPDATING TO CUSTOM FIRMWARE!
|
||||
@@ -225,7 +225,7 @@ $ ./fbt resources icons dolphin_ext
|
||||
- [Music Player (By DrZlo13)-OFW](https://github.com/flipperdevices/flipperzero-firmware/pull/1189)
|
||||
- [NFC Magic (By gornekich)](https://github.com/flipperdevices/flipperzero-firmware/pull/1966)
|
||||
- [NRF Sniff (By mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/nrfsniff) ([Pin Out](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/tree/420/applications/nrfsniff) from nocomp/Frog/UberGuidoZ) `Req: NRF24`
|
||||
- [NRF24 Scanner (By vad7)](https://github.com/vad7/nrf24scan)
|
||||
- [NRF24 Scanner v1.5 (By vad7)](https://github.com/vad7/nrf24scan)
|
||||
- [Ocarina (By invalidna-me)](https://github.com/invalidna-me/flipperzero-ocarina) [Here are the LOTZ Songs](https://www.zeldadungeon.net/wiki/Ocarina_of_Time_Songs)
|
||||
- [Paint (By n-o-T-I-n-s-a-n-e)](https://github.com/n-o-T-I-n-s-a-n-e)
|
||||
- [Password Generator (By anakod)](https://github.com/anakod/flipper_passgen)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# NRF24 scanner with logging and resend ability for Flipper Zero
|
||||
|
||||
An [NRF24](https://www.sparkfun.com/datasheets/Components/SMD/nRF24L01Pluss_Preliminary_Product_Specification_v1_0.pdf) driver for the [Flipper Zero](https://flipperzero.one/) device. The NRF24 is a popular line of 2.4GHz radio transceivers from Nordic Semiconductors. This library is not currently complete, but functional.
|
||||
An [NRF24](https://www.sparkfun.com/datasheets/Components/SMD/nRF24L01Pluss_Preliminary_Product_Specification_v1_0.pdf) driver for the [Flipper Zero](https://flipperzero.one/) device. The NRF24 is a popular line of 2.4GHz radio transceivers from Nordic Semiconductors.<br>
|
||||
NRF24L01+ Enhanced ShockBurst packet decoder example using Python: [nrf24_packet_decoder.py](https://raw.githubusercontent.com/vad7/nrf24scan/master/nrf24_packet_decoder.py)<br>
|
||||
<br>
|
||||
Flipper Zero FAP file: [Nrf24_Scanner.fap](https://raw.githubusercontent.com/vad7/nrf24scan/master/Nrf24_Scanner.fap)<br>
|
||||
|
||||
Settings file (default addr.txt) format:<br>
|
||||
|
||||
@@ -31,15 +34,16 @@ Long press OK - view addresses.<br>
|
||||
<br>
|
||||
<img src="https://raw.githubusercontent.com/vad7/nrf24scan/master/Screenshot-3.png">
|
||||
<br><br>
|
||||
Decode the Packet Control Field (long press OK in the list and then press '>').<br>
|
||||
Decode the Packet Control Field and check CRC (long press OK in the list and then press '<' / '>').<br>
|
||||
ESB (Enhanced Shockburst) option must be turned off.
|
||||
Press '>' to decode CRC.<br>
|
||||
<br>
|
||||
<img src="https://raw.githubusercontent.com/vad7/nrf24scan/master/Screenshot-4.png">
|
||||
<br>
|
||||
<img src="https://raw.githubusercontent.com/vad7/nrf24scan/master/Screenshot-5.png">
|
||||
<br>
|
||||
1 - pipe #<br>
|
||||
2 - Payload length (for valide packet must be 1..20 hex, or 0x33 if not DPL)<br>
|
||||
2 - Payload length (for valide packet must be 1..20 or 33 hex)<br>
|
||||
3 - PID (2 bit) + NO_ACK (1 bit)<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 7.3 KiB |
@@ -1,5 +0,0 @@
|
||||
Rate: 1
|
||||
Ch: 120
|
||||
P0: C8C801
|
||||
P1: C8C802
|
||||
P2: 03
|
||||
@@ -1,3 +0,0 @@
|
||||
Rate: 1
|
||||
Ch: 120
|
||||
P0: C8C8E5
|
||||
99
applications/plugins/nrf24scan/nrf24_packet_decoder.py
Normal file
99
applications/plugins/nrf24scan/nrf24_packet_decoder.py
Normal file
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# NRF24L01+ Enhanced ShockBurst packets decoder
|
||||
#
|
||||
payload_len_default = 4
|
||||
packets = \
|
||||
(
|
||||
'10101010 11101110 00000011 00001000 00001011 01000111 000100 10 0 10101010 10101010 10101010 10101010 00011101',
|
||||
'10101010 11001000 11001000 11000011 110011 10 0 00001011 00000011 00000101 00000000 0010001100100000',
|
||||
)
|
||||
|
||||
def bin2hex(x):
|
||||
def bin2hex_helper(r):
|
||||
while r:
|
||||
yield r[0:2].upper()
|
||||
r = r[2:]
|
||||
|
||||
fmt = "{0:0" + str(int(len(x) / 8 * 2)) + "X}"
|
||||
hex_data = fmt.format(int(x, 2))
|
||||
return list(bin2hex_helper(hex_data))
|
||||
|
||||
|
||||
def split_packet(packet, parts):
|
||||
"""Split a string of 1s and 0s into multiple substrings as specified by parts.
|
||||
Example: "111000011000", (3, 4, 2) -> ["111", "0000", "11", "000"]
|
||||
:param packet: String of 1s and 0s
|
||||
:param parts: Tuple of length of substrings
|
||||
:return: list of substrings
|
||||
"""
|
||||
out = []
|
||||
packet = packet.replace(' ', '')
|
||||
for part_length in parts:
|
||||
out.append(packet[0:part_length])
|
||||
packet = packet[part_length:]
|
||||
out.append(packet)
|
||||
return out
|
||||
|
||||
|
||||
def parse_packet(packet, address_length):
|
||||
"""Split a packet into its fields and return them as tuple."""
|
||||
preamble, address, payload_length, pid, no_ack, rest = split_packet(packet=packet,
|
||||
parts=(8, 8 * address_length, 6, 2, 1))
|
||||
payload, crc = split_packet(packet=rest, parts=((payload_len_default if int(payload_length, 2) > 32 else int(payload_length, 2)) * 8,))
|
||||
|
||||
assert preamble in ('10101010', '01010101')
|
||||
assert len(crc) in (8, 16)
|
||||
|
||||
return preamble, address, payload_length, pid, no_ack, payload, crc
|
||||
|
||||
|
||||
def crc(bits, size=8):
|
||||
"""Calculate the crc value for the polynomial initialized with 0xFF/0xFFFF)
|
||||
:param size: 8 or 16 bit crc
|
||||
:param bits: String of 1s and 0s
|
||||
:return:
|
||||
:polynomial: 1 byte CRC - standard is 0x107 = 0b100000111 = x^8+x^2+x^1+1, result the same for 0x07
|
||||
:polynomial: 2 byte CRC - standard is 0x11021 = X^16+X^12+X^5+1, result the same for 0x1021
|
||||
"""
|
||||
if size == 8:
|
||||
polynomial = 0x107
|
||||
crc = 0xFF
|
||||
else:
|
||||
polynomial = 0x11021
|
||||
crc = 0xFFFF
|
||||
max_crc_value = (1 << size) - 1 # e.g. 0xFF for mode 8bit-crc
|
||||
for bit in bits:
|
||||
bit = int(bit, 2)
|
||||
crc <<= 1
|
||||
if (crc >> size) ^ bit: # top most lfsr bit xor current data bit
|
||||
crc ^= polynomial
|
||||
crc &= max_crc_value # trim the crc to reject carry over bits
|
||||
return crc
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for packet in packets:
|
||||
fld = packet.split(' ');
|
||||
address_length = -1
|
||||
for f in fld:
|
||||
if len(f) == 6: break
|
||||
address_length += 1
|
||||
preamble, address, payload_length, pid, no_ack, payload, crc_received = \
|
||||
parse_packet(packet=packet, address_length=address_length)
|
||||
crc_size = len(crc_received)
|
||||
crc_received = hex(int(crc_received, 2))
|
||||
print(f"Packet: {packet}")
|
||||
print('\n'.join((
|
||||
f'Preamble: {preamble}',
|
||||
f'Address: {address_length} bytes - {bin2hex(address)}',
|
||||
f'Payload length in packet: {int(payload_length, 2)}, used: {(payload_len_default if int(payload_length, 2) > 32 else int(payload_length, 2))}',
|
||||
f'Pid: {int(pid, 2)}',
|
||||
f'No_ack: {int(no_ack, 2) == 1}',
|
||||
f'Payload: {bin2hex(payload)}',
|
||||
f'CRC{crc_size}: {crc_received}')))
|
||||
crc_calculated = hex(crc(address + payload_length + pid + no_ack + payload, size=crc_size))
|
||||
if crc_received == crc_calculated:
|
||||
print('CRC is valid!')
|
||||
else:
|
||||
print(f'CRC mismatch! Calculated CRC is f{crc_calculated}.')
|
||||
print('-------------')
|
||||
@@ -11,9 +11,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <nrf24.h>
|
||||
#include <u8g2.h>
|
||||
|
||||
#define TAG "nrf24scan"
|
||||
#define VERSION "1.4"
|
||||
#define VERSION "1.5"
|
||||
#define MAX_CHANNEL 125
|
||||
#define MAX_ADDR 6
|
||||
|
||||
@@ -61,6 +62,7 @@ uint8_t NRF_ESB = 0; // 0 - ShockBurst, 1 - Enhanced ShockBurst
|
||||
uint8_t NRF_DPL = 0; // 1 - Dynamic Payload Length
|
||||
uint8_t NRF_CRC = 0; // 1 - No, 1 - CRC 1byte, 2 - CRC 2byte
|
||||
uint8_t NRF_Payload = 32; // len in bytes, max 32
|
||||
uint8_t NRF_AA_OFF = 0; // Disable Auto Acknowledgement
|
||||
bool NRF_ERROR = 0;
|
||||
|
||||
struct {
|
||||
@@ -86,6 +88,7 @@ uint8_t menu_selected = 0;
|
||||
uint32_t start_time;
|
||||
uint8_t view_log_decode_PCF =
|
||||
0; // view log: 1 - decode packet control field (9b) when ESB off. After pipe # (hex): <Payload len 6b><PID_2b+NO_ACK_1b>
|
||||
uint8_t view_log_decode_CRC = 0; // CRC bytes - 1/2, 0 - none
|
||||
|
||||
#define menu_selected_max 5
|
||||
enum {
|
||||
@@ -138,7 +141,7 @@ static void add_to_str_hex_bytes_shift_9b(char* out, char* arr, int bytes) {
|
||||
out += strlen(out);
|
||||
arr++; // +8b
|
||||
do {
|
||||
snprintf(out, 4, "%02X", (((*arr) & 0x7F) << 1) | (*(arr + 1) >> 7));
|
||||
snprintf(out, 4, "%02X", ((uint8_t)(*arr << 1)) | (*(arr + 1) >> 7));
|
||||
arr++;
|
||||
out += 2;
|
||||
} while(--bytes);
|
||||
@@ -325,7 +328,7 @@ static uint8_t load_settings_file(Stream* file_stream) {
|
||||
FURI_LOG_D(TAG, "load failed. file_size: %d", file_size);
|
||||
return 1;
|
||||
}
|
||||
file_size = MIN(file_size, LOG_REC_SIZE * MAX_LOG_RECORDS * 2 + 100);
|
||||
file_size = MIN(file_size, (size_t)LOG_REC_SIZE * MAX_LOG_RECORDS * 2 + 100);
|
||||
file_buf = malloc(file_size + 1);
|
||||
if(file_buf == NULL) {
|
||||
FURI_LOG_D(TAG, "Memory low, need: %d", file_size);
|
||||
@@ -338,7 +341,7 @@ static uint8_t load_settings_file(Stream* file_stream) {
|
||||
int16_t line_num = 0;
|
||||
memset((uint8_t*)&addrs, 0, sizeof(addrs));
|
||||
bool log_loaded = false;
|
||||
while(line_ptr && line_ptr - file_buf < file_size) {
|
||||
while(line_ptr && (size_t)(line_ptr - file_buf) < file_size) {
|
||||
char* end_ptr = strstr((char*)line_ptr, "\n");
|
||||
if(end_ptr == NULL)
|
||||
end_ptr = file_buf + file_size;
|
||||
@@ -353,7 +356,7 @@ static uint8_t load_settings_file(Stream* file_stream) {
|
||||
*(end_ptr - 1) = '\0';
|
||||
line_len--;
|
||||
}
|
||||
FURI_LOG_D(TAG, " L#%d: [%d]%s", line_num, line_len, line_ptr);
|
||||
//FURI_LOG_D(TAG, " L#%d: [%d]%s", line_num, line_len, line_ptr);
|
||||
if(strncmp(line_ptr, SettingsFld_Rate, sizeof(SettingsFld_Rate) - 1) == 0) {
|
||||
NRF_rate = atoi(line_ptr + sizeof(SettingsFld_Rate));
|
||||
} else if(strncmp(line_ptr, SettingsFld_Ch, sizeof(SettingsFld_Ch) - 1) == 0) {
|
||||
@@ -373,23 +376,12 @@ static uint8_t load_settings_file(Stream* file_stream) {
|
||||
switch(a) {
|
||||
case '0':
|
||||
addrs.addr_len = ConvertHexToArray(line_ptr, addrs.addr_P0, 5);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" +Addr(%d): %02X%02X%02X...",
|
||||
addrs.addr_len,
|
||||
addrs.addr_P0[0],
|
||||
addrs.addr_P0[1],
|
||||
addrs.addr_P0[2]);
|
||||
//FURI_LOG_D(TAG, " +Addr(%d): %02X%02X%02X...", addrs.addr_len, addrs.addr_P0[0], addrs.addr_P0[1], addrs.addr_P0[2]);
|
||||
if(addrs.addr_len >= 2) err = 0;
|
||||
break;
|
||||
case '1':
|
||||
ConvertHexToArray(line_ptr, addrs.addr_P1, 5);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
" +Addr: %02X%02X%02X...",
|
||||
addrs.addr_P0[1],
|
||||
addrs.addr_P1[1],
|
||||
addrs.addr_P1[2]);
|
||||
//FURI_LOG_D(TAG, " +Addr: %02X%02X%02X...", addrs.addr_P0[1], addrs.addr_P1[1], addrs.addr_P1[2]);
|
||||
break;
|
||||
case '2':
|
||||
ConvertHexToArray(line_ptr, &addrs.addr_P2, 1);
|
||||
@@ -416,7 +408,9 @@ static uint8_t load_settings_file(Stream* file_stream) {
|
||||
}
|
||||
if(log_arr_idx < MAX_LOG_RECORDS - 1) {
|
||||
ConvertHexToArray(
|
||||
line_ptr, APP->log_arr + log_arr_idx * LOG_REC_SIZE, MIN(NRF_Payload, 32));
|
||||
line_ptr,
|
||||
APP->log_arr + log_arr_idx * LOG_REC_SIZE,
|
||||
MIN(NRF_Payload + 1, LOG_REC_SIZE));
|
||||
log_arr_idx++;
|
||||
}
|
||||
}
|
||||
@@ -447,14 +441,15 @@ static void prepare_nrf24() {
|
||||
0x70 | ((NRF_CRC == 1 ? 0b1000 :
|
||||
NRF_CRC == 2 ? 0b1100 :
|
||||
0))); // Mask all interrupts
|
||||
nrf24_write_reg(nrf24_HANDLE, REG_SETUP_RETR, NRF_ESB ? 1 : 0); // Automatic Retransmission
|
||||
nrf24_write_reg(nrf24_HANDLE, REG_EN_AA, 0); // Disable auto acknowledgement
|
||||
nrf24_write_reg(nrf24_HANDLE, REG_SETUP_RETR, NRF_ESB ? 0x11 : 0); // Automatic Retransmission
|
||||
nrf24_write_reg(
|
||||
nrf24_HANDLE, REG_EN_AA, NRF_AA_OFF || !NRF_ESB ? 0 : 0x3F); // Auto acknowledgement
|
||||
nrf24_write_reg(
|
||||
nrf24_HANDLE,
|
||||
REG_FEATURE,
|
||||
1 + (NRF_DPL ?
|
||||
4 :
|
||||
1)); // Enables the W_TX_PAYLOAD_NOACK command, Disable Payload with ACK, set Dynamic Payload
|
||||
NRF_DPL ?
|
||||
4 + 1 :
|
||||
1); // Enables the W_TX_PAYLOAD_NOACK command, Disable Payload with ACK, set Dynamic Payload
|
||||
nrf24_set_maclen(nrf24_HANDLE, addrs.addr_len);
|
||||
for(int i = 0; i < addrs.addr_len; i++) addr[i] = addrs.addr_P0[addrs.addr_len - i - 1];
|
||||
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P0, addr, addrs.addr_len);
|
||||
@@ -525,7 +520,6 @@ bool nrf24_read_newpacket() {
|
||||
if(APP->log_arr == NULL) return false;
|
||||
bool found = false;
|
||||
uint8_t packetsize;
|
||||
uint8_t packet[32] = {0};
|
||||
uint8_t* ptr = APP->log_arr + log_arr_idx * LOG_REC_SIZE;
|
||||
uint8_t status = nrf24_rxpacket(nrf24_HANDLE, ptr + 1, &packetsize, !NRF_DPL);
|
||||
if(status & RX_DR) {
|
||||
@@ -561,6 +555,37 @@ bool nrf24_send_packet() {
|
||||
return last_packet_send_st;
|
||||
}
|
||||
|
||||
uint16_t calc_crc(uint32_t crc, uint8_t* ptr, uint8_t bitnum, uint16_t bits) {
|
||||
//uint8_t bitnum = 7;
|
||||
uint32_t crc_high, polynom;
|
||||
if(view_log_decode_CRC == 2) {
|
||||
crc_high = (1 << 16);
|
||||
polynom = 0x11021; // X^16+X^12+X^5+1
|
||||
} else {
|
||||
crc_high = (1 << 8);
|
||||
polynom = 0x107; // x^8+x^2+x^1+1
|
||||
}
|
||||
while(bits--) {
|
||||
crc <<= 1;
|
||||
if(((crc & crc_high) != 0) ^ ((*ptr >> bitnum) & 1)) crc ^= polynom;
|
||||
if(bitnum == 0) {
|
||||
ptr++;
|
||||
bitnum = 7;
|
||||
} else
|
||||
bitnum--;
|
||||
}
|
||||
return crc & (view_log_decode_CRC == 2 ? 0xFFFF : 0xFF);
|
||||
}
|
||||
|
||||
// shifted 1 bit right
|
||||
uint16_t get_shifted_crc(uint8_t* pcrc) {
|
||||
uint16_t crc = ((uint8_t)(*pcrc << 1)) | (*(pcrc + 1) >> 7);
|
||||
if(view_log_decode_CRC == 2) {
|
||||
crc = (crc << 8) | (((uint8_t)(*(pcrc + 1) << 1))) | (*(pcrc + 2) >> 7);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
const PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25);
|
||||
if(plugin_state == NULL) return;
|
||||
@@ -580,6 +605,10 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
if(NRF_DPL) strcat(screen_buf, " DPL");
|
||||
canvas_draw_str(canvas, 80, 20, screen_buf);
|
||||
}
|
||||
if(NRF_AA_OFF) {
|
||||
canvas_draw_str(canvas, 61, 20, "AA");
|
||||
canvas_draw_line(canvas, 60, 21, 72, 12);
|
||||
}
|
||||
snprintf(
|
||||
screen_buf,
|
||||
sizeof(screen_buf),
|
||||
@@ -588,21 +617,19 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
NRF_rate == 1 ? "1M" :
|
||||
"250K"); // menu_selected = 2
|
||||
canvas_draw_str(canvas, 10, 30, screen_buf);
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
snprintf(screen_buf, sizeof(screen_buf), "R:%d", NRF_Payload);
|
||||
snprintf(screen_buf, sizeof(screen_buf), "Payload: %d", NRF_Payload);
|
||||
canvas_draw_str(canvas, 80, 30, screen_buf);
|
||||
if(NRF_CRC == 1)
|
||||
canvas_draw_str(canvas, 105, 30, "CRC1");
|
||||
else if(NRF_CRC == 2)
|
||||
canvas_draw_str(canvas, 105, 30, "CRC2");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
strcpy(screen_buf, "Find channel period: "); // menu_selected = 3
|
||||
strcpy(screen_buf, "Next Ch time: "); // menu_selected = 3
|
||||
if(find_channel_period == 0)
|
||||
strcat(screen_buf, "off");
|
||||
else
|
||||
snprintf(
|
||||
screen_buf + strlen(screen_buf), sizeof(screen_buf), "%d s", find_channel_period);
|
||||
canvas_draw_str(canvas, 10, 40, screen_buf);
|
||||
if(NRF_CRC == 1)
|
||||
canvas_draw_str(canvas, 99, 40, "CRC1");
|
||||
else if(NRF_CRC == 2)
|
||||
canvas_draw_str(canvas, 99, 40, "CRC2");
|
||||
snprintf(
|
||||
screen_buf,
|
||||
sizeof(screen_buf),
|
||||
@@ -649,8 +676,6 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
if(view_log_arr_idx >= log_arr_idx) view_log_arr_idx = log_arr_idx - 1;
|
||||
uint16_t page = view_log_arr_idx & ~7;
|
||||
for(uint8_t i = 0; i < 8 && page + i < log_arr_idx; i++) {
|
||||
snprintf(screen_buf, sizeof(screen_buf), "%d:", page + i + 1);
|
||||
canvas_draw_str(canvas, 0, 14 + i * 7, screen_buf);
|
||||
screen_buf[0] = (view_log_arr_idx & 7) != i ? ' ' :
|
||||
last_packet_send != view_log_arr_idx ? '>' :
|
||||
last_packet_send_st ? '*' :
|
||||
@@ -661,31 +686,110 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
uint8_t pipe = dpl & 7;
|
||||
dpl >>= 3;
|
||||
if(dpl == 0) dpl = 32;
|
||||
if(view_log_decode_PCF && dpl == 32) dpl -= 2;
|
||||
int count = dpl - view_log_arr_x;
|
||||
uint8_t max_width = view_log_arr_x == 0 && addrs.addr_count > 1 ?
|
||||
view_log_decode_PCF ? VIEW_LOG_WIDTH_B - 3 :
|
||||
VIEW_LOG_WIDTH_B - 1 :
|
||||
VIEW_LOG_WIDTH_B;
|
||||
if(view_log_decode_PCF) count--;
|
||||
uint8_t max_width = VIEW_LOG_WIDTH_B;
|
||||
if(view_log_arr_x == 0) {
|
||||
if(addrs.addr_count > 1) max_width--;
|
||||
if(view_log_decode_PCF) max_width -= 2;
|
||||
}
|
||||
if(count > max_width) count = max_width;
|
||||
ptr += view_log_arr_x;
|
||||
uint8_t* crcptr = NULL;
|
||||
uint8_t pre = 0;
|
||||
if(count > 0) {
|
||||
if(view_log_decode_CRC) {
|
||||
static uint16_t prev_addr_CRC;
|
||||
static int8_t prev_pipe = -1;
|
||||
uint8_t* pcrc = APP->log_arr + (page + i) * LOG_REC_SIZE + 1;
|
||||
uint16_t crc;
|
||||
if(prev_pipe == pipe) {
|
||||
crc = prev_addr_CRC;
|
||||
} else {
|
||||
crc = view_log_decode_CRC == 2 ? 0xFFFF : 0xFF;
|
||||
if(pipe <= 1) {
|
||||
crc = calc_crc(
|
||||
crc,
|
||||
pipe == 0 ? addrs.addr_P0 : addrs.addr_P1,
|
||||
7,
|
||||
addrs.addr_len * 8);
|
||||
} else {
|
||||
crc = calc_crc(crc, addrs.addr_P1, 7, (addrs.addr_len - 1) * 8);
|
||||
crc = calc_crc(
|
||||
crc,
|
||||
pipe == 2 ? &addrs.addr_P2 :
|
||||
pipe == 3 ? &addrs.addr_P3 :
|
||||
pipe == 4 ? &addrs.addr_P4 :
|
||||
&addrs.addr_P5,
|
||||
7,
|
||||
8);
|
||||
}
|
||||
prev_addr_CRC = crc;
|
||||
prev_pipe = pipe;
|
||||
}
|
||||
if(view_log_decode_PCF) {
|
||||
crc = calc_crc(crc, pcrc++, 7, 9);
|
||||
if(crc == get_shifted_crc(pcrc)) crcptr = pcrc;
|
||||
if(crcptr == NULL) {
|
||||
for(int8_t j = 0; j < (int8_t)dpl - view_log_decode_CRC - 1; j++) {
|
||||
crc = calc_crc(crc, pcrc++, 6, 8);
|
||||
if(crc == get_shifted_crc(pcrc)) {
|
||||
crcptr = pcrc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(int8_t j = 0; j < (int8_t)dpl - view_log_decode_CRC; j++) {
|
||||
crc = calc_crc(crc, pcrc++, 7, 8);
|
||||
if((view_log_decode_CRC == 1 && crc == *pcrc) ||
|
||||
(view_log_decode_CRC == 2 &&
|
||||
crc == ((*pcrc << 8) | *(pcrc + 1)))) {
|
||||
crcptr = pcrc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(max_width < VIEW_LOG_WIDTH_B) {
|
||||
snprintf(screen_buf + 1, 10, "%X-", pipe);
|
||||
if(view_log_decode_PCF)
|
||||
snprintf(
|
||||
pre += snprintf(screen_buf + 1, 10, "%X-", pipe);
|
||||
if(view_log_decode_PCF) {
|
||||
pre += snprintf(
|
||||
screen_buf + strlen(screen_buf),
|
||||
10,
|
||||
"%02X%01X-",
|
||||
*ptr >> 2,
|
||||
((*ptr & 3) << 1) | (*(ptr + 1) >> 7));
|
||||
}
|
||||
}
|
||||
if(view_log_decode_PCF)
|
||||
add_to_str_hex_bytes_shift_9b(screen_buf, ptr, count);
|
||||
else
|
||||
add_to_str_hex_bytes(screen_buf, ptr, count);
|
||||
}
|
||||
canvas_draw_str(canvas, 3 * 5, 14 + i * 7, screen_buf);
|
||||
uint16_t y = 14 + i * 7;
|
||||
canvas_draw_str(canvas, 3 * 5, y, screen_buf);
|
||||
uint16_t x = snprintf(screen_buf, sizeof(screen_buf), "%d", page + i + 1);
|
||||
canvas_draw_str(canvas, 0, y, screen_buf);
|
||||
if(crcptr) { // 5x7 font, 9 lines
|
||||
canvas_draw_str(canvas, x * 5, y, "=");
|
||||
int n = crcptr - (uint8_t*)ptr - 1;
|
||||
if(n > -view_log_decode_CRC && n < count) {
|
||||
int len;
|
||||
x = (4 + pre) * 5;
|
||||
if(n < 0) {
|
||||
len = view_log_decode_CRC + n;
|
||||
n = 0;
|
||||
} else {
|
||||
len = MIN(view_log_decode_CRC, count - n);
|
||||
x += n * 2 * 5;
|
||||
canvas_draw_line(canvas, x - 1, y, x - 1, y - 1);
|
||||
}
|
||||
canvas_draw_line(canvas, x - 1, y, n = x + len * 2 * 5 - 1, y);
|
||||
canvas_draw_line(canvas, n, y, n, y - 1);
|
||||
}
|
||||
} else
|
||||
canvas_draw_str(canvas, x * 5, y, ":");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -723,7 +827,15 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
screen_buf[0] = 'v';
|
||||
strcpy(screen_buf + 1, VERSION);
|
||||
canvas_draw_str(canvas, 108, 7, screen_buf);
|
||||
if(view_log_decode_PCF) canvas_draw_str(canvas, 78, 64, "Decode PCF");
|
||||
if(view_log_decode_PCF || view_log_decode_CRC) {
|
||||
strcpy(screen_buf, "Decode: ");
|
||||
if(view_log_decode_PCF) strcat(screen_buf, "PCF ");
|
||||
if(view_log_decode_CRC == 1)
|
||||
strcat(screen_buf, "CRC1");
|
||||
else if(view_log_decode_CRC == 2)
|
||||
strcat(screen_buf, "CRC2");
|
||||
canvas_draw_str(canvas, 0, 64, screen_buf);
|
||||
}
|
||||
}
|
||||
release_mutex((ValueMutex*)ctx, plugin_state);
|
||||
}
|
||||
@@ -809,39 +921,6 @@ int32_t nrf24scan_app(void* p) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(event.input.type == InputTypePress || event.input.type == InputTypeRepeat) {
|
||||
if(what_doing == 0) {
|
||||
switch(menu_selected) {
|
||||
case Menu_open_file:
|
||||
save_settings ^= 1;
|
||||
break;
|
||||
case Menu_enter_channel:
|
||||
NRF_channel += event.input.type == InputTypeRepeat ? 10 : 1;
|
||||
if(NRF_channel > MAX_CHANNEL) NRF_channel = 0;
|
||||
break;
|
||||
case Menu_enter_rate:
|
||||
NRF_rate++;
|
||||
if(NRF_rate > 2) NRF_rate = 0;
|
||||
break;
|
||||
case Menu_enter_scan_period:
|
||||
find_channel_period += event.input.type == InputTypeRepeat ? 10 :
|
||||
1;
|
||||
break;
|
||||
case Menu_log:
|
||||
if(++log_to_file > 2) log_to_file = -1;
|
||||
break;
|
||||
case Menu_ok:
|
||||
what_to_do = !what_to_do;
|
||||
break;
|
||||
}
|
||||
} else if(what_doing == 1) {
|
||||
if(view_log_arr_x < VIEW_LOG_MAX_X) view_log_arr_x++;
|
||||
} else if(what_doing == 2) {
|
||||
if(NRF_ESB == 0) view_log_decode_PCF ^= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(event.input.type == InputTypePress || event.input.type == InputTypeRepeat) {
|
||||
if(what_doing == 0) {
|
||||
@@ -852,7 +931,7 @@ int32_t nrf24scan_app(void* p) {
|
||||
break;
|
||||
case Menu_enter_rate:
|
||||
NRF_Payload -= event.input.type == InputTypeRepeat ? 10 : 1;
|
||||
if(NRF_Payload == 0 || NRF_Payload > 32) NRF_Payload = 32;
|
||||
if(NRF_Payload == 0 || NRF_Payload > 32) NRF_Payload = 1;
|
||||
break;
|
||||
case Menu_enter_scan_period:
|
||||
find_channel_period -= event.input.type == InputTypeRepeat ? 10 :
|
||||
@@ -868,6 +947,42 @@ int32_t nrf24scan_app(void* p) {
|
||||
}
|
||||
} else if(what_doing == 1) {
|
||||
if(view_log_arr_x > 0) view_log_arr_x--;
|
||||
} else if(what_doing == 2) {
|
||||
//if(NRF_ESB == 0)
|
||||
view_log_decode_PCF ^= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(event.input.type == InputTypePress || event.input.type == InputTypeRepeat) {
|
||||
if(what_doing == 0) {
|
||||
switch(menu_selected) {
|
||||
case Menu_open_file:
|
||||
save_settings ^= 1;
|
||||
break;
|
||||
case Menu_enter_channel:
|
||||
NRF_channel += event.input.type == InputTypeRepeat ? 10 : 1;
|
||||
if(NRF_channel > MAX_CHANNEL) NRF_channel = 0;
|
||||
break;
|
||||
case Menu_enter_rate:
|
||||
NRF_Payload += event.input.type == InputTypeRepeat ? 10 : 1;
|
||||
if(NRF_Payload == 0 || NRF_Payload > 32) NRF_Payload = 32;
|
||||
break;
|
||||
case Menu_enter_scan_period:
|
||||
find_channel_period += event.input.type == InputTypeRepeat ? 10 :
|
||||
1;
|
||||
break;
|
||||
case Menu_log:
|
||||
if(++log_to_file > 2) log_to_file = -1;
|
||||
break;
|
||||
case Menu_ok:
|
||||
what_to_do = !what_to_do;
|
||||
break;
|
||||
}
|
||||
} else if(what_doing == 1) {
|
||||
if(view_log_arr_x < VIEW_LOG_MAX_X) view_log_arr_x++;
|
||||
} else if(what_doing == 2) {
|
||||
if(++view_log_decode_CRC > 2) view_log_decode_CRC = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -895,29 +1010,23 @@ int32_t nrf24scan_app(void* p) {
|
||||
stream_free(file_stream);
|
||||
}
|
||||
break;
|
||||
case Menu_enter_channel:
|
||||
if(NRF_ESB) {
|
||||
if(NRF_DPL)
|
||||
NRF_DPL = NRF_ESB = 0;
|
||||
else
|
||||
NRF_DPL = 1;
|
||||
} else
|
||||
NRF_ESB = 1;
|
||||
if(NRF_ESB) view_log_decode_PCF = 0;
|
||||
break;
|
||||
case Menu_enter_rate:
|
||||
NRF_rate++;
|
||||
if(NRF_rate > 2) NRF_rate = 0;
|
||||
break;
|
||||
case Menu_enter_scan_period:
|
||||
if(++NRF_CRC > 2) NRF_CRC = 0;
|
||||
break;
|
||||
case Menu_ok:
|
||||
if(what_to_do) {
|
||||
if(addrs.addr_count) {
|
||||
what_doing = 1;
|
||||
if(log_to_file == -1) {
|
||||
clear_log();
|
||||
save_to_new_log = true;
|
||||
} else if(log_to_file == 1)
|
||||
save_to_new_log = true;
|
||||
start_scanning();
|
||||
if(!NRF_ERROR) what_doing = 1;
|
||||
}
|
||||
} else
|
||||
what_doing = 1;
|
||||
@@ -927,20 +1036,35 @@ int32_t nrf24scan_app(void* p) {
|
||||
}
|
||||
} else if(event.input.type == InputTypeLong) {
|
||||
if(what_doing == 0) {
|
||||
if(menu_selected == Menu_log) { // Log
|
||||
if(menu_selected == Menu_enter_channel) {
|
||||
NRF_AA_OFF ^= 1;
|
||||
key_press_seq_ok = event.input.sequence;
|
||||
} else if(menu_selected == Menu_log) { // Log
|
||||
if(log_arr_idx && (log_to_file == 1 || log_to_file == 2)) {
|
||||
write_to_log_file(APP->storage, false);
|
||||
clear_log();
|
||||
}
|
||||
}
|
||||
nrf24_set_idle(nrf24_HANDLE);
|
||||
} else if(what_doing == 1) {
|
||||
what_doing = 2;
|
||||
}
|
||||
} else if(event.input.type == InputTypeRelease) {
|
||||
if(what_doing == 1 && key_press_seq_ok != event.input.sequence) { // Send
|
||||
if(key_press_seq_ok != event.input.sequence) {
|
||||
if(what_doing == 0) {
|
||||
if(menu_selected == Menu_enter_channel) {
|
||||
if(NRF_ESB) {
|
||||
if(NRF_DPL)
|
||||
NRF_DPL = NRF_ESB = 0;
|
||||
else
|
||||
NRF_DPL = 1;
|
||||
} else
|
||||
NRF_ESB = 1;
|
||||
//if(NRF_ESB) view_log_decode_PCF = 0;
|
||||
}
|
||||
} else if(what_doing == 1) { // Send
|
||||
nrf24_send_packet();
|
||||
}
|
||||
}
|
||||
key_press_seq_ok--;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3,12 +3,12 @@ Version: 1
|
||||
|
||||
Width: 128
|
||||
Height: 64
|
||||
Passive frames: 10
|
||||
Active frames: 42
|
||||
Frames order: 11 11 12 13 14 15 14 13 12 11 0 1 1 1 2 2 3 4 4 5 6 7 7 8 8 9 10 10 10 11 11 11 11 11 11 12 12 13 13 14 14 15 15 15 15 15 16 16 17 18 18 18
|
||||
Active cycles: 1
|
||||
Passive frames: 54
|
||||
Active frames: 0
|
||||
Frames order: 0 0 0 0 1 1 1 2 2 3 4 4 5 6 7 7 8 8 9 10 10 10 11 11 11 11 11 11 12 12 13 13 14 14 15 15 15 15 15 16 16 17 18 18 18 18 18 18 18 18 18 18 18 18
|
||||
Active cycles: 0
|
||||
Frame rate: 6
|
||||
Duration: 3600
|
||||
Active cooldown: 4
|
||||
Active cooldown: 0
|
||||
|
||||
Bubble slots: 0
|
||||
|
||||
BIN
assets/resources/dolphin/L1_New_year_128x64/frame_0.bm
Normal file
BIN
assets/resources/dolphin/L1_New_year_128x64/frame_0.bm
Normal file
Binary file not shown.
BIN
assets/resources/dolphin/L1_New_year_128x64/frame_1.bm
Normal file
BIN
assets/resources/dolphin/L1_New_year_128x64/frame_1.bm
Normal file
Binary file not shown.
BIN
assets/resources/dolphin/L1_New_year_128x64/frame_2.bm
Normal file
BIN
assets/resources/dolphin/L1_New_year_128x64/frame_2.bm
Normal file
Binary file not shown.
BIN
assets/resources/dolphin/L1_New_year_128x64/frame_3.bm
Normal file
BIN
assets/resources/dolphin/L1_New_year_128x64/frame_3.bm
Normal file
Binary file not shown.
14
assets/resources/dolphin/L1_New_year_128x64/meta.txt
Normal file
14
assets/resources/dolphin/L1_New_year_128x64/meta.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Filetype: Flipper Animation
|
||||
Version: 1
|
||||
|
||||
Width: 128
|
||||
Height: 64
|
||||
Passive frames: 4
|
||||
Active frames: 0
|
||||
Frames order: 0 1 2 3
|
||||
Active cycles: 0
|
||||
Frame rate: 2
|
||||
Duration: 3600
|
||||
Active cooldown: 0
|
||||
|
||||
Bubble slots: 0
|
||||
@@ -3,12 +3,12 @@ Version: 1
|
||||
|
||||
Width: 128
|
||||
Height: 64
|
||||
Passive frames: 10
|
||||
Active frames: 40
|
||||
Passive frames: 50
|
||||
Active frames: 0
|
||||
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
||||
Active cycles: 1
|
||||
Active cycles: 0
|
||||
Frame rate: 6
|
||||
Duration: 3600
|
||||
Active cooldown: 4
|
||||
Active cooldown: 0
|
||||
|
||||
Bubble slots: 0
|
||||
|
||||
@@ -3,12 +3,12 @@ Version: 1
|
||||
|
||||
Width: 128
|
||||
Height: 64
|
||||
Passive frames: 10
|
||||
Active frames: 38
|
||||
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 46
|
||||
Active cycles: 1
|
||||
Passive frames: 47
|
||||
Active frames: 0
|
||||
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
||||
Active cycles: 0
|
||||
Frame rate: 5
|
||||
Duration: 3600
|
||||
Active cooldown: 1
|
||||
Active cooldown: 0
|
||||
|
||||
Bubble slots: 0
|
||||
|
||||
@@ -3,12 +3,12 @@ Version: 1
|
||||
|
||||
Width: 128
|
||||
Height: 64
|
||||
Passive frames: 10
|
||||
Active frames: 20
|
||||
Passive frames: 30
|
||||
Active frames: 0
|
||||
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
||||
Active cycles: 1
|
||||
Active cycles: 0
|
||||
Frame rate: 6
|
||||
Duration: 3600
|
||||
Active cooldown: 4
|
||||
Active cooldown: 0
|
||||
|
||||
Bubble slots: 0
|
||||
|
||||
@@ -3,13 +3,13 @@ Version: 1
|
||||
|
||||
Width: 128
|
||||
Height: 64
|
||||
Passive frames: 9
|
||||
Active frames: 99
|
||||
Frames order: 0 1 2 3 4 3 2 1 0 1 2 3 4 5 6 7 8 9 10 11 11 11 11 11 11 11 11 11 11 11 11 12 12 12 12 12 12 12 13 14 15 16 17 18 17 18 17 18 19 20 19 20 19 20 19 20 19 20 21 22 21 22 22 22 23 24 25 26 27 28 29 30 31 32 33 0 34 35 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 37 38
|
||||
Active cycles: 1
|
||||
Passive frames: 100
|
||||
Active frames: 0
|
||||
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 11 11 11 11 11 11 11 11 11 11 11 12 12 12 12 12 12 12 13 14 15 16 17 18 17 18 17 18 19 20 19 20 19 20 19 20 19 20 21 22 21 22 22 22 23 24 25 26 27 28 29 30 31 32 33 0 34 35 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 37 38
|
||||
Active cycles: 0
|
||||
Frame rate: 4
|
||||
Duration: 3600
|
||||
Active cooldown: 4
|
||||
Active cooldown: 0
|
||||
|
||||
Bubble slots: 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user