nico@207: nico@207: nico@215: CanFestival: src/states.c Source File nico@207: nico@207: nico@207: nico@207: nico@207:
nico@207:
nico@207:
nico@207:
nico@215: nico@215:

states.c

Go to the documentation of this file.
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: 

Generated on Mon Jul 2 19:10:16 2007 for CanFestival by  nico@207: nico@207: doxygen 1.5.1
nico@207: nico@207: