Optimizing TComPort Settings for High-Speed Serial Devices

Building a Cross-Platform Serial App with TComPort and DelphiSerial communication remains essential for interfacing with embedded devices, industrial controllers, legacy instruments, and many IoT modules. Delphi developers who need a robust, easy-to-use serial library often turn to TComPort — a component that abstracts platform-specific serial port APIs and exposes a familiar, event-driven interface. This article walks through designing, implementing, and deploying a cross-platform serial application in Delphi using TComPort, covering architecture, key APIs, practical examples, error handling, performance tips, and deployment considerations.


Why TComPort and Delphi?

Delphi provides a single-codebase approach to compile native applications for Windows, macOS, Linux, Android, and iOS (with some platform constraints). TComPort complements Delphi by wrapping serial port access in a component that behaves consistently across supported platforms, enabling developers to focus on application logic rather than low-level OS differences.

Key reasons to use TComPort:

  • Consistent API across platforms.
  • Event-driven model that fits Delphi’s component paradigm.
  • Support for common serial features: baud rates, parity, stop bits, flow control, timeouts, and hardware line control (RTS/CTS, DTR/DSR).
  • Community-driven improvements and examples.

Application overview and goals

We’ll build a demo cross-platform app that:

  • Lists available serial ports.
  • Connects/disconnects to a selected port with configurable settings.
  • Sends and receives ASCII and binary data.
  • Logs communication to a file.
  • Supports auto-reconnect and basic command/response transaction handling.
  • Provides a simple UI for desktop platforms and a minimal UI for mobile where feasible.

This design keeps the serial logic separated from the UI so it can be reused across desktop and mobile front ends.


Project structure and separation of concerns

Organize the project into layers:

  • Serial layer — a wrapper around TComPort providing high-level operations (connect, disconnect, send, receive, events).
  • Protocol layer — implements parsing, framing, checksums, and command/response logic.
  • Persistence layer — logging and configuration storage.
  • UI layer(s) — platform-specific forms or FMX views.

A recommended directory layout:

  • src/
    • Serial/
      • uSerialManager.pas
    • Protocol/
      • uProtocolHandler.pas
    • Persistence/
      • uLogger.pas
      • uConfig.pas
    • UI/
      • MainForm.pas (FMX)
      • MobileForm.pas (FMX, simplified)
    • App.pas

Keep serial code free from UI calls; use events, callbacks, or TThread.Synchronize when UI updates are necessary.


Choosing the right TComPort fork/version

TComPort has multiple forks and variations. Pick a version that:

  • Is actively maintained or matches your Delphi version.
  • Supports the platforms you target (Windows, macOS, Linux, Android, iOS — note: not all forks cover mobile).
  • Includes fixes for modern RTL/FireMonkey compilers.

Test the component early on each target platform — serial APIs and device naming differ (COM1, /dev/ttyS0, /dev/ttyUSB0, /dev/tty.usbserial-xxxx).


Core serial wrapper: uSerialManager.pas

Design a SerialManager class that wraps a TComPort instance and exposes a clean API. Main responsibilities:

  • Enumerate ports.
  • Manage connection and configuration.
  • Read/write operations with thread-safe buffering.
  • Events for data received, port errors, and status changes.
  • Auto-reconnect logic and simple flow-control helpers.

Example public interface (conceptual):

type   TSerialDataEvent = procedure(const AData: TBytes) of object;   TSerialStatusEvent = procedure(const AStatus: string) of object;   TSerialManager = class   private     FComPort: TComPort;     FOnData: TSerialDataEvent;     FOnStatus: TSerialStatusEvent;     FReadBuffer: TBytes;     procedure DoComportData(Sender: TObject; Count: Integer);     procedure DoComportError(Sender: TObject; Err: Integer);   public     constructor Create;     destructor Destroy; override;     function ListPorts: TArray<string>;     procedure Configure(ABaud: Integer; AParity: TParity; AStopBits: TStopBits; AFlowControl: TFlowControl);     procedure Connect(const APortName: string);     procedure Disconnect;     procedure Send(const AData: TBytes);     property OnData: TSerialDataEvent read FOnData write FOnData;     property OnStatus: TSerialStatusEvent read FOnStatus write FOnStatus;   end; 

Key implementation notes:

  • Use TComPort’s OnRxChar/OnRxString or equivalent event for incoming data and move bytes into a thread-safe buffer.
  • Avoid lengthy processing inside the port event; dispatch parsing to a worker thread or queue.
  • For UI updates, marshal with TThread.Queue or Synchronize.

Serial parameters and platform quirks

Standard settings:

  • Baud: 300–115200+ (custom baud rates may be platform-dependent).
  • Data bits: 5–8.
  • Parity: None, Even, Odd, Mark, Space (note some platforms or chips don’t support all).
  • Stop bits: 1, 1.5, 2.
  • Flow control: None, XON/XOFF (software), RTS/CTS (hardware).

Platform notes:

  • Windows uses “COMn”. For COM ports above 9, prefix with “.” in some APIs; TComPort typically handles it.
  • Linux uses “/dev/ttyS”, “/dev/ttyUSB”, “/dev/ttyACM*”.
  • macOS uses “/dev/tty.” or “/dev/cu.”; prefer cu.* for direct connections.
  • Android/iOS: access to USB serial may require platform-specific plugins or unavailable on iOS.

Parsing and protocol layer

Design the protocol handler to be independent of the serial transport. Features:

  • Framing (start/end markers, length fields).
  • Checksums/CRC validation.
  • Timeouts and retries.
  • Synchronous command/response with per-command timeouts.

Example flow for a framed protocol:

  • OnData event appends bytes to parser buffer.
  • Parser scans for start marker (e.g., 0x02), reads length, validates checksum, and emits complete messages to the application.
  • For commands, send then wait on a TEvent or condition variable for the response or timeout.

Keep binary-safe handling — avoid string conversions unless dealing with ASCII.


UI design (FMX for cross-platform)

FMX gives a single UI layer for desktop and mobile. Design guidelines:

  • Desktop: full-featured controls — port list, settings, connect button, text grid for logs, hex/ascii toggle.
  • Mobile: simplified controls — dropdown for ports, connect, basic log view, send button.

Ensure UI responsiveness:

  • All serial I/O runs off the main thread.
  • Large logs should use virtualization (e.g., TStringList with limited size or TListBox with capped items) to avoid memory bloat.

Example UI interactions:

  • User selects port and settings → clicks Connect → SerialManager.Connect triggers background open and emits status.
  • Incoming messages update log and possibly UI controls via queued events.

Logging and persistence

Keep a configurable logger that:

  • Writes timestamped entries (direction: TX/RX, raw hex or ASCII).
  • Rotates logs based on size or age.
  • Optionally masks sensitive data.

Use platform-appropriate storage locations:

  • Windows: %APPDATA%/YourApp
  • macOS: ~/Library/Application Support/YourApp
  • Linux: ~/.config/YourApp or /var/log/yourapp (depending on use)
  • Mobile: sandboxed application storage via FMX.Platform services

Error handling and recovery

Robustness tips:

  • Detect device removal and propagate a clear disconnected event.
  • Implement exponential backoff for reconnect attempts.
  • Surface detailed error messages (e.g., access denied, invalid settings).
  • Validate configuration before applying (unsupported baud or flow settings).

Example auto-reconnect strategy:

  • On disconnect, try reconnecting 3 times with 1s, 2s, 5s delays; if still disconnected, emit alert and wait for user action.

Testing strategies

Test across devices and OSes:

  • Unit tests for protocol parsing and checksum logic.
  • Integration tests using a loopback setup (connect TX→RX) and virtual serial ports (com0com for Windows, socat on Unix).
  • Hardware tests with real devices and varying baudrates and cable types.
  • Stress tests: continuous high-throughput transfers and abrupt disconnects.

Automate tests where possible using scripts that toggle virtual ports and inject errors.


Performance tuning

If throughput or latency matters:

  • Use larger read buffer sizes and batch processing of incoming bytes.
  • Minimize UI updates; aggregate log updates and flush periodically (e.g., every 50–100 ms).
  • Prefer binary TBytes over string manipulation for heavy data.
  • On POSIX systems, tweak termios VMIN/VTIME or device buffer sizes if available.

Deployment notes

  • Build and test native packages per platform (Windows EXE/installer, macOS app bundle/notarization if needed, Linux AppImage/deb/rpm, Android APK).
  • Include necessary runtime libraries and declare hardware permissions on mobile (USB host, etc.).
  • Provide documentation for users on how to find device names on each OS.

Example: simple send/receive code snippet

(Conceptual Pascal code — adapt to your TComPort fork and Delphi version)

procedure TSerialManager.DoComportData(Sender: TObject; Count: Integer); var   Buf: TBytes;   Read: Integer; begin   SetLength(Buf, Count);   Read := FComPort.Read(Buf, Count);   if Read > 0 then   begin     // Queue processing to avoid blocking the port event     TThread.Queue(nil,       procedure       begin         if Assigned(FOnData) then           FOnData(Buf);       end);   end; end; 

Common pitfalls

  • Blocking I/O on the main thread — always use background threads.
  • Assuming device names are identical across platforms.
  • Not handling partial frames — always buffer until a complete message is assembled.
  • Ignoring flow control — hardware handshake can be required for some devices.

Security considerations

  • Sanitize and validate incoming data before acting on it.
  • If controlling devices over serial, enforce authentication or command whitelisting in higher-level protocols.
  • Protect logs that may contain sensitive device identifiers.

Summary

Building a cross-platform serial app with TComPort and Delphi is practical and efficient when you separate concerns, keep serial I/O off the UI thread, implement robust parsing/reconnect logic, and test on each target OS. The combination of Delphi’s cross-compilation and TComPort’s abstraction lets you reuse most code across desktops and mobile platforms while handling OS-specific quirks where necessary.

If you want, I can produce: a ready-to-compile example project for Delphi (FMX) using a specific TComPort fork/version, detailed code files (uSerialManager.pas, uProtocolHandler.pas, MainForm.pas), or a checklist for deployment to a chosen platform. Which would you prefer?

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *