Dann muss mein Oszi lügen. Nagut die "Messung" ist nicht optimal
Bild hier
Bei Dir klang das neulich noch nach weniger als 66%
edit: Jaja, ich hab mich verrechnet, sind 75%![]()
Dann muss mein Oszi lügen. Nagut die "Messung" ist nicht optimal
Bild hier
Bei Dir klang das neulich noch nach weniger als 66%
edit: Jaja, ich hab mich verrechnet, sind 75%![]()
Geändert von MisterMou (03.05.2012 um 11:52 Uhr)
Wie so oft sitzt der Teufel im Detail, Deine Messung lässt Sichern und Wiederherstellen der Prozessorregister unberücksichtigt.
Nach meinem Zitat stehen 4MHz von 16MHz zur Verfügung, 4/16tel sind 25%, entsprechend 75% Last.Bei Dir klang das neulich noch nach weniger als 66%
Die Rechnung: (([Durchschnittliche Takte pro ISR] * 12 * 20 * Bildwiederholrate) / Quarzfrequenz)*100 = Prozessorlast in Prozent.
Bei Deiner C-Version hast Du jetzt ungefähr 680 Takte von ISR-Einsprung bis Rückkehr in den unterbrochenen Code.
2 x 3 macht 4 Widdewiddewitt und Drei macht Neune
Ja, ist richtig, hab' Deinen Code nochmal angesehen. Dann ist's nur das Sichern und der ISR-Einsprung was Du in der Messung nicht mitbekommst. Von der Auslösung bis der Port auf Low geht sind's ~38 Takte, von da bis zum erneuten Setzen auf High sinds >= 642 Takte, also eine Verteilung Gesamt 76,5% auf 4,3% und 72,2%, genau 70% kommt da immer noch nicht raus.Aber die Wiederherstellung geschieht doch noch wenn D0 low ist.
Inzwischen gibt´s eine print() für Strings und eine printInt() für Ganzzahlen in dezimalform.
Gibt es da wieder Tricks die ich noch nicht kenne um die printInt() zu beschleunigen?
Eine Fehlertoleranz ist nicht vorgesehen, schade um die Rechenleistung.
Das große Problem wird die Division und der Modulo-Operator sein, denke ich. Auf jeden Fall wird ein riesieger ASM-Code erstellt.
Code:void printInt(unsigned char xPos, unsigned char yPos, unsigned char length, int num)//32767 -> +32767 { unsigned char temp; unsigned int i=0; xPos+=length-1; if(num<0) { num--; //Zweierkompliment num=~num; do { num-=(temp=num%10); //letzte Stelle extrahieren num/=10; //num>>1 dezimal text[yPos][xPos-i++]=temp+0x30; //um auf passenden char zu kommen if(i==length-1)break; //damit Platz fürs Minus ist }while(num); text[yPos][xPos-i++]=0x2D; //Minuszeichen an erste stelle }else { do { num-=(temp=num%10); num/=10; text[yPos][xPos-i++]=temp+0x30; if(i==length)break; }while(num); } while(i<length) text[yPos][xPos-i++]=0x20; //Rest mit Leerzeichen auffüllen }
Der "Trick" nennt sich "effektiverer Code"
Warum glaubst Du besser als itoa() zu sein ? Noch dazu Du umständlich programmierst. Hast ja bemerkt dass Divisionen "teuer" sind, für Multiplikationen gibt's in manchen AVR's Unterstützung durch den MUL Opcode, Divisionen müssen immer per Code gemacht werden.
Hier führst Du gleich 2 Divisionen durch, wovon Du eine hättest sparen können.
Ein Modulo 10 enthält die gleiche Division wie num/=10, die Multiplikation und Differenzbildung als Modulo zu Fuß wär' wahrscheinlich billiger gewesen.Code:num-=num%10; num/=10;
Dein Code benötigt so ganze 2570 Takte mit printInt(0,0,6,29999).
Braucht noch 1370.Code:void printInt(unsigned char xPos, unsigned char yPos, unsigned char length, int num){ char buff[7]; unsigned char slen; unsigned char spccnt = 0; itoa(num, buff, 10); slen = strlen(buff); if (slen < length) { spccnt = length - slen; memset((void*)&text[yPos][xPos], ' ', spccnt); xPos += spccnt; length -= spccnt; } memcpy((void*)&text[yPos][xPos], (void*)&buff, length); } printInt(0,0,6,29999);
Der noch 540.Code:const int idiv[6] PROGMEM = {0, 1, 10, 100, 1000, 10000}; void printInt(unsigned char xPos, unsigned char yPos, unsigned char length, int num){ unsigned int idx = 5; char lz = 1; char prlz; char chval; char isminus = 0; unsigned char *txtptr = &text[yPos][xPos]; if (num < 0) { num = 0 - num; length--; isminus = 1; } else *txtptr++ = ' '; while ((idx) && (length--)) { chval = '0'; prlz = lz; while (num >= pgm_read_word(&(idiv[idx]))) { num -= pgm_read_word(&(idiv[idx])); chval++; lz = 0; } if ((prlz != lz) && (isminus)) { prlz = lz; *txtptr++ = '-'; } idx--; if ((lz) && (idx)) chval = ' '; *txtptr++ = chval; } } printInt(0,0,6,29999);
Das einzig Lästige dabei ist, durch das Alignement des Fonts kommt const int idiv[6] PROGMEM auf $D00 zu liegen, der Compiler aligned für den darauffolgenden Code nochmals und verhaut damit knapp 240 Bytes Flash, aus der .map-Datei:
Code:0x00000d00 idiv 0x00000e00 . = ALIGN (0x2)
Weil ich itoa() zu bis eben noch nicht kannte
Kam mir zu speziell vor,als das es dafür eine Funktion gibt.
Danke, dass Du so geduldig mit mir bist
Ich kämpfe zur Zeit mit inhomogenen Differenzialgleichungen 2. Grades, sobald das verstanden wurde, werde ich mich an Deinen Code setzen.
Nochmal danke für die Arbeit.
Lesezeichen