text: """Base backend for Arduino Uno and its derivatives."""
  
  from typing import Mapping, Optional, Type
  
  from j5.backends import Backend
  from j5.backends.console import Console
  from j5.components import GPIOPinInterface, GPIOPinMode, LEDInterface
  
  
  class PinData:
      """Contains data about a pin."""
  
      mode: GPIOPinMode
      digital_state: bool
  
      def __init__(self, *, mode: GPIOPinMode, digital_state: bool):
          self.mode = mode
          self.digital_state = digital_state
  
  
  class ArduinoConsoleBackend(
      GPIOPinInterface,
      LEDInterface,
      Backend,
  ):
      """An abstract class to create console backends for different Arduinos."""
  
      def __init__(self, serial: str, console_class: Type[Console] = Console) -> None:
          self._serial = serial
  
          self._pins: Mapping[int, PinData] = {
              i: PinData(mode=GPIOPinMode.DIGITAL_OUTPUT, digital_state=False)
              for i in range(2, 20)
              # Digital 2 - 13
              # Analogue 14 - 19
          }
  
          # Setup console helper
          self._console = console_class(f"{self.board.__name__}({self._serial})")
  
      @property
      def firmware_version(self) -> Optional[str]:
          """The firmware version reported by the board."""
          return None  # Console, so no firmware
  
      def set_gpio_pin_mode(self, identifier: int, pin_mode: GPIOPinMode) -> None:
          """Set the hardware mode of a GPIO pin."""
          self._console.info(f"Set pin {identifier} to {pin_mode.name}")
          self._pins[identifier].mode = pin_mode
  
      def get_gpio_pin_mode(self, identifier: int) -> GPIOPinMode:
          """Get the hardware mode of a GPIO pin."""
          return self._pins[identifier].mode
  
      def write_gpio_pin_digital_state(self, identifier: int, state: bool) -> None:
          """Write to the digital state of a GPIO pin."""
          if self._pins[identifier].mode is not GPIOPinMode.DIGITAL_OUTPUT:
              raise ValueError(f"Pin {identifier} mode needs to be DIGITAL_OUTPUT "
                               f"in order to set the digital state.")
          self._console.info(f"Set pin {identifier} state to {state}")
          self._pins[identifier].digital_state = state
  
      def get_gpio_pin_digital_state(self, identifier: int) -> bool:
          """Get the last written state of the GPIO pin."""
          if self._pins[identifier].mode is not GPIOPinMode.DIGITAL_OUTPUT:
              raise ValueError(f"Pin {identifier} mode needs to be DIGITAL_OUTPUT "
                               f"in order to read the digital state.")
          return self._pins[identifier].digital_state
  
      def read_gpio_pin_digital_state(self, identifier: int) -> bool:
          """Read the digital state of the GPIO pin."""
          if self._pins[identifier].mode not in [
              GPIOPinMode.DIGITAL_INPUT_PULLUP,
              GPIOPinMode.DIGITAL_INPUT,
              GPIOPinMode.DIGITAL_INPUT_PULLDOWN,
          ]:
              raise ValueError(f"Pin {identifier} mode needs to be DIGITAL_INPUT_* "
                               f"in order to read the digital state.")
          return self._console.read(f"Pin {identifier} digital state [true/false]", bool)
  
      def read_gpio_pin_analogue_value(self, identifier: int) -> float:
          """Read the scaled analogue value of the GPIO pin."""
          if self._pins[identifier].mode is not GPIOPinMode.ANALOGUE_INPUT:
              raise ValueError(f"Pin {identifier} mode needs to be ANALOGUE_INPUT "
                               f"in order to read the analogue value.")
          return self._console.read(f"Pin {identifier} ADC state [float]", float)
  
      def write_gpio_pin_dac_value(self, identifier: int, scaled_value: float) -> None:
          """Write a scaled analogue value to the DAC on the GPIO pin."""
          # Uno doesn't have any of these.
          raise NotImplementedError
  
      def write_gpio_pin_pwm_value(self, identifier: int, duty_cycle: float) -> None:
          """Write a scaled analogue value to the PWM on the GPIO pin."""
          # Not implemented on derivitive boards yet.
          raise NotImplementedError
  
      def get_led_state(self, identifier: int) -> bool:
          """Get the state of an LED."""
          if identifier != 0:
              raise ValueError("Arduino Uno only has LED 0 (digital pin 13).")
          return self.get_gpio_pin_digital_state(13)
  
      def set_led_state(self, identifier: int, state: bool) -> None:
          """Set the state of an LED."""
          if identifier != 0:
              raise ValueError("Arduino Uno only has LED 0 (digital pin 13)")
          self.write_gpio_pin_digital_state(13, state)
  