1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: demoapplication for EPL MN (with SDO over UDP)
9 under Linux on X86 with RTL8139 Ethernet controller
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
24 3. Neither the name of SYSTEC electronic GmbH nor the names of its
25 contributors may be used to endorse or promote products derived
26 from this software without prior written permission. For written
27 permission, please contact info@systec-electronic.com.
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
35 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
39 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 POSSIBILITY OF SUCH DAMAGE.
44 If a provision of this License is or becomes illegal, invalid or
45 unenforceable in any jurisdiction, that shall not affect:
46 1. the validity or enforceability in that jurisdiction of any other
47 provision of this License; or
48 2. the validity or enforceability in other jurisdictions of that or
49 any other provision of this License.
51 -------------------------------------------------------------------------
53 $RCSfile: demo_main.c,v $
57 $Revision: 1.10 $ $Date: 2008/11/19 18:11:43 $
64 -------------------------------------------------------------------------
68 2006/09/01 d.k.: start of implementation
70 ****************************************************************************/
72 #include <linux/module.h>
73 #include <linux/kernel.h>
74 #include <linux/init.h>
75 #include <linux/errno.h>
76 #include <linux/major.h>
78 #include <asm/uaccess.h>
79 #include <asm/atomic.h>
80 #include <linux/sched.h>
81 #include <linux/kmod.h>
82 #include <linux/slab.h>
83 #include <linux/pci.h>
84 #include <linux/proc_fs.h>
89 /***************************************************************************/
92 /* G L O B A L D E F I N I T I O N S */
95 /***************************************************************************/
98 MODULE_LICENSE("Dual BSD/GPL");
100 MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
101 MODULE_DESCRIPTION("EPL MN demo");
104 //---------------------------------------------------------------------------
106 //---------------------------------------------------------------------------
108 // TracePoint support for realtime-debugging
109 #ifdef _DBG_TRACE_POINTS_
110 void TgtDbgSignalTracePoint(u8 bTracePointNumber_p);
111 #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
113 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
116 #define NODEID 0xF0 //=> MN
117 #define CYCLE_LEN 5000 // [us]
118 #define IP_ADDR 0xc0a86401 // 192.168.100.1
119 #define SUBNET_MASK 0xFFFFFF00 // 255.255.255.0
120 #define HOSTNAME "SYS TEC electronic EPL Stack "
121 #define IF_ETH EPL_VETH_NAME
124 #define DEFAULT_MAX_CYCLE_COUNT 20 // 6 is very fast
125 #define APP_DEFAULT_MODE 0x01
126 #define APP_LED_COUNT 5 // number of LEDs in one row
127 #define APP_LED_MASK ((1 << APP_LED_COUNT) - 1)
128 #define APP_DOUBLE_LED_MASK ((1 << (APP_LED_COUNT * 2)) - 1)
129 #define APP_MODE_COUNT 5
130 #define APP_MODE_MASK ((1 << APP_MODE_COUNT) - 1)
132 //---------------------------------------------------------------------------
134 //---------------------------------------------------------------------------
136 //---------------------------------------------------------------------------
137 // modul globale vars
138 //---------------------------------------------------------------------------
140 static const u8 abMacAddr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
143 static u8 bVarOut1_l;
144 static u8 bVarOut1Old_l;
145 static u8 bModeSelect_l; // state of the pushbuttons to select the mode
146 static u8 bSpeedSelect_l; // state of the pushbuttons to increase/decrease the speed
147 static u8 bSpeedSelectOld_l; // old state of the pushbuttons
148 static u32 dwLeds_l; // current state of all LEDs
149 static u8 bLedsRow1_l; // current state of the LEDs in row 1
150 static u8 bLedsRow2_l; // current state of the LEDs in row 2
151 static u8 abSelect_l[3]; // pushbuttons from CNs
153 static u32 dwMode_l; // current mode
154 static int iCurCycleCount_l; // current cycle count
155 static int iMaxCycleCount_l; // maximum cycle count (i.e. number of cycles until next light movement step)
156 static int iToggle; // indicates the light movement direction
158 //static u8 abDomain_l[3000];
160 static wait_queue_head_t WaitQueueShutdown_g; // wait queue for tEplNmtEventSwitchOff
161 static atomic_t AtomicShutdown_g = ATOMIC_INIT(FALSE);
163 static u32 dw_le_CycleLen_g;
165 static uint uiNodeId_g = EPL_C_ADR_INVALID;
166 module_param_named(nodeid, uiNodeId_g, uint, 0);
168 static uint uiCycleLen_g = CYCLE_LEN;
169 module_param_named(cyclelen, uiCycleLen_g, uint, 0);
171 //---------------------------------------------------------------------------
172 // local function prototypes
173 //---------------------------------------------------------------------------
175 // This function is the entry point for your object dictionary. It is defined
176 // in OBJDICT.C by define EPL_OBD_INIT_RAM_NAME. Use this function name to define
177 // this function prototype here. If you want to use more than one Epl
178 // instances then the function name of each object dictionary has to differ.
180 tEplKernel EplObdInitRam(tEplObdInitParam *pInitParam_p);
182 tEplKernel AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
183 tEplApiEventArg *pEventArg_p, // IN: event argument (union)
186 tEplKernel AppCbSync(void);
189 //---------------------------------------------------------------------------
190 // Kernel Module specific Data Structures
191 //---------------------------------------------------------------------------
193 //module_init(EplLinInit);
194 //module_exit(EplLinExit);
196 //=========================================================================//
198 // P U B L I C F U N C T I O N S //
200 //=========================================================================//
202 //---------------------------------------------------------------------------
218 //---------------------------------------------------------------------------
220 static int __init EplLinInit(void)
224 static tEplApiInitParam EplApiInitParam = { 0 };
225 char *sHostname = HOSTNAME;
226 char *argv[4], *envp[3];
228 unsigned int uiVarEntries;
231 atomic_set(&AtomicShutdown_g, TRUE);
233 // get node ID from insmod command line
234 EplApiInitParam.m_uiNodeId = uiNodeId_g;
236 if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID) { // invalid node ID set
237 // set default node ID
238 EplApiInitParam.m_uiNodeId = NODEID;
241 uiNodeId_g = EplApiInitParam.m_uiNodeId;
243 // calculate IP address
244 EplApiInitParam.m_dwIpAddress =
245 (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId;
247 EplApiInitParam.m_fAsyncOnly = FALSE;
249 EplApiInitParam.m_uiSizeOfStruct = sizeof(EplApiInitParam);
250 EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr,
251 sizeof(EplApiInitParam.m_abMacAddress));
252 // EplApiInitParam.m_abMacAddress[5] = (u8) EplApiInitParam.m_uiNodeId;
253 EplApiInitParam.m_dwFeatureFlags = -1;
254 EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection
255 EplApiInitParam.m_uiIsochrTxMaxPayload = 100; // const
256 EplApiInitParam.m_uiIsochrRxMaxPayload = 100; // const
257 EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes
258 EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes)
259 EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes)
260 EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes
261 EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection
262 EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size
263 EplApiInitParam.m_uiPrescaler = 2; // required for sync
264 EplApiInitParam.m_dwLossOfFrameTolerance = 500000;
265 EplApiInitParam.m_dwAsyncSlotTimeout = 3000000;
266 EplApiInitParam.m_dwWaitSocPreq = 150000;
267 EplApiInitParam.m_dwDeviceType = -1; // NMT_DeviceType_U32
268 EplApiInitParam.m_dwVendorId = -1; // NMT_IdentityObject_REC.VendorId_U32
269 EplApiInitParam.m_dwProductCode = -1; // NMT_IdentityObject_REC.ProductCode_U32
270 EplApiInitParam.m_dwRevisionNumber = -1; // NMT_IdentityObject_REC.RevisionNo_U32
271 EplApiInitParam.m_dwSerialNumber = -1; // NMT_IdentityObject_REC.SerialNo_U32
272 EplApiInitParam.m_dwSubnetMask = SUBNET_MASK;
273 EplApiInitParam.m_dwDefaultGateway = 0;
274 EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname,
275 sizeof(EplApiInitParam.m_sHostname));
277 // currently unset parameters left at default value 0
278 //EplApiInitParam.m_qwVendorSpecificExt1;
279 //EplApiInitParam.m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32
280 //EplApiInitParam.m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32
281 //EplApiInitParam.m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device
282 //EplApiInitParam.m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device
283 //EplApiInitParam.m_abVendorSpecificExt2[48];
285 // set callback functions
286 EplApiInitParam.m_pfnCbEvent = AppCbEvent;
287 EplApiInitParam.m_pfnCbSync = AppCbSync;
290 ("\n\n Hello, I'm a simple POWERLINK node running as %s!\n (build: %s / %s)\n\n",
292 EPL_C_ADR_MN_DEF_NODE_ID ? "Managing Node" : "Controlled Node"),
295 // initialize the Linux a wait queue for shutdown of this module
296 init_waitqueue_head(&WaitQueueShutdown_g);
298 // initialize the procfs device
299 EplRet = EplLinProcInit();
300 if (EplRet != kEplSuccessful) {
303 // initialize POWERLINK stack
304 EplRet = EplApiInitialize(&EplApiInitParam);
305 if (EplRet != kEplSuccessful) {
308 // link process variables used by CN to object dictionary
309 ObdSize = sizeof(bVarIn1_l);
312 EplApiLinkObject(0x6000, &bVarIn1_l, &uiVarEntries, &ObdSize, 0x01);
313 if (EplRet != kEplSuccessful) {
317 ObdSize = sizeof(bVarOut1_l);
320 EplApiLinkObject(0x6200, &bVarOut1_l, &uiVarEntries, &ObdSize,
322 if (EplRet != kEplSuccessful) {
325 // link process variables used by MN to object dictionary
326 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
327 ObdSize = sizeof(bLedsRow1_l);
330 EplApiLinkObject(0x2000, &bLedsRow1_l, &uiVarEntries, &ObdSize,
332 if (EplRet != kEplSuccessful) {
336 ObdSize = sizeof(bLedsRow2_l);
339 EplApiLinkObject(0x2000, &bLedsRow2_l, &uiVarEntries, &ObdSize,
341 if (EplRet != kEplSuccessful) {
345 ObdSize = sizeof(bSpeedSelect_l);
348 EplApiLinkObject(0x2000, &bSpeedSelect_l, &uiVarEntries, &ObdSize,
350 if (EplRet != kEplSuccessful) {
354 ObdSize = sizeof(bSpeedSelectOld_l);
357 EplApiLinkObject(0x2000, &bSpeedSelectOld_l, &uiVarEntries,
359 if (EplRet != kEplSuccessful) {
363 ObdSize = sizeof(abSelect_l[0]);
364 uiVarEntries = sizeof(abSelect_l);
366 EplApiLinkObject(0x2200, &abSelect_l[0], &uiVarEntries, &ObdSize,
368 if (EplRet != kEplSuccessful) {
373 // link a DOMAIN to object 0x6100, but do not exit, if it is missing
374 ObdSize = sizeof(abDomain_l);
377 EplApiLinkObject(0x6100, &abDomain_l, &uiVarEntries, &ObdSize,
379 if (EplRet != kEplSuccessful) {
380 printk("EplApiLinkObject(0x6100): returns 0x%X\n", EplRet);
382 // reset old process variables
384 bSpeedSelectOld_l = 0;
385 dwMode_l = APP_DEFAULT_MODE;
386 iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
388 // configure IP address of virtual network interface
389 // for TCP/IP communication over the POWERLINK network
390 sprintf(sBuffer, "%u.%u.%u.%u",
391 (EplApiInitParam.m_dwIpAddress >> 24),
392 ((EplApiInitParam.m_dwIpAddress >> 16) & 0xFF),
393 ((EplApiInitParam.m_dwIpAddress >> 8) & 0xFF),
394 (EplApiInitParam.m_dwIpAddress & 0xFF));
395 /* set up a minimal environment */
397 envp[iRet++] = "HOME=/";
398 envp[iRet++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
401 /* set up the argument list */
403 argv[iRet++] = "/sbin/ifconfig";
404 argv[iRet++] = IF_ETH;
405 argv[iRet++] = sBuffer;
408 /* call ifconfig to configure the virtual network interface */
409 iRet = call_usermodehelper(argv[0], argv, envp, 1);
410 printk("ifconfig %s %s returned %d\n", argv[1], argv[2], iRet);
412 // start the NMT state machine
413 EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset);
414 atomic_set(&AtomicShutdown_g, FALSE);
417 printk("EplLinInit(): returns 0x%X\n", EplRet);
421 static void __exit EplLinExit(void)
425 // halt the NMT state machine
426 // so the processing of POWERLINK frames stops
427 EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
429 // wait until NMT state machine is shut down
430 wait_event_interruptible(WaitQueueShutdown_g,
431 (atomic_read(&AtomicShutdown_g) == TRUE));
432 /* if ((iErr != 0) || (atomic_read(&AtomicShutdown_g) == EVENT_STATE_IOCTL))
433 { // waiting was interrupted by signal or application called wrong function
434 EplRet = kEplShutdown;
436 // delete instance for all modules
437 EplRet = EplApiShutdown();
438 printk("EplApiShutdown(): 0x%X\n", EplRet);
440 // deinitialize proc fs
441 EplRet = EplLinProcFree();
442 printk("EplLinProcFree(): 0x%X\n", EplRet);
446 //=========================================================================//
448 // P R I V A T E F U N C T I O N S //
450 //=========================================================================//
452 //---------------------------------------------------------------------------
454 // Function: AppCbEvent
456 // Description: event callback function called by EPL API layer within
457 // user part (low priority).
459 // Parameters: EventType_p = event type
460 // pEventArg_p = pointer to union, which describes
461 // the event in detail
462 // pUserArg_p = user specific argument
464 // Returns: tEplKernel = error code,
465 // kEplSuccessful = no error
466 // kEplReject = reject further processing
467 // otherwise = post error event to API layer
471 //---------------------------------------------------------------------------
473 tEplKernel AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
474 tEplApiEventArg *pEventArg_p, // IN: event argument (union)
477 tEplKernel EplRet = kEplSuccessful;
479 // check if NMT_GS_OFF is reached
480 switch (EventType_p) {
481 case kEplApiEventNmtStateChange:
483 switch (pEventArg_p->m_NmtStateChange.m_NewNmtState) {
485 { // NMT state machine was shut down,
486 // because of user signal (CTRL-C) or critical EPL stack error
487 // -> also shut down EplApiProcess() and main()
488 EplRet = kEplShutdown;
491 ("AppCbEvent(kEplNmtGsOff) originating event = 0x%X\n",
492 pEventArg_p->m_NmtStateChange.
495 // wake up EplLinExit()
496 atomic_set(&AtomicShutdown_g, TRUE);
497 wake_up_interruptible
498 (&WaitQueueShutdown_g);
502 case kEplNmtGsResetCommunication:
506 // configure OD for MN in state ResetComm after reseting the OD
507 // TODO: setup your own network configuration here
508 dwBuffer = (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS); // 0x00000003L
510 EplApiWriteLocalObject(0x1F81, 0x01,
514 EplApiWriteLocalObject(0x1F81, 0x02,
518 EplApiWriteLocalObject(0x1F81, 0x03,
522 EplApiWriteLocalObject(0x1F81, 0x04,
526 EplApiWriteLocalObject(0x1F81, 0x05,
530 EplApiWriteLocalObject(0x1F81, 0x06,
534 EplApiWriteLocalObject(0x1F81, 0x07,
538 EplApiWriteLocalObject(0x1F81, 0x08,
542 EplApiWriteLocalObject(0x1F81, 0x20,
546 EplApiWriteLocalObject(0x1F81, 0xFE,
550 EplApiWriteLocalObject(0x1F81, 0x6E,
554 // dwBuffer |= EPL_NODEASSIGN_MANDATORY_CN; // 0x0000000BL
555 // EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4);
556 dwBuffer = (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS); // 0x00010001L
558 EplApiWriteLocalObject(0x1F81, 0xF0,
565 case kEplNmtGsResetConfiguration:
569 // fetch object 0x1006 NMT_CycleLen_U32 from local OD (in little endian byte order)
570 // for configuration of remote CN
573 EplApiReadObject(NULL, 0, 0x1006,
579 if (EplRet != kEplSuccessful) { // local OD access failed
585 case kEplNmtMsPreOperational1:
588 ("AppCbEvent(0x%X) originating event = 0x%X\n",
589 pEventArg_p->m_NmtStateChange.
591 pEventArg_p->m_NmtStateChange.
597 case kEplNmtGsInitialising:
598 case kEplNmtGsResetApplication:
599 case kEplNmtMsNotActive:
600 case kEplNmtCsNotActive:
601 case kEplNmtCsPreOperational1:
606 case kEplNmtCsOperational:
607 case kEplNmtMsOperational:
619 switch (pEventArg_p->m_NmtStateChange.m_NmtEvent)
621 case kEplNmtEventSwReset:
622 case kEplNmtEventResetNode:
623 case kEplNmtEventResetCom:
624 case kEplNmtEventResetConfig:
625 case kEplNmtEventInternComError:
626 case kEplNmtEventNmtCycleError:
628 printk("AppCbEvent(0x%X) originating event = 0x%X\n",
629 pEventArg_p->m_NmtStateChange.m_NewNmtState,
630 pEventArg_p->m_NmtStateChange.m_NmtEvent);
643 case kEplApiEventCriticalError:
644 case kEplApiEventWarning:
645 { // error or warning occured within the stack or the application
646 // on error the API layer stops the NMT state machine
649 ("AppCbEvent(Err/Warn): Source=%02X EplError=0x%03X",
650 pEventArg_p->m_InternalError.m_EventSource,
651 pEventArg_p->m_InternalError.m_EplError);
652 // check additional argument
653 switch (pEventArg_p->m_InternalError.m_EventSource) {
654 case kEplEventSourceEventk:
655 case kEplEventSourceEventu:
656 { // error occured within event processing
657 // either in kernel or in user part
658 printk(" OrgSource=%02X\n",
659 pEventArg_p->m_InternalError.
660 m_Arg.m_EventSource);
664 case kEplEventSourceDllk:
665 { // error occured within the data link layer (e.g. interrupt processing)
666 // the u32 argument contains the DLL state and the NMT event
668 pEventArg_p->m_InternalError.
682 case kEplApiEventNode:
684 // printk("AppCbEvent(Node): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError);
685 // check additional argument
686 switch (pEventArg_p->m_Node.m_NodeEvent) {
687 case kEplNmtNodeEventCheckConf:
689 tEplSdoComConHdl SdoComConHdl;
690 // update object 0x1006 on CN
692 EplApiWriteObject(&SdoComConHdl,
700 if (EplRet == kEplApiTaskDeferred) { // SDO transfer started
702 } else if (EplRet == kEplSuccessful) { // local OD access (should not occur)
704 ("AppCbEvent(Node) write to local OD\n");
705 } else { // error occured
706 TGT_DBG_SIGNAL_TRACE_POINT(1);
717 m_uiNodeId, 0x1006, 0x00,
718 &dw_le_CycleLen_g, 4,
719 kEplSdoTypeAsnd, NULL);
720 if (EplRet == kEplApiTaskDeferred) { // SDO transfer started
724 ("AppCbEvent(Node): EplApiWriteObject() returned 0x%02X\n",
740 case kEplApiEventSdo:
741 { // SDO transfer finished
743 EplApiFreeSdoChannel(pEventArg_p->m_Sdo.
745 if (EplRet != kEplSuccessful) {
748 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
749 if (pEventArg_p->m_Sdo.m_SdoComConState == kEplSdoComTransferFinished) { // continue boot-up of CN with NMT command Reset Configuration
751 EplApiMnTriggerStateChange(pEventArg_p->
753 kEplNmtNodeCommandConfReset);
754 } else { // indicate configuration error CN
756 EplApiMnTriggerStateChange(pEventArg_p->
758 kEplNmtNodeCommandConfErr);
772 //---------------------------------------------------------------------------
774 // Function: AppCbSync
776 // Description: sync event callback function called by event module within
777 // kernel part (high priority).
778 // This function sets the outputs, reads the inputs and runs
783 // Returns: tEplKernel = error code,
784 // kEplSuccessful = no error
785 // otherwise = post error event to API layer
789 //---------------------------------------------------------------------------
791 tEplKernel AppCbSync(void)
793 tEplKernel EplRet = kEplSuccessful;
795 if (bVarOut1Old_l != bVarOut1_l) { // output variable has changed
796 bVarOut1Old_l = bVarOut1_l;
799 // printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (u16) bVarIn_l, (u16) bVarOut_l);
801 if (uiNodeId_g != EPL_C_ADR_MN_DEF_NODE_ID) {
805 if (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID) { // we are the master and must run the control loop
807 // collect inputs from CNs and own input
808 bSpeedSelect_l = (bVarIn1_l | abSelect_l[0]) & 0x07;
810 bModeSelect_l = abSelect_l[1] | abSelect_l[2];
812 if ((bModeSelect_l & APP_MODE_MASK) != 0) {
813 dwMode_l = bModeSelect_l & APP_MODE_MASK;
818 if (iCurCycleCount_l <= 0) {
819 if ((dwMode_l & 0x01) != 0) { // fill-up
821 if ((dwLeds_l & APP_DOUBLE_LED_MASK) ==
828 APP_DOUBLE_LED_MASK) {
834 if ((dwLeds_l & APP_DOUBLE_LED_MASK) ==
840 (unsigned char)(dwLeds_l & APP_LED_MASK);
842 (unsigned char)((dwLeds_l >> APP_LED_COUNT)
846 else if ((dwMode_l & 0x02) != 0) { // running light forward
848 if ((dwLeds_l > APP_DOUBLE_LED_MASK)
849 || (dwLeds_l == 0x00000000L)) {
853 (unsigned char)(dwLeds_l & APP_LED_MASK);
855 (unsigned char)((dwLeds_l >> APP_LED_COUNT)
859 else if ((dwMode_l & 0x04) != 0) { // running light backward
861 if ((dwLeds_l > APP_DOUBLE_LED_MASK)
862 || (dwLeds_l == 0x00000000L)) {
863 dwLeds_l = 1 << (APP_LED_COUNT * 2);
866 (unsigned char)(dwLeds_l & APP_LED_MASK);
868 (unsigned char)((dwLeds_l >> APP_LED_COUNT)
872 else if ((dwMode_l & 0x08) != 0) { // Knightrider
873 if (bLedsRow1_l == 0x00) {
876 } else if (iToggle) {
879 (1 << (APP_LED_COUNT - 1))) {
884 if (bLedsRow1_l <= 0x01) {
888 bLedsRow2_l = bLedsRow1_l;
891 else if ((dwMode_l & 0x10) != 0) { // Knightrider
892 if ((bLedsRow1_l == 0x00)
893 || (bLedsRow2_l == 0x00)
894 || ((bLedsRow2_l & ~APP_LED_MASK) != 0)) {
897 (1 << (APP_LED_COUNT - 1));
899 } else if (iToggle) {
903 (1 << (APP_LED_COUNT - 1))) {
909 if (bLedsRow1_l <= 0x01) {
915 bVarOut1_l = bLedsRow1_l;
916 // bVarOut1_l = (bLedsRow1_l & 0x03) | (bLedsRow2_l << 2);
918 // restart cycle counter
919 iCurCycleCount_l = iMaxCycleCount_l;
922 if (bSpeedSelectOld_l == 0) {
923 if ((bSpeedSelect_l & 0x01) != 0) {
924 if (iMaxCycleCount_l < 200) {
927 bSpeedSelectOld_l = bSpeedSelect_l;
928 } else if ((bSpeedSelect_l & 0x02) != 0) {
929 if (iMaxCycleCount_l > 1) {
932 bSpeedSelectOld_l = bSpeedSelect_l;
933 } else if ((bSpeedSelect_l & 0x04) != 0) {
934 iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
935 bSpeedSelectOld_l = bSpeedSelect_l;
937 } else if (bSpeedSelect_l == 0) {
938 bSpeedSelectOld_l = 0;
942 TGT_DBG_SIGNAL_TRACE_POINT(1);