//------------------------------------------------------------------------------
//! @file WiMODLR_BASE.cpp
//! @ingroup WiMODLR_BASE
//! <!------------------------------------------------------------------------->
//! @brief High-level Interface class to the WiMOD module running the WiMOD LR-Base firmware
//! @version 0.1
//! <!------------------------------------------------------------------------->
//!
//!
//!
//! <!--------------------------------------------------------------------------
//! Copyright (c) 2016
//! IMST GmbH
//! Carl-Friedrich Gauss Str. 2-4
//! 47475 Kamp-Lintfort
//! --------------------------------------------------------------------------->
//! @author (FB), IMST
//! <!--------------------------------------------------------------------------
//! Target OS:    none
//! Target CPU:   tbd
//! Compiler:     tbd
//! --------------------------------------------------------------------------->
//! @internal
//! @par Revision History:
//! <PRE>
//!-----------------------------------------------------------------------------
//! Version | Date       | Author | Comment
//!-----------------------------------------------------------------------------
//!
//! </PRE>
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
// Section Includes Files
//
//------------------------------------------------------------------------------
#include <WiMODLR_BASE.h>


#include <string.h>
//------------------------------------------------------------------------------
//
// Section public functions
//
//------------------------------------------------------------------------------


//-----------------------------------------------------------------------------
/**
 * @brief Constructor
 *
 * @param s     Reference to the serial interace to be used for communication.
 *              The serial interface must be initialized outside of this class
 *              prior calling the first command in runtime.
 *
 * @code
 * #include <WiMODLR_BASE.h>
 *
 * WiMODLRBASE wimod(Serial3);  // use the Arduino Serial3 as serial interface
 *
 * void setup() {
 *    // init stack
 *     wimod.begin();
 *    ...
 * }
 * @endcode
 */
WiMODLRBASE::WiMODLRBASE(Stream& s) :
    TWiMODLRHCI(s),
    SapDevMgmt(this, txBuffer, WiMOD_LR_BASE_TX_BUFFER_SIZE),
    SapRadioLink(this, txBuffer, WiMOD_LR_BASE_TX_BUFFER_SIZE),
    SapGeneric(this, txBuffer, WiMOD_LR_BASE_TX_BUFFER_SIZE)
//    SapHwTest(this, txBuffer, WiMOD_LR_BASE_TX_BUFFER_SIZE)
{
    cmdResult       = false;
    localStatusRsp  = 0;
    localHciRes     = WiMODLR_RESULT_TRANMIT_ERROR;
    lastHciRes      = WiMODLR_RESULT_TRANMIT_ERROR;
    lastStatusRsp   = 0;
    memset(txBuffer, 0x00, WiMOD_LR_BASE_TX_BUFFER_SIZE);
}

//-----------------------------------------------------------------------------
/**
 * @brief Destructor
 */
WiMODLRBASE::~WiMODLRBASE(void) {

}

//-----------------------------------------------------------------------------
/**
 * @brief Setup internal things
 *
 * This function must be executed at startup before any other service can
 * be used.
 *
 * @code
 * #include <WiMODLR_BASE.h>
 *
 * WiMODLRBASE wimod(Serial3);  // use the Arduino Serial3 as serial interface
 *
 * void setup() {
 *    // init stack
 *    wimod.begin();
 *    ...
 * }
 * @endcode
 */
void WiMODLRBASE::begin(void) {
//    TWiMODLRHCI::begin(s);
//    HciDispatcher.begin(s);
    TWiMODLRHCI::begin();
}

//-----------------------------------------------------------------------------
/**
 * @brief De-Setup internal things
 *
 */
void WiMODLRBASE::end(void) {
    TWiMODLRHCI::end();
//    HciDispatcher.end();
}

//===============================================================================
//
// DevMgmt
//
//===============================================================================

//-----------------------------------------------------------------------------
/**
 * @brief Ping Cmd - Checks serial connetion to WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * if (wimod.Ping()) {
 *     // success ...
 * } else {
 *     // error ...
 * }
 * @endcode
 *
 * OR:
 *
 * @code
 * TWiMODLRResultCodes hciResult;
 *
 * if (!wimod.Ping(&hciResult)) {
 *     // error: check HCI result codes
 *     if (WiMODLR_RESULT_TRANMIT_ERROR == hciResult) {...}
 *     if (WiMODLR_RESULT_NO_RESPONSE   == hciResult) {...}
 * }
 * @endcode
 *
 * OR:
 *
 * @code
 * TWiMODLRResultCodes hciResult;
 * uint8              rspCode;
 *
 * if (!wimod.Ping(&hciResult, &rspCode)) {
 *     // error: check HCI result codes
 *     if (WiMODLR_RESULT_OK == hciResult) {
 *         if (rspCode == DEVMGMT_STATUS_ERROR) {
 *           // operation failed
 *         }
 *         ...
 *     }
 *     ...
 * }
 * @endcode
 */
bool WiMODLRBASE::Ping(TWiMODLRResultCodes*         hciResult,
                       UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.Ping(&localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, (UINT8) DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Reset Cmd - Do a local reboot of the WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * // do a software reboot of the WiMOD device
 * if (wimod.Reset() {
 *     // ok; reset procedure has been started
 *     // wait a while for the reboot to be finished
 * }
 * ...
 * @endcode
 *
 */
bool WiMODLRBASE::Reset(TWiMODLRResultCodes*         hciResult,
                         UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.Reset(&localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Gets the basic DeviceInfo from WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param info      Pointer where to store the retrieved information
 *                  @see TWiMODLR_DevMgmt_DevInfo for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * //local variable
 * TWiMODLR_DevMgmt_DevInfo devInfo;
 *
 * // get information of WiMOD
 * if (wimod.GetDeviceInfo(&devInfo)) {
 *     // ok; process received information
 *     ...
 * }
 * ...
 * @endcode
 *
 */
bool WiMODLRBASE::GetDeviceInfo(TWiMODLR_DevMgmt_DevInfo*    info,
                                 TWiMODLRResultCodes*        hciResult,
                                 UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.GetDeviceInfo(info, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Gets the basic FirmwareInfo from WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param info      Pointer where to store the retrieved information
 *                  @see TWiMODLR_DevMgmt_FwInfo for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * //local variable
 * TWiMODLR_DevMgmt_FwInfo fwInfo;
 *
 * // get information of WiMOD
 * if (wimod.GetFirmwareInfo(&fwInfo)) {
 *     // ok; process received information
 *     if (fwInfo.FirmwareMayorVersion = 0x01) {...}
 * }
 * ...
 * @endcode
 */
bool WiMODLRBASE::GetFirmwareInfo(TWiMODLR_DevMgmt_FwInfo*   info,
                                 TWiMODLRResultCodes*        hciResult,
                                 UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.GetFirmwareInfo(info, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}



//-----------------------------------------------------------------------------
/**
 * @brief Gets the bas SystemStatus info from WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param info      Pointer where to store the retrieved information
 *                  @see TWiMODLR_DevMgmt_SystemStatus for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * //local variable
 * TWiMODLR_DevMgmt_SystemStatus sysStatus;
 *
 * // get information of WiMOD
 * if (wimod.GetSystemStatus(&sysStatus)) {
 *     // ok; process received information
 *     if (sysStatus.BatteryStatus < 2500) { //low batt. voltage detected }
 * }
 * ...
 * @endcode
 */
bool WiMODLRBASE::GetSystemStatus(TWiMODLR_DevMgmt_SystemStatus* info,
                                     TWiMODLRResultCodes*        hciResult,
                                     UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.GetSystemStatus(info, &localStatusRsp);
    if (info) {
        localStatusRsp = info->Status;
    }
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Gets the current RTC data info from WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param rtcTime   Pointer where to store the RTC information
 *                  @see WIMOD_RTC_GET_* Macros for conversation of this value
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * // create a local variable
 * uint32_t timestamp;
 *
 * // get information of WiMOD
 * wimod.GetRtc(&timestamp);
 *
 * //access fields of structure
 * printf("Year : %d:", WIMOD_RTC_GET_YEARS(timestamp));
 * printf("Month: %d:", WIMOD_RTC_GET_MONTHS(timestamp));
 * printf("Day  : %d:", WIMOD_RTC_GET_DAYS(timestamp));
 * printf("Hour : %d:", WIMOD_RTC_GET_HOURS(timestamp));
 * printf("Min  : %d:", WIMOD_RTC_GET_MINUTES(timestamp));
 * printf("Sec  : %d:", WIMOD_RTC_GET_SECONDS(timestamp));
 * ...
 * @endcode
 */
bool WiMODLRBASE::GetRtc(UINT32*                     rtcTime,
                         TWiMODLRResultCodes*        hciResult,
                         UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.GetRtc(rtcTime, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Sets the current RTC values to WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param rtcTime   RTC information to setup
 *                  @see WIMOD_RTC_MAKE_DATETIME_U32 Macro for conversation of this value
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * // create a local variable
 * uint32_t timestamp;
 *
 * // convert date/time to timestamp format ( 1st Oct 2016 16:12:55 )
 * timestamp = WIMOD_RTC_MAKE_DATETIME_U32(55, 12, 16, 1, 10, 2016);
 *
 * // set information to WiMOD
 * wimod.SetRtc(timestamp);
 * ...
 * @endcode
 */
bool WiMODLRBASE::SetRtc(const UINT32                rtcTime,
                         TWiMODLRResultCodes*        hciResult,
                         UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.SetRtc(rtcTime, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Gets the current configuration of the radio of the WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param radioCfg  Pointer where to store the information
 *                  @see TWiMODLR_DevMgmt_RadioConfig for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * // create a local variable
 * TWiMODLR_DevMgmt_RadioConfig radioCfg;
 *
 * // get information from WiMOD
 * if (wimod.GetRadioConfig(&radioCfg)) {
 *    // access the fields
 *     if (radioCfg.RadioMode != RadioMode_Standard) {
 *    // error unsupported mode
 *     }
 *     if (radioCfg.Modulation == Modulation_LoRa) {...}
 *     uint32_t freq = FreqCalc_calcRegisterToFreq(radioCfg.RfFreq_MSB,
 *                                  radioCfg.RfFreq_MID,
 *                                  radioCfg.RfFreq_LSB);
 *     ...
 * }
 * ...
 * @endcode
 */
bool WiMODLRBASE::GetRadioConfig(TWiMODLR_DevMgmt_RadioConfig* radioCfg,
                                 TWiMODLRResultCodes*          hciResult,
                                 UINT8*                        rspStatus)
{
    localHciRes = SapDevMgmt.GetRadioConfig(radioCfg, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Sets the current configuration for the radio of the WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param radioCfg  Pointer where to read the information
 *                  @see TWiMODLR_DevMgmt_RadioConfig for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * // create a local variable
 * TWiMODLR_DevMgmt_RadioConfig radioCfg;
 *
 * // setup new radio config
 * radioCfg.RadioMode    = RadioMode_Standard;
 * radioCfg.StoreNwmFlag = 0x01; // store new config permanently
 * radioCfg.Modulation   = Modulation_LoRa;
 * radioCfg.PowerLevel   = TxPowerLevel_14_dBm;
 * ...
 * FreqCalc_calcFreqToRegister(868300000,
 *                             &radioCfg.RfFreq_MSB,
 *                             &radioCfg.RfFreq_MID,
 *                             &radioCfg.RfFreq_LSB);
 * ...
 *
 * // set information from WiMOD
 * if (wimod.SetRadioConfig(&radioCfg)) {
 *     //ok new config has been setup
 * }
 * ...
 * @endcode
 */
bool WiMODLRBASE::SetRadioConfig(const TWiMODLR_DevMgmt_RadioConfig* radioCfg,
                                 TWiMODLRResultCodes*                hciResult,
                                 UINT8*                              rspStatus)
{
    localHciRes = SapDevMgmt.SetRadioConfig(radioCfg, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Resets the current configuration to defaults
 *
 * @see HCI Documentation for details of default settings
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * ...
 * // reset radio config from WiMOD to defaults
 * if (wimod.ResetRadioConfig()) {
 *     //ok config has been setup to defaults
 * }
 * ...
 * @endcode
 */
bool WiMODLRBASE::ResetRadioConfig(TWiMODLRResultCodes*        hciResult,
                                   UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.ResetRadioConfig(&localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}


//-----------------------------------------------------------------------------
/**
 * @brief SetRadioMode - Set the current radio mode of the WiMOD
 *
 *
 * @param   radioMode    the new radio mode to set
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @warning: This use this command with care!
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 */

bool WiMODLRBASE::SetRadioMode(const TRadioCfg_RadioMode    radioMode,
                               TWiMODLRResultCodes*         hciResult,
                               UINT8*                       rspStatus)
{
    localHciRes = SapDevMgmt.SetRadioMode(radioMode, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}


//-----------------------------------------------------------------------------
/**
 * @brief Gets the current operation mode of the WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param opMode   Pointer where to store the information
 *                  @see TWiMOD_OperationMode for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * // local variable
 * TWiMOD_OperationMode opMode;
 *
 * // get information from WiMOD
 * if (wimod.GetOperationMode(&opMode)) {
 *     //ok
 *     if (opMode != OperationMode_Application) {
 *         // normal operation is disabled; only test functionality is enabled
 *     }
 * }
 * ...
 * @endcode
 */
bool WiMODLRBASE::GetOperationMode(TWiMOD_OperationMode*      opMode,
                                   TWiMODLRResultCodes*       hciResult,
                                   UINT8*                     rspStatus)
{
    localHciRes = SapDevMgmt.GetOperationMode(opMode, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Sets the current operation mode of the WiMOD module
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param opMode    The new operation mode to set
 *                  @see TWiMOD_OperationMode for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * // local variable
 * TWiMOD_OperationMode opMode;
 *
 * // setup new opMode
 * opMode = OperationMode_Application;
 *
 * // write information to WiMOD
 * if (wimod.SetOperationMode(opMode)) {
 *     //ok; wait a little bit to setup everthing
 * }
 * ...
 * @endcode
 */
bool WiMODLRBASE::SetOperationMode(const TWiMOD_OperationMode opMode,
                                   TWiMODLRResultCodes*       hciResult,
                                   UINT8*                     rspStatus)
{
    localHciRes = SapDevMgmt.SetOperationMode(opMode, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Sets the security 128bit AES key to use for RF communication
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param key       Pointer to the 128bit AES key to by used
 *
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * const uint8_t AesKey[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0C, 0x0D, 0x0E, 0x0F};
 *
 * // write new AES key to WiMOD (LR-Base mode ONLY!)
 * if (wimod.SetAesKey(AesKey)) {
 *     //ok;
 * }
 * ...
 * @endcode
 */
bool WiMODLRBASE::SetAesKey(const UINT8*                key,
                            TWiMODLRResultCodes*        hciResult,
                            UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.SetAesKey(key, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);

}

//-----------------------------------------------------------------------------
/**
 * @brief Gets the used security 128bit AES key
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param key       Pointer to the 128bit AES key that is used
 *
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * const uint8_t AesKey[16];
 *
 * // read AES key from WiMOD (LR-Base mode ONLY!)
 * if (wimod.GetAesKey(AesKey)) {
 *     //ok;
 * }
 * ...
 * @endcode
 *
 */
bool WiMODLRBASE::GetAesKey(UINT8*                      key,
                            TWiMODLRResultCodes*        hciResult,
                            UINT8*                      rspStatus)
{
    localHciRes = SapDevMgmt.GetAesKey(key, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);

}

//-----------------------------------------------------------------------------
/**
 * @brief Sets and enables the RTC alarm feature of the WiMOD
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param rtcAlarm   Pointer to a structure containing the RTC alarm related
 *                   information
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * \msc
 * UserApp,WiMOD;
 * UserApp=>WiMOD  [label="SetRtcAlarm(rtcAlarmData)"];
 * ...;
 * --- [label="RTC triggers alarm"];
 * UserApp<<=WiMOD [label="myRtcAlarmCallback()"];
 * UserApp->UserApp [label="start triggered processing"];
 * \endmsc
 *
 *
 * @code
 * // create a local variable
 * TWiMODLR_DevMgmt_RtcAlarm rtcAlarm;
 *
 * // setup RTC Alarm
 * rtcAlarm.Options = RTC_Alarm_Single;  // single, non repeated alarm
 * rtcAlarm.Hour    = 13;                // alarm at 13:45:20
 * rtcAlarm.Minutes = 32;
 * rtcAlarm.Seconds = 20;
 *
 * // set information of WiMOD
 * wimod.SetRtcAlarm(&rtcAlarm);
 * ...
 * // wait for alarm to occur
 * @endcode
 */
bool WiMODLRBASE::SetRtcAlarm(const TWiMODLR_DevMgmt_RtcAlarm*    rtcAlarm,
                              TWiMODLRResultCodes*                hciResult,
                              UINT8*                              rspStatus)
{
    localHciRes = SapDevMgmt.SetRtcAlarm(rtcAlarm, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}


//-----------------------------------------------------------------------------
/**
 * @brief Gets information about the RTC alarm feature of the WiMOD
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param rtcAlarm   Pointer to a structure where to store the RTC alarm related
 *                   information
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * // create a local variable
 * TWiMODLR_DevMgmt_RtcAlarm rtcAlarm;
 *
 * // get information of WiMOD
 * wimod.GetRtcAlarm(&rtcAlarm);
 * ...
 * // access values
 * if (rtcAlarm.AlarmStatus == RTC_Alarm_Alarm_Set) {
 *     printf("Alarm is active");
 *     ...
 * }
 * ...
 * @endcode
 */
bool WiMODLRBASE::GetRtcAlarm(TWiMODLR_DevMgmt_RtcAlarm*         rtcAlarm,
                              TWiMODLRResultCodes*               hciResult,
                              UINT8*                             rspStatus)
{
    localHciRes = SapDevMgmt.GetRtcAlarm(rtcAlarm, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Clears pending RTC Alarms of the WiMOD
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * // clear a pending RTC alarm of WiMOD
 * wimod.ClearRtcAlarm();
 * ...
 * @endcode
 */
bool WiMODLRBASE::ClearRtcAlarm(TWiMODLRResultCodes*             hciResult,
                                UINT8*                           rspStatus)
{
    localHciRes = SapDevMgmt.ClearRtcAlarm(&localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}



//-----------------------------------------------------------------------------
/**
 * @brief Register a callback function for the PowerUp Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TDevMgmtPowerUpCallback for details
 *
 * \msc
 * UserApp,WiMOD;
 * UserApp=>WiMOD  [label="RegisterPowerUpIndicationClient(clientCB)"];
 * ...;
 * ---             [label="if WiMOD reboots"];
 * UserApp<<=WiMOD [label="PowerUpCallback()"];
 * \endmsc
 *
 * @code
 * // user defined callback function
 * void myPowerUpCallback(void) {
 *      // WiMOD just powered up
 *     ...
 * }
 *
 * void setup() {
 *     ...
 *     // "connect" the user defined to callback to the WiMOD callback feature
 *     wimod.RegisterPowerUpIndicationClient(myPowerUpCallback);
 *     ...
 * }
 * @endcode
 */
void WiMODLRBASE::RegisterPowerUpIndicationClient(TDevMgmtPowerUpCallback cb)
{
    SapDevMgmt.RegisterPowerUpIndicationClient(cb);
}


//-----------------------------------------------------------------------------
/**
 * @brief Register a callback function for the RTC Alarm Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TDevMgmtRtcAlarmCallback for details
 * \msc
 * UserApp,WiMOD;
 * UserApp=>WiMOD  [label="RegisterRtcAlarmIndicationClient(clientCB)"];
 * ...;
 * UserApp<<=WiMOD [label="RtcAlarmCallback()"];
 * \endmsc
 *
 * @code
 * // user defined callback function
 * void myRtcAlarmCallback(void) {
 *     // RTC Alarm has just been triggered
 *     ...
 * }
 *
 * void setup() {
 *     ...
 *     // "connect" the user defined to callback to the WiMOD callback feature
 *     wimod.RegisterRtcAlarmIndicationClient(myRtcAlarmCallback);
 *     ...
 * }
 * @endcode
 */
void WiMODLRBASE::RegisterRtcAlarmIndicationClient(TDevMgmtRtcAlarmCallback cb)
{
    SapDevMgmt.RegisterRtcAlarmIndicationClient(cb);
}

//===============================================================================
//
// Radio Link Service
//
//===============================================================================

//-----------------------------------------------------------------------------
/**
 * @brief Tries to send transmit U-Data to peer module via RF link
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param txMsg      Data structure containing the TX-data and options.
 *                   @see TWiMODLR_RadioLink_Msg for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp=>WiMOD       [label="SendUData(data)"];
 * WiMOD->RemotePeer    [label="transfer data"];
 * UserApp<<WiMOD       [label="true/false"];
 * ...;
 * \endmsc
 *
 * @code
 * ...
 * // local variable
 * TWiMODLR_RadioLink_Msg txData;
 *
 * // setup tx packet
 * txData.DestinationGroupAddress   = 0x10;
 * txData.DestinationDeviceAddress  = 0x1234;
 * txData.Length =  strlen("Hello World!");
 * strncpy(txData.Payload, "Hello World!", WiMODLORAWAN_APP_PAYLOAD_LEN);
 *
 * // send data
 * wimod.SendUData(&txData);
 * ...
 * @endcode
 */
bool WiMODLRBASE::SendUData(const TWiMODLR_RadioLink_Msg*  txMsg,
                            TWiMODLRResultCodes*           hciResult,
                            UINT8*                         rspStatus)
{
    localHciRes = SapRadioLink.SendUData(txMsg, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, RADIOLINK_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Tries to send transmit C-Data to peer module via RF link
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param txMsg      Data structure containing the TX-data and options.
 *                   @see TWiMODLR_RadioLink_Msg for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp=>WiMOD     [label="SendUData(data)"];
 * WiMOD->RemotePeer  [label="transfer data"];
 * UserApp<<WiMOD     [label="true/false"];
 * ...;
 * WiMOD << RemotePeer [label= "ACK"];
 * --- [label="if ack callback is registered"];
 * UserApp << WiMOD [label="myAckCallback"];
 * ...;
 *
 * \endmsc
 *
 * @code
 * ...
 * // local variable
 * TWiMODLR_RadioLink_Msg txData;
 *
 * // setup tx packet
 * txData.DestinationGroupAddress   = 0x10;
 * txData.DestinationDeviceAddress  = 0x1234;
 * txData.Length =  strlen("Hello World!");
 * strncpy(txData.Payload, "Hello World!", WiMODLORAWAN_APP_PAYLOAD_LEN);
 *
 * // send data
 * wimod.SendCData(&txData);
 * ...
 * // if ACK callback has been registered: wait for callback
 * // to be called and check the received indication data
 * // in order to get the status of the transmission
 * ...
 * @endcode
 *
 */
bool WiMODLRBASE::SendCData(const TWiMODLR_RadioLink_Msg*  txMsg,
                            TWiMODLRResultCodes*           hciResult,
                            UINT8*                         rspStatus)
{
    localHciRes = SapRadioLink.SendCData(txMsg, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, RADIOLINK_STATUS_OK);
}

//-----------------------------------------------------------------------------
/**
 * @brief Convert a received low level HCI-Msg to a high-level RadioLink-Msg
 *
 * This function should be used by the RxUData / RxCData callback functions
 * prior processing the received data message.
 *
 * @param   RxMsg       Reference to low-level HCI message.
 *                      @warning DO NOT MANIPULATE THESE VALUES !!!
 *
 * @param   radioLinkMsg Pointer to the buffer where to store the received data
 *
 * @retval true     if the conversion was successful
 *
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp=>WiMOD     [label="RegisterUDataRxClient(myRxDataInd)"];
 * ...;
 * --- [label="Peer device want to transfer data"];
 * WiMOD<-RemotePeer  [label="transfer data"];
 * --- [label="if ack callback is registered"];
 * UserApp << WiMOD [label="myRxDataInd()"];
 * UserApp->UserApp [label="further processing"];
 * ...;
 *
 * \endmsc
 *
 * @code
 * // global buffer for incoming messages
 * TWiMODLR_RadioLink_Msg radioRxMsg;
 *
 * void myRxDataInd(TWiMODLR_HCIMessage& rxMsg) {
 *    // convert/copy the raw message to RX radio buffer
 *    if (wimod.convert(rxMsg, &radioRxMsg)) {
 *        // access the radioRxMsg fields
 *
 *        // radioRxMsg.Length
 *        // radioRxMsg.Payload
 *    ...
 *    }
 * }
 *...
 *
 * void setup() {
 *    ...
 *    // init the communication stack
 *    wimod.begin();
 *
 *     // register callbacks for incoming RF messages
 *    wimod.RegisterUDataRxClient(myRxDataInd);
 *    wimod.RegisterCDataRxClient(myRxDataInd);
 *    ...
 * }
 * @endcode
 */
bool WiMODLRBASE::convert(TWiMODLR_HCIMessage&    RxMsg,
                          TWiMODLR_RadioLink_Msg* radioLinkMsg) {
    return SapRadioLink.convert(RxMsg, radioLinkMsg);
}

//-----------------------------------------------------------------------------
/**
 * @brief Convert a received low level HCI-Msg to a high-level CDataTx Info
 *
 * This function should be used by the Tx-C-Data Indication Callback functions
 * prior processing the received data message.
 *
 * @param   RxMsg       Reference to low-level HCI message.
 *                      @warning DO NOT MANIPULATE THESE VALUES !!!
 *
 * @param   cDataTxInfo Pointer to the buffer where to store the received data
 *
 * @retval true     if the conversion was successful
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp=>WiMOD     [label="RegisterCDataTxClient(myTxCDataInd)"];
 * ...;
 * UserApp->WiMOD     [label="SendCData(data)"];
 * WiMOD->RemotePeer  [label="transfer data"];
 * --- [label="if callback is registered"];
 * UserApp << WiMOD   [label="myTxCDataInd()"];
 * UserApp->UserApp [label="further processing"];
 * ...;
 *
 * \endmsc
 *
 * @code
 * // global buffer for indication that CData has been send
 * TWiMODLR_RadioLink_CdataInd txDataMsg;
 *
 * void myTxCDataInd(TWiMODLR_HCIMessage& rxMsg) {
 *    // convert/copy the raw message to RX radio buffer
 *    if (wimod.convert(rxMsg, &txDataMsg)) {
 *        // access the fields folding information about the transmission
 *
 *        // txDataMsg.TxEventCounter
 *    ...
 *    }
 * }
 *...
 *
 * void setup() {
 *    ...
 *    // init the communication stack
 *    wimod.begin();
 *
 *     // register callback
 *    wimod.RegisterCDataTxClient(myTxCDataInd);
 *    ...
 * }
 * @endcode
 *
 */
bool WiMODLRBASE::convert(TWiMODLR_HCIMessage&         RxMsg,
                          TWiMODLR_RadioLink_CdataInd* cDataTxInfo) {
    return SapRadioLink.convert(RxMsg, cDataTxInfo);
}


//-----------------------------------------------------------------------------
/**
 * @brief Convert a received low level HCI-Msg to a high-level UDataTx Info
 *
 * This function should be used by the Tx-U-Data Indication Callback functions
 * prior processing the received data message.
 *
 * @param   RxMsg       Reference to low-level HCI message.
 *                      @warning DO NOT MANIPULATE THESE VALUES !!!
 *
 * @param   uDataTxInfo Pointer to the buffer where to store the received data
 *
 * @retval true     if the conversion was successful
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp=>WiMOD     [label="RegisterUDataTxClient(myTxUDataInd)"];
 * ...;
 * UserApp->WiMOD     [label="SendUData(data)"];
 * WiMOD->RemotePeer  [label="transfer data"];
 * --- [label="if callback is registered"];
 * UserApp << WiMOD   [label="myTxUDataInd()"];
 * UserApp->UserApp [label="further processing"];
 * ...;
 *
 * \endmsc
 *
 * @code
 * // global buffer for indication that UData has been send
 * TWiMODLR_RadioLink_UdataInd txDataMsg;
 *
 * void myTxCDataInd(TWiMODLR_HCIMessage& rxMsg) {
 *    // convert/copy the raw message to RX radio buffer
 *    if (wimod.convert(rxMsg, &txDataMsg)) {
 *        // access the fields folding information about the transmission
 *
 *        // txDataMsg.TxEventCounter
 *    ...
 *    }
 * }
 *...
 *
 * void setup() {
 *    ...
 *    // init the communication stack
 *    wimod.begin();
 *
 *     // register callback
 *    wimod.RegisterCDataTxClient(myTxCDataInd);
 *    ...
 * }
 * @endcode
 *
 */
bool WiMODLRBASE::convert(TWiMODLR_HCIMessage&         RxMsg,
                          TWiMODLR_RadioLink_UdataInd* uDataTxInfo) {
    return SapRadioLink.convert(RxMsg, uDataTxInfo);
}

//-----------------------------------------------------------------------------
/**
 * @brief Convert a received low level HCI-Msg to a high-level AckTxInd Info
 *
 * This function should be used by the AckTx Indication Callback functions
 * prior processing the received data message.
 *
 * @param   RxMsg       Reference to low-level HCI message.
 *                      @warning DO NOT MANIPULATE THESE VALUES !!!
 *
 * @param   txAckIndInfo Pointer to the buffer where to store the received data
 *
 * @retval true     if the conversion was successful
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp=>WiMOD     [label="RegisterAckTxCallback(myTxAckInd)"];
 * ...;
 * WiMOD << RemotePeer [label="transfer C Data"];
 * WiMOD -> RemotePeer [label= "C data ack"];
 * UserApp << WiMOD   [label="myTxAckInd()"];
 * UserApp->UserApp [label="further processing"];
 * ...;
 * \endmsc
 *
 * @code
 * // global buffer
 * TWiMODLR_AckTxInd_Msg txAckData;
 *
 * void myTxAckInd(TWiMODLR_HCIMessage& rxMsg) {
 *    // convert/copy the raw message
 *    if (wimod.convert(rxMsg, &txAckData)) {
 *        // access the fields folding information about the ACK transmission
 *
 *        // txDataMsg.Status
 *    ...
 *    }
 * }
 *...
 *
 * void setup() {
 *    ...
 *    // init the communication stack
 *    wimod.begin();
 *
 *     // register callback
 *    wimod.RegisterAckTxCallback(myTxAckInd);
 *    ...
 * }
 * @endcode
 */
bool WiMODLRBASE::convert(TWiMODLR_HCIMessage&   RxMsg,
                          TWiMODLR_AckTxInd_Msg* txAckIndInfo) {
    return SapRadioLink.convert(RxMsg, txAckIndInfo);
}

//-----------------------------------------------------------------------------

//! @cond Doxygen_Suppress
bool WiMODLRBASE::convert(TWiMODLR_HCIMessage& RxMsg,
                            TWiMODLR_RadioLink_RawMsg* radioLinkRawMsg) {
    return SapRadioLink.convert(RxMsg, radioLinkRawMsg);
}
//! @endcond

//-----------------------------------------------------------------------------
/**
 * @brief Sets additional user payload for the next ack frame to send
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param txMsg     Pointer to data structure containing the payload data.
 *                  note: Max ack payload size is 8 byte!
 *                  @see TWiMODLR_RadioLink_Msg for details
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp -> WiMOD     [label="SetAckData(payload)"];
 * ...;
 * WiMOD << RemotePeer [label="transfer C Data"];
 * WiMOD -> RemotePeer [label= "C data ack + payload"];
 * ...;
 * \endmsc
 *
 * @code
 * // global buffer
 * TWiMODLR_RadioLink_Msg ackPayloadData;
 * ...
 * // if you want that the next ack that will be send should contain
 * // additional payload: setup the data structure
 * ackPayloadData.DestinationGroupAddress = ...;
 * ackPayloadData.DestinationDeviceAddress = ...;
 * ackPayloadData.Length = ...;
 * ackPayloadData.Payload = ...;
 *
 * // prepare the next ack packet
 * wimod.SetAckData(ackPayloadData);
 * ...
 * @endcode
 *
 */
bool WiMODLRBASE::SetAckData(const TWiMODLR_RadioLink_Msg* txMsg,
                             TWiMODLRResultCodes*          hciResult,
                             UINT8*                        rspStatus)
{
    localHciRes = SapRadioLink.SetAckData(txMsg, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, RADIOLINK_STATUS_OK);
}


//-----------------------------------------------------------------------------
/**
 * @brief Register a callback function for the RX U-Data Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TRadioLinkUDataRxIndicationCallback for details
 *
 * @note The callback function should call the corresponding convert in
 *        order to decode the message properly
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp -> WiMOD    [label="RegisterUDataTxClient(rxUDataInd)"];
 * ...;
 * WiMOD << RemotePeer [label="transfer U Data"];
 * --- [label= "if callback is registered"];
 * UserApp << WiMOD    [label="rxUDataInd(U Data)"];
 * ...;
 * \endmsc
 *
 * @code
 * // callback for U data Rx indication
 * void myUDataRxInd(TWiMODLR_HCIMessage& rxMsg) {
 *     // use the convert function before accessing the data
 *     ...
 * }
 *
 * void setup() {
 *     ...
 *     // setup the callback
 *     wimod.RegisterUDataRxClient(myUDataRxInd);
 *     ...
 * }
 *
 * ...
 * @endcode
 */
void WiMODLRBASE::RegisterUDataRxClient(TRadioLinkUDataRxIndicationCallback cb)
{
    SapRadioLink.RegisterUDataRxClient(cb);
}
//-----------------------------------------------------------------------------
/**
 * @brief Register a callback function for the TX U-Data Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TRadioLinkUDataTxIndicationCallback for details
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp -> WiMOD    [label="RegisterUDataTxClient(txUDataInd)"];
 * ...;
 * UserApp -> WiMOD    [label="SendUData(data)"];
 * WiMOD -> RemotePeer [label="transfer data"];
 * --- [label= "if callback is registered"];
 * UserApp << WiMOD    [label="txUDataInd()"];
 * ...;
 * \endmsc
 *
 * @code
 * // callback for U data Tx indication
 * void myUDataTxInd() {
 *     ...
 * }
 *
 * void setup() {
 *     ...
 *     // setup the callback
 *     wimod.RegisterUDataTxClient(myUDataTxInd);
 *     ...
 * }
 *
 * ...
 * @endcode
 */
void WiMODLRBASE::RegisterUDataTxClient(TRadioLinkUDataTxIndicationCallback cb)
{
    SapRadioLink.RegisterUDataTxClient(cb);
}

//-----------------------------------------------------------------------------

/**
 * @internal
 * @brief Register a callback function for the RX Raw-Data Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TRadioLinkRawDataRxIndicationCallback for details
 *
 * @note The callback function should call the corresponding convert in
 *        order to decode the message properly
 *
 * @endinternal
 */
void WiMODLRBASE::RegisterRawDataRxClient(TRadioLinkRawDataRxIndicationCallback cb)
{
    SapRadioLink.RegisterRawDataRxClient(cb);
}

//-----------------------------------------------------------------------------
/**
 * @brief Register a callback function for the RX C-Data Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TRadioLinkCDataRxIndicationCallback for details
 *
 * @note The callback function should call the corresponding convert in
 *        order to decode the message properly
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp -> WiMOD    [label="RegisterCDataTxClient(rxCDataInd)"];
 * ...;
 * WiMOD << RemotePeer [label="transfer C Data"];
 * --- [label= "if callback is registered"];
 * UserApp << WiMOD    [label="rxCDataInd(C Data)"];
 * ...;
 * \endmsc
 *
 * @code
 * // callback for C data Rx indication
 * void myCDataRxInd(TWiMODLR_HCIMessage& rxMsg) {
 *     // use the convert function before accessing the data
 *     ...
 * }
 *
 * void setup() {
 *     ...
 *     // setup the callback
 *     wimod.RegisterCDataRxClient(myCDataRxInd);
 *     ...
 * }
 *
 * ...
 * @endcode
 */
void WiMODLRBASE::RegisterCDataRxClient(TRadioLinkCDataRxIndicationCallback cb)
{
    SapRadioLink.RegisterCDataRxClient(cb);
}

//-----------------------------------------------------------------------------
/**
 * @brief Register a callback function for the TX C-Data Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TRadioLinkCDataTxIndicationCallback for details
 *
 * @note The callback function should call the corresponding convert in
 *        order to decode the message properly
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp -> WiMOD    [label="RegisterCDataTxClient(txCDataInd)"];
 * ...;
 * UserApp -> WiMOD    [label="SendCData(data)"];
 * WiMOD -> RemotePeer [label="transfer data"];
 * --- [label= "if callback is registered"];
 * UserApp << WiMOD    [label="txCDataInd()"];
 * ...;
 * \endmsc
 *
 * @code
 * // callback for U data Tx indication
 * void myCDataTxInd(TWiMODLR_HCIMessage& rxMsg) {
 *     // use the convert function before accesing the data
 *     ...
 * }
 *
 * void setup() {
 *     ...
 *     // setup the callback
 *     wimod.RegisterCDataTxClient(myCDataTxInd);
 *     ...
 * }
 *
 * ...
 * @endcode
 */
void WiMODLRBASE::RegisterCDataTxClient(TRadioLinkCDataTxIndicationCallback cb)
{
    SapRadioLink.RegisterCDataTxClient(cb);
}

//-----------------------------------------------------------------------------
/**
 * @brief Register a callback function for the RX Ack (+data) Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TRadioLinkAckRxIndicationCallback for details
 *
 * @note The callback function should call the corresponding convert in
 *        order to decode the message properly
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp -> WiMOD    [label="RegisterAckRxClient(ackRxInd)"];
 * ...;
 * UserApp -> WiMOD    [label="SendCData(data)"];
 * WiMOD -> RemotePeer [label="transfer data"];
 * WiMOD <- RemotePeer [label="Ack"];
 * --- [label= "if callback is registered"];
 * UserApp << WiMOD    [label="ackRxInd()"];
 * ...;
 * \endmsc
 *
 * @code
 * // callback for U data Tx indication
 * void myAckRxInd(TWiMODLR_HCIMessage& rxMsg) {
 *      // use the convert function before accesing the data
 *   ...
 * }
 *
 * void setup() {
 *     ...
 *     // setup the callback
 *     wimod.RegisterAckRxClient(myAckRxInd);
 *     ...
 * }
 *
 * ...
 * @endcode
 */
void WiMODLRBASE::RegisterAckRxClient(TRadioLinkAckRxIndicationCallback cb)
{
    SapRadioLink.RegisterAckRxClient(cb);
}

//-----------------------------------------------------------------------------
/**
 * @brief Register a callback function for the Ack Timeout Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TRadioLinkAckRxTimeoutIndicationCallback for details
 *
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp -> WiMOD    [label="RegisterAckRxTimeoutClient(ackTimeoutInd)"];
 * ...;
 * UserApp -> WiMOD    [label="SendCData(data)"];
 * WiMOD -> RemotePeer [label="transfer data"];
 * WiMOD x- RemotePeer [label="Ack"];
 * --- [label= "if callback is registered"];
 * ...;
 * UserApp << WiMOD    [label="ackTimeoutInd()"];
 * ...;
 * \endmsc
 *
 * @code
 * // callback for a missing ACK packet
 * void myAckRxTimemoutInd() {
 *      // this is called if an expected ACK has NOT been received
 *      // within expected time; it it up to the application to
 *      // react accordingly! (e.g. retransmission the data)
 *   ...
 * }
 *
 * void setup() {
 *     ...
 *     // setup the callback
 *     wimod.RegisterAckRxTimeoutClient(myAckRxTimemoutInd);
 *     ...
 * }
 *
 * ...
 * @endcode
 */
void WiMODLRBASE::RegisterAckRxTimeoutClient(TRadioLinkAckRxTimeoutIndicationCallback cb)
{
    SapRadioLink.RegisterAckRxTimeoutClient(cb);
}

//-----------------------------------------------------------------------------
/**
 * @brief Register a callback function for the TX Ack Indication - optional -
 *
 *
 * @see TWiMODLRResultCodes for interpretation of the values
 *
 * @param cb        Pointer a callback function
 *                  @see TRadioLinkAckTxIndicationCallback for details
 * \msc
 * UserApp,WiMOD,RemotePeer;
 * ... ;
 * UserApp -> WiMOD    [label="RegisterAckTxCallback(ackTxInd)"];
 * ...;
 * WiMOD <- RemotePeer [label="transfer C data"];
 * WiMOD -> RemotePeer [label= "Ack"];
 * --- [label= "if callback is registered"];
 * UserApp << WiMOD    [label="ackTxInd()"];
 * ...;
 * \endmsc
 *
 * @code
 * // callback for C data Ack Tx indication
 * void myAckTxInd() {
 *      // this is called if an ACK has been send
 *   ...
 * }
 *
 * void setup() {
 *     ...
 *     // setup the callback
 *     wimod.RegisterAckTxCallback(myAckTxInd);
 *     ...
 * }
 *
 * ...
 * @endcode
 *
 */
void WiMODLRBASE::RegisterAckTxCallback(TRadioLinkAckTxIndicationCallback cb)
{
    SapRadioLink.RegisterAckTxCallback(cb);
}


/**
 * @brief Convert a frequency in Hz to the corresponding low level register values
 *
 *
 * @param freq      Target frequencey in Hz
 *
 * @param msb       Pointer to register value for MSB-Part
 * @param mid       Pointer to register value for MID-Part
 * @param lsb       Pointer to register value for LSB-Part
 */
void WiMODLRBASE::calcFreqToRegister(uint32_t freq, uint8_t* msb, uint8_t* mid, uint8_t* lsb)
{
    if (msb && mid && lsb) {
        FreqCalc_calcFreqToRegister(freq, msb, mid, lsb);
    }
}

/**
 * @brief Convert a frequency registers to frequency in Hz
 *
 * @param msb       register value for MSB-Part
 * @param mid       register value for MID-Part
 * @param lsb       register value for LSB-Part
 *
 * return Frequency in Hz
 */
uint32_t WiMODLRBASE::calcRegisterToFreq(uint8_t msb, uint8_t mid, uint8_t lsb)
{
    return FreqCalc_calcRegisterToFreq(msb, mid, lsb);
}


//-----------------------------------------------------------------------------
/**
 * @brief Gets the value of the last local HCI TX status
 *
 * If the optional parameters have been left out (for the normal commands),
 * the user can get the last value back by using this function
 *
 * @retval the last value of the last command issued
 *
 * \msc
 * UserApp,WiMOD;
 * UserApp=>WiMOD    [label="Ping()"];
 * UserApp<<WiMOD   [label="(false)"];
 * UserApp=>WiMOD    [label="GetGetLastHciResult()"];
 * UserApp<<WiMOD    [label="(result of last HCI TX operation)"];
 * ...;
 * \endmsc
 *
 * @code
 * ...
 * if (wimod.Ping() == false) {
 *     TWiMODLRResultCodes hciResult;
 *
 *     // get (local) result of HCI command transmission
 *     hciResult = wimod.GetLastHciResult();
 *
 *     // check result code
 *     switch (hciResult):
 *     case WiMODLR_RESULT_OK:                   // OK, no error
 *     case WiMODLR_RESULT_PAYLOAD_LENGTH_ERROR: // given payload is too big
 *     case WiMODLR_RESULT_PAYLOAD_PTR_ERROR:    // wrong pointer to payload (NULL?)
 *     case WiMODLR_RESULT_TRANMIT_ERROR,        // Error sending data to WiMOD via serial interface
 *     case WiMODLR_RESULT_SLIP_ENCODER_ERROR,   // Error during SLIP encoding
 *     case WiMODLR_RESULT_NO_RESPONSE           // The WiMOD did not respond to a request command
 *  ...
 * }
 *
 * ...
 * @endcode
 */
TWiMODLRResultCodes WiMODLRBASE::GetLastHciResult(void)
{
    return lastHciRes;
}

//-----------------------------------------------------------------------------
/**
 * @brief Gets the value of the last status response value of the WiMOD
 *
 * If the optional parameters have been left out (for the normal commands),
 * the user can get the last value back by using this function
 *
 * @retval the last value of the last command issued
 *
 *
 *  * @code
 * ...
 * if (wimod.Ping() == false) {
 *     uint8_t rsp;
 *
 *     // get (remote) response code
 *     rsp = wimod.GetLastResponseStatus();
 *
 *     // check result code
 *     switch (rsp):
 *     case LoRaWAN_Status_Ok:                    // OK; No error;
 *             // --> check "remote" ResponseStatus
 *     case LoRaWAN_Status_Error:                 // general (un-specific) error
 *     case LoRaWAN_Status_Cmd_Not_Supported:     // Command is not supported (or unknown)
 *     case LoRaWAN_Status_Wrong_parameter:       // Wrong parameter applied
 *     case LoRaWAN_Status_Wrong_DeviceMode:      // Device is in wong device mode for specific command
 *     case LoRaWAN_Status_Device_Not_Activated:  // Device has NOT been activated; command has not been executed
 *     case LoRaWAN_Status_Device_Busy:           // There is another operation pending; and or duty cycle restriction is active
 *     case LoRaWAN_Status_Queue_Full:            // internal command queue is full
 *     case LoRaWAN_Status_Length_Error:          // some error related to the given length information
 *     case LoRaWAN_Status_No_Factory_Settings:   // Factory settings are not available
 *     case LoRaWAN_Status_Channel_Blocked:       // Selected channel is blocked (duty cycle?)
 *     case LoRaWAN_Status_Channel_Not_Available: // Selected channel is not available
 *     ...
 * }
 *
 * ...
 * @endcode
 *
 */
UINT8 WiMODLRBASE::GetLastResponseStatus(void)
{
    return lastStatusRsp;
}



//===============================================================================
//
// Generic
//
//===============================================================================

/**
 * @brief Generic Execution Function for HCI commands that are currently not implemented
 *
 * This funtion enables the user to execute various HCI commands that are
 * currently not implemented as commands within this API class.
 *
 * The user has to know the HCI Command IDs and has to decode the response data
 * on his own.
 *
 * @param info      pointer to a structure containing the HCI commands to execute
 *
 * @param hciResult Result of the local command transmission to module
 *                  This is an optional parameter.
 *
 * @param rspStatus Status byte contained in the local response of the module
 *                  This is an optional parameter.
 *
 * @retval true     if everything is ok
 * @retval false    if something went wrong; see hciResult & rspStatus for details
 *
 * @code
 * ...
 * // prepare command to send to WiMOD
 * TWiMODLR_Generic_CmdInfo cmdInfo;
 * cmdInfo.SapID    = 0x01; // DevMgmt
 * cmdInfo.MsgReqID = 0x01; // Ping Req
 * cmdInfo.MsgRspID = 0x02; // expected response
 *
 * // prepare payload for tx command
 * cmdInfo.CmdPayloadLength = 0
 * cmdInfo.CmdPayload[0] = 0xab;
 * ...
 *
 * // execute command
 * if (wimod.ExecuteGenericCmd(&cmdInfo)) {
 *      // extract cmd reponse data
 *      if (cmdInfo.CmdPayloadLength > 0) {
 *          // repsonse data available
 *          rspData =cmdInfo.CmdPayload[0]
 *          ...
 *          // process data
 *          ...
 *      }
 * }
 *
 * @endcode
 */
bool WiMODLRBASE::ExecuteGenericCmd(TWiMODLR_Generic_CmdInfo*    info,
                                    TWiMODLRResultCodes*         hciResult,
                                    UINT8*                       rspStatus)
{
    localHciRes = SapGeneric.ExecuteGenericCmd(info, &localStatusRsp);
    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
}


//===============================================================================
//
// Hardware Tests
//
//===============================================================================
//bool WiMODLRBASE::StartRadioTest(const TWiMODLR_HWTestParameter* testParams,
//                                        TWiMODLRResultCodes*         hciResult,
//                                  UINT8*                      rspStatus) {
//
//    localHciRes = SapHwTest.StartRadioTest(testParams, &localStatusRsp);
//    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
//}
//
//bool WiMODLRBASE::StopRadioTest(TWiMODLRResultCodes*         hciResult,
//                                  UINT8*                      rspStatus) {
//    localHciRes = SapHwTest.StopRadioTest(&localStatusRsp);
//    return copyResultInfos(hciResult, rspStatus, DEVMGMT_STATUS_OK);
//
//}

//------------------------------------------------------------------------------
//
// Section protected functions
//
//------------------------------------------------------------------------------
/**
 * @internal
 *
 * @brief dispatches an received indication message from the module
 *
 * @param rxMsg     reference to the received messasge
 *
 * @endinternal
 */
void WiMODLRBASE::ProcessUnexpectedRxMessage(TWiMODLR_HCIMessage& rxMsg) {
    switch(rxMsg.SapID)
    {
        case    DEVMGMT_SAP_ID:
                SapDevMgmt.DispatchDeviceMgmtMessage(rxMsg);
                break;

        case RADIOLINK_SAP_ID:
                SapRadioLink.DispatchRadioLinkMessage(rxMsg);
                break;

        default:
                if (StackErrorClientCB) {
                    StackErrorClientCB(WIMOD_STACK_ERR_UNKNOWN_RX_SAP_ID);
                }
                break;
    }
    return;
}


//------------------------------------------------------------------------------
//
// Section private functions
//
//------------------------------------------------------------------------------

/**
 * @internal
 *
 * @brief stores the status and response code of the last executed (user) command
 *
 * @param   hciResult   pointer to the result of the last HCI communication
 *
 * @param   rspStatus   pointer to the status code of the last HCI response
 *
 * @param   successValue expected value if last command was OK
 *
 * @return  true if actual results are equal to the expected value
 *
 * @endinternal
 *
 */
bool WiMODLRBASE::copyResultInfos(TWiMODLRResultCodes* hciResult,
                                  UINT8*               rspStatus,
                                  UINT8                successValue)
{
    cmdResult = false;

    //check if the transmission of the HCI frame was successful
    if ((WiMODLR_RESULT_OK == localHciRes)
            && (localStatusRsp == successValue)) {
        // -> yes
        cmdResult = true;
    }
    // if pointers are valid copy the values for external processing
    if (hciResult) {
        *hciResult = localHciRes;
    }
    if (rspStatus) {
        *rspStatus = localStatusRsp;
    }

    // backup last status data
    lastHciRes = localHciRes;
    lastStatusRsp = localStatusRsp;

    // return true if HCI TX operation and command execution status are OK
    return cmdResult;
}

//-----------------------------------------------------------------------------
// EOF
//-----------------------------------------------------------------------------
