amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Suche [ - Suche - Neue Beiträge - Registrieren - Login - ]

1 2 -3- 4 Ergebnisse der Suche: 110 Treffer (30 pro Seite)
jolo   Nutzer

24.07.2009, 18:02 Uhr

[ - Direktlink - ]
Thema: value to dezimal string
Brett: Programmierung

@AGSzabo:

Hi.

Zitat:
...auf langwortgröße sollte es schon funtionieren. wer weis wie?

code:
ValToDez:
	movem.l	d2-d4/a1,-(a7)
	push	a0
	moveq	#4,d1
	move.l	#10000,d3
	moveq	#0,d2
.lp1	moveq	#-1,d4
.2	addq.w	#1,d4
	sub.w	d3,d0
	bpl.s	.2
	add.w	d3,d0
	divu.w	#10,d3
	add.w	#$30,d4
	tst.w	d2
	bne.b	.4
	cmp.b	#"0",d4
	beq.b	.5
	st	d2
.4	move.b	d4,(a0)+
.5	dbf	d1,.lp1
	cmp.l	(a7)+,a0
	bne.b	.pop
	move.b	#"0",(a0)+
.pop	movem.l	(a7)+,d2-d4/a1
	rts


Dieser Code wurde ursprünglich für eine 68000er CPU, bei der die Eingabe nie größer als 99999 ist, geschrieben.
Aber lass Dich nicht ins Bockshorn jagen; ineffizient ist der Code mitnichten!
Zudem unterdrückt er führende Nullen und testet auch korrekt ob 'd0' null ist, heißt, dann wird trotz Unterdrückung der führenden Nullen eine einzige Null in Deinen Puffer geschrieben. Leider wird der Puffer aber nicht NUL-Byte terminiert.

Alles in allem ist dies Standard-Code der in den 80er Verwendung fand.


Änderungen damit Langworte ausgegeben werden können; ausschließlich 68020(+):
code:
:
	moveq	#4,d1
	move.l	#10000,d3
in
	moveq	#9,d1
	move.l	#1000000000,d3
ändern.

Und die Instruktionen:
	sub.w	d3,d0
	bpl.s	.2
	add.w	d3,d0
	divu.w	#10,d3
gegen
	sub.l	d3,d0
	bpl.s	.2
	add.l   d3,d0
	divul.l	#10,d3:d3
tauschen.


Wie gesagt, 68020+ ist Voraussetzung.

Wenn Du diesen abgeänderten Quellcode für 68000 kompatibel machen willst, musst Du nur 'd3' mittels Werten einer Tabelle (beginnend mit 1000000000 und endend bei 1) aktualisieren, dann entfällt auch 'divu.w' bzw. 'divul.l'.


Grüße
 
jolo   Nutzer

17.05.2009, 17:17 Uhr

[ - Direktlink - ]
Thema: Unicode auf OS3.x
Brett: Programmierung

Aua, aua, aua - das zu lesen wird dauern...


@Thore
Zitat:
Unter MorphOS wird auf den BOM auch verzichtet beim Copy n Paste.

Dateien ohne BOM sollten der Regelfall sein und mit BOM nur Ausnahmen, ansonsten zerstört man nämlich Systemdateien die in ASCII erstellt worden sind aber als UTF-8 gespeichert werden. Ohne BOM unterscheiden sich beide Dateien nicht.

Zitat:
In diesem Fall ist es ein patch für das input.device.

Patch and burn! :)
Oder anders: Watschen fürs Patchen... :)
Ich hoffe, nachdem ich jetzt alle Beiträge gelesen habe, dass ihr nichts mehr patchen wollt?


Zitat:
NoWinEd interpretiert UTF-8 Codes und konvertiert diese zu ISO-8859-x (ich glaub 1), allerdings sind damit z.B. chinesische Zeichen verloren (durch ? ersetzt).

Unter OS3 (ISO-8859-1), ja, unter MorphOS/AmigaOS4/AROS immer entsprechend der IANA-ID (Locale-Bibliothek) (Amiga-1251, ISO-8859-x, TIS-620, UTF-x). Da weder MorphOS/AmigaOS4/AROS Unterstützung für die chinesische Zeichenausgabe und Eingabe anbieten, kann hier nichts abgebildet werden, daher die vielen '?'.
Da aber die MUI TextEditor MCC Klasse neu geschrieben werden müsste um UTF-Konformität zu erzielen ist UTF-x Unterstützung nur theoretisch vorhanden, also verbleiben noch Amiga-1251, ISO-8859-x und TIS-620 im Rennen wobei TIS-620 wiederum ausfällt, da es keine Einzelbyte-Kodierung ist, sondern ein Zeichen aus bis zu drei Bytes (drei Oktetts) besteht und die MUI TextEditor MCC Klasse dies nicht unterstützt.


@Wanderer
Zitat:
Was mir noch einfällt, man könnte durchaus UTF-8 auch tippen, denn man kann ja eine KeyMap machen, die gleich zwei oder drei Zeichen produziert.

Bloß nicht. UTF-8 ist ein Datenformat und nicht ein Wert irgendeiner Taste Deiner Tastatur.
UTF - Datenformat (im RAM, Harddisk oder generelles Speichermedium)
Unicode - Zeichensatz (im Gegensatz zu ASCII aber ein wenig umfangreicher)
Code Point - Wert eines Zeichens
Bitte nicht durcheinander bringen.


Zitat:
Also wenn TTEngline.library 7.2 gescheit funktioniert, scheint mir das der gangbarste Weg zu sein, einen Texteditor mit Unicode-Fähighkeit auszustatten.

Das mag stimmen. Leider, wenn ich das noch recht in Erinnerung habe, hat aber TTEngine unter OS4 arge Probleme bereitet. Ist allerdings schon Jahre her. Um das Ganze zu verifizieren müsste ich die entsprechenden Emails heraus kramen und lesen. Alternativ könnest Du ein paar Beispiele erstellen und OS4 Benutzer zum Testen bereitstellen bevor Du Dir die Mühe machst, alles auf TTEngine zuzuschneiden. Meine Beispiele, die TTEngine verwandten, dürften mit dem letzten Head-Crash einer Festplatte verloren gegangen sein... Muss mal schauen, vielleicht haben einige doch überlebt.


Zitat:
Ausserdem habe ich die ganzen Texteditor Funktionen schon, fehlt nur das Handling von Mehrbyte Zeichen, bzw. erstmal 16bit chars.

Leider unterscheiden sich Ein-Byte-Zeichenfunktionen (die Du derzeit in TuiTED verwendest) grundlegend von Unicode Funktionen. Du wirst diese nicht verwenden können.
Zudem ist die Limitierung auf 16-Bit sehr zeitraubend bedingt durch die Tests auf Surrogate-Code-Points, sofern Du nicht als Basis Unicode 3 verwendest, die allerdings veraltet ist.

Du könntest wie in OS4 für jede unterstützte Sprache die entsprechenden Funktionen (StrCmp/ToLower/ToUpper) als eigenständiges Modul schreiben, was allerdings mit erheblichen Aufwand verbunden ist.
Ich persönlich finde diesen Ansatz in Zeiten von Unicode aber nicht sehr elegant, jedoch immer noch besser als gar keine Funktionen anzubieten.


@Thore
Zitat:
Keine schlechte Idee. Wenn der Editor allgemein nur 2 Byte Zeichen editieren kann.

Wie, was? Das verstehe ich nicht.
16-Bit Code Points sind keine 2-Byte Zeichen. Oder verstehe ich hier etwas nicht richtig?
Erklärung bitte!


@Wanderer
Zitat:
In NTUI ist ein String-Gadget eine einzeilige Textbox mit etwas geänderten Farben und Bordern. Daher kann es automatisch auch Unicode.

Nee, kann es nicht. Unicode ist ein Zeichensatz, kein Datenformat wie IFF, PNG, UTF usw. .
Der Unicode-Zeichensatz enthält eine viel größere Menge an Informationen bereit als der ASCII-Zeichensatz, auf die bei korrekter Implementierung eingegangen werden sollte. Ein Latin-1 oder ASCII-Texteditor kennt gar nicht alle Attribute aus die der Unicode-Zeichensatz besteht. Hier muss dann nachgebessert werden.


@Wanderer
Zitat:
Den Editor würde ich generell nicht auf 16bit umstellen, da sonst schnelles Laden nicht mehr gehen würde, bzw. man hätte grossen Speicherbedarf bei grossen Files. (Ja, bei der Abreit habe ich durchaus mal 1GB grosse Text-Files...).
Aber jede Zeile kann ein Flag besitzen, in welchem Encoding sie vorliegt, und erst beim Speichern wird, nach Bedarf, konvertiert.
Da würde ich 8bit und 16bit unterstützen, später vielleicht UTF-8.


Das ist meinem Erachten nach kein günstiger Ansatz da alle Zeichenoperatoren dann für dieses spezielle Format nochmals vorliegen müssen. Einmal als Byte, dann als Wide-Char (16 Bits). Wäre mir persönlich nicht transparent genug.
Zudem denke ich dass bei halbwegs korrekter Implementierung deinerseits Du sowieso nicht um volle 32-Bit Unterstützung herumkommen wirst. Ist aber nur Spekulation meinerseits. :)


@Thore
Zitat:
Wenn der Suchstring auch nach 16Bit konvertiert wird, und bei der Suchfindung auf gerade Adressen geprüft wird, ist die Suche ohne Probleme möglich, wenn der Editor intern auch nur 16Bit Text verwaltet.

Pweeh, ich hoffe ich schmeiße nicht alle Beiträge durcheinander - eurer Thread ist ein wenig lang und ich hatte keine Zeit in den letzten Tagen zu antworten.

Was erwartest Du auf ungeraden Adressen zu finden wenn das Format als 16-Bit ausgelegt ist?
Alle Code Points sind bei einem 16-Bit Format 'Words', d.h. sie sollten sowieso auf geraden Adressen liegen. 16-Bit ('Words') bedeutet aber nicht, das ein Zeichen aus einem einzelnen 'Word' besteht, es sei denn man beschränkt sich auf Unicode 3.
Habe ich hier was nicht verstanden? Aufklärung bitte! :)


@Wanderer
Zitat:
Für das Casing gibt es unter Unicode.org Listen, die man verwenden kann. Sollte kein Problem sein, so gross sind die Listen nicht, was sind schon ein paar 1000 Einträge?

Autsch. :)
Die Basis-Datei für Unicode 5.1 ist eine Textdatei die schon mal 1 Mbyte groß ist. Alle Basisinformationen, die durch diese Datei beschrieben werden, in ein maschinenlesbares Format umzusetzen ohne irgendwelche Kniffe anzuwenden, wird in einer Tabelle zwischen 3 und 4 Mbytes resultieren, je nachdem welche Informationen abgedeckt werden sollen.


@Thore
Zitat:
Großbuchstabe + 0x20 = Kleinbuchstabe. Das ist auch bei den Unicode-Zeichen so. Allerdings muss man die Grenzen wissen, da die meisten Zeichen keine Groß-/Kleinschreibung haben.

Wie kommst Du an diese Information?
Der Unicode-Zeichensatz (Zeichensalat) gibt keine vordefinierten oder festen Distanzen zur Bestimmung einer Information vor. Groß/Kleinbuchstaben können beliebig weit auseinander liegen - und das tun sie auch!


Zitat:
Am besten suchst Du in unicode.org nach JOHAB.TXT, da hats ziemlich viele drin.

Nee, nix da. UnicodeData.txt ist euer Freund. :)


@Wanderer
Zitat:
Wie Thor schon geschrieben hat, haben die meisten Zeichen keine verschiednene Casings. Deshalb ist die Liste viel kleiner.

Du missachtest aber die Tatsache, dass Du erst einmal überprüfen musst, ob der betreffende Wert eines Zeichens (Code Point) in Deiner privaten Liste aufgeführt ist. Bei einem Spektrum von 1114109 Werten kommt dann Freude auf...
Ich hab' zwar keine Ahnung wie Du vorgehen willst, aber mit einfachen Vergleichsoperationen (ist Code Point in meiner Liste oder nicht) wirst Du nicht weit kommen. Es dauert viel zu lange die betreffende Information einzuholen.


Zitat:
je nach lib, muss man sich fast so lange damit rumschlagen bis es läuft, als wenn man es selbst implementiert.

Da gebe ich Dir recht. Nur in diesem speziellen Fall glaube ich, dass Du sehr viel mehr Zeit aufwenden wirst, um eine halbwegs passable funktionierende ToLower/ToUpper Funktion zu schaffen, ganz zu schweigen um Code Point Attribute abzufragen.


@Thore
Zitat:
Die Ausnahmen von 0x20-Sprung sind nicht so viele wie Du annimmst, man findet sie in ISO-8859-10.

Es gibt keine Ausnahmen. Der Unicode Zeichensatz ist nicht für eine einfache Indexierung geschaffen worden. Alles wäre einfacher falls dass Unicode Konsortium die Maschinen (CPU) in Mittelpunkt gestellt hätten und nicht den Menschen.
Haben sie aber nicht.
Anbei, ISO 8859-10 ist eine leicht geänderte Latin-1 Zeichenkodierung für nordeuropäischen Sprachen, demnach hat ISO 8859-10 nicht das Geringste mit dem Unicode-Zeichensatz zu tun.


Zitat:
Es sind auch keine 100000 Zeichen im 2 Byte Unicode sondern nur 65536 (die nicht darstellbaren mitgerechnet).

Das ist so nicht richtig.
Ersten gibt es kein '2 Byte Unicode' sondern Unicode 3 dass in 16 Bit Code-Units passt und Unicode 5.1 dass deren 32 (aktuell 21) benötigt. Zudem kann man auch Unicode 5.1 mittels 16 Bit Code-Units darstellen (Surrogate Code Points).
100000 Zeichen stimmt fast, es sind etwas mehr als 99000 definierte Zeichen vorhanden.
Aber, Du verwechselst, falls ich das richtig interpretiere, definierte Zeichen mit Werten. Der Wertbereich in Unicode geht von 0 bis 1'114'109 (1.1 Millionen) wobei ca. 99'000 Zeichen eine Bedeutung haben, ob als grafisches Symbol oder als Kontrollcode spielt dabei keine Rolle.


Zitat:
Mit Capital Zeichen meine ich "große Buchstaben, zu denen ein Kleinbuchstabe gehört", also die Zahlen doppelt nehmen, also schätzungsweise 300 Groß + Kleinzeichen

Selbst wenn Deine Aussage stimmen würde (tut sie nicht) ist das Problem nicht Groß- zu Kleinbuchstaben zu wandeln sondern herauszufinden, ob ein Wert ein bestimmtes Attribut hat und es erlaubt ist, eine Aktion basierend auf den Wert bzw. dessen Attribut, auszuführen. Es gibt in Unicode keine feste Bindung zwischen einem Wert und seinen Attributen.
Dein Fehler ist, dass Du zu sehr im Rahmen des griechischen Alphabets denkst. Unicode unterstützt das griechische Alphabet, ist aber nicht beschränkt auf seine Eigenheiten, ansonsten wäre Unicode nämlich unnütz.


Thilo/Thore

Ich will euch nicht vorschreiben, was ihr zu tun oder zu lassen habt, dazu habe ich auch keine Veranlassung.
Ich möchte euch aber verdeutlichen, dass ihr es euch zu einfach macht.
Unicode ist komplex. Selbst um nur eine kleine Teilmenge des Unicode-Standards zu implementieren wird schon sehr viel Zeit verschlingen. Ich spreche hier aus eigener Erfahrung.
Demnach solltet ihr auch das was ich geschrieben haben, als Anregung auslegen und nicht als Bevormundung, was ich wirklich nicht beabsichtige.
Zudem, ich bin kein Unicode-Spezialist und verfüge nur über allgemeines Wissen, nicht viel mehr als ihr beide auch habt.


In diesem Sinne,

viel Glück mit euren Unicode-Projekten,


Grüße

 
jolo   Nutzer

13.05.2009, 21:29 Uhr

[ - Direktlink - ]
Thema: Unicode auf OS3.x
Brett: Programmierung

Hi.

@Wanderer
Zitat:
Mir geht es hierbei mehr draum, mit Unicode Files überhaupt was anfangen zu können und sie editieren zu können ohne das Dokument zu zerstören. Alle Feinheiten der Anzeige muss man nicht unbedingt haben, weil, wie gesagt, es wenig Leute auf dem Amiga betreffen würde.

Okay, das dürftest Du mittels UTF-8 und einem Filter um die originale Text()-Funktion sehr leicht hinbekommen.


Zitat:
Für Darstellung auf einer Website gebe ich dir aber recht, denn da will man ja einen Text schön formatiert lesen. Bei Editoren ist es manchmal sogar umgekehrt, dass man z.B. Non-Spacing Marks seperat hat um sie besser identifizieren/editieren zu können.

Zitat:
Fürs Editieren ist es sogar besser die Marks explizit zu sehen.


Oje, da sind wir beide aber grundsätzlich verschiedener Meinung. :)
Gerade komplexe Schriftbilder sind darauf angewiesen, dass die Non-Spacing-Marks auf die korrekten Positionen ausgerichtet werden ansonsten wird es unleserlich, nicht für Dich und mich, aber für die Menschen die diese Sprache beherrschen.


Zitat:
Es geht hier ja auch nicht darum, ein spezial Tool zum Anzeigen von jeder erdenklichen Unicode File zu machen, sondern um einen Texteditor, der das momentan gar nicht kann, zu erweitern dass eine Unicode File korrekt bearbeitet werden kann.

Das geht mittels UTF-8 und einem Filter um die Text()-Funktion.

Zitat:
Mir gefällt aber die Idee von Holger gar nicht schlecht, die Unicode Zeichen vorzurendern und als Bitmaps dem Editor beizulegen. Den Text() Befehl zu simulieren ist ja dann trivial.

Die Frage ist dann nur, welche Zeichen willst Du vordefinieren. Im Prinzip machst Du nämlich nichts anderes als einen Zeichensatz (Font) zu erstellen, der eine Untermenge an Unicode-Charakteren enthält, wie schon ein paar tausend FreeType und TrueType Zeichensätze. Wäre die FreeType2-Bibliothek nicht so komplex und ihre Benutzung ein wenig einfacher, würde ich Dir diese empfehlen.
Du kannst ja erst einmal mit einer eigenen Zeichensatz-Implementierung beginnen und zu einem späteren Zeitpunkt die Benutzung der FreeType2-Bibliothek in Betracht ziehen.


Zitat:
Mir geht es darum, Text files (oder auch Binaries) verlustfrei im Texteditor zu editieren und wieder zu speichern, dann spart man sich auch ab und an den Hex Editor anzusmeissen.

Relativ einfach durchzuführen.
Lade alle Dokumente als UTF-8 Texte, falls sie in diesem Format noch nicht vorliegen, konvertiere sie beim Laden.
Du kannst nach wie vor die Text()-Funktion für Werte im Bereich 0 bis 127 verwenden, auch die normalen Funktionen zur Ermittlung der Zeichenbreite.
Errechnete Werte im Bereich 128 bis 255 kannst Du auch noch mittels Text() ausgeben, allerdings nur über einen temporären Puffer, und erst bei Werten im Bereich von 256 bis einschließlich 1114109 kommt dann Dein 'Custom-Rendering' zum Einsatz.


Zitat:
Weiss jemand, ob es zur freetype2.library irgendwo ein SDK oder zumindsest eine .fd File gibt?

Normalerweise kommt die FreeType2-Bibliothek als Linker-Bibliothek zum Einsatz. Eine offiziell genormte Schnittstelle für Amiga-Shared-Libs ist mir nicht bekannt, kann mich aber täuschen.
Im Aminet müsste die FreeType2-Bibliothek sowohl als Linker- als auch als Shared-Lib für OS3 zu finden sein. Wie gesagt, ob die Schnittstelle genormt ist, entzieht sich meiner Kenntnis.


Zitat:
Die ttengine.library scheint mir von allen wohl am geeignetsten zu sein. Die hatte ich auch schonmal in TuiTED integriert, allerdings gab es Probleme mit dem Layout. Mal sehen ob ich es diesmal besser hinbekomme.
Wird dann allerdings nicht TuiTED werden, sondern das NTUI TextBox Widget.

Zitat:
@Thore
Die TTEngine.library ist ein guter Ansatz, jedoch ist mir noch kein Programm bekannt, das auch Copy n Paste unterstützt. Vielleicht lassen sich die relevanten Routinen (u.a. OpenFont()/CloseFont(), Text(), TextLength() und TextExtend()) durch die TT_ Funktionen patchen, nur muss hierfür geprüft werden, ob ein TTF-Font benutzt wird oder ein anderer, und je nach dem zwischen den alten Routinen und den TT-Routinen umschalten muss. Wenns denn überhaupt so machbar ist...



Soweit ich weiß benutzt MorphOS2.x TTEengine2 und die hat nicht mehr viele Gemeinsamkeiten mit TTEngine1 für OS3.


@Wanderer
Zitat:
Ich dachte MOS macht das lediglich via TTEngine, was ja aber nicht direkt OS Funktionen sind und auch angeblich Probleme hat wenn zwei Programme die Lib gleichzeitig nutzen.

Betrifft nur TTEngine1. TTEngine2 krankt nicht daran.


Zitat:
Mit dem Clipboard ist es natürlich etwas schwierig. Hier würde sich evtl. utf-8 anbieten, wie für alle OS funktionen, dann bräuchte man keine extra Funktion. Allerdings müssten die Funktionen irgendwie wissen, dass es utf-8 ist, und nicht ISO-xzy etc.
Evtl. wäre das ein Fall für die locale.library?


Unter OS3? Nee, leider nicht. Die Identifizierung eines UTF-8 Textes musst Du leider selber vornehmen. Ist aber nicht sehr schwer. Alternativ kannst Du auch die CodeSets-Bibliothek dafür verwenden.


Grüße
 
jolo   Nutzer

11.05.2009, 20:34 Uhr

[ - Direktlink - ]
Thema: Unicode auf OS3.x
Brett: Programmierung

@Der_Wanderer:

Hi.

Was Du benötigst wäre eine Render-Engine die Unicode unterstützt.
Es gibt zwei für OS3. Beide arbeiten aber nur mäßig und sind sehr eingeschränkt im Umfang.
Im Prinzip fast nutzlos.
Die eine nennt sich TTEngine und die andere UCode.

Vorab, falls Du einem Texteditor Unicode beibringen willst, sollte dieser:
a) bidirektionale Zeichenausgaben beherrschen und auch diverse Methoden für Weak und Strong Characters anbieten
b) zwischen Spacing und Non-Spacing Marks unterscheiden können
c) Proportionale Schriftenausgabe beherrschen
d) mehr als eine Schriftart pro Textzeile zulassen und diese Schriften zudem auch in unterschiedlicher Größe pro Textzeile darstellen können
Alles andere wäre nur eigeschränkt Unicode fähig.

Falls Du nur westliche Schriften unterstützen möchtest, reicht die Codesets-Bibliothek aus, um die Unicode-Werte auf den entsprechenden, westlichen Zeichensatz, abzubilden und dann mittels Text() das auszugeben, was abgebildet werden kann. Allerdings hat das in meinen Augen nichts mehr mit Unicode zu tun.

Mein Rat an Dich wäre derzeit ein solches Projekt auf dem Amiga zurückzustellen und zu warten, bis irgendjemand eine voll funktionsfähige Unicode Render-Engine bereitstellt (z.B. Pango in Verbindung mit Cairo). Alles andere ist entweder halber Kram oder gänzlich Spielerei (siehe UCode).


Grüße
 
jolo   Nutzer

17.03.2009, 20:29 Uhr

[ - Direktlink - ]
Thema: Welcher Assembler ist der Beste?
Brett: Programmierung

@AGSzabo:

Falls Du beim Debuggen wirklich nicht weiter kommst, benutze "_kprintf" zur Ausgabe (linken mit debug.lib) und starte vorab Sushi (oder gleichwertiges Programm).
Falls Dein Programm abstürzt, kannst Du hinter jeder "_kprintf" Ausgabe eine Zeitlang warten, mittels _LVODelay (falls Prozesse Deine Routinen aufrufen) oder mittels eines Busy-Loops des CIA-Bausteins (Tasks), so dass Du eine Ahnung bekommst, welche Routine den Absturz verursacht.

Grüße
 
jolo   Nutzer

30.10.2008, 23:18 Uhr

[ - Direktlink - ]
Thema: Keine Fenster Aktivierung bei Klick
Brett: Programmierung

@Holger:

Hoppala, was muss ich da lesen? :)
Da arbeite ich bis spätabends und will noch kurz vor dem Rechner entspannen und dann so etwas. Ts, ts, ts. :)

Solch verfasste Antworten bin ich von Menschen mit einer defizitären allgemeinen Intelligenz gewohnt, aber von einem Forumsmitglied...

Holger, falls Du von mir ernst genommen werden willst, solltest Du eine andere Tonart anschlagen, falls nicht, auch nicht schlimm. Es mag zudem Menschen geben, die sich auf Deine Strohmann-Argumentation einlassen, ich jedoch zähle nicht dazu.


Grüße
--
Stupid mistakes are always made by others -
we only make unavoidable errors
 
jolo   Nutzer

27.10.2008, 23:02 Uhr

[ - Direktlink - ]
Thema: Keine Fenster Aktivierung bei Klick
Brett: Programmierung

Hi!

Zitat:
@Holger

Trotzdem wird dann das momentan aktive Fenster deaktiviert.


Das Hauptfenster wird nicht deaktiviert.


Zitat:
Ja. Egal ob man den Zeiger innerhalb der Layer-Struktur ändert, die Layer-Struktur bleibt intakt und die Graphics- bzw. die Layer-Bibliothek kann den Refresh ausführen. Intuition ist nicht zuständig für die Erneuerung von Layern - sie kann es nur veranlassen bzw. hinauszögern.

@Holger
Zitat:
Das klingt für mich zu vereinfacht. Intuition sendet Refresh-Nachrichten an Anwendungen. Dazu muss intuition entweder über die Fenster iterieren und deren Layer auf gesetztes Damage-Bit überprüfen, [...].


Ich wollte das Thema Auffrischung (Refresh) bewusst ausklammern da es sehr komplex ist und ich mich auch noch nicht großartig mit diesem Thema befasst habe, noch das, was ich unten schreibe, bis ins kleinste Detail verifiziert habe.
Nichtsdestotrotz, hier meine Sicht der Dinge...
Ich unterscheide stark zwischen der Intuition-Bibliothek und der Layers-Bibliothek.
Die Intuition-Bibliothek fußt auf der Layers-Bibliothek sowie die Layers-Bibliothek auf der Graphics-Bibliothek fußt. Intuition selber, auf dem Input-Task.
Die Layers-Bibliothek verwaltet die Layers; dementsprechend ermittelt sie auch welche Regionen in der Bitmap sich überschneiden bzw. in ihrer Größe verändert wurden und welche Konsequenzen sich daraus ergeben.
Die Intuition-Bibliothek nutzt nun diese Informationen um zu ermitteln ob und welche Bereiche der Fenster, und noch wichtiger, welche Fensterobjekte (Knöpfe, Fensterrahmen) wieder erneuert werden müssen.
Intuition selber reagiert nur auf Benutzereingaben und auf explizit ausgeführte Aktionen.
Die Grafikoperationen führt dabei nicht Intuition aus, sondern die Graphics-Bibliothek, denn alles was mit dargestellten Bitmaps zu tun hat ist ausschließlich Sache der Graphics-Bibliothek. Intuition veranlasst nur diese Dinge. Sie verlässt sich dabei auf Angaben der Layers-Bibliothek.
Dementsprechend ist die Aussage die ich oben getroffen habe, dass die Layers-Struktur intakt bleibt und somit die Layers-Bibliothek entscheiden kann, welche Bereiche aufgefrischt werden müssen oder nicht, wobei der Auffrischvorgang (Refresh) von der Graphics-Bibliothek ausgeführt wird (primitive Grafikoperationen), wobei der Initiator Intuition ist, nach wie vor gültig.


Zitat:
Anbei, bitte nicht IDCMP_INACTIVEWINDOW oder IDCMP_ACTIVEWINDOW spezifizieren falls ein und derselbe MsgPort für das Hauptfenster und die Kindfenster verwendetet wird, ansonsten ist aus ersichtlichen Gründen ein Systemabsturz nicht fern!

Zitat:
Holger
Das ist für mich überhaupt nicht ersichtlich.



Nehme an Du hast zehn Kindfenster geöffnet – dementsprechend bekommt Du laufend MOUSEMOVE-Nachrichten.
Kommt jetzt ein INACTIVWINDOW schließt Du ein oder alle Kindfenster. Nichtsdestotrotz bekommst Du noch die Koordinaten (MOUSEMOVE) nachgereicht, die zum geschlossenen Kindfenster gehören.
Falls Du hier, genauso wie ich ( :) ), keine sonderliche Sorgfalt walten lässt, wirst Du genau wie ich ( :) ), einen Systemabsturz erleben, da Du wohlmöglich nach wie vor eine grafische Operation in einem nicht mehr existenten Objekt durchführen willst, da Du ja die Koordinaten und die Aufforderung zum Zeichnen dazu erhalten hast...

Ich hab’ die obere Erklärung abgegeben, weil ich zu diesem Zeitpunkt noch den Quellcode zum Beispiel mitliefern wollte, mich dann aber anders entschlossen habe. Dementsprechend war die Erklärung auf das nicht mitgelieferte Beispiel gemünzt.
'Tschuldigung.


Zitat:
@whose
Aber mal eine andere Frage: Kann man sich den MessagePort für das Kind-Fenster nicht im Grunde sparen? Oder gibt es Fälle, in denen der tatsächlich sinnvoll wäre?


Ja, habe ich ja auch so programmiert. :)
Und zu zwei: Mir fällt auf die Schnelle kein Fall ein wo es sinnvoll wäre.


Zitat:
@Holger

Entscheidend ist, dass graphics/layers lediglich Damage-Bits auf den Layern setzen und sonst gar nichts weiter tun. Nur intuition weiß, wann diese Bit überprüft werden müssen, nämlich nach jeder Window resize/move/stacking Operation, bzw. jeder anderen Operation, die die Layer verändern kann.

Deshalb darf keine Anwendung die Layer direkt manipulieren, sondern ausschließlich intuition-Funktionen benutzen.


Was hat bitteschön, der Layer->Window Zeiger mit Zeichenoperationen zu tun?
Nochmals, dieser Zeiger dient einzig und alleine zur Eingabestromumleitung.
Auch solltest Du nicht außer Acht lassen, dass man Requester (unsichtbare, mit einer Größe von 0x0 Punkten) zum Blockieren des Eingabestroms für normale Fenster verwendet, die jegliche Auffrischungsnachricht für ein Fenster solange blockieren, wie der Requester aktiv ist. Kommt dadurch das Erscheinungsbild des Schirms durcheinander?


Zitat:
@Holger

Was ist eigentlich mit dem selten benutzten Feature der "Requester"?


Sehr umständlich zu handhaben...
Requester, sofern man kein eigenes Layer generiert, operieren im Layer des Fensters dass man bei der Initialisierung angibt, sprich eine so genannte Clipping Rectangle wird verwendet und somit sind Zeichenoperationen auf das darunter liegende Fenster beschränkt.


Zitat:
@Holger

...gäbe es gar keinen Grund, Hacks zu benutzen...


Frag' mal einen MorphOS oder AmigaOS4 Entwickler, ob es sich hierbei um einen Hack handelt oder um ein Vorgehen, das systemkonform ist. Ich würde auf letzteres tippen.


Lade neues Beispiel (inkl. Quellcode hoch): GoInActive.lha
Bitte, steinigt mich nicht für das lausige Beispiel und den verwendeten Quellcode; hatte leider nicht viel Zeit...


Grüße


--
Stupid mistakes are always made by others -
we only make unavoidable errors
 
jolo   Nutzer

26.10.2008, 11:59 Uhr

[ - Direktlink - ]
Thema: Keine Fenster Aktivierung bei Klick
Brett: Programmierung

Hi!


Zitat:
@Der_Wanderer

Ich dachte nur, vielleicht kann ich das alles direkt im Kind-Fenster emfangen, dann gibt es keine Doppeldeutigkeit, was mit dem Klick gemeint ist. Der klick kann ja auch bedueten, dass ich ein Gadget im Elternfesnter betätigen will.


Nö, wennste ( bin Niederrheiner, wir sprechen so :) ) schon den Zeiger für den Eingabestrom Deines Kindfensters auf Dein Hauptfenster "verbiegst", kriegtste ( :) ) auch die die Nachricht dort, wo der verbogene Zeiger hinzeigt; sprich Dein Hauptfenster.

Allerdings existiert eine elegante Methode, um herauszufinden, ob nun irgendein Mausklick Dein Hauptfenster tangiert oder eines Deiner Kindfenster. Diesen Vorgang beschreibe ich weiter unten.


Zitat:
@Der_Wanderer

Solange muss halt das Elternfenster Disabled sein, was aber ja auch ok ist.


Wozu?
Du kannst immer unterscheiden (kommt noch...), ob ein Mausklick in Deinem Hauptfenster stattfindet oder in einem Kindfenster.
Falls der Klick im Hauptfenster gemacht wurde, schließt Du einfach das Kindfenster.


Zitat:
@Der_Wanderer

Diese Technik bräuchte man für sämtliche Gadgets oder Menus, die über das Elternfenster hinausladen können, also z.B. für den Start Button eines Startmenu's oder andere PopUp Menus, Drop-Down Listen etc.


Solange Du Menüs oder Knöpfe, die von Intuition bzw. GadTools erstellt und verwaltet werden, ausschließlich in Deinem Hauptfenster darstellst, wirst Du keinerlei Probleme bekommen. Erst wenn Du versuchst, Knöpfe (Gadgets) oder Menüs in einem Deiner Kindfenster darzustellen sowie diese anzuwählen, wirst Du feststellen, dass diese tot sind solange der Layer->Window Zeiger nicht den Eingabestrom auf das betreffende Kindfenster umlenkt - und somit wieder das Hauptfenster inaktiv macht, was wir ja nicht wollen.
Dementsprechend musst Du für alle Deine Kindfenster Deine eigenen Objekte darstellen und verwalten, ohne die Hilfe von Intuition oder GadTools.
Dein Hauptfenster, solange alle Deine Kindfenster inaktiv sind, kann Dir nur die Mauskoordinate sowie das Drücken der linken bzw. rechten Maustaste sowie Tastatureingaben melden, mehr nicht. Nicht ob irgendein Menüeintrag (GadTools-Menü) oder Knopf gedrückt wurde.
Wenn ich Dich aber richtig verstanden habe, stellt dies kein Problem für Dich dar?


