]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - src/lifegrd.c
Adding support for replace imported EDS in nodelist
[CanFestival-3.git] / src / lifegrd.c
1 /*
2   This file is part of CanFestival, a library implementing CanOpen
3   Stack.
4
5   Copyright (C): Edouard TISSERANT and Francis DUPIN
6
7   See COPYING file for copyrights details.
8
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.
13
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.
18
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
22   USA
23 */
24
25 /*!
26 ** @file   lifegrd.c
27 ** @author Edouard TISSERANT
28 ** @date   Mon Jun  4 17:19:24 2007
29 **
30 ** @brief
31 **
32 **
33 */
34
35 #include <data.h>
36 #include "lifegrd.h"
37 #include "canfestival.h"
38 #include "dcf.h"
39 #include "sysdep.h"
40
41
42 void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id);
43
44
45 void ProducerHearbeatAlarm(CO_Data* d, UNS32 id);
46
47 UNS32 OnHearbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex);
48
49 /*!
50 **
51 **
52 ** @param d
53 ** @param nodeId
54 **
55 ** @return
56 **/
57 e_nodeState getNodeState (CO_Data* d, UNS8 nodeId)
58 {
59   e_nodeState networkNodeState = d->NMTable[nodeId];
60   return networkNodeState;
61 }
62
63 /*! 
64 ** The Consumer Timer Callback
65 **
66 ** @param d
67 ** @param id
68 **/
69 void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id)
70 {
71   /*MSG_WAR(0x00, "ConsumerHearbeatAlarm", 0x00);*/
72
73   /* timer have been notified and is now free (non periodic)*/
74   /* -> avoid deleting re-assigned timer if message is received too late*/
75   d->ConsumerHeartBeatTimers[id]=TIMER_NONE;
76   /*! call heartbeat error with NodeId */
77   (*d->heartbeatError)(d, (UNS8)( ((d->ConsumerHeartbeatEntries[id]) & (UNS32)0x00FF0000) >> (UNS8)16 ));
78 }
79
80 /*!
81 **
82 **
83 ** @param d
84 ** @param m
85 **/
86 void proceedNODE_GUARD(CO_Data* d, Message* m )
87 {
88   UNS8 nodeId = (UNS8) GET_NODE_ID((*m));
89
90   if((m->rtr == 1) )
91     /*!
92     ** Notice that only the master can have sent this
93     ** node guarding request
94     */
95     {
96       /*!
97       ** Receiving a NMT NodeGuarding (request of the state by the
98       ** master)
99       ** Only answer to the NMT NodeGuarding request, the master is
100       ** not checked (not implemented)
101       */
102       if (nodeId == *d->bDeviceNodeId )
103         {
104           Message msg;
105           UNS16 tmp = *d->bDeviceNodeId + 0x700;
106           msg.cob_id = UNS16_LE(tmp);
107           msg.len = (UNS8)0x01;
108           msg.rtr = 0;
109           msg.data[0] = d->nodeState;
110           if (d->toggle)
111             {
112               msg.data[0] |= 0x80 ;
113               d->toggle = 0 ;
114             }
115           else
116             d->toggle = 1 ;
117           /* send the nodeguard response. */
118           MSG_WAR(0x3130, "Sending NMT Nodeguard to master, state: ", d->nodeState);
119           canSend(d->canHandle,&msg );
120         }
121
122     }else{ /* Not a request CAN */
123
124       MSG_WAR(0x3110, "Received NMT nodeId : ", nodeId);
125       /* the slave's state receievd is stored in the NMTable */
126       /* The state is stored on 7 bit */
127       d->NMTable[nodeId] = (e_nodeState) ((*m).data[0] & 0x7F) ;
128
129       /* Boot-Up frame reception */
130       if ( d->NMTable[nodeId] == Initialisation)
131         {
132           /*
133           ** The device send the boot-up message (Initialisation)
134           ** to indicate the master that it is entered in
135           ** pre_operational mode
136           ** Because the  device enter automaticaly in pre_operational
137           ** mode,
138           ** the pre_operational mode is stored
139           ** NMTable[bus_id][nodeId] = Pre_operational
140           */
141           MSG_WAR(0x3100, "The NMT is a bootup from node : ", nodeId);
142           
143           if(!send_consise_dcf(d,nodeId)){
144              /* call post SlaveBootup with NodeId */
145                         (*d->post_SlaveBootup)(d, nodeId);
146           }
147         }
148
149       if( d->NMTable[nodeId] != Unknown_state ) {
150         UNS8 index, ConsummerHeartBeat_nodeId ;
151         for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
152           {
153             ConsummerHeartBeat_nodeId = (UNS8)( ((d->ConsumerHeartbeatEntries[index]) & (UNS32)0x00FF0000) >> (UNS8)16 );
154             if ( nodeId == ConsummerHeartBeat_nodeId )
155               {
156                 TIMEVAL time = ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ;
157                 /* Renew alarm for next heartbeat. */
158                 DelAlarm(d->ConsumerHeartBeatTimers[index]);
159                 d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0);
160               }
161           }
162       }
163     }
164 }
165
166 /*! The Consumer Timer Callback
167 **
168 **
169 ** @param d
170 ** @param id
171 **/
172 void ProducerHearbeatAlarm(CO_Data* d, UNS32 id)
173 {
174   if(*d->ProducerHeartBeatTime)
175     {
176       Message msg;
177       /* Time expired, the heartbeat must be sent immediately
178       ** generate the correct node-id: this is done by the offset 1792
179       ** (decimal) and additionaly
180       ** the node-id of this device.
181       */
182       UNS16 tmp = *d->bDeviceNodeId + 0x700;
183       msg.cob_id = UNS16_LE(tmp);
184       msg.len = (UNS8)0x01;
185       msg.rtr = 0;
186       msg.data[0] = d->nodeState; /* No toggle for heartbeat !*/
187       /* send the heartbeat */
188       MSG_WAR(0x3130, "Producing heartbeat: ", d->nodeState);
189       canSend(d->canHandle,&msg );
190
191     }else{
192       d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer);
193     }
194 }
195
196 /*! This is called when Index 0x1017 is updated.
197 **
198 **
199 ** @param d
200 ** @param unsused_indextable
201 ** @param unsused_bSubindex
202 **
203 ** @return
204 **/
205 UNS32 OnHeartbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex)
206 {
207   heartbeatStop(d);
208   heartbeatInit(d);
209   return 0;
210 }
211
212 /*!
213 **
214 **
215 ** @param d
216 **/
217 void heartbeatInit(CO_Data* d)
218 {
219
220   UNS8 index; /* Index to scan the table of heartbeat consumers */
221   RegisterSetODentryCallBack(d, 0x1017, 0x00, &OnHeartbeatProducerUpdate);
222
223   d->toggle = 0;
224
225   for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
226     {
227       TIMEVAL time = (UNS16) ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ;
228       /* MSG_WAR(0x3121, "should_time : ", should_time ) ; */
229       if ( time )
230         {
231           d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0);
232         }
233     }
234
235   if ( *d->ProducerHeartBeatTime )
236     {
237       TIMEVAL time = *d->ProducerHeartBeatTime;
238       d->ProducerHeartBeatTimer = SetAlarm(d, 0, &ProducerHearbeatAlarm, MS_TO_TIMEVAL(time), MS_TO_TIMEVAL(time));
239     }
240 }
241
242 /*!
243 **
244 **
245 ** @param d
246 **/
247 void heartbeatStop(CO_Data* d)
248 {
249   UNS8 index;
250   for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
251     {
252       d->ConsumerHeartBeatTimers[index] = DelAlarm(d->ConsumerHeartBeatTimers[index]);
253     }
254
255   d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer);
256 }
257
258 /*!
259 **
260 **
261 ** @param heartbeatID
262 **/
263 void _heartbeatError(CO_Data* d, UNS8 heartbeatID){}
264 void _post_SlaveBootup(CO_Data* d, UNS8 SlaveID){}