examples/AppliSlave_HCS12/appli.c
changeset 93 16c8ceea8f18
parent 92 0d84d95790d9
child 94 bdf4c86be6b2
equal deleted inserted replaced
92:0d84d95790d9 93:16c8ceea8f18
     1 /*
       
     2 This file is part of CanFestival, a library implementing CanOpen Stack. 
       
     3 
       
     4 Copyright (C): Edouard TISSERANT and Francis DUPIN
       
     5 
       
     6 See COPYING file for copyrights details.
       
     7 
       
     8 This library is free software; you can redistribute it and/or
       
     9 modify it under the terms of the GNU Lesser General Public
       
    10 License as published by the Free Software Foundation; either
       
    11 version 2.1 of the License, or (at your option) any later version.
       
    12 
       
    13 This library is distributed in the hope that it will be useful,
       
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16 Lesser General Public License for more details.
       
    17 
       
    18 You should have received a copy of the GNU Lesser General Public
       
    19 License along with this library; if not, write to the Free Software
       
    20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    21 */
       
    22 
       
    23 #include <stddef.h> /* for NULL */
       
    24 
       
    25 #include <asm-m68hc12/portsaccess.h>
       
    26 #include <asm-m68hc12/ports_def.h>
       
    27 #include <asm-m68hc12/ports.h>
       
    28 #include  <interrupt.h>
       
    29 
       
    30 #include <applicfg.h>
       
    31 #include <candriver.h>
       
    32 #include <timerhw.h>
       
    33 
       
    34 #include "../include/def.h"
       
    35 #include "../include/can.h"
       
    36 #include "../include/objdictdef.h"
       
    37 #include "../include/objacces.h"
       
    38 #include "../include/canOpenDriver.h"
       
    39 #include "../include/sdo.h"
       
    40 #include "../include/pdo.h"
       
    41 #include "../include/init.h"
       
    42 #include "../include/timer.h"
       
    43 #include "../include/lifegrd.h"
       
    44 #include "../include/sync.h"
       
    45 
       
    46 #include "../include/nmtSlave.h"
       
    47 
       
    48 
       
    49 
       
    50 // HCS12 configuration
       
    51 // -----------------------------------------------------
       
    52 
       
    53 enum E_CanBaudrate 
       
    54 {
       
    55    CAN_BAUDRATE_250K,
       
    56    CAN_BAUDRATE_500K,
       
    57    CAN_BAUDRATE_1M,
       
    58    CAN_BAUDRATE_OLD_VALUE
       
    59 };
       
    60 
       
    61 const canBusTime CAN_Baudrates[] =
       
    62 {
       
    63    {
       
    64       1,  /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board        */
       
    65       3,  /* brp :  chose btw 0 and 63 (6 bits).  freq time quantum = 16MHz / (brp + 1) */
       
    66       0,  /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum          */
       
    67       0,  /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit              */
       
    68       1,  /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1)  tq       */
       
    69      12,  /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1)  tq      */
       
    70 
       
    71       /*
       
    72       With these values, 
       
    73       - The width of the bit time is 16 time quantum :
       
    74           - 1 tq for the SYNC segment (could not be modified)
       
    75           - 13 tq for the TIME 1 segment (tseg1 = 12)
       
    76           - 2 tq for the TIME 2 segment (tseg2 = 1)
       
    77       - Because the bus clock of the MSCAN is 16 MHZ, and the 
       
    78         freq of the time quantum is 4 MHZ (brp = 3+1), and  there are 16 tq in the bit time,
       
    79         so the freq of the bit time is 250 kHz.
       
    80       */
       
    81    },
       
    82 
       
    83    {
       
    84       1,  /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board        */
       
    85       1,  /* brp :  chose btw 0 and 63 (6 bits).  freq time quantum = 16MHz / (brp + 1) */
       
    86       0,  /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum          */
       
    87       0,  /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit              */
       
    88       1,  /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1)  tq       */
       
    89      12,  /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1)  tq      */
       
    90 
       
    91       /*
       
    92       With these values, 
       
    93       - The width of the bit time is 16 time quantum :
       
    94           - 1 tq for the SYNC segment (could not be modified)
       
    95           - 13 tq for the TIME 1 segment (tseg1 = 12)
       
    96           - 2 tq for the TIME 2 segment (tseg2 = 1)
       
    97       - Because the bus clock of the MSCAN is 16 MHZ, and the 
       
    98         freq of the time quantum is 8 MHZ (brp = 1+1), and  there are 16 tq in the bit time,
       
    99         so the freq of the bit time is 500 kHz.
       
   100       */
       
   101     },
       
   102 
       
   103 	{
       
   104       1,  /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board        */
       
   105       1,  /* brp :  chose btw 0 and 63 (6 bits).  freq time quantum = 16MHz / (brp + 1) */
       
   106       0,  /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum          */
       
   107       0,  /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit              */
       
   108       1,  /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1)  tq       */
       
   109       4,  /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1)  tq      */
       
   110 
       
   111       /*
       
   112       With these values, 
       
   113       - The width of the bit time is 16 time quantum :
       
   114           - 1 tq for the SYNC segment (could not be modified)
       
   115           - 5 tq for the TIME 1 segment (tseg1 = 4)
       
   116           - 2 tq for the TIME 2 segment (tseg2 = 1)
       
   117       - Because the bus clock of the MSCAN is 16 MHZ, and the 
       
   118         freq of the time quantum is 8 MHZ (brp = 1+1), and  there are 8 tq in the bit time,
       
   119         so the freq of the bit time is 1 MHz.
       
   120       */
       
   121     },
       
   122 
       
   123 	{
       
   124       1,  /* clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board        */
       
   125       0,  /* brp :  chose btw 0 and 63 (6 bits).  freq time quantum = 16MHz / (brp + 1) */
       
   126       1,  /* sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum          */
       
   127       1,  /* samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit              */
       
   128       4,  /* tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1)  tq       */
       
   129       9,  /* tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1)  tq      */
       
   130 
       
   131       /*
       
   132       With these values, 
       
   133       - The width of the bit time is 16 time quantum :
       
   134           - 1 tq for the SYNC segment (could not be modified)
       
   135           - 10 tq for the TIME 1 segment (tseg1 = 9)
       
   136           - 5 tq for the TIME 2 segment (tseg2 = 4)
       
   137       - Because the bus clock of the MSCAN is 16 MHZ, and the 
       
   138         freq of the time quantum is 16 MHZ (brp = 0), and  there are 16 tq in the bit time,
       
   139         so the freq of the bit time is 1 MHz.
       
   140       */
       
   141     }
       
   142 };
       
   143 
       
   144 
       
   145 // The variables sent or updated by PDO
       
   146 // -----------------------------------------------------
       
   147 extern UNS8 seconds;		// Mapped at index 0x2000, subindex 0x1
       
   148 extern UNS8 minutes;		// Mapped at index 0x2000, subindex 0x2
       
   149 extern UNS8 hours;		// Mapped at index 0x2000, subindex 0x3
       
   150 extern UNS8 day;		// Mapped at index 0x2000, subindex 0x4
       
   151 extern UNS32 canopenErrNB;	// Mapped at index 0x6000, subindex 0x0
       
   152 extern UNS32 canopenErrVAL;	// Mapped at index 0x6001, subindex 0x0
       
   153 
       
   154 // Required definition variables
       
   155 // -----------------------------
       
   156 // The variables that you should define for debugging.
       
   157 // They are used by the macro MSG_ERR and MSG_WAR in applicfg.h
       
   158 // if the node is a slave, they can be mapped in the object dictionnary.
       
   159 // if not null, allow the printing of message to the console
       
   160 // Could be managed by PDO
       
   161 UNS8 printMsgErrToConsole = 1;
       
   162 UNS8 printMsgWarToConsole = 1;
       
   163 
       
   164 
       
   165 
       
   166 /*************************User's variables declaration**************************/
       
   167 UNS8 softCount = 0;
       
   168 UNS8 lastMinute = 0;
       
   169 UNS8 lastSecond = 0;
       
   170 UNS8 sendingError = 0;
       
   171 //--------------------------------FONCTIONS-------------------------------------
       
   172 /* You *must* have these 2 functions in your code*/
       
   173 void heartbeatError(UNS8 heartbeatID);
       
   174 void SD0timeoutError(UNS8 bus_id, UNS8 line);
       
   175 
       
   176 // Interruption timer 3. (The timer 4 is used by CanOpen)
       
   177 void __attribute__((interrupt)) timer3Hdl (void);
       
   178 
       
   179 void incDate(void);
       
   180 void initLeds(void);
       
   181 void initTimerClk(void);
       
   182 void initCanHCS12 (void);
       
   183 void initialisation(void);
       
   184 void preOperational(void);
       
   185 void operational(void);
       
   186 void stopped(void);
       
   187 //------------------------------------------------------------------------------
       
   188 
       
   189 
       
   190 //------------------------------------------------------------------------------
       
   191 // Interruption timer 3
       
   192 void __attribute__((interrupt)) timer3Hdl (void)
       
   193 {
       
   194   //IO_PORTS_8(PORTB) ^= 0x10;
       
   195   //IO_PORTS_8(PORTB) &= ~0x20;
       
   196   IO_PORTS_8(TFLG1) = 0x08; // RAZ du flag interruption timer 3
       
   197   // Calcul evt suivant. Clock 8 MHz -> 8000 evt de 1 ms!! Doit tenir sur 16 bits
       
   198   // Attention, ça change si on utilise la pll
       
   199   // Lorsque le timer atteindra la valeur de TC3 (16 bits), l'interruption timer3Hdl sera déclenchée
       
   200   // Si on utilise la PLL à 24 MHZ, alors la vitesse du bus est multipliée par 3.
       
   201 
       
   202 /*   Assume that our board uses a 16 MHz quartz */
       
   203 /*   Without pre-division, 8000 counts takes 1 ms. */
       
   204 /*   We are using a pre-divisor of 32. (register TSCR2) See in CanOpenDriverHC12/timerhw.c  */
       
   205 /*   So 10000 counts takes 40 ms. */
       
   206 /*   We must have a soft counter of 25 to count a second. */
       
   207   
       
   208   IO_PORTS_16(TC3H) += (10000); // IT every 40000 count.
       
   209   softCount++;
       
   210   if (softCount == 25) {
       
   211     softCount = 0;
       
   212     incDate();
       
   213   }
       
   214 }
       
   215 
       
   216 //------------------------------------------------------------------------------
       
   217 void heartbeatError(UNS8 heartbeatID)
       
   218 {
       
   219   MSG_ERR(0x1F00, "!!! No heart beat received from node : ", heartbeatID);
       
   220 }
       
   221 
       
   222 //------------------------------------------------------------------------------
       
   223 void SD0timeoutError (UNS8 bus_id, UNS8 line)
       
   224 {
       
   225   // Informations on what occurs are in transfers[bus_id][line]....
       
   226   // See scanSDOtimeout() in sdo.c
       
   227 }
       
   228 
       
   229 //------------------------------------------------------------------------------
       
   230 // Incrementation of the date, every second
       
   231 void incDate(void)
       
   232 {
       
   233   if (seconds == 59) {
       
   234     seconds = 0;
       
   235     if (minutes == 59) {
       
   236       minutes = 0;
       
   237       if (hours == 23) {
       
   238 	hours = 0;
       
   239 	day++;
       
   240       } 
       
   241       else
       
   242 	hours++;
       
   243     }
       
   244     else 
       
   245       minutes++;
       
   246   }
       
   247   else
       
   248     seconds++;
       
   249 
       
   250   // Toggle the led 4 every seconds
       
   251   IO_PORTS_8(PORTB) ^= 0x10;
       
   252 
       
   253 }
       
   254 
       
   255 //Initialisation of the port B for the leds.
       
   256 void initLeds(void)
       
   257 {
       
   258   // Port B is output
       
   259   IO_PORTS_8(DDRB)= 0XFF;
       
   260   // RAZ
       
   261   IO_PORTS_8(PORTB) = 0xFF;
       
   262 }
       
   263 
       
   264 
       
   265 
       
   266 //------------------------------------------------------------------------------
       
   267 // Init the timer for the clock demo
       
   268 void initTimerClk(void)
       
   269 {
       
   270 
       
   271   lock();   // Inhibe les interruptions
       
   272 
       
   273   // Configuration du Channel 3
       
   274   IO_PORTS_8(TIOS) |= 0x08;     // Canal 3 en sortie
       
   275   IO_PORTS_8(TCTL2) &= ~(0xC0); // Canal 3 déconnecté du pin de sortie
       
   276   IO_PORTS_8(TIE) |= 0x08;      // Autorise interruption Canal 3
       
   277   IO_PORTS_8(TSCR1) |= 0x80;    // Mise en route du timer
       
   278   unlock(); // Autorise les interruptions
       
   279 }
       
   280 
       
   281 
       
   282 //------------------------------------------------------------------------------
       
   283 
       
   284 // A placer avant initTimer de la bibliothèque CanOpen
       
   285 /* void initTimerbis(void) */
       
   286 /* {   */
       
   287 
       
   288 /*   lock();                      // Inhibe les interruptions */
       
   289 /*   // Configuration des IT Channels (0..3) */
       
   290 /*   IO_PORTS_8(TIOS)  &= 0xF0;  // Canals 0->3 en entrées.    */
       
   291 /*   IO_PORTS_8(TCTL4) &= 0XFD;  // Canal 0 détection sur front montant. */
       
   292 /*   IO_PORTS_8(TCTL4) |= 0X01;    */
       
   293 /*   IO_PORTS_8(TCTL4) &= 0XF7;  // Canal 1 détection sur front montant. */
       
   294 /*   IO_PORTS_8(TCTL4) |= 0X04; */
       
   295 /*   IO_PORTS_8(TCTL4) &= 0XDF;  // Canal 2 détection sur front montant. */
       
   296 /*   IO_PORTS_8(TCTL4) |= 0X10;   */
       
   297 /*   IO_PORTS_8(TCTL4) &= 0X7F;  // Canal 3 détection sur front montant. */
       
   298 /*   IO_PORTS_8(TCTL4) |= 0X40;        */
       
   299 /*   IO_PORTS_8(TSCR2) |= 0X05;  // Pre-scaler = 32.  */
       
   300    
       
   301 /*   IO_PORTS_8(ICOVW) |= 0x0F;  // La sauvgrade des valeures de TC0 et TC0H  */
       
   302 /*                               // correspondant aux canals (0..3) jusqu'a la */
       
   303 /*                               // prochaine lecture dans ces registres.  */
       
   304 /*   MASK  = IO_PORTS_8(ICSYS); */
       
   305 /*   MASK &= 0xFE;               // Canals (0..3) en IC QUEUE MODE. */
       
   306 /*   MASK |= 0x08;               // Canals (0..3) : génére une interruption aprés  */
       
   307 /*                               // la capture de deux valeures du timer sur detection */
       
   308 /*                               // d'un front montant à l'entrée des canals (0..3). */
       
   309 /*   MASK |= 0x02;               */
       
   310 /*   IO_PORTS_8(ICSYS) = MASK; */
       
   311 /*   IO_PORTS_16(TC0HH);         // Vider le registre holding correspondant au canal0. */
       
   312 /*   IO_PORTS_8(TSCR1) |= 0x10;  // RAZ automatique des flags d'interruption aprés lecture */
       
   313 /*                               // dans les registres correspondant.   */
       
   314                               
       
   315 /*   IO_PORTS_8(TIE)   |= 0x0F;  // Autorise interruption Canals (0..3). */
       
   316 /*   IO_PORTS_8(TSCR2) |= 0X80;  // Autorise interruption sur l'Overflow.  */
       
   317 /*   unlock();                   // Autorise les interruptions  */
       
   318   
       
   319 /* } */
       
   320 
       
   321 //------------------------------------------------------------------------------
       
   322 
       
   323 
       
   324 
       
   325 void initCanHCS12 (void)
       
   326 {  
       
   327   //Init the HCS12 microcontroler for CanOpen 
       
   328   initHCS12();
       
   329    // Init the HCS12  CAN driver
       
   330   const canBusInit bi0 = {
       
   331     0,    /* no low power                 */ 
       
   332     0,    /* no time stamp                */
       
   333     1,    /* enable MSCAN                 */
       
   334     0,    /* clock source : oscillator (In fact, it is not used)   */
       
   335     0,    /* no loop back                 */
       
   336     0,    /* no listen only               */
       
   337     0,    /* no low pass filter for wk up */
       
   338 	CAN_Baudrates[CAN_BAUDRATE_250K],
       
   339     {
       
   340       0x00,    /* Filter on 16 bits. See Motorola Block Guide V02.14 fig 4-3 */
       
   341       0x00, 0xFF, /* filter 0 hight accept all msg      */
       
   342       0x00, 0xFF, /* filter 0 low accept all msg        */
       
   343       0x00, 0xFF, /* filter 1 hight filter all of  msg  */
       
   344       0x00, 0xFF, /* filter 1 low filter all of  msg    */
       
   345       0x00, 0xFF, /* filter 2 hight filter most of  msg */
       
   346       0x00, 0xFF, /* filter 2 low filter most of  msg   */
       
   347       0x00, 0xFF, /* filter 3 hight filter most of  msg */
       
   348       0x00, 0xFF, /* filter 3 low filter most of  msg   */
       
   349     }
       
   350   };   
       
   351 
       
   352   canInit(CANOPEN_LINE_NUMBER_USED, bi0);  //initialize filters...
       
   353   unlock(); // Allow interruptions
       
   354 }
       
   355 
       
   356 
       
   357 /*********************************************************************/
       
   358 void initialisation( void )
       
   359 { 
       
   360   //initcapteur();      //initialisation du capteur, timer, compteurs logiciels
       
   361   initCanHCS12();   //initialisation du bus Can
       
   362   MSG_WAR(0X3F05, "I am in INITIALISATION mode ", 0);
       
   363   /* Defining the node Id */
       
   364   setNodeId(0x05);
       
   365   MSG_WAR(0x3F06, "My node ID is : ", getNodeId()); 
       
   366   {
       
   367     UNS8 *data;
       
   368     UNS8 size;
       
   369     UNS8 dataType;
       
   370     // Manufacturer Device name (default = empty string)
       
   371     getODentry(0x1008, 0x0, (void **)&data, &size, &dataType, 0);
       
   372     MSG_WAR(0x3F09, data, 0);
       
   373     // Manufacturer Hardware version. (default = compilation. date)
       
   374     getODentry(0x1009, 0x0, (void **)&data, &size, &dataType, 0);
       
   375     MSG_WAR(0x3F09, data, 0);
       
   376     // Manufacturer Software version. (default = compilation. time)
       
   377     getODentry(0x100A, 0x0, (void **)&data, &size, &dataType, 0);
       
   378     MSG_WAR(0x3F09, data, 0);
       
   379   }
       
   380   initCANopenMain();    //initialisation du canopen 
       
   381   heartbeatInit();      //initialisation du lifeguarding
       
   382   initResetMode();
       
   383   initTimer();          //initialisation of the timer used by Canopen
       
   384   initTimerClk();
       
   385 }
       
   386 
       
   387 
       
   388 /*********************************************************************/
       
   389 void preOperational(void)
       
   390 {
       
   391   // Test if the heartBeat have been received. Send headbeat
       
   392   heartbeatMGR();
       
   393   // Read message
       
   394   receiveMsgHandler(0);
       
   395 }
       
   396 
       
   397 
       
   398 /********************************************************************/
       
   399 void operational( void )
       
   400 { 
       
   401 
       
   402   // Init the errors
       
   403   canopenErrNB = 0;
       
   404   canopenErrVAL = 0;
       
   405 
       
   406   // Test if the heartBeat have been received. Send headbeat
       
   407   heartbeatMGR();
       
   408   // Read message
       
   409   receiveMsgHandler(0); 
       
   410   
       
   411   if (lastMinute != minutes) {
       
   412     MSG_WAR(0x3F00, "event : minutes change -> node decides to send it. Value : ", minutes);
       
   413     sendPDOevent( 0, &minutes );
       
   414     lastMinute = minutes;
       
   415   }
       
   416 
       
   417   if (canopenErrNB == 0)
       
   418     sendingError = 0;
       
   419 
       
   420   
       
   421   if (lastSecond != seconds) {
       
   422     MSG_WAR (0x3F50, "Seconds = ", seconds);
       
   423     if ((seconds == 50) && (sendingError == 0))
       
   424       {
       
   425 	MSG_ERR(0x1F55, "DEMO of ERROR. Sent by PDO. Value : ", 0xABCD);
       
   426 	sendingError = 1;
       
   427       }
       
   428     
       
   429     if (canopenErrNB) {
       
   430       MSG_WAR(0x3F56, "ERROR nb : ",  canopenErrNB);
       
   431     }
       
   432     lastSecond = seconds;
       
   433     
       
   434   }
       
   435 
       
   436 }
       
   437 
       
   438 
       
   439 /*****************************************************************************/
       
   440 void stopped( void )
       
   441 {
       
   442   heartbeatMGR();
       
   443   // Read message
       
   444   receiveMsgHandler(0);
       
   445 }
       
   446 
       
   447 
       
   448 /*****************************************************************************/
       
   449 
       
   450 
       
   451 
       
   452 /********************************* MAIN ***************************************/
       
   453 
       
   454  
       
   455 int main ()
       
   456 {
       
   457   e_nodeState lastState = Unknown_state;
       
   458 
       
   459   /* CanOpen slave state machine         */
       
   460   /* ------------------------------------*/
       
   461     
       
   462   while(1) { /* slave's state machine */
       
   463       
       
   464     switch( getState() ) {				
       
   465     case Initialisation:
       
   466       if (lastState != getState()) {
       
   467 	initLeds();
       
   468 	IO_PORTS_8(PORTB) &= ~ 0x01; // led  0         : ON
       
   469 	IO_PORTS_8(PORTB) |=   0x0E; // leds 1, 2, 3   : OFF
       
   470 	MSG_WAR(0X3F10, "Entering in INITIALISATION mode ", 0);
       
   471       }
       
   472       initialisation();
       
   473       /* change automatically into pre_operational state */ 
       
   474       lastState = Initialisation;
       
   475       setState(Pre_operational);
       
   476       break;
       
   477 					
       
   478     case Pre_operational:
       
   479       if (lastState != getState()) {
       
   480 	IO_PORTS_8(PORTB) &= ~ 0x03; // leds 0, 1      : ON
       
   481 	IO_PORTS_8(PORTB) |=   0x0C; // leds 2, 3      : OFF
       
   482 	MSG_WAR(0X3F11, "Entering in PRE_OPERATIONAL mode ", 0);
       
   483 	initPreOperationalMode();
       
   484       }
       
   485       preOperational();
       
   486       if (lastState == Initialisation)
       
   487 	slaveSendBootUp(0);
       
   488       lastState = Pre_operational;
       
   489       break;
       
   490 					
       
   491     case Operational:
       
   492       if (lastState != getState()) {
       
   493 	IO_PORTS_8(PORTB) &= ~ 0x07; // leds 0, 1, 2   : ON
       
   494 	IO_PORTS_8(PORTB) |=   0x08; // leds 3         : OFF
       
   495 	MSG_WAR(0X3F12, "Entering in OPERATIONAL mode ", 0);
       
   496       }
       
   497       operational();    
       
   498       lastState = Operational;	
       
   499       break;
       
   500 	  		
       
   501     case Stopped:
       
   502       if (lastState != getState()) {
       
   503 	IO_PORTS_8(PORTB) |=   0x0F; // leds 0, 1, 2, 3 : OFF
       
   504 	MSG_WAR(0X3F13, "Entering in  STOPPED mode", 0);
       
   505       }
       
   506       stopped();
       
   507       lastState = Stopped;
       
   508       break;
       
   509     }//end switch case	
       
   510 
       
   511   }
       
   512   return (0); 
       
   513 }
       
   514