Ahmed HADDAD / EasyCAT_lib

Dependents:   MOTION_LCD

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EasyCAT.cpp Source File

EasyCAT.cpp

00001 //********************************************************************************************
00002 //                                                                                           *
00003 // AB&T Tecnologie Informatiche - Ivrea Italy                                                *
00004 // http://www.bausano.net                                                                    *
00005 // https://www.ethercat.org/en/products/791FFAA126AD43859920EA64384AD4FD.htm                 *
00006 //                                                                                           *  
00007 //********************************************************************************************    
00008 //                                                                                           *
00009 // This software is distributed as an example, in the hope that it could be useful,          *
00010 // WITHOUT ANY WARRANTY, even the implied warranty of FITNESS FOR A PARTICULAR PURPOSE       *
00011 //                                                                                           *
00012 //******************************************************************************************** 
00013 
00014 
00015 //----- EasyCAT library for mbed boards -----------------------------------------------------
00016 //----- Derived from the AB&T EasyCAT Arduino shield library V 1.5 170912--------------------------
00017 
00018 //----- Tested with the STM32 NUCLEO-F767ZI board -------------------------------------------
00019 
00020 
00021 
00022 #include "mbed.h"
00023 #include "EasyCAT.h"                         
00024 
00025 
00026 DigitalOut * SpiCs;                                 
00027 SPI Spi(D11, D12, D13);                          // declare MOSI MISO SCK 
00028 
00029 
00030 #define SCS_Low_macro  (*SpiCs = 0);            // macro for set/reset SPI chip select
00031 #define SCS_High_macro (*SpiCs = 1);            //
00032 
00033                                                 // macro for the SPI transfer       
00034 inline static void SPI_TransferTx (unsigned char Data) 
00035 {                                               //
00036     Spi.write(Data);                            //
00037 };                                              //
00038                                                 //
00039 inline static void SPI_TransferTxLast (unsigned char Data) 
00040 {                                               //
00041     Spi.write(Data);                            // 
00042 };                                              //
00043                                                 //
00044 inline static unsigned char SPI_TransferRx (unsigned char Data) 
00045 {                                               //
00046     return Spi.write(Data);                     //
00047 };                                              //
00048 
00049 
00050   
00051 //---- constructors --------------------------------------------------------------------------------
00052 
00053 EasyCAT::EasyCAT()                              //------- default constructor ---------------------- 
00054 {                                               // 
00055   Sync_ = ASYNC;                                // if no synchronization mode is declared
00056                                                 // ASYNC is the default
00057                                                 //
00058   SCS_ = (PinName)D9;                           // if no chip select is declared                 
00059   SpiCs = new DigitalOut(SCS_, 1);              // pin D9 is the default  
00060 }                                               //
00061 
00062 
00063 EasyCAT::EasyCAT(PinName SCS)                   //------- SPI_CHIP_SELECT options -----------------
00064                                                 //
00065                                                 // for EasyCAT board REV_A we can choose between:
00066                                                 // D8, D9, D10
00067                                                 //  
00068                                                 // for EasyCAT board REV_B we have three additional options:
00069                                                 // A5, D6, D7 
00070 {                                       
00071   SCS_ = SCS;                                   //  initialize chip select  
00072   SpiCs = new DigitalOut(SCS_, 1);              //
00073 }                                               // 
00074 
00075 
00076 EasyCAT::EasyCAT(SyncMode Sync)                 //-------Synchronization options ---------------------- 
00077                                                 //   
00078                                                 // we can choose between:
00079                                                 // ASYNC   = free running i.e. no synchronization
00080                                                 //           between master and slave (default)   
00081                                                 //
00082                                                 // DC_SYNC = interrupt is generated from the
00083                                                 //           Distributed clock unit
00084                                                 //
00085                                                 // SM_SYNC = interrupt is generated from the
00086                                                 //           Syncronizatiom manager 2 
00087 {                                               //
00088   Sync_ = Sync;                                 //                                           
00089                                                 //                                        
00090   SCS_ = (PinName)D9;                           // default chip select is pin 9 
00091   SpiCs = new DigitalOut(SCS_, 1);              //
00092 }                                               //  
00093 
00094 
00095                                                 //-- Synchronization and chip select options -----  
00096 EasyCAT::EasyCAT(PinName SCS, SyncMode Sync)    //
00097                                                 //              
00098 {                                               //
00099   Sync_ = Sync;                                 //  
00100                                                 //   
00101   SCS_ = SCS;                                   //  initialize chip select                                                 
00102   SpiCs = new DigitalOut(SCS_, 1);              // 
00103 }                                               //  
00104 
00105 
00106   
00107 //---- EasyCAT board initialization ---------------------------------------------------------------
00108 
00109 
00110 bool EasyCAT::Init()
00111 {
00112   #define Tout 1000
00113   
00114   ULONG TempLong;
00115   unsigned short i;
00116    
00117   Spi.frequency(14000000);                                // SPI speed 14MHz  
00118   Spi.format(8,0);                                        // 8 bit mode 0
00119   
00120   wait_ms(100);
00121  
00122   SPIWriteRegisterDirect (RESET_CTL, DIGITAL_RST);        // LAN9252 reset 
00123    
00124   i = 0;                                                  // reset timeout 
00125   do                                                      // wait for reset to complete
00126   {                                                       //
00127     i++;                                                  //
00128     TempLong.Long = SPIReadRegisterDirect (RESET_CTL, 4); //
00129   }while (((TempLong.Byte[0] & 0x01) != 0x00) && (i != Tout));    
00130                                                           //                                                       
00131   if (i == Tout)                                          // time out expired      
00132   {                                                       //   
00133     return false;                                         // initialization failed  
00134   }                                                         
00135   
00136   i = 0;                                                  // reset timeout  
00137   do                                                      // check the Byte Order Test Register
00138   {                                                       //
00139     i++;                                                  //      
00140     TempLong.Long = SPIReadRegisterDirect (BYTE_TEST, 4); //
00141   }while ((TempLong.Long != 0x87654321) && (i != Tout));  //    
00142                                                           //                                                            
00143   if (i == Tout)                                          // time out expired      
00144   {                                                       // 
00145     return false;                                         // initialization failed  
00146   }            
00147   
00148   i = 0;                                                  // reset timeout  
00149   do                                                      // check the Ready flag
00150   {                                                       //
00151     i++;                                                  //    
00152     TempLong.Long = SPIReadRegisterDirect (HW_CFG, 4);    //
00153   }while (((TempLong.Byte[3] & READY) == 0) && (i != Tout));//
00154                                                           //
00155   if (i == Tout)                                          // time out expired      
00156   {                                                       //
00157     return false;                                         // initialization failed  
00158   }            
00159   
00160 
00161   
00162 #ifdef BYTE_NUM
00163   printf ("STANDARD MODE\n"); 
00164 #else
00165   printf ("CUSTOM MODE\n"); 
00166 #endif
00167 
00168   printf ("%u Byte Out\n",TOT_BYTE_NUM_OUT);  
00169   printf ("%u Byte In\n",TOT_BYTE_NUM_IN);      
00170 
00171   printf ("Sync = ");                                                              
00172                                                             
00173                                                           
00174   if ((Sync_ == DC_SYNC) || (Sync_ == SM_SYNC))           //--- if requested, enable --------   
00175   {                                                       //--- interrupt generation -------- 
00176   
00177     if (Sync_ == DC_SYNC)
00178     {                                                     // enable interrupt from SYNC 0
00179       SPIWriteRegisterIndirect (0x00000004, AL_EVENT_MASK, 4);  
00180                                                           // in AL event mask register, and disable 
00181                                                           // other interrupt sources    
00182       printf("DC_SYNC\n");                                                      
00183     }                                                       
00184                                                                                                          
00185     else
00186     {                                                     // enable interrupt from SM 0 event
00187       SPIWriteRegisterIndirect (0x00000100, AL_EVENT_MASK, 4);  
00188                                                           // in AL event mask register, and disable 
00189                                                           // other interrupt sources 
00190       printf("SM_SYNC\n");    
00191     }   
00192                                                          
00193     SPIWriteRegisterDirect (IRQ_CFG, 0x00000111);         // set LAN9252 interrupt pin driver  
00194                                                           // as push-pull active high
00195                                                           // (On the EasyCAT shield board the IRQ pin
00196                                                           // is inverted by a mosfet, so Arduino                                                        
00197                                                           // receives an active low signal)
00198                                                                         
00199     SPIWriteRegisterDirect (INT_EN, 0x00000001);          // enable LAN9252 interrupt      
00200   } 
00201 
00202   else
00203   {
00204     printf("ASYNC\n");
00205   }
00206   
00207 
00208   TempLong.Long = SPIReadRegisterDirect (ID_REV, 4);      // read the chip identification 
00209   printf ("Detected chip ");                              // and revision, and print it
00210   printf ("%x ", TempLong.Word[1]);                       // out on the serial line
00211   printf (" Rev ");                                       //    
00212   printf ("%u \n", TempLong.Word[0]);                     //    
00213   
00214   
00215  /* 
00216   printf ("%u \n", TOT_BYTE_NUM_OUT); 
00217   printf ("%u \n", BYTE_NUM_OUT);                   
00218   printf ("%u \n", BYTE_NUM_ROUND_OUT);                
00219   printf ("%u \n", LONG_NUM_OUT);                  
00220      
00221   printf ("%u \n", SEC_BYTE_NUM_OUT);                    
00222   printf ("%u \n", SEC_BYTE_NUM_ROUND_OUT);                       
00223   printf ("%u \n\n", SEC_LONG_NUM_OUT);                   
00224 
00225   printf ("%u \n", TOT_BYTE_NUM_IN); 
00226   printf ("%u \n", BYTE_NUM_IN);                       
00227   printf ("%u \n", BYTE_NUM_ROUND_IN);                   
00228   printf ("%u \n", LONG_NUM_IN);                    
00229      
00230   printf ("%u \n", SEC_BYTE_NUM_IN);                    
00231   printf ("%u \n", SEC_BYTE_NUM_ROUND_IN);                         
00232   printf ("%u \n", SEC_LONG_NUM_IN);                         
00233 */
00234   
00235   
00236 //--------------------------------------------------------------------------------------------  
00237   
00238   
00239   return true;                                            // initalization completed        
00240 };  
00241 
00242 
00243 
00244 
00245 //---- EtherCAT task ------------------------------------------------------------------------------
00246 
00247 unsigned char EasyCAT::MainTask()                           // must be called cyclically by the application
00248 
00249 {
00250   bool WatchDog = true;
00251   bool Operational = false; 
00252   unsigned char i;
00253   ULONG TempLong; 
00254   unsigned char Status;  
00255  
00256   
00257   TempLong.Long = SPIReadRegisterIndirect (WDOG_STATUS, 1); // read watchdog status
00258   if ((TempLong.Byte[0] & 0x01) == 0x01)                    //
00259     WatchDog = false;                                       // set/reset the corrisponding flag
00260   else                                                      //
00261     WatchDog = true;                                        //
00262 
00263     
00264   TempLong.Long = SPIReadRegisterIndirect (AL_STATUS, 1);   // read the EtherCAT State Machine status
00265   Status = TempLong.Byte[0] & 0x0F;                         //
00266   if (Status == ESM_OP)                                     // to see if we are in operational state
00267     Operational = true;                                     //
00268   else                                                      // set/reset the corrisponding flag
00269     Operational = false;                                    //    
00270 
00271 
00272                                                             //--- process data transfert ----------
00273                                                             //                                                        
00274   if (WatchDog | !Operational)                              // if watchdog is active or we are 
00275   {                                                         // not in operational state, reset 
00276     for (i=0; i < TOT_BYTE_NUM_OUT ; i++)                   // the output buffer
00277     BufferOut.Byte[i] = 0;                                  //
00278 
00279 /*                                                          // debug
00280     if (!Operational)                                       //
00281       printf("Not operational\n");                          //
00282     if (WatchDog)                                           //    
00283       printf("WatchDog\n");                                 //  
00284 */                                                          //
00285   }
00286   
00287   else                                                      
00288   {                                                         
00289     SPIReadProcRamFifo();                                   // otherwise transfer process data from 
00290   }                                                         // the EtherCAT core to the output buffer  
00291                  
00292   SPIWriteProcRamFifo();                                    // we always transfer process data from
00293                                                             // the input buffer to the EtherCAT core  
00294 
00295   if (WatchDog)                                             // return the status of the State Machine      
00296   {                                                         // and of the watchdog
00297     Status |= 0x80;                                         //
00298   }                                                         //
00299   return Status;                                            //   
00300   
00301 }
00302 
00303 
00304     
00305 //---- read a directly addressable registers  -----------------------------------------------------
00306 
00307 unsigned long EasyCAT::SPIReadRegisterDirect (unsigned short Address, unsigned char Len)
00308 
00309                                                    // Address = register to read
00310                                                    // Len = number of bytes to read (1,2,3,4)
00311                                                    //
00312                                                    // a long is returned but only the requested bytes
00313                                                    // are meaningful, starting from LsByte                                                 
00314 {
00315   ULONG Result; 
00316   UWORD Addr;
00317   Addr.Word = Address; 
00318   unsigned char i; 
00319 
00320   SCS_Low_macro                                             // SPI chip select enable
00321 
00322   SPI_TransferTx(COMM_SPI_READ);                            // SPI read command
00323   SPI_TransferTx(Addr.Byte[1]);                             // address of the register
00324   SPI_TransferTxLast(Addr.Byte[0]);                         // to read, MsByte first
00325  
00326   for (i=0; i<Len; i++)                                     // read the requested number of bytes
00327   {                                                         // LsByte first 
00328     Result.Byte[i] = SPI_TransferRx(DUMMY_BYTE);            //
00329   }                                                         //    
00330   
00331   SCS_High_macro                                            // SPI chip select disable 
00332  
00333   return Result.Long;                                       // return the result
00334 }
00335 
00336 
00337 
00338 
00339 //---- write a directly addressable registers  ----------------------------------------------------
00340 
00341 void EasyCAT::SPIWriteRegisterDirect (unsigned short Address, unsigned long DataOut)
00342 
00343                                                    // Address = register to write
00344                                                    // DataOut = data to write
00345 { 
00346   ULONG Data; 
00347   UWORD Addr;
00348   Addr.Word = Address;
00349   Data.Long = DataOut;    
00350 
00351   SCS_Low_macro                                             // SPI chip select enable  
00352   
00353   SPI_TransferTx(COMM_SPI_WRITE);                           // SPI write command
00354   SPI_TransferTx(Addr.Byte[1]);                             // address of the register
00355   SPI_TransferTx(Addr.Byte[0]);                             // to write MsByte first
00356 
00357   SPI_TransferTx(Data.Byte[0]);                             // data to write 
00358   SPI_TransferTx(Data.Byte[1]);                             // LsByte first
00359   SPI_TransferTx(Data.Byte[2]);                             //
00360   SPI_TransferTxLast(Data.Byte[3]);                         //
00361  
00362   SCS_High_macro                                            // SPI chip select enable   
00363 }
00364 
00365 
00366 //---- read an undirectly addressable registers  --------------------------------------------------
00367 
00368 unsigned long EasyCAT::SPIReadRegisterIndirect (unsigned short Address, unsigned char Len)
00369 
00370                                                    // Address = register to read
00371                                                    // Len = number of bytes to read (1,2,3,4)
00372                                                    //
00373                                                    // a long is returned but only the requested bytes
00374                                                    // are meaningful, starting from LsByte                                                  
00375 {
00376   ULONG TempLong;
00377   UWORD Addr;
00378   Addr.Word = Address;
00379                                                             // compose the command
00380                                                             //
00381   TempLong.Byte[0] = Addr.Byte[0];                          // address of the register
00382   TempLong.Byte[1] = Addr.Byte[1];                          // to read, LsByte first
00383   TempLong.Byte[2] = Len;                                   // number of bytes to read
00384   TempLong.Byte[3] = ESC_READ;                              // ESC read 
00385 
00386   SPIWriteRegisterDirect (ECAT_CSR_CMD, TempLong.Long);     // write the command
00387 
00388   do
00389   {                                                         // wait for command execution
00390     TempLong.Long = SPIReadRegisterDirect(ECAT_CSR_CMD,4);  //
00391   }                                                         //
00392   while(TempLong.Byte[3] & ECAT_CSR_BUSY);                  //
00393                                                              
00394                                                               
00395   TempLong.Long = SPIReadRegisterDirect(ECAT_CSR_DATA,Len); // read the requested register
00396   return TempLong.Long;                                     //
00397 }
00398 
00399 
00400 //---- write an undirectly addressable registers  -------------------------------------------------
00401 
00402 void  EasyCAT::SPIWriteRegisterIndirect (unsigned long DataOut, unsigned short Address, unsigned char Len)
00403 
00404                                                    // Address = register to write
00405                                                    // DataOut = data to write                                                    
00406 {
00407   ULONG TempLong;
00408   UWORD Addr;
00409   Addr.Word = Address;
00410 
00411 
00412   SPIWriteRegisterDirect (ECAT_CSR_DATA, DataOut);            // write the data
00413 
00414                                                               // compose the command
00415                                                               //                                
00416   TempLong.Byte[0] = Addr.Byte[0];                            // address of the register  
00417   TempLong.Byte[1] = Addr.Byte[1];                            // to write, LsByte first
00418   TempLong.Byte[2] = Len;                                     // number of bytes to write
00419   TempLong.Byte[3] = ESC_WRITE;                               // ESC write
00420 
00421   SPIWriteRegisterDirect (ECAT_CSR_CMD, TempLong.Long);       // write the command
00422 
00423   do                                                          // wait for command execution
00424   {                                                           //
00425     TempLong.Long = SPIReadRegisterDirect (ECAT_CSR_CMD, 4);  //  
00426   }                                                           //  
00427   while (TempLong.Byte[3] & ECAT_CSR_BUSY);                   //
00428 }
00429 
00430 
00431 //---- read from process ram fifo ----------------------------------------------------------------
00432 
00433 
00434 void EasyCAT::SPIReadProcRamFifo()    // read BYTE_NUM bytes from the output process ram, through the fifo
00435                                       //        
00436                                       // these are the bytes received from the EtherCAT master and
00437                                       // that will be use by our application to write the outputs
00438 {
00439   ULONG TempLong;
00440   unsigned char i;
00441    
00442   #if TOT_BYTE_NUM_OUT > 0
00443 
00444     SPIWriteRegisterDirect (ECAT_PRAM_RD_CMD, PRAM_ABORT);        // abort any possible pending transfer
00445 
00446   
00447     SPIWriteRegisterDirect (ECAT_PRAM_RD_ADDR_LEN, (0x00001000 | (((uint32_t)TOT_BYTE_NUM_OUT) << 16)));   
00448                                                                   // the high word is the num of bytes
00449                                                                   // to read 0xTOT_BYTE_NUM_OUT----
00450                                                                   // the low word is the output process        
00451                                                                   // ram offset 0x----1000 
00452 
00453     SPIWriteRegisterDirect (ECAT_PRAM_RD_CMD, 0x80000000);        // start command        
00454  
00455  
00456                                                 //------- one round is enough if we have ----
00457                                                 //------- to transfer up to 64 bytes --------
00458    
00459     do                                                            // wait for the data to be       
00460     {                                                             // transferred from the output  
00461       TempLong.Long = SPIReadRegisterDirect (ECAT_PRAM_RD_CMD,2); // process ram to the read fifo       
00462     }                                                             //    
00463     while (TempLong.Byte[1] != FST_LONG_NUM_OUT);                 // 
00464   
00465     SCS_Low_macro                                                 // enable SPI chip select 
00466   
00467     SPI_TransferTx(COMM_SPI_READ);                                // SPI read command
00468     SPI_TransferTx(0x00);                                         // address of the read  
00469     SPI_TransferTxLast(0x00);                                     // fifo MsByte first
00470   
00471     for (i=0; i< FST_BYTE_NUM_ROUND_OUT; i++)                     // transfer the data
00472     {                                                             //
00473       BufferOut.Byte[i] = SPI_TransferRx(DUMMY_BYTE);             //
00474     }                                                             //
00475     
00476     SCS_High_macro                                                // disable SPI chip select    
00477   #endif  
00478 
00479   
00480   #if SEC_BYTE_NUM_OUT > 0                    //-- if we have to transfer more then 64 bytes --
00481                                               //-- we must do another round -------------------
00482                                               //-- to transfer the remainig bytes -------------
00483 
00484 
00485     do                                                          // wait for the data to be       
00486     {                                                           // transferred from the output  
00487       TempLong.Long = SPIReadRegisterDirect(ECAT_PRAM_RD_CMD,2);// process ram to the read fifo 
00488     }                                                           //    
00489     while (TempLong.Byte[1] != SEC_LONG_NUM_OUT);               //  
00490 
00491     SCS_Low_macro                                               // enable SPI chip select   
00492     
00493     SPI_TransferTx(COMM_SPI_READ);                              // SPI read command
00494     SPI_TransferTx(0x00);                                       // address of the read  
00495     SPI_TransferTxLast(0x00);                                   // fifo MsByte first
00496     
00497     for (i=0; i< (SEC_BYTE_NUM_ROUND_OUT); i++)                 // transfer loop for the remaining 
00498     {                                                           // bytes
00499       BufferOut.Byte[i+64] = SPI_TransferRx(DUMMY_BYTE);        // we transfer the second part of
00500     }                                                           // the buffer, so offset by 64
00501       
00502     SCS_High_macro                                              // SPI chip select disable  
00503   #endif    
00504 }
00505 
00506 
00507 //---- write to the process ram fifo --------------------------------------------------------------
00508 
00509 void EasyCAT::SPIWriteProcRamFifo()    // write BYTE_NUM bytes to the input process ram, through the fifo
00510                                        //    
00511                                        // these are the bytes that we have read from the inputs of our                   
00512                                        // application and that will be sent to the EtherCAT master
00513 {
00514   ULONG TempLong;
00515   unsigned char i;  
00516   
00517   
00518   
00519   #if TOT_BYTE_NUM_IN > 0  
00520   
00521     SPIWriteRegisterDirect (ECAT_PRAM_WR_CMD, PRAM_ABORT);        // abort any possible pending transfer
00522   
00523  
00524     SPIWriteRegisterDirect (ECAT_PRAM_WR_ADDR_LEN, (0x00001200 | (((uint32_t)TOT_BYTE_NUM_IN) << 16)));   
00525                                                                   // the high word is the num of bytes
00526                                                                   // to write 0xTOT_BYTE_NUM_IN----
00527                                                                   // the low word is the input process        
00528                                                                   // ram offset  0x----1200
00529                                                                                                
00530     SPIWriteRegisterDirect (ECAT_PRAM_WR_CMD, 0x80000000);        // start command  
00531   
00532   
00533                                                 //------- one round is enough if we have ----
00534                                                 //------- to transfer up to 64 bytes --------
00535     
00536     do                                                            // check that the fifo has      
00537     {                                                             // enough free space 
00538       TempLong.Long = SPIReadRegisterDirect (ECAT_PRAM_WR_CMD,2); //  
00539     }                                                             //  
00540     while (TempLong.Byte[1] < FST_LONG_NUM_IN);                   //
00541   
00542     SCS_Low_macro                                                 // enable SPI chip select
00543   
00544     SPI_TransferTx(COMM_SPI_WRITE);                               // SPI write command
00545     SPI_TransferTx(0x00);                                         // address of the write fifo 
00546     SPI_TransferTx(0x20);                                         // MsByte first 
00547 
00548     for (i=0; i< (FST_BYTE_NUM_ROUND_IN - 1 ); i++)               // transfer the data
00549     {                                                             //
00550       SPI_TransferTx (BufferIn.Byte[i]);                          // 
00551     }                                                             //
00552                                                                   //  
00553     SPI_TransferTxLast (BufferIn.Byte[i]);                        // one last byte
00554   
00555     SCS_High_macro                                                // disable SPI chip select           
00556   #endif        
00557 
00558   
00559   #if SEC_BYTE_NUM_IN > 0                     //-- if we have to transfer more then 64 bytes --
00560                                               //-- we must do another round -------------------
00561                                               //-- to transfer the remainig bytes -------------
00562 
00563     do                                                          // check that the fifo has     
00564     {                                                           // enough free space       
00565       TempLong.Long = SPIReadRegisterDirect(ECAT_PRAM_WR_CMD,2);// 
00566     }                                                           //  
00567     while (TempLong.Byte[1] < (SEC_LONG_NUM_IN));               //
00568                              
00569     SCS_Low_macro                                               // enable SPI chip select
00570     
00571     SPI_TransferTx(COMM_SPI_WRITE);                             // SPI write command
00572     SPI_TransferTx(0x00);                                       // address of the write fifo 
00573     SPI_TransferTx(0x20);                                       // MsByte first 
00574 
00575     for (i=0; i< (SEC_BYTE_NUM_ROUND_IN - 1); i++)              // transfer loop for the remaining 
00576     {                                                           // bytes
00577       SPI_TransferTx (BufferIn.Byte[i+64]);                     // we transfer the second part of
00578     }                                                           // the buffer, so offset by 64
00579                                                                 //  
00580     SPI_TransferTxLast (BufferIn.Byte[i+64]);                   // one last byte  
00581 
00582     SCS_High_macro                                              // disable SPI chip select    
00583   #endif       
00584 }