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