diff options
Diffstat (limited to 'Src/Network/IndustrialStack.h')
-rw-r--r-- | Src/Network/IndustrialStack.h | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/Src/Network/IndustrialStack.h b/Src/Network/IndustrialStack.h new file mode 100644 index 0000000..fc42f66 --- /dev/null +++ b/Src/Network/IndustrialStack.h @@ -0,0 +1,238 @@ +/* + * Video On Demand Samples + * + * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * You may also obtain this software under a propriety license from Microchip. + * Please contact Microchip for further information. + * + */ + +/*----------------------------------------------------------*/ +/*! \file + * \brief This file contains the CIndustrialStack class (common part). + */ +/*----------------------------------------------------------*/ + +#ifndef INDUSTRIAL_STACK_H +#define INDUSTRIAL_STACK_H + +#include <stdint.h> +#include <stdbool.h> +#include <stddef.h> +#include <string.h> +#include "SafeVector.h" +#include "IndustrialStack_Types.h" +#include "IndustrialStack_MNS.h" +#include "Console.h" + +class CIndustrialStack : IISNetServiceWrapperCB +{ +private: + CISNetServiceWrapper *msnw; + CSafeVector<CISDeviceQueue *> deviceQueues; + CSafeVector<CSInternalEvent *> intEventListeners; + CISDeviceQueue *GetQueue(uint16_t deviceType); + void HandleStateChange(ISReturn_t state, IISElement * element); +public: + CIndustrialStack(uint8_t deviceApi, int controlRxHandle, int controlTxHandle); + virtual ~CIndustrialStack(); + void ServiceStack(uint32_t time); + void EnqueueElement(uint16_t nodeAddress, IISElement *element); + bool ElementsPending(); + bool ElementsPending(uint16_t ingoreNodeAddress); + void ClearAllElements(); + bool SendMostMessage(CISMostMsg *message); + void Unsynchronize(); + void AddInternalEventListener(CSInternalEvent* callback); + + /* Callback from IISNetServiceWrapperCB interface */ + virtual void OnReceivedMostMessage(CISMostMsg *rcvMessage); + virtual void OnSyncStateChanged(bool isSynced); + virtual void OnControlReadEnd(); +}; + +class CISWaitElement : public IISElement +{ +protected: + uint32_t startTime; + uint32_t timeout; +public: + CISWaitElement() : IISElement(), startTime(0), timeout(2000) + { + ElementName = "Wait Element"; + } + + void SetTimeout(uint32_t timeInMillis) + { + timeout = timeInMillis; + } + + virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time) + { + assert(NULL != iStack); + if (0 == startTime) + startTime = time; + else if ( ( time - startTime >= timeout ) ) + return ISReturn_Success; + return ISReturn_NoChange; + } + + virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *rcvMessage) + { + assert(NULL != iStack); + return ISReturn_NoChange; + } +}; + +class CISWaitForPendingElements : public CISWaitElement +{ +private: + uint16_t ignoreNode; +public: + CISWaitForPendingElements(uint16_t ingoreNodeAddress) + : CISWaitElement(), ignoreNode(ingoreNodeAddress) + { + } + + virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time) + { + assert(NULL != iStack); + if (!iStack->ElementsPending(ignoreNode)) + return ISReturn_Success; + return (CISWaitElement::Service(iStack, time) == ISReturn_NoChange) + ? ISReturn_NoChange : ISReturn_Timeout; + } +}; + +class CISSendMostMsgElement : public CISWaitElement +{ +private: + uint8_t retryCount; +public: + CISMostMsg Request; + CISMostMsg Response; + bool WaitForResponse; + CISOpType_t WaitForResponseOpType; + + CISSendMostMsgElement() : CISWaitElement(), retryCount(4), + WaitForResponse(false), + WaitForResponseOpType(CISOpType_INVALID) + { + timeout = 500; + } + + virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time) + { + assert(NULL != iStack); + if (0 == startTime) + { + CISWaitElement::Service(iStack, time); + if (Request.IsValid == false || Request.FBlock == 0xFFFFFFFF + || Request.Func == 0xFFFFFFFF || Request.Inst == 0xFFFFFFFF + || Request.OpType == CISOpType_INVALID) + { + ConsolePrintf(PRIO_ERROR, + RED"CISSendMostMsgElement %s invalid MOST message to be"\ + " sent"RESETCOLOR"\n", ElementName); + return ISReturn_Failure; + } + bool success = iStack->SendMostMessage(&Request); + if (success && !WaitForResponse) + return ISReturn_Success; + return success ? ISReturn_NoChange : ISReturn_Failure; + } + ISReturn_t waitState = CISWaitElement::Service(iStack, time); + if (ISReturn_Success == waitState) + { + if (0 == --retryCount) + { + ConsolePrintf(PRIO_ERROR, RED"All High level retries failed for Request '%s',"\ + " node 0x%X!"RESETCOLOR"\n", + ElementName, Request.TargetAddress); + return ISReturn_Timeout; + } + //Retry sending + ConsolePrintf(PRIO_HIGH, YELLOW"High level retry after timeout for Request '%s',"\ + " node 0x%X"RESETCOLOR"\n", + ElementName, Request.TargetAddress); + startTime = time; + return (iStack->SendMostMessage(&Request)) ? ISReturn_NoChange : ISReturn_Failure; + } + return ISReturn_NoChange; + } + + virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *rcvMessage) + { + if (!WaitForResponse) + return ISReturn_NoChange; + assert(NULL != iStack); + assert(NULL != rcvMessage); + assert(Request.IsValid); + assert(rcvMessage->IsValid); + + uint32_t requestAddr = Request.TargetAddress; + uint32_t responseAddr = rcvMessage->SourceAddress; + if (requestAddr >= 0x400 && requestAddr <= 0x4FF ) + requestAddr -= 0x300; + if (responseAddr >= 0x400 && responseAddr <= 0x4FF ) + responseAddr -= 0x300; + + if ( ( requestAddr < 0x300 || requestAddr > 0x3FF ) + && ( responseAddr != requestAddr)) + return ISReturn_NoChange; + + if ( rcvMessage->FBlock == Request.FBlock + && rcvMessage->Func == Request.Func) + { + if (rcvMessage->OpType == WaitForResponseOpType) + { + Response.DeepCopy(rcvMessage); + return ISReturn_Success; + } + else if(0 == --retryCount) + { + Response.DeepCopy(rcvMessage); + return ISReturn_Failure; + } + //Retry sending + ConsolePrintf(PRIO_HIGH, YELLOW"High level retry after wrong result for Request '%s',"\ + " node 0x%X"RESETCOLOR"\n", + ElementName, Request.TargetAddress); + return (iStack->SendMostMessage(&Request)) ? ISReturn_NoChange : ISReturn_Failure; + } + return ISReturn_NoChange; + } +}; + +class CSInternalEvent : public IISElement +{ +public: + virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time) + { + //Must not be called + return ISReturn_Failure; + } + virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *r) + { + //Must not be called + return ISReturn_Failure; + } + virtual void OnSyncStateChanged(CIndustrialStack *iStack, bool isSynced) {} + virtual void OnControlReadEnd(CIndustrialStack *iStack) {} +}; + +#endif //INDUSTRIAL_STACK_H |