aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThorsten Kummermehr <thorsten.kummermehr@k2l.de>2017-07-26 16:54:13 +0200
committerThorsten Kummermehr <thorsten.kummermehr@k2l.de>2017-07-26 16:54:13 +0200
commitb472aba95f7fbbfd61e9b8830dd30a4fe73af86f (patch)
tree95c6ca7c59856056cdbc25254f6e61ea815008ed
parent734e76786c52b832e702a113a0583e51ea433f23 (diff)
Implement handling of GPIO, I2C, Routes
-rw-r--r--ucs2-afb/ucs_binding.c8
-rw-r--r--ucs2-interface/ucs-xml/UcsXml.c7
-rw-r--r--ucs2-interface/ucs_config.h42
-rw-r--r--ucs2-interface/ucs_interface.h52
-rw-r--r--ucs2-interface/ucs_lib_interf.c128
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 <string.h>
#include <stdarg.h>
@@ -72,7 +73,10 @@ typedef enum
UnicensCmd_Init,
UnicensCmd_Stop,
UnicensCmd_RmSetRoute,
- UnicensCmd_NsRun
+ UnicensCmd_NsRun,
+ UnicensCmd_GpioCreatePort,
+ UnicensCmd_GpioWritePort,
+ UnicensCmd_I2CWrite
} UnicensCmd_t;
/**
@@ -105,12 +109,48 @@ typedef struct
*/
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
+ */
+typedef struct
+{
UnicensCmd_t cmd;
union
{
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:
*----------------------------------------