First Attempt: Generating MIDI Note-On and Note-Off with ChatGPT (Continued)
1. Code Review
I conducted a detailed review of the program generated by ChatGPT. The following issues were identified:
- Incorrect ACIA initialization Since ACIA is already initialized by SCM, I decided to omit the initialization step and commented out the corresponding section.
- Destruction of the A register in the SEND_BYTE routine The A register, which stores the data to be transmitted, was being overwritten. To fix this, I modified the routine to push the A register onto the stack at the entry point and pop it before outputting the data.
- Incorrect address for the ACIA data register The address should be $A1 instead of $A0.
- Infinite loop After outputting the Note-On and Note-Off messages, the program returned to the start. For testing purposes, I modified the program to output only once and then return to the monitor.
The manually corrected program is as follows:
; 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
RET
; 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
PUSH AF
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
POP AF
; Send the byte
OUT ($A1), 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
After making these corrections, I saved the program on my computer as midi_test.asm.
2. Assembly Process
To execute the above program, I created a HEX file using a Z80 assembler. Although I usually develop on a Mac mini, I used sjasm and bin2hex for Z80 development. The following commands can be used to assemble the program:
$ sjasm test_ai.asm
$ bin2hex -o0x8000 -b16 test_ai.out > test_ai.hex
In practice, I automated the process using a Makefile:
.PHONY: clean
.SUFFIXES: .out .hex .asm
TARGET : midi_test.hex
.out.hex:
bin2hex -o0x8000 -b16 $< > $@
.asm.out:
sjasm $<
clean:
rm -f *.out *.hex *.lst
Run the make command generate the following messages.
$ make
sjasm midi_test.asm
Sjasm Z80 Assembler v0.42c - www.xl2s.tk
bin2hex -o0x8000 -b16 midi_test.out > midi_test.hex
rm midi_test.out
3. Test Environment
To debug, I needed to verify that the MIDI messages were being sent correctly. Instead of using a MIDI sound module, I used a MIDI interface on my Mac, which made it easier to check the program's behavior. I looped back the messages from the RC-2014 using a Roland UM-ONE-MK2 MIDI interface I had on hand. Below is a diagram of the setup:


4. Results
Dropping the HEX file into the SCM console sends the file. You can verify that it was sent correctly using the D command. To execute the program, type g 8000 in the SC114 console. As expected, both the Note-On and Note-Off messages were output.

By using MIDI Monitor, I was able to directly confirm the MIDI messages. Additionally, I launched GarageBand and configured a software instrument, which played the corresponding sounds based on the MIDI messages.


And so, all is well that ends well.
morecat_lab
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.