2 This file is part of CanFestival, a library implementing CanOpen Stack.
5 Copyright (C): Jorge Berzosa
8 See COPYING file for copyrights details.
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Lesser General Public License for more details.
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 ** @author Jorge Berzosa
32 ** @date Mon Oct 22 05:44:32 2007
43 #include "canfestival.h"
46 //#define LSS_TIMEOUT_MS (TIMEVAL)1000 /* ms */
47 //#define LSS_FS_TIMEOUT_MS (TIMEVAL)100 /* ms */
49 /* Returns the LSS ident field from a Message struct */
50 #define getLSSIdent(msg) ((msg->data[4] << 24) | (msg->data[3] << 16) | (msg->data[2] << 8) | (msg->data[1]))
52 /* Returns the LSS switch delay field from a Message struct */
53 #define getLSSDelay(msg) ((msg->data[2] << 8) | (msg->data[1]))
55 /* Returns the LSS FastScan BitCheck field from a Message struct */
56 #define getLSSBitCheck(msg) msg->data[5]
58 /* Returns the LSS FastScan LSSSub field from a Message struct */
59 #define getLSSSub(msg) msg->data[6]
61 /* Returns the LSS FastScan LSSNext field from a Message struct */
62 #define getLSSNext(msg) msg->data[7]
64 /* Prototypes for internals functions */
65 UNS8 sendMasterLSSMessage(CO_Data* d, UNS8 command,void *dat1,void *dat2);
66 void LssAlarmMSG(CO_Data* d, UNS32 id);
67 void LssAlarmSDELAY(CO_Data* d, UNS32 id);
70 #define StopLSS_MSG_TIMER(){\
71 MSG_WAR(0x3D01, "StopLSS_MSG_TIMER", 0);\
72 d->lss_transfer.timerMSG = DelAlarm(d->lss_transfer.timerMSG);}
74 #define StartLSS_MSG_TIMER(){\
75 MSG_WAR(0x3D02, "StartLSS_MSG_TIMER",0);\
76 d->lss_transfer.timerMSG = SetAlarm(d,0,&LssAlarmMSG,MS_TO_TIMEVAL(LSS_TIMEOUT_MS),0);}
78 #define StopLSS_SDELAY_TIMER(){\
79 MSG_WAR(0x3D03, "StopLSS_SDELAY_TIMER", 0);\
80 d->lss_transfer.timerSDELAY = DelAlarm(d->lss_transfer.timerSDELAY);}
82 #define StartLSS_SDELAY_TIMER(){\
83 MSG_WAR(0x3D04, "StartLSS_SDELAY_TIMER",0);\
84 d->lss_transfer.timerSDELAY= SetAlarm(d,0,&LssAlarmSDELAY,MS_TO_TIMEVAL(d->lss_transfer.switchDelay),MS_TO_TIMEVAL(d->lss_transfer.switchDelay));}
87 #ifdef CO_ENABLE_LSS_FS
88 /* Prototypes for internals functions */
89 void LssAlarmFS(CO_Data* d, UNS32 id);
91 #define StopLSS_FS_TIMER(){\
92 MSG_WAR(0x3D05, "StopLSS_FS_TIMER", id);\
93 d->lss_transfer.timerFS = DelAlarm(d->lss_transfer.timerFS);}
95 #define StartLSS_FS_TIMER(){\
96 MSG_WAR(0x3D06, "StartLSS_FS_TIMER",0);\
97 d->lss_transfer.timerFS = SetAlarm(d,0,&LssAlarmFS,MS_TO_TIMEVAL(LSS_FS_TIMEOUT_MS),0);}
101 void LssAlarmMSG(CO_Data* d, UNS32 id)
104 #ifdef CO_ENABLE_LSS_FS
105 if(d->lss_transfer.command==LSS_IDENT_FASTSCAN){
106 if(d->lss_transfer.FastScan_SM==LSS_FS_RESET){
107 /* if at least one node had answered before the timer expired, start the FastScan protocol*/
108 if(d->lss_transfer.LSSanswer!=0){
109 d->lss_transfer.LSSanswer=0;
110 d->lss_transfer.BitChecked=31;
111 d->lss_transfer.IDNumber=0;
112 d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
114 sendMasterLSSMessage(d,LSS_IDENT_FASTSCAN,0,0);
119 d->lss_transfer.state = LSS_FINISHED;
120 /* Inform the application that there aren't not configured nodes in the net */
121 d->lss_transfer.dat1=1;
125 /* This should not happen, an error ocurred*/
126 MSG_ERR(0x1D07, "LSS FastScan timeout. FastScan_SM inconsisten state.", d->lss_transfer.FastScan_SM);
131 if(d->lss_transfer.command==LSS_IDENT_REMOTE_NON_CONF){
132 MSG_WAR(0x2D08, "LSS timeout. There are not no-configured slaves in the net", 0);
133 d->lss_transfer.state = LSS_FINISHED;
134 d->lss_transfer.dat1=1;
137 MSG_ERR(0x1D09, "LSS timeout. LSS response not received.", 0);
138 MSG_WAR(0x2D0A, "LSS timeout command specifier : ", d->lss_transfer.command);
139 /* Set aborted state */
140 d->lss_transfer.state = LSS_ABORTED_INTERNAL;
143 /* Call the user function to inform of the problem.*/
144 if(d->lss_transfer.Callback){
145 /*If there is a callback, it is responsible of the error*/
146 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
157 void LssAlarmSDELAY(CO_Data* d, UNS32 id)
160 /* The first switch_delay period expired. Store the node state, change it
161 * so no CAN messages will be sent or received, call the ChangeBaudRate function*/
162 if(d->lss_transfer.switchDelayState==SDELAY_FIRST){
163 MSG_WAR(0x3D0B, "LSS switch delay first period expired",0);
164 d->lss_transfer.switchDelayState=SDELAY_SECOND;
165 (*d->lss_ChangeBaudRate)(d,d->lss_transfer.baudRate);
167 else{ /* d->lss_transfer.switchDelayState==SDELAY_SECOND */
168 MSG_WAR(0x3D0C, "LSS switch delay second period expired",0);
169 d->lss_transfer.switchDelayState=SDELAY_OFF;
170 StopLSS_SDELAY_TIMER();
172 if (*(d->iam_a_slave))
173 d->canHandle=d->lss_transfer.canHandle_t;
175 d->lss_transfer.dat1=0;
176 d->lss_transfer.state=LSS_FINISHED;
177 /* Call the user function */
178 if(d->lss_transfer.Callback){
179 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
185 #ifdef CO_ENABLE_LSS_FS
192 void LssAlarmFS(CO_Data* d, UNS32 id)
196 switch(d->lss_transfer.FastScan_SM){
199 /* This should not happen, an error ocurred*/
200 MSG_ERR(0x1D0D, "LSS FastScan timeout. FastScan_SM inconsisten state.", d->lss_transfer.FastScan_SM);
203 case LSS_FS_PROCESSING:
205 /* If there isn't any answer, set the bit */
206 if(d->lss_transfer.LSSanswer==0){
208 Mask<<=d->lss_transfer.BitChecked;
209 d->lss_transfer.IDNumber|=Mask;
212 if(d->lss_transfer.BitChecked==0){
213 /* We finished with the current LSS-ID[sub], confirm it */
214 d->lss_transfer.FastScan_SM=LSS_FS_CONFIRMATION;
215 if(d->lss_transfer.LSSNext<3)d->lss_transfer.LSSNext++;
218 d->lss_transfer.BitChecked--;
221 d->lss_transfer.LSSanswer=0;
223 sendMasterLSSMessage(d,LSS_IDENT_FASTSCAN,0,0);
227 case LSS_FS_CONFIRMATION:
229 if(d->lss_transfer.LSSanswer!=0){
230 d->lss_transfer.LSSanswer=0;
232 if(d->lss_transfer.LSSSub==3){
233 /* The LSS FastScan protocol finished correctly. Restore the parameters */
234 d->lss_transfer.BitChecked=128;
235 d->lss_transfer.FastScan_SM=LSS_FS_RESET;
236 d->lss_transfer.LSSSub=0;
237 d->lss_transfer.LSSNext=0;
238 d->lss_transfer.IDNumber=0;
240 /* Inform the application that the FastScan finished correctly */
241 d->lss_transfer.state = LSS_FINISHED;
242 d->lss_transfer.dat1=0;
245 /* Start with the next LSS-ID[sub] */
246 d->lss_transfer.LSSSub++;
247 d->lss_transfer.BitChecked=31;
248 d->lss_transfer.IDNumber=0;
249 d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
251 sendMasterLSSMessage(d,LSS_IDENT_FASTSCAN,0,0);
256 /* This should not happen, an error ocurred*/
257 MSG_ERR(0x1D0E, "LSS FastScan timeout. FastScan response not received.", 0);
258 /* Set aborted state */
259 d->lss_transfer.state = LSS_ABORTED_INTERNAL;
265 /* Call the user function to inform of the problem.*/
266 if(d->lss_transfer.Callback){
267 /*If there is a callback, it is responsible of the error*/
268 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
279 void startLSS(CO_Data* d)
281 /*MSG_WAR(0x3D09, "LSS services started",0);*/
289 void stopLSS(CO_Data* d)
291 /*MSG_WAR(0x3D09, "LSS services stopped",0);*/
302 UNS8 sendSlaveLSSMessage(CO_Data* d, UNS8 command,void *dat1,void *dat2)
307 if (!d->CurrentCommunicationState.csLSS){
308 MSG_WAR(0x2D17, "unable to send the LSS message, not in the proper state =>", d->nodeState);
312 for(i=1;i<8;i++)m.data[i]=0;
314 m.rtr = NOT_A_REQUEST;
316 m.cob_id=UNS16_LE(SLSS_ADRESS);
318 /* Tha data sent with the msg depends on the command */
320 case LSS_INQ_NODE_ID: /* Inquire Node-ID */
321 m.data[1]=*(UNS8 *)dat1;
323 case LSS_CONF_NODE_ID: /* Configure Node-ID */
324 case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
325 case LSS_CONF_STORE: /* Store Configured Parameters */
326 m.data[1]=*(UNS8 *)dat1;
327 m.data[2]=*(UNS8 *)dat2;
329 case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
330 case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
331 case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
332 case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
333 m.data[1]=(UNS8)(*(UNS32*)dat1 & 0xFF);
334 m.data[2]=(UNS8)(*(UNS32*)dat1>>8 & 0xFF);
335 m.data[3]=(UNS8)(*(UNS32*)dat1>>16 & 0xFF);
336 m.data[4]=(UNS8)(*(UNS32*)dat1>>24 & 0xFF);
338 case LSS_SM_SELECTIVE_RESP: /* Switch Mode Selective response*/
339 case LSS_IDENT_SLAVE: /* LSS Identify Slave */
340 case LSS_IDENT_NON_CONF_SLAVE: /* LSS identify non-configured remote slave */
343 MSG_ERR(0x1D18, "send Slave LSS command not implemented", command);
347 return canSend(d->canHandle,&m);
358 UNS8 sendMasterLSSMessage(CO_Data* d, UNS8 command,void *dat1,void *dat2)
365 for(i=1;i<8;i++)m.data[i]=0;
367 m.rtr = NOT_A_REQUEST;
369 m.cob_id=UNS16_LE(MLSS_ADRESS);
371 /* Tha data sent with the msg depends on the command */
373 case LSS_CONF_NODE_ID: /* Configure Node-ID */
375 case LSS_SM_GLOBAL: /* Switch Mode Global */
376 m.data[1]=*(UNS8 *)dat1;
378 case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
379 m.data[1]=*(UNS8 *)dat1;
380 m.data[2]=*(UNS8 *)dat2;
381 if(d->lss_ChangeBaudRate){
382 /* If a baud rate is not supported just comment the line. */
384 case 0x00:d->lss_transfer.baudRate="1M";break;
385 case 0x01:d->lss_transfer.baudRate="800K";break;
386 case 0x02:d->lss_transfer.baudRate="500K";break;
387 case 0x03:d->lss_transfer.baudRate="250K";break;
388 case 0x04:d->lss_transfer.baudRate="125K";break;
389 case 0x05:d->lss_transfer.baudRate="100K";break;
390 case 0x06:d->lss_transfer.baudRate="50K";break;
391 case 0x07:d->lss_transfer.baudRate="20K";break;
392 case 0x08:d->lss_transfer.baudRate="10K";break;
394 MSG_ERR(0x1D19, "Master-> Baud rate not supported",0);
395 d->lss_transfer.dat1=0xFF;
396 goto ErrorBitRateMaster;
403 MSG_ERR(0x1D1A, "Master-> Bit timing not supported",0);
404 d->lss_transfer.dat1=0x01;
408 d->lss_transfer.dat2=0;
409 /* If there is a callback, it is responsible of the error */
410 if(d->lss_transfer.Callback)
411 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
414 case LSS_CONF_ACT_BIT_TIMING: /* Activate Bit Timing Parameters */
415 m.data[1]=(UNS8)(*(UNS32*)dat1 & 0xFF);
416 m.data[2]=(UNS8)(*(UNS32*)dat1>>8 & 0xFF);
417 if(d->lss_transfer.baudRate!="none"){
418 d->lss_transfer.switchDelay=(UNS16)(*(UNS32*)dat1 & 0xFFFF);
419 d->lss_transfer.switchDelayState=SDELAY_FIRST;
420 res=canSend(d->canHandle,&m);
422 StartLSS_SDELAY_TIMER();
423 d->lss_transfer.state=LSS_TRANS_IN_PROGRESS;
428 MSG_ERR(0x1D1B, "Master-> Baud rate not specified",0);
429 d->lss_transfer.dat1=1;
430 /* If there is a callback, it is responsible of the error */
431 if(d->lss_transfer.Callback){
432 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
437 case LSS_SM_SELECTIVE_SERIAL:
438 case LSS_IDENT_REMOTE_SERIAL_HIGH:
440 case LSS_SM_SELECTIVE_VENDOR: /* Switch Mode Selective */
441 case LSS_SM_SELECTIVE_PRODUCT:
442 case LSS_SM_SELECTIVE_REVISION:
443 case LSS_IDENT_REMOTE_VENDOR: /* LSS Identify Remote Slaves */
444 case LSS_IDENT_REMOTE_PRODUCT:
445 case LSS_IDENT_REMOTE_REV_LOW:
446 case LSS_IDENT_REMOTE_REV_HIGH:
447 case LSS_IDENT_REMOTE_SERIAL_LOW:
448 m.data[1]=(UNS8)(*(UNS32*)dat1 & 0xFF);
449 m.data[2]=(UNS8)(*(UNS32*)dat1>>8 & 0xFF);
450 m.data[3]=(UNS8)(*(UNS32*)dat1>>16 & 0xFF);
451 m.data[4]=(UNS8)(*(UNS32*)dat1>>24 & 0xFF);
454 case LSS_CONF_STORE: /* Store Configured Parameters */
455 case LSS_IDENT_REMOTE_NON_CONF: /* LSS identify non-configured remote slave */
456 case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
457 case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
458 case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
459 case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
460 case LSS_INQ_NODE_ID: /* Inquire Node-ID */
463 #ifdef CO_ENABLE_LSS_FS
464 case LSS_IDENT_FASTSCAN:
465 m.data[1]=(UNS8)(d->lss_transfer.IDNumber & 0xFF);
466 m.data[2]=(UNS8)(d->lss_transfer.IDNumber>>8 & 0xFF);
467 m.data[3]=(UNS8)(d->lss_transfer.IDNumber>>16 & 0xFF);
468 m.data[4]=(UNS8)(d->lss_transfer.IDNumber>>24 & 0xFF);
469 m.data[5]=d->lss_transfer.BitChecked;
470 m.data[6]=d->lss_transfer.LSSSub;
471 m.data[7]=d->lss_transfer.LSSNext;
472 /* it will generate a response only if it is the start of the FastScan protocol*/
473 if(d->lss_transfer.FastScan_SM==LSS_FS_RESET)hasResponse=1;
477 MSG_ERR(0x1D1C, "send Master LSS command not implemented", command);
481 res=canSend(d->canHandle,&m);
482 if(res==0 && hasResponse==1){
483 StartLSS_MSG_TIMER();
484 d->lss_transfer.state=LSS_TRANS_IN_PROGRESS;
497 UNS8 sendLSS(CO_Data* d, UNS8 command,void *dat1,void *dat2)
501 /* Tha data sent with the msg depends on the command and if the sender is a master or a slave */
502 if (*(d->iam_a_slave)){
503 res = sendSlaveLSSMessage(d, command,dat1,dat2);
505 else {/* It is a Master */
506 res = sendMasterLSSMessage(d, command,dat1,dat2);
520 UNS8 proceedLSS_Master(CO_Data* d, Message* m )
526 if(d->lss_transfer.state!=LSS_TRANS_IN_PROGRESS)
528 //MSG_WAR(0x3D0D, "MasterLSS proceedLSS; unexpected message arrived;command ", m->data[0]);
530 goto ErrorProcessMaster;
533 MSG_WAR(0x3D1E, "MasterLSS proceedLSS; command ", m->data[0]);
535 switch(msg_cs=m->data[0]){
536 case LSS_INQ_NODE_ID: /* Inquire Node-ID */
537 if(d->lss_transfer.command!=LSS_INQ_NODE_ID)goto ErrorProcessMaster;
540 case LSS_CONF_NODE_ID: /* Configure Node-ID */
541 case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
542 case LSS_CONF_STORE: /* Store Configured Parameters */
543 if(d->lss_transfer.command!=msg_cs)goto ErrorProcessMaster;
547 case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
548 case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
549 case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
550 case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
551 if(d->lss_transfer.command!=msg_cs)goto ErrorProcessMaster;
554 case LSS_IDENT_SLAVE: /* LSS Identify Slave */
555 #ifdef CO_ENABLE_LSS_FS
556 if(d->lss_transfer.command==LSS_IDENT_FASTSCAN){
557 /* A message arrived during the timer period */
558 d->lss_transfer.LSSanswer=1;
563 if(d->lss_transfer.command!=LSS_IDENT_REMOTE_VENDOR && \
564 d->lss_transfer.command!=LSS_IDENT_REMOTE_PRODUCT && \
565 d->lss_transfer.command!=LSS_IDENT_REMOTE_REV_LOW && \
566 d->lss_transfer.command!=LSS_IDENT_REMOTE_REV_HIGH && \
567 d->lss_transfer.command!=LSS_IDENT_REMOTE_SERIAL_LOW && \
568 d->lss_transfer.command!=LSS_IDENT_REMOTE_SERIAL_HIGH )
569 goto ErrorProcessMaster;
571 case LSS_SM_SELECTIVE_RESP: /* Switch Mode Selective response */
572 if(d->lss_transfer.command!=LSS_SM_SELECTIVE_VENDOR && \
573 d->lss_transfer.command!=LSS_SM_SELECTIVE_PRODUCT && \
574 d->lss_transfer.command!=LSS_SM_SELECTIVE_REVISION && \
575 d->lss_transfer.command!=LSS_SM_SELECTIVE_SERIAL )
576 goto ErrorProcessMaster;
578 case LSS_IDENT_NON_CONF_SLAVE: /* LSS identify non-configured remote slave */
579 if(d->lss_transfer.command!=LSS_IDENT_REMOTE_NON_CONF)goto ErrorProcessMaster;
582 MSG_ERR(0x1D1F, "Master LSS command not implemented", msg_cs);
587 d->lss_transfer.state = LSS_FINISHED;
589 d->lss_transfer.dat1=Dat1;
590 d->lss_transfer.dat2=Dat2;
591 /* If there is a callback, it is responsible of the received response */
592 if(d->lss_transfer.Callback)
593 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
598 MSG_WAR(0x3D20, "MasterLSS proceedLSS; unexpected message arrived;command ", m->data[0]);
611 UNS8 proceedLSS_Slave(CO_Data* d, Message* m )
615 MSG_WAR(0x3D21, "SlaveLSS proceedLSS; command ", m->data[0]);
617 switch(msg_cs=m->data[0]){
618 case LSS_SM_GLOBAL: /* Switch Mode Global */
619 /* if there is not a mode change break*/
620 if(m->data[1] == d->lss_transfer.mode){
621 MSG_WAR(0x3D22, "SlaveLSS already in the mode ", m->data[1]);
625 if(m->data[1]==LSS_CONFIGURATION_MODE) {
626 MSG_WAR(0x3D23, "SlaveLSS switching to configuration mode ", 0);
627 /* Store the NodeId in case it will be changed */
628 //d->lss_transfer.nodeID=getNodeId(d);
629 d->lss_transfer.mode=LSS_CONFIGURATION_MODE;
631 else if(m->data[1]==LSS_WAITING_MODE){
632 MSG_WAR(0x3D24, "SlaveLSS switching to operational mode ", 0);
634 /* If the nodeID has changed update it and put the node state to Initialisation. */
635 if(d->lss_transfer.nodeID!=getNodeId(d)){
636 if(getNodeId(d)==0xFF){/* The nodeID was 0xFF; initialize the application*/
637 MSG_WAR(0x3D25, "The node Id has changed. Reseting to Initialisation state",0);
638 setNodeId(d, d->lss_transfer.nodeID);
639 setState(d, Initialisation);
641 else{/* The nodeID will be changed on NMT_Reset Request*/
642 setNodeId(d, d->lss_transfer.nodeID);
645 d->lss_transfer.mode=LSS_WAITING_MODE;
648 case LSS_CONF_NODE_ID: /* Configure Node-ID */
653 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE){
654 if(m->data[1]>127 && m->data[1]!=0xFF){
655 MSG_ERR(0x1D26, "NodeID out of range",0);
656 error_code=1; /* NodeID out of range */
659 d->lss_transfer.nodeID=m->data[1];
663 MSG_WAR(0x3D27, "SlaveLSS not in configuration mode",0);
667 sendSlaveLSSMessage(d,msg_cs,&error_code,&spec_error);
670 case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
675 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE){
676 /* Change the baud rate only if the function lss_ChangeBaudRate
677 * has been implemented. If not send an error.
679 if(d->lss_ChangeBaudRate){
680 /* If a baud rate is not supported just comment the line. */
682 case 0x00:d->lss_transfer.baudRate="1M";break;
683 case 0x01:d->lss_transfer.baudRate="800K";break;
684 case 0x02:d->lss_transfer.baudRate="500K";break;
685 case 0x03:d->lss_transfer.baudRate="250K";break;
686 case 0x04:d->lss_transfer.baudRate="125K";break;
687 case 0x05:d->lss_transfer.baudRate="100K";break;
688 case 0x06:d->lss_transfer.baudRate="50K";break;
689 case 0x07:d->lss_transfer.baudRate="20K";break;
690 case 0x08:d->lss_transfer.baudRate="10K";break;
692 MSG_ERR(0x1D28, "Baud rate not supported",0);
693 error_code=0xFF; /* Baud rate not supported*/
699 MSG_ERR(0x1D29, "Bit timing not supported",0);
700 error_code=0x01; /* bit timing not supported */
704 MSG_WAR(0x3D2A, "SlaveLSS not in configuration mode",0);
709 sendSlaveLSSMessage(d,msg_cs,&error_code,&spec_error);
712 case LSS_CONF_ACT_BIT_TIMING: /* Activate Bit Timing Parameters */
714 if(d->lss_transfer.mode!=LSS_CONFIGURATION_MODE){
715 MSG_ERR(0x3D2B, "SlaveLSS not in configuration mode",0);
719 if(d->lss_transfer.baudRate!="none"){
720 d->lss_transfer.switchDelay=getLSSDelay(m);
721 MSG_WAR(0x3D2C, "Slave Switch Delay set to: ",d->lss_transfer.switchDelay);
722 d->lss_transfer.switchDelayState=SDELAY_FIRST;
723 //d->lss_transfer.currentState=getState(d);
724 //setState(d, LssTimingDelay);
725 d->lss_transfer.canHandle_t=d->canHandle;
727 StartLSS_SDELAY_TIMER();
730 case LSS_CONF_STORE: /* Store Configured Parameters */
735 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE){
736 if(d->lss_StoreConfiguration){
737 /* call lss_StoreConfiguration with NodeId */
738 (*d->lss_StoreConfiguration)(d,&error_code,&spec_error);
741 MSG_ERR(0x1D2E, "Store configuration not supported",0);
742 error_code=1; /* store configuration is not supported */
746 MSG_WAR(0x3D2F, "SlaveLSS not in configuration mode",0);
750 sendSlaveLSSMessage(d,msg_cs,&error_code,&spec_error);
753 case LSS_SM_SELECTIVE_VENDOR: /* Switch Mode Selective */
754 case LSS_SM_SELECTIVE_PRODUCT:
755 case LSS_SM_SELECTIVE_REVISION:
756 case LSS_SM_SELECTIVE_SERIAL:
759 const indextable *ptrTable;
760 ODCallback_t *Callback;
761 UNS32 _SpecificNodeInfo;
763 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE)
765 MSG_ERR(0x1D30, "Switch Mode Selective only supported in operational mode",0);
769 _SpecificNodeInfo=getLSSIdent(m);
771 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
772 if(_SpecificNodeInfo==*(UNS32*)ptrTable->pSubindex[msg_cs-(LSS_SM_SELECTIVE_VENDOR-1)].pObject){
774 d->lss_transfer.addr_sel_match|=(0x01<<(msg_cs-LSS_SM_SELECTIVE_VENDOR));
775 /* If all the fields has been set */
776 if(d->lss_transfer.addr_sel_match==0x0F){
778 MSG_WAR(0x3D31, "SlaveLSS switching to configuration mode ", 0);
779 d->lss_transfer.addr_sel_match=0;
780 d->lss_transfer.nodeID=getNodeId(d);
781 d->lss_transfer.mode=LSS_CONFIGURATION_MODE;
783 sendSlaveLSSMessage(d,LSS_SM_SELECTIVE_RESP,0,0);
787 MSG_WAR(0x3D32, "LSS identity field doesn't match ", _SpecificNodeInfo);
788 d->lss_transfer.addr_sel_match=0;
792 case LSS_IDENT_REMOTE_VENDOR: /* LSS Identify Remote Slaves */
793 case LSS_IDENT_REMOTE_PRODUCT:
794 case LSS_IDENT_REMOTE_REV_LOW:
795 case LSS_IDENT_REMOTE_REV_HIGH:
796 case LSS_IDENT_REMOTE_SERIAL_LOW:
797 case LSS_IDENT_REMOTE_SERIAL_HIGH:
800 const indextable *ptrTable;
801 ODCallback_t *Callback;
802 UNS32 _SpecificNodeInfo;
804 _SpecificNodeInfo=getLSSIdent(m);
806 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
808 /* Check if the data match the identity object. */
810 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;
811 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;
812 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;
813 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;
814 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;
815 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;
817 /* If all the fields has been set.. */
818 if(d->lss_transfer.addr_ident_match==0x3F){
819 MSG_WAR(0x3D33, "SlaveLSS identified ", 0);
820 d->lss_transfer.addr_ident_match=0;
821 sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
823 else if(d->lss_transfer.addr_ident_match==0){
824 MSG_WAR(0x3D34, "LSS identify field doesn't match ", _SpecificNodeInfo);
828 case LSS_IDENT_REMOTE_NON_CONF: /* LSS identify non-configured remote slave */
830 if(getNodeId(d)==0xFF){
831 MSG_WAR(0x3D35, "SlaveLSS non-configured ", 0);
832 sendSlaveLSSMessage(d,LSS_IDENT_NON_CONF_SLAVE,0,0);
835 MSG_WAR(0x3D36, "SlaveLSS already configured ", 0);
839 case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
840 case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
841 case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
842 case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
843 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE)
847 const indextable *ptrTable;
848 ODCallback_t *Callback;
849 UNS32 _SpecificNodeInfo;
851 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
852 _SpecificNodeInfo=*(UNS32*)ptrTable->pSubindex[msg_cs-(LSS_INQ_VENDOR_ID-1)].pObject;
853 MSG_WAR(0x3D37, "SlaveLSS identity field inquired ", _SpecificNodeInfo);
855 sendSlaveLSSMessage(d,msg_cs,&_SpecificNodeInfo,0);
858 case LSS_INQ_NODE_ID: /* Inquire Node-ID */
859 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE)
864 MSG_WAR(0x3D38, "SlaveLSS Node ID inquired ", NodeID);
865 sendSlaveLSSMessage(d,msg_cs,&NodeID,0);
868 MSG_WAR(0x3D39, "SlaveLSS not in configuration mode",0);
871 #ifdef CO_ENABLE_LSS_FS
872 case LSS_IDENT_FASTSCAN:
874 /* If the nodeID isn't 0xFF the slave shall not participate */
875 if(getNodeId(d)!=0xFF)break;
876 if(getLSSBitCheck(m)==128)d->lss_transfer.FastScan_SM=LSS_FS_RESET;
878 switch(d->lss_transfer.FastScan_SM){
882 const indextable *ptrTable;
883 ODCallback_t *Callback;
885 MSG_WAR(0x3D3A, "SlaveLSS Reseting LSSPos", 0);
886 d->lss_transfer.LSSPos=0;
887 d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
889 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
890 d->lss_transfer.IDNumber=*(UNS32*)ptrTable->pSubindex[d->lss_transfer.LSSPos+1].pObject;
892 sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
895 case LSS_FS_PROCESSING:/*if(getLSSBitCheck(m)<32)*/
896 if(d->lss_transfer.LSSPos==getLSSSub(m))
898 UNS32 Mask=0xFFFFFFFF<<getLSSBitCheck(m);
900 MSG_WAR(0x3D3B, "SlaveLSS FastScan IDNumber", getLSSIdent(m));
901 MSG_WAR(0x3D3C, "SlaveLSS FastScan BitMask ", Mask);
902 MSG_WAR(0x3D3D, "SlaveLSS FastScan LSS-ID ", d->lss_transfer.IDNumber);
904 if((getLSSIdent(m) & Mask)==(d->lss_transfer.IDNumber & Mask))
906 sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
909 if(getLSSBitCheck(m)==0)
911 d->lss_transfer.FastScan_SM=LSS_FS_CONFIRMATION;
915 case LSS_FS_CONFIRMATION:
916 if(d->lss_transfer.LSSPos==getLSSSub(m))
918 if(getLSSIdent(m)==d->lss_transfer.IDNumber)
920 /* Current LSS-ID[sub] confirmed correctly */
921 MSG_WAR(0x3D3E, "SlaveLSS FastScan IDNumber and LSS-ID match=>", d->lss_transfer.IDNumber);
922 if(d->lss_transfer.LSSPos==3)
924 /* All LSS-ID[sub] identified correctly, switching to configuration mode */
925 MSG_WAR(0x3D3F, "SlaveLSS switching to configuration mode ", 0);
926 d->lss_transfer.nodeID=getNodeId(d);
927 d->lss_transfer.mode=LSS_CONFIGURATION_MODE;
928 d->lss_transfer.FastScan_SM=LSS_FS_RESET;
929 d->lss_transfer.LSSPos=0xFF;
933 /* Switch to the next LSS-ID[sub] */
935 const indextable *ptrTable;
936 ODCallback_t *Callback;
938 d->lss_transfer.LSSPos=getLSSNext(m);
939 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
940 d->lss_transfer.IDNumber=*(UNS32*)ptrTable->pSubindex[d->lss_transfer.LSSPos+1].pObject;
941 d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
943 sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
952 MSG_ERR(0x1D40, "SlaveLSS command not implemented", msg_cs);
959 /*UNS8 configNetworkNode(CO_Data* d, UNS8 command, void *dat1, void* dat2)
961 return sendMasterLSSMessage(d,command,dat1,dat2);
964 UNS8 configNetworkNode (CO_Data* d, UNS8 command, void *dat1, void* dat2, LSSCallback_t Callback)
966 //d->lss_transfer.state=LSS_TRANS_IN_PROGRESS;
967 d->lss_transfer.Callback=Callback;
968 d->lss_transfer.command=command;
971 //StartLSS_MSG_TIMER();
973 return sendMasterLSSMessage(d,command,dat1,dat2);
976 UNS8 getConfigResultNetworkNode (CO_Data* d, UNS8 command, UNS32* dat1, UNS8* dat2)
978 *dat1=d->lss_transfer.dat1;
979 *dat2=d->lss_transfer.dat2;
980 return d->lss_transfer.state;
983 //void _lss_StoreConfiguration(UNS8 *error, UNS8 *spec_error){printf("_lss_StoreConfiguration\n");}
984 //void _lss_ChangeBaudRate(char *BaudRate){printf("_lss_ChangeBaudRate\n");}