Sam Grove / canopen_masternode

Description: CANfestival - an open source CANopen framework

Files at this revision

API Documentation at this revision

Comitter:
http://mbed
Date:
Mon May 30 07:36:47 2011 +0000
Child:
1:cb8989598a0f
Commit message:
Initial public release of master node example

Changed in this revision

framework/driver/mbed/can_mbed.cpp Show annotated file Show diff for this revision Revisions of this file
framework/driver/mbed/timer_mbed.cpp Show annotated file Show diff for this revision Revisions of this file
framework/include/can_driver.h Show annotated file Show diff for this revision Revisions of this file
framework/include/canopen_can.h Show annotated file Show diff for this revision Revisions of this file
framework/include/canopen_timer.h Show annotated file Show diff for this revision Revisions of this file
framework/include/data.h Show annotated file Show diff for this revision Revisions of this file
framework/include/dcf.h Show annotated file Show diff for this revision Revisions of this file
framework/include/def.h Show annotated file Show diff for this revision Revisions of this file
framework/include/emcy.h Show annotated file Show diff for this revision Revisions of this file
framework/include/lifegrd.h Show annotated file Show diff for this revision Revisions of this file
framework/include/lss.h Show annotated file Show diff for this revision Revisions of this file
framework/include/mbed/applicfg.h Show annotated file Show diff for this revision Revisions of this file
framework/include/mbed/can_mbed.h Show annotated file Show diff for this revision Revisions of this file
framework/include/mbed/canfestival.h Show annotated file Show diff for this revision Revisions of this file
framework/include/mbed/config.h Show annotated file Show diff for this revision Revisions of this file
framework/include/mbed/timerscfg.h Show annotated file Show diff for this revision Revisions of this file
framework/include/nmtMaster.h Show annotated file Show diff for this revision Revisions of this file
framework/include/nmtSlave.h Show annotated file Show diff for this revision Revisions of this file
framework/include/objacces.h Show annotated file Show diff for this revision Revisions of this file
framework/include/objdictdef.h Show annotated file Show diff for this revision Revisions of this file
framework/include/pdo.h Show annotated file Show diff for this revision Revisions of this file
framework/include/sdo.h Show annotated file Show diff for this revision Revisions of this file
framework/include/states.h Show annotated file Show diff for this revision Revisions of this file
framework/include/sync.h Show annotated file Show diff for this revision Revisions of this file
framework/include/sysdep.h Show annotated file Show diff for this revision Revisions of this file
framework/include/timers_driver.h Show annotated file Show diff for this revision Revisions of this file
framework/src/canopen_timer.c Show annotated file Show diff for this revision Revisions of this file
framework/src/dcf.c Show annotated file Show diff for this revision Revisions of this file
framework/src/emcy.c Show annotated file Show diff for this revision Revisions of this file
framework/src/lifegrd.c Show annotated file Show diff for this revision Revisions of this file
framework/src/lss.c Show annotated file Show diff for this revision Revisions of this file
framework/src/nmtMaster.c Show annotated file Show diff for this revision Revisions of this file
framework/src/nmtSlave.c Show annotated file Show diff for this revision Revisions of this file
framework/src/objacces.c Show annotated file Show diff for this revision Revisions of this file
framework/src/pdo.c Show annotated file Show diff for this revision Revisions of this file
framework/src/sdo.c Show annotated file Show diff for this revision Revisions of this file
framework/src/states.c Show annotated file Show diff for this revision Revisions of this file
framework/src/sync.c Show annotated file Show diff for this revision Revisions of this file
mbed.lib Show annotated file Show diff for this revision Revisions of this file
source/main.cpp Show annotated file Show diff for this revision Revisions of this file
source/main.h Show annotated file Show diff for this revision Revisions of this file
source/mbed_master.c Show annotated file Show diff for this revision Revisions of this file
source/mbed_master.h Show annotated file Show diff for this revision Revisions of this file
source/port_helper.cpp Show annotated file Show diff for this revision Revisions of this file
source/port_helper.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/driver/mbed/can_mbed.cpp	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,100 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+mbed Port: sgrove
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//#define DEBUG_WAR_CONSOLE_ON
+//#define DEBUG_ERR_CONSOLE_ON
+
+#include "can_mbed.h"
+#include "canfestival.h"
+
+volatile unsigned char msg_received = 0;
+// initialize the CAN object from the mbed api
+CAN CANopen(p9, p10);
+
+unsigned char canInit(unsigned int bitrate)
+/******************************************************************************
+Initialize the hardware to send and receive CAN messages 
+INPUT    bitrate        bitrate in kilobit
+OUTPUT    1 if successful    
+******************************************************************************/
+{
+      // make sure the requested baudrate is supported
+    if (CANopen.frequency(bitrate*1000) == 0){
+          return 0;
+    }
+      // desired baud was set
+    return 1;
+}
+
+unsigned char canSend(CAN_PORT notused, Message *m)
+/******************************************************************************
+The driver send a CAN message passed from the CANopen stack
+INPUT    CAN_PORT is not used (only 1 avaiable)
+    Message *m pointer to message to send
+OUTPUT    1 if  hardware -> CAN frame
+******************************************************************************/
+{
+    // convert the message from a CANopen object to a mbed object
+    CANMessage msg(m->cob_id, (char*)m->data, m->len, static_cast<CANType>(m->rtr), CANStandard);
+    // make sure the message was sent
+    if (CANopen.write(msg) == 0){
+        return 0;                               
+    }
+    // message was sent
+    return 1;
+}
+
+unsigned char canReceive(Message *m)
+/******************************************************************************
+The driver pass a received CAN message to the stack
+INPUT    Message *m pointer to received CAN message
+OUTPUT    1 if a message received
+******************************************************************************/
+{
+    // object to store the last message
+    CANMessage msg;
+    // look if something has been rec'd
+    if (CANopen.read(msg) == 0){
+        return 0;
+    }
+    // conver the CANMessage object to a Message object
+    m->cob_id = msg.id;
+    m->len = msg.len;
+    m->rtr = static_cast<UNS8>(msg.type);
+    // clear erroneous data from the stack
+	for (int i=0; i<=7; i++){
+		if ((msg.len-1) >= i)
+			m->data[i] = msg.data[i];
+		else
+			m->data[i] = 0;
+	}
+    return 1;
+}
+
+/***************************************************************************/
+unsigned char canChangeBaudRate_driver( CAN_HANDLE fd, char* baud)
+{
+	// not sure how baud is passed as a char* yet
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/driver/mbed/timer_mbed.cpp	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,104 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+mbed Port: sgrove
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// Includes for the Canfestival driver
+#include "canfestival.h"
+#include "canopen_timer.h"
+#include "mbed.h"
+
+// make the system speed available for timer configuration
+extern uint32_t SystemCoreClock;
+
+// Define the timer registers
+#define TimerAlarm        LPC_TIM1->MR0	// compare register to genterate an interrupt
+#define TimerCounter      LPC_TIM1->TC	// free running timer counter register
+
+/************************** Module variables **********************************/
+// Store the last timer value to calculate the elapsed time
+static TIMEVAL last_time_set = TIMEVAL_MAX;     
+
+void initTimer(void)
+/******************************************************************************
+Initializes the timer, turn on the interrupt and put the interrupt time to zero
+INPUT    void
+OUTPUT    void
+******************************************************************************/
+{
+	float prescaler = 0;
+	TimerAlarm = 0;
+	// power up the timer (if not already done)
+	LPC_SC->PCONP |= (0x1 << 0x2);
+	// reset the timer
+	LPC_TIM1->TCR = 0x2;
+	// set up the prescaler to create an 8us incrementing tick using Timer1
+	switch ((LPC_SC->PCLKSEL0 >> 0x4) & 0x3){
+			case 0x00:	prescaler = 0.000008 / (1.0 / (SystemCoreClock / 4.0));	break;
+			case 0x01:	prescaler = 0.000008 / (1.0 / SystemCoreClock);	 		break;
+			case 0x02:	prescaler = 0.000008 / (1.0 / (SystemCoreClock / 2.0));	break;
+			case 0x03:	prescaler = 0.000008 / (1.0 / (SystemCoreClock / 8.0));	break;
+	}
+	LPC_TIM1->PR = static_cast<uint32_t>(prescaler);
+	// MR0 is used as a match event to trigger an interrupt - managed through TimerAlarm
+	LPC_TIM1->MCR |= (0x1 << 0);
+	NVIC_EnableIRQ(TIMER1_IRQn);
+	// start the timer
+	LPC_TIM1->TCR = 0x1; 
+    // Set timer for CANopen operation tick 8us , max time is 9+ hrs
+}
+
+void setTimer(TIMEVAL value)
+/******************************************************************************
+Set the timer for the next alarm.
+INPUT    value TIMEVAL (unsigned long)
+OUTPUT    void
+******************************************************************************/
+{
+  TimerAlarm += (uint32_t)value;    // Add the desired time to timer interrupt time
+}
+
+TIMEVAL getElapsedTime(void)
+/******************************************************************************
+Return the elapsed time to tell the Stack how much time is spent since last call.
+INPUT    void
+OUTPUT    value TIMEVAL (unsigned long) the elapsed time
+******************************************************************************/
+{
+	uint32_t timer = TimerCounter;	// Copy the value of the running timer
+  	// Calculate the time difference and return it
+  	return timer > last_time_set ? timer - last_time_set : last_time_set - timer;
+}
+
+///******************************************************************************
+//Interruptserviceroutine Timer Compare for the stack CAN timer
+//******************************************************************************/
+
+extern "C" void TIMER1_IRQHandler()
+{
+	// clear all pending interrupts
+	LPC_TIM1->IR = 0x3F;
+	// store the time of the last interrupt occurance
+	last_time_set = TimerCounter;
+	// Call the time handler of the stack to adapt the elapsed time
+	TimeDispatch();                          
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/can_driver.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,141 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __can_driver_h__
+#define __can_driver_h__
+
+struct struct_s_BOARD;
+
+typedef struct struct_s_BOARD s_BOARD;
+
+#include "applicfg.h"
+#include "can.h"
+
+/**
+ * @brief The CAN board configuration
+ * @ingroup can
+ */
+
+//struct struct_s_BOARD {
+//  char busname[100]; /**< The bus name on which the CAN board is connected */
+//  char baudrate[4]; /**< The board baudrate */
+//};
+
+struct struct_s_BOARD {
+  char * busname;  /**< The bus name on which the CAN board is connected */
+  char * baudrate; /**< The board baudrate */
+};
+
+#ifndef DLL_CALL
+#if !defined(WIN32) || defined(__CYGWIN__)
+#define DLL_CALL(funcname) funcname##_driver
+#else
+//Windows was missing the definition of the calling convention
+#define DLL_CALL(funcname) __stdcall funcname##_driver
+#endif
+#endif //DLL_CALL
+
+#ifndef FCT_PTR_INIT
+#define FCT_PTR_INIT
+#endif
+
+
+UNS8 DLL_CALL(canReceive)(CAN_HANDLE, Message *)FCT_PTR_INIT;
+UNS8 DLL_CALL(canSend)(CAN_HANDLE, Message const *)FCT_PTR_INIT;
+CAN_HANDLE DLL_CALL(canOpen)(s_BOARD *)FCT_PTR_INIT;
+int DLL_CALL(canClose)(CAN_HANDLE)FCT_PTR_INIT;
+UNS8 DLL_CALL(canChangeBaudRate)(CAN_HANDLE, char *)FCT_PTR_INIT;
+
+#if defined DEBUG_MSG_CONSOLE_ON || defined NEED_PRINT_MESSAGE
+#include "def.h"
+
+#define _P(fc) case fc: MSG(#fc" ");break;
+
+static inline void print_message(Message const *m)
+{
+    int i;
+    UNS8 fc;
+    MSG("id:%02x ", m->cob_id & 0x7F);
+    fc = m->cob_id >> 7;
+    switch(fc)
+    {
+        case SYNC:
+            if(m->cob_id == 0x080)
+                MSG("SYNC ");
+            else
+                MSG("EMCY ");
+        break;
+#ifdef CO_ENABLE_LSS
+        case LSS:
+        	if(m->cob_id == 0x7E5)
+                MSG("MLSS ");
+            else
+                MSG("SLSS ");
+        break;
+#endif
+        _P(TIME_STAMP)
+        _P(PDO1tx)
+        _P(PDO1rx)
+        _P(PDO2tx)
+        _P(PDO2rx)
+        _P(PDO3tx)
+        _P(PDO3rx)
+        _P(PDO4tx)
+        _P(PDO4rx)
+        _P(SDOtx)
+        _P(SDOrx)
+        _P(NODE_GUARD)
+        _P(NMT)
+    }
+    if( fc == SDOtx)
+    {
+        switch(m->data[0] >> 5)
+        {
+            /* scs: server command specifier */
+            _P(UPLOAD_SEGMENT_RESPONSE)
+            _P(DOWNLOAD_SEGMENT_RESPONSE)
+            _P(INITIATE_DOWNLOAD_RESPONSE)
+            _P(INITIATE_UPLOAD_RESPONSE)
+            _P(ABORT_TRANSFER_REQUEST)
+        }
+    }else if( fc == SDOrx)
+    {
+        switch(m->data[0] >> 5)
+        {
+            /* ccs: client command specifier */
+            _P(DOWNLOAD_SEGMENT_REQUEST)
+            _P(INITIATE_DOWNLOAD_REQUEST)
+            _P(INITIATE_UPLOAD_REQUEST)
+            _P(UPLOAD_SEGMENT_REQUEST)
+            _P(ABORT_TRANSFER_REQUEST)
+        }
+    }
+    MSG(" rtr:%d", m->rtr);
+    MSG(" len:%d", m->len);
+    for (i = 0 ; i < m->len ; i++)
+        MSG(" %02x", m->data[i]);
+    MSG("\n");
+}
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/canopen_can.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,55 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __can_h__
+#define __can_h__
+
+#include "applicfg.h"
+
+/*
+union SHORT_CAN {
+  struct { UNS8 b0,b1; } b;
+  UNS32 w;
+};
+*/
+/*
+typedef struct {
+  UNS32 w;
+} SHORT_CAN;
+*/
+
+/** 
+ * @brief The CAN message structure 
+ * @ingroup can
+ */
+typedef struct {
+  UNS16 cob_id;    /**< message's ID */
+  UNS8 rtr;        /**< remote transmission request. (0 if not rtr message, 1 if rtr message) */
+  UNS8 len;        /**< message's length (0 to 8) */
+  UNS8 data[8]; /**< message's datas */
+} Message;
+
+#define Message_Initializer {0,0,0,{0,0,0,0,0,0,0,0}}
+
+typedef UNS8 (*canSend_t)(Message *);
+
+#endif /* __can_h__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/canopen_timer.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,100 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef canopen_timer_h
+#define canopen_timer_h
+
+#include <timerscfg.h>
+#include <applicfg.h>
+
+#define TIMER_HANDLE INTEGER16
+
+#include "data.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* --------- types and constants definitions --------- */
+#define TIMER_FREE 0
+#define TIMER_ARMED 1
+#define TIMER_TRIG 2
+#define TIMER_TRIG_PERIOD 3
+
+#define TIMER_NONE -1
+
+typedef void (*TimerCallback_t)(CO_Data* d, UNS32 id);
+
+struct struct_s_timer_entry {
+    UNS8 state;
+    CO_Data* d;
+    TimerCallback_t callback; /* The callback func. */
+    UNS32 id; /* The callback func. */
+    TIMEVAL val;
+    TIMEVAL interval; /* Periodicity */
+};
+
+typedef struct struct_s_timer_entry s_timer_entry;
+
+/* ---------  prototypes --------- */
+/*#define SetAlarm(d, id, callback, value, period) printf("%s, %d, SetAlarm(%s, %s, %s, %s, %s)\n",__FILE__, __LINE__, #d, #id, #callback, #value, #period); _SetAlarm(d, id, callback, value, period)*/
+/**
+ * @ingroup timer
+ * @brief Set an alarm to execute a callback function when expired.
+ * @param *d Pointer to a CAN object data structure
+ * @param id The alarm Id
+ * @param callback A callback function
+ * @param value Call the callback function at current time + value
+ * @param period Call periodically the callback function
+ * @return handle The timer handle
+ */
+TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period);
+
+/**
+ * @ingroup timer
+ * @brief Delete an alarm before expiring.
+ * @param handle A timer handle
+ * @return The timer handle
+ */
+TIMER_HANDLE DelAlarm(TIMER_HANDLE handle);
+
+void TimeDispatch(void);
+
+/**
+ * @ingroup timer
+ * @brief Set a timerfor a given time.
+ * @param value The time value.
+ */
+void setTimer(TIMEVAL value);
+
+/**
+ * @ingroup timer
+ * @brief Get the time elapsed since latest timer occurence.
+ * @return time elapsed since latest timer occurence
+ */
+TIMEVAL getElapsedTime(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #define __timer_h__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/data.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,306 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __data_h__
+#define __data_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* declaration of CO_Data type let us include all necessary headers
+ struct struct_CO_Data can then be defined later
+ */
+typedef struct struct_CO_Data CO_Data;
+
+#include "applicfg.h"
+#include "def.h"
+#include "canopen_can.h"
+#include "objdictdef.h"
+#include "objacces.h"
+#include "sdo.h"
+#include "pdo.h"
+#include "states.h"
+#include "lifegrd.h"
+#include "sync.h"
+#include "nmtSlave.h"
+#include "nmtMaster.h"
+#include "emcy.h"
+#ifdef CO_ENABLE_LSS
+#include "lss.h"
+#endif
+
+/**
+ * @ingroup od
+ * @brief This structure contains all necessary informations to define a CANOpen node 
+ */
+struct struct_CO_Data {
+    /* Object dictionary */
+    UNS8 *bDeviceNodeId;
+    const indextable *objdict;
+    s_PDO_status *PDO_status;
+    const quick_index *firstIndex;
+    const quick_index *lastIndex;
+    const UNS16 *ObjdictSize;
+    const UNS8 *iam_a_slave;
+    valueRangeTest_t valueRangeTest;
+    
+    /* SDO */
+    s_transfer transfers[SDO_MAX_SIMULTANEOUS_TRANSFERTS];
+    /* s_sdo_parameter *sdo_parameters; */
+
+    /* State machine */
+    e_nodeState nodeState;
+    s_state_communication CurrentCommunicationState;
+    initialisation_t initialisation;
+    preOperational_t preOperational;
+    operational_t operational;
+    stopped_t stopped;
+    void (*NMT_Slave_Node_Reset_Callback)(CO_Data*);
+    void (*NMT_Slave_Communications_Reset_Callback)(CO_Data*);
+     
+    /* NMT-heartbeat */
+    UNS8 *ConsumerHeartbeatCount;
+    UNS32 *ConsumerHeartbeatEntries;
+    TIMER_HANDLE *ConsumerHeartBeatTimers;
+    UNS16 *ProducerHeartBeatTime;
+    TIMER_HANDLE ProducerHeartBeatTimer;
+    heartbeatError_t heartbeatError;
+    e_nodeState NMTable[NMT_MAX_NODE_ID]; 
+
+    /* SYNC */
+    TIMER_HANDLE syncTimer;
+    UNS32 *COB_ID_Sync;
+    UNS32 *Sync_Cycle_Period;
+    /*UNS32 *Sync_window_length;;*/
+    post_sync_t post_sync;
+    post_TPDO_t post_TPDO;
+    post_SlaveBootup_t post_SlaveBootup;
+      post_SlaveStateChange_t post_SlaveStateChange;
+    
+    /* General */
+    UNS8 toggle;
+    CAN_PORT canHandle;    
+    scanIndexOD_t scanIndexOD;
+    storeODSubIndex_t storeODSubIndex; 
+    
+    /* DCF concise */
+    const indextable* dcf_odentry;
+    UNS8* dcf_cursor;
+    UNS32 dcf_entries_count;
+    UNS8 dcf_request;
+    
+    /* EMCY */
+    e_errorState error_state;
+    UNS8 error_history_size;
+    UNS8* error_number;
+    UNS32* error_first_element;
+    UNS8* error_register;
+    UNS32* error_cobid;
+    s_errors error_data[EMCY_MAX_ERRORS];
+    post_emcy_t post_emcy;
+    
+#ifdef CO_ENABLE_LSS
+    /* LSS */
+    lss_transfer_t lss_transfer;
+    lss_StoreConfiguration_t lss_StoreConfiguration;
+#endif    
+};
+
+#define NMTable_Initializer Unknown_state,
+
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+#define s_transfer_Initializer {\
+        0,          /* nodeId */\
+        0,          /* wohami */\
+        SDO_RESET,  /* state */\
+        0,          /* toggle */\
+        0,          /* abortCode */\
+        0,          /* index */\
+        0,          /* subIndex */\
+        0,          /* count */\
+        0,          /* offset */\
+        {0},        /* data (static use, so that all the table is initialize at 0)*/\
+        NULL,       /* dynamicData */ \
+        0,          /* dynamicDataSize */ \
+        0,          /* dataType */\
+        -1,         /* timer */\
+        NULL        /* Callback */\
+      },
+#else
+#define s_transfer_Initializer {\
+        0,          /* nodeId */\
+        0,          /* wohami */\
+        SDO_RESET,  /* state */\
+        0,          /* toggle */\
+        0,          /* abortCode */\
+        0,          /* index */\
+        0,          /* subIndex */\
+        0,          /* count */\
+        0,          /* offset */\
+        {0},        /* data (static use, so that all the table is initialize at 0)*/\
+        0,          /* dataType */\
+        -1,         /* timer */\
+        NULL        /* Callback */\
+      },
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
+#define ERROR_DATA_INITIALIZER \
+    {\
+    0, /* errCode */\
+    0, /* errRegMask */\
+    0 /* active */\
+    },
+    
+#ifdef CO_ENABLE_LSS
+
+#ifdef CO_ENABLE_LSS_FS    
+#define lss_fs_Initializer \
+        ,0,                        /* IDNumber */\
+          128,                     /* BitChecked */\
+          0,                        /* LSSSub */\
+          0,                         /* LSSNext */\
+          0,                         /* LSSPos */\
+          LSS_FS_RESET,            /* FastScan_SM */\
+          -1,                        /* timerFS */\
+          {{0,0,0,0},{0,0,0,0}}   /* lss_fs_transfer */
+#else
+#define lss_fs_Initializer
+#endif        
+
+#define lss_Initializer {\
+        LSS_RESET,              /* state */\
+        0,                        /* command */\
+        LSS_WAITING_MODE,         /* mode */\
+        0,                        /* dat1 */\
+        0,                        /* dat2 */\
+        0,                      /* NodeID */\
+        0,                      /* addr_sel_match */\
+        0,                      /* addr_ident_match */\
+        "none",                 /* BaudRate */\
+        0,                      /* SwitchDelay */\
+        SDELAY_OFF,               /* SwitchDelayState */\
+        NULL,                    /* canHandle_t */\
+        -1,                        /* TimerMSG */\
+        -1,                      /* TimerSDELAY */\
+        NULL,                    /* Callback */\
+        0                        /* LSSanswer */\
+        lss_fs_Initializer        /*FastScan service initialization */\
+      },\
+      NULL     /* _lss_StoreConfiguration*/
+#else
+#define lss_Initializer
+#endif
+
+
+/* A macro to initialize the data in client app.*/
+/* CO_Data structure */
+#define CANOPEN_NODE_DATA_INITIALIZER(NODE_PREFIX) {\
+    /* Object dictionary*/\
+    & NODE_PREFIX ## _bDeviceNodeId,     /* bDeviceNodeId */\
+    NODE_PREFIX ## _objdict,             /* objdict  */\
+    NODE_PREFIX ## _PDO_status,          /* PDO_status */\
+    & NODE_PREFIX ## _firstIndex,        /* firstIndex */\
+    & NODE_PREFIX ## _lastIndex,         /* lastIndex */\
+    & NODE_PREFIX ## _ObjdictSize,       /* ObjdictSize */\
+    & NODE_PREFIX ## _iam_a_slave,       /* iam_a_slave */\
+    NODE_PREFIX ## _valueRangeTest,      /* valueRangeTest */\
+    \
+    /* SDO, structure s_transfer */\
+    {\
+          REPEAT_SDO_MAX_SIMULTANEOUS_TRANSFERTS_TIMES(s_transfer_Initializer)\
+    },\
+    \
+    /* State machine*/\
+    Unknown_state,      /* nodeState */\
+    /* structure s_state_communication */\
+    {\
+        0,          /* csBoot_Up */\
+        0,          /* csSDO */\
+        0,          /* csEmergency */\
+        0,          /* csSYNC */\
+        0,          /* csHeartbeat */\
+        0,           /* csPDO */\
+        0           /* csLSS */\
+    },\
+    _initialisation,     /* initialisation */\
+    _preOperational,     /* preOperational */\
+    _operational,        /* operational */\
+    _stopped,            /* stopped */\
+    NULL,                /* NMT node reset callback */\
+    NULL,                /* NMT communications reset callback */\
+    \
+    /* NMT-heartbeat */\
+    & NODE_PREFIX ## _highestSubIndex_obj1016, /* ConsumerHeartbeatCount */\
+    NODE_PREFIX ## _obj1016,                   /* ConsumerHeartbeatEntries */\
+    NODE_PREFIX ## _heartBeatTimers,           /* ConsumerHeartBeatTimers  */\
+    & NODE_PREFIX ## _obj1017,                 /* ProducerHeartBeatTime */\
+    TIMER_NONE,                                /* ProducerHeartBeatTimer */\
+    _heartbeatError,           /* heartbeatError */\
+    \
+    {REPEAT_NMT_MAX_NODE_ID_TIMES(NMTable_Initializer)},\
+                                                   /* is  well initialized at "Unknown_state". Is it ok ? (FD)*/\
+    \
+    /* SYNC */\
+    TIMER_NONE,                                /* syncTimer */\
+    & NODE_PREFIX ## _obj1005,                 /* COB_ID_Sync */\
+    & NODE_PREFIX ## _obj1006,                 /* Sync_Cycle_Period */\
+    /*& NODE_PREFIX ## _obj1007, */            /* Sync_window_length */\
+    _post_sync,                 /* post_sync */\
+    _post_TPDO,                 /* post_TPDO */\
+    _post_SlaveBootup,            /* post_SlaveBootup */\
+  _post_SlaveStateChange,            /* post_SlaveStateChange */\
+    \
+    /* General */\
+    0,                                         /* toggle */\
+    NULL,                   /* canSend */\
+    NODE_PREFIX ## _scanIndexOD,                /* scanIndexOD */\
+    _storeODSubIndex,                /* storeODSubIndex */\
+    /* DCF concise */\
+    NULL,       /*dcf_odentry*/\
+    NULL,        /*dcf_cursor*/\
+    1,        /*dcf_entries_count*/\
+    0,        /* dcf_request*/\
+    \
+    /* EMCY */\
+    Error_free,                      /* error_state */\
+    sizeof(NODE_PREFIX ## _obj1003) / sizeof(NODE_PREFIX ## _obj1003[0]),      /* error_history_size */\
+    & NODE_PREFIX ## _highestSubIndex_obj1003,    /* error_number */\
+    & NODE_PREFIX ## _obj1003[0],    /* error_first_element */\
+    & NODE_PREFIX ## _obj1001,       /* error_register */\
+    & NODE_PREFIX ## _obj1014,       /* error_cobid */\
+    /* error_data: structure s_errors */\
+    {\
+    REPEAT_EMCY_MAX_ERRORS_TIMES(ERROR_DATA_INITIALIZER)\
+    },\
+    _post_emcy,              /* post_emcy */\
+    /* LSS */\
+    lss_Initializer\
+}
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* __data_h__ */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/dcf.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,29 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** 
+ * @brief Send the consise dcf to node corresping to nodeId
+ * @param *d Pointer on a CAN object data structure
+ * @param nodeId Id of the slave node
+ * @return
+ */
+UNS8 send_consise_dcf(CO_Data* d, UNS8 nodeId);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/def.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,151 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifndef __def_h__
+#define __def_h__
+
+#include "config.h"
+
+/** definitions used for object dictionary access. ie SDO Abort codes . (See DS 301 v.4.02 p.48)
+ */
+#define OD_SUCCESSFUL 	             0x00000000
+#define OD_READ_NOT_ALLOWED          0x06010001
+#define OD_WRITE_NOT_ALLOWED         0x06010002
+#define OD_NO_SUCH_OBJECT            0x06020000
+#define OD_NOT_MAPPABLE              0x06040041
+#define OD_LENGTH_DATA_INVALID       0x06070010
+#define OD_NO_SUCH_SUBINDEX 	     0x06090011
+#define OD_VALUE_RANGE_EXCEEDED      0x06090030 /* Value range test result */
+#define OD_VALUE_TOO_LOW             0x06090031 /* Value range test result */
+#define OD_VALUE_TOO_HIGH            0x06090032 /* Value range test result */
+/* Others SDO abort codes 
+ */
+#define SDOABT_TOGGLE_NOT_ALTERNED   0x05030000
+#define SDOABT_TIMED_OUT             0x05040000
+#define SDOABT_OUT_OF_MEMORY         0x05040005 /* Size data exceed SDO_MAX_LENGTH_TRANSFERT */
+#define SDOABT_GENERAL_ERROR         0x08000000 /* Error size of SDO message */
+#define SDOABT_LOCAL_CTRL_ERROR      0x08000021 
+
+/******************** CONSTANTS ****************/
+
+/** Constantes which permit to define if a PDO frame
+   is a request one or a data one
+*/
+/* Should not be modified */
+#define REQUEST 1
+#define NOT_A_REQUEST 0
+
+/* Misc constants */
+/* -------------- */
+/* Should not be modified */
+#define Rx 0
+#define Tx 1
+#ifndef TRUE
+#define TRUE  1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+    
+/** Status of the SDO transmission
+ */
+#define SDO_RESET                0x0      /* Transmission not started. Init state. */
+#define SDO_FINISHED             0x1      /* data are available */                          
+#define	SDO_ABORTED_RCV          0x80     /* Received an abort message. Data not available */
+#define	SDO_ABORTED_INTERNAL     0x85     /* Aborted but not because of an abort message. */
+#define	SDO_DOWNLOAD_IN_PROGRESS 0x2 
+#define	SDO_UPLOAD_IN_PROGRESS   0x3   
+
+/* Status of the node during the SDO transfert : */
+#define SDO_SERVER  0x1
+#define SDO_CLIENT  0x2
+#define SDO_UNKNOWN 0x3             
+
+/* SDOrx ccs: client command specifier */
+#define DOWNLOAD_SEGMENT_REQUEST     0
+#define INITIATE_DOWNLOAD_REQUEST    1
+#define INITIATE_UPLOAD_REQUEST      2
+#define UPLOAD_SEGMENT_REQUEST       3
+#define ABORT_TRANSFER_REQUEST       4
+
+/* SDOtx scs: server command specifier */
+#define UPLOAD_SEGMENT_RESPONSE      0
+#define DOWNLOAD_SEGMENT_RESPONSE    1
+#define INITIATE_DOWNLOAD_RESPONSE   3
+#define INITIATE_UPLOAD_RESPONSE     2
+#define ABORT_TRANSFER_REQUEST       4
+
+
+/*  Function Codes 
+   ---------------
+  defined in the canopen DS301 
+*/
+#define NMT	   0x0
+#define SYNC       0x1
+#define TIME_STAMP 0x2
+#define PDO1tx     0x3
+#define PDO1rx     0x4
+#define PDO2tx     0x5
+#define PDO2rx     0x6
+#define PDO3tx     0x7
+#define PDO3rx     0x8
+#define PDO4tx     0x9
+#define PDO4rx     0xA
+#define SDOtx      0xB
+#define SDOrx      0xC
+#define NODE_GUARD 0xE
+#define LSS 	   0xF
+
+/* NMT Command Specifier, sent by master to change a slave state */
+/* ------------------------------------------------------------- */
+/* Should not be modified */
+#define NMT_Start_Node              0x01
+#define NMT_Stop_Node               0x02
+#define NMT_Enter_PreOperational    0x80
+#define NMT_Reset_Node              0x81
+#define NMT_Reset_Comunication      0x82
+
+/** Status of the LSS transmission
+ */
+#define LSS_RESET                0x0      /* Transmission not started. Init state. */
+#define LSS_FINISHED             0x1      /* data are available */                          
+#define	LSS_ABORTED_INTERNAL     0x2     /* Aborted but not because of an abort message. */
+#define	LSS_TRANS_IN_PROGRESS 	 0x3    
+
+/* constantes used in the different state machines */
+/* ----------------------------------------------- */
+/* Must not be modified */
+#define state1  0x01
+#define state2  0x02
+#define state3  0x03
+#define state4  0x04
+#define state5  0x05
+#define state6  0x06
+#define state7  0x07
+#define state8  0x08
+#define state9  0x09
+#define state10 0x0A
+#define state11 0x0B
+
+#endif /* __def_h__ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/emcy.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,108 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*!
+** @file   emcy.h
+** @author Luis Jimenez
+** @date   Wed Sep 26 2007
+**
+** @brief Declarations of the functions that manage EMCY (emergency) messages
+**
+**
+*/
+ 
+/** @defgroup emcyo Emergency Object
+ *  Emergency Object is used to communicate device and application failures.
+ *  @ingroup comobj
+ */
+					 
+#ifndef __emcy_h__
+#define __emcy_h__
+
+
+#include <applicfg.h>
+
+/* The error states 
+ * ----------------- */
+typedef enum enum_errorState {
+  Error_free		= 0x00, 
+  Error_occurred	= 0x01
+} e_errorState;
+
+typedef struct {
+	UNS16 errCode;
+	UNS8 errRegMask;
+	UNS8 active;
+} s_errors;
+
+#include "data.h"
+
+
+typedef void (*post_emcy_t)(CO_Data* d, UNS8 nodeID, UNS16 errCode, UNS8 errReg);
+void _post_emcy(CO_Data* d, UNS8 nodeID, UNS16 errCode, UNS8 errReg);
+
+/*************************************************************************
+ * Functions
+ *************************************************************************/
+
+/** 
+ * @ingroup emcy
+ * @brief Sets a new error with code errCode. Also sets corresponding bits in Error register (1001h)
+ * @param *d Pointer on a CAN object data structure
+ * @param errCode The error code
+ * @param errRegMask
+ * @param addInfo
+ * @return
+ */
+UNS8 EMCY_setError(CO_Data* d, UNS16 errCode, UNS8 errRegMask, UNS16 addInfo);
+
+/**
+ * @ingroup emcy 
+ * @brief Indicates it has recovered from error errCode. Also clears corresponding bits in Error register (1001h)
+ * @param *d Pointer on a CAN object data structure
+ * @param errCode The error code
+ */
+void EMCY_errorRecovered(CO_Data* d, UNS16 errCode);
+
+/**
+ * @ingroup emcy 
+ * @brief Start EMCY consumer and producer
+ * @param *d Pointer on a CAN object data structure
+ */
+void emergencyInit(CO_Data* d);
+
+/** 
+ * @ingroup emcy
+ * @brief Stop EMCY producer and consumer
+ * @param *d Pointer on a CAN object data structure 
+ */
+void emergencyStop(CO_Data* d);
+
+/** 
+ * @ingroup emcy
+ * @brief This function is responsible to process an EMCY canopen-message
+ * @param *d Pointer on a CAN object data structure 
+ * @param *m Pointer on the CAN-message which has to be analysed.
+ */
+void proceedEMCY(CO_Data* d, Message* m);
+
+#endif /*__emcy_h__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/lifegrd.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,87 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @defgroup heartbeato Heartbeat Object
+ *  The heartbeat mechanism for a device is established through cyclically transmitting a message by a
+ *    heartbeat producer. One or more devices in the network are aware of this heartbeat message. If the
+ *    heartbeat cycle fails for the heartbeat producer the local application on the heartbeat consumer will be
+ *    informed about that event.
+ *  @ingroup comobj
+ */
+                     
+#ifndef __lifegrd_h__
+#define __lifegrd_h__
+
+
+#include <applicfg.h>
+
+typedef void (*heartbeatError_t)(CO_Data*, UNS8);
+void _heartbeatError(CO_Data* d, UNS8 heartbeatID);
+
+typedef void (*post_SlaveBootup_t)(CO_Data*, UNS8);
+void _post_SlaveBootup(CO_Data* d, UNS8 SlaveID);
+
+typedef void (*post_SlaveStateChange_t)(CO_Data*, UNS8, e_nodeState);
+void _post_SlaveStateChange(CO_Data* d, UNS8 nodeId, e_nodeState newNodeState);
+
+#include "data.h"
+
+/*************************************************************************
+ * Functions
+ *************************************************************************/
+
+/** 
+ * @ingroup statemachine
+ * @brief To read the state of a node
+ * This can be used by the master after having sent a life guard request,
+ * of by any node if it is waiting for heartbeat.
+ * @param *d Pointer on a CAN object data structure
+ * @param nodeId Id of a node
+ * @return e_nodeState State of the node corresponding to the nodeId
+ */
+e_nodeState getNodeState (CO_Data* d, UNS8 nodeId);
+
+/** 
+ * @brief Start heartbeat consumer and producer
+ * with respect to 0x1016 and 0x1017
+ * object dictionary entries
+ * @param *d Pointer on a CAN object data structure
+ */
+void heartbeatInit(CO_Data* d);
+
+/** 
+ * @brief Stop heartbeat consumer and producer
+ * @param *d Pointer on a CAN object data structure
+ */
+void heartbeatStop(CO_Data* d);
+
+/** 
+ * @brief This function is responsible to process a canopen-message which seams to be an NMT Error Control
+ * Messages. At them moment we assume that every NMT error control message
+ * is a heartbeat message.
+ * If a BootUp message is detected, it will return the nodeId of the Slave who booted up
+ * @param *d Pointer on a CAN object data structure 
+ * @param *m Pointer on the CAN-message which has to be analysed.
+ */
+void proceedNODE_GUARD (CO_Data* d, Message* m);
+
+#endif /*__lifegrd_h__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/lss.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,244 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Jorge Berzosa
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @defgroup lss Layer Setting Services Object
+ * @brief LSS offers the possibility to inquire and change the settings of certain parameters of the local layers on
+ * a CANopen module with LSS Slave capabilities by a CANopen module with LSS Master capabilities via the
+ * CAN Network.
+ * The following parameters can be inquired and/or changed by the use of LSS:
+ *               - Node-ID of the CANopen Slave
+ *               - Bit timing parameters of the physical layer (baud rate)
+ *               - LSS address (/2/ Identity Object, Index 1018H)
+ *  @ingroup comobj
+ */
+                     
+#ifndef __LSS_h__
+#define __LSS_h__
+
+#define SLSS_ADRESS    0x7E4
+#define MLSS_ADRESS    0x7E5
+
+#define SDELAY_OFF        0
+#define SDELAY_FIRST     1
+#define SDELAY_SECOND     2
+
+#define LSS_WAITING_MODE 0
+#define LSS_CONFIGURATION_MODE 1
+
+/* Switch mode services */
+#define LSS_SM_GLOBAL                  4
+#define LSS_SM_SELECTIVE_VENDOR     64
+#define LSS_SM_SELECTIVE_PRODUCT     65
+#define LSS_SM_SELECTIVE_REVISION     66
+#define LSS_SM_SELECTIVE_SERIAL     67
+#define LSS_SM_SELECTIVE_RESP         68
+/* Configuration services */
+#define LSS_CONF_NODE_ID             17
+#define LSS_CONF_BIT_TIMING         19
+#define LSS_CONF_ACT_BIT_TIMING     21
+#define LSS_CONF_STORE                 23
+/* Inquire services */
+#define LSS_INQ_VENDOR_ID         90
+#define LSS_INQ_PRODUCT_CODE     91
+#define LSS_INQ_REV_NUMBER         92
+#define LSS_INQ_SERIAL_NUMBER     93
+#define LSS_INQ_NODE_ID         94
+/* Identification services */
+#define LSS_IDENT_REMOTE_VENDOR         70
+#define LSS_IDENT_REMOTE_PRODUCT         71
+#define LSS_IDENT_REMOTE_REV_LOW         72
+#define LSS_IDENT_REMOTE_REV_HIGH         73
+#define LSS_IDENT_REMOTE_SERIAL_LOW     74
+#define LSS_IDENT_REMOTE_SERIAL_HIGH     75
+#define LSS_IDENT_REMOTE_NON_CONF         76
+#define LSS_IDENT_SLAVE                 79
+#define LSS_IDENT_NON_CONF_SLAVE         80
+#define LSS_IDENT_FASTSCAN                81
+
+/*FastScan State Machine*/
+#define LSS_FS_RESET    0
+#define LSS_FS_PROCESSING 1
+#define LSS_FS_CONFIRMATION 2
+
+
+typedef void (*LSSCallback_t)(CO_Data* d, UNS8 command); 
+
+typedef void (*lss_StoreConfiguration_t)(CO_Data* d,UNS8*,UNS8*);
+//void _lss_StoreConfiguration(UNS8 *error, UNS8 *spec_error);
+
+//typedef void (*lss_ChangeBaudRate_t)(CO_Data* d,char*);
+//void _lss_ChangeBaudRate(char *BaudRate);
+
+
+struct struct_lss_transfer;
+
+//#include "timer.h"
+
+#ifdef CO_ENABLE_LSS_FS
+struct struct_lss_fs_transfer {
+    UNS32 FS_LSS_ID[4];
+    UNS8 FS_BitChecked[4];
+};
+
+typedef struct struct_lss_fs_transfer lss_fs_transfer_t;
+#endif
+
+/* The Transfer structure
+* Used to store the different fields of the internal state of the LSS  
+*/
+
+struct struct_lss_transfer {
+  UNS8          state;      /* state of the transmission : Takes the values LSS_... */
+  UNS8             command;     /* the LSS command of the transmision */
+  UNS8            mode;       /* LSS mode */
+  
+  UNS32         dat1;        /* the data from the last msg received */
+  UNS8            dat2; 
+  
+  UNS8 nodeID;              /* the new nodeid stored to update the nodeid when switching to LSS operational*/
+  UNS8 addr_sel_match;        /* the matching mask for the LSS Switch Mode Selective service */
+  UNS8 addr_ident_match;    /* the matching mask for the LSS Identify Remote Slaves service*/
+
+  char *baudRate;           /* the new baudrate stored to update the node baudrate when a Activate Bit 
+                               * Timing Parameters is received*/
+  UNS16 switchDelay;        /* the period of the two delay */
+  UNS8  switchDelayState;   /* the state machine for the switchDelay */
+  CAN_PORT canHandle_t;
+    
+                              /* Time counters to implement a timeout in milliseconds.*/
+  TIMER_HANDLE timerMSG;      /* timerMSG is automatically incremented whenever 
+                              * the lss state is in LSS_TRANS_IN_PROGRESS, and reseted to 0 
+                              * when the response LSS have been received.
+                              */
+                             
+  TIMER_HANDLE timerSDELAY;      /* timerSDELAY is automatically incremented whenever 
+                              * the lss switchDelayState is in SDELAY_FIRST or SDELAY_SECOND, and reseted to 0 
+                              * when the two periods have been expired.
+                              */
+                              
+  LSSCallback_t Callback;   /* The user callback func to be called at LSS transaction end */
+  
+  UNS8 LSSanswer;            /* stores if a message has been received during a timer period */
+
+#ifdef CO_ENABLE_LSS_FS 
+  UNS32 IDNumber;            /* in the master, the LSS address parameter which it currently tries to identify.
+                               * in the slave, the LSS address parameter which is being checked (LSS-ID[sub]). */
+  UNS8 BitChecked;            /* bits of the current IDNumber that are currently checked */
+  UNS8 LSSSub;                /* which part of the LSS-ID is currently checked in IDNumber */
+  UNS8 LSSNext;                /* which LSSSub value will be used in the next request */
+  UNS8 LSSPos;                /* in the slave, which part of the LSS-ID is currently processed*/
+  UNS8 FastScan_SM;            /* the state machine for the FastScan protocol */
+  TIMER_HANDLE timerFS;        /* timerFS is automatically incremented when the FastScan service
+                               * has been requested and reseted to 0 when the protocol ends.
+                              */
+#ifdef CO_ENABLE_LSS_FS
+  lss_fs_transfer_t lss_fs_transfer;
+#endif
+  
+#endif                           
+};
+
+#ifdef CO_ENABLE_LSS
+typedef struct struct_lss_transfer lss_transfer_t;
+#else
+typedef UNS8 lss_transfer_t;
+#endif
+  
+
+
+void startLSS(CO_Data* d);
+void stopLSS(CO_Data* d);
+
+
+/** transmit a LSS message 
+ * command is the LSS command specifier
+ * dat1 and dat2 are pointers to optional data (depend on command)
+ * return sendLSSMessage(d,command,dat1,dat2)
+ */
+UNS8 sendLSS (CO_Data* d, UNS8 command,void *dat1, void *dat2);
+
+/** transmit a LSS message on CAN bus
+ * comamnd is the LSS command specifier
+ * bus_id is MLSS_ADRESS or SLSS_ADRESS depending in d->iam_a_slave. 
+ * dat1 and dat2 are pointers to optional data (depend on command).
+ * return canSend(bus_id,&m)
+ */
+ 
+UNS8 sendLSSMessage(CO_Data* d, UNS8 command,  void *dat1, void *dat2);
+
+/** This function is called when the node is receiving a Master LSS message (cob-id = 0x7E5).
+ *  - Check if there is a callback which will take care of the response. If not return 0 but does nothing.
+ *  - Stops the timer so the alarm wont raise an error.
+ *  - return 0 if OK
+ */
+UNS8 proceedLSS_Master (CO_Data* d, Message* m );
+
+/** This function is called when the node is receiving a Slave LSS message (cob-id = 0x7E4).
+ *  - Call the callback function or send the response message depending on the LSS comand within m.
+ *  - return 0 if OK
+ */
+UNS8 proceedLSS_Slave (CO_Data* d, Message* m );
+
+/** Used by the Master application to send a LSS command, WITHOUT response, to the slave. 
+ * command: the LSS command. LSS_...
+ * dat1 and dat2: pointers to optional data (depend on command).
+ * return sendLSS(d,command,dat1,dat2)
+ */
+//UNS8 configNetworkNode(CO_Data* d, UNS8 command, void *dat1, void* dat2);
+
+/** 
+ * @ingroup lss
+ * @brief Used by the Master application to send a LSS command, WITH response, to the slave. 
+ * @param *d Pointer on a CAN object data structure
+ * @param command
+ * @param *dat1
+ * @param *dat2
+ * @param Callback The function Callback, which must be defined in the user code, is called at the
+ * end of the exchange (on succes or abort) and can be NULL.
+ * @return sendLSS(d,command,dat1,dat2)
+ * The LSS_MSG_TIMER timer is started to control the timeout
+ */
+UNS8 configNetworkNode (CO_Data* d, UNS8 command, void *dat1, void* dat2, LSSCallback_t Callback);
+
+/**
+ * @ingroup lss 
+ * @brief Use this function after a configNetworkNode or configNetworkNodeCallBack to get the result.
+ * @param *d Pointer on a CAN object data structure
+ * @param command The LSS command (unused).
+ * @param *dat1
+ * @param *dat2
+ * @return : 
+ *          - LSS_RESET                // Transmission not started. Init state.
+ *          - LSS_FINISHED            // data are available                           
+ *          - LSS_ABORTED_INTERNAL    // Aborted but not because of an abort message. 
+ *          - LSS_TRANS_IN_PROGRESS    // Data not yet available
+ * @code
+ * example:
+ * UNS32 dat1;
+ * UNS8 dat2;
+ * res=configNetworkNodeCallBack(&_Data,LSS_INQ_NODE_ID,0,0,NULL); // inquire the nodeID
+ * while (getConfigResultNetworkNode (&_Data, LSS_INQ_NODE_ID, &dat1, &dat2) != LSS_TRANS_IN_PROGRESS);
+ * @endcode
+*/
+UNS8 getConfigResultNetworkNode (CO_Data* d, UNS8 command, UNS32* dat1, UNS8* dat2);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/mbed/applicfg.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,94 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+AVR Port: Andreas GLAUSER and Peter CHRISTEN
+mbed port: sgrove
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __APPLICFG__
+#define __APPLICFG__
+
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+
+// Integers
+#define INTEGER8    signed char
+#define INTEGER16   signed short int
+#define INTEGER24
+#define INTEGER32   signed int
+#define INTEGER40
+#define INTEGER48
+#define INTEGER56
+#define INTEGER64   signed __int64
+
+// Unsigned integers
+#define UNS8        unsigned char
+#define UNS16       unsigned short int
+#define UNS32     	unsigned int
+/*
+#define UNS24
+#define UNS40
+#define UNS48
+#define UNS56
+#define UNS64
+*/ 
+
+
+// Reals
+#define REAL32  	float
+#define REAL64    	double
+
+#include "canopen_can.h"
+
+// MSG functions
+// not finished, the strings have to be placed to the flash and printed out 
+// using the printf_P function
+/// Definition of MSG_ERR
+// ---------------------
+#ifdef DEBUG_ERR_CONSOLE_ON
+#define MSG_ERR(num, str, val)	\
+          printf(num, ' ');   	\
+          printf(str);       	\
+          printf(val);       	\
+          printf('\n');
+#else
+#    define MSG_ERR(num, str, val)
+#endif
+
+/// Definition of MSG_WAR
+// ---------------------
+#ifdef DEBUG_WAR_CONSOLE_ON
+#define MSG_WAR(num, str, val)	\
+          printf(num, ' ');    	\
+          printf(str);        	\
+          printf(val);        	\
+          printf('\n');
+#else
+#    define MSG_WAR(num, str, val)
+#endif
+
+typedef void* CAN_HANDLE;
+
+typedef void* CAN_PORT;
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/mbed/can_mbed.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,48 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+mbed Port: sgrove
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __CAN_MBED__
+#define __CAN_MBED__
+
+#include "config.h"
+#include "mbed.h"
+
+// Canfestivals includes
+#include "canopen_can.h"
+
+/************************* To be called by user app ***************************/
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+unsigned char canInit(unsigned int bitrate);
+unsigned char canSend(CAN_PORT notused, Message *m);
+unsigned char canReceive(Message *m);
+unsigned char canChangeBaudRate_driver( CAN_HANDLE fd, char* baud);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/mbed/canfestival.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,45 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+mbed port: sgrove
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifndef __CAN_CANFESTIVAL__
+#define __CAN_CANFESTIVAL__
+
+#include "applicfg.h"
+#include "data.h"
+
+/************************* To be called by user app ***************************/
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+extern void initTimer(void);
+extern UNS8 canSend(CAN_PORT notused, Message *m);
+extern UNS8 canChangeBaudRate(CAN_PORT port, char* baud);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/mbed/config.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,52 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+mbed port: sgrove
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+#define CAN_BAUDRATE    125
+
+// Needed defines by Canfestival lib
+#define MAX_CAN_BUS_ID 1
+#define SDO_MAX_LENGTH_TRANSFERT 32
+#define SDO_MAX_SIMULTANEOUS_TRANSFERTS 1
+#define NMT_MAX_NODE_ID 128
+#define SDO_TIMEOUT_MS 3000U
+#define MAX_NB_TIMER 8
+
+// CANOPEN_BIG_ENDIAN is not defined
+#define CANOPEN_LITTLE_ENDIAN 1
+
+#define US_TO_TIMEVAL_FACTOR 8
+
+#define REPEAT_SDO_MAX_SIMULTANEOUS_TRANSFERTS_TIMES(repeat)\
+repeat
+#define REPEAT_NMT_MAX_NODE_ID_TIMES(repeat)\
+repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat
+
+#define EMCY_MAX_ERRORS 8
+#define REPEAT_EMCY_MAX_ERRORS_TIMES(repeat)\
+repeat repeat repeat repeat repeat repeat repeat repeat
+
+
+#endif /* _CONFIG_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/mbed/timerscfg.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,42 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+mbed port: sgrove
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __TIMERSCFG_H__
+#define __TIMERSCFG_H__
+
+// Whatever your microcontroller, the timer wont work if
+// TIMEVAL is not at least on 32 bits
+#define TIMEVAL UNS32
+
+// The max count for the freerunning counter register
+#define TIMEVAL_MAX 0xFFFFFFFF
+
+// The timer is incrementing every 4 us.
+//#define MS_TO_TIMEVAL(ms) (ms * 250)
+//#define US_TO_TIMEVAL(us) (us>>2)
+
+// The timer is incrementing every 8 us.
+#define MS_TO_TIMEVAL(ms) ((ms) * 125)
+#define US_TO_TIMEVAL(us) ((us)>>3)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/nmtMaster.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,93 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @defgroup networkmanagement Network Management
+ *  @ingroup userapi
+ */
+/** @defgroup nmtmaster NMT Master
+ *  @brief NMT master provides mechanisms that control and monitor the state of nodes and their behavior in the network.
+ *  @ingroup networkmanagement
+ */
+ 
+#ifndef __nmtMaster_h__
+#define __nmtMaster_h__
+
+#include "data.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/** 
+ * @ingroup nmtmaster
+ * @brief Transmit a NMT message on the network to the slave whose nodeId is node ID.
+ * 
+ * @param *d Pointer to a CAN object data structure
+ * @param nodeId Id of the slave node
+ * @param cs The order of state changement \n\n
+ * 
+ * Allowed states :
+ *  - cs =  NMT_Start_Node               // Put the node in operational mode             
+ *  - cs =    NMT_Stop_Node                 // Put the node in stopped mode
+ *  - cs =    NMT_Enter_PreOperational     // Put the node in pre_operational mode  
+ *  - cs =  NMT_Reset_Node                 // Put the node in initialization mode 
+ *  - cs =  NMT_Reset_Comunication         // Put the node in initialization mode
+ *  
+ * The mode is changed according to the slave state machine mode :
+ *  - initialisation  ---> pre-operational (Automatic transition)
+ *  - pre-operational <--> operational
+ *  - pre-operational <--> stopped
+ *  - pre-operational, operational, stopped -> initialisation
+ * \n\n
+ * @return errorcode
+ *                   - 0 if the NMT message was send
+ *                   - 1 if an error occurs 
+ */
+UNS8 masterSendNMTstateChange (CO_Data* d, UNS8 nodeId, UNS8 cs);
+
+/**
+ * @ingroup nmtmaster 
+ * @brief Transmit a NodeGuard message on the network to the slave whose nodeId is node ID
+ * 
+ * @param *d Pointer to a CAN object data structure
+ * @param nodeId Id of the slave node
+ * @return
+ *         - 0 is returned if the NodeGuard message was send.
+ *         - 1 is returned if an error occurs.
+ */
+UNS8 masterSendNMTnodeguard (CO_Data* d, UNS8 nodeId);
+
+/** 
+ * @ingroup nmtmaster
+ * @brief Ask the state of the slave node whose nodeId is node Id.
+ * 
+ * To ask states of all nodes on the network (NMT broadcast), nodeId must be equal to 0
+ * @param *d Pointer to a CAN object data structure
+ * @param nodeId Id of the slave node
+ */
+UNS8 masterRequestNodeState (CO_Data* d, UNS8 nodeId);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __nmtMaster_h__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/nmtSlave.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,60 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @defgroup nmtslave NMT Slave
+ *  @brief The NMT Slave methods are called automatically when a NMT message from Master are received. 
+ *  @ingroup networkmanagement
+ */
+ 
+#ifndef __nmtSlave_h__
+#define __nmtSlave_h__
+
+#include <applicfg.h>
+#include "data.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/** 
+ * @brief Threat the reception of a NMT message from the master.
+ * @param *d Pointer to the CAN data structure
+ * @param *m Pointer to the message received
+ * @return 
+ *  -  0 if OK 
+ *  - -1 if the slave is not allowed, by its state, to receive the message
+ */
+void proceedNMTstateChange (CO_Data* d, Message * m);
+
+/** 
+ * @brief Transmit the boot-Up frame when the slave is moving from initialization
+ * state to pre_operational state.
+ * @param *d Pointer on the CAN data structure
+ * @return canSend(bus_id,&m)
+ */
+UNS8 slaveSendBootUp (CO_Data* d);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __nmtSlave_h__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/objacces.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,287 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @file
+ *  @brief Responsible for accessing the object dictionary.
+ *
+ *  This file contains functions for accessing the object dictionary and
+ *  variables that are contained by the object dictionary.
+ *  Accessing the object dictionary contains setting local variables
+ *  as PDOs and accessing (read/write) all entries of the object dictionary
+ *  @warning Only the basic entries of an object dictionary are included
+ *           at the moment.
+ */
+
+/** @defgroup od Object Dictionary Management
+ *  @brief The Object Dictionary is the heart of each CANopen device containing all communication and application objects.
+ *  @ingroup userapi
+ */
+ 
+#ifndef __objacces_h__
+#define __objacces_h__
+
+#include <applicfg.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef UNS32 (*valueRangeTest_t)(UNS8 typeValue, void *Value);
+typedef void (* storeODSubIndex_t)(CO_Data* d, UNS16 wIndex, UNS8 bSubindex);
+void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex);
+
+/**
+ * @brief Print MSG_WAR (s) if error to the access to the object dictionary occurs.
+ * 
+ * You must uncomment the lines in the file objaccess.c :\n
+ * //#define DEBUG_CAN\n
+ * //#define DEBUG_WAR_CONSOLE_ON\n
+ * //#define DEBUG_ERR_CONSOLE_ON\n\n
+ * Beware that sometimes, we force the sizeDataDict or sizeDataGiven to 0, when we wants to use
+ * this function but we do not have the access to the right value. One example is
+ * getSDOerror(). So do not take attention to these variables if they are null.
+ * @param index
+ * @param subIndex
+ * @param sizeDataDict Size of the data defined in the dictionary
+ * @param sizeDataGiven Size data given by the user.
+ * @param code error code to print. (SDO abort code. See file def.h)
+ * @return
+ */ 
+UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex, 
+			   UNS32 sizeDataDict, UNS32 sizeDataGiven, UNS32 code);
+
+
+/* _getODentry() Reads an entry from the object dictionary.\n
+ * 
+ *    use getODentry() macro to read from object and endianize
+ *    use readLocalDict() macro to read from object and not endianize   
+ *
+ * @code
+ * // Example usage:
+ * UNS8  *pbData;
+ * UNS8 length;
+ * UNS32 returnValue;
+ *
+ * returnValue = getODentry( (UNS16)0x100B, (UNS8)1, 
+ * (void * *)&pbData, (UNS8 *)&length );
+ * if( returnValue != SUCCESSFUL )
+ * {
+ *     // error handling
+ * }
+ * @endcode 
+ * @param *d Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to read
+ *               an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pDestData Pointer to the pointer which points to the variable where
+ *                   the value of this object dictionary entry should be copied
+ * @param pExpectedSize This function writes the size of the copied value (in Byte)
+ *                      into this variable.
+ * @param *pDataType Pointer to the type of the data. See objdictdef.h
+ * @param CheckAccess if other than 0, do not read if the data is Write Only
+ *                    [Not used today. Put always 0].
+ * @param Endianize  When not 0, data is endianized into network byte order
+ *                   when 0, data is not endianized and copied in machine native
+ *                   endianness 
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+UNS32 _getODentry( CO_Data* d,
+                   UNS16 wIndex,
+                   UNS8 bSubindex,
+                   void * pDestData,
+                   UNS32 * pExpectedSize,
+                   UNS8 * pDataType,
+                   UNS8 checkAccess,
+                   UNS8 endianize);
+
+/** 
+ * @ingroup od
+ * @brief getODentry() to read from object and endianize
+ * @param OD Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to read
+ *                an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pDestData Pointer to the pointer which points to the variable where
+ *                   the value of this object dictionary entry should be copied
+ * @param pExpectedSize This function writes the size of the copied value (in Byte)
+ *                      into this variable.
+ * @param *pDataType Pointer to the type of the data. See objdictdef.h
+ * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
+ * @param endianize  Set to 1 : endianized into network byte order 
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+#define getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
+		          pDataType,  checkAccess)                         \
+       _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
+		          pDataType,  checkAccess, 1)            
+
+/** 
+ * @ingroup od
+ * @brief readLocalDict() reads an entry from the object dictionary, but in 
+ * contrast to getODentry(), readLocalDict() doesn't endianize entry and reads
+ * entry in machine native endianness. 
+ * @param OD Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to read
+ *                an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pDestData Pointer to the pointer which points to the variable where
+ *                   the value of this object dictionary entry should be copied
+ * @param pExpectedSize This function writes the size of the copied value (in Byte)
+ *                      into this variable.
+ * @param *pDataType Pointer to the type of the data. See objdictdef.h
+ * @param checkAccess if other than 0, do not read if the data is Write Only
+ *                    [Not used today. Put always 0].
+ * @param endianize Set to 0, data is not endianized and copied in machine native
+ *                  endianness 
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+#define readLocalDict( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
+		          pDataType,  checkAccess)                         \
+       _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
+		          pDataType,  checkAccess, 0)
+
+/* By this function you can write an entry into the object dictionary
+ * @param *d Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to write
+ *               an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pSourceData Pointer to the variable that holds the value that should
+ *                     be copied into the object dictionary
+ * @param *pExpectedSize The size of the value (in Byte).
+ * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
+ * @param endianize When not 0, data is endianized into network byte order
+ *                  when 0, data is not endianized and copied in machine native
+ *                  endianness   
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+UNS32 _setODentry( CO_Data* d,
+                   UNS16 wIndex,
+                   UNS8 bSubindex,
+                   void * pSourceData,
+                   UNS32 * pExpectedSize,
+                   UNS8 checkAccess,
+                   UNS8 endianize);
+
+/**
+ * @ingroup od
+ * @brief setODentry converts SourceData from network byte order to machine native 
+ * format, and writes that to OD.
+ * @code
+ * // Example usage:
+ * UNS8 B;
+ * B = 0xFF; // set transmission type
+ *
+ * retcode = setODentry( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 );
+ * @endcode
+ * @param d Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to write
+ *               an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pSourceData Pointer to the variable that holds the value that should
+ *                     be copied into the object dictionary
+ * @param *pExpectedSize The size of the value (in Byte).
+ * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
+ * @param endianize Set to 1 : endianized into network byte order
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+#define setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \
+                  checkAccess) \
+       _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \
+                  checkAccess, 1)
+
+/** @fn UNS32 writeLocalDict(d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess)
+ * @ingroup od
+ * @hideinitializer
+ * @brief Writes machine native SourceData to OD.
+ * @param d Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to write
+ *               an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pSourceData Pointer to the variable that holds the value that should
+ *                     be copied into the object dictionary
+ * @param *pExpectedSize The size of the value (in Byte).
+ * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
+ * @param endianize Data is not endianized and copied in machine native endianness 
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ * \n\n
+ * @code
+ * // Example usage:
+ * UNS8 B;
+ * B = 0xFF; // set transmission type
+ *
+ * retcode = writeLocalDict( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 );
+ * @endcode
+ */
+#define writeLocalDict( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess) \
+       _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess, 0)
+
+
+
+/**
+ * @brief Scan the index of object dictionary. Used only by setODentry and getODentry.
+ * @param *d Pointer to a CAN object data structure
+ * @param wIndex
+ * @param *errorCode :  OD_SUCCESSFUL if index foundor SDO abort code. (See file def.h)
+ * @param **Callback
+ * @return NULL if index not found. Else : return the table part of the object dictionary.
+ */
+ const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback);
+
+UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __objacces_h__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/objdictdef.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,124 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __objdictdef_h__
+#define __objdictdef_h__
+
+/************************* CONSTANTES **********************************/
+/** this are static defined datatypes taken fCODE the canopen standard. They
+ *  are located at index 0x0001 to 0x001B. As described in the standard, they
+ *  are in the object dictionary for definition purpose only. a device does not
+ *  to support all of this datatypes.
+ */
+#define boolean         0x01
+#define int8            0x02
+#define int16           0x03
+#define int32           0x04
+#define uint8           0x05
+#define uint16          0x06
+#define uint32          0x07
+#define real32          0x08
+#define visible_string  0x09
+#define octet_string    0x0A
+#define unicode_string  0x0B
+#define time_of_day     0x0C
+#define time_difference 0x0D
+
+#define domain          0x0F
+#define int24           0x10
+#define real64          0x11
+#define int40           0x12
+#define int48           0x13
+#define int56           0x14
+#define int64           0x15
+#define uint24          0x16
+
+#define uint40          0x18
+#define uint48          0x19
+#define uint56          0x1A
+#define uint64          0x1B
+
+#define pdo_communication_parameter 0x20
+#define pdo_mapping                 0x21
+#define sdo_parameter               0x22
+#define identity                    0x23
+
+/* CanFestival is using 0x24 to 0xFF to define some types containing a 
+ value range (See how it works in objdict.c)
+ */
+
+
+/** Each entry of the object dictionary can be READONLY (RO), READ/WRITE (RW),
+ *  WRITE-ONLY (WO)
+ */
+#define RW     0x00  
+#define WO     0x01
+#define RO     0x02
+
+#define TO_BE_SAVE  0x04
+#define DCF_TO_SEND 0x08
+
+/************************ STRUCTURES ****************************/
+/** This are some structs which are neccessary for creating the entries
+ *  of the object dictionary.
+ */
+typedef struct td_subindex
+{
+    UNS8                    bAccessType;
+    UNS8                    bDataType; /* Defines of what datatype the entry is */
+    UNS32                   size;      /* The size (in Byte) of the variable */
+    void*                   pObject;   /* This is the pointer of the Variable */
+} subindex;
+
+/** Struct for creating entries in the communictaion profile
+ */
+typedef struct td_indextable
+{
+    subindex*   pSubindex;   /* Pointer to the subindex */
+    UNS8   bSubCount;   /* the count of valid entries for this subindex
+                         * This count here defines how many memory has been
+                         * allocated. this memory does not have to be used.
+                         */
+    UNS16   index;
+} indextable;
+
+typedef struct s_quick_index{
+	UNS16 SDO_SVR;
+	UNS16 SDO_CLT;
+	UNS16 PDO_RCV;
+	UNS16 PDO_RCV_MAP;
+	UNS16 PDO_TRS;
+	UNS16 PDO_TRS_MAP;
+}quick_index;
+
+
+/*typedef struct struct_CO_Data CO_Data; */
+typedef UNS32 (*ODCallback_t)(CO_Data* d, const indextable *, UNS8 bSubindex);
+typedef const indextable * (*scanIndexOD_t)(UNS16 wIndex, UNS32 * errorCode, ODCallback_t **Callback);
+
+/************************** MACROS *********************************/
+
+/* CANopen usefull helpers */
+#define GET_NODE_ID(m)         (UNS16_LE(m.cob_id) & 0x7f)
+#define GET_FUNCTION_CODE(m)   (UNS16_LE(m.cob_id) >> 7)
+
+#endif /* __objdictdef_h__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/pdo.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,159 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @defgroup pdo Process Data Object (PDO)
+ *  PDO is a communication object defined by the DPO communication parameter and PDA mapping parameter objects.
+ *  It is an uncomfirmed communication service without protocol overhead.
+ *  @ingroup comobj
+ */
+ 
+#ifndef __pdo_h__
+#define __pdo_h__
+
+#include <applicfg.h>
+#include <def.h>
+
+#include "canopen_can.h"
+
+typedef struct struct_s_PDO_status s_PDO_status;
+
+#include "data.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Status of the TPDO : */
+#define PDO_INHIBITED 0x01
+#define PDO_RTR_SYNC_READY 0x01
+
+/** The PDO structure */
+struct struct_s_PDO_status {
+  UNS8 transmit_type_parameter;
+  TIMER_HANDLE event_timer;
+  TIMER_HANDLE inhibit_timer;
+  Message last_message;
+};
+
+#define s_PDO_status_Initializer {0, TIMER_NONE, TIMER_NONE, Message_Initializer}
+
+/** definitions of the different types of PDOs' transmission
+ * 
+ * SYNCHRO(n) means that the PDO will be transmited every n SYNC signal.
+ */
+#define TRANS_EVERY_N_SYNC(n) (n) /*n = 1 to 240 */
+#define TRANS_SYNC_ACYCLIC    0    /* Trans after reception of n SYNC. n = 1 to 240 */
+#define TRANS_SYNC_MIN        1    /* Trans after reception of n SYNC. n = 1 to 240 */
+#define TRANS_SYNC_MAX        240  /* Trans after reception of n SYNC. n = 1 to 240 */
+#define TRANS_RTR_SYNC        252  /* Transmission on request */
+#define TRANS_RTR             253  /* Transmission on request */
+#define TRANS_EVENT_SPECIFIC  254  /* Transmission on event */
+#define TRANS_EVENT_PROFILE   255  /* Transmission on event */
+
+/** 
+ * @brief Copy all the data to transmit in process_var
+ * Prepare the PDO defined at index to be sent
+ * *pwCobId : returns the value of the cobid. (subindex 1)
+ * @param *d Pointer on a CAN object data structure
+ * @param numPdo The PDO number
+ * @param *pdo Pointer on a CAN message structure
+ * @return 0 or 0xFF if error.
+ */
+UNS8 buildPDO(CO_Data* d, UNS8 numPdo, Message *pdo);
+
+/** 
+ * @ingroup pdo
+ * @brief Transmit a PDO request frame on the network to the slave.
+ * @param *d Pointer on a CAN object data structure
+ * @param RPDOIndex Index of the receive PDO
+ * @return
+ *       - CanFestival file descriptor is returned upon success.
+ *       - 0xFF is returned if RPDO Index is not found.
+ 
+ * @return 0xFF if error, other in success.
+ */
+UNS8 sendPDOrequest( CO_Data* d, UNS16 RPDOIndex );
+
+/**
+ * @brief Compute a PDO frame reception
+ * bus_id is hardware dependant
+ * @param *d Pointer on a CAN object data structure
+ * @param *m Pointer on a CAN message structure
+ * @return 0xFF if error, else return 0
+ */
+UNS8 proceedPDO (CO_Data* d, Message *m);
+
+/** 
+ * @brief Used by the application to signal changes in process data
+ * that could be mapped to some TPDO.
+ * This do not necessarily imply PDO emission.
+ * Function iterates on all TPDO and look TPDO transmit 
+ * type and content change before sending it.    
+ * @param *d Pointer on a CAN object data structure
+ */
+UNS8 sendPDOevent (CO_Data* d);
+UNS8 sendOnePDOevent (CO_Data* d, UNS8 pdoNum);
+
+/** 
+ * @ingroup pdo
+ * @brief Function iterates on all TPDO and look TPDO transmit 
+ * type and content change before sending it.
+ * @param *d Pointer on a CAN object data structure
+ * @param isSyncEvent
+ */
+UNS8 _sendPDOevent(CO_Data* d, UNS8 isSyncEvent);
+
+/** 
+ * @brief Initialize PDO feature 
+ * @param *d Pointer on a CAN object data structure
+ */
+void PDOInit(CO_Data* d);
+
+/** 
+ * @brief Stop PDO feature 
+ * @param *d Pointer on a CAN object data structure
+ */
+void PDOStop(CO_Data* d);
+
+/** 
+ * @ingroup pdo
+ * @brief Set timer for PDO event
+ * @param *d Pointer on a CAN object data structure
+ * @param pdoNum The PDO number
+ */
+void PDOEventTimerAlarm(CO_Data* d, UNS32 pdoNum);
+
+/** 
+ * @ingroup pdo
+ * @brief Inhibit timer for PDO event
+ * @param *d Pointer on a CAN object data structure
+ * @param pdoNum The PDO number
+ */
+void PDOInhibitTimerAlarm(CO_Data* d, UNS32 pdoNum);
+
+/* copy bit per bit in little endian */
+void CopyBits(UNS8 NbBits, UNS8* SrcByteIndex, UNS8 SrcBitIndex, UNS8 SrcBigEndian, UNS8* DestByteIndex, UNS8 DestBitIndex, UNS8 DestBigEndian);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/sdo.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,479 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @defgroup comobj Communication Objects
+ *  @ingroup userapi
+ */
+ 
+/** @defgroup sdo Service Data Object (SDO)
+ *  SDOs provide the access to entries in the CANopen Object Dictionary.
+ *     An SDO is made up of at least two CAN messages with different identifiers.
+ *     SDO s are always confirmed point-to-point communications services. 
+ *  @ingroup comobj
+ */
+ 
+#ifndef __sdo_h__
+#define __sdo_h__
+
+struct struct_s_transfer;
+
+#include "canopen_timer.h"
+
+typedef void (*SDOCallback_t)(CO_Data* d, UNS8 nodeId);
+
+/* The Transfer structure
+Used to store the different segments of
+ - a SDO received before writing in the dictionary
+ - the reading of the dictionary to put on a SDO to transmit
+*/
+
+struct struct_s_transfer {
+  UNS8           nodeId;     /**<own ID if server, or node ID of the server if client */
+
+  UNS8           whoami;     /**< Takes the values SDO_CLIENT or SDO_SERVER */
+  UNS8           state;      /**< state of the transmission : Takes the values SDO_... */
+  UNS8           toggle;    
+  UNS32          abortCode;  /**< Sent or received */
+  /**< index and subindex of the dictionary where to store */
+  /**< (for a received SDO) or to read (for a transmit SDO) */
+  UNS16          index;
+  UNS8           subIndex;
+  UNS32          count;      /**< Number of data received or to be sent. */
+  UNS32          offset;     /**< stack pointer of data[]
+                              * Used only to tranfer part of a line to or from a SDO.
+                              * offset is always pointing on the next free cell of data[].
+                              * WARNING s_transfer.data is subject to ENDIANISATION
+                              * (with respect to CANOPEN_BIG_ENDIAN)
+                              */
+  UNS8           data [SDO_MAX_LENGTH_TRANSFERT];
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  UNS8           *dynamicData;
+  UNS32          dynamicDataSize;
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+  UNS8           dataType;   /**< Defined in objdictdef.h Value is visible_string
+                              * if it is a string, any other value if it is not a string,
+                              * like 0. In fact, it is used only if client.
+                              */
+  TIMER_HANDLE   timer;      /**< Time counter to implement a timeout in milliseconds.
+                              * It is automatically incremented whenever
+                              * the line state is in SDO_DOWNLOAD_IN_PROGRESS or
+                              * SDO_UPLOAD_IN_PROGRESS, and reseted to 0
+                              * when the response SDO have been received.
+                              */
+  SDOCallback_t Callback;   /**< The user callback func to be called at SDO transaction end */
+};
+typedef struct struct_s_transfer s_transfer;
+
+
+#include "data.h"
+
+
+struct BODY{
+    UNS8 data[8]; /**< The 8 bytes data of the SDO */
+};
+
+/* The SDO structure ...*/
+struct struct_s_SDO {
+  UNS8 nodeId;        /**< In any case, Node ID of the server (case sender or receiver).*/
+  struct BODY body;
+};
+
+
+typedef struct struct_s_SDO s_SDO;
+
+/*!
+** Called by writeNetworkDict
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+** @param Callback
+** @param endianize
+**
+** @return
+**/
+UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
+               UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
+
+/** 
+ * @brief Reset of a SDO exchange on timeout.
+ * Send a SDO abort.
+ * @param *d Pointer on a CAN object data structure
+ * @param id
+ */
+void SDOTimeoutAlarm(CO_Data* d, UNS32 id);
+
+/** 
+ * @brief Reset all SDO buffers.
+ * @param *d Pointer on a CAN object data structure
+ */
+void resetSDO (CO_Data* d);
+
+
+/** 
+ * @brief Copy the data received from the SDO line transfert to the object dictionary.
+ * @param *d Pointer on a CAN object data structure
+ * @param line SDO line
+ * @return SDO error code if error. Else, returns 0.
+ */
+UNS32 SDOlineToObjdict (CO_Data* d, UNS8 line);
+
+/** 
+ * @brief Copy the data from the object dictionary to the SDO line for a network transfert.
+ * @param *d Pointer on a CAN object data structure
+ * @param line SDO line
+ * @return SDO error code if error. Else, returns 0.
+ */
+UNS32 objdictToSDOline (CO_Data* d, UNS8 line);
+
+/** 
+ * @brief Copy data from an existant line in the argument "* data"
+ * @param d Pointer on a CAN object data structure
+ * @param line SDO line
+ * @param nbBytes
+ * @param *data Pointer on the data
+ * @return 0xFF if error. Else, returns 0.
+ */
+UNS8 lineToSDO (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8 * data);
+
+/** 
+ * @brief Add data to an existant line
+ * @param d Pointer on a CAN object data structure
+ * @param line SDO line
+ * @param nbBytes
+ * @param *data Pointer on the data
+ * @return 0xFF if error. Else, returns 0.
+ */
+UNS8 SDOtoLine (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8 * data);
+
+/** 
+ * @brief Called when an internal SDO abort occurs.
+ * Release the line * Only if server *
+ * If client, the line must be released manually in the core application.
+ * The reason of that is to permit the program to read the transfers structure before its reset,
+ * because many informations are stored on it : index, subindex, data received or trasmited, ...
+ * In all cases, sends a SDO abort.
+ * @param *d Pointer on a CAN object data structure
+ * @param nodeId
+ * @param whoami
+ * @param index
+ * @param subIndex
+ * @param abortCode
+ * @return 0
+ */
+UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode);
+
+/** 
+ * @brief Reset an unused line.
+ * @param *d Pointer on a CAN object data structure
+ * @param line SDO line
+ */
+void resetSDOline (CO_Data* d, UNS8 line);
+
+/** 
+ * @brief Initialize some fields of the structure.
+ * @param *d Pointer on a CAN object data structure
+ * @param line
+ * @param nodeId
+ * @param index
+ * @param subIndex
+ * @param state
+ * @return 0
+ */
+UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state);
+
+/** 
+ * @brief Search for an unused line in the transfers array
+ * to store a new SDO.
+ * ie a line which value of the field "state" is "SDO_RESET"
+ * An unused line have the field "state" at the value SDO_RESET
+ * @param *d Pointer on a CAN object data structure
+ * @param whoami Create the line for a SDO_SERVER or SDO_CLIENT.
+ * @param *line Pointer on a SDO line 
+ * @return 0xFF if all the lines are on use. Else, return 0.
+ */
+UNS8 getSDOfreeLine (CO_Data* d, UNS8 whoami, UNS8 *line);
+
+/** 
+ * @brief Search for the line, in the transfers array, which contains the
+ * beginning of the reception of a fragmented SDO
+ * @param *d Pointer on a CAN object data structure
+ * @param nodeId correspond to the message node-id
+ * @param whoami takes 2 values : look for a line opened as SDO_CLIENT or SDO_SERVER
+ * @param *line Pointer on a SDO line 
+ * @return 0xFF if error.  Else, return 0
+ */
+UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line);
+
+/** 
+ * @brief Search for the line, in the transfers array, which contains the
+ * beginning of the reception of a fragmented SDO
+ *
+ * Because getSDOlineOnUse() does not return any line in state \c SDO_ABORTED_INTERNAL,
+ * this funtion is used to return them, too.
+ *
+ * @param *d Pointer on a CAN object data structure
+ * @param nodeId correspond to the message node-id
+ * @param whoami takes 2 values : look for a line opened as SDO_CLIENT or SDO_SERVER
+ * @param *line Pointer on a SDO line
+ * @return 0xFF if error.  Else, return 0
+ */
+UNS8 getSDOlineToClose (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line);
+
+/** 
+ * @brief Close a transmission.
+ * @param *d Pointer on a CAN object data structure
+ * @param nodeId Node id of the server if both server or client
+ * @param whoami Line opened as SDO_CLIENT or SDO_SERVER
+ */
+UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami);
+
+/** 
+ * @brief Bytes in the line structure which must be transmited (or received)
+ * @param *d Pointer on a CAN object data structure
+ * @param line SDO line 
+ * @param *nbBytes Pointer on nbBytes
+ * @return 0.
+ */
+UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS32 * nbBytes);
+
+/** 
+ * @brief Store in the line structure the nb of bytes which must be transmited (or received)
+ * @param *d Pointer on a CAN object data structure
+ * @param line SDO line 
+ * @param nbBytes
+ * @return 0 if success, 0xFF if error.
+ */
+UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS32 nbBytes);
+
+/**
+ * @brief Transmit a SDO frame on the bus bus_id
+ * @param *d Pointer on a CAN object data structure
+ * @param whoami Takes 2 values : SDO_CLIENT or SDO_SERVER
+ * @param sdo SDO Structure which contains the sdo to transmit
+ * @return canSend(bus_id,&m) or 0xFF if error.
+ */
+UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo);
+
+/** 
+ * @brief Transmit a SDO error to the client. The reasons may be :
+ * Read/Write to a undefined object
+ * Read/Write to a undefined subindex
+ * Read/write a not valid length object
+ * Write a read only object
+ * @param *d Pointer on a CAN object data structure
+ * @param whoami takes 2 values : SDO_CLIENT or SDO_SERVER
+ * @param nodeId
+ * @param index
+ * @param subIndex
+ * @param abortCode
+ * @return 0
+ */
+UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 abortCode);
+
+/** 
+ * @brief Treat a SDO frame reception
+ * call the function sendSDO
+ * @param *d Pointer on a CAN object data structure
+ * @param *m Pointer on a CAN message structure 
+ * @return code : 
+ *            - 0xFF if error
+ *         - 0x80 if transfert aborted by the server
+ *         - 0x0  ok
+ */
+UNS8 proceedSDO (CO_Data* d, Message *m);
+
+/** 
+ * @ingroup sdo
+ * @brief Used to send a SDO request frame to write the data at the index and subIndex indicated
+ * @param *d Pointer to a CAN object data structure
+ * @param nodeId Node Id of the slave
+ * @param index At index indicated
+ * @param subIndex At subIndex indicated
+ * @param count number of bytes to write in the dictionnary.
+ * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
+ * @param *data Pointer to data
+ * @return 
+ * - 0 is returned upon success.
+ * - 0xFE is returned when no sdo client to communicate with node.
+ * - 0xFF is returned when error occurs.
+ */
+UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
+               UNS8 subIndex, UNS32 count, UNS8 dataType, void *data);
+
+/** 
+ * @ingroup sdo
+ * @brief Used to send a SDO request frame to write in a distant node dictionnary.
+ * @details The function Callback which must be defined in the user code is called at the
+ * end of the exchange. (on succes or abort).
+ * @param *d Pointer to a CAN object data structure
+ * @param nodeId Node Id of the slave
+ * @param index At index indicated
+ * @param subIndex At subIndex indicated
+ * @param count number of bytes to write in the dictionnary.
+ * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
+ * @param *data Pointer to data
+ * @param Callback Callback function
+ * @return 
+ * - 0 is returned upon success.
+ * - 0xFE is returned when no sdo client to communicate with node.
+ * - 0xFF is returned when error occurs.
+ */
+UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
+               UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback);
+
+/**
+ * @ingroup sdo 
+ * @brief Used to send a SDO request frame to write in a distant node dictionnary.
+ * @details The function Callback which must be defined in the user code is called at the
+ * end of the exchange. (on succes or abort). First free SDO client parameter is
+ * automatically initialized for specific node if not already defined.
+ * @param *d Pointer to a CAN object data structure
+ * @param nodeId Node Id of the slave
+ * @param index At index indicated
+ * @param subIndex At subIndex indicated
+ * @param count number of bytes to write in the dictionnary.
+ * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
+ * @param *data Pointer to data
+ * @param Callback Callback function
+ * @param endianize When not 0, data is endianized into network byte order
+ *                  when 0, data is not endianized and copied in machine native
+ *                  endianness
+ * @return 
+ * - 0 is returned upon success.
+ * - 0xFF is returned when error occurs.
+ */
+UNS8 writeNetworkDictCallBackAI (CO_Data* d, UNS8 nodeId, UNS16 index,
+               UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
+
+/**
+ * @ingroup sdo 
+ * @brief Used to send a SDO request frame to read.
+ * @param *d Pointer to a CAN object data structure
+ * @param nodeId Node Id of the slave
+ * @param index At index indicated
+ * @param subIndex At subIndex indicated
+ * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
+ * @return 
+ * - 0 is returned upon success.
+ * - 0xFE is returned when no sdo client to communicate with node.
+ * - 0xFF is returned when error occurs.
+ */
+UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType);
+
+/** 
+ * @ingroup sdo
+ * @brief Used to send a SDO request frame to read in a distant node dictionnary.
+ * @details The function Callback which must be defined in the user code is called at the
+ * end of the exchange. (on succes or abort).
+ * @param *d Pointer on a CAN object data structure
+ * @param nodeId Node Id of the slave
+ * @param index At index indicated
+ * @param subIndex At subIndex indicated
+ * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
+ * @param Callback Callback function
+ * @return 
+ * - 0 is returned upon success.
+ * - 0xFE is returned when no sdo client to communicate with node.
+ * - 0xFF is returned when error occurs.
+ */
+UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback);
+
+/** 
+ * @ingroup sdo
+ * @brief Used to send a SDO request frame to read in a distant node dictionnary.
+ * @details The function Callback which must be defined in the user code is called at the
+ * end of the exchange. (on succes or abort). First free SDO client parameter is
+ * automatically initialized for specific node if not already defined.
+ * @param *d Pointer on a CAN object data structure
+ * @param nodeId Node Id of the slave
+ * @param index At index indicated
+ * @param subIndex At subIndex indicated
+ * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value.
+ * @param Callback Callback function
+ * @return 
+ * - 0 is returned upon success.
+ * - 0xFF is returned when error occurs.
+ */
+UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback);
+
+/** 
+ * @ingroup sdo
+ * @brief Use this function after calling readNetworkDict to get the result.
+ * 
+ * @param *d Pointer to a CAN object data structure
+ * @param nodeId Node Id of the slave
+ * @param *data Pointer to the datas
+ * @param *size Pointer to the size
+ * @param *abortCode Pointer to the abortcode. (0 = not available. Else : SDO abort code. (received if return SDO_ABORTED_RCV)
+ * 
+ * 
+ * @return
+ *           - SDO_FINISHED             // datas are available
+ *           - SDO_ABORTED_RCV          // Transfert failed (abort SDO received)
+ *           - SDO_ABORTED_INTERNAL     // Transfert failed (internal abort)
+ *           - SDO_UPLOAD_IN_PROGRESS   // Datas are not yet available
+ *           - SDO_DOWNLOAD_IN_PROGRESS // Download is in progress
+ * \n\n
+ * example :
+ * @code
+ * UNS32 data;
+ * UNS8 size;
+ * readNetworkDict(0, 0x05, 0x1016, 1, 0) // get the data index 1016 subindex 1 of node 5
+ * while (getReadResultNetworkDict (0, 0x05, &data, &size) == SDO_UPLOAD_IN_PROGRESS);
+ * @endcode
+*/
+UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS32 *size, UNS32 * abortCode);
+
+/**
+ * @ingroup sdo
+ * @brief Use this function after calling writeNetworkDict function to get the result of the write.
+ * @details It is mandatory to call this function because it is releasing the line used for the transfer.
+ * @param *d Pointer to a CAN object data structure
+ * @param nodeId Node Id of the slave
+ * @param *abortCode Pointer to the abortcode
+ * - 0 = not available. 
+ * - SDO abort code (received if return SDO_ABORTED_RCV)
+ * 
+ * @return : 
+ *           - SDO_FINISHED             // datas are available
+ *           - SDO_ABORTED_RCV          // Transfert failed (abort SDO received)
+ *           - SDO_ABORTED_INTERNAL     // Transfert failed (Internal abort)
+ *           - SDO_DOWNLOAD_IN_PROGRESS // Datas are not yet available
+ *           - SDO_UPLOAD_IN_PROGRESS   // Upload in progress
+ * \n\n
+ * example :
+ * @code
+ * UNS32 data = 0x50;
+ * UNS8 size;
+ * UNS32 abortCode;
+ * writeNetworkDict(0, 0x05, 0x1016, 1, size, &data) // write the data index 1016 subindex 1 of node 5
+ * while (getWriteResultNetworkDict (0, 0x05, &abortCode) == SDO_DOWNLOAD_IN_PROGRESS);
+ * @endcode
+*/
+UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/states.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,150 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @defgroup statemachine State Machine
+ *  @ingroup userapi
+ */
+ 
+#ifndef __states_h__
+#define __states_h__
+
+#include <applicfg.h>
+
+/* The nodes states 
+ * -----------------
+ * values are choosen so, that they can be sent directly
+ * for heartbeat messages...
+ * Must be coded on 7 bits only
+ * */
+/* Should not be modified */
+enum enum_nodeState {
+  Initialisation  = 0x00, 
+  Disconnected    = 0x01,
+  Connecting      = 0x02,
+  Preparing       = 0x02,
+  Stopped         = 0x04,
+  Operational     = 0x05,
+  Pre_operational = 0x7F,
+  Unknown_state   = 0x0F
+};
+
+typedef enum enum_nodeState e_nodeState;
+
+typedef struct
+{
+	INTEGER8 csBoot_Up;
+	INTEGER8 csSDO;
+	INTEGER8 csEmergency;
+	INTEGER8 csSYNC;
+	INTEGER8 csHeartbeat;
+	INTEGER8 csPDO;
+	INTEGER8 csLSS;
+} s_state_communication;
+
+/** 
+ * @brief Function that user app can overload
+ * @ingroup statemachine
+ */
+typedef void (*initialisation_t)(CO_Data*);
+typedef void (*preOperational_t)(CO_Data*);
+typedef void (*operational_t)(CO_Data*);
+typedef void (*stopped_t)(CO_Data*);
+
+/** 
+ * @ingroup statemachine
+ * @brief Function that user app can overload
+ * @param *d Pointer on a CAN object data structure
+ */
+void _initialisation(CO_Data* d);
+
+/** 
+ * @ingroup statemachine
+ * @brief Function that user app can overload
+ * @param *d Pointer on a CAN object data structure
+ */
+void _preOperational(CO_Data* d);
+
+/**
+ * @ingroup statemachine 
+ * @brief Function that user app can overload
+ * @param *d Pointer on a CAN object data structure
+ */
+void _operational(CO_Data* d);
+
+/** 
+ * @ingroup statemachine
+ * @brief Function that user app can overload
+ * @param *d Pointer on a CAN object data structure
+ */
+void _stopped(CO_Data* d);
+
+#include "data.h"
+
+/************************* prototypes ******************************/
+
+/** 
+ * @brief Called by driver/app when receiving messages
+ * @param *d Pointer on a CAN object data structure
+ * @param *m Pointer on a CAN message structure
+ */
+void canDispatch(CO_Data* d, Message *m);
+
+/** 
+ * @ingroup statemachine
+ * @brief Returns the state of the node
+ * @param *d Pointer on a CAN object data structure
+ * @return The node state
+ */
+e_nodeState getState (CO_Data* d);
+
+/** 
+ * @ingroup statemachine
+ * @brief Change the state of the node 
+ * @param *d Pointer on a CAN object data structure
+ * @param newState The state to assign
+ * @return 
+ */
+UNS8 setState (CO_Data* d, e_nodeState newState);
+
+/**
+ * @ingroup statemachine 
+ * @brief Returns the nodId 
+ * @param *d Pointer on a CAN object data structure
+ * @return
+ */
+UNS8 getNodeId (CO_Data* d);
+
+/** 
+ * @ingroup statemachine
+ * @brief Define the node ID. Initialize the object dictionary
+ * @param *d Pointer on a CAN object data structure
+ * @param nodeId The node ID to assign
+ */
+void setNodeId (CO_Data* d, UNS8 nodeId);
+
+/** 
+ * @brief Some stuff to do when the node enter in pre-operational mode
+ * @param *d Pointer on a CAN object data structure
+ */
+void initPreOperationalMode (CO_Data* d);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/sync.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,66 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @defgroup synco Synchronisation Object
+ *  SYNC object is a CANopen message forcing the receiving nodes to sample the inputs mapped into synchronous TPDOS.
+ *  Receiving this message cause the node to set the outputs to values received in the previous synchronous RPDO.
+ *  @ingroup comobj
+ */
+					 
+#ifndef __SYNC_h__
+#define __SYNC_h__
+
+void startSYNC(CO_Data* d);
+
+void stopSYNC(CO_Data* d);
+
+typedef void (*post_sync_t)(CO_Data*);
+void _post_sync(CO_Data* d);
+
+typedef void (*post_TPDO_t)(CO_Data*);
+void _post_TPDO(CO_Data* d);
+
+/** 
+ * @brief Transmit a SYNC message and trigger sync TPDOs
+ * @param *d Pointer on a CAN object data structure
+ * @return
+ */
+UNS8 sendSYNC (CO_Data* d);
+
+/** 
+ * @brief Transmit a SYNC message on CAN bus
+ * @param *d Pointer on a CAN object data structure
+ * @return
+ */
+UNS8 sendSYNCMessage(CO_Data* d);
+
+/** 
+ * @brief This function is called when the node is receiving a SYNC message (cob-id = 0x80).
+ *  - Check if the node is in OERATIONAL mode. (other mode : return 0 but does nothing).
+ *  - Get the SYNC cobId by reading the dictionary index 1005, check it does correspond to the received cobId
+ *  - Trigger sync TPDO emission 
+ * @param *d Pointer on a CAN object data structure
+ * @return 0 if OK, 0xFF if error 
+ */
+UNS8 proceedSYNC (CO_Data* d);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/sysdep.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,27 @@
+#ifndef __sysdep_h__
+#define __sysdep_h__
+
+#include "config.h"
+
+#ifdef CANOPEN_BIG_ENDIAN
+
+/* Warning: the argument must not update pointers, e.g. *p++ */
+
+#define UNS16_LE(v)  ((((UNS16)(v) & 0xff00) >> 8) | \
+		      (((UNS16)(v) & 0x00ff) << 8))
+
+#define UNS32_LE(v)  ((((UNS32)(v) & 0xff000000) >> 24) |	\
+		      (((UNS32)(v) & 0x00ff0000) >> 8)  |	\
+		      (((UNS32)(v) & 0x0000ff00) << 8)  |	\
+		      (((UNS32)(v) & 0x000000ff) << 24))
+
+#else
+
+#define UNS16_LE(v)  (v)
+
+#define UNS32_LE(v)  (v)
+
+#endif
+
+#endif /* __sysdep_h__ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/include/timers_driver.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,84 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/** @defgroup timer Timer Management
+ *  @ingroup userapi
+ */
+
+#ifndef __timer_driver_h__
+#define __timer_driver_h__
+
+#include "timerscfg.h"
+#include "canopen_timer.h"
+
+// For use from CAN driver
+
+
+/**
+ * @ingroup timer
+ * @brief Acquire mutex
+ */
+void EnterMutex(void);
+
+/**
+ * @ingroup timer
+ * @brief Release mutex
+ */
+void LeaveMutex(void);
+
+void WaitReceiveTaskEnd(TASK_HANDLE*);
+
+/**
+ * @ingroup timer
+ * @brief Initialize Timer
+ */
+void TimerInit(void);
+
+/**
+ * @ingroup timer
+ * @brief Cleanup Timer  
+ */
+void TimerCleanup(void);
+
+/**
+ * @ingroup timer
+ * @brief Start the timer task
+ * @param Callback A callback function
+ */
+void StartTimerLoop(TimerCallback_t Callback);
+
+/**
+ * @ingroup timer
+ * @brief Stop the timer task
+ * @param Callback A callback function
+ */
+void StopTimerLoop(TimerCallback_t Callback);
+
+/**
+ * @brief Stop the timer task
+ * @param port CanFestival file descriptor
+ * @param *handle handle of receive loop thread
+ * @param *ReceiveLoopPtr Pointer on the receive loop function
+ */
+void CreateReceiveTask(CAN_PORT port, TASK_HANDLE* handle, void* ReceiveLoopPtr);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/canopen_timer.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,182 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/*!
+** @file   timer.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Tue Jun  5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
+
+/* #define DEBUG_WAR_CONSOLE_ON */
+/* #define DEBUG_ERR_CONSOLE_ON */
+
+#include <applicfg.h>
+#include "canopen_timer.h"
+
+/*  ---------  The timer table --------- */
+s_timer_entry timers[MAX_NB_TIMER] = {{TIMER_FREE, NULL, NULL, 0, 0, 0},};
+
+TIMEVAL total_sleep_time = TIMEVAL_MAX;
+TIMER_HANDLE last_timer_raw = -1;
+
+#define min_val(a,b) ((a<b)?a:b)
+
+/*!
+** -------  Use this to declare a new alarm ------
+**
+** @param d
+** @param id
+** @param callback
+** @param value
+** @param period
+**
+** @return
+**/
+TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period)
+{
+    TIMER_HANDLE row_number;
+    s_timer_entry *row;
+
+    /* in order to decide new timer setting we have to run over all timer rows */
+    for(row_number=0, row=timers; row_number <= last_timer_raw + 1 && row_number < MAX_NB_TIMER; row_number++, row++)
+    {
+        if (callback &&     /* if something to store */
+           row->state == TIMER_FREE) /* and empty row */
+        {    /* just store */
+            TIMEVAL real_timer_value;
+            TIMEVAL elapsed_time;
+
+            if (row_number == last_timer_raw + 1) last_timer_raw++;
+
+            elapsed_time = getElapsedTime();
+            /* set next wakeup alarm if new entry is sooner than others, or if it is alone */
+            real_timer_value = value;
+            real_timer_value = min_val(real_timer_value, TIMEVAL_MAX);
+
+            if (total_sleep_time > elapsed_time && total_sleep_time - elapsed_time > real_timer_value)
+            {
+                total_sleep_time = elapsed_time + real_timer_value;
+                setTimer(real_timer_value);
+            }
+            row->callback = callback;
+            row->d = d;
+            row->id = id;
+            row->val = value + elapsed_time;
+            row->interval = period;
+            row->state = TIMER_ARMED;
+            return row_number;
+        }
+    }
+
+    return TIMER_NONE;
+}
+
+/*!
+**  -----  Use this to remove an alarm ----
+**
+** @param handle
+**
+** @return
+**/
+TIMER_HANDLE DelAlarm(TIMER_HANDLE handle)
+{
+    /* Quick and dirty. system timer will continue to be trigged, but no action will be preformed. */
+    MSG_WAR(0x3320, "DelAlarm. handle = ", handle);
+    if(handle != TIMER_NONE)
+    {
+        if(handle == last_timer_raw)
+            last_timer_raw--;
+        timers[handle].state = TIMER_FREE;
+    }
+    return TIMER_NONE;
+}
+
+/*!
+** ------  TimeDispatch is called on each timer expiration ----
+**
+**/
+int tdcount=0;
+void TimeDispatch(void)
+{
+    TIMER_HANDLE i;
+    TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */
+    /* First run : change timer state depending on time */
+    /* Get time since timer signal */
+    UNS32 overrun = (UNS32)getElapsedTime();
+
+    TIMEVAL real_total_sleep_time = total_sleep_time + overrun;
+
+    s_timer_entry *row;
+
+    for(i=0, row = timers; i <= last_timer_raw; i++, row++)
+    {
+        if (row->state & TIMER_ARMED) /* if row is active */
+        {
+            if (row->val <= real_total_sleep_time) /* to be trigged */
+            {
+                if (!row->interval) /* if simply outdated */
+                {
+                    row->state = TIMER_TRIG; /* ask for trig */
+                }
+                else /* or period have expired */
+                {
+                    /* set val as interval, with 32 bit overrun correction, */
+                    /* modulo for 64 bit not available on all platforms     */
+                    row->val = row->interval - (overrun % (UNS32)row->interval);
+                    row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */
+                    /* Check if this new timer value is the soonest */
+                    if(row->val < next_wakeup)
+                        next_wakeup = row->val;
+                }
+            }
+            else
+            {
+                /* Each armed timer value in decremented. */
+                row->val -= real_total_sleep_time;
+
+                /* Check if this new timer value is the soonest */
+                if(row->val < next_wakeup)
+                    next_wakeup = row->val;
+            }
+        }
+    }
+
+    /* Remember how much time we should sleep. */
+    total_sleep_time = next_wakeup;
+
+    /* Set timer to soonest occurence */
+    setTimer(next_wakeup);
+
+    /* Then trig them or not. */
+    for(i=0, row = timers; i<=last_timer_raw; i++, row++)
+    {
+        if (row->state & TIMER_TRIG)
+        {
+            row->state &= ~TIMER_TRIG; /* reset trig state (will be free if not periodic) */
+            if(row->callback)
+                (*row->callback)(row->d, row->id); /* trig ! */
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/dcf.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,203 @@
+/*
+  This file is part of CanFestival, a library implementing CanOpen
+  Stack.
+
+  Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+  See COPYING file for copyrights details.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+  USA
+*/
+
+
+/**
+** @file   dcf.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Mon Jun  4 17:06:12 2007
+**
+** @brief EXEMPLE OF SOMMARY
+**
+**
+*/
+
+
+#include "data.h"
+#include "sysdep.h"
+//#include "sdo.h"
+
+//extern UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
+//                             UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
+
+
+static void send_consise_dcf_loop(CO_Data* d,UNS8 nodeId);
+
+/* Seek to next NodeID's DCF */
+#define SEEK_NEXT_DCF() \
+       nodeId=(nodeId+1) % d->dcf_odentry->bSubCount; \
+       if(nodeId==0) nodeId=1; \
+       d->dcf_cursor = NULL;
+
+/**
+**
+**
+** @param d
+** @param nodeId
+*/
+static void CheckSDOAndContinue(CO_Data* d, UNS8 nodeId)
+{
+  UNS32 abortCode = 0;
+
+  if(getWriteResultNetworkDict (d, nodeId, &abortCode) != SDO_FINISHED)
+    {
+      MSG_ERR(0x1A01, "SDO error in consise DCF", abortCode);
+      MSG_WAR(0x2A02, "server node : ", nodeId);
+    }
+
+  closeSDOtransfer(d, nodeId, SDO_CLIENT);
+  /* Timedout ? */
+  if(abortCode == SDOABT_TIMED_OUT){
+    /* Node may not be ready, try another one */
+    /* Warning, this might leed to endless attempts */
+    /* if node does never answer */
+    SEEK_NEXT_DCF()
+  }
+  send_consise_dcf_loop(d,nodeId);
+}
+
+
+/**
+**
+**
+** @param d
+** @param nodeId
+**
+** @return
+*/
+UNS8 send_consise_dcf(CO_Data* d,UNS8 nodeId)
+{
+  UNS32 szData;
+  /* Fetch DCF OD entry, if not already done */
+  if(!d->dcf_odentry)
+  {
+    UNS32 errorCode;
+    ODCallback_t *Callback;
+    d->dcf_odentry = (*d->scanIndexOD)(0x1F22, &errorCode, &Callback);
+    /* If DCF entry do not exist... Nothing to do.*/
+    if (errorCode != OD_SUCCESSFUL) goto DCF_finish;
+  }
+
+  szData = d->dcf_odentry->pSubindex[nodeId].size;
+  
+  /* if the entry for the nodeId is not empty. */
+  if(szData!=0){
+      /* if the entry for the nodeId is already been processing, quit.*/
+      if(d->dcf_odentry->pSubindex[nodeId].bAccessType & DCF_TO_SEND) return 1;
+      
+      d->dcf_odentry->pSubindex[nodeId].bAccessType|=DCF_TO_SEND;
+      d->dcf_request++;
+      if(d->dcf_request==1)
+          send_consise_dcf_loop(d,nodeId);
+      return 1;
+  }
+  
+  DCF_finish:
+  return 0;
+}
+
+static void send_consise_dcf_loop(CO_Data* d,UNS8 nodeId)
+{
+  if(nodeId > d->dcf_odentry->bSubCount) return;
+/* Loop on all DCF subindexes, corresponding to node ID until there is no request*/
+  //while (nodeId < d->dcf_odentry->bSubCount){
+  while (d->dcf_request>0){
+      if(d->dcf_odentry->pSubindex[nodeId].bAccessType & DCF_TO_SEND){        
+        UNS8* dcfend;
+          UNS32 nb_entries;
+          UNS32 szData = d->dcf_odentry->pSubindex[nodeId].size;
+           
+           {
+               UNS8* dcf = *((UNS8**)d->dcf_odentry->pSubindex[nodeId].pObject);
+               dcfend = dcf + szData;
+               if (!d->dcf_cursor){
+                  d->dcf_cursor = (UNS8*)dcf + 4;
+                   d->dcf_entries_count = 0;
+               }
+               nb_entries = UNS32_LE(*((UNS32*)dcf));
+           }
+
+        /* condition on consise DCF string for NodeID, if big enough */
+        if((UNS8*)d->dcf_cursor + 7 < (UNS8*)dcfend && d->dcf_entries_count < nb_entries){
+        
+            UNS16 target_Index;
+            UNS8 target_Subindex;
+            UNS32 target_Size;
+
+            /* DCF data may not be 32/16b aligned, 
+             * we cannot directly dereference d->dcf_cursor 
+             * as UNS16 or UNS32 
+             * Do it byte per byte taking care on endianess*/
+#ifdef CANOPEN_BIG_ENDIAN
+            target_Index = *(d->dcf_cursor++) << 8 | 
+                           *(d->dcf_cursor++);
+#else
+            memcpy(&target_Index, d->dcf_cursor,2);
+            d->dcf_cursor+=2;
+#endif
+
+            target_Subindex = *(d->dcf_cursor++);
+
+#ifdef CANOPEN_BIG_ENDIAN
+            target_Size = *(d->dcf_cursor++) << 24 | 
+                          *(d->dcf_cursor++) << 16 | 
+                          *(d->dcf_cursor++) << 8 | 
+                          *(d->dcf_cursor++);
+#else
+            memcpy(&target_Size, d->dcf_cursor,4);
+            d->dcf_cursor+=4;
+#endif
+    
+           _writeNetworkDict(d, /* CO_Data* d*/
+                                nodeId, /* UNS8 nodeId*/
+                                target_Index, /* UNS16 index*/
+                                target_Subindex, /* UNS8 subindex*/
+                                (UNS8)target_Size, /* UNS8 count*/
+                                0, /* UNS8 dataType*/
+                                d->dcf_cursor,/* void *data*/
+                                CheckSDOAndContinue,/* SDOCallback_t
+                                                      Callback*/
+                                0); /* no endianize*/
+            /* Push d->dcf_cursor to the end of data*/
+
+            d->dcf_cursor += target_Size;
+            d->dcf_entries_count++;
+
+            /* send_consise_dcf_loop will be called by CheckSDOAndContinue for next DCF entry*/
+            return;
+          }
+          else
+          {
+              /* We have finished with the dcf entry. Change the flag, decrement the request
+               *  and execute the bootup callback. */
+              d->dcf_odentry->pSubindex[nodeId].bAccessType&=~DCF_TO_SEND;
+              d->dcf_request--;
+              (*d->post_SlaveBootup)(d, nodeId);
+          }
+     }
+     
+    SEEK_NEXT_DCF()
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/emcy.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,248 @@
+/*
+  This file is part of CanFestival, a library implementing CanOpen
+  Stack.
+
+  Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+  See COPYING file for copyrights details.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+  USA
+*/
+
+/*!
+** @file   emcy.c
+** @author Luis Jimenez
+** @date   Wed Sep 26 2007
+**
+** @brief Definitions of the functions that manage EMCY (emergency) messages
+**
+**
+*/
+
+#include <data.h>
+#include "emcy.h"
+#include "canfestival.h"
+#include "sysdep.h"
+
+
+
+UNS32 OnNumberOfErrorsUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex);
+UNS8 sendEMCY(CO_Data* d, UNS16 errCode, UNS8 errRegister);
+
+
+/*! This is called when Index 0x1003 is updated.
+**
+**
+** @param d
+** @param unsused_indextable
+** @param unsused_bSubindex
+**
+** @return
+**/
+UNS32 OnNumberOfErrorsUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex)
+{
+	UNS8 index;
+  // if 0, reset Pre-defined Error Field
+  // else, don't change and give an abort message (eeror code: 0609 0030h)
+	if (*d->error_number == 0)
+		for (index = 0; index < d->error_history_size; ++index)
+			*(d->error_first_element + index) = 0;		/* clear all the fields in Pre-defined Error Field (1003h) */
+	else
+		;// abort message
+  return 0;
+}
+
+/*! start the EMCY mangagement.
+**
+**
+** @param d
+**/
+void emergencyInit(CO_Data* d)
+{
+  RegisterSetODentryCallBack(d, 0x1003, 0x00, &OnNumberOfErrorsUpdate);
+
+  *d->error_number = 0;
+}
+
+/*!
+**
+**
+** @param d
+**/
+void emergencyStop(CO_Data* d)
+{
+  
+}
+
+/*!                                                                                                
+ **                                                                                                 
+ **                                                                                                 
+ ** @param d                                                                                        
+ ** @param cob_id                                                                                   
+ **                                                                                                 
+ ** @return                                                                                         
+ **/  
+UNS8 sendEMCY(CO_Data* d, UNS16 errCode, UNS8 errRegister)
+{
+	Message m;
+  
+	MSG_WAR(0x3051, "sendEMCY", 0);
+  
+	m.cob_id = (UNS16)UNS16_LE(*(UNS32*)d->error_cobid);
+	m.rtr = NOT_A_REQUEST;
+	m.len = 8;
+	m.data[0] = errCode & 0xFF;        /* LSB */
+	m.data[1] = (errCode >> 8) & 0xFF; /* MSB */
+	m.data[2] = errRegister;
+	m.data[3] = 0;		/* Manufacturer specific Error Field still not implemented */
+	m.data[4] = 0;
+	m.data[5] = 0;
+	m.data[6] = 0;
+	m.data[7] = 0;
+  
+	return canSend(d->canHandle,&m);
+}
+
+/*! Sets a new error with code errCode. Also sets corresponding bits in Error register (1001h)
+ **                                                                                                 
+ **  
+ ** @param d
+ ** @param errCode Code of the error                                                                                        
+ ** @param errRegister Bits of Error register (1001h) to be set.
+ ** @return 1 if error, 0 if successful
+ */
+UNS8 EMCY_setError(CO_Data* d, UNS16 errCode, UNS8 errRegMask, UNS16 addInfo)
+{
+	UNS8 index;
+	UNS8 errRegister_tmp;
+	
+	for (index = 0; index < EMCY_MAX_ERRORS; ++index)
+	{
+		if (d->error_data[index].errCode == errCode)		/* error already registered */
+		{
+			if (d->error_data[index].active)
+			{
+				MSG_WAR(0x3052, "EMCY message already sent", 0);
+				return 0;
+			} else d->error_data[index].active = 1;		/* set as active error */
+			break;
+		}
+	}
+	
+	if (index == EMCY_MAX_ERRORS)		/* if errCode not already registered */
+		for (index = 0; index < EMCY_MAX_ERRORS; ++index) if (d->error_data[index].active == 0) break;	/* find first inactive error */
+	
+	if (index == EMCY_MAX_ERRORS)		/* error_data full */
+	{
+		MSG_ERR(0x3053, "error_data full", 0);
+		return 1;
+	}
+	
+	d->error_data[index].errCode = errCode;
+	d->error_data[index].errRegMask = errRegMask;
+	d->error_data[index].active = 1;
+	
+	/* set the new state in the error state machine */
+	d->error_state = Error_occurred;
+
+	/* set Error Register (1001h) */
+	for (index = 0, errRegister_tmp = 0; index < EMCY_MAX_ERRORS; ++index)
+		if (d->error_data[index].active == 1) errRegister_tmp |= d->error_data[index].errRegMask;
+	*d->error_register = errRegister_tmp;
+	
+	/* set Pre-defined Error Field (1003h) */
+	for (index = d->error_history_size - 1; index > 0; --index)
+		*(d->error_first_element + index) = *(d->error_first_element + index - 1);
+	*(d->error_first_element) = errCode | ((UNS32)addInfo << 16);
+	if(*d->error_number < d->error_history_size) ++(*d->error_number);
+	
+	/* send EMCY message */
+	if (d->CurrentCommunicationState.csEmergency)
+		return sendEMCY(d, errCode, *d->error_register);
+	else return 1;
+}
+
+/*! Deletes error errCode. Also clears corresponding bits in Error register (1001h)
+ **                                                                                                 
+ **  
+ ** @param d
+ ** @param errCode Code of the error                                                                                        
+ ** @param errRegister Bits of Error register (1001h) to be set.
+ ** @return 1 if error, 0 if successful
+ */
+void EMCY_errorRecovered(CO_Data* d, UNS16 errCode)
+{
+	UNS8 index;
+	UNS8 errRegister_tmp;
+	UNS8 anyActiveError = 0;
+	
+	for (index = 0; index < EMCY_MAX_ERRORS; ++index)
+		if (d->error_data[index].errCode == errCode) break;		/* find the position of the error */
+
+	
+	if ((index != EMCY_MAX_ERRORS) && (d->error_data[index].active == 1))
+	{
+		d->error_data[index].active = 0;
+		
+		/* set Error Register (1001h) and check error state machine */
+		for (index = 0, errRegister_tmp = 0; index < EMCY_MAX_ERRORS; ++index)
+			if (d->error_data[index].active == 1)
+			{
+				anyActiveError = 1;
+				errRegister_tmp |= d->error_data[index].errRegMask;
+			}
+		if(anyActiveError == 0)
+		{
+			d->error_state = Error_free;
+			/* send a EMCY message with code "Error Reset or No Error" */
+			if (d->CurrentCommunicationState.csEmergency)
+				sendEMCY(d, 0x0000, 0x00);
+		}
+		*d->error_register = errRegister_tmp;
+	}
+	else
+		MSG_WAR(0x3054, "recovered error was not active", 0);
+}
+
+/*! This function is responsible to process an EMCY canopen-message.
+ **
+ **
+ ** @param d
+ ** @param m The CAN-message which has to be analysed.
+ **
+ **/
+void proceedEMCY(CO_Data* d, Message* m)
+{
+	UNS8 nodeID;
+	UNS16 errCode;
+	UNS8 errReg;
+	
+	MSG_WAR(0x3055, "EMCY received. Proceed. ", 0);
+  
+	/* Test if the size of the EMCY is ok */
+	if ( m->len != 8) {
+		MSG_ERR(0x1056, "Error size EMCY. CobId  : ", m->cob_id);
+		return;
+	}
+	
+	/* post the received EMCY */
+	nodeID = UNS16_LE(m->cob_id) & 0x7F;
+	errCode = m->data[0] | ((UNS16)m->data[1] << 8);
+	errReg = m->data[2];
+	(*d->post_emcy)(d, nodeID, errCode, errReg);
+}
+
+void _post_emcy(CO_Data* d, UNS8 nodeID, UNS16 errCode, UNS8 errReg){}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/lifegrd.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,276 @@
+/*
+  This file is part of CanFestival, a library implementing CanOpen
+  Stack.
+
+  Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+  See COPYING file for copyrights details.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+  USA
+*/
+
+/*!
+** @file   lifegrd.c
+** @author Edouard TISSERANT
+** @date   Mon Jun  4 17:19:24 2007
+**
+** @brief
+**
+**
+*/
+
+#include <data.h>
+#include "lifegrd.h"
+#include "canfestival.h"
+#include "dcf.h"
+#include "sysdep.h"
+
+
+void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id);
+
+
+void ProducerHearbeatAlarm(CO_Data* d, UNS32 id);
+
+UNS32 OnHearbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex);
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+**
+** @return
+**/
+e_nodeState getNodeState (CO_Data* d, UNS8 nodeId)
+{
+  e_nodeState networkNodeState = d->NMTable[nodeId];
+  return networkNodeState;
+}
+
+/*! 
+** The Consumer Timer Callback
+**
+** @param d
+** @param id
+**/
+void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id)
+{
+  UNS8 nodeId = (UNS8)(((d->ConsumerHeartbeatEntries[id]) & (UNS32)0x00FF0000) >> (UNS8)16);
+  /*MSG_WAR(0x00, "ConsumerHearbeatAlarm", 0x00);*/
+
+  /* timer have been notified and is now free (non periodic)*/
+  /* -> avoid deleting re-assigned timer if message is received too late*/
+  d->ConsumerHeartBeatTimers[id]=TIMER_NONE;
+  
+  /* set node state */
+  d->NMTable[nodeId] = Disconnected;
+  /*! call heartbeat error with NodeId */
+  (*d->heartbeatError)(d, nodeId);
+}
+
+/*!
+**
+**
+** @param d
+** @param m
+**/
+void proceedNODE_GUARD(CO_Data* d, Message* m )
+{
+  UNS8 nodeId = (UNS8) GET_NODE_ID((*m));
+
+  if((m->rtr == 1) )
+    /*!
+    ** Notice that only the master can have sent this
+    ** node guarding request
+    */
+    {
+      /*!
+      ** Receiving a NMT NodeGuarding (request of the state by the
+      ** master)
+      ** Only answer to the NMT NodeGuarding request, the master is
+      ** not checked (not implemented)
+      */
+      if (nodeId == *d->bDeviceNodeId )
+        {
+          Message msg;
+          UNS16 tmp = *d->bDeviceNodeId + 0x700;
+          msg.cob_id = UNS16_LE(tmp);
+          msg.len = (UNS8)0x01;
+          msg.rtr = 0;
+          msg.data[0] = d->nodeState;
+          if (d->toggle)
+            {
+              msg.data[0] |= 0x80 ;
+              d->toggle = 0 ;
+            }
+          else
+            d->toggle = 1 ;
+          /* send the nodeguard response. */
+          MSG_WAR(0x3130, "Sending NMT Nodeguard to master, state: ", d->nodeState);
+          canSend(d->canHandle,&msg );
+        }
+
+    }else{ /* Not a request CAN */
+      /* The state is stored on 7 bit */
+      e_nodeState newNodeState = (e_nodeState) ((*m).data[0] & 0x7F);
+
+      MSG_WAR(0x3110, "Received NMT nodeId : ", nodeId);
+      
+      if (d->NMTable[nodeId] != newNodeState)
+      {
+        (*d->post_SlaveStateChange)(d, nodeId, newNodeState);
+        /* the slave's state receievd is stored in the NMTable */
+        d->NMTable[nodeId] = newNodeState;
+      }
+
+      /* Boot-Up frame reception */
+      if ( d->NMTable[nodeId] == Initialisation)
+        {
+          /*
+          ** The device send the boot-up message (Initialisation)
+          ** to indicate the master that it is entered in
+          ** pre_operational mode
+          ** Because the  device enter automaticaly in pre_operational
+          ** mode,
+          ** the pre_operational mode is stored
+          ** NMTable[bus_id][nodeId] = Pre_operational
+          */
+          MSG_WAR(0x3100, "The NMT is a bootup from node : ", nodeId);
+          
+          if(!send_consise_dcf(d,nodeId)){
+             /* call post SlaveBootup with NodeId */
+              (*d->post_SlaveBootup)(d, nodeId);
+          }
+        }
+
+      if( d->NMTable[nodeId] != Unknown_state ) {
+        UNS8 index, ConsummerHeartBeat_nodeId ;
+        for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
+          {
+            ConsummerHeartBeat_nodeId = (UNS8)( ((d->ConsumerHeartbeatEntries[index]) & (UNS32)0x00FF0000) >> (UNS8)16 );
+            if ( nodeId == ConsummerHeartBeat_nodeId )
+              {
+                TIMEVAL time = ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ;
+                /* Renew alarm for next heartbeat. */
+                DelAlarm(d->ConsumerHeartBeatTimers[index]);
+                d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0);
+              }
+          }
+      }
+    }
+}
+
+/*! The Consumer Timer Callback
+**
+**
+** @param d
+** @param id
+**/
+void ProducerHearbeatAlarm(CO_Data* d, UNS32 id)
+{
+  if(*d->ProducerHeartBeatTime)
+    {
+      Message msg;
+      /* Time expired, the heartbeat must be sent immediately
+      ** generate the correct node-id: this is done by the offset 1792
+      ** (decimal) and additionaly
+      ** the node-id of this device.
+      */
+      UNS16 tmp = *d->bDeviceNodeId + 0x700;
+      msg.cob_id = UNS16_LE(tmp);
+      msg.len = (UNS8)0x01;
+      msg.rtr = 0;
+      msg.data[0] = d->nodeState; /* No toggle for heartbeat !*/
+      /* send the heartbeat */
+      MSG_WAR(0x3130, "Producing heartbeat: ", d->nodeState);
+      canSend(d->canHandle,&msg );
+
+    }else{
+      d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer);
+    }
+}
+
+/*! This is called when Index 0x1017 is updated.
+**
+**
+** @param d
+** @param unsused_indextable
+** @param unsused_bSubindex
+**
+** @return
+**/
+UNS32 OnHeartbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex)
+{
+  heartbeatStop(d);
+  heartbeatInit(d);
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+**/
+void heartbeatInit(CO_Data* d)
+{
+
+  UNS8 index; /* Index to scan the table of heartbeat consumers */
+  RegisterSetODentryCallBack(d, 0x1017, 0x00, &OnHeartbeatProducerUpdate);
+
+  d->toggle = 0;
+
+  for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
+    {
+      TIMEVAL time = (UNS16) ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ;
+      /* MSG_WAR(0x3121, "should_time : ", should_time ) ; */
+      if ( time )
+        {
+          d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0);
+        }
+    }
+
+  if ( *d->ProducerHeartBeatTime )
+    {
+      TIMEVAL time = *d->ProducerHeartBeatTime;
+      d->ProducerHeartBeatTimer = SetAlarm(d, 0, &ProducerHearbeatAlarm, MS_TO_TIMEVAL(time), MS_TO_TIMEVAL(time));
+    }
+}
+
+/*!
+**
+**
+** @param d
+**/
+void heartbeatStop(CO_Data* d)
+{
+  UNS8 index;
+  for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
+    {
+      d->ConsumerHeartBeatTimers[index] = DelAlarm(d->ConsumerHeartBeatTimers[index]);
+    }
+
+  d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer);
+}
+
+/*!
+**
+**
+** @param heartbeatID
+**/
+void _heartbeatError(CO_Data* d, UNS8 heartbeatID){}
+void _post_SlaveBootup(CO_Data* d, UNS8 SlaveID){}
+void _post_SlaveStateChange(CO_Data* d, UNS8 nodeId, e_nodeState newNodeState){}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/lss.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,1017 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+
+Copyright (C): Jorge Berzosa
+
+
+See COPYING file for copyrights details.
+
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+/*!
+** @file   lss.c
+** @author Jorge Berzosa
+** @date   Mon Oct  22 05:44:32 2007
+**
+** @brief
+**
+**
+*/
+
+
+#include "data.h"
+#include "lss.h"
+#include "canfestival.h"
+#include "sysdep.h"
+
+#ifdef CO_ENABLE_LSS
+
+//#define LSS_TIMEOUT_MS	(TIMEVAL)1000  /* ms */
+//#define LSS_FS_TIMEOUT_MS	(TIMEVAL)100  /* ms */
+
+/* Returns the LSS ident field from a Message struct */
+#define getLSSIdent(msg) (((UNS32)msg->data[4] << 24) | ((UNS32)msg->data[3] << 16) | (msg->data[2] << 8) | (msg->data[1]))
+
+
+/* Returns the LSS switch delay field from a Message struct */
+#define getLSSDelay(msg) ((msg->data[2] << 8) | (msg->data[1]))
+
+/* Returns the LSS FastScan BitCheck field from a Message struct */
+#define getLSSBitCheck(msg) msg->data[5]
+
+/* Returns the LSS FastScan LSSSub field from a Message struct */
+#define getLSSSub(msg) msg->data[6]
+
+/* Returns the LSS FastScan LSSNext field from a Message struct */
+#define getLSSNext(msg) msg->data[7]
+
+/* Prototypes for internals functions */
+UNS8 sendMasterLSSMessage(CO_Data* d, UNS8 command,void *dat1,void *dat2);
+void LssAlarmMSG(CO_Data* d, UNS32 id);
+void LssAlarmSDELAY(CO_Data* d, UNS32 id);
+
+
+#define StopLSS_MSG_TIMER(){\
+ MSG_WAR(0x3D01, "StopLSS_MSG_TIMER", 0);\
+ d->lss_transfer.timerMSG = DelAlarm(d->lss_transfer.timerMSG);}
+
+#define StartLSS_MSG_TIMER(){\
+ MSG_WAR(0x3D02, "StartLSS_MSG_TIMER",0);\
+ d->lss_transfer.timerMSG = SetAlarm(d,0,&LssAlarmMSG,MS_TO_TIMEVAL(LSS_TIMEOUT_MS),0);}
+ 
+#define StopLSS_SDELAY_TIMER(){\
+ MSG_WAR(0x3D03, "StopLSS_SDELAY_TIMER", 0);\
+ d->lss_transfer.timerSDELAY = DelAlarm(d->lss_transfer.timerSDELAY);}
+
+#define StartLSS_SDELAY_TIMER(){\
+ MSG_WAR(0x3D04, "StartLSS_SDELAY_TIMER",0);\
+ d->lss_transfer.timerSDELAY= SetAlarm(d,0,&LssAlarmSDELAY,MS_TO_TIMEVAL(d->lss_transfer.switchDelay),MS_TO_TIMEVAL(d->lss_transfer.switchDelay));}
+
+
+#ifdef CO_ENABLE_LSS_FS
+/* Prototypes for internals functions */
+void LssAlarmFS(CO_Data* d, UNS32 id);
+
+#define StopLSS_FS_TIMER(){\
+ MSG_WAR(0x3D05, "StopLSS_FS_TIMER", id);\
+ d->lss_transfer.timerFS = DelAlarm(d->lss_transfer.timerFS);}
+
+#define StartLSS_FS_TIMER(){\
+ MSG_WAR(0x3D06, "StartLSS_FS_TIMER",0);\
+ d->lss_transfer.timerFS = SetAlarm(d,0,&LssAlarmFS,MS_TO_TIMEVAL(LSS_FS_TIMEOUT_MS),0);}
+#endif
+
+
+void LssAlarmMSG(CO_Data* d, UNS32 id)
+{	
+ 	StopLSS_MSG_TIMER();
+#ifdef CO_ENABLE_LSS_FS
+	if(d->lss_transfer.command==LSS_IDENT_FASTSCAN){
+		if(d->lss_transfer.FastScan_SM==LSS_FS_RESET){
+   			/* if at least one node had answered before the timer expired, start the FastScan protocol*/
+   			if(d->lss_transfer.LSSanswer!=0){
+   				UNS32 Mask=0xFFFFFFFF;
+   				d->lss_transfer.LSSanswer=0;
+   				d->lss_transfer.BitChecked=d->lss_transfer.lss_fs_transfer.FS_BitChecked[0];
+   				Mask=(UNS32)((UNS64)Mask<<(d->lss_transfer.BitChecked+1));
+   				d->lss_transfer.IDNumber=d->lss_transfer.lss_fs_transfer.FS_LSS_ID[0] & Mask;
+   				d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
+   				//printf("BitChecked=%d, IDNumber=%x MASK=%x\n",d->lss_transfer.BitChecked,d->lss_transfer.IDNumber,Mask);
+   				StartLSS_FS_TIMER();
+   				sendMasterLSSMessage(d,LSS_IDENT_FASTSCAN,0,0);
+   				return;
+   			}
+   			else{ 
+   			
+    			d->lss_transfer.state = LSS_FINISHED;
+    			/* Inform the application that there aren't not configured nodes in the net  */
+    			d->lss_transfer.dat1=1;
+   			}
+   		}
+   		else{
+			/* This should not happen, an error ocurred*/
+			MSG_ERR(0x1D07, "LSS FastScan timeout. FastScan_SM inconsisten state.", d->lss_transfer.FastScan_SM);
+			d->lss_transfer.state = LSS_ABORTED_INTERNAL;
+			d->lss_transfer.FastScan_SM=LSS_FS_RESET;
+   		}
+	}
+	else
+#endif
+	if(d->lss_transfer.command==LSS_IDENT_REMOTE_NON_CONF){
+			MSG_WAR(0x2D08, "LSS timeout. There are not no-configured slaves in the net", 0);
+			d->lss_transfer.state = LSS_FINISHED;
+			d->lss_transfer.dat1=1;
+	}
+	else{
+		MSG_ERR(0x1D09, "LSS timeout. LSS response not received.", 0);
+    	MSG_WAR(0x2D0A, "LSS timeout command specifier : ", d->lss_transfer.command);
+    	/* Set aborted state */
+    	d->lss_transfer.state = LSS_ABORTED_INTERNAL;
+#ifdef CO_ENABLE_LSS_FS
+    	d->lss_transfer.FastScan_SM = LSS_FS_RESET;
+#endif
+    }
+    	
+    /* Call the user function to inform of the problem.*/
+    if(d->lss_transfer.Callback){
+	   	/*If there is a callback, it is responsible of the error*/
+    	(*d->lss_transfer.Callback)(d,d->lss_transfer.command);
+    }
+}
+    
+    
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param id                                                                                       
+**/   
+void LssAlarmSDELAY(CO_Data* d, UNS32 id)
+{	
+	
+	/* The first switch_delay period expired. Store the node state, change it 
+ 	 * so no CAN messages will be sent or received, call the ChangeBaudRate function*/
+   	if(d->lss_transfer.switchDelayState==SDELAY_FIRST){
+   		MSG_WAR(0x3D0B, "LSS switch delay first period expired",0);
+    	d->lss_transfer.switchDelayState=SDELAY_SECOND;
+    	//(*d->lss_ChangeBaudRate)(d,d->lss_transfer.baudRate);
+    	canChangeBaudRate(d->lss_transfer.canHandle_t, d->lss_transfer.baudRate);
+    }
+    else{ /* d->lss_transfer.switchDelayState==SDELAY_SECOND */
+    	MSG_WAR(0x3D0C, "LSS switch delay second period expired",0);
+    	d->lss_transfer.switchDelayState=SDELAY_OFF;
+    	StopLSS_SDELAY_TIMER();
+    		
+    	if (*(d->iam_a_slave))
+    		d->canHandle=d->lss_transfer.canHandle_t;
+    	else{
+    		d->lss_transfer.dat1=0;
+    		d->lss_transfer.state=LSS_FINISHED;
+    		/* Call the user function */
+    		if(d->lss_transfer.Callback){
+	    		(*d->lss_transfer.Callback)(d,d->lss_transfer.command);
+    		}
+    	}
+    }
+} 
+
+#ifdef CO_ENABLE_LSS_FS
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param id                                                                                       
+**/   
+void LssAlarmFS(CO_Data* d, UNS32 id)
+{	
+	StopLSS_FS_TIMER();
+		
+	switch(d->lss_transfer.FastScan_SM){
+   	case LSS_FS_RESET:
+   	{
+   	   	/* This should not happen, an error ocurred*/
+		MSG_ERR(0x1D0D, "LSS FastScan timeout. FastScan_SM inconsisten state.", d->lss_transfer.FastScan_SM);
+   	}
+   	break;
+	case LSS_FS_PROCESSING:
+	{
+		/* If there isn't any answer, set the bit */
+		if(d->lss_transfer.LSSanswer==0){
+			UNS32 Mask=0x1;
+			Mask<<=d->lss_transfer.BitChecked;
+			d->lss_transfer.IDNumber|=Mask;
+		}
+		
+		if(d->lss_transfer.BitChecked==0){
+			/* We finished with the current LSS-ID[sub], confirm it */
+			d->lss_transfer.FastScan_SM=LSS_FS_CONFIRMATION;
+			if(d->lss_transfer.LSSNext<3)d->lss_transfer.LSSNext++;
+		}
+		else{
+			d->lss_transfer.BitChecked--;
+		}
+		//printf("BitChecked=%d, IDNumber=%x\n",d->lss_transfer.BitChecked,d->lss_transfer.IDNumber);
+   		d->lss_transfer.LSSanswer=0;
+  		StartLSS_FS_TIMER();
+   		sendMasterLSSMessage(d,LSS_IDENT_FASTSCAN,0,0);
+   		return;
+   	}
+	break;
+	case LSS_FS_CONFIRMATION:
+	{
+		if(d->lss_transfer.LSSanswer!=0){
+			d->lss_transfer.LSSanswer=0;
+			
+			if(d->lss_transfer.LSSSub==3){
+				/* The LSS FastScan protocol finished correctly. Restore the parameters */
+				d->lss_transfer.BitChecked=128;
+				d->lss_transfer.FastScan_SM=LSS_FS_RESET;
+				d->lss_transfer.LSSSub=0;
+				d->lss_transfer.LSSNext=0;
+   				d->lss_transfer.IDNumber=0;
+				
+				/* Inform the application that the FastScan finished correctly */
+				d->lss_transfer.state = LSS_FINISHED;
+				d->lss_transfer.dat1=0;
+			}
+			else{
+				UNS32 Mask=0xFFFFFFFF;
+				/* Start with the next LSS-ID[sub] */
+				d->lss_transfer.LSSSub++;
+				d->lss_transfer.BitChecked=d->lss_transfer.lss_fs_transfer.FS_BitChecked[d->lss_transfer.LSSSub];
+				Mask=(UNS32)((UNS64)Mask<<(d->lss_transfer.BitChecked+1));
+   				d->lss_transfer.IDNumber=d->lss_transfer.lss_fs_transfer.FS_LSS_ID[d->lss_transfer.LSSSub] & Mask;
+   				d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
+   				//printf("BitChecked=%d, IDNumber=%x MASK=%x\n",d->lss_transfer.BitChecked,d->lss_transfer.IDNumber,Mask);
+   				StartLSS_FS_TIMER();
+   				sendMasterLSSMessage(d,LSS_IDENT_FASTSCAN,0,0);
+   				return;
+			}
+		}
+		else{
+			/* This should not happen, an error ocurred*/
+			MSG_ERR(0x1D0E, "LSS FastScan timeout. FastScan response not received.", 0);
+			MSG_ERR(0x1D0E, "There is not any node with LSS_ID# =>", d->lss_transfer.LSSSub);
+			MSG_ERR(0x1D0E, "with the value =>", d->lss_transfer.IDNumber);
+			/* Set aborted state */
+    		d->lss_transfer.state = LSS_ABORTED_INTERNAL;
+    		d->lss_transfer.FastScan_SM = LSS_FS_RESET;
+		}
+	}
+	break;
+	}
+
+   	/* Call the user function to inform of the problem.*/
+   	if(d->lss_transfer.Callback){
+    	/*If there is a callback, it is responsible of the error*/
+   		(*d->lss_transfer.Callback)(d,d->lss_transfer.command);
+   	}
+}
+#endif
+
+	
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+**/ 
+void startLSS(CO_Data* d)
+{
+	/*MSG_WAR(0x3D09, "LSS services started",0);*/
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+**/   
+void stopLSS(CO_Data* d)
+{
+	/*MSG_WAR(0x3D09, "LSS services stopped",0);*/
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param cob_id                                                                                   
+**                                                                                                 
+** @return                                                                                         
+**/  
+UNS8 sendSlaveLSSMessage(CO_Data* d, UNS8 command,void *dat1,void *dat2)
+{
+  Message m;
+  UNS8 i;
+  
+  if (!d->CurrentCommunicationState.csLSS){
+  	MSG_WAR(0x2D17, "unable to send the LSS message, not in the proper state =>", d->nodeState);
+  	return 0xFF;
+  }
+   
+  for(i=1;i<8;i++)m.data[i]=0;
+  m.len = 8;
+  m.rtr = NOT_A_REQUEST;
+  m.data[0]=command;
+  m.cob_id=UNS16_LE(SLSS_ADRESS);
+  
+  /* Tha data sent with the msg depends on the command */
+  switch(command){
+  case LSS_INQ_NODE_ID: /* Inquire Node-ID */
+  	m.data[1]=*(UNS8 *)dat1;
+  	break;
+  case LSS_CONF_NODE_ID: /* Configure Node-ID */
+  case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
+  case LSS_CONF_STORE: /* Store Configured Parameters */
+  	m.data[1]=*(UNS8 *)dat1;
+  	m.data[2]=*(UNS8 *)dat2;
+  	break; 
+  case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
+  case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
+  case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
+  case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
+	m.data[1]=(UNS8)(*(UNS32*)dat1 & 0xFF);
+	m.data[2]=(UNS8)(*(UNS32*)dat1>>8 & 0xFF);
+	m.data[3]=(UNS8)(*(UNS32*)dat1>>16 & 0xFF);
+	m.data[4]=(UNS8)(*(UNS32*)dat1>>24 & 0xFF);
+	break;
+  case LSS_SM_SELECTIVE_RESP: /* Switch Mode Selective response*/
+  case LSS_IDENT_SLAVE: /* LSS Identify Slave */
+  case LSS_IDENT_NON_CONF_SLAVE: /* LSS identify non-configured remote slave */
+  	break;
+  default:
+  	MSG_ERR(0x1D18, "send Slave LSS command not implemented", command);
+  	return 0xFF;
+  }
+  
+  return canSend(d->canHandle,&m);
+}
+			
+/* If a baud rate is not supported just comment the line. */
+static UNS8 CO_TranslateBaudRate(char* optarg){
+	if(!strcmp( optarg, "1M")) return 0x00;
+	if(!strcmp( optarg, "800K")) return 0x01;
+	if(!strcmp( optarg, "500K")) return 0x02;
+	if(!strcmp( optarg, "250K")) return 0x03;
+	if(!strcmp( optarg, "125K")) return 0x04;
+	if(!strcmp( optarg, "100K")) return 0x05;
+	if(!strcmp( optarg, "50K")) return 0x06;
+	if(!strcmp( optarg, "20K")) return 0x07;
+	if(!strcmp( optarg, "10K")) return 0x08;
+	return 0xFF;
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param cob_id                                                                                   
+**                                                                                                 
+** @return                                                                                         
+**/  
+UNS8 sendMasterLSSMessage(CO_Data* d, UNS8 command,void *dat1,void *dat2)
+{
+  Message m;
+  UNS8 i;
+  UNS8 res;
+  UNS8 hasResponse=0;
+   
+  for(i=1;i<8;i++)m.data[i]=0;
+  m.len = 8;
+  m.rtr = NOT_A_REQUEST;
+  m.data[0]=command;
+  m.cob_id=UNS16_LE(MLSS_ADRESS);
+  
+  /* Tha data sent with the msg depends on the command */	
+  switch(command){
+  case LSS_CONF_NODE_ID: /* Configure Node-ID */
+  	hasResponse=1;
+  case LSS_SM_GLOBAL: /* Switch Mode Global */
+  	m.data[1]=*(UNS8 *)dat1;
+  	break;
+  case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
+  	
+  	m.data[1]=*(UNS8 *)dat1;
+  	d->lss_transfer.baudRate=*(char **)dat2;
+  	
+  	if((m.data[2]=CO_TranslateBaudRate(d->lss_transfer.baudRate))!=0xFF){
+  		hasResponse=1;
+		break;	 
+  	}
+  		
+	MSG_ERR(0x1D19, "Master-> Baud rate not supported",0);
+	d->lss_transfer.dat1=0xFF;
+	
+	/* if bit timing is not supported comment the previous code and uncomment the following one*/
+	/*{
+		MSG_ERR(0x1D1A, "Master-> Bit timing not supported",0);
+		d->lss_transfer.dat1=0x01;
+	}*/
+	
+	d->lss_transfer.dat2=0;
+ 	/* If there is a callback, it is responsible of the error */
+	if(d->lss_transfer.Callback)
+	   	(*d->lss_transfer.Callback)(d,d->lss_transfer.command);
+	return 0xFF;
+  	//break;
+  case LSS_CONF_ACT_BIT_TIMING: /* Activate Bit Timing Parameters */
+	m.data[1]=(UNS8)(*(UNS32*)dat1 & 0xFF);
+	m.data[2]=(UNS8)(*(UNS32*)dat1>>8 & 0xFF);
+	if(d->lss_transfer.baudRate!="none"){
+		d->lss_transfer.switchDelay=(UNS16)(*(UNS32*)dat1 & 0xFFFF);
+		d->lss_transfer.switchDelayState=SDELAY_FIRST;
+		d->lss_transfer.canHandle_t=d->canHandle;
+		res=canSend(d->canHandle,&m);
+  		if(res==0){
+  			StartLSS_SDELAY_TIMER();
+  			d->lss_transfer.state=LSS_TRANS_IN_PROGRESS;
+  		}
+  		return res;	
+	}
+	else{
+		MSG_ERR(0x1D1B, "Master-> Baud rate not specified",0);
+		d->lss_transfer.dat1=1;
+    	/* If there is a callback, it is responsible of the error */
+    	if(d->lss_transfer.Callback){
+	    	(*d->lss_transfer.Callback)(d,d->lss_transfer.command);
+    	}
+		return 0xFF;
+	}
+  	//break;
+  case LSS_SM_SELECTIVE_SERIAL:
+  case LSS_IDENT_REMOTE_SERIAL_HIGH:
+  	hasResponse=1;
+  case LSS_SM_SELECTIVE_VENDOR: /* Switch Mode Selective */
+  case LSS_SM_SELECTIVE_PRODUCT:
+  case LSS_SM_SELECTIVE_REVISION:
+  case LSS_IDENT_REMOTE_VENDOR: /* LSS Identify Remote Slaves */
+  case LSS_IDENT_REMOTE_PRODUCT:
+  case LSS_IDENT_REMOTE_REV_LOW:
+  case LSS_IDENT_REMOTE_REV_HIGH:
+  case LSS_IDENT_REMOTE_SERIAL_LOW:
+	m.data[1]=(UNS8)(*(UNS32*)dat1 & 0xFF);
+	m.data[2]=(UNS8)(*(UNS32*)dat1>>8 & 0xFF);
+	m.data[3]=(UNS8)(*(UNS32*)dat1>>16 & 0xFF);
+	m.data[4]=(UNS8)(*(UNS32*)dat1>>24 & 0xFF);
+	break;
+	
+  case LSS_CONF_STORE: /* Store Configured Parameters */
+  case LSS_IDENT_REMOTE_NON_CONF: /* LSS identify non-configured remote slave */
+  case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
+  case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
+  case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
+  case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
+  case LSS_INQ_NODE_ID: /* Inquire Node-ID */
+	 hasResponse=1;
+  	break;
+#ifdef CO_ENABLE_LSS_FS
+  case LSS_IDENT_FASTSCAN:
+	  	if(d->lss_transfer.FastScan_SM==LSS_FS_RESET){
+	  		UNS8 i;
+	  		 /* Initialize the lss_fs_transfer FastScan parameters */
+	  		for(i=0;i<4;i++){
+	  			d->lss_transfer.lss_fs_transfer.FS_LSS_ID[i]=(*(lss_fs_transfer_t*)dat1).FS_LSS_ID[i];
+	  			d->lss_transfer.lss_fs_transfer.FS_BitChecked[i]=(*(lss_fs_transfer_t*)dat1).FS_BitChecked[i];
+	  			/* Adjust BitChecked from 32-1 to 31-0 */
+	  			if(d->lss_transfer.lss_fs_transfer.FS_BitChecked[i]>0)d->lss_transfer.lss_fs_transfer.FS_BitChecked[i]--;
+	  		}
+	  		
+	  		d->lss_transfer.IDNumber=0;
+	  		d->lss_transfer.BitChecked=128;
+	  		d->lss_transfer.LSSSub=0;
+	  		d->lss_transfer.LSSNext=0;
+	  				
+	  		/* it will generate a response only if it is the start of the FastScan protocol*/
+	  		hasResponse=1;
+	  	}
+		m.data[1]=(UNS8)(d->lss_transfer.IDNumber & 0xFF);
+		m.data[2]=(UNS8)(d->lss_transfer.IDNumber>>8 & 0xFF);
+		m.data[3]=(UNS8)(d->lss_transfer.IDNumber>>16 & 0xFF);
+		m.data[4]=(UNS8)(d->lss_transfer.IDNumber>>24 & 0xFF);
+		m.data[5]=d->lss_transfer.BitChecked;
+		m.data[6]=d->lss_transfer.LSSSub;
+		m.data[7]=d->lss_transfer.LSSNext;
+	break;
+#endif
+  default:
+   	MSG_ERR(0x1D1C, "send Master LSS command not implemented", command);
+  	return 0xFF;
+  }
+	
+  res=canSend(d->canHandle,&m);
+  if(res==0 && hasResponse==1){
+  	StartLSS_MSG_TIMER();
+  	d->lss_transfer.state=LSS_TRANS_IN_PROGRESS;
+  }
+  return res;
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param cob_id                                                                                   
+**                                                                                                 
+** @return                                                                                         
+**/  
+UNS8 sendLSS(CO_Data* d, UNS8 command,void *dat1,void *dat2)
+{
+  UNS8 res=1;
+  
+  /* Tha data sent with the msg depends on the command and if the sender is a master or a slave */
+  if (*(d->iam_a_slave)){ 
+  	res = sendSlaveLSSMessage(d, command,dat1,dat2);
+  }
+  else {/* It is a Master */
+  	res = sendMasterLSSMessage(d, command,dat1,dat2);
+  }
+  return res ;
+}
+
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param m                                                                                        
+**                                                                                                 
+** @return                                                                                         
+**/ 
+UNS8 proceedLSS_Master(CO_Data* d, Message* m )
+{ 
+	UNS8 msg_cs;
+	UNS32 Dat1=0;
+	UNS8 Dat2=0;
+	
+	if(d->lss_transfer.state!=LSS_TRANS_IN_PROGRESS)
+	{
+		//MSG_WAR(0x3D0D, "MasterLSS proceedLSS; unexpected message arrived;command ", m->data[0]);
+		//return 0;
+		goto ErrorProcessMaster;
+	}
+	
+ 	MSG_WAR(0x3D1E, "MasterLSS proceedLSS; command ", m->data[0]);
+	
+   	switch(msg_cs=m->data[0]){
+   		case LSS_INQ_NODE_ID: /* Inquire Node-ID */
+   			if(d->lss_transfer.command!=LSS_INQ_NODE_ID)goto ErrorProcessMaster;
+   			Dat1=m->data[1];
+   			break;
+   		case LSS_CONF_NODE_ID: /* Configure Node-ID */
+   		case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
+   		case LSS_CONF_STORE: /* Store Configured Parameters */
+   			if(d->lss_transfer.command!=msg_cs)goto ErrorProcessMaster;
+   			Dat1=m->data[1];
+   			Dat2=m->data[2];
+   			break;
+   		case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
+   		case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
+   		case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
+   		case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
+   			if(d->lss_transfer.command!=msg_cs)goto ErrorProcessMaster;
+   			Dat1=getLSSIdent(m);
+ 			break;
+ 		case LSS_IDENT_SLAVE: /* LSS Identify Slave */
+#ifdef CO_ENABLE_LSS_FS
+   			if(d->lss_transfer.command==LSS_IDENT_FASTSCAN){
+   				/* A message arrived during the timer period */
+   				d->lss_transfer.LSSanswer=1;
+   				return 0;
+  			}
+  			else
+#endif
+			if(d->lss_transfer.command!=LSS_IDENT_REMOTE_VENDOR && \
+ 				d->lss_transfer.command!=LSS_IDENT_REMOTE_PRODUCT && \
+ 				d->lss_transfer.command!=LSS_IDENT_REMOTE_REV_LOW && \
+ 				d->lss_transfer.command!=LSS_IDENT_REMOTE_REV_HIGH && \
+ 				d->lss_transfer.command!=LSS_IDENT_REMOTE_SERIAL_LOW && \
+ 				d->lss_transfer.command!=LSS_IDENT_REMOTE_SERIAL_HIGH )
+ 					goto ErrorProcessMaster;
+  		break;
+ 		case LSS_SM_SELECTIVE_RESP: /* Switch Mode Selective response */
+ 			if(d->lss_transfer.command!=LSS_SM_SELECTIVE_VENDOR && \
+ 				d->lss_transfer.command!=LSS_SM_SELECTIVE_PRODUCT && \
+ 				d->lss_transfer.command!=LSS_SM_SELECTIVE_REVISION && \
+ 				d->lss_transfer.command!=LSS_SM_SELECTIVE_SERIAL )
+ 					goto ErrorProcessMaster;
+ 			break;
+   		case LSS_IDENT_NON_CONF_SLAVE: /* LSS identify non-configured remote slave */
+   			if(d->lss_transfer.command!=LSS_IDENT_REMOTE_NON_CONF)goto ErrorProcessMaster;
+   			break;
+   		default:
+   			MSG_ERR(0x1D1F, "Master LSS command not implemented", msg_cs);
+  			return 0xFF;
+   	}
+	
+	StopLSS_MSG_TIMER();
+    d->lss_transfer.state = LSS_FINISHED;
+    	
+	d->lss_transfer.dat1=Dat1;
+	d->lss_transfer.dat2=Dat2;
+ 	/* If there is a callback, it is responsible of the received response */
+	if(d->lss_transfer.Callback)
+    	(*d->lss_transfer.Callback)(d,d->lss_transfer.command);
+    			
+   return 0;
+   
+ErrorProcessMaster:
+    MSG_WAR(0x3D20, "MasterLSS proceedLSS; unexpected message arrived;command ", m->data[0]);
+	return 0xFF;
+		
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param m                                                                                        
+**                                                                                                 
+** @return                                                                                         
+**/ 
+UNS8 proceedLSS_Slave(CO_Data* d, Message* m )
+{  
+	UNS8 msg_cs;
+	
+  	MSG_WAR(0x3D21, "SlaveLSS proceedLSS; command ", m->data[0]);
+  	
+   	switch(msg_cs=m->data[0]){
+   	case LSS_SM_GLOBAL:		/* Switch Mode Global */
+   		/* if there is not a mode change break*/
+   		if(m->data[1] == d->lss_transfer.mode){
+   			MSG_WAR(0x3D22, "SlaveLSS already in the mode ", m->data[1]);
+   			break;
+   		}
+   		
+		if(m->data[1]==LSS_CONFIGURATION_MODE)	{
+			MSG_WAR(0x3D23, "SlaveLSS switching to configuration mode ", 0);
+			/* Store the NodeId in case it will be changed */
+			//d->lss_transfer.nodeID=getNodeId(d);
+			d->lss_transfer.mode=LSS_CONFIGURATION_MODE;
+		}
+		else if(m->data[1]==LSS_WAITING_MODE){
+			MSG_WAR(0x3D24, "SlaveLSS switching to operational mode ", 0);
+			
+			/* If the nodeID has changed update it and put the node state to Initialisation. */
+			if(d->lss_transfer.nodeID!=getNodeId(d)){
+				if(getNodeId(d)==0xFF){/* The nodeID was 0xFF; initialize the application*/
+					MSG_WAR(0x3D25, "The node Id has changed. Reseting to Initialisation state",0);
+					setNodeId(d, d->lss_transfer.nodeID);
+					setState(d, Initialisation);
+				}
+				else{/* The nodeID will be changed on NMT_Reset_Comunication Request*/
+				}
+			}
+			d->lss_transfer.mode=LSS_WAITING_MODE;
+		}
+	break;
+	case LSS_CONF_NODE_ID: /* Configure Node-ID */
+	{ 
+		UNS8 error_code=0;
+		UNS8 spec_error=0;
+			
+		if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE){
+			if(m->data[1]>127 && m->data[1]!=0xFF){
+				MSG_ERR(0x1D26, "NodeID out of range",0);
+				error_code=1; /* NodeID out of range */
+			}
+			else{
+				d->lss_transfer.nodeID=m->data[1];
+			}
+		}
+		else{
+			MSG_WAR(0x3D27, "SlaveLSS not in configuration mode",0);
+			//error_code=0xFF;
+			break;
+		}
+		sendSlaveLSSMessage(d,msg_cs,&error_code,&spec_error);
+	}	
+	break;
+	case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
+	{
+		UNS8 error_code=0;
+		UNS8 spec_error=0;
+			
+		if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE){
+			/* If a baud rate is not supported just comment the line. */
+			switch(m->data[2]){
+			case 0x00:d->lss_transfer.baudRate="1M";break;
+			case 0x01:d->lss_transfer.baudRate="800K";break;
+			case 0x02:d->lss_transfer.baudRate="500K";break;
+			case 0x03:d->lss_transfer.baudRate="250K";break;
+			case 0x04:d->lss_transfer.baudRate="125K";break;
+			case 0x05:d->lss_transfer.baudRate="100K";break;
+			case 0x06:d->lss_transfer.baudRate="50K";break;
+			case 0x07:d->lss_transfer.baudRate="20K";break;
+			case 0x08:d->lss_transfer.baudRate="10K";break;
+			default:
+				MSG_ERR(0x1D28, "Baud rate not supported",0);
+				error_code=0xFF; /* Baud rate not supported*/
+				break; 		
+			}
+		}
+		else{
+			MSG_WAR(0x3D2A, "SlaveLSS not in configuration mode",0);
+			//error_code=0xFF;
+			break;
+		}
+		
+		/* if bit timing is not supported comment the previous code and uncomment the following */
+		/*{
+			MSG_ERR(0x1D29, "Bit timing not supported",0);
+			error_code=0x01; // bit timing not supported 
+		}*/
+			
+		sendSlaveLSSMessage(d,msg_cs,&error_code,&spec_error);
+	}
+	break;
+	case LSS_CONF_ACT_BIT_TIMING: /* Activate Bit Timing Parameters */
+		
+		if(d->lss_transfer.mode!=LSS_CONFIGURATION_MODE){
+			MSG_ERR(0x3D2B, "SlaveLSS not in configuration mode",0);
+			break;
+		}
+		
+		if(d->lss_transfer.baudRate!="none"){
+			d->lss_transfer.switchDelay=getLSSDelay(m);
+			MSG_WAR(0x3D2C, "Slave Switch Delay set to: ",d->lss_transfer.switchDelay);
+			d->lss_transfer.switchDelayState=SDELAY_FIRST;
+			//d->lss_transfer.currentState=getState(d);
+			//setState(d, LssTimingDelay);
+			d->lss_transfer.canHandle_t=d->canHandle;
+			d->canHandle=NULL;
+			StartLSS_SDELAY_TIMER();
+		}
+	break;
+	case LSS_CONF_STORE: /* Store Configured Parameters */
+	{
+		UNS8 error_code=0;
+		UNS8 spec_error=0;
+		
+		if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE){ 
+			if(d->lss_StoreConfiguration){
+				 /* call lss_StoreConfiguration with NodeId */
+	  			(*d->lss_StoreConfiguration)(d,&error_code,&spec_error);
+			}
+			else{
+				MSG_ERR(0x1D2E, "Store configuration not supported",0);
+				error_code=1; /* store configuration is not supported */
+			}	
+		}
+		else{
+			MSG_WAR(0x3D2F, "SlaveLSS not in configuration mode",0);
+			//error_code=0xFF;
+			break;
+		}
+		sendSlaveLSSMessage(d,msg_cs,&error_code,&spec_error);
+	}
+	break;
+	case LSS_SM_SELECTIVE_VENDOR:	/* Switch Mode Selective */
+	case LSS_SM_SELECTIVE_PRODUCT:
+	case LSS_SM_SELECTIVE_REVISION:
+	case LSS_SM_SELECTIVE_SERIAL:
+	{
+		UNS32 errorCode;
+  		const indextable *ptrTable;
+  		ODCallback_t *Callback;
+  		UNS32 _SpecificNodeInfo;
+  
+  		if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE)
+  		{
+  			MSG_ERR(0x1D30, "Switch Mode Selective only supported in operational mode",0);
+  			break;
+  		}
+  			
+		_SpecificNodeInfo=getLSSIdent(m);
+				
+		ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
+		if(_SpecificNodeInfo==*(UNS32*)ptrTable->pSubindex[msg_cs-(LSS_SM_SELECTIVE_VENDOR-1)].pObject){
+			
+			d->lss_transfer.addr_sel_match|=(0x01<<(msg_cs-LSS_SM_SELECTIVE_VENDOR));
+			/* If all the fields has been set */
+			if(d->lss_transfer.addr_sel_match==0x0F){
+				
+				MSG_WAR(0x3D31, "SlaveLSS switching to configuration mode ", 0);
+				d->lss_transfer.addr_sel_match=0;
+				d->lss_transfer.nodeID=getNodeId(d);
+				d->lss_transfer.mode=LSS_CONFIGURATION_MODE;
+
+				sendSlaveLSSMessage(d,LSS_SM_SELECTIVE_RESP,0,0);
+			}
+		}	
+		else {
+			MSG_WAR(0x3D32, "LSS identity field doesn't match ", _SpecificNodeInfo);
+			d->lss_transfer.addr_sel_match=0;
+		}	
+	}	
+	break;
+	case LSS_IDENT_REMOTE_VENDOR: /* LSS Identify Remote Slaves */
+	case LSS_IDENT_REMOTE_PRODUCT:
+	case LSS_IDENT_REMOTE_REV_LOW:
+	case LSS_IDENT_REMOTE_REV_HIGH:
+	case LSS_IDENT_REMOTE_SERIAL_LOW:
+	case LSS_IDENT_REMOTE_SERIAL_HIGH:
+	{
+		UNS32 errorCode;
+  		const indextable *ptrTable;
+  		ODCallback_t *Callback;
+  		UNS32 _SpecificNodeInfo;
+  		
+		_SpecificNodeInfo=getLSSIdent(m);
+		
+		ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
+			
+		/* Check if the data match the identity object. */
+		switch(msg_cs){
+		case LSS_IDENT_REMOTE_VENDOR:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo == *(UNS32*)ptrTable->pSubindex[1].pObject)? d->lss_transfer.addr_ident_match|0x01:0;	break;
+		case LSS_IDENT_REMOTE_PRODUCT:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo == *(UNS32*)ptrTable->pSubindex[2].pObject)? d->lss_transfer.addr_ident_match|0x02:0;	break;
+		case LSS_IDENT_REMOTE_REV_LOW:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo <= *(UNS32*)ptrTable->pSubindex[3].pObject)? d->lss_transfer.addr_ident_match|0x04:0; break;
+		case LSS_IDENT_REMOTE_REV_HIGH:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo >= *(UNS32*)ptrTable->pSubindex[3].pObject)? d->lss_transfer.addr_ident_match|0x08:0;	break;
+		case LSS_IDENT_REMOTE_SERIAL_LOW:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo <= *(UNS32*)ptrTable->pSubindex[4].pObject)? d->lss_transfer.addr_ident_match|0x10:0;	break;
+		case LSS_IDENT_REMOTE_SERIAL_HIGH:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo >= *(UNS32*)ptrTable->pSubindex[4].pObject)? d->lss_transfer.addr_ident_match|0x20:0;	break;
+		}
+		/* If all the fields has been set.. */
+		if(d->lss_transfer.addr_ident_match==0x3F){
+			MSG_WAR(0x3D33, "SlaveLSS identified ", 0);
+			d->lss_transfer.addr_ident_match=0;
+			sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
+		}
+		else if(d->lss_transfer.addr_ident_match==0){
+			MSG_WAR(0x3D34, "LSS identify field doesn't match ", _SpecificNodeInfo);
+		}
+	}
+	break;
+	case LSS_IDENT_REMOTE_NON_CONF: /* LSS identify non-configured remote slave */
+	{
+		if(getNodeId(d)==0xFF){		
+			MSG_WAR(0x3D35, "SlaveLSS non-configured ", 0);
+			sendSlaveLSSMessage(d,LSS_IDENT_NON_CONF_SLAVE,0,0);
+		}
+		else{
+			MSG_WAR(0x3D36, "SlaveLSS already configured ", 0);
+		}
+	}
+	break;
+	case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
+	case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
+	case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
+	case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
+	if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE)
+	{
+	
+		UNS32 errorCode;
+  		const indextable *ptrTable;
+  		ODCallback_t *Callback;
+  		UNS32 _SpecificNodeInfo;
+  
+  		ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
+  		_SpecificNodeInfo=*(UNS32*)ptrTable->pSubindex[msg_cs-(LSS_INQ_VENDOR_ID-1)].pObject;
+  		MSG_WAR(0x3D37, "SlaveLSS identity field inquired ", _SpecificNodeInfo);
+			
+		sendSlaveLSSMessage(d,msg_cs,&_SpecificNodeInfo,0);
+	}
+	break;
+	case LSS_INQ_NODE_ID: /* Inquire Node-ID */
+		if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE)
+		{
+			UNS8 NodeID;
+	
+			NodeID=getNodeId(d);
+			MSG_WAR(0x3D38, "SlaveLSS Node ID inquired ", NodeID);
+			sendSlaveLSSMessage(d,msg_cs,&NodeID,0);
+		}
+		else{
+			MSG_WAR(0x3D39, "SlaveLSS not in configuration mode",0);
+		}
+	break;
+#ifdef CO_ENABLE_LSS_FS
+	case LSS_IDENT_FASTSCAN:
+	{
+		/* If the nodeID isn't 0xFF the slave shall not participate  */
+		if(getNodeId(d)!=0xFF)break;
+		if(getLSSBitCheck(m)==128)d->lss_transfer.FastScan_SM=LSS_FS_RESET;
+		
+   		switch(d->lss_transfer.FastScan_SM){
+   		case LSS_FS_RESET:
+   		{
+   			UNS32 errorCode;
+  			const indextable *ptrTable;
+  			ODCallback_t *Callback;
+  				
+			MSG_WAR(0x3D3A, "SlaveLSS Reseting LSSPos", 0);
+			d->lss_transfer.LSSPos=0;
+			d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
+			
+  			ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
+  			d->lss_transfer.IDNumber=*(UNS32*)ptrTable->pSubindex[d->lss_transfer.LSSPos+1].pObject;
+			
+			sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
+   		}
+		break;
+		case LSS_FS_PROCESSING:/*if(getLSSBitCheck(m)<32)*/
+			if(d->lss_transfer.LSSPos==getLSSSub(m))
+			{
+				UNS32 Mask=0xFFFFFFFF<<getLSSBitCheck(m);
+				
+				MSG_WAR(0x3D3B, "SlaveLSS FastScan IDNumber", getLSSIdent(m));
+				MSG_WAR(0x3D3C, "SlaveLSS FastScan BitMask ", Mask);
+				MSG_WAR(0x3D3D, "SlaveLSS FastScan LSS-ID  ", d->lss_transfer.IDNumber);
+				
+				if((getLSSIdent(m) & Mask)==(d->lss_transfer.IDNumber & Mask))
+				{
+					sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
+				}
+				
+				if(getLSSBitCheck(m)==0)
+				{
+					d->lss_transfer.FastScan_SM=LSS_FS_CONFIRMATION;
+				}
+			}
+			break;
+		case LSS_FS_CONFIRMATION:
+			if(d->lss_transfer.LSSPos==getLSSSub(m))
+			{
+				if(getLSSIdent(m)==d->lss_transfer.IDNumber)
+				{
+					/* Current LSS-ID[sub] confirmed correctly */
+					MSG_WAR(0x3D3E, "SlaveLSS FastScan IDNumber and LSS-ID match=>", d->lss_transfer.IDNumber);
+					if(d->lss_transfer.LSSPos==3)
+					{
+						/* All LSS-ID[sub] identified correctly, switching to configuration mode */
+						MSG_WAR(0x3D3F, "SlaveLSS switching to configuration mode ", 0);
+			   			d->lss_transfer.nodeID=getNodeId(d);
+			   			d->lss_transfer.mode=LSS_CONFIGURATION_MODE;
+			    		d->lss_transfer.FastScan_SM=LSS_FS_RESET;
+			    		d->lss_transfer.LSSPos=0xFF;
+					}		
+					else
+					{
+						/* Switch to the next LSS-ID[sub] */
+						UNS32 errorCode;
+  						const indextable *ptrTable;
+  						ODCallback_t *Callback;
+		
+						d->lss_transfer.LSSPos=getLSSNext(m);
+						ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
+  						d->lss_transfer.IDNumber=*(UNS32*)ptrTable->pSubindex[d->lss_transfer.LSSPos+1].pObject;
+						d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;						
+					}
+					sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
+				}
+			}
+			break;
+		}
+	}	
+	break;
+#endif
+   	default:
+   		MSG_ERR(0x1D40, "SlaveLSS command not implemented", msg_cs);
+  		return 0xFF;
+   	}
+   
+    return 0;
+}
+
+/*UNS8 configNetworkNode(CO_Data* d, UNS8 command, void *dat1, void* dat2)
+{
+	return sendMasterLSSMessage(d,command,dat1,dat2);
+}*/
+
+UNS8 configNetworkNode (CO_Data* d, UNS8 command, void *dat1, void* dat2, LSSCallback_t Callback)
+{
+	//d->lss_transfer.state=LSS_TRANS_IN_PROGRESS;
+	d->lss_transfer.Callback=Callback;
+	d->lss_transfer.command=command;
+	
+	StopLSS_MSG_TIMER();
+  	//StartLSS_MSG_TIMER();
+  	
+	return sendMasterLSSMessage(d,command,dat1,dat2);
+}
+
+UNS8 getConfigResultNetworkNode (CO_Data* d, UNS8 command, UNS32* dat1, UNS8* dat2)
+{ 
+  *dat1=d->lss_transfer.dat1;
+  *dat2=d->lss_transfer.dat2;
+  return d->lss_transfer.state;
+}
+
+//void _lss_StoreConfiguration(UNS8 *error, UNS8 *spec_error){printf("_lss_StoreConfiguration\n");}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/nmtMaster.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,112 @@
+/*
+  This file is part of CanFestival, a library implementing CanOpen
+  Stack.
+
+  Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+  See COPYING file for copyrights details.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+  USA
+*/
+/*!
+** @file   nmtMaster.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Tue Jun  5 08:47:18 2007
+**
+** @brief
+**
+**
+*/
+#include "nmtMaster.h"
+#include "canfestival.h"
+#include "sysdep.h"
+
+/*!
+**
+**
+** @param d
+** @param Node_ID
+** @param cs
+**
+** @return
+**/
+UNS8 masterSendNMTstateChange(CO_Data* d, UNS8 Node_ID, UNS8 cs)
+{
+  Message m;
+
+  MSG_WAR(0x3501, "Send_NMT cs : ", cs);
+  MSG_WAR(0x3502, "    to node : ", Node_ID);
+  /* message configuration */
+  m.cob_id = 0x0000; /*(NMT) << 7*/
+  m.rtr = NOT_A_REQUEST;
+  m.len = 2;
+  m.data[0] = cs;
+  m.data[1] = Node_ID;
+
+  return canSend(d->canHandle,&m);
+}
+
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+**
+** @return
+**/
+UNS8 masterSendNMTnodeguard(CO_Data* d, UNS8 nodeId)
+{
+  Message m;
+
+  /* message configuration */
+  UNS16 tmp = nodeId | (NODE_GUARD << 7); 
+  m.cob_id = UNS16_LE(tmp);
+  m.rtr = REQUEST;
+  m.len = 0;
+
+  MSG_WAR(0x3503, "Send_NODE_GUARD to node : ", nodeId);
+
+  return canSend(d->canHandle,&m);
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+**
+** @return
+**/
+UNS8 masterRequestNodeState(CO_Data* d, UNS8 nodeId)
+{
+  /* FIXME: should warn for bad toggle bit. */
+
+  /* NMTable configuration to indicate that the master is waiting
+    for a Node_Guard frame from the slave whose node_id is ID
+  */
+  d->NMTable[nodeId] = Unknown_state; /* A state that does not exist
+                                       */
+
+  if (nodeId == 0) { /* NMT broadcast */
+    UNS8 i = 0;
+    for (i = 0 ; i < NMT_MAX_NODE_ID ; i++) {
+      d->NMTable[i] = Unknown_state;
+    }
+  }
+  return masterSendNMTnodeguard(d,nodeId);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/nmtSlave.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,139 @@
+/*
+  This file is part of CanFestival, a library implementing CanOpen
+  Stack.
+
+  Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+  See COPYING file for copyrights details.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+  USA
+*/
+/*!
+** @file   nmtSlave.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Tue Jun  5 08:50:53 2007
+**
+** @brief
+**
+**
+*/
+#include "nmtSlave.h"
+#include "states.h"
+#include "canfestival.h"
+#include "sysdep.h"
+
+/*!
+** put the slave in the state wanted by the master
+**
+** @param d
+** @param m
+**/
+void proceedNMTstateChange(CO_Data* d, Message *m)
+{
+  if( d->nodeState == Pre_operational ||
+      d->nodeState == Operational ||
+      d->nodeState == Stopped ) {
+
+    MSG_WAR(0x3400, "NMT received. for node :  ", (*m).data[1]);
+
+    /* Check if this NMT-message is for this node */
+    /* byte 1 = 0 : all the nodes are concerned (broadcast) */
+
+    if( ( (*m).data[1] == 0 ) || ( (*m).data[1] == *d->bDeviceNodeId ) ){
+
+      switch( (*m).data[0]){ /* command specifier (cs) */
+      case NMT_Start_Node:
+        if ( (d->nodeState == Pre_operational) || (d->nodeState == Stopped) )
+          setState(d,Operational);
+        break;
+
+      case NMT_Stop_Node:
+        if ( d->nodeState == Pre_operational ||
+             d->nodeState == Operational )
+          setState(d,Stopped);
+        break;
+
+      case NMT_Enter_PreOperational:
+        if ( d->nodeState == Operational ||
+             d->nodeState == Stopped )
+          setState(d,Pre_operational);
+        break;
+
+      case NMT_Reset_Node:
+         if(d->NMT_Slave_Node_Reset_Callback != NULL)
+            d->NMT_Slave_Node_Reset_Callback(d);
+        setState(d,Initialisation);
+        break;
+
+      case NMT_Reset_Comunication:
+         {
+         UNS8 currentNodeId = getNodeId(d);
+         
+            if(d->NMT_Slave_Communications_Reset_Callback != NULL)
+               d->NMT_Slave_Communications_Reset_Callback(d);
+#ifdef CO_ENABLE_LSS
+            // LSS changes NodeId here in case lss_transfer.nodeID doesn't 
+            // match current getNodeId()
+            if(currentNodeId!=d->lss_transfer.nodeID)
+               currentNodeId = d->lss_transfer.nodeID;
+#endif
+
+            // clear old NodeId to make SetNodeId reinitializing
+            // SDO, EMCY and other COB Ids
+            *d->bDeviceNodeId = 0xFF; 
+         
+            setNodeId(d, currentNodeId);
+         }
+         setState(d,Initialisation);
+         break;
+
+      }/* end switch */
+
+    }/* end if( ( (*m).data[1] == 0 ) || ( (*m).data[1] ==
+        bDeviceNodeId ) ) */
+  }
+}
+
+
+/*!
+**
+**
+** @param d
+**
+** @return
+**/
+UNS8 slaveSendBootUp(CO_Data* d)
+{
+  Message m;
+
+#ifdef CO_ENABLE_LSS
+  if(*d->bDeviceNodeId==0xFF)return 0;
+#endif
+
+  MSG_WAR(0x3407, "Send a Boot-Up msg ", 0);
+
+  /* message configuration */
+  {
+	  UNS16 tmp = NODE_GUARD << 7 | *d->bDeviceNodeId; 
+	  m.cob_id = UNS16_LE(tmp);
+  }
+  m.rtr = NOT_A_REQUEST;
+  m.len = 1;
+  m.data[0] = 0x00;
+
+  return canSend(d->canHandle,&m);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/objacces.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,282 @@
+/*
+  This file is part of CanFestival, a library implementing CanOpen
+  Stack.
+
+  Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+  See COPYING file for copyrights details.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+  USA
+*/
+/*!
+** @file   objacces.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Tue Jun  5 08:55:23 2007
+**
+** @brief
+**
+**
+*/
+
+
+
+
+/* #define DEBUG_WAR_CONSOLE_ON */
+/* #define DEBUG_ERR_CONSOLE_ON */
+
+
+#include "data.h"
+
+//We need the function implementation for linking
+//Only a placeholder with a define isnt enough!
+UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex,
+                           UNS32 sizeDataDict, UNS32 sizeDataGiven, UNS32 code)
+{
+#ifdef DEBUG_WAR_CONSOLE_ON
+  MSG_WAR(0x2B09,"Dictionary index : ", index);
+  MSG_WAR(0X2B10,"           subindex : ", subIndex);
+  switch (code) {
+  case  OD_NO_SUCH_OBJECT:
+    MSG_WAR(0x2B11,"Index not found ", index);
+    break;
+  case OD_NO_SUCH_SUBINDEX :
+    MSG_WAR(0x2B12,"SubIndex not found ", subIndex);
+    break;
+  case OD_WRITE_NOT_ALLOWED :
+    MSG_WAR(0x2B13,"Write not allowed, data is read only ", index);
+    break;
+  case OD_LENGTH_DATA_INVALID :
+    MSG_WAR(0x2B14,"Conflict size data. Should be (bytes)  : ", sizeDataDict);
+    MSG_WAR(0x2B15,"But you have given the size  : ", sizeDataGiven);
+    break;
+  case OD_NOT_MAPPABLE :
+    MSG_WAR(0x2B16,"Not mappable data in a PDO at index    : ", index);
+    break;
+  case OD_VALUE_TOO_LOW :
+    MSG_WAR(0x2B17,"Value range error : value too low. SDOabort : ", code);
+    break;
+  case OD_VALUE_TOO_HIGH :
+    MSG_WAR(0x2B18,"Value range error : value too high. SDOabort : ", code);
+    break;
+  default :
+    MSG_WAR(0x2B20, "Unknown error code : ", code);
+  }
+  #endif
+
+  return 0;
+}
+
+UNS32 _getODentry( CO_Data* d,
+                   UNS16 wIndex,
+                   UNS8 bSubindex,
+                   void * pDestData,
+                   UNS32 * pExpectedSize,
+                   UNS8 * pDataType,
+                   UNS8 checkAccess,
+                   UNS8 endianize)
+{ /* DO NOT USE MSG_ERR because the macro may send a PDO -> infinite
+    loop if it fails. */
+  UNS32 errorCode;
+  UNS32 szData;
+  const indextable *ptrTable;
+  ODCallback_t *Callback;
+
+  ptrTable = (*d->scanIndexOD)(wIndex, &errorCode, &Callback);
+
+  if (errorCode != OD_SUCCESSFUL)
+    return errorCode;
+  if( ptrTable->bSubCount <= bSubindex ) {
+    /* Subindex not found */
+    accessDictionaryError(wIndex, bSubindex, 0, 0, OD_NO_SUCH_SUBINDEX);
+    return OD_NO_SUCH_SUBINDEX;
+  }
+
+  if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType & WO)) {
+    MSG_WAR(0x2B30, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
+    accessDictionaryError(wIndex, bSubindex, 0, 0, OD_READ_NOT_ALLOWED);
+    return OD_READ_NOT_ALLOWED;
+  }
+
+  *pDataType = ptrTable->pSubindex[bSubindex].bDataType;
+  szData = ptrTable->pSubindex[bSubindex].size;
+
+  if(*pExpectedSize == 0 ||
+     *pExpectedSize == szData ||
+     /* allow to fetch a shorter string than expected */
+     (*pDataType >= visible_string && *pExpectedSize < szData)) { 
+
+#  ifdef CANOPEN_BIG_ENDIAN
+     if(endianize && *pDataType > boolean && !(
+            *pDataType >= visible_string && 
+            *pDataType <= domain)) {
+      /* data must be transmited with low byte first */
+      UNS8 i, j = 0;
+      MSG_WAR(boolean, "data type ", *pDataType);
+      MSG_WAR(visible_string, "data type ", *pDataType);
+      for ( i = szData ; i > 0 ; i--) {
+        MSG_WAR(i," ", j);
+        ((UNS8*)pDestData)[j++] =
+          ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[i-1];
+      }
+      *pExpectedSize = szData;
+    }
+    else /* no endianisation change */
+#  endif
+    if(*pDataType != visible_string) {
+        memcpy(pDestData, ptrTable->pSubindex[bSubindex].pObject,szData);
+        *pExpectedSize = szData;
+    }else{
+        /* TODO : CONFORM TO DS-301 : 
+         *  - stop using NULL terminated strings
+         *  - store string size in td_subindex 
+         * */
+        /* Copy null terminated string to user, and return discovered size */
+        UNS8 *ptr = (UNS8*)ptrTable->pSubindex[bSubindex].pObject;
+        UNS8 *ptr_start = ptr;
+        /* *pExpectedSize IS < szData . if null, use szData */
+        UNS8 *ptr_end = ptr + (*pExpectedSize ? *pExpectedSize : szData) ; 
+        UNS8 *ptr_dest = (UNS8*)pDestData;
+        while( *ptr && ptr < ptr_end){
+            *(ptr_dest++) = *(ptr++);
+        } 
+         
+        *pExpectedSize = (UNS32) (ptr - ptr_start);
+        /* terminate string if not maximum length */
+        if (*pExpectedSize < szData) 
+            *(ptr) = 0; 
+    }
+
+    return OD_SUCCESSFUL;
+  }
+  else { /* Error ! */
+    *pExpectedSize = szData;
+    accessDictionaryError(wIndex, bSubindex, szData,
+                          *pExpectedSize, OD_LENGTH_DATA_INVALID);
+    return OD_LENGTH_DATA_INVALID;
+  }
+}
+
+UNS32 _setODentry( CO_Data* d,
+                   UNS16 wIndex,
+                   UNS8 bSubindex,
+                   void * pSourceData,
+                   UNS32 * pExpectedSize,
+                   UNS8 checkAccess,
+                   UNS8 endianize)
+{
+  UNS32 szData;
+  UNS8 dataType;
+  UNS32 errorCode;
+  const indextable *ptrTable;
+  ODCallback_t *Callback;
+
+  ptrTable =(*d->scanIndexOD)(wIndex, &errorCode, &Callback);
+  if (errorCode != OD_SUCCESSFUL)
+    return errorCode;
+
+  if( ptrTable->bSubCount <= bSubindex ) {
+    /* Subindex not found */
+    accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_NO_SUCH_SUBINDEX);
+    return OD_NO_SUCH_SUBINDEX;
+  }
+  if (checkAccess && (ptrTable->pSubindex[bSubindex].bAccessType == RO)) {
+    MSG_WAR(0x2B25, "Access Type : ", ptrTable->pSubindex[bSubindex].bAccessType);
+    accessDictionaryError(wIndex, bSubindex, 0, *pExpectedSize, OD_WRITE_NOT_ALLOWED);
+    return OD_WRITE_NOT_ALLOWED;
+  }
+
+
+  dataType = ptrTable->pSubindex[bSubindex].bDataType;
+  szData = ptrTable->pSubindex[bSubindex].size;
+
+  if( *pExpectedSize == 0 ||
+      *pExpectedSize == szData ||
+      /* allow to store a shorter string than entry size */
+      (dataType == visible_string && *pExpectedSize < szData))
+    {
+#ifdef CANOPEN_BIG_ENDIAN
+      /* re-endianize do not occur for bool, strings time and domains */
+      if(endianize && dataType > boolean && !(
+            dataType >= visible_string && 
+            dataType <= domain))
+        {
+          /* we invert the data source directly. This let us do range
+            testing without */
+          /* additional temp variable */
+          UNS8 i;
+          for ( i = 0 ; i < ( ptrTable->pSubindex[bSubindex].size >> 1)  ; i++)
+            {
+              UNS8 tmp =((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i];
+              ((UNS8 *)pSourceData) [(ptrTable->pSubindex[bSubindex].size - 1) - i] = ((UNS8 *)pSourceData)[i];
+              ((UNS8 *)pSourceData)[i] = tmp;
+            }
+        }
+#endif
+      errorCode = (*d->valueRangeTest)(dataType, pSourceData);
+      if (errorCode) {
+        accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, errorCode);
+        return errorCode;
+      }
+      memcpy(ptrTable->pSubindex[bSubindex].pObject,pSourceData, *pExpectedSize);
+     /* TODO : CONFORM TO DS-301 : 
+      *  - stop using NULL terminated strings
+      *  - store string size in td_subindex 
+      * */
+      /* terminate visible_string with '\0' */
+      if(dataType == visible_string && *pExpectedSize < szData)
+        ((UNS8*)ptrTable->pSubindex[bSubindex].pObject)[*pExpectedSize] = 0;
+      
+      *pExpectedSize = szData;
+
+      /* Callbacks */
+      if(Callback && Callback[bSubindex]){
+        errorCode = (Callback[bSubindex])(d, ptrTable, bSubindex);
+        if(errorCode != OD_SUCCESSFUL)
+        {
+            return errorCode;
+        }
+       }
+
+      /* TODO : Store dans NVRAM */
+      if (ptrTable->pSubindex[bSubindex].bAccessType & TO_BE_SAVE){
+        (*d->storeODSubIndex)(d, wIndex, bSubindex);
+      }
+      return OD_SUCCESSFUL;
+    }else{
+      *pExpectedSize = szData;
+      accessDictionaryError(wIndex, bSubindex, szData, *pExpectedSize, OD_LENGTH_DATA_INVALID);
+      return OD_LENGTH_DATA_INVALID;
+    }
+}
+
+const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback)
+{
+  return (*d->scanIndexOD)(wIndex, errorCode, Callback);
+}
+
+UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback)
+{
+UNS32 errorCode;
+ODCallback_t *CallbackList;
+const indextable *odentry;
+
+  odentry = scanIndexOD (d, wIndex, &errorCode, &CallbackList);
+  if(errorCode == OD_SUCCESSFUL  &&  CallbackList  &&  bSubindex < odentry->bSubCount) 
+    CallbackList[bSubindex] = Callback;
+  return errorCode;
+}
+
+void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex){}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/pdo.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,842 @@
+/*
+  This file is part of CanFestival, a library implementing CanOpen
+  Stack.
+
+  Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+  See COPYING file for copyrights details.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+  USA
+*/
+#include "pdo.h"
+#include "objacces.h"
+#include "canfestival.h"
+#include "sysdep.h"
+
+/*!
+** @file   pdo.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Tue Jun  5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
+
+/*!
+**
+**
+** @param d
+** @param TPDO_com TPDO communication parameters OD entry
+** @param TPDO_map TPDO mapping parameters OD entry
+**
+** @return
+**/
+
+UNS8 buildPDO (CO_Data * d, UNS8 numPdo, Message * pdo)
+{
+  const indextable *TPDO_com = d->objdict + d->firstIndex->PDO_TRS + numPdo;
+  const indextable *TPDO_map = d->objdict + d->firstIndex->PDO_TRS_MAP + numPdo;
+
+  UNS8 prp_j = 0x00;
+  UNS32 offset = 0x00000000;
+  const UNS8 *pMappingCount = (UNS8 *) TPDO_map->pSubindex[0].pObject;
+
+  pdo->cob_id = (UNS16) UNS16_LE(*(UNS32*)TPDO_com->pSubindex[1].pObject & 0x7FF);
+  pdo->rtr = NOT_A_REQUEST;
+
+  MSG_WAR (0x3009, "  PDO CobId is : ",
+           *(UNS32 *) TPDO_com->pSubindex[1].pObject);
+  MSG_WAR (0x300D, "  Number of objects mapped : ", *pMappingCount);
+
+  do
+    {
+      UNS8 dataType;            /* Unused */
+      UNS8 tmp[] = { 0, 0, 0, 0, 0, 0, 0, 0 };  /* temporary space to hold bits */
+
+      /* pointer fo the var which holds the mapping parameter of an mapping entry  */
+      UNS32 *pMappingParameter =
+        (UNS32 *) TPDO_map->pSubindex[prp_j + 1].pObject;
+      UNS16 index = (UNS16) ((*pMappingParameter) >> 16);
+      UNS32 Size = (UNS32) (*pMappingParameter & (UNS32) 0x000000FF);     /* Size in bits */
+
+      /* get variable only if Size != 0 and Size is lower than remaining bits in the PDO */
+      if (Size && ((offset + Size) <= 64))
+        {
+          UNS32 ByteSize = 1 + ((Size - 1) >> 3);        /*1->8 => 1 ; 9->16 => 2, ... */
+          UNS8 subIndex =
+            (UNS8) (((*pMappingParameter) >> (UNS8) 8) & (UNS32) 0x000000FF);
+
+          MSG_WAR (0x300F, "  got mapping parameter : ", *pMappingParameter);
+          MSG_WAR (0x3050, "    at index : ", TPDO_map->index);
+          MSG_WAR (0x3051, "    sub-index : ", prp_j + 1);
+
+          if (getODentry (d, index, subIndex, tmp, &ByteSize, &dataType, 0) !=
+              OD_SUCCESSFUL)
+            {
+              MSG_ERR (0x1013,
+                       " Couldn't find mapped variable at index-subindex-size : ",
+                       (UNS16) (*pMappingParameter));
+              return 0xFF;
+            }
+          /* copy bit per bit in little endian */
+          CopyBits ((UNS8) Size, ((UNS8 *) tmp), 0, 0,
+                    (UNS8 *) & pdo->data[offset >> 3], (UNS8)(offset % 8), 0);
+
+          offset += Size;
+        }
+      prp_j++;
+    }
+  while (prp_j < *pMappingCount);
+
+  pdo->len = (UNS8)(1 + ((offset - 1) >> 3));
+
+  MSG_WAR (0x3015, "  End scan mapped variable", 0);
+
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param cobId
+**
+** @return
+**/
+UNS8
+sendPDOrequest (CO_Data * d, UNS16 RPDOIndex)
+{
+  UNS32 *pwCobId;
+  UNS16 offset = d->firstIndex->PDO_RCV;
+  UNS16 lastIndex = d->lastIndex->PDO_RCV;
+
+  if (!d->CurrentCommunicationState.csPDO)
+    {
+      return 0;
+    }
+
+  /* Sending the request only if the cobid have been found on the PDO
+     receive */
+  /* part dictionary */
+
+  MSG_WAR (0x3930, "sendPDOrequest RPDO Index : ", RPDOIndex);
+
+  if (offset && RPDOIndex >= 0x1400)
+    {
+      offset += RPDOIndex - 0x1400;
+      if (offset <= lastIndex)
+        {
+          /* get the CobId */
+          // mbed error 513 - needs typecast
+          pwCobId = (unsigned int*)d->objdict[offset].pSubindex[1].pObject;
+
+          MSG_WAR (0x3930, "sendPDOrequest cobId is : ", *pwCobId);
+          {
+            Message pdo;
+            pdo.cob_id = (UNS16)UNS16_LE(*pwCobId);
+            pdo.rtr = REQUEST;
+            pdo.len = 0;
+            return canSend (d->canHandle, &pdo);
+          }
+        }
+    }
+  MSG_ERR (0x1931, "sendPDOrequest : RPDO Index not found : ", RPDOIndex);
+  return 0xFF;
+}
+
+
+/*!
+**
+**
+** @param d
+** @param m
+**
+** @return
+**/
+UNS8
+proceedPDO (CO_Data * d, Message * m)
+{
+  UNS8 numPdo;
+  UNS8 numMap;                  /* Number of the mapped varable */
+  UNS8 *pMappingCount = NULL;   /* count of mapped objects... */
+  /* pointer to the var which is mapped to a pdo... */
+  /*  void *     pMappedAppObject = NULL;   */
+  /* pointer fo the var which holds the mapping parameter of an
+     mapping entry */
+  UNS32 *pMappingParameter = NULL;
+  UNS8 *pTransmissionType = NULL;       /* pointer to the transmission
+                                           type */
+  UNS32 *pwCobId = NULL;
+  UNS8 Size;
+  UNS8 offset;
+  UNS8 status;
+  UNS32 objDict;
+  UNS16 offsetObjdict;
+  UNS16 lastIndex;
+
+  status = state2;
+
+  MSG_WAR (0x3935, "proceedPDO, cobID : ", (UNS16_LE(m->cob_id) & 0x7ff));
+  offset = 0x00;
+  numPdo = 0;
+  numMap = 0;
+  if ((*m).rtr == NOT_A_REQUEST)
+    {                           /* The PDO received is not a
+                                   request. */
+
+      offsetObjdict = d->firstIndex->PDO_RCV;
+      lastIndex = d->lastIndex->PDO_RCV;
+
+      /* study of all the PDO stored in the dictionary */
+      if (offsetObjdict)
+        while (offsetObjdict <= lastIndex)
+          {
+
+            switch (status)
+              {
+
+              case state2:
+                /* get CobId of the dictionary correspondant to the received
+                   PDO */
+                // mbed error 513 - needs typecast
+                pwCobId = (unsigned int*)
+                  d->objdict[offsetObjdict].pSubindex[1].pObject;
+                /* check the CobId coherance */
+                /*pwCobId is the cobId read in the dictionary at the state 3
+                 */
+                if (*pwCobId == UNS16_LE(m->cob_id))
+                  {
+                    /* The cobId is recognized */
+                    status = state4;
+                    MSG_WAR (0x3936, "cobId found at index ",
+                             0x1400 + numPdo);
+                    break;
+                  }
+                else
+                  {
+                    /* cobId received does not match with those write in the
+                       dictionnary */
+                    numPdo++;
+                    offsetObjdict++;
+                    status = state2;
+                    break;
+                  }
+
+              case state4:     /* Get Mapped Objects Number */
+                /* The cobId of the message received has been found in the
+                   dictionnary. */
+                offsetObjdict = d->firstIndex->PDO_RCV_MAP;
+                lastIndex = d->lastIndex->PDO_RCV_MAP;
+                pMappingCount =
+                  (UNS8 *) (d->objdict + offsetObjdict +
+                            numPdo)->pSubindex[0].pObject;
+                numMap = 0;
+                while (numMap < *pMappingCount)
+                  {
+                    UNS8 tmp[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+                    UNS32 ByteSize;
+                    pMappingParameter =
+                      (UNS32 *) (d->objdict + offsetObjdict +
+                                 numPdo)->pSubindex[numMap + 1].pObject;
+                    if (pMappingParameter == NULL)
+                      {
+                        MSG_ERR (0x1937, "Couldn't get mapping parameter : ",
+                                 numMap + 1);
+                        return 0xFF;
+                      }
+                    /* Get the addresse of the mapped variable. */
+                    /* detail of *pMappingParameter : */
+                    /* The 16 hight bits contains the index, the medium 8 bits
+                       contains the subindex, */
+                    /* and the lower 8 bits contains the size of the mapped
+                       variable. */
+
+                    Size = (UNS8) (*pMappingParameter & (UNS32) 0x000000FF);
+
+                    /* set variable only if Size != 0 and 
+                     * Size is lower than remaining bits in the PDO */
+                    if (Size && ((offset + Size) <= (m->len << 3)))
+                      {
+                        /* copy bit per bit in little endian */
+                        CopyBits (Size, (UNS8 *) & m->data[offset >> 3],
+                                  offset % 8, 0, ((UNS8 *) tmp), 0, 0);
+                        /*1->8 => 1 ; 9->16 =>2, ... */
+                        ByteSize = (UNS32)(1 + ((Size - 1) >> 3));
+
+                        objDict =
+                          setODentry (d, (UNS16) ((*pMappingParameter) >> 16),
+                                      (UNS8) (((*pMappingParameter) >> 8) &
+                                              0xFF), tmp, &ByteSize, 0);
+
+                        if (objDict != OD_SUCCESSFUL)
+                          {
+                            MSG_ERR (0x1938,
+                                     "error accessing to the mapped var : ",
+                                     numMap + 1);
+                            MSG_WAR (0x2939, "         Mapped at index : ",
+                                     (*pMappingParameter) >> 16);
+                            MSG_WAR (0x2940, "                subindex : ",
+                                     ((*pMappingParameter) >> 8) & 0xFF);
+                            return 0xFF;
+                          }
+
+                        MSG_WAR (0x3942,
+                                 "Variable updated by PDO cobid : ",
+                                 UNS16_LE(m->cob_id));
+                        MSG_WAR (0x3943, "         Mapped at index : ",
+                                 (*pMappingParameter) >> 16);
+                        MSG_WAR (0x3944, "                subindex : ",
+                                 ((*pMappingParameter) >> 8) & 0xFF);
+                        offset += Size;
+                      }
+                    numMap++;
+                  }             /* end loop while on mapped variables */
+
+                return 0;
+
+              }                 /* end switch status */
+          }                     /* end while */
+    }                           /* end if Donnees */
+  else if ((*m).rtr == REQUEST)
+    {
+      MSG_WAR (0x3946, "Receive a PDO request cobId : ", UNS16_LE(m->cob_id));
+      status = state1;
+      offsetObjdict = d->firstIndex->PDO_TRS;
+      lastIndex = d->lastIndex->PDO_TRS;
+      if (offsetObjdict)
+        while (offsetObjdict <= lastIndex)
+          {
+            /* study of all PDO stored in the objects dictionary */
+
+            switch (status)
+              {
+
+              case state1:     /* check the CobId */
+                /* get CobId of the dictionary which match to the received PDO
+                 */
+                // mbed error 513 - needs typecast
+                pwCobId = (unsigned int*)
+                   (d->objdict +
+                             offsetObjdict)->pSubindex[1].pObject;
+                if (*pwCobId == UNS16_LE(m->cob_id))
+                  {
+                    status = state4;
+                    break;
+                  }
+                else
+                  {
+                    numPdo++;
+                    offsetObjdict++;
+                  }
+                status = state1;
+                break;
+
+
+              case state4:     /* check transmission type */
+                pTransmissionType =
+                  (UNS8 *) d->objdict[offsetObjdict].pSubindex[2].pObject;
+                /* If PDO is to be sampled and send on RTR, do it */
+                if ((*pTransmissionType == TRANS_RTR))
+                  {
+                    status = state5;
+                    break;
+                  }
+                /* RTR_SYNC means data prepared at SYNC, transmitted on RTR */
+                else if ((*pTransmissionType == TRANS_RTR_SYNC))
+                  {
+                    if (d->PDO_status[numPdo].
+                        transmit_type_parameter & PDO_RTR_SYNC_READY)
+                      {
+                        /*Data ready, just send */
+                        canSend (d->canHandle,
+                                 &d->PDO_status[numPdo].last_message);
+                        return 0;
+                      }
+                    else
+                      {
+                        /* if SYNC did never occur, transmit current data */
+                        /* DS301 do not tell what to do in such a case... */
+                        MSG_ERR (0x1947,
+                                 "Not ready RTR_SYNC TPDO send current data : ",
+                                 UNS16_LE(m->cob_id));
+                        status = state5;
+                      }
+                    break;
+                  }
+                else if ((*pTransmissionType == TRANS_EVENT_PROFILE) ||
+                         (*pTransmissionType == TRANS_EVENT_SPECIFIC))
+                  {
+                    /* Zap all timers and inhibit flag */
+                    d->PDO_status[numPdo].event_timer =
+                      DelAlarm (d->PDO_status[numPdo].event_timer);
+                    d->PDO_status[numPdo].inhibit_timer =
+                      DelAlarm (d->PDO_status[numPdo].inhibit_timer);
+                    d->PDO_status[numPdo].transmit_type_parameter &=
+                      ~PDO_INHIBITED;
+                    /* Call  PDOEventTimerAlarm for this TPDO, 
+                     * this will trigger emission et reset timers */
+                    PDOEventTimerAlarm (d, numPdo);
+                    return 0;
+                  }
+                else
+                  {
+                    /* The requested PDO is not to send on request. So, does
+                       nothing. */
+                    MSG_WAR (0x2947, "PDO is not to send on request : ",
+                             UNS16_LE(m->cob_id));
+                    return 0xFF;
+                  }
+
+              case state5:     /* build and send requested PDO */
+                {
+                  Message pdo;
+                  if (buildPDO (d, numPdo, &pdo))
+                    {
+                      MSG_ERR (0x1948, " Couldn't build TPDO n&#65533;", numPdo);
+                      return 0xFF;
+                    }
+                  canSend (d->canHandle, &pdo);
+                  return 0;
+                }
+              }                 /* end switch status */
+          }                     /* end while */
+    }                           /* end if Requete */
+
+  return 0;
+}
+
+/*!
+**
+**
+** @param NbBits
+** @param SrcByteIndex
+** @param SrcBitIndex
+** @param SrcBigEndian
+** @param DestByteIndex
+** @param DestBitIndex
+** @param DestBigEndian
+**/
+void
+CopyBits (UNS8 NbBits, UNS8 * SrcByteIndex, UNS8 SrcBitIndex,
+          UNS8 SrcBigEndian, UNS8 * DestByteIndex, UNS8 DestBitIndex,
+          UNS8 DestBigEndian)
+{
+  /* This loop copy as many bits that it can each time, crossing */
+  /* successively bytes */
+  // boundaries from LSB to MSB.
+  while (NbBits > 0)
+    {
+      /* Bit missalignement between src and dest */
+      INTEGER8 Vect = DestBitIndex - SrcBitIndex;
+
+      /* We can now get src and align it to dest */
+      UNS8 Aligned =
+        Vect > 0 ? *SrcByteIndex << Vect : *SrcByteIndex >> -Vect;
+
+      /* Compute the nb of bit we will be able to copy */
+      UNS8 BoudaryLimit = (Vect > 0 ? 8 - DestBitIndex : 8 - SrcBitIndex);
+      UNS8 BitsToCopy = BoudaryLimit > NbBits ? NbBits : BoudaryLimit;
+
+      /* Create a mask that will serve in: */
+      UNS8 Mask =
+        ((0xff << (DestBitIndex + BitsToCopy)) |
+         (0xff >> (8 - DestBitIndex)));
+
+      /* - Filtering src */
+      UNS8 Filtered = Aligned & ~Mask;
+
+      /* - and erase bits where we write, preserve where we don't */
+      *DestByteIndex &= Mask;
+
+      /* Then write. */
+      *DestByteIndex |= Filtered;
+
+      /*Compute next time cursors for src */
+      if ((SrcBitIndex += BitsToCopy) > 7)      /* cross boundary ? */
+        {
+          SrcBitIndex = 0;      /* First bit */
+          SrcByteIndex += (SrcBigEndian ? -1 : 1);      /* Next byte */
+        }
+
+
+      /*Compute next time cursors for dest */
+      if ((DestBitIndex += BitsToCopy) > 7)
+        {
+          DestBitIndex = 0;     /* First bit */
+          DestByteIndex += (DestBigEndian ? -1 : 1);    /* Next byte */
+        }
+
+      /*And decrement counter. */
+      NbBits -= BitsToCopy;
+    }
+
+}
+
+static void sendPdo(CO_Data * d, UNS32 pdoNum, Message * pdo)
+{
+  /*store_as_last_message */
+  d->PDO_status[pdoNum].last_message = *pdo;
+  MSG_WAR (0x396D, "sendPDO cobId :", UNS16_LE(pdo.cob_id));
+  MSG_WAR (0x396E, "     Nb octets  : ", pdo.len);
+
+  canSend (d->canHandle, pdo);
+}
+
+
+/*!
+**
+**
+** @param d
+**
+** @return
+**/
+
+UNS8
+sendPDOevent (CO_Data * d)
+{
+  /* Calls _sendPDOevent specifying it is not a sync event */
+  return _sendPDOevent (d, 0);
+}
+
+UNS8
+sendOnePDOevent (CO_Data * d, UNS8 pdoNum)
+{
+  UNS16 offsetObjdict;
+  Message pdo;
+  if (!d->CurrentCommunicationState.csPDO ||
+      (d->PDO_status[pdoNum].transmit_type_parameter & PDO_INHIBITED))
+    {
+      return 0;
+    }
+
+  offsetObjdict = (UNS16) (d->firstIndex->PDO_TRS + pdoNum);
+  MSG_WAR (0x3968, "  PDO is on EVENT. Trans type : ",
+           *pTransmissionType);
+  
+  memset(&pdo, 0, sizeof(pdo));
+  if (buildPDO (d, pdoNum, &pdo))
+    {
+      MSG_ERR (0x3907, " Couldn't build TPDO number : ",
+               pdoNum);
+      return 0;
+    }
+
+  /*Compare new and old PDO */
+  if (d->PDO_status[pdoNum].last_message.cob_id == pdo.cob_id
+      && d->PDO_status[pdoNum].last_message.len == pdo.len
+      && memcmp(d->PDO_status[pdoNum].last_message.data,
+                    pdo.data, 8) == 0
+    )
+    {
+      /* No changes -> go to next pdo */
+      return 0;
+    }
+  else
+    {
+
+      TIMEVAL EventTimerDuration;
+      TIMEVAL InhibitTimerDuration;
+
+      MSG_WAR (0x306A, "Changes TPDO number : ", pdoNum);
+      /* Changes detected -> transmit message */
+      EventTimerDuration =
+        *(UNS16 *) d->objdict[offsetObjdict].pSubindex[5].
+        pObject;
+      InhibitTimerDuration =
+        *(UNS16 *) d->objdict[offsetObjdict].pSubindex[3].
+        pObject;
+
+      /* Start both event_timer and inhibit_timer */
+      if (EventTimerDuration)
+        {
+          DelAlarm (d->PDO_status[pdoNum].event_timer);
+          d->PDO_status[pdoNum].event_timer =
+            SetAlarm (d, pdoNum, &PDOEventTimerAlarm,
+                      MS_TO_TIMEVAL (EventTimerDuration), 0);
+        }
+
+      if (InhibitTimerDuration)
+        {
+          DelAlarm (d->PDO_status[pdoNum].inhibit_timer);
+          d->PDO_status[pdoNum].inhibit_timer =
+            SetAlarm (d, pdoNum, &PDOInhibitTimerAlarm,
+                      US_TO_TIMEVAL (InhibitTimerDuration *
+                                     100), 0);
+          /* and inhibit TPDO */
+          d->PDO_status[pdoNum].transmit_type_parameter |=
+            PDO_INHIBITED;
+        }
+
+      sendPdo(d, pdoNum, &pdo);
+    }
+    return 1;
+}
+
+void
+PDOEventTimerAlarm (CO_Data * d, UNS32 pdoNum)
+{
+  /* This is needed to avoid deletion of re-attribuated timer */
+  d->PDO_status[pdoNum].event_timer = TIMER_NONE;
+  /* force emission of PDO by artificially changing last emitted */
+  d->PDO_status[pdoNum].last_message.cob_id = 0;
+  sendOnePDOevent (d, (UNS8) pdoNum);
+}
+
+void
+PDOInhibitTimerAlarm (CO_Data * d, UNS32 pdoNum)
+{
+  /* This is needed to avoid deletion of re-attribuated timer */
+  d->PDO_status[pdoNum].inhibit_timer = TIMER_NONE;
+  /* Remove inhibit flag */
+  d->PDO_status[pdoNum].transmit_type_parameter &= ~PDO_INHIBITED;
+  sendOnePDOevent (d, (UNS8) pdoNum);
+}
+
+/*!
+**
+**
+** @param d
+** @param isSyncEvent
+**
+** @return
+**/
+
+UNS8
+_sendPDOevent (CO_Data * d, UNS8 isSyncEvent)
+{
+  UNS8 pdoNum = 0x00;           /* number of the actual processed pdo-nr. */
+  UNS8 *pTransmissionType = NULL;
+  UNS8 status = state3;
+  UNS16 offsetObjdict = d->firstIndex->PDO_TRS;
+  UNS16 offsetObjdictMap = d->firstIndex->PDO_TRS_MAP;
+  UNS16 lastIndex = d->lastIndex->PDO_TRS;
+
+  if (!d->CurrentCommunicationState.csPDO)
+    {
+      return 0;
+    }
+
+
+  /* study all PDO stored in the objects dictionary */
+  if (offsetObjdict)
+    {
+      Message pdo;/* = Message_Initializer;*/
+      memset(&pdo, 0, sizeof(pdo));
+      while (offsetObjdict <= lastIndex)
+        {
+          switch (status)
+            {
+            case state3:
+              if ( /* bSubCount always 5 with objdictedit -> check disabled */
+                   /*d->objdict[offsetObjdict].bSubCount < 5 ||*/
+                   /* check if TPDO is not valid */
+                   *(UNS32 *) d->objdict[offsetObjdict].pSubindex[1].
+                   pObject & 0x80000000)
+                {
+                  MSG_WAR (0x3960, "Not a valid PDO ", 0x1800 + pdoNum);
+                  /*Go next TPDO */
+                  status = state11;
+                  break;
+                }
+              /* get the PDO transmission type */
+              pTransmissionType =
+                (UNS8 *) d->objdict[offsetObjdict].pSubindex[2].pObject;
+              MSG_WAR (0x3962, "Reading PDO at index : ", 0x1800 + pdoNum);
+
+              /* check if transmission type is SYNCRONOUS */
+              /* message transmited every n SYNC with n=TransmissionType */
+              if (isSyncEvent &&
+                  (*pTransmissionType >= TRANS_SYNC_MIN) &&
+                  (*pTransmissionType <= TRANS_SYNC_MAX) &&
+                  (++d->PDO_status[pdoNum].transmit_type_parameter ==
+                   *pTransmissionType))
+                {
+                  /*Reset count of SYNC */
+                  d->PDO_status[pdoNum].transmit_type_parameter = 0;
+                  MSG_WAR (0x3964, "  PDO is on SYNCHRO. Trans type : ",
+                           *pTransmissionType);
+                  memset(&pdo, 0, sizeof(pdo));
+                  /*{
+                    Message msg_init = Message_Initializer;
+                    pdo = msg_init;
+                  }*/
+                  if (buildPDO (d, pdoNum, &pdo))
+                    {
+                      MSG_ERR (0x1906, " Couldn't build TPDO number : ",
+                               pdoNum);
+                      status = state11;
+                      break;
+                    }
+                  status = state5;
+                  /* If transmission RTR, with data sampled on SYNC */
+                }
+              else if (isSyncEvent && (*pTransmissionType == TRANS_RTR_SYNC))
+                {
+                  if (buildPDO
+                      (d, pdoNum, &d->PDO_status[pdoNum].last_message))
+                    {
+                      MSG_ERR (0x1966, " Couldn't build TPDO number : ",
+                               pdoNum);
+                      d->PDO_status[pdoNum].transmit_type_parameter &=
+                        ~PDO_RTR_SYNC_READY;
+                    }
+                  else
+                    {
+                      d->PDO_status[pdoNum].transmit_type_parameter |=
+                        PDO_RTR_SYNC_READY;
+                    }
+                  status = state11;
+                  break;
+                  /* If transmission on Event and not inhibited, check for changes */
+                }
+              else
+                if ( (isSyncEvent && (*pTransmissionType == TRANS_SYNC_ACYCLIC))
+                     ||
+                     (!isSyncEvent && (*pTransmissionType == TRANS_EVENT_PROFILE || *pTransmissionType == TRANS_EVENT_SPECIFIC)
+                       && !(d->PDO_status[pdoNum].transmit_type_parameter & PDO_INHIBITED)))
+                {
+                  sendOnePDOevent(d, pdoNum);
+                  status = state11;
+                }
+              else
+                {
+                  MSG_WAR (0x306C,
+                           "  PDO is not on EVENT or synchro or not at this SYNC. Trans type : ",
+                           *pTransmissionType);
+                  status = state11;
+                }
+              break;
+            case state5:       /*Send the pdo */
+              sendPdo(d, pdoNum, &pdo);
+              status = state11;
+              break;
+            case state11:      /*Go to next TPDO */
+              pdoNum++;
+              offsetObjdict++;
+              offsetObjdictMap++;
+              MSG_WAR (0x3970, "next pdo index : ", pdoNum);
+              status = state3;
+              break;
+
+            default:
+              MSG_ERR (0x1972, "Unknown state has been reached : %d", status);
+              return 0xFF;
+            }                   /* end switch case */
+
+        }                       /* end while */
+    }
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param OD_entry
+** @param bSubindex
+** @return always 0
+**/
+
+UNS32
+TPDO_Communication_Parameter_Callback (CO_Data * d,
+                                       const indextable * OD_entry,
+                                       UNS8 bSubindex)
+{
+  /* If PDO are actives */
+  if (d->CurrentCommunicationState.csPDO)
+    switch (bSubindex)
+      {
+      case 2:                  /* Changed transmition type */
+      case 3:                  /* Changed inhibit time */
+      case 5:                  /* Changed event time */
+        {
+          const indextable *TPDO_com = d->objdict + d->firstIndex->PDO_TRS;
+          UNS8 numPdo = (UNS8) (OD_entry - TPDO_com);    /* number of the actual processed pdo-nr. */
+
+          /* Zap all timers and inhibit flag */
+          d->PDO_status[numPdo].event_timer =
+            DelAlarm (d->PDO_status[numPdo].event_timer);
+          d->PDO_status[numPdo].inhibit_timer =
+            DelAlarm (d->PDO_status[numPdo].inhibit_timer);
+          d->PDO_status[numPdo].transmit_type_parameter = 0;
+          /* Call  PDOEventTimerAlarm for this TPDO, this will trigger emission et reset timers */
+          PDOEventTimerAlarm (d, numPdo);
+          return 0;
+        }
+
+      default:                 /* other subindex are ignored */
+        break;
+      }
+  return 0;
+}
+
+void
+PDOInit (CO_Data * d)
+{
+  /* For each TPDO mapping parameters */
+  UNS16 pdoIndex = 0x1800;      /* OD index of TDPO */
+
+  UNS16 offsetObjdict = d->firstIndex->PDO_TRS;
+  UNS16 lastIndex = d->lastIndex->PDO_TRS;
+  if (offsetObjdict)
+    while (offsetObjdict <= lastIndex)
+      {
+        /* Assign callbacks to sensible TPDO mapping subindexes */
+        UNS32 errorCode;
+        ODCallback_t *CallbackList;
+        /* Find callback list */
+        scanIndexOD (d, pdoIndex, &errorCode, &CallbackList);
+        if (errorCode == OD_SUCCESSFUL && CallbackList)
+          {
+            /*Assign callbacks to corresponding subindex */
+            /* Transmission type */
+            CallbackList[2] = &TPDO_Communication_Parameter_Callback;
+            /* Inhibit time */
+            CallbackList[3] = &TPDO_Communication_Parameter_Callback;
+            /* Event timer */
+            CallbackList[5] = &TPDO_Communication_Parameter_Callback;
+          }
+        pdoIndex++;
+        offsetObjdict++;
+      }
+
+  /* Trigger a non-sync event */
+  _sendPDOevent (d, 0);
+}
+
+void
+PDOStop (CO_Data * d)
+{
+  /* For each TPDO mapping parameters */
+  UNS8 pdoNum = 0x00;           /* number of the actual processed pdo-nr. */
+  UNS16 offsetObjdict = d->firstIndex->PDO_TRS;
+  UNS16 lastIndex = d->lastIndex->PDO_TRS;
+  if (offsetObjdict)
+    while (offsetObjdict <= lastIndex)
+      {
+        /* Delete TPDO timers */
+        d->PDO_status[pdoNum].event_timer =
+          DelAlarm (d->PDO_status[pdoNum].event_timer);
+        d->PDO_status[pdoNum].inhibit_timer =
+          DelAlarm (d->PDO_status[pdoNum].inhibit_timer);
+        /* Reset transmit type parameter */
+        d->PDO_status[pdoNum].transmit_type_parameter = 0;
+        d->PDO_status[pdoNum].last_message.cob_id = 0;
+        pdoNum++;
+        offsetObjdict++;
+      }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/sdo.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,1866 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/*!
+** @file   sdo.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Tue Jun  5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
+
+/* #define DEBUG_WAR_CONSOLE_ON */
+/* #define DEBUG_ERR_CONSOLE_ON */
+
+#include "canfestival.h"
+#include "sysdep.h"
+
+/* Uncomment if your compiler does not support inline functions */
+#define NO_INLINE
+
+#ifdef NO_INLINE
+  #define INLINE
+#else
+  #define INLINE inline
+#endif
+
+/*Internals prototypes*/
+
+/*!
+** Called by writeNetworkDict
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+** @param Callback
+** @param endianize
+**
+** @return
+**/
+INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
+               UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
+
+/*!
+** Called by readNetworkDict
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param dataType
+** @param Callback
+**
+** @return
+**/
+INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex,
+    UNS8 dataType, SDOCallback_t Callback);
+
+
+/***************************************************************************/
+/* SDO (un)packing macros */
+
+/** Returns the command specifier (cs, ccs, scs) from the first byte of the SDO
+ */
+#define getSDOcs(byte) (byte >> 5)
+
+/** Returns the number of bytes without data from the first byte of the SDO. Coded in 2 bits
+ */
+#define getSDOn2(byte) ((byte >> 2) & 3)
+
+/** Returns the number of bytes without data from the first byte of the SDO. Coded in 3 bits
+ */
+#define getSDOn3(byte) ((byte >> 1) & 7)
+
+/** Returns the transfer type from the first byte of the SDO
+ */
+#define getSDOe(byte) ((byte >> 1) & 1)
+
+/** Returns the size indicator from the first byte of the SDO
+ */
+#define getSDOs(byte) (byte & 1)
+
+/** Returns the indicator of end transmission from the first byte of the SDO
+ */
+#define getSDOc(byte) (byte & 1)
+
+/** Returns the toggle from the first byte of the SDO
+ */
+#define getSDOt(byte) ((byte >> 4) & 1)
+
+/** Returns the index from the bytes 1 and 2 of the SDO
+ */
+#define getSDOindex(byte1, byte2) (((UNS16)byte2 << 8) | ((UNS16)byte1))
+
+/** Returns the subIndex from the byte 3 of the SDO
+ */
+#define getSDOsubIndex(byte3) (byte3)
+
+/*!
+**
+**
+** @param d
+** @param id
+**/
+void SDOTimeoutAlarm(CO_Data* d, UNS32 id)
+{
+    MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);
+    MSG_WAR(0x2A02, "server node : ", d->transfers[id].nodeId);
+    MSG_WAR(0x2A02, "      index : ", d->transfers[id].index);
+    MSG_WAR(0x2A02, "   subIndex : ", d->transfers[id].subIndex);
+    /* Reset timer handler */
+    d->transfers[id].timer = TIMER_NONE;
+    /*Set aborted state*/
+    d->transfers[id].state = SDO_ABORTED_INTERNAL;
+    /* Sending a SDO abort */
+    sendSDOabort(d, d->transfers[id].whoami, d->transfers[id].nodeId,
+         d->transfers[id].index, d->transfers[id].subIndex, SDOABT_TIMED_OUT);
+    d->transfers[id].abortCode = SDOABT_TIMED_OUT;
+    /* Call the user function to inform of the problem.*/
+    if(d->transfers[id].Callback)
+        /*If ther is a callback, it is responsible to close SDO transfer (client)*/
+        (*d->transfers[id].Callback)(d,d->transfers[id].nodeId);
+    
+    /*Reset the line if (whoami == SDO_SERVER) or the callback did not close the line.
+      Otherwise this sdo transfer would never be closed. */
+    resetSDOline(d, (UNS8)id);
+}
+
+#define StopSDO_TIMER(id) \
+MSG_WAR(0x3A05, "StopSDO_TIMER for line : ", line);\
+d->transfers[id].timer = DelAlarm(d->transfers[id].timer);
+
+#define StartSDO_TIMER(id) \
+MSG_WAR(0x3A06, "StartSDO_TIMER for line : ", line);\
+d->transfers[id].timer = SetAlarm(d,id,&SDOTimeoutAlarm,MS_TO_TIMEVAL(SDO_TIMEOUT_MS),0);
+
+#define RestartSDO_TIMER(id) \
+MSG_WAR(0x3A07, "restartSDO_TIMER for line : ", line);\
+if(d->transfers[id].timer != TIMER_NONE) { StopSDO_TIMER(id) StartSDO_TIMER(id) }
+
+/*!
+** Reset all sdo buffers
+**
+** @param d
+**/
+void resetSDO (CO_Data* d)
+{
+  UNS8 j;
+
+  /* transfer structure initialization */
+    for (j = 0 ; j < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; j++)
+      resetSDOline(d, j);
+}
+
+/*!
+**
+**
+** @param d
+** @param line
+**
+** @return
+**/
+UNS32 SDOlineToObjdict (CO_Data* d, UNS8 line)
+{
+  UNS32 size;
+  UNS32 errorCode;
+  MSG_WAR(0x3A08, "Enter in SDOlineToObjdict ", line);
+  /* if SDO initiated with e=0 and s=0 count is null, offset carry effective size*/
+  if( d->transfers[line].count == 0)
+      d->transfers[line].count = d->transfers[line].offset;
+  size = d->transfers[line].count;
+
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  if (size > SDO_MAX_LENGTH_TRANSFERT)
+  {
+    errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,
+             (void *) d->transfers[line].dynamicData, &size, 1);
+  }
+  else
+  {
+   errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,
+             (void *) d->transfers[line].data, &size, 1);
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
+  errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,
+             (void *) d->transfers[line].data, &size, 1);
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
+  if (errorCode != OD_SUCCESSFUL)
+    return errorCode;
+  MSG_WAR(0x3A08, "exit of SDOlineToObjdict ", line);
+  return 0;
+
+}
+
+/*!
+**
+**
+** @param d
+** @param line
+**
+** @return
+**/
+UNS32 objdictToSDOline (CO_Data* d, UNS8 line)
+{
+  UNS32  size = 0;
+  UNS8  dataType;
+  UNS32 errorCode;
+
+  MSG_WAR(0x3A05, "objdict->line index : ", d->transfers[line].index);
+  MSG_WAR(0x3A06, "  subIndex : ", d->transfers[line].subIndex);
+
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  //TODO: Read the size of the object. Depending o it put data into data or dynamicData
+  errorCode = getODentry(d,     d->transfers[line].index,
+                  d->transfers[line].subIndex,
+                  (void *)d->transfers[line].data,
+                  &size, &dataType, 1);
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
+  errorCode = getODentry(d,     d->transfers[line].index,
+                  d->transfers[line].subIndex,
+                  (void *)d->transfers[line].data,
+                  &size, &dataType, 1);
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
+  if (errorCode != OD_SUCCESSFUL)
+    return errorCode;
+
+  d->transfers[line].count = size;
+  d->transfers[line].offset = 0;
+
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param line
+** @param nbBytes
+** @param data
+**
+** @return
+**/
+UNS8 lineToSDO (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8* data) {
+  UNS8 i;
+  UNS32 offset;
+
+#ifndef SDO_DYNAMIC_BUFFER_ALLOCATION
+  if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
+    MSG_ERR(0x1A10,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
+    return 0xFF;
+  }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
+    if ((d->transfers[line].offset + nbBytes) > d->transfers[line].count) {
+    MSG_ERR(0x1A11,"SDO Size of data too large. Exceed count", nbBytes);
+    return 0xFF;
+  }
+  offset = d->transfers[line].offset;
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  if (d->transfers[line].count <= SDO_MAX_LENGTH_TRANSFERT)
+  {
+    for (i = 0 ; i < nbBytes ; i++)
+      * (data + i) = d->transfers[line].data[offset + i];
+  }
+  else
+  {
+    if (d->transfers[line].dynamicData == NULL)
+    {
+      MSG_ERR(0x1A11,"SDO's dynamic buffer not allocated. Line", line);
+      return 0xFF;
+    }
+    for (i = 0 ; i < nbBytes ; i++)
+      * (data + i) = d->transfers[line].dynamicData[offset + i];
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
+    for (i = 0 ; i < nbBytes ; i++)
+    * (data + i) = d->transfers[line].data[offset + i];
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+  d->transfers[line].offset = d->transfers[line].offset + nbBytes;
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param line
+** @param nbBytes
+** @param data
+**
+** @return
+**/
+UNS8 SDOtoLine (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8* data)
+{
+  UNS8 i;
+  UNS32 offset;
+#ifndef SDO_DYNAMIC_BUFFER_ALLOCATION
+  if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
+    MSG_ERR(0x1A15,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
+    return 0xFF;
+  }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
+  offset = d->transfers[line].offset;
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  {
+    UNS8* lineData = d->transfers[line].data;
+    if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
+      if (d->transfers[line].dynamicData == NULL) {
+        d->transfers[line].dynamicData = (UNS8*) malloc(SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);
+        d->transfers[line].dynamicDataSize = SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE;
+
+        if (d->transfers[line].dynamicData == NULL) {
+          MSG_ERR(0x1A15,"SDO allocating dynamic buffer failed, size", SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);
+          return 0xFF;
+        }
+        //Copy present data
+        memcpy(d->transfers[line].dynamicData, d->transfers[line].data, offset);
+      }
+      else if ((d->transfers[line].offset + nbBytes) > d->transfers[line].dynamicDataSize)
+      {
+        UNS8* newDynamicBuffer = (UNS8*) realloc(d->transfers[line].dynamicData, d->transfers[line].dynamicDataSize + SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);
+        if (newDynamicBuffer == NULL) {
+          MSG_ERR(0x1A15,"SDO reallocating dynamic buffer failed, size", d->transfers[line].dynamicDataSize + SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);
+          return 0xFF;
+        }
+        d->transfers[line].dynamicData = newDynamicBuffer;
+        d->transfers[line].dynamicDataSize += SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE;
+      }
+      lineData = d->transfers[line].dynamicData;
+    }
+    
+    for (i = 0 ; i < nbBytes ; i++)
+      lineData[offset + i] = * (data + i);
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
+  for (i = 0 ; i < nbBytes ; i++)
+    d->transfers[line].data[offset + i] = * (data + i);
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
+  d->transfers[line].offset = d->transfers[line].offset + nbBytes;
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param whoami
+** @param index
+** @param subIndex
+** @param abortCode
+**
+** @return
+**/
+UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index,
+        UNS8 subIndex, UNS32 abortCode)
+{
+  UNS8 err;
+  UNS8 line;
+  err = getSDOlineOnUse( d, nodeId, whoami, &line );
+  if (!err) /* If a line on use have been found.*/
+    MSG_WAR(0x3A20, "FailedSDO : line found : ", line);
+  if ((! err) && (whoami == SDO_SERVER)) {
+    resetSDOline( d, line );
+    MSG_WAR(0x3A21, "FailedSDO : line released : ", line);
+  }
+  if ((! err) && (whoami == SDO_CLIENT)) {
+    StopSDO_TIMER(line);
+    d->transfers[line].state = SDO_ABORTED_INTERNAL;
+  }
+  MSG_WAR(0x3A22, "Sending SDO abort ", 0);
+  err = sendSDOabort(d, whoami, nodeId, index, subIndex, abortCode);
+  if (err) {
+    MSG_WAR(0x3A23, "Unable to send the SDO abort", 0);
+    return 0xFF;
+  }
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param line
+**/
+void resetSDOline ( CO_Data* d, UNS8 line )
+{
+  UNS32 i;
+  MSG_WAR(0x3A25, "reset SDO line nb : ", line);
+  initSDOline(d, line, 0, 0, 0, SDO_RESET);
+  for (i = 0 ; i < SDO_MAX_LENGTH_TRANSFERT ; i++)
+    d->transfers[line].data[i] = 0;
+  d->transfers[line].whoami = 0;
+  d->transfers[line].abortCode = 0;
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  free(d->transfers[line].dynamicData);
+  d->transfers[line].dynamicData = 0;
+  d->transfers[line].dynamicDataSize = 0;
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+}
+
+/*!
+**
+**
+** @param d
+** @param line
+** @param nodeId
+** @param index
+** @param subIndex
+** @param state
+**
+** @return
+**/
+UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state)
+{
+  MSG_WAR(0x3A25, "init SDO line nb : ", line);
+  if (state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS){
+      StartSDO_TIMER(line)
+  }else{
+      StopSDO_TIMER(line)
+  }
+  d->transfers[line].nodeId = nodeId;
+  d->transfers[line].index = index;
+  d->transfers[line].subIndex = subIndex;
+  d->transfers[line].state = state;
+  d->transfers[line].toggle = 0;
+  d->transfers[line].count = 0;
+  d->transfers[line].offset = 0;
+  d->transfers[line].dataType = 0;
+  d->transfers[line].Callback = NULL;
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  free(d->transfers[line].dynamicData);
+  d->transfers[line].dynamicData = 0;
+  d->transfers[line].dynamicDataSize = 0;
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param whoami
+** @param line
+**
+** @return
+**/
+UNS8 getSDOfreeLine ( CO_Data* d, UNS8 whoami, UNS8 *line )
+{
+
+  UNS8 i;
+
+  for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
+    if ( d->transfers[i].state == SDO_RESET ) {
+      *line = i;
+      d->transfers[i].whoami = whoami;
+      return 0;
+    } /* end if */
+  } /* end for */
+  MSG_ERR(0x1A25, "Too many SDO in progress. Aborted.", i);
+  return 0xFF;
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param whoami
+** @param line
+**
+** @return
+**/
+UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
+{
+
+  UNS8 i;
+
+  for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
+    if ( (d->transfers[i].state != SDO_RESET) &&
+     (d->transfers[i].state != SDO_ABORTED_INTERNAL) &&
+     (d->transfers[i].nodeId == nodeId) &&
+     (d->transfers[i].whoami == whoami) ) {
+      if (line) *line = i;
+      return 0;
+    }
+  }
+  return 0xFF;
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param whoami
+** @param line
+**
+** @return
+**/
+UNS8 getSDOlineToClose (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
+{
+
+  UNS8 i;
+
+  for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
+    if ( (d->transfers[i].state != SDO_RESET) &&
+     (d->transfers[i].nodeId == nodeId) &&
+     (d->transfers[i].whoami == whoami) ) {
+      if (line) *line = i;
+      return 0;
+    }
+  }
+  return 0xFF;
+}
+
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param whoami
+**
+** @return
+**/
+UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami)
+{
+  UNS8 err;
+  UNS8 line;
+  err = getSDOlineToClose(d, nodeId, whoami, &line);
+  if (err) {
+    MSG_WAR(0x2A30, "No SDO communication to close for node : ", nodeId);
+    return 0xFF;
+  }
+  resetSDOline(d, line);
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param line
+** @param nbBytes
+**
+** @return
+**/
+UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS32 * nbBytes)
+{
+  /* SDO initiated with e=0 and s=0 have count set to null */
+  if (d->transfers[line].count == 0)
+    * nbBytes = 0;
+  else
+    * nbBytes = d->transfers[line].count - d->transfers[line].offset;
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param line
+** @param nbBytes
+**
+** @return
+**/
+UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS32 nbBytes)
+{
+#ifndef SDO_DYNAMIC_BUFFER_ALLOCATION
+  if (nbBytes > SDO_MAX_LENGTH_TRANSFERT) {
+    MSG_ERR(0x1A35,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
+    return 0xFF;
+  }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
+  d->transfers[line].count = nbBytes;
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param whoami
+** @param sdo
+**
+** @return
+**/
+UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo)
+{
+  UNS16 offset;
+  UNS16 lastIndex;
+  UNS8 found = 0;
+  Message m;
+  UNS8 i;
+  UNS32 * pwCobId = NULL;
+  UNS8 * pwNodeId = NULL;
+
+  MSG_WAR(0x3A38, "sendSDO",0);
+  if( !((d->nodeState == Operational) ||  (d->nodeState == Pre_operational ))) {
+    MSG_WAR(0x2A39, "unable to send the SDO (not in op or pre-op mode", d->nodeState);
+    return 0xFF;
+  }
+
+  /*get the server->client cobid*/
+  if ( whoami == SDO_SERVER )    {/*case server. only one SDO server*/
+    offset = d->firstIndex->SDO_SVR;
+    if (offset == 0) {
+      MSG_ERR(0x1A42, "SendSDO : No SDO server found", 0);
+      return 0xFF;
+    }
+    pwCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
+    MSG_WAR(0x3A41, "I am server. cobId : ", *pwCobId);
+  }
+  else {            /*case client*/
+    /* Get the client->server cobid.*/
+    UNS16 sdoNum = 0;
+    offset = d->firstIndex->SDO_CLT;
+    lastIndex = d->lastIndex->SDO_CLT;
+    if (offset == 0) {
+      MSG_ERR(0x1A42, "SendSDO : No SDO client index found", 0);
+      return 0xFF;
+    }
+    /* find index for communication server node */
+    while (offset <= lastIndex){
+      MSG_WAR(0x3A43,"Reading index : ", 0x1280 + sdoNum);
+      if (d->objdict[offset].bSubCount <= 3) {
+    MSG_ERR(0x1A28, "Subindex 3  not found at index ", 0x1280 + sdoNum);
+    return 0xFF;
+      }
+      pwNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
+      MSG_WAR(0x3A44, "Found nodeId server = ", *pwNodeId);
+      if(*pwNodeId == sdo.nodeId) {
+    found = 1;
+    break;
+      }
+      offset ++;
+      sdoNum ++;
+    }
+    if (! found){
+      MSG_WAR (0x2A45, "No SDO client corresponds to the mesage to send to node ", sdo.nodeId);
+      return 0xFF;
+    }
+    /* read the client->server cobid */
+    pwCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
+  }
+  /* message copy for sending */
+  m.cob_id = (UNS16)UNS16_LE(*pwCobId);
+  m.rtr = NOT_A_REQUEST;
+  /* the length of SDO must be 8 */
+  m.len = 8;
+  for (i = 0 ; i < 8 ; i++) {
+    m.data[i] =  sdo.body.data[i];
+  }
+  return canSend(d->canHandle,&m);
+}
+
+/*!
+**
+**
+** @param d
+** @param whoami
+** @param index
+** @param subIndex
+** @param abortCode
+**
+** @return
+**/
+UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS8 nodeID, UNS16 index, UNS8 subIndex, UNS32 abortCode)
+{
+  s_SDO sdo;
+  UNS8 ret;
+  
+  MSG_WAR(0x2A50,"Sending SDO abort ", abortCode);
+  if(whoami == SDO_SERVER)
+  {
+    sdo.nodeId = *d->bDeviceNodeId;
+  }
+  else
+  {
+    sdo.nodeId = nodeID;
+  }
+  sdo.body.data[0] = 0x80;
+  /* Index */
+  sdo.body.data[1] = index & 0xFF; /* LSB */
+  sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
+  /* Subindex */
+  sdo.body.data[3] = subIndex;
+  /* Data */
+  sdo.body.data[4] = (UNS8)(abortCode & 0xFF);
+  sdo.body.data[5] = (UNS8)((abortCode >> 8) & 0xFF);
+  sdo.body.data[6] = (UNS8)((abortCode >> 16) & 0xFF);
+  sdo.body.data[7] = (UNS8)((abortCode >> 24) & 0xFF);
+  ret = sendSDO(d, whoami, sdo);
+
+  return ret;
+}
+
+/*!
+**
+**
+** @param d
+** @param m
+**
+** @return
+**/
+UNS8 proceedSDO (CO_Data* d, Message *m)
+{
+  UNS8 err;
+  UNS8 line;
+  UNS32 nbBytes; /* received or to be transmited. */
+  UNS8 nodeId = 0;  /* The node from which the SDO is received */
+  UNS8 *pNodeId = NULL;
+  UNS8 whoami = SDO_UNKNOWN;  /* SDO_SERVER or SDO_CLIENT.*/
+  UNS32 errorCode; /* while reading or writing in the local object dictionary.*/
+  s_SDO sdo;    /* SDO to transmit */
+  UNS16 index;
+  UNS8 subIndex;
+  UNS32 abortCode;
+  UNS32 i;
+  UNS8    j;
+  UNS32 *pCobId = NULL;
+  UNS16 offset;
+  UNS16 lastIndex;
+
+  MSG_WAR(0x3A60, "proceedSDO ", 0);
+  whoami = SDO_UNKNOWN;
+  /* Looking for the cobId in the object dictionary. */
+  /* Am-I a server ? */
+  offset = d->firstIndex->SDO_SVR;
+  lastIndex = d->lastIndex->SDO_SVR;
+  j = 0;
+  if(offset) while (offset <= lastIndex) {
+     if (d->objdict[offset].bSubCount <= 1) {
+      MSG_ERR(0x1A61, "Subindex 1  not found at index ", 0x1200 + j);
+      return 0xFF;
+    }
+      pCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
+      if ( *pCobId == UNS16_LE(m->cob_id) ) {
+    whoami = SDO_SERVER;
+    MSG_WAR(0x3A62, "proceedSDO. I am server. index : ", 0x1200 + j);
+    /* In case of server, the node id of the client may be unknown. So we put the index minus offset */
+    /* 0x1200 where the cobid received is defined. */
+    nodeId = j;
+    break;
+      }
+      j++;
+      offset++;
+  } /* end while */
+  if (whoami == SDO_UNKNOWN) {
+    /* Am-I client ? */
+    offset = d->firstIndex->SDO_CLT;
+    lastIndex = d->lastIndex->SDO_CLT;
+    j = 0;
+    if(offset) while (offset <= lastIndex) {
+       if (d->objdict[offset].bSubCount <= 3) {
+     MSG_ERR(0x1A63, "Subindex 3  not found at index ", 0x1280 + j);
+     return 0xFF;
+       }
+       /* a) Looking for the cobid received. */
+       pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
+       if (*pCobId == UNS16_LE(m->cob_id) ) {
+     /* b) cobid found, so reading the node id of the server. */
+     pNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
+     whoami = SDO_CLIENT;
+     nodeId = *pNodeId;
+     MSG_WAR(0x3A64, "proceedSDO. I am server. index : ", 0x1280 + j);
+     MSG_WAR(0x3A65, "                 Server nodeId : ", nodeId);
+     break;
+    }
+       j++;
+       offset++;
+    } /* end while */
+  }
+  if (whoami == SDO_UNKNOWN) {
+    return 0xFF;/* This SDO was not for us ! */
+  }
+
+  /* Test if the size of the SDO is ok */
+  if ( (*m).len != 8) {
+    MSG_ERR(0x1A67, "Error size SDO. CobId  : ", UNS16_LE(m->cob_id));
+    failedSDO(d, nodeId, whoami, 0, 0, SDOABT_GENERAL_ERROR);
+    return 0xFF;
+  }
+
+  if (whoami == SDO_CLIENT) {
+    MSG_WAR(0x3A68, "I am CLIENT. Received SDO from nodeId : ", nodeId);
+  }
+  else {
+    MSG_WAR(0x3A69, "I am SERVER. Received SDO cobId : ", UNS16_LE(m->cob_id));
+  }
+
+  /* Testing the command specifier */
+  /* Allowed : cs = 0, 1, 2, 3, 4. (=  all except those for block tranfert). */
+  /* cs = other : Not allowed -> abort. */
+  switch (getSDOcs(m->data[0])) {
+
+  case 0:
+    /* I am SERVER */
+    if (whoami == SDO_SERVER) {
+      /* Receiving a download segment data. */
+      /* A SDO transfert should have been yet initiated. */
+      err = getSDOlineOnUse( d, nodeId, whoami, &line );
+      if (!err)
+    err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
+      if (err) {
+    MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ",
+        nodeId);
+    failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+    return 0xFF;
+      }
+      /* Reset the wathdog */
+      RestartSDO_TIMER(line)
+      MSG_WAR(0x3A71, "Received SDO download segment defined at index 0x1200 + ", nodeId);
+      index = d->transfers[line].index;
+      subIndex = d->transfers[line].subIndex;
+      /* Toggle test. */
+      if (d->transfers[line].toggle != getSDOt(m->data[0])) {
+    MSG_ERR(0x1A72, "SDO error : Toggle error : ", getSDOt(m->data[0]));
+    failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
+    return 0xFF;
+      }
+      /* Nb of data to be downloaded */
+      nbBytes = 7 - getSDOn3(m->data[0]);
+      /* Store the data in the transfert structure. */
+      err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
+      if (err) {
+    failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+    return 0xFF;
+      }
+      /* Sending the SDO response, CS = 1 */
+      sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender). */
+      sdo.body.data[0] = (1 << 5) | (d->transfers[line].toggle << 4);
+      for (i = 1 ; i < 8 ; i++)
+    sdo.body.data[i] = 0;
+      MSG_WAR(0x3A73, "SDO. Send response to download request defined at index 0x1200 + ", nodeId);
+      sendSDO(d, whoami, sdo);
+      /* Inverting the toggle for the next segment. */
+      d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
+      /* If it was the last segment, */
+      if (getSDOc(m->data[0])) {
+    /* Transfering line data to object dictionary. */
+    /* The code does not use the "d" of initiate frame. So it is safe if e=s=0 */
+    errorCode = SDOlineToObjdict(d, line);
+    if (errorCode) {
+      MSG_ERR(0x1A54, "SDO error : Unable to copy the data in the object dictionary", 0);
+      failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
+      return 0xFF;
+    }
+    /* Release of the line */
+    resetSDOline(d, line);
+    MSG_WAR(0x3A74, "SDO. End of download defined at index 0x1200 + ", nodeId);
+      }
+    } /* end if SERVER */
+    else { /* if CLIENT */
+      /* I am CLIENT */
+      /* It is a request for a previous upload segment. We should find a line opened for this.*/
+      err = getSDOlineOnUse( d, nodeId, whoami, &line);
+      if (!err)
+    err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
+      if (err) {
+    MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
+    failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+    return 0xFF;
+      }
+      /* Reset the wathdog */
+      RestartSDO_TIMER(line)
+      index = d->transfers[line].index;
+      subIndex = d->transfers[line].subIndex;
+      /* test of the toggle; */
+      if (d->transfers[line].toggle != getSDOt(m->data[0])) {
+    MSG_ERR(0x1A76, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
+    failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
+    return 0xFF;
+      }
+      /* nb of data to be uploaded */
+      nbBytes = 7 - getSDOn3(m->data[0]);
+      /* Storing the data in the line structure. */
+      err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
+      if (err) {
+    failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+    return 0xFF;
+      }
+      /* Inverting the toggle for the next segment. */
+      d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
+      /* If it was the last segment,*/
+      if ( getSDOc(m->data[0])) {
+    /* Put in state finished */
+    /* The code is safe for the case e=s=0 in initiate frame. */
+    StopSDO_TIMER(line)
+    d->transfers[line].state = SDO_FINISHED;
+    if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
+
+    MSG_WAR(0x3A77, "SDO. End of upload from node : ", nodeId);
+      }
+      else { /* more segments to receive */
+         /* Sending the request for the next segment. */
+    sdo.nodeId = nodeId;
+    sdo.body.data[0] = (3 << 5) | (d->transfers[line].toggle << 4);
+    for (i = 1 ; i < 8 ; i++)
+      sdo.body.data[i] = 0;
+    sendSDO(d, whoami, sdo);
+    MSG_WAR(0x3A78, "SDO send upload segment request to nodeId", nodeId);
+      }
+    } /* End if CLIENT */
+    break;
+
+  case 1:
+    /* I am SERVER */
+    /* Receive of an initiate download */
+    if (whoami == SDO_SERVER) {
+      index = getSDOindex(m->data[1],m->data[2]);
+      subIndex = getSDOsubIndex(m->data[3]);
+      MSG_WAR(0x3A79, "Received SDO Initiate Download (to store data) defined at index 0x1200 + ",
+          nodeId);
+      MSG_WAR(0x3A80, "Writing at index : ", index);
+      MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
+
+      /* Search if a SDO transfert have been yet initiated */
+      err = getSDOlineOnUse( d, nodeId, whoami, &line );
+      if (! err) {
+    MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
+    failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
+    return 0xFF;
+      }
+      /* No line on use. Great ! */
+      /* Try to open a new line. */
+      err = getSDOfreeLine( d, whoami, &line );
+      if (err) {
+    MSG_ERR(0x1A82, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
+    failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
+    return 0xFF;
+      }
+      initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
+
+      if (getSDOe(m->data[0])) { /* If SDO expedited */
+    /* nb of data to be downloaded */
+    nbBytes = 4 - getSDOn2(m->data[0]);
+    /* Storing the data in the line structure. */
+    d->transfers[line].count = nbBytes;
+    err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
+
+    if (err) {
+      failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+      return 0xFF;
+    }
+
+    /* SDO expedited -> transfert finished. Data can be stored in the dictionary. */
+    /*The line will be reseted when it is downloading in the dictionary. */
+    MSG_WAR(0x3A83, "SDO Initiate Download is an expedited transfert. Finished.: ", nodeId);
+    /* Transfering line data to object dictionary. */
+    errorCode = SDOlineToObjdict(d, line);
+    if (errorCode) {
+      MSG_ERR(0x1A84, "SDO error : Unable to copy the data in the object dictionary", 0);
+      failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
+      return 0xFF;
+    }
+    /* Release of the line. */
+    resetSDOline(d, line);
+      }
+      else {/* So, if it is not an expedited transfert */
+    if (getSDOs(m->data[0])) {
+      nbBytes = (m->data[4]) + ((UNS32)(m->data[5])<<8) + ((UNS32)(m->data[6])<<16) + ((UNS32)(m->data[7])<<24);
+      err = setSDOlineRestBytes(d, nodeId, nbBytes);
+      if (err) {
+        failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+        return 0xFF;
+      }
+    }
+      }
+      /*Sending a SDO, cs=3*/
+      sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender).*/
+      sdo.body.data[0] = 3 << 5;
+      sdo.body.data[1] = index & 0xFF;        /* LSB */
+      sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
+      sdo.body.data[3] = subIndex;
+      for (i = 4 ; i < 8 ; i++)
+        sdo.body.data[i] = 0;
+      sendSDO(d, whoami, sdo);
+    } /* end if I am SERVER */
+    else {
+      /* I am CLIENT */
+      /* It is a response for a previous download segment. We should find a line opened for this. */
+      err = getSDOlineOnUse( d, nodeId, whoami, &line);
+      if (!err)
+    err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
+      if (err) {
+    MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
+    failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+    return 0xFF;
+      }
+      /* Reset the wathdog */
+      RestartSDO_TIMER(line)
+      index = d->transfers[line].index;
+      subIndex = d->transfers[line].subIndex;
+      /* test of the toggle; */
+      if (d->transfers[line].toggle != getSDOt(m->data[0])) {
+    MSG_ERR(0x1A86, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
+    failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
+    return 0xFF;
+      }
+
+      /* End transmission or downloading next segment. We need to know if it will be the last one. */
+      getSDOlineRestBytes(d, line, &nbBytes);
+      if (nbBytes == 0) {
+    MSG_WAR(0x3A87, "SDO End download. segment response received. OK. from nodeId", nodeId);
+    StopSDO_TIMER(line)
+    d->transfers[line].state = SDO_FINISHED;
+    if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
+    return 0x00;
+      }
+      /* At least one transfer to send.    */
+      if (nbBytes > 7) {
+    /* several segments to download.*/
+    /* code to send the next segment. (cs = 0; c = 0) */
+    d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
+    sdo.nodeId = nodeId; /* The server node Id; */
+    sdo.body.data[0] = (d->transfers[line].toggle << 4);
+    err = lineToSDO(d, line, 7, sdo.body.data + 1);
+    if (err) {
+      failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+      return 0xFF;
+    }
+      }
+      else {
+    /* Last segment. */
+    /* code to send the last segment. (cs = 0; c = 1)*/
+    d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
+    sdo.nodeId = nodeId; /* The server node Id; */
+    sdo.body.data[0] = (UNS8)((d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1);
+    err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
+    if (err) {
+      failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+      return 0xFF;
+    }
+    for (i = nbBytes + 1 ; i < 8 ; i++)
+      sdo.body.data[i] = 0;
+      }
+      MSG_WAR(0x3A88, "SDO sending download segment to nodeId", nodeId);
+      sendSDO(d, whoami, sdo);
+    } /* end if I am a CLIENT */
+    break;
+
+  case 2:
+    /* I am SERVER */
+    /* Receive of an initiate upload.*/
+    if (whoami == SDO_SERVER) {
+      index = getSDOindex(m->data[1],m->data[2]);
+      subIndex = getSDOsubIndex(m->data[3]);
+      MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ",
+          nodeId);
+      MSG_WAR(0x3A90, "Reading at index : ", index);
+      MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
+      /* Search if a SDO transfert have been yet initiated*/
+      err = getSDOlineOnUse( d, nodeId, whoami, &line );
+      if (! err) {
+        MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
+        MSG_WAR(0x3A93, "nodeId = ", nodeId);
+        failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
+        return 0xFF;
+      }
+      /* No line on use. Great !*/
+      /* Try to open a new line.*/
+      err = getSDOfreeLine( d, whoami, &line );
+      if (err) {
+    MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
+    failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
+    return 0xFF;
+      }
+      initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
+      /* Transfer data from dictionary to the line structure. */
+      errorCode = objdictToSDOline(d, line);
+
+      if (errorCode) {
+    MSG_ERR(0x1A94, "SDO error : Unable to copy the data from object dictionary. Err code : ",
+        errorCode);
+    failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
+    return 0xFF;
+    }
+      /* Preparing the response.*/
+      getSDOlineRestBytes(d, line, &nbBytes);    /* Nb bytes to transfer ? */
+      sdo.nodeId = nodeId; /* The server node Id; */
+      if (nbBytes > 4) {
+    /* normal transfert. (segmented). */
+    /* code to send the initiate upload response. (cs = 2) */
+    sdo.body.data[0] = (2 << 5) | 1;
+    sdo.body.data[1] = index & 0xFF;        /* LSB */
+    sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
+    sdo.body.data[3] = subIndex;
+    sdo.body.data[4] = (UNS8)nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
+    /* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
+    /* in the object dictionary, at every index and subindex. */
+    for (i = 5 ; i < 8 ; i++)
+      sdo.body.data[i] = 0;
+    MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
+    sendSDO(d, whoami, sdo);
+      }
+      else {
+    /* Expedited upload. (cs = 2 ; e = 1) */
+    sdo.body.data[0] = (UNS8)((2 << 5) | ((4 - nbBytes) << 2) | 3);
+    sdo.body.data[1] = index & 0xFF;        /* LSB */
+    sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
+    sdo.body.data[3] = subIndex;
+    err = lineToSDO(d, line, nbBytes, sdo.body.data + 4);
+    if (err) {
+      failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+      return 0xFF;
+    }
+    for (i = 4 + nbBytes ; i < 8 ; i++)
+      sdo.body.data[i] = 0;
+    MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ",
+        nodeId);
+    sendSDO(d, whoami, sdo);
+    /* Release the line.*/
+    resetSDOline(d, line);
+      }
+    } /* end if I am SERVER*/
+    else {
+      /* I am CLIENT */
+      /* It is the response for the previous initiate upload request.*/
+      /* We should find a line opened for this. */
+      err = getSDOlineOnUse( d, nodeId, whoami, &line);
+      if (!err)
+    err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
+      if (err) {
+    MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);
+    failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+    return 0xFF;
+      }
+      /* Reset the wathdog */
+      RestartSDO_TIMER(line)
+      index = d->transfers[line].index;
+      subIndex = d->transfers[line].subIndex;
+
+      if (getSDOe(m->data[0])) { /* If SDO expedited */
+    /* nb of data to be uploaded */
+      nbBytes = 4 - getSDOn2(m->data[0]);
+    /* Storing the data in the line structure. */
+    err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
+    if (err) {
+      failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+      return 0xFF;
+    }
+    /* SDO expedited -> transfert finished. data are available via  getReadResultNetworkDict(). */
+    MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);
+    StopSDO_TIMER(line)
+    d->transfers[line].count = nbBytes;
+    d->transfers[line].state = SDO_FINISHED;
+    if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
+    return 0;
+      }
+      else { /* So, if it is not an expedited transfert */
+    /* Storing the nb of data to receive. */
+    if (getSDOs(m->data[0])) {
+      nbBytes = m->data[4] + ((UNS32)(m->data[5])<<8) + ((UNS32)(m->data[6])<<16) + ((UNS32)(m->data[7])<<24);
+      err = setSDOlineRestBytes(d, line, nbBytes);
+      if (err) {
+        failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+        return 0xFF;
+      }
+    }
+    /* Requesting next segment. (cs = 3) */
+    sdo.nodeId = nodeId;
+    sdo.body.data[0] = 3 << 5;
+    for (i = 1 ; i < 8 ; i++)
+      sdo.body.data[i] = 0;
+    MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId);
+    sendSDO(d, whoami, sdo);
+      }
+    } /* End if CLIENT */
+    break;
+
+  case 3:
+    /* I am SERVER */
+    if (whoami == SDO_SERVER) {
+      /* Receiving a upload segment. */
+      /* A SDO transfert should have been yet initiated. */
+      err = getSDOlineOnUse( d, nodeId, whoami, &line );
+      if (!err)
+    err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
+      if (err) {
+    MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ",
+        nodeId);
+    failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+    return 0xFF;
+      }
+      /* Reset the wathdog */
+      RestartSDO_TIMER(line)
+      MSG_WAR(0x3AA1, "Received SDO upload segment defined at index 0x1200 + ", nodeId);
+      index = d->transfers[line].index;
+      subIndex = d->transfers[line].subIndex;
+      /* Toggle test.*/
+      if (d->transfers[line].toggle != getSDOt(m->data[0])) {
+    MSG_ERR(0x1AA2, "SDO error : Toggle error : ", getSDOt(m->data[0]));
+    failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
+    return 0xFF;
+      }
+      /* Uploading next segment. We need to know if it will be the last one. */
+      getSDOlineRestBytes(d, line, &nbBytes);
+      if (nbBytes > 7) {
+    /* The segment to transfer is not the last one.*/
+    /* code to send the next segment. (cs = 0; c = 0) */
+    sdo.nodeId = nodeId; /* The server node Id; */
+    sdo.body.data[0] = (d->transfers[line].toggle << 4);
+    err = lineToSDO(d, line, 7, sdo.body.data + 1);
+    if (err) {
+      failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+      return 0xFF;
+    }
+    /* Inverting the toggle for the next tranfert. */
+    d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
+    MSG_WAR(0x3AA3, "SDO. Sending upload segment defined at index 0x1200 + ", nodeId);
+    sendSDO(d, whoami, sdo);
+      }
+      else {
+    /* Last segment. */
+    /* code to send the last segment. (cs = 0; c = 1) */
+    sdo.nodeId = nodeId; /** The server node Id; */
+    sdo.body.data[0] = (UNS8)((d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1);
+    err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
+    if (err) {
+      failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+      return 0xFF;
+    }
+    for (i = nbBytes + 1 ; i < 8 ; i++)
+      sdo.body.data[i] = 0;
+    MSG_WAR(0x3AA4, "SDO. Sending last upload segment defined at index 0x1200 + ", nodeId);
+    sendSDO(d, whoami, sdo);
+    /* Release the line */
+    resetSDOline(d, line);
+      }
+    } /* end if SERVER*/
+    else {
+      /* I am CLIENT */
+      /* It is the response for the previous initiate download request. */
+      /* We should find a line opened for this. */
+      err = getSDOlineOnUse( d, nodeId, whoami, &line);
+      if (!err)
+    err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
+      if (err) {
+    MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId);
+    failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
+    return 0xFF;
+      }
+      /* Reset the watchdog */
+      RestartSDO_TIMER(line)
+      index = d->transfers[line].index;
+      subIndex = d->transfers[line].subIndex;
+      /* End transmission or requesting  next segment. */
+      getSDOlineRestBytes(d, line, &nbBytes);
+      if (nbBytes == 0) {
+    MSG_WAR(0x3AA6, "SDO End download expedited. Response received. from nodeId", nodeId);
+    StopSDO_TIMER(line)
+    d->transfers[line].state = SDO_FINISHED;
+    if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
+    return 0x00;
+      }
+      if (nbBytes > 7) {
+    /* more than one request to send */
+    /* code to send the next segment. (cs = 0; c = 0)    */
+    sdo.nodeId = nodeId; /** The server node Id; */
+    sdo.body.data[0] = (d->transfers[line].toggle << 4);
+    err = lineToSDO(d, line, 7, sdo.body.data + 1);
+    if (err) {
+      failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+      return 0xFF;
+    }
+      }
+      else {
+    /* Last segment.*/
+    /* code to send the last segment. (cs = 0; c = 1)    */
+    sdo.nodeId = nodeId; /* The server node Id; */
+    sdo.body.data[0] = (UNS8)((d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1);
+    err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
+    if (err) {
+      failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
+      return 0xFF;
+    }
+    for (i = nbBytes + 1 ; i < 8 ; i++)
+      sdo.body.data[i] = 0;
+      }
+      MSG_WAR(0x3AA7, "SDO sending download segment to nodeId", nodeId);
+      sendSDO(d, whoami, sdo);
+
+    } /* end if I am a CLIENT        */
+    break;
+
+   case 4:
+     abortCode =
+      (UNS32)m->data[4] |
+      ((UNS32)m->data[5] << 8) |
+      ((UNS32)m->data[6] << 16) |
+      ((UNS32)m->data[7] << 24);
+    /* Received SDO abort. */
+    /* Looking for the line concerned. */
+    if (whoami == SDO_SERVER) {
+      err = getSDOlineOnUse( d, nodeId, whoami, &line );
+      if (!err) {
+    resetSDOline( d, line );
+    MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
+      }
+      else
+    MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
+      /* Tips : The end user has no way to know that the server node has received an abort SDO. */
+      /* Its is ok, I think.*/
+    }
+    else { /* If I am CLIENT */
+      err = getSDOlineOnUse( d, nodeId, whoami, &line );
+      if (!err) {
+    /* The line *must* be released by the core program. */
+    StopSDO_TIMER(line)
+    d->transfers[line].state = SDO_ABORTED_RCV;
+    d->transfers[line].abortCode = abortCode;
+    MSG_WAR(0x3AB0, "SD0. Received SDO abort. Line state ABORTED. Code : ", abortCode);
+    if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
+      }
+      else
+    MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
+    }
+    break;
+  default:
+    /* Error : Unknown cs */
+    MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
+    return 0xFF;
+
+  } /* End switch */
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+** @param Callback
+** @param endianize
+**
+** @return
+**/
+INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
+               UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
+{
+  UNS8 err;
+  UNS8 SDOfound = 0;
+  UNS8 line;
+  s_SDO sdo;    /* SDO to transmit */
+  UNS8 i;
+  UNS32 j;
+  UNS16     lastIndex;
+  UNS16     offset;
+  UNS8      *pNodeIdServer;
+  UNS8      nodeIdServer;
+
+  MSG_WAR(0x3AC0, "Send SDO to write in the dictionary of node : ", nodeId);
+  MSG_WAR(0x3AC1, "                                   At index : ", index);
+  MSG_WAR(0x3AC2, "                                   subIndex : ", subIndex);
+  MSG_WAR(0x3AC3, "                                   nb bytes : ", count);
+
+  /* Verify that there is no SDO communication yet. */
+  err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
+  if (!err) {
+    MSG_ERR(0x1AC4, "SDO error : Communication yet established. with node : ", nodeId);
+    return 0xFF;
+  }
+  /* Taking the line ... */
+  err = getSDOfreeLine( d, SDO_CLIENT, &line );
+  if (err) {
+    MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
+    return (0xFF);
+  }
+  /* Check which SDO to use to communicate with the node */
+  offset = d->firstIndex->SDO_CLT;
+  lastIndex = d->lastIndex->SDO_CLT;
+  if (offset == 0) {
+    MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
+    return 0xFF;
+  }
+  i = 0;
+   while (offset <= lastIndex) {
+     if (d->objdict[offset].bSubCount <= 3) {
+     MSG_ERR(0x1AC8, "Subindex 3  not found at index ", 0x1280 + i);
+     return 0xFF;
+     }
+     /* looking for the nodeId server */
+     pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
+     nodeIdServer = *pNodeIdServer;
+     MSG_WAR(0x1AD2, "index : ", 0x1280 + i);
+     MSG_WAR(0x1AD3, "nodeIdServer : ", nodeIdServer);
+
+    if(nodeIdServer == nodeId) {
+      SDOfound = 1;
+      break;
+    }
+    offset++;
+    i++;
+  } /* end while */
+  if (!SDOfound) {
+    MSG_ERR(0x1AC9, "SDO. Error. No client found to communicate with node : ", nodeId);
+    return 0xFE;
+  }
+  MSG_WAR(0x3AD0,"        SDO client defined at index  : ", 0x1280 + i);
+  initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
+  d->transfers[line].count = count;
+  d->transfers[line].dataType = dataType;
+
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  {
+    UNS8* lineData = d->transfers[line].data;
+    if (count > SDO_MAX_LENGTH_TRANSFERT)
+    {
+      d->transfers[line].dynamicData = (UNS8*) malloc(count);
+      d->transfers[line].dynamicDataSize = count;
+      if (d->transfers[line].dynamicData == NULL)
+      {
+        MSG_ERR(0x1AC9, "SDO. Error. Could not allocate enough bytes : ", count);
+        return 0xFE;
+      }
+      lineData = d->transfers[line].dynamicData;
+    }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
+  /* Copy data to transfers structure. */
+  for (j = 0 ; j < count ; j++) {
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+# ifdef CANOPEN_BIG_ENDIAN
+      if (dataType == 0 && endianize)
+        lineData[count - 1 - j] = ((char *)data)[j];
+      else /* String of bytes. */
+        lineData[j] = ((char *)data)[j];
+#  else
+      lineData[j] = ((char *)data)[j];
+#  endif
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
+# ifdef CANOPEN_BIG_ENDIAN
+    if (dataType == 0 && endianize)
+      d->transfers[line].data[count - 1 - j] = ((char *)data)[j];
+    else /* String of bytes. */
+      d->transfers[line].data[j] = ((char *)data)[j];
+#  else
+    d->transfers[line].data[j] = ((char *)data)[j];
+#  endif
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+  }
+  /* Send the SDO to the server. Initiate download, cs=1. */
+  sdo.nodeId = nodeId;
+  if (count <= 4) { /* Expedited transfert */
+    sdo.body.data[0] = (UNS8)((1 << 5) | ((4 - count) << 2) | 3);
+    for (i = 4 ; i < 8 ; i++)
+      sdo.body.data[i] = d->transfers[line].data[i - 4];
+    d->transfers[line].offset = count;
+  }
+  else { /** Normal transfert */
+    sdo.body.data[0] = (1 << 5) | 1;
+    for (i = 0 ; i < 4 ; i++)
+      sdo.body.data[i+4] = (UNS8)((count >> (i<<3))); /* i*8 */
+  }
+  sdo.body.data[1] = index & 0xFF;        /* LSB */
+  sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
+  sdo.body.data[3] = subIndex;
+
+  d->transfers[line].Callback = Callback;
+
+  err = sendSDO(d, SDO_CLIENT, sdo);
+  if (err) {
+    MSG_ERR(0x1AD1, "SDO. Error while sending SDO to node : ", nodeId);
+    /* release the line */
+    resetSDOline(d, line);
+    return 0xFF;
+  }
+
+
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+**
+** @return
+**/
+UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
+               UNS8 subIndex, UNS32 count, UNS8 dataType, void *data)
+{
+    return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param count
+** @param dataType
+** @param data
+** @param Callback
+**
+** @return
+**/
+UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index,
+               UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback)
+{
+    return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
+}
+
+UNS8 writeNetworkDictCallBackAI (CO_Data* d, UNS8 nodeId, UNS16 index,
+               UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
+{
+    UNS8 ret;
+    UNS16 lastIndex;
+    UNS16 offset;
+    UNS8 nodeIdServer;
+    UNS8 i;
+
+    ret = _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, endianize);
+    if(ret == 0xFE)
+    {
+        offset = d->firstIndex->SDO_CLT;
+        lastIndex = d->lastIndex->SDO_CLT;
+        if (offset == 0)
+        {
+            MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
+            return 0xFF;
+        }
+        i = 0;
+        while (offset <= lastIndex)
+        {
+            if (d->objdict[offset].bSubCount <= 3)
+            {
+                MSG_ERR(0x1AC8, "Subindex 3  not found at index ", 0x1280 + i);
+                return 0xFF;
+            }
+            nodeIdServer = *(UNS8*) d->objdict[offset].pSubindex[3].pObject;
+            if(nodeIdServer == 0)
+            {
+                *(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
+                *(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
+                *(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
+                return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
+            }
+            offset++;
+        }
+        return 0xFF;
+    }
+    else if(ret == 0)
+    {
+        return 0;
+    }
+    else
+    {
+        return 0xFF;
+    }
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param dataType
+** @param Callback
+**
+** @return
+**/
+INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
+{
+  UNS8 err;
+  UNS8 SDOfound = 0;
+  UNS8 i;
+  UNS8 line;
+  s_SDO sdo;    /* SDO to transmit */
+  UNS8      *pNodeIdServer;
+  UNS8      nodeIdServer;
+  UNS16     offset;
+  UNS16     lastIndex;
+  MSG_WAR(0x3AD5, "Send SDO to read in the dictionary of node : ", nodeId);
+  MSG_WAR(0x3AD6, "                                  At index : ", index);
+  MSG_WAR(0x3AD7, "                                  subIndex : ", subIndex);
+
+
+  /* Verify that there is no SDO communication yet. */
+  err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
+  if (!err) {
+    MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId);
+    return 0xFF;
+  }
+  /* Taking the line ... */
+  err = getSDOfreeLine( d, SDO_CLIENT, &line );
+  if (err) {
+    MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
+    return (0xFF);
+  }
+  else
+    MSG_WAR(0x3AE0, "Transmission on line : ", line);
+
+  /* Check which SDO to use to communicate with the node */
+  offset = d->firstIndex->SDO_CLT;
+  lastIndex = d->lastIndex->SDO_CLT;
+  if (offset == 0) {
+    MSG_ERR(0x1AE1, "writeNetworkDict : No SDO client index found", 0);
+    return 0xFF;
+  }
+  i = 0;
+  while (offset <= lastIndex) {
+     if (d->objdict[offset].bSubCount <= 3) {
+     MSG_ERR(0x1AE2, "Subindex 3  not found at index ", 0x1280 + i);
+     return 0xFF;
+     }
+     /* looking for the nodeId server */
+     pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
+     nodeIdServer = *pNodeIdServer;
+
+    if(nodeIdServer == nodeId) {
+      SDOfound = 1;
+      break;
+    }
+    offset++;
+    i++;
+  } /* end while */
+  if (!SDOfound) {
+    MSG_ERR(0x1AE3, "SDO. Error. No client found to communicate with node : ", nodeId);
+    return 0xFE;
+  }
+  MSG_WAR(0x3AE4,"        SDO client defined at index  : ", 0x1280 + i);
+  initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
+  getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
+  sdo.nodeId = nodeId;
+  /* Send the SDO to the server. Initiate upload, cs=2. */
+  d->transfers[line].dataType = dataType;
+  sdo.body.data[0] = (2 << 5);
+  sdo.body.data[1] = index & 0xFF;        /* LSB */
+  sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
+  sdo.body.data[3] = subIndex;
+  for (i = 4 ; i < 8 ; i++)
+    sdo.body.data[i] = 0;
+  d->transfers[line].Callback = Callback;
+  err = sendSDO(d, SDO_CLIENT, sdo);
+  if (err) {
+    MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
+    /* release the line */
+    resetSDOline(d, line);
+    return 0xFF;
+  }
+  return 0;
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param dataType
+**
+** @return
+**/
+UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
+{
+    return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param index
+** @param subIndex
+** @param dataType
+** @param Callback
+**
+** @return
+**/
+UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
+{
+    return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
+}
+
+UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
+{
+    UNS8 ret;
+    UNS16 lastIndex;
+    UNS16 offset;
+    UNS8 nodeIdServer;
+    UNS8 i;
+
+    ret = _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
+    if(ret == 0xFE)
+    {
+        offset = d->firstIndex->SDO_CLT;
+        lastIndex = d->lastIndex->SDO_CLT;
+        if (offset == 0)
+        {
+            MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
+            return 0xFF;
+        }
+        i = 0;
+        while (offset <= lastIndex)
+        {
+            if (d->objdict[offset].bSubCount <= 3)
+            {
+                MSG_ERR(0x1AC8, "Subindex 3  not found at index ", 0x1280 + i);
+                return 0xFF;
+            }
+            nodeIdServer = *(UNS8*) d->objdict[offset].pSubindex[3].pObject;
+            if(nodeIdServer == 0)
+            {
+                *(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
+                *(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
+                *(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
+                return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
+            }
+            offset++;
+        }
+        return 0xFF;
+    }
+    else if(ret == 0)
+    {
+        return 0;
+    }
+    else
+    {
+        return 0xFF;
+    }
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param data
+** @param size pointer to expected size, changed into returned size. Expected size will be truncated to transfered data size
+** @param abortCode
+**
+** @return
+**/
+UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS32 *size,
+                   UNS32 * abortCode)
+{
+  UNS32 i;
+  UNS8 err;
+  UNS8 line;
+  * abortCode = 0;
+
+  /* Looking for the line tranfert. */
+  err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
+  if (err) {
+    MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
+    return SDO_ABORTED_INTERNAL;
+  }
+  * abortCode = d->transfers[line].abortCode;
+  if (d->transfers[line].state != SDO_FINISHED)
+    return d->transfers[line].state;
+
+  /* if SDO initiated with e=0 and s=0 count is null, offset carry effective size*/
+  if( d->transfers[line].count == 0)
+      d->transfers[line].count = d->transfers[line].offset;
+  /* use transfers[line].count as max size */
+  if( d->transfers[line].count < *size )
+      *size = d->transfers[line].count;
+
+  /* Copy payload to data pointer */
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  {
+    UNS8 *lineData = d->transfers[line].data;
+
+    if (d->transfers[line].dynamicData && d->transfers[line].dynamicDataSize)
+    {
+      lineData = d->transfers[line].dynamicData;
+    }
+    for  ( i = 0 ; i < *size ; i++) {
+# ifdef CANOPEN_BIG_ENDIAN
+      if (d->transfers[line].dataType != visible_string)
+        ( (char *) data)[*size - 1 - i] = lineData[i];
+      else /* String of bytes. */
+        ( (char *) data)[i] = lineData[i];
+# else
+      ( (char *) data)[i] = lineData[i];
+# endif
+    }
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
+  for  ( i = 0 ; i < *size ; i++) {
+# ifdef CANOPEN_BIG_ENDIAN
+    if (d->transfers[line].dataType != visible_string)
+      ( (char *) data)[*size - 1 - i] = d->transfers[line].data[i];
+    else /* String of bytes. */
+      ( (char *) data)[i] = d->transfers[line].data[i];
+# else
+    ( (char *) data)[i] = d->transfers[line].data[i];
+# endif
+  }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+  return SDO_FINISHED;
+}
+
+/*!
+**
+**
+** @param d
+** @param nodeId
+** @param abortCode
+**
+** @return
+**/
+UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode)
+{
+  UNS8 line = 0;
+  UNS8 err;
+
+  * abortCode = 0;
+  /* Looking for the line tranfert. */
+  err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
+  if (err) {
+    MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);
+    return SDO_ABORTED_INTERNAL;
+  }
+  * abortCode = d->transfers[line].abortCode;
+  return d->transfers[line].state;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/states.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,317 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/*!
+** @file   states.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Tue Jun  5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
+
+#include "data.h"
+#include "sysdep.h"
+
+/** Prototypes for internals functions */
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param newCommunicationState                                                                    
+**/     
+void switchCommunicationState(CO_Data* d, 
+    s_state_communication *newCommunicationState);
+    
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+**                                                                                                 
+** @return                                                                                         
+**/    
+e_nodeState getState(CO_Data* d)
+{
+  return d->nodeState;
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param m                                                                                        
+**/  
+void canDispatch(CO_Data* d, Message *m)
+{
+    UNS16 cob_id = UNS16_LE(m->cob_id);
+     switch(cob_id >> 7)
+    {
+        case SYNC:        /* can be a SYNC or a EMCY message */
+            if(cob_id == 0x080)    /* SYNC */
+            {
+                if(d->CurrentCommunicationState.csSYNC)
+                    proceedSYNC(d);
+            } else         /* EMCY */
+                if(d->CurrentCommunicationState.csEmergency)
+                    proceedEMCY(d,m);
+            break;
+        /* case TIME_STAMP: */
+        case PDO1tx:
+        case PDO1rx:
+        case PDO2tx:
+        case PDO2rx:
+        case PDO3tx:
+        case PDO3rx:
+        case PDO4tx:
+        case PDO4rx:
+            if (d->CurrentCommunicationState.csPDO)
+                proceedPDO(d,m);
+            break;
+        case SDOtx:
+        case SDOrx:
+            if (d->CurrentCommunicationState.csSDO)
+                proceedSDO(d,m);
+            break;
+        case NODE_GUARD:
+            if (d->CurrentCommunicationState.csHeartbeat)
+                proceedNODE_GUARD(d,m);
+            break;
+        case NMT:
+            if (*(d->iam_a_slave))
+            {
+                proceedNMTstateChange(d,m);
+            }
+#ifdef CO_ENABLE_LSS
+        case LSS:
+            if (!d->CurrentCommunicationState.csLSS)break;
+            if ((*(d->iam_a_slave)) && cob_id==MLSS_ADRESS)
+            {
+                proceedLSS_Slave(d,m);
+            }
+            else if(!(*(d->iam_a_slave)) && cob_id==SLSS_ADRESS)
+            {
+                proceedLSS_Master(d,m);
+            }
+            break;
+#endif
+    }
+}
+
+#define StartOrStop(CommType, FuncStart, FuncStop) \
+    if(newCommunicationState->CommType && d->CurrentCommunicationState.CommType == 0){\
+        MSG_WAR(0x9999,#FuncStart, 9999);\
+        d->CurrentCommunicationState.CommType = 1;\
+        FuncStart;\
+    }else if(!newCommunicationState->CommType && d->CurrentCommunicationState.CommType == 1){\
+        MSG_WAR(0x9999,#FuncStop, 9999);\
+        d->CurrentCommunicationState.CommType = 0;\
+        FuncStop;\
+    }
+#define None
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param newCommunicationState                                                                    
+**/      
+void switchCommunicationState(CO_Data* d, s_state_communication *newCommunicationState)
+{
+#ifdef CO_ENABLE_LSS
+    StartOrStop(csLSS,    startLSS(d),    stopLSS(d))
+#endif
+    StartOrStop(csSDO,    None,        resetSDO(d))
+    StartOrStop(csSYNC,    startSYNC(d),        stopSYNC(d))
+    StartOrStop(csHeartbeat,    heartbeatInit(d),    heartbeatStop(d))
+    StartOrStop(csEmergency,    emergencyInit(d),    emergencyStop(d)) 
+    StartOrStop(csPDO,    PDOInit(d),    PDOStop(d))
+    StartOrStop(csBoot_Up,    None,    slaveSendBootUp(d))
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param newState                                                                                 
+**                                                                                                 
+** @return                                                                                         
+**/  
+UNS8 setState(CO_Data* d, e_nodeState newState)
+{
+    if(newState != d->nodeState){
+        switch( newState ){
+            case Initialisation:
+            {
+                s_state_communication newCommunicationState = {1, 0, 0, 0, 0, 0, 0};
+                d->nodeState = Initialisation;
+                switchCommunicationState(d, &newCommunicationState);
+                /* call user app init callback now. */
+                /* d->initialisation MUST NOT CALL SetState */
+                (*d->initialisation)(d);                
+            }
+
+            /* Automatic transition - No break statement ! */
+            /* Transition from Initialisation to Pre_operational */
+            /* is automatic as defined in DS301. */
+            /* App don't have to call SetState(d, Pre_operational) */
+                                
+            case Pre_operational:
+            {
+                
+                s_state_communication newCommunicationState = {0, 1, 1, 1, 1, 0, 1};
+                d->nodeState = Pre_operational;
+                switchCommunicationState(d, &newCommunicationState);
+                if (!(*(d->iam_a_slave)))
+                {
+                    masterSendNMTstateChange (d, 0, NMT_Reset_Node);
+                }
+                (*d->preOperational)(d);
+            }
+            break;
+                                
+            case Operational:
+            if(d->nodeState == Initialisation) return 0xFF;
+            {
+                s_state_communication newCommunicationState = {0, 1, 1, 1, 1, 1, 0};
+                d->nodeState = Operational;
+                newState = Operational;
+                switchCommunicationState(d, &newCommunicationState);
+                (*d->operational)(d);
+            }
+            break;
+                        
+            case Stopped:
+            if(d->nodeState == Initialisation) return 0xFF;
+            {
+                s_state_communication newCommunicationState = {0, 0, 0, 0, 1, 0, 1};
+                d->nodeState = Stopped;
+                newState = Stopped;
+                switchCommunicationState(d, &newCommunicationState);
+                (*d->stopped)(d);
+            }
+            break;
+            default:
+                return 0xFF;
+
+        }/* end switch case */
+    
+    }
+    /* d->nodeState contains the final state */
+    /* may not be the requested state */
+    return d->nodeState;  
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+**                                                                                                 
+** @return                                                                                         
+**/ 
+UNS8 getNodeId(CO_Data* d)
+{
+  return *d->bDeviceNodeId;
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param nodeId                                                                                   
+**/   
+void setNodeId(CO_Data* d, UNS8 nodeId)
+{
+  UNS16 offset = d->firstIndex->SDO_SVR;
+  
+#ifdef CO_ENABLE_LSS
+  d->lss_transfer.nodeID=nodeId;
+  if(nodeId==0xFF){
+      *d->bDeviceNodeId = nodeId;
+      return;
+  }
+  else
+#endif
+  if(!(nodeId>0 && nodeId<=127)){
+      MSG_WAR(0x2D01, "Invalid NodeID",nodeId);
+      return;
+  }
+
+  if(offset){
+    /* Adjust COB-ID Client->Server (rx) only id already set to default value or id not valid (id==0xFF)*/
+    if((*(UNS32*)d->objdict[offset].pSubindex[1].pObject == 0x600 + *d->bDeviceNodeId)||(*d->bDeviceNodeId==0xFF)){
+      /* cob_id_client = 0x600 + nodeId; */
+      *(UNS32*)d->objdict[offset].pSubindex[1].pObject = 0x600 + nodeId;
+    }
+    /* Adjust COB-ID Server -> Client (tx) only id already set to default value or id not valid (id==0xFF)*/
+    if((*(UNS32*)d->objdict[offset].pSubindex[2].pObject == 0x580 + *d->bDeviceNodeId)||(*d->bDeviceNodeId==0xFF)){
+      /* cob_id_server = 0x580 + nodeId; */
+      *(UNS32*)d->objdict[offset].pSubindex[2].pObject = 0x580 + nodeId;
+    }
+  }
+
+  /* 
+       Initialize the server(s) SDO parameters
+      Remember that only one SDO server is allowed, defined at index 0x1200    
+         
+      Initialize the client(s) SDO parameters     
+      Nothing to initialize (no default values required by the DS 401)    
+      Initialize the receive PDO communication parameters. Only for 0x1400 to 0x1403 
+  */
+  {
+    UNS8 i = 0;
+    UNS16 offset = d->firstIndex->PDO_RCV;
+    UNS16 lastIndex = d->lastIndex->PDO_RCV;
+    UNS32 cobID[] = {0x200, 0x300, 0x400, 0x500};
+    if( offset ) while( (offset <= lastIndex) && (i < 4)) {
+      if((*(UNS32*)d->objdict[offset].pSubindex[1].pObject == cobID[i] + *d->bDeviceNodeId)||(*d->bDeviceNodeId==0xFF))
+          *(UNS32*)d->objdict[offset].pSubindex[1].pObject = cobID[i] + nodeId;
+      i ++;
+      offset ++;
+    }
+  }
+  /* ** Initialize the transmit PDO communication parameters. Only for 0x1800 to 0x1803 */
+  {
+    UNS8 i = 0;
+    UNS16 offset = d->firstIndex->PDO_TRS;
+    UNS16 lastIndex = d->lastIndex->PDO_TRS;
+    UNS32 cobID[] = {0x180, 0x280, 0x380, 0x480};
+    i = 0;
+    if( offset ) while ((offset <= lastIndex) && (i < 4)) {
+      if((*(UNS32*)d->objdict[offset].pSubindex[1].pObject == cobID[i] + *d->bDeviceNodeId)||(*d->bDeviceNodeId==0xFF))
+          *(UNS32*)d->objdict[offset].pSubindex[1].pObject = cobID[i] + nodeId;
+      i ++;
+      offset ++;
+    }
+  }
+
+  /* Update EMCY COB-ID if already set to default*/
+  if((*d->error_cobid == *d->bDeviceNodeId + 0x80)||(*d->bDeviceNodeId==0xFF))
+    *d->error_cobid = nodeId + 0x80;
+
+  /* bDeviceNodeId is defined in the object dictionary. */
+  *d->bDeviceNodeId = nodeId;
+}
+
+void _initialisation(CO_Data* d){}
+void _preOperational(CO_Data* d){}
+void _operational(CO_Data* d){}
+void _stopped(CO_Data* d){}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/framework/src/sync.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,190 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+
+See COPYING file for copyrights details.
+
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+/*!
+** @file   sync.c
+** @author Edouard TISSERANT and Francis DUPIN
+** @date   Tue Jun  5 09:32:32 2007
+**
+** @brief
+**
+**
+*/
+
+#include "data.h"
+#include "sync.h"
+#include "canfestival.h"
+#include "sysdep.h"
+
+/* Prototypes for internals functions */
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param id                                                                                       
+**/  
+void SyncAlarm(CO_Data* d, UNS32 id);
+UNS32 OnCOB_ID_SyncUpdate(CO_Data* d, const indextable * unsused_indextable, 
+	UNS8 unsused_bSubindex);
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param id                                                                                       
+**/   
+void SyncAlarm(CO_Data* d, UNS32 id)
+{
+	sendSYNC(d) ;
+}
+
+/*!                                                                                                
+** This is called when Index 0x1005 is updated.                                                                                                
+**                                                                                                 
+** @param d                                                                                        
+** @param unsused_indextable                                                                       
+** @param unsused_bSubindex                                                                        
+**                                                                                                 
+** @return                                                                                         
+**/  
+UNS32 OnCOB_ID_SyncUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex)
+{
+	startSYNC(d);
+	return 0;
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+**/ 
+void startSYNC(CO_Data* d)
+{
+	if(d->syncTimer != TIMER_NONE){
+		stopSYNC(d);
+	}
+
+	RegisterSetODentryCallBack(d, 0x1005, 0, &OnCOB_ID_SyncUpdate);
+	RegisterSetODentryCallBack(d, 0x1006, 0, &OnCOB_ID_SyncUpdate);
+
+	if(*d->COB_ID_Sync & 0x40000000ul && *d->Sync_Cycle_Period)
+	{
+		d->syncTimer = SetAlarm(
+				d,
+				0 /*No id needed*/,
+				&SyncAlarm,
+				US_TO_TIMEVAL(*d->Sync_Cycle_Period), 
+				US_TO_TIMEVAL(*d->Sync_Cycle_Period));
+	}
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+**/   
+void stopSYNC(CO_Data* d)
+{
+    RegisterSetODentryCallBack(d, 0x1005, 0, NULL);
+    RegisterSetODentryCallBack(d, 0x1006, 0, NULL);
+	d->syncTimer = DelAlarm(d->syncTimer);
+}
+
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param cob_id                                                                                   
+**                                                                                                 
+** @return                                                                                         
+**/  
+UNS8 sendSYNCMessage(CO_Data* d)
+{
+  Message m;
+  
+  MSG_WAR(0x3001, "sendSYNC ", 0);
+  
+  m.cob_id = (UNS16)UNS16_LE(*d->COB_ID_Sync);
+  m.rtr = NOT_A_REQUEST;
+  m.len = 0;
+  
+  return canSend(d->canHandle,&m);
+}
+
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param cob_id                                                                                   
+**                                                                                                 
+** @return                                                                                         
+**/  
+UNS8 sendSYNC(CO_Data* d)
+{
+  UNS8 res;
+  res = sendSYNCMessage(d);
+  proceedSYNC(d) ; 
+  return res ;
+}
+
+/*!                                                                                                
+**                                                                                                 
+**                                                                                                 
+** @param d                                                                                        
+** @param m                                                                                        
+**                                                                                                 
+** @return                                                                                         
+**/ 
+UNS8 proceedSYNC(CO_Data* d)
+{
+
+  UNS8 res;
+  
+  MSG_WAR(0x3002, "SYNC received. Proceed. ", 0);
+  
+  (*d->post_sync)(d);
+
+  /* only operational state allows PDO transmission */
+  if(! d->CurrentCommunicationState.csPDO) 
+    return 0;
+
+  res = _sendPDOevent(d, 1 /*isSyncEvent*/ );
+  
+  /*Call user app callback*/
+  (*d->post_TPDO)(d);
+  
+  return res;
+  
+}
+
+
+void _post_sync(CO_Data* d){}
+void _post_TPDO(CO_Data* d){}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.lib	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/projects/libraries/svn/mbed/trunk@28
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/main.cpp	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,148 @@
+/**************************************************************
+    CAN OPEN SAMPLE    - MBED MASTER
+**************************************************************/
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+mbed Port: sgrove
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/******************************************************************************
+Project description:
+    
+    Allow a user to change the bus state by sending COM messages to the device
+    57600 baud 8-n-1 send "help" for a list of options and formating info
+    CAN speed - 125k
+
+******************************************************************************/
+
+#include "mbed.h"
+#include "main.h"
+#include "canfestival.h"
+#include "can_mbed.h"
+#include "mbed_master.h"
+#include "port_helper.h"
+
+// Set used for main program timing control
+Ticker SysTimer;
+// flag used by the main program timing control interrupt
+uint8_t timer_interrupt = 0;
+
+// CAN - put and take data from the stack
+uint8_t nodeID;
+uint8_t change_node_id;
+NMTStateAdjustment stack_state = reset;
+
+// read a can message from the stack
+static Message m = Message_Initializer;
+const Message empty_msg = Message_Initializer;
+
+int main() 
+{
+    // start the debug helper
+    initHelper();
+    // start the system timer 
+    SysTimer.attach_us(&serviceSysTimer, CYCLE_TIME*10);
+    // Initialize the CANopen bus
+    canInit(CAN_BAUDRATE);
+    // Start timer for the CANopen stack
+    initTimer();  
+    // set the default node id (1-127)
+    nodeID = 0x7f;
+    // Init the state
+    setState(&mbed_master_Data, Initialisation);
+    setNodeId (&mbed_master_Data, nodeID);
+    // Put the master in operational mode
+    setState(&mbed_master_Data, Operational);
+
+    // keep on loopin'
+    while(1){
+        
+        // just testing the rx functionality
+        if (canReceive(&m)){
+            // the stack can crash with interrupts enabled
+            __disable_irq();
+            // pass the message on and process it
+            canDispatch(&mbed_master_Data, &m); 
+            // get back to work
+            __enable_irq();
+            // and print the message for debugging
+            printMsg(m);
+            // empty it for the next use
+            m = empty_msg;
+        }
+
+        // set the main loop exectuion speed at 10mS
+        if (sys_timer){
+            // Reset timer
+            reset_sys_timer();    
+
+            // look for COM requests
+            serviceCOMCommands();
+
+            // change operational state??
+            switch(stack_state){
+
+                case start:
+                    masterSendNMTstateChange (&mbed_master_Data, 0x00, NMT_Start_Node);
+                    startSYNC(&mbed_master_Data);
+                    stack_state = undefined;
+                    break;
+
+                case reset:
+                    masterSendNMTstateChange (&mbed_master_Data, 0x00, NMT_Reset_Node);
+                    startSYNC(&mbed_master_Data);
+                    stack_state = undefined;
+                    break;
+
+                case stop:
+                    masterSendNMTstateChange (&mbed_master_Data, 0x00, NMT_Stop_Node );
+                    stopSYNC(&mbed_master_Data);
+                    stack_state = undefined;
+                    break;
+                
+                default:
+                    break;
+            }
+
+            // Check if CAN address has been changed
+            if(change_node_id == 1){
+                reset_node_id();
+                setState(&mbed_master_Data, Stopped);             // Stop the node, to change the node ID
+                setNodeId(&mbed_master_Data, nodeID);             // Now the CAN adress is changed
+                setState(&mbed_master_Data, Initialisation);      // Set to Pre_operational, master must boot it again
+                setState(&mbed_master_Data, Operational);
+                stack_state = reset;
+            }
+
+            // other events
+            //sendPDOevent (&mbed_master_Data);
+        }
+    }
+}
+
+// ISR for the Ticker
+void serviceSysTimer()
+{
+    // just used for debugging purposes
+    serviceHelper();
+    // set a flag cleared by the main loop
+    timer_interrupt = 1;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/main.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,25 @@
+
+#ifndef MAIN_H
+#define MAIN_H
+
+// macros to handle the schedule timer
+#define sys_timer			timer_interrupt
+#define reset_sys_timer()	timer_interrupt = 0
+#define reset_node_id()		change_node_id = 0
+// Sample Timebase [us] - used by demo (not the stack)
+#define CYCLE_TIME			1000
+
+typedef enum NMTStateAdjustment NMTStateAdjustment;
+enum NMTStateAdjustment{
+	reset,
+	start,
+	stop,
+	undefined
+};
+
+// interrupt for the main program timing control
+void serviceSysTimer();
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/mbed_master.c	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,535 @@
+
+/* File generated by gen_cfile.py. Should not be modified. */
+
+#include "mbed_master.h"
+
+/**************************************************************************/
+/* Declaration of mapped variables                                        */
+/**************************************************************************/
+UNS8 MasterMap1 = 0x0;        /* Mapped at index 0x2000, subindex 0x00 */
+UNS8 MasterMap2 = 0x0;        /* Mapped at index 0x2001, subindex 0x00 */
+UNS8 MasterMap3 = 0x0;        /* Mapped at index 0x2002, subindex 0x00 */
+UNS8 MasterMap4 = 0x0;        /* Mapped at index 0x2003, subindex 0x00 */
+UNS8 MasterMap5 = 0x0;        /* Mapped at index 0x2004, subindex 0x00 */
+UNS8 MasterMap6 = 0x0;        /* Mapped at index 0x2005, subindex 0x00 */
+UNS8 MasterMap7 = 0x0;        /* Mapped at index 0x2006, subindex 0x00 */
+UNS8 MasterMap8 = 0x0;        /* Mapped at index 0x2007, subindex 0x00 */
+UNS8 MasterMap9 = 0x0;        /* Mapped at index 0x2008, subindex 0x00 */
+UNS32 MasterMap10 = 0x0;        /* Mapped at index 0x2009, subindex 0x00 */
+UNS16 MasterMap11 = 0x0;        /* Mapped at index 0x200A, subindex 0x00 */
+INTEGER16 MasterMap12 = 0x0;        /* Mapped at index 0x200B, subindex 0x00 */
+INTEGER16 MasterMap13 = 0x0;        /* Mapped at index 0x200C, subindex 0x00 */
+
+/**************************************************************************/
+/* Declaration of value range types                                       */
+/**************************************************************************/
+
+#define valueRange_EMC 0x9F /* Type for index 0x1003 subindex 0x00 (only set of value 0 is possible) */
+UNS32 mbed_master_valueRangeTest (UNS8 typeValue, void * value)
+{
+  switch (typeValue) {
+    case valueRange_EMC:
+      if (*(UNS8*)value != (UNS8)0) return OD_VALUE_RANGE_EXCEEDED;
+      break;
+  }
+  return 0;
+}
+
+/**************************************************************************/
+/* The node id                                                            */
+/**************************************************************************/
+/* node_id default value.*/
+UNS8 mbed_master_bDeviceNodeId = 0x00;
+
+/**************************************************************************/
+/* Array of message processing information */
+
+const UNS8 mbed_master_iam_a_slave = 0;
+
+TIMER_HANDLE mbed_master_heartBeatTimers[1] = {TIMER_NONE};
+
+/*
+$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+
+                               OBJECT DICTIONARY
+
+$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+*/
+
+/* index 0x1000 :   Device Type. */
+                    UNS32 mbed_master_obj1000 = 0x12D;    /* 301 */
+                    subindex mbed_master_Index1000[] = 
+                     {
+                       { RO, uint32, sizeof (UNS32), (void*)&mbed_master_obj1000 }
+                     };
+
+/* index 0x1001 :   Error Register. */
+                    UNS8 mbed_master_obj1001 = 0x0;    /* 0 */
+                    subindex mbed_master_Index1001[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_obj1001 }
+                     };
+
+/* index 0x1003 :   Pre-defined Error Field */
+                    UNS8 mbed_master_highestSubIndex_obj1003 = 0; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1003[] = 
+                    {
+                      0x0    /* 0 */
+                    };
+                    ODCallback_t mbed_master_Index1003_callbacks[] = 
+                     {
+                       NULL,
+                       NULL,
+                     };
+                    subindex mbed_master_Index1003[] = 
+                     {
+                       { RW, valueRange_EMC, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1003 },
+                       { RO, uint32, sizeof (UNS32), (void*)&mbed_master_obj1003[0] }
+                     };
+
+/* index 0x1005 :   SYNC COB ID. */
+                    UNS32 mbed_master_obj1005 = 0x40000080;    /* 1073741952 */
+                    ODCallback_t mbed_master_Index1005_callbacks[] = 
+                     {
+                       NULL,
+                     };
+                    subindex mbed_master_Index1005[] = 
+                     {
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1005 }
+                     };
+
+/* index 0x1006 :   Communication / Cycle Period. */
+                    UNS32 mbed_master_obj1006 = 0xC350;    /* 50000 */
+                    ODCallback_t mbed_master_Index1006_callbacks[] = 
+                     {
+                       NULL,
+                     };
+                    subindex mbed_master_Index1006[] = 
+                     {
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1006 }
+                     };
+
+/* index 0x1010 :   Store parameters. */
+                    UNS8 mbed_master_highestSubIndex_obj1010 = 4; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1010_Save_All_Parameters = 0x0;    /* 0 */
+                    UNS32 mbed_master_obj1010_Save_Communication_Parameters = 0x0;    /* 0 */
+                    UNS32 mbed_master_obj1010_Save_Application_Parameters = 0x0;    /* 0 */
+                    UNS32 mbed_master_obj1010_Save_Manufacturer_Parameters_1 = 0x0;    /* 0 */
+                    subindex mbed_master_Index1010[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1010 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1010_Save_All_Parameters },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1010_Save_Communication_Parameters },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1010_Save_Application_Parameters },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1010_Save_Manufacturer_Parameters_1 }
+                     };
+
+/* index 0x1011 :   Restore Default Parameters. */
+                    UNS8 mbed_master_highestSubIndex_obj1011 = 4; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1011_Restore_All_Default_Parameters = 0x0;    /* 0 */
+                    UNS32 mbed_master_obj1011_Restore_Communication_Default_Parameters = 0x0;    /* 0 */
+                    UNS32 mbed_master_obj1011_Restore_Application_Default_Parameters = 0x0;    /* 0 */
+                    UNS32 mbed_master_obj1011_Restore_Manufacturer_Defined_Default_Parameters_1 = 0x0;    /* 0 */
+                    subindex mbed_master_Index1011[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1011 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1011_Restore_All_Default_Parameters },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1011_Restore_Communication_Default_Parameters },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1011_Restore_Application_Default_Parameters },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1011_Restore_Manufacturer_Defined_Default_Parameters_1 }
+                     };
+
+/* index 0x1014 :   Emergency COB ID. */
+                    UNS32 mbed_master_obj1014 = 0x80;    /* 128 */
+                    subindex mbed_master_Index1014[] = 
+                     {
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1014 }
+                     };
+
+/* index 0x1016 :   Consumer Heartbeat Time. */
+                    UNS8 mbed_master_highestSubIndex_obj1016 = 1; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1016[] = 
+                    {
+                      0x205DC    /* 132572 */
+                    };
+                    subindex mbed_master_Index1016[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1016 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1016[0] }
+                     };
+
+/* index 0x1017 :   Producer Heartbeat Time */ 
+                    UNS16 mbed_master_obj1017 = 0x0;   /* 0 */
+
+/* index 0x1018 :   Identity. */
+                    UNS8 mbed_master_highestSubIndex_obj1018 = 4; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1018_Vendor_ID = 0x0;    /* 0 */
+                    UNS32 mbed_master_obj1018_Product_Code = 0x0;    /* 0 */
+                    UNS32 mbed_master_obj1018_Revision_Number = 0x0;    /* 0 */
+                    UNS32 mbed_master_obj1018_Serial_Number = 0x0;    /* 0 */
+                    subindex mbed_master_Index1018[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1018 },
+                       { RO, uint32, sizeof (UNS32), (void*)&mbed_master_obj1018_Vendor_ID },
+                       { RO, uint32, sizeof (UNS32), (void*)&mbed_master_obj1018_Product_Code },
+                       { RO, uint32, sizeof (UNS32), (void*)&mbed_master_obj1018_Revision_Number },
+                       { RO, uint32, sizeof (UNS32), (void*)&mbed_master_obj1018_Serial_Number }
+                     };
+
+/* index 0x1280 :   Client SDO 1 Parameter. */
+                    UNS8 mbed_master_highestSubIndex_obj1280 = 3; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1280_COB_ID_Client_to_Server_Transmit_SDO = 0x582;    /* 1410 */
+                    UNS32 mbed_master_obj1280_COB_ID_Server_to_Client_Receive_SDO = 0x582;    /* 1410 */
+                    UNS8 mbed_master_obj1280_Node_ID_of_the_SDO_Server = 0x2;    /* 2 */
+                    subindex mbed_master_Index1280[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1280 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1280_COB_ID_Client_to_Server_Transmit_SDO },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1280_COB_ID_Server_to_Client_Receive_SDO },
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_obj1280_Node_ID_of_the_SDO_Server }
+                     };
+
+/* index 0x1400 :   Receive PDO 1 Parameter. */
+                    UNS8 mbed_master_highestSubIndex_obj1400 = 5; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1400_COB_ID_used_by_PDO = 0x200;    /* 512 */
+                    UNS8 mbed_master_obj1400_Transmission_Type = 0x1;    /* 1 */
+                    UNS16 mbed_master_obj1400_Inhibit_Time = 0x0;    /* 0 */
+                    UNS8 mbed_master_obj1400_Compatibility_Entry = 0x0;    /* 0 */
+                    UNS16 mbed_master_obj1400_Event_Timer = 0x0;    /* 0 */
+                    subindex mbed_master_Index1400[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1400 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1400_COB_ID_used_by_PDO },
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_obj1400_Transmission_Type },
+                       { RW, uint16, sizeof (UNS16), (void*)&mbed_master_obj1400_Inhibit_Time },
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_obj1400_Compatibility_Entry },
+                       { RW, uint16, sizeof (UNS16), (void*)&mbed_master_obj1400_Event_Timer }
+                     };
+
+/* index 0x1401 :   Receive PDO 2 Parameter. */
+                    UNS8 mbed_master_highestSubIndex_obj1401 = 5; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1401_COB_ID_used_by_PDO = 0x300;    /* 768 */
+                    UNS8 mbed_master_obj1401_Transmission_Type = 0x0;    /* 0 */
+                    UNS16 mbed_master_obj1401_Inhibit_Time = 0x0;    /* 0 */
+                    UNS8 mbed_master_obj1401_Compatibility_Entry = 0x0;    /* 0 */
+                    UNS16 mbed_master_obj1401_Event_Timer = 0x0;    /* 0 */
+                    subindex mbed_master_Index1401[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1401 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1401_COB_ID_used_by_PDO },
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_obj1401_Transmission_Type },
+                       { RW, uint16, sizeof (UNS16), (void*)&mbed_master_obj1401_Inhibit_Time },
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_obj1401_Compatibility_Entry },
+                       { RW, uint16, sizeof (UNS16), (void*)&mbed_master_obj1401_Event_Timer }
+                     };
+
+/* index 0x1402 :   Receive PDO 3 Parameter. */
+                    UNS8 mbed_master_highestSubIndex_obj1402 = 5; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1402_COB_ID_used_by_PDO = 0x191;    /* 401 */
+                    UNS8 mbed_master_obj1402_Transmission_Type = 0x0;    /* 0 */
+                    UNS16 mbed_master_obj1402_Inhibit_Time = 0x0;    /* 0 */
+                    UNS8 mbed_master_obj1402_Compatibility_Entry = 0x0;    /* 0 */
+                    UNS16 mbed_master_obj1402_Event_Timer = 0x0;    /* 0 */
+                    subindex mbed_master_Index1402[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1402 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1402_COB_ID_used_by_PDO },
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_obj1402_Transmission_Type },
+                       { RW, uint16, sizeof (UNS16), (void*)&mbed_master_obj1402_Inhibit_Time },
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_obj1402_Compatibility_Entry },
+                       { RW, uint16, sizeof (UNS16), (void*)&mbed_master_obj1402_Event_Timer }
+                     };
+
+/* index 0x1403 :   Receive PDO 4 Parameter. */
+                    UNS8 mbed_master_highestSubIndex_obj1403 = 5; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1403_COB_ID_used_by_PDO = 0x482;    /* 1154 */
+                    UNS8 mbed_master_obj1403_Transmission_Type = 0x0;    /* 0 */
+                    UNS16 mbed_master_obj1403_Inhibit_Time = 0x0;    /* 0 */
+                    UNS8 mbed_master_obj1403_Compatibility_Entry = 0x0;    /* 0 */
+                    UNS16 mbed_master_obj1403_Event_Timer = 0x0;    /* 0 */
+                    subindex mbed_master_Index1403[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1403 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1403_COB_ID_used_by_PDO },
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_obj1403_Transmission_Type },
+                       { RW, uint16, sizeof (UNS16), (void*)&mbed_master_obj1403_Inhibit_Time },
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_obj1403_Compatibility_Entry },
+                       { RW, uint16, sizeof (UNS16), (void*)&mbed_master_obj1403_Event_Timer }
+                     };
+
+/* index 0x1600 :   Receive PDO 1 Mapping. */
+                    UNS8 mbed_master_highestSubIndex_obj1600 = 10; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1600[] = 
+                    {
+                      0x20000001,    /* 536870913 */
+                      0x20010001,    /* 536936449 */
+                      0x20020001,    /* 537001985 */
+                      0x20030001,    /* 537067521 */
+                      0x20040001,    /* 537133057 */
+                      0x20050001,    /* 537198593 */
+                      0x20060001,    /* 537264129 */
+                      0x20070001,    /* 537329665 */
+                      0x20080008,    /* 537395208 */
+                      0x20090020    /* 537460768 */
+                    };
+                    subindex mbed_master_Index1600[] = 
+                     {
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1600 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[0] },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[1] },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[2] },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[3] },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[4] },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[5] },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[6] },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[7] },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[8] },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1600[9] }
+                     };
+
+/* index 0x1601 :   Receive PDO 2 Mapping. */
+                    UNS8 mbed_master_highestSubIndex_obj1601 = 1; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1601[] = 
+                    {
+                      0x200A0010    /* 537526288 */
+                    };
+                    subindex mbed_master_Index1601[] = 
+                     {
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1601 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1601[0] }
+                     };
+
+/* index 0x1602 :   Receive PDO 3 Mapping. */
+                    UNS8 mbed_master_highestSubIndex_obj1602 = 1; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1602[] = 
+                    {
+                      0x200B0010    /* 537591824 */
+                    };
+                    subindex mbed_master_Index1602[] = 
+                     {
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1602 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1602[0] }
+                     };
+
+/* index 0x1603 :   Receive PDO 4 Mapping. */
+                    UNS8 mbed_master_highestSubIndex_obj1603 = 1; /* number of subindex - 1*/
+                    UNS32 mbed_master_obj1603[] = 
+                    {
+                      0x200C0010    /* 537657360 */
+                    };
+                    subindex mbed_master_Index1603[] = 
+                     {
+                       { RW, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1603 },
+                       { RW, uint32, sizeof (UNS32), (void*)&mbed_master_obj1603[0] }
+                     };
+
+/* index 0x1F22 :   Concise DCF. */
+                    UNS8 mbed_master_highestSubIndex_obj1F22 = 2; /* number of subindex - 1*/
+                    INTEGER8* mbed_master_obj1F22[] = 
+                    {
+                      (char*)"",
+                      (char*)"\x01\x00\x00\x00\x17\x10\x00\x02\x00\x00\x00\xe8\x03"
+                    };
+                    subindex mbed_master_Index1F22[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&mbed_master_highestSubIndex_obj1F22 },
+                       { RW, domain, 0, (void*)&mbed_master_obj1F22[0] },
+                       { RW, domain, 13, (void*)&mbed_master_obj1F22[1] }
+                     };
+
+/* index 0x2000 :   Mapped variable MasterMap1 */
+                    ODCallback_t MasterMap1_callbacks[] = 
+                     {
+                       NULL,
+                     };
+                    subindex mbed_master_Index2000[] = 
+                     {
+                       { RW, boolean, sizeof (UNS8), (void*)&MasterMap1 }
+                     };
+
+/* index 0x2001 :   Mapped variable MasterMap2 */
+                    subindex mbed_master_Index2001[] = 
+                     {
+                       { RW, boolean, sizeof (UNS8), (void*)&MasterMap2 }
+                     };
+
+/* index 0x2002 :   Mapped variable MasterMap3 */
+                    subindex mbed_master_Index2002[] = 
+                     {
+                       { RW, boolean, sizeof (UNS8), (void*)&MasterMap3 }
+                     };
+
+/* index 0x2003 :   Mapped variable MasterMap4 */
+                    subindex mbed_master_Index2003[] = 
+                     {
+                       { RW, boolean, sizeof (UNS8), (void*)&MasterMap4 }
+                     };
+
+/* index 0x2004 :   Mapped variable MasterMap5 */
+                    subindex mbed_master_Index2004[] = 
+                     {
+                       { RW, boolean, sizeof (UNS8), (void*)&MasterMap5 }
+                     };
+
+/* index 0x2005 :   Mapped variable MasterMap6 */
+                    subindex mbed_master_Index2005[] = 
+                     {
+                       { RW, boolean, sizeof (UNS8), (void*)&MasterMap6 }
+                     };
+
+/* index 0x2006 :   Mapped variable MasterMap7 */
+                    subindex mbed_master_Index2006[] = 
+                     {
+                       { RW, boolean, sizeof (UNS8), (void*)&MasterMap7 }
+                     };
+
+/* index 0x2007 :   Mapped variable MasterMap8 */
+                    subindex mbed_master_Index2007[] = 
+                     {
+                       { RW, boolean, sizeof (UNS8), (void*)&MasterMap8 }
+                     };
+
+/* index 0x2008 :   Mapped variable MasterMap9 */
+                    subindex mbed_master_Index2008[] = 
+                     {
+                       { RW, uint8, sizeof (UNS8), (void*)&MasterMap9 }
+                     };
+
+/* index 0x2009 :   Mapped variable MasterMap10 */
+                    subindex mbed_master_Index2009[] = 
+                     {
+                       { RW, uint32, sizeof (UNS32), (void*)&MasterMap10 }
+                     };
+
+/* index 0x200A :   Mapped variable MasterMap11 */
+                    subindex mbed_master_Index200A[] = 
+                     {
+                       { RW, uint16, sizeof (UNS16), (void*)&MasterMap11 }
+                     };
+
+/* index 0x200B :   Mapped variable MasterMap12 */
+                    subindex mbed_master_Index200B[] = 
+                     {
+                       { RW, int16, sizeof (INTEGER16), (void*)&MasterMap12 }
+                     };
+
+/* index 0x200C :   Mapped variable MasterMap13 */
+                    subindex mbed_master_Index200C[] = 
+                     {
+                       { RW, int16, sizeof (INTEGER16), (void*)&MasterMap13 }
+                     };
+
+/**************************************************************************/
+/* Declaration of pointed variables                                       */
+/**************************************************************************/
+
+const indextable mbed_master_objdict[] = 
+{
+  { (subindex*)mbed_master_Index1000,sizeof(mbed_master_Index1000)/sizeof(mbed_master_Index1000[0]), 0x1000},
+  { (subindex*)mbed_master_Index1001,sizeof(mbed_master_Index1001)/sizeof(mbed_master_Index1001[0]), 0x1001},
+  { (subindex*)mbed_master_Index1005,sizeof(mbed_master_Index1005)/sizeof(mbed_master_Index1005[0]), 0x1005},
+  { (subindex*)mbed_master_Index1006,sizeof(mbed_master_Index1006)/sizeof(mbed_master_Index1006[0]), 0x1006},
+  { (subindex*)mbed_master_Index1010,sizeof(mbed_master_Index1010)/sizeof(mbed_master_Index1010[0]), 0x1010},
+  { (subindex*)mbed_master_Index1011,sizeof(mbed_master_Index1011)/sizeof(mbed_master_Index1011[0]), 0x1011},
+  { (subindex*)mbed_master_Index1014,sizeof(mbed_master_Index1014)/sizeof(mbed_master_Index1014[0]), 0x1014},
+  { (subindex*)mbed_master_Index1016,sizeof(mbed_master_Index1016)/sizeof(mbed_master_Index1016[0]), 0x1016},
+  { (subindex*)mbed_master_Index1018,sizeof(mbed_master_Index1018)/sizeof(mbed_master_Index1018[0]), 0x1018},
+  { (subindex*)mbed_master_Index1280,sizeof(mbed_master_Index1280)/sizeof(mbed_master_Index1280[0]), 0x1280},
+  { (subindex*)mbed_master_Index1400,sizeof(mbed_master_Index1400)/sizeof(mbed_master_Index1400[0]), 0x1400},
+  { (subindex*)mbed_master_Index1401,sizeof(mbed_master_Index1401)/sizeof(mbed_master_Index1401[0]), 0x1401},
+  { (subindex*)mbed_master_Index1402,sizeof(mbed_master_Index1402)/sizeof(mbed_master_Index1402[0]), 0x1402},
+  { (subindex*)mbed_master_Index1403,sizeof(mbed_master_Index1403)/sizeof(mbed_master_Index1403[0]), 0x1403},
+  { (subindex*)mbed_master_Index1600,sizeof(mbed_master_Index1600)/sizeof(mbed_master_Index1600[0]), 0x1600},
+  { (subindex*)mbed_master_Index1601,sizeof(mbed_master_Index1601)/sizeof(mbed_master_Index1601[0]), 0x1601},
+  { (subindex*)mbed_master_Index1602,sizeof(mbed_master_Index1602)/sizeof(mbed_master_Index1602[0]), 0x1602},
+  { (subindex*)mbed_master_Index1603,sizeof(mbed_master_Index1603)/sizeof(mbed_master_Index1603[0]), 0x1603},
+  { (subindex*)mbed_master_Index1F22,sizeof(mbed_master_Index1F22)/sizeof(mbed_master_Index1F22[0]), 0x1F22},
+  { (subindex*)mbed_master_Index2000,sizeof(mbed_master_Index2000)/sizeof(mbed_master_Index2000[0]), 0x2000},
+  { (subindex*)mbed_master_Index2001,sizeof(mbed_master_Index2001)/sizeof(mbed_master_Index2001[0]), 0x2001},
+  { (subindex*)mbed_master_Index2002,sizeof(mbed_master_Index2002)/sizeof(mbed_master_Index2002[0]), 0x2002},
+  { (subindex*)mbed_master_Index2003,sizeof(mbed_master_Index2003)/sizeof(mbed_master_Index2003[0]), 0x2003},
+  { (subindex*)mbed_master_Index2004,sizeof(mbed_master_Index2004)/sizeof(mbed_master_Index2004[0]), 0x2004},
+  { (subindex*)mbed_master_Index2005,sizeof(mbed_master_Index2005)/sizeof(mbed_master_Index2005[0]), 0x2005},
+  { (subindex*)mbed_master_Index2006,sizeof(mbed_master_Index2006)/sizeof(mbed_master_Index2006[0]), 0x2006},
+  { (subindex*)mbed_master_Index2007,sizeof(mbed_master_Index2007)/sizeof(mbed_master_Index2007[0]), 0x2007},
+  { (subindex*)mbed_master_Index2008,sizeof(mbed_master_Index2008)/sizeof(mbed_master_Index2008[0]), 0x2008},
+  { (subindex*)mbed_master_Index2009,sizeof(mbed_master_Index2009)/sizeof(mbed_master_Index2009[0]), 0x2009},
+  { (subindex*)mbed_master_Index200A,sizeof(mbed_master_Index200A)/sizeof(mbed_master_Index200A[0]), 0x200A},
+  { (subindex*)mbed_master_Index200B,sizeof(mbed_master_Index200B)/sizeof(mbed_master_Index200B[0]), 0x200B},
+  { (subindex*)mbed_master_Index200C,sizeof(mbed_master_Index200C)/sizeof(mbed_master_Index200C[0]), 0x200C},
+};
+
+const indextable * mbed_master_scanIndexOD (UNS16 wIndex, UNS32 * errorCode, ODCallback_t **callbacks)
+{
+    int i;
+    *callbacks = NULL;
+    switch(wIndex){
+        case 0x1000: i = 0;break;
+        case 0x1001: i = 1;break;
+        case 0x1005: i = 2;*callbacks = mbed_master_Index1005_callbacks; break;
+        case 0x1006: i = 3;*callbacks = mbed_master_Index1006_callbacks; break;
+        case 0x1010: i = 4;break;
+        case 0x1011: i = 5;break;
+        case 0x1014: i = 6;break;
+        case 0x1016: i = 7;break;
+        case 0x1018: i = 8;break;
+        case 0x1280: i = 9;break;
+        case 0x1400: i = 10;break;
+        case 0x1401: i = 11;break;
+        case 0x1402: i = 12;break;
+        case 0x1403: i = 13;break;
+        case 0x1600: i = 14;break;
+        case 0x1601: i = 15;break;
+        case 0x1602: i = 16;break;
+        case 0x1603: i = 17;break;
+        case 0x1F22: i = 18;break;
+        case 0x2000: i = 19;*callbacks = MasterMap1_callbacks; break;
+        case 0x2001: i = 20;break;
+        case 0x2002: i = 21;break;
+        case 0x2003: i = 22;break;
+        case 0x2004: i = 23;break;
+        case 0x2005: i = 24;break;
+        case 0x2006: i = 25;break;
+        case 0x2007: i = 26;break;
+        case 0x2008: i = 27;break;
+        case 0x2009: i = 28;break;
+        case 0x200A: i = 29;break;
+        case 0x200B: i = 30;break;
+        case 0x200C: i = 31;break;
+        default:
+            *errorCode = OD_NO_SUCH_OBJECT;
+            return NULL;
+    }
+    *errorCode = OD_SUCCESSFUL;
+    return &mbed_master_objdict[i];
+}
+
+/* 
+ * To count at which received SYNC a PDO must be sent.
+ * Even if no pdoTransmit are defined, at least one entry is computed
+ * for compilations issues.
+ */
+s_PDO_status mbed_master_PDO_status[1] = {s_PDO_status_Initializer};
+
+const quick_index mbed_master_firstIndex = {
+  0, /* SDO_SVR */
+  9, /* SDO_CLT */
+  10, /* PDO_RCV */
+  14, /* PDO_RCV_MAP */
+  0, /* PDO_TRS */
+  0 /* PDO_TRS_MAP */
+};
+
+const quick_index mbed_master_lastIndex = {
+  0, /* SDO_SVR */
+  9, /* SDO_CLT */
+  13, /* PDO_RCV */
+  17, /* PDO_RCV_MAP */
+  0, /* PDO_TRS */
+  0 /* PDO_TRS_MAP */
+};
+
+const UNS16 mbed_master_ObjdictSize = sizeof(mbed_master_objdict)/sizeof(mbed_master_objdict[0]); 
+
+CO_Data mbed_master_Data = CANOPEN_NODE_DATA_INITIALIZER(mbed_master);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/mbed_master.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,29 @@
+
+/* File generated by gen_cfile.py. Should not be modified. */
+
+#ifndef MBED_MASTER_H
+#define MBED_MASTER_H
+
+#include "data.h"
+
+/* Prototypes of function provided by object dictionnary */
+UNS32 mbed_master_valueRangeTest (UNS8 typeValue, void * value);
+const indextable * mbed_master_scanIndexOD (UNS16 wIndex, UNS32 * errorCode, ODCallback_t **callbacks);
+
+/* Master node data struct */
+extern CO_Data mbed_master_Data;
+extern UNS8 MasterMap1;		/* Mapped at index 0x2000, subindex 0x00*/
+extern UNS8 MasterMap2;		/* Mapped at index 0x2001, subindex 0x00*/
+extern UNS8 MasterMap3;		/* Mapped at index 0x2002, subindex 0x00*/
+extern UNS8 MasterMap4;		/* Mapped at index 0x2003, subindex 0x00*/
+extern UNS8 MasterMap5;		/* Mapped at index 0x2004, subindex 0x00*/
+extern UNS8 MasterMap6;		/* Mapped at index 0x2005, subindex 0x00*/
+extern UNS8 MasterMap7;		/* Mapped at index 0x2006, subindex 0x00*/
+extern UNS8 MasterMap8;		/* Mapped at index 0x2007, subindex 0x00*/
+extern UNS8 MasterMap9;		/* Mapped at index 0x2008, subindex 0x00*/
+extern UNS32 MasterMap10;		/* Mapped at index 0x2009, subindex 0x00*/
+extern UNS16 MasterMap11;		/* Mapped at index 0x200A, subindex 0x00*/
+extern INTEGER16 MasterMap12;		/* Mapped at index 0x200B, subindex 0x00*/
+extern INTEGER16 MasterMap13;		/* Mapped at index 0x200C, subindex 0x00*/
+
+#endif // MBED_MASTER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/port_helper.cpp	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,149 @@
+
+
+#include "port_helper.h"
+#include "main.h"
+
+Serial Debug(USBTX, USBRX);
+DigitalOut running_status(LED1);
+
+extern uint8_t nodeID;
+extern uint8_t change_node_id;
+extern NMTStateAdjustment stack_state;
+
+void initHelper()
+{
+	Debug.baud(57600);
+	printf(" CANopen port of CANfestival master node \n");
+}
+
+void serviceHelper()
+{
+	static uint32_t cnt = 0;
+	// indicate that the stack is running
+	if (cnt++ > 100){
+		cnt = 0;
+		running_status = !running_status;
+	}	
+}
+
+
+void printMsg(Message& msg)
+{
+	CANMessage m(msg.cob_id, (char*)msg.data, msg.len, static_cast<CANType>(msg.rtr), CANStandard);
+	// call the CANMessage formatted method
+	printMsg(m);
+}
+
+void printMsg(CANMessage& msg)
+{
+	printf("ID: 0x%04X DLC: %d Data(0->7): 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
+		msg.id, msg.len, msg.data[0], msg.data[1], msg.data[2], 
+		msg.data[3], msg.data[4], msg.data[5], msg.data[6],msg.data[7]);
+}
+
+void serviceCOMCommands()
+{
+ 	static char msg[64];
+	static char w_loc=0;
+	if (Debug.readable()){
+		// store the data
+		if (w_loc < 64){
+			msg[w_loc++] = Debug.getc();
+		}
+		// clear the buffer and try again
+		else{
+			// clear the buffer
+			memset(msg, 0, 64);
+			w_loc = 0;
+			return;
+		}
+		// parse the message and act on it
+		if ((msg[w_loc-1] == '\r') || (msg[w_loc-1] == '\n') ){
+			// format the message
+			// process the message and look for something familiar
+			if (strncmp(msg, "help", strlen("help")) == 0){
+			 	// print the help menu
+				printf("\t HELP OPTIONS (case sesnitive):\n");
+				printf("\t  help - display the available options\n");
+				printf("\t  id=xxx - change the node id\n");
+				printf("\t  about - get info about the node\n");
+				printf("\t  state=xxxx - start, stop, reset\n");
+			}
+			else if (strncmp(msg, "id=", strlen("id=")) == 0){
+				// change the node ID
+				int res = atoi(msg+strlen("id="));
+				if ( (res > 0) && (res < 128) ){
+					nodeID = res;
+					printf("the new node_id = %d\n", nodeID);
+					change_node_id = 1;
+				}
+				else{
+					printf("invalid parameter");
+				}
+			}
+			else if (strncmp(msg, "about", strlen("about")) == 0){
+				// our call tag
+				printf(" CANopen port of CANfestival master node \n");
+			}
+			else if (strncmp(msg, "state=", strlen("state=")) == 0){
+				// ohh what to do
+				if (strncmp(msg+strlen("state="), "start", strlen("start")) == 0){
+					printf("stack state = start");
+					// signal back
+					stack_state = start;
+				}
+				else if (strncmp(msg+strlen("state="), "stop", strlen("stop")) == 0){
+				 	printf("stack state = stop");
+					// signal back
+					stack_state = stop;
+				}
+				else if (strncmp(msg+strlen("state="), "reset", strlen("reset")) == 0){
+				 	printf("stack state = reset");
+					// signal back
+					stack_state = reset;
+				}
+			}
+			// clear the buffer
+			memset(msg, 0, 64);
+			w_loc = 0;
+		}
+	}
+}
+
+/*
+WDT_IRQHandler           
+TIMER0_IRQHandler         
+TIMER1_IRQHandler         
+TIMER2_IRQHandler         
+TIMER3_IRQHandler         
+UART0_IRQHandler          
+UART1_IRQHandler          
+UART2_IRQHandler          
+UART3_IRQHandler          
+PWM1_IRQHandler           
+I2C0_IRQHandler           
+I2C1_IRQHandler           
+I2C2_IRQHandler           
+SPI_IRQHandler            
+SSP0_IRQHandler           
+SSP1_IRQHandler           
+PLL0_IRQHandler           
+RTC_IRQHandler            
+EINT0_IRQHandler          
+EINT1_IRQHandler          
+EINT2_IRQHandler          
+EINT3_IRQHandler          
+ADC_IRQHandler            
+BOD_IRQHandler            
+USB_IRQHandler            
+CAN_IRQHandler            
+DMA_IRQHandler          
+I2S_IRQHandler            
+ENET_IRQHandler       
+RIT_IRQHandler          
+MCPWM_IRQHandler             
+QEI_IRQHandler            
+PLL1_IRQHandler           
+USBActivity_IRQHandler
+CANActivity_IRQHandler
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/port_helper.h	Mon May 30 07:36:47 2011 +0000
@@ -0,0 +1,17 @@
+
+
+#ifndef PORT_HELPER_H
+#define PORT_HELPER_H
+
+#include "canfestival.h"
+#include "mbed.h"
+
+void initHelper();
+void serviceHelper();
+
+void serviceCOMCommands();;
+
+void printMsg(Message& msg);
+void printMsg(CANMessage& msg);
+
+#endif