Browse Source

Resync

pull/38/head
b1ackmai1er 7 years ago
parent
commit
cf9d077057
  1. 2
      Doc/ChangeLog.txt
  2. 2
      Source/CBIOS/ver.inc
  3. 4
      Source/HBIOS/Config/MK4_std.asm
  4. 4
      Source/HBIOS/Config/N8_std.asm
  5. 5
      Source/HBIOS/Config/RCZ180_ext.asm
  6. 5
      Source/HBIOS/Config/RCZ180_nat.asm
  7. 11
      Source/HBIOS/Config/RCZ180_sc126.asm
  8. 3
      Source/HBIOS/Config/RCZ80_std.asm
  9. 68
      Source/HBIOS/acia.asm
  10. 288
      Source/HBIOS/dsrtc.asm
  11. 138
      Source/HBIOS/sd.asm
  12. 723
      Source/HBIOS/sio.asm
  13. 5
      Source/HBIOS/spk.asm

2
Doc/ChangeLog.txt

@ -3,6 +3,8 @@ Version 2.9.2
- PMS: Fixed DS1210-related issue resulting in "Invalid BIOS" errors
- SCC: Support for SC126 motherboard
- WBW: Enable Auto-CTS/DCD in SIO driver for pacing output data
- WBW: Support missing pull-up resistors in SD driver (a common occurence)
- WBW: Support two SIO modules w/ auto-detection
Version 2.9.1
-------------

2
Source/CBIOS/ver.inc

@ -2,4 +2,4 @@
#DEFINE RMN 9
#DEFINE RUP 2
#DEFINE RTP 0
#DEFINE BIOSVER "2.9.2-pre.0"
#DEFINE BIOSVER "2.9.2-pre.1"

4
Source/HBIOS/Config/MK4_std.asm

@ -6,8 +6,8 @@
#include "cfg_mk4.asm"
;
Z180_CLKDIV .SET 1 ; 0=OSC/2, 1=OSC, 2=OSC*2
Z180_MEMWAIT .SET 0 ; MEMORY WAIT STATES TO INSERT (0-3)
Z180_IOWAIT .SET 1 ; IO WAIT STATES TO INSERT (0-3)
Z180_MEMWAIT .SET 0 ; MEMORY WAIT STATES (0-3)
Z180_IOWAIT .SET 1 ; ADD (0-3) I/O WAIT STATES ABOVE 1 W/S BUILT-IN
;
FDENABLE .SET FALSE ; TRUE FOR FLOPPY DEVICE SUPPORT
FDMODE .SET FDMODE_DIDE ; FDMODE_DIO, FDMODE_DIDE, FDMODE_DIO3

4
Source/HBIOS/Config/N8_std.asm

@ -6,8 +6,8 @@
#include "cfg_n8.asm"
;
Z180_CLKDIV .SET 1 ; 0=OSC/2, 1=OSC, 2=OSC*2
Z180_MEMWAIT .SET 1 ; MEMORY WAIT STATES TO INSERT (0-3)
Z180_IOWAIT .SET 3 ; IO WAIT STATES TO INSERT (0-3)
Z180_MEMWAIT .SET 1 ; MEMORY WAIT STATES (0-3)
Z180_IOWAIT .SET 3 ; ADD (0-3) I/O WAIT STATES ABOVE 1 W/S BUILT-IN
;
SDMODE .SET SDMODE_CSIO ; FOR N8 PROTOTYPE (DATECODE 2511), USE SDMODE_N8
;

5
Source/HBIOS/Config/RCZ180_ext.asm

@ -7,15 +7,14 @@
;
MEMMGR .SET MM_Z2 ; 512K RAM/ROM MODULE MEM MGR
Z180_CLKDIV .SET 1 ; 0=OSC/2, 1=OSC, 2=OSC*2
Z180_MEMWAIT .SET 0 ; MEMORY WAIT STATES TO INSERT (0-3)
Z180_IOWAIT .SET 1 ; IO WAIT STATES TO INSERT (0-3)
Z180_MEMWAIT .SET 0 ; MEMORY WAIT STATES (0-3)
Z180_IOWAIT .SET 1 ; ADD (0-3) I/O WAIT STATES ABOVE 1 W/S BUILT-IN
;
CPUOSC .SET 18432000 ; CPU OSC FREQ
DEFSERCFG .SET SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG
;
ASCIENABLE .SET TRUE ; TRUE FOR Z180 ASCI SUPPORT
SIOENABLE .SET FALSE ; TRUE TO AUTO-DETECT ZILOG SIO/2
SIOMODE .SET SIOMODE_RC ; TYPE OF SIO/2 TO DETECT: SIOMODE_RC, SIOMODE_SMB
ACIAENABLE .SET FALSE ; TRUE TO AUTO-DETECT MOTOROLA 6850 ACIA
;
FDENABLE .SET FALSE ; TRUE FOR FLOPPY SUPPORT

5
Source/HBIOS/Config/RCZ180_nat.asm

@ -6,15 +6,14 @@
#include "cfg_rcz180.asm"
;
Z180_CLKDIV .SET 1 ; 0=OSC/2, 1=OSC, 2=OSC*2
Z180_MEMWAIT .SET 0 ; MEMORY WAIT STATES TO INSERT (0-3)
Z180_IOWAIT .SET 1 ; IO WAIT STATES TO INSERT (0-3)
Z180_MEMWAIT .SET 0 ; MEMORY WAIT STATES (0-3)
Z180_IOWAIT .SET 1 ; ADD (0-3) I/O WAIT STATES ABOVE 1 W/S BUILT-IN
;
CPUOSC .SET 18432000 ; CPU OSC FREQ
DEFSERCFG .SET SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG
;
ASCIENABLE .SET TRUE ; TRUE FOR Z180 ASCI SUPPORT
SIOENABLE .SET FALSE ; TRUE TO AUTO-DETECT ZILOG SIO/2
SIOMODE .SET SIOMODE_RC ; TYPE OF SIO/2 TO DETECT: SIOMODE_RC, SIOMODE_SMB
ACIAENABLE .SET FALSE ; TRUE TO AUTO-DETECT MOTOROLA 6850 ACIA
;
FDENABLE .SET FALSE ; TRUE FOR FLOPPY SUPPORT

11
Source/HBIOS/Config/RCZ180_sc126.asm

@ -6,15 +6,16 @@
#include "cfg_rcz180.asm"
;
Z180_CLKDIV .SET 1 ; 0=OSC/2, 1=OSC, 2=OSC*2
Z180_MEMWAIT .SET 0 ; MEMORY WAIT STATES TO INSERT (0-3)
Z180_IOWAIT .SET 1 ; IO WAIT STATES TO INSERT (0-3)
Z180_MEMWAIT .SET 0 ; MEMORY WAIT STATES (0-3)
Z180_IOWAIT .SET 1 ; ADD (0-3) I/O WAIT STATES ABOVE 1 W/S BUILT-IN
;
DIAGPORT .SET $0D ; DIAGNOSTIC PORT ADDRESS
;
CPUOSC .SET 18432000 ; CPU OSC FREQ
DEFSERCFG .SET SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG
;
ASCIENABLE .SET TRUE ; TRUE FOR Z180 ASCI SUPPORT
SIOENABLE .SET FALSE ; TRUE TO AUTO-DETECT ZILOG SIO/2
SIOMODE .SET SIOMODE_RC ; TYPE OF SIO/2 TO DETECT: SIOMODE_RC, SIOMODE_SMB
SIOENABLE .SET FALSE ; TRUE TO AUTO-DETECT ZILOG SIO/2
ACIAENABLE .SET FALSE ; TRUE TO AUTO-DETECT MOTOROLA 6850 ACIA
;
FDENABLE .SET FALSE ; TRUE FOR FLOPPY SUPPORT
@ -28,5 +29,5 @@ DSRTCENABLE .SET TRUE ; DS-1302 CLOCK DRIVER
;
SDENABLE .SET TRUE ; TRUE FOR SD SUPPORT
SDMODE .SET SDMODE_SC126 ; SDMODE_JUHA, SDMODE_CSIO, SDMODE_UART, SDMODE_PPI, SDMODE_DSD
SDTRACE .SET 2 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
SDTRACE .SET 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE)
SDCSIOFAST .SET TRUE ; TABLE-DRIVEN BIT INVERTER

3
Source/HBIOS/Config/RCZ80_std.asm

@ -8,8 +8,7 @@
CPUOSC .SET 7372800 ; CPU OSC FREQ
DEFSERCFG .SET SER_115200_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE)
;
SIOENABLE .SET TRUE ; TRUE TO AUTO-DETECT ZILOG SIO/2
SIOMODE .SET SIOMODE_RC ; TYPE OF SIO/2 TO DETECT: SIOMODE_RC, SIOMODE_SMB
SIOENABLE .SET TRUE ; TRUE TO AUTO-DETECT ZILOG SIO/2
ACIAENABLE .SET TRUE ; TRUE TO AUTO-DETECT MOTOROLA 6850 ACIA
;
FDENABLE .SET FALSE ; TRUE FOR FLOPPY SUPPORT

68
Source/HBIOS/acia.asm

