001package jmri.jmrix.pi.simulator;
002
003import java.util.HashMap;
004import java.util.Map;
005
006/**
007 * Simulate Raspberry Pi GPIO — pure JMRI implementation, no Pi4J dependency.
008 * <p>
009 * Maintains a registry of provisioned input and output pins keyed by BCM
010 * address so that {@link jmri.jmrix.pi.RaspberryPiSensor} and
011 * {@link jmri.jmrix.pi.RaspberryPiTurnout} can share state.
012 *
013 * @author Daniel Bergqvist Copyright (C) 2022
014 */
015public class GpioSimulator {
016
017    private static GpioSimulator instance = new GpioSimulator();
018
019    private final Map<Integer, GpioPinDigitalInputSimulator> inputPins = new HashMap<>();
020    private final Map<Integer, GpioPinDigitalOutputSimulator> outputPins = new HashMap<>();
021
022    public static GpioSimulator getInstance() {
023        return instance;
024    }
025
026    private GpioSimulator() {
027    }
028
029    /**
030     * Provision (or replace) a simulated digital input pin.
031     *
032     * @param address BCM pin address
033     * @param name    descriptive name (unused internally)
034     * @return the new pin instance
035     */
036    public GpioPinDigitalInputSimulator provisionDigitalInputPin(int address, String name) {
037        GpioPinDigitalInputSimulator pin = new GpioPinDigitalInputSimulator();
038        inputPins.put(address, pin);
039        return pin;
040    }
041
042    /**
043     * Provision (or replace) a simulated digital output pin.
044     *
045     * @param address BCM pin address
046     * @param name    descriptive name (unused internally)
047     * @return the new pin instance
048     */
049    public GpioPinDigitalOutputSimulator provisionDigitalOutputPin(int address, String name) {
050        GpioPinDigitalOutputSimulator pin = new GpioPinDigitalOutputSimulator();
051        outputPins.put(address, pin);
052        return pin;
053    }
054
055    /** Remove a provisioned input pin (called from sensor dispose). */
056    public void unprovisionInputPin(int address) {
057        inputPins.remove(address);
058    }
059
060    /** Remove a provisioned output pin (called from turnout dispose). */
061    public void unprovisionOutputPin(int address) {
062        outputPins.remove(address);
063    }
064
065    /** Remove all provisioned pins (called from adapter shutdown). */
066    public void shutdown() {
067        inputPins.clear();
068        outputPins.clear();
069    }
070
071    /**
072     * Reset pin registry for testing. Preserves the singleton instance but
073     * clears all provisioned pins so that the next test starts clean.
074     */
075    public void reset() {
076        inputPins.clear();
077        outputPins.clear();
078    }
079}