Repository navigation
Conversation
The old driver bit-banged every frame with interrupts masked for up to ~74 ms (96-byte frame). TIM1 now counts carrier periods, its repetition counter raises one update per segment, and DMA2 ch1/ch2 feed CCMR2 and RCR on each update. The TX thread sleeps until DMA transfer-complete. - ir/tagtinker_ir_seq.[ch]: pure-C DMA table builder (host testable) - ir/tagtinker_ir.c: TIM1 + DMA driver, same public API - tests/test_ir_seq.c, make test, CI job with ASan/UBSan - README/CONTRIBUTING: document make test - build_and_flash.bat: Windows helper (ufbt update, build, launch) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYkmJ3RnCgGZEBKnfRJt5x
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYkmJ3RnCgGZEBKnfRJt5x
Settings gain "IR Output" (Internal / GPIO A7 / Auto) and "5V on GPIO", mirroring the stock Infrared app. The DMA driver drives TIM1 CH1N on PA7 (CCMR1) instead of CH3N on PB9 (CCMR2); Auto uses furi_hal_infrared_detect_tx_output() and, like the stock app, powers a detected module. The 5V rail is only switched on if it was off and is restored when the transmitter is released. Settings file keeps reading the old 2- and 3-field formats. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYkmJ3RnCgGZEBKnfRJt5x
Image and multi-frame sends now draw a bar with a percentage instead of the three dots: each payload covers a share of the whole send and every data frame moves the bar inside it (text chunks by rows, BMP and Color 2.6 as one payload). Single commands and Repeat mode keep the dots. The old comment said the GUI could not animate because the IR blaster starved it; with TIM1 + DMA the TX thread sleeps during frames. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYkmJ3RnCgGZEBKnfRJt5x
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYkmJ3RnCgGZEBKnfRJt5x
Same steps as the Windows helper: ufbt update, build, ufbt launch. It uses .venv/bin/ufbt from `make setup` when present, else ufbt on PATH, else `python3 -m ufbt`. .gitattributes keeps *.sh in LF so a Windows checkout does not break it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYkmJ3RnCgGZEBKnfRJt5x
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
IR: TIM1 + DMA engine, external IR module and progress bar
1. Play PP4 frames with TIM1 + DMA instead of a busy loop
Problem
tagtinker_ir_transmit()bit-bangs each frame with aDWT->CYCCNTbusy loopinside
FURI_CRITICAL_ENTER/EXIT. The comment says the critical section lasts1-2 ms, but one PP4 symbol takes ~191 us on average (40 us burst + 151 us mean
gap), i.e. ~0.77 ms per byte:
While masked, USB, BLE, the GUI and the expansion UART stall, and the TX thread
spins at the highest priority between frames.
Change
The stock
furi_hal_infraredasync TX cannot be reused: it caps the carrier atINFRARED_MAX_FREQUENCY(1 MHz) and ESLs need ~1.25 MHz. So this PR drives TIM1directly with the same technique the firmware uses:
CCMR2(PWM2 = carrier on, forced inactive = off) and DMA2 ch2 writes the next
segment length to
RCR.Files:
ir/tagtinker_ir_seq.[ch](new, pure C): builds the DMA tables from a frame.No Flipper headers, so it is unit-testable on a PC.
ir/tagtinker_ir.c: hardware driver. Public API unchanged, no caller changes.tests/test_ir_seq.c+make test+ atestsCI job (ASan + UBSan):replays the tables through a model of TIM1 + DMA and compares the waveform
with the timing of the old driver (2000 random frames + edge cases).
README.md/CONTRIBUTING.md: documentmake test.build_and_flash.bat: small Windows helper (ufbt update, build,ufbt launch) for contributors withoutmake. Happy to drop it or move itto a separate PR if you prefer.
Behaviour notes
0.4 us of the old timing, every symbol (burst + gap) within 0.8 us. Bursts
are 40.6 us instead of 40.3 us. PP4 is pulse-position coded, so this is far
below the ~60 us spacing between symbol values.
TAGTINKER_MAX_FRAME_SIZE) instead of 255.All callers already use frames of at most 96 bytes.
tagtinker_ir_init()refuses to start iffuri_hal_infrared_is_busy().tagtinker_ir_stop()only signals; the TX thread halts the hardware itself.tagtinker_ir_is_busy()was declared but never defined; it is now.Tested
make testpasses (host, ASan + UBSan); the test fails if two gap constantsare swapped.
-Wall -Wextra -Werroragainst thefirmware headers; all external symbols are exported in
api_symbols.csv.(type 1327, 208x112 red):
2. External IR module on GPIO A7 (#39, #45, #52)
Problem
The built-in IR LED has a short range; several users get partial or no
image updates (#39, #45, #52).
Change
Two settings, like the stock Infrared app:
Internal/GPIO A7/Auto(detects a module when sending);The driver uses TIM1 CH1N on PA7 instead of CH3N on PB9.
Autousesfuri_hal_infrared_detect_tx_output()and, like the stock app, powers adetected module. The 5V rail is only switched on if it was off and is
restored afterwards. The transmit screen says "Point the IR module at tag".
Old settings files are still read.
Tested
Flipper Zero, firmware mntm 12, external IR module:
Internal / GPIO A7 / Auto, settings kept after restart, stock Infrared app
fine afterwards, image sent to a Pricer F14 through the module.
3. Progress bar while sending images (#45)
Problem
An image send takes up to ~30 s with only three animated dots (#45).
Change
Image and multi-frame sends draw a bar with a percentage. Each payload
covers a share of the send and each data frame moves the bar. Single
commands and Repeat mode keep the dots. This needs the DMA engine: the old
driver blocked the CPU during frames.
Tested
Flipper Zero, firmware mntm 12: bar from 0 to 100 %, Back during a
send stops cleanly and a new send works.