@ -101,7 +101,7 @@ ACIA_INITUNIT:
LD HL,ACIA_DEV ; POINT TO CURRENT UART DEVICE NUM
LD A,(HL) ; PUT IN ACCUM
INC (HL) ; INCREMENT IT (FOR NEXT LOOP)
LD (IY),A ; UDPATE UNIT NUM
LD (IY),A ; UPDATE UNIT NUM
;
#IF (INTMODE == 1)
; ADD IM1 INT CALL LIST ENTRY
@ -171,11 +171,10 @@ ACIAA_INT00:
LD E,A ; SAVE BYTE READ
LD A,(ACIAA_BUFCNT) ; GET CURRENT BUFFER USED COUNT
CP ACIAA_BUFSZ ; COMPARE TO BUFFER SIZE
;RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
JR Z,ACIAA_INT2 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
INC A ; INCREMENT THE COUNT
LD (ACIAA_BUFCNT),A ; AND SAVE IT
CP ACIAA_BUFSZ - 5 ; BUFFER GETTING FULL?
CP ACIAA_BUFSZ / 2 ; BUFFER GETTING FULL?
JR NZ,ACIAA_INT0 ; IF NOT, BYPASS DEASSERTING RTS
LD A,ACIA_RTSOFF ; VALUE TO DEASSERT RTS
OUT (C),A ; DO IT
@ -216,11 +215,10 @@ ACIAB_INT00:
LD E,A ; SAVE BYTE READ
LD A,(ACIAB_BUFCNT) ; GET CURRENT BUFFER USED COUNT
CP ACIAB_BUFSZ ; COMPARE TO BUFFER SIZE
;RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
JR Z,ACIAB_INT2 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
INC A ; INCREMENT THE COUNT
LD (ACIAB_BUFCNT),A ; AND SAVE IT
CP ACIAB_BUFSZ - 5 ; BUFFER GETTING FULL?
CP ACIAB_BUFSZ / 2 ; BUFFER GETTING FULL?
JR NZ,ACIAB_INT0 ; IF NOT, BYPASS DEASSERTING RTS
LD A,ACIA_RTSOFF ; VALUE TO DEASSERT RTS
OUT (C),A ; DO IT
@ -291,9 +289,8 @@ ACIAA_IN:
LD A,(ACIAA_BUFCNT) ; GET COUNT
DEC A ; DECREMENT COUNT
LD (ACIAA_BUFCNT),A ; SAVE SAVE IT
CP 5 ; BUFFER LOW THRESHOLD
CP ACIAA_BUFSZ / 4 ; BUFFER LOW THRESHOLD
JR NZ,ACIAA_IN0 ; IF NOT, BYPASS SETTING RTS
LD C,(IY+3) ; C := ACIA CMD PORT
LD A,ACIA_RTSON ; ASSERT RTS
OUT (C),A ; DO IT
@ -318,9 +315,8 @@ ACIAB_IN:
LD A,(ACIAB_BUFCNT) ; GET COUNT
DEC A ; DECREMENT COUNT
LD (ACIAB_BUFCNT),A ; SAVE SAVE IT
CP 5 ; BUFFER LOW THRESHOLD
CP ACIAB_BUFSZ / 4 ; BUFFER LOW THRESHOLD
JR NZ,ACIAB_IN0 ; IF NOT, BYPASS SETTING RTS
LD C,(IY+3) ; C := ACIA CMD PORT
LD A,ACIA_RTSON ; ASSERT RTS
OUT (C),A ; DO IT
@ -458,46 +454,40 @@ ACIA_QUERY:
;
;
ACIA_DEVICE:
LD D,CIODEV_ACIA ; D := DEVICE TYPE
LD E,(IY) ; E := PHYSICAL UNIT
LD C,$00 ; C := DEVICE TYPE, 0x00 IS RS-232
XOR A ; SIGNAL SUCCESS
LD D,CIODEV_ACIA ; D := DEVICE TYPE
LD E,(IY) ; E := PHYSICAL UNIT
LD C,$00 ; C := DEVICE TYPE, 0x00 IS RS-232
XOR A ; SIGNAL SUCCESS
RET
;
; ACIA DETECTION ROUTINE
;
ACIA_DETECT:
;LD C,ACIA_BASE ; BASE PORT ADDRESS
LD C,(IY+3) ; BASE PORT ADDRESS
CALL ACIA_DETECT2 ; CHECK IT
JR Z,ACIA_DETECT1 ; FOUND IT, RECORD IT
;LD C,ACIA_ALTBASE ; ALT BASE PORT ADDRESS
;CALL ACIA_DETECT2 ; CHECK IT
;JR Z,ACIA_DETECT1 ; FOUND IT, RECORD IT
LD A,ACIA_NONE ; NOTHING FOUND
RET ; DONE
;
ACIA_DETECT1:
; ACIA FOUND, RECORD IT
;LD A,C ; BASE PORT ADDRESS TO A
;LD (IY+3),A ; SAVE ACTIVE BASE PORT
LD A,ACIA_ACIA ; RETURN CHIP TYPE
RET ; DONE
LD C,(IY+3) ; BASE PORT ADDRESS
CALL ACIA_DETECT2 ; CHECK IT
JR Z,ACIA_DETECT1 ; FOUND IT, RECORD IT
LD A,ACIA_NONE ; NOTHING FOUND
RET ; DONE
;
ACIA_DETECT1:
; ACIA FOUND, RECORD IT
LD A,ACIA_ACIA ; RETURN CHIP TYPE
RET ; DONE
;
ACIA_DETECT2:
; LOOK FOR ACIA AT PORT ADDRESS IN C
LD A,$03 ; MASTER RESET
OUT (C),A ; DO IT
IN A,(C) ; GET STATUS
OR A ; CHECK FOR ZERO
RET NZ ; RETURN IF NOT ZERO
LD A,$02 ; CLEAR MASTER RESET
OUT (C),A ; DO IT
LD A,$03 ; MASTER RESET
OUT (C),A ; DO IT
IN A,(C) ; GET STATUS
OR A ; CHECK FOR ZERO
RET NZ ; RETURN IF NOT ZERO
LD A,$02 ; CLEAR MASTER RESET
OUT (C),A ; DO IT
; CHECK FOR EXPECTED BITS:
; TDRE=1, DCD & CTS = 0
AND %00001110 ; BIT MASK FOR "STABLE" BITS
CP %00000010 ; EXPECTED VALUE
RET ; RETURN RESULT, Z = CHIP FOUND
AND %00001110 ; BIT MASK FOR "STABLE" BITS
CP %00000010 ; EXPECTED VALUE
RET ; RETURN RESULT, Z = CHIP FOUND
;
;
;

288
Source/HBIOS/dsrtc.asm

@ -63,16 +63,37 @@
;
; CONSTANTS
;
; RTC SBC SBC-004 MFPIC N8 N8-CSIO SC126
; ----- ------- ------- ------- ------- ------- -------
; D7 WR RTC_OUT RTC_OUT -- RTC_OUT RTC_OUT RTC_OUT, I2C_SDA
; D6 WR RTC_CLK RTC_CLK -- RTC_CLK RTC_CLK RTC_CLK
; D5 WR /RTC_WE /RTC_WE -- /RTC_WE /RTC_WE /RTC_WE
; D4 WR RTC_CE RTC_CE -- RTC_CE RTC_CE RTC_CE
; D3 WR NC SPK /RTC_CE NC NC /SPI_CS2
; D2 WR NC CLKHI RTC_CLK SPI_CS SPI_CS /SPI_CS1
; D1 WR -- -- RTC_WE SPI_CLK NC FS
; D0 WR -- -- RTC_OUT SPI_DI NC I2C_SCL
;
; D7 RD -- -- -- -- -- I2C_SDA
; D6 RD CFG CFG -- SPI_DO CFG --
; D5 RD -- -- -- -- -- --
; D4 RD -- -- -- -- -- --
; D3 RD -- -- -- -- -- --
; D2 RD -- -- -- -- -- --
; D1 RD -- -- -- -- -- --
; D0 RD RTC_IN RTC_IN RTC_IN RTC_IN RTC_IN RTC_IN
;
#IF (DSRTCMODE == DSRTCMODE_STD)
;
DSRTC_BASE .EQU RTC ; RTC PORT ON ALL SBC SERIES Z80 PLATFORMS
DSRTC_BASE .EQU RTC ; RTC PORT
;
DSRTC_DATA .EQU %10000000 ; BIT 7 CONTROLS RTC DATA (I/O) LINE
DSRTC_CLK .EQU %01000000 ; BIT 6 CONTROLS RTC CLOCK LINE, 1 = HIGH
DSRTC_RD .EQU %00100000 ; BIT 5 CONTROLS DATA DIRECTION, 1 = READ
DSRTC_CE .EQU %00010000 ; BIT 4 CONTROLS RTC CE LINE, 1 = HIGH (ENABLED)
DSRTC_DATA .EQU %10000000 ; BIT 7 IS RTC DATA OUT
DSRTC_CLK .EQU %01000000 ; BIT 6 IS RTC CLOCK (CLK)
DSRTC_RD .EQU %00100000 ; BIT 5 IS DATA DIRECTION (/WE)
DSRTC_CE .EQU %00010000 ; BIT 4 IS CHIP ENABLE (CE)
;
DSRTC_RESET .EQU %00000000 ; ALL LOW
DSRTC_MASK .EQU %11110000 ; MASK FOR BITS WE OWN IN RTC LATCH PORT
DSRTC_IDLE .EQU %00100000 ; QUIESCENT STATE
;
#ENDIF
;
@ -80,12 +101,13 @@ DSRTC_RESET .EQU %00000000 ; ALL LOW
;
DSRTC_BASE .EQU $43 ; RTC PORT ON MF/PIC
;
DSRTC_DATA .EQU %00000001 ; BIT 0 CONTROLS RTC DATA (I/O) LINE
DSRTC_CLK .EQU %00000100 ; BIT 2 CONTROLS RTC CLOCK LINE, 1 = HIGH
DSRTC_WR .EQU %00000010 ; BIT 1 CONTROLS DATA DIRECTION, 1 = WRITE
DSRTC_CE .EQU %00001000 ; BIT 3 CONTROLS RTC CE LINE, 0 = ENABLED
DSRTC_DATA .EQU %00000001 ; BIT 0 IS RTC DATA OUT
DSRTC_CLK .EQU %00000100 ; BIT 2 IS RTC CLOCK (CLK)
DSRTC_WR .EQU %00000010 ; BIT 1 IS DATA DIRECTION (WE)
DSRTC_CE .EQU %00001000 ; BIT 3 CHIP ENABLE (/CE)
;
DSRTC_RESET .EQU %00001000 ; ALL LOW, BUT CE = 1
DSRTC_MASK .EQU %00001111 ; MASK FOR BITS WE OWN IN RTC LATCH PORT
DSRTC_IDLE .EQU %00101000 ; QUIESCENT STATE
;
#ENDIF
;
@ -103,6 +125,13 @@ DSRTC_INIT:
#IF (DSRTCMODE == DSRTCMODE_MFPIC)
PRTS("MFPIC$")
#ENDIF
;
; SET RELEVANT BITS IN RTC LATCH SHADOW REGISTER
; TO THEIR QUIESENT STATE
LD A,(RTCVAL)
AND DSRTC_MASK
OR DSRTC_IDLE
LD (RTCVAL),A
;
; CHECK FOR CLOCK HALTED
CALL DSRTC_TSTCLK
@ -123,22 +152,22 @@ DSRTC_INIT1:
LD HL,DSRTC_TIMBUF
CALL PRTDT
#IF DSRTCCHG ; FORCE_RTC_CHARGE_ENABLE
LD C,$8E ; ACCESS WRITE PROT REG
#IF DSRTCCHG ; FORCE_RTC_CHARGE_ENABLE
LD E,$8E ; ACCESS WRITE PROT REG
CALL DSRTC_CMD ;
LD A,$00 ; WRITE PROTECT OFF
LD E,$00 ; WRITE PROTECT OFF
CALL DSRTC_PUT ;
CALL DSRTC_END ; FINISH CMD
LD C,$90 ; ACCESS CHARGE REGISTER
LD E,$90 ; ACCESS CHARGE REGISTER
CALL DSRTC_CMD ;
LD A,$A5 ; STD CHARGE VALUES
LD E,$A5 ; STD CHARGE VALUES
CALL DSRTC_PUT ;
CALL DSRTC_END ; FINISH REG WRITE
LD C,$8E ; ACCESS WRITE PROT REG
LD E,$8E ; ACCESS WRITE PROT REG
CALL DSRTC_CMD ;
LD A,$80 ; WRITE PROTECT ON
LD E,$80 ; WRITE PROTECT ON
CALL DSRTC_PUT ;
CALL DSRTC_END ; FINISH CMD
#ENDIF
@ -303,12 +332,13 @@ DSRTC_TIM2CLK:
; TEST CLOCK FOR CHARGE DATA
;
DSRTC_TSTCHG:
LD C,$91 ; CHARGE RESISTOR & DIODE VALUES
LD E,$91 ; CHARGE RESISTOR & DIODE VALUES
CALL DSRTC_CMD ; SEND THE COMMAND
CALL DSRTC_GET ; READ THE REGISTER
CALL DSRTC_END ; FINISH IT
AND %11110000 ; CHECK FOR
CP %10100000 ; ENABLED FLAG
LD A,E ; VALUE TO A
AND %11110000 ; CHECK FOR
CP %10100000 ; ENABLED FLAG
RET
;
; TEST CLOCK FOR VALID DATA
@ -317,23 +347,24 @@ DSRTC_TSTCHG:
; 1 = HALTED
;
DSRTC_TSTCLK:
LD C,$81 ; SECONDS REGISTER HAS CLOCK HALT FLAG
LD E,$81 ; SECONDS REGISTER HAS CLOCK HALT FLAG
CALL DSRTC_CMD ; SEND THE COMMAND
CALL DSRTC_GET ; READ THE REGISTER
CALL DSRTC_END ; FINISH IT
LD A,E ; VALUE TO A
AND %10000000 ; HIGH ORDER BIT IS CLOCK HALT
RET
;
; BURST READ CLOCK DATA INTO BUFFER AT HL
;
DSRTC_RDCLK:
LD C,$BF ; COMMAND = $BF TO BURST READ CLOCK
LD E,$BF ; COMMAND = $BF TO BURST READ CLOCK
CALL DSRTC_CMD ; SEND COMMAND TO RTC
LD B,DSRTC_BUFSIZ ; B IS LOOP COUNTER
DSRTC_RDCLK1:
PUSH BC ; PRESERVE BC
CALL DSRTC_GET ; GET NEXT BYTE
LD (HL),A ; SAVE IN BUFFER
LD (HL),E ; SAVE IN BUFFER
INC HL ; INC BUF POINTER
POP BC ; RESTORE BC
DJNZ DSRTC_RDCLK1 ; LOOP IF NOT DONE
@ -342,34 +373,35 @@ DSRTC_RDCLK1:
; BURST WRITE CLOCK DATA FROM BUFFER AT HL
;
DSRTC_WRCLK:
LD C,$8E ; COMMAND = $8E TO WRITE CONTROL REGISTER
LD E,$8E ; COMMAND = $8E TO WRITE CONTROL REGISTER
CALL DSRTC_CMD ; SEND COMMAND
XOR A ; $00 = UNPROTECT
LD E,$00 ; $00 = UNPROTECT
CALL DSRTC_PUT ; SEND VALUE TO CONTROL REGISTER
CALL DSRTC_END ; FINISH IT
;
LD C,$BE ; COMMAND = $BE TO BURST WRITE CLOCK
LD E,$BE ; COMMAND = $BE TO BURST WRITE CLOCK
CALL DSRTC_CMD ; SEND COMMAND TO RTC
LD B,DSRTC_BUFSIZ ; B IS LOOP COUNTER
DSRTC_WRCLK1:
PUSH BC ; PRESERVE BC
LD A,(HL) ; GET NEXT BYTE TO WRITE
LD E,(HL) ; GET NEXT BYTE TO WRITE
CALL DSRTC_PUT ; PUT NEXT BYTE
INC HL ; INC BUF POINTER
POP BC ; RESTORE BC
DJNZ DSRTC_WRCLK1 ; LOOP IF NOT DONE
LD A,$80 ; ADD CONTROL REG BYTE, $80 = PROTECT ON
LD E,$80 ; ADD CONTROL REG BYTE, $80 = PROTECT ON
CALL DSRTC_PUT ; WRITE REQUIRED 8TH BYTE
JP DSRTC_END ; FINISH IT
;
#IF (DSRTCMODE == DSRTCMODE_STD)
;
; SEND COMMAND IN C TO RTC
; SEND COMMAND IN E TO RTC
; ALL RTC SEQUENCES MUST CALL THIS FIRST TO SEND THE RTC COMMAND.
; THE COMMAND IS SENT VIA A PUT. CE AND CLK ARE LEFT HIGH! THIS
; THE COMMAND IS SENT VIA A PUT. CE AND CLK ARE LEFT ASSERTED! THIS
; IS INTENTIONAL BECAUSE WHEN THE CLOCK IS LOWERED, THE FIRST BIT
; WILL BE PRESENTED TO READ (IN THE CASE OF A READ CMD).
;
; N.B. REGISTER A CONTAINS WORKING VALUE OF LATCH PORT AND MUST NOT
; BE MODIFIED BETWEEN CALLS TO DSRTC_CMD, DSRTC_PUT, AND DSRTC_GET.
;
; 0) ASSUME ALL LINES UNDEFINED AT ENTRY
; 1) DEASSERT ALL LINES (CE, RD, CLOCK, & DATA)
; 2) WAIT 1US
@ -378,19 +410,22 @@ DSRTC_WRCLK1:
; 5) PUT COMMAND
;
DSRTC_CMD:
XOR A ; ALL LINES LOW TO RESET
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
LD A,(RTCVAL) ; INIT A WITH QUIESCENT STATE
OUT (DSRTC_BASE),A ; WRITE TO PORT
CALL DLY2 ; DELAY 2 * 27 T-STATES
XOR DSRTC_CE ; NOW SET CE HIGH
#IF (DSRTCMODE == DSRTCMODE_MFPIC)
AND ~DSRTC_CE ; ASSERT CE (LOW)
#ELSE
OR DSRTC_CE ; ASSERT CE (HIGH)
#ENDIF
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
CALL DLY2 ; DELAY 2 * 27 T-STATES
LD A,C ; LOAD COMMAND
CALL DSRTC_PUT ; WRITE IT
RET
;
; WRITE BYTE IN A TO THE RTC
; WRITE BYTE IN A TO THE RTC. CE IS IMPLICITY ASSERTED AT
; THE START. CE AND CLK ARE LEFT HIGH AT THE END IN CASE
; WRITE BYTE IN E TO THE RTC
; WRITE BYTE IN E TO THE RTC. CE IS IMPLICITY ASSERTED AT
; THE START. CE AND CLK ARE LEFT ASSERTED AT THE END IN CASE
; NEXT ACTION IS A READ.
;
; 0) ASSUME ENTRY WITH CE HI, OTHERS UNDEFINED
@ -404,135 +439,36 @@ DSRTC_CMD:
;
DSRTC_PUT:
LD B,8 ; LOOP FOR 8 BITS
LD C,A ; SAVE THE WORKING VALUE
DSRTC_PUT1:
LD A,DSRTC_CE ; SET CLOCK LOW
OUT (DSRTC_BASE),A ; DO IT
CALL DLY1 ; DELAY 27 T-STATES
LD A,C ; RECOVER WORKING VALUE
RRCA ; ROTATE NEXT BIT TO SEND INTO BIT 7
LD C,A ; SAVE WORKING VALUE
AND %10000000 ; ISOLATE THE DATA BIT
OR DSRTC_CE ; KEEP CE HIGH
OUT (DSRTC_BASE),A ; ASSERT DATA BIT ON BUS
OR DSRTC_CLK ; SET CLOCK HI
OUT (DSRTC_BASE),A ; DO IT
CALL DLY1 ; DELAY 27 T-STATES
DJNZ DSRTC_PUT1 ; LOOP IF NOT DONE
RET
;
; READ BYTE FROM RTC, RETURN VALUE IN A
; READ THE NEXT BYTE FROM THE RTC INTO A. CE IS IMPLICITLY
; ASSERTED AT THE START. CE AND CLK ARE LEFT HIGH AT
; THE END. CLOCK *MUST* BE LEFT HIGH FROM DSRTC_CMD!
;
; 0) ASSUME ENTRY WITH CE HI, OTHERS UNDEFINED
; 1) SET RD HI AND CLOCK LOW
; 3) WAIT 250NS (CLOCK PUTS DATA BIT ON BUS)
; 4) READ DATA BIT
; 5) SET CLOCK HI
; 6) WAIT 250NS
; 7) LOOP FOR 8 DATA BITS
; 8) EXIT WITH CE,CLK,RD HI
;
DSRTC_GET:
LD C,0 ; INITIALIZE WORKING VALUE TO 0
LD B,8 ; LOOP FOR 8 BITS
DSRTC_GET1:
LD A,DSRTC_CE | DSRTC_RD ; SET CLK LO
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
CALL DLY2 ; DELAY 2 * 27 T-STATES
IN A,(DSRTC_BASE) ; READ THE RTC PORT
AND %00000001 ; ISOLATE THE DATA BIT
OR C ; COMBINE WITH WORKING VALUE
RRCA ; ROTATE FOR NEXT BIT
LD C,A ; SAVE WORKING VALUE
LD A,DSRTC_CE | DSRTC_CLK | DSRTC_RD ; CLOCK BACK TO HI
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
CALL DLY1 ; DELAY 27 T-STATES
DJNZ DSRTC_GET1 ; LOOP IF NOT DONE (13)
LD A,C ; GET RESULT INTO A
RET
;
; COMPLETE A COMMAND SEQUENCE
; FINISHES UP A COMMAND SEQUENCE.
; DOES NOT DESTROY ANY REGISTERS.
;
; 1) SET ALL LINES LO
;
DSRTC_END:
PUSH AF ; SAVE AF
XOR A ; ALL LINES OFF TO CLEAN UP
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
POP AF ; RESTORE AF
RET
;
#ENDIF
;
#IF (DSRTCMODE == DSRTCMODE_MFPIC)
;
;
; SEND COMMAND IN C TO RTC
; ALL RTC SEQUENCES MUST CALL THIS FIRST TO SEND THE RTC COMMAND.
; THE COMMAND IS SENT VIA A PUT. CE AND CLK ARE LEFT ACTIVE! THIS
; IS INTENTIONAL BECAUSE WHEN THE CLOCK IS LOWERED, THE FIRST BIT
; WILL BE PRESENTED TO READ (IN THE CASE OF A READ CMD).
;
; 0) ASSUME ALL LINES UNDEFINED AT ENTRY
; 1) DEASSERT ALL LINES (CE, RD, CLOCK, & DATA)
; 2) WAIT 1US
; 3) SET CE HI
; 4) WAIT 1US
; 5) PUT COMMAND
;
DSRTC_CMD:
;XOR A ; ALL LINES LOW TO RESET
LD A,DSRTC_RESET ; QUIESCENT STATE
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
CALL DLY2 ; DELAY 2 * 27 T-STATES
XOR DSRTC_CE ; NOW ASSERT CE
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
CALL DLY2 ; DELAY 2 * 27 T-STATES
LD A,C ; LOAD COMMAND
CALL DSRTC_PUT ; WRITE IT
RET
;
; WRITE BYTE IN A TO THE RTC
; WRITE BYTE IN A TO THE RTC. CE IS IMPLICITY ASSERTED AT
; THE START. CE AND CLK ARE LEFT ASSERTED AT THE END IN CASE
; NEXT ACTION IS A READ.
;
; 0) ASSUME ENTRY WITH CE ASSERTED, OTHERS UNDEFINED
; 1) CLOCK -> LOW
; 2) WAIT 250NS
; 3) SET DATA ACCORDING TO BIT VALUE
; 4) CLOCK -> HIGH
; 5) WAIT 250NS (CLOCK READS DATA BIT FROM BUS)
; 6) LOOP FOR 8 DATA BITS
; 7) EXIT WITH CE AND CLOCK ASSERTED
;
DSRTC_PUT:
LD B,8 ; LOOP FOR 8 BITS
LD C,A ; SAVE THE WORKING VALUE
LD A,DSRTC_WR | DSRTC_CLK ; MODE=WRITE, CLOCK ON, CE ACTIVE (0)
OR DSRTC_WR ; SET WRITE MODE
#ELSE
AND ~DSRTC_RD ; SET WRITE MODE
#ENDIF
DSRTC_PUT1:
XOR DSRTC_CLK ; FLIP CLOCK OFF
AND ~DSRTC_CLK ; SET CLOCK LOW
OUT (DSRTC_BASE),A ; DO IT
CALL DLY1 ; DELAY 27 T-STATES
#IF (DSRTCMODE == DSRTCMODE_MFPIC)
RRA ; PREP ACCUM TO GET DATA BIT IN CARRY
RR C ; ROTATE NEXT BIT TO SEND INTO CARRY
RR E ; ROTATE NEXT BIT TO SEND INTO CARRY
RLA ; ROTATE BITS BACK TO CORRECT POSTIIONS
#ELSE
RLA ; PREP ACCUM TO GET DATA BIT IN CARRY
RR E ; ROTATE NEXT BIT TO SEND INTO CARRY
RRA ; ROTATE BITS BACK TO CORRECT POSTIIONS
#ENDIF
OUT (DSRTC_BASE),A ; ASSERT DATA BIT ON BUS
XOR DSRTC_CLK ; FLIP CLOCK ON
OUT (DSRTC_BASE),A ; DO IT, DATA BIT SENT ON RISING EDGE
OR DSRTC_CLK ; SET CLOCK HI
OUT (DSRTC_BASE),A ; DO IT
CALL DLY1 ; DELAY 27 T-STATES
DJNZ DSRTC_PUT1 ; LOOP IF NOT DONE
RET
;
; READ BYTE FROM RTC, RETURN VALUE IN A
; READ THE NEXT BYTE FROM THE RTC INTO A. CE IS IMPLICITLY
; ASSERTED AT THE START. CE AND CLK ARE LEFT HIGH AT
; THE END. CLOCK *MUST* BE LEFT HIGH FROM DSRTC_CMD!
; READ BYTE FROM RTC, RETURN VALUE IN E
; READ THE NEXT BYTE FROM THE RTC INTO E. CE IS IMPLICITLY
; ASSERTED AT THE START. CE AND CLK ARE LEFT ASSERTED AT
; THE END. CLOCK *MUST* BE LEFT ASSERTED FROM DSRTC_CMD!
;
; 0) ASSUME ENTRY WITH CE HI, OTHERS UNDEFINED
; 1) SET RD HI AND CLOCK LOW
@ -544,38 +480,38 @@ DSRTC_PUT1:
; 8) EXIT WITH CE,CLK,RD HI
;
DSRTC_GET:
LD C,0 ; INITIALIZE WORKING VALUE TO 0
LD E,0 ; INITIALIZE WORKING VALUE TO 0
LD B,8 ; LOOP FOR 8 BITS
LD A,DSRTC_CLK ; MODE=READ, CLOCK ON, CE ACTIVE (0)
#IF (DSRTCMODE == DSRTCMODE_MFPIC)
AND ~DSRTC_WR ; SET READ MODE
#ELSE
OR DSRTC_RD ; SET READ MODE
#ENDIF
DSRTC_GET1:
XOR DSRTC_CLK ; FLIP CLOCK OFF
OUT (DSRTC_BASE),A ; DO IT
CALL DLY2 ; DELAY 2 * 27 T-STATES
AND ~DSRTC_CLK ; SET CLK LO
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
CALL DLY1 ; DELAY 2 * 27 T-STATES
PUSH AF ; SAVE PORT VALUE
IN A,(DSRTC_BASE) ; READ THE RTC PORT
RRA ; DATA BIT TO CARRY
RR C ; SHIFT INTO WORKING VALUE
LD A,DSRTC_CLK ; CLOCK ON
RR E ; SHIFT INTO WORKING VALUE
POP AF ; RESTORE PORT VALUE
OR DSRTC_CLK ; CLOCK BACK TO HI
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
CALL DLY1 ; DELAY 27 T-STATES
DJNZ DSRTC_GET1 ; LOOP IF NOT DONE
LD A,C ; GET RESULT INTO A
DJNZ DSRTC_GET1 ; LOOP IF NOT DONE (13)
RET
;
; COMPLETE A COMMAND SEQUENCE
; FINISHES UP A COMMAND SEQUENCE.
; DOES NOT DESTROY ANY REGISTERS.
;
; 1) BACK TO QUIESCENT STATE
; 1) SET ALL LINES BACK TO QUIESCENT STATE
;
DSRTC_END:
PUSH AF ; SAVE AF
;XOR A ; ALL LINES OFF TO CLEAN UP
LD A,DSRTC_RESET ; QUIESCENT STATE
OUT (DSRTC_BASE),A ; WRITE TO RTC PORT
POP AF ; RESTORE AF
RET
;
#ENDIF
LD A,(RTCVAL) ; INIT A WITH QUIESCENT STATE
OUT (DSRTC_BASE),A ; WRITE TO PORT
RET ; RETURN
;
; WORKING VARIABLES
;

