Navigation

cube.io.pwm

Inputs

Name

Type

Title

Mandatory

Description

arm

core.type.bool

Arming signal

True

CUBE IO PWM output arming signal

ch1

core.type.f64

Channel 1 input

False

None

ch2

core.type.f64

Channel 2 input

False

None

ch3

core.type.f64

Channel 3 input

False

None

ch4

core.type.f64

Channel 4 input

False

None

ch5

core.type.f64

Channel 5 input

False

None

ch6

core.type.f64

Channel 6 input

False

None

ch7

core.type.f64

Channel 7 input

False

None

ch8

core.type.f64

Channel 8 input

False

None

Outputs

Function has no outputs

Parameters

Name

Type

Title

Mandatory

Default value

Description

ch1_min

core.type.u32

Channel 1 minimum PWM

False

700

None

ch2_min

core.type.u32

Channel 2 minimum PWM

False

700

None

ch3_min

core.type.u32

Channel 3 minimum PWM

False

700

None

ch4_min

core.type.u32

Channel 4 minimum PWM

False

700

None

ch5_min

core.type.u32

Channel 5 minimum PWM

False

700

None

ch6_min

core.type.u32

Channel 6 minimum PWM

False

700

None

ch7_min

core.type.u32

Channel 7 minimum PWM

False

700

None

ch8_min

core.type.u32

Channel 8 minimum PWM

False

700

None

ch1_max

core.type.u32

Channel 1 maximum PWM

False

2200

None

ch2_max

core.type.u32

Channel 2 maximum PWM

False

2200

None

ch3_max

core.type.u32

Channel 3 maximum PWM

False

2200

None

ch4_max

core.type.u32

Channel 4 maximum PWM

False

2200

None

ch5_max

core.type.u32

Channel 5 maximum PWM

False

2200

None

ch6_max

core.type.u32

Channel 6 maximum PWM

False

2200

None

ch7_max

core.type.u32

Channel 7 maximum PWM

False

2200

None

ch8_max

core.type.u32

Channel 8 maximum PWM

False

2200

None

ch1_bipolar

core.type.bool

Channel 1 bipolar mode enable

False

FALSE

None

ch2_bipolar

core.type.bool

Channel 2 bipolar mode enable

False

FALSE

None

ch3_bipolar

core.type.bool

Channel 3 bipolar mode enable

False

FALSE

None

ch4_bipolar

core.type.bool

Channel 4 bipolar mode enable

False

FALSE

None

ch5_bipolar

core.type.bool

Channel 5 bipolar mode enable

False

FALSE

None

ch6_bipolar

core.type.bool

Channel 6 bipolar mode enable

False

FALSE

None

ch7_bipolar

core.type.bool

Channel 7 bipolar mode enable

False

FALSE

None

ch8_bipolar

core.type.bool

Channel 8 bipolar mode enable

False

FALSE

None

State variables

Name

Type

Title

Description

decimation_counter

core.type.u32

Decimation counter

None

inited

core.type.bool

FIXME

None

arm_passed

core.type.bool

Arm passed event

None

disarm_passed

core.type.bool

Disarm passed event

None

Usage XML code snippet

cube_io_pwm snippet for FLOW configuration file
<f name="pwm" by_spec="cube.io.pwm">
    <in alias="arm">some_block_1/output</in>
    <in alias="ch1">some_block_2/output</in>   <!-- optional -->
    <in alias="ch2">some_block_3/output</in>   <!-- optional -->
    <in alias="ch3">some_block_4/output</in>   <!-- optional -->
    <in alias="ch4">some_block_5/output</in>   <!-- optional -->
    <in alias="ch5">some_block_6/output</in>   <!-- optional -->
    <in alias="ch6">some_block_7/output</in>   <!-- optional -->
    <in alias="ch7">some_block_8/output</in>   <!-- optional -->
    <in alias="ch8">some_block_9/output</in>   <!-- optional -->
    <param alias="ch1_min">0.0</param>   <!-- optional -->
    <param alias="ch2_min">0.0</param>   <!-- optional -->
    <param alias="ch3_min">0.0</param>   <!-- optional -->
    <param alias="ch4_min">0.0</param>   <!-- optional -->
    <param alias="ch5_min">0.0</param>   <!-- optional -->
    <param alias="ch6_min">0.0</param>   <!-- optional -->
    <param alias="ch7_min">0.0</param>   <!-- optional -->
    <param alias="ch8_min">0.0</param>   <!-- optional -->
    <param alias="ch1_max">0.0</param>   <!-- optional -->
    <param alias="ch2_max">0.0</param>   <!-- optional -->
    <param alias="ch3_max">0.0</param>   <!-- optional -->
    <param alias="ch4_max">0.0</param>   <!-- optional -->
    <param alias="ch5_max">0.0</param>   <!-- optional -->
    <param alias="ch6_max">0.0</param>   <!-- optional -->
    <param alias="ch7_max">0.0</param>   <!-- optional -->
    <param alias="ch8_max">0.0</param>   <!-- optional -->
    <param alias="ch1_bipolar">0.0</param>   <!-- optional -->
    <param alias="ch2_bipolar">0.0</param>   <!-- optional -->
    <param alias="ch3_bipolar">0.0</param>   <!-- optional -->
    <param alias="ch4_bipolar">0.0</param>   <!-- optional -->
    <param alias="ch5_bipolar">0.0</param>   <!-- optional -->
    <param alias="ch6_bipolar">0.0</param>   <!-- optional -->
    <param alias="ch7_bipolar">0.0</param>   <!-- optional -->
    <param alias="ch8_bipolar">0.0</param>   <!-- optional -->
</f>

Function’s artifacts

declaration.py
from fspeclib import *

Function(
    name='cube.io.pwm',
    title=LocalizedString(
        en='io'
    ),
    has_pre_exec_init_call=True,
    parameters=[
        Parameter(
            name='ch1_min',
            title='Channel 1 minimum PWM',
            value_type='core.type.u32',
            default=700,
        ),
        Parameter(
            name='ch2_min',
            title='Channel 2 minimum PWM',
            value_type='core.type.u32',
            default=700,
        ),
        Parameter(
            name='ch3_min',
            title='Channel 3 minimum PWM',
            value_type='core.type.u32',
            default=700,
        ),
        Parameter(
            name='ch4_min',
            title='Channel 4 minimum PWM',
            value_type='core.type.u32',
            default=700,
        ),
        Parameter(
            name='ch5_min',
            title='Channel 5 minimum PWM',
            value_type='core.type.u32',
            default=700,
        ),
        Parameter(
            name='ch6_min',
            title='Channel 6 minimum PWM',
            value_type='core.type.u32',
            default=700,
        ),
        Parameter(
            name='ch7_min',
            title='Channel 7 minimum PWM',
            value_type='core.type.u32',
            default=700,
        ),
        Parameter(
            name='ch8_min',
            title='Channel  8 minimum PWM',
            value_type='core.type.u32',
            default=700,
        ),
        Parameter(
            name='ch1_max',
            title='Channel 1 maximum PWM',
            value_type='core.type.u32',
            default=2200,
        ),
        Parameter(
            name='ch2_max',
            title='Channel 2 maximum PWM',
            value_type='core.type.u32',
            default=2200,
        ),
        Parameter(
            name='ch3_max',
            title='Channel 3 maximum PWM',
            value_type='core.type.u32',
            default=2200,
        ),
        Parameter(
            name='ch4_max',
            title='Channel 4 maximum PWM',
            value_type='core.type.u32',
            default=2200,
        ),
        Parameter(
            name='ch5_max',
            title='Channel 5 maximum PWM',
            value_type='core.type.u32',
            default=2200,
        ),
        Parameter(
            name='ch6_max',
            title='Channel 6 maximum PWM',
            value_type='core.type.u32',
            default=2200,
        ),
        Parameter(
            name='ch7_max',
            title='Channel 7 maximum PWM',
            value_type='core.type.u32',
            default=2200,
        ),
        Parameter(
            name='ch8_max',
            title='Channel 8 maximum PWM',
            value_type='core.type.u32',
            default=2200,
        ),
        Parameter(
            name='ch1_bipolar',
            title='Channel 1 bipolar mode enable',
            value_type='core.type.bool',
            default='FALSE',
        ),
        Parameter(
            name='ch2_bipolar',
            title='Channel 2 bipolar mode enable',
            value_type='core.type.bool',
            default='FALSE',
        ),
        Parameter(
            name='ch3_bipolar',
            title='Channel 3 bipolar mode enable',
            value_type='core.type.bool',
            default='FALSE',
        ),
        Parameter(
            name='ch4_bipolar',
            title='Channel 4 bipolar mode enable',
            value_type='core.type.bool',
            default='FALSE',
        ),
        Parameter(
            name='ch5_bipolar',
            title='Channel 5 bipolar mode enable',
            value_type='core.type.bool',
            default='FALSE',
        ),
        Parameter(
            name='ch6_bipolar',
            title='Channel 6 bipolar mode enable',
            value_type='core.type.bool',
            default='FALSE',
        ),
        Parameter(
            name='ch7_bipolar',
            title='Channel 7 bipolar mode enable',
            value_type='core.type.bool',
            default='FALSE',
        ),
        Parameter(
            name='ch8_bipolar',
            title='Channel 8 bipolar mode enable',
            value_type='core.type.bool',
            default='FALSE',
        ),
    ],
    inputs=[
        Input(
            name='arm',
            title='Arming signal',
            description='CUBE IO PWM output arming signal',
            value_type='core.type.bool'
        ),
        Input(
            name='ch1',
            title='Channel 1 input',
            value_type='core.type.f64',
            mandatory=False
        ),
        Input(
            name='ch2',
            title='Channel 2 input',
            value_type='core.type.f64',
            mandatory=False
        ),
        Input(
            name='ch3',
            title='Channel 3 input',
            value_type='core.type.f64',
            mandatory=False
        ),
        Input(
            name='ch4',
            title='Channel 4 input',
            value_type='core.type.f64',
            mandatory=False
        ),
        Input(
            name='ch5',
            title='Channel 5 input',
            value_type='core.type.f64',
            mandatory=False
        ),
        Input(
            name='ch6',
            title='Channel 6 input',
            value_type='core.type.f64',
            mandatory=False
        ),
        Input(
            name='ch7',
            title='Channel 7 input',
            value_type='core.type.f64',
            mandatory=False
        ),
        Input(
            name='ch8',
            title='Channel 8 input',
            value_type='core.type.f64',
            mandatory=False
        ),
    ],
    outputs=[],
    state=[
        Variable(
            name='decimation_counter',
            title='Decimation counter',
            value_type='core.type.u32'
        ),
        Variable(
            name='inited',
            title='FIXME',
            value_type='core.type.bool'
        ),
        Variable(
            name='arm_passed',
            title='Arm passed event',
            value_type='core.type.bool'
        ),
        Variable(
            name='disarm_passed',
            title='Disarm passed event',
            value_type='core.type.bool'
        ),
    ],
    parameter_constraints=[],
)
cube_io_pwm_exec.c
#include "cube_io_pwm.h"
#include "board.h"