Zitat:
@Der_Wanderer

Ich frage mich nur wie "legal" (und somit Kompatibel) das verbiegen des Window Pointers ist, oder ob man das schon als "Hack" werten muss.


Es ist die einzige mir bekannte Maßnahme um ein SuperBitMap-Layer mit einem Fenster zu koppeln. Dies ist auch so offiziell von Commodore Amiga publiziert worden, dementsprechend ist es kein Hack.
Allerdings erstellt man hierbei die Zeichenfläche (Bitmap und Layer) von Hand und erst dann setzt man den Zeiger in der Layer-Struktur auf ein geöffnetes Fenster.
Es ist auch nicht so, dass man den Window-Zeiger verbiegt, sondern nur in die Layer-Struktur das Empfangsfensters einträgt, im Falle dass der freche Nutzer die Maus zum Linksklicken benutzt und somit Intuition einen Anhaltspunkt hat, welche Zeichenfläche betroffen ist und ob der freche Nutzer unter Umständen eine andere Zeichenfläche nutzen möchte, d.h. er möchte ein anderes Fenster zur Eingabe auswählen und somit aktivieren.
Die Window-Struktur ist *das* Bindeglied zwischen dem Input-Task und den einzelnen Zeichenflächen, mehr nicht.
Layers sind die eigentlichen Grundgerüste für das, was wir Fenster nennen. Aber, vor lauter Fenstern sieht man die Layers nicht! :)


Zitat:
@Holger

Dann kannst Du aber nicht verhindern, dass das Elternfenster deaktiviert wird.


Doch, kann man. Es ist egal wie viele Fenster man öffnet, entscheidend ist nur, ob die geöffneten Fenster einen Zeiger auf das zu aktivierende Fenster innerhalb der Layer-Struktur setzen. Ein Fenster kann ja nur explizit (ActivateWindow()) oder mittels Linksklick aktiviert werden - und ausschließlich dazu dient dieser ominöse Zeiger in der Layer-Struktur (wer wird bei einer Aktivierung informiert bzw. wer bekommt den Eingabestrom ab: Layer->Window!). Ist Layer->Window == NULL wird dementsprechend "niemand" informiert.


Zitat:
@Holger

Aber ob das mit dem Refresh auch noch korrekt funktioniert?


Ja. Egal ob man den Zeiger innerhalb der Layer-Struktur ändert, die Layer-Struktur bleibt intakt und die Graphics- bzw. die Layer-Bibliothek kann den Refresh ausführen. Intuition ist nicht zuständig für die Erneuerung von Layern - sie kann es nur veranlassen bzw. hinauszögern.
Ist leider ein zu komplexes Thema als dass ich es in ein paar Zeilen abhandeln könnte.


Jetzt mal ein konkretes Beispiel:
Man öffnet ein Fenster ganz gewöhnlich mit all seinen speziellen Eigenschaften und den IDCMP-Flaggen, die Benachrichtigungen auslösen sollen. Dementsprechend haben wir unser Hauptfenster. :)

Nun öffnet man das Kindfenster, mit oder ohne irgendwelche Angaben von IDCMP-Flaggen; ist eigentlich egal. Bei Angaben von IDCMP-Flaggen, die so nicht im Hauptfenster vorhanden sind, muss natürlich das Hauptfenster mittels ModifyIDCMP() mitgeteilt werden, dass auch andere als die ursprünglich spezifizierten Flaggen eine Benachrichtigung auslösen sollen.
Anbei, bitte nicht IDCMP_INACTIVEWINDOW oder IDCMP_ACTIVEWINDOW spezifizieren falls ein und derselbe MsgPort für das Hauptfenster und die Kindfenster verwendetet wird, ansonsten ist aus ersichtlichen Gründen ein Systemabsturz nicht fern! :)

Bei der Initialisierung der Fensterbeschreibung (z.B. OpenWindowTagList()) wird eine Aktivierung des Fensters unterbunden (mittels "WA_Activate, FALSE"). Ansonsten deaktivieren wir beim Öffnen des Kindfensters das Hauptfenster... Ist wohl nicht gewollt. ;)

Falls das Öffnen klappte, haben wir ein Fenster, welches bei Angaben ohne IDCMPs (siehe oben) *keinen* eigenen MsgPort besitzt.
Also erlauben wir dem Kindfenster den MsgPort des Hauptfensters zu benutzen:
C code:
if (Kindfenster->UserPort == NULL)
    Kindfenster->UserPort = Hauptfenster->UserPort;


Jetzt müssen wir uns aber beeilen den Window-Zieger des Layers zu verbiegen, ansonsten wird ein Mausklick innerhalb des Kindfensters dieses aktivieren und unser ganzes Vorhaben geht den Bach runter:
C code:
Kindfenster->WLayer->Window = Hauptfenster;


So, diese Arbeit ist getan; ein Klick in das Kindfenster sendet eine Nachricht ans Hauptfenster.

Bleibt noch das Problem mit den Mauskoordinaten.
Da alle Nachrichten an das Hauptfenster gesendet werden, müssen wir von diesem ausgehen um die Mauskoordinaten auf das Kindfenster umzumünzen. Hört sich aber schwieriger an als es ist:

Unser Hauptfenster bekommt relative Koordinaten zum Ursprung seines Fensters, dementsprechend immer relativ zur oberen, linken Ecke (0,0).
Addieren wir hier die obere, linke Ecke, haben wir die absolute Koordinate innerhalb des Schirms (Screen). Bei Verwendung von OS1.x müssen wir aber den Overscan-Modus berücksichtigen, was bei Benutzung von OS2 und höher durch das System erledigt wird. Ich gehe hier mal von OS2 und höher aus:
C code:
struct InutiMessage *msg;
LONG x, y;            /* Muss mit Vorzeichen arbeiten (speziell für OS1.x) */
struct Layer *welches;

msg = (struct IntuiMessage *) GetMsg( Hauptfenster->UserPort);
if (msg)
{
    if (msg->Class == IDCMP_MOUSEMOVE)
    {
        x = (LONG) msg->MouseX;
        y = (LONG) msg->MouseY;
        /* x,y relativ zur linken, oberen Ecke des Hauptfensters */

        x += Hauptfenster->LeftEdge;
        y += Hauptfenster->TopEdge;
        /* x,y absolut im Display */

        /* Nun, welches Layer liegt unterhalb des Mauszeigers? */
        welches = WhichLayer( Hauptfenster->WLayer->LayerInfo, x, y);
        if (welches)
        {
            /* Berechne relative Koordinate für das betreffende Layer */
            x -= (LONG) welches->bounds.MinX;
            y -= (LONG) welches->bounds.MinY;
            /* "bounds" ist eine Struktur innerhalb der Layer-Struktur,
               die den Ursprung des Layers im Display beschreibt sowie
               dessen Ausmaße. */
        }
        else
        {
            x = 0;
            y = 0;
        }
    }

    if (msg->Class == IDCMP_MOUSEBUTTONS)
    {
    /* Watt tun bei 'nem Klick? ( ;-) ) */
    }
}


So, nun kann man noch eine Abfrage einbauen, ob eins der eigenen Kindfenster gemeint ist oder das Hauptfenster.
Falls die Nachricht für das Hauptfenster ist, schließt man einfach die Kindfenster oder das Kindfenster:
C code:
void SchließeKindFenster( struct Window *kindFenster, struct Window *hauptFenster)
{
    struct Message *msg;

    Forbid();

    /* Teilen wir uns einen MessagePort mit dem Hauptfenster? */
    if (kindFenster->UserPort == hauptFenster->UserPort)
    {
        kindFenster->UserPort = NULL;    /* Extrem wichtig - ansonsten gibt
                                            CloseWindow( HauptFenster) den MsgPort
                                            ein zweites Mal frei --- CRASH! */
    }
    else
    {
        /* Haben eigenen Port... */

        while ( (msg = (struct Message *) GetMsg( kindFenster->UserPort)) )
            ReplyMsg( msg);
        ModifyIDCMP( kindFenster, 0)
    }

    /* Man könnte noch ein:
    kindFenster->WLayer->Window = kindFenster;
       einbauen, muss man aber nicht. Es werden ja keine Nachrichten mehr empfangen. */

    Permit();

    CloseWindow( kindFenster);
}


Das war's. :)


Habe eine Testdatei hochgeladen: ContextMenus.lha


Grüße


--
Stupid mistakes are always made by others -
we only make unavoidable errors
 
jolo   Nutzer

20.10.2008, 20:01 Uhr

[ - Direktlink - ]
Thema: Keine Fenster Aktivierung bei Klick
Brett: Programmierung

Zitat:
Original von Der_Wanderer:
Aber geht das nun was ich vorhabe oder nicht?



'Tschuldige dass ich erst so spät antworten kann, leider bin ich im Moment zeitlich sehr eingeschränkt.

Zu Deiner Frage:
Theoretisch müsste es möglich sein. Einschränkend muss ich aber sagen, dass ich Deine, Dir selbst gestellte Aufgabe, so noch nicht programmiert habe. Unter Umständen, bei Verwendung von BOOPSI-Klassen oder Intuition-Gadgets könnte es aber zu Problemen kommen, da diese nach einer Window-Struktur oder einer Requester-Struktur verlangen, die bei der Initialisierung vorhanden sein muss.
Ich müsste es mal selber ausprobieren um hier eine definitive Aussage treffen zu können.
Leider ist es eine Aufgabe, die ich erst kommendes Wochenende machen könnte; vielleicht bist Du hier schon ein wenig weiter als ich und kannst mir mitteilen, wie weit Du gekommen bist?


Gruß
--
Stupid mistakes are always made by others -
we only make unavoidable errors
 
jolo   Nutzer

18.10.2008, 18:33 Uhr

[ - Direktlink - ]
Thema: Keine Fenster Aktivierung bei Klick
Brett: Programmierung

Zitat:
Original von Der_Wanderer:

Das Fenser empfaengt dann aber keine IDCMP Messages, hab ich recht?


Hi.

Du musst zwischen Zeichenoberflächen (Layers) und Fenstern (Windows) unterscheiden.
Layers sind Grafik-Bausteine (struct Layer) und haben nichts mit Intuition im herkömmlichen Sinn zu tun. Intuition ist nur ein verlängerter Arm des Input-Devices und verlangt dementsprechend nach einer eigenen Struktur (struct Window). Ereignisse des Input-Device treten auch ohne Fenster auf, jedoch leitet das Input-Device unter Normalbedingungen diese Ereignisse an Intuition weiter, wobei Intuition aufgrund der Fenster-Struktur (Window) entscheidet, an welchen Message-Port die Nachricht bzw. das Ereignis gesendet wird.


Zitat:
Das geht nur, wenn es aktiv ist, oder?

Hat mit Aktivierung eines Layers nichts zu tun. Im Prinzip gibt es nämlich keine aktiven Layers sondern nur aktive Fenster. Layer = Grafik, Window = Input.
Ein Layer ist nichts anderes als ein Teil einer BitMap (Screen) oder die Zeichenfläche einer ganzen BitMap (SuperBitMap-Layer), aber immer ausschließlich eine Zeichenfläche. Intuition dockt seine Windows-Struktur an eine vorhandene Layer-Struktur an, damit Intuition ermitteln kann, welchem Programm (Message-Port) es eine Nachricht zukommen lassen muss, falls ein Ereignis auftaucht. Dazu geht Intuition davon aus, dass das Layer, welches das aktive Fenster repräsentiert, die Ereignisse erhalten soll.

Nachtrag:
Layers sind Lösungen um mehreren gleichzeitig laufenden Programmen exklusive Zeichenflächen zu bieten, ohne dass sich der Programmierer um die Bereichsgrenzen kümmern müsste, d.h. dass er nicht unabsichtlich fremde Zeichenbereiche überschreibt/übermalt, aber Layers haben rein gar nichts mit Ereignissen zu tun. Layers werden von Intuition nur "vergewaltigt", damit Intuition cleverer erscheint als es ist. :)


Gruß

--
Stupid mistakes are always made by others -
we only make unavoidable errors
 
jolo   Nutzer

16.10.2008, 18:00 Uhr

[ - Direktlink - ]
Thema: Keine Fenster Aktivierung bei Klick
Brett: Programmierung

Zitat:
Original von Der_Wanderer:
Hallo!

Kann ich irgendwie verhindern, dass mein Fenster aktiv wird, wenn der User mit der Maus hineinklickt?

Beim Amistart ist das so, muss also irgendwie gehen.


Innerhalb der Layers-Struktur den Window-Zeiger auf ein Fenster Deiner Wahl verbiegen oder Nullen.

Gruß


 
jolo   Nutzer

19.12.2007, 21:25 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

Hallo.

Ich habe mit Hilfe von Maik die Bibliothek dahingehend zum Laufen gebracht, dass nun diese Knackser während der Aufnahme und dem gleichzeitigen Betrieb eines kommerziellen Programms nicht mehr aufgezeichnet werden.

Ein kleiner Trick hilft hier - meines Wissens nach von Bert Jahn (WHDLoad) - und als Interrupt Acknowledge Fix bekannt:
Unter schnellen Prozessoren (68040 und höher) kann es passieren, dass ein Interrupt-Acknowledge unter geht, falls kurzeitig danach der Supervisor-Modus (Interrupts werden im Supervisor-Modus abgearbeitet) verlassen wird (rte). Was hier hilft, ist vor dem eigentlichen Bestätigen (Acknowledge) eines Interrupts und verlassen des Supervisor-Modus eins der CIA-Register oder eins der Custom-Register auszulesen.
Dann klappt es wieder mit der Bestätigung (im ROM). :)

Maik hat mich mit der Nase darauf gestoßen... :)

Ich ziehe meinen Hut vor Bert Jahn - ich selber wäre nie auf die Idee gekommen...


Neue Version inklusive Quellcode kann unter http://www.amimedic.de heruntergeladen werden.


Gruß
 
jolo   Nutzer

05.12.2007, 19:01 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@Holger:

Hi.

Zitat:
Es gibt viele mögliche Fehlerquellen.

Das ist ein wunder Punkt - Maik und ich probieren derzeit ein wenig herum, da anscheinend Störungen von außen die Daten am parallelen Port beeinträchtigen.

Auch habe ich zwei Fehler in der Ire-Bibliothek ausgemacht:
1. Der CIA-A Interrupt wurde mit einer falschen Maske gestartet.
2. INTENA und INTREQ wurden vertauscht - was unter einem echten Chip-Satz fatale Folgen haben kann.

Dementsprechend habe ich das schon korrigiert - INTENA und INTREQ werden jetzt auch nicht mehr benutzt.

Wenn's denn irgendwann so läuft wie es laufen soll, wird der Quell-Code beigefügt - im Moment sind zu viele #ifdefs drin und ein Mix aus Deutsch und Englisch...


Zitat:
Auch, wenn Du das bereits korrigiert hast, bleibt ja immer noch der Fakt, dass Deine Daten von Dir mit demselben Timing generiert werden, mit dem Du hinterher liest, während der echte Parallelport vom Timing des Lesens unabhängig funktioniert [...]

Das ist richtig - allerdings fällt mir keine bessere Lösung ein um das hier unter WinUAE auszuprobieren.
Ich könnte natürlich von Windows aus Daten auf den Port zaubern - aber um ehrlich zu sein, ich hatte schon mal gravierende Probleme bezüglich des Timings unter XP dass ich da lieber die Hände von lasse...


Zitat:
[...] wenn man z.B. die Ressource nicht korrekt gelockt hat

In neueren Versionen wird der parallele Port gelockt - allerdings hat das meines Wissens nach keinen Einfluss auf irgendwelche Werte, da hier nur sichergestellt wird, dass ausschließlich ein Nutzer einen Baustein (Centronics) verwenden kann.

Was ich derzeit mache, ist das DDRA und das DDRB Register zu initialisieren, abgesehen vom Generieren des Interrupts.

Maik hat mittels eines anderen Digitizer herausgefunden, dass die Störgeräusche auch unter diesem aufgezeichnet werden.
Verantwortlich dafür scheint ein kommerzielles Programm zu sein, welches einen CIA-B Timer-B Interrupt generiert um eine Hardware-Erweiterung nutzbar zu machen.
Verantwortlich ist allerdings das falsche Wort: Ich gehe davon aus, dass dieses kommerzielle Programm alles richtig macht, jedoch es dadurch zu Störungen des Sound-Samplers (sprich Digitizer) kommt. Und hier muss ich jetzt irgendwie eine Lösung finden, die beiden, also diesem kommerziellen Programm als auch dem Digitizer der Ire-Bibliothek gerecht wird.
Mal schauen ob ich's hinbekomme.


Gruß

 
jolo   Nutzer

01.12.2007, 10:14 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi.

Zitat:
Was glaubst Du?!?!? Ich bin kein Hellseher.
Zitat:
der code steht doch oben:
code:
junk&=SetIRQAttrI&(ihandle&,4)

das war doch was du meinst?


Für mich sind das Senden von Infrarotsignalen und das Digitalisieren zwei Paar Schuhe - dementsprechend zwei Programme.
Beim Senden von Infrarotsignalen bist Du auf Signale vom Interrupt angewiesen um das Timing hinzubekommen; beim Digitalisieren aber nicht.
Das Beispiel, dass Du aufzeigst, dient dem Digitalisieren - nicht dem Senden von Infrarotsignalen.


