Forum: Mikrocontroller und Digitale Elektronik MIDI Note mit assembler über UART ausgeben


von Walter (Gast)


Lesenswert?

Hallo Mitstreiter,

ich bin hier am verzweifeln und hoffe auf einen Hilfreichen Tipp.
Ich kann leider Nur Assembler und damit habe ich auch schon viel 
erreichen können.
Es geht mir um das Ausgeben einer MIDI-Note.

Ich habe schon einiges zu dem Thema gefunden und normalerweise sollte es 
recht einfach gehen. Dennoch gelingt es mir nicht, einen Ton aus dem 
01R/W zu bekommen.

Ich schließe meine Keyboard an den 01R/W an und betätige die Taste für 
ein A (440Hz) und die Empfangs Led am 01R/W blinkt auf und auch der Ton 
wird höhrbar.

So weit, so gut.

Nun schließe ich meine Schaltung an und auch bei mir blinkt die Empfangs 
Led aber es wird kein Ton hörbar. Cubasis empfängt auch keine Noten ...

Mit dem Oszi werden 3 gesendete Bytes erkennbar und ein Bit braucht 33µs
Am Keyboard sind es auch 33µs

Vieleicht hat ja einer von euch eine Idee...

Ich dachte mir, Mit dem ATMega 32 sollte es kein Problem sein.

**** 1. Bautrate ermitteln:
;Variabelen und Vorgabewerte

     .equ     TAKT = 8000000    ; Systemtakt 8.000 MHz
     .equ     BAUD  = 31250     ; Baudrate für MIDI

; Berechnungen
.equ UBRR_VAL   = ((TAKT+BAUD*8)/(BAUD*16)-1)    ; clever runden
.equ BAUD_REAL  = (TAKT/(16*(UBRR_VAL+1)))      ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille

.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille 
Fehler
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit 
zu hoch!"
.endif

**** 2. Bautrate in Register ablegen

; Baudrate einstellen

    ldi     akku, HIGH(UBRR_VAL)
    out     UBRRH, akku
    ldi     akku, LOW(UBRR_VAL)
    out     UBRRL, akku

**** 3. UART konfigurieren
    ; Frame-Format: 8 Bit

;    ldi     akku, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
;    out     UCSRC, akku
; Abgeschaltet da in Midirec auch nicht gewesen

    sbi     UCSRB,TXEN                  ; TX aktivieren

**** 4. 3 Byte Vorbereiten:

lds   akku, 0b01101111  ; Note on CH1
sts    MIDI1, akku
lds   akku, 0b10000101  ; Note A4 (69 MIDI = 45 Hex)
sts    MIDI2, akku
lds   akku, 0b10000000  ; minimale Lautstärke (0) (Note off)
sts    MIDI3, akku

**** 5. 3 Byte senden

MIDIout:
  push  akku

MIDIout1:
sbis    UCSRA,UDRE               ; Warten bis UDR für das nächste
                                 ; Byte bereit ist
rjmp    MIDIout1
LDS  akku, MIDI1
out     UDR, akku
MIDIout2:
sbis    UCSRA,UDRE                ; Warten bis UDR für das nächste
                                  ; Byte bereit ist
rjmp    MIDIout2
LDS  akku, MIDI2
out     UDR, akku
MIDIout3:
sbis    UCSRA,UDRE                  ; Warten bis UDR für das nächste
                                        ; Byte bereit ist
rjmp    MIDIout3
LDS     akku, MIDI3
out     UDR, akku

pop  akku
ret

**** und zum Schluss
.DSEG
MIDI1:  .BYTE   1         ; MIDI - Befehl/Kanal
MIDI2:  .BYTE   1         ; MIDI - Controlernummer(Note)
MIDI3:  .BYTE   1         ; MIDI - Controlerwert (Lautstärke)

Ich hoffe Ihr könnt mir folgen,
Liebe Grüße und vielen Dank
Walter

von eProfi (Gast)


Lesenswert?

Ein Bit dauert 32 Mikrosekunden.
Du schickst im 2. Byte nicht 45, sondern 85.
Lautstärke 0 oder 80? Kommentar muss immer zum Code passen.
Manche Geräte schicken statt Note off ein Note on mit Lautstärke 0.

Passt die Polarität? Normal fließt kein Strom in der Schleife.

von Thomas E. (picalic)


Lesenswert?

Walter schrieb:
> lds   akku, 0b01101111  ; Note on CH1
> sts    MIDI1, akku
> lds   akku, 0b10000101  ; Note A4 (69 MIDI = 45 Hex)
> sts    MIDI2, akku
> lds   akku, 0b10000000  ; minimale Lautstärke (0) (Note off)
> sts    MIDI3, akku

Warum gibst Du die Werte der Bytes binär an? Wenn Du es dann wenigstens 
selbst korrekt ausgerechnet hättest...

