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