Zitat:
Ja, mach das. Dann habe ich zumindest einen Anhaltspunkt.
Zitat:
Hab deine Email Adresse aber nicht...


Habe übers Forumsformular Dir meine Email-Adresse zukommen lassen.


Zitat:
Die Funktion TIMER ist mehr als ungenau.
Zitat:
Das muss an WinUAE liegen.


Nee, daran dass man oft bei der Amiga-Programmierung auf Programmierer stößt, die ein bestimmtes Verhalten voraussetzen - was aber nie von Commodore als solches dokumentiert wurde.
Mache solche Fehler selber…


Zitat:
Ja, ist halt so eine sache mit UAE<->Amiga was auf dem einen läuft tuts manchal nicht auf dem anderen.

Eigentlich schon. Da aber Deine Timing-Intervalle an die Grenzen des Machbaren stoßen, wird's ein wenig kritisch.


Gruß
 
jolo   Nutzer

30.11.2007, 19:47 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi.

Zitat:
Leider wurden hier auf meiner Maschine Abschnitte doppelt wiedergegeben [...]
Zitat:
Du hast doch nur UAE oder?


Ja, schon. Trotzdem kann ich es testen. Habe drei Möglichkeiten:
1) Die Bibliothek besteht zusätzlich aus einer Audio-Datei (2,2 Mbytes). Im Interrupt wird nicht das Datenbyte vom parallelen Port gelesen sondern das entsprechende Byte in der Audio-Datei.
2) Am Ende des Interrupt-Codes wird ein Byte der Audio-Datei auf den parallelen Port geschrieben.
3) AudioGrabber.asm wurde abgewandelt um aus einer Audio-Datei das entsprechende Byte auf den parallelen Port zu schreiben - hat allerdings den Nachteil, dass damit nur Frequenzen bis zu 7 kHz verwendet werden können (wie gesagt, WinUAE ist bei der Emulation des Chip-Satzes nicht so schnell wie die echte Hardware).


Zitat:
Hast Du das normale Signal-Handling abgeschaltet? - Dann kann es nicht funktionieren.
Zitat:
Ich glaub schon.


Was glaubst Du?!?!? Ich bin kein Hellseher.


Zitat:
Wie oft pro Sekunde kommen diese vor (schätzungsweise)?
Zitat:
5 mal vielleicht. Das variiert. Ich kann dir eine Datei auch Mailen.


Ja, mach das. Dann habe ich zumindest einen Anhaltspunkt.


Zitat:
t! = TIMER-t! REM --- Und Ende festhalten (TIMER ist seeeehr ungenau:
REM --- bei 200004 Bytes 13,76 Sek. mit Stoppuhr aber 16,18 Sek. laut TIMER)!
Zitat:
Bei mir sinds 10.1x Sek.


Ich kann nicht mit 22 kHz digitalisieren - sondern bis maximal 14. Dementsprechend sind 200004 Bytes durch 14840 Bytes/Sekunde 13,4 Sekunden und nicht 16,1. Die Funktion TIMER ist mehr als ungenau.


Zitat:
Hier funktioniert es.
Zitat:
Ja, funktioniert, leider nur so wie meins. Also mit Knackser.


Komisch.
Hier funktioniert es ohne Knackser - dementsprechend muss ich etwas übersehen haben, was WinUAE ignoriert die originale Hardware aber nicht.


Gruß
 
jolo   Nutzer

28.11.2007, 22:35 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi.

Zitat:
Hat das ASM Beispiel und das C-Beispiel doch auch nicht, solange man den Puffer so lässt wie er ist.

Leider wurden hier auf meiner Maschine Abschnitte doppelt wiedergegeben - das habe ich auf ein Minimum in der letzten Version reduzieren können (60 Hz / 50 Hz Timing).


Zitat:
Nur wenn Deine Routine innerhalb des Interrupt aufgerufen wird (usersCode, usersData). Ansonsten, wenn's auf Prozess-Ebene läuft, nicht.
Zitat:
Ja, dachte ich mir auch so, geht aber nicht.


Hier geht's.

Hast Du das normale Signal-Handling abgeschaltet? - Dann kann es nicht funktionieren.


Zitat:
Ja, wie ich sagte es gibt diese (Intensiv) Knackser mit aktiver und deaktiver Audio-Ausgabe.

Wie oft pro Sekunde kommen diese vor (schätzungsweise)?


Zitat:
Hört sich aber so gut an wie Multimon bis auf die (kleinen) Knackser.

Hier funktioniert das nicht so gut.


Zitat:
Jetzt geht die Monitorausgabe nicht mehr...

Was heißt Monitorausgabe?



code:
REM  Zwei Macken sind mir in MBasic aufgefallen:
REM  Umlaute mag es gar nicht und CALL funktioniert nicht so wie in AmigaBasic

    REM ON BREAK GOTO FastOut
    REM BREAK ON

    LIBRARY "exec.library"
    DECLARE FUNCTION AllocVec&() LIBRARY
    DECLARE FUNCTION FreeVec&() LIBRARY
    DECLARE FUNCTION xWait&() LIBRARY

    LIBRARY "dos.library"
    DECLARE FUNCTION xOpen&() LIBRARY
    DECLARE FUNCTION xWrite&() LIBRARY
    DECLARE FUNCTION xClose&() LIBRARY
    DECLARE FUNCTION Delay&() LIBRARY

    LIBRARY "ire.library"
    DECLARE FUNCTION InitIRQ&() LIBRARY
    DECLARE FUNCTION StartIRQ&() LIBRARY
    DECLARE FUNCTION DeleteIRQ&() LIBRARY
    DECLARE FUNCTION GetIRQAttrI&() LIBRARY
    DECLARE FUNCTION SetIRQAttrI&() LIBRARY

    LIBRARY OPEN "exec.library"
    LIBRARY OPEN "dos.library"
    LIBRARY OPEN "ire.library"


    CONST PGROESSE& = 40000    REM --- Puffergroesse
    CONST Hz&       = 14880    REM --- Frequenz


    CONST MEMF_CLEAR& = 65536

    CONST MODE_NEWFILE&     = 1006
    CONST SIGBREAKF_CTRL_C& = 4096


    CONST THIS_SIGBIT_DBUF_FULL& = 1
    CONST THIS_DBUF_FULL&        = 16
    CONST THIS_IRQ_SIGBIT&       = 2
    CONST DISABLE_SIGNALLING&    = 4
    CONST ENABLE_SIGNALLING&     = 8
    CONST THIS_FREQUENCY&        = 32
    CONST THIS_PERIOD&           = 256
    CONST THIS_SAMPLE_POS&       = 1024
    CONST TOGGLE_DMA_ACCESS&     = 64
    CONST TOGGLE_MAKE_AUDIBLE&   = 128
    CONST TOGGLE_16BIT&          = 512


    REM $NOEVENT
    REM $NOOVERFLOW
    REM $NOLINES


    REM --- Los geht's
    REM POKEB &hBFD000,2    --- Paper Out signalisieren
    POKEB &hBFE301,0     REM --- Parallel-Port auf Eingang

    Index& = 0    REM --- Dateinamenerweiterung

    MySample1& = AllocVec&( PGROESSE&, MEMF_CLEAR&)
    MySample2& = AllocVec&( PGROESSE&, MEMF_CLEAR&)
    IF MySample1& <> 0 AND MySample2& <> 0 THEN

        DIM pufferliste&(12)
        pufferliste&(0) = MySample1&
        pufferliste&(1) = MySample2&
        pufferliste&(2) = 0

        REM --- Interrupt und benötigte Strukturen initialisieren
        ihandle& = InitIRQ&( Hz&, SADD("MBasic Digitizer"+CHR$(0)), 0, 0, VARPTR( pufferliste&(0) ), PGROESSE&)

        IF ihandle& <> 0 THEN
            REM --- Signal-Bit für "Puffer-Ist-Voll" holen und in Maske wandeln
            sigmask& = ( 1 << GetIRQAttrI&( ihandle&, THIS_SIGBIT_DBUF_FULL&) )

            REM --- Normales Interrupt-Signal-Handling ausschalten
            junk& = SetIRQAttrI&( ihandle&, DISABLE_SIGNALLING&)

            REM --- Audio-Ausgabe aus/anschalten
            REM junk& = SetIRQAttrI&( ihandle&, TOGGLE_MAKE_AUDIBLE&)

            REM --- DMA Audio-Ausgabe einschalten
            junk& = SetIRQAttrI&( ihandle&, TOGGLE_DMA_ACCESS&)


            junk& = Delay&( 50)    REM --- 1 Sekunde warten


            REM --- Interrupt starten
            junk& = StartIRQ&( ihandle&)

            DO
                PRINT "Starte Timer..."
                t! = TIMER    REM --- Zeit des Starts festhalten

                REM --- Warten bis irgendetwas passiert...
                received& = xWait&( sigmask& OR SIGBREAKF_CTRL_C&)

                IF received& AND SIGBREAKF_CTRL_C& THEN
                    EXIT LOOP
                ELSE
                    t! = TIMER-t!    REM --- Und Ende festhalten (TIMER ist seeeehr ungenau:
                    REM --- bei 200004 Bytes 13,76 Sek. mit Stoppuhr aber 16,18 Sek. laut TIMER)!

                    CALL WriteBuffer( GetIRQAttrI&( ihandle&, THIS_DBUF_FULL&), PGROESSE&)

                    REM --- Benötigte Zeit wiedergeben
                    PRINT PGROESSE& "Bytes wurden innerhalb von" t! "Sekunden mit";
                    PRINT GetIRQAttrI&( ihandle&, THIS_FREQUENCY&) "Hz digitalisiert."
                    PRINT "Diese Angabe ist mit Vorsicht zu genießen!"
                END IF
            LOOP

            REM --- Interrupt beenden und Ressourcen freigeben
       FastOut:
            junk& = DeleteIRQ&( ihandle&)
       END IF


    END IF

    IF MySample2& <> 0 THEN
       REM --- Puffer freigeben
       junk& = FreeVec&( MySample2&)
    END IF

    IF MySample1& <> 0 THEN
       REM --- Puffer freigeben
       junk& = FreeVec&( MySample1&)
    END IF


    REM --- Alle geoeffneten Bibliotheken schliessen
    LIBRARY CLOSE

    END
    REM ---- PROGRAMMENDE ----



    REM --- Pufferinhalt als Datei schreiben.
    SUB WriteBuffer( adr&, xlen&)
    fh& = xOpen&( SADD("RAM:sample_raw"+STR$(Index&)+CHR$(0)), MODE_NEWFILE&)
    IF fh& <> 0 THEN
        junk& = xWrite&( fh&, adr&, xlen&)
        junk& = xClose&( fh&)
    END IF

    Index& = Index& + 1

    END SUB


Habe die Demo-Version von MBasic runtergeladen und Dein Programm abgewandelt. Hier funktioniert es.


Gruß
 
jolo   Nutzer

28.11.2007, 00:15 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi.

Zitat:
[...] wie willst Du dann von Basic aus vorgehen?
Zitat:
Einfach einen Wert nehmen der grade Teilbar ist.


Das wird nicht funktionieren, da beide, die Audio-Hardware und die CIA-Chips unterschiedliche Taktfrequenzen haben.


Zitat:
Das dürfte normal sein - das Timining-Verhalten ist bei DMA-freier Wiedergabe was gänzlich anderes als mit DMA.
Zitat:
Warum eigentlich ohne DMA? Besser als das ASM beispiel und hört es sich nicht an.
Das Timing war doch ohnehin exakt.



Ja, Klangeinbußen gibt es - aber das Timing (CIA zu Audio) war nicht akkurat (50 Hz vs. 60 Hz...).
Zudem hat die DMA-freie Audioausgabe keinerlei Probleme mit Abschnitten die doppelt wiederholt werden.
Es wird analog das ausgegeben, was rein kommt.


Zitat:
Heißt das, dass Deine eigenen Routinen zum Digitalisieren diese Knackser beinhalten und TimerIRQ solche Mätzchen nicht macht?
Zitat:
Ich glaube schon. Muss ich bei der Lib verwendung ohne eigenen Code etwa die Register sichern?


Nur wenn Deine Routine innerhalb des Interrupt aufgerufen wird (usersCode, usersData). Ansonsten, wenn's auf Prozess-Ebene läuft, nicht.


Zitat:
Das Timing wurde komplett geändert.
Zitat:
Habe ich jetzt beim Infrarot-Senden eine Abweichung dadurch?


Nein, für normale Interrupt-Aufgaben, also alles ohne Digitalisierung, bleibt alles beim Alten.
Nur für die Audio-Ausgabe wird eine Neuberechnung durchgeführt.

Mir ist allerdings ein Malheur passiert und ich habe eine Version mit halber Ablaufverfolgung hochgeladen, die eigentlich nur für mich bestimmt war. Dementsprechend müsste es bei Deiner Version zu Störungen bei der Wiedergabe kommen (Abschnitte werden des Öfteren wiederholt).


Zitat:
Es wäre nett, wenn Du mir sagen könntest, ob mittels Digi digitalisierte Dateien und mittels SampleEngine wiedergegebene Dateien korrekt sind - d.h. ob keine Fehler (Blips) darin enthalten sind.
Zitat:
Also bei Basic keine änderung. Ja, Fehler sind relativ.
Kleine störungen sind noch drin, also nicht so gut wie mit dem ASM-Beispiel. Samplemanager sagt was von über 14000 "crackles" wobei das sehr relativ zu sehen ist.



Zu 1)
Du digitalisierst auf Prozess-Ebene? Dementsprechend benutzt Du von Basic aus einen Interrupt, um 22000-mal in der Sekunde ein Signal zu empfangen - und wenn es eintrifft liest Du den Wert der am parallelen Port anliegt?
Wenn dem so ist kann ich Dir jetzt schon sagen, dass Du das niemals auf Prozess-Ebene schaffen wirst - okay, vielleicht mit einem neuen OS und einer CPU die um ein vielfaches schneller ist als Deine 68060 - aber nicht mit der jetzigen Software und Hardware.

Extra für diesen Zweck habe ich einen Digitizer auf Interrupt-Ebene entworfen. Er sollte Dir die Arbeit abnehmen.

Zu 2)
Wie schon im letzten Beitrag von mir geschildert, soll die Audio-Ausgabe nur grob einen Überblick über die tatsächliche Digitalisierung geben. Leider, wie oben geschildert, habe ich eine Version hochgeladen, die mit dem falschen Compiler-Aufruf erstellt worden ist - hier ist die Wiedergabe nicht ganz so genau wie bei der Version die Du eigentlich verwenden müsstest.


Um eine Ablaufverfolgung zu starten, löscht die Version die Du jetzt besitzt, alle Audio-Interrupt-Quellen und wartet solange, bis diese durch die Hardware neu gesetzt wurden. Dementsprechend kann ich exakt bestimmen, wie viele Bytes pro Sekunde von der Audio-Hardware ausgegeben werden, bzw. wie viele Bytes pro Sekunde der Interrupt zu langsam oder zu schnell läuft. Der Nachteil der damit erkauft wird, ist, dass die Audio-Hardware kurzzeitig aus dem Tritt gebracht wird, da sie selber auf diese Audio-Interrupt-Quellen angewiesen ist, bzw. für einen Störungsfreien Ablauf diese Quellen nicht zurückgesetzt werden dürfen.


SampleManager (hallo Thilo - nettes Programm!) habe ich mal runtergeladen und über die Dateien gejagt, die ich hier digitalisiere. Es sagt mir kein Crackle (Knistern?). Dementsprechend gehe ich davon aus, dass der Interrupt-Code in Ordnung ist. Bleibt nur noch die Frage was mit den Daten vom parallelen Port geschieht.
Ich kann mir nicht vorstellen, dass der CIA-A Interrupt irgendwelchen Einfluss auf die Daten vom parallelen Port hat, da ansonsten das von Commodore vorgesehen Handshake zwischen CIA-A und CIA-B beim Senden oder Empfangen von Daten am parallelen Port gestört sein würde - und ich das als Hardwarebug bezeichnen würde, der mindestens mit dem Erscheinen des ECS-Chipsatz hätte verschwunden sein müssen.
Zudem bist Du Dir auch nicht sicher, ob es an Deinem Programm liegt oder an der Bibliothek. Daher würde ich Dich bitten, mir Klarheit zu verschaffen. Tauchen Probleme beim Digitalisieren mittels Digi auf oder nicht?


Zum CIA-B Interrupt:
Meiner Meinung nach sollte dieser gar nicht verwendet werden, jedenfalls nicht bei gleichzeitiger Benutzung der Audio-Hardware - da die Audio-Hardware Interrupts der Ebene 4 generiert und bei der Benutzung eines Level-6 Interrupts diese nicht zum korrekten Zeitpunkt erstellt werden können - womit die Audio-Hardware dann aus dem Tritt kommt und es zu Störungen bei der Wiedergabe kommen muss (jedenfalls geschieht dies hier unter WinUAE). Somit ist das ASM-Beispiel eigentlich ein gutes Beispiel wie man es nicht machen sollte...


