From 2c7939ad8606054cd8dc3536b5d8392c14fb3b6d Mon Sep 17 00:00:00 2001 From: Scott-Falk Huehn Date: Wed, 28 Aug 2024 07:51:59 +0300 Subject: [PATCH] add zx next uart output - thanks Scott-Falk Huehn for patch --- README.md | 1 + src/main.asm | 1 + src/nextuart.asm | 104 +++++++++++++++++++++++++++++++++++++++++++++++ src/player.asm | 10 +++++ src/settings.asm | 3 +- src/strings.asm | 1 + 6 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 src/nextuart.asm diff --git a/README.md b/README.md index 1778164..6fa6c79 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ Quick demo video: https://www.youtube.com/watch?v=X_hX_dGmGeg - [MAYK](https://github.com/konkotgit/MAYK); - [Sizif-512](https://github.com/UzixLS/zx-sizif-512) [extension board](https://github.com/UzixLS/zx-sizif-512-ext); - [ZX-Uno.1010](https://github.com/UzixLS/zxuno1010-board) / [ZX-Uno](https://zxuno.speccy.org/index_e.shtml) MIDI addon. + - [ZX Spectrum Next MIDI Box](https://s-huehn.de/spectrum/hardware2.htm#nextmidi) ## 128K MIDI synthesizer wiring MIDI synthesizer data input should be connected to AY port A2. diff --git a/src/main.asm b/src/main.asm index 373038a..e5d514e 100644 --- a/src/main.asm +++ b/src/main.asm @@ -52,6 +52,7 @@ int_im2_vector_table: include "uart.asm" include "neogs.asm" include "shama2695.asm" + include "nextuart.asm" include "smf.asm" include "player.asm" include "screen.asm" diff --git a/src/nextuart.asm b/src/nextuart.asm new file mode 100644 index 0000000..926ef0c --- /dev/null +++ b/src/nextuart.asm @@ -0,0 +1,104 @@ +; MIDI Out for ZX Spectrum Next, using joystick port 2 in UART mode +; OUT - AF - garbage +; OUT - BC - garbage +; OUT - HL - garbage +nextuart_prepare: + ld bc, #243b ; NextReg Register Select port + xor a ; Register 0 (Machine ID) + out (c), a ; Select register + ld b, #25 ; NextReg Data port + in a, (c) ; Read register + and #0f ; Select relevant bits + cp #0a ; ZX Spectrum Next machine? + ret nz ; No -> break + + xor a ; Opcode for NOP + ld (nextuart_putc), a ; Enable UART send routine + ld b, #24 ; NextReg Register Select port + ld a, #0b ; Register 11 (Joystick I/O Mode) + out (c), a ; Select register + ld b, #25 ; NextReg Data port + ld a, #b0 ; I/O mode, UART on Joystick 2 + out (c), a ; Write register + ld b, #15 ; UART Select port + ld a, #10 ; Select UART 0, set 3 highest prescaler bits (always 0 for MIDI) + out (c), a ; Write UART settings + ld b, #16 ; UART Frame port + ld a, #98 ; Init TX/RX, set 8N1 + out (c), a ; Write UART settings + ld a, #18 ; set 8N1 + out (c), a ; Write UART settings + ld b, #24 ; NextReg Register Select port + ld a, #11 ; Register 17 (Video timing) + out (c), a ; Select register + ld b, #25 ; NextReg Data port + in a, (c) ; Read register + and #07 ; Select relevant bits + cp 0 ; Video timing 0? (28,0 MHz) + jr nz, .clock1 ; No -> Check next timing + ld hl, 28000000 / 31250 ; Calculate prescaler + jr .clock9 ; Set prescaler +.clock1: + cp 1 ; Video timing 1? (28,571429 MHz) + jr nz, .clock2 ; No -> Check next timing + ld hl, 28571429 / 31250 ; Calculate prescaler + jr .clock9 ; Set prescaler +.clock2: + cp 2 ; Video timing 2? (29,464286 MHz) + jr nz, .clock3 ; No -> Check next timing + ld hl, 29464286 / 31250 ; Calculate prescaler + jr .clock9 ; Set prescaler +.clock3: + cp 3 ; Video timing 3? (30,0 MHz) + jr nz, .clock4 ; No -> Check next timing + ld hl, 30000000 / 31250 ; Calculate prescaler + jr .clock9 ; Set prescaler +.clock4: + cp 4 ; Video timing 4? (31,0 MHz) + jr nz, .clock5 ; No -> Check next timing + ld hl, 31000000 / 31250 ; Calculate prescaler + jr .clock9 ; Set prescaler +.clock5: + cp 5 ; Video timing 5? (32,0 MHz) + jr nz, .clock6 ; No -> Check next timing + ld hl, 32000000 / 31250 ; Calculate prescaler + jr .clock9 ; Set prescaler +.clock6: + cp 6 ; Video timing 6? (33,0 MHz) + jr nz, .clock7 ; No -> Video timing 7 + ld hl, 33000000 / 31250 ; Calculate prescaler + jr .clock9 ; Set prescaler +.clock7: + ld hl, 27000000 / 31250 ; Video timing 7 (27,0 MHz) +.clock9: + rl l ; Shift bit 7 from low byte to carry + rl h ; Shift carry to high byte, H contains now upper 7 prescaler bits + srl l ; Restore low byte, L contains now lower 7 prescaler bits + ld b, #14 ; UART RX / Set prescaler port + ld a, h ; Prescaler upper 7 bits + or #80 ; Set bit 7 (indentifies high byte) + out (c), a ; Write prescaler upper 7 bits + out (c), l ; Write prescaler lower 7 bits + ret ; + + +; Send byte to MIDI device +; IN - A - byte to send +; OUT - AF - garbage +; OUT - BC - garbage +; OUT - E - garbage +nextuart_putc: + ret ; will be replaced by NOP if ZX Next detected + ; (prevents hanging in next part) + ld e, a ; Store the byte to send + ld bc, #133b ; UART TX / Status port +.wait: + in a, (c) ; Read UART status + and #02 ; TX buffer full? + jr nz, .wait ; wait + out (c), e ; Send byte to UART TX + ret ; + + +nextuart_flush_txbuf: + ret ; diff --git a/src/player.asm b/src/player.asm index e42a6ed..c4f91ba 100644 --- a/src/player.asm +++ b/src/player.asm @@ -19,6 +19,8 @@ player_driver_select: jr z, .shama2095 ; cp 4 ; jr z, .neogs ; + cp 5 ; + jr z, .nextuart ; .uart128: ld hl, uart_putc_txbuf ; ld (player_driver_tx+1), hl ; @@ -43,6 +45,14 @@ player_driver_select: ld hl, neogs_vs1053_midi_flush_txbuf ; ld (player_driver_flush_txbuf+1), hl ; jp neogs_vs1053_midi_prepare ; +.nextuart: + ld hl, nextuart_putc ; + ld (player_driver_tx+1), hl ; + ld (player_loop.A+1), hl ; + ld (player_loop.B+1), hl ; + ld hl, nextuart_flush_txbuf ; + ld (player_driver_flush_txbuf+1), hl ; + jp nextuart_prepare ; player_driver_tx: jp 0 diff --git a/src/settings.asm b/src/settings.asm index a5f4fe9..3c2d5ca 100644 --- a/src/settings.asm +++ b/src/settings.asm @@ -154,13 +154,14 @@ settings_menu_cb: settings_menuentry_output: - DB 5 + DB 6 DW var_settings.output DW str_128std.end DW str_ts1.end DW str_ts2.end DW str_shama.end DW str_neogs1053.end + DW str_zxnext.end settings_menuentry_divmmc: DB 2 DW var_settings.divmmc diff --git a/src/strings.asm b/src/strings.asm index def4ee9..663a932 100644 --- a/src/strings.asm +++ b/src/strings.asm @@ -28,6 +28,7 @@ str_ts1: DEFSTR " TS chip 1" str_ts2: DEFSTR " TS chip 2" str_shama: DEFSTR " ShamaZX" str_neogs1053: DEFSTR "NeoGS+VS1053" +str_zxnext: DEFSTR "ZX Next UART" str_divmmc: DEFSTR "DivMMC" str_zxmmc: DEFSTR "ZXMMC" str_zcontroller: DEFSTR "Z-Controller"