//! PORT PMUX and PINCFG configuration for {{ ir.board.name }}.
//!
//! Per CHIPS-MICROCHIP-00 §9, each SAM pad is identified by a
//! `(group, pin)` pair and carries:
//!
//! - **PMUX** register — 4-bit selector picking one of A..H (D5x) or
//!   A..N (D21 superset) alternate-function columns. Adjacent pads share
//!   a `PMUXn` register byte: even pin → `pmuxe`, odd pin → `pmuxo`.
//!   Half-index is `pin / 2`.
//! - **PINCFG** register — input-enable / pull / drive-strength bits.
//!   PMUXEN selects whether PMUX is honoured (peripheral function) or
//!   the pad is plain software-driven GPIO.
//!
//! Each board pin's `pmux:` letter is matched against the chip yaml's
//! `io_mux.fn_<letter>:` column to produce a 4-bit field value
//! (A=0, B=1, ..., H=7, N=0xf). Pins with `signal: GPIO` skip the PMUX
//! write entirely and configure PINCFG for direct GPIO use.
//!
//! The pinned `atsamd51j19a 0.7.1` PAC predates svd2rust's method-style
//! register accessors: `PORT` exposes `group0` / `group1` as direct
//! register-block fields, and within each group `pmux` / `pincfg` are
//! fixed-size arrays (`[PMUX; 16]`, `[PINCFG; 32]`). The generator
//! emits the corresponding `p.PORT.groupN.pmux[H]` / `p.PORT.groupN.pincfg[P]`
//! field-and-index syntax accordingly.

use {{ ir.chip.pac_crate }} as pac;

/// Apply the board's PORT PMUX and PINCFG routing.
pub fn init() {
    let p = unsafe { pac::Peripherals::steal() };
    {% for pad in pad_routes %}
    // {{ pad.pad }} (group {{ pad.group }} pin {{ pad.pin }}) — {{ pad.signal }}{% if pad.peripheral %} ({{ pad.peripheral }}){% endif %}
    {% if pad.unmatched_peripheral %}
    // MISMATCH: board claims peripheral signal `{{ pad.signal }}` on
    //           pad {{ pad.pad }} but chip yaml `io_mux.fn_<letter>:` columns
    //           do not list it. Falling back to plain GPIO PINCFG. Fix
    //           by amending chipdb/rlvgl-chips-microchip/db/chips/{{ ir.chip.name }}.yaml
    //           per CHIPS-MICROCHIP §15.
    {% endif %}
    {% if pad.pmux_enable %}
    // PMUX letter {{ pad.pmux_letter }} → bits {{ pad.pmux_bits }}
    p.PORT.group{{ pad.group }}.pmux[{{ pad.pmux_half }}].modify(|_, w| unsafe {
        w.{% if pad.pmux_odd %}pmuxo{% else %}pmuxe{% endif %}().bits({{ pad.pmux_bits }})
    });
    p.PORT.group{{ pad.group }}.pincfg[{{ pad.pin }}].write(|w| {
        w.pmuxen().set_bit()
         .inen().{% if pad.direction == "in" or pad.direction == "inout" %}set_bit{% else %}clear_bit{% endif %}()
         .pullen().{% if pad.pull == "up" or pad.pull == "down" %}set_bit{% else %}clear_bit{% endif %}()
    });
    {% if pad.pull == "up" %}
    // Pull-up: OUT bit selects pull direction when PULLEN is set.
    p.PORT.group{{ pad.group }}.outset.write(|w| unsafe { w.bits(1 << {{ pad.pin }}) });
    {% elif pad.pull == "down" %}
    p.PORT.group{{ pad.group }}.outclr.write(|w| unsafe { w.bits(1 << {{ pad.pin }}) });
    {% endif %}
    {% else %}
    // Plain GPIO (signal `{{ pad.signal }}`): no PMUX, configure PINCFG only.
    p.PORT.group{{ pad.group }}.pincfg[{{ pad.pin }}].write(|w| {
        w.pmuxen().clear_bit()
         .inen().{% if pad.direction == "in" or pad.direction == "inout" %}set_bit{% else %}clear_bit{% endif %}()
         .pullen().{% if pad.pull == "up" or pad.pull == "down" %}set_bit{% else %}clear_bit{% endif %}()
    });
    {% if pad.direction == "out" or pad.direction == "inout" %}
    // Drive direction set for output pad.
    p.PORT.group{{ pad.group }}.dirset.write(|w| unsafe { w.bits(1 << {{ pad.pin }}) });
    {% else %}
    p.PORT.group{{ pad.group }}.dirclr.write(|w| unsafe { w.bits(1 << {{ pad.pin }}) });
    {% endif %}
    {% if pad.pull == "up" %}
    p.PORT.group{{ pad.group }}.outset.write(|w| unsafe { w.bits(1 << {{ pad.pin }}) });
    {% elif pad.pull == "down" %}
    p.PORT.group{{ pad.group }}.outclr.write(|w| unsafe { w.bits(1 << {{ pad.pin }}) });
    {% endif %}
    {% endif %}
    {% endfor %}
}
