Intro
=====

Pinmux is a tool that provide configuration files for arena for a target
application in compination of an selected board/mcu.
Goal is to provide an way to develop Software for a MCU boards while not
knowing which board/concrete periphery will be used in the end.

"pinmux" will only create an header and an symbolmap-file. The header is
sufficient to create the platform with the use of libarena.

There are description files for the boards which listen all possible periphery
as well as possible extern devices.
The other part is describing the applications needs; e.g. i want a button, a
graphical display (resulting in SPI-Bus and Chip-Selects)


Basic-Periphery
===============
The board is a simple list of all periphery:

* Type:       Periphery type. Can be intern or extern
                e.g. GPIO, TIMER, CAN, SPI, GDISPLAY
* periphery: "PA9", "SPI1"
* pin:        Pin name on board (not MCU-Pad). Pinmux can proivide some wiring
          information for breadboard construction.
          e.g. "D1", "A0"
* irq:        Which IRQ Handlers have to be implemented when we want to use
          IRQ support on that periphery
          e.g. "EXTI9_5_IRQHandler"
* values:     Currently only used for ADC to mangle ADC host and channel int
          a line. Want to avoid periphery-specific paramaters as general
          parameter.
          e.g.: "values": [ { "value": "Adc2" },
                            { "value": "AdcChannel3" } ]
* priority:   Simple example: There is one LED soldered on your eval board.
          When requiring an LED this will be used before consuming an
          available GPIO and connect the LED externally.
          Lower values are preffered over higher Values.
          Default priority is 5.
* arguments:  Currently only used for ADC to mangle ADC host and channel int
          a line. Want to avoid periphery-specific paramaters as general
          parameter.
          e.g.: "arguments": [ { "argument": "Adc2", "position": "-1" },
                               { "argument": AdcChannel3", "position": "0" } ]
* functions: Alternate functions. An reference can be resolved by looking for
         periphery/GPIO with specific alternate function.


More complex periphery
======================
The most trivial thing is a GPIO-Pin. All GPIO-Pins are available by default.
Some peripheral need multiple things. e.g. an SPI needs SCK/MOSI/MISO lines. So
it "consumes" these three GPIOs.

e.g.:
```
{
   "type": "SPI", "periphery": "SPI1", "name": "Spi1",
   "arguments": [
       { "argument": "eSpiMode500Khz", "position": "1" }
   ],
   "consumes": [
       { "periphery": "PA5",   "name": "SCK" },
       { "periphery": "PA7",   "name": "MOSI" },
       { "periphery": "PA6",   "name": "MISO" }
   ]
},
{
   "type": "EADISPLAY", "name": "EADISPLAY",
   "prefix": "eEaDisplayTypeW162Oled5VSpi",
   "consumes": [
       { "type": "SPI",   "name": "spi", "mode": "shared" },
       { "type": "GPIO",  "name": "CS -> 38" },
       { "type": "GPIO",  "name": "DC -> 39" }
   ]
}
```

A periphery can either consume concrete periphery or a type. if only the type
if given an available periphery is allocated.

## "relation"

Per default the periphery is exclusively needed. But some periphery can be
shared. The "mode" attribute defines this.

* "shared":
Check if the periphery is already available in
             aplication. Otherwise consume it actively from the
             board.
             Both periphery and the consuming part must specify
             the shared mode. E.g. An SPI bus is generally shared.
             But an Device like an Display can specify that it
             wants an SPI bus exclucively for performance reasons.
* "fabricate":The periphery is usually extern and only consumes
             generic periphery. As long as these peripheries
             are available this periphery can be instantiated
             over and over again.
             This parameter tells "pinmux" that it actually has
             to recreate an instance in the board periphery list
             whenever this periphery is used.
             Example: Retain, LED, GDisplay
* "exclusive":Non of the consumed preiphery must be shared.
             Example: PWM; for most cases the frequency of the time
             stays constatnt and is not that important.
             But if you need to change the frequency e.g. for sound
             generation, you dont want to affect other PWM signals.
             Or an SPI-Flash might wants its very own SPI-Bus for
             perfomrance.
* "placeholder": This periphery is not instanciating directly in
            the platforms constructor. The periphery can be
            instantiatet afterwords e.g. depending on
            configuration in EEPROM. Two peripheries may compete
            with same GPIOs.
* "clash"		Internal use only

The Application
===============
The application describes the peripheries you want to use.

e.g.:
```
{
   { "type": "UART", "name": "Debug", "irq": "yes" },
   { "type": "CAN", "name": "can" },
   { "type": "OUTPUT", "name": "Pot0" },
   { "type": "LED", "name": "Heartbeat" },
   { "type": "BUTTON", "name": "User1", "irq": "yes"},
   { "type": "SPI", "name": "Primary", "arguments": "eSpiMode12Mhz" , "prefered": "PA5 PA7 PA6" },
   { "type": "CAN", "name": "Can", "irq": "yes", "prefered": "PA12 PA11" },
   { "type": "GDISPLAY", "name": "nh1", "prefered": "SPI1 PB0 PB1", "class": "CGraphicDisplayNh" },
   { "type": "BUTTON", "name": "Button1", "irq": "yes", "prefered": "PF1" },
}
```

Virtual Periphery name
======================

Fabricated periphery does not have any periphery name which is ok.
unfortunately the "prefered"-feature needs to know exactly which periphery in
the list was used. Therefore every periphery needs an unique periphery name.
if no periphery name is given in the json file for an periphery the regular
name is also set fer periphery name.
e.g. "LD3" is a fixed led on the mcu board while "LED" means fabricated led.

Classes
=======
    * Real periphery
        periphery, type, name, pin, irq, arguments, values, priority
        array of references "consumes"
    * Periphery reference
        periphery, type, name, mode, useIrq, arguments, prefered, arguments, class, *realPeriphery
        wiring

Both periphery and reference have arguments. Take the references arguments when
they exist. If not use the peripherals as default.


Workflow
========
    * A List of real periphery
    * A list of periphery references

At first we have the list of unreloved references, the "app".
    * Iterate
        * Find periphery
            *iterate find consumes
        -> consume
We have to find it first and then to consume it.


Data Model
==========

An application has an list of wanted peripheries represented as references.
An board has an list of availavble peripheries. Each periphery has an list of
consumed peripheries represented as references.

```
   Application             Board
   -----------             -----
   Qlist<CReference>       Qlist<CPeriphery>
   Periphery1 -----------> Periphery1
   Periphery2 -----------> Periphery2
   Periphery3 -----------> Periphery3
                           Periphery4 <------\
                           Periphery5 <----\ |
                           Periphery6 <--\ | |
   Periphery4 -----------> Periphery7    | | |
                              consumes1--/ | |
                              consumes2----/ |
                              consumes3------/
                           Periphery8 <------\
                           Periphery9 <----\ |
                           Periphery10     | |       <fabricate>
   Periphery5 -----------> Periphery10_1 --/ |       fabricated
   Periphery6 -----------> Peripher<10_2 ----/       fabricated
```

Special attributes
==================

arguments
    Each periphery can specify arguments for the constructor of the peripherys
    constructor.
    Example: "arguments": [ { "argument": "eSpiMode500Khz", "position": "1" } ]
    The arguments can be specified by the board definition, by a fabric consume
    reference, or the application definition. An example is the speed of an
    SPI-Bus. The board definition will specify the fastest speed the board
    supports. The consume-periphery of an Display will specify the speed the
    Display supports. The board definition will specify the value that is
    actually tested with the final PCB. The behaviour with shared periphery is
    not defined when multiple peripheries are using the peripheries.

predefined
    Once the hardware layout is fixed and you ordered PCBs you dont want
    "pinmux" to rearrange the periphery just beause some descriptor files
	 changed. Use "predefined" array to fixate the arangement.
	 The "predefined" attribute is a space separeated list of periphery names.
    
Special application attributes
==============================

heartbeat
   If 'heartbeat' is set to anything, the macro "ARENA_USE_LED_HEARTBEAT" will
   be set. It can be used in generic code to let an heartbeat led blink.
   The heartbeat led should have the name "heartbeat".
dbugUart
   name of the uart which should be used for logging.
overlap
   In some cases there are peripheries which compete with e.g. pins or memory
   and there is no way to have both available.
   You may want to decide which one to use during runtime, e.g. by some setting
   in EEPROM configuration.    

Periphery/Reference attributes
==============================

"variant"
      Thsi reference is only resolved/used, when this attributes matches the
      string given via "--variant" when calling "pinmux".
"like"
      An periphery type can act like another type.
      Typical example is "FDCAN". When an application needs CAN, FDCAN can also
      be used.

Tweaks
======

## Feature

"feature" specifies that an consumed periphery has to have an attribute on each
pin. This makes it easy e.g. to find an UART that is usable via ROM-Bootloader. 

The uart could also be specified as different periphery type (e.g. "UART_BL", 
"like": "UART"), but it would not be possible to use non-bootloader-uart for
specific MCUs where its just not possible due to conflicts with other.

"physical led" could specify that we want an LED thats already soldered on the 
board or an UART thats already soldered to STLink. The "predefined" feature will
force to use the according pins but with "feature" you can find them in the 
first place without browsing the data sheet.

The "feature" has to be specified for each board or "remaining". It can be empty
for an board, e.g. when an uart-bootloader is just not available, but still 
wanted to be checked for new/remaining MCUs.

Common Features:
"uart bootloader","usb bootloader", "physical led", "physical button",
"physical uart", "<label>", "VCP", "wkup"

Writers
=======

## dot

the dot writer creates an graphical overview over the peripherals and ther 
consumes.

## pinout

Pinout creates an markdown table for all pins of the MCU.

## Linkerscript

Creates an linkerscript with variables filled like flash- and ram size.

Constructors
============

The parameters for an C++ periphery object is contructed with the consumed
periepheries. The contructors for base periphery (e.g. Timer) can be specified
in the "constructor" arrays in the JSON files.

Example:
```
"constructors": [
   {
      "type": "UART",
      "arguments": [
         { "type": "fixed", "value": "<attribute:configBlock>" },
         { "type": "consuming" }
      ]
   }
]
```

There are two cond of constructor field:
    constructorArgument: the constructor/parameter string for direct instancing
    attributeName: the name for an instance.

Example:
```
{
   "type": "DAC",
   "constructorArgument": "eDac<PeripheryNumber>",
   "attributeName": "m_dac<ReferenceName>"
}
```

Overloading
===========

At least GPIOs can be overloaded. THis means they can be declared in multiple
files. The GPIOs can be completely declared in an MCU-Family-file but will be
"disabled".
In the MCU-Package file the GPIO can be enabled. This avoids redundant
declaration of all SPIOs alternate functions in all MCU-package-files.


Variants
========

To have different board variants for different boards (but same application)
the wanted peripheries have an "variant" field. When running the pinmuxer, the
argument "-t/--varinat" can specifiy the intended variant to be generated.

e.g.
```
"periphery": [
   { "type": "GPIO", "name": "1", "variant": "myVariant"}
 ]
```
When using the cmake integration, the variable ARENA_VARIANT can be used.
e.g.
```
set ( ARENA_VARIANT "debug" )
```
Multiple variants can be specified by using a comma seperated list.
e.g.
```
set ( ARENA_VARIANT "bme680,tmp117,si705x" )
```
Variants are used by arena app-files.


Optional
========

The "optional" attribute are like "variant" attribute but on a lower level. For 
example it can control if the hardware CS-Pin for an SPI is used or not.
Unlike "variant", the options can be specified in the arena app file.
"Optional" is used by arena board files.


Pin Remapping
=============

On small packages, sometimes a pin can be remapped to several GPIOs. So when a
GPIO is used, some other GPIO may not be used any more due to physical
limitations. To realize this, a pseudo periphery is introduced. The GPIOs consume
this and when one GPIO is instantiated, the others are automatically blockes.

Have a look at "stm32f042fx.json" for an reference.

e.g.
```
"periphery": [
   {
      "type": "GPIO",
      "periphery": "PA11",
      "pin": "PA11/#17",
      "initFunction": "__HAL_REMAP_PIN_ENABLE( SYSCFG_CFGR1_PA11_PA12_RMP );",
      "comment": "remap to PA9",
      "consumes": [
         {
            "periphery": "REMAP_PA9_PA11"
         }
      ]
   },
   {
      "type": "GPIO_REMAP",
      "periphery": "REMAP_PA9_PA11",
      "pseudo": "yes"
   }
]
```

Using PA11 will automatically block PA9 because PA9 would also consume
"REMAP_PA9_PA11". Also the command for remaping will
be added to arenaInitFunctions().

Leting the GPIO consume the others directly does not work because there are
circular consumtions.

PA9  -> PA11
PA10 -> PA12

        PA9_PA11 PA10_PA12 BLOCK_PA9_PA12 BLOCK_PA10_PA11
PA9     X                  X
PA10             X                        X
PA11    X                                 X
PA12             X         X

'required' attribute
====================

An reference can defined reuired attributes for each board. When searching for
the periphery, all GPIOs need to have this attribute to be set.

e.g.
```
"periphery": [
      {
         "type": "UART",
         "name": "Debug",
         "required": {
            "stm32g030cx": "uartBootloader"
         }
      }
]
```

The uart has to be used by the ROM bootloader. For boards not explicitly
mentioned in the list, the name "other" has to be used. When a board has to be
excluded, set the required field to an empty string.

```
"periphery": [
      {
         "type": "UART",
         "name": "Debug",
         "required": {
            "stm32g030cx": "",
            "other": "uartBootloader"
         }
      }
]
```

This means all boards except "stm32g030cx" needs an uart with bootloader
capabilities.

```
"periphery": [
      {
         "type": "LED",
         "name": "User",
         "required": {
            "st_nucleo_f303": "physicalLED"
         }
      }
]
```

## sub-periphery

The required feature can also be specified for sub-periphery.

e.g.
```
"periphery": [
   {
      "type": "DEBUG",
      "name": "Debug",
      "required": {
         "other": "uart:uartBootloader"
      }
   }
]
```

'optional' attribute
====================

Some periphery may have optional components. For example when using SPI-Bus, the
periphery can use an hardware-controlled CS-signal (NSS). Optionaly an custom
GPIO can be used and be controlled by software.

```
"periphery": [
   {
      "type": "SPI",
      "consumes": [
         {
            "periphery": "PB3",
            "name": "SCK"
         },
         {
            "periphery": "PB5",
            "name": "MOSI"
         },
         {
            "periphery": "PB4",
            "name": "MISO"
         },
         {
            "periphery": "PB0",
            "name": "NSS",
            "optional": "use_spi_nss"
         }
      ],
   }
]
```

When the NSS-Signal shall be used, the option has to be specified in the
application file.

```
{
   "name": "mito",
   "options": [ "use_spi_nss" ]
}
```

The option has also be integrated in the framework file for the constructors.

```
{
   "type": "SPI",
   "implementation": [
      "const SSpiConfig spiConfig_<PeripheryName>",
      "{",
      [...]
      "   .eGpioPeripheralMosi = eGpioPeripheral<periphery:2>,",
      "   .eGpioPinMosi = eGpioPin<pin:2>,",
          "<option:use_spi_nss>",
      "};"
   ],
   "implementation_use_spi_nss": [
      "   .eGpioPeripheralNss = eGpioPeripheral<periphery:3>,",
      "   .eGpioPinNss = eGpioPin<pin:3>,"
   ],
}
```

In the framework itself the automatically generated defines can be used. For all
activated options, an macro with format "<framework>_<option>" will be defined
(uppercase). e.g. for "use_spi_nss" an macro "BIWAK_USE_SPI_NSS" will be
defined.

"Optional" attributes can also be specified in the app file to optionaly use periphery.
This was called "variants" in the past.

Examples for "option":

* SPI hardware CS
* optional usage of UART on the Debug-connector (debug periphery)
* Only support specific I2C sensors on a specific build

