Skip to content

feat: Support SD cards behind a co-processor (SenseCAP Indicator)#342

Open
caveman99 wants to merge 6 commits into
masterfrom
indicator
Open

feat: Support SD cards behind a co-processor (SenseCAP Indicator)#342
caveman99 wants to merge 6 commits into
masterfrom
indicator

Conversation

@caveman99

@caveman99 caveman99 commented Jul 12, 2026

Copy link
Copy Markdown
Member

Companion to meshtastic/firmware#6220, which makes the SenseCAP Indicator RP2040 peripherals available to the main firmware over a serial protobuf link.

  • RemoteSDService: LVGL filesystem driver that loads map tiles chunk-wise through an IRemoteFS backend registered by the firmware. Includes a chunk read-ahead cache; save() supports the URLService tile download backup path.
  • RemoteSdCard: ISdCard implementation providing map style detection, url providers and card statistics over the same backend.
  • I2CKeyboardScanner: the secondary bus for the bus 1 rescan is injectable, so devices whose second I2C bus lives behind a co-processor can pass a bridged TwoWire implementation instead of the uninitialized local Wire1.

All wiring is gated on SENSECAP_INDICATOR; other targets are unaffected. Verified on hardware: map tiles, style dropdown and SD statistics work with tiles on the SD card behind the RP2040.

Summary by CodeRabbit

  • New Features
    • Added remote SD-card support (remote filesystem + LVGL tile service) for compatible builds, including remote map style discovery and URL-based map provider lookup with chunked transfers.
    • Added SD statistics freshness support, with a new “pending/unavailable/valid” status and automatic stats refreshing.
    • Added the ability to configure a secondary I2C bus for keyboard scanning (bus 1).
  • UI Updates
    • Improved SD-card stats display by using background polling and showing placeholders until stats are ready.
    • When remote storage is active, SD-card backup and restore are disabled to match the remote workflow.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a64a62cd-93fd-4663-b58b-e49539f29a76

📥 Commits

Reviewing files that changed from the base of the PR and between dcb45b7 and f74a67f.

📒 Files selected for processing (7)
  • include/graphics/common/SdCard.h
  • include/graphics/map/RemoteSDService.h
  • include/graphics/view/TFT/TFTView_320x240.h
  • locale/en.yml
  • source/graphics/TFT/TFTView_320x240.cpp
  • source/graphics/common/SdCard.cpp
  • source/graphics/map/RemoteSDService.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • include/graphics/map/RemoteSDService.h
  • source/graphics/map/RemoteSDService.cpp
  • source/graphics/common/SdCard.cpp

📝 Walkthrough

Walkthrough

The change adds remote filesystem-backed SD-card and tile access for SENSECAP_INDICATOR, integrates remote map storage and asynchronous SD statistics into the TFT view, and adds configurable secondary I2C bus selection for keyboard scanning.

Changes

Remote SD storage

Layer / File(s) Summary
Remote filesystem contracts
include/graphics/map/RemoteSDService.h, include/graphics/common/SdCard.h
Defines remote SD metadata, chunked filesystem operations, tile-service APIs, SD statistics support, and cached file state.
Chunked LVGL filesystem service
source/graphics/map/RemoteSDService.cpp
Registers LVGL callbacks and implements remote image loading, chunked writes, cached reads, seeking, and position reporting.
Remote SD-card integration
source/graphics/common/SdCard.cpp, include/graphics/common/SdCard.h
Adds the SENSECAP_INDICATOR remote SD adapter, maps remote metadata, discovers map styles, and reads URL providers.
Remote map and SD status UI
source/graphics/TFT/TFTView_320x240.cpp, include/graphics/view/TFT/TFTView_320x240.h, locale/en.yml
Wires remote tile loading into the TFT view and adds bounded SD-statistics polling, label formatting, and localization text.

Secondary keyboard I2C bus

