diff --git a/dist/proto_pirate.fap b/dist/proto_pirate.fap
index 67caf70..d3f9d03 100644
Binary files a/dist/proto_pirate.fap and b/dist/proto_pirate.fap differ
diff --git a/views/protopirate_receiver.c b/views/protopirate_receiver.c
index af4a174..b36d127 100644
--- a/views/protopirate_receiver.c
+++ b/views/protopirate_receiver.c
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
#define FRAME_HEIGHT 12
#define MAX_LEN_PX 112
@@ -34,6 +35,7 @@ typedef struct {
bool external_radio;
ProtoPirateLock lock;
uint8_t lock_count;
+ uint8_t animation_frame;
} ProtoPirateReceiverModel;
void protopirate_view_receiver_set_rssi(ProtoPirateReceiver* receiver, float rssi) {
@@ -133,27 +135,14 @@ static void protopirate_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, b
canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11);
}
-static void protopirate_view_receiver_draw_rssi(Canvas* canvas, ProtoPirateReceiverModel* model) {
- uint8_t x = 58;
- uint8_t y = 51;
- float rssi = model->rssi;
-
- if(rssi >= -60.0f) {
- canvas_draw_box(canvas, x + 8, y + 2, 4, 5);
- }
- if(rssi >= -70.0f) {
- canvas_draw_box(canvas, x + 4, y + 4, 4, 3);
- }
- if(rssi >= -80.0f) {
- canvas_draw_box(canvas, x, y + 6, 4, 1);
- }
-}
-
void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* model) {
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
+ // Increment animation frame
+ model->animation_frame = (model->animation_frame + 1) % 96;
+
size_t item_count = ProtoPirateReceiverMenuItemArray_size(model->history_item_arr);
bool scrollbar = item_count > MENU_ITEMS;
@@ -161,6 +150,7 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
str_buff = furi_string_alloc();
if(item_count > 0) {
+ // Draw received items list
size_t shift_position = model->list_offset;
for(size_t i = 0; i < MIN(item_count, MENU_ITEMS); i++) {
@@ -184,34 +174,158 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
elements_scrollbar_pos(canvas, 128, 0, 49, shift_position, item_count);
}
} else {
- canvas_draw_str_aligned(canvas, 64, 14, AlignCenter, AlignCenter, "ProtoPirate");
- canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignCenter, "Waiting for signal...");
- canvas_draw_str_aligned(canvas, 64, 38, AlignCenter, AlignCenter, "<- to Config");
+ // Cool animated radar with expanding dots
+ int center_x = 64;
+ int center_y = 22;
+
+ // Three waves of expanding circles with different speeds
+ for(int wave = 0; wave < 3; wave++) {
+ // Calculate radius for this wave with offset
+ int base_radius = ((model->animation_frame + wave * 32) % 96) / 3;
+
+ if(base_radius < 28) {
+ // Calculate fade based on distance from center
+ int dot_density = 24 - (base_radius / 2);
+
+ // Draw circle with dots
+ for(int angle = 0; angle < 360; angle += (360 / dot_density)) {
+ float rad = (angle + wave * 15) * 3.14159 / 180.0;
+ int x = center_x + base_radius * cosf(rad);
+ int y = center_y + base_radius * sinf(rad);
+
+ // Only draw if within bounds and create fade effect
+ if(x > 0 && x < 128 && y > 0 && y < 48) {
+ // Dots get smaller/fade as they expand
+ if(base_radius < 10) {
+ canvas_draw_dot(canvas, x, y);
+ // Double dot for inner circles for brightness
+ if(base_radius < 5) {
+ canvas_draw_dot(canvas, x+1, y);
+ }
+ } else if(base_radius < 20) {
+ // Skip some dots for fade effect
+ if(angle % 30 == 0) {
+ canvas_draw_dot(canvas, x, y);
+ }
+ } else {
+ // Very sparse dots at edge
+ if(angle % 60 == 0) {
+ canvas_draw_dot(canvas, x, y);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Static guide circles (very faint)
+ for(int angle = 0; angle < 360; angle += 45) {
+ float rad = angle * 3.14159 / 180.0;
+ canvas_draw_dot(canvas, center_x + 15 * cosf(rad), center_y + 15 * sinf(rad));
+ }
+
+ // Rotating sweep line with glow effect
+ float sweep_angle = (model->animation_frame * 3.75) * 3.14159 / 180.0;
+
+ // Main sweep line
+ int sweep_x = center_x + 22 * cosf(sweep_angle);
+ int sweep_y = center_y + 22 * sinf(sweep_angle);
+ canvas_draw_line(canvas, center_x, center_y, sweep_x, sweep_y);
+
+ // Sweep "glow" - additional lines at slight offsets
+ float glow_angle1 = sweep_angle - 0.05;
+ float glow_angle2 = sweep_angle + 0.05;
+ canvas_draw_line(canvas, center_x, center_y,
+ center_x + 20 * cosf(glow_angle1),
+ center_y + 20 * sinf(glow_angle1));
+ canvas_draw_line(canvas, center_x, center_y,
+ center_x + 20 * cosf(glow_angle2),
+ center_y + 20 * sinf(glow_angle2));
+
+ // Sweep trail (fading dots)
+ for(int i = 1; i <= 12; i++) {
+ float trail_angle = sweep_angle - (i * 0.15);
+ int trail_radius = 22 - i;
+ if(trail_radius > 0) {
+ int trail_x = center_x + trail_radius * cosf(trail_angle);
+ int trail_y = center_y + trail_radius * sinf(trail_angle);
+ // Only draw every other dot in trail for fade effect
+ if(i % 2 == 0 || i < 4) {
+ canvas_draw_dot(canvas, trail_x, trail_y);
+ }
+ }
+ }
+
+ // Pulsing center
+ int pulse = (model->animation_frame % 32);
+ if(pulse < 16) {
+ canvas_draw_disc(canvas, center_x, center_y, 2);
+ } else {
+ canvas_draw_circle(canvas, center_x, center_y, 2);
+ }
+ if(pulse < 8 || (pulse > 16 && pulse < 24)) {
+ canvas_draw_dot(canvas, center_x, center_y);
+ }
+
+ // Left-aligned config hint
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str(canvas, 2, 45, "< Config");
}
furi_string_free(str_buff);
+ // Status bar separator
canvas_set_color(canvas, ColorBlack);
canvas_draw_line(canvas, 0, 48, 127, 48);
// Draw status bar
canvas_set_font(canvas, FontSecondary);
- canvas_draw_str(canvas, 2, 58, furi_string_get_cstr(model->frequency_str));
- canvas_draw_str(canvas, 40, 58, furi_string_get_cstr(model->preset_str));
+
+ // Activity indicator - pulsing when receiving
+ if(model->rssi > -90) {
+ int pulse = model->animation_frame % 16;
+ if(pulse < 8) {
+ canvas_draw_disc(canvas, 2, 54, 1);
+ }
+ }
+
+ // Frequency
+ canvas_draw_str(canvas, 5, 58, furi_string_get_cstr(model->frequency_str));
+
+ // Preset
+ canvas_draw_str(canvas, 44, 58, furi_string_get_cstr(model->preset_str));
+
+ // History counter
canvas_draw_str_aligned(
- canvas, 110, 58, AlignCenter, AlignBottom, furi_string_get_cstr(model->history_stat_str));
+ canvas, 108, 58, AlignCenter, AlignBottom, furi_string_get_cstr(model->history_stat_str));
- // Draw RSSI
- protopirate_view_receiver_draw_rssi(canvas, model);
+ // Draw RSSI indicator with animation
+ uint8_t x = 70;
+ uint8_t y = 51;
+ float rssi = model->rssi;
- // Draw external radio indicator if needed
- if(model->external_radio) {
- canvas_draw_str(canvas, 100, 58, "Ext");
+ if(rssi >= -80.0f) {
+ canvas_draw_box(canvas, x, y + 5, 3, 2);
+ }
+ if(rssi >= -70.0f) {
+ canvas_draw_box(canvas, x + 4, y + 3, 3, 4);
+ }
+ if(rssi >= -60.0f) {
+ canvas_draw_box(canvas, x + 8, y + 1, 3, 6);
+ // Pulse effect for strong signal
+ if(model->animation_frame % 24 < 12) {
+ canvas_draw_frame(canvas, x + 7, y, 5, 8);
+ }
}
- // Draw lock indicator
+ // External radio indicator
+ if(model->external_radio) {
+ canvas_draw_str(canvas, 116, 58, "E");
+ }
+
+ // Lock indicator
if(model->lock == ProtoPirateLockOn) {
- canvas_draw_str(canvas, 119, 58, "L");
+ canvas_draw_str(canvas, 122, 58, "L");
}
}
@@ -367,6 +481,7 @@ ProtoPirateReceiver* protopirate_view_receiver_alloc() {
model->external_radio = false;
model->lock = ProtoPirateLockOff;
model->lock_count = 0;
+ model->animation_frame = 0;
},
true);
@@ -424,4 +539,4 @@ void protopirate_view_receiver_set_idx_menu(ProtoPirateReceiver* receiver, uint1
},
true);
protopirate_view_receiver_update_offset(receiver);
-}
+}
\ No newline at end of file