fspec_rv_t cube_io_pwm_pre_exec_init(
        const cube_io_pwm_optional_inputs_flags_t *input_flags,
        const cube_io_pwm_params_t *p,
        cube_io_pwm_state_t *state
) {

    cubeio_set_freq(cubeio, 0xFFFF, 400);
    cubeio_set_range(cubeio, CUBEIO_PWM, 0, p->ch1_bipolar ? CUBEIO_CHANNEL_BIPOLAR : CUBEIO_CHANNEL_UNIPOLAR, p->ch1_min, p->ch1_max);
    cubeio_set_range(cubeio, CUBEIO_PWM, 1, p->ch2_bipolar ? CUBEIO_CHANNEL_BIPOLAR : CUBEIO_CHANNEL_UNIPOLAR, p->ch2_min, p->ch2_max);
    cubeio_set_range(cubeio, CUBEIO_PWM, 2, p->ch3_bipolar ? CUBEIO_CHANNEL_BIPOLAR : CUBEIO_CHANNEL_UNIPOLAR, p->ch3_min, p->ch3_max);
    cubeio_set_range(cubeio, CUBEIO_PWM, 3, p->ch4_bipolar ? CUBEIO_CHANNEL_BIPOLAR : CUBEIO_CHANNEL_UNIPOLAR, p->ch4_min, p->ch4_max);
    cubeio_set_range(cubeio, CUBEIO_PWM, 4, p->ch5_bipolar ? CUBEIO_CHANNEL_BIPOLAR : CUBEIO_CHANNEL_UNIPOLAR, p->ch5_min, p->ch5_max);
    cubeio_set_range(cubeio, CUBEIO_PWM, 5, p->ch6_bipolar ? CUBEIO_CHANNEL_BIPOLAR : CUBEIO_CHANNEL_UNIPOLAR, p->ch6_min, p->ch6_max);
    cubeio_set_range(cubeio, CUBEIO_PWM, 6, p->ch7_bipolar ? CUBEIO_CHANNEL_BIPOLAR : CUBEIO_CHANNEL_UNIPOLAR, p->ch7_min, p->ch7_max);
    cubeio_set_range(cubeio, CUBEIO_PWM, 7, p->ch8_bipolar ? CUBEIO_CHANNEL_BIPOLAR : CUBEIO_CHANNEL_UNIPOLAR, p->ch8_min, p->ch8_max);
    state->inited = TRUE;

    return fspec_rv_ok;
}

void cube_io_pwm_exec(const cube_io_pwm_inputs_t *i, const cube_io_pwm_params_t *p, cube_io_pwm_state_t *state){
    double pwm[16];

    gpio_set(&gpio_fmu_pwm[1]);

    if(i->arm && !state->arm_passed) {
        cubeio_force_safety_off(cubeio);
        state->arm_passed = TRUE;
        state->disarm_passed = FALSE;
    } else if (!i->arm && !state->disarm_passed){
        cubeio_force_safety_on(cubeio);
        state->arm_passed = FALSE;
        state->disarm_passed = TRUE;
    }

    pwm[0] = i->ch1;
    pwm[1] = i->ch2;
    pwm[2] = i->ch3;
    pwm[3] = i->ch4;
    pwm[4] = i->ch5;
    pwm[5] = i->ch6;
    pwm[6] = i->ch7;
    pwm[7] = i->ch8;

    cubeio_set_pwm(cubeio, 8, pwm);

    // For debug reset pin in CubeIO thread
    // gpio_reset(&gpio_fmu_pwm[1]);
}
cube_io_pwm_set_params.c
#include "cube_io_pwm.h"
#include "conv.h"

#include <string.h>

#include "error.h"

fspec_rv_t cube_io_pwm_set_params(cube_io_pwm_params_t *params, const func_param_t *param_pairs, int initial_call)
{
    // Get parameters
    cube_io_pwm_params_t p = *params;

    cube_io_pwm_params_flags_t flags;
    memset(&flags, 0, sizeof(flags));

    int violation_count = 0;
    conv_rv_t crv = conv_rv_ok;

    // Parse parameters
    for (int i = 0; param_pairs[i].alias != NULL; i++) {
        if (strcmp(param_pairs[i].alias, "ch1_min") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch1_min)) == conv_rv_ok) {
                flags.changed_param_ch1_min = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch2_min") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch2_min)) == conv_rv_ok) {
                flags.changed_param_ch2_min = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch3_min") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch3_min)) == conv_rv_ok) {
                flags.changed_param_ch3_min = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch4_min") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch4_min)) == conv_rv_ok) {
                flags.changed_param_ch4_min = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch5_min") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch5_min)) == conv_rv_ok) {
                flags.changed_param_ch5_min = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch6_min") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch6_min)) == conv_rv_ok) {
                flags.changed_param_ch6_min = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch7_min") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch7_min)) == conv_rv_ok) {
                flags.changed_param_ch7_min = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch8_min") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch8_min)) == conv_rv_ok) {
                flags.changed_param_ch8_min = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch1_max") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch1_max)) == conv_rv_ok) {
                flags.changed_param_ch1_max = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch2_max") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch2_max)) == conv_rv_ok) {
                flags.changed_param_ch2_max = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch3_max") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch3_max)) == conv_rv_ok) {
                flags.changed_param_ch3_max = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch4_max") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch4_max)) == conv_rv_ok) {
                flags.changed_param_ch4_max = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch5_max") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch5_max)) == conv_rv_ok) {
                flags.changed_param_ch5_max = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch6_max") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch6_max)) == conv_rv_ok) {
                flags.changed_param_ch6_max = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch7_max") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch7_max)) == conv_rv_ok) {
                flags.changed_param_ch7_max = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch8_max") == 0) {
            if ((crv = conv_str_uint32(param_pairs[i].value, &p.ch8_max)) == conv_rv_ok) {
                flags.changed_param_ch8_max = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch1_bipolar") == 0) {
            if ((crv = conv_str_bool(param_pairs[i].value, &p.ch1_bipolar)) == conv_rv_ok) {
                flags.changed_param_ch1_bipolar = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch2_bipolar") == 0) {
            if ((crv = conv_str_bool(param_pairs[i].value, &p.ch2_bipolar)) == conv_rv_ok) {
                flags.changed_param_ch2_bipolar = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch3_bipolar") == 0) {
            if ((crv = conv_str_bool(param_pairs[i].value, &p.ch3_bipolar)) == conv_rv_ok) {
                flags.changed_param_ch3_bipolar = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch4_bipolar") == 0) {
            if ((crv = conv_str_bool(param_pairs[i].value, &p.ch4_bipolar)) == conv_rv_ok) {
                flags.changed_param_ch4_bipolar = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch5_bipolar") == 0) {
            if ((crv = conv_str_bool(param_pairs[i].value, &p.ch5_bipolar)) == conv_rv_ok) {
                flags.changed_param_ch5_bipolar = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch6_bipolar") == 0) {
            if ((crv = conv_str_bool(param_pairs[i].value, &p.ch6_bipolar)) == conv_rv_ok) {
                flags.changed_param_ch6_bipolar = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch7_bipolar") == 0) {
            if ((crv = conv_str_bool(param_pairs[i].value, &p.ch7_bipolar)) == conv_rv_ok) {
                flags.changed_param_ch7_bipolar = 1;
            }
        } else if (strcmp(param_pairs[i].alias, "ch8_bipolar") == 0) {
            if ((crv = conv_str_bool(param_pairs[i].value, &p.ch8_bipolar)) == conv_rv_ok) {
                flags.changed_param_ch8_bipolar = 1;
            }
        } else {
            error("failed unsupported parameter '%s'", param_pairs[i].alias);
            violation_count ++;
        }

        if (crv != conv_rv_ok) {
            error("Parameter '%s' format error (%s)", param_pairs[i].alias, param_pairs[i].value);
            violation_count++;
        }
    }

    if (initial_call) {
        // Set default value for non mandatory parameters which are not set
        if (!flags.changed_param_ch1_min) {
            p.ch1_min = 700;
            flags.changed_param_ch1_min = 1;
        }
        if (!flags.changed_param_ch2_min) {
            p.ch2_min = 700;
            flags.changed_param_ch2_min = 1;
        }
        if (!flags.changed_param_ch3_min) {
            p.ch3_min = 700;
            flags.changed_param_ch3_min = 1;
        }
        if (!flags.changed_param_ch4_min) {
            p.ch4_min = 700;
            flags.changed_param_ch4_min = 1;
        }
        if (!flags.changed_param_ch5_min) {
            p.ch5_min = 700;
            flags.changed_param_ch5_min = 1;
        }
        if (!flags.changed_param_ch6_min) {
            p.ch6_min = 700;
            flags.changed_param_ch6_min = 1;
        }
        if (!flags.changed_param_ch7_min) {
            p.ch7_min = 700;
            flags.changed_param_ch7_min = 1;
        }
        if (!flags.changed_param_ch8_min) {
            p.ch8_min = 700;
            flags.changed_param_ch8_min = 1;
        }
        if (!flags.changed_param_ch1_max) {
            p.ch1_max = 2200;
            flags.changed_param_ch1_max = 1;
        }
        if (!flags.changed_param_ch2_max) {
            p.ch2_max = 2200;
            flags.changed_param_ch2_max = 1;
        }
        if (!flags.changed_param_ch3_max) {
            p.ch3_max = 2200;
            flags.changed_param_ch3_max = 1;
        }
        if (!flags.changed_param_ch4_max) {
            p.ch4_max = 2200;
            flags.changed_param_ch4_max = 1;
        }
        if (!flags.changed_param_ch5_max) {
            p.ch5_max = 2200;
            flags.changed_param_ch5_max = 1;
        }
        if (!flags.changed_param_ch6_max) {
            p.ch6_max = 2200;
            flags.changed_param_ch6_max = 1;
        }
        if (!flags.changed_param_ch7_max) {
            p.ch7_max = 2200;
            flags.changed_param_ch7_max = 1;
        }
        if (!flags.changed_param_ch8_max) {
            p.ch8_max = 2200;
            flags.changed_param_ch8_max = 1;
        }
        if (!flags.changed_param_ch1_bipolar) {
            p.ch1_bipolar = FALSE;
            flags.changed_param_ch1_bipolar = 1;
        }
        if (!flags.changed_param_ch2_bipolar) {
            p.ch2_bipolar = FALSE;
            flags.changed_param_ch2_bipolar = 1;
        }
        if (!flags.changed_param_ch3_bipolar) {
            p.ch3_bipolar = FALSE;
            flags.changed_param_ch3_bipolar = 1;
        }
        if (!flags.changed_param_ch4_bipolar) {
            p.ch4_bipolar = FALSE;
            flags.changed_param_ch4_bipolar = 1;
        }
        if (!flags.changed_param_ch5_bipolar) {
            p.ch5_bipolar = FALSE;
            flags.changed_param_ch5_bipolar = 1;
        }
        if (!flags.changed_param_ch6_bipolar) {
            p.ch6_bipolar = FALSE;
            flags.changed_param_ch6_bipolar = 1;
        }
        if (!flags.changed_param_ch7_bipolar) {
            p.ch7_bipolar = FALSE;
            flags.changed_param_ch7_bipolar = 1;
        }
        if (!flags.changed_param_ch8_bipolar) {
            p.ch8_bipolar = FALSE;
            flags.changed_param_ch8_bipolar = 1;
        }
    }

    if (violation_count > 0) {
        return fspec_rv_inval_param;
    }

    // Set parameters
    *params = p;

    return fspec_rv_ok;
}
cube_io_pwm.h
/**
 *  Automatically-generated file. Do not edit!
 */

#ifndef FSPEC_CUBE_IO_PWM_H
#define FSPEC_CUBE_IO_PWM_H

#include <stdint.h>
#include <eswb/types.h>

#include "function.h"

/* Include declaration of dependency types */
#include "core_type_bool.h"
#include "core_type_f64.h"
#include "core_type_u32.h"

/**
 * @brief Parameters of `cube.io.pwm` function
 */
typedef struct cube_io_pwm_params_{
    core_type_u32_t ch1_min;  /// Channel 1 minimum PWM
    core_type_u32_t ch2_min;  /// Channel 2 minimum PWM
    core_type_u32_t ch3_min;  /// Channel 3 minimum PWM
    core_type_u32_t ch4_min;  /// Channel 4 minimum PWM
    core_type_u32_t ch5_min;  /// Channel 5 minimum PWM
    core_type_u32_t ch6_min;  /// Channel 6 minimum PWM
    core_type_u32_t ch7_min;  /// Channel 7 minimum PWM
    core_type_u32_t ch8_min;  /// Channel  8 minimum PWM
    core_type_u32_t ch1_max;  /// Channel 1 maximum PWM
    core_type_u32_t ch2_max;  /// Channel 2 maximum PWM
    core_type_u32_t ch3_max;  /// Channel 3 maximum PWM
    core_type_u32_t ch4_max;  /// Channel 4 maximum PWM
    core_type_u32_t ch5_max;  /// Channel 5 maximum PWM
    core_type_u32_t ch6_max;  /// Channel 6 maximum PWM
    core_type_u32_t ch7_max;  /// Channel 7 maximum PWM
    core_type_u32_t ch8_max;  /// Channel 8 maximum PWM
    core_type_bool_t ch1_bipolar;  /// Channel 1 bipolar mode enable
    core_type_bool_t ch2_bipolar;  /// Channel 2 bipolar mode enable
    core_type_bool_t ch3_bipolar;  /// Channel 3 bipolar mode enable
    core_type_bool_t ch4_bipolar;  /// Channel 4 bipolar mode enable
    core_type_bool_t ch5_bipolar;  /// Channel 5 bipolar mode enable
    core_type_bool_t ch6_bipolar;  /// Channel 6 bipolar mode enable
    core_type_bool_t ch7_bipolar;  /// Channel 7 bipolar mode enable
    core_type_bool_t ch8_bipolar;  /// Channel 8 bipolar mode enable
} cube_io_pwm_params_t;

/**
 * @brief Optional inputs connectivity flags structure for `cube.io.pwm` function
 */
typedef struct {
    uint32_t ch1:1;
    uint32_t ch2:1;
    uint32_t ch3:1;
    uint32_t ch4:1;
    uint32_t ch5:1;
    uint32_t ch6:1;
    uint32_t ch7:1;
    uint32_t ch8:1;
} cube_io_pwm_optional_inputs_flags_t;

/**
 * @brief Inputs of `cube.io.pwm` function
 */
typedef struct cube_io_pwm_inputs_ {
    core_type_bool_t arm;  /// Arming signal
    core_type_f64_t ch1;  /// Channel 1 input
    core_type_f64_t ch2;  /// Channel 2 input
    core_type_f64_t ch3;  /// Channel 3 input
    core_type_f64_t ch4;  /// Channel 4 input
    core_type_f64_t ch5;  /// Channel 5 input
    core_type_f64_t ch6;  /// Channel 6 input
    core_type_f64_t ch7;  /// Channel 7 input
    core_type_f64_t ch8;  /// Channel 8 input

    cube_io_pwm_optional_inputs_flags_t optional_inputs_flags;
} cube_io_pwm_inputs_t;

/**
 * @brief State variables of `cube.io.pwm` function
 */
typedef struct cube_io_pwm_state_ {
    core_type_u32_t decimation_counter;  /// Decimation counter
    core_type_bool_t inited;  /// FIXME
    core_type_bool_t arm_passed;  /// Arm passed event
    core_type_bool_t disarm_passed;  /// Disarm passed event
} cube_io_pwm_state_t;

/**
 * @brief Parameter flags of `cube.io.pwm` function
 */
typedef struct cube_io_pwm_params_flags_ {
    uint64_t changed_param_ch1_min:1;
    uint64_t changed_param_ch2_min:1;
    uint64_t changed_param_ch3_min:1;
    uint64_t changed_param_ch4_min:1;
    uint64_t changed_param_ch5_min:1;
    uint64_t changed_param_ch6_min:1;
    uint64_t changed_param_ch7_min:1;
    uint64_t changed_param_ch8_min:1;
    uint64_t changed_param_ch1_max:1;
    uint64_t changed_param_ch2_max:1;
    uint64_t changed_param_ch3_max:1;
    uint64_t changed_param_ch4_max:1;
    uint64_t changed_param_ch5_max:1;
    uint64_t changed_param_ch6_max:1;
    uint64_t changed_param_ch7_max:1;
    uint64_t changed_param_ch8_max:1;
    uint64_t changed_param_ch1_bipolar:1;
    uint64_t changed_param_ch2_bipolar:1;
    uint64_t changed_param_ch3_bipolar:1;
    uint64_t changed_param_ch4_bipolar:1;
    uint64_t changed_param_ch5_bipolar:1;
    uint64_t changed_param_ch6_bipolar:1;
    uint64_t changed_param_ch7_bipolar:1;
    uint64_t changed_param_ch8_bipolar:1;
} cube_io_pwm_params_flags_t;

typedef struct cube_io_pwm_eswb_descriptors_ {
    eswb_topic_descr_t in_arm;
    eswb_topic_descr_t in_ch1;
    eswb_topic_descr_t in_ch2;
    eswb_topic_descr_t in_ch3;
    eswb_topic_descr_t in_ch4;
    eswb_topic_descr_t in_ch5;
    eswb_topic_descr_t in_ch6;
    eswb_topic_descr_t in_ch7;
    eswb_topic_descr_t in_ch8;
} cube_io_pwm_eswb_descriptors_t;

typedef struct cube_io_pwm_interface_ {
    cube_io_pwm_inputs_t i;
    cube_io_pwm_params_t p;
    cube_io_pwm_state_t state;
    cube_io_pwm_eswb_descriptors_t eswb_descriptors;
} cube_io_pwm_interface_t;

fspec_rv_t cube_io_pwm_set_params(cube_io_pwm_params_t *params, const func_param_t *param_pairs, int initial_call);

fspec_rv_t cube_io_pwm_pre_exec_init(
    const cube_io_pwm_optional_inputs_flags_t *input_flags,
    const cube_io_pwm_params_t *p,
    cube_io_pwm_state_t *state
);
void cube_io_pwm_exec(const cube_io_pwm_inputs_t *i, const cube_io_pwm_params_t *p, cube_io_pwm_state_t *state);

#endif // FSPEC_CUBE_IO_PWM_H
cube_io_pwm_spec.c
/**
 *  Automatically-generated file. Do not edit!
 */

#include "cube_io_pwm.h"
#include <eswb/types.h>

static const param_spec_t param_ch1_min = {
    .name = "ch1_min",
    .default_value = "0.0",
    .annotation = "Channel 1 minimum PWM",
    .flags = 0
};

static const param_spec_t param_ch2_min = {
    .name = "ch2_min",
    .default_value = "0.0",
    .annotation = "Channel 2 minimum PWM",
    .flags = 0
};

static const param_spec_t param_ch3_min = {
    .name = "ch3_min",
    .default_value = "0.0",
    .annotation = "Channel 3 minimum PWM",
    .flags = 0
};

static const param_spec_t param_ch4_min = {
    .name = "ch4_min",
    .default_value = "0.0",
    .annotation = "Channel 4 minimum PWM",
    .flags = 0
};

static const param_spec_t param_ch5_min = {
    .name = "ch5_min",
    .default_value = "0.0",
    .annotation = "Channel 5 minimum PWM",
    .flags = 0
};

static const param_spec_t param_ch6_min = {
    .name = "ch6_min",
    .default_value = "0.0",
    .annotation = "Channel 6 minimum PWM",
    .flags = 0
};

static const param_spec_t param_ch7_min = {
    .name = "ch7_min",
    .default_value = "0.0",
    .annotation = "Channel 7 minimum PWM",
    .flags = 0
};

static const param_spec_t param_ch8_min = {
    .name = "ch8_min",
    .default_value = "0.0",
    .annotation = "Channel  8 minimum PWM",
    .flags = 0
};

static const param_spec_t param_ch1_max = {
    .name = "ch1_max",
    .default_value = "0.0",
    .annotation = "Channel 1 maximum PWM",
    .flags = 0
};

static const param_spec_t param_ch2_max = {
    .name = "ch2_max",
    .default_value = "0.0",
    .annotation = "Channel 2 maximum PWM",
    .flags = 0
};

static const param_spec_t param_ch3_max = {
    .name = "ch3_max",
    .default_value = "0.0",
    .annotation = "Channel 3 maximum PWM",
    .flags = 0
};

static const param_spec_t param_ch4_max = {
    .name = "ch4_max",
    .default_value = "0.0",
    .annotation = "Channel 4 maximum PWM",
    .flags = 0
};

static const param_spec_t param_ch5_max = {
    .name = "ch5_max",
    .default_value = "0.0",
    .annotation = "Channel 5 maximum PWM",
    .flags = 0
};

static const param_spec_t param_ch6_max = {
    .name = "ch6_max",
    .default_value = "0.0",
    .annotation = "Channel 6 maximum PWM",
    .flags = 0
};

static const param_spec_t param_ch7_max = {
    .name = "ch7_max",
    .default_value = "0.0",
    .annotation = "Channel 7 maximum PWM",
    .flags = 0
};

static const param_spec_t param_ch8_max = {
    .name = "ch8_max",
    .default_value = "0.0",
    .annotation = "Channel 8 maximum PWM",
    .flags = 0
};

static const param_spec_t param_ch1_bipolar = {
    .name = "ch1_bipolar",
    .default_value = "0.0",
    .annotation = "Channel 1 bipolar mode enable",
    .flags = 0
};

static const param_spec_t param_ch2_bipolar = {
    .name = "ch2_bipolar",
    .default_value = "0.0",
    .annotation = "Channel 2 bipolar mode enable",
    .flags = 0
};

static const param_spec_t param_ch3_bipolar = {
    .name = "ch3_bipolar",
    .default_value = "0.0",
    .annotation = "Channel 3 bipolar mode enable",
    .flags = 0
};

static const param_spec_t param_ch4_bipolar = {
    .name = "ch4_bipolar",
    .default_value = "0.0",
    .annotation = "Channel 4 bipolar mode enable",
    .flags = 0
};

static const param_spec_t param_ch5_bipolar = {
    .name = "ch5_bipolar",
    .default_value = "0.0",
    .annotation = "Channel 5 bipolar mode enable",
    .flags = 0
};

static const param_spec_t param_ch6_bipolar = {
    .name = "ch6_bipolar",
    .default_value = "0.0",
    .annotation = "Channel 6 bipolar mode enable",
    .flags = 0
};

static const param_spec_t param_ch7_bipolar = {
    .name = "ch7_bipolar",
    .default_value = "0.0",
    .annotation = "Channel 7 bipolar mode enable",
    .flags = 0
};

static const param_spec_t param_ch8_bipolar = {
    .name = "ch8_bipolar",
    .default_value = "0.0",
    .annotation = "Channel 8 bipolar mode enable",
    .flags = 0
};

static const param_spec_t *params[25] = {
    &param_ch1_min,
    &param_ch2_min,
    &param_ch3_min,
    &param_ch4_min,
    &param_ch5_min,
    &param_ch6_min,
    &param_ch7_min,
    &param_ch8_min,
    &param_ch1_max,
    &param_ch2_max,
    &param_ch3_max,
    &param_ch4_max,
    &param_ch5_max,
    &param_ch6_max,
    &param_ch7_max,
    &param_ch8_max,
    &param_ch1_bipolar,
    &param_ch2_bipolar,
    &param_ch3_bipolar,
    &param_ch4_bipolar,
    &param_ch5_bipolar,
    &param_ch6_bipolar,
    &param_ch7_bipolar,
    &param_ch8_bipolar,
    NULL
};

static const input_spec_t i_arm = {
    .name = "arm",
    .annotation = "Arming signal",
    .flags = 0
};

static const input_spec_t i_ch1 = {
    .name = "ch1",
    .annotation = "Channel 1 input",
    .flags = 0
};

static const input_spec_t i_ch2 = {
    .name = "ch2",
    .annotation = "Channel 2 input",
    .flags = 0
};

static const input_spec_t i_ch3 = {
    .name = "ch3",
    .annotation = "Channel 3 input",
    .flags = 0
};

static const input_spec_t i_ch4 = {
    .name = "ch4",
    .annotation = "Channel 4 input",
    .flags = 0
};

static const input_spec_t i_ch5 = {
    .name = "ch5",
    .annotation = "Channel 5 input",
    .flags = 0
};

static const input_spec_t i_ch6 = {
    .name = "ch6",
    .annotation = "Channel 6 input",
    .flags = 0
};

static const input_spec_t i_ch7 = {
    .name = "ch7",
    .annotation = "Channel 7 input",
    .flags = 0
};

static const input_spec_t i_ch8 = {
    .name = "ch8",
    .annotation = "Channel 8 input",
    .flags = 0
};

static const input_spec_t *inputs[10] = {
    &i_arm,
    &i_ch1,
    &i_ch2,
    &i_ch3,
    &i_ch4,
    &i_ch5,
    &i_ch6,
    &i_ch7,
    &i_ch8,
    NULL
};

static const output_spec_t *outputs[1] = {
    NULL
};

fspec_rv_t cube_io_pwm_call_init_inputs(void *dh, const func_conn_spec_t *conn_spec, eswb_topic_descr_t mounting_td);

fspec_rv_t cube_io_pwm_call_pre_exec_init(void *dh);

void cube_io_pwm_call_exec(void *dh);

fspec_rv_t cube_io_pwm_call_set_params(void *dh, const func_param_t *param_pairs, int initial_call);

const function_spec_t atomic_cube_io_pwm_spec = {
    .name = "cube.io.pwm",
    .annotation = "io",
    .inputs = inputs,
    .outputs = outputs,
    .params = params
};

const function_calls_t atomic_cube_io_pwm_calls = {
    .interface_handle_size = sizeof(cube_io_pwm_interface_t),
    .init = NULL,
    .init_inputs = cube_io_pwm_call_init_inputs,
    .init_outputs = NULL,
    .pre_exec_init = cube_io_pwm_call_pre_exec_init,
    .exec = cube_io_pwm_call_exec,
    .set_params = cube_io_pwm_call_set_params
};

const function_handler_t atomic_cube_io_pwm_handler = {
    .spec = &atomic_cube_io_pwm_spec,
    .calls = &atomic_cube_io_pwm_calls,
    .extension_handler = NULL
};
cube_io_pwm_interface.c
/**
 *  Automatically-generated file. Do not edit!
 */

#include "cube_io_pwm.h"

#include "error.h"
#include <eswb/api.h>
#include <eswb/topic_proclaiming_tree.h>
#include <eswb/errors.h>

int cube_io_pwm_interface_inputs_init(
    cube_io_pwm_interface_t *interface,
    const func_conn_spec_t *conn_spec,
    eswb_topic_descr_t mounting_td
)
{
    eswb_rv_t rv;
    int errcnt_no_topic = 0;
    int errcnt_no_input = 0;
    const char *topic_path_in_arm = fspec_find_path2connect(conn_spec,"arm");
    const char *topic_path_in_ch1 = fspec_find_path2connect(conn_spec,"ch1");
    const char *topic_path_in_ch2 = fspec_find_path2connect(conn_spec,"ch2");
    const char *topic_path_in_ch3 = fspec_find_path2connect(conn_spec,"ch3");
    const char *topic_path_in_ch4 = fspec_find_path2connect(conn_spec,"ch4");
    const char *topic_path_in_ch5 = fspec_find_path2connect(conn_spec,"ch5");
    const char *topic_path_in_ch6 = fspec_find_path2connect(conn_spec,"ch6");
    const char *topic_path_in_ch7 = fspec_find_path2connect(conn_spec,"ch7");
    const char *topic_path_in_ch8 = fspec_find_path2connect(conn_spec,"ch8");

    // Connecting mandatory input "arm"
    if (topic_path_in_arm != NULL) {
        rv = eswb_connect_nested(mounting_td, topic_path_in_arm, &interface->eswb_descriptors.in_arm);
        if(rv != eswb_e_ok) {
            error("failed connect input \"arm\" to topic \"%s\": %s", topic_path_in_arm, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    } else {
        error("mandatory input \"arm\" is not speicifed");
        errcnt_no_input++;
    }

    // Connecting optional input "ch1"
    if (topic_path_in_ch1 != NULL) {
        interface->i.optional_inputs_flags.ch1 = 1;
        rv = eswb_connect_nested(mounting_td, topic_path_in_ch1, &interface->eswb_descriptors.in_ch1);
        if(rv != eswb_e_ok) {
            error("failed connect input \"ch1\" to topic \"%s\": %s", topic_path_in_ch1, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    }

    // Connecting optional input "ch2"
    if (topic_path_in_ch2 != NULL) {
        interface->i.optional_inputs_flags.ch2 = 1;
        rv = eswb_connect_nested(mounting_td, topic_path_in_ch2, &interface->eswb_descriptors.in_ch2);
        if(rv != eswb_e_ok) {
            error("failed connect input \"ch2\" to topic \"%s\": %s", topic_path_in_ch2, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    }

    // Connecting optional input "ch3"
    if (topic_path_in_ch3 != NULL) {
        interface->i.optional_inputs_flags.ch3 = 1;
        rv = eswb_connect_nested(mounting_td, topic_path_in_ch3, &interface->eswb_descriptors.in_ch3);
        if(rv != eswb_e_ok) {
            error("failed connect input \"ch3\" to topic \"%s\": %s", topic_path_in_ch3, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    }

    // Connecting optional input "ch4"
    if (topic_path_in_ch4 != NULL) {
        interface->i.optional_inputs_flags.ch4 = 1;
        rv = eswb_connect_nested(mounting_td, topic_path_in_ch4, &interface->eswb_descriptors.in_ch4);
        if(rv != eswb_e_ok) {
            error("failed connect input \"ch4\" to topic \"%s\": %s", topic_path_in_ch4, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    }

    // Connecting optional input "ch5"
    if (topic_path_in_ch5 != NULL) {
        interface->i.optional_inputs_flags.ch5 = 1;
        rv = eswb_connect_nested(mounting_td, topic_path_in_ch5, &interface->eswb_descriptors.in_ch5);
        if(rv != eswb_e_ok) {
            error("failed connect input \"ch5\" to topic \"%s\": %s", topic_path_in_ch5, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    }

    // Connecting optional input "ch6"
    if (topic_path_in_ch6 != NULL) {
        interface->i.optional_inputs_flags.ch6 = 1;
        rv = eswb_connect_nested(mounting_td, topic_path_in_ch6, &interface->eswb_descriptors.in_ch6);
        if(rv != eswb_e_ok) {
            error("failed connect input \"ch6\" to topic \"%s\": %s", topic_path_in_ch6, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    }

    // Connecting optional input "ch7"
    if (topic_path_in_ch7 != NULL) {
        interface->i.optional_inputs_flags.ch7 = 1;
        rv = eswb_connect_nested(mounting_td, topic_path_in_ch7, &interface->eswb_descriptors.in_ch7);
        if(rv != eswb_e_ok) {
            error("failed connect input \"ch7\" to topic \"%s\": %s", topic_path_in_ch7, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    }

    // Connecting optional input "ch8"
    if (topic_path_in_ch8 != NULL) {
        interface->i.optional_inputs_flags.ch8 = 1;
        rv = eswb_connect_nested(mounting_td, topic_path_in_ch8, &interface->eswb_descriptors.in_ch8);
        if(rv != eswb_e_ok) {
            error("failed connect input \"ch8\" to topic \"%s\": %s", topic_path_in_ch8, eswb_strerror(rv));
            errcnt_no_topic++;
        }
    }

    if ((errcnt_no_input > 0) || (errcnt_no_topic > 0)) {
        if (errcnt_no_input > errcnt_no_topic) {
            return fspec_rv_no_input;
        } else {
            return fspec_rv_no_topic;
        }
    }
    return fspec_rv_ok;
}

fspec_rv_t cube_io_pwm_interface_inputs_update(cube_io_pwm_interface_t *interface)
{
    eswb_rv_t rv;

    rv = eswb_read(interface->eswb_descriptors.in_arm, &interface->i.arm);
    if(rv != eswb_e_ok) {
        /*FIXME nothing to do yet*/
    }

    if (interface->i.optional_inputs_flags.ch1) {
        rv = eswb_read(interface->eswb_descriptors.in_ch1, &interface->i.ch1);
        if(rv != eswb_e_ok) {
            /*FIXME nothing to do yet*/
        }
    }

    if (interface->i.optional_inputs_flags.ch2) {
        rv = eswb_read(interface->eswb_descriptors.in_ch2, &interface->i.ch2);
        if(rv != eswb_e_ok) {
            /*FIXME nothing to do yet*/
        }
    }

    if (interface->i.optional_inputs_flags.ch3) {
        rv = eswb_read(interface->eswb_descriptors.in_ch3, &interface->i.ch3);
        if(rv != eswb_e_ok) {
            /*FIXME nothing to do yet*/
        }
    }

    if (interface->i.optional_inputs_flags.ch4) {
        rv = eswb_read(interface->eswb_descriptors.in_ch4, &interface->i.ch4);
        if(rv != eswb_e_ok) {
            /*FIXME nothing to do yet*/
        }
    }

    if (interface->i.optional_inputs_flags.ch5) {
        rv = eswb_read(interface->eswb_descriptors.in_ch5, &interface->i.ch5);
        if(rv != eswb_e_ok) {
            /*FIXME nothing to do yet*/
        }
    }

    if (interface->i.optional_inputs_flags.ch6) {
        rv = eswb_read(interface->eswb_descriptors.in_ch6, &interface->i.ch6);
        if(rv != eswb_e_ok) {
            /*FIXME nothing to do yet*/
        }
    }

    if (interface->i.optional_inputs_flags.ch7) {
        rv = eswb_read(interface->eswb_descriptors.in_ch7, &interface->i.ch7);
        if(rv != eswb_e_ok) {
            /*FIXME nothing to do yet*/
        }
    }

    if (interface->i.optional_inputs_flags.ch8) {
        rv = eswb_read(interface->eswb_descriptors.in_ch8, &interface->i.ch8);
        if(rv != eswb_e_ok) {
            /*FIXME nothing to do yet*/
        }
    }

    return 0;
}

fspec_rv_t cube_io_pwm_interface_pre_exec_init(cube_io_pwm_interface_t *interface)
{
    return cube_io_pwm_pre_exec_init(&interface->i.optional_inputs_flags, &interface->p, &interface->state);
}

void cube_io_pwm_interface_update(cube_io_pwm_interface_t *interface)
{
    cube_io_pwm_interface_inputs_update(interface);
    cube_io_pwm_exec(&interface->i, &interface->p, &interface->state);
}

fspec_rv_t cube_io_pwm_call_set_params(void *dh, const func_param_t *param_pairs, int initial_call)
{
    cube_io_pwm_interface_t *interface = (cube_io_pwm_interface_t*) dh;
    return cube_io_pwm_set_params(&interface->p, param_pairs, initial_call);
}

fspec_rv_t cube_io_pwm_call_init_inputs(void *dh, const func_conn_spec_t *conn_spec, eswb_topic_descr_t mounting_td)
{
    cube_io_pwm_interface_t *interface = (cube_io_pwm_interface_t*) dh;
    return cube_io_pwm_interface_inputs_init(interface, conn_spec, mounting_td);
}

fspec_rv_t cube_io_pwm_call_pre_exec_init(void *dh)
{
    cube_io_pwm_interface_t *interface = (cube_io_pwm_interface_t*) dh;
    return cube_io_pwm_interface_pre_exec_init(interface);
}

void cube_io_pwm_call_exec(void *dh)
{
    cube_io_pwm_interface_t *interface = (cube_io_pwm_interface_t*) dh;
    cube_io_pwm_interface_update(interface);
}
←   cube.io.gpio cube.io.rc  →