Anbei, SetIRQAttrI( ihandle, 512) schaltet vom 8-Bit Modus in den 16-bittigen und umgekehrt. Dementsprechend kannst Du die Audio-Ausgabe über AHI bewerkstelligen, falls Du möchtest.
Um die aktuelle Position in Deinem FAST-RAM Puffer zu erfahren, kannst Du:
GetIRQAttrI( ihandle, 1024) benutzen - es retourniert die Position des aktuellen Samples im Puffer (FAST-RAM) - bei 16-Bit Samples musst Du den Wert mit 2 multiplizieren - dann hast Du die Byte-Position.
Dementsprechend kannst Du z.B. auf Position 32 warten und dann mittels AHI die Audio-Daten ausgeben - falls Du dies möchtest.


Neue Version ohne Ablaufverfolgung wurde hochgeladen.


Gruß
 
jolo   Nutzer

25.11.2007, 15:44 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi.

Zitat:
Ja, aber man könnte dem mit einigem Aufwand entgegentreten - ich persönlich kann aber mit diesen kurzen Blips gut leben, da diese ja nicht als Daten in die FAST-RAM Puffer übernommen werden.
Zitat:
Na wenn ich die Audio-Ausgabe selbst machen kann und das nicht in den Puffer geschrieben wird, bekomme ich das auch
irgendwie in den griff.



Ohne Dir zu nahe treten zu wollen: Wenn ich schon Schwierigkeiten habe dass korrekte Timing hinzubekommen, wie willst Du dann von Basic aus vorgehen?


Zitat:
Der Digitizer-Code funktioniert - und schmiert nicht ab?
Zitat:
Jetzt soweit ja, ins Array Poke't man nicht, da nimmt man =.
Poken macht man dann bei AllocVec bereich.



Höre ich da leichte Kritik bezüglich meiner BASIC-Programmierkenntnisse? ;-)


Zitat:
Sag mir mal ob jetzt die Audio-Ausgabe ansatzweise in Ordnung ist.
Zitat:
Das schnarren ist weg, aber jetzt hört sich es bei 22050 etwa so an wie bei 14000 HZ. Also nicht in der Geschwindigkeit sondern in der Qualität.


Das dürfte normal sein - das Timining-Verhalten ist bei DMA-freier Wiedergabe was gänzlich anderes als mit DMA.
Nichtsdestotrotz ist es die einzige Möglichkeit ein absolut exaktes Timing hinzubekommen.


Zitat:
Ja, per MBasic habe ich diese Knackser die voll in den -127er bereich gehen. Das ist im Puffer(Audioausgabe aus) und bei der Aktiven Audioausgabe so. Beim beiligenden Tool hab ich das nicht mehr vernommen.

Heißt das, dass Deine eigenen Routinen zum Digitalisieren diese Knackser beinhalten und TimerIRQ solche Mätzchen nicht macht?


Habe jetzt so was wie die endgültige Fassung der Bibliothek fertig gestellt.

Das Timing wurde komplett geändert. Es basiert nicht mehr auf 60 Hz Netzspannungen... War ein Fehler zur Berechnung der Periode (Audio-Ausgabe). Jetzt wird die Periode anhand der Frequenz berechnet und danach die Frequenz anhand der Periode. Danach wird aufgrund der neu berechneten Frequenz einer der beiden CIA-A Timer mit dem korrekten Wert initialisiert.

Beispiel: Falls Du 14880 Hz als "callsPerSecond" spezifizierst, wird stattdessen eine Frequenz von 14840 verwandt.
Du kannst das abfragen, indem Du GetIRQAttrI( 32) aufrufst.
Um die Periode zu ermitteln, kannst Du GetIRQAttrI( 256) verwenden.

Als nächstes habe ich die DMA-freie Audio-Ausgabe überarbeitet: Das INTEN-Bit im Interrupt-Kontrollregister wird jetzt immer gelöscht - damit man DMA-freie und DMA-unterstützende Ausgabe während der Audio-Wiedergabe wechseln kann. Hoffentlich hat das keine negativen Seiteneffekte auf den Blitter/Copper…
Das Programm Digi wechselt alle 5 Sekunden den Modus während es digitalisiert.

Voreingestellt ist jetzt der Typ DMA-freie Audio-Ausgabe. Falls Du das nicht willst, musst Du SetIRQAttrI( 64) einmalig aufrufen.

Das Programm Digi digitalisiert wirklich - es schreibt Dateien mit maximal 540000 Bytes in die RAM-Disk - allerdings kann eine einzige Audio-Ausgabe aus mehreren solcher Dateien bestehen. CTRL-C beendet es wie gewohnt.

Habe das Programm SampleEngine beigefügt (dafür muss die noise.library ins LIBS-Verzeichnis), mit dem Du diese Dateien abspielen kannst. Ist allerdings ein Uralt-Tool - könnte ein paar Macken haben. Eine ist z.B. dass die einzuladende Datei komplett ins CHIP-RAM passen muss - ich hoffe Du hast 1 bis 2 MBytes CHIP-RAM?
Wenn keine Audio-Ausgabe erfolgt, kann das an einem Bug im Programm liegen. Einfach solange den Play Button betätigen bis es geht (evt. solange warten, bis der Warten-Mauszeiger verschwindet).

Mit diesem Programm kannst Du verifizieren, dass die Audio-Ausgabe mehr oder weniger unabhängig von dem Digitalisieren ist, was bedeutet, das selbst eine inkorrekte Audio-Ausgabe nicht gleichzusetzen ist mit einer inkorrekten Digitalisierung. Probiere es mal aus - dann verstehst Du was ich meine.

Anbei, DMA-unterstützende Audio-Wiedergabe (also mittels CHIP-RAM Puffer) sollte jetzt seltener einen Abschnitt doppelt wiedergeben - bedingt durch die korrekte 50 Hz Initialisierung.

Ach ja, und zu guter Letzt: Cause() kann doch nicht beliebig oft innerhalb einer Sekunde aufgerufen werden. :(

Es wäre nett, wenn Du mir sagen könntest, ob mittels Digi digitalisierte Dateien und mittels SampleEngine wiedergegebene Dateien korrekt sind - d.h. ob keine Fehler (Blips) darin enthalten sind.


Gruß
 
jolo   Nutzer

23.11.2007, 00:25 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi.

Zitat:
Bei nur 500 MHz würde ich Amithlon empfehlen.

Zitat:
Das kostet doch Geld und hat keine Custom Chip Emu?


Stimmt schon - allerdings *fühlt* sich Amithlon wie ein echter Amiga an.
Ist kein Vergleich zu (Win)UAE.
Da es nicht mehr vertrieben und weiterentwickelt wird und die meisten, die es besitzen, nicht verkaufen/missen wollen, kommt man kaum noch an Amithlon ran.

Zitat:
Meines Wissens nach spielt es keine Rolle beim Lesen von Daten die an der parallelen Schnittstelle anliegen, ob Eingang oder Ausgang spezifiziert wurde; es wird immer der aktuelle Wert der anliegt, zurückgegeben.

Falls ich mich täusche berichtige ich das im Programm-Code.

Zitat:
Am besten ist gar nicht schalten, das kann ich ja in mein Prog machen und L/R wähle ich ja auch selbst.


In Ordnung. Wird gemacht.


Zitat:
Du meinst anstelle des CIA-A Interrupts einen CIA-B?

Zitat:
Ähm, so wie es im ASM-Beispiel ist.


Das Assembler-Beispiel benutzt einen der beiden CIA-B Timer.
Wie Du aus meinen Postings ersehen kannst, möchte ich das Ganze auf Basis der CIA-A Timer belassen und zwar weil dadurch das System nicht bei unsachgemäßer, sprich übergebührlicher Benutzung in die Knie geht. Falls es mit dem CIA-A Timern klappt, lassen wir es so wie es ist, falls allerdings nicht, stelle ich auf CIA-B um.


Zitat:
Also das "kleine" Kacken, vermute ich kommt daher das der CIA-Counter nicht Syncron mit der Wiedergabe läuft.
Man macht ja eine User angabe z.B. 22050 Hz, nun ist das mit den 709379 nicht grade zu Teilen -> abweichung von 0.17138322.


Ja, aber man könnte dem mit einigem Aufwand entgegentreten - ich persönlich kann aber mit diesen kurzen Blips gut leben, da diese ja nicht als Daten in die FAST-RAM Puffer übernommen werden.


Zitat:
Und ja, falls eine Pufferliste spezifiziert wird, also nicht NULL ist, wird die Audio-Hardware in Gang gesetzt.

Zitat:
Benutzt aber Random-Speicherbereiche. Nach einem Neustart spielte es noch daten die vom voherigen Versuch waren


Nee, nur AllocVec() ohne MEMF_CLEAR Flagge - dementsprechend ist der Puffer (CHIP-RAM) in einen undefinierten Zustand - verwende ich, um Initialisierungs-Fehler aufzuspüren. Wird zu einem späteren Zeitpunkt - wenn alles klappt wie es soll, geändert.


Zitat:
Falls Du das nicht wünscht, kann ich das ausbauen.

Zitat:
Ich denke mal, dies ist vom Hauptprogramm sinnvoller.
Sonst wäre es ja nicht so sinnvoll das das Programm die Puffer zur verfügung stellt.



Hier missverstehen wir uns. Deine Puffer (FAST-RAM) werden mit Werten gefüllt - sie werden aber nicht für die Audio-Ausgabe verwendet. Dafür fordert InitIRQ() vom System CHIP-RAM an. Dieser CHIP-RAM Puffer ist allerdings privat, d.h. Du hast keinen Zugriff darauf.
CHIP-RAM bremst eine CPU ein - im FAST-RAM Bereich kann die CPU mit voller Geschwindigkeit werkeln. Dementsprechend sollte man nur dann CHIP-RAM verwenden, wenn es unbedingt nötig ist (Custom-Chips) und die CPU soweit möglich, nicht auf diesen Speicherbereich zugreifen lassen. Eine 68060 die aufs CHIP-RAM zugreifen muss, ist nur unwesentlich schneller als eine 68000er.
Anbei, die letzte wie auch die aktuelle Version verwenden überhaupt keinen CHIP-RAM Puffer - obschon dieser nach wie vor alloziert wird. Die Audio-Ausgabe erfolgt ohne DMA - das heißt ohne Speicherzugriffe seitens der Custom-Chips.


Zitat:
Tut mir leid, dass Du das Versuchskaninchen spielen musst -

Zitat:
Das ist absolut kein Problem, ich bin sehr froh das du mir bei diesem Timing Problem hilfst...


Mache ich gerne weil es mir Spaß bereitet, die Hardware wieder direkt anzusprechen.


Zitat:
Wenn's leiert oder blechern klingt baue ich das wieder raus.

Zitat:
Leiern und blechern nicht, aber da sind massive Störungen drauf.
Wie soll ich die beschreiben, brummen, schnarren?



Das habe ich befürchtet - Mist! :)

Komisch, nachdem ich alle Preprozessor-Kommandos durch Laufzeitvariabeln ersetzt habe, lief es plötzlich auch hier. Nach mehreren Tests hat sich herausgestellt, dass im Falle einer Veränderung am Inhalt des Audio-Puffers (CHIP-RAM), der ja eigentlich bei der Verwendung der Audio-Hardware ohne DMA, dass heißt Speicherzugriffe durch die Custom-Chips, keinerlei Bedeutung hat, diese Veränderung am Pufferinhalt von der Audio-Hardware registriert und in irgendeiner Weise mit negative Folgen quittiert wird. Hmmm, nachdem der CHIP-RAM Puffer nicht mehr verändert wird, kann selbst unter WinUAE DMA-freie Audio-Ausgabe erzeugt werden. :)
Kann mir jemand dieses Verhalten erklären?

Um noch einen drauf zu setzen:
Cause() kann beliebig oft innerhalb einer Sekunde aufgerufen werden. Meine Spekulation bezüglich des Timings ist vollkommen falsch. Dies bedeutet im Umkehrschluss, dass es mittels des Timer-Device theoretisch möglich sein sollte, zigtausend Prozessor-Unterbrechungen pro Sekunde zu generieren. Auch unter MorphOS/OS4!
Dementsprechend brauch man/frau keine CIAs. :)
Kann aber noch nicht sagen, welche Voraussetzungen für das Timer-Device geschaffen werden müssen um das zu erreichen (doppelte Interrupt-Struktur?).


Zitat:
Probiere mal TimerIRQ() - wenn's damit klappt, ist dein Basic-Programm für die Hits verantwortlich (falsche Parameter?).

Zitat:
Ja, sag mir gleich nochmal, die Puffer, benötigst du da einen Pointer auf einen Pointer der auf den Allocierten
Speicher Zeigt?
Ich hab jetzt nur den Pointer in der Pufferliste geschrieben welcher von AllocVec kommt.
Und Fast-Mem ist richtig?



Der Digitizer-Code funktioniert - und schmiert nicht ab?


Okay, das mit der Pufferliste ist easy.
Wenn Du nur einen Puffer verwenden willst, muss die Pufferliste acht Bytes groß sein - wegen des terminierenden NULL-Pointers.

Pufferliste
0 - 0xnnnnnnnn Adresse Deines Puffer (also hier die Adresse die AllocVec() zurück gibt eintragen)
4 - 0x00000000 NULL-Pointer
Ende der Pufferliste

InitIRQ() erwartet nun die Adresse der besagten acht Bytes - also einen einfachen Zeiger.

Im Prinzip könntest Du AllocVec() mit acht Bytes aufrufen - die zurückgegebene Adresse ist dann die Pufferliste.
Jetzt allozierst Du 50000 Bytes und trägst die retournierte Adresse an erster Stelle in Deine Pufferliste.
Das Langwort an zweiter Stelle in der Pufferliste musst Du jetzt löschen - das war's.

Oder für zwei Puffer:

pufferliste = AllocVec( 12, MEMF_CLEAR)
puffer1 = AllocVec( 50000, MEMF_CLEAR)
puffer2 = AllocVec( 50000, MEMF_CLEAR)

Nehme jetzt mal an, 'pufferliste' liegt ab Adresse 3000 im Speicher, 'puffer1' ab 15000 und 'puffer2' ab 90000.
Dann müsste nach der korrekten Initialisierung der Speicherbereich ab 3000 so aussehen:
(3000 = $BB8, 15000 = $3A98, 90000 = $15F90, 3016 = $BC8)
code:
__________1. Langwort  2. Langwort  3. Langwort  4. Langwort
00000BB8: 00 00 3A 98  00 01 5F 90  00 00 00 00  XX XX XX XX
00000BC8: XX XX XX XX  usw.


InitIRQ() benötig in diesem Beispiel als fünften Parameter den Wert $BB8 - ab diesem Speicherbereich stehen die Langworte (Adressen) zu den einzelnen Puffern. Und solange es kein Langwort dessen Wert null ist findet, interpretiert es jedes gesetzte Langwort als Adresse (in oberen Beispiel zwei).

Nehme zudem an, dass ab Adresse 9999 der String steht, der dem Interrupt einen Namen gibt, dann lautet der Aufruf für InitIRQ mit 22050 Hz wie folgt:
InitIRQ( 22050, 9999, 0, 0, 3000, 50000)
oder ausgeschrieben - in C:
InitIRQ( 22050, "Test", 0, 0, pufferliste, 50000)


Im Prinzip ganz einfach zu handhaben.

Und ja, Deine Puffer dürfen im FAST-RAM Bereich liegen - sie werden vom Interrupt nur gefüllt (ein Byte pro Timer-Tick) und dann nicht weiter beachtet.


Neue Version wurde hochgeladen. Benutzt weiterhin einen CIA-A Interrupt und eine DMA-freie Audio-Ausagbe. DMA-frei bedeutet, dass kein CHIP-RAM Puffer verwendet wird.
Du kannst das ändern, indem Du SetIRQAttrI( ihandle, 64) aufrufst (habe ich aber noch nicht ausprobiert).
Ein nochmaliger Aufruf stellt den voreingestellten Modus wieder her.

Gleiches gilt für die Audio-Ausgabe:
Die Audio-Ausgabe kannst Du unterdrücken, indem Du SetIRQAttrI( ihandle, 128) verwendest - oder wieder einschalten, bei nochmaligen, gleich lautenden Aufruf. Habe ich auch noch nicht ausprobiert...

Die Werte 64 und 128 sind Kippschalter. :) An, aus, an, aus, an, aus...


Sag mir mal ob jetzt die Audio-Ausgabe ansatzweise in Ordnung ist.


Gruß
 
jolo   Nutzer

21.11.2007, 23:46 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

Hi.

Zitat:
Holger:

UAE emuliert den Amiga halt exakt.

Zitat:
Maik:

Scheinbar nicht exakt, ein echter Amiga bringt mehr CIA-Speed.
Hat mit Turbo nichts zu tun, denn ich habe den CIA ja nicht übertaktet oder so.



Das Problem einer jeden Emulation ist, dass diese sukzessiv vorgehen muss - denke ich zumindest. Ich habe noch keine geschrieben - und habe es auch nicht vor.
Der Amiga und seine Custom-Chips verarbeiten aber Daten parallel zueinander, d.h. unabhängig von einander.
Dementsprechend sind die Zeitabstände in denen eine Aktion stattfinden kann, auf der echten Hardware immer kleiner als unter einer Emulation - zudem laufen die meisten Emulationen noch unter einem Host-Betriebssystem, d.h. im Multitasking. Amithlon ist hier eine Besonderheit und daraus resultiert auch eine mehrfach höhere Ausführungsgeschwindigkeit gegenüber (Win)UAE.
Und ja, Maik hat Recht - unter der echten Hardware sind ohne Probleme Frequenzen bis zu 28000 Hz möglich, da die CIA-Chips Hardwarebausteine sind denen es egal ist, ob die CPU mitkommt oder nicht, da diese eh keine Ahnung von der Existenz einer CPU haben. Man legt von Außen eine Taktfrequenz an und die CIAs werkeln vor sich hin - entsprechend dem Inhalt ihrer Register. Die CPU kann hier eingreifen falls sie nicht mitkommt - aber das ist ein anderes Thema.

Nehmen wir mal unser Beispiel zum Digitalisieren:
Die Emulation muss bei 14 kHz Frequenz 14000-mal pro Sekunde das Verhalten des CIA-Chips emulieren, 4 * 14000-mal das Verhalten der Audio-Hardware (abgesehen davon, das 8-Bit Sounds in 16-bittige gewandelt werden müssen), 14000-mal das Verhalten der Centronics-Schnittstelle und das Abgleichen mit der Host-Hardware.
Zudem kommt noch hinzu, das eine CPU emuliert werden muss und die Video-Ausgabe.

Lange Rede, kurzer Sinn: Je mehr Aufgaben eine Emulation gleichzeitig zu bewältigen hat, desto weiter entfernt sie sich vom Original.


Gruß

 
jolo   Nutzer

21.11.2007, 23:31 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi.

Zitat:
Aber mit Interrupts muss ich sagen das UAE bei der Customchip benutzung extrem in die Knie geht.

Habe ich bis dato nicht wahrgenommen - aber es stimmt.


Zitat:
Versuch mal nur die WB in AGA zu fahren, das ist auf einem 500 MHZ Rechner langsamer als mit einem A600.

Bei nur 500 MHz würde ich Amithlon empfehlen. WinUAE läuft erst ab 2 GHz aufwärts manierlich.


Zitat:
Ich habe die Bibliothek auch dahingehend geändert, dass der parallele Port nun auf Eingang geschaltet wird.

Zitat:
Das wird nicht helfen, es sei denn du schaltst den ParPort in der alten Version immer auf Ausgang.


Meines Wissens nach spielt es keine Rolle beim Lesen von Daten die an der parallelen Schnittstelle anliegen, ob Eingang oder Ausgang spezifiziert wurde; es wird immer der aktuelle Wert der anliegt, zurückgegeben.
Falls ich mich täusche berichtige ich das im Programm-Code.


Zitat:
Kannst du den anderen CIA-Timer wieder benutzen(da ging es ja)?

Du meinst anstelle des CIA-A Interrupts einen CIA-B?
Kann ich machen - hatte aber hier Probleme, da der CIA-B sich nicht richtig mit der Audio-Hardware verträgt und der Cause()-Aufruf, der die Audio-Hardware in Gang setzt, nur zu bestimmten Zeiten eine Aktion durchführt.
Bei der Verwendung des CIA-A Interrupts konnte ich die Audio-Hardware von innerhalb des Interrupts starten - ohne Umweg über Cause().


Zitat:
Die Wiederholungen resultieren aus der nicht hundertprozentigen [...]

Zitat:
Nein, das passiert wenn man einen zu großen Puffer nimmt, das hatte ich beim ASM Programm auch. Lässt man den Puffer beim Standard wert ist es okay.


Der Puffer ist genau für eine Sekunde Abspielzeit ausreichend - falls aber der Interrupt nicht genügend Daten, sprich Bytes bereit stellt, werden aufgrund des mangelnden Timings nur ca. 2/3 des Puffers innerhalb einer Sekunde gefüllt.
Der Audio-Hardware Interrupt beginnt dann schon wieder diesen Puffer abzuspielen (nach exakt einer Sekunde), während die Routine, die mit dem Interrupt synchronisiert ist, sich erst bei 2/3 des Puffer-Inhalts und damit bei 2/3 einer Sekunde wähnt.
Wie gesagt, bis 14 KHz klappts, danach läuft der CIA-A Interrupt aus dem Ruder, sprich, er kann nicht so oft pro Sekunde ausgeführt werden.


Zitat:
Klappt das? Wäre schön - dann funktioniert nämlich etwas. :)

Zitat:
Ja, wesentlich besser als mit dem timer.device, vor allem weil ich auf den beiden Prozessoren nicht 2 verschidene
Zeiten angeben muss. Der Joyport scheint nicht gestört zu werden.



Na, dann war ja meine Mühe nicht ganz umsonst.


Zitat:
Ob's allerdings nach wie vor knackt, kann ich nicht sagen - hier hilft nur ausprobieren.

Zitat:
Du verwechselst jetzt das Knacken was mit dem ASM+C Programm minimal da war mit dem was ich jetzt meine - welches die
Parallel Information immer zwischendurch auf -127 runterschaltet.
Das jetzt ist viel schlimmer.



Jetzt verstehe ich so langsam. Es könnte sein, dass dem CIA-A-CHIP dadurch mitgeteilt wird, das Daten anstehen. Müsste das aber erst mal nachlesen. Probehalber wird jetzt der FLAG-Interrupt unterdrückt.


Zitat:
Das mit der Pufferliste hab ich nicht Verstanden:
(0)
(4)
(8)

damit würde man unter Basic jeweils 3 LONG's freilassen.
Also hab ich es in (0), (1), (2) geändert, also folgen die Adressen hintereinander. Geholfen hats aber nicht.


1. Parameter: Frequenz pro Sekunde.
2. Parameter: Adresse Zeichenkette für Namen des Interrupt.
3. Parameter: Benutzer definierter Code der im Interrupt ausgeführt werden soll.
4. Parameter: Daten/Struktur für Benutzer definierten Code (halt irgendwelche Argumente).
5. Parameter: Pufferliste - zeigt auf einen Speicherbereich, in dem die Adresse(n) Deine(s)(r) FAST-RAM Puffer vermerkt sind; InitIRQ() zählt die gesetzten Langworte und interpretiert diese als Adressen zu den einzelnen Puffern. Deshalb muss als letztes Element ein NULL-Zeiger gesetzt sein (Ende der Pufferliste).
Da ich kein Basic verstehe, habe ich den POKEL-Befehl falsch eingesetzt - so wie Du es macht müsste es klappen.
6. Parameter: Größe in Bytes eines einzelnen Puffers - das heißt dann aber auch, das alle Puffer von der gleichen Größe sein müssen.

In Deinem Beispiel allozierst Du 200004 Bytes für einen Puffer - sagst InitIRQ() aber, dass der Puffer nur 50000 Bytes groß ist. Warum?

Und ja, falls eine Pufferliste spezifiziert wird, also nicht NULL ist, wird die Audio-Hardware in Gang gesetzt.
Falls Du das nicht wünscht, kann ich das ausbauen.

Weshalb bei Dir der Digitizer abschmiert kann ich (derzeit) noch nicht sagen. Probiere mal TimerIRQ() - wenn's damit klappt, ist dein Basic-Programm für die Hits verantwortlich (falsche Parameter?). Allerdings ist auch ein Programmierfehler meinerseits nicht auszuschließen.


Habe die Bibliothek wieder ein klein wenig modifiziert und dabei festgestellt, dass das CIA-A Kontrollregister eine falsche Bitmaske abbekam - zudem wird jetzt auch der FLAG-Interrupt gesperrt (zuständig für das Handshake-Signal des parallelen Ports).
Die Audio-Ausgabe habe ich dahingehend geändert, dass kein Puffer mehr verwendet wird. Kann das aber hier nicht ausprobieren weil WinUAE da nicht mehr mitspielt (zu viele Daten in zu kurzen Intervallen).
Wenn's leiert oder blechern klingt baue ich das wieder raus.

Ich verwende nach wie vor noch einen CIA-A Interrupt - falls es wider Erwarten damit Probleme gibt, werde ich einen CIA-B Interrupt verwenden - dann muss ich die Audio-Ausgabe aber wieder gepuffert durchführen.

Tut mir leid, dass Du das Versuchskaninchen spielen musst - aber ich habe wirklich keine Lust, meinen A4000 wieder zu reanimieren.

Neues Archiv wurde hochgeladen.


Gruß
 
jolo   Nutzer

20.11.2007, 20:33 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

Hi Maik,

ich habe vorhin diverse Tests durchgeführt und alles was ich sagen kann ist, dass selbst hier unter WinUAE und einem nicht geraden langsamen PC ca. 14000 Aufrufe pro Sekunde das Maximum sind, dass der CIA-A Interrupt im Multitasking-Betrieb mit diversen anderen Interrupts eingeschaltet, imstande ist zu signalisieren, ohne aus dem Ruder zu laufen.
Alles was darüber hinausgeht, klappt hier bei mir nicht!

Ich habe eine gefakte Bibliothek dafür benutzt, die einen Sound beinhaltet, der mit 14880 Hz (Periode 240) abgespielt werden muss. Tests mit 18896 erbrachten, dass maximal 15000-mal pro Sekunde ein Interrupt generiert wurde - anstelle von fast 19000-mal. Aber wie gesagt, die Schmerzgrenze liegt irgendwo im Bereich von 14000.

Betreffend der Störungen:
Dazu kann ich im Moment nicht viel sagen, da mein 4000er im Keller schön verpackt dahin vegetiert - und ich derzeit keine Motivation verspüre, diesen neu aufzubauen (Festplatte und diverse Kleinigkeiten fehlen).
Dementsprechend kann ich nicht selber digitalisieren.

Wie oben schon erwähnt, versuch es mal mit 12000 bzw. 14000 Hz - und benutze zu Testzwecken mal TimerIRQ - es zeigt Dir an, wie viele Daten pro Sekunde wirklich gesampelt werden können (der Wert den TimerIRQ ausgibt entspricht nicht hundertprozentig dem gewählten Wert bedingt durch die Integer-Arithmetik - sollte aber nichtsdestotrotz einen groben Überblick gewähren). Bei Abweichungen von mehr als 400 Samples kannst Du davon ausgehen, dass Dein gewählter Wert zu groß ist.

Ich habe die Bibliothek auch dahingehend geändert, dass der parallele Port nun auf Eingang geschaltet wird.

Die Wiederholungen resultieren aus der nicht hundertprozentigen Synchronisation - allerdings wird jetzt die Audio-Hardware dahingehen ausspioniert, wie viele Bytes (annähernd) pro Sekunde ausgegeben werden und dementsprechend wird die Abspiellänge beschnitten (ac_len). Das sollte schon mal etwas bessere Ergebnisse liefern; aber wie gesagt, hundertprozentig bekomme ich das ohne vorherige Synchronisation nicht hin.

Zitat:
Ja, das versuche ich auch noch. Erstmal habe ich versucht das mit den Infrarot-Senden zu Timen.

Klappt das? Wäre schön - dann funktioniert nämlich etwas. :)


Zitat:
Serielle Schnittstelle? Das ist doch die Parallele.

Autsch. :)
Natürlich. Manchmal bin ich nicht im Vollbesitz meiner geistigen Kräfte... ;)


Zitat:
Das Prog knackt genauso, zusätzlich wiederholt es bereits gespielte Teile und scheidet andere weg.

Sollte mit der neueren Version besser gelingen, allerdings, wie gesagt, musst Du dann Deine Ansprüche (Hz) herunterschrauben. Ob's allerdings nach wie vor knackt, kann ich nicht sagen - hier hilft nur ausprobieren. Wiederholungen sollten jetzt seltener auftreten - da ja die Abspiellänge auf einen regulären Wert beschnitten wird.


Neue Version (auch die getürkte) kann von der bekannten Seite heruntergeladen werden. Archiv ist jetzt allerdings 2.6 MBytes groß - bedingt durch den Sound.

Installiere mal die getürkte Bibliothek anstelle der echten und rufe TimerIRQ mit 14880 Hz auf - die Anzahl Bytes die der CIA-A Interrupt der Audio-Hardware pro Sekunde zur Verfügung stellt, wird ausgegeben - und das sollte eine Orientierungshilfe sein.

Wenn der Wert unter 14400 liegt weißt Du, dass der CIA-A Interrupt überfordert ist.


Gruß

 
jolo   Nutzer

18.11.2007, 12:17 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

Hallo Maik,

Zitat:
Es gab mehrere Programme von verschiedensten Programmierern die alle Fehlgeschlagen sind. UAE ist kein echter Amiga, er
Syncronisiert das Timing mit der Echtzeit auf kosten anderer aktivitäten.


Wie, UAE ist kein echter Amiga? Soll das heißen, isch haabe gaar keinen Amiga? Ische nix Amiganer? ;)
Nee, Recht hast Du - aber was ich eigentlich sagen wollte ist, dass ich unter WindowsXP arge Probleme hatte, ein korrektes Timing hinzubekommen - dementsprechend war ich einigermaßen erfreulich erstaunt, dass das Timer-Device unter WinUAE ziemlich genau arbeitet.


Zitat:
ich habs erstmal was einfaches zusammengebastelt.
Also es geht bis 16000 HZ auf 060. Allerdings sind im Sample solche Knackser drin. Hört sich an wie eine sehr zerkratzte Platte. Es gehen Spikes auf -127. Beeinflusst der Interrupt irgenwie den BFE101 Register?


Normalerweise sollte das Empfangen der Daten keinen Einfluss auf einen der beiden Timer haben, ansonsten wären die Timer nur Makulatur. Ich könnte aber die anderen Interrupts sperren die nicht benötigt werden - allerdings wird dann nichts mehr richtig funktionieren, was die serielle Schnittstelle betrifft - und das will ich vermeiden.

Was mir aber aufgefallen ist, dass Du einen Wert "peekst", ohne das gelesene Datenbyte vorzeichengerecht zu erweitern (+128) - müsste in etwas so aussehen:

code:
POKEB MySample&+count&, PEEKB(&hBFE101) + 128
INCR count&


Anbei, das kleine Tool "TimerIRQ" kannst Du benutzen um festzustellen, ob der von mir favorisierte CIA-A Timer überhaupt mit der Seriellen-Schnittstelle harmonisiert.
Um Deinem Beispiel zu folgen, brauchst Du nur "timerirq 16000" im CLI zu tippen. Es digitalisiert dann mit 16000 Hz.

Was mir zudem aufgefallen ist, dass Du das Digitalisieren wieder auf Prozess-Ebene verlagerst, wo wir uns doch einig waren, dass das nie und nimmer richtig funktioniert kann.
Wieso benutzt Du nicht den "eingebauten" Digitizer? Dafür habe ich ihn ja geschrieben.

Im Prinzip musst Du nur einen Speicherbereich allozieren/definieren, der groß genug ist, die Zeiger auf die einzelnen Puffer aufzunehmen; bei einem Puffer also 8 Bytes, weil ja der zusätzliche, letzte Zeiger genullt werden muss.

code:
DIM pufferListe 8   REM  8 Bytes reservieren = 2 Langworte


Jetzt musst Du die Adresse von "MySample" dort als erstes Langwort eintragen:

code:
POKEL pufferliste&, VARPTR(MySample&)


und zum Schluss das zweite Langwort nullen:

code:
POKEL pufferlist& + 4, 0   REM  Ende der Puffer-Liste


Das war's. Jetzt kannst Du den eingebauten Digitizer verwenden:

code:
ihandle& = InitIRQ&( 16000, "DigiTest", 0, 0, pufferListe&, 200004)   REM  Puffergröße = 200004 Bytes


Das "normale" Signal-Handling solltest Du dann auch ausschalten, ansonsten wird Dein Prozess 16000-mal pro Sekunde wieder aufgeweckt - was nicht gerade im Sinne des Erfinders ist.

code:
SetIRQAttrI&(ihandle&, 4)   REM  Normales Signal-Handling ausschalten


Beim Eintreffen des "Puffer ist voll" Signals ( sigmask&=(1<<GetIRQAttrI&(ihandle&,1)) ) kannst Du den Interrupt und damit auch den Digitizer beenden.
Am Besten wäre es aber, wenn Du eine kleine Mini-Funktion mitlaufen lassen würdest, die entscheidet, wann ein "normales" Signal zum Hauptprogramm gesendet wird, um den Hauptprogramm zu irgendeiner Aktivität (Goertzel) verleitet sobald genug Daten bereitstehen.
Wie gesagt, die Mini-Funktion wird im Interrupt-Code ausgeführt und muss dementsprechend die Register auf die von MaxonBasic verwendete verbiegen, ansonsten ist ein Crash nicht fern.
Wie schon gesagt, falls Deine Mini-Funktion null retourniert, wird *kein* Signal an Dein Hauptprogramm gesendet, nur wenn Deine Mini-Funktion irgendeinen Wert ungleich null zurückgibt, wird der Interrupt-Code, der Deine Mini-Funktion aufrief, dem Hauptprogramm das "normale" Signal signalisieren.

Anbei, das ist der echte Interrupt-Code der u.a. auch Deinen Code (Mini-Funktion) aufruft/aufrufen könnte:
C code:
SUPERIOR ULONG CIAA_Code( REG(a1, struct TimeOutIRQData *tid) )
{
	LONG i;

	i = 2;

	/* Dürfen wir eine Aktion ausführen? */
	if ( tid->TimeOutFlag == ALIVE )
	{
		if (tid->IntType == IRQ_DIGITIZE)
			CallDigitizerCode( tid);	/* Rufe Digitizer auf */

		/* Falls Benutzer-Code vorhanden, diesen jetzt anspringen */
		if (tid->IRQUsersCode)
			tid->SendSignal = (LONG) tid->IRQUsersCode( (APTR) tid->IRQUsersData);

		/* Falls SendSignal != 0 wird Signal gesendet! */
		if (tid->SendSignal)
			Signal( tid->TimeOutTask, (1 << tid->TimeOutSignal) );
	}
	else	/* Nee, keine Aktion ausführen. Ende? */
	{
		if (tid->TimeOutFlag == KILL)	/* DeleteIrq() setzt dies - hat für uns */ 
			tid->TimeOutFlag = KILLED; /* aber eigentlich Bedeutung, da wir */
	}					/* diesen Punkt nie erreichen (Interrupt */
						/* schon gestoppt falls KILL gesetzt) */
	return i - 2;
}



Gruß
 
jolo   Nutzer

17.11.2007, 11:42 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@whose:

Tach,

Zitat:
Sag das nicht mir ;) Im Grunde war das nur ein verzweifelter Versuch, seine enormen Abweichungen zu ergründen. Wie gesagt, auf meinen Kisten läuft das timer.device recht genau, bei ihm hingegen nicht.

Zu Deiner Information: Auch hier ist das Timer-Device sehr genau - und dass unter WindowsXP/WinUAE. :)
Also gehe ich davon aus, dass er einen simplen Programmierfehler irgendwo eingebaut hat.
Habe leider keine Zeit gefunden, den anderen Thread zu lesen. Werde das aber nächste Woche mal nachholen. Vielleicht fällt mir irgendetwas Ungewöhnliches auf.

Zitat:
Was da nun genau verkehrt läuft: Frag mich was Leichteres ;)

Wenn Du mich schon so fragst: Wie wird das Wetter nächste Woche? ;)

Gruß
 
jolo   Nutzer

17.11.2007, 11:39 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

Hi Maik,

habe mein Versprechen gehalten und eine Bibliothek für Dein Problem erstellt.
Kriege ich jetzt meinen Lutscher? ;)

Zitat:
Zweiter Grund (falls die Audio-Hardware keinen Prefetch benutzt - müsste das mal selber nachlesen - also ist diese Aussage nur mit Vorsicht zu genießen):
Je kleiner der verwendete Puffer, desto mehr Störgeräusche. Da der CIA-B Interrupt und die Audio-Hardware sich einen Speicherbereich teilen, und es sein kann, dass beide zum gleichen Zeitpunkt auf ein bestimmtes Datenword zugreifen wollen, bedingt durch die nicht hundertprozentige analoge Abtastrate, bekommt derjenige den Zugriff, der die höhere Priorität hat - und das ist der CIA-B Interrupt. Somit kommt es kurzzeitig zu diesem Effekt.


Diese Aussage von mir hat ihre Gültigkeit und war dafür verantwortlich, dass die Audio-Hardware nicht störungsfrei betrieben werden konnte...


Zitat:
Multimon macht in etwa das selbe und knackt nicht. Also muss es ja möglich sein...

Zitat:
Das hab ich schon, da wird ein kurzer part dann mehrmals wiederholt.

Ja, Du hast Recht. Siehe erstes Zitat.
Es hat sich herausgestellt, dass der CIA-B Interrupt wirklich die Audio-Hardware stört - dementsprechend verwende ich jetzt einen CIA-A Interrupt. Jetzt sind die hörbaren Störungen minimal - die gesammelten Daten waren ja davon nie betroffen (FAST-RAM Puffer).


Zitat:
Wenn ich gleichzeitig dnetc laufen habe und ein Benchmark mache bekomme ich mit 4 Kanälen um die 96000 keys/s. Mit 2 Kanälen
102000 keys/s und mit Multimon auf der selben Frequenz 116000 keys/s.
Der Wert ohne Monitor liegt bei 176000 keys/s.


Benchmark-Ergebnisse sind generell mit Vorsicht zu genießen - zu viele Faktoren beeinflussen das Ergebnis.
Das Audio-Device (also die Hardware) hat, auch wenn Du mir das nicht glaubst, rein gar nichts mit der CPU und ihrer Last zu tun.
Die CUSTOM-CHIPS sind entworfen worden, um die CPU zu entlasten. Das einzige was die CPU und die CUTSOM-CHIP gemeinsam verwenden ist der Daten- und Adressbus.
Nur wenn beide auf ein- und demselben Speicherbereich zugreifen wollen, gibt es Konflikte - sprich eine Verzögerung. Diese liegen aber im Millisekundenbereich.


Zitat:
Eine erkennung von DTMF tönen(Tonwahl) welche von einem Handy in den Sampler kommen decodieren.

Und dafür brauchst Du CD Qualität (44,1 kHz) ?


So, nun zu der Bibliothek:

Diese nennt sich "ire" und muss ins Libs-Verzeichnis.
Die "bmap" Datei habe ich mittels "fd2pragma" erstellt und sollte von Dir ohne weitere Anpassung unter MaxonBasic benutzt werden können.

Es gibt nur 5 Funktionen:

InitIRQ
StartIRQ
DeleteIRQ
SetIRQAttrI
GetIRQAttrI

InitIRQ kann sowohl normale Interrupts auslösen als auch digitalisieren.

void * InitIRQ( ULONG callsPerSecond, STRPTR irqname, LONG (*usersCode)(), APTR usersData, UBYTE **buffers, ULONG singleBufSize) (d0,a0,a1,d1,a2,d2)

callsPerSecond --- wie oft pro Sekunde soll der Interrupt aufgerufen werden, z.B. 16668.
irqname --- Name Deines Interrupts, z.B. "Maik's Interrupt".
usersCode --- Zeiger auf die Funktion die innerhalb des Interrupts aufgerufen wird - oder null falls keine eigene Routine aufgerufen werden soll.
usersData --- Zeiger auf eine Struktur oder Variable die dein "usersCode" auf dem Stack empfängt, darf auch null sein.
buffers --- falls gesetzt, wird der Digitizer aufgerufen! buffers zeigt auf einen Speicherbereich, in dem Du die Adressen Deiner FAST-RAM Puffer vermerkt hast. Der letzte Eintrag muss NULL (0) sein.
singleBufSize --- die Größe *eines* Puffer, d.h. falls Du jeden Puffer eine Größe von 20000 Bytes zugewiesen hast, musst Du hier 20000 eintragen. Bei zwei Puffern (buffers: Puffer1, Puffer2, NULL) macht das Summa Summarum 40000 Bytes FAST-RAM. Die einzelnen Puffer dürfen nicht in der Größe variieren!

Ein paar Beispiele:
ihandle = InitIRQ( 50, "Maik's Interrupt", NULL, 0, NULL, 0)

Hier wird dann jede fünfzigstel Sekunde ein Interrupt ausgelöst und ein Signal zu Deinem Hauptprogramm gesendet.
Du kannst mittels:
GetIRQAttr( ihandle, 2)
das Signal-Bit ermitteln, welches Dir signalisiert wird (z.B. für die Verwendung mit Wait() ).
Für Wait() musst Du das Signal-Bit in eine Signal-Maske umwandeln:
sigmask = (1 << GetIRQAttr( ihandle, 2))

ihandle = InitIRQ( 50, "Maik's Interrupt", (*usersCode)() &yourcode, &counter, NULL, 0)

Wie oben, nur wird hier noch deine "yourcode"-Routine aufgerufen und bekommt als Argument auf dem Stack die Adresse der Variable "counter".
Falls "yourcode" null zurückgibt, wird kein Signal an Dein Hauptprogramm gesendet. Nur wenn Du irgendeinen Wert zurückgibst, wird das Signal gesendet.

Du musst wissen, welche Prozessor-Register MaxonBasic benötigt und deren Inhalt irgendwo vor Aufruf von StartIRQ() ablegen und dann innerhalb von "yourcode" diese Registerinhalte restaurieren - und beim Verlassen von "yourcode" die ursprünglichen Registerinhalte für den originalen Interrupt-Code, der "yourcode" aufgerufen hat, wieder instand setzen.

-------------------------------------

ihandle = InitIRQ( 50, "Maik's Interrupt", SADD yourcode, SADD counter, 0, 0)

#asm
move.l a4,inhaltA4
move.l a5,inhaltA5
move.l a6,inhaltA6
#endasm

StartIRQ( ihandle)

------------------------------------

SUB yourcode( arg) STATIC
#asm
move.l 4(sp),argument ; Adresse von "counter"
movem.l D2-D7/A2-A6,-(sp)
movea.l inhaltA4,A4
movea.l inhaltA5,A5
movea.l inhaltA6,A6
#endasm
Dein Basic-Code hier - "argument" zeigt aufs Argument für "yourcode"
returnWert = 0 ; Kein Signal senden
#asm
movem.l (sp)+,D2-D7/A2/A6
move.l returnWert,D0
rts ; Muss RTS für Basic angegeben werden?
#endasm
-------------------------------------

DIM pufferListe (12)
DIM puffer1 (20000)
DIM puffer2 (20000)

POKEL( pufferListe(0), SADD puffer1)
POKEL( pufferListe(4), SADD puffer2)
POKEL( pufferListe(8), 0)

ihandle = InitIRQ( 16668, "Maik's Interrupt", 0, 0, SADD pufferListe, 20000)

Da wir nicht wollen, dass wir ein Signal für jeden Eintritt in den Interrupt erlangen, müssen wir das Signal-Handling für normale Signale ausschalten:

SetIRQAttrI( ihandle, 4)

Jetzt kann man (frau auch) StartIRQ( ihandle) aufrufen.

Und da wir informiert werden wollen, wann einer der beiden Puffer voll ist, müssen wir dessen Signal-Bit ermitteln:
sigmask = (1 << GetIRQAttr( ihandle, 1))

Jetzt mittels Wait( sigmask) horchen, ob eine Nachricht eintrifft.

Um die Adresse des Puffers zu erfahren, welcher voll ist, muss man dies verwenden:
vollerPuffer = GetIRQAttr( ihandle, 16)


Flaggen für Get/SetIRQAttrI():

1 = (get) - hole Signal-Bit das signalsiert, das ein Puffer voll ist.
2 = (get) - hole Signal-Bit das signalsiert, das Interrupt aufgerufen wurde.
4 = (set) - normale Signal-Handhabung ausschalten (Interrupt wird nicht signalsiert).
8 = (set) - normale Signal-Handhabung einschalten (Interrupt wird signalsiert).
16 = (get) - hole Adresse des Puffers, welcher voll ist.


Ich spreche kein Basic, daher weiß ich nicht ob das was ich oben verbrochen habe, so von einem Basic-Compiler/Interpreter akzeptiert wird - ich glaube kaum... :)

Archiv kann unter http://www.amimedic.de heruntergeladen werden.

Das (nährlose) Beispiel TimerIRQ digitalisiert und kann auch mit anderen Werten betrieben werden:
TimerIRQ 28801 - digitalsiert mit 28801 Hz!

Gruß
 
jolo   Nutzer

10.11.2007, 10:04 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi.

Zitat:
Ach ja, Du kannst STARTOFFSET auch einen größeren Wert zuweisen - dann startet die Audio-Ausgabe verzögert und somit stehen mehr Daten bereit, bevor eine hörbare Ausgabe erfolgt (kannst ja mal die halbe Größe von AUDSIZE probieren).
STARTOFFSET ist hier zu finden:

Zitat:
Und dann knackt es nicht?


Das Knacken rührt daher, weil die Audio-Abtastrate nicht hundertprozentig dem der Abtastrate des CIA-B Interrupts entspricht.
Du solltest Dir vergegenwärtigen, dass die Audio-Hardware unabhängig von Deinem Interrupt werkelt.
Du sagst dieser nur, wie schnell sie von dem Puffer Daten lesen soll (Periode 214 oder 124) und wo das erste Byte des Puffers zu finden ist (Anfangsadresse) und wie groß der Puffer ist (Endadresse). Danach macht sie alles selbstständig - wenn die Endadresse erreicht wurde, beginnt sie wieder mit der Ausgabe bei der Anfangsadresse - und das fortlaufend.
Zwischenzeitlich und unabhängig davon werkelt Dein CIA-B Interrupt - der die Daten einliest, die die Audio-Hardware ausgeben soll. Falls nun der CIA-B Interrupt etwas langsamer Daten einliest als die Audio-Hardware ausgibt, gibt die Audio-Hardware die Daten aus, die beim letzten Durchlauf gesammelt worden sind - und nicht die, die beim jetzigen Durchlauf aktuell sind.
Wie gesagt, dies passiert aber nur bei der Wiedergabe in Echtzeit - die Daten, die der Interrupt sammelt, sind davon nicht betroffen.
Zweiter Grund (falls die Audio-Hardware keinen Prefetch benutzt - müsste das mal selber nachlesen - also ist diese Aussage nur mit Vorsicht zu genießen):
Je kleiner der verwendete Puffer, desto mehr Störgeräusche. Da der CIA-B Interrupt und die Audio-Hardware sich einen Speicherbereich teilen, und es sein kann, dass beide zum gleichen Zeitpunkt auf ein bestimmtes Datenword zugreifen wollen, bedingt durch die nicht hundertprozentige analoge Abtastrate, bekommt derjenige den Zugriff, der die höhere Priorität hat - und das ist der CIA-B Interrupt. Somit kommt es kurzzeitig zu diesem Effekt.

Probiere wie im letzten Posting beschrieben AUDSIZE eine andere Größe zu geben und den STARTOFFSET auf die Hälfte von AUDSIZE zu setzen. Dann nämlich fängt die Audio-Hardware erst dann an, wenn der CIA-B Interrupt die Hälfte des Puffers schon gefüllt hat. Dann ist das Ganze aber zeitlich versetzt...


Zitat:
Da die maximale Sampling-Frequenz 28801 Hertz beträgt

Zitat:
Bei einen DBL-PAL Screen geht dann das doppelte?


Theoretisch ja, praktisch kann ich nichts dazu beisteuern, da ich es nie selber ausprobiert habe.
Da die Datenmenge, die die Custom-Chips, welche ja nach wie vor mit 7 MHz getaktet werden, bewältigen müssen um den Faktor 2 ansteigen würde (jeweils für Audio und Video), könnte es zu viel des Guten sein.
Aber wie gesagt, ich selber habe es nicht ausprobiert.


Zitat:
Ausserdem benutze ich jetzt nur noch 2 Audiokanäle, 4 nehmen nur mehr Resourcen.

Nein, tun sie nicht. Die Audio-Hardware hat rein gar nichts mit Deiner CPU zu tun.


Zitat:
Anbei, wieso sind 16000 Hz nicht ausreichend?

Zitat:
Weil es qualitativ schlecht ist. Da sind dann solche zischlaute und so


Zitat:
Ich habe früher mit 14000 Hz digitalisiert - und zwar ganze Musikstücke und diese sind
selbst nach heutigen Standards noch ganz manierlich anzuhören.

Zitat:
Ähm, mit PC-Lautsprecher vielleicht. Ich bin da doch anspruchsvoller.
Früher habe ich immer in etwa 22khz gesamplet. Heute 44khz in 16 Bit, also bei Musik die ich brennen will.



Du vergleichst da Äpfel mit Birnen. 44kHz in 16-Bit sind was anderes als 44kHz in 8-Bit.
Du hast im Amiga kein 16-Bit Sound, nur 8-Bit, es sei denn Du benutzt eine Soundkarte.
Wenn Du 16-Bit Samples benötigst, musst Du erst die 8-Bit Samples in 16-bittige umwandeln bevor Du diese als solche benutzen kannst.
Und Digitizer für Amigas waren immer als 8-Bit Lösungen ausgelegt - nicht 16 Bit.


Zitat:
Soweit bin ich noch lang nicht...
Prinzipell brauche ich ja a) einen Monitor und b) ein (Speicher) aufzeichungsprogramm.
Also das ist jetzt a.


Da widerspreche ich Dir - zwar ungern, aber tue es trotzdem. ;)
AudioGrabber2 bietet Dir beides. Schau Dir das Beispiel mal an.


Zitat:
Mit "Scout" kann ich dem ASM-Programm ein "Break" senden und es beendet
sich problemlos. Selbiges müsste man doch bewerkstelligen können.
Hab es schon mit Signal + SetSignal probiert, erfolglos.


Studiere mal die Beispiele - speziell die Interaktion zwischen Interrupt und Programm (Task). Dann weißt Du wie es gemacht wird.
Aber abgesehen davon, selbst das Senden eines CTRL-C Signals wird Dir nichts bringen - denn eine Frage bleibt: Wo hat das Programm (AudioGrabber) nun die Daten versteckt - und was passiert, wenn es ein CTRL-C Signal empfängt? :)
Beim Eintreffen des Signals werden alle Ressourcen freigegeben - und somit auch der Datenpuffer. Dementsprechend existieren die Daten nicht mehr!


Zitat:
Eine Library die Samplen kann?
Klingt nicht schlecht. Unter Basic kann man prinzipell alle Librarys benutzen, nur die Includes muss man sich ggf. selber machen.


Brauchst Du eine FD oder SFD Datei um eine BMAP Datei zu erstellen?


Zitat:
Frage: Meinst Du auf Prozess/Task-Ebene oder das Beispiel mit dem Software-Interrupt?

Zitat:
Ein Standard warten mittels timer.device, also momentan sende ich Infrarot Signale mit etwa 1000-1500HZ. Beim 060er gebe ich 560 micros beim 030er 250 micros um das selbe ergebniss zu erhalten. Von Timing, Maschienenunabhängig kann also keine Rede sein.


