add zx next uart output - thanks Scott-Falk Huehn for patch

This commit is contained in:
Scott-Falk Huehn
2024-08-28 07:51:59 +03:00
committed by Eugene Lozovoy
parent ebfb6f4c5d
commit 2c7939ad86
6 changed files with 119 additions and 1 deletions

View File

@ -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.

View File

@ -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"

104
src/nextuart.asm Normal file
View File

@ -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 ;

View File

@ -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

View File

@ -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

View File

@ -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"