CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Int16 array copy with byte swaping

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Int16 array copy with byte swaping
PostPosted: Sat May 19, 2007 12:12 pm     Reply with quote

I'm looking for a way to copy a large array of Int16 data to another array while swapping the byte order or the Int16 elements of the array. This is part of several functions I am trying to optimize in a MODBUS driver. I have been using arrays for indirect addressing while incrementing an array index. I think this could be done more effectively using pointers and simply incrementing the pointers.

This is an example of code I have been using.
Code:
/***********************************************************
*    COMM1 Function 3                                      *
***********************************************************/
/* evaluate for optimizations */
Void COMM1_Function_3(Void)
{  Const Int16 Max_Reg_Count=(COMM1_Buff_Size-9)/2;         // Limit on count based on buffer size
   COMM1.Start=Make16(COMM1_Buffer[2],COMM1_Buffer[3]);     // Little indian conversion
   COMM1.Count=Make16(COMM1_Buffer[4],COMM1_Buffer[5]);     // Little indian conversion
   if(COMM1.Count>Max_Reg_Count)                            // Test count of registers aginst buffer size
      COMM1.End=REG_Map_Size+1;                             // Set data range error condition
   else
      COMM1.End=COMM1.Start+COMM1.Count;                    // Ending register address
   if(COMM1.CRClo_Index!=6)                                 // Check for a packet formating error
      COMM1.End=REG_Map_Size+1;                             // Set data range error condition
   if(COMM1.End<=REG_Map_Size)                              // Check aginst size of reg map
   {  COMM1.Index=3;                                        // Set the index to the first byte
      COMM1_Buffer[2]=COMM1.Count*2;                        // Data Byte Count


      for(COMM1.y=COMM1.start;COMM1.y<COMM1.End;COMM1.y++)
      {  COMM1.x=(COMM1.y*2)+1;
         COMM1_Buffer[COMM1.Index] = REG_Map[COMM1.x];
         COMM1.Index++;
         --COMM1.x;
         COMM1_Buffer[COMM1.Index] = REG_Map[COMM1.x];
         COMM1.Index++;
      }


      COMM1.CRChi_Index=COMM1.Index+1;
   }
   else
   {  bit_set(COMM1_Buffer[1],7);                           // Report_Exception
      if(COMM1.CRClo_Index==6)                              // Valid packet size
         COMM1_Buffer[2]=Illegal_Data_Address;              // Data range exception type
      else
         COMM1_Buffer[2]=Illegal_Data_Value;                // Packet formating exception type
      COMM1.CRChi_Index=4;                                  // Index CRChi
   }
}


I think the code within the for loop in the middle can be greatly improved.
future



Joined: 14 May 2004
Posts: 330

View user's profile Send private message

PostPosted: Sat May 19, 2007 1:28 pm     Reply with quote

I would declare pointers to COMM1_Buffer[] and REG_Map[], load them in FSR0 and FSR1 and use POSTINC/PREINC/INDF.

The compiler does a poor job using only FSR0 for all array access.

I could not understand the loop and what it does, but I think the idea is valid.
libor



Joined: 14 Dec 2004
Posts: 288
Location: Hungary

View user's profile Send private message

PostPosted: Sun May 20, 2007 6:33 pm     Reply with quote

Code:
#byte POSTINC0=0xFEE
#byte POSTINC1=0xFE6
#byte FSR0H=0xFEA
#byte FSR0L=0xFE9
#byte FSR1H=0xFE2
#byte FSR1L=0xFE1

//this function copies the memory from src to dest swapping byte order
void memcpy_swap(int8 *dest, int8 *src, int8 n)  {   // n number of words to copy
int16 temp;
 #asm
  movff &dest+1, FSR1H
  movff dest, FSR1L
  movff &src+1, FSR0H
  movff src, FSR0L
 loop:
  movff POSTINC0, temp
  movff POSTINC0, &temp+1
  movff &temp+1, POSTINC1
  movff temp, POSTINC1
  decfsz n
  goto loop
 #endasm
}
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Sun May 20, 2007 11:10 pm     Reply with quote

This is what I ended up with. I think it is as tightly optimized as it's going to be but I think it could be more readable. I'm not sure that can be fixed. I think I was unclear in what I needed to do but your replies got me going in the right direction. This code copies Int16 values from one array to another while reversing the byte order of the Int16 elements. Change Int16 element values from big Indian to little Indian.
Code:
/***********************************************************
*    COMM1 Function 3                                      *
***********************************************************/
Void COMM1_Function_3(Void)
{  #Byte Target_Inc = 0x0FE6                                // Increments FSR1 after use
   #byte Source_Inc = 0x0FDE                                // Increments FSR2 after use
   #byte Source_Dec = 0x0FDD                                // Decrements FSR2 after use
   Int16 Target_Address;
   #locate Target_Address = 0x0FE1                          // FSR1 address
   Int16 Source_Address;
   #locate Source_Address = 0x0FD9                          // FSR2 address

   Const Int16 Max_Reg_Count=(COMM1_Buff_Size-9)/2;         // Limit on count based on buffer size
   COMM1.Start=Make16(COMM1_Buffer[2],COMM1_Buffer[3]);     // Little indian conversion
   COMM1.Count=Make16(COMM1_Buffer[4],COMM1_Buffer[5]);     // Little indian conversion
   if(COMM1.Count>Max_Reg_Count)                            // Test count of registers aginst buffer size
      COMM1.End=REG_Map_Size+1;                             // Set data range error condition
   else
      COMM1.End=COMM1.Start+COMM1.Count;                    // Ending register address
   if(COMM1.CRClo_Index!=6)                                 // Check for a packet formating error
      COMM1.End=REG_Map_Size+1;                             // Set data range error condition
   if(COMM1.End<=REG_Map_Size)                              // Check aginst size of reg map
   {  COMM1_Buffer[2]=COMM1.Count*2;                        // Data Byte Count
      Target_Address = &COMM1_Buffer[3];
      Source_Address = (COMM1.Start*2) + &REG_Map[1];
      While(COMM1.Count)                                    // Number of Int16 to be copied
      {  Target_Inc = Source_Dec;                           // Low byte copied
         Target_Inc = Source_Inc;                           // High byte copied
         COMM1.X = Source_Inc;                              // Address next byte to be copied
         COMM1.X = Source_Inc;                              // Address next byte to be copied
         --COMM1.Count;
      }
      COMM1.CRChi_Index=COMM1_Buffer[2];
      COMM1.CRChi_Index+=5;
   }
   else
   {  bit_set(COMM1_Buffer[1],7);                           // Report_Exception
      if(COMM1.CRClo_Index==6)                              // Valid packet size
         COMM1_Buffer[2]=Illegal_Data_Address;              // Data range exception type
      else
         COMM1_Buffer[2]=Illegal_Data_Value;                // Packet formating exception type
      COMM1.CRChi_Index=4;                                  // Index CRChi
   }
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group