Layer / File(s) Summary
Configurable secondary bus
include/input/I2CKeyboardScanner.h, source/input/I2CKeyboardScanner.cpp
Adds a secondary TwoWire override and uses it for bus-1 keyboard scanning, falling back to Wire1 when unset.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MapPanel
  participant RemoteSDService
  participant LVGL
  participant IRemoteFS
  MapPanel->>RemoteSDService: Request map tile
  RemoteSDService->>LVGL: Set remote image source
  LVGL->>RemoteSDService: Open and read file
  RemoteSDService->>IRemoteFS: Fetch aligned chunk
  IRemoteFS-->>RemoteSDService: Return chunk data
  RemoteSDService-->>LVGL: Provide requested bytes
Loading

Possibly related PRs

Poem

I hop through chunks where map tiles gleam,
Remote paths now feed the screen’s bright dream.
A bridged bus hums, keyboards reply,
SD facts travel softly by.
Squeak, scan, and render—what a wonderful view!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding SenseCAP Indicator support for SD cards behind a co-processor.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
source/graphics/map/RemoteSDService.cpp (1)

21-35: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Function-local static lv_fs_drv_t drv is shared/re-registered if constructed twice.

Since drv is a function-local static, a second RemoteSDService instantiation would re-run lv_fs_drv_register(&drv) on the same struct, inserting a duplicate pointer into LVGL's driver list under the same letter. Currently only one instance is created (TFTView_320x240::loadMap()), so this is latent rather than active, but guarding registration (e.g. a one-time static flag, or moving drv/registration to a static init function) would make the class safe against future misuse.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@source/graphics/map/RemoteSDService.cpp` around lines 21 - 35, Update the
RemoteSDService constructor’s LVGL driver registration so repeated
RemoteSDService instances do not call lv_fs_drv_register(&drv) more than once.
Guard the existing function-local static drv initialization and registration
with one-time state, while preserving the current driver configuration and
shared driver instance.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/graphics/common/SdCard.cpp`:
- Around line 331-339: Update RemoteSdCard::init and the updateSDCard flow so
the potentially multi-second IRemoteFS::sdInfo call does not run synchronously
on LVGL/UI paths such as ui_event_SDCardButton. Move the SD-status refresh to a
worker/background context, or establish a loading/timeout state before polling
asynchronously, while preserving the existing info.present result once the
refresh completes.

In `@source/graphics/map/RemoteSDService.cpp`:
- Around line 39-50: Replace the unbounded strcat in RemoteSDService::load with
a bounds-checked path construction that limits name to the remaining capacity of
buf and always preserves null termination. Keep the DRIVE_LETTER prefix and
existing lv_image_set_src/error behavior unchanged, and handle an overlong name
by returning false before using a truncated or overflowing path.

---

Nitpick comments:
In `@source/graphics/map/RemoteSDService.cpp`:
- Around line 21-35: Update the RemoteSDService constructor’s LVGL driver
registration so repeated RemoteSDService instances do not call
lv_fs_drv_register(&drv) more than once. Guard the existing function-local
static drv initialization and registration with one-time state, while preserving
the current driver configuration and shared driver instance.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cb4cee29-a315-4dbd-92be-ee67645f58ae

📥 Commits

Reviewing files that changed from the base of the PR and between effbb92 and f8d480d.

📒 Files selected for processing (7)
  • include/graphics/common/SdCard.h
  • include/graphics/map/RemoteSDService.h
  • include/input/I2CKeyboardScanner.h
  • source/graphics/TFT/TFTView_320x240.cpp
  • source/graphics/common/SdCard.cpp
  • source/graphics/map/RemoteSDService.cpp
  • source/input/I2CKeyboardScanner.cpp

Comment thread source/graphics/common/SdCard.cpp
Comment thread source/graphics/map/RemoteSDService.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/graphics/map/RemoteSDService.cpp`:
- Around line 101-119: Update the read logic around the chunk-fetch loop in
RemoteSDService to track backend or readChunk failures separately from a normal
loop exit. Return LV_FS_RES_UNKNOWN only when an explicit chunk/backend error
occurs, and return LV_FS_RES_OK for EOF or other successful zero-byte reads
while preserving the existing byte-count behavior.
- Around line 44-47: Update the load-failure check in the tile-loading flow
around lv_image_set_src and lv_image_get_src so it verifies that the returned
image source matches buf, rather than only checking for non-null. Preserve the
existing debug log and false return when loading fails, preventing a stale
previous source from being treated as success.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d9348240-f71e-4ada-b0c5-8a7cab042ebe

📥 Commits

Reviewing files that changed from the base of the PR and between f8d480d and aaac0d2.

📒 Files selected for processing (7)
  • include/graphics/common/SdCard.h
  • include/graphics/map/RemoteSDService.h
  • include/input/I2CKeyboardScanner.h
  • source/graphics/TFT/TFTView_320x240.cpp
  • source/graphics/common/SdCard.cpp
  • source/graphics/map/RemoteSDService.cpp
  • source/input/I2CKeyboardScanner.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • source/input/I2CKeyboardScanner.cpp
  • include/graphics/common/SdCard.h
  • source/graphics/common/SdCard.cpp

Comment thread source/graphics/map/RemoteSDService.cpp
Comment thread source/graphics/map/RemoteSDService.cpp Outdated
@caveman99 caveman99 changed the title Support SD cards behind a co-processor (SenseCAP Indicator) feat: Support SD cards behind a co-processor (SenseCAP Indicator) Jul 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@source/graphics/TFT/TFTView_320x240.cpp`:
- Around line 48-49: Reorder the conditional compilation branches so
SENSECAP_INDICATOR is evaluated before HAS_SD_MMC, ensuring SenseCap builds use
RemoteSDService/RemoteSdCard when both macros are defined. Apply the same
precedence change in updateSDCard(), or explicitly enforce mutual exclusivity
between the macros.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 659140d4-f33e-473a-a845-4be803a03c46

📥 Commits

Reviewing files that changed from the base of the PR and between aaac0d2 and a57fd74.

📒 Files selected for processing (7)
  • include/graphics/common/SdCard.h
  • include/graphics/map/RemoteSDService.h
  • include/input/I2CKeyboardScanner.h
  • source/graphics/TFT/TFTView_320x240.cpp
  • source/graphics/common/SdCard.cpp
  • source/graphics/map/RemoteSDService.cpp
  • source/input/I2CKeyboardScanner.cpp
🚧 Files skipped from review as they are similar to previous changes (6)
  • include/input/I2CKeyboardScanner.h
  • source/input/I2CKeyboardScanner.cpp
  • source/graphics/common/SdCard.cpp
  • include/graphics/map/RemoteSDService.h
  • source/graphics/map/RemoteSDService.cpp
  • include/graphics/common/SdCard.h

Comment thread source/graphics/TFT/TFTView_320x240.cpp
RemoteSDService implements an LVGL filesystem driver that fetches map
tiles chunk-wise through an IRemoteFS backend registered by the
firmware. RemoteSdCard provides map style detection, url providers and
card statistics over the same backend. The I2CKeyboardScanner secondary
bus is injectable so the bus 1 rescan can use a bridged TwoWire
implementation instead of the local Wire1.
…validity

fs_read verifies the fetched chunk covers the read position (a shrunk
file would loop or over-read) and picks up size changes. The LVGL fs
cache is disabled for the remote driver, its own chunk cache already
serves header reads without pulling whole tiles twice over the UART.
SEEK_END follows the LVGL size+pos convention. Failed multi-chunk saves
delete the partial file via the new IRemoteFS remove operation. Map
style listing only accepts directories. The .url provider reads until
the first line is complete. SD stats display shows a placeholder while
the co-processor scan is running (RemoteSdInfo.statsValid). SENSECAP
branches take precedence over generic SD defines in SdCard.h/.cpp.
… chain

Polling the co-processor for the background computed used/free values no
longer recreates the card object: that reset its updated flag, so the next
loadMap() rescanned the styles with a stale prefix and could offer the zoom
level directories of a flat /map card as map styles.

The generic SD implementations are now excluded on SENSECAP_INDICATOR in
the definition chain as well, matching their declarations.
The poll treated every failure as a scan that had not finished, so a removed
card or a down link made it retry forever, blocking the UI thread on a link
round trip each time. refreshStats now reports whether the statistics are
pending or unavailable, the poll is bounded, and a card that disappears
re-runs the detection instead of painting statistics over the error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant