Porting Guide - Infineon/pas-co2-sensor GitHub Wiki

Porting the library to a new software development framework and hardware platform entails the implementation of the corresponding PAL classes.

Certainly, for then sensor operation, not all the serial communication (I2C and UART) and sensor readout output (PWM) firmware modules are required. In fact, the sensor hardware interfaces enablement is fixed during its power up, and only one of the serial hardware interfaced can be used at once.

The PWM hardware interface can also be enabled and used in combination with one of the serial interfaces, or standalone.

In practice, normally only one of the three interfaces will be selected. Consequently, only and at least for that one interface, the corresponding framework PAL firmware implementation is required.

In the following sections, some additional explanations and hints are provided:

Framework PAL Implementation

Implement the abstract PAL interface for your framework. The GPIO class and Timer class implementation is mandatory. If the serial API is used, at least one the two serial interfaces is required, either the I2CPAL class or the UARTPAL class.

If the PWM readout output mode is required, the PWM class can be implemented in terms of a GPIO and Timer, or by a more specific and dedicated platform hardware peripheral (hardware timer input, counter, comparator, etc.).

Finally, for the optional logger interface, in the LoggerPAL class an output stream for the debugging text traces needs to be provided.

The Doxygen comments on the "src/pal/pas-co2-xxxx.hpp" describe the required behavior of each function of the PAL Interface.

Consider the existing framework implementations as reference examples for you design: "/src/framework/sample_fmwk/pal". Some of the functions are optional depending on your framework and intended usage of the library.

That is the case, for example, of the init() and deinit() functions (usually found in all PAL interfaces), which take care of the hardware peripherals init/deinitialization. If this is done in your main application (or somewhere else outside the library), there is no need of delegating such initialization to the PAS CO2 Sensor library. The definition of these functions can just be a return with the success return code.

Framework API Wrapper

The framework API wrapper implementation is optional. It is meant to ease the usage of PAS CO2 core library APIs. Mostly the main help is to avoid the creation of the GPIO, Timer, UART, etc. PAL object instances for the developer.

To illustrate this approach, it is easier to evaluate a concrete implementation, as the Arduino Wrapper implementation "src/framework/arduino/wrapper/pas-co2-serial-ino.hpp/cpp":

  1. Adapt the constructor arguments to those used for the GPIO ports and SBus interface creation in the new framework, using the native data types and structures. Hide what can be already defined for that platform, and provide as much abstraction and simplicity as possible.

    For example, the core library PAS CO2 API constructor:

    PASCO2Serial(pasco2::SBus  * const sbus,
                 pasco2::Timer * const timer       = nullptr,
                 pasco2::GPIO  * const interrupt   = nullptr, 
                 pasco2::GPIO  * const protoSelect = nullptr,
                 pasco2::GPIO  * const power3V3    = nullptr,
                 pasco2::GPIO  * const power12V    = nullptr);
    

    is wrapped for Arduino like this:

        PASCO2SerialIno(HardwareSerial * serial, 
                        uint8_t          intPin         = GPIOIno::unusedPin, 
                        uint8_t          protoSelectPin = GPIOIno::unusedPin,
                        uint8_t          power3V3Pin    = GPIOIno::unusedPin,
                        uint8_t          power12VPin    = GPIOIno::unusedPin);
    

    An Arduino developer can now simply pass the HardwareSerial instance and pin number as arguments, and does not need to deal with the (probably unknown) GPIO and SBus classes, neither specify their configuration. The Timer instance is automatically handled by the Arduino constructor and abstracted.

    As for the constructor, the same philosophy can apply to other functions of the public API. In case of Arduino, as a hobbyist and makers environment, clarity and simplicity might prevail over configurability and functionality. Therefore, the wrapper API might further hide, group or eliminate certain functionalities.

    For each ecosystem and framework, any other criteria can be chosen, hopefully matching as well its code conventions, implementation principles and paradigms.

  2. Define structures or macros with the hardware configuration parameters pre-configured for the ported stackable eval kit based hardware platforms. For existing hardware peripheral break-out boards and shields hardware connections with the base MCU evaluation boards, GPIO ports, and UART, I2C and/or PWM instances might be are already fixed.

    Considering again the Arduino framework as example, in "src/frawework/Arduino/wrapper/pas-co2-platf-ino.hpp" some hardware platforms (the ones validated) are already provided:

    extern PlatformIno_t PASCO2_S2Go_XMC2Go; 
    extern PlatformIno_t PASCO2_S2Go_XMC4700;
    

    These can be directly used when creating the corresponding PASCO2 instances. Their definitions can be found in the corresponding .cpp file.

    Additionally, for example, a constructor accepting as argument these predefined configuration structures can make life even easier to the library users.

    A PASCO2 constructor could be provided which accepts PlatformIno_t structure:

    PASCO2SerialIno(PlatformIno_t hwPlatf);
    

    That might simplify beginners life. An Arduino user can just deal with the constructor needing to select a single argument, the pre-configured eval kit based setup he is using. Furthermore, via conditional compiling, we might be able to automatically select the target board and hardware platform.