From b472aba95f7fbbfd61e9b8830dd30a4fe73af86f Mon Sep 17 00:00:00 2001 From: Thorsten Kummermehr Date: Wed, 26 Jul 2017 16:54:13 +0200 Subject: [PATCH] Implement handling of GPIO, I2C, Routes --- ucs2-afb/ucs_binding.c | 8 +++ ucs2-interface/ucs-xml/UcsXml.c | 7 +-- ucs2-interface/ucs_config.h | 42 ++++++++++++- ucs2-interface/ucs_interface.h | 52 +++++++++++++++- ucs2-interface/ucs_lib_interf.c | 128 ++++++++++++++++++++++++++++++++++++---- 5 files changed, 220 insertions(+), 17 deletions(-) diff --git a/ucs2-afb/ucs_binding.c b/ucs2-afb/ucs_binding.c index fc8d613..59e1532 100644 --- a/ucs2-afb/ucs_binding.c +++ b/ucs2-afb/ucs_binding.c @@ -185,6 +185,14 @@ void UCSI_CB_OnAmsMessageReceived(void *pTag) Don't forget to call UCSI_ReleaseAmsMessage after that */ } +void UCSI_CB_OnRouteResult(void *pTag, uint16_t routeId, bool isActive) +{ +} + +void UCSI_CB_OnGpioStateChange(void *pTag, uint16_t nodeAddress, uint8_t gpioPinId, bool isHighState) +{ +} + bool Cdev_Init(CdevData_t *d, const char *fileName, bool read, bool write) { if (NULL == d || NULL == fileName) goto OnErrorExit; diff --git a/ucs2-interface/ucs-xml/UcsXml.c b/ucs2-interface/ucs-xml/UcsXml.c index efce887..8837356 100644 --- a/ucs2-interface/ucs-xml/UcsXml.c +++ b/ucs2-interface/ucs-xml/UcsXml.c @@ -1158,12 +1158,11 @@ static ParseResult_t ParseScriptMsgSend(mxml_node_t *act, Ucs_Ns_Script_t *scr, if (!GetUInt8(act, OP_TYPE_REQUEST, &req->OpCode, true)) RETURN_ASSERT(Parse_XmlError); - if (!GetUInt8(act, OP_TYPE_RESPONSE, &res->OpCode, true)) - RETURN_ASSERT(Parse_XmlError); - res->FBlockId = req->FBlockId; res->FunktId = req->FunktId; - GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, 0, &priv->objList, false); + + if (GetUInt8(act, OP_TYPE_RESPONSE, &res->OpCode, false)) + GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, 0, &priv->objList, false); if (!GetPayload(act, PAYLOAD_REQ_HEX, &req->DataPtr, &req->DataLen, 0, &priv->objList, true)) RETURN_ASSERT(Parse_XmlError); diff --git a/ucs2-interface/ucs_config.h b/ucs2-interface/ucs_config.h index 74c82c6..16210af 100644 --- a/ucs2-interface/ucs_config.h +++ b/ucs2-interface/ucs_config.h @@ -39,6 +39,7 @@ #define DEBUG_XRM #define BOARD_PMS_TX_SIZE (72) #define CMD_QUEUE_LEN (6) +#define I2C_WRITE_MAX_LEN (32) #include #include @@ -72,7 +73,10 @@ typedef enum UnicensCmd_Init, UnicensCmd_Stop, UnicensCmd_RmSetRoute, - UnicensCmd_NsRun + UnicensCmd_NsRun, + UnicensCmd_GpioCreatePort, + UnicensCmd_GpioWritePort, + UnicensCmd_I2CWrite } UnicensCmd_t; /** @@ -100,6 +104,39 @@ typedef struct Ucs_Rm_Node_t * node_ptr; } UnicensCmdNsRun_t; +/** + * \brief Internal struct for Unicens Integration + */ +typedef struct +{ + uint16_t destination; + uint16_t debounceTime; +} UnicensCmdGpioCreatePort_t; + +/** + * \brief Internal struct for Unicens Integration + */ +typedef struct +{ + uint16_t destination; + uint16_t mask; + uint16_t data; +} UnicensCmdGpioWritePort_t; + +/** + * \brief Internal struct for Unicens Integration + */ +typedef struct +{ + uint16_t destination; + bool isBurst; + uint8_t blockCount; + uint8_t slaveAddr; + uint16_t timeout; + uint8_t dataLen; + uint8_t data[I2C_WRITE_MAX_LEN]; +} UnicensCmdI2CWrite_t; + /** * \brief Internal struct for Unicens Integration */ @@ -111,6 +148,9 @@ typedef struct UnicensCmdInit_t Init; UnicensCmdRmSetRoute_t RmSetRoute; UnicensCmdNsRun_t NsRun; + UnicensCmdGpioCreatePort_t GpioCreatePort; + UnicensCmdGpioWritePort_t GpioWritePort; + UnicensCmdI2CWrite_t I2CWrite; } val; } UnicensCmdEntry_t; diff --git a/ucs2-interface/ucs_interface.h b/ucs2-interface/ucs_interface.h index b7dda35..c18d440 100644 --- a/ucs2-interface/ucs_interface.h +++ b/ucs2-interface/ucs_interface.h @@ -160,13 +160,44 @@ void UCSI_ReleaseAmsMessage(UCSI_Data_t *my); * \note Call this function only from single context (not from ISR) * * \param pPriv - private data section of this instance - * \param routeId - identifier as given in XML file along with MOST socket + * \param routeId - identifier as given in XML file along with MOST socket (unique) * \param isActive - true, route will become active. false, route will be deallocated * * \return true, if route was found and the specific command was enqueued to Unicens. */ bool UCSI_SetRouteActive(UCSI_Data_t *pPriv, uint16_t routeId, bool isActive); +/** + * \brief Enables or disables a route by the given routeId + * \note Call this function only from single context (not from ISR) + * + * \param pPriv - private data section of this instance + * \param targetAddress - targetAddress - The node / group target address + * \param isBurst - true, write blockCount I2C telegrams dataLen with a single call. false, write a single I2C message. + * \param blockCount - amount of blocks to write. Only used when isBurst is set to true. + * \param slaveAddr - The I2C address. + * \param timeout - Timeout in milliseconds. + * \param dataLen - Amount of bytes to send via I2C + * \param pData - The payload to be send. + * + * \return true, if route command was enqueued to Unicens. + */ +bool UCSI_I2CWrite(UCSI_Data_t *pPriv, uint16_t targetAddress, bool isBurst, uint8_t blockCount, + uint8_t slaveAddr, uint16_t timeout, uint8_t dataLen, uint8_t *pData); + +/** + * \brief Enables or disables a route by the given routeId + * \note Call this function only from single context (not from ISR) + * + * \param pPriv - private data section of this instance + * \param targetAddress - targetAddress - The node / group target address + * \param gpioPinId - INIC GPIO PIN starting with 0 for the first GPIO. + * \param isHighState - true, high state = 3,3V. false, low state = 0V. + * + * \return true, if GPIO command was enqueued to Unicens. + */ +bool UCSI_SetGpioState(UCSI_Data_t *pPriv, uint16_t targetAddress, uint8_t gpioPinId, bool isHighState); + /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ /* CALLBACK SECTION */ /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ @@ -239,6 +270,25 @@ extern void UCSI_CB_OnStop(void *pTag); */ extern void UCSI_CB_OnAmsMessageReceived(void *pTag); +/** + * \brief Callback when a route become active / inactive. + * \note This function must be implemented by the integrator + * \param pTag - Pointer given by the integrator by UCSI_Init + * \param routeId - identifier as given in XML file along with MOST socket (unique) + * \param isActive - true, if the route is now in use. false, the route is not established. + */ +extern void UCSI_CB_OnRouteResult(void *pTag, uint16_t routeId, bool isActive); + +/** + * \brief Callback when a INIC GPIO changes its state + * \note This function must be implemented by the integrator + * \param pTag - Pointer given by the integrator by UCSI_Init + * \param nodeAddress - Node Address of the INIC sending the update. + * \param gpioPinId - INIC GPIO PIN starting with 0 for the first GPIO. + * \param isHighState - true, high state = 3,3V. false, low state = 0V. + */ +extern void UCSI_CB_OnGpioStateChange(void *pTag, uint16_t nodeAddress, uint8_t gpioPinId, bool isHighState); + #ifdef __cplusplus } #endif diff --git a/ucs2-interface/ucs_lib_interf.c b/ucs2-interface/ucs_lib_interf.c index 5a6c08b..3eda07f 100644 --- a/ucs2-interface/ucs_lib_interf.c +++ b/ucs2-interface/ucs_lib_interf.c @@ -64,9 +64,15 @@ static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type, Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr); static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr); static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr); +static void OnUcsGpioPortCreate(uint16_t node_address, uint16_t gpio_port_handle, Ucs_Gpio_Result_t result, void *user_ptr); +static void OnUcsGpioPortWrite(uint16_t node_address, uint16_t gpio_port_handle, uint16_t current_state, uint16_t sticky_state, Ucs_Gpio_Result_t result, void *user_ptr); static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr); static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr); static void OnUcsAmsRxMsgReceived(void *user_ptr); +static void OnUcsGpioTriggerEventStatus(uint16_t node_address, uint16_t gpio_port_handle, + uint16_t rising_edges, uint16_t falling_edges, uint16_t levels, void * user_ptr); +static void OnUcsI2CWrite(uint16_t node_address, uint16_t i2c_port_handle, + uint8_t i2c_slave_address, uint8_t data_len, Ucs_I2c_Result_t result, void *user_ptr); /************************************************************************/ /* Public Function Implementations */ @@ -116,6 +122,8 @@ void UCSI_Init(UCSI_Data_t *my, void *pTag) my->uniInitData.rm.xrm.most_port_status_fptr = &OnUnicensMostPortStatus; my->uniInitData.rm.debug_resource_status_fptr = &OnUnicensDebugXrmResources; + my->uniInitData.gpio.trigger_event_status_fptr = &OnUcsGpioTriggerEventStatus; + RB_Init(&my->rb, CMD_QUEUE_LEN, sizeof(UnicensCmdEntry_t), my->rbBuf); } @@ -197,6 +205,26 @@ void UCSI_Service(UCSI_Data_t *my) if (UCS_RET_SUCCESS != Ucs_Ns_Run(my->unicens, e->val.NsRun.node_ptr, OnUcsNsRun)) UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Ns_Run failed", 0); break; + case UnicensCmd_GpioCreatePort: + if (UCS_RET_SUCCESS == Ucs_Gpio_CreatePort(my->unicens, e->val.GpioCreatePort.destination, 0, e->val.GpioCreatePort.debounceTime, OnUcsGpioPortCreate)) + popEntry = false; + else + UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Gpio_CreatePort failed", 0); + break; + case UnicensCmd_GpioWritePort: + if (UCS_RET_SUCCESS == Ucs_Gpio_WritePort(my->unicens, e->val.GpioWritePort.destination, 0x1D00, e->val.GpioWritePort.mask, e->val.GpioWritePort.data, OnUcsGpioPortWrite)) + popEntry = false; + else + UCSI_CB_OnUserMessage(my->tag, true, "UnicensCmd_GpioWritePort failed", 0); + break; + case UnicensCmd_I2CWrite: + if (UCS_RET_SUCCESS == Ucs_I2c_WritePort(my->unicens, e->val.I2CWrite.destination, 0x0F00, + (e->val.I2CWrite.isBurst ? UCS_I2C_BURST_MODE : UCS_I2C_DEFAULT_MODE), e->val.I2CWrite.blockCount, + e->val.I2CWrite.slaveAddr, e->val.I2CWrite.timeout, e->val.I2CWrite.dataLen, e->val.I2CWrite.data, OnUcsI2CWrite)) + popEntry = false; + else + UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Gpio_CreatePort failed", 0); + break; default: assert(false); break; @@ -279,6 +307,38 @@ bool UCSI_SetRouteActive(UCSI_Data_t *my, uint16_t routeId, bool isActive) return false; } +bool UCSI_I2CWrite(UCSI_Data_t *my, uint16_t targetAddress, bool isBurst, uint8_t blockCount, + uint8_t slaveAddr, uint16_t timeout, uint8_t dataLen, uint8_t *pData) +{ + UnicensCmdEntry_t entry; + assert(MAGIC == my->magic); + if (NULL == my || NULL == pData || 0 == dataLen) return false; + if (dataLen > I2C_WRITE_MAX_LEN) return false; + entry.cmd = UnicensCmd_I2CWrite; + entry.val.I2CWrite.destination = targetAddress; + entry.val.I2CWrite.isBurst = isBurst; + entry.val.I2CWrite.blockCount = blockCount; + entry.val.I2CWrite.slaveAddr = slaveAddr; + entry.val.I2CWrite.timeout = timeout; + entry.val.I2CWrite.dataLen = dataLen; + memcpy(entry.val.I2CWrite.data, pData, dataLen); + return EnqueueCommand(my, &entry); +} + +bool UCSI_SetGpioState(UCSI_Data_t *my, uint16_t targetAddress, uint8_t gpioPinId, bool isHighState) +{ + uint16_t mask; + UnicensCmdEntry_t entry; + assert(MAGIC == my->magic); + if (NULL == my) return false; + mask = 1 << gpioPinId; + entry.cmd = UnicensCmd_GpioWritePort; + entry.val.GpioWritePort.destination = targetAddress; + entry.val.GpioWritePort.mask = mask; + entry.val.GpioWritePort.data = isHighState ? mask : 0; + return EnqueueCommand(my, &entry); +} + /************************************************************************/ /* Private Functions */ /************************************************************************/ @@ -488,10 +548,9 @@ static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr ) static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr) { - /*TODO: implement*/ - route_ptr = route_ptr; - route_infos = route_infos; - user_ptr = user_ptr; + UCSI_Data_t *my = (UCSI_Data_t *)user_ptr; + assert(MAGIC == my->magic); + UCSI_CB_OnRouteResult(my->tag, route_ptr->route_id, UCS_RM_ROUTE_INFOS_BUILT == route_infos); } static void OnUnicensMostPortStatus(uint16_t most_port_handle, @@ -668,17 +727,24 @@ static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr) UCSI_CB_OnStop(my->tag); } +static void OnUcsGpioPortCreate(uint16_t node_address, uint16_t gpio_port_handle, Ucs_Gpio_Result_t result, void *user_ptr) +{ + UCSI_Data_t *my = (UCSI_Data_t *)user_ptr; + assert(MAGIC == my->magic); + OnCommandExecuted(my, UnicensCmd_GpioCreatePort); +} + +static void OnUcsGpioPortWrite(uint16_t node_address, uint16_t gpio_port_handle, uint16_t current_state, uint16_t sticky_state, Ucs_Gpio_Result_t result, void *user_ptr) +{ + UCSI_Data_t *my = (UCSI_Data_t *)user_ptr; + assert(MAGIC == my->magic); + OnCommandExecuted(my, UnicensCmd_GpioWritePort); +} + static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr) { UCSI_Data_t *my = (UCSI_Data_t *)user_ptr; assert(MAGIC == my->magic); - if (node_ptr && node_ptr->script_list_ptr && node_ptr->script_list_size) - { - UnicensCmdEntry_t e; - e.cmd = UnicensCmd_NsRun; - e.val.NsRun.node_ptr = node_ptr; - EnqueueCommand(my, &e); - } switch (code) { case UCS_MGR_REP_IGNORED_UNKNOWN: @@ -688,8 +754,23 @@ static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_N UCSI_CB_OnUserMessage(my->tag, true, "Node=%X: Ignored, because duplicated", 1, node_address); break; case UCS_MGR_REP_AVAILABLE: + { + UnicensCmdEntry_t e; UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Available", 1, node_address); + /* Enable usage of remote GPIO ports */ + e.cmd = UnicensCmd_GpioCreatePort; + e.val.GpioCreatePort.destination = node_address; + e.val.GpioCreatePort.debounceTime = 20; + EnqueueCommand(my, &e); + /* Execute scripts, if there are any */ + if (node_ptr && node_ptr->script_list_ptr && node_ptr->script_list_size) + { + e.cmd = UnicensCmd_NsRun; + e.val.NsRun.node_ptr = node_ptr; + EnqueueCommand(my, &e); + } break; + } case UCS_MGR_REP_NOT_AVAILABLE: UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Not available", 1, node_address); break; @@ -722,6 +803,31 @@ static void OnUcsAmsRxMsgReceived(void *user_ptr) UCSI_CB_OnAmsMessageReceived(my->tag); } +static void OnUcsGpioTriggerEventStatus(uint16_t node_address, uint16_t gpio_port_handle, + uint16_t rising_edges, uint16_t falling_edges, uint16_t levels, void * user_ptr) +{ + uint8_t i; + UCSI_Data_t *my = (UCSI_Data_t *)user_ptr; + assert(MAGIC == my->magic); + for (i = 0; i < 16; i++) + { + if (0 != ((rising_edges >> i) & 0x1)) + UCSI_CB_OnGpioStateChange(my->tag, node_address, i, true); + if (0 != ((falling_edges >> i) & 0x1)) + UCSI_CB_OnGpioStateChange(my->tag, node_address, i, false); + } +} + +static void OnUcsI2CWrite(uint16_t node_address, uint16_t i2c_port_handle, + uint8_t i2c_slave_address, uint8_t data_len, Ucs_I2c_Result_t result, void *user_ptr) +{ + UCSI_Data_t *my = (UCSI_Data_t *)user_ptr; + assert(MAGIC == my->magic); + OnCommandExecuted(my, UnicensCmd_I2CWrite); + if (UCS_I2C_RES_SUCCESS != result.code) + UCSI_CB_OnUserMessage(my->tag, true, "Remote I2C Write to node=0x%X failed", 1, node_address); +} + /*---------------------------------------- * Debug Message output from Unicens stack: *---------------------------------------- -- 2.16.6