CANSIGNAL Module Sources


cansignal.c

/**
 *
 * @copyright © 2010 - 2019, Fraunhofer-Gesellschaft zur Foerderung der
 *  angewandten Forschung e.V. All rights reserved.
 *
 * BSD 3-Clause License
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1.  Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of the copyright holder nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * We kindly request you to use one or more of the following phrases to refer
 * to foxBMS in your hardware, software, documentation or advertising
 * materials:
 *
 * ″This product uses parts of foxBMS®″
 *
 * ″This product includes parts of foxBMS®″
 *
 * ″This product is derived from foxBMS®″
 *
 */

/**
 * @file    cansignal.c
 * @author  foxBMS Team
 * @date    01.10.2015 (date of creation)
 * @ingroup DRIVERS
 * @prefix  CANS
 *
 * @brief   Messages and signal settings for the CAN driver
 *
 * generic conversion module of Can signals from CAN buffered reception to
 * DATA Manager and vice versa
 *
 */

/*================== Includes =============================================*/
#include "cansignal.h"

#include "database.h"
#include "diag.h"
#include "os.h"

/*================== Macros and Definitions ===============================*/

/*================== Constant and Variable Definitions ====================*/
static CANS_STATE_s cans_state = {
        .periodic_enable = FALSE,
        .current_sensor_present = FALSE,
        .current_sensor_cc_present = FALSE,
    };

static DATA_BLOCK_STATEREQUEST_s canstatereq_tab;

/*================== Function Prototypes ==================================*/
static STD_RETURN_TYPE_e CANS_PeriodicTransmit(void);
static STD_RETURN_TYPE_e CANS_PeriodicReceive(void);
static void CANS_SetSignalData(CANS_signal_s signal, uint64_t value, uint8_t *dataPtr);
static void CANS_GetSignalData(uint64_t *dst, CANS_signal_s signal, uint8_t *dataPtr);
static void CANS_ComposeMessage(CAN_NodeTypeDef_e canNode, CANS_messagesTx_e msgIdx, uint8_t dataptr[]);
static void CANS_ParseMessage(CAN_NodeTypeDef_e canNode, CANS_messagesRx_e msgIdx, uint8_t dataptr[]);
static uint8_t CANS_CheckCanTiming(void);
static void CANS_SetCurrentSensorPresent(uint8_t command);
static void CANS_SetCurrentSensorCCPresent(uint8_t command);
/*================== Function Implementations =============================*/

/*================== Public functions =====================================*/
void CANS_Init(void) {
    /* custom initialization could be made here. right now no need for any init */
}

void CANS_MainFunction(void) {
    (void)CANS_PeriodicReceive();
    CANS_CheckCanTiming();
    if (cans_state.periodic_enable == TRUE) {
        (void)CANS_PeriodicTransmit();
    }
    DIAG_SysMonNotify(DIAG_SYSMON_CANS_ID, 0);  /* task is running, state = ok */
}


STD_RETURN_TYPE_e CANS_AddMessage(CAN_NodeTypeDef_e canNode, uint32_t msgID, uint8_t* ptrMsgData,
        uint32_t msgLength, uint32_t RTR) {
    STD_RETURN_TYPE_e retVal = E_NOT_OK;
    OS_TaskEnter_Critical();
    /* Function should not be interrupted by the OS during the execution */
    retVal = CAN_Send(canNode, msgID, ptrMsgData, msgLength, RTR);
    OS_TaskExit_Critical();
    return retVal;
}

STD_RETURN_TYPE_e CANS_TransmitBuffer(CAN_NodeTypeDef_e canNode) {
    STD_RETURN_TYPE_e retVal = E_NOT_OK;
    OS_TaskEnter_Critical();
    /* Function should not be interrupted by the OS during the execution */
    retVal = CAN_TxMsgBuffer(canNode);
    OS_TaskExit_Critical();
    return retVal;
}

STD_RETURN_TYPE_e CANS_TransmitMessage(CAN_NodeTypeDef_e canNode, uint32_t msgID, uint8_t* ptrMsgData,
        uint32_t msgLength, uint32_t RTR) {
    STD_RETURN_TYPE_e retVal = E_NOT_OK;
    retVal = CAN_TxMsg(canNode, msgID, ptrMsgData, msgLength, RTR);
    return retVal;
}



/*================== Static functions =====================================*/
/**
 * handles the processing of messages that are meant to be transmitted.
 *
 * This function looks for the repetition times and the repetition phase of
 * messages that are intended to be sent periodically. If a comparison with
 * an internal counter (i.e., the counter how often this function has been called)
 * states that a transmit is pending, the message is composed by call of CANS_ComposeMessage
 * and transfered to the buffer of the CAN module. If a callback function
 * is declared in configuration, this callback is called after successful transmission.
 *
 * @return E_OK if a successful transfer to CAN buffer occured, E_NOT_OK otherwise
 */
static STD_RETURN_TYPE_e CANS_PeriodicTransmit(void) {
    static uint32_t counter_ticks = 0;
    uint32_t i = 0;
    STD_RETURN_TYPE_e result = E_NOT_OK;

#if CAN_USE_CAN_NODE0 == TRUE
    for (i = 0; i < can_CAN0_tx_length; i++) {
        if (((counter_ticks * CANS_TICK_MS) % (can_CAN0_messages_tx[i].repetition_time)) == can_CAN0_messages_tx[i].repetition_phase) {
            Can_PduType PduToSend = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0x0, 8 };
            CANS_ComposeMessage(CAN_NODE0, (CANS_messagesTx_e)(i), PduToSend.sdu);
            PduToSend.id = can_CAN0_messages_tx[i].ID;

            result = CANS_AddMessage(CAN_NODE0, PduToSend.id, PduToSend.sdu, PduToSend.dlc, 0);
            DIAG_checkEvent(result, DIAG_CH_CANS_CAN_MOD_FAILURE, 1);

            if (can_CAN0_messages_tx[i].cbk_func != NULL_PTR && result == E_OK) {
                can_CAN0_messages_tx[i].cbk_func(i, NULL_PTR);
            }
        }
    }
#endif

#if CAN_USE_CAN_NODE1 == TRUE
    for (i = 0; i < can_CAN1_tx_length; i++) {
        if (((counter_ticks * CANS_TICK_MS) % (can_CAN1_messages_tx[i].repetition_time)) == can_CAN1_messages_tx[i].repetition_phase) {
            Can_PduType PduToSend = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0x0, 8 };
            CANS_ComposeMessage(CAN_NODE1, (CANS_messagesTx_e)i + can_CAN0_tx_length, PduToSend.sdu);
            PduToSend.id = can_CAN1_messages_tx[i].ID;

            result = CANS_AddMessage(CAN_NODE1, PduToSend.id, PduToSend.sdu, PduToSend.dlc, 0);
            DIAG_checkEvent(result, DIAG_CH_CANS_CAN_MOD_FAILURE, 0);

            if (can_CAN1_messages_tx[i].cbk_func != NULL_PTR && result == E_OK) {
                can_CAN1_messages_tx[i].cbk_func(i, NULL_PTR);
            }
        }
    }
#endif

    result = E_NOT_OK;

    counter_ticks++;
    return TRUE;
}

/**
 * handles the processing of received CAN messages.
 *
 * This function gets the messages in the receive buffer
 * of the CAN module. If a message ID is
 * matching one of the IDs in the configuration of
 * CANS module, the signal processing is executed
 * by call to CANS_ParseMessage.
 *
 * @return E_OK, if a message has been received and parsed, E_NOT_OK otherwise
 */
static STD_RETURN_TYPE_e CANS_PeriodicReceive(void) {
    Can_PduType msg = {};
    STD_RETURN_TYPE_e result_node0 = E_NOT_OK, result_node1 = E_NOT_OK;
    uint32_t i = 0;

#if CAN_USE_CAN_NODE0 == TRUE
    while (CAN_ReceiveBuffer(CAN_NODE0, &msg)  ==  E_OK) {
        for (i = 0; i < can_CAN0_rx_length; i++) {
            if (msg.id  ==  can0_RxMsgs[i].ID) {
                CANS_ParseMessage(CAN_NODE0, (CANS_messagesRx_e)i, msg.sdu);
                result_node0 = E_OK;
            }
        }
    }
#else
    result_node0 = E_OK;
#endif

#if CAN_USE_CAN_NODE1 == TRUE
    while (CAN_ReceiveBuffer(CAN_NODE1, &msg) == E_OK) {
        for (i = 0; i < can_CAN1_rx_length; i++) {
            if (msg.id == can1_RxMsgs[i].ID) {
                CANS_ParseMessage(CAN_NODE1, (CANS_messagesRx_e)i + can_CAN0_rx_length - CAN0_BUFFER_BYPASS_NUMBER_OF_IDs, msg.sdu);
                result_node1 = E_OK;
            }
        }
    }
#else
    result_node1 = E_OK;
#endif

    return result_node0 && result_node1;
}
/**
 * @brief   generates bitfield, which masks the bits where the actual signal (defined by its bitlength) is located
 *
 * @param   bitlength   length of the signal in bits
 *
 * @return  bitmask     bitfield mask
 */
static uint64_t CANS_GetBitmask(uint8_t bitlength) {
    uint64_t bitmask = 0x00000000;
    uint8_t i = 0;
    for (i = 0; i < bitlength; i++) {
        bitmask = bitmask << 1;
        bitmask = bitmask | 0x00000001;
    }
    return bitmask;
}

/**
 * extracts signal data from CAN message data
 *
 * @param[out] dst       pointer where the signal data should be copied to
 * @param[in]  signal    signal identifier
 * @param[in]  dataPtr   CAN message data, from which signal data is extracted
 */
static void CANS_GetSignalData(uint64_t *dst, CANS_signal_s signal, uint8_t *dataPtr) {
    uint8_t bitposition = signal.bit_position;
    uint8_t bitlength = (uint8_t)signal.bit_length;
    uint64_t bitmask = 0x00000000;
    uint64_t *dataPtr64 = (uint64_t *)dataPtr;

    bitmask = CANS_GetBitmask(bitlength);
    *dst = (((*dataPtr64) >> bitposition) & bitmask);
}
/**
 * assembles signal data in CAN message data
 *
 * @param signal    signal identifier
 * @param value     signal value data
 * @param dataPtr   CAN message data, in which the signal data is inserted
 */
static void CANS_SetSignalData(CANS_signal_s signal, uint64_t value, uint8_t *dataPtr) {
    uint8_t bitposition = signal.bit_position;
    uint8_t bitlength = (uint8_t)signal.bit_length;
    uint64_t bitmask = 0x0000000000000000;
    uint64_t *dataPtr64 = (uint64_t *)dataPtr;

    bitmask = CANS_GetBitmask(bitlength);
    dataPtr64[0] &= ~(((uint64_t)bitmask) << bitposition);
    dataPtr64[0] |= ((((uint64_t)value) & bitmask) << bitposition);
}

/**
 * composes message data from all signals associated with this msgIdx
 *
 * signal data is received by callback getter functions
 *
 * @param[in] msgIdx   message index for which the data should be composed
 * @param[out] dataptr  pointer where the message data should be stored to
 */
static void CANS_ComposeMessage(CAN_NodeTypeDef_e canNode, CANS_messagesTx_e msgIdx, uint8_t dataptr[]) {
    uint32_t i = 0;
    uint32_t nrTxSignals = 0;
    /* find multiplexor if multiplexed signal */

    CANS_signal_s *cans_signals_tx;

    if (canNode == CAN_NODE0) {
        cans_signals_tx = (CANS_signal_s *)&cans_CAN0_signals_tx;
        nrTxSignals = cans_CAN0_signals_tx_length;
    } else if (canNode == CAN_NODE1) {
        cans_signals_tx = (CANS_signal_s *)&cans_CAN1_signals_tx;
        nrTxSignals = cans_CAN1_signals_tx_length;
    }

    for (i = 0; i < nrTxSignals; i++) {
        if (cans_signals_tx[i].msgIdx.Tx == msgIdx) {
            /* simple, not multiplexed signal */
            uint64_t value = 0;
            if (cans_signals_tx[i].getter != NULL_PTR) {
                cans_signals_tx[i].getter(i, &value);
            }
            CANS_SetSignalData(cans_signals_tx[i], value, dataptr);
        } else {
            /* TODO: explain why empty else */
        }
    }
}

/**
 * @brief   parses signal data from message associated with this msgIdx
 *
 * signal data is received by callback setter functions
 *
 * @param[in]   msgIdx   message index for which the data should be parsed
 * @param[in]   dataptr  pointer where the message data is stored
*/
static void CANS_ParseMessage(CAN_NodeTypeDef_e canNode, CANS_messagesRx_e msgIdx, uint8_t dataptr[]) {
    uint32_t i = 0;

    if (canNode == CAN_NODE0) {
        for (i = 0; i < cans_CAN0_signals_rx_length; i++) {
            /* Iterate over CAN0 rx signals and find message */

            if (cans_CAN0_signals_rx[i].msgIdx.Rx  ==  msgIdx) {
                uint64_t value = 0;
                CANS_GetSignalData(&value, cans_CAN0_signals_rx[i], dataptr);
                if (cans_CAN0_signals_rx[i].setter != NULL_PTR) {
                    cans_CAN0_signals_rx[i].setter(i, &value);
                }
            }
        }
    } else if (canNode == CAN_NODE1) {
        for (i = 0; i < cans_CAN1_signals_rx_length; i++) {
            /* Iterate over CAN1 rx signals and find message */

            if (cans_CAN1_signals_rx[i].msgIdx.Rx  ==  msgIdx) {
                uint64_t value = 0;
                CANS_GetSignalData(&value, cans_CAN1_signals_rx[i], dataptr);
                if (cans_CAN1_signals_rx[i].setter != NULL_PTR) {
                    cans_CAN1_signals_rx[i].setter(i, &value);
                }
            }
        }
    }
}

/**
 * @brief   Checks if the CAN messages come in the specified time window
 *
 * if actual time stamp- previous time stamp is > 96 and < 104 check is good
 * else the check is bad
 *
 * @return  TRUE if timing is in tolerance range, FLASE if not
 */

static uint8_t CANS_CheckCanTiming(void) {
    uint8_t retVal = FALSE;

    uint32_t current_time;
    DATA_BLOCK_ERRORSTATE_s error_flags;
    DATA_BLOCK_CURRENT_SENSOR_s current_tab;


    current_time = OS_getOSSysTick();
    DB_ReadBlock(&canstatereq_tab, DATA_BLOCK_ID_STATEREQUEST);

    DB_ReadBlock(&error_flags, DATA_BLOCK_ID_ERRORSTATE);

    /* Is the BMS still getting CAN messages? */
    if ((current_time-canstatereq_tab.timestamp) <= 105) {
        if (((canstatereq_tab.timestamp - canstatereq_tab.previous_timestamp) >= 95) && \
                ((canstatereq_tab.timestamp - canstatereq_tab.previous_timestamp) <= 105)) {
            retVal = TRUE;
            DIAG_Handler(DIAG_CH_CAN_TIMING, DIAG_EVENT_OK, 0);
        } else {
            retVal = FALSE;
            DIAG_Handler(DIAG_CH_CAN_TIMING, DIAG_EVENT_NOK, 0);
        }
    } else {
        retVal = FALSE;
        DIAG_Handler(DIAG_CH_CAN_TIMING, DIAG_EVENT_NOK, 0);
    }

#if CURRENT_SENSOR_PRESENT == TRUE
    /* check time stamps of current measurements */
    DB_ReadBlock(&current_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
    if (current_time-current_tab.timestamp > CURRENT_SENSOR_RESPONSE_TIMEOUT_MS) {
        DIAG_Handler(DIAG_CH_CURRENT_SENSOR_RESPONDING, DIAG_EVENT_NOK, 0);
    } else {
        DIAG_Handler(DIAG_CH_CURRENT_SENSOR_RESPONDING, DIAG_EVENT_OK, 0);
        if (cans_state.current_sensor_present == FALSE) {
            CANS_SetCurrentSensorPresent(TRUE);
        }
    }

    /* check time stamps of CC measurements */
    /* if timestamp_cc != 0, this means current sensor cc message has been received at least once */
    if (current_tab.timestamp_cc != 0) {
        if (current_time-current_tab.timestamp_cc > CURRENT_SENSOR_RESPONSE_TIMEOUT_MS) {
            DIAG_Handler(DIAG_CH_CAN_CC_RESPONDING, DIAG_EVENT_NOK, 0);
        } else {
            DIAG_Handler(DIAG_CH_CAN_CC_RESPONDING, DIAG_EVENT_OK, 0);
            if (cans_state.current_sensor_cc_present == FALSE) {
                CANS_SetCurrentSensorCCPresent(TRUE);
            }
        }
    }
#endif /* CURRENT_SENSOR_PRESENT == TRUE */

    return retVal;
}


/**
 * @brief   enable/disable the periodic transmit/receive.
 *
 * @return  none
 *
 */
extern void CANS_Enable_Periodic(uint8_t command) {
    if (command == TRUE) {
        cans_state.periodic_enable = TRUE;
    } else {
        cans_state.periodic_enable = FALSE;
    }
}



/**
 * @brief   set flag for presence of current sensor.
 *
 * @return  none
 *
 */
static void CANS_SetCurrentSensorPresent(uint8_t command) {
    if (command == TRUE) {
        taskENTER_CRITICAL();
        cans_state.current_sensor_present = TRUE;
        taskEXIT_CRITICAL();
    } else {
        taskENTER_CRITICAL();
        cans_state.current_sensor_present = FALSE;
        taskEXIT_CRITICAL();
    }
}


/**
 * @brief   set flag for sending of C-C by current sensor.
 *
 * @return  none
 *
 */
static void CANS_SetCurrentSensorCCPresent(uint8_t command) {
    if (command == TRUE) {
        taskENTER_CRITICAL();
        cans_state.current_sensor_cc_present = TRUE;
        taskEXIT_CRITICAL();
    } else {
        taskENTER_CRITICAL();
        cans_state.current_sensor_cc_present = FALSE;
        taskEXIT_CRITICAL();
    }
}



/**
 * @brief   set flag for presence of current sensor.
 *
 * @return  retval  TRUE if a current sensor is present, FALSE otherwise
 *
 */
extern uint8_t CANS_IsCurrentSensorPresent(void) {
    uint8_t retval = FALSE;

    retval    = cans_state.current_sensor_present;

    return (retval);
}



/**
 * @brief   set flag for sending of C-C by current sensor.
 *
 * @return  retval  TRUE if C-C is being sent, FALSE otherwise
 *
 */
extern uint8_t CANS_IsCurrentSensorCCPresent(void) {
    uint8_t retval = FALSE;

    retval    = cans_state.current_sensor_cc_present;

    return (retval);
}

cansignal.h

/**
 *
 * @copyright &copy; 2010 - 2019, Fraunhofer-Gesellschaft zur Foerderung der
 *  angewandten Forschung e.V. All rights reserved.
 *
 * BSD 3-Clause License
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1.  Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of the copyright holder nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * We kindly request you to use one or more of the following phrases to refer
 * to foxBMS in your hardware, software, documentation or advertising
 * materials:
 *
 * &Prime;This product uses parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product includes parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product is derived from foxBMS&reg;&Prime;
 *
 */

/**
 * @file    cansignal.h
 * @author  foxBMS Team
 * @date    01.10.2015 (date of creation)
 * @ingroup DRIVERS
 * @prefix  CANS
 *
 * @brief   Headers for the messages and signal settings for the CAN driver
 *
 * generic conversion module header of Can signals from CAN buffered reception to
 * DATA Manager and vice versa
 *
 */

#ifndef CANSIGNAL_H_
#define CANSIGNAL_H_

/*================== Includes =============================================*/
#include "cansignal_cfg.h"

#include "can.h"

/*================== Macros and Definitions ===============================*/

/*================== Constant and Variable Definitions ====================*/
/**
 * This structure contains variables relevant for the CAN signal module.
 */
typedef struct {
    uint8_t periodic_enable;                   /*!< defines if periodic transmit and receive should run  */
    uint8_t current_sensor_present;            /*!< defines if a current sensor is detected  */
    uint8_t current_sensor_cc_present;         /*!< defines if a CC info is being sent  */
} CANS_STATE_s;


/*================== Function Prototypes ==================================*/
/**
 * initializes local variables and module internals needed to use conversion of
 * can signals. Until now no initialization is needed and thus the function does
 * nothing.
 */
extern void CANS_Init(void);

/**
 * handles the conversion of can signals from and to datamanager database or
 * other modules defined by the getter and setter configuration.
 */
extern void CANS_MainFunction(void);

extern void CANS_Enable_Periodic(uint8_t command);
extern uint8_t CANS_IsCurrentSensorPresent(void);
extern uint8_t CANS_IsCurrentSensorCCPresent(void);

/**
 * @brief  Add message to transmit buffer, message will be transmitted shortly after.
 *
 * @param  canNode: canNode on which the message shall be transmitted
 * @param  msgID:    ID of the message that will be transmitted
 * @param  ptrMsgData:    pointer to a uint8_t array that contains the message that will be transmitted
 * @param  msgLength:    length of the message that will be transmitted
 *                 This parameter can be a value of CAN_identifier_type.
 * @param  RTR     Specifies the type of frame for the message that will be transmitted.
 *                 This parameter can be a value of CAN_remote_transmission_request
 *
 * @retval E_OK if successful, E_NOT_OK if buffer is full or error occurred
 */
extern STD_RETURN_TYPE_e CANS_AddMessage(CAN_NodeTypeDef_e canNode, uint32_t msgID, uint8_t* ptrMsgData,
        uint32_t msgLength, uint32_t RTR);

/**
 * @brief  Transmits canNode transmit buffer
 *
 * @param canNode:  canNode on which the message shall be transmitted
 *
 * @retval E_OK if transmission successful, otherwise E_NOT_OK
 */
extern STD_RETURN_TYPE_e CANS_TransmitBuffer(CAN_NodeTypeDef_e canNode);


/**
 * @brief  Transmits message directly on the CAN bus
 *
 * @param  canNode: canNode on which the message shall be transmitted
 * @param  msgID:    ID of the message that will be transmitted
 * @param  ptrMsgData:    pointer to the data that shall be transmitted
 * @param  msgLength:    Specifies the data length
 * @param  RTR: Specifies the type of frame for the message that will be transmitted.
 *
 * @retval E_OK if transmission successful, otherwise E_NOT_OK
 */
extern STD_RETURN_TYPE_e CANS_TransmitMessage(CAN_NodeTypeDef_e canNode, uint32_t msgID, uint8_t* ptrMsgData,
        uint32_t msgLength, uint32_t RTR);

/*================== Function Implementations =============================*/

#endif /* CANSIGNAL_H_ */

cansignal_cfg.c

/**
 *
 * @copyright &copy; 2010 - 2019, Fraunhofer-Gesellschaft zur Foerderung der
 *  angewandten Forschung e.V. All rights reserved.
 *
 * BSD 3-Clause License
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1.  Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of the copyright holder nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * We kindly request you to use one or more of the following phrases to refer
 * to foxBMS in your hardware, software, documentation or advertising
 * materials:
 *
 * &Prime;This product uses parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product includes parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product is derived from foxBMS&reg;&Prime;
 *
 */

/**
 * @file    cansignal_cfg.c
 * @author  foxBMS Team
 * @date    16.09.2015 (date of creation)
 * @ingroup DRIVERS_CONF
 * @prefix  CANS
 *
 * @brief   Configuration of the messages and signal settings for the CAN driver
 *
 */

/*================== Includes ===============================================*/
#include "cansignal_cfg.h"

#include "bal.h"
#include "database.h"
#include "diag.h"
#include "sox.h"
#include "sys.h"

/*================== Macros and Definitions =================================*/
static DATA_BLOCK_CURRENT_SENSOR_s cans_current_tab;

#define CANS_MODULSIGNALS_VOLT      (CAN0_SIG_Mod0_temp_valid_0_2 - CAN0_SIG_Mod0_volt_valid_0_2)
#define CANS_MODULSIGNALS_TEMP      (CAN0_SIG_Mod1_volt_valid_0_2 - CAN0_SIG_Mod0_temp_valid_0_2)


/*================== Static Function Prototypes =============================*/

static float cans_checkLimits(float value, uint32_t sigIdx);

/* TX/Getter functions */
static uint32_t cans_getvolt(uint32_t, void *);
static uint32_t cans_gettempering(uint32_t, void *);
static uint32_t cans_getcanerr(uint32_t, void *);
static uint32_t cans_gettemp(uint32_t, void *);
static uint32_t cans_getsoc(uint32_t, void *);
static uint32_t cans_getRecommendedOperatingCurrent(uint32_t, void *);
static uint32_t cans_getMaxAllowedPower(uint32_t, void *);
static uint32_t cans_getpower(uint32_t, void *);
static uint32_t cans_getcurr(uint32_t, void *);
static uint32_t cans_getPackVoltage(uint32_t, void *);
static uint32_t cans_getminmaxvolt(uint32_t, void *);
static uint32_t cans_getminmaxtemp(uint32_t, void *);
static uint32_t cans_getisoguard(uint32_t, void *);


/* RX/Setter functions */
static uint32_t cans_setcurr(uint32_t, void *);
static uint32_t cans_setstaterequest(uint32_t, void *);
static uint32_t cans_setdebug(uint32_t, void *);
static uint32_t cans_setSWversion(uint32_t, void *);


#ifdef CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED
static uint32_t cans_gettriggercurrent(uint32_t sigIdx, void *value);
#endif /* CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED */



/*================== Static Constant and Variable Definitions ===============*/

/*================== Extern Constant and Variable Definitions ===============*/

const CANS_signal_s cans_CAN0_signals_tx[] = {
    { {CAN0_MSG_SystemState_0}, 0, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS0_general_error, */
    { {CAN0_MSG_SystemState_0}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS0_current_state, */
    { {CAN0_MSG_SystemState_0}, 16, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS0_error_overtemp_charge, */
    { {CAN0_MSG_SystemState_0}, 24, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS0_error_undertemp_charge, */
    { {CAN0_MSG_SystemState_0}, 32, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS0_error_overtemp_discharge, */
    { {CAN0_MSG_SystemState_0}, 40, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS0_error_undertemp_discharge, */
    { {CAN0_MSG_SystemState_0}, 48, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS0_error_overcurrent_charge, */
    { {CAN0_MSG_SystemState_0}, 56, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS0_error_overcurrent_discharge, */

    { {CAN0_MSG_SystemState_1}, 0, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS1_error_overvoltage, */
    { {CAN0_MSG_SystemState_1}, 8, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS1_error_undervoltage, */
    { {CAN0_MSG_SystemState_1}, 11, 1, 0, 1, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS1_error_deep_discharge, */
    { {CAN0_MSG_SystemState_1}, 16, 1, 0, 1, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS1_error_temperature_MCU0 */
    { {CAN0_MSG_SystemState_1}, 24, 1, 0, 1, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS1_error_contactor */
    { {CAN0_MSG_SystemState_1}, 32, 1, 0, 1, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS1_error_selftest, */
    { {CAN0_MSG_SystemState_1}, 40, 1, 0, 1, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN_SIG_GS1_error_cantiming, */
    { {CAN0_MSG_SystemState_1}, 48, 1, 0, 1, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS1_current_sensor, */
    { {CAN0_MSG_SystemState_1}, 56, 1, 0, 1, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS1_balancing_active, */

    { {CAN0_MSG_SystemState_2}, 0, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS2_states_relays */
    { {CAN0_MSG_SystemState_2}, 16, 1, 0, 1, 1, 0, NULL_PTR, &cans_getcanerr },   /*!< CAN0_SIG_GS2_error_insulation */
    { {CAN0_MSG_SystemState_2}, 24, 4, 0, 15, 1, 0, NULL_PTR, &cans_getcanerr },  /*!< CAN0_SIG_GS2_fuse_state */
    { {CAN0_MSG_SystemState_2}, 32, 2, 0, 3, 1, 0, NULL_PTR, &cans_getcanerr },   /*!< CAN0_SIG_GS2_lowCoinCellVolt */
    { {CAN0_MSG_SystemState_2}, 40, 1, 0, 1, 1, 0, NULL_PTR, &cans_getcanerr },   /*!< CAN0_SIG_GS2_error_openWire */
    { {CAN0_MSG_SystemState_2}, 48, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },   /*!< CAN0_SIG_GS2_daisyChain */
    { {CAN0_MSG_SystemState_2}, 56, 3, 0, 7, 1, 0, NULL_PTR, &cans_getcanerr },   /*!< CAN0_SIG_GS2_plausibilityCheck */

    { {CAN0_MSG_SlaveState_0}, 0, 64, 0, UINT64_MAX, 1, 0, NULL_PTR, NULL_PTR },  /*!< CAN0_SIG_SS0_states */
    { {CAN0_MSG_SlaveState_1}, 0, 64, 0, UINT64_MAX, 1, 0, NULL_PTR, NULL_PTR },  /*!< CAN0_SIG_SS0_states */

    { {CAN0_MSG_RecOperatingCurrent}, 0, 16, 0, 6553.5, 10, 0, NULL_PTR, &cans_getRecommendedOperatingCurrent },  /*!< CAN0_SIG_MaxChargeCurrent */
    { {CAN0_MSG_RecOperatingCurrent}, 16, 16, 0, 6553.5, 10, 0, NULL_PTR, &cans_getRecommendedOperatingCurrent },  /*!< CAN0_SIG_MaxChargeCurrent_Peak */
    { {CAN0_MSG_RecOperatingCurrent}, 32, 16, 0, 6553.5, 10, 0, NULL_PTR, &cans_getRecommendedOperatingCurrent },  /*!< CAN0_SIG_MaxDischargeCurrent */
    { {CAN0_MSG_RecOperatingCurrent}, 48, 16, 0, 6553.5, 10, 0, NULL_PTR, &cans_getRecommendedOperatingCurrent },  /*!< CAN0_SIG_MaxDischargeCurrent_Peak */

    { {CAN0_MSG_SOP}, 0, 16, 0, 6553.5, 10, 0, NULL_PTR, &cans_getMaxAllowedPower },  /*!< CAN0_SIG_MaxChargePower */
    { {CAN0_MSG_SOP}, 16, 16, 0, 6553.5, 10, 0, NULL_PTR, &cans_getMaxAllowedPower },  /*!< CAN0_SIG_MaxChargePower_Peak */
    { {CAN0_MSG_SOP}, 32, 16, 0, 6553.5, 10, 0, NULL_PTR, &cans_getMaxAllowedPower },  /*!< CAN0_SIG_MaxDischargePower */
    { {CAN0_MSG_SOP}, 48, 16, 0, 6553.5, 10, 0, NULL_PTR, &cans_getMaxAllowedPower },  /*!< CAN0_SIG_MaxDischargePower_Peak */

    { {CAN0_MSG_SOC}, 0, 16, 0, 100, 100, 0, NULL_PTR, &cans_getsoc },  /*!< CAN0_SIG_SOC_mean */
    { {CAN0_MSG_SOC}, 16, 16, 0, 100, 100, 0, NULL_PTR, &cans_getsoc },  /*!< CAN0_SIG_SOC_min */
    { {CAN0_MSG_SOC}, 32, 16, 0, 100, 100, 0, NULL_PTR, &cans_getsoc },  /*!< CAN0_SIG_SOC_max */

    { {CAN0_MSG_SOH}, 0, 16, 0, 0, 100, 0, NULL_PTR, NULL_PTR },  /*!< CAN0_SIG_SOH_mean */
    { {CAN0_MSG_SOH}, 16, 16, 0, 0, 100, 0, NULL_PTR, NULL_PTR },  /*!< CAN0_SIG_SOH_min */
    { {CAN0_MSG_SOH}, 32, 16, 0, 0, 100, 0, NULL_PTR, NULL_PTR },  /*!< CAN0_SIG_SOH_max */

    { {CAN0_MSG_SOE}, 0, 16, 0, 0, 100, 0, NULL_PTR, NULL_PTR },  /*!< CAN0_SIG_SOE */
    { {CAN0_MSG_SOE}, 16, 32, 0, UINT32_MAX, 1, 0, NULL_PTR, NULL_PTR },  /*!< CAN0_SIG_RemainingEnergy */

    { {CAN0_MSG_MinMaxCellVolt}, 0, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getminmaxvolt },  /*!< CAN0_SIG_Cellvolt_mean */
    { {CAN0_MSG_MinMaxCellVolt}, 16, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getminmaxvolt },  /*!< CAN0_SIG_Cellvolt_min */
    { {CAN0_MSG_MinMaxCellVolt}, 32, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getminmaxvolt },  /*!< CAN0_SIG_Cellvolt_max */
    { {CAN0_MSG_MinMaxCellVolt}, 48, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getminmaxvolt },  /*!< CAN0_SIG_ModNumber_min */
    { {CAN0_MSG_MinMaxCellVolt}, 56, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getminmaxvolt },  /*!< CAN0_SIG_ModNumber_max */

    { {CAN0_MSG_SOV}, 0, 16, 0, 100, 100, 0, NULL_PTR, NULL_PTR },  /*!< CAN0_SIG_SOV */

    { {CAN0_MSG_MinMaxCellTemp}, 0, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_getminmaxtemp },  /*!< CAN0_SIG_Cellvolt_mean */
    { {CAN0_MSG_MinMaxCellTemp}, 16, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_getminmaxtemp },  /*!< CAN0_SIG_Cellvolt_min */
    { {CAN0_MSG_MinMaxCellTemp}, 32, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_getminmaxtemp },  /*!< CAN0_SIG_Cellvolt_max */
    { {CAN0_MSG_MinMaxCellTemp}, 48, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getminmaxtemp },  /*!< CAN0_SIG_ModNumber_min */
    { {CAN0_MSG_MinMaxCellTemp}, 56, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getminmaxtemp },  /*!< CAN0_SIG_ModNumber_max */

    { {CAN0_MSG_Tempering}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettempering },  /*!< CAN0_SIG_CoolingNeeded */
    { {CAN0_MSG_Tempering}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettempering },  /*!< CAN0_SIG_HeatingNeeded */
    { {CAN0_MSG_Tempering}, 16, 32, 0, UINT32_MAX, 1, 0, NULL_PTR, &cans_gettempering },  /*!< CAN0_SIG_TemperingDemand */

    { {CAN0_MSG_Insulation}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getisoguard },  /*!< CAN0_SIG_InsulationStatus */
    { {CAN0_MSG_Insulation}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getisoguard },  /*!< CAN0_SIG_InsulationValue */

    { {CAN0_MSG_Power_0}, 0, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getpower },  /*!< CAN0_SIG_RunAverage_Power_1s */
    { {CAN0_MSG_Power_0}, 32, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getpower },  /*!< CAN0_SIG_RunAverage_Power_5s */
    { {CAN0_MSG_Power_1}, 0, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getpower },  /*!< CAN0_SIG_RunAverage_Power_10s */
    { {CAN0_MSG_Power_1}, 32, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getpower },  /*!< CAN0_SIG_RunAverage_Power_30s */
    { {CAN0_MSG_Power_2}, 0, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getpower },  /*!< CAN0_SIG_RunAverage_Power_60s */
    { {CAN0_MSG_Power_2}, 32, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getpower },  /*!< CAN0_SIG_RunAverage_Power_config */

    { {CAN0_MSG_Current_0}, 0, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getcurr },  /*!< CAN0_SIG_RunAverage_Current_1s */
    { {CAN0_MSG_Current_0}, 32, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getcurr },  /*!< CAN0_SIG_RunAverage_Current_5s */
    { {CAN0_MSG_Current_1}, 0, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getcurr },  /*!< CAN0_SIG_RunAverage_Current_10s */
    { {CAN0_MSG_Current_1}, 32, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getcurr },  /*!< CAN0_SIG_RunAverage_Current_30s */
    { {CAN0_MSG_Current_2}, 0, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getcurr },  /*!< CAN0_SIG_RunAverage_Current_60s */
    { {CAN0_MSG_Current_2}, 32, 32, -2500000, 4292467295, 1, 2500000, NULL_PTR, &cans_getcurr },  /*!< CAN0_SIG_RunAverage_Current_config */

    { {CAN0_MSG_PackVoltage}, 0, 32, 0, UINT32_MAX, 1, 0, NULL_PTR, &cans_getPackVoltage },  /*!< CAN0_SIG_PackVolt_Battery */
    { {CAN0_MSG_PackVoltage}, 32, 32, 0, UINT32_MAX, 1, 0, NULL_PTR, &cans_getPackVoltage },  /*!< CAN0_SIG_PackVolt_PowerNet */

    /* Module 0 cell voltages */
    { {CAN0_MSG_Mod0_Cellvolt_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_valid_0_2 */
    { {CAN0_MSG_Mod0_Cellvolt_0}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_0 */
    { {CAN0_MSG_Mod0_Cellvolt_0}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_1 */
    { {CAN0_MSG_Mod0_Cellvolt_0}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_2 */
    { {CAN0_MSG_Mod0_Cellvolt_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_valid_3_5 */
    { {CAN0_MSG_Mod0_Cellvolt_1}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_3 */
    { {CAN0_MSG_Mod0_Cellvolt_1}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_4 */
    { {CAN0_MSG_Mod0_Cellvolt_1}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_5 */
    { {CAN0_MSG_Mod0_Cellvolt_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_valid_6_8 */
    { {CAN0_MSG_Mod0_Cellvolt_2}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_6 */
    { {CAN0_MSG_Mod0_Cellvolt_2}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_7 */
    { {CAN0_MSG_Mod0_Cellvolt_2}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_8 */
    { {CAN0_MSG_Mod0_Cellvolt_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_valid_9_11 */
    { {CAN0_MSG_Mod0_Cellvolt_3}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_9 */
    { {CAN0_MSG_Mod0_Cellvolt_3}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_10 */
    { {CAN0_MSG_Mod0_Cellvolt_3}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_11 */
    { {CAN0_MSG_Mod0_Cellvolt_4}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_valid_12_14 */
    { {CAN0_MSG_Mod0_Cellvolt_4}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_12 */
    { {CAN0_MSG_Mod0_Cellvolt_4}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_13 */
    { {CAN0_MSG_Mod0_Cellvolt_4}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_14 */
    { {CAN0_MSG_Mod0_Cellvolt_5}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_valid_15_17 */
    { {CAN0_MSG_Mod0_Cellvolt_5}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_15 */
    { {CAN0_MSG_Mod0_Cellvolt_5}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_16 */
    { {CAN0_MSG_Mod0_Cellvolt_5}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod0_volt_17 */

    /* Module 0 cell temperatures */
    { {CAN0_MSG_Mod0_Celltemp_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_volt_valid_0_2 */
    { {CAN0_MSG_Mod0_Celltemp_0}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_0 */
    { {CAN0_MSG_Mod0_Celltemp_0}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_1 */
    { {CAN0_MSG_Mod0_Celltemp_0}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_2 */
    { {CAN0_MSG_Mod0_Celltemp_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_volt_valid_3_5 */
    { {CAN0_MSG_Mod0_Celltemp_1}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_3 */
    { {CAN0_MSG_Mod0_Celltemp_1}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_4 */
    { {CAN0_MSG_Mod0_Celltemp_1}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_5 */
    { {CAN0_MSG_Mod0_Celltemp_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_volt_valid_6_8 */
    { {CAN0_MSG_Mod0_Celltemp_2}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_6 */
    { {CAN0_MSG_Mod0_Celltemp_2}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_7 */
    { {CAN0_MSG_Mod0_Celltemp_2}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_8 */
    { {CAN0_MSG_Mod0_Celltemp_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_volt_valid_9_11 */
    { {CAN0_MSG_Mod0_Celltemp_3}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_9 */
    { {CAN0_MSG_Mod0_Celltemp_3}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_10 */
    { {CAN0_MSG_Mod0_Celltemp_3}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod0_temp_11 */

    /* Module 1 cell voltages */
    { {CAN0_MSG_Mod1_Cellvolt_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_valid_0_2 */
    { {CAN0_MSG_Mod1_Cellvolt_0}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_0 */
    { {CAN0_MSG_Mod1_Cellvolt_0}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_1 */
    { {CAN0_MSG_Mod1_Cellvolt_0}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_2 */
    { {CAN0_MSG_Mod1_Cellvolt_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_valid_3_5 */
    { {CAN0_MSG_Mod1_Cellvolt_1}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_3 */
    { {CAN0_MSG_Mod1_Cellvolt_1}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_4 */
    { {CAN0_MSG_Mod1_Cellvolt_1}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_5 */
    { {CAN0_MSG_Mod1_Cellvolt_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_valid_6_8 */
    { {CAN0_MSG_Mod1_Cellvolt_2}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_6 */
    { {CAN0_MSG_Mod1_Cellvolt_2}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_7 */
    { {CAN0_MSG_Mod1_Cellvolt_2}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_8 */
    { {CAN0_MSG_Mod1_Cellvolt_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_valid_9_11 */
    { {CAN0_MSG_Mod1_Cellvolt_3}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_9 */
    { {CAN0_MSG_Mod1_Cellvolt_3}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_10 */
    { {CAN0_MSG_Mod1_Cellvolt_3}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_11 */
    { {CAN0_MSG_Mod1_Cellvolt_4}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_valid_12_14 */
    { {CAN0_MSG_Mod1_Cellvolt_4}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_12 */
    { {CAN0_MSG_Mod1_Cellvolt_4}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_13 */
    { {CAN0_MSG_Mod1_Cellvolt_4}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_14 */
    { {CAN0_MSG_Mod1_Cellvolt_5}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_valid_15_17 */
    { {CAN0_MSG_Mod1_Cellvolt_5}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_15 */
    { {CAN0_MSG_Mod1_Cellvolt_5}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_16 */
    { {CAN0_MSG_Mod1_Cellvolt_5}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod1_volt_17 */

    /* Module 1 cell temperatures */
    { {CAN0_MSG_Mod1_Celltemp_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_volt_valid_0_2 */
    { {CAN0_MSG_Mod1_Celltemp_0}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_0 */
    { {CAN0_MSG_Mod1_Celltemp_0}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_1 */
    { {CAN0_MSG_Mod1_Celltemp_0}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_2 */
    { {CAN0_MSG_Mod1_Celltemp_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_volt_valid_3_5 */
    { {CAN0_MSG_Mod1_Celltemp_1}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_3 */
    { {CAN0_MSG_Mod1_Celltemp_1}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_4 */
    { {CAN0_MSG_Mod1_Celltemp_1}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_5 */
    { {CAN0_MSG_Mod1_Celltemp_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_volt_valid_6_8 */
    { {CAN0_MSG_Mod1_Celltemp_2}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_6 */
    { {CAN0_MSG_Mod1_Celltemp_2}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_7 */
    { {CAN0_MSG_Mod1_Celltemp_2}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_8 */
    { {CAN0_MSG_Mod1_Celltemp_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_volt_valid_9_11 */
    { {CAN0_MSG_Mod1_Celltemp_3}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_9 */
    { {CAN0_MSG_Mod1_Celltemp_3}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_10 */
    { {CAN0_MSG_Mod1_Celltemp_3}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod1_temp_11 */

    /* Module 2 cell voltages */
    { {CAN0_MSG_Mod2_Cellvolt_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_valid_0_2 */
    { {CAN0_MSG_Mod2_Cellvolt_0}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_0 */
    { {CAN0_MSG_Mod2_Cellvolt_0}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_1 */
    { {CAN0_MSG_Mod2_Cellvolt_0}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_2 */
    { {CAN0_MSG_Mod2_Cellvolt_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_valid_3_5 */
    { {CAN0_MSG_Mod2_Cellvolt_1}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_3 */
    { {CAN0_MSG_Mod2_Cellvolt_1}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_4 */
    { {CAN0_MSG_Mod2_Cellvolt_1}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_5 */
    { {CAN0_MSG_Mod2_Cellvolt_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_valid_6_8 */
    { {CAN0_MSG_Mod2_Cellvolt_2}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_6 */
    { {CAN0_MSG_Mod2_Cellvolt_2}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_7 */
    { {CAN0_MSG_Mod2_Cellvolt_2}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_8 */
    { {CAN0_MSG_Mod2_Cellvolt_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_valid_9_11 */
    { {CAN0_MSG_Mod2_Cellvolt_3}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_9 */
    { {CAN0_MSG_Mod2_Cellvolt_3}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_10 */
    { {CAN0_MSG_Mod2_Cellvolt_3}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_11 */
    { {CAN0_MSG_Mod2_Cellvolt_4}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_valid_12_14 */
    { {CAN0_MSG_Mod2_Cellvolt_4}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_12 */
    { {CAN0_MSG_Mod2_Cellvolt_4}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_13 */
    { {CAN0_MSG_Mod2_Cellvolt_4}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_14 */
    { {CAN0_MSG_Mod2_Cellvolt_5}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_valid_15_17 */
    { {CAN0_MSG_Mod2_Cellvolt_5}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_15 */
    { {CAN0_MSG_Mod2_Cellvolt_5}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_16 */
    { {CAN0_MSG_Mod2_Cellvolt_5}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod2_volt_17 */

    /* Module 2 cell temperatures */
    { {CAN0_MSG_Mod2_Celltemp_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_volt_valid_0_2 */
    { {CAN0_MSG_Mod2_Celltemp_0}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_0 */
    { {CAN0_MSG_Mod2_Celltemp_0}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_1 */
    { {CAN0_MSG_Mod2_Celltemp_0}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_2 */
    { {CAN0_MSG_Mod2_Celltemp_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_volt_valid_3_5 */
    { {CAN0_MSG_Mod2_Celltemp_1}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_3 */
    { {CAN0_MSG_Mod2_Celltemp_1}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_4 */
    { {CAN0_MSG_Mod2_Celltemp_1}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_5 */
    { {CAN0_MSG_Mod2_Celltemp_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_volt_valid_6_8 */
    { {CAN0_MSG_Mod2_Celltemp_2}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_6 */
    { {CAN0_MSG_Mod2_Celltemp_2}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_7 */
    { {CAN0_MSG_Mod2_Celltemp_2}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_8 */
    { {CAN0_MSG_Mod2_Celltemp_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_volt_valid_9_11 */
    { {CAN0_MSG_Mod2_Celltemp_3}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_9 */
    { {CAN0_MSG_Mod2_Celltemp_3}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_10 */
    { {CAN0_MSG_Mod2_Celltemp_3}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod2_temp_11 */

    /* Module 3 cell voltages */
    { {CAN0_MSG_Mod3_Cellvolt_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_valid_0_2 */
    { {CAN0_MSG_Mod3_Cellvolt_0}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_0 */
    { {CAN0_MSG_Mod3_Cellvolt_0}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_1 */
    { {CAN0_MSG_Mod3_Cellvolt_0}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_2 */
    { {CAN0_MSG_Mod3_Cellvolt_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_valid_3_5 */
    { {CAN0_MSG_Mod3_Cellvolt_1}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_3 */
    { {CAN0_MSG_Mod3_Cellvolt_1}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_4 */
    { {CAN0_MSG_Mod3_Cellvolt_1}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_5 */
    { {CAN0_MSG_Mod3_Cellvolt_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_valid_6_8 */
    { {CAN0_MSG_Mod3_Cellvolt_2}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_6 */
    { {CAN0_MSG_Mod3_Cellvolt_2}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_7 */
    { {CAN0_MSG_Mod3_Cellvolt_2}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_8 */
    { {CAN0_MSG_Mod3_Cellvolt_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_valid_9_11 */
    { {CAN0_MSG_Mod3_Cellvolt_3}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_9 */
    { {CAN0_MSG_Mod3_Cellvolt_3}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_10 */
    { {CAN0_MSG_Mod3_Cellvolt_3}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_11 */
    { {CAN0_MSG_Mod3_Cellvolt_4}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_valid_12_14 */
    { {CAN0_MSG_Mod3_Cellvolt_4}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_12 */
    { {CAN0_MSG_Mod3_Cellvolt_4}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_13 */
    { {CAN0_MSG_Mod3_Cellvolt_4}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_14 */
    { {CAN0_MSG_Mod3_Cellvolt_5}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_valid_15_17 */
    { {CAN0_MSG_Mod3_Cellvolt_5}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_15 */
    { {CAN0_MSG_Mod3_Cellvolt_5}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_16 */
    { {CAN0_MSG_Mod3_Cellvolt_5}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod3_volt_17 */

    /* Module 3 cell temperatures */
    { {CAN0_MSG_Mod3_Celltemp_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_volt_valid_0_2 */
    { {CAN0_MSG_Mod3_Celltemp_0}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_0 */
    { {CAN0_MSG_Mod3_Celltemp_0}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_1 */
    { {CAN0_MSG_Mod3_Celltemp_0}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_2 */
    { {CAN0_MSG_Mod3_Celltemp_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_volt_valid_3_5 */
    { {CAN0_MSG_Mod3_Celltemp_1}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_3 */
    { {CAN0_MSG_Mod3_Celltemp_1}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_4 */
    { {CAN0_MSG_Mod3_Celltemp_1}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_5 */
    { {CAN0_MSG_Mod3_Celltemp_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_volt_valid_6_8 */
    { {CAN0_MSG_Mod3_Celltemp_2}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_6 */
    { {CAN0_MSG_Mod3_Celltemp_2}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_7 */
    { {CAN0_MSG_Mod3_Celltemp_2}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_8 */
    { {CAN0_MSG_Mod3_Celltemp_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_volt_valid_9_11 */
    { {CAN0_MSG_Mod3_Celltemp_3}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_9 */
    { {CAN0_MSG_Mod3_Celltemp_3}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_10 */
    { {CAN0_MSG_Mod3_Celltemp_3}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod3_temp_11 */

    /* Module 4 cell voltages */
    { {CAN0_MSG_Mod4_Cellvolt_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_valid_0_2 */
    { {CAN0_MSG_Mod4_Cellvolt_0}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_0 */
    { {CAN0_MSG_Mod4_Cellvolt_0}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_1 */
    { {CAN0_MSG_Mod4_Cellvolt_0}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_2 */
    { {CAN0_MSG_Mod4_Cellvolt_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_valid_3_5 */
    { {CAN0_MSG_Mod4_Cellvolt_1}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_3 */
    { {CAN0_MSG_Mod4_Cellvolt_1}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_4 */
    { {CAN0_MSG_Mod4_Cellvolt_1}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_5 */
    { {CAN0_MSG_Mod4_Cellvolt_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_valid_6_8 */
    { {CAN0_MSG_Mod4_Cellvolt_2}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_6 */
    { {CAN0_MSG_Mod4_Cellvolt_2}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_7 */
    { {CAN0_MSG_Mod4_Cellvolt_2}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_8 */
    { {CAN0_MSG_Mod4_Cellvolt_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_valid_9_11 */
    { {CAN0_MSG_Mod4_Cellvolt_3}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_9 */
    { {CAN0_MSG_Mod4_Cellvolt_3}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_10 */
    { {CAN0_MSG_Mod4_Cellvolt_3}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod4_volt_11 */
    { {CAN0_MSG_Mod4_Cellvolt_4}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_valid_12_14 */
    { {CAN0_MSG_Mod4_Cellvolt_4}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_12 */
    { {CAN0_MSG_Mod4_Cellvolt_4}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_13 */
    { {CAN0_MSG_Mod4_Cellvolt_4}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_14 */
    { {CAN0_MSG_Mod4_Cellvolt_5}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_valid_15_17 */
    { {CAN0_MSG_Mod4_Cellvolt_5}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_15 */
    { {CAN0_MSG_Mod4_Cellvolt_5}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_16 */
    { {CAN0_MSG_Mod4_Cellvolt_5}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_17 */

    /* Module 4 cell temperatures */
    { {CAN0_MSG_Mod4_Celltemp_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_volt_valid_0_2 */
    { {CAN0_MSG_Mod4_Celltemp_0}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_0 */
    { {CAN0_MSG_Mod4_Celltemp_0}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_1 */
    { {CAN0_MSG_Mod4_Celltemp_0}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_2 */
    { {CAN0_MSG_Mod4_Celltemp_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_volt_valid_3_5 */
    { {CAN0_MSG_Mod4_Celltemp_1}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_3 */
    { {CAN0_MSG_Mod4_Celltemp_1}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_4 */
    { {CAN0_MSG_Mod4_Celltemp_1}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_5 */
    { {CAN0_MSG_Mod4_Celltemp_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_volt_valid_6_8 */
    { {CAN0_MSG_Mod4_Celltemp_2}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_6 */
    { {CAN0_MSG_Mod4_Celltemp_2}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_7 */
    { {CAN0_MSG_Mod4_Celltemp_2}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_8 */
    { {CAN0_MSG_Mod4_Celltemp_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_volt_valid_9_11 */
    { {CAN0_MSG_Mod4_Celltemp_3}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_9 */
    { {CAN0_MSG_Mod4_Celltemp_3}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_10 */
    { {CAN0_MSG_Mod4_Celltemp_3}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_11 */

    /* Module 5 cell voltages */
    { {CAN0_MSG_Mod5_Cellvolt_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_valid_0_2 */
    { {CAN0_MSG_Mod5_Cellvolt_0}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_0 */
    { {CAN0_MSG_Mod5_Cellvolt_0}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_1 */
    { {CAN0_MSG_Mod5_Cellvolt_0}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_2 */
    { {CAN0_MSG_Mod5_Cellvolt_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_valid_3_5 */
    { {CAN0_MSG_Mod5_Cellvolt_1}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_3 */
    { {CAN0_MSG_Mod5_Cellvolt_1}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_4 */
    { {CAN0_MSG_Mod5_Cellvolt_1}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_5 */
    { {CAN0_MSG_Mod5_Cellvolt_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_valid_6_8 */
    { {CAN0_MSG_Mod5_Cellvolt_2}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_6 */
    { {CAN0_MSG_Mod5_Cellvolt_2}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_7 */
    { {CAN0_MSG_Mod5_Cellvolt_2}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_8 */
    { {CAN0_MSG_Mod5_Cellvolt_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_valid_9_11 */
    { {CAN0_MSG_Mod5_Cellvolt_3}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_9 */
    { {CAN0_MSG_Mod5_Cellvolt_3}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_10 */
    { {CAN0_MSG_Mod5_Cellvolt_3}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_11 */
    { {CAN0_MSG_Mod5_Cellvolt_4}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_valid_12_14 */
    { {CAN0_MSG_Mod5_Cellvolt_4}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_12 */
    { {CAN0_MSG_Mod5_Cellvolt_4}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_13 */
    { {CAN0_MSG_Mod5_Cellvolt_4}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_14 */
    { {CAN0_MSG_Mod5_Cellvolt_5}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_valid_15_17 */
    { {CAN0_MSG_Mod5_Cellvolt_5}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_15 */
    { {CAN0_MSG_Mod5_Cellvolt_5}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_16 */
    { {CAN0_MSG_Mod5_Cellvolt_5}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod5_volt_17 */

    /* Module 5 cell temperatures */
    { {CAN0_MSG_Mod5_Celltemp_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_volt_valid_0_2 */
    { {CAN0_MSG_Mod5_Celltemp_0}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_0 */
    { {CAN0_MSG_Mod5_Celltemp_0}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_1 */
    { {CAN0_MSG_Mod5_Celltemp_0}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_2 */
    { {CAN0_MSG_Mod5_Celltemp_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_volt_valid_3_5 */
    { {CAN0_MSG_Mod5_Celltemp_1}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_3 */
    { {CAN0_MSG_Mod5_Celltemp_1}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_4 */
    { {CAN0_MSG_Mod5_Celltemp_1}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_5 */
    { {CAN0_MSG_Mod5_Celltemp_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_volt_valid_6_8 */
    { {CAN0_MSG_Mod5_Celltemp_2}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_6 */
    { {CAN0_MSG_Mod5_Celltemp_2}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_7 */
    { {CAN0_MSG_Mod5_Celltemp_2}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_8 */
    { {CAN0_MSG_Mod5_Celltemp_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_volt_valid_9_11 */
    { {CAN0_MSG_Mod5_Celltemp_3}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_9 */
    { {CAN0_MSG_Mod5_Celltemp_3}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_10 */
    { {CAN0_MSG_Mod5_Celltemp_3}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod5_temp_11 */

    /* Module 6 cell voltages */
    { {CAN0_MSG_Mod6_Cellvolt_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_valid_0_2 */
    { {CAN0_MSG_Mod6_Cellvolt_0}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_0 */
    { {CAN0_MSG_Mod6_Cellvolt_0}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_1 */
    { {CAN0_MSG_Mod6_Cellvolt_0}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_2 */
    { {CAN0_MSG_Mod6_Cellvolt_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_valid_3_5 */
    { {CAN0_MSG_Mod6_Cellvolt_1}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_3 */
    { {CAN0_MSG_Mod6_Cellvolt_1}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_4 */
    { {CAN0_MSG_Mod6_Cellvolt_1}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_5 */
    { {CAN0_MSG_Mod6_Cellvolt_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_valid_6_8 */
    { {CAN0_MSG_Mod6_Cellvolt_2}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_6 */
    { {CAN0_MSG_Mod6_Cellvolt_2}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_7 */
    { {CAN0_MSG_Mod6_Cellvolt_2}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_8 */
    { {CAN0_MSG_Mod6_Cellvolt_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_valid_9_11 */
    { {CAN0_MSG_Mod6_Cellvolt_3}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_9 */
    { {CAN0_MSG_Mod6_Cellvolt_3}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_10 */
    { {CAN0_MSG_Mod6_Cellvolt_3}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_11 */
    { {CAN0_MSG_Mod6_Cellvolt_4}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_valid_12_14 */
    { {CAN0_MSG_Mod6_Cellvolt_4}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_12 */
    { {CAN0_MSG_Mod6_Cellvolt_4}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_13 */
    { {CAN0_MSG_Mod6_Cellvolt_4}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_14 */
    { {CAN0_MSG_Mod6_Cellvolt_5}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_valid_15_17 */
    { {CAN0_MSG_Mod6_Cellvolt_5}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_15 */
    { {CAN0_MSG_Mod6_Cellvolt_5}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_16 */
    { {CAN0_MSG_Mod6_Cellvolt_5}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod6_volt_17 */

    /* Module 6 cell temperatures */
    { {CAN0_MSG_Mod6_Celltemp_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_volt_valid_0_2 */
    { {CAN0_MSG_Mod6_Celltemp_0}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_0 */
    { {CAN0_MSG_Mod6_Celltemp_0}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_1 */
    { {CAN0_MSG_Mod6_Celltemp_0}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_2 */
    { {CAN0_MSG_Mod6_Celltemp_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_volt_valid_3_5 */
    { {CAN0_MSG_Mod6_Celltemp_1}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_3 */
    { {CAN0_MSG_Mod6_Celltemp_1}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_4 */
    { {CAN0_MSG_Mod6_Celltemp_1}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_5 */
    { {CAN0_MSG_Mod6_Celltemp_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_volt_valid_6_8 */
    { {CAN0_MSG_Mod6_Celltemp_2}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_6 */
    { {CAN0_MSG_Mod6_Celltemp_2}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_7 */
    { {CAN0_MSG_Mod6_Celltemp_2}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_8 */
    { {CAN0_MSG_Mod6_Celltemp_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_volt_valid_9_11 */
    { {CAN0_MSG_Mod6_Celltemp_3}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_9 */
    { {CAN0_MSG_Mod6_Celltemp_3}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_10 */
    { {CAN0_MSG_Mod6_Celltemp_3}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod6_temp_11 */

    /* Module 7 cell voltages */
    { {CAN0_MSG_Mod7_Cellvolt_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_valid_0_2 */
    { {CAN0_MSG_Mod7_Cellvolt_0}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_0 */
    { {CAN0_MSG_Mod7_Cellvolt_0}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_1 */
    { {CAN0_MSG_Mod7_Cellvolt_0}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_2 */
    { {CAN0_MSG_Mod7_Cellvolt_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_valid_3_5 */
    { {CAN0_MSG_Mod7_Cellvolt_1}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_3 */
    { {CAN0_MSG_Mod7_Cellvolt_1}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_4 */
    { {CAN0_MSG_Mod7_Cellvolt_1}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_5 */
    { {CAN0_MSG_Mod7_Cellvolt_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_valid_6_8 */
    { {CAN0_MSG_Mod7_Cellvolt_2}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_6 */
    { {CAN0_MSG_Mod7_Cellvolt_2}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_7 */
    { {CAN0_MSG_Mod7_Cellvolt_2}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_8 */
    { {CAN0_MSG_Mod7_Cellvolt_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_valid_9_11 */
    { {CAN0_MSG_Mod7_Cellvolt_3}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_9 */
    { {CAN0_MSG_Mod7_Cellvolt_3}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_10 */
    { {CAN0_MSG_Mod7_Cellvolt_3}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_11 */
    { {CAN0_MSG_Mod7_Cellvolt_4}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_valid_12_14 */
    { {CAN0_MSG_Mod7_Cellvolt_4}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_12 */
    { {CAN0_MSG_Mod7_Cellvolt_4}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_13 */
    { {CAN0_MSG_Mod7_Cellvolt_4}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_14 */
    { {CAN0_MSG_Mod7_Cellvolt_5}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_valid_15_17 */
    { {CAN0_MSG_Mod7_Cellvolt_5}, 8, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_15 */
    { {CAN0_MSG_Mod7_Cellvolt_5}, 24, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_16 */
    { {CAN0_MSG_Mod7_Cellvolt_5}, 40, 16, 0, UINT16_MAX, 1, 0, NULL_PTR, &cans_getvolt },  /*!< CAN0_SIG_Mod7_volt_17 */

    /* Module 7 cell temperatures */
    { {CAN0_MSG_Mod7_Celltemp_0}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_volt_valid_0_2 */
    { {CAN0_MSG_Mod7_Celltemp_0}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_0 */
    { {CAN0_MSG_Mod7_Celltemp_0}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_1 */
    { {CAN0_MSG_Mod7_Celltemp_0}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_2 */
    { {CAN0_MSG_Mod7_Celltemp_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_volt_valid_3_5 */
    { {CAN0_MSG_Mod7_Celltemp_1}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_3 */
    { {CAN0_MSG_Mod7_Celltemp_1}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_4 */
    { {CAN0_MSG_Mod7_Celltemp_1}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_5 */
    { {CAN0_MSG_Mod7_Celltemp_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_volt_valid_6_8 */
    { {CAN0_MSG_Mod7_Celltemp_2}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_6 */
    { {CAN0_MSG_Mod7_Celltemp_2}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_7 */
    { {CAN0_MSG_Mod7_Celltemp_2}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_8 */
    { {CAN0_MSG_Mod7_Celltemp_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_volt_valid_9_11 */
    { {CAN0_MSG_Mod7_Celltemp_3}, 8, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_9 */
    { {CAN0_MSG_Mod7_Celltemp_3}, 24, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_10 */
    { {CAN0_MSG_Mod7_Celltemp_3}, 40, 16, -128, 527.35, 100, 128, NULL_PTR, &cans_gettemp },  /*!< CAN0_SIG_Mod4_temp_11 */

#ifdef CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED
        {{CAN0_MSG_BMS_CurrentTrigger}, 0, 32, 0, 0, 1, 0, NULL_PTR, &cans_gettriggercurrent }  /*!< CAN0_SIG_ISA_Trigger */
#endif /* CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED */
};


const CANS_signal_s cans_CAN1_signals_tx[] = {
};


const CANS_signal_s cans_CAN0_signals_rx[] = {
    { {CAN0_MSG_StateRequest}, 8, 8, 0, UINT8_MAX, 1, 0, &cans_setstaterequest, NULL_PTR },
    { {CAN0_MSG_IVT_Current}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS0_I_MuxID */
    { {CAN0_MSG_IVT_Current}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS0_I_Status */
    { {CAN0_MSG_IVT_Current}, 16, 32, INT32_MIN, INT32_MAX, 1, 0, &cans_setcurr, NULL_PTR },  /* CAN0_SIG_ISENS0_I_Measurement */
    { {CAN0_MSG_IVT_Voltage_1}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS1_U1_MuxID */
    { {CAN0_MSG_IVT_Voltage_1}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS1_U1_Status */
    { {CAN0_MSG_IVT_Voltage_1}, 16, 32, 0, INT32_MAX, 1, 0, &cans_setcurr, NULL_PTR },  /* CAN0_SIG_ISENS1_U1_Measurement */
    { {CAN0_MSG_IVT_Voltage_2}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS2_U2_MuxID */
    { {CAN0_MSG_IVT_Voltage_2}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS2_U2_Status */
    { {CAN0_MSG_IVT_Voltage_2}, 16, 32, 0, INT32_MAX, 1, 0, &cans_setcurr, NULL_PTR },  /* CAN0_SIG_ISENS2_U2_Measurement */
    { {CAN0_MSG_IVT_Voltage_3}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS3_U3_MuxID */
    { {CAN0_MSG_IVT_Voltage_3}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS3_U3_Status */
    { {CAN0_MSG_IVT_Voltage_3}, 16, 32, 0, INT32_MAX, 1, 0, &cans_setcurr, NULL_PTR },  /* CAN0_SIG_ISENS3_U3_Measurement */
    { {CAN0_MSG_IVT_Temperature}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS4_T_MuxID */
    { {CAN0_MSG_IVT_Temperature}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS4_T_Status */
    { {CAN0_MSG_IVT_Temperature}, 16, 32, INT32_MIN, INT32_MAX, 0.1, 0, &cans_setcurr, NULL_PTR },  /* CAN0_SIG_ISENS4_T_Measurement */
    { {CAN0_MSG_IVT_Power}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS5_P_MuxID */
    { {CAN0_MSG_IVT_Power}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS5_P_Status */
    { {CAN0_MSG_IVT_Power}, 16, 32, INT32_MIN, INT32_MAX, 1, 0, &cans_setcurr, NULL_PTR },  /* CAN0_SIG_ISENS5_P_Measurement */
    { {CAN0_MSG_IVT_CoulombCount}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS6_CC_MuxID */
    { {CAN0_MSG_IVT_CoulombCount}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS6_CC_Status */
    { {CAN0_MSG_IVT_CoulombCount}, 16, 32, INT32_MIN, INT32_MAX, 1, 0, &cans_setcurr, NULL_PTR },  /* CAN0_SIG_ISENS6_CC_Measurement */
    { {CAN0_MSG_IVT_EnergyCount}, 0, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS7_EC_MuxID */
    { {CAN0_MSG_IVT_EnergyCount}, 8, 8, 0, UINT8_MAX, 1, 0, NULL_PTR, NULL_PTR },  /* CAN0_SIG_ISENS7_EC_Status */
    { {CAN0_MSG_IVT_EnergyCount}, 16, 32, INT32_MIN, INT32_MAX, 1, 0, &cans_setcurr, NULL_PTR },  /* CAN0_SIG_ISENS7_EC_Measurement */
    { {CAN0_MSG_DEBUG}, 0, 64, 0, UINT64_MAX, 1, 0, &cans_setdebug, NULL_PTR },  /* CAN0_SIG_DEBUG_Data */
    { {CAN0_MSG_GetReleaseVersion}, 0, 64, 0, UINT64_MAX, 1, 0, &cans_setSWversion, NULL_PTR }  /* CAN0_SIG_DEBUG_Data */
};

const CANS_signal_s cans_CAN1_signals_rx[] = {
};


const uint16_t cans_CAN0_signals_tx_length = sizeof(cans_CAN0_signals_tx)/sizeof(cans_CAN0_signals_tx[0]);
const uint16_t cans_CAN1_signals_tx_length = sizeof(cans_CAN1_signals_tx)/sizeof(cans_CAN1_signals_tx[0]);

const uint16_t cans_CAN0_signals_rx_length = sizeof(cans_CAN0_signals_rx)/sizeof(cans_CAN0_signals_rx[0]);
const uint16_t cans_CAN1_signals_rx_length = sizeof(cans_CAN1_signals_rx)/sizeof(cans_CAN1_signals_rx[0]);

/*================== Static Function Implementations ========================*/

static uint32_t cans_getvolt(uint32_t sigIdx, void *value) {
    static DATA_BLOCK_CELLVOLTAGE_s volt_tab;
    uint16_t modIdx = 0;
    uint32_t cellIdx = 0;
    uint32_t tmp = 0;
    uint32_t tmpVal = 0;
    float canData = 0;

    /* first signal to transmit cell voltages */
    if (sigIdx == CAN0_SIG_Mod0_volt_valid_0_2) {
        DB_ReadBlock(&volt_tab, DATA_BLOCK_ID_CELLVOLTAGE);
    }

    /* Determine module and cell number */
    if (sigIdx - CAN0_SIG_Mod0_volt_valid_0_2 < CANS_MODULSIGNALS_VOLT) {
        modIdx = 0;
        cellIdx = sigIdx - CAN0_SIG_Mod0_volt_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod1_volt_valid_0_2 < CANS_MODULSIGNALS_VOLT) {
        modIdx = 1;
        cellIdx = sigIdx - CAN0_SIG_Mod1_volt_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod2_volt_valid_0_2 < CANS_MODULSIGNALS_VOLT) {
        modIdx = 2;
        cellIdx = sigIdx - CAN0_SIG_Mod2_volt_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod3_volt_valid_0_2 < CANS_MODULSIGNALS_VOLT) {
        modIdx = 3;
        cellIdx = sigIdx - CAN0_SIG_Mod3_volt_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod4_volt_valid_0_2 < CANS_MODULSIGNALS_VOLT) {
        modIdx = 4;
        cellIdx = sigIdx - CAN0_SIG_Mod4_volt_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod5_volt_valid_0_2 < CANS_MODULSIGNALS_VOLT) {
        modIdx = 5;
        cellIdx = sigIdx - CAN0_SIG_Mod5_volt_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod6_volt_valid_0_2 < CANS_MODULSIGNALS_VOLT) {
        modIdx = 6;
        cellIdx = sigIdx - CAN0_SIG_Mod6_volt_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod7_volt_valid_0_2 < CANS_MODULSIGNALS_VOLT) {
        modIdx = 7;
        cellIdx = sigIdx - CAN0_SIG_Mod7_volt_valid_0_2;
    }

    if (value != NULL_PTR) {
        switch (sigIdx) {
            case CAN0_SIG_Mod0_volt_valid_0_2:
            case CAN0_SIG_Mod1_volt_valid_0_2:
            case CAN0_SIG_Mod2_volt_valid_0_2:
            case CAN0_SIG_Mod3_volt_valid_0_2:
            case CAN0_SIG_Mod4_volt_valid_0_2:  /* Valid flags for cell voltages 0 - 2 */
            case CAN0_SIG_Mod5_volt_valid_0_2:
            case CAN0_SIG_Mod6_volt_valid_0_2:
            case CAN0_SIG_Mod7_volt_valid_0_2:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = volt_tab.valid_volt[modIdx];
                }
                *(uint32_t *)value = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_volt_valid_3_5:
            case CAN0_SIG_Mod1_volt_valid_3_5:
            case CAN0_SIG_Mod2_volt_valid_3_5:
            case CAN0_SIG_Mod3_volt_valid_3_5:
            case CAN0_SIG_Mod4_volt_valid_3_5:  /* Valid flags for cell voltages 3 - 5 */
            case CAN0_SIG_Mod5_volt_valid_3_5:
            case CAN0_SIG_Mod6_volt_valid_3_5:
            case CAN0_SIG_Mod7_volt_valid_3_5:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = volt_tab.valid_volt[modIdx] >> 3;
                }
                tmpVal = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_volt_valid_6_8:
            case CAN0_SIG_Mod1_volt_valid_6_8:
            case CAN0_SIG_Mod2_volt_valid_6_8:
            case CAN0_SIG_Mod3_volt_valid_6_8:
            case CAN0_SIG_Mod4_volt_valid_6_8:  /* Valid flags for cell voltages 6 - 8 */
            case CAN0_SIG_Mod5_volt_valid_6_8:
            case CAN0_SIG_Mod6_volt_valid_6_8:
            case CAN0_SIG_Mod7_volt_valid_6_8:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = volt_tab.valid_volt[modIdx] >> 6;
                }
                tmpVal = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_volt_valid_9_11:
            case CAN0_SIG_Mod1_volt_valid_9_11:
            case CAN0_SIG_Mod2_volt_valid_9_11:
            case CAN0_SIG_Mod3_volt_valid_9_11:
            case CAN0_SIG_Mod4_volt_valid_9_11:  /* Valid flags for cell voltages 9 - 11 */
            case CAN0_SIG_Mod5_volt_valid_9_11:
            case CAN0_SIG_Mod6_volt_valid_9_11:
            case CAN0_SIG_Mod7_volt_valid_9_11:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = volt_tab.valid_volt[modIdx] >> 9;
                }
                tmpVal = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_volt_valid_12_14:
            case CAN0_SIG_Mod1_volt_valid_12_14:
            case CAN0_SIG_Mod2_volt_valid_12_14:
            case CAN0_SIG_Mod3_volt_valid_12_14:
            case CAN0_SIG_Mod4_volt_valid_12_14:  /* Valid flags for cell voltages 12 - 14 */
            case CAN0_SIG_Mod5_volt_valid_12_14:
            case CAN0_SIG_Mod6_volt_valid_12_14:
            case CAN0_SIG_Mod7_volt_valid_12_14:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = volt_tab.valid_volt[modIdx] >> 12;
                }
                tmpVal = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_volt_valid_15_17:
            case CAN0_SIG_Mod1_volt_valid_15_17:
            case CAN0_SIG_Mod2_volt_valid_15_17:
            case CAN0_SIG_Mod3_volt_valid_15_17:
            case CAN0_SIG_Mod4_volt_valid_15_17:  /* Valid flags for cell voltages 15 - 17 */
            case CAN0_SIG_Mod5_volt_valid_15_17:
            case CAN0_SIG_Mod6_volt_valid_15_17:
            case CAN0_SIG_Mod7_volt_valid_15_17:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = volt_tab.valid_volt[modIdx] >> 15;
                }
                tmpVal = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_volt_0:
            case CAN0_SIG_Mod0_volt_1:
            case CAN0_SIG_Mod0_volt_2:
            case CAN0_SIG_Mod1_volt_0:
            case CAN0_SIG_Mod1_volt_1:
            case CAN0_SIG_Mod1_volt_2:
            case CAN0_SIG_Mod2_volt_0:
            case CAN0_SIG_Mod2_volt_1:
            case CAN0_SIG_Mod2_volt_2:
            case CAN0_SIG_Mod3_volt_0:
            case CAN0_SIG_Mod3_volt_1:
            case CAN0_SIG_Mod3_volt_2:
            case CAN0_SIG_Mod4_volt_0:
            case CAN0_SIG_Mod4_volt_1:
            case CAN0_SIG_Mod4_volt_2:
            case CAN0_SIG_Mod5_volt_0:
            case CAN0_SIG_Mod5_volt_1:
            case CAN0_SIG_Mod5_volt_2:
            case CAN0_SIG_Mod6_volt_0:
            case CAN0_SIG_Mod6_volt_1:
            case CAN0_SIG_Mod6_volt_2:
            case CAN0_SIG_Mod7_volt_0:
            case CAN0_SIG_Mod7_volt_1:
            case CAN0_SIG_Mod7_volt_2:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                if ((modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx >= BS_NR_OF_BAT_CELLS) {
                    tmpVal = CAN_DEFAULT_VOLTAGE;
                } else {
                    tmpVal = volt_tab.voltage[(modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx];
                }
                break;

            case CAN0_SIG_Mod0_volt_3:
            case CAN0_SIG_Mod0_volt_4:
            case CAN0_SIG_Mod0_volt_5:
            case CAN0_SIG_Mod1_volt_3:
            case CAN0_SIG_Mod1_volt_4:
            case CAN0_SIG_Mod1_volt_5:
            case CAN0_SIG_Mod2_volt_3:
            case CAN0_SIG_Mod2_volt_4:
            case CAN0_SIG_Mod2_volt_5:
            case CAN0_SIG_Mod3_volt_3:
            case CAN0_SIG_Mod3_volt_4:
            case CAN0_SIG_Mod3_volt_5:
            case CAN0_SIG_Mod4_volt_3:
            case CAN0_SIG_Mod4_volt_4:
            case CAN0_SIG_Mod4_volt_5:
            case CAN0_SIG_Mod5_volt_3:
            case CAN0_SIG_Mod5_volt_4:
            case CAN0_SIG_Mod5_volt_5:
            case CAN0_SIG_Mod6_volt_3:
            case CAN0_SIG_Mod6_volt_4:
            case CAN0_SIG_Mod6_volt_5:
            case CAN0_SIG_Mod7_volt_3:
            case CAN0_SIG_Mod7_volt_4:
            case CAN0_SIG_Mod7_volt_5:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_3_5 */
                if ((modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx >= BS_NR_OF_BAT_CELLS) {
                    tmpVal = CAN_DEFAULT_VOLTAGE;
                } else {
                    tmpVal = volt_tab.voltage[(modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx];
                }
                break;

            case CAN0_SIG_Mod0_volt_6:
            case CAN0_SIG_Mod0_volt_7:
            case CAN0_SIG_Mod0_volt_8:
            case CAN0_SIG_Mod1_volt_6:
            case CAN0_SIG_Mod1_volt_7:
            case CAN0_SIG_Mod1_volt_8:
            case CAN0_SIG_Mod2_volt_6:
            case CAN0_SIG_Mod2_volt_7:
            case CAN0_SIG_Mod2_volt_8:
            case CAN0_SIG_Mod3_volt_6:
            case CAN0_SIG_Mod3_volt_7:
            case CAN0_SIG_Mod3_volt_8:
            case CAN0_SIG_Mod4_volt_6:
            case CAN0_SIG_Mod4_volt_7:
            case CAN0_SIG_Mod4_volt_8:
            case CAN0_SIG_Mod5_volt_6:
            case CAN0_SIG_Mod5_volt_7:
            case CAN0_SIG_Mod5_volt_8:
            case CAN0_SIG_Mod6_volt_6:
            case CAN0_SIG_Mod6_volt_7:
            case CAN0_SIG_Mod6_volt_8:
            case CAN0_SIG_Mod7_volt_6:
            case CAN0_SIG_Mod7_volt_7:
            case CAN0_SIG_Mod7_volt_8:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_3_5 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_6_8 */
                if ((modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx >= BS_NR_OF_BAT_CELLS) {
                    tmpVal = CAN_DEFAULT_VOLTAGE;
                } else {
                    tmpVal = volt_tab.voltage[(modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx];
                }
                break;

            case CAN0_SIG_Mod0_volt_9:
            case CAN0_SIG_Mod0_volt_10:
            case CAN0_SIG_Mod0_volt_11:
            case CAN0_SIG_Mod1_volt_9:
            case CAN0_SIG_Mod1_volt_10:
            case CAN0_SIG_Mod1_volt_11:
            case CAN0_SIG_Mod2_volt_9:
            case CAN0_SIG_Mod2_volt_10:
            case CAN0_SIG_Mod2_volt_11:
            case CAN0_SIG_Mod3_volt_9:
            case CAN0_SIG_Mod3_volt_10:
            case CAN0_SIG_Mod3_volt_11:
            case CAN0_SIG_Mod4_volt_9:
            case CAN0_SIG_Mod4_volt_10:
            case CAN0_SIG_Mod4_volt_11:
            case CAN0_SIG_Mod5_volt_9:
            case CAN0_SIG_Mod5_volt_10:
            case CAN0_SIG_Mod5_volt_11:
            case CAN0_SIG_Mod6_volt_9:
            case CAN0_SIG_Mod6_volt_10:
            case CAN0_SIG_Mod6_volt_11:
            case CAN0_SIG_Mod7_volt_9:
            case CAN0_SIG_Mod7_volt_10:
            case CAN0_SIG_Mod7_volt_11:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_3_5 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_6_8 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_9_11 */
                if ((modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx >= BS_NR_OF_BAT_CELLS) {
                    tmpVal = CAN_DEFAULT_VOLTAGE;
                } else {
                    tmpVal = volt_tab.voltage[(modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx];
                }
                break;

            case CAN0_SIG_Mod0_volt_12:
            case CAN0_SIG_Mod0_volt_13:
            case CAN0_SIG_Mod0_volt_14:
            case CAN0_SIG_Mod1_volt_12:
            case CAN0_SIG_Mod1_volt_13:
            case CAN0_SIG_Mod1_volt_14:
            case CAN0_SIG_Mod2_volt_12:
            case CAN0_SIG_Mod2_volt_13:
            case CAN0_SIG_Mod2_volt_14:
            case CAN0_SIG_Mod3_volt_12:
            case CAN0_SIG_Mod3_volt_13:
            case CAN0_SIG_Mod3_volt_14:
            case CAN0_SIG_Mod4_volt_12:
            case CAN0_SIG_Mod4_volt_13:
            case CAN0_SIG_Mod4_volt_14:
            case CAN0_SIG_Mod5_volt_12:
            case CAN0_SIG_Mod5_volt_13:
            case CAN0_SIG_Mod5_volt_14:
            case CAN0_SIG_Mod6_volt_12:
            case CAN0_SIG_Mod6_volt_13:
            case CAN0_SIG_Mod6_volt_14:
            case CAN0_SIG_Mod7_volt_12:
            case CAN0_SIG_Mod7_volt_13:
            case CAN0_SIG_Mod7_volt_14:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_3_5 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_6_8 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_9_11 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_12_14 */
                if ((modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx >= BS_NR_OF_BAT_CELLS) {
                    tmpVal = CAN_DEFAULT_VOLTAGE;
                } else {
                    tmpVal = volt_tab.voltage[(modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx];
                }
                break;

            case CAN0_SIG_Mod0_volt_15:
            case CAN0_SIG_Mod0_volt_16:
            case CAN0_SIG_Mod0_volt_17:
            case CAN0_SIG_Mod1_volt_15:
            case CAN0_SIG_Mod1_volt_16:
            case CAN0_SIG_Mod1_volt_17:
            case CAN0_SIG_Mod2_volt_15:
            case CAN0_SIG_Mod2_volt_16:
            case CAN0_SIG_Mod2_volt_17:
            case CAN0_SIG_Mod3_volt_15:
            case CAN0_SIG_Mod3_volt_16:
            case CAN0_SIG_Mod3_volt_17:
            case CAN0_SIG_Mod4_volt_15:
            case CAN0_SIG_Mod4_volt_16:
            case CAN0_SIG_Mod4_volt_17:
            case CAN0_SIG_Mod5_volt_15:
            case CAN0_SIG_Mod5_volt_16:
            case CAN0_SIG_Mod5_volt_17:
            case CAN0_SIG_Mod6_volt_15:
            case CAN0_SIG_Mod6_volt_16:
            case CAN0_SIG_Mod6_volt_17:
            case CAN0_SIG_Mod7_volt_15:
            case CAN0_SIG_Mod7_volt_16:
            case CAN0_SIG_Mod7_volt_17:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_3_5 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_6_8 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_9_11 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_12_14 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_volt_valid_15_17 */
                if ((modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx >= BS_NR_OF_BAT_CELLS) {
                    tmpVal = CAN_DEFAULT_VOLTAGE;
                } else {
                    tmpVal = volt_tab.voltage[(modIdx * BS_NR_OF_BAT_CELLS_PER_MODULE) + cellIdx];
                }
                break;

            default:
                break;
        }
        /* Check limits */
        canData = cans_checkLimits((float)tmpVal, sigIdx);
        /* Apply offset and factor */
        *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
    }

    return 0;
}

uint32_t cans_gettemp(uint32_t sigIdx, void *value) {
    static DATA_BLOCK_CELLTEMPERATURE_s temp_tab;
    uint16_t modIdx = 0;
    uint32_t cellIdx = 0;
    uint32_t tmp = 0;
    float tmpVal = 0;
    float canData = 0;

    /* first signal to transmit cell temperatures */
    if (sigIdx == CAN0_SIG_Mod0_temp_valid_0_2) {
        DB_ReadBlock(&temp_tab, DATA_BLOCK_ID_CELLTEMPERATURE);
    }

    /* Determine module and cell number */
    if (sigIdx - CAN0_SIG_Mod0_temp_valid_0_2 < CANS_MODULSIGNALS_TEMP) {
        modIdx = 0;
        cellIdx = sigIdx - CAN0_SIG_Mod0_temp_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod1_temp_valid_0_2 < CANS_MODULSIGNALS_TEMP) {
        modIdx = 1;
        cellIdx = sigIdx - CAN0_SIG_Mod1_temp_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod2_temp_valid_0_2 < CANS_MODULSIGNALS_TEMP) {
        modIdx = 2;
        cellIdx = sigIdx - CAN0_SIG_Mod2_temp_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod3_temp_valid_0_2 < CANS_MODULSIGNALS_TEMP) {
        modIdx = 3;
        cellIdx = sigIdx - CAN0_SIG_Mod3_temp_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod4_temp_valid_0_2 < CANS_MODULSIGNALS_TEMP) {
        modIdx = 4;
        cellIdx = sigIdx - CAN0_SIG_Mod4_temp_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod5_temp_valid_0_2 < CANS_MODULSIGNALS_TEMP) {
        modIdx = 5;
        cellIdx = sigIdx - CAN0_SIG_Mod5_temp_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod6_temp_valid_0_2 < CANS_MODULSIGNALS_TEMP) {
        modIdx = 6;
        cellIdx = sigIdx - CAN0_SIG_Mod6_temp_valid_0_2;
    } else if (sigIdx - CAN0_SIG_Mod7_temp_valid_0_2 < CANS_MODULSIGNALS_TEMP) {
        modIdx = 7;
        cellIdx = sigIdx - CAN0_SIG_Mod7_temp_valid_0_2;
    }

    if (value != NULL_PTR) {
        switch (sigIdx) {
            case CAN0_SIG_Mod0_temp_valid_0_2:
            case CAN0_SIG_Mod1_temp_valid_0_2:
            case CAN0_SIG_Mod2_temp_valid_0_2:
            case CAN0_SIG_Mod3_temp_valid_0_2:
            case CAN0_SIG_Mod4_temp_valid_0_2:
            case CAN0_SIG_Mod5_temp_valid_0_2:
            case CAN0_SIG_Mod6_temp_valid_0_2:
            case CAN0_SIG_Mod7_temp_valid_0_2:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = temp_tab.valid_temperature[modIdx];
                }
                tmpVal = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_temp_valid_3_5:
            case CAN0_SIG_Mod1_temp_valid_3_5:
            case CAN0_SIG_Mod2_temp_valid_3_5:
            case CAN0_SIG_Mod3_temp_valid_3_5:
            case CAN0_SIG_Mod4_temp_valid_3_5:
            case CAN0_SIG_Mod5_temp_valid_3_5:
            case CAN0_SIG_Mod6_temp_valid_3_5:
            case CAN0_SIG_Mod7_temp_valid_3_5:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = temp_tab.valid_temperature[modIdx] >> 3;
                }
                tmpVal = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_temp_valid_6_8:
            case CAN0_SIG_Mod1_temp_valid_6_8:
            case CAN0_SIG_Mod2_temp_valid_6_8:
            case CAN0_SIG_Mod3_temp_valid_6_8:
            case CAN0_SIG_Mod4_temp_valid_6_8:
            case CAN0_SIG_Mod5_temp_valid_6_8:
            case CAN0_SIG_Mod6_temp_valid_6_8:
            case CAN0_SIG_Mod7_temp_valid_6_8:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = temp_tab.valid_temperature[modIdx] >> 6;
                }
                tmpVal = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_temp_valid_9_11:
            case CAN0_SIG_Mod1_temp_valid_9_11:
            case CAN0_SIG_Mod2_temp_valid_9_11:
            case CAN0_SIG_Mod3_temp_valid_9_11:
            case CAN0_SIG_Mod4_temp_valid_9_11:
            case CAN0_SIG_Mod5_temp_valid_9_11:
            case CAN0_SIG_Mod6_temp_valid_9_11:
            case CAN0_SIG_Mod7_temp_valid_9_11:
                if (modIdx >= BS_NR_OF_MODULES) {
                    tmpVal = CAN_DEFAULT_VALID_FLAG;
                } else {
                    tmp = temp_tab.valid_temperature[modIdx] >> 9;
                }
                tmpVal = 0x07 & tmp;
                break;

            case CAN0_SIG_Mod0_temp_0:
            case CAN0_SIG_Mod0_temp_1:
            case CAN0_SIG_Mod0_temp_2:
            case CAN0_SIG_Mod1_temp_0:
            case CAN0_SIG_Mod1_temp_1:
            case CAN0_SIG_Mod1_temp_2:
            case CAN0_SIG_Mod2_temp_0:
            case CAN0_SIG_Mod2_temp_1:
            case CAN0_SIG_Mod2_temp_2:
            case CAN0_SIG_Mod3_temp_0:
            case CAN0_SIG_Mod3_temp_1:
            case CAN0_SIG_Mod3_temp_2:
            case CAN0_SIG_Mod4_temp_0:
            case CAN0_SIG_Mod4_temp_1:
            case CAN0_SIG_Mod4_temp_2:
            case CAN0_SIG_Mod5_temp_0:
            case CAN0_SIG_Mod5_temp_1:
            case CAN0_SIG_Mod5_temp_2:
            case CAN0_SIG_Mod6_temp_0:
            case CAN0_SIG_Mod6_temp_1:
            case CAN0_SIG_Mod6_temp_2:
            case CAN0_SIG_Mod7_temp_0:
            case CAN0_SIG_Mod7_temp_1:
            case CAN0_SIG_Mod7_temp_2:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                if ((modIdx * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + cellIdx >= BS_NR_OF_TEMP_SENSORS) {
                    tmpVal = CAN_DEFAULT_TEMPERATURE;
                } else {
                    tmpVal = temp_tab.temperature[(modIdx * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + cellIdx];
                }
                break;

            case CAN0_SIG_Mod0_temp_3:
            case CAN0_SIG_Mod0_temp_4:
            case CAN0_SIG_Mod0_temp_5:
            case CAN0_SIG_Mod1_temp_3:
            case CAN0_SIG_Mod1_temp_4:
            case CAN0_SIG_Mod1_temp_5:
            case CAN0_SIG_Mod2_temp_3:
            case CAN0_SIG_Mod2_temp_4:
            case CAN0_SIG_Mod2_temp_5:
            case CAN0_SIG_Mod3_temp_3:
            case CAN0_SIG_Mod3_temp_4:
            case CAN0_SIG_Mod3_temp_5:
            case CAN0_SIG_Mod4_temp_3:
            case CAN0_SIG_Mod4_temp_4:
            case CAN0_SIG_Mod4_temp_5:
            case CAN0_SIG_Mod5_temp_3:
            case CAN0_SIG_Mod5_temp_4:
            case CAN0_SIG_Mod5_temp_5:
            case CAN0_SIG_Mod6_temp_3:
            case CAN0_SIG_Mod6_temp_4:
            case CAN0_SIG_Mod6_temp_5:
            case CAN0_SIG_Mod7_temp_3:
            case CAN0_SIG_Mod7_temp_4:
            case CAN0_SIG_Mod7_temp_5:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_temp_valid_3_5 */
                if ((modIdx * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + cellIdx >= BS_NR_OF_TEMP_SENSORS) {
                    tmpVal = CAN_DEFAULT_TEMPERATURE;
                } else {
                    tmpVal = temp_tab.temperature[(modIdx * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + cellIdx];
                }
                break;

            case CAN0_SIG_Mod0_temp_6:
            case CAN0_SIG_Mod0_temp_7:
            case CAN0_SIG_Mod0_temp_8:
            case CAN0_SIG_Mod1_temp_6:
            case CAN0_SIG_Mod1_temp_7:
            case CAN0_SIG_Mod1_temp_8:
            case CAN0_SIG_Mod2_temp_6:
            case CAN0_SIG_Mod2_temp_7:
            case CAN0_SIG_Mod2_temp_8:
            case CAN0_SIG_Mod3_temp_6:
            case CAN0_SIG_Mod3_temp_7:
            case CAN0_SIG_Mod3_temp_8:
            case CAN0_SIG_Mod4_temp_6:
            case CAN0_SIG_Mod4_temp_7:
            case CAN0_SIG_Mod4_temp_8:
            case CAN0_SIG_Mod5_temp_6:
            case CAN0_SIG_Mod5_temp_7:
            case CAN0_SIG_Mod5_temp_8:
            case CAN0_SIG_Mod6_temp_6:
            case CAN0_SIG_Mod6_temp_7:
            case CAN0_SIG_Mod6_temp_8:
            case CAN0_SIG_Mod7_temp_6:
            case CAN0_SIG_Mod7_temp_7:
            case CAN0_SIG_Mod7_temp_8:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_temp_valid_3_5 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_temp_valid_6_8 */
                if ((modIdx * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + cellIdx >= BS_NR_OF_TEMP_SENSORS) {
                    tmpVal = CAN_DEFAULT_TEMPERATURE;
                } else {
                    tmpVal = temp_tab.temperature[(modIdx * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + cellIdx];
                }
                break;

            case CAN0_SIG_Mod0_temp_9:
            case CAN0_SIG_Mod0_temp_10:
            case CAN0_SIG_Mod0_temp_11:
            case CAN0_SIG_Mod1_temp_9:
            case CAN0_SIG_Mod1_temp_10:
            case CAN0_SIG_Mod1_temp_11:
            case CAN0_SIG_Mod2_temp_9:
            case CAN0_SIG_Mod2_temp_10:
            case CAN0_SIG_Mod2_temp_11:
            case CAN0_SIG_Mod3_temp_9:
            case CAN0_SIG_Mod3_temp_10:
            case CAN0_SIG_Mod3_temp_11:
            case CAN0_SIG_Mod4_temp_9:
            case CAN0_SIG_Mod4_temp_10:
            case CAN0_SIG_Mod4_temp_11:
            case CAN0_SIG_Mod5_temp_9:
            case CAN0_SIG_Mod5_temp_10:
            case CAN0_SIG_Mod5_temp_11:
            case CAN0_SIG_Mod6_temp_9:
            case CAN0_SIG_Mod6_temp_10:
            case CAN0_SIG_Mod6_temp_11:
            case CAN0_SIG_Mod7_temp_9:
            case CAN0_SIG_Mod7_temp_10:
            case CAN0_SIG_Mod7_temp_11:
                cellIdx--;  /* Because cell 0 - valid flag = 1, decrement by one to get the right index */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_temp_valid_3_5 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_temp_valid_6_8 */
                cellIdx--;  /* Because of signal: CAN0_SIG_Modx_temp_valid_9_11 */
                if ((modIdx * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + cellIdx >= BS_NR_OF_TEMP_SENSORS) {
                    tmpVal = CAN_DEFAULT_TEMPERATURE;
                } else {
                    tmpVal = temp_tab.temperature[(modIdx * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + cellIdx];
                }
                break;

            default:
                break;
        }
        /* Check limits */
        canData = cans_checkLimits((float)tmpVal, sigIdx);
        /* Apply offset and factor */
        *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
    }

    return 0;
}


uint32_t cans_gettempering(uint32_t sigIdx, void *value) {
    if (value != NULL_PTR) {
        switch (sigIdx) {
            case CAN0_SIG_CoolingNeeded:
                *(uint32_t *)value = 0;
                break;

            case CAN0_SIG_HeatingNeeded:
                *(uint32_t *)value = 0;
                break;

            case CAN0_SIG_TemperingDemand:
                *(uint32_t *)value = 0;
                break;

            default:
                *(uint32_t *)value = 0;
                break;
        }
    }
    return 0;
}


uint32_t cans_getcanerr(uint32_t sigIdx, void *value) {
    static DATA_BLOCK_ERRORSTATE_s canerr_tab;
    static DATA_BLOCK_MSL_FLAG_s canMSL_tab;
    static DATA_BLOCK_RSL_FLAG_s canRSL_tab;
    static DATA_BLOCK_MOL_FLAG_s canMOL_tab;
    static DATA_BLOCK_CONTFEEDBACK_s cancontfeedback_tab;
    static DATA_BLOCK_ILCKFEEDBACK_s canilckfeedback_tab;
    static DATA_BLOCK_BALANCING_CONTROL_s balancing_tab;
    static DATA_BLOCK_SYSTEMSTATE_s systemstate_tab;

    static uint8_t tmp = 0;

    if (value != NULL_PTR) {
        switch (sigIdx) {
            case CAN0_SIG_GS0_general_error:

                /* First signal in CAN_MSG_GeneralState messages -> get database entry */
                DB_ReadBlock(&canerr_tab, DATA_BLOCK_ID_ERRORSTATE);
                DB_ReadBlock(&canMSL_tab, DATA_BLOCK_ID_MSL);
                DB_ReadBlock(&canRSL_tab, DATA_BLOCK_ID_RSL);
                DB_ReadBlock(&canMOL_tab, DATA_BLOCK_ID_MOL);
                tmp = 0;

                /* Check maximum safety limit flags */
                if (canMSL_tab.over_current_charge_cell    == 1 ||
                    canMSL_tab.over_current_discharge_cell == 1 ||
                    canMSL_tab.over_current_charge_pl0     == 1 ||
                    canMSL_tab.over_current_discharge_pl0  == 1 ||
                    canMSL_tab.over_current_charge_pl1     == 1 ||
                    canMSL_tab.over_current_discharge_pl1  == 1 ||
                    canMSL_tab.over_voltage                == 1 ||
                    canMSL_tab.under_voltage               == 1 ||
                    canMSL_tab.over_temperature_charge     == 1 ||
                    canMSL_tab.over_temperature_discharge  == 1 ||
                    canMSL_tab.under_temperature_charge    == 1 ||
                    canMSL_tab.under_temperature_discharge == 1 ||
                /* Check system error flags */
                    canerr_tab.deepDischargeDetected     == 1 ||
                    canerr_tab.main_plus                 == 1 ||
                    canerr_tab.main_minus                == 1 ||
                    canerr_tab.precharge                 == 1 ||
                    canerr_tab.charge_main_plus          == 1 ||
                    canerr_tab.charge_main_minus         == 1 ||
                    canerr_tab.charge_precharge          == 1 ||
                    canerr_tab.fuse_state_normal         == 1 ||
                    canerr_tab.fuse_state_charge         == 1 ||
                    canerr_tab.interlock                 == 1 ||
                    canerr_tab.crc_error                 == 1 ||
                    canerr_tab.mux_error                 == 1 ||
                    canerr_tab.spi_error                 == 1 ||
                    canerr_tab.currentsensorresponding   == 1 ||
                    canerr_tab.open_wire                 == 1 ||
            #if BMS_OPEN_CONTACTORS_ON_INSULATION_ERROR == TRUE
                    canerr_tab.insulation_error          == 1 ||
            #endif /* BMS_OPEN_CONTACTORS_ON_INSULATION_ERROR */
                    canerr_tab.can_timing_cc             == 1 ||
                    canerr_tab.can_timing                == 1) {
                    /* set flag if error detected */
                    tmp |= 0x01 << 0;
                }
                /* Check recommended safety limit flags */
                if (canRSL_tab.over_current_charge_cell    == 1 ||
                    canRSL_tab.over_current_discharge_cell == 1 ||
                    canRSL_tab.over_current_charge_pl0     == 1 ||
                    canRSL_tab.over_current_discharge_pl0  == 1 ||
                    canRSL_tab.over_current_charge_pl1     == 1 ||
                    canRSL_tab.over_current_discharge_pl1  == 1 ||
                    canRSL_tab.over_voltage                == 1 ||
                    canRSL_tab.under_voltage               == 1 ||
                    canRSL_tab.over_temperature_charge     == 1 ||
                    canRSL_tab.over_temperature_discharge  == 1 ||
                    canRSL_tab.under_temperature_charge    == 1 ||
                    canRSL_tab.under_temperature_discharge == 1) {
                    /* set flag if error detected */
                    tmp |= 0x01 << 1;
                }
                /* Check maximum operating limit flags */
                if (canMOL_tab.over_current_charge_cell    == 1 ||
                    canMOL_tab.over_current_discharge_cell == 1 ||
                    canMOL_tab.over_current_charge_pl0     == 1 ||
                    canMOL_tab.over_current_discharge_pl0  == 1 ||
                    canMOL_tab.over_current_charge_pl1     == 1 ||
                    canMOL_tab.over_current_discharge_pl1  == 1 ||
                    canMOL_tab.over_voltage                == 1 ||
                    canMOL_tab.under_voltage               == 1 ||
                    canMOL_tab.over_temperature_charge     == 1 ||
                    canMOL_tab.over_temperature_discharge  == 1 ||
                    canMOL_tab.under_temperature_charge    == 1 ||
                    canMOL_tab.under_temperature_discharge == 1) {
                    /* set flag if error detected */
                    tmp |= 0x01 << 2;
                }
                *(uint32_t *)value = tmp;
                break;

            case CAN0_SIG_GS0_current_state:
                DB_ReadBlock(&systemstate_tab, DATA_BLOCK_ID_SYSTEMSTATE);
                *(uint32_t *)value = systemstate_tab.bms_state;
                break;
            case CAN0_SIG_GS0_error_overtemp_charge:
                tmp = 0;
                tmp |= canMOL_tab.over_temperature_charge << 2;
                tmp |= canRSL_tab.over_temperature_charge << 1;
                tmp |= canMSL_tab.over_temperature_charge;
                *(uint32_t *)value = tmp;
                break;
            case CAN0_SIG_GS0_error_undertemp_charge:
                tmp = 0;
                tmp |= canMOL_tab.under_temperature_charge << 2;
                tmp |= canRSL_tab.under_temperature_charge << 1;
                tmp |= canMSL_tab.under_temperature_charge;
                *(uint32_t *)value = tmp;
                break;
            case CAN0_SIG_GS0_error_overtemp_discharge:
                tmp = 0;
                tmp |= canMOL_tab.over_temperature_discharge << 2;
                tmp |= canRSL_tab.over_temperature_discharge << 1;
                tmp |= canMSL_tab.over_temperature_discharge;
                *(uint32_t *)value = tmp;
                break;
            case CAN0_SIG_GS0_error_undertemp_discharge:
                tmp = 0;
                tmp |= canMOL_tab.under_temperature_discharge << 2;
                tmp |= canRSL_tab.under_temperature_discharge << 1;
                tmp |= canMSL_tab.under_temperature_discharge;
                *(uint32_t *)value = tmp;
                break;
            case CAN0_SIG_GS0_error_overcurrent_charge:
                tmp = 0;
                tmp |= canMOL_tab.over_current_charge_cell << 2;
                tmp |= canMOL_tab.over_current_charge_pl0 << 2;
                tmp |= canMOL_tab.over_current_charge_pl1 << 2;
                tmp |= canRSL_tab.over_current_charge_cell << 1;
                tmp |= canRSL_tab.over_current_charge_pl0 << 1;
                tmp |= canRSL_tab.over_current_charge_pl1 << 1;
                tmp |= canMSL_tab.over_current_charge_cell;
                tmp |= canMSL_tab.over_current_charge_pl0;
                tmp |= canMSL_tab.over_current_charge_pl1;
                *(uint32_t *)value = tmp;
                break;
            case CAN0_SIG_GS0_error_overcurrent_discharge:
                tmp = 0;
                tmp |= canMOL_tab.over_current_discharge_cell << 2;
                tmp |= canMOL_tab.over_current_discharge_pl0 << 2;
                tmp |= canMOL_tab.over_current_discharge_pl1 << 2;
                tmp |= canRSL_tab.over_current_discharge_cell << 1;
                tmp |= canRSL_tab.over_current_discharge_pl0 << 1;
                tmp |= canRSL_tab.over_current_discharge_pl1 << 1;
                tmp |= canMSL_tab.over_current_discharge_cell;
                tmp |= canMSL_tab.over_current_discharge_pl0;
                tmp |= canMSL_tab.over_current_discharge_pl1;
                *(uint32_t *)value = tmp;
                break;
            case CAN0_SIG_GS1_error_overvoltage:
                tmp = 0;
                tmp |= canMOL_tab.over_voltage << 2;
                tmp |= canRSL_tab.over_voltage << 1;
                tmp |= canMSL_tab.over_voltage;
                *(uint32_t *)value = tmp;
                break;
            case CAN0_SIG_GS1_error_undervoltage:
                tmp = 0;
                tmp |= canMOL_tab.under_voltage << 2;
                tmp |= canRSL_tab.under_voltage << 1;
                tmp |= canMSL_tab.under_voltage;
                *(uint32_t *)value = tmp;
                break;
            case CAN0_SIG_GS1_error_deep_discharge:
                *(uint32_t *)value = canerr_tab.deepDischargeDetected;
                break;
            case CAN0_SIG_GS1_error_temperature_MCU0:
                *(uint32_t *)value = canerr_tab.mcuDieTemperature;
                break;
            case CAN0_SIG_GS1_error_contactor:
                *(uint32_t *)value = canerr_tab.main_plus | canerr_tab.main_minus | canerr_tab.precharge | canerr_tab.charge_main_plus | canerr_tab.charge_main_minus | canerr_tab.charge_precharge;
                break;
            case CAN0_SIG_GS1_error_selftest:
                *(uint32_t *)value = 0;
                break;
            case CAN0_SIG_GS1_error_cantiming:
                *(uint32_t *)value = canerr_tab.can_timing;
                break;
            case CAN0_SIG_GS1_current_sensor:
                *(uint32_t *)value = canerr_tab.currentsensorresponding | canerr_tab.can_timing_cc;
                break;
            case CAN0_SIG_GS1_balancing_active:

                /* only signal to use the balancing database entry */
                DB_ReadBlock(&balancing_tab, DATA_BLOCK_ID_BALANCING_CONTROL_VALUES);
                *(uint32_t *)value = balancing_tab.enable_balancing;
                break;

            case CAN0_SIG_GS2_state_cont_interlock:
                DB_ReadBlock(&cancontfeedback_tab, DATA_BLOCK_ID_CONTFEEDBACK);
                DB_ReadBlock(&canilckfeedback_tab, DATA_BLOCK_ID_ILCKFEEDBACK);
                cancontfeedback_tab.contactor_feedback &= ~(1 << 9);
                cancontfeedback_tab.contactor_feedback |= canilckfeedback_tab.interlock_feedback << 9;
                *(uint32_t *)value = cancontfeedback_tab.contactor_feedback;
                break;

            case CAN0_SIG_GS2_error_insulation:
                *(uint32_t *)value = canerr_tab.insulation_error;
                break;

            case CAN0_SIG_GS2_fuse_state:
                tmp = 0;
                if (canerr_tab.fuse_state_normal != 0) {
#if BS_CHECK_FUSE_PLACED_IN_NORMAL_PATH == TRUE
                    tmp |= 0x01;
#else /* BS_CHECK_FUSE_PLACED_IN_NORMAL_PATH == FALSE */
                    tmp |= 0x02;
#endif
                }
                if (canerr_tab.fuse_state_charge != 0) {
#if BS_CHECK_FUSE_PLACED_IN_CHARGE_PATH == TRUE
                    tmp |= 0x04;
#else /* BS_CHECK_FUSE_PLACED_IN_CHARGE_PATH == FALSE */
                    tmp |= 0x08;
#endif
                }
                *(uint32_t *)value = tmp;
                break;

            case CAN0_SIG_GS2_lowCoinCellVolt:
                *(uint32_t *)value = canerr_tab.coinCellVoltage;
                break;

            case CAN0_SIG_GS2_error_openWire:
                *(uint32_t *)value = canerr_tab.open_wire;
                break;

            case CAN0_SIG_GS2_daisyChain:
                tmp = 0;
                tmp |= canerr_tab.spi_error;
                tmp |= canerr_tab.crc_error << 1;
                tmp |= canerr_tab.mux_error << 2;
                *(uint32_t *)value = tmp;
                break;

            case CAN0_SIG_GS2_plausibilityCheck:
                *(uint32_t *)value = canerr_tab.plausibilityCheck;
                break;

            default:
                *(uint32_t *)value = 0;
                break;
        }
    }
    return 0;
}


uint32_t cans_getsoc(uint32_t sigIdx, void *value) {
    static DATA_BLOCK_SOX_s sox_tab;
    DB_ReadBlock(&sox_tab, DATA_BLOCK_ID_SOX);
    if (value != NULL_PTR) {
        switch (sigIdx) {
            case CAN0_SIG_SOC_mean:
                /* CAN signal resolution 0.01%, --> factor 100 */
                *(uint32_t *)value = (uint32_t)(sox_tab.soc_mean * cans_CAN0_signals_tx[sigIdx].factor);
                break;
            case CAN0_SIG_SOC_min:
                /* CAN signal resolution 0.01%, --> factor 100 */
                *(uint32_t *)value = (uint32_t)(sox_tab.soc_min * cans_CAN0_signals_tx[sigIdx].factor);
                break;
            case CAN0_SIG_SOC_max:
                /* CAN signal resolution 0.01%, --> factor 100 */
                *(uint32_t *)value = (uint32_t)(sox_tab.soc_max * cans_CAN0_signals_tx[sigIdx].factor);
                break;
            default:
                *(uint32_t *)value = 50.0;
                break;
        }
    }
    return 0;
}


static uint32_t cans_getRecommendedOperatingCurrent(uint32_t sigIdx, void *value) {
    static DATA_BLOCK_SOF_s sof_tab;
    float canData = 0;

    if (value != NULL_PTR) {
        /* values transmitted in resolution of 10mA (16bit means 0A-655.35A) */
        switch (sigIdx) {
            case CAN0_SIG_RecChargeCurrent:
                /* first signal */
                DB_ReadBlock(&sof_tab, DATA_BLOCK_ID_SOF);

                /* Check limits */
                canData = cans_checkLimits((float)sof_tab.recommended_continuous_charge, sigIdx);
                /* Apply offset and factor */
                *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
                break;

            case CAN0_SIG_RecChargeCurrent_Peak:
                /* Check limits */
                canData = cans_checkLimits((float)sof_tab.recommended_peak_charge, sigIdx);
                /* Apply offset and factor */
                *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
                break;

            case CAN0_SIG_RecDischargeCurrent:
                /* Check limits */
                canData = cans_checkLimits((float)sof_tab.recommended_continuous_discharge, sigIdx);
                /* Apply offset and factor */
                *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
                break;

            case CAN0_SIG_RecDischargeCurrent_Peak:
                /* Check limits */
                canData = cans_checkLimits((float)sof_tab.recommended_peak_discharge, sigIdx);
                /* Apply offset and factor */
                *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
                break;

            default:
                break;
        }
    }
    return 0;
}


static uint32_t cans_getMaxAllowedPower(uint32_t sigIdx, void *value) {
    if (value != NULL_PTR) {
        switch (sigIdx) {
            default:
                *(uint32_t *)value = 0;
                break;
        }
    }
    return 0;
}


static uint32_t cans_getminmaxvolt(uint32_t sigIdx, void *value) {
    static DATA_BLOCK_MINMAX_s minmax_volt_tab;
    float canData = 0;

    if (value != NULL_PTR) {
        switch (sigIdx) {
            case CAN0_SIG_Cellvolt_mean:
                /* First signal that is called */
                DB_ReadBlock(&minmax_volt_tab, DATA_BLOCK_ID_MINMAX);

                /* Check limits */
                canData = cans_checkLimits((float)minmax_volt_tab.voltage_mean, sigIdx);
                /* Apply offset and factor */
                *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
                break;

            case CAN0_SIG_Cellvolt_min:
                /* Check limits */
                canData = cans_checkLimits((float)minmax_volt_tab.voltage_min, sigIdx);
                /* Apply offset and factor */
                *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
                break;

            case CAN0_SIG_Cellvolt_max:
                /* Check limits */
                canData = cans_checkLimits((float)minmax_volt_tab.voltage_max, sigIdx);
                /* Apply offset and factor */
                *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
                break;

            case CAN0_SIG_ModNumber_volt_min:
                /* Check limits */
                canData = cans_checkLimits((float)minmax_volt_tab.voltage_module_number_min, sigIdx);
                /* Apply offset and factor */
                *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
                break;

            case CAN0_SIG_ModNumber_volt_max:
                /* Check limits */
                canData = cans_checkLimits((float)minmax_volt_tab.voltage_module_number_max, sigIdx);
                /* Apply offset and factor */
                *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
                break;

            default:
                *(uint32_t *)value = 0;
                break;
        }
    }
    return 0;
}

uint32_t cans_getminmaxtemp(uint32_t sigIdx, void *value) {
    static DATA_BLOCK_MINMAX_s minmax_temp_tab;
    float canData = 0;

    if (value != NULL_PTR) {
        switch (sigIdx) {
        case CAN0_SIG_Celltemp_mean:
            /* First signal that is called */
            DB_ReadBlock(&minmax_temp_tab, DATA_BLOCK_ID_MINMAX);

            /*  Check limits */
            canData = cans_checkLimits((float)minmax_temp_tab.temperature_mean, sigIdx);
            /* Apply offset and factor */
            *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
            break;

        case CAN0_SIG_Celltemp_min:
            /* Check limits */
            canData = cans_checkLimits((float)minmax_temp_tab.temperature_min, sigIdx);
            /* Apply offset and factor */
            *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
            break;

        case CAN0_SIG_Celltemp_max:
            /* Check limits */
            canData = cans_checkLimits((float)minmax_temp_tab.temperature_max, sigIdx);
            /* Apply offset and factor */
            *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
            break;

        case CAN0_SIG_ModNumber_temp_min:
            /* Check limits */
            canData = cans_checkLimits((float)minmax_temp_tab.temperature_module_number_min, sigIdx);
            /* Apply offset and factor */
            *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
            break;

        case CAN0_SIG_ModNumber_temp_max:
            /* Check limits */
            canData = cans_checkLimits((float)minmax_temp_tab.temperature_module_number_max, sigIdx);
            /* Apply offset and factor */
            *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
            break;

        default:
            *(uint32_t *)value = 0;
            break;
        }
    }
    return 0;
}


#ifdef CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED
uint32_t cans_gettriggercurrent(uint32_t sigIdx, void *value) {
    *(uint32_t *)value = 0x00FFFF31;
    return 0;
}
#endif /* CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED */


static uint32_t cans_getpower(uint32_t sigIdx, void *value) {
    uint32_t retVal = 0;
    float canData = 0;
    static DATA_BLOCK_MOVING_AVERAGE_s powMovMean_tab;

    if (value != NULL_PTR) {
       switch (sigIdx) {
           case CAN0_SIG_MovAverage_Power_1s:
               /* first signal to call function */
               DB_ReadBlock(&powMovMean_tab, DATA_BLOCK_ID_MOV_AVERAGE);
               /* Check limits */
               canData = cans_checkLimits((float)powMovMean_tab.movAverage_power_1s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Power_5s:
               /* Check limits */
               canData = cans_checkLimits((float)powMovMean_tab.movAverage_power_5s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Power_10s:
               /* Check limits */
               canData = cans_checkLimits((float)powMovMean_tab.movAverage_power_10s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Power_30s:
               /* Check limits */
               canData = cans_checkLimits((float)powMovMean_tab.movAverage_power_30s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Power_60s:
               /* Check limits */
               canData = cans_checkLimits((float)powMovMean_tab.movAverage_power_60s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Power_config:
               /* Check limits */
               canData = cans_checkLimits((float)powMovMean_tab.movAverage_power_config, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           default:
               *(uint32_t *)value = 0;
               break;
       }
    }
    return retVal;
}

static uint32_t cans_getcurr(uint32_t sigIdx, void *value) {
    uint32_t retVal = 0;
    float canData = 0;
    static DATA_BLOCK_MOVING_AVERAGE_s curMovMean_tab;

    if (value != NULL_PTR) {
       switch (sigIdx) {
           case CAN0_SIG_MovAverage_Current_1s:
               /* first signal to call function */
               DB_ReadBlock(&curMovMean_tab, DATA_BLOCK_ID_MOV_AVERAGE);
               /* Check limits */
               canData = cans_checkLimits((float)curMovMean_tab.movAverage_current_1s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Current_5s:
               /* Check limits */
               canData = cans_checkLimits((float)curMovMean_tab.movAverage_current_5s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Current_10s:
               /* Check limits */
               canData = cans_checkLimits((float)curMovMean_tab.movAverage_current_10s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Current_30s:
               /* Check limits */
               canData = cans_checkLimits((float)curMovMean_tab.movAverage_current_30s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Current_60s:
               /* Check limits */
               canData = cans_checkLimits((float)curMovMean_tab.movAverage_current_60s, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_MovAverage_Current_config:
               /* Check limits */
               canData = cans_checkLimits((float)curMovMean_tab.movAverage_current_config, sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           default:
                   *(uint32_t *)value = 0;
                   break;
       }
    }
    return retVal;
}


static uint32_t cans_getPackVoltage(uint32_t sigIdx, void *value) {
    uint32_t retVal = 0;
    float canData = 0;
    static DATA_BLOCK_CURRENT_SENSOR_s packVolt_tab;

    if (value != NULL_PTR) {
       switch (sigIdx) {
           case CAN0_SIG_PackVolt_Battery:
               /* first signal to call function */
               DB_ReadBlock(&packVolt_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
               /* Check limits */
               canData = cans_checkLimits((float)packVolt_tab.voltage[0], sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           case CAN0_SIG_PackVolt_PowerNet:
               /* first signal to call function */
               DB_ReadBlock(&packVolt_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
               /* Check limits */
               canData = cans_checkLimits((float)packVolt_tab.voltage[2], sigIdx);
               /* Apply offset and factor */
               *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
               break;

           default:
               break;
       }
    }
    return retVal;
}


static uint32_t cans_setcurr(uint32_t sigIdx, void *value) {
    int32_t currentValue;
    int32_t temperatureValue;
    int32_t powerValue;
    int32_t currentcounterValue;
    int32_t energycounterValue;
    int32_t voltageValue[3];
    uint32_t idx = 0;
    uint8_t dummy[4] = {0, 0, 0, 0};
    dummy[0] = *(uint32_t *)value & 0x000000FF;
    dummy[1] = (*(uint32_t *)value & 0x0000FF00) >> 8;
    dummy[2] = (*(uint32_t *)value & 0x00FF0000) >> 16;
    dummy[3] = (*(uint32_t *)value & 0xFF000000) >> 24;

    if (value != NULL_PTR) {
        switch (sigIdx) {
            case CAN0_SIG_IVT_Current_Status:
            case CAN0_SIG_IVT_Voltage_1_Status:
            case CAN0_SIG_IVT_Voltage_2_Status:
            case CAN0_SIG_IVT_Voltage_3_Status:
            case CAN0_SIG_IVT_Temperature_Status:
            case CAN0_SIG_IVT_Power_Status:
            case CAN0_SIG_IVT_CC_Status:
            case CAN0_SIG_IVT_EC_Status:
                dummy[0] &= 0xF0;   /* only high nibble contains diag info */
                if ((dummy[0] & 0x10) == TRUE) {
                    /* Overcurrent detected. This feature is currently not supported. */
                }
                if ((dummy[0] & 0x20) == TRUE) {
                    if (sigIdx == CAN0_SIG_IVT_Current_Status) {
                        cans_current_tab.state_current = 1;
                    } else if (sigIdx == CAN0_SIG_IVT_Voltage_1_Status || sigIdx == CAN0_SIG_IVT_Voltage_2_Status || sigIdx == CAN0_SIG_IVT_Voltage_3_Status) {
                        cans_current_tab.state_voltage = 1;
                    } else if (sigIdx == CAN0_SIG_IVT_Temperature_Status) {
                        cans_current_tab.state_temperature = 1;
                    } else if (sigIdx == CAN0_SIG_IVT_Power_Status) {
                        cans_current_tab.state_power = 1;
                    } else if (sigIdx == CAN0_SIG_IVT_CC_Status) {
                        cans_current_tab.state_cc = 1;
                    } else {
                        cans_current_tab.state_ec = 1;
                    }
                } else {
                    cans_current_tab.state_current = 0;
                    cans_current_tab.state_voltage = 0;
                    cans_current_tab.state_temperature = 0;
                    cans_current_tab.state_power = 0;
                    cans_current_tab.state_cc = 0;
                    cans_current_tab.state_ec = 0;
                }
                if ((dummy[0] & 0x40) == TRUE || (dummy[0] & 0x80) == TRUE) {
                    cans_current_tab.state_current = 1;
                    cans_current_tab.state_voltage = 1;
                    cans_current_tab.state_temperature = 1;
                    cans_current_tab.state_power = 1;
                    cans_current_tab.state_cc = 1;
                    cans_current_tab.state_ec = 1;
                }

                break;

                case CAN0_SIG_IVT_Current_Measurement:
                /* case CAN1_SIG_ISENS0_I_Measurement:  uncommented because identical position in CAN0 and CAN1 rx signal struct */
                    currentValue = (int32_t)(dummy[3] | dummy[2] << 8
                            | dummy[1] << 16 | dummy[0] << 24);
                    cans_current_tab.current = (currentValue);
                    cans_current_tab.newCurrent++;
                    cans_current_tab.previous_timestamp_cur = cans_current_tab.timestamp_cur;
                    cans_current_tab.timestamp_cur = OS_getOSSysTick();
                    DB_WriteBlock(&cans_current_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
                    break;
                case CAN0_SIG_IVT_Voltage_1_Measurement:
                /* case CAN1_SIG_ISENS1_U1_Measurement:  uncommented because identical position in CAN0 and CAN1 rx signal struct */
                    idx = 0;
                    voltageValue[idx] = (int32_t)(dummy[3] | dummy[2] << 8
                            | dummy[1] << 16 | dummy[0] << 24);
                    cans_current_tab.voltage[idx] = (float)(voltageValue[idx])*cans_CAN0_signals_rx[sigIdx].factor;
                    DB_WriteBlock(&cans_current_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
                    break;
                case CAN0_SIG_IVT_Voltage_2_Measurement:
                /* case CAN1_SIG_ISENS2_U2_Measurement:  uncommented because identical position in CAN0 and CAN1 rx signal struct */
                    idx = 1;
                    voltageValue[idx] = (int32_t)(dummy[3] | dummy[2] << 8
                            | dummy[1] << 16 | dummy[0] << 24);
                    cans_current_tab.voltage[idx] = (float)(voltageValue[idx])*cans_CAN0_signals_rx[sigIdx].factor;
                    DB_WriteBlock(&cans_current_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
                    break;
                case CAN0_SIG_IVT_Voltage_3_Measurement:
                /* case CAN1_SIG_ISENS3_U3_Measurement:  uncommented because identical position in CAN0 and CAN1 rx signal struct */
                    idx = 2;
                    voltageValue[idx] = (int32_t)(dummy[3] | dummy[2] << 8
                            | dummy[1] << 16 | dummy[0] << 24);
                    cans_current_tab.voltage[idx]=(float)(voltageValue[idx])*cans_CAN0_signals_rx[sigIdx].factor;
                    DB_WriteBlock(&cans_current_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
                    break;
                case CAN0_SIG_IVT_Temperature_Measurement:
                /* case CAN1_SIG_ISENS4_T_Measurement:  uncommented because identical position in CAN0 and CAN1 rx signal struct */
                    temperatureValue = (int32_t)(dummy[3] | dummy[2] << 8
                            | dummy[1] << 16 | dummy[0] << 24);
                    cans_current_tab.temperature = (float)(temperatureValue)*cans_CAN0_signals_rx[sigIdx].factor;
                    DB_WriteBlock(&cans_current_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
                    break;
                case CAN0_SIG_IVT_Power_Measurement:
                /* case CAN1_SIG_ISENS5_P_Measurement:  uncommented because identical position in CAN0 and CAN1 rx signal struct */
                    powerValue = (int32_t)(dummy[3] | dummy[2] << 8
                            | dummy[1] << 16 | dummy[0] << 24);
                    cans_current_tab.power = (float)(powerValue);
                    cans_current_tab.newPower++;
                    DB_WriteBlock(&cans_current_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
                    break;
                case CAN0_SIG_IVT_CC_Measurement:
                /* case CAN1_SIG_ISENS6_CC_Measurement:  uncommented because identical position in CAN0 and CAN1 rx signal struct */
                    currentcounterValue = (int32_t)(dummy[3] | dummy[2] << 8
                            | dummy[1] << 16 | dummy[0] << 24);
                    cans_current_tab.previous_timestamp_cc = cans_current_tab.timestamp_cc;
                    cans_current_tab.timestamp_cc = OS_getOSSysTick();
                    cans_current_tab.current_counter = (float)(currentcounterValue);
                    DB_WriteBlock(&cans_current_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
                    break;
                case CAN0_SIG_IVT_EC_Measurement:
                /* case CAN1_SIG_ISENS7_EC_Measurement:  uncommented because identical position in CAN0 and CAN1 rx signal struct */
                    energycounterValue = (int32_t)(dummy[3] | dummy[2] << 8
                            | dummy[1] << 16 | dummy[0] << 24);
                    cans_current_tab.energy_counter = (float)(energycounterValue);
                    DB_WriteBlock(&cans_current_tab, DATA_BLOCK_ID_CURRENT_SENSOR);
                    break;
        }
    }
    return 0;
}


uint32_t cans_setstaterequest(uint32_t sigIdx, void *value) {
    DATA_BLOCK_STATEREQUEST_s staterequest_tab;
    uint8_t staterequest;

    DB_ReadBlock(&staterequest_tab, DATA_BLOCK_ID_STATEREQUEST);

    if (value != NULL_PTR) {
        if (sigIdx == CAN0_SIG_ReceiveStateRequest) {
            staterequest = *(uint8_t *)value;
            staterequest_tab.previous_state_request = staterequest_tab.state_request;
            staterequest_tab.state_request = staterequest;
            if ((staterequest_tab.state_request != staterequest_tab.previous_state_request)|| \
                    (OS_getOSSysTick()- staterequest_tab.timestamp) > 3000) {
                staterequest_tab.state_request_pending = staterequest;
            }
            staterequest_tab.state++;
            DB_WriteBlock(&staterequest_tab, DATA_BLOCK_ID_STATEREQUEST);
        }
    }
    return 0;
}


uint32_t cans_getisoguard(uint32_t sigIdx, void *value) {
    static DATA_BLOCK_ISOMETER_s isoguard_tab;
    float canData = 0;

    if (value != NULL_PTR) {
        switch (sigIdx) {
            case CAN0_SIG_InsulationStatus:
            /* First signal call */
            DB_ReadBlock(&isoguard_tab, DATA_BLOCK_ID_ISOGUARD);

            /* Check limits */
            canData = cans_checkLimits((float)isoguard_tab.state, sigIdx);
            /* Apply offset and factor */
            *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
            break;

            case CAN0_SIG_InsulationValue:
            /* Check limits */
            canData = cans_checkLimits((float)isoguard_tab.resistance_kOhm, sigIdx);
            /* Apply offset and factor */
            *(uint32_t *)value = (uint32_t)((canData + cans_CAN0_signals_tx[sigIdx].offset) * cans_CAN0_signals_tx[sigIdx].factor);
            break;

            default:
                *(uint32_t *)value = 0;
                break;
        }
    }
    return 0;
}


uint32_t cans_setdebug(uint32_t sigIdx, void *value) {
    uint8_t data[8] = {0, 0, 0, 0, 0, 0, 0, 0};

    data[0] = *(uint64_t *)value & 0x00000000000000FF;
    data[1] = (*(uint64_t *)value & 0x000000000000FF00) >> 8;
    data[2] = (*(uint64_t *)value & 0x0000000000FF0000) >> 16;
    data[3] = (*(uint64_t *)value & 0x00000000FF000000) >> 24;
    data[4] = (*(uint64_t *)value & 0x000000FF00000000) >> 32;
    data[5] = (*(uint64_t *)value & 0x0000FF0000000000) >> 40;
    data[6] = (*(uint64_t *)value & 0x00FF000000000000) >> 48;
    data[7] = (*(uint64_t *)value & 0xFF00000000000000) >> 56;


    if (value != NULL_PTR) {
        switch (data[0]) {
            case 0x0B:  /* Set Soc directly with value. Unit in CAN message: 0.01 percent --> range 0...10000 means 0%Soc...100%Soc */
                SOC_SetValue(((float)((data[1]) << 8 | (data[2])))/100.0f, ((float)((data[1]) << 8 | (data[2])))/100.0f, ((float)((data[1]) << 8 | (data[2])))/100.0f); /* divide by 100 to get SOC between 0 and 100 */
                break;
            case 0x0E:  /* debug Message for Balancing on pack level */
                if (data[1] == 0) {
                    BAL_SetStateRequest(BAL_STATE_GLOBAL_DISABLE_REQUEST);
                } else {
                    BAL_SetStateRequest(BAL_STATE_GLOBAL_ENABLE_REQUEST);
                }
                break;
            case 0xAA:
                DIAG_Handler(DIAG_CH_DEEP_DISCHARGE_DETECTED, DIAG_EVENT_OK, 0);
                break;

            default:
                break;
        }
    }
    return 0;
}


uint32_t cans_setSWversion(uint32_t sigIdx, void *value) {
    SYS_SendBootMessage(0);
    return 0;
}


float cans_checkLimits(float value, uint32_t sigIdx) {
    float retVal = value;

    if (value < cans_CAN0_signals_tx[sigIdx].min)
        retVal = cans_CAN0_signals_tx[sigIdx].min;

    if (value > cans_CAN0_signals_tx[sigIdx].max)
        retVal = cans_CAN0_signals_tx[sigIdx].max;

    return retVal;
}

/*================== Extern Function Implementations ========================*/

cansignal_cfg.h

/**
 *
 * @copyright &copy; 2010 - 2019, Fraunhofer-Gesellschaft zur Foerderung der
 *  angewandten Forschung e.V. All rights reserved.
 *
 * BSD 3-Clause License
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1.  Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of the copyright holder nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * We kindly request you to use one or more of the following phrases to refer
 * to foxBMS in your hardware, software, documentation or advertising
 * materials:
 *
 * &Prime;This product uses parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product includes parts of foxBMS&reg;&Prime;
 *
 * &Prime;This product is derived from foxBMS&reg;&Prime;
 *
 */

/**
 * @file    cansignal_cfg.h
 * @author  foxBMS Team
 * @date    16.09.2015 (date of creation)
 * @ingroup DRIVERS_CONF
 * @prefix  CANS
 *
 * @brief   Headers for the configuration of the messages and signal settings for the CAN driver
 *
 */

#ifndef CANSIGNAL_CFG_H_
#define CANSIGNAL_CFG_H_

/*================== Includes =============================================*/
#include "batterysystem_cfg.h"
#include "general.h"
#include "can_cfg.h"

/*================== Macros and Definitions ===============================*/

/**
 * Default value send when less voltages are configured than voltages values configured for CAN transmission
 */
#define CAN_DEFAULT_VOLTAGE 3000

/**
 * Default value send when less temperatures are configured than temperatures values configured for CAN transmission
 */
#define CAN_DEFAULT_TEMPERATURE 20

/**
 * Default value send when less valid flags are configured than valid flags values configured for CAN transmission
 */
#define CAN_DEFAULT_VALID_FLAG 0

/**
 * @ingroup CONFIG_CANSIGNAL
 * task timeslot where the CANS main function is called. Repetition time of periodic CAN messages must be multiple of this
 * \par Type:
 * select(3)
 * \par Default:
 * 1
*/
/* #define CANS_TICK_MS 1 */
#define CANS_TICK_MS 10
/* #define CANS_TICK_MS 100 */


/**
 * symbolic names for TX CAN messages. Every used TX message needs to get an individual message name.
 */
typedef enum {
    /* Insert here symbolic names for CAN0 messages */
    CAN0_MSG_SystemState_0,  /*!< BMS general state 0 */
    CAN0_MSG_SystemState_1,  /*!< BMS general state 1 */
    CAN0_MSG_SystemState_2,  /*!< BMS general state 2 */
    CAN0_MSG_SlaveState_0,    /*!< Slave state 0 */
    CAN0_MSG_SlaveState_1,    /*!< Slave state 1 */

    CAN0_MSG_RecOperatingCurrent,  /*!< Max allowed charge/discharge current */
    CAN0_MSG_SOP,  /*!< SOP */
    CAN0_MSG_SOC,  /*!< SOC */
    CAN0_MSG_SOH,  /*!< SOH */
    CAN0_MSG_SOE,  /*!< SOE */
    CAN0_MSG_MinMaxCellVolt,  /*!< min/max/mean cell voltages */
    CAN0_MSG_SOV,  /*!< SOV */
    CAN0_MSG_MinMaxCellTemp,  /*!< min/max/mean cell temperatures */
    CAN0_MSG_Tempering,  /*!< Tempering */
    CAN0_MSG_Insulation,  /*!< Insulation */
    CAN0_MSG_Power_0,  /*!< Moving average power 1s 5s */
    CAN0_MSG_Power_1,  /*!< Moving average power 10s 30s */
    CAN0_MSG_Power_2,  /*!< Moving average power 60s configurable duration */
    CAN0_MSG_Current_0,  /*!< Moving average current 1s 5s */
    CAN0_MSG_Current_1,  /*!< Moving average current 10s 30s */
    CAN0_MSG_Current_2,  /*!< Moving average current 60s configurable duration */
    CAN0_MSG_PackVoltage,  /*!< Pack voltage */

    CAN0_MSG_Mod0_Cellvolt_0,  /*!< Module 0 Cell voltages 0-2 */
    CAN0_MSG_Mod0_Cellvolt_1,  /*!< Module 0 Cell voltages 3-5 */
    CAN0_MSG_Mod0_Cellvolt_2,  /*!< Module 0 Cell voltages 6-8 */
    CAN0_MSG_Mod0_Cellvolt_3,  /*!< Module 0 Cell voltages 9-11 */
    CAN0_MSG_Mod0_Cellvolt_4,  /*!< Module 0 Cell voltages 12-14 */
    CAN0_MSG_Mod0_Cellvolt_5,  /*!< Module 0 Cell voltages 15-17 */
    CAN0_MSG_Mod0_Celltemp_0,  /*!< Module 0 Cell temperatures 0-2 */
    CAN0_MSG_Mod0_Celltemp_1,  /*!< Module 0 Cell temperatures 3-5 */
    CAN0_MSG_Mod0_Celltemp_2,  /*!< Module 0 Cell temperatures 6-8 */
    CAN0_MSG_Mod0_Celltemp_3,  /*!< Module 0 Cell temperatures 9-11 */

    CAN0_MSG_Mod1_Cellvolt_0,  /*!< Module 1 Cell voltages 0-2 */
    CAN0_MSG_Mod1_Cellvolt_1,  /*!< Module 1 Cell voltages 3-5 */
    CAN0_MSG_Mod1_Cellvolt_2,  /*!< Module 1 Cell voltages 6-8 */
    CAN0_MSG_Mod1_Cellvolt_3,  /*!< Module 1 Cell voltages 9-11 */
    CAN0_MSG_Mod1_Cellvolt_4,  /*!< Module 1 Cell voltages 12-14 */
    CAN0_MSG_Mod1_Cellvolt_5,  /*!< Module 1 Cell voltages 15-17 */
    CAN0_MSG_Mod1_Celltemp_0,  /*!< Module 1 Cell temperatures 0-2 */
    CAN0_MSG_Mod1_Celltemp_1,  /*!< Module 1 Cell temperatures 3-5 */
    CAN0_MSG_Mod1_Celltemp_2,  /*!< Module 1 Cell temperatures 6-8 */
    CAN0_MSG_Mod1_Celltemp_3,  /*!< Module 1 Cell temperatures 9-11 */

    CAN0_MSG_Mod2_Cellvolt_0,  /*!< Module 2 Cell voltages 0-2 */
    CAN0_MSG_Mod2_Cellvolt_1,  /*!< Module 2 Cell voltages 3-5 */
    CAN0_MSG_Mod2_Cellvolt_2,  /*!< Module 2 Cell voltages 6-8 */
    CAN0_MSG_Mod2_Cellvolt_3,  /*!< Module 2 Cell voltages 9-11 */
    CAN0_MSG_Mod2_Cellvolt_4,  /*!< Module 2 Cell voltages 12-14 */
    CAN0_MSG_Mod2_Cellvolt_5,  /*!< Module 2 Cell voltages 15-17 */
    CAN0_MSG_Mod2_Celltemp_0,  /*!< Module 2 Cell temperatures 0-2 */
    CAN0_MSG_Mod2_Celltemp_1,  /*!< Module 2 Cell temperatures 3-5 */
    CAN0_MSG_Mod2_Celltemp_2,  /*!< Module 2 Cell temperatures 6-8 */
    CAN0_MSG_Mod2_Celltemp_3,  /*!< Module 2 Cell temperatures 9-11 */

    CAN0_MSG_Mod3_Cellvolt_0,  /*!< Module 3 Cell voltages 0-2 */
    CAN0_MSG_Mod3_Cellvolt_1,  /*!< Module 3 Cell voltages 3-5 */
    CAN0_MSG_Mod3_Cellvolt_2,  /*!< Module 3 Cell voltages 6-8 */
    CAN0_MSG_Mod3_Cellvolt_3,  /*!< Module 3 Cell voltages 9-11 */
    CAN0_MSG_Mod3_Cellvolt_4,  /*!< Module 3 Cell voltages 12-14 */
    CAN0_MSG_Mod3_Cellvolt_5,  /*!< Module 3 Cell voltages 15-17 */
    CAN0_MSG_Mod3_Celltemp_0,  /*!< Module 3 Cell temperatures 0-2 */
    CAN0_MSG_Mod3_Celltemp_1,  /*!< Module 3 Cell temperatures 3-5 */
    CAN0_MSG_Mod3_Celltemp_2,  /*!< Module 3 Cell temperatures 6-8 */
    CAN0_MSG_Mod3_Celltemp_3,  /*!< Module 3 Cell temperatures 9-11 */

    CAN0_MSG_Mod4_Cellvolt_0,  /*!< Module 4 Cell voltages 0-2 */
    CAN0_MSG_Mod4_Cellvolt_1,  /*!< Module 4 Cell voltages 3-5 */
    CAN0_MSG_Mod4_Cellvolt_2,  /*!< Module 4 Cell voltages 6-8 */
    CAN0_MSG_Mod4_Cellvolt_3,  /*!< Module 4 Cell voltages 9-11 */
    CAN0_MSG_Mod4_Cellvolt_4,  /*!< Module 4 Cell voltages 12-14 */
    CAN0_MSG_Mod4_Cellvolt_5,  /*!< Module 4 Cell voltages 15-17 */
    CAN0_MSG_Mod4_Celltemp_0,  /*!< Module 4 Cell temperatures 0-2 */
    CAN0_MSG_Mod4_Celltemp_1,  /*!< Module 4 Cell temperatures 3-5 */
    CAN0_MSG_Mod4_Celltemp_2,  /*!< Module 4 Cell temperatures 6-8 */
    CAN0_MSG_Mod4_Celltemp_3,  /*!< Module 4 Cell temperatures 9-11 */

    CAN0_MSG_Mod5_Cellvolt_0,  /*!< Module 5 Cell voltages 0-2 */
    CAN0_MSG_Mod5_Cellvolt_1,  /*!< Module 5 Cell voltages 3-5 */
    CAN0_MSG_Mod5_Cellvolt_2,  /*!< Module 5 Cell voltages 6-8 */
    CAN0_MSG_Mod5_Cellvolt_3,  /*!< Module 5 Cell voltages 9-11 */
    CAN0_MSG_Mod5_Cellvolt_4,  /*!< Module 5 Cell voltages 12-14 */
    CAN0_MSG_Mod5_Cellvolt_5,  /*!< Module 5 Cell voltages 15-17 */
    CAN0_MSG_Mod5_Celltemp_0,  /*!< Module 5 Cell temperatures 0-2 */
    CAN0_MSG_Mod5_Celltemp_1,  /*!< Module 5 Cell temperatures 3-5 */
    CAN0_MSG_Mod5_Celltemp_2,  /*!< Module 5 Cell temperatures 6-8 */
    CAN0_MSG_Mod5_Celltemp_3,  /*!< Module 5 Cell temperatures 9-11 */

    CAN0_MSG_Mod6_Cellvolt_0,  /*!< Module 6 Cell voltages 0-2 */
    CAN0_MSG_Mod6_Cellvolt_1,  /*!< Module 6 Cell voltages 3-5 */
    CAN0_MSG_Mod6_Cellvolt_2,  /*!< Module 6 Cell voltages 6-8 */
    CAN0_MSG_Mod6_Cellvolt_3,  /*!< Module 6 Cell voltages 9-11 */
    CAN0_MSG_Mod6_Cellvolt_4,  /*!< Module 6 Cell voltages 12-14 */
    CAN0_MSG_Mod6_Cellvolt_5,  /*!< Module 6 Cell voltages 15-17 */
    CAN0_MSG_Mod6_Celltemp_0,  /*!< Module 6 Cell temperatures 0-2 */
    CAN0_MSG_Mod6_Celltemp_1,  /*!< Module 6 Cell temperatures 3-5 */
    CAN0_MSG_Mod6_Celltemp_2,  /*!< Module 6 Cell temperatures 6-8 */
    CAN0_MSG_Mod6_Celltemp_3,  /*!< Module 6 Cell temperatures 9-11 */

    CAN0_MSG_Mod7_Cellvolt_0,  /*!< Module 7 Cell voltages 0-2 */
    CAN0_MSG_Mod7_Cellvolt_1,  /*!< Module 7 Cell voltages 3-5 */
    CAN0_MSG_Mod7_Cellvolt_2,  /*!< Module 7 Cell voltages 6-8 */
    CAN0_MSG_Mod7_Cellvolt_3,  /*!< Module 7 Cell voltages 9-11 */
    CAN0_MSG_Mod7_Cellvolt_4,  /*!< Module 7 Cell voltages 12-14 */
    CAN0_MSG_Mod7_Cellvolt_5,  /*!< Module 7 Cell voltages 15-17 */
    CAN0_MSG_Mod7_Celltemp_0,  /*!< Module 7 Cell temperatures 0-2 */
    CAN0_MSG_Mod7_Celltemp_1,  /*!< Module 7 Cell temperatures 3-5 */
    CAN0_MSG_Mod7_Celltemp_2,  /*!< Module 7 Cell temperatures 6-8 */
    CAN0_MSG_Mod7_Celltemp_3,  /*!< Module 7 Cell temperatures 9-11 */

#ifdef CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED
    CAN0_MSG_BMS_CurrentTrigger,    /*!< Cell Voltages Max Min Average */
#endif /* CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED */


    /* Insert here symbolic names for CAN1 messages */
} CANS_messagesTx_e;

/**
 * symbolic names for RX CAN messages
 */
typedef enum {
    /* Insert here symbolic names for CAN0 messages */
    CAN0_MSG_StateRequest,                   /*!< state request */
    CAN0_MSG_SW_RESET,                       /*!< can message for SW reset */
    CAN0_MSG_IVT_Current,                    /*!< current sensing */
    CAN0_MSG_IVT_Voltage_1,                  /*!< current sensor voltage 1 */
    CAN0_MSG_IVT_Voltage_2,                  /*!< current sensor voltage 2 */
    CAN0_MSG_IVT_Voltage_3,                  /*!< current sensor voltage 3 */
    CAN0_MSG_IVT_Temperature,                /*!< current sensor temperature */
    CAN0_MSG_IVT_Power,                      /*!< current sensor power */
    CAN0_MSG_IVT_CoulombCount,               /*!< current sensor C-C */
    CAN0_MSG_IVT_EnergyCount,                /*!< current sensor E-C */
    CAN0_MSG_DEBUG,                          /*!< debug messages */
    CAN0_MSG_GetReleaseVersion,              /*!< Get SW release version */

    /* Insert here symbolic names for CAN1 messages */
} CANS_messagesRx_e;

/**
 * symbolic names for CAN0 transmission signals
 */
typedef enum {
    CAN0_SIG_GS0_general_error,  /* 0:good, 1:error */
    CAN0_SIG_GS0_current_state,  /* currently no used */
    CAN0_SIG_GS0_error_overtemp_charge,  /* 0:good, 1:error */
    CAN0_SIG_GS0_error_undertemp_charge,  /* 0:good, 1:error */
    CAN0_SIG_GS0_error_overtemp_discharge,  /* 0:good, 1:error */
    CAN0_SIG_GS0_error_undertemp_discharge,  /* 0:good, 1:error */
    CAN0_SIG_GS0_error_overcurrent_charge,  /* 0:good, 1:error */
    CAN0_SIG_GS0_error_overcurrent_discharge,  /* 0:good, 1:error */

    CAN0_SIG_GS1_error_overvoltage,  /* 0:good, 1:error */
    CAN0_SIG_GS1_error_undervoltage,  /* 0:good, 1:error */
    CAN0_SIG_GS1_error_deep_discharge,  /* 0:good, 1:error */
    CAN0_SIG_GS1_error_temperature_MCU0,  /* 0:good, 1:error */
    CAN0_SIG_GS1_error_contactor,  /* 0:good, 1:error */
    CAN0_SIG_GS1_error_selftest,  /* 0:good, 1:error */
    CAN0_SIG_GS1_error_cantiming,  /* 0:good, 1:error */
    CAN0_SIG_GS1_current_sensor,  /* 0:good, 1:error */
    CAN0_SIG_GS1_balancing_active,  /* 0:off, 1:on */

    CAN0_SIG_GS2_state_cont_interlock,  /* bitfield 0:off, 1:on */
    CAN0_SIG_GS2_error_insulation,  /* 0: good, 1: error */
    CAN0_SIG_GS2_fuse_state,  /* 0: fuse intact, 1: fuse tripped */
    CAN0_SIG_GS2_lowCoinCellVolt,  /* 0: okay, else: low voltage */
    CAN0_SIG_GS2_error_openWire,  /* 0: okay, 1: open wire detected */
    CAN0_SIG_GS2_daisyChain,  /* 0: okay, else: error */
    CAN0_SIG_GS2_plausibilityCheck,  /* 0: okay, else: error */

    CAN0_SIG_SS0_states,  /* 0: good, 1: error */
    CAN0_SIG_SS1_states,  /* 0: good, 1: error */

    CAN0_SIG_RecChargeCurrent,
    CAN0_SIG_RecChargeCurrent_Peak,
    CAN0_SIG_RecDischargeCurrent,
    CAN0_SIG_RecDischargeCurrent_Peak,

    CAN0_SIG_MaxChargePower,
    CAN0_SIG_MaxChargePower_Peak,
    CAN0_SIG_MaxDischargePower,
    CAN0_SIG_MaxDischargePower_Peak,

    CAN0_SIG_SOC_mean,
    CAN0_SIG_SOC_min,
    CAN0_SIG_SOC_max,

    CAN0_SIG_SOH_mean,
    CAN0_SIG_SOH_min,
    CAN0_SIG_SOH_max,

    CAN0_SIG_SOE,
    CAN0_SIG_RemainingEnergy,

    CAN0_SIG_Cellvolt_mean,
    CAN0_SIG_Cellvolt_min,
    CAN0_SIG_Cellvolt_max,
    CAN0_SIG_ModNumber_volt_min,
    CAN0_SIG_ModNumber_volt_max,

    CAN0_SIG_SOV,

    CAN0_SIG_Celltemp_mean,
    CAN0_SIG_Celltemp_min,
    CAN0_SIG_Celltemp_max,
    CAN0_SIG_ModNumber_temp_min,
    CAN0_SIG_ModNumber_temp_max,

    CAN0_SIG_CoolingNeeded,
    CAN0_SIG_HeatingNeeded,
    CAN0_SIG_TemperingDemand,

    CAN0_SIG_InsulationStatus,
    CAN0_SIG_InsulationValue,

    CAN0_SIG_MovAverage_Power_1s,
    CAN0_SIG_MovAverage_Power_5s,
    CAN0_SIG_MovAverage_Power_10s,
    CAN0_SIG_MovAverage_Power_30s,
    CAN0_SIG_MovAverage_Power_60s,
    CAN0_SIG_MovAverage_Power_config,

    CAN0_SIG_MovAverage_Current_1s,
    CAN0_SIG_MovAverage_Current_5s,
    CAN0_SIG_MovAverage_Current_10s,
    CAN0_SIG_MovAverage_Current_30s,
    CAN0_SIG_MovAverage_Current_60s,
    CAN0_SIG_MovAverage_Current_config,

    CAN0_SIG_PackVolt_Battery,
    CAN0_SIG_PackVolt_PowerNet,

    CAN0_SIG_Mod0_volt_valid_0_2,
    CAN0_SIG_Mod0_volt_0,
    CAN0_SIG_Mod0_volt_1,
    CAN0_SIG_Mod0_volt_2,
    CAN0_SIG_Mod0_volt_valid_3_5,
    CAN0_SIG_Mod0_volt_3,
    CAN0_SIG_Mod0_volt_4,
    CAN0_SIG_Mod0_volt_5,
    CAN0_SIG_Mod0_volt_valid_6_8,
    CAN0_SIG_Mod0_volt_6,
    CAN0_SIG_Mod0_volt_7,
    CAN0_SIG_Mod0_volt_8,
    CAN0_SIG_Mod0_volt_valid_9_11,
    CAN0_SIG_Mod0_volt_9,
    CAN0_SIG_Mod0_volt_10,
    CAN0_SIG_Mod0_volt_11,
    CAN0_SIG_Mod0_volt_valid_12_14,
    CAN0_SIG_Mod0_volt_12,
    CAN0_SIG_Mod0_volt_13,
    CAN0_SIG_Mod0_volt_14,
    CAN0_SIG_Mod0_volt_valid_15_17,
    CAN0_SIG_Mod0_volt_15,
    CAN0_SIG_Mod0_volt_16,
    CAN0_SIG_Mod0_volt_17,

    CAN0_SIG_Mod0_temp_valid_0_2,
    CAN0_SIG_Mod0_temp_0,
    CAN0_SIG_Mod0_temp_1,
    CAN0_SIG_Mod0_temp_2,
    CAN0_SIG_Mod0_temp_valid_3_5,
    CAN0_SIG_Mod0_temp_3,
    CAN0_SIG_Mod0_temp_4,
    CAN0_SIG_Mod0_temp_5,
    CAN0_SIG_Mod0_temp_valid_6_8,
    CAN0_SIG_Mod0_temp_6,
    CAN0_SIG_Mod0_temp_7,
    CAN0_SIG_Mod0_temp_8,
    CAN0_SIG_Mod0_temp_valid_9_11,
    CAN0_SIG_Mod0_temp_9,
    CAN0_SIG_Mod0_temp_10,
    CAN0_SIG_Mod0_temp_11,

    CAN0_SIG_Mod1_volt_valid_0_2,
    CAN0_SIG_Mod1_volt_0,
    CAN0_SIG_Mod1_volt_1,
    CAN0_SIG_Mod1_volt_2,
    CAN0_SIG_Mod1_volt_valid_3_5,
    CAN0_SIG_Mod1_volt_3,
    CAN0_SIG_Mod1_volt_4,
    CAN0_SIG_Mod1_volt_5,
    CAN0_SIG_Mod1_volt_valid_6_8,
    CAN0_SIG_Mod1_volt_6,
    CAN0_SIG_Mod1_volt_7,
    CAN0_SIG_Mod1_volt_8,
    CAN0_SIG_Mod1_volt_valid_9_11,
    CAN0_SIG_Mod1_volt_9,
    CAN0_SIG_Mod1_volt_10,
    CAN0_SIG_Mod1_volt_11,
    CAN0_SIG_Mod1_volt_valid_12_14,
    CAN0_SIG_Mod1_volt_12,
    CAN0_SIG_Mod1_volt_13,
    CAN0_SIG_Mod1_volt_14,
    CAN0_SIG_Mod1_volt_valid_15_17,
    CAN0_SIG_Mod1_volt_15,
    CAN0_SIG_Mod1_volt_16,
    CAN0_SIG_Mod1_volt_17,

    CAN0_SIG_Mod1_temp_valid_0_2,
    CAN0_SIG_Mod1_temp_0,
    CAN0_SIG_Mod1_temp_1,
    CAN0_SIG_Mod1_temp_2,
    CAN0_SIG_Mod1_temp_valid_3_5,
    CAN0_SIG_Mod1_temp_3,
    CAN0_SIG_Mod1_temp_4,
    CAN0_SIG_Mod1_temp_5,
    CAN0_SIG_Mod1_temp_valid_6_8,
    CAN0_SIG_Mod1_temp_6,
    CAN0_SIG_Mod1_temp_7,
    CAN0_SIG_Mod1_temp_8,
    CAN0_SIG_Mod1_temp_valid_9_11,
    CAN0_SIG_Mod1_temp_9,
    CAN0_SIG_Mod1_temp_10,
    CAN0_SIG_Mod1_temp_11,

    CAN0_SIG_Mod2_volt_valid_0_2,
    CAN0_SIG_Mod2_volt_0,
    CAN0_SIG_Mod2_volt_1,
    CAN0_SIG_Mod2_volt_2,
    CAN0_SIG_Mod2_volt_valid_3_5,
    CAN0_SIG_Mod2_volt_3,
    CAN0_SIG_Mod2_volt_4,
    CAN0_SIG_Mod2_volt_5,
    CAN0_SIG_Mod2_volt_valid_6_8,
    CAN0_SIG_Mod2_volt_6,
    CAN0_SIG_Mod2_volt_7,
    CAN0_SIG_Mod2_volt_8,
    CAN0_SIG_Mod2_volt_valid_9_11,
    CAN0_SIG_Mod2_volt_9,
    CAN0_SIG_Mod2_volt_10,
    CAN0_SIG_Mod2_volt_11,
    CAN0_SIG_Mod2_volt_valid_12_14,
    CAN0_SIG_Mod2_volt_12,
    CAN0_SIG_Mod2_volt_13,
    CAN0_SIG_Mod2_volt_14,
    CAN0_SIG_Mod2_volt_valid_15_17,
    CAN0_SIG_Mod2_volt_15,
    CAN0_SIG_Mod2_volt_16,
    CAN0_SIG_Mod2_volt_17,

    CAN0_SIG_Mod2_temp_valid_0_2,
    CAN0_SIG_Mod2_temp_0,
    CAN0_SIG_Mod2_temp_1,
    CAN0_SIG_Mod2_temp_2,
    CAN0_SIG_Mod2_temp_valid_3_5,
    CAN0_SIG_Mod2_temp_3,
    CAN0_SIG_Mod2_temp_4,
    CAN0_SIG_Mod2_temp_5,
    CAN0_SIG_Mod2_temp_valid_6_8,
    CAN0_SIG_Mod2_temp_6,
    CAN0_SIG_Mod2_temp_7,
    CAN0_SIG_Mod2_temp_8,
    CAN0_SIG_Mod2_temp_valid_9_11,
    CAN0_SIG_Mod2_temp_9,
    CAN0_SIG_Mod2_temp_10,
    CAN0_SIG_Mod2_temp_11,

    CAN0_SIG_Mod3_volt_valid_0_2,
    CAN0_SIG_Mod3_volt_0,
    CAN0_SIG_Mod3_volt_1,
    CAN0_SIG_Mod3_volt_2,
    CAN0_SIG_Mod3_volt_valid_3_5,
    CAN0_SIG_Mod3_volt_3,
    CAN0_SIG_Mod3_volt_4,
    CAN0_SIG_Mod3_volt_5,
    CAN0_SIG_Mod3_volt_valid_6_8,
    CAN0_SIG_Mod3_volt_6,
    CAN0_SIG_Mod3_volt_7,
    CAN0_SIG_Mod3_volt_8,
    CAN0_SIG_Mod3_volt_valid_9_11,
    CAN0_SIG_Mod3_volt_9,
    CAN0_SIG_Mod3_volt_10,
    CAN0_SIG_Mod3_volt_11,
    CAN0_SIG_Mod3_volt_valid_12_14,
    CAN0_SIG_Mod3_volt_12,
    CAN0_SIG_Mod3_volt_13,
    CAN0_SIG_Mod3_volt_14,
    CAN0_SIG_Mod3_volt_valid_15_17,
    CAN0_SIG_Mod3_volt_15,
    CAN0_SIG_Mod3_volt_16,
    CAN0_SIG_Mod3_volt_17,

    CAN0_SIG_Mod3_temp_valid_0_2,
    CAN0_SIG_Mod3_temp_0,
    CAN0_SIG_Mod3_temp_1,
    CAN0_SIG_Mod3_temp_2,
    CAN0_SIG_Mod3_temp_valid_3_5,
    CAN0_SIG_Mod3_temp_3,
    CAN0_SIG_Mod3_temp_4,
    CAN0_SIG_Mod3_temp_5,
    CAN0_SIG_Mod3_temp_valid_6_8,
    CAN0_SIG_Mod3_temp_6,
    CAN0_SIG_Mod3_temp_7,
    CAN0_SIG_Mod3_temp_8,
    CAN0_SIG_Mod3_temp_valid_9_11,
    CAN0_SIG_Mod3_temp_9,
    CAN0_SIG_Mod3_temp_10,
    CAN0_SIG_Mod3_temp_11,

    CAN0_SIG_Mod4_volt_valid_0_2,
    CAN0_SIG_Mod4_volt_0,
    CAN0_SIG_Mod4_volt_1,
    CAN0_SIG_Mod4_volt_2,
    CAN0_SIG_Mod4_volt_valid_3_5,
    CAN0_SIG_Mod4_volt_3,
    CAN0_SIG_Mod4_volt_4,
    CAN0_SIG_Mod4_volt_5,
    CAN0_SIG_Mod4_volt_valid_6_8,
    CAN0_SIG_Mod4_volt_6,
    CAN0_SIG_Mod4_volt_7,
    CAN0_SIG_Mod4_volt_8,
    CAN0_SIG_Mod4_volt_valid_9_11,
    CAN0_SIG_Mod4_volt_9,
    CAN0_SIG_Mod4_volt_10,
    CAN0_SIG_Mod4_volt_11,
    CAN0_SIG_Mod4_volt_valid_12_14,
    CAN0_SIG_Mod4_volt_12,
    CAN0_SIG_Mod4_volt_13,
    CAN0_SIG_Mod4_volt_14,
    CAN0_SIG_Mod4_volt_valid_15_17,
    CAN0_SIG_Mod4_volt_15,
    CAN0_SIG_Mod4_volt_16,
    CAN0_SIG_Mod4_volt_17,

    CAN0_SIG_Mod4_temp_valid_0_2,
    CAN0_SIG_Mod4_temp_0,
    CAN0_SIG_Mod4_temp_1,
    CAN0_SIG_Mod4_temp_2,
    CAN0_SIG_Mod4_temp_valid_3_5,
    CAN0_SIG_Mod4_temp_3,
    CAN0_SIG_Mod4_temp_4,
    CAN0_SIG_Mod4_temp_5,
    CAN0_SIG_Mod4_temp_valid_6_8,
    CAN0_SIG_Mod4_temp_6,
    CAN0_SIG_Mod4_temp_7,
    CAN0_SIG_Mod4_temp_8,
    CAN0_SIG_Mod4_temp_valid_9_11,
    CAN0_SIG_Mod4_temp_9,
    CAN0_SIG_Mod4_temp_10,
    CAN0_SIG_Mod4_temp_11,

    CAN0_SIG_Mod5_volt_valid_0_2,
    CAN0_SIG_Mod5_volt_0,
    CAN0_SIG_Mod5_volt_1,
    CAN0_SIG_Mod5_volt_2,
    CAN0_SIG_Mod5_volt_valid_3_5,
    CAN0_SIG_Mod5_volt_3,
    CAN0_SIG_Mod5_volt_4,
    CAN0_SIG_Mod5_volt_5,
    CAN0_SIG_Mod5_volt_valid_6_8,
    CAN0_SIG_Mod5_volt_6,
    CAN0_SIG_Mod5_volt_7,
    CAN0_SIG_Mod5_volt_8,
    CAN0_SIG_Mod5_volt_valid_9_11,
    CAN0_SIG_Mod5_volt_9,
    CAN0_SIG_Mod5_volt_10,
    CAN0_SIG_Mod5_volt_11,
    CAN0_SIG_Mod5_volt_valid_12_14,
    CAN0_SIG_Mod5_volt_12,
    CAN0_SIG_Mod5_volt_13,
    CAN0_SIG_Mod5_volt_14,
    CAN0_SIG_Mod5_volt_valid_15_17,
    CAN0_SIG_Mod5_volt_15,
    CAN0_SIG_Mod5_volt_16,
    CAN0_SIG_Mod5_volt_17,

    CAN0_SIG_Mod5_temp_valid_0_2,
    CAN0_SIG_Mod5_temp_0,
    CAN0_SIG_Mod5_temp_1,
    CAN0_SIG_Mod5_temp_2,
    CAN0_SIG_Mod5_temp_valid_3_5,
    CAN0_SIG_Mod5_temp_3,
    CAN0_SIG_Mod5_temp_4,
    CAN0_SIG_Mod5_temp_5,
    CAN0_SIG_Mod5_temp_valid_6_8,
    CAN0_SIG_Mod5_temp_6,
    CAN0_SIG_Mod5_temp_7,
    CAN0_SIG_Mod5_temp_8,
    CAN0_SIG_Mod5_temp_valid_9_11,
    CAN0_SIG_Mod5_temp_9,
    CAN0_SIG_Mod5_temp_10,
    CAN0_SIG_Mod5_temp_11,

    CAN0_SIG_Mod6_volt_valid_0_2,
    CAN0_SIG_Mod6_volt_0,
    CAN0_SIG_Mod6_volt_1,
    CAN0_SIG_Mod6_volt_2,
    CAN0_SIG_Mod6_volt_valid_3_5,
    CAN0_SIG_Mod6_volt_3,
    CAN0_SIG_Mod6_volt_4,
    CAN0_SIG_Mod6_volt_5,
    CAN0_SIG_Mod6_volt_valid_6_8,
    CAN0_SIG_Mod6_volt_6,
    CAN0_SIG_Mod6_volt_7,
    CAN0_SIG_Mod6_volt_8,
    CAN0_SIG_Mod6_volt_valid_9_11,
    CAN0_SIG_Mod6_volt_9,
    CAN0_SIG_Mod6_volt_10,
    CAN0_SIG_Mod6_volt_11,
    CAN0_SIG_Mod6_volt_valid_12_14,
    CAN0_SIG_Mod6_volt_12,
    CAN0_SIG_Mod6_volt_13,
    CAN0_SIG_Mod6_volt_14,
    CAN0_SIG_Mod6_volt_valid_15_17,
    CAN0_SIG_Mod6_volt_15,
    CAN0_SIG_Mod6_volt_16,
    CAN0_SIG_Mod6_volt_17,

    CAN0_SIG_Mod6_temp_valid_0_2,
    CAN0_SIG_Mod6_temp_0,
    CAN0_SIG_Mod6_temp_1,
    CAN0_SIG_Mod6_temp_2,
    CAN0_SIG_Mod6_temp_valid_3_5,
    CAN0_SIG_Mod6_temp_3,
    CAN0_SIG_Mod6_temp_4,
    CAN0_SIG_Mod6_temp_5,
    CAN0_SIG_Mod6_temp_valid_6_8,
    CAN0_SIG_Mod6_temp_6,
    CAN0_SIG_Mod6_temp_7,
    CAN0_SIG_Mod6_temp_8,
    CAN0_SIG_Mod6_temp_valid_9_11,
    CAN0_SIG_Mod6_temp_9,
    CAN0_SIG_Mod6_temp_10,
    CAN0_SIG_Mod6_temp_11,

    CAN0_SIG_Mod7_volt_valid_0_2,
    CAN0_SIG_Mod7_volt_0,
    CAN0_SIG_Mod7_volt_1,
    CAN0_SIG_Mod7_volt_2,
    CAN0_SIG_Mod7_volt_valid_3_5,
    CAN0_SIG_Mod7_volt_3,
    CAN0_SIG_Mod7_volt_4,
    CAN0_SIG_Mod7_volt_5,
    CAN0_SIG_Mod7_volt_valid_6_8,
    CAN0_SIG_Mod7_volt_6,
    CAN0_SIG_Mod7_volt_7,
    CAN0_SIG_Mod7_volt_8,
    CAN0_SIG_Mod7_volt_valid_9_11,
    CAN0_SIG_Mod7_volt_9,
    CAN0_SIG_Mod7_volt_10,
    CAN0_SIG_Mod7_volt_11,
    CAN0_SIG_Mod7_volt_valid_12_14,
    CAN0_SIG_Mod7_volt_12,
    CAN0_SIG_Mod7_volt_13,
    CAN0_SIG_Mod7_volt_14,
    CAN0_SIG_Mod7_volt_valid_15_17,
    CAN0_SIG_Mod7_volt_15,
    CAN0_SIG_Mod7_volt_16,
    CAN0_SIG_Mod7_volt_17,

    CAN0_SIG_Mod7_temp_valid_0_2,
    CAN0_SIG_Mod7_temp_0,
    CAN0_SIG_Mod7_temp_1,
    CAN0_SIG_Mod7_temp_2,
    CAN0_SIG_Mod7_temp_valid_3_5,
    CAN0_SIG_Mod7_temp_3,
    CAN0_SIG_Mod7_temp_4,
    CAN0_SIG_Mod7_temp_5,
    CAN0_SIG_Mod7_temp_valid_6_8,
    CAN0_SIG_Mod7_temp_6,
    CAN0_SIG_Mod7_temp_7,
    CAN0_SIG_Mod7_temp_8,
    CAN0_SIG_Mod7_temp_valid_9_11,
    CAN0_SIG_Mod7_temp_9,
    CAN0_SIG_Mod7_temp_10,
    CAN0_SIG_Mod7_temp_11,

#ifdef CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED
    CAN0_SIG_ISA_Trigger,
#endif /* CURRENT_SENSOR_ISABELLENHUETTE_TRIGGERED */

    CAN0_SIGNAL_NONE = 0xFFFF
} CANS_CAN0_signalsTx_e;

/**
 * symbolic names for CAN1 transmission signals
 */
typedef enum {
    CAN1_TX_SIGNAL_NONE = 0xFFFF,
} CANS_CAN1_signalsTx_e;


/**
 * symbolic names for CAN 0 receive signals
 */
typedef enum {
    CAN0_SIG_ReceiveStateRequest,          /*!< current sensor counter */
    CAN0_SIG_IVT_Current_MuxID,            /*!< current sensor measurement type */
    CAN0_SIG_IVT_Current_Status,           /*!< current sensor counter */
    CAN0_SIG_IVT_Current_Measurement,      /*!< current sensor measurement I */
    CAN0_SIG_IVT_Voltage_1_MuxID,          /*!< current sensor measurement type */
    CAN0_SIG_IVT_Voltage_1_Status,         /*!< current sensor counter */
    CAN0_SIG_IVT_Voltage_1_Measurement,    /*!< current sensor measurement U1 */
    CAN0_SIG_IVT_Voltage_2_MuxID,          /*!< current sensor measurement type */
    CAN0_SIG_IVT_Voltage_2_Status,         /*!< current sensor counter */
    CAN0_SIG_IVT_Voltage_2_Measurement,    /*!< current sensor measurement U2 */
    CAN0_SIG_IVT_Voltage_3_MuxID,          /*!< current sensor measurement type */
    CAN0_SIG_IVT_Voltage_3_Status,         /*!< current sensor counter */
    CAN0_SIG_IVT_Voltage_3_Measurement,    /*!< current sensor measurement U3 */
    CAN0_SIG_IVT_Temperature_MuxID,        /*!< current sensor measurement type */
    CAN0_SIG_IVT_Temperature_Status,       /*!< current sensor counter */
    CAN0_SIG_IVT_Temperature_Measurement,  /*!< current sensor measurement T */
    CAN0_SIG_IVT_Power_MuxID,              /*!< current sensor measurement type */
    CAN0_SIG_IVT_Power_Status,             /*!< current sensor counter */
    CAN0_SIG_IVT_Power_Measurement,        /*!< current sensor measurement P */
    CAN0_SIG_IVT_CC_MuxID,                 /*!< current sensor measurement type */
    CAN0_SIG_IVT_CC_Status,                /*!< current sensor counter */
    CAN0_SIG_IVT_CC_Measurement,           /*!< current sensor measurement C-C */
    CAN0_SIG_IVT_EC_MuxID,                 /*!< current sensor measurement type */
    CAN0_SIG_IVT_EC_Status,                /*!< current sensor counter */
    CAN0_SIG_IVT_EC_Measurement,           /*!< current sensor measurement E-C */
    CAN0_SIG_DEBUG_Data,                   /*!< Data of debug message */
    CAN0_SIG_GetReleaseVersion
} CANS_CAN0_signalsRx_e;


/**
 * symbolic names for CAN 1 receive signals
 */
typedef enum {
    CAN1_RX_SIGNAL_NONE = 0xFFFF,
} CANS_CAN1_signalsRx_e;

typedef enum {
    CAN_RX_DIRECTION = 0,
    CAN_TX_DIRECTION = 1
} CANS_messageDirection_t;

typedef union {
    CANS_messagesTx_e Tx;
    CANS_messagesRx_e Rx;
} CANS_messages_t;

typedef union {
    CANS_CAN0_signalsTx_e Tx;
    CANS_CAN0_signalsRx_e Rx;
} CANS_signals_t;

/**
 * type definition for structure of a CAN signal
 *
 * until now, multiplexed signal handling is hard coded
 * in the corresponding getters/setters. For use of multiplexed
 * signals refer to description in documentation.
 *
 * support for automatic scaling is planned, but not implemented yet,
 * so min, max, factor and offset are not relevant.
 */
typedef struct  {
    CANS_messages_t msgIdx;
    uint8_t bit_position;
    uint8_t bit_length;
    float min;
    float max;
    float factor;
    float offset;
    can_callback_funcPtr setter;
    can_callback_funcPtr getter;
} CANS_signal_s;

/*================== Constant and Variable Definitions ====================*/

/**
 * array for transmission CAN0 signals definition
 */
extern const CANS_signal_s cans_CAN0_signals_tx[];

/**
 * array for transmission CAN1 signals definition
 */
extern const CANS_signal_s cans_CAN1_signals_tx[];

/**
 * array for received CAN0 signals definition
 */
extern const CANS_signal_s cans_CAN0_signals_rx[];

/**
 * array for received CAN1 signals definition
 */
extern const CANS_signal_s cans_CAN1_signals_rx[];

/**
 * length of the array for the CAN0 tx signals
 */
extern const uint16_t cans_CAN0_signals_tx_length;

/**
 * length of the array for the CAN1 tx signals
 */
extern const uint16_t cans_CAN1_signals_tx_length;

/**
 * length of the array for the CAN0 rx signals
 */
extern const uint16_t cans_CAN0_signals_rx_length;

/**
 * length of the array for the CAN1 rx signals
 */
extern const uint16_t cans_CAN1_signals_rx_length;

/*================== Function Prototypes ==================================*/


/*================== Function Implementations =============================*/

#endif /* CANSIGNAL_CFG_H_ */