1000 oder 1500 Signale pro Sekunde bedeuten nicht, dass Du 1000 oder 1500 Hz verwendest. Der Zeitabstand zwischen den einzelnen Zyklen ist ausschlaggebend. Dieser muss konstant sein.
Hz bedeutet das etwas in periodischen Abständen auftritt - und nicht soundsooft innerhalb eines bestimmten Zeitrahmens.
Ich kann in der ersten halben Sekunde die 1500 Signale raushauen und die restliche Zeit warten. Das hat dann allerdings nichts mit periodischen Intervallen zu tun.


Zitat:
Von Timing, Maschienenunabhängig kann also keine Rede sein.

Auf Task-Ebene bestimmt nicht... aber annähernd sollte es schon funktionieren.
Gehe ich recht in der Annahme, dass Du *nicht* am Anfang Deines Loops die "Auszeit" spezifizierst sowie DoIO anstelle von SendIO verwendest?

Müsste ungefähr so aussehen damit es richtig funktioniert:

code:
LOOP
	SendIO( timerrequest)
	....
	Sende Infrarot-Signal
	....
	signale = Wait( (1 << TimerSigBit) )
	IF signale AND (1 <<TimerSigBit) <> 0
		GOTO LOOP
	ENDIF
ENDLOOP


Zitat:
Ich nehme an dem timer.device fehlt es an effizienz, daher dürfte eine PPC-CPU da einiges kompensieren können.

Du würdest das nicht behaupten, wenn Du die betreffenden Routinen mal disassembliert hättest.
Diejenigen, die das originale AmigaOS programmierten, verstanden effizient und ressourcenschonend zu programmieren.
Leider hat das aber auch seine Kehrseiten... :)


Zitat:
Ausserdem verwendete ich das selbe Programm...
Dann hab ich es sogar Prozessorspezifisch Compiliert...


Ihr könnt mich ja dumm sterben lassen aber es wäre nett von euch wenn ihr mir stattdessen mal sagt, über welches Programm ihr euch unterhaltet... Erbarmen, bitte... :)

Zitat:
Das kann aber (und wird auch) "durchbrochen" werden. Z.B. durch das "Wait()en" auf das Signal vom timer.device, schau mal in die RKMs/AutoDocs (NDK3.9) zum Thema "Forbid()", da stehts nochmal.

Zitat:
Half aber gegen das leiern und Stoppte den Mauscursor.
Sollte ich Forbid dann wohl mehrfach innerhalb der Schleife benutzen?



Verwendet ihr DoIO()? Dann habt ihr euer Wait() gefunden...

Forbid() in einer Schleife zu verwenden ohne entsprechendes Permit() wird das System lahm legen.
Vergiss die Existenz von Forbid()!


Zitat:
Öhm... wo liegt das Problem? Open(), Write(), Close(), fertig.

Zitat:
In Assembler sind die aufrufe etwas schwieriger...


Nö.

code:
_WriteBufferContents
	movem.l	D2-D4/A6,-(sp)
	movea.l	_DOSBase(pc),A6
	move.l	_DateiName(pc),D1
	move.l	#1006,D2
	jsr	_LVOOpen(A6)
	move.l	D0,D4
	beq.s	_error
	move.l	D0,D1
	move.l	_PufferAdresse(pc),D2
	move.l	_PufferLaenge(pc),D3
	jsr	_LVOWrite(A6)
	move.l	D0,D2
	move.l	D4,D1
	jsr	_LVOClose(A6)
	cmp.l	D2,D3
	bne.s	_error
	moveq	#1,D0
_out
	movem.l	(sp)+,D2-D4/A6
	rts
_error
	moveq	#0,D0
	bra.s	_out

_DOSBase
	ds.l	1
DateiName
	ds.l	1
PufferAdresse
	ds.l	1
PufferLaenge
	ds.l	1



Zitat:
Im Internet hab ich schon gesucht, ausser was mit dem Seriell Port fand ich nichts.

http://gega.homelinux.net/AmigaDevDocs/


Zitat:
Ausserdem verwendete ich das selbe Programm...
Dann hab ich es sogar Prozessorspezifisch Compiliert...

Zitat:
Ich habe nie etwas anderes gesagt.


Selbst mit dem Beispiel für Software-Interrupts kann man nachvollziehen, wie oft pro Sekunde der Interrupt aufgerufen wurde - man braucht dazu nur die Ausgabe im Auge zu behalten.


Gruß
 
jolo   Nutzer

10.11.2007, 09:45 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@whose:

Moin Moin :)

Zitat:
Ich hatte ihm schon einmal zu verstehen gegeben, daß das Multitasking da eine Rolle spielen kann.

Ungeachtet dessen behauptet Maik, dass mittels einer Schleife und ausgeschalteten Multitasking er 18000 Hz erreichen kann - was ich aber anzweifle da 18000 Lesezugriffe pro Sekunde nicht gleichzusetzen sind mit 18000 Hz. Es kommt auf die Zeitspanne zwischen den einzelnen Lesezyklen an - ist diese immer gleich (kontinuierlich) für alle Lesezugriffe, so könnte er mit Fug und Recht behaupten, dass er das auf Task-Ebene schafft - aber das wage ich zu bezweifeln, da ihm alle mögliche Interrupts einen Strich durch die Rechnung machen.
Es kann sein, dass ein Teil der Lesezyklen tatsächlich in gleichen Abständen gelesen wird, aber der Rest?
Somit kommt es beim Einsatz eines Prozesses für diese Aufgabe zu Unregelmäßigkeiten, die in einer verfälschten Wiedergabe resultieren.


Zitat:
In Sachen Verständnis hätte evtl. auch ein Hinweis auf den VBI helfen können, dessen Beispielprogramm im RKM ich heute "wiederentdeckt" habe. Sehr trivial, wie ich fand, und für das Verständnis der Feinheiten, auf die vorher schon eingegangen wird, auch recht hilfreich.

Hmmm, wie kann ich Dir nur schonend beibringen, dass ich diesen Abschnitt heutzutage als nicht mehr aktuell betrachte - ohne dass Du mich gleich steinigst. :}

Wir müssen uns heutzutage auch mit AROS, MorphOS und OS4 auseinander setzen - und dies beinhaltet, dass Interrupts dort ganz anders aussehen weil ja die Hardware eine andere ist.
Okay, für Classics mag das alles noch seine Gültigkeit besitzen, aber schon unter einer Emulation kann ein VBlank Interrupt-Code, der unter Classics fünfzig Mal in der Sekunde aufgerufen wird, weitaus öfter aufgerufen werden. Unter WinUAE ist es keine Schwierigkeit, einen VBlank zweihundert Mal pro Sekunde zu initiieren.
Das Timer-Device bleibt davon allerdings verschont...

CIA Interrupts, um die es in diesen Beispielen geht, werden auch nicht von Exec verwaltet sondern von der betreffenden Ressource - somit ist die Abhandlung im RKM nicht vollständig.

Wer allerdings die Interna verstehen will, der sollte Deinem Rat folgen und diese Abhandlung im RKM lesen.

Anbei, C-Compiler berücksichtigen heutzutage solche Feinheiten wie Interrupts (vbcc geht hier noch einen Schritt weiter als gcc, da vbcc, wenn ich es richtig verstanden habe, auch anbietet Interrupts mit einem "rte" beenden zu lassen, was hilfreich ist, falls man einen Interrupt-Server/Handler schreiben will oder die Auto-Vektoren direkt, ohne Umweg übers Betriebssystem benutzt).

Auch bin ich persönlich der Meinung, dass gerade Anfänger, nicht Programmieranfänger sondern in Bezug auf Interrupts, nicht zu viel auf einmal zugemutet werden sollte - man kann einfache Dinge auch verkomplizieren. Als es noch Stand der Dinge war, Intros/Demos zu schreiben, haben wir ja die Auto-Vektoren direkt benutzt und deren Handhabung ist ja wirklich alles andere als schwer.


Zitat:
Was ich allerdings bis heute nicht begreife ist, wie er so schlechte Ergebnisse bekommen kann. Auf meinen Maschinen hier ist das timer.device auch bei recht kurzen Intervallen "stabil" genug, um nicht dermaßen gigantische Abweichungen zu produzieren. Insofern wäre es schon recht interessant zu erfahren, woran es bei ihm hapern könnte.

Viele Dinge haben einen Einfluss darauf. Die verwendete Programmiersprache zum Beispiel - Basic ist langsamer als C. Wenn dann noch der verwandte Basic-Compiler nicht der schnellste ist, wird's langsam eng (je mehr Sicherheit geboten wird desto langsamer muss das erstellte Programm sein; alle Überprüfungen kosten Laufzeit).
Zudem haben viele Leute den Wunsch, das Aussehen der Oberfläche aufzupeppen - wenn dann noch Patches verwandt werden, die sich unsauber ins System einklinken und Ressourcen verschwenden, geht die CPU-Last rauf und die Leistungsfähigkeit runter.
Es kann aber auch sein, das ein simpler Fehler in seinem Programm so drastische Unterschiede zu Tage bringt.

Kann man irgendwo einen Blick auf seinen Code werfen?


Zitat:
Mal davon ab, wenn die Puffer groß genug sind kannst Du den Goertzel sicherlich auch "direkt" drüberrennen lassen, es wird ja im Interrupt weitergesamplet (am schlauesten in den nächsten Puffer).

Zitat:
Ja, da müsste ich dann wieder zu C übergehen.

Zitat:
Ich dachte, der Basic-Goertzel wäre schnell genug für Echtzeit?



Wenn er den gleichen Algorithmus meint wie ich und er mit 28kHz oder gar 44kHz digitalisieren will, wird das nicht in Echtzeit unter Basic gehen - zumindest nicht mit 'ner 030 CPU.


Tschö! :)
 
jolo   Nutzer

08.11.2007, 19:35 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi,

Zitat:
Kannst Du das Beispiel mittels Holgers Hinweis assemblieren?

Zitat:
Ja, geht. Naja bis auf diese click-störungen.


Diese Störungen sind nur während der Datenaufzeichnung und dem gleichzeitigen Abspielen hörbar.
Es hat nichts mit der Aufzeichnung selber zu tun. Da der CIA-B Timer nicht hundertprozentig im Takt mit der Audio-Ausgabe läuft, kommt es zu Überschneidungen, die diese Störgeräusche verursachen. Ein größerer CHIP-RAM Puffer für die Audio-Hardware ("AUDSIZE EQU 65535") wirkt dem entgegen sowie die Leseintervalle um einen Tick erhöhen (41 anstatt 42 (_PAL_NTSC_TIMES)) - denn wenn die Audio-Hardware schneller Daten ausgibt als der CIA-B-Interrupt Daten liest, kommt es unweigerlich zu Störungen - aber wie gesagt, diese Störungen hörst Du nur während des Digitalisierens - nicht beim Abspielen der aufgezeichneten Daten zu einem späteren Zeitpunkt. Nochmals, diese Knackgeräusche werden nicht aufgezeichnet!
Ach ja, Du kannst STARTOFFSET auch einen größeren Wert zuweisen - dann startet die Audio-Ausgabe verzögert und somit stehen mehr Daten bereit, bevor eine hörbare Ausgabe erfolgt (kannst ja mal die halbe Größe von AUDSIZE probieren).
STARTOFFSET ist hier zu finden:
code:
Original:
	cmpi.l	#4,D0	; Indicator for start audio (leading bytes)
	bne.s	.out	; If not...
in
	cmpi.l	#AUDSIZE/2,D0	; Indicator for start audio (leading bytes)
	bne.s	.out	; If not...
ändern.



Zitat:
Jetzt muss ich das ganze noch auf eine bessere Frequenz bringen [...]

Da die maximale Sampling-Frequenz 28801 Hertz beträgt (Hardware-Limit), entspricht dieser Wert einer Periode von 124 (für die Audio-Hardware müssen Hertz-Werte in Perioden-Werte umgerechnet werden) - also musst Du im Beispiel 214 durch 124 ( 1 / (28801 * 0.000000279365) = 124,28 ) ersetzen - und das für alle vier Audio-Kanäle.

Zudem musst Du die Leseintervalle verkürzen:
_PAL_NTSC_TIMES 25,25 -> 709379/28801 bzw. für 60 Hz-Netzspannungen: 715909/28801

Anbei, wieso sind 16000 Hz nicht ausreichend? Ich habe früher mit 14000 Hz digitalisiert - und zwar ganze Musikstücke und diese sind selbst nach heutigen Standards noch ganz manierlich anzuhören.


Zitat:
[...] und herrausfinden wie man ein CTRL-C an das Programm schickt.

Selbst das Senden eines CTRL-C Signals bringt Dir alleine rein gar nichts - weißt Du wo die Daten liegen, damit diese von Deinem Hauptprogramm aus gelesen werden können? Und, gibt es überhaupt einen Datenbereich? Weiterhin, was passiert, wenn das Programm ein CTRL-C Signal empfängt?
Das Beispielprogramm (ASM) in seiner jetzigen Form ist dafür gänzlich ungeeignet - das zweite, in C verfasste Beispiel (AudioGrabber2) schon eher.


Zitat:
Am besten währe natürlich das vollständige Verstehen.

Solange Du keine fehlerfreie Installation von vbcc hast, wird das nichts.

Ich kann Dir alternativ anbieten, eine Shared-Library für Dein Problem zu programmieren - falls Du diese von Basic aus benutzen kannst.
Allerdings kann ich schon jetzt sagen, dass ich dies diese Woche nicht mehr schaffe.


Zitat:
Momentan hab ich herrausgefunden das das timer.device unter einem 030er noch nichtmal mit 1500 HZ korrekt arbeitet...

Das ist doch schon mal ein Anfang. :)

Frage: Meinst Du auf Prozess/Task-Ebene oder das Beispiel mit dem Software-Interrupt?
Was ich vergessen habe zu erwähnen ist, dass der Agnus-Baustein bedingt durch das Zusammenspiel aller Hardware-Komponenten nur in festgelegten Intervallen Software-Interrupts auslösen darf/kann. Weil ich mich aber nie damit tiefer beschäftigt habe, gehe ich davon aus, dass nur entsprechend der Bildschirmwiederholfrequenz Software-Interrupts ausgelöst werden. Um das zu verifizieren müsste ich aber erstmal das Hardware-Reference-Manual wieder finden... (dem Betreffenden, der eine abfällige Bemerkung über meinen Ordnungssinn macht, haue ich die Kartoffel vom Kopf ;) ).
Wie gesagt, ich benutze Software-Interrupts in abgewandelter Form - bei mir wird 50-mal in der Sekunde eine Aktion durchgeführt - und nicht 14000 oder gar 28000-mal. Das überfordert den Agnus-Chip.

Es würde mich interessieren, ob unter MorphOS/OS4 diese Einschränkung weiterhin besteht.


Auf Prozess/Task-Ebene wage ich zu bezweifeln, ob Du das Timing überhaupt in den Griff bekommst - zu viele Faktoren spielen hier eine Rolle.


Gruß
 
jolo   Nutzer

07.11.2007, 23:22 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@MaikG:

Hi Maik,

Kannst Du das Beispiel mittels Holgers Hinweis assemblieren?


Gruß
 
jolo   Nutzer

07.11.2007, 23:19 Uhr

[ - Direktlink - ]
Thema: Registerzugriff in C
Brett: Programmierung

@uho:
Zitat:
Übrigens ist AsmOne (bzw. dessen Grafikkarten-fähiges Pedant
AsmPro) nicht einfach nur ein Assembler, sondern eine komplette
Entwicklungsungebung mit grafischer Oberfläche, Monitor,
Debugger und Vielem mehr !
Dabei besteht er nur aus einer einzigen Datei (plus Config)
und kann dadurch praktisch auf jedem Amiga-System bei gleich-
zeitig sehr ergonomischer Benutzführung verwendet werden.

Fazit: Unbedingt anschauen !


Nee, Danke. Seit 1992 benutze ich ausschließlich Devpac 3 für meine Assembler-Projekte.
Devpac heißt die gesamte IDE, GenAm ist der Assembler, MonAm der Debugger und der Devpac nennt sich auch der Texteditor und es ist wohl das Beste kommerzielle Assembler Paket, dass je für den Amiga entwickelt wurde.
Vorher habe ich wie viele andere auch den ASSEM-Assembler (MetaComCo) und ALink verwendet, als dann SEKA rauskam, den SEKA-Assembler, der war sehr viel schneller als die Verbindung ASSEM und ALink - und man brauchte nur eine Diskette, auf der die System-Dateien (S, C, LIBS etc. - die Workbench war ja was für Memmen ;) ) sowie der Assembler Platz fanden. Das waren noch Zeiten... :)


Zitat:
@jolo: Alles ganz falsche Vermutungen ;-)

Yep, damit habe ich nicht gerechnet... :)
Ich habe vorausgesetzt, dass Maik schon eigenständig Programme in Assembler verfasst hätte.
Mein Fehler...


Gruß
 
 
1 2 -3- 4 Ergebnisse der Suche: 110 Treffer (30 pro Seite)

Suchbegriffe
Schlüsselwörter      Benutzername
Suchoptionen
Nur in diesen Foren suchen
   nur ganze Wörter
Nur Titel anzeigen
alle Treffer anzeigen

.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.