|
|
View previous topic :: View next topic |
Author |
Message |
The Puma
Joined: 23 Apr 2004 Posts: 227 Location: The Netherlands
|
How can i make this routine smaller and efficientely |
Posted: Sun Feb 12, 2006 6:49 am |
|
|
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
|
|
Posted: Sun Feb 12, 2006 7:51 am |
|
|
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
|
|
Posted: Sun Feb 12, 2006 9:21 am |
|
|
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
|
|
Posted: Sun Feb 12, 2006 9:55 am |
|
|
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
|
|
Posted: Sun Feb 12, 2006 10:04 am |
|
|
Thanks i will try both codes |
|
|
Falgellus
Joined: 12 Feb 2006 Posts: 8
|
more efficient |
Posted: Mon Feb 13, 2006 1:56 am |
|
|
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
|
|
Posted: Mon Feb 13, 2006 3:21 am |
|
|
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
|
|
Posted: Thu Feb 16, 2006 3:01 pm |
|
|
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();
} |
|
|
|
|
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
|