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

Calculations are too long,how to reduce it
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Thu Mar 03, 2011 12:24 am     Reply with quote

Actually memory is consuming here I think.

After total_kg_i=total_kg_i -1;
I am breaking total_kg_i into seperate kg's like
Code:

sprintf(buffer_a,"%lu",total_kg_i);
 if(total_kg_i==0)
 {
  kg_1=0;kg_2=0;kg_3=0;kg_4=0;kg_5=0;kg_6=0;kg_7=0;kg_8=0;
 }
 else if(total_kg_i>=1 && total_kg_i<10)
 {                 
  kg_1=ToInt(buffer_a[0]);kg_2=0;kg_3=0;kg_4=0;
  kg_5=0;kg_6=0;kg_7=0;kg_8=0;
 }                                                 
 else if(total_kg_i>=10 && total_kg_i<100)   
 {                                       
  kg_1=ToInt(buffer_a[1]);kg_2=ToInt(buffer_a[0]);kg_3=0;kg_4=0;
  kg_5=0;kg_6=0;kg_7=0;kg_8=0;
 }
 else if(total_kg_i>=100 && total_kg_i<1000)   
 {                                       
  kg_1=ToInt(buffer_a[2]);kg_2=ToInt(buffer_a[1]);kg_3=ToInt(buffer_a[0]);kg_4=0;
  kg_5=0;kg_6=0;kg_7=0;kg_8=0;
 }
 else if(total_kg_i>=1000 && total_kg_i<10000)   
 {                                       
  kg_1=ToInt(buffer_a[3]);kg_2=ToInt(buffer_a[2]);kg_3=ToInt(buffer_a[1]);
  kg_4=ToInt(buffer_a[0]);kg_5=0;kg_6=0;kg_7=0;kg_8=0;
 }
 else if(total_kg_i>=10000 && total_kg_i<100000)   
 {                                         
  kg_1=ToInt(buffer_a[4]);kg_2=ToInt(buffer_a[3]);kg_3=ToInt(buffer_a[2]);
  kg_4=ToInt(buffer_a[1]);kg_5=ToInt(buffer_a[0]);kg_6=0;kg_7=0;kg_8=0;
 }
 else if(total_kg_i>=100000 && total_kg_i<1000000)   
 {                                       
  kg_1=ToInt(buffer_a[5]);kg_2=ToInt(buffer_a[4]);kg_3=ToInt(buffer_a[3]);
  kg_4=ToInt(buffer_a[2]);kg_5=ToInt(buffer_a[1]);kg_6=ToInt(buffer_a[0]);
  kg_7=0;kg_8=0;
 }
 else if(total_kg_i>=1000000 && total_kg_i<10000000)
 {
  kg_1=ToInt(buffer_a[6]);kg_2=ToInt(buffer_a[5]);kg_3=ToInt(buffer_a[4]);
  kg_4=ToInt(buffer_a[3]);kg_5=ToInt(buffer_a[2]);kg_6=ToInt(buffer_a[1]);
  kg_7=ToInt(buffer_a[0]);kg_8=0;
 }
 else if(total_kg_i>=10000000 && total_kg_i<100000000)
 {
  kg_1=ToInt(buffer_a[7]);kg_2=ToInt(buffer_a[6]);kg_3=ToInt(buffer_a[5]);
  kg_4=ToInt(buffer_a[4]);kg_5=ToInt(buffer_a[3]);kg_6=ToInt(buffer_a[2]);
  kg_7=ToInt(buffer_a[1]);kg_8=ToInt(buffer_a[0]);
 }

Can I get rid of this code into simple routine?
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Thu Mar 03, 2011 3:18 am     Reply with quote

You may be able to reduce this but it depends.
We have not got the full picture here and it looks like you are trying to crack an egg with a hammer.

it looks like you are using kg_1, kg_2 etc to ooutput you left justified value!
I also assume you are using putc(c) for 6 of the chars and output_(port) for the other 2.

I don't think there is any need for this routine at all. You have the value in buffer_a why move it to int8's ?

Also how is your buffer defined?

Show us your display routine.

how big is the full program?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Mar 03, 2011 3:32 am     Reply with quote

Whenever I see variables like kg_1 to kg_8 my fingers start to itch. This is a perfect example of code to be replaced by a function as it will be smaller, better to understand and hence less error prone.

As Wayne points out, it looks like you are trying to create a left justified output. You can create that with a simple extra parameter to the sprintf command, see the manual for details.
Ttelmah



Joined: 11 Mar 2010
Posts: 19732

View user's profile Send private message

PostPosted: Thu Mar 03, 2011 4:11 am     Reply with quote

Seriously, go back to small counters, keeping the digits separate. It is important to understand that an 'increment', or a 'test', in machine terms are single instructions. Something like a multiply is dozens of instructions, while a division can be thousands. Some things that look easy to us, can involve huge amounts of machine time, while other solutions that almost look 'silly' to us, are really fast.
Just handle your digits as needed:
Code:

#define INC_DIGIT(x) (((x=(x==9)?(x=0):++x)),x==0)

int kg00001=0;
int kg00010=0;
int kg00100=0;
int kg01000=0;
int kg10000=0;

     if (INC_DIGIT(kg00001))
         if (INC_DIGIT(kg00010))
            if (INC_DIGIT(kg00100))
               if (INC_DIGIT(kg01000))
                  if (INC_DIGIT(kg10000)) ;

This shows five digits being handled, and you could add another digit, or overflow handling at the end.
The key is that the later code only gets called when there _is_ a carry. So for 9 out of ten digits, it takes just 15 machine cycles. In the tenth call, this almost doubles, then on the hundredth rises again, but even handling a wrap on all five digits, takes less than 75 machine cycles.
Syntactically, the macro definition is 'wrong', in standard C terms, but for some reason CCS needs the odd double assignment to actually perform the required result, and the resulting assembler is efficient:
Code:

27:                      if (INC_DIGIT(kg00001))
  005D    0020     MOVLB 0                 //bank select
  005E    0820     MOVF 0x20, W         //Load the value
  005F    3C09     SUBLW 0x9              //test if nine 
  0060    1D03     BTFSS 0x3, 0x2
  0061    2865     GOTO 0x65              //here if 0 to 8
  0062    01A0     CLRF 0x20               //Here if nine
  0063    0820     MOVF 0x20, W
  0064    2867     GOTO 0x67              //Clear and exit
  0065    0AA0     INCF 0x20, F           //Increment
  0066    0820     MOVF 0x20, W
  0067    3A00     XORLW 0                 //Test for zero and exit
  0068    1D03     BTFSS 0x3, 0x2
  0069    289A     GOTO 0x9a


Best Wishes
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Thu Mar 03, 2011 4:24 am     Reply with quote

Something like this should do what you want.
I have not tested it. I don't know if it reduces your code.
It may be possible to improve on this based on the rest of your code.
Someone here may have a better solution.

Code:

int32 val;
int32 d;
int8 pos;
int8 c;
int1 outFlag = false;

val = total_kg_i;
d = 100000000;
pos = 0;

do {
  c = val / d;  // Get the (d) value.
  val = val - (c * d);  // Adjust val
  d = d / 10;  // Move d  on to the next d val

  if (c > 0)
    outFlag = true;
  if (outFlag)
  {
    if (pos < 6)
      putc(c + '0'); // LCD
    else if (pos == 6)
       output_a(c + '0');  // 7 Seg 1
    else
       output_b(c + '0');  // 7 Seg 2

    pos++;
  }
} while ((pos < 8) && (d > 1));

while (pos < 8)
{
  // Clean up by clearing the rest of the display.
    if (pos < 6)
      putc(0);  // LCD
    else if (pos == 6)
       output_a(0);  // 7 Seg 1
    else
       output_b(0);  // 7 Seg 2
  pos++;
}



[ EDIT ]
LOL, As sugested above, single 8 bit vars is proberbly your best way to go for speed and code size.
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Thu Mar 03, 2011 5:15 am     Reply with quote

Thanks for your support again.
I am going to use two variables.one for total kg and one for sending pulse.
total kg should be int32.
Tell me how i read and write int32 in/form eeprom.

for storing and reading int16 bit data i use the following macro
Code:

#define mReadWord(addr)  make16(read_eeprom(addr+1),read_eeprom(addr)) //macros for read and write on                     
#define mWriteWord(addr,data) {write_eeprom(addr,make8(data,0));write_eeprom((addr+1),make8(data,1));}//eeprom 16 bit data


can i add the remainng address in the above macro to save the data like
Code:

#define mReadWord(addr)  make32(read_eeprom(addr+4),read_eeprom(addr+2),read_eeprom(addr+1),read_eeprom(addr)) //macros for read and write on                     
#define mWriteWord(addr,data) {write_eeprom(addr,make8(data,0));write_eeprom((addr+1),make8(data,1));write_eeprom((addr+2),make8(data,2));write_eeprom((addr+4),make8(data,4));}//eeprom 16 bit data
Ttelmah



Joined: 11 Mar 2010
Posts: 19732

View user's profile Send private message

PostPosted: Thu Mar 03, 2011 5:40 am     Reply with quote

As a further comment on what I posted, understand that if you want a pulse every 100 counts for example, you can do it as:
Code:

     if (INC_DIGIT(kg00001))
         if (INC_DIGIT(kg00010)) {
            //pulse here will be given every 100 counts
            if (INC_DIGIT(kg00100))
               if (INC_DIGIT(kg01000))
                  if (INC_DIGIT(kg10000)) ;
           }

With this the digits are already separate, kept and handled as decimal digits, instead of converting backwards and forwards to binary, with divisions of multiplications, and lots of time/space.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
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