Also, das Statusbyte für "Note On Ch1" ist 0x90 (= 0b10010000) - Deins 
scheint (warum auch immer) invertiert zu sein.

0x45 ist 0b01000101 - Deins ist 0x85 (=>Statusbyte "Note off on Ch 6")

Dein Velocity-Wert 0 würde (wenn er richtig codiert wäre - tatsächlich 
sendest Du 0x80 = Statusbyte Note Off on Ch1) als
 "Note Off" interpretiert - da müsstest Du Dich auch nicht wundern, wenn 
Du nix hörst. Probier's mal mit mittlerem Velocity-Wert, also 0x40.

Bei der obigen Sequenz also:
> lds   akku, 0x90  ; Note on CH1
> sts    MIDI1, akku
> lds   akku, 0x45  ; Note A4 (69 MIDI = 45 Hex)
> sts    MIDI2, akku
> lds   akku, 0x40  ; mittlere Lautstärke 64
> sts    MIDI3, akku

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

> lds   akku, 0x90  ; Note on CH1
> sts    MIDI1, akku
> lds   akku, 0x45  ; Note A4 (69 MIDI = 45 Hex)
> sts    MIDI2, akku
> lds   akku, 0x40  ; mittlere Lautstärke 64
> sts    MIDI3, akku

Da muss doch jeweils ldi stehen statt lds, oder?

von Walter (Gast)


Lesenswert?

Hallo, zusammen,

das ist ja der Hammer! Wer wird mir schon helfen? Und dann so schnell! 
Ganz herzliches Dankeschön! Super Kommentare und es läuft.

Aber für alle die das Gleiche erleben, hier noch mal konkret:

Ich war so verzweifelt und suchte nach jedem Halm. In einem der Beiträge 
war erwähnt, dass die Bits invertiert werden müssen – ein Versuch 
zeigte, dass es deshalb trotzdem nicht klappte. Ich vergas die 
Invertierten Bits zurück zu schreiben!

Also Rüffel zu Recht und sorry!

; **** Note on:
    ldi   akku, 0b10010000  ; Note on und CH1 (000)
    sts    MIDI1, akku
    ldi   akku, 0b00100100  ; Note C1 (36 MIDI = 25 Hex)
    sts    MIDI2, akku
    ldi   akku, 0b01111111  ; maximale Lautstärke (127) (Note on)
    sts    MIDI3, akku

    call  MIDIout

; **** Note off:
    ldi   akku, 0b10010000  ; Note on und CH1 (000)
    sts    MIDI1, akku
    ldi   akku, 0b00100100  ; Note C1 (36 MIDI = 25 Hex)
    sts    MIDI2, akku
    ldi   akku, 0b00000000  ; minimale Lautstärke (0) (Note off)
    sts    MIDI3, akku


Mein Fehler bestand tatsächlich in dem LDS ... ganz klar, den akku läd 
man mit einer Zahl mit "ldi" und schon spielt die Musik! - Naja - die 
Note ;-)

Übrigens angeregt durch den Beitrag "MIDI-Controller selber bauen" von 
Götz Müller-Dürholt

https://www.youtube.com/watch?v=a6pex3DwNjs

baue ich ein Gerät zum wiedergeben von Wierderständen in Form von 
Midinoten.

Also nochmals Danke für die absoulut korrekte und sehr ziehführende 
Hilfe!

Viele Grüße
Walter

von Thomas E. (picalic)


Lesenswert?

Ok, das mit dem LDS vs. LDI wäre mir vielleicht auch aufgefallen, wenn 
ich mehr mit AVRs zu tun hätte... ;)

Deinen Hang zu Zahlenwerten im Binärsystem kann ich immer noch nicht 
nachvollziehen. Das macht es hier doch nur unleserlich und 
fehleranfällig.
Beim MIDI Statusbyte bietet sich hexadezimale Schreibweise an (erstes 
Digit = Funktion, z.B. 9 = Note On, zweites Digit: MIDI-Kanal 0..F -> 
K.1..16), Notennummer und Velocitywert könnte man auch dezimal angeben - 
was soll hier die Binärdarstellung?

: Bearbeitet durch User
von Walter (Gast)


Lesenswert?

Hallo Thomas,

ja, Du hast recht, die Hex darstellung ist sehr schön. Ich war nur auf 
der Fehlersuche und wollte die seriellen Bits mit dem Bild vom Oszi 
vergleichen und da kann ich mir besser vorstellen wie das Signal 
aussehen muss :-)

von J. S. (engineer) Benutzerseite


Lesenswert?

Sendest Du regelmäßig den MIDI-Takt?

von Bla (Gast)


Lesenswert?

Wie kann man leider nur assembler können? C ist viel einfacher und 
schnell gelernt, wenn man eh weiß was sich unter dem Blech abspielt.

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
Noch kein Account? Hier anmelden.