138
Source/HBIOS/sd.asm

@ -9,14 +9,14 @@
; - TEST XC CARD TYPE DETECTION
; - TRY TO GET INIT TO FAIL, REMOVE DELAYS AT START OF GOIDLE?
;
;------------------------------------------------------------------------------
; SD Signal Active JUHA N8 CSIO PPI UART DSD MK4
; ------------ ------- ------- ------- ------- ------- ------- ------- -------
; CS (DAT3) LO -> RTC:2 RTC:2 RTC:2 ~PC:4 ~MCR:3 OPR:2 MK4_SD:2
; CLK HI -> RTC:1 RTC:1 N/A PC:1 ~MCR:2 OPR:1 N/A
; DI (CMD) HI -> RTC:0 RTC:0 N/A PC:0 ~MCR:0 OPR:0 N/A
; DO (DAT0) HI -> RTC:7 RTC:6 N/A PB:7 ~MSR:5 OPR:0 N/A
;------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------
; SD Signal Active JUHA N8 CSIO PPI UART DSD MK4 SC126
; ------------ ------- ------- ------- ------- ------- ------- ------- ------- -------
; CS (DAT3) LO -> RTC:2 RTC:2 RTC:2 ~PC:4 ~MCR:3 OPR:2 SD:2 ~RTC:2
; CLK HI -> RTC:1 RTC:1 CSIO PC:1 ~MCR:2 OPR:1 CSIO CSIO
; DI (CMD) HI -> RTC:0 RTC:0 CSIO PC:0 ~MCR:0 OPR:0 CSIO CSIO
; DO (DAT0) HI -> RTC:7 RTC:6 CSIO PB:7 ~MSR:5 OPR:0 CSIO CSIO
;--------------------------------------------------------------------------------------
;
; CS = CHIP SELECT (AKA DAT3 FOR NON-SPI MODE)
; CLK = CLOCK
@ -79,10 +79,46 @@
; | +----------- CARD ECC FAILED - CARD INTERNAL ECC FAILED TO CORRECT DATA
; +--------------- OUT OF RANGE - PARAMAETER OUT OF RANGE ALLOWED FOR CARD
;
;------------------------------------------------------------------------------
;
; *** HACK FOR MISSING PULLUP RESISTORS ***
;
; THERE IS A RECENT TREND FOR SD ADAPTER BOARDS (SUCH AS THOSE USED TO ATTACH AN
; SD CARD TO AN ARDUINO OR RASPBERRY PI) TO OMIT THE PULLUP RESISTORS THAT ARE SUPPOSED
; TO BE ON ALL LINES. DESPITE BEING A CLEAR VIOLATION OF THE SPEC, IT IS SOMETHING THAT
; WE WILL NOW NEED TO LIVE WITH. THE CLK, CS, AND MOSI SIGNALS ARE NOT AN ISSUE SINCE
; WE ARE DRIVING THOSE SIGNALS AS THE HOST. THE PROBLEM IS WITH THE MISO SIGNAL.
; FORTUNATELY, MOST OF THE TIME, THE SD CARD WILL BE DRIVING THE SIGNAL. HOWEVER,
; THERE ARE TWO SCEANRIOS WE NEED TO ACCOMMODATE IN THE CODE:
;
; 1. MISO WILL NOT BE DRIVEN BY THE SD CARD (FLOATING) PRIOR TO RESETING THE
; CARD WITH CMD0. NORMALLY, A COMMAND SEQUENCE INVOLVES WAITING FOR THE
; CARD TO BE "READY" BY READING BYTES FROM THE CARD AND LOOKING FOR $FF.
; WHEN MISO IS FLOATING THIS WILL NOT BE RELIABLE. SINCE THE SPEC INDICATES
; IT IS NOT NECESSARY TO WAIT FOR READY PRIOR TO CMD0, THE CODE HAS BEEN
; MODIFIED TO ISSUE CMD0 WITHOUT WAITING FOR READY.
;
; 2. MISO MAY NOT BE DRIVEN IMMEDIATELY AFTER SENDING A COMMAND (POSSIBLY
; JUST CMD0, BUT NOT SURE). NORMALLY, AFTER SENDING A COMMAND, YOU
; LOOK FOR "FILL" BYTES OF $FF THAT MAY OCCUR PRIOR TO THE RESULT. WHEN MISO
; IS FLOATING IT IS IMPOSSIBLE TO DETERMINE IF THE BYTE RECEIVED IS A FILL
; BYTE OR NOT. BASED ON WHAT I HAVE READ, THERE WILL ALWAYS BE AT LEAST
; ONE FILL BYTE PRIOR TO THE ACTUAL RESULT. ADDITIONALLY, THE SD CARD WILL
; START DRIVING MISO SOMETIME WITHING THAT FIRST FILL BYTE. SO, WE NOW
; JUST DISCARD THE FIRST BYTE RECEIVED AFTER A COMMAND IS SENT WITH THE
; ASSUMPTION THAT IT MUST BE A FILL BYTE AND IS NOT RELIABLE DUE TO FLOATING
; MISO.
;
; THESE CHANGES ARE CONSISTENT WITH THE POPULAR ARDUINO SDFAT LIBRARY, SO THEY ARE
; PROBABLY PRETTY SAFE. HOWEVER, I HAVE BRACKETED THE CHANGES WITH THE EQUATE BELOW.
; IF YOU WANT TO REVERT THESE HACKS, JUST SET THE EQUATE TO FALSE.
;
SD_NOPULLUP .EQU TRUE ; ASSUME NO PULLUP
;
#IF (SDMODE == SDMODE_JUHA) ; JUHA MINI-BOARD
SD_DEVCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS)
SD_OPRREG .EQU RTC ; USES RTC LATCHES FOR OPERATION
SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE???
SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE
SD_INPREG .EQU RTC ; INPUT REGISTER IS RTC
SD_CS .EQU %00000100 ; RTC:2 IS SELECT
SD_CLK .EQU %00000010 ; RTC:1 IS CLOCK
@ -93,7 +129,7 @@ SD_DO .EQU %10000000 ; RTC:7 IS DATA OUT (CARD -> CPU)
#IF (SDMODE == SDMODE_N8) ; UNMODIFIED N8-2511
SD_DEVCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS)
SD_OPRREG .EQU RTC ; USES RTC LATCHES FOR OPERATION
SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE???
SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE
SD_INPREG .EQU RTC ; INPUT REGISTER IS RTC
SD_CS .EQU %00000100 ; RTC:2 IS SELECT
SD_CLK .EQU %00000010 ; RTC:1 IS CLOCK
@ -158,11 +194,11 @@ SD_CNTR .EQU Z180_CNTR
SD_TRDR .EQU Z180_TRDR
#ENDIF
;
#IF (SDMODE == SDMODE_SC126) ; N8-2312
#IF (SDMODE == SDMODE_SC126) ; SC126
SD_DEVCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS)
SD_OPRREG .EQU RTC ; USES RTC LATCHES FOR OPERATION
SD_OPRDEF .EQU %00001101 ; QUIESCENT STATE
SD_CS .EQU %00000100 ; RTC:2 IS SELECT
SD_OPRDEF .EQU %00001100 ; QUIESCENT STATE (DEASSERT /CS1 & /CS2)
SD_CS .EQU %00000100 ; RTC:2 IS SELECT FOR PRIMARY SPI CARD
SD_CNTR .EQU Z180_CNTR
SD_TRDR .EQU Z180_TRDR
#ENDIF
@ -257,6 +293,10 @@ SD_INIT:
PRTS(" IO=0x$")
LD A,SD_OPRREG
CALL PRTHEXBYTE
;
LD A,(RTCVAL) ; GET RTC PORT SHADOW VALUE
OR SD_OPRDEF ; SET OUR BIT DEFAULTS
LD (RTCVAL),A ; SAVE IT
#ENDIF
;
#IF (SDMODE == SDMODE_N8)
@ -264,6 +304,10 @@ SD_INIT:
PRTS(" IO=0x$")
LD A,SD_OPRREG
CALL PRTHEXBYTE
;
LD A,(RTCVAL) ; GET RTC PORT SHADOW VALUE
OR SD_OPRDEF ; SET OUR BIT DEFAULTS
LD (RTCVAL),A ; SAVE IT
#ENDIF
;
#IF (SDMODE == SDMODE_CSIO)
@ -280,6 +324,10 @@ SD_INIT:
PRTS(" TRDR=0x$")
LD A,SD_TRDR
CALL PRTHEXBYTE
;
LD A,(RTCVAL) ; GET RTC PORT SHADOW VALUE
OR SD_OPRDEF ; SET OUR BIT DEFAULTS
LD (RTCVAL),A ; SAVE IT
#ENDIF
;
#IF (SDMODE == SDMODE_PPI)
@ -339,6 +387,10 @@ SD_INIT:
PRTS(" TRDR=0x$")
LD A,SD_TRDR
CALL PRTHEXBYTE
;
LD A,(RTCVAL) ; GET RTC PORT SHADOW VALUE
OR SD_OPRDEF ; SET OUR BIT DEFAULTS
LD (RTCVAL),A ; SAVE IT
#ENDIF
;
CALL SD_PROBE ; CHECK FOR HARDWARE
@ -704,12 +756,6 @@ SD_GEOM:
; (RE)INITIALIZE CARD
;
SD_INITCARD:
;
;; CLEAR OUT UNIT SPECIFIC DATA
;SD_DPTR(0) ; SET HL TO START OF UNIT DATA
;LD BC,SD_UNITDATALEN
;XOR A
;CALL FILL
;
CALL SD_CHKCD ; CHECK CARD DETECT
JP Z,SD_NOMEDIA ; Z=NO MEDIA, HANDLE IF SO
@ -725,7 +771,7 @@ SD_INITCARD1:
;
; PUT CARD IN IDLE STATE
CALL SD_GOIDLE ; GO TO IDLE
RET NZ ; ABORT IF FAILED
JP NZ,SD_NOMEDIA ; CONVERT ERROR TO NO MEDIA
;
SD_INITCARD2:
LD (IY+SD_TYPE),SD_TYPESDSC ; ASSUME SDSC CARD TYPE
@ -1106,9 +1152,8 @@ SD_GOIDLE1:
RET NZ ; ABORT ON ERROR
LD A,(SD_RC) ; GET CARD RESULT
DEC A ; MAP EXPECTED $01 -> $00
RET Z ; ALL IS GOOD, RETURN WITH Z=0 AND Z SET
LD A,SD_STCMDERR ; SET COMMAND ERROR VALUE, NZ ALREADY SET
RET ; AND RETURN
RET Z ; ALL IS GOOD, RETURN WITH A=0 AND Z SET
JP SD_ERRCMD ; SET COMMAND ERROR VALUE
;
; INITIALIZE COMMAND BUFFER
; COMMAND BYTE IN ACCUM
@ -1155,10 +1200,23 @@ SD_EXECCMD:
CALL WRITESTR
POP AF
#ENDIF
;
CALL SD_SELECT
;
#IF (SD_NOPULLUP)
; DO NOT WAIT FOR READY PRIOR TO CMD0! THIS HACK IS REQUIRED BY
; STUPID SD CARD ADAPTERS THAT NOW OMIT THE MISO PULL-UP. SEE
; COMMENTS AT TOP OF THIS FILE.
LD A,(SD_CMDBUF)
CP SD_CMD_GO_IDLE_STATE
JR Z,SD_EXECCMD0
#ENDIF
;
; WAIT FOR CARD TO BE READY
CALL SD_WAITRDY ; WAIT FOR CARD TO BE READY FOR A COMMAND
JP NZ,SD_ERRRDYTO ; HANDLE TIMEOUT ERROR
;
SD_EXECCMD0:
; SEND THE COMMAND
LD HL,SD_CMDBUF ; POINT TO COMMAND BUFFER
LD E,6 ; COMMANDS ARE 6 BYTES
@ -1168,6 +1226,13 @@ SD_EXECCMD1:
INC HL ; POINT TO NEXT BYTE
DEC E ; DEC LOOP COUNTER
JR NZ,SD_EXECCMD1 ; LOOP TILL DONE W/ ALL 6 BYTES
;
#IF (SD_NOPULLUP)
; THE FIRST FILL BYTE IS DISCARDED! THIS HACK IS REQUIRED BY
; STUPID SD CARD ADAPTERS THAT NOW OMIT THE MISO PULL-UP. SEE
; COMMENTS AT TOP OF THIS FILE.
CALL SD_GET ; GET A BYTE AND DISCARD IT
#ENDIF
;
; GET RESULT
LD E,0 ; INIT TIMEOUT LOOP COUNTER
@ -1277,10 +1342,9 @@ SD_PUTDATA3:
XOR A
RET
;
; SELECT CARD AND WAIT FOR IT TO BE READY ($FF)
; WAIT FOR CARD TO BE READY ($FF). MUST ALREADY BE SELECTED.
;
SD_WAITRDY:
CALL SD_SELECT ; SELECT CARD
LD DE,$FFFF ; LOOP MAX (TIMEOUT)
SD_WAITRDY1:
CALL SD_GET
@ -1320,27 +1384,27 @@ SD_DONE:
;
SD_SETUP:
;
#IF ((SDMODE == SDMODE_JUHA) | (SDMODE == SDMODE_N8) | (SDMODE == SDMODE_DSD))
LD A,SD_OPRDEF
LD (SD_OPRVAL),A
OUT (SD_OPRREG),A
#IF (SDMODE == SDMODE_PPI)
; PPISD IS DESIGNED TO CORESIDE ON THE SAME PARALLEL PORT
; AS A DSKY. SEE DSKY.ASM FOR DETAILS.
LD A,82H ; PPI PORT A=OUT, B=IN, C=OUT
OUT (SD_PPIX),A
#ENDIF
;
#IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4) | (SDMODE == SDMODE_SC126))
; CSIO SETUP
; CSIO SETUP FOR Z180 CSIO
; LD A,2 ; 18MHz/20 <= 400kHz
LD A,6 ; ???
OUT0 (SD_CNTR),A
LD A,SD_OPRDEF
#ENDIF
;
#IF ((SDMODE == SDMODE_JUHA) | (SDMODE == SDMODE_N8) | (SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_SC126))
LD A,(RTCVAL)
LD (SD_OPRVAL),A
OUT (SD_OPRREG),A
#ENDIF
;
#IF (SDMODE == SDMODE_PPI)
; PPISD IS DESIGNED TO CORESIDE ON THE SAME PARALLEL PORT
; AS A DSKY. SEE DSKY.ASM FOR DETAILS.
LD A,82H ; PPI PORT A=OUT, B=IN, C=OUT
OUT (SD_PPIX),A
#IF ((SDMODE == SDMODE_MK4) | (SDMODE == SDMODE_DSD) | (SDMODE == SDMODE_PPI))
LD A,SD_OPRDEF
LD (SD_OPRVAL),A
OUT (SD_OPRREG),A

