2 This file is part of CanFestival, a library implementing CanOpen
5 Copyright (C): Edouard TISSERANT and Francis DUPIN
7 See COPYING file for copyrights details.
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 ** @author Edouard TISSERANT
28 ** @date Mon Jun 4 17:19:24 2007
37 #include "canfestival.h"
39 /*! Prototypes for internals functions
45 void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id);
53 void ProducerHearbeatAlarm(CO_Data* d, UNS32 id);
59 ** @param unsused_indextable
60 ** @param unsused_bSubindex
64 UNS32 OnHearbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex);
74 e_nodeState getNodeState (CO_Data* d, UNS8 nodeId)
76 e_nodeState networkNodeState = d->NMTable[nodeId];
77 return networkNodeState;
80 /*! The Consumer Timer Callback
86 void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id)
88 /*MSG_WAR(0x00, "ConsumerHearbeatAlarm", 0x00);*/
90 /*! call heartbeat error with NodeId */
91 (*d->heartbeatError)((UNS8)( ((d->ConsumerHeartbeatEntries[id]) & (UNS32)0x00FF0000) >> (UNS8)16 ));
100 void proceedNODE_GUARD(CO_Data* d, Message* m )
102 UNS8 nodeId = (UNS8) GET_NODE_ID((*m));
106 ** Notice that only the master can have sent this
107 ** node guarding request
111 ** Receiving a NMT NodeGuarding (request of the state by the
113 ** Only answer to the NMT NodeGuarding request, the master is
114 ** not checked (not implemented)
116 if (nodeId == *d->bDeviceNodeId )
119 msg.cob_id.w = *d->bDeviceNodeId + 0x700;
120 msg.len = (UNS8)0x01;
122 msg.data[0] = d->nodeState;
125 msg.data[0] |= 0x80 ;
130 /*! send the nodeguard response. */
131 MSG_WAR(0x3130, "Sending NMT Nodeguard to master, state: ", d->nodeState);
132 canSend(d->canHandle,&msg );
135 }else{ /*! Not a request CAN */
137 MSG_WAR(0x3110, "Received NMT nodeId : ", nodeId);
138 /*! the slave's state receievd is stored in the NMTable */
139 /*! The state is stored on 7 bit */
140 d->NMTable[nodeId] = (e_nodeState) ((*m).data[0] & 0x7F) ;
142 /*! Boot-Up frame reception */
143 if ( d->NMTable[nodeId] == Initialisation)
146 ** The device send the boot-up message (Initialisation)
147 ** to indicate the master that it is entered in
148 ** pre_operational mode
149 ** Because the device enter automaticaly in pre_operational
151 ** the pre_operational mode is stored
152 ** NMTable[bus_id][nodeId] = Pre_operational
154 MSG_WAR(0x3100, "The NMT is a bootup from node : ", nodeId);
157 if( d->NMTable[nodeId] != Unknown_state ) {
158 UNS8 index, ConsummerHeartBeat_nodeId ;
159 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
161 ConsummerHeartBeat_nodeId = (UNS8)( ((d->ConsumerHeartbeatEntries[index]) & (UNS32)0x00FF0000) >> (UNS8)16 );
162 if ( nodeId == ConsummerHeartBeat_nodeId )
164 TIMEVAL time = ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ;
165 /* Renew alarm for next heartbeat. */
166 DelAlarm(d->ConsumerHeartBeatTimers[index]);
167 d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0);
174 /*! The Consumer Timer Callback
180 void ProducerHearbeatAlarm(CO_Data* d, UNS32 id)
182 if(*d->ProducerHeartBeatTime)
185 /*! Time expired, the heartbeat must be sent immediately
186 ** generate the correct node-id: this is done by the offset 1792
187 ** (decimal) and additionaly
188 ** the node-id of this device.
191 msg.cob_id.w = *d->bDeviceNodeId + 0x700;
192 msg.len = (UNS8)0x01;
194 msg.data[0] = d->nodeState; /*! No toggle for heartbeat !*/
195 /*! send the heartbeat */
196 MSG_WAR(0x3130, "Producing heartbeat: ", d->nodeState);
197 canSend(d->canHandle,&msg );
200 d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer);
204 /*! This is called when Index 0x1017 is updated.
208 ** @param unsused_indextable
209 ** @param unsused_bSubindex
213 UNS32 OnHeartbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex)
225 void heartbeatInit(CO_Data* d)
228 UNS8 index; /*! Index to scan the table of heartbeat consumers */
229 RegisterSetODentryCallBack(d, 0x1017, 0x00, &OnHeartbeatProducerUpdate);
233 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
235 TIMEVAL time = (UNS16) ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ;
236 /*! MSG_WAR(0x3121, "should_time : ", should_time ) ; */
239 d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0);
243 if ( *d->ProducerHeartBeatTime )
245 TIMEVAL time = *d->ProducerHeartBeatTime;
246 d->ProducerHeartBeatTimer = SetAlarm(d, 0, &ProducerHearbeatAlarm, MS_TO_TIMEVAL(time), MS_TO_TIMEVAL(time));
255 void heartbeatStop(CO_Data* d)
258 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
260 d->ConsumerHeartBeatTimers[index + 1] = DelAlarm(d->ConsumerHeartBeatTimers[index + 1]);;
263 d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer);;
269 ** @param heartbeatID
271 void _heartbeatError(UNS8 heartbeatID){}