adaptation to the new build system + fixes

This commit is contained in:
Eng1n33r 2022-06-26 20:57:29 +03:00
parent aaeede7793
commit 1c55a55ddd
No known key found for this signature in database
GPG key ID: 6C4C311DFD4B4AB5
28 changed files with 173 additions and 868 deletions

View file

@ -11,23 +11,15 @@ steps:
- git submodule foreach git config --local gc.auto 0
- git log -1 --format='%H'
- name: 'Rebuild Assets'
image: hfdj/fztools
pull: never
commands:
- export DIST_SUFFIX=${DRONE_TAG}
- export WORKFLOW_BRANCH_OR_TAG=${DRONE_TAG}
- make assets_rebuild assets_manifest
- name: 'Build default fw'
image: hfdj/fztools
pull: never
commands:
- export DIST_SUFFIX=${DRONE_TAG}
- export WORKFLOW_BRANCH_OR_TAG=${DRONE_TAG}
- make updater_package TARGET=f7 DEBUG=0 COMPACT=1
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
- ./fbt --with-updater COMPACT=1 DEBUG=0 updater_package
- mkdir artifacts-default
- mv dist/f7/* artifacts-default/
- mv dist/f7-C/* artifacts-default/
- ls -laS artifacts-default
- ls -laS artifacts-default/f7-update-${DRONE_TAG}
@ -36,7 +28,6 @@ steps:
commands:
- tar czpf artifacts-default/flipper-z-any-resources-${DRONE_TAG}.tgz -C assets resources
- mkdir sd-card
- mkdir -p sd-card/wav_player
- mkdir -p sd-card/subghz/assets
- mkdir -p sd-card/nfc/assets
- cp assets/resources/subghz/assets/universal_rf_map sd-card/subghz/assets/universal_rf_map

View file

@ -1,10 +1,13 @@
### New Update
* Merged latest ofw changes - scons build system
* Removed WAV Player - it's not bad as a concept but has a lot of problems
* Some small fixes
#### Previous changes
* Spectrum Analyzer - show current mode on screen when changing modes
* Spectrum Analyzer - Ultra Narrow mode
* Desktop autolock more time options
* Merged latest ofw dev changes:
SubGhz: PowerSmart protocol, Infrared app fixes
#### Previous changes
* Merged latest ofw dev changes:
Infrared app C port, nfc: NTAG21x complete emulation, nfc: DESFire fixes
SubGhz: frequency analyzer combined frequency detection method, etc...

View file

@ -67,7 +67,7 @@ then select **`flipper-z-f7-full-(CURRENT VERSION).dfu`**
- And wait, if all flashed successfully - you can manually upload IR libs and other stuff to sd card
- If you doing install for first time or migrating from official fw, unpack 3 folders from archive `sd-card-(CURRENT VERSION).zip` onto your microSD card
- If you doing install for first time or migrating from official fw, unpack 2 folders from archive `sd-card-(CURRENT VERSION).zip` onto your microSD card
<br>
@ -85,13 +85,13 @@ then select **`flipper-z-f7-full-(CURRENT VERSION).dfu`**
### **Replace (CURRENT VERSION) with version that you downloaded from releases**
3. Run `dfu-util -D flipper-z-f7-full-(CURRENT VERSION).dfu -a 0`
4. If you doing install for first time or migrating from official fw, unpack 3 folders from archive `sd-card-(CURRENT VERSION).zip` to your microSD card
4. If you doing install for first time or migrating from official fw, unpack 2 folders from archive `sd-card-(CURRENT VERSION).zip` to your microSD card
<br>
<br>
# After install:
- ### If you installed using .dfu - unpack 3 folders from archive `sd-card-(CURRENT VERSION).zip` to your microSD card
- ### If you installed using .dfu - unpack 2 folders from archive `sd-card-(CURRENT VERSION).zip` to your microSD card
<br>
- ## [How To: Configure UniversalRF Remix App](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/UniRFRemix.md)
@ -128,13 +128,13 @@ $ git clone --recursive https://github.com/Eng1n33r/flipperzero-firmware.git
### Compile everything for development
```sh
docker-compose exec dev make
docker-compose exec dev ./fbt
```
### Compile everything for release + get updater package to update from microSD card
```sh
docker-compose exec dev make updater_package TARGET=f7 DEBUG=0 COMPACT=1
docker-compose exec dev ./fbt --with-updater COMPACT=1 DEBUG=0 updater_package
```
Check `dist/` for build outputs.
@ -145,6 +145,8 @@ If compilation fails, make sure all submodules are all initialized. Either clone
# Build on macOS
Check out `documentation/fbt.md` for details on building and flashing firmware.
## macOS Prerequisites
Make sure you have [brew](https://brew.sh) and install all the dependencies:
@ -152,18 +154,18 @@ Make sure you have [brew](https://brew.sh) and install all the dependencies:
brew bundle --verbose
```
**P.S. Brewfile has been fixed, so build works now**
Install Python packages required by assets build scripts: `pip3 install -r scripts/requirements.txt`
### Compile everything for development
```sh
make
./fbt
```
### Compile everything for release + get updater package to update from microSD card
```sh
make updater_package TARGET=f7 DEBUG=0 COMPACT=1
./fbt --with-updater COMPACT=1 DEBUG=0 updater_package
```
Check `dist/` for build outputs.
@ -174,7 +176,6 @@ Use **`flipper-z-{target}-full-{suffix}.dfu`** to flash your device.
- [Clock/Stopwatch (By CompaqDisc, Stopwatch & Sound Alert By RogueMaster)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/unleashed/applications/clock_app/clock_app.c)
- [UniversalRF Remix (By ESurge)(Original UniversalRF By jimilinuxguy)](https://github.com/ESurge/flipperzero-firmware-unirfremix)
- [WAV Player (By DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) With Fix From [Atmanos](https://github.com/at-manos)
- [Tetris (By jeffplang)](https://github.com/jeffplang/flipperzero-firmware/tree/tetris_game/applications/tetris_game)
- [Spectrum Analyzer (By jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) - [Ultra Narrow mode & scan channels non-consecutively](https://github.com/theY4Kman/flipperzero-firmware/commits?author=theY4Kman)
- [Arkanoid (By gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins)
@ -198,7 +199,7 @@ Use **`flipper-z-{target}-full-{suffix}.dfu`** to flash your device.
- `documentation` - Documentation generation system configs and input files
- `firmware` - Firmware source code
- `lib` - Our and 3rd party libraries, drivers and etc...
- `make` - Make helpers
- `site_scons` - Build helpers
- `scripts` - Supplementary scripts and python libraries home
Also pay attention to `ReadMe.md` files inside of those directories.

View file

@ -0,0 +1,10 @@
App(
appid="arkanoid_game",
name="Arkanoid",
apptype=FlipperAppType.GAME,
entry_point="arkanoid_game_app",
cdefines=["APP_ARKANOID_GAME"],
requires=["gui"],
stack_size=1 * 1024,
order=30,
)

View file

@ -2,7 +2,6 @@
#include <gui/gui.h>
#include <input/input.h>
#include <stdlib.h>
#include <notification/notification_messages.h>
#include <gui/view.h>
#define TAG "Arkanoid"
@ -154,8 +153,8 @@ void move_ball(Canvas* canvas) {
}
//Bounce off Bricks
for(int row = 0; row < ROWS; row++) {
for(int column = 0; column < COLUMNS; column++) {
for(unsigned int row = 0; row < ROWS; row++) {
for(unsigned int column = 0; column < COLUMNS; column++) {
if(!isHit[row][column]) {
//Sets Brick bounds
leftBrick = 10 * column;
@ -244,8 +243,8 @@ void reset_level(Canvas* canvas) {
released = false;
// Reset all brick hit states
for(int row = 0; row < ROWS; row++) {
for(int column = 0; column < COLUMNS; column++) {
for(unsigned int row = 0; row < ROWS; row++) {
for(unsigned int column = 0; column < COLUMNS; column++) {
isHit[row][column] = false;
}
}
@ -277,8 +276,8 @@ static void arkanoid_draw_callback(Canvas* const canvas, void* ctx) {
}
//Draws new bricks and resets their values
for(int row = 0; row < ROWS; row++) {
for(int column = 0; column < COLUMNS; column++) {
for(unsigned int row = 0; row < ROWS; row++) {
for(unsigned int column = 0; column < COLUMNS; column++) {
if(!isHit[row][column]) {
canvas_draw_frame(canvas, 10 * column, 2 + 6 * row, 8, 4);
}
@ -320,6 +319,10 @@ static void arkanoid_update_timer_callback(osMessageQueueId_t event_queue) {
}
int32_t arkanoid_game_app(void* p) {
UNUSED(p);
// Set random seed from interrupts
srand(DWT->CYCCNT);
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(GameEvent), NULL);
ArkanoidState* arkanoid_state = malloc(sizeof(ArkanoidState));
@ -404,7 +407,6 @@ int32_t arkanoid_game_app(void* p) {
furi_record_close("gui");
view_port_free(view_port);
osMessageQueueDelete(event_queue);
furi_record_close("notification");
return 0;
}

View file

@ -0,0 +1,11 @@
App(
appid="clock",
name="Clock",
apptype=FlipperAppType.APP,
entry_point="clock_app",
cdefines=["APP_CLOCK"],
requires=["gui"],
icon="A_Clock_14",
stack_size=2 * 1024,
order=9,
)

View file

@ -35,7 +35,29 @@ App(
apptype=FlipperAppType.METAPACKAGE,
provides=[
"music_player",
"snake_game",
"bt_hid",
],
)
App(
appid="custom_games",
name="Custom applications for games menu",
apptype=FlipperAppType.METAPACKAGE,
provides=[
"snake_game",
"tetris_game",
"arkanoid_game",
"tictactoe_game",
],
)
App(
appid="custom_apps",
name="Custom applications for main menu",
apptype=FlipperAppType.METAPACKAGE,
provides=[
"clock",
"spectrum_analyzer",
"unirfremix",
],
)

View file

@ -1,11 +1,10 @@
App(
appid="snake_game",
name="Snake Game",
apptype=FlipperAppType.PLUGIN,
apptype=FlipperAppType.GAME,
entry_point="snake_game_app",
cdefines=["APP_SNAKE_GAME"],
requires=["gui"],
stack_size=1 * 1024,
icon="A_Plugins_14",
order=30,
order=10,
)

View file

@ -0,0 +1,11 @@
App(
appid="spectrum_analyzer",
name="Spectrum Analyzer",
apptype=FlipperAppType.APP,
entry_point="spectrum_analyzer_app",
cdefines=["APP_SPECTRUM_ANALYZER"],
requires=["gui"],
icon="A_SpectrumAnalyzer_14",
stack_size=1 * 1024,
order=12,
)

View file

@ -17,35 +17,26 @@
static const uint32_t subghz_frequency_list[] = {
/* 300 - 348 */
300000000,
302757000, /* FCC ID N6U303NTX */
303875000,
304250000, /* Ceiling Fan - Harbor Breeze*/
304250000,
310000000,
313850000, /* 2007 Honda Key */
315000000,
318000000,
348000000,
387000000,
/* 387 - 464 */
390000000,
418000000,
433075000, /* LPD433 first */
433220000, /* 2016-2020 Honda */
433420000,
433889000, /* ROGUE? */
433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */
434420000,
434775000, /* LPD433 last channels */
438900000,
464000000,
/* 779 - 928 */
779000000,
868350000,
915000000,
925000000,
928000000,
0,
};

View file

@ -0,0 +1,10 @@
App(
appid="tetris_game",
name="Tetris",
apptype=FlipperAppType.GAME,
entry_point="tetris_game_app",
cdefines=["APP_TETRIS_GAME"],
requires=["gui"],
stack_size=1 * 1024,
order=20,
)

View file

@ -0,0 +1,10 @@
App(
appid="tictactoe_game",
name="Tic Tac Toe",
apptype=FlipperAppType.GAME,
entry_point="tictactoe_game_app",
cdefines=["APP_TICTACTOE_GAME"],
requires=["gui"],
stack_size=1 * 1024,
order=40,
)

View file

@ -2,7 +2,6 @@
#include <gui/gui.h>
#include <input/input.h>
#include <stdlib.h>
#include <notification/notification_messages.h>
#include <gui/view.h>
#define TAG "TicTacToe"
@ -269,6 +268,7 @@ static void tictactoe_update_timer_callback(osMessageQueueId_t event_queue) {
}
int32_t tictactoe_game_app(void* p) {
UNUSED(p);
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(GameEvent), NULL);
TicTacToeState* tictactoe_state = malloc(sizeof(TicTacToeState));
@ -277,6 +277,7 @@ int32_t tictactoe_game_app(void* p) {
if(!init_mutex(&state_mutex, tictactoe_state, sizeof(TicTacToeState))) {
FURI_LOG_E(TAG, "Cannot create mutex\r\n");
free(tictactoe_state);
osMessageQueueDelete(event_queue);
return 255;
}
@ -341,7 +342,6 @@ int32_t tictactoe_game_app(void* p) {
furi_record_close("gui");
view_port_free(view_port);
osMessageQueueDelete(event_queue);
furi_record_close("notification");
delete_mutex(&state_mutex);
free(tictactoe_state);

View file

@ -0,0 +1,11 @@
App(
appid="unirfremix",
name="UniRF Remix",
apptype=FlipperAppType.APP,
entry_point="unirfremix_app",
cdefines=["APP_UNIRFREMIX"],
requires=["gui"],
icon="A_UniRFRemix_14",
stack_size=2 * 1024,
order=11,
)

View file

@ -1,84 +0,0 @@
#include "wav_parser.h"
#define TAG "WavParser"
const char* format_text(FormatTag tag) {
switch(tag) {
case FormatTagPCM:
return "PCM";
case FormatTagIEEE_FLOAT:
return "IEEE FLOAT";
default:
return "Unknown";
}
};
struct WavParser {
WavHeaderChunk header;
WavFormatChunk format;
WavDataChunk data;
size_t wav_data_start;
size_t wav_data_end;
};
WavParser* wav_parser_alloc() {
return malloc(sizeof(WavParser));
}
void wav_parser_free(WavParser* parser) {
free(parser);
}
bool wav_parser_parse(WavParser* parser, Stream* stream) {
stream_read(stream, (uint8_t*)&parser->header, sizeof(WavHeaderChunk));
stream_read(stream, (uint8_t*)&parser->format, sizeof(WavFormatChunk));
stream_read(stream, (uint8_t*)&parser->data, sizeof(WavDataChunk));
if(memcmp(parser->header.riff, "RIFF", 4) != 0 ||
memcmp(parser->header.wave, "WAVE", 4) != 0) {
FURI_LOG_E(TAG, "WAV: wrong header");
return false;
}
if(memcmp(parser->format.fmt, "fmt ", 4) != 0) {
FURI_LOG_E(TAG, "WAV: wrong format");
return false;
}
if(parser->format.tag != FormatTagPCM || memcmp(parser->data.data, "data", 4) != 0) {
FURI_LOG_E(
TAG,
"WAV: non-PCM format %u, next '%lu'",
parser->format.tag,
(uint32_t)parser->data.data);
return false;
}
FURI_LOG_I(
TAG,
"Format tag: %s, ch: %u, smplrate: %lu, bps: %lu, bits: %u",
format_text(parser->format.tag),
parser->format.channels,
parser->format.sample_rate,
parser->format.byte_per_sec,
parser->format.bits_per_sample);
parser->wav_data_start = stream_tell(stream);
parser->wav_data_end = parser->wav_data_start + parser->data.size;
FURI_LOG_I(TAG, "data: %u - %u", parser->wav_data_start, parser->wav_data_end);
return true;
}
size_t wav_parser_get_data_start(WavParser* parser) {
return parser->wav_data_start;
}
size_t wav_parser_get_data_end(WavParser* parser) {
return parser->wav_data_end;
}
size_t wav_parser_get_data_len(WavParser* parser) {
return parser->wav_data_end - parser->wav_data_start;
}

View file

@ -1,51 +0,0 @@
#pragma once
#include <toolbox/stream/stream.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
FormatTagPCM = 0x0001,
FormatTagIEEE_FLOAT = 0x0003,
} FormatTag;
typedef struct {
uint8_t riff[4];
uint32_t size;
uint8_t wave[4];
} WavHeaderChunk;
typedef struct {
uint8_t fmt[4];
uint32_t size;
uint16_t tag;
uint16_t channels;
uint32_t sample_rate;
uint32_t byte_per_sec;
uint16_t block_align;
uint16_t bits_per_sample;
} WavFormatChunk;
typedef struct {
uint8_t data[4];
uint32_t size;
} WavDataChunk;
typedef struct WavParser WavParser;
WavParser* wav_parser_alloc();
void wav_parser_free(WavParser* parser);
bool wav_parser_parse(WavParser* parser, Stream* stream);
size_t wav_parser_get_data_start(WavParser* parser);
size_t wav_parser_get_data_end(WavParser* parser);
size_t wav_parser_get_data_len(WavParser* parser);
#ifdef __cplusplus
}
#endif

View file

@ -1,297 +0,0 @@
#include <furi.h>
#include <furi_hal.h>
#include <cli/cli.h>
#include <gui/gui.h>
#include <stm32wbxx_ll_dma.h>
#include <dialogs/dialogs.h>
#include <notification/notification_messages.h>
#include <gui/view_dispatcher.h>
#include <toolbox/stream/file_stream.h>
#include "wav_player_hal.h"
#include "wav_parser.h"
#include "wav_player_view.h"
#define TAG "WavPlayer"
static bool open_wav_stream(Storage* storage, Stream* stream) {
DialogsApp* dialogs = furi_record_open("dialogs");
bool result = false;
string_t path;
string_init(path);
string_set_str(path, "/ext/wav_player");
bool ret = dialog_file_browser_show(dialogs, path, path, ".wav", true, &I_music_10px, false);
furi_record_close("dialogs");
if(ret) {
if(!file_stream_open(stream, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
FURI_LOG_E(TAG, "Cannot open file \"%s\"", string_get_cstr(path));
} else {
result = true;
}
}
string_clear(path);
return result;
}
typedef enum {
WavPlayerEventHalfTransfer,
WavPlayerEventFullTransfer,
WavPlayerEventCtrlVolUp,
WavPlayerEventCtrlVolDn,
WavPlayerEventCtrlMoveL,
WavPlayerEventCtrlMoveR,
WavPlayerEventCtrlOk,
WavPlayerEventCtrlBack,
} WavPlayerEventType;
typedef struct {
WavPlayerEventType type;
} WavPlayerEvent;
static void wav_player_dma_isr(void* ctx) {
osMessageQueueId_t event_queue = ctx;
// half of transfer
if(LL_DMA_IsActiveFlag_HT1(DMA1)) {
LL_DMA_ClearFlag_HT1(DMA1);
// fill first half of buffer
WavPlayerEvent event = {.type = WavPlayerEventHalfTransfer};
osMessageQueuePut(event_queue, &event, 0, 0);
}
// transfer complete
if(LL_DMA_IsActiveFlag_TC1(DMA1)) {
LL_DMA_ClearFlag_TC1(DMA1);
// fill second half of buffer
WavPlayerEvent event = {.type = WavPlayerEventFullTransfer};
osMessageQueuePut(event_queue, &event, 0, 0);
}
}
typedef struct {
Storage* storage;
Stream* stream;
WavParser* parser;
uint16_t* sample_buffer;
uint8_t* tmp_buffer;
size_t samples_count_half;
size_t samples_count;
osMessageQueueId_t queue;
float volume;
bool play;
WavPlayerView* view;
ViewDispatcher* view_dispatcher;
Gui* gui;
NotificationApp* notification;
} WavPlayerApp;
static WavPlayerApp* app_alloc() {
WavPlayerApp* app = malloc(sizeof(WavPlayerApp));
app->samples_count_half = 1024 * 4;
app->samples_count = app->samples_count_half * 2;
app->storage = furi_record_open("storage");
app->stream = file_stream_alloc(app->storage);
app->parser = wav_parser_alloc();
app->sample_buffer = malloc(sizeof(uint16_t) * app->samples_count);
app->tmp_buffer = malloc(sizeof(uint8_t) * app->samples_count);
app->queue = osMessageQueueNew(10, sizeof(WavPlayerEvent), NULL);
app->volume = 10.0f;
app->play = true;
app->gui = furi_record_open("gui");
app->view_dispatcher = view_dispatcher_alloc();
app->view = wav_player_view_alloc();
view_dispatcher_add_view(app->view_dispatcher, 0, wav_player_view_get_view(app->view));
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
view_dispatcher_switch_to_view(app->view_dispatcher, 0);
app->notification = furi_record_open("notification");
notification_message(app->notification, &sequence_display_backlight_enforce_on);
return app;
}
static void app_free(WavPlayerApp* app) {
view_dispatcher_remove_view(app->view_dispatcher, 0);
view_dispatcher_free(app->view_dispatcher);
wav_player_view_free(app->view);
furi_record_close("gui");
osMessageQueueDelete(app->queue);
free(app->tmp_buffer);
free(app->sample_buffer);
wav_parser_free(app->parser);
stream_free(app->stream);
furi_record_close("storage");
notification_message(app->notification, &sequence_display_backlight_enforce_auto);
furi_record_close("notification");
free(app);
}
// TODO: that works only with 8-bit 2ch audio
static bool fill_data(WavPlayerApp* app, size_t index) {
uint16_t* sample_buffer_start = &app->sample_buffer[index];
size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count);
for(size_t i = count; i < app->samples_count; i++) {
app->tmp_buffer[i] = 0;
}
for(size_t i = 0; i < app->samples_count; i += 2) {
float data = app->tmp_buffer[i];
data -= UINT8_MAX / 2; // to signed
data /= UINT8_MAX / 2; // scale -1..1
data *= app->volume; // volume
data = tanhf(data); // hyperbolic tangent limiter
data *= UINT8_MAX / 2; // scale -128..127
data += UINT8_MAX / 2; // to unsigned
if(data < 0) {
data = 0;
}
if(data > 255) {
data = 255;
}
sample_buffer_start[i / 2] = data;
}
wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half);
return count != app->samples_count;
}
static void ctrl_callback(WavPlayerCtrl ctrl, void* ctx) {
osMessageQueueId_t event_queue = ctx;
WavPlayerEvent event;
switch(ctrl) {
case WavPlayerCtrlVolUp:
event.type = WavPlayerEventCtrlVolUp;
osMessageQueuePut(event_queue, &event, 0, 0);
break;
case WavPlayerCtrlVolDn:
event.type = WavPlayerEventCtrlVolDn;
osMessageQueuePut(event_queue, &event, 0, 0);
break;
case WavPlayerCtrlMoveL:
event.type = WavPlayerEventCtrlMoveL;
osMessageQueuePut(event_queue, &event, 0, 0);
break;
case WavPlayerCtrlMoveR:
event.type = WavPlayerEventCtrlMoveR;
osMessageQueuePut(event_queue, &event, 0, 0);
break;
case WavPlayerCtrlOk:
event.type = WavPlayerEventCtrlOk;
osMessageQueuePut(event_queue, &event, 0, 0);
break;
case WavPlayerCtrlBack:
event.type = WavPlayerEventCtrlBack;
osMessageQueuePut(event_queue, &event, 0, 0);
break;
default:
break;
}
}
static void app_run(WavPlayerApp* app) {
if(!open_wav_stream(app->storage, app->stream)) return;
if(!wav_parser_parse(app->parser, app->stream)) return;
wav_player_view_set_volume(app->view, app->volume);
wav_player_view_set_start(app->view, wav_parser_get_data_start(app->parser));
wav_player_view_set_current(app->view, stream_tell(app->stream));
wav_player_view_set_end(app->view, wav_parser_get_data_end(app->parser));
wav_player_view_set_play(app->view, app->play);
wav_player_view_set_context(app->view, app->queue);
wav_player_view_set_ctrl_callback(app->view, ctrl_callback);
bool eof = fill_data(app, 0);
eof = fill_data(app, app->samples_count_half);
wav_player_speaker_init();
wav_player_dma_init((uint32_t)app->sample_buffer, app->samples_count);
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, wav_player_dma_isr, app->queue);
wav_player_dma_start();
wav_player_speaker_start();
WavPlayerEvent event;
while(1) {
if(osMessageQueueGet(app->queue, &event, NULL, osWaitForever) == osOK) {
if(event.type == WavPlayerEventHalfTransfer) {
eof = fill_data(app, 0);
wav_player_view_set_current(app->view, stream_tell(app->stream));
if(eof) {
stream_seek(
app->stream,
wav_parser_get_data_start(app->parser),
StreamOffsetFromStart);
}
} else if(event.type == WavPlayerEventFullTransfer) {
eof = fill_data(app, app->samples_count_half);
wav_player_view_set_current(app->view, stream_tell(app->stream));
if(eof) {
stream_seek(
app->stream,
wav_parser_get_data_start(app->parser),
StreamOffsetFromStart);
}
} else if(event.type == WavPlayerEventCtrlVolUp) {
if(app->volume < 9.9) app->volume += 0.2;
wav_player_view_set_volume(app->view, app->volume);
} else if(event.type == WavPlayerEventCtrlVolDn) {
if(app->volume > 0.01) app->volume -= 0.2;
wav_player_view_set_volume(app->view, app->volume);
} else if(event.type == WavPlayerEventCtrlMoveL) {
int32_t seek = stream_tell(app->stream) - wav_parser_get_data_start(app->parser);
seek = MIN(seek, wav_parser_get_data_len(app->parser) / 100);
stream_seek(app->stream, -seek, StreamOffsetFromCurrent);
wav_player_view_set_current(app->view, stream_tell(app->stream));
} else if(event.type == WavPlayerEventCtrlMoveR) {
int32_t seek = wav_parser_get_data_end(app->parser) - stream_tell(app->stream);
seek = MIN(seek, wav_parser_get_data_len(app->parser) / 100);
stream_seek(app->stream, seek, StreamOffsetFromCurrent);
wav_player_view_set_current(app->view, stream_tell(app->stream));
} else if(event.type == WavPlayerEventCtrlOk) {
app->play = !app->play;
wav_player_view_set_play(app->view, app->play);
if(!app->play) {
wav_player_speaker_stop();
} else {
wav_player_speaker_start();
}
} else if(event.type == WavPlayerEventCtrlBack) {
break;
}
}
}
wav_player_speaker_stop();
wav_player_dma_stop();
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL);
}
int32_t wav_player_app(void* p) {
WavPlayerApp* app = app_alloc();
app_run(app);
app_free(app);
return 0;
}

View file

@ -1,58 +0,0 @@
#include "wav_player_hal.h"
#include <stm32wbxx_ll_tim.h>
#include <stm32wbxx_ll_dma.h>
#define FURI_HAL_SPEAKER_TIMER TIM16
#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1
#define DMA_INSTANCE DMA1, LL_DMA_CHANNEL_1
void wav_player_speaker_init() {
LL_TIM_InitTypeDef TIM_InitStruct = {0};
TIM_InitStruct.Prescaler = 4;
TIM_InitStruct.Autoreload = 255;
LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct);
LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
TIM_OC_InitStruct.CompareValue = 127;
LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct);
}
void wav_player_speaker_start() {
LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER);
LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER);
}
void wav_player_speaker_stop() {
LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER);
LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER);
}
void wav_player_dma_init(uint32_t address, size_t size) {
uint32_t dma_dst = (uint32_t) & (FURI_HAL_SPEAKER_TIMER->CCR1);
LL_DMA_ConfigAddresses(DMA_INSTANCE, address, dma_dst, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetDataLength(DMA_INSTANCE, size);
LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM16_UP);
LL_DMA_SetDataTransferDirection(DMA_INSTANCE, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetChannelPriorityLevel(DMA_INSTANCE, LL_DMA_PRIORITY_VERYHIGH);
LL_DMA_SetMode(DMA_INSTANCE, LL_DMA_MODE_CIRCULAR);
LL_DMA_SetPeriphIncMode(DMA_INSTANCE, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA_INSTANCE, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA_INSTANCE, LL_DMA_PDATAALIGN_HALFWORD);
LL_DMA_SetMemorySize(DMA_INSTANCE, LL_DMA_MDATAALIGN_HALFWORD);
LL_DMA_EnableIT_TC(DMA_INSTANCE);
LL_DMA_EnableIT_HT(DMA_INSTANCE);
}
void wav_player_dma_start() {
LL_DMA_EnableChannel(DMA_INSTANCE);
LL_TIM_EnableDMAReq_UPDATE(FURI_HAL_SPEAKER_TIMER);
}
void wav_player_dma_stop() {
LL_DMA_DisableChannel(DMA_INSTANCE);
}

View file

@ -1,23 +0,0 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void wav_player_speaker_init();
void wav_player_speaker_start();
void wav_player_speaker_stop();
void wav_player_dma_init(uint32_t address, size_t size);
void wav_player_dma_start();
void wav_player_dma_stop();
#ifdef __cplusplus
}
#endif

View file

@ -1,214 +0,0 @@
#include "wav_player_view.h"
#define DATA_COUNT 116
struct WavPlayerView {
View* view;
WavPlayerCtrlCallback callback;
void* context;
};
typedef struct {
bool play;
float volume;
size_t start;
size_t end;
size_t current;
uint8_t data[DATA_COUNT];
} WavPlayerViewModel;
float map(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
}
static void wav_player_view_draw_callback(Canvas* canvas, void* _model) {
WavPlayerViewModel* model = _model;
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
uint8_t x_pos = 0;
uint8_t y_pos = 0;
// volume
x_pos = 124;
y_pos = 0;
const float volume = (64 / 10.0f) * model->volume;
canvas_draw_frame(canvas, x_pos, y_pos, 4, 64);
canvas_draw_box(canvas, x_pos, y_pos + (64 - volume), 4, volume);
// play / pause
x_pos = 58;
y_pos = 55;
if(model->play) {
canvas_draw_line(canvas, x_pos, y_pos, x_pos + 8, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 8, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos);
} else {
canvas_draw_box(canvas, x_pos, y_pos, 3, 9);
canvas_draw_box(canvas, x_pos + 4, y_pos, 3, 9);
}
x_pos = 78;
y_pos = 55;
canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos);
x_pos = 82;
y_pos = 55;
canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos);
x_pos = 40;
y_pos = 55;
canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos);
x_pos = 44;
y_pos = 55;
canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4);
canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos);
// len
x_pos = 4;
y_pos = 47;
const uint8_t play_len = 116;
uint8_t play_pos = map(model->current, model->start, model->end, 0, play_len - 4);
canvas_draw_frame(canvas, x_pos, y_pos, play_len, 4);
canvas_draw_box(canvas, x_pos + play_pos, y_pos - 2, 4, 8);
canvas_draw_box(canvas, x_pos, y_pos, play_pos, 4);
// osc
x_pos = 4;
y_pos = 0;
for(size_t i = 1; i < DATA_COUNT; i++) {
canvas_draw_line(canvas, x_pos + i - 1, model->data[i - 1], x_pos + i, model->data[i]);
}
}
static bool wav_player_view_input_callback(InputEvent* event, void* context) {
WavPlayerView* wav_player_view = context;
bool consumed = false;
if(wav_player_view->callback) {
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
if(event->key == InputKeyUp) {
wav_player_view->callback(WavPlayerCtrlVolUp, wav_player_view->context);
consumed = true;
} else if(event->key == InputKeyDown) {
wav_player_view->callback(WavPlayerCtrlVolDn, wav_player_view->context);
consumed = true;
} else if(event->key == InputKeyLeft) {
wav_player_view->callback(WavPlayerCtrlMoveL, wav_player_view->context);
consumed = true;
} else if(event->key == InputKeyRight) {
wav_player_view->callback(WavPlayerCtrlMoveR, wav_player_view->context);
consumed = true;
} else if(event->key == InputKeyOk) {
wav_player_view->callback(WavPlayerCtrlOk, wav_player_view->context);
consumed = true;
} else if(event->key == InputKeyBack) {
wav_player_view->callback(WavPlayerCtrlBack, wav_player_view->context);
consumed = true;
}
}
}
return consumed;
}
WavPlayerView* wav_player_view_alloc() {
WavPlayerView* wav_view = malloc(sizeof(WavPlayerView));
wav_view->view = view_alloc();
view_set_context(wav_view->view, wav_view);
view_allocate_model(wav_view->view, ViewModelTypeLocking, sizeof(WavPlayerViewModel));
view_set_draw_callback(wav_view->view, wav_player_view_draw_callback);
view_set_input_callback(wav_view->view, wav_player_view_input_callback);
return wav_view;
}
void wav_player_view_free(WavPlayerView* wav_view) {
furi_assert(wav_view);
view_free(wav_view->view);
free(wav_view);
}
View* wav_player_view_get_view(WavPlayerView* wav_view) {
furi_assert(wav_view);
return wav_view->view;
}
void wav_player_view_set_volume(WavPlayerView* wav_view, float volume) {
furi_assert(wav_view);
with_view_model(
wav_view->view, (WavPlayerViewModel * model) {
model->volume = volume;
return true;
});
}
void wav_player_view_set_start(WavPlayerView* wav_view, size_t start) {
furi_assert(wav_view);
with_view_model(
wav_view->view, (WavPlayerViewModel * model) {
model->start = start;
return true;
});
}
void wav_player_view_set_end(WavPlayerView* wav_view, size_t end) {
furi_assert(wav_view);
with_view_model(
wav_view->view, (WavPlayerViewModel * model) {
model->end = end;
return true;
});
}
void wav_player_view_set_current(WavPlayerView* wav_view, size_t current) {
furi_assert(wav_view);
with_view_model(
wav_view->view, (WavPlayerViewModel * model) {
model->current = current;
return true;
});
}
void wav_player_view_set_play(WavPlayerView* wav_view, bool play) {
furi_assert(wav_view);
with_view_model(
wav_view->view, (WavPlayerViewModel * model) {
model->play = play;
return true;
});
}
void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count) {
furi_assert(wav_view);
with_view_model(
wav_view->view, (WavPlayerViewModel * model) {
size_t inc = (data_count / DATA_COUNT) - 1;
for(size_t i = 0; i < DATA_COUNT; i++) {
model->data[i] = *data / 6;
if(model->data[i] > 42) model->data[i] = 42;
data += inc;
}
return true;
});
}
void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback) {
furi_assert(wav_view);
wav_view->callback = callback;
}
void wav_player_view_set_context(WavPlayerView* wav_view, void* context) {
furi_assert(wav_view);
wav_view->context = context;
}

View file

@ -1,45 +0,0 @@
#pragma once
#include <gui/view.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct WavPlayerView WavPlayerView;
typedef enum {
WavPlayerCtrlVolUp,
WavPlayerCtrlVolDn,
WavPlayerCtrlMoveL,
WavPlayerCtrlMoveR,
WavPlayerCtrlOk,
WavPlayerCtrlBack,
} WavPlayerCtrl;
typedef void (*WavPlayerCtrlCallback)(WavPlayerCtrl ctrl, void* context);
WavPlayerView* wav_player_view_alloc();
void wav_player_view_free(WavPlayerView* wav_view);
View* wav_player_view_get_view(WavPlayerView* wav_view);
void wav_player_view_set_volume(WavPlayerView* wav_view, float volume);
void wav_player_view_set_start(WavPlayerView* wav_view, size_t start);
void wav_player_view_set_end(WavPlayerView* wav_view, size_t end);
void wav_player_view_set_current(WavPlayerView* wav_view, size_t current);
void wav_player_view_set_play(WavPlayerView* wav_view, bool play);
void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count);
void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback);
void wav_player_view_set_context(WavPlayerView* wav_view, void* context);
#ifdef __cplusplus
}
#endif

View file

@ -1,53 +1,29 @@
Filetype: Flipper SubGhz Setting File
Version: 1
# Add Standard frequencies for your region
# Add All Standard frequencies
#add_standard_frequencies: true
# Default Frequency: used as default for "Read" and "Read Raw"
#default_frequency: 433920000
# Frequencies used for "Read", "Read Raw" and "Frequency Analyzer"
frequency: 300000000
# Frequencies used for "Read", "Read Raw" and "Frequency Analyzer" + default ones if enabled in add_standard_frequencies
frequency: 302757000
frequency: 303875000
frequency: 304250000
frequency: 310000000
frequency: 312000000
frequency: 312100000
frequency: 313850000
frequency: 314000000
frequency: 314350000
frequency: 315000000
frequency: 318000000
frequency: 345000000
frequency: 348000000
frequency: 387000000
frequency: 390000000
frequency: 418000000
frequency: 433075000
frequency: 433220000
frequency: 433420000
frequency: 433889000
frequency: 433920000
frequency: 434420000
frequency: 434775000
frequency: 438900000
frequency: 464000000
frequency: 779000000
frequency: 868350000
frequency: 915000000
frequency: 925000000
frequency: 928000000
# Frequencies used for hopping mode (keep this list small or flipper will miss signal)
hopper_frequency: 300000000
# Frequencies used for hopping mode (keep this list small or flipper will miss signal) + default ones if enabled in add_standard_frequencies
#hopper_frequency: 300000000
hopper_frequency: 345000000
#hopper_frequency: 310000000
#hopper_frequency: 312000000
#hopper_frequency: 314000000
#hopper_frequency: 315000000
#hopper_frequency: 318000000
#hopper_frequency: 390000000
#hopper_frequency: 433920000
#hopper_frequency: 868350000
hopper_frequency: 434420000

View file

@ -54,12 +54,16 @@ FIRMWARE_APPS = {
"basic_apps",
"updater_app",
"archive",
# Custom Apps
"custom_apps",
# Settings
"passport",
"system_settings",
"about",
# Plugins
"basic_plugins",
# Custom Games
"custom_games",
# Debug
"debug_apps",
),

View file

@ -277,6 +277,7 @@ LevelDuration subghz_protocol_encoder_came_atomo_yield(void* context) {
}
void* subghz_protocol_decoder_came_atomo_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
SubGhzProtocolDecoderCameAtomo* instance = malloc(sizeof(SubGhzProtocolDecoderCameAtomo));
instance->base.protocol = &subghz_protocol_came_atomo;
instance->generic.protocol_name = instance->base.protocol->name;

View file

@ -3,20 +3,41 @@
#include <stdlib.h>
#include <stdbool.h>
#include <furi.h>
#include <furi_hal.h>
void set_random_name(char* name, uint8_t max_name_size) {
FuriHalRtcDateTime datetime;
furi_hal_rtc_get_datetime(&datetime);
char strings[1][25];
sprintf(
strings[0],
"%s%.4d%.2d%.2d%.2d%.2d",
"s",
datetime.year,
datetime.month,
datetime.day,
datetime.hour,
datetime.minute);
sniprintf(name, max_name_size, "%s", strings[0]);
}
static bool rand_generator_inited = false;
if(!rand_generator_inited) {
srand(DWT->CYCCNT);
rand_generator_inited = true;
}
const char* prefix[] = {
"super",
"big",
"little",
"liquid",
"unknown",
"thin",
"thick",
"great",
"my",
};
const char* suffix[] = {
"maslina",
"sus",
"anomalija",
"artefact",
"monolit",
"burer",
"sidorovich",
"habar",
};
// sus is not (sus)pect - this is about super sus
uint8_t prefix_i = rand() % COUNT_OF(prefix);
uint8_t suffix_i = rand() % COUNT_OF(suffix);
sniprintf(name, max_name_size, "%s_%s", prefix[prefix_i], suffix[suffix_i]);
// Set first symbol to upper case
name[0] = name[0] - 0x20;
}

View file

@ -14,4 +14,4 @@ void set_random_name(char* name, uint8_t max_name_size);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -32,10 +32,10 @@ class GitVersion:
branch_num = self._exec_git("rev-list --count HEAD") or "n/a"
try:
version = self._exec_git("describe --tags --abbrev=0 --exact-match")
except subprocess.CalledProcessError:
version = "unknown"
version = (
os.environ.get("DIST_SUFFIX", None)
or "unknown"
)
return {
"GIT_COMMIT": commit,

View file

@ -19,6 +19,7 @@ class FlipperAppType(Enum):
STARTUP = "StartupHook"
EXTERNAL = "External"
METAPACKAGE = "Package"
GAME = "Game"
@dataclass
@ -98,6 +99,7 @@ class AppBuildset:
FlipperAppType.ARCHIVE,
FlipperAppType.SETTINGS,
FlipperAppType.STARTUP,
FlipperAppType.GAME,
)
def __init__(self, appmgr: AppManager, appnames: List[str]):
@ -190,6 +192,7 @@ class ApplicationsCGenerator:
FlipperAppType.SYSTEM: ("FlipperApplication", "FLIPPER_SYSTEM_APPS"),
FlipperAppType.APP: ("FlipperApplication", "FLIPPER_APPS"),
FlipperAppType.PLUGIN: ("FlipperApplication", "FLIPPER_PLUGINS"),
FlipperAppType.GAME: ("FlipperApplication", "FLIPPER_GAMES"),
FlipperAppType.DEBUG: ("FlipperApplication", "FLIPPER_DEBUG_APPS"),
FlipperAppType.SETTINGS: ("FlipperApplication", "FLIPPER_SETTINGS_APPS"),
FlipperAppType.STARTUP: ("FlipperOnStartHook", "FLIPPER_ON_SYSTEM_START"),