nico@207: nico@207:
nico@215:00001 /* nico@207: 00002 This file is part of CanFestival, a library implementing CanOpen Stack. nico@207: 00003 nico@207: 00004 Copyright (C): Edouard TISSERANT and Francis DUPIN nico@207: 00005 nico@207: 00006 See COPYING file for copyrights details. nico@207: 00007 nico@207: 00008 This library is free software; you can redistribute it and/or nico@207: 00009 modify it under the terms of the GNU Lesser General Public nico@207: 00010 License as published by the Free Software Foundation; either nico@207: 00011 version 2.1 of the License, or (at your option) any later version. nico@207: 00012 nico@207: 00013 This library is distributed in the hope that it will be useful, nico@207: 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of nico@207: 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU nico@207: 00016 Lesser General Public License for more details. nico@207: 00017 nico@207: 00018 You should have received a copy of the GNU Lesser General Public nico@207: 00019 License along with this library; if not, write to the Free Software nico@207: 00020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA nico@207: 00021 */ nico@215: 00032 #include "states.h" nico@215: 00033 #include "def.h" nico@215: 00034 #include "dcf.h" nico@215: 00035 #include "nmtSlave.h" nico@210: 00036 etisserant@240: 00044 void switchCommunicationState(CO_Data* d, nico@215: 00045 s_state_communication *newCommunicationState); nico@210: 00046 etisserant@240: 00054 e_nodeState getState(CO_Data* d) nico@210: 00055 { etisserant@240: 00056 return d->nodeState; nico@210: 00057 } nico@210: 00058 etisserant@240: 00065 void canDispatch(CO_Data* d, Message *m) nico@210: 00066 { etisserant@240: 00067 switch(m->cob_id.w >> 7) nico@210: 00068 { etisserant@240: 00069 case SYNC: etisserant@240: 00070 if(d->CurrentCommunicationState.csSYNC) etisserant@240: 00071 proceedSYNC(d,m); nico@210: 00072 break; nico@215: 00073 /* case TIME_STAMP: */ etisserant@240: 00074 case PDO1tx: etisserant@240: 00075 case PDO1rx: etisserant@240: 00076 case PDO2tx: etisserant@240: 00077 case PDO2rx: etisserant@240: 00078 case PDO3tx: etisserant@240: 00079 case PDO3rx: etisserant@240: 00080 case PDO4tx: etisserant@240: 00081 case PDO4rx: etisserant@240: 00082 if (d->CurrentCommunicationState.csPDO) etisserant@240: 00083 proceedPDO(d,m); nico@210: 00084 break; etisserant@240: 00085 case SDOtx: etisserant@240: 00086 case SDOrx: etisserant@240: 00087 if (d->CurrentCommunicationState.csSDO) etisserant@240: 00088 proceedSDO(d,m); nico@210: 00089 break; etisserant@240: 00090 case NODE_GUARD: etisserant@240: 00091 if (d->CurrentCommunicationState.csHeartbeat) etisserant@240: 00092 proceedNODE_GUARD(d,m); nico@210: 00093 break; etisserant@240: 00094 case NMT: etisserant@240: 00095 if (*(d->iam_a_slave)) nico@210: 00096 { etisserant@240: 00097 proceedNMTstateChange(d,m); nico@210: 00098 } nico@210: 00099 } nico@210: 00100 } nico@210: 00101 etisserant@240: 00102 #define StartOrStop(CommType, FuncStart, FuncStop) \ nico@210: 00103 if(newCommunicationState->CommType && !d->CurrentCommunicationState.CommType){\ nico@210: 00104 MSG_WAR(0x9999,#FuncStart, 9999);\ nico@210: 00105 d->CurrentCommunicationState.CommType = 1;\ nico@210: 00106 FuncStart;\ nico@210: 00107 }else if(!newCommunicationState->CommType && d->CurrentCommunicationState.CommType){\ nico@210: 00108 MSG_WAR(0x9999,#FuncStop, 9999);\ nico@210: 00109 d->CurrentCommunicationState.CommType = 0;\ nico@210: 00110 FuncStop;\ nico@210: 00111 } etisserant@240: 00112 #define None nico@210: 00113 etisserant@240: 00120 void switchCommunicationState(CO_Data* d, s_state_communication *newCommunicationState) nico@210: 00121 { etisserant@240: 00122 StartOrStop(csSDO, None, resetSDO(d)) etisserant@240: 00123 StartOrStop(csSYNC, startSYNC(d), stopSYNC(d)) etisserant@240: 00124 StartOrStop(csHeartbeat, heartbeatInit(d), heartbeatStop(d)) nico@210: 00125 /* StartOrStop(Emergency,,) */ etisserant@240: 00126 StartOrStop(csPDO, PDOInit(d), PDOStop(d)) etisserant@240: 00127 StartOrStop(csBoot_Up, None, slaveSendBootUp(d)) nico@210: 00128 } nico@210: 00129 etisserant@240: 00138 UNS8 setState(CO_Data* d, e_nodeState newState) nico@210: 00139 { etisserant@240: 00140 UNS16 wIndex = 0x1F22; etisserant@240: 00141 const indextable *ptrTable; etisserant@240: 00142 ODCallback_t *Callback; etisserant@240: 00143 UNS32 errorCode; etisserant@240: 00144 while(newState != d->nodeState){ nico@210: 00145 switch( newState ){ etisserant@240: 00146 case Initialisation: nico@210: 00147 { nico@215: 00148 s_state_communication newCommunicationState = {1, 0, 0, 0, 0, 0}; nico@215: 00149 /* This will force a second loop for the state switch */ etisserant@240: 00150 d->nodeState = Initialisation; etisserant@240: 00151 newState = Pre_operational; etisserant@240: 00152 switchCommunicationState(d, &newCommunicationState); nico@215: 00153 /* call user app related state func. */ etisserant@240: 00154 (*d->initialisation)(); nico@210: 00155 nico@210: 00156 } nico@210: 00157 break; nico@210: 00158 etisserant@240: 00159 case Pre_operational: nico@210: 00160 { nico@210: 00161 nico@215: 00162 s_state_communication newCommunicationState = {0, 1, 1, 1, 1, 0}; etisserant@240: 00163 d->nodeState = Pre_operational; etisserant@240: 00164 newState = Pre_operational; etisserant@240: 00165 switchCommunicationState(d, &newCommunicationState); etisserant@240: 00166 if (!(*(d->iam_a_slave))) nico@210: 00167 { etisserant@240: 00168 ptrTable =(*d->scanIndexOD)(wIndex, &errorCode, &Callback); nico@210: 00169 etisserant@240: 00170 if (errorCode != OD_SUCCESSFUL) nico@210: 00171 { etisserant@240: 00172 (*d->preOperational)(); nico@210: 00173 } nico@210: 00174 else nico@210: 00175 { etisserant@240: 00176 UNS32 res; etisserant@240: 00177 res = decompo_dcf(d,0x01); nico@210: 00178 } nico@210: 00179 } nico@210: 00180 else nico@210: 00181 { etisserant@240: 00182 (*d->preOperational)(); nico@210: 00183 } nico@210: 00184 } nico@210: 00185 break; nico@210: 00186 etisserant@240: 00187 case Operational: etisserant@240: 00188 if(d->nodeState == Initialisation) return 0xFF; nico@210: 00189 { nico@215: 00190 s_state_communication newCommunicationState = {0, 1, 1, 1, 1, 1}; etisserant@240: 00191 d->nodeState = Operational; etisserant@240: 00192 newState = Operational; etisserant@240: 00193 switchCommunicationState(d, &newCommunicationState); etisserant@240: 00194 (*d->operational)(); nico@210: 00195 } nico@210: 00196 break; nico@210: 00197 etisserant@240: 00198 case Stopped: etisserant@240: 00199 if(d->nodeState == Initialisation) return 0xFF; nico@210: 00200 { nico@215: 00201 s_state_communication newCommunicationState = {0, 0, 0, 0, 1, 0}; etisserant@240: 00202 d->nodeState = Stopped; etisserant@240: 00203 newState = Stopped; etisserant@240: 00204 switchCommunicationState(d, &newCommunicationState); etisserant@240: 00205 (*d->stopped)(); nico@210: 00206 } nico@210: 00207 break; nico@210: 00208 nico@210: 00209 default: nico@210: 00210 return 0xFF; nico@215: 00211 }/* end switch case */ nico@215: 00212 nico@210: 00213 } nico@210: 00214 return 0; nico@210: 00215 } nico@210: 00216 etisserant@240: 00224 UNS8 getNodeId(CO_Data* d) nico@210: 00225 { etisserant@240: 00226 return *d->bDeviceNodeId; nico@210: 00227 } nico@210: 00228 etisserant@240: 00235 void setNodeId(CO_Data* d, UNS8 nodeId) nico@210: 00236 { etisserant@240: 00237 UNS16 offset = d->firstIndex->SDO_SVR; nico@210: 00238 if(offset){ nico@215: 00239 /* cob_id_client = 0x600 + nodeId; */ etisserant@240: 00240 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = 0x600 + nodeId; nico@215: 00241 /* cob_id_server = 0x580 + nodeId; */ etisserant@240: 00242 *(UNS32*)d->objdict[offset].pSubindex[2].pObject = 0x580 + nodeId; nico@215: 00243 /* node Id client. As we do not know the value, we put the node Id Server */ nico@215: 00244 /* *(UNS8*)d->objdict[offset].pSubindex[3].pObject = nodeId; */ nico@210: 00245 } nico@210: 00246 nico@215: 00247 /* nico@215: 00248 Initialize the server(s) SDO parameters nico@215: 00249 Remember that only one SDO server is allowed, defined at index 0x1200 nico@215: 00250 nico@215: 00251 Initialize the client(s) SDO parameters nico@215: 00252 Nothing to initialize (no default values required by the DS 401) nico@215: 00253 Initialize the receive PDO communication parameters. Only for 0x1400 to 0x1403 nico@215: 00254 */ nico@210: 00255 { etisserant@240: 00256 UNS8 i = 0; etisserant@240: 00257 UNS16 offset = d->firstIndex->PDO_RCV; etisserant@240: 00258 UNS16 lastIndex = d->lastIndex->PDO_RCV; etisserant@240: 00259 UNS32 cobID[] = {0x200, 0x300, 0x400, 0x500}; nico@210: 00260 if( offset ) while( (offset <= lastIndex) && (i < 4)) { etisserant@240: 00261 if(*(UNS32*)d->objdict[offset].pSubindex[1].pObject == cobID[i] + *d->bDeviceNodeId) etisserant@240: 00262 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = cobID[i] + nodeId; nico@210: 00263 i ++; nico@210: 00264 offset ++; nico@210: 00265 } nico@210: 00266 } nico@210: 00267 /* ** Initialize the transmit PDO communication parameters. Only for 0x1800 to 0x1803 */ nico@210: 00268 { etisserant@240: 00269 UNS8 i = 0; etisserant@240: 00270 UNS16 offset = d->firstIndex->PDO_TRS; etisserant@240: 00271 UNS16 lastIndex = d->lastIndex->PDO_TRS; etisserant@240: 00272 UNS32 cobID[] = {0x180, 0x280, 0x380, 0x480}; nico@210: 00273 i = 0; nico@210: 00274 if( offset ) while ((offset <= lastIndex) && (i < 4)) { etisserant@240: 00275 if(*(UNS32*)d->objdict[offset].pSubindex[1].pObject == cobID[i] + *d->bDeviceNodeId) etisserant@240: 00276 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = cobID[i] + nodeId; nico@210: 00277 i ++; nico@210: 00278 offset ++; nico@210: 00279 } nico@210: 00280 } nico@215: 00281 /* bDeviceNodeId is defined in the object dictionary. */ etisserant@240: 00282 *d->bDeviceNodeId = nodeId; nico@210: 00283 } nico@210: 00284 etisserant@240: 00285 void _initialisation(){} etisserant@240: 00286 void _preOperational(){} etisserant@240: 00287 void _operational(){} etisserant@240: 00288 void _stopped(){} etisserant@240: