Hallo Leute
Ich muss für ein VHDL Projekt ein Zeitsignal, welches ich über GPS
empfange in einen UNIX timestamp umwandeln. Der UNIX timestamp ist die
Anzahl Sekunden seit dem 01.01.1970 00:00 Uhr. Das GPS Signal enthält
aber normale Werte für Datum und Zeit.
Hat da vielleicht jemand einen VHDL Code der diese Umwandlung macht? Ich
stell mir das nicht sehr einfach vor wegen den Schaltjahren und
Schaltsekunden die zu berücksichtigen sind.
Danke für eure Hilfe.
Nein, es sollte schon auf der Hardware laufen.
@Christopher: Daran habe ich auch schon gedacht, jedoch wird die
Implementation in C einfacher sein, denke ich. Am idealsten wäre es halt
schon wenn das schon jemand hätte.
Virtex4 kann kein GPS.
Du solltest dir erstmal einen passenden GPS-Empfänger raussuchen und
schauen wie der angesteuert wird (wohl I2C). Dann suchst du dir ein
passendes I2C-VHDL Modul und pappst einen pico oder microblaze
(uC-Softcore) dran und schreibst das Programm zur Umwandlung in C.
MfG
Hallo Viertelgott
Danke für die Antwort.
Das GPS Signal liegt in Form eines seriellen Datenstreams vor. (NMEA
Protokoll). Darin ist die UTC Zeit codiert. Es gelingt mir diese zu
decodieren. Die Umwandlung in einen Unix Timestamp möchte ich eben in
VHDL machen.
Mittlerweile ist es mir gelungen mit Matlab einen Algorithmus zu
schreiben, der diese Umwandlung macht. Ich denke ich kann diesen
Algorithmus mit einer Statemachine nachbauen.
Gruss
Hey Car,
mich würde der Algorithmus interessieren! Gibt es da Besonderheiten oder
muss man nur die Schalttage berücksichtigen… Welchen GPS-Empfänger
möchtest du verwenden?
Gruß
Gast
Hallo Car,
das Thema ist zwar schon ein gutes Jahr alt, aber auch mich würde der
Algorithmus interessieren.
Ich möchte es auf einem ATMega umsetzen.
Hab zwar als Ausgangsbasis den http://de.wikipedia.org/wiki/Unixzeit
genommen, allerdings bin ich der Meinung, der stimmt nicht 100%ig.
Ich habe den Code nach Bascom portiert und habe bei Daten nach dem
31.12.2004 fehlerhafte Timestamps im Folgejahr nach einem Schaltjahr.
Dort bin ich zwar stets um einen Tag falsch, was sich mit einer extra
Abfrage ja kompensieren ließe - allerdings macht mich dies skeptisch.
Ich wäre dir also dankbar, wenn ich deinen Algorithmus bekommen könnte.
Gruß
BoGe-Ro
Auch mich würde eine Lösung hierfür sehr interessieren! Die Quellcodes
von gcc für mktime() sind extrem aufwändig und erzeugen eine gewaltige
Codemenge, die z.B. in einem AVR-Controller nicht akzeptabel wäre.
Ich nutze einen ATTiny85 zum Empfang eines DCF-Signals. Auch hier liegt
die Zeit nur als "struct tm" vor, also aufgedröselt in Jahr, Monat, Tag,
Stunde, Minute, Sekunde. Bisher wandern die Daten als solcher Bytestream
per I2C nach draußen. Ich will aus Kompatibilitätsgründen aber auch
gerne noch einen Unix Timestamp (time_t) mitliefern. Leider ist nix
brauchbares zur Konvertierung dafür zu finden. Die Routine ist - wie
schon gesagt - vermutlich auch nicht ganz trivial.
Der umgekehrte Weg (time_t -> struct tm) ist sehr einfach und in etwas
über 1 kb zu codieren (liegt als Quelle in glibc-x.x/time/offtime.c
vor). Eigentlich müsste doch (struct tm -> time_t) dann auch
einigermaßen knapp zu codieren sein, also quasi "offtime.c rückwärts"
;-).
Denkbar wäre noch eine Approximation, indem man den vermuteten time_t
Wert näherungsweise bestimmt, diesen in eine struct tm umrechnet und
dann so lange Sekunden addiert, bis der "Probierwert" mit dem realen
übereinstimmt. Das ist aber keine schöne und auch sehr rechenaufwändige
Lösung.
Besser wäre eine vernünftige, nicht approximative Lösung. :-/
Tschö, Volker
Sodele, hier nun Beispielcode für die Wandlung einer Zeit-Struktur tm
(Jahr, Monat, Tag, Stunde, Minute, Sekunde) in einen Unix Timestamp
(time_t / Sekunden seit 1.1.1970 00:00:00 Uhr) und wieder zürück.
Ich habe mich mal etwas mit dem Beispielprogramm bei Wikipedia
beschäftigt. Es funktioniert so weit, aber es ist noch ein Fehler drin.
Der Monat muss nicht von 1 (Januar) bis 12 (Dezember) eingegeben werden,
sondern natürlich im Unix "struct tm"-Format: Januar = 0, Dezember =
11!!! Dann funktioniert die Routine auch.
Außerdem habe ich durch Verwendung von unsigned longs die
unixzeit-Funktion so abgeändert, dass Daten bis zum Jahr 2106 (time_t
0xFFFFFFFF) verarbeitet werden können und nicht nur bis 2038, wie bei
vorzeichenbehafteten 32 bit Werten. Aber ACHTUNG: Daten vor dem
1.1.1970 dürfen dann mit dieser Funktion nicht verarbeitet werden und
führen zu falschen Ergebnissen!
Im Folgenden mal ein auf den meisten AVR lauffähiges Programm, das mit
WinAVR compiliert werden kann. In der Funktion main() wird zuerst aus
einem time_t Wert (l) ein Datum als "struct tm" erzeugt (mit der
Funktion __offtime()). Die Daten dieser Struktur werden danach wieder
zurück in einen time_t Wert (lt) gewandelt (mit der Funktion
unixzeit()).
Klaus schrieb:> komisch, mein VHDL-Compiler spuckt lauter Fehler aus... Oder ob ich das> mit dem Verilog Compiler probieren muss?VHDL hat mit ANSI C nichts zu tun, es ist eine eigene Sprache, die mehr
Pascal ähnlich ist. Mein obiger Code ist für gcc gedacht (WinAVR bzw.
Atmel AVR Studio). Du musst dir WinAVR installieren, wenn du das
compilieren willst, oder es in VHDL umschreiben ;-).
http://winavr.sourceforge.net/
Gruß, Volker
Volker schrieb:> VHDL hat mit ANSI C nichts zu tun, es ist eine eigene Sprache, die mehr> Pascal ähnlich ist. Mein obiger Code ist für gcc gedacht (WinAVR bzw.> Atmel AVR Studio). Du musst dir WinAVR installieren, wenn du das> compilieren willst, oder es in VHDL umschreiben ;-).
Komisch, und ich dachte in diesem Thread geht es um VHDL...
Klaus schrieb:> Volker schrieb:>> VHDL hat mit ANSI C nichts zu tun, es ist eine eigene Sprache, die mehr>> Pascal ähnlich ist. Mein obiger Code ist für gcc gedacht (WinAVR bzw.>> Atmel AVR Studio). Du musst dir WinAVR installieren, wenn du das>> compilieren willst, oder es in VHDL umschreiben ;-).>> Komisch, und ich dachte in diesem Thread geht es um VHDL...
UPS! Au weia, da habe ich mich im Thread geirrt :-). So ist das, wenn
man die Suchfunktion benutzt und dann gar nicht so genau hinschaut.
SORRY SORRY!!! :-)
Vielleicht schreibt das ja mal jemand in VHDL um?!
Nichts für ungut, Volker
Also VHDL ist eine Hardwarebeschreibungssprache, da kann man nicht so
einfach Programmcode umschreiben.
Nehmen wir mal an, Du hast das NMEA Paket schon eingelesen,
beispielsweise in Schieberegistern.
Dann könntest Du beispielsweise folgendes machen. Du machst 2
Zeitzähler. Der eine zählt einfach 32 Bit durch (Unix-Zeit), der andere
zählt in Sekunden, Minuten, Stunden, Tag, Monat, Jahr, wobei natürlich
die Schaltjahre beachtet werden müssen.
Jetzt setzt Du beide auf Anfang und lässt sie so lange zählen, bis die
UTC-Zeit übereinstimmt. Nach spätestens 4,3 Milliarden Taktzyklen hast
Du das Ergebnis.
Nun ist das nicht besonders effizient. Was Du machen kannst ist dem
Unix-Zähler Taktsignale zu geben, bei denen er 365 oder 366 Tage
weiterzählt, sowie 1, 28, 29, 30 oder 31 Tage.
Jetzt kannst Du beide Zähler zuerst um die Jahre, dann die Monate, und
dann die Tage inkrementieren. Das kannst Du auch auf Stunden, Minuten
und Sekunden erweitern. Damit hast Du innerhalb von grob 100 Taktzyklen
die Zeit umgerechnet.
Christian Berger schrieb:> Also VHDL ist eine Hardwarebeschreibungssprache, da kann man nicht so> einfach Programmcode umschreiben.
Das erinnert mich stark an die Steuerungstechnik in meinem Studium, wo
wir SPS "programmiert" haben. Obwohl ich das kaum als Programmieren
bezeichnen würde. Aber Variablen gabs da auch und einfache arithmetische
Operatoren ebenso.
> Nehmen wir mal an, Du hast das NMEA Paket schon eingelesen,> beispielsweise in Schieberegistern.> [..]
Schön erklärt! Aber es dürfte schwierig sein, aus dem Unix-Zeitwert
wieder den Datums- und Uhrzeitwert zurückzurechnen, oder? Allenfalls
auch durch eine Approximation, so wie du es beschrieben hast...
Da bin ich schon froh, dass ich mich ausschließlich aufs "richtige"
Programmieren verlegt habe und mit solchen Makro- oder
Beschreibungssprachen wenig am Hut habe. Ich denke, der höhere
Lernaufwand lohnt sich langfristig gesehen allemal. ;-)
Tschö, Volker
Hallo,
wie mir grade aufgefallen ist, befindet sich leider noch ein Fehler in
dem weiter oben von mir geposteten Code. Dieser tritt nur in
Schaltjahren im März auf, weshalb ich ihn auch jetzt erst entdeckt habe.
:-(
Im Code-Teil zur Konvertierung gegliederter UTC-Angaben in Unix-Zeit
heißt es:
> if ( (monat>2) && (jahr%4==0 && (jahr%100!=0 || jahr%400==0)) )> unix_zeit+=60L*60L*24L; /* +Schalttag wenn jahr Schaltjahr ist */
Es muss aber korrekt heißen: