modbus-impl 0.7.0

A small `no_std` Modbus RTU helper library designed to run on embedded Rust targets
Documentation
# Modbus-Impl (RTU) for rp-usb-serial & rp-pio-serial

A small `no_std` Modbus RTU helper library designed to run on embedded Rust targets (e.g. RP2040/RP2350) and work with  `rp-usb-serial` USB CDC link & `rp-pio-serial` PIO-based software serial for RP2040 & RP2350 using arbitrary GPIO pins. It currently focuses on **Modbus function codes 01, 02, 03, and 04** (read operations) and builds valid Modbus RTU frames including **CRC16**.

---

## What it does

At runtime the library processes fixed-length Modbus requests carried over a byte-stream transport (USB CDC). For each incoming request frame it:

1. Validates **CRC16 (Modbus polynomial 0xA001, init 0xFFFF)**  
2. Parses the request fields:
   - Unit ID
   - Function code (0x01/0x02/0x03/0x04/0x05/0x06)
   - Start address
   - Quantity
3. Checks **address range** using `is_valid(addr)`
4. Builds one of:
   - A normal response frame for the requested function, or
   - An exception response frame:
     - Function | 0x80
     - Exception code (ILLEGAL_FUNCTION / ILLEGAL_DATA_ADDRESS / ILLEGAL_DATA_VALUE)
     - CRC16

---

## Supported Modbus Functions

- **0x01** Read Coils  
- **0x02** Read Discrete Inputs  
- **0x03** Read Holding Registers (16-bit registers, big-endian in the payload)  
- **0x04** Read Input Registers (16-bit registers, big-endian in the payload)
- **0x05** Write Single Coil
- **0x06** Write Single Register
- **0x0F** Write Multiple Coils
- **0x10** Write Multiple Registers

Coils/inputs are packed into bytes using Modbus rules (**LSB-first bit packing**).

---

## Data Model

The library defines interfaces so you can plug in your own memory map:

### `RegisterRead`
Used for 16-bit register based functions (FC03/FC04):
- `get(addr: u16) -> u16`
- `is_valid(addr: u16) -> bool`

### `RegisterWrite`
Used for 16-bit register based functions (FC06/FC16)
-  `set_reg(addr: u16, val: u16)`
-  `set_qty(qty: u16)`
-  `get_qty() -> usize`

### `BitRead`
Used for bit based functions (FC01/FC02):
- `get(addr: u16) -> bool`
- `is_valid(addr: u16) -> bool`

### `BitWrite`
Used for 16 bit based functions (FC05/FC15)
-  `set_bit(addr: u16, val: bool)`
-  `set_qty(qty: u16)`
-  `get_qty() -> usize`

It also provides basic storage types that implement these traits:
- `Hreg<N>` for Holding Registers (FC03/FC06/FC16)
- `Ireg<N>` for Input Registers (FC04)
- `Coil<N>` for Coils (FC01/FC05/FC15)
- `Ists<N>` for Discrete Inputs (FC02)

---

## Implementation Overview

Key components:

- **`crc16_modbus(data: &[u8]) -> u16`**  
  Implements Modbus RTU CRC16.

- **Frame parsing**  
  - Requests are assumed to be **8 bytes long** (standard RTU frame for function 01/02/03/04 read requests, 05/06/15/16 write requests).
  - `parse_pdu()`  | `parse_frame` dispatch supports multiple function codes.

- **Response builders**
  - `build_resp_bit_reads()` builds FC01/FC02 responses.
  - `build_resp_regs()` builds FC03/FC04 responses.
  - `build_exception_resp()` builds exception responses.

- **`ModbusCtx::pharse_frame()`**
  The main entry that takes a request frame and outputs either a response or an exception.

---

## Typical Usage Flow

In your main loop you typically:
1. Receive bytes from `rp-usb-serial` into an 8-byte  or more byte depend on func `FrameLen4Func(func, &rx_accum, rx_len);` buffer.
2. Call:
   - `ctx.pharse_frame::<MAX_QTY>(frame, &mut resp_buf, &mut exc_buf);`
3. Send the resulting frame back with:
   - `RpUsbConsole::write(&resp_or_exc[..len])`

## Example for use

[rp2040-usb-modbus-example](https://github.com/sndnvaps/modbus-impl/tree/main/rp2040-usb-modbus-example)

[rp2040-usb-modbus-example-2](https://github.com/sndnvaps/modbus-impl/tree/main/rp2040-usb-modbus-example-2)

[rp2350-pio-soft-serial-modbus-example](https://github.com/sndnvaps/modbus-impl/tree/main/rp2350-pio-modbus-example)

---

## Notes / Limitations

- This library is RTU-focused but transport-agnostic: it assumes requests arrive as a byte stream and are accumulated into **exact 8-byte frames**.
- **Read** functions are implemented (01/02/03/04).
- **Write** functions are implemented (05/06/15/16).
- Bit packing follows Modbus LSB-first conventions.

---