Ich suche nach einer Möglichkeit, um z.B. mit einem Atmega8 die MIDI-Telegramme, welche von einem MIDI-Keyboard kommen, dahingehend zu ananlysieren, a) Welche Taste ist gedrückt und b) die Lautstärke. Nach meinen ersten Versuchen bin ich so weit, dass ich über PinD.0 (RXD) (Pin2-Atmega8) Signale über den UART lesen kann. Ich benutze BASCOM und habe festgestellt, dass Waitkey() und Input bzw. Inkey() nicht brauchbar sind. Deshalb warte ich in einer ISR auf ein Byte. Bei der Auswertung scheint aber alles zu langsam zu sein, was ich bis jetzt so probiert habe. Jetzt meine Frage: Wer hat Erfahrung mit dem UART und der anschließenden Auswertung? Ich bin für jeden Tipp und jede Hilfestellung dankbar. Schönen Abend wünscht HPT
Er meinte damit, daß du dein Programm hier komplett posten sollst, damit er abkupfern und es als sein geistiges Eigentum verkaufen kann ..... wie immer.
Du kannst dir z.B. zunutze machen, das Command Bytes bei Midi das 8.Bit gesetzt haben und Datenbytes nicht. Deine ISR könnte also darauf achten und bei einem Commandbytes anfangen, in einen Buffer zu schreiben. Sobald das nächste Command Byte kommt, ist der MIDI Befehl abgeschlossen und fertig zur Ausgabe, während das nächste Command im Buffer landet. Das Problem ist, das der Mega8 nur einen Hardware UART hat, du kannst also nur mit 31250 Baud empfangen und senden, wenn du TXD des Mega zur Ausgabe benutzt.Wenn du hingegen z.B. ein LCD als Augabe benutzt, entsteht dieses Problem nicht. Ein Software Serial geht natürlich auch, oder du schickst was auf eine LED (7-Segment) Anzeige oder so. Es gibt natürlich noch massenweise andere MIDI Empfangsstrategien. Man könnte z.B. ein Flag bei einem Command Byte setzen, oder eben bei einem Datenbyte usw. Geräte, die nur auf einen MIDI Kanal reagieren, filtern alles weg, was nicht mit einem Command für ihren Kanal begonnen hat, usw.
:
Bearbeitet durch User
Servus Matthias - danke für die Tipps. Eigentlich möchte ich nur nach "dez.144" (Noteon) suchen und danach die beiden Bytes auswerten (Ton, Lautstärke) alles andere brauche ich gar nicht. Aber wie mache ich das so schnell, dass nichts verschluckt wird, wenn eine Taste nur kurz gedrückt wird, bzw. ein "Lauf" auf der Tastatur gespielt wird? Gibr es Beispiele ? Bin für alles dankbar!!!
HPT schrieb: > . Aber wie mache ich das > so schnell, dass nichts verschluckt wird, wenn eine Taste nur kurz > gedrückt wird, bzw. ein "Lauf" auf der Tastatur gespielt wird? alles was du man Tasten erreichen kannst ist LANGSAM. in Der Zeit kann der Controller noch PI neu berechnen. Keine Ahnung wie es mit BASCOM geht. Bei C würde man den code einfach in der ISR für den UART RX hängen und die Daten abfragen. Das langsamste ist die UART(Midi) Übertragung und nicht der Controller.
HPT schrieb: > Aber wie mache ich das > so schnell, dass nichts verschluckt wird, wenn eine Taste nur kurz > gedrückt wird, bzw. ein "Lauf" auf der Tastatur gespielt wird? Du könntest in der ISR bspw. nach einem 'NoteOn' eine Flagge setzen und solange die Flagge gesetzt ist, Bytes, die kleiner sind als 128 (also Datenbytes) speichern. Die Flagge wird gelöscht, wenn ein Byte >128 kommt, das kein NoteOn ist. Das langsame ist nicht der Empfang des Zeichens, die ISR meldet sich ja erst, wenn ein Zeichen komplett da ist - beim Stopbit. Deswegen hast du während des Empfangs Zeit, um dich um andere Sachen zu kümmern. Dein Problem ist vermutlich, den Kram auszugeben. Ob ein LCD unter Bascom schnell genug ist, weiss ich nicht, aber in C klappt das immer.
HPT schrieb: > "dez.144" (Noteon) suchen und danach die beiden Bytes auswerten (Ton, > Lautstärke) alles andere brauche ich gar nicht. Nur so nebenbei: Das Statusbyte ("Note On") muss nicht zwingend am Anfang jeder Noten-Message stehen - u.U. wird das nur einmal gesendet und es kommen minutenlang nur Datenbytes (Notennummer-Anschlag-Notennummer-Anschlag...) Das heißt "Running Status".
:
Bearbeitet durch User
... liest sich alles interessant! Aber wie geh ich vor? Es gelingt wie schon geschrieben, in der ISR das Byte auszulesen. Ich bräuchte ein Beispiel wie man prinzipiell Daten in einen Buffer schreibt, bzw. vor allem auch wie ich danach im Hauptprogramm nach "144" suche und das alles so gestalte, dass ein weiterer Interrupt, der ja zu jeder zeit kommen kann und auch wird, wenn die Tasten schnell genug hintereinander gedrückt werden! Von diesem "running status" habe ich noch nichts gelesen Thomas. Ist auch interessant, aber momentan sind meine Probleme noch grundsätzlicher. Vielleicht hat doch noch jemand verwertbare Programm-Teile. Ich würde mich sehr freuen.
Du könntest Dir erstmal ein FIFO (als Ringpuffer) anlegen und in der ISR nix anderes machen, als jedes Datenbyte, das über UART hereinkommt, dort hineinzuschreiben. Google mal nach FIFO (s.auch: https://www.mikrocontroller.net/articles/FIFO) Im Hauptprogramm holst Du die Bytes aus dem FIFO (wenn welche drin sind, d.h. wenn write- und read-Indexe verschieden sind) und verarbeitest sie - damit ist schonmal das Timing der Verarbeitung vom Timing des Empfangs entkoppelt. Für die Verarbeitung bietet sich eine State-Machine an. Kommt ein Byte mit MSB=1, ist es ein Statusbyte -> Statusbyte abspeichern, State auf "erwarte erstes Datenbyte" setzen. Außer, wenn es eine Echtzeit-Message (>= 0xF8) ist - die darf immer kommen, auch zwischen Datenbytes einer anderen Message -> Du ignorierst sie, ohne den State der Statemachine zu ändern. Ist das Statusbyte eines, mit dem Du nix anfangen kannst oder willst (z.B. SysEx und co., Bereich 0xF0..0xF7), setzt Du den neuen State Deiner Statemachine auf "erwarte Statusbyte" Kommt ein Datenbyte (MSB = 0) und State ist "erwarte erstes Datenbyte", speicherst Du das erste Datenbyte in einer Variablen (z.B. data1). Wenn das gespeicherte Statusbyte zu einer MIDI-Message gehört, die nur ein Datenbyte hat (z.B. Program Change), ist die empfangene MIDI Message vollständig (-> verarbeiten), neuer State der Statemachine ist dann wieder "erwarte erstes Datenbyte". Wenn zum Statusbyte zwei Datenbytes gehören: State = "erwarte zweites Datenbyte". Kommt ein Datenbyte (MSB = 0) und State ist "erwarte zweites Datenbyte", ist Deine MIDI-Message komplett -> verarbeiten. State auf "erwarte erstes Datenbyte" setzen - wg. Running Status! Kommt ein Datenbyte und nach aktuellem State erwartest Du kein Datenbyte, ignorierst Du das Datenbyte einfach.
Hallo picalic Einiges konnte ich umsetzen. Es läuft mein Ringpuffer und ich kann über eine ISR die MIDI-Telegramme hineinschreiben. Es ist mir in BASCOM auch gelungen, Bytes aus dem Ringpuffer zu lesen. Nur bei der Realisierung der Decodierung nach Status bzw. Daten-Bytes will es mit if-then ... nicht gelingen. Vor allem auch der running-status und wenn andere Statusbytes zwischenkommen wird alles komplex. Wahrscheinlich ist die "state-machine" wohl das Richtige! Wie geht man da an die Sache? Könnte man das mit "select case" Kommandos aufbauen? Noch kann ich mir nicht vorstellen, wie das aussehen könnte. Kann man dein obiges Prinzip noch etwas veranschaulichen? Schönen Abend und Danke für die Unterstützung!
HPT schrieb: > Wie geht man da an die Sache? Könnte man das mit "select case" Kommandos > aufbauen? von BASCOM habe ich keine Ahnung - "select case" klingt aber so, als wäre es wie "switch case" in C, und somit könnte es schonmal ein geeignetes Werkzeug sein. "If"-Abfragen gehen im Prinzip aber auch, nur ist es dann halt ggf. etwas unübersichtlicher, als eine einzige Verzweigung mit vielen cases. Die State-Machine kann man mit einer simplen Variablen realisieren, über die dann mit "case" auf die entsprechenden Programmteile verzweigt wird. Da Status- und Datenbytes grundsätzlich leicht zu unterscheiden sind (am MSB) und auch grundverschieden verarbeitet werden müssen, bietet sich an, zunächst mit "if" in je eine Verarbeitungsroutine für Daten- und eine für Statusbyte zu verzweigen. Dort kann es dann anhand von gespeicherten Daten (z.B. vorher empfangenes Statusbyte, aktueller Wert der "State"-Variablen) entsprechend weiterverarbeitet werden.
:
Bearbeitet durch User
Ich denke, meine Dekodierung der MIDI-Telegramme funktioniert jetzt! Habe eine state-machine (glaube ich) zusammengebastelt und im Simulator getestet. Jetzt habe ich sie zusammen mit dem Ringpuffer am Atmega 8 im Probelauf und es schaut gut aus. Ich möchte mich nochmal bei allen Ratgebern herzlich bedanken.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.