Tut mir langsam echt leid, dass ich immer nerven muss, aber ich denke ein letztes Mal muss es noch sein. Ich muss Bei einer Division den Rest festellen, ich möchte also, falls ich 128 durch 10 teile, eine Variabel mit 12 und eine mit dem Rest 8 bekommen. Allerdings kann ich die Variante, immer 10 von x abzuziehen, bis x kleiner als 10 ist nicht verwenden. Und zwar weil das ganze schneller gehen muss, und auch mit höheren Zahlen. Eventuell funktioniert es ja auch ohne die Division, sondern mit Operatoren, aber obwohl ich prinzipiell weiss, was die Operatoren machen, kann ich mir nicht vorstellen wie ich das anstellen könnte. Diejenigen die schonmal ein Fat in C programmiert haben, wissen warscheinlich wo mein Problem liegt. Ich hab den Cluster, und muss den nächsten finden, dazu muss ich in der Fat tabelle nachschauen. Doch ich muss ja irgendwoher wissen, in welchem Sektor der gesuchte Eintrag denn ist und an welcher Position im Sektor. Falls man eine Division immer dazu zwingen könnte abzurunden, wäre das vielleicht auch ein Ansatz, aber ich hab keine Ahnung ob das überhaupt gehen könnte. Nik
Einfach: a = 128; b = a / 10; c = a % 10; Mir ist allerdings nicht klar, wozu Du bei einer FAT-Implementierung durch 10 teilen musst, aber das wirst Du Dir schon irgendwie erklären können.
Nein die 10 war nur ein Beispiel um nicht gleich die grösseren Zahlen ausgraben zu müssen ;) Allerdings enthält b nun 13, da es aufgerundet wurde....der Rest stimmt aber wieder...Kann man gcc irgendwie dazu zwingen abzurunden?
Autsch, sehr peinlich, 0C ist natürlich 12, nicht 13...funktioniert perfekt so, danke :)
Btw., die Division ist eine recht kostspielige Angelegenheit (die teuerste der vier Grundrechenarten). Prinzipbedingt fällt bei den Divisionsalgorithmen der Rest der Division gleich immer nebenbei mit ab. Von daher gibt es in C einen Funktionsaufruf, der in einem Zug sowohl die Division als auch den Modulus gleichzeitig zurückgibt. Die Funktion heißt div() und ist einerseits in jeder C-Bibel dokumentiert, andererseits natürlich auch in der avr-libc-Doku.
>Die Funktion heißt div() und ist einerseits in jeder C-Bibel >dokumentiert, andererseits natürlich auch in der avr-libc-Doku. allerdings habe ich hier erst kürzlich gelesen dass die mathematischen Funktionen der libc ziemlich viel platz verwenden...? Aber auch wenn die Division nun ein bisschen mehr Rechenzeit in Anspruch nimmt, das erste mp3 File ab Fat32 läuft, aktuell ist es ein File mit 128kbit/s. Ich werde mal noch andere Testen ( 192 und 320 kbits). Interessant wäre sicher auch, mit einem Timerinterrupt die genaue Anzahl bytes/sek Lesedurchsatz zu errechnen...
Das hat nun nicht mehr so viel mit meiner Ursprünglichen Frage zu tun, aber Ich selbst Dateien mit 380kbits noch korrekt abspielen. Und falls jemand Fat32 benutzen möchte, sich aber nicht mit der Microsoft Doku abquälen möchte, dem kann ich diese Seite wirklich empfehlen: http://www.pjrc.com/tech/8051/ide/fat32.html Der einzige kleine Nachteil, sie ist auf Englisch.
> allerdings habe ich hier erst kürzlich gelesen dass die > mathematischen Funktionen der libc ziemlich viel platz verwenden...? Ich habe kürzlich gelesen, die Erde sei eine Scheibe... :-) Erstens hat das mit ``mathematischer Funktion'' nicht wirklich was am Hut, unter solchen versteht man gemeinhin eher die numerischen Funktionen, also alles, was man in <math.h> beschrieben findet. Zweitens ist hier ein wichtiger Unterschied: div() macht weiter nichts, als die ganz normale Divisionsimplementierung aufzurufen, also dieselbe, die du auch mit den Operatoren / und % aufrufst -- es gibt dir eben nur beide Resultate gleichzeitig zurück (in Form einer struct). Dein Code wird davon also eher kleiner (und schneller sowieso).
Hallo Ihr, Ich persönlich fand das Microsoft-paper zum Thema FAT eigentlich sehr erhellend. Da sind doch sogar Code-Beispiele drin. Ich habe mit dem Whitepaper als alleinige Referenz meinen FAT16/32-Code mit Schreiben und Lesen von Dateien und Verzeichnissen implementiert. &Nik: Die meisten Divisionen und Modulo-Operationen bei FAT-Implementationen haben folgende Eigenschaften : 1. Sie sind vorab bekannt, wenn man eine bestimmte Festplatte verwendet. 2. Sie sind 2er-Potenzen und da ist es wesentlich einfacher zu dividieren und die Modulo-Operation zu implementieren. Ich habe meinen Code so organisiert, dass man beliebige Festplatten anschließen kann und die FAT wird gefunden (OK, OK natürlich nur die erste FAT auf der Platte). Falls man aber zum Programmerstellungszeitpunkt schon weiß, welche Eckdaten die FAT hat, dann kann man einen Teil davon bereits vor dem kompilieren spezifizieren und dann wertvolle Zeit bei der Propgrammausführung und außerdem noch Speicher sparen. Ich würde Euch gerne zum jetzigen Zeitpunkt meine FAT-Routinen vorstellen, sie sind aber noch ein wenig unsortiert und enthalten noch teilweise kleinere Formatierungsschwächen (Funktion ist einwandfrei). Ich werde im Laufe des Monats vielleicht noch dazu kommen, die FAT16/32-Routinen hier mit einer Dokumentation vorzustellen. Kommt darauf an, wie viel Zeit ich finde. MfG, Daniel.
"2. Sie sind 2er-Potenzen" Und ich hatte mir schon den Kopf zerbrochen, wo zum Teufel denn in der FAT durch 10 dividiert werden muß. D.h. die ganze Frage ist falsch. Es geht garnicht ums Dividieren sondern nur ums rechts schieben und UNDieren. Und beides ist einsdreifix in wenigen Zyklen erledigt. Peter
Das selbe ist es etwa bei mir, ich habe ein Funktion die erstmal die erste Partition auf fat32 überprüft, dann die Wichtigsten Daten aus dem Volume boot record ausliest. (clustergrösse, etc.) Die wichtigsten paar bytes speichert die Funktion dann in einige globale Variabeln, damit auch andere Funktionen einfach darauf zugreifen können. Dann gibts noch eine einfache Funktion die den Inhalt des Root Directorys ausgibt, eine die eine Datei von einem bestimmten Cluster beginnt abzuspielen und eine die den nächsten Cluster aus der Fat ausliest. Insgesamt ist das ganze wie bei dir noch ziemlichunsortiert(hab die fat unterstützung jetzt in 3 Tagen geschrieben, alles ist noch ziemlich durcheinander). Das File für ata und Fat ist etwa 500 Zeilen lang und benötigt warscheinlich etwa 2 bis 3 kb flash. Die Routinen sind zwar nun auf das Auslesen wie es für einen mp3 player üblich ist optimiert(liest die Datei einfach fortlaufend). Nun habe ich noch einen Monat Schule bis zu den Ferien, aber dann kann ich die Sourcen vielleicht auch mal ordnen und Online stellen. Evtl. werde ich den mp3 Player auch auf auf einen mega8 portieren, der Speicher scheint nämlich locker genug zu sein...und da der mega8 sogar noch 512byte mehr ram hat als der mega8515 liegen vielleicht noch einige Sachen mehr drinn, wie ein buffer für einen ganzen Sektor...was das ganze noch um einiges schneller machen würde. Falls das dann fertig ist, werde ich es vielleicht als Projektins Wiki stellen.
>D.h. die ganze Frage ist falsch. >Es geht garnicht ums Dividieren sondern nur ums rechts schieben und >UNDieren. Und beides ist einsdreifix in wenigen Zyklen erledigt. Im prinzip ist sie nicht falsch, denn so funktionierts auch, vom "rechts schieben und UNDieren" hab ich leider noch nicht allzuviel Ahnung...
@Nik,
falsch ist Deine Lösung nicht, aber nicht optimal. Du schriebst ganz am
Anfang:
> Und zwar weil das ganze schneller gehen muss
Und das geht mit den Schiebeoperationen definitiv schneller. Beispiel
mit Teiler durch 128:
rest = wert & 127;
ergebnis = wert >> 7;
Volkmar
@Nik "vom "rechts schieben und UNDieren" hab ich leider noch nicht allzuviel Ahnung..." Nimm eine Dezimalzahl, teile sie durch 10 bzw. schiebe sie eine Stelle nach recht (letztes Digit fällt weg) und nun vergleiche beide Ergebnisse miteinander. Was könnte nun passieren, wenn man eine Binärzahl durch 2 teilt bzw. eine Stelle nach recht schiebt ? In meinen Augen gehören Kenntnisse über die interne Darstellung von Ganzzahlen im MC/PC und Grundrechenarten mit Binärzahlen zum absoluten Basiswissen eines jeden Programmierers. Sonst kommt noch sowas raus wie neulich, als jemand allen Ernstes mit sage und schreibe 10240 IF-Abfragen einen 10Bit-Binärwert nach dezimal wandeln wollte !!! http://www.mikrocontroller.net/forum/read-1-196647.html#new Auch sollte man wissen, wann und warum z.B. 65535 + 10 = 9 rauskommt. Peter
Hallo Peter, da muss ich Dir zustimmen - mir kämen 10240 (!) if-Anweisungen schon recht viel Aufwand vor ;-). Aber natürlich hast Du sonst auch ernsthaft recht. MfG, Daniel
> In meinen Augen gehören Kenntnisse über die interne Darstellung von > Ganzzahlen im MC/PC und Grundrechenarten mit Binärzahlen zum absoluten > Basiswissen eines jeden Programmierers. Nik hat doch nirgends behauptet, dass er ein Programmierer ist. Das du das alles von Geburt an kannst, hat sich ja hier mitlerweile rumgesprochen.
> Nik hat doch nirgends behauptet, dass er ein Programmierer ist. Das > du das alles von Geburt an kannst, hat sich ja hier mitlerweile > rumgesprochen. Polemischer Unsinn - zumal Peter immer versucht (und es ihm gelingt) neutral zu bleiben und keinem auf den Schlips zu treten. Ich bin sicher Nik würde ihm auch recht geben. ----, (QuadDash).
>In meinen Augen gehören Kenntnisse über die interne >Darstellung von Ganzzahlen im MC/PC und >Grundrechenarten mit Binärzahlen zum absoluten Basiswissen >eines jeden Programmierers. Grundrechenarten mit Binär Zahlen sind auch nicht mein Problem, Sachen die ich nicht verstehe sind Masken etc mit &, | usw. Auch wenn man das in Visual Basic oder Bascom verwenden kann, ich habs bis jetzt schlichtwegs nicht gebraucht, da ich noch nie Programme in die Richtung programmiert habe, auf dem Pc waren es hauptsächlich Netzwerk Programme wie zum Beispiel ein http server. Nun in Visualbasic gibts auch einen Befehl um z.b. den Rest aus zurechnen, und zwar schlicht und eifach "mod" wenn ich mich recht errinere. Dazu braucht man dann nicht gerade Kentnisse wie man die bits hin und her schieben kann... Nun habe ich eigentlich als erstes grösseres C programm, diesen Mp3 Player programmiert, und ja, als Programmierer bezeichne ich mich dennoch, das einzige was ich nicht selbst gemacht habe sind die Funktionen für den Uart und eben die Sachen, die ich hier nachfragen musste. >65535 + 10 = 9 Warum dies nun ergibt ist mir auch klar, wäre die Variabel 32 bit lang wäre das Ergebniss wohl viel eher 65545 ;-). Da die Variabel aber anscheinend 16 bit lang unsigned ist, gibt das ganze eben den übertrag nicht an das nächste bit weiter, sondern wieder an das erste, welches folglich "überläuft" und wieder bei Null anfängt. Ich denke das das so einigermassen korrekt war, da ich die Innereien von addierwerken bis jetzt noch längst nicht in der Schule hatte(bin 15), sondern mir das bis einigermassen selbst beigebracht habe. Das soll aber nicht heissen das ich nun irgendjemanden Böse wäre, >Ich bin sicher Nik würde ihm auch recht geben. trifft nämlich zu. mfg Nik
In C gibt es auch einen "mod"-Befehl, nur wird der C-typisch knapper geschrieben - das ist das von mir im zweiten Beitrag in diesem Thread erwähnte %. @Nik: Weiter so.
>@Nik: Weiter so.
danke danke :)
Nun, ich hab grad was ziemlich krasses entdeckt; entweder sind meine
Fat Routinen derart schnell, oder ich spinne...naja, jedenfalls hab
ich
hier ein lied, das normal 5 minuten 18 sekunden, das mit einer Bitrate
von 128 kbit. Nun hab ich spasseshalber mal den Befehl weggelassen,
der
auf Dreq wartet. Folglich sendet das die Daten so schnell wie möglich;
nach 10 sekunden war nichts mehr zu höhren und der song war fertig.
Falls das überhaupt möglich ist, hätte das ganze ja dann mit
490 kbyte/sek gelesen (file Grösse ist 4977kbyte).
Nun kann ich mir das aber kaum vorstellen, ich verwende nämlich nur
einen 7.xxx Quarz verwende.
Gibts vielleicht eine einfache möglichkeit die Geschwindigkeit
zu messen? (In Sofware meine ich jetzt, sonst geht ein 10mb file und ne
Stoppuhr ja auch ;) )
mfg Nik
Also ich hab nun ein ziemlich genaues Ergebniss; 102 kbyte/sek, die Dateien werden dabei aber auch noch über spi versandt, Quarz ist wie gesagt nicht ein mal 8 mhz schnell, ausserdem habe ich kein Buffer für die Fat Tabelle oder derartiges, sondern für alles immer nur einer mit 32 byte. Mit einem 16 mhz Quarz und ohne übers spi senden könnten da doch gut 200 kbyte/sek drin sein denke ich...
Hallo Nik, da Du über die Lesegeschwindigkeit schreibst, wüßte ich gerne, was für ein Speichermedium Du verwendest. Leider kam es bisher nicht rüber oder ich habe es überlesen. Volkmar
Hallo Nik! Ich finde dein Projekt sehr interessant! Ich hoffe du kannst es bald veröffentlichen, ich werde es gerne lesen. Momentan hab ich eine CF an einem uC, und ich bringe 300kB/s hin. Da ich bald mit HD's experimentieren will, verfolge ich diesen Thread schon länger. Danke für den FAT-Link!
>Ich finde dein Projekt sehr interessant! >Ich hoffe du kannst es bald veröffentlichen, ich werde es gerne lesen Das ist eigentlich auch mein Ziel, ich werde mich dann dahinter machen wenn die Prüfungen erst mal vorbei sind. Zudem muss ich den Code noch ziemlich aufräumen(Funktionen die ich zum debuggen benutzt habe rauslöschen etc.) Dann muss ich mir noch einiges überlegen wie ich das ganze mit den Fat Funktionen eingermasses klug beschreiben kann-denn ich hab ja keinen Buffer verwendet, der einen ganzen Sektor speichert, das ginge auch gar nicht, da der mega8515 ja nur 512 byte ram hat. So kam es dann das ich drei verschiedene kleinere buffer habe... >Momentan hab ich eine CF an >einem uC, und ich bringe 300kB/s hin. Woah das ist ganz schön heftig, was für einen Controller Compiler Quarz verwendest du denn? >Da ich bald mit HD's experimentieren will, >verfolge ich diesen Thread schon länger. Für Hardware/Software für hdd's kann ich bis jetzt mal den Source von Yampp3 empfehlen (http://www.myplace.nu/mp3/yampp3.htm) Ich wollte anfänglich den yampp3 nachbauen, doch habe ich dann bemerkt, das man wegen des memory interface timings leider nicht so einfach einen atmega8515 anstelle des verwendeten at90s8515 beenutzen kann, obwohl die bei atmel das eigentlich schreiben...) Desshalb ist meine Hardware grösstenteils gleich aufgebaut, ausser das ich eben kein Ram benötige.
> Ich wollte anfänglich den yampp3 nachbauen, doch habe ich dann > bemerkt, das man wegen des memory interface timings leider nicht so > einfach einen atmega8515 anstelle des verwendeten at90s8515 > beenutzen kann, Was ist denn daran so grundlegend anders? Ganz davon abgesehen, AT90S8515 bekommst du doch fast hinterhergeworfen...
Hi Nik! Thanks für den yamp3-Link. Ich hab das in Assembler geproggt, die Routinen zum Schreiben/Lesen sind optimiert und laufen auf nem mega32 @16MHz. Die Geschwindigkeit ist sehr von der verwendeten Karten abhängig, neue CF's sind Ca. 4x schneller als ältere, neuere Karten sind allerdings oft nicht kompatibel. Ich hab mit ner alten 16MB von Sandisk angefangen, alle neuen Karten von Sandisk funktionieren mit den gleichen Routinen nicht mehr zuverlässig! Ser empfehlen kann ich die Elite Pro Karten von Kingston, die sind einfach spitze! Mich würde ein tragbarer mp3-Player mit einer 4GB Karte und Fat32 reizen, viel Speicher, wenig Strom und vorallem keine mechanische Harddisk! Mal sehen ob deine Fat-Routinen mich inspirieren, hab im Moment leider nicht so viel Zeit und werde dann gleichzeitig mein 1. Projekt in C starten. Gruss.
@Jörg >Was ist denn daran so grundlegend anders? Was es genau ist, kann ich nicht sagen, ich habs selbst mit Datenblatt nicht herausfinden können. Das Timing ist irgendwie schneller und somit funktionierte die Ansteurung vom ram/hdd nicht mehr mit der yampp3 software. Ich hab nach etwa 2 wochen rumprogrammieren an dem prog. von yampp entschlossen aufzugeben, dafür aber mein eigenes Programm zu schreiben, dabei lerne ich schliesslich auch noch was :) >Ganz davon abgesehen, AT90S8515 bekommst du doch fast >hinterhergeworfen... Das dachte ich zuerst auch, doch dann musste ich leider festellen, das ich in der Schweiz wohl nur noch an die atmegas rankomme, die at90s8515 fand ich nur noch beim grossen C und bei dem mit angegebener Lieferzeit von mehr als 2 wochen....
Tja, ohne Mailadresse keine Hilfe... (Ich wollte dir 'ne PM schreiben.) Vielleicht hast du einfach nur ein zu langsames Latch genommen? Hast du die Taktfrequenz gegenüber yampp hochgesetzt (der mega kann ja mehr)? Das Latch ist kritischer als der RAM selbst.
Ich gib die email Adresse eigentlich an, hab das hier früher auch gemacht, nun wegen den vielen die sich Gedanken machen wegen irgendwelchen Spam attacken dachte ich mal ich lass die adresse weg, bis jemand fragt, also häng ich sie nun mal an :D Das es das Latch war denke ich aber weniger, ich hab mehrere ausprobiert, einmal ein HC, aber auch einmal ein hct. Dann habe ich auch alle beim mega8515 neuen sram waitstate bits gesetzt, damit alles möglichst langsam abläuft, einmal mit at90s8515 compatible fuse und einmal ohne, beide Male ging nichts :( Aber im Moment verwende ich immer noch dasselbe Latch für die Ansteuerung der hdd um einige Anschlüsse zu sparen, und es läuft :P
Naja, die email-Adressen sind ganz gut geschützt, das at-Sign ist ja eine kleine Grafik. ;-) Merkst du mit einem grafikfähigen Browser nicht direkt. > Das es das Latch war denke ich aber weniger, ich hab mehrere > ausprobiert, einmal ein HC, aber auch einmal ein hct. Hmm, die Manpage meint: ``When operating at conditions above these frequencies, the typical old style 74HC series latch becomes inadequate. The external memory interface is designed in compliance to the 74AHC series latch.'' Nach meinen Erfahrungen kommt es auf die RAM-Geschwindigkeit nicht so sehr an, auf die des Latches schon. (Meine Erfahrungen beziehen sich auf einen ATmega128, aber der sollte nicht grundlegend anders als ein ATmega8515 sein, auch was das Timing betrifft.)
Ich bins nochmals ;-) Es wär wohl ziemlich doof wenn ich nun für das einen neuen Thread mache...desshalb halt einfach nochmals hier. Also bis jetzt kann der Player: +Fat32 +Lange Dateinamen(jedenfalls die ersten 12 Zeichen mit gross/kleinschreibung) +Subdirectories +Files mit 320kbits gehen ohne probleme +Steuerung mit Rotary Encoders.. -Die Drehencoder bereiten noch einige Probleme, die Drehrichtung wird nicht immer ganz erkannt. Im Prinzip sollte das später so funktionieren, dass es einen Drehencoder mit und einen ohne Taste gibt. Der mit Taste ist für die Songauswahl/Navigation gedacht(die Taste fürs selektieren/play) Und der ohne Taste, um die Lautstärke einzustellen Also alles in allem funzt eigentlich alles perfekt, bis halt auf diese Drehencoder...soll heissen, fall noch Interesse besteht, könnte ich nächste Woche oder so ja mal etwas dazu ins Wiki stellen.(?) Mfg Nik
@Nik "Die Drehencoder bereiten noch einige Probleme, die Drehrichtung wird nicht immer ganz erkannt." Hast Du mal in die Codesammlung gesehen ? Nen Timerinterrupt wirst Du ja bestimmt schon benutzen, einfach da mit reinhauen. Peter
Ja deinen Code hab ich schon entdeckt ;-) Ich werds dann vielleicht auch mal mit deinem Versuchen. Bei mir geht das bis jetzt etwa so: KanalA an Int0 KanalB an einen beliebigen anderen Pin
1 | SIGNAL(SIG_INTERRUPT1) // rottary switch |
2 | interrupt
|
3 | {
|
4 | |
5 | u08 a,b; |
6 | a = bit_is_set(MCUCR,ISC10) ? 0 : 1; |
7 | b = bit_is_set(PIND,PD4) ? 1 : 0; |
8 | |
9 | cbi(GIMSK, INT1); |
10 | //delay(500);
|
11 | |
12 | if (a==b) // rottary second input |
13 | {
|
14 | PRINT("UP!");LoadFileInfo('n'); |
15 | }else{ |
16 | PRINT("DOWN!");LoadFileInfo('p'); |
17 | }
|
18 | |
19 | |
20 | if(a==1) |
21 | {
|
22 | sbi(MCUCR, ISC10); |
23 | sbi(MCUCR, ISC11); |
24 | }
|
25 | |
26 | if(a==0) |
27 | {
|
28 | cbi(MCUCR, ISC10); |
29 | sbi(MCUCR, ISC11); |
30 | }
|
31 | |
32 | sbi(GIMSK, INT1); |
33 | }
|
Der Code ist allerdings auf auf einen ec-11b von alps ausgerichtet, denn die machen ja nur 1/2 des signals(soll heissen bei jeder rastung wechseln kanal a und b von low auf high oder umgekehrt, allerdings nicht wieder in den Ursprungszutand...) Nun seit ich an den Eingängen noch C mit 100nF rangeklemmt habe geht das ganze schon sehr zuverlässig, etwa 5/100 vorgängen werden aber immer noch falsch interpretiert. Wenn ich das nicht selbst noch besser hinbekomme, seh ich mir gern mal deinen Code an, ich brauch bis jetzt nämlich nicht mal einen einzigen Timerinterrupt ;-) mfg Nik
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.