Close

First Attempt: Generating MIDI Note-On and Note-Off with ChatGPT

A project log for MIDI Interface for RC2014

Building MIDI Interface for RC2014. The goal of this project is to build a music system with RC2014 computer and external (legacy) MIDI box

morecatlabmorecat_lab 10/05/2024 at 05:510 Comments

First Attempt: Generating MIDI Note-On and Note-Off with ChatGPT

As the first step in this challenge, I tried creating a Z80 assembler program using ChatGPT.

While it is well-known that ChatGPT excels at generating programs in languages like Python, I am unsure if it can create a Z80 assembler program. For this attempt, I used "ChatGPT 4.0" (paid version). This version is relatively unrestricted and allows for the creation of customized GPTs, which I plan to try later.

Anyway, I entered the following prompt:

"Show me a program to send MIDI note messages in Z80 assembler.

MIDI messages are sent via ACIA at $A0. The program should start

at $8000. Please include an ACIA initialize routine."

As a result, I received the following output:

; Z80 Assembly Program to send MIDI Note messages via ACIA at $A0
; Program starts at $8000

ORG $8000           ; Program starting address

START:
    ; Initialize ACIA
    LD A, $03       ; Control register: 8 data bits, no parity, 1 stop bit, divide by 16 clock
    OUT ($A0), A    ; Write to ACIA control register

    ; Send MIDI Note On (Channel 1, Note 60, Velocity 127)
    CALL MIDI_NOTE_ON

    ; Delay (for demonstration purposes)
    CALL DELAY

    ; Send MIDI Note Off (Channel 1, Note 60, Velocity 0)
    CALL MIDI_NOTE_OFF

    ; End of program loop
    JR START        ; Jump to the beginning to repeat

; Routine to send MIDI Note On
MIDI_NOTE_ON:
    LD A, $90       ; Status byte for Note On, Channel 1
    CALL SEND_BYTE

    LD A, $3C       ; Note number (Middle C)
    CALL SEND_BYTE

    LD A, $7F       ; Velocity (maximum)
    CALL SEND_BYTE

    RET             ; Return from subroutine

; Routine to send MIDI Note Off
MIDI_NOTE_OFF:
    LD A, $80       ; Status byte for Note Off, Channel 1
    CALL SEND_BYTE

    LD A, $3C       ; Note number (Middle C)
    CALL SEND_BYTE

    LD A, $00       ; Velocity (0)
    CALL SEND_BYTE

    RET             ; Return from subroutine

; Routine to send a byte to the ACIA
SEND_BYTE:
    ; Wait until ACIA is ready to transmit
WAIT_TX_READY:
    IN A, ($A0)     ; Read status register
    BIT 1, A        ; Check if transmit buffer is empty (bit 1)
    JR Z, WAIT_TX_READY ; If not empty, wait

    ; Send the byte
    OUT ($A0), A    ; Send byte to ACIA data register
    RET             ; Return from subroutine

; Delay routine (simple loop for demonstration)
DELAY:
    LD BC, $FFFF    ; Load BC with a large value
DELAY_LOOP:
    DEC BC          ; Decrement BC
    LD A, B         ; Check if BC reached 0
    OR C
    JR NZ, DELAY_LOOP ; If not zero, keep looping
    RET             ; Return from subroutine

At first glance, it looks correct. I will review the contents in more detail later, but for now, I asked it to assemble the code and display the result.

"Please assemble this program and show me the Intel hex file, which can

run on an actual Z80 CPU."

 

I received the following output:

It seems that I currently don't have access to the required module to 
generate the Intel HEX file. However, I can provide the bytecode for 
the Z80 assembly program, which you can use to assemble it using a Z80 
assembler that supports Intel HEX output.

Here is the bytecode in hexadecimal format, starting at address $8000:

8000: 3E 03       ; LD A, $03
8002: D3 A0       ; OUT ($A0), A
8004: CD 08 80    ; CALL MIDI_NOTE_ON
8007: CD 1A 80    ; CALL DELAY
800A: CD 0E 80    ; CALL MIDI_NOTE_OFF
800D: 18 F6       ; JR START
800F: 3E 90       ; LD A, $90
8011: CD 22 80    ; CALL SEND_BYTE
8014: 3E 3C       ; LD A, $3C
8016: CD 22 80    ; CALL SEND_BYTE
8019: 3E 7F       ; LD A, $7F
801B: CD 22 80    ; CALL SEND_BYTE
801E: C9          ; RET
801F: 3E 80       ; LD A, $80
8021: CD 22 80    ; CALL SEND_BYTE
8024: 3E 3C       ; LD A, $3C
8026: CD 22 80    ; CALL SEND_BYTE
8029: 3E 00       ; LD A, $00
802B: CD 22 80    ; CALL SEND_BYTE
802E: C9          ; RET
802F: DB A0       ; IN A, ($A0)
8031: CB 4A       ; BIT 1, A
8033: 28 FB       ; JR Z, WAIT_TX_READY
8035: D3 A0       ; OUT ($A0), A
8037: C9          ; RET
8038: 01 FF FF    ; LD BC, $FFFF
803B: 0B          ; DEC BC
803C: 78          ; LD A, B
803D: B1          ; OR C
803E: 20 FB       ; JR NZ, DELAY_LOOP
8040: C9          ; RET

No HEX file was output, but an assembly listing was provided. Of course, I need to verify whether the generated code is correct, and I plan to do that later.

 If a HEX file were generated, it would have been convenient, as it could be copied and pasted directly into the Small Computer Monitor. Unfortunately, that was not the case.

From this experiment, I learned the following:

  1. ChatGPT can generate Z80 assembler programs.
  2. It has knowledge of MIDI and produced appropriate code.
  3. It cannot generate HEX files.

By the way, the conversation is publicly available. You can view it from the following link: https://chatgpt.com/share/6700ce0a-70a8-8003-b571-a45570f236b4

POSTSCRIPT

As the result of inspection, I found at least one error exist in the code. The address of data register in ACIA should be $A1, not $A0. I need to change it by myself, or ask CharGPT to correct it.

Discussions