feat: PicoMSO Flutter mobile app — full architecture scaffold#36
Draft
Copilot wants to merge 8 commits into
Draft
feat: PicoMSO Flutter mobile app — full architecture scaffold#36Copilot wants to merge 8 commits into
Copilot wants to merge 8 commits into
Conversation
- pubspec.yaml: Flutter project config with Riverpod, go_router, freezed - analysis_options.yaml: lint rules extending flutter_lints - README.md: architecture overview and getting-started guide - lib/transport/transport_interface.dart: abstract Transport + TransportException - lib/transport/usb_transport.dart: singleton USB stub (EP0/EP6) - lib/protocol/protocol_constants.dart: wire constants mirroring firmware headers - lib/protocol/protocol_codec.dart: little-endian encode/decode for all packet types - lib/protocol/capture_request_builder.dart: validated CaptureRequest builder Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: dgatf <33811722+dgatf@users.noreply.github.com>
Add 10 immutable Dart domain model files under mobile_app/lib/domain/models/: - capture_mode.dart – CaptureMode enum (logicOnly / mixedSignal) - trigger_config.dart – TriggerConfig + TriggerMatch enum w/ wire values - capture_request.dart – CaptureRequest (maps to picomso_request_capture_request_t) - digital_track.dart – DigitalTrack with packed-bit storage & transition index - analog_track.dart – AnalogTrack with normalized Float32List samples - min_max_pyramid.dart – MinMaxPyramid for efficient waveform downsampling - capture_session.dart – CaptureSession (immutable capture result) - decoder_result.dart – DecoderResult + DecoderSeverity enum - viewport_state.dart – ViewportState with zoom/pan helpers - device_info.dart – DeviceInfo, DeviceCapabilities, DeviceStatus Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: dgatf <33811722+dgatf@users.noreply.github.com>
- domain/decoders: DecoderConfig/ProtocolDecoder interface, UART, SPI, I2C decoders - repository: DeviceRepository (GET_INFO/CAPS/STATUS), CaptureRepository (full capture cycle with isolate assembly) - controllers: DeviceController, CaptureController (state machine), ViewportController (pan/zoom/cursors), DecoderController (isolate-based dispatch) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: dgatf <33811722+dgatf@users.noreply.github.com>
- ui/shared/theme/app_theme.dart: dark/light Material 3 theme, channel/analog colors, waveform canvas colors - ui/shared/widgets/connection_state_chip.dart: Riverpod-backed USB connection status chip - ui/waveform/painters/grid_painter.dart: time-axis grid with auto-scaling intervals and labels - ui/waveform/painters/digital_track_painter.dart: transition-indexed fast digital waveform renderer - ui/waveform/painters/analog_track_painter.dart: min-max pyramid downsampling analog renderer - ui/waveform/painters/decoder_overlay_painter.dart: protocol decoder annotation overlay - ui/waveform/painters/cursor_painter.dart: dashed cursor A/B lines with labels Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: dgatf <33811722+dgatf@users.noreply.github.com>
- lib/main.dart: app entry point with ProviderScope - lib/app.dart: root MaterialApp with named routes and dark theme - test/protocol/protocol_codec_test.dart: codec encode/decode tests - test/domain/decoders/uart_decoder_test.dart: UART decoder tests - test/controllers/capture_controller_test.dart: state machine tests - android/: minimal Android project stubs (build.gradle, settings.gradle, gradle wrapper, app/build.gradle, AndroidManifest.xml, MainActivity.kt) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: dgatf <33811722+dgatf@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dgatf/PicoMSO/sessions/178a90e6-15b2-4532-8ddf-b5a25eafafe0 Co-authored-by: dgatf <33811722+dgatf@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dgatf/PicoMSO/sessions/178a90e6-15b2-4532-8ddf-b5a25eafafe0 Co-authored-by: dgatf <33811722+dgatf@users.noreply.github.com>
…epository Agent-Logs-Url: https://github.com/dgatf/PicoMSO/sessions/178a90e6-15b2-4532-8ddf-b5a25eafafe0 Co-authored-by: dgatf <33811722+dgatf@users.noreply.github.com>
Copilot created this pull request from a session on behalf of
dgatf
April 9, 2026 21:18
View session
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.
Implements the complete Flutter app scaffold for PicoMSO based on the architecture proposal: mobile-first waveform viewer for logic-only and mixed-signal triggered captures over USB.
Transport / Protocol
UsbTransportsingleton stub (EP0 control + EP6 bulk IN); swappable via abstractTransportProtocolCodec:ByteDatalittle-endian encode/decode for all wire types; mirrors firmware packed structs exactly including the optional 25th byte (analog_channelsbitmask) inREQUEST_CAPTUREprotocol_constants.dartmirrors all firmware#definesDomain Models
DigitalTrack: packed bits (1 bit/sample, LSB-first) + pre-computed transition index list for O(log n) binary-search renderingAnalogTrack: normalizedFloat32List(12-bit ADC → 0.0–1.0)MinMaxPyramid: 4× downsampling levels, async build viaIsolate.runViewportState: zoom/pan/cursor math helpersCaptureStatefor the lifecycle FSMRepository
CaptureRepository.runCapture:SET_MODE → REQUEST_CAPTURE → READ_DATA_BLOCKloop; handles dual-stream independentTERMINALflags for mixed-signal; assemblesCaptureSessionoff-threadscope_demux_phasecounter (interleaved channels in ascending index order)Controllers (Riverpod)
CaptureController(Notifier<CaptureState>): sealedIdle → Arming → Armed → Downloading → Complete | ErrorViewportController: auto zoom-to-fit on new session arrivalDecoderController: runs all active decoders in an isolate; invalidates on session or config changeDecoders
Stateless, isolate-safe plugins behind
ProtocolDecoder<C extends DecoderConfig>:UI
HomeScreen→CaptureSetupSheet(bottom sheet: trigger config, rate/count, pre-trigger %, analog channel toggles) →CaptureRunScreen(pulsing armed animation + download progress) →WaveformViewerScreenWaveformViewerScreen: manualGestureDetector(split-axis pan/zoom);Stack+RepaintBoundaryper layer;ChannelLabelListsidebar (long-press →DecoderConfigSheet); retrigger FABDecoderConfigSheet: segmented UART/SPI/I2C config, pre-populates from existing configPainters
Each in its own
RepaintBoundary;Paint/Pathpre-allocated as fields, never insidepaint():GridPainterDigitalTrackPainterdrawPathper trackAnalogTrackPaintersamplesPerPixel; raw polygon at zoom-inDecoderOverlayPainterCursorPainterRepaintBoundary; cursor drag doesn't invalidate signal layersTests
protocol_codec_test: encoding correctness, sequence counter, ACK/error/DATA_BLOCK decodeuart_decoder_test: synthetic frame encode → decode round-trip for 0x00/0x55/0xFF; format variants; edge casescapture_controller_test: state machine transitions viaProviderContainer