This commit is contained in:
Derek Jamison 2023-10-11 16:30:05 -05:00
commit 367a8ff09e
6 changed files with 159 additions and 8 deletions

View File

@ -0,0 +1,13 @@
# WIP thread demo
The Flipper Zero supports the concepts of threads. The idea is that while your main application is running some code, another thread can be running different code in the same application process, at the same time. The reality is likely that the processor will end up switching back and forth between the various threads. Threads can get paused momentarily, while processing instructions from another thread. A thread can set its priority by calling `furi_thread_set_current_priority(FuriThreadPriorityHigh)`, passing the new priority of the thread. Warning -- shanging the priority could cause other threads to not get time to execute.
In this demonstration, we use a thread to blink pin A7 on/off quickly, effectively creating a PWM signal and varying the brightness of an LED connected to pin A7. Our main thread sets information, such as the frequency and duty cycle (percentage of time to have the pin on.)
A thread is allocated using a command like `FuriThread* thread = furi_thread_alloc_ex("MyThread", 2048, my_thread_callback, context);`. The first parameter is the friendly name for the thread. The second parameter is the stack size. The third parameter is the method that the thread should run, with a signature like `int32_t my_thread_callback(void* context)`. The fourth parameter is the context to pass to the method.
After you have allocated the thread, you can call `furi_thread_flags_set` passing the `furi_thread_get_id` of the Thread and the bits you want to set. When the main application is done, it should signal to the thread that it should terminate, and then the main application should do a `furi_thread_join` to wait for the thread to complete.
In the thread callback, it can get the flags, clear the flags, and wait on flags. Typically you want your thread to check periodically to see if it should be exiting (for example, because the main application is exiting.)
NOTE: This current demo has a flicker when the PWM is a low percentage, because while the code in the thread checking to see if it should exit is running, the LED is not blinking. This is just a demo app of how to use a Thread. If you really want to do PWM, you should look into the `furi_hal_pwm_start` API, or the underlying LL*TIM* functions in `lib\stm32wb_hal\Inc\stm32wbxx_ll_tim.h`.

View File

@ -0,0 +1,10 @@
App(
appid="wip_thread_demo",
name="WIP Thread Demo",
apptype=FlipperAppType.EXTERNAL,
entry_point="thread_demo_app",
requires=["gui", "subghz"],
stack_size=2 * 1024,
fap_icon="demo.png",
fap_category="Misc",
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,101 @@
#include <furi.h>
#include <furi_hal.h>
#define TAG "WIP_Thread_Demo"
const GpioPin* pin = &gpio_ext_pa7;
typedef struct {
uint8_t duty_cycle;
uint32_t freq;
} MyThreadContext;
typedef enum {
MyThreadFlagUpdated = 1 << 0,
MyThreadFlagFoo = 1 << 1,
MyThreadFlagExiting = 1 << 2,
MyThreadFlagAll = (1 << 3) - 1,
} MyThreadFlags;
int32_t my_thread_callback(void* context) {
MyThreadContext* mtc = (MyThreadContext*)context;
furi_thread_flags_clear(MyThreadFlagAll);
uint32_t cycle = 1000000 / mtc->freq;
uint32_t cycle_on = cycle * mtc->duty_cycle / 100;
uint32_t cycle_off = cycle - cycle_on;
uint32_t num_cycles = mtc->freq;
MyThreadFlags flags;
while(((flags = furi_thread_flags_get()) & MyThreadFlagExiting) != MyThreadFlagExiting) {
// Do some work (for ~1 second) then check to see if thead should exit...
// NOTE: This causes some "flicker" because the LED is not changing states
// while we do the above and below checks.
if(flags & MyThreadFlagUpdated) {
cycle = 1000000 / mtc->freq;
cycle_on = cycle * mtc->duty_cycle / 100;
cycle_off = cycle - cycle_on;
num_cycles = mtc->freq;
furi_thread_flags_clear(MyThreadFlagUpdated);
}
for(uint32_t i = 0; i < num_cycles * 3; i++) {
// Turn on
furi_hal_gpio_write(pin, true);
furi_delay_us(cycle_on);
// Turn off
furi_hal_gpio_write(pin, false);
furi_delay_us(cycle_off);
}
};
FURI_LOG_D(TAG, "Exiting the thread");
return 0;
}
int thread_demo_app(char* p) {
UNUSED(p);
furi_hal_gpio_init_simple(pin, GpioModeOutputPushPull);
MyThreadContext* context = (MyThreadContext*)malloc(sizeof(MyThreadContext));
context->duty_cycle = 100;
context->freq = 30000;
FuriThread* thread = furi_thread_alloc_ex("MyThread", 2048, my_thread_callback, context);
furi_thread_start(thread);
// This would normally do some work. We sleep here just as a demo..
FURI_LOG_D(TAG, "Running the main program");
furi_delay_ms(3000);
context->duty_cycle = 50;
furi_thread_flags_set(furi_thread_get_id(thread), MyThreadFlagUpdated);
FURI_LOG_D(TAG, "Set duty cycle to %d.", context->duty_cycle);
furi_delay_ms(3000);
context->duty_cycle = 10;
furi_thread_flags_set(furi_thread_get_id(thread), MyThreadFlagUpdated);
FURI_LOG_D(TAG, "Set duty cycle to %d.", context->duty_cycle);
furi_delay_ms(3000);
context->duty_cycle = 2;
furi_thread_flags_set(furi_thread_get_id(thread), MyThreadFlagUpdated);
FURI_LOG_D(TAG, "Set duty cycle to %d.", context->duty_cycle);
furi_delay_ms(3000);
FURI_LOG_D(TAG, "Exiting the main program");
// Our app is done. Release any resources...
// Tell the thread we are exiting.
furi_thread_flags_set(furi_thread_get_id(thread), MyThreadFlagExiting);
// Wait for thread to exit.
furi_thread_join(thread);
furi_hal_gpio_init_simple(pin, GpioModeAnalog);
return 0;
}

View File

@ -22,9 +22,9 @@ WARNING -- Don't run this near your garage. There is no reason to open the phys
## Running
- Step 1. Copy [these files](https://github.com/jamisonderek/flipper-zero-tutorials/tree/main/subghz/apps/genie-recorder) into your firmware ``applications_user\genie-recorder`` folder.
- Step 2. Build your firmware.
- Step 2. Build your firmware (``./fbt vscode_dist`` & ``./fbt`` -- "[Debug] Build Firmware"). You may get a build error.
- Step 3. Edit ``lib\subghz\protocols\keeloq.c`` so it have te_short=200, te_long=400, te_delta=70. NOTE: This will no longer be able to receive signals from other KeeLoq devices.
- Step 4. Build your firmware & deploy onto Flipper.
- Step 4. Build your firmware & deploy onto Flipper ``./fbt FORCE=1 flash_usb_full`` -- "[Debug]Flash (USB, with Resources)".
- Step 5. On your Flipper Zero, load ``Sub-GHz`` app.
- Step 6. Choose ``Read`` to start scanning.
- Step 7. Press the LEFT button to edit the Config.

View File

@ -106,6 +106,7 @@ void subghz_protocol_decoder_keeloq_get_string(void* context, FuriString* output
// Continue with the original code.
```
### HCS300
Two common hardware implementations of KeeLoq are the HCS300, which uses 10 bits in discriminator & the HCS200, which uses 8 bits. The Flipper Zero software implementation decodes using 8 bits. If you make a custom change to the ``.\lib\subghz\protocols\keeloq.c`` file you can return the encoded data, which will be used by the Rolling Flaws application. For "SN00/cfw*" set to "No" to work properly, you will need these changes. For "SN bits/cfw*" set to "10 (dec)", you will also need this changes. These changes allow the application to see the encrypted data, which is needed for the "SN00/cfw*" and "SN bits/cfw*" features to work properly.
Step 1. Change the two occurances of ``decrypt & 0x0000FFFF`` to read ``decrypt``.
@ -150,19 +151,45 @@ Method 2: (command-line + allows for "SN00/cfw*" and "SN bits/cfw*" features + a
- Clone the firmware repository (make sure you use ``git clone --recursive``).
- Copy the ``rolling_flaws`` folder into your firmware's ``applications_user`` folder.
- Build the firmware using ``fbt updater_package``.
- Do the steps in the previous [HCS300](#hcs300) section and then reflash the device.
- ``fbt update_package``
- In qFlipper choose "Install from file" and choose the .tgz file from the ``dist\f7-C`` folder.
Method 3: (VS Code + allows for "SN00/cfw*" and "SN bits/cfw*" features + allows for replay feature)
- Install VS Code
- Clone the firmware repository (make sure you use ``git clone --recursive``).
- Install [VS Code](https://code.visualstudio.com/Download)
- Clone the firmware repository (make sure you use **Git: Clone (Recursive)**).
- The URL for firmware is at https://github.com/flipperdevices/flipperzero-firmware
- Make sure you have run ``fbt vscode_dist`` at least once, so VSCode works properly.
- You can right click on "FBT" and then choose `Open in Integrated Terminal`.
- Then type: `./fbt vscode_dist`
- It should populate your `.vscode` folder.
- Copy the ``rolling_flaws`` folder into your firmware's ``applications_user`` folder.
- Ctrl+Shift+B
- Select "[Debug] Flash (USB, with resources)"
- Ctrl+Shift+B
- Select "[Debug] Launch App on Flipper"
- Do the steps in the previous [HCS300](#hcs300) section (so the "Enc:" data is present) and then reflash the device
- Select "[Debug] Flash (USB, with resources)"
- Select "[Debug] Launch App on Flipper"
Here is a command-line method. Before the last two commands, you should follow the steps in [HCS300](#hcs300) section (so the "Enc:" data is present). Be sure your Flipper Zero is connected and that qFlipper is not running:
```c
mkdir \repos
cd \repos
git clone https://github.com/jamisonderek/flipper-zero-tutorials.git
git clone --recursive https://github.com/flipperdevices/flipperzero-firmware
cd flipperzero-firmware
fbt vscode_dist
cd applications_user
md rolling-flaws
cd rolling-flaws
xcopy ..\..\..\flipper-zero-tutorials\subghz\apps\rolling-flaws\*.* . /e
cd ..
cd ..
fbt FORCE=1 flash_usb_full
fbt launch APPSRC=applications_user\rolling-flaws
```
Method 4: (command-line)
- Install [ufbt](https://github.com/flipperdevices/flipperzero-ufbt)
- Switch into the ``rolling_flaws`` folder.
- Install and launch the app using ``ufbt launch``.
## Menu Options
### Config