2 This file is part of CanFestival, a library implementing CanOpen Stack.
4 Copyright (C): Edouard TISSERANT and Francis DUPIN
6 See COPYING file for copyrights details.
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 ** @author Edouard TISSERANT and Francis DUPIN
25 ** @date Tue Jun 5 09:32:32 2007
35 /** Prototypes for internals functions */
40 ** @param newCommunicationState
42 void switchCommunicationState(CO_Data* d,
43 s_state_communication *newCommunicationState);
52 e_nodeState getState(CO_Data* d)
63 void canDispatch(CO_Data* d, Message *m)
65 UNS16 cob_id = UNS16_LE(m->cob_id);
68 case SYNC: /* can be a SYNC or a EMCY message */
69 if(cob_id == 0x080) /* SYNC */
71 if(d->CurrentCommunicationState.csSYNC)
74 if(d->CurrentCommunicationState.csEmergency)
77 /* case TIME_STAMP: */
86 if (d->CurrentCommunicationState.csPDO)
91 if (d->CurrentCommunicationState.csSDO)
95 if (d->CurrentCommunicationState.csHeartbeat)
96 proceedNODE_GUARD(d,m);
99 if (*(d->iam_a_slave))
101 proceedNMTstateChange(d,m);
105 if (!d->CurrentCommunicationState.csLSS)break;
106 if ((*(d->iam_a_slave)) && cob_id==MLSS_ADRESS)
108 proceedLSS_Slave(d,m);
110 else if(!(*(d->iam_a_slave)) && cob_id==SLSS_ADRESS)
112 proceedLSS_Master(d,m);
119 #define StartOrStop(CommType, FuncStart, FuncStop) \
120 if(newCommunicationState->CommType && d->CurrentCommunicationState.CommType == 0){\
121 MSG_WAR(0x9999,#FuncStart, 9999);\
122 d->CurrentCommunicationState.CommType = 1;\
124 }else if(!newCommunicationState->CommType && d->CurrentCommunicationState.CommType == 1){\
125 MSG_WAR(0x9999,#FuncStop, 9999);\
126 d->CurrentCommunicationState.CommType = 0;\
135 ** @param newCommunicationState
137 void switchCommunicationState(CO_Data* d, s_state_communication *newCommunicationState)
140 StartOrStop(csLSS, startLSS(d), stopLSS(d))
142 StartOrStop(csSDO, None, resetSDO(d))
143 StartOrStop(csSYNC, startSYNC(d), stopSYNC(d))
144 StartOrStop(csHeartbeat, heartbeatInit(d), heartbeatStop(d))
145 StartOrStop(csEmergency, emergencyInit(d), emergencyStop(d))
146 StartOrStop(csPDO, PDOInit(d), PDOStop(d))
147 StartOrStop(csBoot_Up, None, slaveSendBootUp(d))
158 UNS8 setState(CO_Data* d, e_nodeState newState)
160 if(newState != d->nodeState){
164 s_state_communication newCommunicationState = {1, 0, 0, 0, 0, 0, 0};
165 d->nodeState = Initialisation;
166 switchCommunicationState(d, &newCommunicationState);
167 /* call user app init callback now. */
168 /* d->initialisation MUST NOT CALL SetState */
169 (*d->initialisation)(d);
172 /* Automatic transition - No break statement ! */
173 /* Transition from Initialisation to Pre_operational */
174 /* is automatic as defined in DS301. */
175 /* App don't have to call SetState(d, Pre_operational) */
177 case Pre_operational:
180 s_state_communication newCommunicationState = {0, 1, 1, 1, 1, 0, 1};
181 d->nodeState = Pre_operational;
182 switchCommunicationState(d, &newCommunicationState);
183 if (!(*(d->iam_a_slave)))
185 masterSendNMTstateChange (d, 0, NMT_Reset_Node);
187 (*d->preOperational)(d);
192 if(d->nodeState == Initialisation) return 0xFF;
194 s_state_communication newCommunicationState = {0, 1, 1, 1, 1, 1, 0};
195 d->nodeState = Operational;
196 newState = Operational;
197 switchCommunicationState(d, &newCommunicationState);
198 (*d->operational)(d);
203 if(d->nodeState == Initialisation) return 0xFF;
205 s_state_communication newCommunicationState = {0, 0, 0, 0, 1, 0, 1};
206 d->nodeState = Stopped;
208 switchCommunicationState(d, &newCommunicationState);
215 }/* end switch case */
218 /* d->nodeState contains the final state */
219 /* may not be the requested state */
230 UNS8 getNodeId(CO_Data* d)
232 return *d->bDeviceNodeId;
241 void setNodeId(CO_Data* d, UNS8 nodeId)
243 UNS16 offset = d->firstIndex->SDO_SVR;
246 d->lss_transfer.nodeID=nodeId;
249 *d->bDeviceNodeId = nodeId;
255 /* Adjust COB-ID Client->Server (rx) only id already set to default value or id not valid (id==0xFF)*/
256 if((*(UNS32*)d->objdict[offset].pSubindex[1].pObject == 0x600 + *d->bDeviceNodeId)||(*d->bDeviceNodeId==0xFF)){
257 /* cob_id_client = 0x600 + nodeId; */
258 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = 0x600 + nodeId;
260 /* Adjust COB-ID Server -> Client (tx) only id already set to default value or id not valid (id==0xFF)*/
261 if((*(UNS32*)d->objdict[offset].pSubindex[2].pObject == 0x580 + *d->bDeviceNodeId)||(*d->bDeviceNodeId==0xFF)){
262 /* cob_id_server = 0x580 + nodeId; */
263 *(UNS32*)d->objdict[offset].pSubindex[2].pObject = 0x580 + nodeId;
268 Initialize the server(s) SDO parameters
269 Remember that only one SDO server is allowed, defined at index 0x1200
271 Initialize the client(s) SDO parameters
272 Nothing to initialize (no default values required by the DS 401)
273 Initialize the receive PDO communication parameters. Only for 0x1400 to 0x1403
277 UNS16 offset = d->firstIndex->PDO_RCV;
278 UNS16 lastIndex = d->lastIndex->PDO_RCV;
279 UNS32 cobID[] = {0x200, 0x300, 0x400, 0x500};
280 if( offset ) while( (offset <= lastIndex) && (i < 4)) {
281 if((*(UNS32*)d->objdict[offset].pSubindex[1].pObject == cobID[i] + *d->bDeviceNodeId)||(*d->bDeviceNodeId==0xFF))
282 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = cobID[i] + nodeId;
287 /* ** Initialize the transmit PDO communication parameters. Only for 0x1800 to 0x1803 */
290 UNS16 offset = d->firstIndex->PDO_TRS;
291 UNS16 lastIndex = d->lastIndex->PDO_TRS;
292 UNS32 cobID[] = {0x180, 0x280, 0x380, 0x480};
294 if( offset ) while ((offset <= lastIndex) && (i < 4)) {
295 if((*(UNS32*)d->objdict[offset].pSubindex[1].pObject == cobID[i] + *d->bDeviceNodeId)||(*d->bDeviceNodeId==0xFF))
296 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = cobID[i] + nodeId;
302 /* Update EMCY COB-ID if already set to default*/
303 if((*d->error_cobid == *d->bDeviceNodeId + 0x80)||(*d->bDeviceNodeId==0xFF))
304 *d->error_cobid = nodeId + 0x80;
306 /* bDeviceNodeId is defined in the object dictionary. */
307 *d->bDeviceNodeId = nodeId;
310 void _initialisation(CO_Data* d){}
311 void _preOperational(CO_Data* d){}
312 void _operational(CO_Data* d){}
313 void _stopped(CO_Data* d){}