723
Source/HBIOS/sio.asm

@ -15,38 +15,91 @@
; https://www.retrobrewcomputers.org/doku.php?id=boards:ecb:zilog-peripherals:clock-divider
;
; SIO PORT A (COM1:) and SIO PORT B (COM2:) ARE MAPPED TO DEVICE UC1: AND UL1: IN CP/M.
;
;
SIO_BUFSZ .EQU 32 ; RECEIVE RING BUFFER SIZE
;
SIO_NONE .EQU 0
SIO_SIO .EQU 1
;
#IF (SIOMODE == SIOMODE_RC)
SIOA_CMD .EQU SIOBASE + $00
SIOA_DAT .EQU SIOBASE + $01
SIOB_CMD .EQU SIOBASE + $02
SIOB_DAT .EQU SIOBASE + $03
;
SIO_RTSON .EQU $EA
SIO_RTSOFF .EQU $E8
;
#IF (INTMODE == 2)
;
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RCZ180))
SIO0_IVT .EQU HB_IVT0D
SIO1_IVT .EQU HB_IVT0E
SIO0_VEC .EQU IVT_SER2
SIO1_VEC .EQU IVT_SER3
#ELSE
SIO0_IVT .EQU HB_IVT07
SIO1_IVT .EQU HB_IVT08
SIO0_VEC .EQU IVT_SER0
SIO1_VEC .EQU IVT_SER1
#ENDIF
;
#ENDIF
;
#IF (SIO0MODE == SIOMODE_RC)
SIO0A_CMD .EQU SIO0BASE + $00
SIO0A_DAT .EQU SIO0BASE + $01
SIO0B_CMD .EQU SIO0BASE + $02
SIO0B_DAT .EQU SIO0BASE + $03
#ENDIF
;
#IF (SIOMODE == SIOMODE_SMB)
SIOA_CMD .EQU SIOBASE + $02
SIOA_DAT .EQU SIOBASE + $00
SIOB_CMD .EQU SIOBASE + $03
SIOB_DAT .EQU SIOBASE + $01
#IF (SIO0MODE == SIOMODE_SMB)
SIO0A_CMD .EQU SIO0BASE + $02
SIO0A_DAT .EQU SIO0BASE + $00
SIO0B_CMD .EQU SIO0BASE + $03
SIO0B_DAT .EQU SIO0BASE + $01
#ENDIF
;
#IF (SIO0MODE == SIOMODE_ZP)
SIO0A_CMD .EQU SIO0BASE + $06
SIO0A_DAT .EQU SIO0BASE + $04
SIO0B_CMD .EQU SIO0BASE + $07
SIO0B_DAT .EQU SIO0BASE + $05
#ENDIF
;
#IF (SIOMODE == SIOMODE_ZP)
SIOA_CMD .EQU SIOBASE + $06
SIOA_DAT .EQU SIOBASE + $04
SIOB_CMD .EQU SIOBASE + $07
SIOB_DAT .EQU SIOBASE + $05
#IF (SIO0MODE == SIOMODE_EZZ80)
SIO0A_CMD .EQU SIO0BASE + $01
SIO0A_DAT .EQU SIO0BASE + $00
SIO0B_CMD .EQU SIO0BASE + $03
SIO0B_DAT .EQU SIO0BASE + $02
#ENDIF
;
#IF (SIOMODE == SIOMODE_EZZ80)
SIOA_CMD .EQU SIOBASE + $01
SIOA_DAT .EQU SIOBASE + $00
SIOB_CMD .EQU SIOBASE + $03
SIOB_DAT .EQU SIOBASE + $02
#IF (SIOCNT >= 2)
;
#IF (SIO1MODE == SIOMODE_RC)
SIO1A_CMD .EQU SIO1BASE + $00
SIO1A_DAT .EQU SIO1BASE + $01
SIO1B_CMD .EQU SIO1BASE + $02
SIO1B_DAT .EQU SIO1BASE + $03
#ENDIF
;
#IF (SIO1MODE == SIOMODE_SMB)
SIO1A_CMD .EQU SIO1BASE + $02
SIO1A_DAT .EQU SIO1BASE + $00
SIO1B_CMD .EQU SIO1BASE + $03
SIO1B_DAT .EQU SIO1BASE + $01
#ENDIF
;
#IF (SIO1MODE == SIOMODE_ZP)
SIO1A_CMD .EQU SIO1BASE + $06
SIO1A_DAT .EQU SIO1BASE + $04
SIO1B_CMD .EQU SIO1BASE + $07
SIO1B_DAT .EQU SIO1BASE + $05
#ENDIF
;
#IF (SIO1MODE == SIOMODE_EZZ80)
SIO1A_CMD .EQU SIO1BASE + $01
SIO1A_DAT .EQU SIO1BASE + $00
SIO1B_CMD .EQU SIO1BASE + $03
SIO1B_DAT .EQU SIO1BASE + $02
#ENDIF
;
#ENDIF
;
; CONDITIONALS THAT DETERMINE THE ENCODED VALUE OF THE BAUD RATE
;
#INCLUDE "siobaud.inc"
@ -57,23 +110,15 @@ SIO_PREINIT:
; NOTE: INTS WILL BE DISABLED WHEN PREINIT IS CALLED AND THEY MUST REMIAIN
; DISABLED.
;
LD B,SIO_CNT ; LOOP CONTROL
LD C,0 ; PHYSICAL UNIT INDEX
CALL SIO_PROBE ; PROBE FOR CHIPS
;
LD B,SIO_CFGCNT ; LOOP CONTROL
XOR A ; ZERO TO ACCUM
LD (SIO_DEV),A ; CURRENT DEVICE NUMBER
LD IY,SIO_CFG ; POINT TO START OF CFG TABLE
SIO_PREINIT0:
PUSH BC ; SAVE LOOP CONTROL
LD A,C ; PHYSICAL UNIT TO A
RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES)
RLCA ; ...
RLCA ; ... TO GET OFFSET INTO CFG TABLE
LD HL,SIO_CFG ; POINT TO START OF CFG TABLE
CALL ADDHLA ; HL := ENTRY ADDRESS
PUSH HL ; SAVE IT
PUSH HL ; COPY CFG DATA PTR
POP IY ; ... TO IY
CALL SIO_INITUNIT ; HAND OFF TO GENERIC INIT CODE
POP DE ; GET ENTRY ADDRESS BACK, BUT PUT IN DE
POP BC ; RESTORE LOOP CONTROL
;
LD A,(IY+1) ; GET THE SIO TYPE DETECTED
@ -81,16 +126,25 @@ SIO_PREINIT0:
JR Z,SIO_PREINIT2 ; SKIP IT IF NOTHING FOUND
;
PUSH BC ; SAVE LOOP CONTROL
PUSH IY ; CFG ENTRY ADDRESS
POP DE ; ... TO DE
LD BC,SIO_FNTBL ; BC := FUNCTION TABLE ADDRESS
CALL NZ,CIO_ADDENT ; ADD ENTRY IF SIO FOUND, BC:DE
POP BC ; RESTORE LOOP CONTROL
;
SIO_PREINIT2:
INC C ; NEXT PHYSICAL UNIT
LD DE,SIO_CFGSIZ ; SIZE OF CFG ENTRY
ADD IY,DE ; BUMP IY TO NEXT ENTRY
DJNZ SIO_PREINIT0 ; LOOP UNTIL DONE
;
#IF (INTMODE >= 1)
; SETUP INT VECTORS AS APPROPRIATE
LD A,(SIO_DEV) ; GET NEXT DEVICE NUM
OR A ; SET FLAGS
JR Z,SIO_PREINIT3 ; IF ZERO, NO SIO DEVICES, ABORT
;
#IF (INTMODE == 1)
; ADD IM1 INT CALL LIST ENTRY IF APPROPRIATE
; ADD IM1 INT CALL LIST ENTRY
LD A,(SIO_DEV) ; GET NEXT DEVICE NUM
OR A ; SET FLAGS
JR Z,SIO_PREINIT3 ; IF ZERO, NO SIO DEVICES
@ -99,9 +153,17 @@ SIO_PREINIT2:
#ENDIF
;
#IF (INTMODE == 2)
; SETUP SIO INTERRUPT VECTOR IN IVT
LD HL,SIO_INT
LD (HB_IVT07 + 1),HL ; IVT INDEX 7
; SETUP IM2 VECTORS
LD HL,SIO_INT0
LD (SIO0_IVT + 1),HL ; IVT INDEX
;
#IF (SIOCNT >= 2)
LD HL,SIO_INT1
LD (SIO1_IVT + 1),HL ; IVT INDEX
#ENDIF
;
#ENDIF
;
#ENDIF
;
SIO_PREINIT3:
@ -131,26 +193,16 @@ SIO_INITUNIT:
;
;
SIO_INIT:
LD B,SIO_CNT ; COUNT OF POSSIBLE SIO UNITS
LD C,0 ; INDEX INTO SIO CONFIG TABLE
LD B,SIO_CFGCNT ; COUNT OF POSSIBLE SIO UNITS
LD IY,SIO_CFG ; POINT TO START OF CFG TABLE
SIO_INIT1:
PUSH BC ; SAVE LOOP CONTROL
LD A,C ; PHYSICAL UNIT TO A
RLCA ; MULTIPLY BY CFG TABLE ENTRY SIZE (8 BYTES)
RLCA ; ...
RLCA ; ... TO GET OFFSET INTO CFG TABLE
LD HL,SIO_CFG ; POINT TO START OF CFG TABLE
CALL ADDHLA ; HL := ENTRY ADDRESS
PUSH HL ; COPY CFG DATA PTR
POP IY ; ... TO IY
LD A,(IY+1) ; GET SIO TYPE
OR A ; SET FLAGS
CALL NZ,SIO_PRTCFG ; PRINT IF NOT ZERO
POP BC ; RESTORE LOOP CONTROL
INC C ; NEXT UNIT
LD DE,SIO_CFGSIZ ; SIZE OF CFG ENTRY
ADD IY,DE ; BUMP IY TO NEXT ENTRY
DJNZ SIO_INIT1 ; LOOP TILL DONE
;
XOR A ; SIGNAL SUCCESS
@ -160,96 +212,110 @@ SIO_INIT1:
;
#IF (INTMODE > 0)
;
; IM0 ENTRY POINT
;
SIO_INT:
SIOA_INT:
; CHECK FOR RECEIVE PENDING ON CHANNEL A
XOR A ; A := 0
OUT (SIOA_CMD),A ; ADDRESS RD0
IN A,(SIOA_CMD) ; GET RD0
AND $01 ; ISOLATE RECEIVE READY BIT
JR Z,SIOB_INT ; CHECK CHANNEL B
;
SIOA_INT00:
; HANDLE CHANNEL A
IN A,(SIOA_DAT) ; READ PORT
LD E,A ; SAVE BYTE READ
LD A,(SIOA_CNT) ; GET CURRENT BUFFER USED COUNT
CP SIOA_BUFSZ ; COMPARE TO BUFFER SIZE
;RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
JR Z,SIOA_INT2 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
INC A ; INCREMENT THE COUNT
LD (SIOA_CNT),A ; AND SAVE IT
CP SIOA_BUFSZ / 2 ; BUFFER GETTING FULL?
JR NZ,SIOA_INT0 ; IF NOT, BYPASS CLEARING RTS
LD A,5 ; RTS IS IN WR5
OUT (SIOA_CMD),A ; ADDRESS WR5
LD A,$E8 ; VALUE TO CLEAR RTS
OUT (SIOA_CMD),A ; DO IT
SIOA_INT0:
LD HL,(SIOA_HD) ; GET HEAD POINTER
LD A,L ; GET LOW BYTE
CP SIOA_BUFEND & $FF ; PAST END?
JR NZ,SIOA_INT1 ; IF NOT, BYPASS POINTER RESET
LD HL,SIOA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER
SIOA_INT1:
LD A,E ; RECOVER BYTE READ
LD (HL),A ; SAVE RECEIVED BYTE TO HEAD POSITION
INC HL ; INCREMENT HEAD POINTER
LD (SIOA_HD),HL ; SAVE IT
;
SIOA_INT2:
; CHECK FOR MORE PENDING...
XOR A ; A := 0
OUT (SIOA_CMD),A ; ADDRESS RD0
IN A,(SIOA_CMD) ; GET RD0
RRA ; READY BIT TO CF
JR C,SIOA_INT00 ; IF SET, DO SOME MORE
OR $FF ; NZ SET TO INDICATE INT HANDLED
RET ; AND RETURN
; CHECK/HANDLE FIRST CARD (SIO0) IF IT EXISTS
LD A,(SIO0A_CFG + 1) ; GET SIO TYPE FOR FIRST CHANNEL OF FIRST SIO
OR A ; SET FLAGS
CALL NZ,SIO_INT0 ; CALL IF CARD EXISTS
RET NZ ; DONE IF INT HANDLED
;
#IF (SIOCNT >= 2)
; CHECK/HANDLE SECOND CARD (SIO1) IF IT EXISTS
LD A,(SIO1A_CFG + 1) ; GET SIO TYPE FOR FIRST CHANNEL OF SECOND SIO
OR A ; SET FLAGS
CALL NZ,SIO_INT1 ; CALL IF CARD EXISTS
#ENDIF
;
SIOB_INT:
; CHECK FOR RECEIVE PENDING ON CHANNEL B
RET ; DONE
;
; IM1 ENTRY POINTS
;
SIO_INT0:
; INTERRUPT HANDLER FOR FIRST SIO (SIO0)
LD IY,SIO0A_CFG ; POINT TO SIO0A CFG
CALL SIO_INTRCV ; TRY TO RECEIVE FROM IT
RET NZ ; DONE IF INT HANDLED
LD IY,SIO0B_CFG ; POINT TO SIO0B CFG
JR SIO_INTRCV ; TRY TO RECEIVE FROM IT AND RETURN
;
#IF (SIOCNT >= 2)
;
SIO_INT1:
; INTERRUPT HANDLER FOR SECOND SIO (SIO1)
LD IY,SIO1A_CFG ; POINT TO SIO1A CFG
CALL SIO_INTRCV ; TRY TO RECEIVE FROM IT
RET NZ ; DONE IF INT HANDLED
LD IY,SIO1B_CFG ; POINT TO SIO1B CFG
JR SIO_INTRCV ; TRY TO RECEIVE FROM IT AND RETURN
;
#ENDIF
;
; HANDLE INT FOR A SPECIFIC CHANNEL
; BASED ON UNIT CFG POINTED TO BY IY
;
SIO_INTRCV:
; CHECK TO SEE IF SOMETHING IS ACTUALLY THERE
LD C,(IY+3) ; CMD/STAT PORT TO C
XOR A ; A := 0
OUT (SIOB_CMD),A ; ADDRESS RD0
IN A,(SIOB_CMD) ; GET RD0
OUT (C),A ; ADDRESS RD0
IN A,(C) ; GET RD0
AND $01 ; ISOLATE RECEIVE READY BIT
RET Z ; IF NOT, RETURN WITH Z SET
;
SIOB_INT00:
; HANDLE CHANNEL B
IN A,(SIOB_DAT) ; READ PORT
LD E,A ; SAVE BYTE READ
LD A,(SIOB_CNT) ; GET CURRENT BUFFER USED COUNT
CP SIOB_BUFSZ ; COMPARE TO BUFFER SIZE
;RET Z ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
JR Z,SIOB_INT2 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
RET Z ; NOTHING AVAILABLE ON CURRENT CHANNEL
;
SIO_INTRCV1:
; RECEIVE CHARACTER INTO BUFFER
LD C,(IY+4) ; DATA PORT TO C
IN A,(C) ; READ PORT
LD B,A ; SAVE BYTE READ
LD L,(IY+7) ; SET HL TO
LD H,(IY+8) ; ... START OF BUFFER STRUCT
LD A,(HL) ; GET COUNT
CP SIO_BUFSZ ; COMPARE TO BUFFER SIZE
JR Z,SIO_INTRCV4 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED
INC A ; INCREMENT THE COUNT
LD (SIOB_CNT),A ; AND SAVE IT
CP SIOB_BUFSZ / 2 ; BUFFER GETTING FULL?
JR NZ,SIOB_INT0 ; IF NOT, BYPASS CLEARING RTS
LD (HL),A ; AND SAVE IT
CP SIO_BUFSZ / 2 ; BUFFER GETTING FULL?
JR NZ,SIO_INTRCV2 ; IF NOT, BYPASS CLEARING RTS
LD C,(IY+3) ; CMD/STAT PORT TO C
LD A,5 ; RTS IS IN WR5
OUT (SIOB_CMD),A ; ADDRESS WR5
LD A,$E8 ; VALUE TO CLEAR RTS
OUT (SIOB_CMD),A ; DO IT
SIOB_INT0:
LD HL,(SIOB_HD) ; GET HEAD POINTER
LD A,L ; GET LOW BYTE
CP SIOB_BUFEND & $FF ; PAST END?
JR NZ,SIOB_INT1 ; IF NOT, BYPASS POINTER RESET
LD HL,SIOB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER
SIOB_INT1:
LD A,E ; RECOVER BYTE READ
LD (HL),A ; SAVE RECEIVED BYTE TO HEAD POSITION
INC HL ; INCREMENT HEAD POINTER
LD (SIOB_HD),HL ; SAVE IT
;
SIOB_INT2:
OUT (C),A ; ADDRESS WR5
LD A,SIO_RTSOFF ; VALUE TO CLEAR RTS
OUT (C),A ; DO IT
SIO_INTRCV2:
INC HL ; HL NOW HAS ADR OF HEAD PTR
PUSH HL ; SAVE ADR OF HEAD PTR
LD A,(HL) ; DEREFERENCE HL
INC HL
LD H,(HL)
LD L,A ; HL IS NOW ACTUAL HEAD PTR
LD (HL),B ; SAVE CHARACTER RECEIVED IN BUFFER AT HEAD
INC HL ; BUMP HEAD POINTER
POP DE ; RECOVER ADR OF HEAD PTR
LD A,L ; GET LOW BYTE OF HEAD PTR
ADD A,-SIO_BUFSZ-4 ; SUBTRACT SIZE OF BUFFER AND POINTER
CP E ; IF EQUAL TO START, HEAD PTR IS PAST BUF END
JR NZ,SIO_INTRCV3 ; IF NOT, BYPASS
LD H,D ; SET HL TO
LD L,E ; ... HEAD PTR ADR
INC HL ; BUMP PAST HEAD PTR
INC HL
INC HL
INC HL ; ... SO HL NOW HAS ADR OF ACTUAL BUFFER START
SIO_INTRCV3:
EX DE,HL ; DE := HEAD PTR VAL, HL := ADR OF HEAD PTR
LD (HL),E ; SAVE UPDATED HEAD PTR
INC HL
LD (HL),D
; CHECK FOR MORE PENDING...
LD C,(IY+3) ; CMD/STAT PORT TO C
XOR A ; A := 0
OUT (SIOB_CMD),A ; ADDRESS RD0
IN A,(SIOB_CMD) ; GET RD0
OUT (C),A ; ADDRESS RD0
IN A,(C) ; GET RD0
RRA ; READY BIT TO CF
JR C,SIOB_INT00 ; IF SET, DO SOME MORE
JR C,SIO_INTRCV1 ; IF SET, DO SOME MORE
SIO_INTRCV4:
OR $FF ; NZ SET TO INDICATE INT HANDLED
RET ; AND RETURN
;
@ -276,17 +342,7 @@ SIO_FNTBL:
SIO_IN:
CALL SIO_IST ; CHAR WAITING?
JR Z,SIO_IN ; LOOP IF NOT
LD C,(IY+3) ; C := SIO CMD PORT
#IF (SIOMODE == SIOMODE_RC)
INC C ; BUMP TO DATA PORT
#ENDIF
#IF ((SIOMODE == SIOMODE_SMB) | (SIOMODE == SIOMODE_ZP))
DEC C ; DECREMENT CMD PORT TWICE TO GET DATA PORT
DEC C
#ENDIF
#IF (SIOMODE == SIOMODE_EZZ80)
DEC C ; DECREMENT CMD PORT TO GET DATA PORT
#ENDIF
LD C,(IY+4) ; DATA PORT
IN E,(C) ; GET CHAR
XOR A ; SIGNAL SUCCESS
RET
@ -294,68 +350,50 @@ SIO_IN:
#ELSE
;
SIO_IN:
LD A,(IY+2) ; GET CHANNEL
OR A ; SET FLAGS
JR Z,SIOA_IN ; HANDLE CHANNEL A
DEC A ; TEST FOR NEXT DEVICE
JR Z,SIOB_IN ; HANDLE CHANNEL B
CALL PANIC ; ELSE FATAL ERROR
RET ; ... AND RETURN
;
SIOA_IN:
CALL SIOA_IST ; RECEIVED CHAR READY?
JR Z,SIOA_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER
HB_DI ; AVOID COLLISION WITH INT HANDLER
LD A,(SIOA_CNT) ; GET COUNT
DEC A ; DECREMENT COUNT
LD (SIOA_CNT),A ; SAVE SAVE IT
CP 5 ; BUFFER LOW THRESHOLD
JR NZ,SIOA_IN0 ; IF NOT, BYPASS SETTING RTS
LD A,5 ; RTS IS IN WR5
OUT (SIOA_CMD),A ; ADDRESS WR5
LD A,$EA ; VALUE TO SET RTS
OUT (SIOA_CMD),A ; DO IT
SIOA_IN0:
LD HL,(SIOA_TL) ; GET BUFFER TAIL POINTER
LD E,(HL) ; GET BYTE
INC HL ; BUMP TAIL POINTER
LD A,L ; GET LOW BYTE
CP SIOA_BUFEND & $FF ; PAST END?
JR NZ,SIOA_IN1 ; IF NOT, BYPASS POINTER RESET
LD HL,SIOA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER
SIOA_IN1:
LD (SIOA_TL),HL ; SAVE UPDATED TAIL POINTER
HB_EI ; INTERRUPTS OK AGAIN
XOR A ; SIGNAL SUCCESS
RET ; AND DONE
;
SIOB_IN:
CALL SIOB_IST ; RECEIVED CHAR READY?
JR Z,SIOB_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER
CALL SIO_IST ; SEE IF CHAR AVAILABLE
JR Z,SIO_IN ; LOOP UNTIL SO
HB_DI ; AVOID COLLISION WITH INT HANDLER
LD A,(SIOB_CNT) ; GET COUNT
LD L,(IY+7) ; SET HL TO
LD H,(IY+8) ; ... START OF BUFFER STRUCT
LD A,(HL) ; GET COUNT
DEC A ; DECREMENT COUNT
LD (SIOB_CNT),A ; SAVE SAVE IT
CP 5 ; BUFFER LOW THRESHOLD
JR NZ,SIOB_IN0 ; IF NOT, BYPASS SETTING RTS
LD (HL),A ; SAVE UPDATED COUNT
CP SIO_BUFSZ / 4 ; BUFFER LOW THRESHOLD
JR NZ,SIO_IN1 ; IF NOT, BYPASS SETTING RTS
LD C,(IY+3) ; C IS CMD/STATUS PORT ADR
LD A,5 ; RTS IS IN WR5
OUT (SIOB_CMD),A ; ADDRESS WR5
LD A,$EA ; VALUE TO SET RTS
OUT (SIOB_CMD),A ; DO IT
SIOB_IN0:
LD HL,(SIOB_TL) ; GET BUFFER TAIL POINTER
LD E,(HL) ; GET BYTE
INC HL ; BUMP TAIL POINTER
LD A,L ; GET LOW BYTE
CP SIOB_BUFEND & $FF ; PAST END?
JR NZ,SIOB_IN1 ; IF NOT, BYPASS POINTER RESET
LD HL,SIOB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER
SIOB_IN1:
LD (SIOB_TL),HL ; SAVE UPDATED TAIL POINTER
OUT (C),A ; ADDRESS WR5
LD A,SIO_RTSON ; VALUE TO SET RTS
OUT (C),A ; DO IT
SIO_IN1:
INC HL
INC HL
INC HL ; HL NOW HAS ADR OF TAIL PTR
PUSH HL ; SAVE ADR OF TAIL PTR
LD A,(HL) ; DEREFERENCE HL
INC HL
LD H,(HL)
LD L,A ; HL IS NOW ACTUAL TAIL PTR
LD C,(HL) ; C := CHAR TO BE RETURNED
INC HL ; BUMP TAIL PTR
POP DE ; RECOVER ADR OF TAIL PTR
LD A,L ; GET LOW BYTE OF TAIL PTR
ADD A,-SIO_BUFSZ-2 ; SUBTRACT SIZE OF BUFFER AND POINTER
CP E ; IF EQUAL TO START, TAIL PTR IS PAST BUF END
JR NZ,SIO_IN2 ; IF NOT, BYPASS
LD H,D ; SET HL TO
LD L,E ; ... TAIL PTR ADR
INC HL ; BUMP PAST TAIL PTR
INC HL ; ... SO HL NOW HAS ADR OF ACTUAL BUFFER START
SIO_IN2:
EX DE,HL ; DE := TAIL PTR VAL, HL := ADR OF TAIL PTR
LD (HL),E ; SAVE UPDATED TAIL PTR
INC HL
LD (HL),D
LD E,C ; MOVE CHAR TO RETURN TO E
HB_EI ; INTERRUPTS OK AGAIN
XOR A ; SIGNAL SUCCESS
RET ; AND DONE
;
#ENDIF
;
;
@ -363,17 +401,7 @@ SIOB_IN1:
SIO_OUT:
CALL SIO_OST ; READY FOR CHAR?
JR Z,SIO_OUT ; LOOP IF NOT
LD C,(IY+3) ; C := SIO CMD PORT
#IF (SIOMODE == SIOMODE_RC)
INC C ; BUMP TO DATA PORT
#ENDIF
#IF ((SIOMODE == SIOMODE_SMB) | (SIOMODE == SIOMODE_ZP))
DEC C ; DECREMENT CMD PORT TWICE TO GET DATA PORT
DEC C
#ENDIF
#IF (SIOMODE == SIOMODE_EZZ80)
DEC C ; DECREMENT CMD PORT TO GET DATA PORT
#ENDIF
LD C,(IY+4) ; DATA PORT
OUT (C),E ; SEND CHAR FROM E
XOR A ; SIGNAL SUCCESS
RET
@ -396,25 +424,12 @@ SIO_IST:
#ELSE
;
SIO_IST:
LD A,(IY+2) ; GET CHANNEL
OR A ; SET FLAGS
JR Z,SIOA_IST ; HANDLE CHANNEL A
DEC A ; TEST FOR NEXT DEVICE
JR Z,SIOB_IST ; HANDLE CHANNEL B
CALL PANIC ; ELSE FATAL ERROR
RET ; ... AND RETURN
;
SIOA_IST:
LD A,(SIOA_CNT) ; GET BUFFER UTILIZATION COUNT
OR A ; SET FLAGS
JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING
RET ; AND DONE
;
SIOB_IST:
LD A,(SIOB_CNT) ; GET BUFFER UTILIZATION COUNT
LD L,(IY+7) ; GET ADDRESS
LD H,(IY+8) ; ... OF RECEIVE BUFFER
LD A,(HL) ; BUFFER UTILIZATION COUNT
OR A ; SET FLAGS
JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING
RET ; DONE
RET
;
#ENDIF
;
@ -461,8 +476,8 @@ SIO_INITDEVX:
JR NZ,SIO_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG
;
; LOAD EXISTING CONFIG TO REINIT
LD E,(IY+4) ; LOW BYTE
LD D,(IY+5) ; HIGH BYTE
LD E,(IY+5) ; LOW BYTE
LD D,(IY+6) ; HIGH BYTE
;
SIO_INITDEV1:
PUSH DE ; SAVE CONFIG
@ -575,12 +590,37 @@ BROK:
CALL PRTHEXBYTE
PRTC(']')
POP AF
#ENDIF
#ENDIF
;
; SET INTERRUPT VECTOR OFFSET WR2
;
#IF (INTMODE == 2)
LD A,(IY+2) ; CHIP / CHANNEL
SRL A ; SHIFT AWAY CHANNEL BIT
LD E,SIO0_VEC ; ASSUME CHIP 0
JR Z,SIO_IVT1 ; IF SO, DO IT
LD E,SIO1_VEC ; ASSUME CHIP 1
DEC A ; CHIP 1?
JR Z,SIO_IVT1 ; IF SO, TO IT
CALL PANIC ; IMPOSSIBLE SITUATION
SIO_IVT1:
LD A,E ; VALUE TO A
LD (SIO_INITVALS+7),A ; SAVE IT
#IF (SIODEBUG)
PUSH AF
PRTS(" WR2[$")
CALL PRTHEXBYTE
PRTC(']')
POP AF
#ENDIF
#ENDIF
POP DE ; RESTORE CONFIG
LD (IY+4),E ; SAVE LOW WORD
LD (IY+5),D ; SAVE HI WORD
LD (IY+5),E ; SAVE LOW WORD
LD (IY+6),D ; SAVE HI WORD
;
; PROGRAM THE SIO CHIP CHANNEL
LD C,(IY+3) ; COMMAND PORT
@ -591,8 +631,8 @@ BROK:
#IF (INTMODE > 0)
;
; RESET THE RECEIVE BUFFER
LD E,(IY+6)
LD D,(IY+7) ; DE := _CNT
LD E,(IY+7)
LD D,(IY+8) ; DE := _CNT
XOR A ; A := 0
LD (DE),A ; _CNT = 0
INC DE ; DE := ADR OF _HD
@ -624,16 +664,16 @@ SIO_INITVALS:
#ELSE
.DB $01, $18 ; WR1: INTERRUPT ON ALL RECEIVE CHARACTERS
#ENDIF
.DB $02, IVT_SER0 ; WR2: INTERRUPT VECTOR OFFSET
.DB $02, IVT_SER0 ; WR2: IM2 INTERRUPT VECTOR OFFSET
.DB $03, $E1 ; WR3: 8 BIT RCV, CTS/DCD AUTO, RX ENABLE
.DB $05, $EA ; WR5: DTR, 8 BITS SEND, TX ENABLE, RTS 1 11 0 1 0 1 0 (1=DTR,11=8bits,0=sendbreak,1=TxEnable,0=sdlc,1=RTS,0=txcrc)
.DB $05, SIO_RTSON ; WR5: DTR, 8 BITS SEND, TX ENABLE, RTS 1 11 0 1 0 1 0 (1=DTR,11=8bits,0=sendbreak,1=TxEnable,0=sdlc,1=RTS,0=txcrc)
SIO_INITLEN .EQU $ - SIO_INITVALS
;
;
;
SIO_QUERY:
LD E,(IY+4) ; FIRST CONFIG BYTE TO E
LD D,(IY+5) ; SECOND CONFIG BYTE TO D
LD E,(IY+5) ; FIRST CONFIG BYTE TO E
LD D,(IY+6) ; SECOND CONFIG BYTE TO D
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
@ -646,21 +686,86 @@ SIO_DEVICE:
XOR A ; SIGNAL SUCCESS
RET
;
; SIO CHIP PROBE
; CHECK FOR PRESENCE OF SIO CHIPS AND POPULATE THE
; SIO_MAP BITMAP (ONE BIT PER CHIP). THIS DETECTS
; CHIPS, NOT CHANNELS. EACH CHIP HAS 2 CHANNELS.
; MAX OF TWO CHIPS CURRENTLY. INT VEC VALUE IS TRASHED!
;
SIO_PROBE:
; CLEAR THE PRESENCE BITMAP
LD HL,SIO_MAP ; HL POINTS TO BITMAP
XOR A ; ZERO
LD (SIO_MAP),A ; CLEAR CHIP PRESENT BITMAP
; INIT THE INT VEC REGISTER OF ALL POSSIBLE CHIPS
; TO ZERO. A IS STILL ZERO.
LD B,2 ; WR2 REGISTER (INT VEC)
LD C,SIO0B_CMD ; FIRST CHIP
CALL SIO_WR ; WRITE ZERO TO CHIP REG
#IF (SIOCNT >= 2)
LD C,SIO1B_CMD ; SECOND CHIP
CALL SIO_WR ; WRITE ZERO TO CHIP REG
#ENDIF
; FIRST POSSIBLE CHIP
LD C,SIO0B_CMD ; FIRST CHIP CMD/STAT PORT
CALL SIO_PROBECHIP ; PROBE IT
JR NZ,SIO_PROBE1 ; IF NOT ZERO, NOT FOUND
SET 0,(HL) ; SET BIT FOR FIRST CARD
SIO_PROBE1:
;
#IF (SIOCNT >= 2)
LD C,SIO1B_CMD ; SECOND CHIP CMD/STAT PORT
CALL SIO_PROBECHIP ; PROBE IT
JR NZ,SIO_PROBE2 ; IF NOT ZERO, NOT FOUND
SET 1,(HL) ; SET BIT FOR SECOND CARD
SIO_PROBE2:
#ENDIF
;
RET
;
SIO_PROBECHIP:
; READ WR2 TO ENSURE IT IS ZERO (AVOID PHANTOM PORTS)
CALL SIO_RD ; GET VALUE
AND $F0 ; ONLY TOP NIBBLE
RET NZ ; ABORT IF NOT ZERO
; WRITE INT VEC VALUE TO WR2
LD A,$FF ; TEST VALUE
CALL SIO_WR ; WRITE IT
; READ WR2 TO CONFIRM VALUE WRITTEN
CALL SIO_RD ; REREAD VALUE
AND $F0 ; ONLY TOP NIBBLE
CP $F0 ; COMPARE
RET ; DONE, Z IF FOUND, NZ IF MISCOMPARE
;
; READ/WRITE CHIP REGISTER. ENTER CHIP CMD/STAT PORT ADR IN C
; AND CHIP REGISTER NUMBER IN B. VALUE TO WRITE IN A OR VALUE
; RETURNED IN A.
;
SIO_WR:
OUT (C),B ; SELECT CHIP REGISTER
OUT (C),A ; WRITE VALUE
RET
;
SIO_RD:
OUT (C),B ; SELECT CHIP REGISTER
IN A,(C) ; GET VALUE
RET
;
; SIO DETECTION ROUTINE
;
SIO_DETECT:
LD C,(IY+3) ; COMMAND PORT
XOR A
OUT (C),A ; ACCESS RD0
IN A,(C) ; GET RD0 VALUE
LD B,A ; SAVE IT
LD A,1
OUT (C),A ; ACCESS RD1
IN A,(C) ; GET RD1 VALUE
CP B ; COMPARE
LD A,SIO_NONE ; ASSUME NOTHING THERE
RET Z ; RD0=RD1 MEANS NOTHING THERE
LD A,SIO_SIO ; GUESS WE HAVE A VALID SIO HERE
LD B,(IY+2) ; GET CHIP/CHANNEL
SRL B ; SHIFT AWAY THE CHANNEL BIT
INC B ; NUMBER OF TIMES TO ROTATE BITS
LD A,(SIO_MAP) ; BIT MAP IN A
SIO_DETECT1:
; ROTATE DESIRED CHIP BIT INTO CF
RRA ; ROTATE NEXT BIT INTO CF
DJNZ SIO_DETECT1 ; DO THIS UNTIL WE HAVE DESIRED BIT
; RETURN CHIP TYPE
LD A,SIO_NONE ; ASSUME NOTHING HERE
RET NC ; IF CF NOT SET, RETURN
LD A,SIO_SIO ; CHIP TYPE IS SIO
RET ; DONE
;
;
@ -692,8 +797,8 @@ SIO_PRTCFG:
RET Z ; IF ZERO, NOT PRESENT
;
PRTS(" MODE=$") ; FORMATTING
LD E,(IY+4) ; LOAD CONFIG
LD D,(IY+5) ; ... WORD TO DE
LD E,(IY+5) ; LOAD CONFIG
LD D,(IY+6) ; ... WORD TO DE
CALL PS_PRTSC0 ; PRINT CONFIG
;
XOR A
@ -711,51 +816,101 @@ SIO_STR_SIO .DB "SIO$"
; WORKING VARIABLES
;
SIO_DEV .DB 0 ; DEVICE NUM USED DURING INIT
SIO_MAP .DB 0 ; CHIP PRESENCE BITMAP
;
#IF (INTMODE == 0)
;
SIOA_RCVBUF .EQU 0
SIOB_RCVBUF .EQU 0
SIO0A_RCVBUF .EQU 0
SIO0B_RCVBUF .EQU 0
;
#IF (SIOCNT >= 2)
SIO1A_RCVBUF .EQU 0
SIO1B_RCVBUF .EQU 0
#ENDIF
;
#ELSE
;
; CHANNEL A RECEIVE BUFFER
SIOA_RCVBUF:
SIOA_CNT .DB 0 ; CHARACTERS IN RING BUFFER
SIOA_HD .DW SIOA_BUF ; BUFFER HEAD POINTER
SIOA_TL .DW SIOA_BUF ; BUFFER TAIL POINTER
SIOA_BUF .FILL 32,0 ; RECEIVE RING BUFFER
SIOA_BUFEND .EQU $ ; END OF BUFFER
SIOA_BUFSZ .EQU $ - SIOA_BUF ; SIZE OF RING BUFFER
; SIO0 CHANNEL A RECEIVE BUFFER
SIO0A_RCVBUF:
SIO0A_CNT .DB 0 ; CHARACTERS IN RING BUFFER
SIO0A_HD .DW SIO0A_BUF ; BUFFER HEAD POINTER
SIO0A_TL .DW SIO0A_BUF ; BUFFER TAIL POINTER
SIO0A_BUF .FILL SIO_BUFSZ,0 ; RECEIVE RING BUFFER
;
; SIO0 CHANNEL B RECEIVE BUFFER
SIO0B_RCVBUF:
SIO0B_CNT .DB 0 ; CHARACTERS IN RING BUFFER
SIO0B_HD .DW SIO0B_BUF ; BUFFER HEAD POINTER
SIO0B_TL .DW SIO0B_BUF ; BUFFER TAIL POINTER
SIO0B_BUF .FILL SIO_BUFSZ,0 ; RECEIVE RING BUFFER
;
#IF (SIOCNT >= 2)
;
; SIO1 CHANNEL A RECEIVE BUFFER
SIO1A_RCVBUF:
SIO1A_CNT .DB 0 ; CHARACTERS IN RING BUFFER
SIO1A_HD .DW SIO1A_BUF ; BUFFER HEAD POINTER
SIO1A_TL .DW SIO1A_BUF ; BUFFER TAIL POINTER
SIO1A_BUF .FILL SIO_BUFSZ,0 ; RECEIVE RING BUFFER
;
; SIO1 CHANNEL B RECEIVE BUFFER
SIO1B_RCVBUF:
SIO1B_CNT .DB 0 ; CHARACTERS IN RING BUFFER
SIO1B_HD .DW SIO1B_BUF ; BUFFER HEAD POINTER
SIO1B_TL .DW SIO1B_BUF ; BUFFER TAIL POINTER
SIO1B_BUF .FILL SIO_BUFSZ,0 ; RECEIVE RING BUFFER
;
; CHANNEL B RECEIVE BUFFER
SIOB_RCVBUF:
SIOB_CNT .DB 0 ; CHARACTERS IN RING BUFFER
SIOB_HD .DW SIOB_BUF ; BUFFER HEAD POINTER
SIOB_TL .DW SIOB_BUF ; BUFFER TAIL POINTER
SIOB_BUF .FILL 32,0 ; RECEIVE RING BUFFER
SIOB_BUFEND .EQU $ ; END OF BUFFER
SIOB_BUFSZ .EQU $ - SIOB_BUF ; SIZE OF RING BUFFER
#ENDIF
;
#ENDIF
;
; SIO PORT TABLE
;
SIO_CFG:
; SIO CHANNEL A
; SIO0 CHANNEL A
SIO0A_CFG:
.DB 0 ; DEVICE NUMBER (SET DURING INIT)
.DB 0 ; SIO TYPE (SET DURING INIT)
.DB 0 ; SIO CHANNEL (A)
.DB SIOA_CMD ; BASE PORT (CMD PORT)
.DW DEFSIOACFG ; LINE CONFIGURATION
.DW SIOA_RCVBUF ; POINTER TO RCV BUFFER STRUCT
.DB $00 ; CHIP 0 / CHANNEL A (LOW BIT IS CHANNEL)
.DB SIO0A_CMD ; CMD/STATUS PORT
.DB SIO0A_DAT ; DATA PORT
.DW DEFSIO0ACFG ; LINE CONFIGURATION
.DW SIO0A_RCVBUF ; POINTER TO RCV BUFFER STRUCT
;
; SIO CHANNEL B
SIO_CFGSIZ .EQU $ - SIO_CFG ; SIZE OF ONE CFG TABLE ENTRY
;
; SIO0 CHANNEL B
SIO0B_CFG:
.DB 0 ; DEVICE NUMBER (SET DURING INIT)
.DB 0 ; SIO TYPE (SET DURING INIT)
.DB 1 ; SIO CHANNEL (B)
.DB SIOB_CMD ; BASE PORT (CMD PORT)
.DW DEFSIOBCFG ; LINE CONFIGURATION
.DW SIOB_RCVBUF ; POINTER TO RCV BUFFER STRUCT
.DB $01 ; CHIP 0 / CHANNEL B (LOW BIT IS CHANNEL)
.DB SIO0B_CMD ; CMD/STATUS PORT
.DB SIO0B_DAT ; DATA PORT
.DW DEFSIO0BCFG ; LINE CONFIGURATION
.DW SIO0B_RCVBUF ; POINTER TO RCV BUFFER STRUCT
;
#IF (SIOCNT >= 2)
;
; SIO1 CHANNEL A
SIO1A_CFG:
.DB 0 ; DEVICE NUMBER (SET DURING INIT)
.DB 0 ; SIO TYPE (SET DURING INIT)
.DB $02 ; CHIP 1 / CHANNEL A (LOW BIT IS CHANNEL)
.DB SIO1A_CMD ; CMD/STATUS PORT
.DB SIO1A_DAT ; DATA PORT
.DW DEFSIO1ACFG ; LINE CONFIGURATION
.DW SIO1A_RCVBUF ; POINTER TO RCV BUFFER STRUCT
;
; SIO1 CHANNEL B
SIO1B_CFG:
.DB 0 ; DEVICE NUMBER (SET DURING INIT)
.DB 0 ; SIO TYPE (SET DURING INIT)
.DB $03 ; CHIP 1 / CHANNEL B (LOW BIT IS CHANNEL)
.DB SIO1B_CMD ; CMD/STATUS PORT
.DB SIO1B_DAT ; DATA PORT
.DW DEFSIO1BCFG ; LINE CONFIGURATION
.DW SIO1B_RCVBUF ; POINTER TO RCV BUFFER STRUCT
;
#ENDIF
;
SIO_CNT .EQU ($ - SIO_CFG) / 8
SIO_CFGCNT .EQU ($ - SIO_CFG) / SIO_CFGSIZ

5
Source/HBIOS/spk.asm

@ -9,7 +9,7 @@ SPK_INIT:
LD A,DSRTC_BASE
CALL PRTHEXBYTE
CALL SPK_BEEP
XOR A
XOR A
RET
;
SPK_BEEP:
@ -17,7 +17,8 @@ SPK_BEEP:
PUSH HL
LD HL,400 ; CYCLES OF TONE
;LD B,%00000100 ; D2 MAPPED TO Q0
LD A,DSRTC_RESET
;LD A,DSRTC_RESET
LD A,(RTCVAL) ; GET RTC PORT VALUE FROM SHADOW
OR %00000100 ; D2 MAPPED TO Q0
LD B,A
SPK_BEEP1:

Loading…
Cancel
Save