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 support@ccsinfo.com

How can i make this routine smaller and efficientely

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



Joined: 23 Apr 2004
Posts: 227
Location: The Netherlands

View user's profile Send private message

How can i make this routine smaller and efficientely
PostPosted: Sun Feb 12, 2006 6:49 am     Reply with quote

void max7221_write_value( int32 num ) {
int8 i;

led_data[0]=(num%10);
led_data[1]=(num%100)/10;
led_data[2]=(num%1000)/100;
led_data[3]=(num%10000)/1000;
led_data[4]=(num%100000)/10000;
led_data[5]=(num%1000000)/100000;
led_data[6]=(num%10000000)/1000000;
led_data[7]=(num%100000000)/10000000;

// Do leading zero blanking
if (num<1) led_data[0] = SEGMENT_CHAR_BLANK;
if (num<10) led_data[1] = SEGMENT_CHAR_BLANK;
if (num<100) led_data[2] = SEGMENT_CHAR_BLANK;
if (num<1000) led_data[3] = SEGMENT_CHAR_BLANK;
if (num<10000) led_data[4] = SEGMENT_CHAR_BLANK;
if (num<100000) led_data[5] = SEGMENT_CHAR_BLANK;
if (num<1000000) led_data[6] = SEGMENT_CHAR_BLANK;
if (num<10000000) led_data[7] = SEGMENT_CHAR_BLANK;

for(i=DIGIT_0;i<=DIGIT_7;i++)
max7221_write(i,led_data[i-1]);
}
Ttelmah
Guest







PostPosted: Sun Feb 12, 2006 7:51 am     Reply with quote

Unfortunately, you seem to want the data in 'reverse order'. Otherwise, make LED_DATA one character larger, and use:

sprintf(led_data,"%8LU",num);

Best Wishes
Falgellus



Joined: 12 Feb 2006
Posts: 8

View user's profile Send private message

PostPosted: Sun Feb 12, 2006 9:21 am     Reply with quote

Something like that:

int32 dv=10;

for (i=0; i<8 ; i++ )
{
led_data[i]=(num%(dv))/(dv/10);
if (num<(dv/10)) led_data[i] = SEGMENT_CHAR_BLANK;
dv *= 10;
}


Caution: I have not tested it so make all tests.

Bye

Paolo
Ttemah
Guest







PostPosted: Sun Feb 12, 2006 9:55 am     Reply with quote

Also, remember that the value%10, is really developed by performing value-((value/10*10), so you can save work by seperating this yourself.
Also if you run the result 'forward', the division is only /10 at each stage.
You should also remember that only seven such divisions are needed, and then the remainder is the last digit.
You seem to also blank the bottom digit. Normally this would not be done.
Code:

int32 temp;
int1 leading=true;
signed int8 i;

for (i=0; i<7 ; i++ ) {
   temp=num/10;
   led_data[i]=num-(temp*10);
   num=temp;
}
led_data[7]=num;
//Don't blank the bottom digit
for (i=7;i>0;i--) {
   if (leading && led_data[i]==0)
       led_data[i] = SEGMENT_CHAR_BLANK;
   else
       leading=false;       
}


Best Wishes
The Puma



Joined: 23 Apr 2004
Posts: 227
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Feb 12, 2006 10:04 am     Reply with quote

Thanks i will try both codes
Falgellus



Joined: 12 Feb 2006
Posts: 8

View user's profile Send private message

more efficient
PostPosted: Mon Feb 13, 2006 1:56 am     Reply with quote

int32 dv=10;

for (i=0; i<8 ; i++ )
{
if (num<(dv/10))
led_data[i] = SEGMENT_CHAR_BLANK;
else
led_data[i]=(num%(dv))/(dv/10);

dv *= 10;
}


Caution: I have not tested it so make all tests.

Bye

Paolo
Ttelmah
Guest







PostPosted: Mon Feb 13, 2006 3:21 am     Reply with quote

I don't think this is 'more efficient'. The problem is that division, is a very slow operation (the slowest of the basic arithmetic operations). The test now involves a division, as does the sum itself. Basic 'tests' are quick (perhaps ten machine cycles for an int32), but divisions, can easily involve 1000 machine cycles. The '%' operation, actually involves the sum I have already outlined, and is even worse, involving a division, multiplication, and subtraction. So though this code is a lot smaller, in terms of machine operations , it will be worse.
This is why, though my code could do with a lot of tweaking I'm sure, one of the key things was to keep the divisions to a minimum (just one per loop).

Best Wishes
The Puma



Joined: 23 Apr 2004
Posts: 227
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Feb 16, 2006 3:01 pm     Reply with quote

I will use the code above for driving a SAA1064

My question is now how to implement this segment table in the below code
It displays now only segments, but not correct numbers (0,1,2,3,4,5,6,7,8,9)

// Segment table (In hex: d.p.=80,g=40,f=20,e=10,d=08,c=04,b=02,a=01)
byte const seg_table[10] = {
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F }; // 0,1,2,3,4,5,6,7,8,9

void saa1064_write_num(int8 addr,int8 control,int16 num) {
int1 leading=true;
int8 led_data[4];
int8 j;
int16 temp16;

for(j=0;j<3;j++) {
temp16=num/10;
led_data[j]=num-(temp16*10);
num=temp16;
}
led_data[3]=num;

for(j=3;j>0;j--) {
if (leading && led_data[j]==0)
led_data[j]=SEGMENT_CHAR_BLANK;
else
leading=false;
}

i2c_start();
i2c_write(addr);
i2c_write(SAA1064_REG_CONTROL);
i2c_write(control);

for(j=0;j<=3;j++)
i2c_write(led_data[j]);

i2c_stop();
}
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