watterott ;title =
Seite 2 von 4 ErsteErste 1234 LetzteLetzte
Ergebnis 11 bis 20 von 35

Thema: MIDI Monitor mit Bascom und Atmega8

  1. #11
    Kabelträger
    Registriert seit
    28.12.2016
    Beiträge
    16
    Guten Abend! Ich hab inzwischen einiges probiert! Das Auslesen der Bytes per Interrupt und das Einschreiben in einen Buffer scheinen soweit zu funktionieren. Aber insgesamt ist alles noch zu langsam. Etwas schnellere Tastenbetätigungen werden nicht erkannt! Das Prinzip scheint zu funktionieren, aber wie kann ich diese Routinen schneller machen? Wie liest man aus dem Buffer am schnellsten aus? Ich hänge mal meinen Versuch an, vielleicht kann jemand helfen!! Würde mich sehr freuen .....
    $regfile = "M8adef.dat"
    $crystal = 16000000 '16Mhz
    $baud = 31250 ' 31,25 kBit (MIDI-Baudrate)
    '************************************************* ***********************
    Config Lcdpin = Pin , Db4 = Portb.3 , Db5 = Portb.2 , Db6 = Portc.2 , _
    Db7 = Portc.1 , E = Portb.4 , Rs = Portb.5
    Config Lcd = 16 * 2
    ' ************************************************** *********************
    Config Portd = Output 'PinD.5=LED1, PinD.6=LED2, PinD.7=Summer
    Config Pind.2 = Input '=Taster 1
    Config Pind.3 = Input '=Taster 2
    Config Pind.4 = Input '=Taster 3

    Config Pind.0 = Input '= RXD - Pin2 Atmega8 = Midi-Eingang

    ' ------------------------
    Dim S As String * 5 At &H60
    Dim B(5) As Byte At &H60 Overlay
    Dim N As Byte
    Dim T As Integer 'Zählvariable


    On Urxc Rxd_isr
    Enable Urxc
    Enable Interrupts

    '************************************************* ***********************
    Cursor Off Noblink
    Cls
    Main:

    If N > 2 Then 'Wenn Buffer 3 bytes eingeschrieben hat, dann
    ' 5 Werte auf "144" prüfen
    For T = 1 To 3
    If B(t) = 144 Then
    Cls
    Locate 1 , 1
    Lcd B(t) 'Byte 1 = note an
    Locate 1 , 5
    Lcd B(t + 1) 'Byte 2 = Note (welcher Ton)
    Locate 1 , 8
    Lcd B(t + 2) 'Byte 3 = Lautstärke (0= Ton aus)
    End If
    Next T
    N = 0 'Rücksetzten Buffer-Zähler
    End If


    Goto Main

    '*** UP - Empfangen ***********

    Rxd_isr:
    Incr N
    B(n) = Udr
    Toggle Portd.5 'signalisiert Interrupt

    Return

    Bitte um Hilfestellung - Danke !!! Schönen Abend noch!

  2. #12
    Administrator Avatar von DON
    Registriert seit
    19.11.2016
    Ort
    Herford
    Beiträge
    371
    On Urxc Rxd_isr no save
    dann werden nicht mehr alle 32 Register gerettet.
    Das must du dann per Hand erledigen.

    When you omit NOSAVE all used registers will be saved. These are SREG , R31 to R16 and R11 to R0 with exception of R6,R8 and R9 .

    R12 – R15 are not saved. When you use floating point math in the ISR(not recommended) you must save and restore R12-R15 yourself in the ISR.
    My_Isr:
    Push R12 ' save registers
    Push R13
    Push R14
    Push R15

    Single = single + 1 ' we use FP

    Pop R15 ' restore registers
    Pop R14
    Pop R13
    Pop R12
    RETURN


    When the AVR has extended IO-space (for example ATMega48, 88 or 168, see datasheet at the end: Registersummary), the compiler uses R23 for a number of operations. So Push and Pop R23 as well when using the NOSAVE-option when using these AVR's with extended IO-space.
    Cls dauert sehr lange.
    Besser Lcd " " zum Löschen.
    Geändert von DON (03.01.2017 um 20:14 Uhr)
    Ein Mensch mag noch so herausragende Fähigkeiten haben – wenn er arrogant und selbstsüchtig ist, sind sie nichts wert.
    Konfuzius


  3. #13
    Spaghetti-Coder
    Registriert seit
    10.11.2016
    Beiträge
    74
    Zitat Zitat von DON Beitrag anzeigen
    On Urxc Rxd_isr no save
    dann werden nicht mehr alle 32 Register gerettet.
    Das must du dann per Hand erledigen.
    Hallo Don,
    um die 130 Takte (weniger als eine 1/100.000 s braucht er sich keine Gedanken zu machen.
    Die Verarbeitung dauert dagegen fast 300.000, also fast 20ms. Das kommt halt von der Ausgabe aufs Display.

    @hpt_neu,
    da sind einige Dinge, die ich ändern würde.
    Lass zunächst mal das overlay auf den String s weg. Du benutzt s eh nicht, als schreibe einfach
    Dim B(5) as Byte 'warum eigentlich 5 wenn du nur 3 Byte erwartest?
    Wozu benötigst du T und die For-Schleife über T?
    Da in B(1)=144 sein muss, kannst du auch genauso gut dies nehmen:
    If N>2 then
    Cls
    Locate 1 , 1
    Lcd B(1) 'Byte 1 = note an
    Locate 1 , 5
    Lcd B(2) 'Byte 2 = Note (welcher Ton)
    Locate 1 , 8
    Lcd B(3) 'Byte 3 = Lautstärke (0= Ton aus)
    End If

    Das CLS benötigt etwa 6ms. Kannst du das nicht einfach weglassen und sicherstellen, dass du an die richtige Stelle schreibst?
    Wenn du das Einlesen und die Ausgabe entzerren willst, kannst du direkt hinter der Abfrage N>2 dein B-Array in ein C-Array retten und damit die Ausgabe machen. Dann kann in der Zwischenzeit die Leseroutine wieder Zeichen empfangen.
    Da du immer mit 144 startest wäre es sinnvoll, eine Abfrage auf das eingelesene Zeichen zu machen und die 144 dann in B(1) einzulesen.

  4. #14
    Kabelträger
    Registriert seit
    28.12.2016
    Beiträge
    16
    Hallo Don, hallo Basti! Danke für eure Experisen. Ich bin für jede Anregung dankbar! Vielleicht sollte ich sagen, dass die Anzeige gar nicht mein Ziel ist! Mein Vorhaben wäre, eine selbstgebastelte Pfeifenorgel, mit einer Midi-Tastatur anzusteuern - sprich - einmal zu spielen. Dazu muß ich aber erst einmal die MIDI- Informationen welche von einem MIDI-Keyboard kommen dahingehend decodieren, um welchen Ton es sich handelt! Nach meinen Studien kommt vom Keyboard ca. alle 300ms ein sogenanntes "activ Sense"-Signal (dez.254). Wenn eine Taste gedrückt wird, kommt "Note on" (dez.144). Auf dieses muß ich reagieren, denn anschließend kommt ein Byte mit der Info um welchen Ton es sich handelt (z.B. C entspricht dez. 60) und um die velocity( dez.0 bedeutet Ton aus).
    Im ersten Versuch möchte ich eine Oktave abdecken, d.h. ich bräuchte 12 Ausgänge (liese sich mit dem Atmega8 machen) die in Anhängigkeit vom Ton, meine Magnetventile für die Luftzufuhr an die Pfeifen, ein und aus-schalten. Die hardware wäre schon testfähig, aber meine Programmierkenntnisse scheinen hier doch nicht ausreichend zu sein.
    Von meinem Verständnis her denke ich mir das so, dass ein Interrupt bei jedem Zeichen welches über MIDI kommt ausgelöst wird. Aber beim zeitgerechten Verarbeiten scheint es zu hapern. Wie könnte ich also effizient abfragen, 1. ist es 144 (alle anderen Informationen auf dem MIDI interessieren im Moment nicht) - 2. Welche Taste wurde gedrückt (welcher Ton)- 3. ein oder aus , dann gib an einem bestimmten Portpin (zugeordnet C,cis,d,dis,e,f ....) eine log 1 aus!
    Meine ersten Versuche mit waitkey() usw. funktionieren zwar prinzipiell, aber sind viel zu langsam. Beispiel: wenn eine Taste z.B. "C" gedrückt wird und kurz darauf wieder losgelassen (kurzer Ton) kommen unmittelbar z.B. 144,60,80 für Noteon,C,Lautstärke 80 - gefolgt von 144,60,0 Noteon,C,Lautstärke 0 (bedeutet Ton aus!). Wenn ich diese Info verschlucke, bleibt mein "C" hängen d.h. Ton klingt weiter, obwohl schon lange keine Taste mehr gedrückt ist!
    Ich denke, meine Sorgen sind damit beschrieben, aber nicht meine Hilflosigkeit, wie ich richtig an die Sache gehen soll .....

  5. #15
    Spaghetti-Coder
    Registriert seit
    10.11.2016
    Beiträge
    74
    Hallo hpt_neu,
    ich denke, die Abfrage mittels URXC Interrupt ist schon die richtige Vorgehensweise, weil es am schnellsten ist.
    Wie gesagt, würde ich das ankommende Byte zunächst mal auf 144 überprüfen.
    Dann merkst du dir, dass 144 eingetroffen ist, also als nächstes der Ton kommen muss.
    Kommt irgendwann einmal 144 an falscher Stelle, springt er wieder aus Start zurück. Bedeutet, 144 darf nicht als Ton oder Lautstärke kommen.
    Falls doch, muss die Überprüfung raus.
    Code:
    Const waiting=0
    Const start=1
    Const ton=2
    Dim Status as Byte
    Dim Zeichen as Byte
    Status=Waiting
     
    Rxd_isr:
       Zeichen = UDR
       Select case Status
       Case waiting:
          If zeichen = 144 then
             Status=start
          End If
       Case start:
          If zeichen <> 144 then 'dies ist für den Fall von Fehlern
             Note=zeichen
             Status=Ton
          End If
       Case Ton:
          If zeichen <> 144 then
             Laut=zeichen
             Status=waiting
             'nun könntest du auch gleich die Ausgabe aktivieren
          Else
             Status=Start
          End If 
       End Select
    Return
    Dies ist nicht getestet.
    Falls du ganz auf Nummer sicher gehen willst, kannst du auch noch einen Timer laufen lassen, der den Ton nach spätestens x Sekunden abschaltet.
    Ich hoffe, dass gibt dir einen Stupser in die richtige Richtung

  6. #16
    Kabelträger
    Registriert seit
    28.12.2016
    Beiträge
    16
    Hallo Basti - danke für deine letzte Version mit Case-Abfrage. Sind interessant und ich habe sie auch getestet. Sie funktioniert im Prinzip auch! Danke ! Leider ist auch diese Version zu langsam. Und zwar schon in der ISR (also ohne Anzeige am Display). ich habe zur Visualisierung einfach am Beginn der ISR ein Toggeln einer LED eingebaut und auch nach der Auswertung "Case Ton" an der stelle, wo du den Kommentar ' nun könntest du auch gleich die Ausgabe aktivieren - geschrieben hast.
    Durch Betätigen von Tasten am Keyboard erkennt man dann optisch sofort, ob der Tastenanschlag überhaupt erkannt wird! Der kritische Fall tritt ja ein, wenn z.B. eine Taste nur kurz angeschlagen wird, denn da folgen sofort zweimal 3 Byte - zuerst Ton ein - danach Ton aus, oder auch wenn mehrere Tasten fast gleichzeitig betätigt werden.....
    Im Moment kann ich mir nur vorstellen, die ISR-Routine so kurz als möglich zu halten und danach aus einem Buffer auszuwerten.
    Habe auch irgendwo schon gesehen, dass BASCOM auch mit Assembler kombinierbar ist. Vielleicht wäre auch das eine Möglichkeit? Vielleicht gibts auch irgendwo schon eine ähnliche Anwendung, wo praktisch fast in Echtzeit Bytes gelesen werden ?! D.h. eigentlich werden die Daten-Bytes wahrscheinlich schnell genug gelesen und danach der Interrupt ausgelöst, aber das Erkennen und Verarbeiten.....
    Im Internet bin ich bis jetzt nicht wirklich fündig geworden, aber die Hoffnung stirbt zuletzt - sagt man zumindest!

  7. #17
    Administrator Avatar von DON
    Registriert seit
    19.11.2016
    Ort
    Herford
    Beiträge
    371
    Kannst du die Quarz ändern.
    Angeblich soll 8 MHz am besten sein.
    Geändert von DON (05.01.2017 um 12:54 Uhr)
    Ein Mensch mag noch so herausragende Fähigkeiten haben – wenn er arrogant und selbstsüchtig ist, sind sie nichts wert.
    Konfuzius


  8. #18
    Spaghetti-Coder
    Registriert seit
    10.11.2016
    Beiträge
    74
    Hallo hpt_neu,
    ich kann es jetzt nicht verifizieren, würde aber aus Erfahrung tippen, dass die ISR, so wie von mir gepostet, max. 160 Takte benötigt, also etwa 1/100000s. In der Zeit schaffen alle, für Menschen hörbare Töne nur den Bruchteil einer Schwingung.
    Aber deine Übertragungsrate beträgt nur 31.250baud, was bei 3 Byte ungefähr 1ms pro Tastenanschlag entspricht. Da würde ich eher ein Problem sehen, was du aber wohl nicht ändern kannst. Der Controller wartet etwa 16.000 Takte, bis die nächste taste komplett übertragen wird. Da ist es egal, ob du es schaffst, ihn tatsächlich 16.100 Takte warten zu lassen.
    Wie soll das überhaupt gehen mit dieser langsamen Übertragung, wenn du zwei oder noch mehr Tasten gleichzeitig drückst? Während der Start eines Tones noch übertragen wird, ist der andere schon wieder aus, aber seine Übertragung muss noch warten.

    Was in meinem Schnipsel auf keinen Fall passieren wird, ist das auch nur ein einziges Byte übersehen wird, solange du nicht für irgendetwas anderes z.B. die Interrupts abschaltest.

    Zeige doch nochmal das ganze Programm, in dem der Fehler auftritt, dann kann ich das mal zu Hause simulieren.
    Und erkläre mal, wie du anhand der LED feststellst, dass etwas übersehen wurde.

    @DON 16MHz lässt sich glatt durch 31.250 teilen (=512), da tritt kein Baudfehler auf. Und je langsamer der Controller arbeitet, um so eher tritt sein Problem auf, wenn es denn daran liegen würde.
    Geändert von Basti (05.01.2017 um 14:34 Uhr)

  9. #19
    Kabelträger
    Registriert seit
    28.12.2016
    Beiträge
    16
    Hallo Basti - danke für deine rasche Reaktion!
    Hier mein Programm:

    ' Version 05 :
    ' File : At8N_MIDI_lesen_05.bas
    ' @ hpt 5.1.2017
    ' Atmega 8
    ' Midi Eingang auf RXD PinD0 (Pin2 Atmega8) !!!
    '
    ' Vorschlag und Idee Bascom-Forum Basti
    '
    ' ************************************************** *********************
    $regfile = "M8adef.dat"
    $crystal = 16000000 '16Mhz
    $baud = 31250 ' 31,25 kBit (MIDI-Baudrate)
    '************************************************* ***********************
    Config Lcdpin = Pin , Db4 = Portb.3 , Db5 = Portb.2 , Db6 = Portc.2 , _
    Db7 = Portc.1 , E = Portb.4 , Rs = Portb.5
    Config Lcd = 16 * 2
    ' ************************************************** *********************
    Config Portd = Output 'PinD.5=LED1, PinD.6=LED2, PinD.7=Summer
    Config Pind.2 = Input '=Taster 1
    Config Pind.3 = Input '=Taster 2
    Config Pind.4 = Input '=Taster 3

    Config Pind.0 = Input '= RXD - Pin2 Atmega8 = Midi-Eingang

    ' ------------------------
    Const Suchen = 0
    Const Decod = 1
    Const Ton = 2
    Dim Status As Byte
    Dim Zeichen As Byte
    Dim Note As Byte
    Dim Laut As Byte

    Status = Suchen 'Status zu Beginn setzen auf suchen



    On Urxc Rxd_isr ' Interrupt Routine RXD_isr setzen
    Enable Urxc 'Interruptroutine einschalten
    Enable Interrupts 'Interrupt global zulassen

    '************************************************* ***********************
    Cursor Off Noblink
    Cls
    Main:
    Locate 1 , 1 : Lcd " " 'löschen
    Locate 1 , 1
    Lcd Note 'Byte 2 = Note (welcher Ton)

    Locate 1 , 5 : Lcd " " 'löschen
    Locate 1 , 5
    Lcd Laut 'Byte 3 = Lautstärke (0= Ton aus)
    Goto Main


    '*** UP - Empfangen ***********
    Rxd_isr:

    Toggle Portd.6 ' singnalisieren

    Zeichen = Udr 'Byte auslesen und Zeichen übergeben
    Select Case Status 'Status abfragen
    Case Suchen:
    If Zeichen = 144 Then
    Status = Decod
    End If
    Case Decod:
    'If Zeichen <> 144 Then
    Note = Zeichen
    Status = Ton
    'End If
    Case Ton:
    If Zeichen <> 144 Then
    Laut = Zeichen
    Status = Suchen

    Toggle Portd.5 ' singnalisieren

    Else
    Status = Decod
    End If
    End Select
    Return
    ************************************************** *******************************************

    Mit Toggle Portd.6 sehe ich optisch an der Led wie schnell und wie oft die ISR aufgerufen wird, und mit Toggle Portd.5 erkennt man am Aufleuchten, ob und wie schnell die Routine diese Position erreicht!
    Interessanter weise muß ich ca eine halbe Sekunde auf der Taste verharren, damit sie erkannt und verarbeitet wird! Aber wenn man so lange wartet, kommt auch die Anzeige im Display wie erwartet.

    Nach der Theorie muß man damit rechnen, dass MIDI mit eben den genormten 31,25 kBit Baudrate arbeitet.

  10. #20
    Administrator Avatar von DON
    Registriert seit
    19.11.2016
    Ort
    Herford
    Beiträge
    371
    Sonst könntest du noch den gepufferten Empfang
    Testen der ist in Assembler geschrieben.
    Ein Mensch mag noch so herausragende Fähigkeiten haben – wenn er arrogant und selbstsüchtig ist, sind sie nichts wert.
    Konfuzius


Lesezeichen

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •