From b8a0515791e37ccffb34695c7049cd05147c47bf Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 23 May 2021 18:40:21 +0800 Subject: [PATCH 01/13] Create I2C directory. Add i2cscan --- Source/Apps/Build.cmd | 2 +- Source/Apps/I2C/Build.cmd | 14 + Source/Apps/I2C/Clean.cmd | 5 + Source/Apps/I2C/I2CSCAN.ASM | 527 +++++++++++++++++++++++++++++++ Source/Apps/I2C/Makefile | 12 + Source/Apps/{ => I2C}/RTCds7.asm | 88 +++++- Source/Apps/Makefile | 2 +- Source/Apps/RTChb.asm | 94 +++++- 8 files changed, 729 insertions(+), 15 deletions(-) create mode 100644 Source/Apps/I2C/Build.cmd create mode 100644 Source/Apps/I2C/Clean.cmd create mode 100644 Source/Apps/I2C/I2CSCAN.ASM create mode 100644 Source/Apps/I2C/Makefile rename Source/Apps/{ => I2C}/RTCds7.asm (86%) diff --git a/Source/Apps/Build.cmd b/Source/Apps/Build.cmd index d9c389ff..dc97b94d 100644 --- a/Source/Apps/Build.cmd +++ b/Source/Apps/Build.cmd @@ -20,7 +20,6 @@ call :asm Mode || goto :eof call :asm RTC || goto :eof call :asm Timer || goto :eof call :asm180 IntTest || goto :eof -call :asm rtcds7 || goto :eof call :asm rtchb || goto :eof zx Z80ASM -SYSGEN/F @@ -32,6 +31,7 @@ setlocal & cd XM && call Build || exit /b 1 & endlocal setlocal & cd FDU && call Build || exit /b 1 & endlocal setlocal & cd Tune && call Build || exit /b 1 & endlocal setlocal & cd FAT && call Build || exit /b 1 & endlocal +setlocal & cd I2C && call Build || exit /b 1 & endlocal copy *.com %APPBIN%\ diff --git a/Source/Apps/I2C/Build.cmd b/Source/Apps/I2C/Build.cmd new file mode 100644 index 00000000..4ddbf8b2 --- /dev/null +++ b/Source/Apps/I2C/Build.cmd @@ -0,0 +1,14 @@ +@echo off +setlocal + +set TOOLS=../../../Tools +set PATH=%TOOLS%\tasm32;%PATH% +set TASMTABS=%TOOLS%\tasm32 + +tasm -t180 -g3 -fFF i2cscan.asm i2cscan.com i2cscan.lst +tasm -t180 -g3 -fFF rtcds7.asm rtcds7.com rtcds7.lst + +if errorlevel 1 goto :eof + +copy /Y i2cscan*.com ..\..\..\Binary\Apps\ +copy /Y rtcds7*.com ..\..\..\Binary\Apps\ diff --git a/Source/Apps/I2C/Clean.cmd b/Source/Apps/I2C/Clean.cmd new file mode 100644 index 00000000..07f1d4c3 --- /dev/null +++ b/Source/Apps/I2C/Clean.cmd @@ -0,0 +1,5 @@ +@echo off +setlocal + +if exist *.com del *.com +if exist *.lst del *.lst diff --git a/Source/Apps/I2C/I2CSCAN.ASM b/Source/Apps/I2C/I2CSCAN.ASM new file mode 100644 index 00000000..ff8bc356 --- /dev/null +++ b/Source/Apps/I2C/I2CSCAN.ASM @@ -0,0 +1,527 @@ + + .ECHO "I2CSCAN"/N + +; I2C BUS SCANNER +; +_io .equ 0A0h +_sda .equ 0 +_scl .equ 1 +_idle .equ 00000011B + +; +;----------------------------------------------------------------------------- +; +PCF_BASE .EQU 0F0H +PCF_ID .EQU 0AAH +CPU_CLK .EQU 12 +; +PCF_RS0 .EQU PCF_BASE +PCF_RS1 .EQU PCF_RS0+1 +PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE + + .org 100h + + ld sp,stack + + ld hl,signon + call _strout + + ld c,' ' + call _cout + call _cout + call _cout + + + +; display x axis header 00-0F + + xor a + ld (x),a + ld b, 16 +lp1: ld c,' ' + call _cout + ld a,(x) + ld c,a + inc a + ld (x),a + call _hexout + djnz lp1 + call _eolout + +; start of line loop 00-07 + + xor a ; display + ld (y),a ; y-axis + ld (addr),a ; prefix + ld d,8 +lp3b: ld a,(y) + ld c,a + add a,10h + ld (y),a + call _hexout + ld c,':' + call _cout + +; set up x axis loop + + xor a + ld (x),a + ld e,16 +lp2b: push de + + ld c,' ' + call _cout + +; i2c challenge +; . issue device start command +; . write address to device +; . issue device stop command. +; . delay +; . display response + +; call _i2c_start +; ld a,(addr) +; ld c,a +; call _i2c_write +; ld (rc),a +; call _i2c_stop + + CALL PCF_WAIT_FOR_BB + JP NZ,PCF_BBERR +; + LD A,(addr) + OUT (PCF_RS0),A + CALL PCF_START ; GENERATE START CONDITION +; + ld bc,100 ; delay +lp6: nop + dec bc + ld a,c + or b + jr nz,lp6 + + CALL PCF_WAIT_FOR_ACK; AND ISSUE THE SLAVE ADDRESS + or a + jp nz,lp4f + + ld c,'-' ; display no + call _cout ; response + call _cout + jp lp5f + +lp4f: ld a,(addr) ; adjust address + ld c,a ; and display it + srl c + call _hexout + +lp5f: ld a,(addr) ; next address + add a,2 ; adjust for + ld (addr),a ; 7-bit + + CALL PCF_STOP + + pop de ; check if + dec e ; reached end + jp nz,lp2b ; of line + call _eolout + + dec d ; loop until + jp nz,lp3b ; all done + + jp 0 + +signon: .db "I2C Bus Scanner" + .db 13, 10, 13, 10, 0, "$" + +_strout: +st1: ld a,(hl) ; display + CP '$' ; zero + ret z ; terminated + ld c,a ; string + call _cout + inc hl + jp st1 + +_hexout: ; display + ld a,c ; A in hex + srl a + srl a + srl a + srl a + add a,30h + cp 3Ah + jp c,h1 + add a,7 +h1: ld h,a + ld a,c + and 0Fh + add a,30h + cp 3Ah + jp c,h2 + add a,7 +h2: ld l,a + ld c,h + call _cout + ld c,l + call _cout + ret + +_eolout: ; newline + ld c,13 + call _cout + ld c,10 + call _cout + ret + +_cout: ; character + push af ; output + push bc + push de + push hl + ld e,c + ld c,02h + call 5 + pop hl + pop de + pop bc + pop af + ret + +;----------------------------------------------------------------------------- +_i2c_start: +PCF_START: + LD A,PCF_START_ + OUT (PCF_RS1),A + RET +; +;_i2c_start: + ld a,_idle ; issue + out (_io),a ; start + ; command + res _sda,a + out (_io),a + nop + nop + res _scl,a + out (_io),a + + ld (oprval),a + ret + +; +;----------------------------------------------------------------------------- +; +; CONTROL REGISTER BITS +; +PCF_PIN .EQU 10000000B +PCF_ES0 .EQU 01000000B +PCF_ES1 .EQU 00100000B +PCF_ES2 .EQU 00010000B +PCF_EN1 .EQU 00001000B +PCF_STA .EQU 00000100B +PCF_STO .EQU 00000010B +PCF_ACK .EQU 00000001B +; +; STATUS REGISTER BITS +; +;PCF_PIN .EQU 10000000B +PCF_INI .EQU 01000000B ; 1 if not initialized +PCF_STS .EQU 00100000B +PCF_BER .EQU 00010000B +PCF_AD0 .EQU 00001000B +PCF_LRB .EQU 00001000B +PCF_AAS .EQU 00000100B +PCF_LAB .EQU 00000010B +PCF_BB .EQU 00000001B +; +PCF_START_ .EQU (PCF_PIN | PCF_ES0 | PCF_STA | PCF_ACK) +PCF_STOP_ .EQU (PCF_PIN | PCF_ES0 | PCF_STO | PCF_ACK) +; +; TIMEOUT AND DELAY VALUES (ARBITRARY) +; +PCF_PINTO .EQU 65000 +PCF_ACKTO .EQU 65000 +PCF_BBTO .EQU 65000 +PCF_LABDLY .EQU 65000 +; +;----------------------------------------------------------------------------- +; +; RETURN A=00/Z IF SUCCESSFULL +; RETURN A=FF/NZ IF TIMEOUT +; RETURN A=01/NZ IF LOST ARBITRATION +; PCF_STATUS HOLDS LAST PCF STATUS +; +PCF_WAIT_FOR_PIN: + PUSH HL + LD HL,PCF_PINTO ; SET TIMEOUT VALUE + +PCF_WFP0: + IN A,(PCF_RS1) ; GET BUS + LD (PCF_STATUS),A ; STATUS + LD B,A + + DEC HL ; HAVE WE + LD A,H ; TIMED OUT + OR L + JR Z,PCF_WFP1 ; YES WE HAVE, GO ACTION IT + + LD A,B ; + AND PCF_PIN ; IS TRANSMISSION COMPLETE? + JR NZ,PCF_WFP0 ; KEEP ASKING IF NOT OR + POP HL ; YES COMPLETE (PIN=0) RETURN WITH ZERO + RET +PCF_WFP1: + LD A,B ; DID WE LOSE ARBITRATION? + AND PCF_LAB ; IF A=0 THEN NO + CPL + JR NZ,PCF_WFP2 ; NO + CALL PCF_HANDLE_LAB ; YES GO HANDLE IT + LD (PCF_STATUS),A + XOR A ; RETURN NZ, A=01H + INC A +PCF_WFP2: + POP HL ; RET NZ, A=FF IF TIMEOUT + RET +; +PCF_STATUS .DB 00H + +;-------------------------------------------------------------------------------- +; +; RETURN NZ/FF IF TIMEOUT ERROR +; RETURN NZ/01 IF FAILED TO RECEIVE ACKNOWLEDGE +; RETURN Z/00 IF RECEIVED ACKNOWLEDGE +; +PCF_WAIT_FOR_ACK: + PUSH HL + LD HL,PCF_ACKTO +; +PCF_WFA0: + IN A,(PCF_RS1) ; READ PIN + LD (PCF_STATUS),A ; STATUS + LD B,A +; + DEC HL ; SEE IF WE HAVE TIMED + LD A,H ; OUT WAITING FOR PIN + OR L ; EXIT IF + JR Z,PCF_WFA1 ; WE HAVE +; + LD A,B ; OTHERWISE KEEP LOOPING + AND PCF_PIN ; UNTIL WE GET PIN + JR NZ,PCF_WFA0 ; OR TIMEOUT +; + LD A,B ; WE GOT PIN SO NOW + AND PCF_LRB ; CHECK WE HAVE + LD A,1 + JR Z,PCF_WFA2 ; RECEIVED ACKNOWLEDGE + XOR A + JR PCF_WFA2 +PCF_WFA1: + CPL ; TIMOUT ERROR +PCF_WFA2: + POP HL ; EXIT WITH NZ = FF + RET +; +;----------------------------------------------------------------------------- +; +; POLL THE BUS BUSY BIT TO DETERMINE IF BUS IS FREE. +; RETURN WITH A=00H/Z STATUS IF BUS IS FREE +; RETURN WITH A=FFH/NZ STATUS IF BUS +; +; AFTER RESET THE BUS BUSY BIT WILL BE SET TO 1 I.E. NOT BUSY +; +PCF_WAIT_FOR_BB: + LD HL,PCF_BBTO +PCF_WFBB0: + IN A,(PCF_RS1) + AND PCF_BB + RET Z ; BUS IS FREE RETURN ZERO + DEC HL + LD A,H + OR L + JR NZ,PCF_WFBB0 ; REPEAT IF NOT TIMED OUT + CPL ; RET NZ IF TIMEOUT + RET +; +;----------------------------------------------------------------------------- +PCF_HANDLE_LAB: +; + LD A,PCF_PIN + OUT (PCF_RS1),A + LD A,PCF_ES0 + OUT (PCF_RS1),A +; + LD HL,PCF_LABDLY +PCF_LABLP: + LD A,H + OR L + DEC HL + JR NZ,PCF_LABLP +; + IN A,(PCF_RS1) + RET +; +;----------------------------------------------------------------------------- +; DISPLAY ERROR MESSAGES +; +PCF_RDERR: + PUSH HL + LD HL,PCF_RDFAIL + JR PCF_PRTERR +; +PCF_INIERR: + PUSH HL + LD HL,PCF_NOPCF + JR PCF_PRTERR +; +PCF_SETERR: + PUSH HL + LD HL,PCF_WRTFAIL + JR PCF_PRTERR +; +PCF_REGERR: + PUSH HL + LD HL,PCF_REGFAIL + JR PCF_PRTERR +; +PCF_CLKERR: + PUSH HL + LD HL,PCF_CLKFAIL + JR PCF_PRTERR +; +PCF_IDLERR: + PUSH HL + LD HL,PCF_IDLFAIL + JR PCF_PRTERR +; +PCF_ACKERR: + PUSH HL + LD HL,PCF_ACKFAIL + JR PCF_PRTERR +; +PCF_RDBERR: + PUSH HL + LD HL,PCF_RDBFAIL + JR PCF_PRTERR +; +PCF_TOERR: + PUSH HL + LD HL,PCF_TOFAIL + JR PCF_PRTERR +; +PCF_ARBERR: + PUSH HL + LD HL,PCF_ARBFAIL + JR PCF_PRTERR +; +PCF_PINERR: + PUSH HL + LD HL,PCF_PINFAIL + JR PCF_PRTERR +; +PCF_BBERR: + PUSH HL + LD HL,PCF_BBFAIL + JR PCF_PRTERR +; +PCF_PRTERR: + CALL _strout + CALL _eolout + POP HL + RET +; +; +PCF_NOPCF .DB "NO DEVICE FOUND$" +PCF_WRTFAIL .DB "SETTING DEVICE ID FAILED$" +PCF_REGFAIL .DB "CLOCK REGISTER SELECT ERROR$" +PCF_CLKFAIL .DB "CLOCK SET FAIL$" +PCF_IDLFAIL .DB "BUS IDLE FAILED$" +PCF_ACKFAIL .DB "FAILED TO RECEIVE ACKNOWLEDGE$" +PCF_RDFAIL .DB "READ FAILED$" +PCF_RDBFAIL .DB "READBYTES FAILED$" +PCF_TOFAIL .DB "TIMEOUT ERROR$" +PCF_ARBFAIL .DB "LOST ARBITRATION$" +PCF_PINFAIL .DB "PIN FAIL$" +PCF_BBFAIL .DB "BUS BUSY$" +; +;----------------------------------------------------------------------------- +_i2c_stop: +PCF_STOP: + LD A,PCF_STOP_ ; issue + OUT (PCF_RS1),A ; stop + RET ; command + +;_i2c_stop: + ld a,(oprval) + res _scl,a + res _sda,a + out (_io),a + + set _scl,a + out (_io),a + nop + nop + set _sda,a + out (_io),a + + ld (oprval),a + ret + +_i2c_write: ; write + ld a,(oprval) ; to i2c + ; bus + ld b,8 +i2c1: res _sda,a + rl c + jr nc,i2c2 + set _sda,a +i2c2: out (_io),a + set _scl,a + out (_io),a + +; COND SC126=0 +; ld d,a +;i2c3: in a,(_io) +; bit _scl,a +; jr z,i2c3 +; ld a,d +; ENDC + + res _scl,a + out (_io),a + djnz i2c1 + + set _sda,a + out (_io),a + set _scl,a + out (_io),a + + ld d,a +i2c4: in a,(_io) +; COND SC126=0 +; bit _scl,a +; jr z,4b +; ENDC + ld c,a + ld a,d + + res _scl,a + out (_io),a + ld (oprval),a + + xor a + bit _sda,c + ret z + inc a + + ret + + +oprval: .db 0 +x: .db 0 +y: .db 0 +addr: .db 0 +rc: .db 0 + + .fill 128 +stack: + .end diff --git a/Source/Apps/I2C/Makefile b/Source/Apps/I2C/Makefile new file mode 100644 index 00000000..8cc30294 --- /dev/null +++ b/Source/Apps/I2C/Makefile @@ -0,0 +1,12 @@ +OBJECTS = I2CSCAN.COM +DEST = ../../../Binary/Apps +TOOLS = ../../../Tools + +include $(TOOLS)/Makefile.inc + +DEPS := I2CSCAN.ASM $(shell find . -name '*.inc') + +I2CSCAN.COM: $(DEPS) + $(TASM) -dWBW I2CSCAN.ASM I2CSCAN.COM I2CSCAN.LST + + diff --git a/Source/Apps/RTCds7.asm b/Source/Apps/I2C/RTCds7.asm similarity index 86% rename from Source/Apps/RTCds7.asm rename to Source/Apps/I2C/RTCds7.asm index a2ac01e5..c99d7123 100644 --- a/Source/Apps/RTCds7.asm +++ b/Source/Apps/I2C/RTCds7.asm @@ -6,9 +6,12 @@ PCF_BASE .EQU 0F0H PCF_ID .EQU 0AAH CPU_CLK .EQU 12 +PCF_RS0 .EQU PCF_BASE +PCF_RS1 .EQU PCF_RS0+1 +PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE + REGS0 .EQU PCF_BASE REGS1 .EQU REGS0+1 -PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE ; ;T4LC512D .EQU 10100000B ; DEVICE IDENTIFIER ;T4LC512A1 .EQU 00000000B ; DEVICE ADDRESS @@ -103,15 +106,94 @@ DS7_READ .EQU (DS7_DS1307 | DS7_R) ; READ DS7_WRITE .EQU (DS7_DS1307 | DS7_W) ; WRITE ; DS7_CTL .EQU (DS7_OUT | DS7_SQWE | DS7_RATE) +; +CLIARGS .EQU $81 +RESTART .EQU $0000 ; CP/M restart vector +BDOS .EQU $0005 ; BDOS invocation vector +FCB .EQU $5C ; Location of default FCB ; .ORG 100H ; +DS7_START: + CALL DS7_PROBE ; PROBE FRO DEVICE + RET Z ; EXIT IF DEVICE NOT FOUND +; + LD A,(FCB+1) ; GET FIRST CHAR + CP ' ' ; COMPARE TO BLANK. IF SO NO + JR Z,DS7_ST0 ; ARGUMENTS SO DISLAY TIME AND DATE +; + LD A,(FCB+1) ; GET FIRST CHAR + CP '/' ; IS IT INDICATING AN ARGUMENT + JR NZ,DS7_ST0 ; +; + LD A,(FCB+2) ; GET NEXT CHARACTER + CP 'D' ; + JR NZ,DS7_ST1 ; +; +; /D SET DATE +; + RET +; +DS7_ST1: + LD A,(FCB+2) ; GET NEXT CHARACTER + CP 'T' ; + JR NZ,DS7_ST2 ; +; +; /T SET TIME +; + RET +; +DS7_ST2: + LD A,(FCB+2) ; GET NEXT CHARACTER + CP 'S' ; + JR NZ,DS7_ST3 ; +; +; /S SET TIME AND DATE +; + RET +; +DS7_ST3: +; +; UNREGOGNIZED ARGUMENT ; + RET +; +DS7_ST0: CALL DS7_RDC ; READ CLOCK DATA INTO BUFFER CALL DS7_DISP ; DISPLAY TIME AND DATE FROM BUFFER RET ; ;----------------------------------------------------------------------------- +; RETURN 00/Z IF NOT FOUND +; NZ IF FOUND +; +; +DS7_PROBE: + LD A,PCF_PIN ; SET PIN BIT + OUT (PCF_RS1),A + NOP + IN A,(PCF_RS1) ; CHECK IF SET + AND 07FH + JR NZ,DS7_PR0 ; ERROR IF NOT SET + + LD A,'%' + CALL COUT + + OR 0FFH ; SUCCESS + RET + +DS7_PR0: + LD A,PCF_OWN ; LOAD OWN ADDRESS IN S0, + OUT (PCF_RS0),A ; EFFECTIVE ADDRESS IS (OWN <<1) + + LD A,PCF_IDLE_ + OUT (PCF_RS1),A + + CALL PCF_INIERR ; DISLAY ERROR + XOR A ; SET ERROR + RET +; +;----------------------------------------------------------------------------- ; RTC READ ; ; 1. ISSUE SLAVE ADDRESS WITH START CONDITION AND WRITE STATUS @@ -572,7 +654,7 @@ PCF_BBFAIL .DB "BUS BUSY$" ; ;----------------------------------------------------------------------------- ; -BDOS .EQU 5 ;ENTRY BDOS +;BDOS .EQU 5 ;ENTRY BDOS BS .EQU 8 ;BACKSPACE TAB .EQU 9 ;TABULATOR LF .EQU 0AH ;LINE-FEED @@ -581,7 +663,7 @@ CR .EQU 0DH ;CARRIAGE-RETURN ; OUTPUT TEXT AT HL ; PRTSTR: LD A,(HL) - OR A + CP '$' RET Z CALL PRINP INC HL diff --git a/Source/Apps/Makefile b/Source/Apps/Makefile index dd0ae956..bf58bc14 100644 --- a/Source/Apps/Makefile +++ b/Source/Apps/Makefile @@ -2,7 +2,7 @@ OBJECTS = SysGen.com Survey.com \ SysCopy.com Assign.com Format.com Talk.com Mode.com RTC.com \ Timer.com IntTest.com RTCds7.com RTChb.com OTHERS = *.hex *.com -SUBDIRS = XM FDU FAT Tune +SUBDIRS = XM FDU FAT Tune I2C DEST = ../../Binary/Apps TOOLS =../../Tools diff --git a/Source/Apps/RTChb.asm b/Source/Apps/RTChb.asm index cf4669bf..6103b551 100644 --- a/Source/Apps/RTChb.asm +++ b/Source/Apps/RTChb.asm @@ -3,24 +3,104 @@ ;================================================================================================== ; ; HBIOS FORMAT = YYMMDDHHMMSS +; +;----------------------------------------------------------------------------- +; GENERIC CP/M STUFF +; +BS .EQU 8 ; BACKSPACE +TAB .EQU 9 ; TABULATOR +LF .EQU 0AH ; LINE-FEED +CR .EQU 0DH ; CARRIAGE-RETURN +CLIARGS .EQU $81 +RESTART .EQU $0000 ; CP/M restart vector +BDOS .EQU $0005 ; BDOS invocation vector +FCB .EQU $5C ; Location of default FCB +; +;----------------------------------------------------------------------------- ; .ORG 100H ; +HBC_START: + LD A,(FCB+1) ; GET FIRST CHAR + CP ' ' ; COMPARE TO BLANK. IF SO NO + JR Z,HBC_ST0 ; ARGUMENTS SO DISLAY TIME AND DATE +; + LD A,(FCB+1) ; GET FIRST CHAR + CP '/' ; IS IT INDICATING AN ARGUMENT + JR NZ,HBC_ST0 ; +; + LD A,(FCB+2) ; GET NEXT CHARACTER + CP 'D' ; + JR NZ,HBC_ST1 ; +; +; /D SET DATE DDMMYY +; + LD B,$21 ; WRITE CLOCK DATA INTO BUFFER + LD HL,HBC_BUF1 + RST 08 +; + LD HL,FCB+3 +; + LD A,(HL) + CP 0 +; JP HBC_ST4 ; EXIT IF END OF BUFFER + LD B,6 + + + + + JP HBC_ST0 +; +HBC_ST1: + LD A,(FCB+2) ; GET NEXT CHARACTER + CP 'T' ; + JR NZ,HBC_ST2 ; +; +; /T SET TIME HHMMSS +; + LD B,$21 ; WRITE CLOCK DATA INTO BUFFER + LD HL,HBC_BUF1 + RST 08 + JP HBC_ST0 +; +HBC_ST2: + LD A,(FCB+2) ; GET NEXT CHARACTER + CP 'S' ; + JR NZ,HBC_ST3 ; +; +; /S SET TIME AND DATE +; + JP HBC_ST0 ; - LD B,$20 ; READ CLOCK DATA INTO BUFFER - LD HL,HBC_BUF ; DISPLAY TIME AND DATE FROM BUFFER +HBC_ST3: +; +; UNREGOGNIZED ARGUMENT +; + RET +; +HBC_ST0: + LD B,$20 ; READ CLOCK DATA INTO BUFFER + LD HL,HBC_BUF RST 08 ; #IF (0) LD A,6 - LD DE,HBC_BUF ; DISLAY DATA READ + LD DE,HBC_BUF ; DISLAY DATA READ ; CALL PRTHEXBUF CALL NEWLINE #ENDIF ; CALL HBC_DISP RET - +; +HBC_BUF1: + .DB 099H + .DB 011H + .DB 022H + .DB 008H + .DB 031H + .DB 000H +; HBC_BUF .FILL 6,0 ; ;----------------------------------------------------------------------------- @@ -87,12 +167,6 @@ HBC_FAIL .DB "ERROR$" ;----------------------------------------------------------------------------- ; GENERIC CP/M ROUTINES ; -BDOS .EQU 5 ;ENTRY BDOS -BS .EQU 8 ;BACKSPACE -TAB .EQU 9 ;TABULATOR -LF .EQU 0AH ;LINE-FEED -CR .EQU 0DH ;CARRIAGE-RETURN -; ; OUTPUT TEXT AT HL ; PRTSTR: LD A,(HL) From ef71aa74604cc329d5f034a7e356e92247676e09 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Fri, 2 Jul 2021 15:30:56 +0800 Subject: [PATCH 02/13] Initial ecb-dma support --- Binary/RCZ80_std.upd | Bin 0 -> 131072 bytes Binary/SBC_std.upd | Bin 0 -> 131072 bytes Source/HBIOS/cfg_dyno.asm | 4 + Source/HBIOS/cfg_ezz80.asm | 4 + Source/HBIOS/cfg_master.asm | 4 + Source/HBIOS/cfg_mk4.asm | 4 + Source/HBIOS/cfg_n8.asm | 4 + Source/HBIOS/cfg_rcz180.asm | 4 + Source/HBIOS/cfg_rcz280.asm | 4 + Source/HBIOS/cfg_rcz80.asm | 4 + Source/HBIOS/cfg_sbc.asm | 4 + Source/HBIOS/cfg_scz180.asm | 4 + Source/HBIOS/cfg_zeta.asm | 4 + Source/HBIOS/cfg_zeta2.asm | 5 + Source/HBIOS/dma.asm | 198 ++++++++++++++++++++++++++++++++++++ Source/HBIOS/hbios.asm | 11 ++ Source/HBIOS/md.asm | 14 ++- Source/HBIOS/rf.asm | 17 +++- Source/HBIOS/std.asm | 8 ++ 19 files changed, 292 insertions(+), 5 deletions(-) create mode 100644 Binary/RCZ80_std.upd create mode 100644 Binary/SBC_std.upd create mode 100644 Source/HBIOS/dma.asm diff --git a/Binary/RCZ80_std.upd b/Binary/RCZ80_std.upd new file mode 100644 index 0000000000000000000000000000000000000000..2890b61dfc6fa891de363ae59de6c73f91170ed7 GIT binary patch literal 131072 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 Z01+SpM1Tko0U|&IhyW2F0*{fvzX8;h3U2@a literal 0 HcmV?d00001 diff --git a/Binary/SBC_std.upd b/Binary/SBC_std.upd new file mode 100644 index 0000000000000000000000000000000000000000..6c9791fbb4632db6790cbeb0653c771ab26e231a GIT binary patch literal 131072 zcmeFa3s_Xw)i-`-fWt)?X28n<44#2eM-&`KQ5=WiHrzyJ5KyBg0xGBp3IP-lB$!4_ zqfwK-?VGgk*P1qInxt>BO%sxsT3~|ZfG2{A8m)=MKw`|885Pv%ocaIunL#mWzxH|B z?|J{<_b_nwW$m@sUVH7e_u2PjQF)b9PN&migMlCCvi@n?js6cTYw8HXwznnTjnvE3 ztCZ`PYtCMgyn@{}H)c-Eoapk3;+VL(vskT0J11JRAX=lP5K8@Rq?EGq+KNpZHde9f zlo=$7W){1msCG*+%!;aw#am{v>853Ddd?D%Cwcr^Ka0w1#c$@wB|eE$KU0`PdGUXw0UOfwJK?v_p(sv! z(Rs4wWIbnHF=VY=Bg{ESVhnX$k|a_s*5o+)5?>-P_7>~nOKl&P2zElo>9l`VEZpHb z`V_$aoRG2}>TMfP!uN&C*UxG93l}2(Lm<-EFu*YLl2eGqW@j%W zQISc0DT$nw%%TMb&I6F7Y=T7lDqf($XH%BLZVksK40Elt)A%O(3t}yfC=j& z-_k6DjUYdFkrvo3tu!l-~D&lmh>C zDG{Q9zHXv{z98!3@qpNC1_QftedD`+g6DtXc@58h<9Q!X2cAwm$ML-D7vD9A=L#O1 zUwo}Vse=WH`XNE8o*{UswQfy}`Y;FeTbW2jNT_Cxf6SLO2luMNb>gGMigDY?Ddclv zB+cA_vftV8gt@<&!)w^w%+*1{+fiZ>Upf&O^`-Mt8$S%EMdD8q5n4DT-nHIOkaRuf zC&;_%`~*eUPCtR|dd5#k?D~ssaK=399*hyO*oOxw&UyNOHJm18v?)q)*eprp*YIslBK721G?3_f4@ zCd$L*fSr@9(0wc^fJ>lZcGrEl&5zVW%YXZ!5*Bc}A9({z^dFFLO81ISi&`=n=Z1@zy3+tcgJ{A=SJ1HH&-k2*x?g_JLry!byohf;U>Yy7%Hldf&EiEt4kcr%`1J$}0rHe&bpj zB1_63csSM4{?-BFz0}+GL}dAuW^PDl$%)rma*n-1+d0c4<19~%Ba-9Nm0dZpEN#$M z^DD;zl%quA&6lJRW(FKvq>d7gOAcs^J8#6g+rrIk7}C!? zf>t21Ix^my;CDcG-b}Z15lR025h?xyQAz%N3QsB|ZklyG>&Y1m9A>pWIsBCX?KxR1A0kuxE5DNQ?*%9?$oO?K zlq!n174HIM(3qE-pQ2;4&BoMt^1{i>Hxi4@G{7HfZ~aagi9G65|tMT#)tih77&-GZ`m)9;ws~+Ju9gYzqHGK%Mry?5eW>?wtW5 zKu7$C4U}4HKyUxNOboHNaI&3Z#71r<|BQ@(N5-F$aec(y%l}ODEbWu+3#a&KS?^*P za5uu@!v72u+PecWDkIzEH!Y`R;rjprrWh^!h%0;zyd)g4ekKDFROn zXrIAP2mcIjZ`!2puqh|YhZ9AQ{3|Y;qJ4&0ci_S?TtbI|@QS0sPt$ay=+AuKS=;tE?d)pihk`}d3hvebF4~J>I1J9!-O_w{W zB`uxG7ZnZj9MzNpqvaO^36aqR9Q`EfhkbHH`l6XD39JZg2;39+VxU4EBIg?d)pr~w zsr6xy+v9exMB``ju+|Jpx-!Q#>)jsK<=Or#Jxe>*csiDQ_3`cU-d0DYr=!Bl(8$kG zc+|j<)WV<)EKF%L0UD+gr=!7hFoAd-4PJv6hdto*1Y-iNrUf6hlnLim3XdVfpWP_k zWrkK(LgGv91O%4EG>INM)=)BP8ih8cnIjkySK@|M#0@eMVO9Gczc_Q2s@CnRBM}t(@sP-^W zoI%1Fq@2NnGk9_aFU~-725-*b!)+g&QZ|iJNGN_@<`pGHTdt(Jnwe!ux%nzb1Lf-O z>fFr>2$E)Yvk_A9Rwj_bUlX~Ue?65HUnglvTPNd^XG|X?1-5J5IiZc=8Lceq8SI% zWHzOmvQ2qV)s34ye4QA+HSY3|5<4T?C zgD=W~bThJe&vcsF{+4=Nx2`*^dvfZ=hpzF}KyUsQpI5<-@&K_$z50{W~O{ z)Q-VGHdtcx+%Y(X9VdC(YsX*$>mm7&Za$=@yY<}<$-hnN-4U<$z?-CQ&~wtEvbydB z^7pnjIk;}hlqqFX1`CIu)h-U+G1xk+)Mf-bD!m*PG&4?_6|6`ImiSZFL#VXMgkaj= z`c^YXF`gfy>r8p{dwn(9?N~!{hFX*()*?rV%&`TPOBp)8SsOZ@mdaZAmx5t51+&ub zqa6S9;6Ym}27WIEi%!ADS(B`_#HisMY0~aEPhIHvDRPH_>Onnl>33eH`ERMW$0+so z82|Uxn=mMriGhESGOStwGNfh@G!qI#}MKkh32O|oUh`&Ci1$8eBXG!PAPe9yaJ?u?_*ZHHl8G6 z);Dt<2_Go?l@=u;Hghs+Vn}!nMwZQJ7_=&; zSv!-#Se&n)XkZmR-hB5&mrv>G$yZK5(InzUOT}Dtb(Qd@2PWxa&t#bKv`_cAN%A{* zJq#{0*9}I!1$w%fO!o?PkWR%64f+(=5#~KuO#%>!|0Rif1!<7(;qHlT*40xP%h5@7 zEuDSemQLXBOzeG#xyC;>sdqASWvG7k23-{M%G=r~=H%ygZm9O;XZDkqxO)Bv6a05D zHh9lt9Q30J8~kCEak2sHQh)18f9S(KXVK&U0@?J?eNfGPXQ3-}<3pTb3L(~QZe?yG z_l8%~`Cm<#JR8PCeA|R~TPMSu{Vu1ZoDd2B&_v}dropW5jBJPmFU$=YMXQ?$SMu8s zFRcbUF6Hu<-$0~tM6yg5E3V89!&?B5P-%L41|dJ z1BJiOFW0T?mUr;}%oXz7%YV&1b*UBe?nCnKfxHA84jyLVd!O}yR$Q7{|EEhV*T#v$ zAQBu<91JA#7cE z`lLZP&75Zj8A-^vkf4xBAyFZQ5MxMI$chkmgD{9%Il4iRY4?Yb>Yo&f#(?tSpA2>R z&*IsieG#3^Yfph&-1PQ*^`=7ypG zBJA76bR$I!cok0X5D^Z!%BEOKL;8R?z`qcR2E!+$7f^;uM^zPZWDIgR_#~LC5vhb- zk%iZ{>>vXbz$Q`!P|;4tYG9FP{zNDuD=8m_8WQ6THv&f_gQ^rFW05$G+9?YMSbp<9 zX%~YAvlswjplpGw<#F{dPNQZe{?(_{o64*|98^>jK1bp zd7#EH|B5ZdcNV{qxy#PjK)#Yc+qxOxNE!ExJD{7Gzbj_nKW;4!y!|H z$-m^TQng?4BS()G)(?MD?_XB`M(|ob{ZM8@cKX4@^hC)o(hkthIsP)I z%%5^~R5|mmPufAH&(T}cvV`ADZBwP}^r*<}hJ$IU$S5&(=G~{qF7oMSH7F-(I2* z{Nt_Ct6NKN?Mm2KQn#^dbS@*d&X zS)1+bv0z)FEo1G0X+px)tHSBirw=}18yw91X#a+TZ1I6KHn*g{aC%bWkrnkcm01&3 zHmFflmrrI_G_1;5WeF_N2VBMtWMfS{S)*&+g9-F4j{`&YsIn|5@1H7#L8v zrT(GojjhqrzyN<$;3l~ykh;3p`TT7E^o*Jh5889S{_9fe;!n1eP#YYkR(9!R{}WQ% z>;~n{qrz|I+t|x@7ielcH*J$X@zJ&;=?9w!Z4YmbqnZSdtjU^}WvS(bWtU6SdT3$) z4owVYT7QF!(=N=))c)vJ6y_6RishF^>nsIX`bKs_%Yiz+kAlY zv`v^@I{S^%XQxYxFE)LneM-n*E66X)zA87%DEaz3s>|hH$x6$8hqwLpwUcXJ{$^3} z+-v%ho%;%ZkrkIGxoUj!*F_sN=E8;hk6nD2nzpa$g=zbKEtwX$yDfg_3AKNm@le{q zv_sRHdhF8+zAS0FxU2Kzw6vb-p8JpX&rW?pQlm;!{zkZQ=yLrQA<Fg<5q{g;JPuO2Ot7q@O^4kjjFw$=NW z443x5YX66X>noMuh#>q<9lESIalpLIv&Svj?_h~0<{p&m1{(6w! z_lKiL_rLmC;Vor26+ZXQLmSr3eJCUO^~^;le`26p|De&_`O}udL&bZNVs<~C{qla# z-~Do8W@%l{U+0(1HZ(pmd;XSB<~LmU)wO;44}Si%-WgPSwsgMo7dJ}JE>IYk-F#!& z%?s59fy~FVZ#_JHivRqf;rUISh11j1du+qBw_t3aPPYuxt&vkVP9K+6{#sax`Bq%a zl(?y8XU~Rjob;h->8;z+Pn1ouZTfn_v=y3!wTTN7G&!c52h(3L-)vo)-ZRy+%xN>< z?3tJvQReJPKUi&cvKz_^({s|;4KHVuO}SW>peecPEIzT};D((2SEmFz*QaGq3$zV? z6Ih(y+4RXLPd)VOuQV^evghmvIo4x8E?K*8_ses~mELVCykl6aVHnNYU-OyA4*#ya z_vNokRfzX$CG&lS{;`RC# zP3G`{sc%ize9g9KCR2sxqjNmJ+Wm6f*A1_>NACIc^UA`=sSW=b9%?=Ki-&78FE{x% zoZ7HYdU3;n{WWjoc~|cq9xBY4R})uMcD5>|z+Qf~`PPr4J??x%ePR1@q)~VEld_VH zBi$qnx6w~BBx-Aw23EUOX?TObrQ}r+hC4Tp&$!*NV85nFmy$`xSN@~V=h`RCK*!(1H+ zsBQi}R6?LY9aOU3A}X1)l2~gnS{hV#GS~4c7P+FS4)E5-O650eF#fW-pu)GU;3E*f zL2nntGF`Rl3}qu0}c7*vc=A=+ss!kqhAsHjsZc?OtvXkw7o9e!v`-AZN@8 zp`TS4u4=24WWEup%WqqzL<%++ij<%<6S5L@D54f9sXdf$k%S5+QXvEZq7>fMqzQ-Ol4;NI#?#H+9`S1Lc(t#5n9(S=DH$(i zwUVJoGE&U0dDXpB&3M;cb^f{UgK~gWm@{>U;!V@#o`owmL0G z;pV#9KJ55Q*q^@rsGUF7d4z-xe*GX54K5~@DiO9SFKI=h)0y(HF;x`_CYGn==T3Dx zP01PQE7u@Ad-1YqQBJ2mE7Lqf?Q|LvmgsT{0FQ9i%@mo~;jD*O{DFxc=gHG>e|)a@ zRNome@yUq`e?9AFLh<(ax2C)^y=C?{3%*Ubv$%WJ@ilihU4Q&m>9um(6ZVRmRkybe zZy&0+?zqw5ps4FNhi*A;eE=U_Qlc(y1`VgF*1fEYH+YvplRi$&{Bl zLxmL%jpV6m{4lLmV6E=JwAZG+H0{u|Bhxyj@zeO1rm63of4zV^|C_;sr&+aUvn6v} zJjWjbxbEcZ1bpDM{2th~>WQ%&#sC=0X~HSlpE0TP8_dj&`Z;NdL;3Nv4$122m<8qc zcw-(9i)ZqyZa6=F`iHt1ZlImxO%U|EGl;D7SLTp4r4ynjd5JkCD^Fab^5lO<)wZwWu$ zn(}EBNG`eDR78IiMvv)Ore8Q?06QbpZR|rGQJ+R(j|3|-_>hFLsQ6jbym`%S ztcSn+(#oj*sFqH{O_02+HfV^d$ljzWK&^kU{sFHEKodtp-?F}iA_5v3b4+@35L`K# zrp$3k4%rX)>}U&y5Dzf^>I}BIx77f730vnyK|3;Pcc3}PhGlh;(>5E zw2F|$tLkla`>YxK(~#ry>Q*t8PK(LShQa1$#uM5~7&J%;;QX78YOFLEJVrvrWW;b! zH%PAhQjDOz6~*_fwU?s0pKO=U(A|nU`G(8i(kViaeNW}*K($PsVa>W7b^eV4jJjob zf#ILjfU9*_-Q|eJ6I4;C*0(r=lbLQ17}nrmCL8WDjNuM5-ta9WH{53Y4YwE{!%fE1 zFwA(6IdiUa2%AzMJw;5EIzg|P6Qy3LR~VwybM=ZPQR-;DVqKJax?WKkrB><{JEPQL zdd1!-^#r}*r6_fvUh%6awXa_B+bFe%;)5unY?vAq*C2#D$9_7azZY7#*{Hh|<(hA^ zyfK3t=tGuVI@jCJ4c)7Cc}6k|d{l!;RleG2hp?rJ&M0g^U=+uqum?e*=#9cQ1V6>; zD8UoSeHdkVJ(Z1)HmKO#lz0`JZ_a|5l4oRzl_^?zDY?W4SV~f^s}``C#(0%EOOhyfDT=@Mx+`eP(>dGRVJrfc^Uwm%s&^B^Z>qvZYs71{^P zTDb$L`vHnOQK5p9g)&RF%L(ndUV)wOP~8z-SX884l`g!VbGAv_Utq-g9=@ldVz&+M4EGhB{oDRE(= z4b_;e**Q$!sK;mx9c$=`uEQ`B#r2u%PL-t(y zgHYEN1v1M>o+Zfeprm%FJH9xEvabI5EM(2D_BiUv9c_G|2}h=}1V*y%vYk*xveK5B zowFo08=C{54-YDqOQ({O%~%CYUY3@Yn#-m>oRXSq1ZGmQ$();=w1mx1&CSj$b zX0a=hGV||2sP|?$KbR#Po8>q+>+Z!_cLrzO8lH7?T=Z~Q^w9L^8w;YZCr4jf9Bt2y zwiQHwQx$!+Dcbsz=&#?1zS0t%BlVT|QqriL9^XMs@dinPC}~(}kK&iu74Sevpd=6> z`3Dh_Ep>Z(=KhjWdc|%)+xUhBKLS#P&fnjHydp)z@VbFOfh#q(SUVqbe;s zpZM}pl1!;fMQe%K?a0W4BR4fAX^9Gg%1gy|8C70RYD#9>N|iBpd0u`J{1Au=C846% z#Q3j^@p?SQ_lX$k_87mXVgh~`qc{)~@}Dse9gOjQJ;tXw#^c=>&(@g0&KNl#Q?9Ag ze5MJTGj&eL?2y^)>}Z%z&i>JCca@wdCvV2H)99G_nCNX$r$J%0{ju1K`B|*?QmkJ4 zd91-hJ4gVRV`(pJuG}}sWom4A~nBn>JqJ$>(ZY`FK2gHJxr7?Vnmb06F)!cE4}UyBe#z8Vku{#dx5jU-!*@ zciYmol>=g*L);l9wviEEqhJ|7w2;IlVJMWeyHNziHg=wiWCve6hmA1MXddT*{1H|@ zpNgCZ;zw9|K80Og^OV-uktXxR%BZiAAD13sy9N{q?Jji5(LfV*B0_VZ}6G1 zL_BuGFy_6{#nWAh6`UWwuKA9VC{D#n0>JL;Q-?*ujFJ!717!vBA1av4awC?{r;%?4ZY? zpkRX(aj_>-3)X^2D2&fx7^HBVCBE~-=fvYX8WUB|6)#M8fna??utXR%_N0!}b;S;K z|Cv9lMZeDuOYsvj;vwMfzns){?@21X)JK;SEb$NPRu>rleOU>!00V% zkCAH5#bQ3>d1(7!D+biw=NHKBmNoN~t+Bd4$F8^^)Ts6oTDvCClV7#0o!4-3LF5GX zGu@F`Y{ZEWywr~fergZP^=T$sO95O+YL6Ctcdbr`Y|#w;cnK59RL zA^rB1d5pj87Bfe7lZloMGc$A_#ma`dpJZ9tjqWlwRCc|413O-Jt$PJ4li9n?tdGpr zoz6-b&swAf)g^n!q0jVqB^RympiJ+n6(RE5q_@4(NLtD!BO`||lI#Hj1jFSfqqxaj zjCdrLmMeQ>{!T=1G1lv;BEIf2>Z{J&4 znmXP+{K&~Pree&Gp0I24rlTQ1oVb{;9*5j1V)V!n1RS@Jub+=C{15Ah-LDA31|;Uc zb)Z~L>5+isTZEEaluNXhgeB!#_N-JT}JO#Lx?-tK-`Pe!j)nA<=q7#3#Kjz!e7;bXJPUSK3y%#mz=cw=(NAp7lw=76U z8gEU0fqQ5^q|4It7j!Z^3}3@H+6=vAZJZls_!?e*ZCoq1>sx9@pnO^!rlDN{$iRaE zno$A0agK&@ARFLl@Pp;=Xz+zK4t=2uIzNst)wSwC<$^Ade?`~IM=flp7h&#N*J^k{ zEE0o{!z8oT7F5?vjRNG;W_>SnX|K9}| zH{$RYC>JC^bQmP!R15kLB)&`BD6Pv2S{X0HPT0`AR-EH-%=e_A5{74wuzrz-r;o6n z(AuNA&zE+a)x`OcsB8lSrN*^?kL)RL#{39}t>|(`i2~bd`_a|G#@M)poGw+LZe5+G zC#;$WTdyW|lGl)3e#IhN^kCRCSAFh<1$`&1Q4F~*w^}AHy42y8dRl-rsoQ2vLZQ|8 z`*$C*in}u}bqu*x!7d_vDI(MY;WsV>ytBga&Ki$*mK^Uaf4sANFyrHi86WDwS)QYd z$ea$hNIgrhIK7C>>3q6~%;{JckvW~=MPyFLQ%~k}F8#9rpywy?Gc_PEO{7Q^Il4$(RP}?4jLn5#8hZ z^nqa~Ul`xt+Si6AU7X}qKCYjK8Cl($cztV)wjjP%yC$B0O5dvZIn)+8I)*sP#>rd)wljT44d_Re^1THK~(23#X$Q^$; z-tv?lTUW6NfLRb$R}fzS3fxl5|a1A7>XNGt}xQ$n@JJdIqkznPFREm%~eMIV4!vte7c^~nsoS;tBK|m zgfy7Fy?1&yR&&}FM$VNfj%05wQ76&0Rdn^~rVv@^Qj9Gh`X}|G3LK8tg&5OylZ<-p zB;&hh<6-i5Q=n&4jGS93;kT|1G2W{RsAqRm5Ce5#k`c~km!)Hj1kF_$7!n{>1|+~B z&FS%45r))IEhiZd_vlwZjrpkb?X1^fjg+yusDwLFfeyzb2uS=x>6~sgVtZj=I*xM# zBh!hCW<~LEGAH9Hqp;Ws>7+v*9RvL7#QwHO`LI}aUMM>st|3wwuMXrIFvgXERG{Fk z4&rK2vtT3k(%TpH3E#kwmqp?8EQNdCvAvdp?ky_e{Bx{Aud3HHE#qFgL7XnJ{i;a zQP>CzvG^JXh^TR##@E=3ooI{_MMbBgFx|nCOyGS;2#FvzVy==~ZFEy4hZARwqBsc@ z$B&Twh>*e&8$vZ|l5rXp$s8UH3IT|DeI#>Y$%j*Tr7cVDB`1FFru2zXd!q;1&j~ju<@>QoQi%M*cOs8>#STSm-|t1fSKtl&`D9Y!L%N5I1#}wG>2NsG z;oy+fDG=T?3^!+D$gM%i#|q(Rg=ujM1oc@#6Bkd$^zP=CL%d-hw7VQA4NCzQ9g-1; zCvlt(F96!$t+xo?X*Jm+Dgv-W6o9``XHxO{5GC(wLFpWvRy5N~g?@D=ohy8%PNDOJ zOX_%9i;;agJy)=+lju3ZHT5ETo^V|qOUDW~)U)aN!jO6forFQ;0y-JP$vLzUgUOk6 zif~&!l{17@M;gr4ku}wr`7jz?{?)`EX=tc6coLW{2|9gR#1unZnB)~h$`!Ax!|{EP zckwDR5s9r2n0n7)URX?dKQK7_7d=kg@4zzpAwvwaV920jv_pnjO!SapHKQIfJjz54 z8T3r}kio!&3>nnS_#wj#CUD3Q#rO>w0vN9$1GY6_&JrDQOoG0Gp}LW~G}J&KIERB; zuIhxF8NM{c|HWv>Ih~<~$bphFc={vZ9qQx5Qnv%64iD*q)u4k_iwDknSUW^#M_(I% z%Q!%cHf{wUm0GZ!6fztuxWT}q2d00NIGw}dEP8LDh!BjeGvKDLfBg6kS0n_;%7Is@gX+SWvOw1~5Zy)KI9P>N=7N3cBB<>Jb`jc_Y=%^(j`QVT|1i*?g4BU5Z$c z)_*BtVcI2Y<)Sn)g)xMsUx=u~nzb;E)42XRyoi(rq@J~K3u5c#(_LWths z3~%DO&DCeaL(3O*D<)YV!{&NvNPzrWdi~qj+0D-A4(<+`^j@6w`C0PoT>hig!Q-rl zIDU5eJJrOT{cF+sH8A4i!@%wY;)Vn{!)(28++Az(VYL_9@{Kv%{o_oWxHtxWpj|_lm%?d`k}~@h zZfJ+pqh9J!C-vAawR1Sl=-U%aEL^_Q6UNPJjdcHW);xX2fMPv`Iqn_WMH#hPT}D5D zJVP0gf!+Tx8M^q4c#PH>(slZb#&q2xm*FZFoi1b0qkB3Ic+-uv_W_Lqt8gA3w8WE^ zdQl!;PU(F&QGkKS2LAE16{1!ktteiv%HOzEl~%Dy zl~+`SV}sb%mca&*+`|q~9FV|PdodIlvtx_?m9&2D!oZcj3;i9vGM4u0yD-E0Sm^%g zLBaCdy#egiD;N5?Nc?CooDsE_@v|~r=1km9@m^=ZQH^C|PQA?8!m>LARui`NaX}s@ z4GBTpKNzU?%Saa$Nq##?M%7~WWnZRx1`f2fwDt|iJmBc>l~FCMx9FD1Y57Q@$I<@s z>)^2d?LWN5HK+S9QT({Y1+@a(9nAPobfVk(jZoMfv?daK4|*S!3ckl~WSTEs39%mP zZ-^WkWYoUcWcM{-)I5?p@sB3v7(=J?$yLDlpmpKBsUhR3> zzLPTq?re(eX^2dVZ0+qeH~ZXb7`FK|L=KZJdx5T_$^7QU+PbBDmfNgZxo1rwqO7zK1YHwx`ZKs`6#FN(V`nG$u z&b~ODBK6L`82h3~)w3@~)q_D?f3xD@D8AyV8C0<2X8aO;M)zd~x-V1F zeNob($J>XpyWf9ss}WyMQY6!&+&u)zy}d|T$*NHZS%yNzHzs};_LM1TGqL>@GGe=M zQZn+;P=i{^#-a*Wjz%(r+|bBPs2RCw>)?$`+IsndB_ub>8gus(te?%MWaOK7jG<2du#HI&`wKFOIy4(v+mm-06<`0<&LPrb2j(Bo(<3fbimbFbWK zCbA(wf&h6*j?RG(YlkBQvka|@ADS(@Qfq}jtHZ$V@=fcD%UIQ5Albbk%7$z_Q*j8& zsVFPYFRs|^7KsZ^^6QR6if|;uDmn%E{VmBa7@C)j(o4z~^V>ZthrrG+uBjpf>7?Ui zCm!a)Hs+9>d7>cm%C>G<|9#z1b*yYw95>_Q9x=&kOie&>@M=HpHyh>OMlTEZJYGXO zAA^C4lLU{11(PrYNsiZ$gk~b45st}51ykx0T<7x+`YzicyugubAy6FR4#8@p!B12! z5%DN zQ@g3#bjtLpDXp}uyu6krwMmsxRI%RWN-5i1UbL<%t+c3eBM7l62vIG|OJ5YdH8+Ns0K&}6o2@e90c%FWoeFzIH0D^d z&YWOQGiRHZnwOhbo7b4vo5e%rNqH%mDzbHiWD2_;Nv?=R&dnyJV5d?J*>tijO=T3( zS8122a`U3KbG0g>dz-ctm8x=zDvC-=i%ahv_%?5?D&JbA%G^TCSiEi1x?-0vzqZ`%8VOA)g3LEn)y~c?TVEXD7k%%? zVnJ%;H`?ujeIG*L0e&jd7cIcGFIfEdG1C(MBF#{wCrSECF0d~;RRGtC@cUq3OGmId zoD>(kl47s?t%=kl#kh}!bVTseiY5y)w`?=HQ!pbr)13GBZx&RM>#j)eH3@RwR#dfV z%LW!AWK+tvRF;(%ySuRjVdRPyxRDdm=_Q@pCFT_f$%h)OWZ?(gU@)*bNv2HPZQ}Oj zt;|cw$P&FEizK!dv+9+zO*0bMe`f7Y%+Z+f|Fi_$+s((UF$s)GU`zsI5*U-fm;}Zo zFeZU935-c#OafyP7?Z%51jZyVCV?>tj7eZj0%H;wlfak+#w0K%fiVe;NnlI@V-gsX zz?cNaBrqm{F$s)GU`zsI5*U-fm;}ZoFeZU935-c#OalK%0v6n-Nq!ca3v=W<>i?|W zFY&PPHm5{F%)k4yrvBZa|KR`}2~|*y5=v%0WRdNhGiNU^Yof2o_8qU)&e@AoS{I+i ziKg{?A{OmcQjIv_hWkgYhg=`=<(KYKHa^2I+QqNmsa&&jfcSsr_VeeO*dXS1vv$Wb z%q3+bMK?BA%N-oA+r^jcQZ!P0^R5|2z^ROAjXm| z$Ur^1ZJ3A1DH-3n3R8s0;5%*sola z_|JB=H|^%zcAab5t&QK?tTpUK%AqY?FZ@7=!NnLlTte5hI~cGBFb#VxFZ@9H`47Py zrwk+(pTCPF=Azz-Byl_~atKhI96Hj3e>)z7ju-@RVGDJkM1pv@l<r%$;!7uXX`ySvlXUi$6?#w)%%;iz0| z+oQZF%9?MYy>#E~F&{@pw+~WE+n#q;(4Hd@WhX&`kB@Ak?@WBIKp7-Cey`v-S6VIV z38S;`!V8uhSN?@CO@BM_IVF5`Ai*h{#Y8=tXq!xWT$xW0?q&8ugD0*?^U%%NJ5(@n z--Ru{7fSr-8^>|%8xmRLePOxJg)LqeN@#k>1+(MR!W4a5cF~QpW!!}l|I5m)gs3il zFVa))72PN`uzyP?KMwHW6MJ^UGSm2w&GGi1?yl47_Ua6KThsv}bkgzdxNqgaZYXwy zc5lQy=xtI&++Lk-ui(jUK!OO6Q2VSY^Y_vc5`&M})fy%2-ytkxXVl}f3o6{5-M+s8 z`r)IHQz7ypCWw3&SfSmE?<+$0sYF7~us2G(*SdP%UTany()RY%NP^>;VI*nILz;&P z-);>4r6zvOF6cMGaVIUZDj`WD$hx|5zv0#Q+kdg!u<9^OfRsNb1O}8}?B|WU`iaw; z_3eIsUz6K?ca&QgaYx&Z%3Sk3sx!lqHEgf{c4U&GC4vw0?cj7)G^=6K1XoX4RnE3?F z1o8SR-y}K~#_$GjLjGuT5EqK81=-GE=BDUqg+nMhE7bK2ev0pZh2koUNrFxjTMBQ7CBu%yvu#Mes~v7*F(o_$9If6 zV;|AP(XPYoF-@Znw=ZiVhiqZugzd5>oUmQiBpz;G*7W@|wnv&cep3@)+QgSN@fA({ z)+WBDi4)Ip;Z}xUH*H5Q>+ra4WoT%sDG4EkB37T28ghJBSwxhpmej9u;_ARLU0%K$r+Ejs zz5(&*vr$loj2+a zM+&KIBb8>Pa3V2{!tqB+JPJvPM)CZ>n>QD2Sx<@Q zkhhXUep||_*rIJkn@Wq;mKKkKuP-aE6ay=_mY0`RRI!z%I0aaFpAydf;;?0L1uK%N zEH7TSsbteS9FHs8;vz#16PAGR){0`vRK`}i?ta*`xoAT%TegK=kHeePvMt3mh)HgP z0KN6qMHR)Ycp48ULhnV+pz!X;Av`v@49qSmD_UP%K_zXiDkFX!ONrps8Sxp#rR9&p z@5B0tH%{ahS5_5Oi0AcO7f-~*#E1dxy|a7ZV;PY`DkWz{ikPDOEL zC0oQkUR=vom9g+`-Ha>9iDb!v(xmco$VJR`rA~y3qII2_bVJC|z>xyL8C6mMf5k*wvaEDjLr$ws=cb zMJ=1i!t*G+c@S|~1@RHSUFRK*n~FAUDXXm7w2oa;ysfwtf+K+}yJX~OC+ui;$)?IG z_PaS1d3^wFRIW*0k$zc4EkVnD04=w8Eh$4+agg9lR=?H2uGX(JJc`8fimUDwP39IT zS4q*j;@QbXTZ!h9rQVNa4N_HeT4fS>-m7J89 znL_0kRaVvF94c|=lor)OrPGTx7gNhBQH7z!6lE%|sxGT|Tolj0|0L!AaQA&I`F~LY zb0|R>Wao!$Q4ia#tC!nfv*v#LsVyqU9$~Ua^+tP$F*}OTEU{Zx6>pSKp08Px&o$fH7>_pj(=~(M*0p7d z$Lt{uya$l-?T8!#b}f@_{55=VYn2^TLn4;jExtBoEXkYLDL{{1f-&kg@|B&^N-66)PHR-P(KsVxZ;27&$8~eCE@zNelb_^FfQgY z+xU1JpKKE^<^ts2#azY1;>BErwow;z71~BF=K7;;J6}9phsV_g+-a-jciO~@xpvxi zh)&WQeBOrM;PW=p8?@Nmy+Mm@RBw=6%thNm5kb6|%WNCDmc zznH6dc;sTPhwS8HF0;+jZ~NO9b0yioe=*kzJGj>++4b5ad$1+NPOh=B+4*EUxtME% z9T#);*l{t}2|F(4I%OZZmjaA50h-$q4H5$63~zj|ZO=85M%n zwgyCV)$IXTf4gp*uDj|s^UeqlZt*=R#oo65nPHK^4MFwqvbT1;$KLoJJCGZAH;;(D zw|{12ZFT+o?Cl+g*&$#nlihh$ULXZW;-4MrDjecJ9b!E!H-{E*_x;x`fx|MYj|e>g zH&ptlLoq>MPp=iGt9@%w1l5uL%x9PjKw+GRI-QvrfDe`x4`ZSY25~VT&Zl}g6cVJ7 zBu)zy;J#C~HIljAFf#gY=J0VyT1eO63Si6w$SA^z4Bw7Yo|WI>XAJ+|%vdp5K<@BD zfE)pl-9cyZrGy#7Zxt|CTF4EHi5ic=KynYFFUMyLle>x1VINBWK|u{k{j^5#JA2xj zt4BeQR+}UBVBSqjq3xd?rjLGI{_otlYDK(;#oZxhbBl}C*8;L^%i|c_ZNXSW9E|~z zSG%REsD@3gs3@y|H)Uh-y2mlny9dZEURQ>DhQ#}CMv%mj=z0|!H8Qx%D6V0XYpaUc zlE$qhPni;wPzhpAD8U1q) zSzIIN06!yJgCARqp9?FRHE!Kp&TcN=j6oM$Qc>wc0`J1(>5XL zzZZk8-c+@b-M&4*FB36Gvx1o7%|otK#EF5LngGA72XMp$vWjchmXW)eiq~x{3-B8~ zsuYniw8YRC)T)Y0NzU2zMO8(R(F3f4*=P)BwiS=Cy0)}z-Qyxkw3vTnaXWqierCex zh(JgJ(X8vHBrbumb#YT*-)>xY@y#UmGflHj_`au|-v4IL7$j$IIQiMI4RZ zN6NcT#^u6DwyLarWXeOGk+dX#Mu6YL-$zTW!Q{hc*Jw^G^6rev_}zfWg0SoYdxdj&se&9WO8_A3StDoAiz(1WWlZoEu3t;<%S5n z-6NX-r)(m@oP^+Tr;H_7!M)^4YUMX)-qCteobH=5#B#5@6>z#Y&$M*?q!(aZ*8Sn1 zdKAAs!*}-($l){b+GA&k|8`INPkI%&zL;zP;FC`&-#>#71ICh|b0R7tBdXG;hyQI4 z-`?BxS}%X0*Yea!n0#oj%uhl0Ab0$XUZr%kpM#HKIj4)5FQe z0R_ui5@K<(5U`HrMp-Cq<(p?9v-wmr@8a*992MpEKP?VX+M54IMS=#f#Ji8 zJyFm0VA#+VaiRr}DCkH_;0Z$lM2=7wXW|0nIo}hVLVTxC&?&@p3c5~VQKz8q6bzlN zh04}oi}{4OzGuKUA|6buIs>w zFmP6F`N@eI;FSl{KD_2c*Lx=-g{bz|Ps~rSym_KJ*sJ};69n9PBG}S=B62?K)&AZI z+CzwGzkDK?1Y8#JKPLF+Mf^??-v<0oUHF%QA32}$YQF|9p6ThAjH4nOgoJkAlb!+X zl9M$poG}xhiOo$CKm47Sgb#|Qn%HG|sktsqSISS~VrPNwQG9fU_JsJ%qWJVDF=T7c zKUvE`mgbZGmboXJwcb5*-aOM$I|aYNzyf|kFaK_j_RTYGxcOZB%^8%4&bz0j{l$~O zBGT>YJ(>hT8w^C+3wz0m@!4KL3GSK`ANroq+0L}Izj~UFIjL+rS%6FWL&)0X_nIeWzbNt-QW1g6dIHJ(ne)p0vEyLq7E5`g{*1u@L~i43w6+B$Wb9k)ZDh ztS_s=$>u*vfjp7elrpHpOLiLl6k_PM8OINGBj zC=x}Je2RmX??hQQaLro&3?bebkIHkT6ACxV=h8qV&*z^)(uCOlQ}np`2@u^gr@}D~ zzT9){tCL+}eY&e>$Q8haW_&y=>(r!kfqlJollulehT4yvg2Xx?oHob|Erbq+<)l_-Hy~ zsp^X-{*O=cC8sQ)bnE2MJ(@_g52^O@zP(*{`bfKH$KC5Q6qKa??Jj%Y%mI)L8GsTI z?mT;Y``hpISx)s4-?<)ryX3UQ`!vZ@AIT@wA}=Q?MbrzhjPkM4__S(~^!io!L zXgL}%cMTTeyAnEX{VULYbOs8E98c)A{O}Av)GGqoKRit|sq2SmVNoq+ z^r99aSaJFcseisF`oMFq@&{-5L{Z|8pHbr5hgaMpKw~U9(~o+E%i4Q({HXq?C!RQC z=|9~c-~PlIumrh+|A7W@jjz}jp6GATUN|GZO&%eQ7_B7jw@(i;XdtW^&O}-?XJ|^X zlWGWR=`x@3jKsX}nHnw15w*FGwBI}>A(h+3CK`3I3?EJvfz_? zeqlu5`8i4Fo3$4Qw4V$ps|E&Yg&93r%Jj2h6NJwbL;?S@$6)8V10R2ME@&`t@YFf$ zx$Ea{{eSGedwf$>);E4~Y0{)=()5~^nkG3ohLlT*P%yTE(w0&#O>GNRQ32&5UMK?E z8-y~VGdeR4j>dfGo zz?tDQqi4crgshZRvQvF2><#QM*lBDYTf{D7fV{qrnlo3-Hz<@n8CSPy zLGM?2#;?4*&%MlvZae<8@?L8;Wovdy0?dzICb8R#7kYcT5o02@H7sonOIpLxFuQS? z+8SL(d9Ru0GD(4SZ+8nrcjIt$S-{?6itV)>Q3UL@ zT3K&+XX~u6rhPVM_@S+6#xx2c^&b$-?@j|E&VbuQ|bA{2_Cg*3(PJVEe` zF}>)d5}FlJ2$A%oH?Y%hM=ULS58`X#675Lt!P4TN-3T+^Yn1jnH}`~hI(`v>S)($Y zf9(lJIp*{rudBNeg*ivM!*Py9J*+ksP2XGXcmA_Gta7aC@tb0L(b}dCfA?(Wt!`&Y zPdLf(U=QfPxsIzQ7Ck0x8Lrp>0t>A-6P#7U@xdZeyy~3 zw&PDdsE)1{wy+is(;61kIR4%f=7IU2_58EjzZpwGa75JY0h%30P0L(#e84G(6k{jUv&iJ9UF^#XXOfV{}sDk>tnOWZ0e-dn~PBe8V!foYP#BBBUcx5Q^5H}FJlPUTD20db8)ZXJd1Av=lgUls~cvuEL%b^ z1TGnxhgh;ksC};HrH;$JtijIKzp$$Al}dl6^9=Wx+N0>JeWB(R`~>~9^K!2rR#QR4 zF&1B78Fj#e0=CjyJSYu6_S)wxH7^wz+M!aj0^pxEpmnk(rXkjr5$h=ID>6s#wU|z` zvF^M2Y$?w2z6KY>j@S@NOg`4;exz^HFDRFU@Cl)|`p9wL_Yk682A19NvCHISaWf^? zv8PXWmNgw=EhzafhpIRXlp{k}B2u1$N)00DRjP~mpwDU?VuMyAzHq$VXKG>JHlAh) z*wo2}`Hud+MpDGC>Y&NbR=dzO+ie*ec4SmJgMIP_!)I*clUT%D=_4sqoKe0O(q&p6 z#Rz@&+Cx<}A8&9O-e+e7g5pLn})M4F?HdT+BT_rG!egrnGAn zq(d0BuT>k%bk_HXsm1{VK|#={KHZZOtu=vzIyPvpZk))ds{lt14^B>MX-jLv~5O`p8nlJr)@b zvl6TL2FHqiS0^*OKM=Nmq)2kC?FW%y6NI5fuJpvVc5))|>;4wDL_|5C>5pvznQZNc z?mzcq5bSt%`->;<>i5%j=cD8q0aMQR(Xa|Q%whwD5Y`VDRneVB9r^Os)mFq^FG znXnI$KBD@WQC}yYp%-Vjx$5s2Gqj><+JH7&`HJu^~O_T&tx*Zw_ zo$N&E<2572O8TsNoCJBCTE_4ON#!>UUZoAiOhD%kLXVA8{C1ypltr;Ylp@!3lEQ0z z9xcXki57!+p?{>hwyDPbn?W0Lbn~54ttDcmJ-9%xp@jPn`vKUv* z7&n22=Bt(P;-Ex)5>kak9>>Yl*MnADnxl8H+UD>NTH~7>8Gh%LLFW0vAo;_dEyItJ z$xmzo#y>O28y=GcC237PDgJ6=B^;Dkve|1g^gk%F$GaWeJ|D`oxzo@UniwmKg=jWHpSV4TYNgd8Z6r-_En&2@Zn+TK#j{jyL`l?Wz(;kT!u zy$okDqoG6uX6dyA zBrwO$A$!Yop$uv0(&k zfrec$9r|?aBr{TW)XxU=B47U~4tV1_rB{!ZT3F zz<|AnS%>D6jmG;dN@_GN=*6a0_Yvt`6vb@uF}Iy@-Zn_CZw$(*Al}uu9cM7vf1|$$kQ_him%qs&<-T=w^rJr2G{_*lKqL7+Ah*UJgIfb+jWCT$!CQnQ$ z0Ab?CmEhgV;eEkkFXTcy!()zHSAD)h(DfzaX5iO|{5 z&Cv`ETgrk)-4#PV1q22GvrbvuEhH79A2bd|lRCkZtv|wxJhaC<4%8rY^53T%m zSW8787mXUe9>%`?INn?GM0lZT8AdkM6tfdyU$laNjz<~szEkAYVW8X`P|l}-h0=S@ z@~|O4a@J)MB0!skdFi}9%5-*ECBU=ANwtgk+S|{nVvuRYS(Q-4^WT9zLO`G@B)6(4 zkpRhnAPSS0ln#Q+ZrBEdzWN?ea1k+8C00}AcD0An7uTEgKh z{&81045zCxczmo5E~$YHVl%?9IuWDvSwyCN4nP7^044`a0+W%pQei)%lRnfJ^?}p7h6=l3ItV(PIrZF?*BH3CSjTeWV z`_G#$43m-@frlj3WYc%UVZKJptofRNY#Igg#Mc@rr0%<6=8s>igpI&rKKYvI|5~5Q zoIcykbbQTa(Z?`vp4W>;!QT;Aq|hivi1^XWH(x^mTpT7?Joo9djV|q_VdXDEyeRaB zVQg3_g~Gy?1dF{;{?t%rrj;WxGi1~7bH{N-Q7VfzGc-H2a!M#6R6ZqSm>Oyfl{M>d zcT;1~O}#vJz>812qq? zs6(uG`W`McW238aLsjLf99KRw=1t?|-uoiRMD8yl`S28YpTyiYO@D}^D>f6CrA zU$fQ}9*+2L)f>+b+n@kji4qis+J4fBLR=!;xB}mX<1|rPaj30{_;3vmGXv*<)@(XI ztSt=?D##XZY?uerbj+^g4zq7iJ6;i<5zqVlFyhC-<|nlEn_-M9G~LJgwEXkTr7@pB zRR7Je3;jw&MU+75jrfPPU1rXlZ${gdVP2{gj$x&E-}$a)u}DZ@4g&kxJ8YJcc!!Nw zO7^;)xcCvYsdqSN3Zk9VoX~%*CQObWZ|CW+K8or-v-28$<9sRD@Qhg$$}tTTa^zZSks%7Tkk!kq~v7(n5!- zLQ8ZZNieizawxPoXm26@TckOpD8(MOVOHl-wi|4Pg{6xUSn<5p4gNT)=2-oUk5HC>_-lXTN zf{#V4oh?l4S(1nNNHL+e)NZfARKz}1P! zsS%&Cdxx*J(tK)|SZU%4E6t~dVWs)hFlVLt)bRh;N^=A}?PLxO*MX(=_=^|@zcgIS zyfi%Gs$`A~j~f6V8U7Cjz!%S_0f!g>+uD-a5=mUwxY3CiVgKp8$%V50Ipse*{+z(w zsi?U5lu*Gt3=?m-cKjP`=QS{j$Kg?9;xXRU5_y{WR8$6!z)0RWl6xHXqj*d}@Q8Ow z0~I$Jbx`;4c2dohh7v|#iwNv1KB<>@pj^e{y-V!`>?&Rk!L$539tXSSD(pM$Z!l#B z;1hS@c%AWED5{ZROuy9C8JC9{7cbA18BZQJ{rIG@X}9@#qkv*^g36R9AlRZ2c$v=B zNa{Hq#aBs4%FA5JMKWC)~s(EjNYZvs7s1*Tcs#YcO~2Vvg-%mj9B8f4tFn zc9>{aYnVS*FG`_Hj@Jg}hV`0sQ3}9jArxH%q|pn*b2U-ew45Clp&tJ6BddctXrv-i zv$pw4XyuE$;X=vWJFIjQ5N3LOvn8~he!@g~!*^-~%72msRg z2na*kMeqerl84o#gwY)1@!iJncH;$W6g47ODv$5RO-?KBzKh&x5AViDUMOFL3^rvw zi3vW+9CE;U)d2>nt5}1jlOCjEIV&(ON_gm>3cNFw@rjV z%e%v4t=}=`?N7D@jR z(d4H-87hBix8cRzwC>h`?#12L_*^DaYD)X(-OLlel*L`HGyZ+IipH)Bj+b><3Wl?? zgpbgPaK3EeyqW=O#&f!>ULBpQ7psN2dcK-pZ+vBUXyr@05k2tIFHL{nU4-)35>f`X zfxW-9%lvfQKV67h&#Su)X0JliE4zzKFYo?bBQ?FW`wNXQ9U*)pau(M_yaQ6+_k=1++3*D16BY(BH)AFc zr7S*P*NL}y*joNdo3|S^S?Lw4knX8REY(V)rqRTD+_~26zJK?FyEpINw!3b3!|um- zKehY!yVqRvABnX&9t<>Z+5cWRP@)VkhM)oeD~lS6lH&u|vf>I&X_+3}W+g&N-aQ#EcMq@G#yM=ljI>_C7O!TJTCHO#Jh6Qx;2|MmdD_g`A}6gSLlDnzw5B; z9JtPb>m0bwf$JQ&&VlP3xXyw95ghoh7Ted;|7UZ+neK6_Jf#$8S2%IO)1CRHWz!0N zu~<{JUNalVAZ)>YW9BWl%+hH7+hWiAKR08HZYTZ$cv)6Z+>v#1X>s|drK zyNU`=zHn;s@@4Hgr%DS8+rI58wJd3wa;iN4=+|8fES8g0fV1D;+CFZ+ZG5+#m~9_` z+X3GF7_&PrHqPAI&P?eD->Qd2?g@>S`J0D1=V89{Fh87N22U_Abm;p+QqW_Xd&O36+ zV{Z)$nwe7`)gEO-yFAe(Pf`_e#{H`K1fVp@<5h}Atxe3I}RncgP>0KBNt|G5~qbO|Y_Y-1}3RCK*JxJTHSAIp^G#dEUJoCuY zo{@`L06XhEn&oI>BXiM%BF)tPBW{m=j_H@}xyI+(nFAh;Uc0Nknw~v+^pt1h2;*Ud z9dBuOQD`Dwnvj=crQ~bea~{0{twCbbgl_}vsjd65+~6O8RdBVA3~AHk)X$Wt`T?!(hHf&{sSW)5`VZJj|Ql+T+~8=j{TMCU{&RL7kK z90$f-GVN*)Yd{Yu(WHW?Z#~xB?*pWtiP?bmKs)E$@`+}$wy|B5K$!KxuQc)mGzwhP zNI4gSHY=_Fk*4GP&O8{zpJ0}sKxe~nUnA!1_TfMNLWgK9oTrZ!HH6FYg>ylTh|-8S z(XXkjG45+`Ec!|i_-R#VVoS}@iyr1PkKLnD)Cj|h`Yhp{>H5?AopGJHc=1F`{g=M^fwkUYffU!I8S@V8#KlP zRhrnT%}liir<%cZm~}mLqvoc`Q(2BM^f-J5j+|s}@6;$8QJbluy*kL8_V}l*QyuYx z4h?*09`UF|C?M~lVGum;bt3RTLa4)cxXfbb(;n@YQ7VD8K*}tMRCkK9{s}HR;RMl^hSG}r0sBcr(S?pqET@f_zpJN^k#co zky>WX(ZtC`>M;y`{SVCR9&@5vO3G1o#qlP{FH9)ln#F~pL4`@cImH@x|=(Irhe*Hh|aT)<{mh%!xVWtK4>wi$oz98XTEM{P-_mI5IO%IKL%V<9qEcs9^K0AHcRw1Y0N3iDiDm+&JRZQ0IBw zN;65PVq4?BQ=Qw6yB(wCB`BjlHG;Da_S|%A{!Qq+@r>Mf+Tm}lrd2p?;)E(q`xF@p zAUQjq&bH9m%kbHRd7bk-FuV;b-@7O@O#2YIHX656e%`HP(BKI|xXsw~!oO-pfBBt&;DsXyoLE$v?0lN2DX33qls+x<*;XU_}W zww~jC(!M(1$EV*J*wptz-@d-4p|K(U(1(3r_kG%T^Wd32!9ZW%Kl+CIe(d{r==&kD zPvJ}JYw8>9`+leizvRCk@b_(>x9=2tl6CYQ?t6=Ui)9||_Oi^{9=|JHpO~%}rR(Ei zg>IVSwV8QGMFC8<>$_XEQ@q6U;3#|u{@v98ABkW^;xhfhYrM&u(1>$cP@YHoS~qLB z+gn28d=Nft_F-1P6Q9DOHQAWsC(Z6$NC&mQK(aNnTBwRjW1j1QtwZhJqDMTP@@V3W zzh7x@tnlFAvS<8RQ{ zkz+*236A6_5uEXXuizRoRjk8JtaP&JF0Vx~_b%81cJwH3>Sa26OqpIRtJd}?bIFqj zf66%=e2JGC=rNUe_v@$FTYRhua-5(MG9&#%%J~GrFN&eff=|uUk5+U;UxU!Nf1*^o zS-3|NtDWk#W;W@gT9{ovdt0$aW#;Y4ifT08<^2cqNcVotWx^Rjvno`xVSnrNF^nP9 zWYfz`)4aZF$~4uBe4+X^UZ3GlUc*vvXyqy|%*~*bb<@4foIx1wGm?2HMu$0Sm|}u&sbGA zqf&dBt$(|ku6rBZmf^z@(p~fPu|BIjJWnt5Wy>kEg86RHFw4tpz`AF;7avi5hTAd5 z@Ad+nk@{6bdn9Lr+_NGgH(bL;>gw-DQ^a)+)WhP~_cy$bxp)@2jeN z>yUX&&&w(Ls1-I!AL^yGHjO0Gd%7@d$n!F*`e9WMyY-5@6B?^SANoTp3%$gc$mqpd zlliINJjP@VFzEyCWqpuN@@Y5}*6PnOWqmM&eteLj2TmpqsJgLc4QhE5+Js4MO0MRo zx{o*1AF9GSmDuRSU3M8NyqvWTo^)m2AX(!s$?=+%w$OrkbNLb*vD3)a3qud6Lad?K z8}UD}hgN2J;cHT`48A75O`5hO(|oV*ZP^Bs*;^!J*7TR|0Pp2-5{tyNz-zllA4R-N zGV2b))QBQDK^&$R_hZmB54ki4SHY8N(6qt}S>p^>i1$N<*99?Q7WeCZ!spt2FB(pB zJ{Zi%AZXscFUJKCP8sw@d^9Wo(#S<{iJkr2&v%dyrmKxByfAFOzn{q+WL_A+D6*p; zLMzL>uv}{;H8O+jlZLt8RGEff?P_WzowWh(gZ$njOM6K-Vz@E0`@r!=)yr`4f&L{P zJ|dn{+G~(_&p|+aZE|Zf;~ivD2U?kL`Z;4SG+z?Tn>9O4FKlwu4Z&tU?t*f749CFB zn&w7V(=_d~Dyo_2LFVlteQXPlqL^2QP=H+@(*md=-OGH&!lh#foeM8uNn4YzEv5+{ zg-80~f&W84JSy(*he7h4185j}{G|aEz93_eE}8Dd-I7^exR%tz9mLXRYMV6iR|JVl zwTk1eE_RGFE!&wkBA&j`R~BgZz8wWQug7UJ$i{ zt~;oYg;jQ*7xo+{R}b3#af2>`7)`+(FTtC(Un6X@YT{^IVtj34D`9AW-)vBLMFOR| z_Z-6xHjDU5y4MivJs0WWP?^gt)0!2=m0k?wJE382_k!QtcsT+us|{7UQZLGCib%X( z9$I<37d{?(aVNywll36#$Cgju1+$Hn-l7_tepT8x^8!2dw_;T3P=7{NIt_v{Gxdoi zo8kkcrJ}0ayiDV1m7*5Yw-ml0dL2GCO?Q#FmIVNS0Xv|^4 z>GuX99fY&6OX~+=O_`aPRT9#${GX@cSyS4QGpb=Q0aPFB0SZYp3qRG!Swn)?>ff)4 zYO^|y52m#xr?jc#hFlPy+n6L@q{dccAl?tqmUX_p+FIYMx*FfB^huL7Sn~_N^=kabR`rh4Aha$ugBUK9SuX#HYkmV-s_zjzwTY8ca8VmnUgu{lrVcU-ftO&Hbu^pBX7am1sUh?DUOU%O*C_0z_iqx)5<(CG&cdQ(j=QKknCtiGK5k!F+hil z&li1+<8-6y2Mo@(&2yS%wQxGnh=nzQc|~(tec2ky_lV55S-#)pE0OsY%4;DdZJ&Nf zCM&#%IinYHcSeiXXVruo^b%i_Vy+nWzx$bUL(IGV`tO-j{Y+gy^pW$-8RoVjP-JWM ztKd5X|Dvk}KtL^CwBFYyv1;VZkwMb?`!!-;TQuo@Uz^5yge%YCJj3GrIbkl-+<)(b z7@#qe*iH=Zj4X}EA6k;;fyzNG6)Mp8nh*M5NpPl;OFF*Q|WQ% zp=dpFiWJ!rX{;TIUuZu}qHBB~$OH5AIJi}#06_;ph+05; zT7MH!tRsWuUXz5*Rts}93FvNh6qg(gh3+`*{N)g2t+^fp*aphNu2d^=>!^gYL|gnZ zDx)pULeo~V`y34jibew8?y|I_m$A4>9njA-sJ)~q>-AED2Ad3a(67G%qN7n^PD3aL zFE3?~#rno2=fN+;knCk)*CX2bBsh7E{Ub*4wg0Z$|6jNNzi$73-Twc&{r{+WrAj|) zzFS3)nsZd@QL|Zy4;Uvy`lluiO7$xBnlXNGE&(uG{~^ zGvK=Y|8@KS>-PWG?f~S(O4xK(dwdB?6alfoN2;T#zhySuh~V7Z6A`ijxT57OMF< zz`VD19Xa00`R&+xJQXZ2Z5c0S8)}?~=bDc+!{eaG0V*i7lui)27tiIDd8OC1=xu;3 zIGi2_>0WL7XDGPLQsE!^8N>ioQd|le4}dZ?e-PO!mgg_w08IdVE1>x1GH`7(>99wr zi7IhY5x>mb;wvHDzwnywC-C_kd?9a~+?hg3P+mH}1tvGQTqUNE18P@qyfjhdoq&`9 z4WSFiGd{#Yv@JgW1jH(&c*p}o_stWaJ*Y9CgH1r*1k(J~8-JFILj+~M6bB8B7yK0p zF3s2aLmMaZoZ=w!LyNBBoI@#@*GSHfC}de?&@&`iuq2Bo@Qfd)a4sf_;!X3zO6h9T z=qO5%S5n}wd8?>)pJlwt*-;eVQs%GuxTyBf1Z*)7ZzsU_ifZ4V0NxWtiHb|mbrm%@ zZgj>3cq_mqg++N4g%Pk|yxgZz?##@Ir#Hycw3zX<5AkHqsmYrtqY2MOLz}iOZXDql z0nBLAx228)22jh=@m!1m8-4#7D;7SlY|kgt*faxAdR1?^-G`N3#7m0 zPjGb#pjo*!A9e9wE1Do;9)abwX?}*3izr?$;h@%iOqWbkd{b*rAn@bO8yuU0TyOo{cGToy8hyX`91 z1~J7eZi!^}mGFHF1=osL9a0w~Rp?tE!nUq09p_`EwN1+6Npdw8I@#`to;yy8STd@? z(Nt9aGAJoRj=$z3J^z}-yP_!(muTkdN2*wo8I)v(KE0a1HX2%QNpUG^@vj1ctUmM? zP1N}V(JHk9`R}5;A&;u)%%<16 zi!Sme1o$lI&RbesR5IS$LYHFu!o=Qsy;2pPDH_3-ORCm>8etaY(t- z6IDv?7v+^@I`>80HGW^NdiQ?Znip6K$i$J&7f@F)L2Q+fnQvJs0wGLwjw*g7p#<9e zg&YDyHDM0f7xf3A?FD=)2k%t8Bq5o}4ElkD5^3`-OD!c_hAU%d71{i9{@)~O{t?tQ zl}zJYikiO%umLn@>VmSolKe%e>N|o_P*`4pdmJMdrRDDbAVe%<{sPiUoOddv#1+L0 z%8TzT#B-Q8SxO1;%zVkG!n1(3Jd4~?^8q#&m*AdHEs;_}L?kc7gOI93v6#~<$dia# ziyQ@|xQ(W^px~RzEz8UDNs^S>A%$`RUU>x`<<#$hxrkuKQLo^3DY=cO_T#pktC9CN z)L5EV0I;6-cY;B{4Llca%Qy`FNmRYOxCHGdb34U_XFf#MHq?E%4j`50QeQ*CS5R8H zxd5E15v+g;iHU)>h-hTMR$zLc9`kIJnm;K9+J8YgheyY#`8NZv;40n$L0uI2BMTfk zu=8W6=y^XUlVTo?S%Pe9Vlc-~l=A=pbupNK3@CO$c5jqWct9{GhWwonrwd8)Z(=A> z`LY>hh0Cs@Gzo;lIWa=v&X{x|6@5UEE~Jr#T-E${fxeI%-yESr;YTr~S)-yc4&@5U zKNvM263EhpWL?l5L-9!6&%}_YXc;9WssR9@P=V41QDU-;;>`eLlI#pnGG&w?f-y-( zvfLu0q6}B_JTsoBSVr*;B$I{9w2EZPyB*I1vfqG~owCTPWD|iybO`*ffd6qE{v@&+ z=L1|LD3I7dvJHdaRRYukctFr3_=B)OLPo|xRBt3pCct0jRywU{gAvOr0GfcP=Jya3 zvWf!41I~HCDK$SxpkyHhs1W}Kz>sv|h)m6gy?0c;WjVJLtr6TSIe;Y{dOsFR4T7A_ zkEMojmEx-A&jd0TJ_RZ1QUX~Ni~b@3RU(oyD%uiT5=&UVHkR<~&R8sEC)#`zZT?Mc zgcr43!Z?#YMZ#O-34cI=dHMN;rDQNS39bkaMl}iM3u**}k{v+26k8)02CK3$v^L;5 zh>8wElA6%aKgJG-Mq?wIq)A}K)8CPLMsPrIBZTw->Vz{bS(^V^Fe)<0N%02+G2-oF zmvES$BTknOh^ER3-6A=r%5vQl(oUf^c0hJTI8`D9V`j>E{Bj+@+5Bwz9w;XrRTbxg z;+o1W^A{s|I!Rt8&*sMfLCxPN#}rg>Rc6R?c^2f@BOpCPe%1W#a?EE1L@;a6V<*Hf zgWz=hdO)9={~BmnWLZkYG#h6|y(XP1dQEB*k`?#gBTt3fNWV5S?C*} zb|(`sS#cbbky`E2CXSc4Dli*i@<0L^ZtJ0or%|MsGT<+t4sb6xKv6d-%!(L!NvxXx zpn~E>;58WUku;B>@@o2S1r$tSe(|!rrN~Vr?k=uLZz(9jqCzs7vY{d)urE>jB8030 z@KF$@=C>=zWVX~ogyvB&2pcX`Hx*Bvia(&?6Wg%wKwW+W{5A*P#C4k_4pJP^(B=Fm zq<_J<(8N*V8RZpaIGqZmcrdoEU@UpK#@`%AMVq-nQ%HJcK=!tf44iwT)qG1FC9JfR zMfB@UaTZW_YaHoSkKixSM3Z?0uIL&_-}7+?qsSN}C0ao7D1JK?x5srV(!pYF>=mwq z9{?343-ioN7v`ZNG8Ga*{%jnY&q1}Z+5DYc2dnwV(U9V0%L)tT0sUYU8OrBC(Zb>q zLecY}WI({m(8Ebr4u>fVU*tj+);GuT=B9kbmAa`H4){po_J!Z!3ku ze&wjBFg{&)Om+;pFpY|q#~*`!Pe;RVi+>hv7#qWM5l=~qOTd=WvO*$!Pe?!Euq}|? zbZHg3-Ua-_@jN9_Ie&@Y7e!dNK(s7sRP=JZg+CzrbNn93far^Ob^NI4{rDwHa<7ez z!RVO>ojWTwCt*OeHJ($Z@lf?j$P^($&HpN%65h6) zTNE9Yz6*LzNq-6MQPcytpDV2qOqKo(%6e^lgrZT=jD%US*>XYEgPIs9LPf%8JOlxW@r$b$yml@KG(NjQeu7A5dRT*`#@vm_AhcV7aye zY&mb9B>~HT1S~MIY8+46$BF76P{v9Ey&K>^;_b3+2z#;cNrZ|jE||zj zv7MMiRQq>V&y3EsgdqWBM@J`?Ke zPN+$|FR=|Yc|g;xfcz4fqqDw916{VIELRq9&$l#Ck z3sL2{NfUf0+$XX*FNri-lEmW|M;7a&q8}xliW-4fs^%9Y@q`tN3duy!sW>1=0B9vZ zg-bb}WkbLxa1RJpC#m_Hl6X-I3X6(MoSll_;2tZF;)ud0rIHf=2xwkW9=A}6si*=hm=*!ISa?WERy(Jm zvip-MSz*bF;xbFgvci%IqL?G9OwGTDEM%G@^L<46h{`F6{dq1>r;uT$OriMG2@)yy zM(C{jQpjC4Ha|B;k%f~@xCx94k5!46r(k&u^n!^=o~+n!Qltxip5pH($(h~o#O?M= z*zVBctM6TYl|l)OW}*$q%I5&)N%BV)Tz?@cWuybiY)R6{s#eVhfbeA*H#3|Cu}iqQ zA{{&;+ZQAgVZNNw4zlnN*=pz6EH4&8_r&DGbH5%h=&Ehqi$Wb%1r)tWo9>(dLc+gnx+omyQ&AcU6N)#*E!u?EcW%8QjmXd<6EM>*kn|VuF;Xf=mbG4(eVtH9fN8z#)6_(QD%PWqT99zD0>8ZTpiX(*!+bv59kKpeF z=B~n$qs1kK<<6z$r-}_^ZYe);TUkd*!BI<5%k8C3JQkOn%qy{1l(ZKXE;)j~b_=RKT3B+TqHJwQ}`Zr(7{7;mr@NtD*AOY`SS14*M;s*tqG@b=Oe4u;gm{C>)c!m6Tq!c^zH_ucfeA zq81dFP#Eq`k?aKJ>Y}Q)_fs2c`l%u_MLeWtFLwXwmh{J7)V*-F};*e7T_6jjQVp2Hm?wLFfa#Yw)*9oSQ_+mi)H4da>0;YkrKo1dU?XmWl9V7}hDnW2n%rJ2&Zjr zj%UQofS3;6`yc{=p*}bjUak~W{#<Mx&XQM}az=^Wr`bT@=>2+oEmmj%bsawpkqqqQmpduOh)3 z&gxka9nR@F5Z$TF7PRp8N4JP}TElC4s-na79aYhRRn;Xy`jZQfL<@1IL+fXbN1}sl zLYnRJo6(k<@UIGe`?Kh9vE$2V z5Y<)Tm>OM#h_oHipQ3&`UY6i=L~Fm*#V6oDm+7Pqp~;OWb&h{VN4aGZw8k8j=@v+= zq+Lmps7(Aik_a3#8w6Q9q7(5Nk%4hbEa9E*-e^*Ud%6S%tn+ z$aE_$bT><)J_Q*$##`wTJM(;oiz!gUn^@6|3^O3Y2p|$8YqmosTbP+rKN)m2AGzbj zj7iEYhV%Q`Sn^p2uB!S;W{n^9V{o|7N-l_{T{|txIfAqV+l5qVtRq#5<2PQ%M+4gh zTI!TaS%X)n>(cpMY^R}1hjTJQcjD3G|8_h9WFRo?-BQ2PB#odt-{G6rLb{lc%+4}h zGF>IDC+L)NEJ?K{x`4^ zXWQw;sv!K2eY)n0&7f0zamFtNq z8h58CXt47T;@l|Ozj+pfx|<=9nY=W{!%40H4A0K(^C?Z)$xfah{c{Ci$1?|NbDXE zGectDfYkX18Dd+$DzdX&KbwC$dUFeS%XnqvnaBg(_lfu<;dG`~EeDm&$z#j|qD$f5 zs)deDD9~XYc;RT5neL)(4y9N-ARRLMc_zH@q-qyIIkbM-N<(Ay$(#c+<_#sN{kYSV zOOG;5ijg7kJcId2;hrDM8n)30ObfX{4-@=T8n-xxk;%eSo1K-hsLLAuwRYEVD7HCH#4Sp%I?U{q*G7SmxJ>jYoc+=yyI53z)6dc{Vnif=0w)7SJ$KTpFP;Odefs z>u4jMMx6hOHJ#v83d!D)EANtbDCIMpM)@csO#!`AGDo`JVcpZ@C~wB&K*%ZLCWa_S zw%m^vIDZ>EuWa4gD$V*WRS#>nZd!iKb>UMTtRelwzpU86680=7qE& z^q-%Ivs7&BhIzsyCNat93wi3vaM$W=ITMkPfZc|!?7gVZ|yA-dFQr4iZZXzCEl+>+ua zwKKj{ZW!A4;LiPuf+(hqtDU{lOBnuWvSWbLaBCG1go|^~z~9@xcAgM{EBef2suQP@ zyeeX5$LUtnhSjvaCR}r}QDIG{x(@bSRD=Z`xbRZm{k#&xS+|@lRGdAEI-BDLr4^4| z?|H-G_Ejh}_h7xdK1uxeD(%a{)S4Bax6_c*79OK$$zRMIPQCp$GJ~`jmeWoa%{?!qF}|3NSK`9I(8QB=FLH;};RWuyGt_(}hu?G0jtftBzmOJw-~F37bV)&C z_+9r7Wq7~)orJDWI^K_CJ}1h3iYs{sV^^RFEMrSW-56AFC=odjVvasNdK7~V77REx zDK#&z<>_|W3(H=auhzuy|3)|wd3 zYz@EHn(4aOI7$ZLNX$skJ``k*r{eI8m=Sxec71|FrF_#;^TxS@mYTnv)6P($?u@#W zRmp2>K5uub<7O&rZ5ejYD3peFtCDp~(g-g)nbssLO@l+8mQm(t68dqZ(qI3#*19g9 zxABXd_M{u6O|-zhQaR80r_`L^+h6}`>^0}>smXVu#SuziVo*1OS)X8cG72JrtwiW~ z&nsIn3UUy1*%yQUYqUfd-_xWdfHtKCm_3KdL&sqyqWktJbAX}PMc}5DbguhX@fXf3 ztzCNes`y4s!EEUrhD}75DL2#Z<0`}bh~d1RJiBj*M@&pde0MuiIXDO82d;NeUwv42JyOh(&La=zb=PXQ=Lk76ttLAgD9Tt2;7I`t)J13zr{oPLA`Zb~hV^XWJp zZx@iXQI@Go3;IWL9X;`*3zh^^F*{+iffkGtPbCN{A=~!^r$~aCnWP;fJ$VU57Au|1 z8SxE`f~txp` zmhCU)l_L62F1=N>$GI;RinOTFxgmiGCqOImx@0&o4P%*;cCr@o6NvzO@b_`SvLVp# z%uNJxC*&GQLxdr92i=T_tod2==MdKIhAmh@ZKhf6W=JDZD(`V(gbCTN+YB~u!QUpX zL%0dk->gms`%uMxa{~n9lOkrn(usQUKR3sq4Lmxz1yap2uO^b^BQqzFtzy1N!tso+ zCSpcJFm|$S@w+lbx>8m?Mq6bz_Z^9!57-XhzHs9jrw@rG+-+(GUoPfr92Z zM^+cuclfQ%YBi{!F{crp`BKwwXeD!0IQHmBtibvEM4NnMbexYfETS<95!IeA6S0?} z;eS4&PJ@OyJj#1Lu_dy@K_{@lXR)sdqDF3W*`4T^mINse5@{#0MUk;;W3rN*=M(K$ zC2j?&zn+!YE{r8Yi2R5+E0G}6@`+5mjHH%}4aiFP|E;YR=Z2LNdRA}r`iJm4#ID}h zZXX%JK`kzif5*qInF}*Z*v!mLzn~GaX5|(j zPpZ><&?~bNJV2`;{^%MFO!fTMFq*) zq`9;7j!7jE${c5siX`9_4qeNm2{oCSptBjAckv!eXkl8C8Y|HsR$JupM{H$eT=UXg zI0I-_A`_Q_>bKfaDbt+XIAme1pZ3g7u0b647RZ3zj|J00dj0+26rv%|N#vvhgh%i_ zooRcVnaM#b(~>NVLeVYivG5dkT{47jDpWNQ@sT0kwB(lDCK1(cu|E4nkvHGPfQ%1P zRzU!#6rUOJ?rQz-clsq}lzOT|rWe-P3}MaVf^*I_8+p z`B(yTIoY{ahwG@C;wJZRCu+3=;lS(ekz}%D1HSQ(Izo>V^h6fP!5B=AA{oh5j}y0I z(nxVwJdebXQA!B+#JjYzbV!SHQ3|eFy9X0ijja_cYn%Ic>Yk2!Q)c7@F=vvQ#qJ5G zwvRI3r*0TwVpSh&x6v1Vox+4tI*z5#v)t{X={$y3Igh0@?kTdqyo$EIR7qR^Wa+z< za{qmeMYUK%r7W&kS5?y$9UgSNlF|s(>WZ3Dmr_~#d&`A`DK&Q$+T6!dwAJ*J)g2$C zwASFx_S0a>LfRT=_^ZWvJT<*Jv02tEZXC+VQ>S2WDhN^jTxDTUSUQ{h~%ZCGE~+#VG> zJvw7UZO361Yxot7-H7Q)`l)MZo3`EYfy(a!@fH`D&(rKCb&(z*tL-DA>0_v3)+|I^ zeM5)KtK{;ME-%< zN=-_UX`e0y7`1;p=#ZqcX!mSCZou9en|pKW4gfxAD9U)J=0X(?oUX=fh2F2ubb*Q) zew+Wo2Pr_sE*28=6~CulR0Mt?57$9Ngj!9H(cu{>uQlh8ETUhd6-c&h7EyF|LyB{6 z3ZUO=AET|`G*n|hN>)CG$H?->1z{x1B}~eXVLuAK5luywZ7$_DS|lV9<)a+IR2RuC zo|92MFN3D5YjJ1E_`n6?pGnpJ5lhi$Qfpg*@5m69dziU$6n>o!fF3@fbzi8SAGNt56%*YV3VS9sc}`!8wXOk6UV4^oOM zSIyv7Iv3Kgl4R1tg$_>|8Ln&`u04s967k&l+$x#O{ns?Me$V&k(=H6AjWS)TksQa# zG|$LUTWZkNI?7aI=5}>f);v|zf|I-O)RhH6^xHkozotQCnAagJ7}WJ*@#EqrvFUXl zPGhxqkoSQ8V58_oW?!mycOt8;#hmy|YPRM=-lXhlbas~ehe_;Dwp1)CuT0|QKdbzg z1-ok7=}nVHm|)tdvvd+i2}xzLQ*yusNF`4s7}=F``RPgF=#Hl+VNb=+&GnBen5GU&~AABNnYGd)Yk%PEoU!?p{TW`;#|GMsYK@;jf|!m_oL|-=BL{*s%-AYl+Kpg zi#tK&g}c)+@Yke~^)X&6Y|rpR5dDzIK3zJx0BH+U7>$ps$nc!IOL^L^hex1=z2su5CBVG7i%_E0**rei4B7dszUMbDr9zuNou@F=P@@9M7Z z>Q40~-3c^JLXxU(gigYx(?Akh(h!m+FpxxZF-C4OiolE#hs!1*7jYfM1$SZRqK~dS zkF%pQyD)3iS*CT|osUi%pH#9X1~$kK>-IG^+FGk?sp-}9Y@ zRGss_?>Xl^zjNwT)v0sd_eZ<#ub$VuUHj;sk!SMSZ#jIpb7JCw2T*|r$pD1{><>Bz zl@9ul6V}P$bQ#KX$gre$um_KWgi7AKR!)mW&doq`ivQxevL#FGb3qQ_-bY3Z9MkOH zx34+{f<)1Ob}boUIe6xN)c4OW@w-_H3wjPsZ)-ePU0t|0e?{S5@fWUzou`g;Z^&vk zPn{t@ISn~RMsWS(Uu1dK))!Z7ee&!Nw%G=DZxws8NHu}Qs)y`vr>aBMhXfo2LsVRp zvM_c+xuOd%W})vO6dJz>G(cZGZS21glCvVGX1txcid6dn{cqmNe&p_1Pwu;Yp?lx^ z>z{jMD0S6CB)by!Y^70M0y^ocU5`yQE=JD`LEU z?MFGn=gPcDo9~1RhDXUAG+ukk6|X&wDDI{(t=vhTg0H)`D#0_#L#6sw)Prk{IEOUL zZ)Ue7ydEufpt#!*0TE{KCn;pMI}Fjt)F~Assc>ANeckZ7x4MNGlKU!NA(4l4nadfP zmE+XoT%411Yw&40jQ#gtlIzJczd7e2jC8Kt~EIYW;kXSh$0_vCmleVM0H=AN7c%JeOjvOOpv ziq8%B3`<-hZ^T@pvQuYFO8SMz+)30WHwh7^HXa;*Cj2r!+Td9kGdy@E8Bac&3@dIs z?I(okXC|Lk&W!dfAMbQ;>~uF^?qOqR!yp#C8xMJG6^gl1;tchYmqp3pVJov~+tTS? z4P2D=FIE=MUw0fBjShd>(O=SEGJk}{BxzJE6QU`8eC5GrDYHemW?ic9UMZZ@oxH!i zx_^t10%M0Mt(BS4vz6xP*)OomB_=WOh(;551aW>N&!+G{e&rVS;4ZCIn% z#1jIZ7Ozz?*H&nv!^61h141-6{+-eIcd$M`>h`kOmoQo)K%s$aJGIw#uy_r;Ha&(S zY`xMQa4TGcGs+r(=}JguC%9hIu!eVKUeHzLmLl zC2H~iI2WBmq3xPnA$^E-n4ekVwxnP5{V2GemY_S=HL51;$t9n#F`-;gYrl* zI4ZIxVjVj@dUh0kO1_^K`AM3*$aET6EHd?~M>W#ad-`5NJf;xeY?5M9Yb-q6Qw>~3 z&&dC1RyLbxB$PN;PjH!yP(CAn-$c$+hY=V((|&l*^nokuOuxLa&V)%pBKsKO$Pb%w zBl?ht=H(6}z%lY)o6q16X|VZj&r74-1J({?8}j5$9~!Wh2$!8Aq~}+DO?nhl0t40_ z`5rSikPRpxw1locY>w5M{Jbjk1uf&Ak2i4=~CWQ2e6#jC%2ggk`c6Dn;EaWQynm> zT?kvW1Jdxlvl#h%=F*PX7VCr=Z10unlDgPKY7d=9FFIhB+Q;W_>6qW-9{c5mH?1w_ z_Et#khcEohJPI8owfm4(E#aYac_n#`R+KjKe%)9EozTcz5csE52|XEZ1qSV(S)V{x z8^{=cB8_x4OwtbYv8kP*E0w&gw`Pu|VFo#5Co<@|gZ67y=W)bI_uFUpd;!b*PDEjQ z|9l8Gzo&YprKKa=wnV4!UR$EjW6Xp@fsoyKLOyDTsk|NqI{P%oFzTHTm1Czfeq52B z@pQ2+^93m#gS|z#lJ1OEWTd~`OY*e{DQUfk%kg&x1{wWo+Zf8N8tqaU{euThA zQ{ZnQi~lj_8N8hV@e9AUaC0q#Fb_OvA&o({4xO2csR!qUu%$J0<#!g$&O@zFTSBje z?CaYS{6H@Z{eyCGjeOoxsW^0!FI(WwNp9|n(Qw~Cq-D0JWpggvW;QdGA?OGdr%2 zJRYckHz3cn4#Xho{F!{xoV>UH6@ub42iS6@8NCrv^@t9Is>`=phFE+T&^SiZ)6qM{ zH06SJV^}?Dh6)%W#+>gH6_qGt(ZL~ybj}M_4n4`QM-`o~A!JcPhY@mfxRNTJUIb^( zB0&V^%;`ZW95BAp?XtmE)reekc`Sx_+-g%Civecj2&ouo?MM4Qv*J#{qTgV6mwi@}4HEwX-%?W?VoS1m z=v-oZG7QH-8U{TM*`mLVqQ7Co7P`~uom&?N;Opeq9%pC%Z-nvASA{WUGPb-@gbi(= zeHoo_loX)cf?RqGSW55g8zP;~lS0bR(>t7hz#vEZC>g7-WZQpvrPNLYaT7xC9SdEU z2Zu5k?Tb^YwwjmviDS+;ytM?;Y6xn^)rt7Nay@8z=Xn5;?AKi`^bB6YXRwiWgOg) zpv4@hd>muRF?`w!*#j2oYmbiCeUrZNDIG54>JIkT)K?vRx+>Uka9v|l+cO^%|~d3gtm~-ZtY8FBTKX-^R?aTxs-@4Ct_tptQ=yH z@O$|L(+7#g98naKhAk)}~!*-Im3J2%!?Vl2qCtq$fz5<@J zp#?gztmYK!wtXfKv8dk9*)DL1&Pw#?jnUU`jGml~`U`jodAa7{=|-2(^oqiD;hEQk zJ;|^H&ntZ1JdBBK21<47s$Rjtoo*ZJ!d$r2<@55%{GQS!Gebbl2>~^mr*snDJCe0v zx;N-%xNVo(5=`%){5`{f{FotVRcpv}cVI^RVV&F3y;B$2t{Vm)cXUYDQ^>JxNes>+ z`gAua)m!yScaLsKn%t=GYDU{Hflip==+ngppy#_1wC8l4Q2uv1peL=bBjJyAY4B^3 zly=)bhC>p64qxquf3zIlpT+yKdH)RFm&N-9-Zz8y&*Xgq@AvS&nY=%j_j!1K9`DQL z{rS8vkN3~!efhlK&HHBatv)wz`!~M}d5OHw#rtpKeIoCl#rtjoZx%1%71qIsCydjl zV_5Ys;vbsrTg3Yp^807|7V`cD{2R<{-vZw6QvyEN%9lhRZ}*cr;_m8B_i2ER+-D8aD4TgP25V9zJ1B>8}TvLGcXx(BE08NOaJHoQT8pNqNw z4=4E^Lo7c(|Bu8ksp4NheUtc~$lVRat2hY@1jJ&s5uo*e{aLKyPWd`@Q2eDqX(u8g zWoH6`?6o+cG6~zzLc?T(Y*cBaQAjZRW)h!6WNyDvW)Ar?nX??Q#Y(7RaS7Z)rh{5s=$<2}YEV~g=Y<9_20jZYh&Gd^z&8IKty zW9Hh0-kTQ`-8U0~g_D88$$)P%u;AteUPWfnB&A?7P&CQxE{@I z+BE%4+e+c_Wj}b3%ymGkrM^X5GuJAG`-;nmnkca7zIXoQZ{~Y{@|VoddtZI|ni`=* zXx@oM(;I>tZr@P5p%DAVpLWG{Ey1$xv-5HR%n<`*-b}IsEPK%AcfQMVuS1 z(d5f1&P(J;iPKn_jby>zm^9u7>KJ)Q;uvdkD)XD?gTAZ)3Yxk3|K;B|*O7840u%v? z07ZZzKoOt_Py{Ff6ak6=MSvne5ugZA1SkR&0g3=cfFeK*hQWUMs>Yy+zo5DB`El-wn5H@2=HpGtn2p3t zCee*OUpg#djn_I%qWPLU!yx{zP*;3;fbsZ5&9fw=@p#0XbQ02fvc(*Q#(JiR!Uu$= z^YCK#vk2(Bf5!S!O`7wcAMe<=&$s={TvJW`zm>an@&R3<-jkQOt?vna;`Y9uu!)+! zV=OiR{8W!!1U-7}0+`Sx3i|Hnuz_F?=R79I^&yX5{zC5@7q<~L{m_>;J?^ubV0LGU zDUk3@HQApriD{<7DI6zn)}7$lMSc5O>s0w&y)%xj3T-SlEj)=$1j2h_mPx)#*X%B? zQco3D27%&b&GBa}-T5pb7B3KUOx)hCN8Gln&kMo4DW>@9EK_{Bu(Y*gBqx#6{-5u# zA;B$9F)eg2!Y-tD^^pr&@e|&;045KuCP^WQYk8+noSWjDD<0>a)5U-1om0f8d1tD) zF2%`>Jfz*CBA|GJg#2bx$YW9BEhO%>tgy_Hun8uS zG>cOguszc3x0ocq)dWKw4pT@li$@i(rqyIWRL_u2S~5mkXzXHBH|0fwx31zvf(g_LYvI@nN1NW)JD`L>UoQ&B>Z06 zDK9QdS>#A(pU*kRzb11YG9N?6L=wXmQzNGlO{S{jaKZ+Yr9GVXh8Uy7+6Z%;w5i9M zOv0;4#*%50Q6^GLp#`Z;m zBxiG`k=<}g$e0WXqzSGP(21>Kr^%IJ>H)ep!YjYUg}(yp1JVL2VE-iwq#eaf6Q>JI zJdf^{Z~F`tC)jHkTYRn4l!pwXoy-x=*uR9h!^=6r88)_`i*M;T_j1#oa}PDNofGuk zA9EX{?y#xl#qMD)UaP1h>J52ufCq9+u8op?i&So~W$oUDezP|8qyYFyb;i33y zY|cO5yeE>MSU8^K*$?M+>`W`%yEARmJSO06?yUNk{$`J@wSSxEV(0S+>aFL$=hRe= zAyLMr?SB`JaEFFUwZ$yJ+SVTeFLjC`Z!Z97?bSZk4ZkTNs=mt6dO3~tFI5# zL#Mzq2z^f}Q@9NAv2l{$AStYHQp3W-9Yp)R$+Jz>(EgQ%T;X}^gcDxaNHSuqzoxp9 zSmM7OPQQYc!iqJewJU}CTVPl`SOYtdL;{`^f;B>;P*+V1bFWxcQ>m<3Z>WKD9ISj- zWYk6Ob?`n{y8^=1D}+XP7fNO%z{ODo7P{96C``#TS%5%X*age6ja4A-UlrE!(yG-Y zPgRq$m8)(Ms;cXR+WK2=fn%0nxgt~(TwYyW2Tw)9ym|8!N?G+SjW@(g*Ob-6>D=`+ zxbmsJJ`R)mHD%Z{q0~VwPp#C7Qn=kvOH!&-xvI8yRdto{O>{UZB<=!}Ni4hv_W5f! z!;X2=_MJ`lZWhWn|JAm;HVbM&o?4YzyLrbpSZ$x=C7HM73Uy6ewjfc%j%~X(6Z8Mu z?rBXjYjTB}&EIZnf*n#%eXg*4^A?yQufPB9O}pSUz;k=95Nz4D3-;8Bdj(-l)26#O z?*P3#S18|o|GnGpf|#)4-c38V3hn|T<@SMFkShQM0eeGMt4z>*DvfLu`I2biYd7Bu zd+(|$fDUdAv6B+5NBntI*VhTbnwsjGT0vBm1-7hd#((Yt*))FypE*g57!aFx|+sh!r<*?!C-k3_b>Tn!Bw{f zg}POhL8yh?7-j366S-!$8DZh`LZ;QX+*sl(Gva-`)F{G!OhPl1tr>;_ zv9lSW-gK$|bG#KmxHlmPobwV1$**XNt^F?#VmCFhRyKXWc{U;R7D4Wj7E76@(0bK*Bo3Ctk-wyqOp*0 zZoV&Q_Lmr=%^Lq>+Gw*jTFAU0w`fn}#Ub&ca6H<{hCEV<$6w-^Q{pj|2>%h?u8-cs zbxC<;W|-lMY4l8rW-o00jJnFq(L$Dq7U~%1zp7FoIf>9Pk&-{qL}Si(qQl`H`LHe= z>iN$*^iTmc`fopOOz8jHqJKHTfbrx8>$*Fo)mhrBW8?d+Zdftin ztz+?4(536CYKlAKcgDAVjRX1krua5cE3!5HC$38bM(N27@+wTST*+o}#%pFr&+s<6 zNf!%O{8TXHw;vTgDUwIk*mG~+7=07QoO8;jiTh}3XMF>7FQ%YYNzgX4mN_`V79n|Z1zmKjdhi>c|kV5 zx|B^p{Kq5$W6-R;SO@JZXACV>Z4P9Ozv$srNGI4bk?{h2#1tsrSYJbFg8$ zHx((>s=<)feR_#hNvl?APyu{|f9-B|fY3*5eVsZubk!M29f&rGg205Jli$kcoIF31=x8M#Z~$(#)7O!31k}z##vKlYh-cJG0~gE?dWG<-=UI88fJdIgP+X zQwT0$+dvn(2Z~`ZWJcW&ZS)$Z2)a3fW+vuTgi&a(xvG)Z7@{%FMNKp%TE$0KfD>PS zELvrZu1I;|#ZiQD9d$`d{z!N?AKhh&?leYsz`BJ1sM(Y2+E1?QP_b+a^+|>)fTt|} z(p2FKf?#Exx1d01*tVxCST|Fs+Ptf|X~%bk<;pwpObc%Sg}fjOI~C_?!sZ=2n(z*s zmP8St2v7tl0u%v?07ZZzKoOt_ zPy{Ff6ak6=MSvne5ugZA1SkR&0g3=cfFeK B, start address, block length follow + .dw 0 ; R0-Port A, Start address + .dw 0 ; R0-Block length + .db %00010100 ; R1-No timing bytes follow, address increments, is memory + .db %00010000 ; R2-No timing bytes follow, address increments, is memory + .db %10000000 ; R3-DMA, interrupt, stop on match disabled + .db DMA_CONTINUOUS ; R4-Continuous mode, destination address, interrupt and control byte follow + .dw 0 ; R4-Port B, Destination address + .db %00001100 ; R4-Pulse byte follows, Pulse generated + .db 0 ; R4-Pulse offset + .db %10011010 ; R5-Stop on end of block, ce/wait multiplexed, READY active HIGH + .db DMA_LOAD ; R6-Command Load +; .db DMA_FORCE_READY ; R6-Command Force ready +; .db DMA_ENABLE ; R6-Command Enable DMA +DMACode_Len .equ $-DMACode +; +;================================================================================================== +; DMA COPY BLOCK CODE - ASSUMES DMA PREINITIALIZED +;================================================================================================== +; +DMALDIR: + ld (DMASource),hl ; populate the dma + ld (DMADest),de ; register template + ld (DMALength),bc +; + ld hl,DMACopy ; program the + ld b,DMACopy_Len ; dma command + ld c,DMABASE ; block +; + ld a,(RTCVAL) + or %00001000 ; half + out (112),a ; clock + di + otir ; load and execute dma + ei + and %11110111 ; full + out (112),a ; clock + ret +; +DMACopy ;.db DMA_DISABLE ; R6-Command Disable DMA + .db %01111101 ; R0-Transfer mode, A -> B, start address, block length follow +DMASource .dw 0 ; R0-Port A, Start address +DMALength .dw 0 ; R0-Block length + .db %00010100 ; R1-No timing bytes follow, address increments, is memory + .db %00010000 ; R2-No timing bytes follow, address increments, is memory + .db %10000000 ; R3-DMA, interrupt, stop on match disabled + .db DMA_CONTINUOUS ; R4-Continuous mode, destination address, interrupt and control byte follow +DMADest .dw 0 ; R4-Port B, Destination address + .db %00001100 ; R4-Pulse byte follows, Pulse generated + .db 0 ; R4-Pulse offset +; .db %10011010 ; R5-Stop on end of block, ce/wait multiplexed, READY active HIGH + .db DMA_LOAD ; R6-Command Load + .db DMA_FORCE_READY ; R6-Command Force ready + .db DMA_ENABLE ; R6-Command Enable DMA +DMACopy_Len .equ $-DMACopy +; +;================================================================================================== +; DMA I/O OUT BLOCK CODE - ADDRESS TO I/O PORT +;================================================================================================== +; +DMAOTIR: + ld (DMAOutSource),hl ; populate the dma + ld (DMAOutDest),a ; register template + ld (DMAOutLength),bc +; + ld hl,DMAOutCode ; program the + ld b,DMAOut_Len ; dma command + ld c,DMABASE ; block +; + ld a,(RTCVAL) + or %00001000 ; half + out (112),a ; clock + di + otir ; load and execute dma + ei + and %11110111 ; full + out (112),a ; clock + ret +; +DMAOutCode ;.db DMA_DISABLE ; R6-Command Disable DMA + .db %01111001 ; R0-Transfer mode, B -> A (temp), start address, block length follow +DMAOutSource .dw 0 ; R0-Port A, Start address +DMAOutLength .dw 0 ; R0-Block length + + .db %00010100 ; R1-No timing bytes follow, fixed incrementing address, is memory + .db %00101000 ; R2-No timing bytes follow, address static, is i/o + .db %10000000 ; R3-DMA, interrupt, stop on match disabled + + .db %10100101 ; R4-Continuous mode, destination port, interrupt and control byte follow +DMAOutDest .db 0 ; R4-Port B, Destination port +; .db %00001100 ; R4-Pulse byte follows, Pulse generated +; .db 0 ; R4-Pulse offset + + .db %10011010 ; R5-Stop on end of block, ce/wait multiplexed, READY active HIGH + .db DMA_LOAD ; R6-Command Load + .db %00000101 ; R0-Port A is Source + .db DMA_LOAD ; R6-Command Load + .db DMA_FORCE_READY ; R6-Command Force ready + .db DMA_ENABLE ; R6-Command Enable DMA +DMAOut_Len .equ $-DMAOutCode +; +;================================================================================================== +; DMA I/O INPUT BLOCK CODE - I/O PORT TO ADDRESS +;================================================================================================== +; +DMAINIR: + ld (DMAInDest),hl ; populate the dma + ld (DMAInSource),a ; register template + ld (DMAInLength),bc +; + ld hl,DMAInCode ; program the + ld b,DMAIn_Len ; dma command + ld c,DMABASE ; block +; + ld a,(RTCVAL) + or %00001000 ; half + out (112),a ; clock + di + otir ; load and execute dma + ei + and %11110111 ; full + out (112),a ; clock + ret +; +DMAInCode ;.db DMA_DISABLE ; R6-Command Disable DMA + .db %01111001 ; R0-Transfer mode, B -> A, start address, block length follow +DMAInDest .dw 0 ; R0-Port A, Start address +DMAInLength .dw 0 ; R0-Block length + .db %00010100 ; R1-No timing bytes follow, address increments, is memory + .db %00111000 ; R2-No timing bytes follow, address static, is i/o + .db %10000000 ; R3-DMA, interrupt, stop on match disabled + .db %10100101 ; R4-Continuous mode, destination port, no interrupt, control byte. +DMAInSource .db 0 ; R4-Port B, Destination port +; .db %00001100 ; R4-Pulse byte follows, Pulse generated +; .db 0 ; R4-Pulse offset + .db %10011010 ; R5-Stop on end of block, ce/wait multiplexed, READY active HIGH + .db DMA_LOAD ; R6-Command Load + .db DMA_FORCE_READY ; R6-Command Force ready + .db DMA_ENABLE ; R6-Command Enable DMA + +DMAIn_Len .equ $-DMAInCode diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 81761114..33888bbe 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -2339,6 +2339,9 @@ HB_INITTBL: #IF (DSKYENABLE) .DW DSKY_INIT #ENDIF +#IF (DMAENABLE) + .DW DMA_INIT +#ENDIF #IF (MDENABLE) .DW MD_INIT #ENDIF @@ -4645,6 +4648,14 @@ SIZ_NEC .EQU $ - ORG_NEC .ECHO SIZ_NEC .ECHO " bytes.\n" #ENDIF +#IF (DMAENABLE) +ORG_DMA .EQU $ +#INCLUDE "dma.asm" +SIZ_DMA .EQU $ - ORG_DMA + .ECHO "DMA occupies " + .ECHO SIZ_DMA + .ECHO " bytes.\n" +#ENDIF ; ; FONTS AREA ; diff --git a/Source/HBIOS/md.asm b/Source/HBIOS/md.asm index 8ef62440..d7098c44 100644 --- a/Source/HBIOS/md.asm +++ b/Source/HBIOS/md.asm @@ -350,9 +350,14 @@ MD_SECM: LD HL,MD_F4KBUF ; POINT TO THE SECTOR WE ADD HL,DE ; WANT TO COPY LD DE,(MD_DSKBUF) +; +#IF (DMAENABLE) + LD BC,512-1 ; COPY ONE 512B SECTOR FROM THE + CALL DMALDIR ; 4K SECTOR TO THE DISK BUFFER +#ELSE LD BC,512 ; COPY ONE 512B SECTOR FROM THE LDIR ; 4K SECTOR TO THE DISK BUFFER -; +#ENDIF XOR A RET ; @@ -466,8 +471,13 @@ MD_SECM1: ; DESIRED SECTOR IS IN BUFFER EX DE,HL ; LD HL,(MD_DSKBUF) +#IF (DMAENABLE) + LD BC,512-1 ; COPY ONE 512B SECTOR FROM THE + CALL DMALDIR ; THE DISK BUFFER TO 4K SECTOR +#ELSE LD BC,512 ; COPY ONE 512B SECTOR FROM THE LDIR ; THE DISK BUFFER TO 4K SECTOR +#ENDIF ; LD IX,MD_F4KBUF ; SET SOURCE ADDRESS LD HL,MD_FWRIT_R ; PUT ROUTINE TO CALL @@ -745,7 +755,7 @@ MD_PROBE: JR Z,MD_PR2 ; R/W FLAG TO R/O LD HL,MD_FFSEN ; A NON ZERO VALUE SET 0,(HL) ; MEANS WE CAN'T - ; ENABLE FLASH WRITING; + ; ENABLE FLASH WRITING MD_PR2: POP HL #IF (MD_FVBS==1) diff --git a/Source/HBIOS/rf.asm b/Source/HBIOS/rf.asm index 282a962e..263dadb1 100644 --- a/Source/HBIOS/rf.asm +++ b/Source/HBIOS/rf.asm @@ -12,7 +12,7 @@ RF_U3IO .EQU $AC ; BASED ADDRESS OF RAMFLOPPY 4 ; ; IO PORT OFFSETS ; -RF_DAT .EQU 0 ; DATA IN/OUT ONLT TO SRAM - R/W +RF_DAT .EQU 0 ; DATA IN/OUT ONLY TO SRAM - R/W RF_AL .EQU 1 ; ADDRESS LOW FOR RAMF MEMORY - W/O RF_AH .EQU 2 ; ADDRESS HIGH FOR RAMF MEMORY - W/O RF_ST .EQU 3 ; STATUS PORT - R/O @@ -271,12 +271,18 @@ RF_RW3: RF_RDSEC: CALL RF_SETADR ; SEND SECTOR STARTING ADDRESS TO CARD LD HL,(RF_DSKBUF) ; HL := DISK BUFFER ADDRESS - LD B,0 ; INIT BYTE COUNTER LD A,(RF_IO) ; GET IO PORT BASE +#IF (DMAENABLE) + LD BC,512-1 ; READ 512 BYTES + CALL DMAINIR ; USING DMA +#ELSE OR RF_DAT ; OFFSET TO DAT PORT LD C,A ; PUT IN C FOR PORT IO + LD B,0 ; INIT BYTE COUNTER INIR ; READ 256 BYTES INIR ; AND ANOTHER 256 BYTES FOR 512 TOTAL +#ENDIF + XOR A ; SIGNAL SUCCESS RET ; AND DONE ; @@ -285,12 +291,17 @@ RF_RDSEC: RF_WRSEC: CALL RF_SETADR ; SEND SECTOR STARTING ADDRESS TO CARD LD HL,(RF_DSKBUF) ; HL := DISK BUFFER ADDRESS - LD B,0 ; INIT BYTE COUNTER LD A,(RF_IO) ; GET IO PORT BASE OR RF_DAT ; OFFSET TO DAT PORT +#IF (DMAENABLE==1) + LD BC,512-1 ; WRITE 512 BYTES + CALL DMAOTIR ; USING DMA +#ELSE LD C,A ; PUT IN C FOR PORT IO + LD B,0 ; INIT BYTE COUNTER OTIR ; WRITE 256 BYTES OTIR ; AND ANOTHER 256 BYTES FOR 512 TOTAL +#ENDIF XOR A ; SIGNAL SUCCESS RET ; AND DONE ; diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 467d5d9f..fb944299 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -203,6 +203,14 @@ TMSMODE_N8 .EQU 2 ; N8 BUILT-IN VIDEO TMSMODE_RC .EQU 3 ; RC2014 TMS9918 VIDEO BOARD TMSMODE_RCV9958 .EQU 4 ; RC2014 V9958 VIDEO BOARD ; +; DMA MODE SELECTIONS +; +DMAMODE_NONE .EQU 0 +DMAMODE_WKD .EQU 1 ; ECB-DMA WOLFGANG KABATZKE'S Z80 DMA ECB BOARD +DMAMODE_Z180 .EQU 2 ; Z180 INTEGRATED DMA +DMAMODE_Z280 .EQU 3 ; Z280 INTEGRATED DMA +DMAMODE_RC .EQU 4 ; RC2014 Z80 DMA +; ; SERIAL DEVICE CONFIGURATION CONSTANTS ; SER_DATA5 .EQU 0 << 0 From 4d208094e7eb54762cc6c8f4c755c99f65f35d69 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Fri, 2 Jul 2021 16:37:28 +0800 Subject: [PATCH 03/13] I2C updates --- Source/Apps/I2C/Build.cmd | 3 +- Source/Apps/I2C/I2CSCAN.ASM | 193 ++++++-------- Source/Apps/I2C/RTCds7.asm | 238 +---------------- Source/Apps/I2C/i2ccpm.inc | 132 +++++++++ Source/Apps/I2C/i2clcd.asm | 517 ++++++++++++++++++++++++++++++++++++ Source/HBIOS/ds7rtc.asm | 107 +++++++- Source/HBIOS/pcf8584.asm | 25 +- 7 files changed, 863 insertions(+), 352 deletions(-) create mode 100644 Source/Apps/I2C/i2ccpm.inc create mode 100644 Source/Apps/I2C/i2clcd.asm diff --git a/Source/Apps/I2C/Build.cmd b/Source/Apps/I2C/Build.cmd index 4ddbf8b2..60b6a312 100644 --- a/Source/Apps/I2C/Build.cmd +++ b/Source/Apps/I2C/Build.cmd @@ -7,8 +7,9 @@ set TASMTABS=%TOOLS%\tasm32 tasm -t180 -g3 -fFF i2cscan.asm i2cscan.com i2cscan.lst tasm -t180 -g3 -fFF rtcds7.asm rtcds7.com rtcds7.lst +tasm -t180 -g3 -fFF i2clcd.asm i2clcd.com i2clcd.lst if errorlevel 1 goto :eof -copy /Y i2cscan*.com ..\..\..\Binary\Apps\ +copy /Y i2c*.com ..\..\..\Binary\Apps\ copy /Y rtcds7*.com ..\..\..\Binary\Apps\ diff --git a/Source/Apps/I2C/I2CSCAN.ASM b/Source/Apps/I2C/I2CSCAN.ASM index ff8bc356..5b594ef5 100644 --- a/Source/Apps/I2C/I2CSCAN.ASM +++ b/Source/Apps/I2C/I2CSCAN.ASM @@ -1,24 +1,48 @@ - - .ECHO "I2CSCAN"/N - -; I2C BUS SCANNER ; -_io .equ 0A0h -_sda .equ 0 -_scl .equ 1 -_idle .equ 00000011B - + .ECHO "i2cscan\n" ; -;----------------------------------------------------------------------------- +; I2C BUS SCANNER +; MARCO MACCAFERRI, HTTPS://WWW.MACCASOFT.COM +; HBIOS VERSION BY PHIL SUMMERS (B1ACKMAILER) DIFFICULTLEVELHIGH@GMAIL.COM +; +PCF .EQU 1 +P8X180 .EQU 0 +SC126 .EQU 0 +SC137 .EQU 0 +; +#IF (PCF) +I2C_BASE .EQU 0F0H +PCF_ID .EQU 0AAH +CPU_CLK .EQU 12 +; +PCF_RS0 .EQU I2C_BASE +PCF_RS1 .EQU PCF_RS0+1 +PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE +#ENDIF +; +#IF (P8X180) +I2C_BASE .EQU 0A0h +_sda .EQU 0 +_scl .EQU 1 +_idle .EQU 00000011B +#ENDIF +; +#IF (SC126) +I2C_BASE .EQU 0Ch +_sda .EQU 7 +_scl .EQU 0 +_idle .EQU 10001101B +#ENDIF +; +#IF (SC137) +I2C_BASE .EQU 20h +_sda .EQU 7 +_scl .EQU 0 +_idle .EQU 10000001B +#ENDIF ; -PCF_BASE .EQU 0F0H -PCF_ID .EQU 0AAH -CPU_CLK .EQU 12 +;----------------------------------------------------------------------------- ; -PCF_RS0 .EQU PCF_BASE -PCF_RS1 .EQU PCF_RS0+1 -PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE - .org 100h ld sp,stack @@ -31,8 +55,6 @@ PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE call _cout call _cout - - ; display x axis header 00-0F xor a @@ -131,7 +153,16 @@ lp5f: ld a,(addr) ; next address jp 0 signon: .db "I2C Bus Scanner" - .db 13, 10, 13, 10, 0, "$" +#IF (PCF) + .DB " - PCF8584" +#ENDIF +#IF (SC126) + .DB " - SC126" +#ENDIF +#IF (SC137) + .DB " - SC137" +#ENDIF + .db 13, 10, 13, 10, 0, "$"8 _strout: st1: ld a,(hl) ; display @@ -188,26 +219,27 @@ _cout: ; character ret ;----------------------------------------------------------------------------- +#IF (PCF) _i2c_start: PCF_START: LD A,PCF_START_ OUT (PCF_RS1),A RET -; +#ELSE ;_i2c_start: ld a,_idle ; issue - out (_io),a ; start + out (I2C_BASE),a ; start ; command res _sda,a - out (_io),a + out (I2C_BASE),a nop nop res _scl,a - out (_io),a + out (I2C_BASE),a ld (oprval),a ret - +#ENDIF ; ;----------------------------------------------------------------------------- ; @@ -244,47 +276,8 @@ PCF_ACKTO .EQU 65000 PCF_BBTO .EQU 65000 PCF_LABDLY .EQU 65000 ; -;----------------------------------------------------------------------------- -; -; RETURN A=00/Z IF SUCCESSFULL -; RETURN A=FF/NZ IF TIMEOUT -; RETURN A=01/NZ IF LOST ARBITRATION -; PCF_STATUS HOLDS LAST PCF STATUS -; -PCF_WAIT_FOR_PIN: - PUSH HL - LD HL,PCF_PINTO ; SET TIMEOUT VALUE - -PCF_WFP0: - IN A,(PCF_RS1) ; GET BUS - LD (PCF_STATUS),A ; STATUS - LD B,A - - DEC HL ; HAVE WE - LD A,H ; TIMED OUT - OR L - JR Z,PCF_WFP1 ; YES WE HAVE, GO ACTION IT - - LD A,B ; - AND PCF_PIN ; IS TRANSMISSION COMPLETE? - JR NZ,PCF_WFP0 ; KEEP ASKING IF NOT OR - POP HL ; YES COMPLETE (PIN=0) RETURN WITH ZERO - RET -PCF_WFP1: - LD A,B ; DID WE LOSE ARBITRATION? - AND PCF_LAB ; IF A=0 THEN NO - CPL - JR NZ,PCF_WFP2 ; NO - CALL PCF_HANDLE_LAB ; YES GO HANDLE IT - LD (PCF_STATUS),A - XOR A ; RETURN NZ, A=01H - INC A -PCF_WFP2: - POP HL ; RET NZ, A=FF IF TIMEOUT - RET -; PCF_STATUS .DB 00H - +; ;-------------------------------------------------------------------------------- ; ; RETURN NZ/FF IF TIMEOUT ERROR @@ -343,24 +336,6 @@ PCF_WFBB0: RET ; ;----------------------------------------------------------------------------- -PCF_HANDLE_LAB: -; - LD A,PCF_PIN - OUT (PCF_RS1),A - LD A,PCF_ES0 - OUT (PCF_RS1),A -; - LD HL,PCF_LABDLY -PCF_LABLP: - LD A,H - OR L - DEC HL - JR NZ,PCF_LABLP -; - IN A,(PCF_RS1) - RET -; -;----------------------------------------------------------------------------- ; DISPLAY ERROR MESSAGES ; PCF_RDERR: @@ -429,7 +404,6 @@ PCF_PRTERR: POP HL RET ; -; PCF_NOPCF .DB "NO DEVICE FOUND$" PCF_WRTFAIL .DB "SETTING DEVICE ID FAILED$" PCF_REGFAIL .DB "CLOCK REGISTER SELECT ERROR$" @@ -444,28 +418,29 @@ PCF_PINFAIL .DB "PIN FAIL$" PCF_BBFAIL .DB "BUS BUSY$" ; ;----------------------------------------------------------------------------- +#IF (PCF) _i2c_stop: PCF_STOP: LD A,PCF_STOP_ ; issue OUT (PCF_RS1),A ; stop RET ; command - +#ELSE ;_i2c_stop: ld a,(oprval) res _scl,a res _sda,a - out (_io),a + out (I2C_BASE),a set _scl,a - out (_io),a + out (I2C_BASE),a nop nop set _sda,a - out (_io),a + out (I2C_BASE),a ld (oprval),a ret - +; _i2c_write: ; write ld a,(oprval) ; to i2c ; bus @@ -474,38 +449,37 @@ i2c1: res _sda,a rl c jr nc,i2c2 set _sda,a -i2c2: out (_io),a +i2c2: out (I2C_BASE),a set _scl,a - out (_io),a - -; COND SC126=0 -; ld d,a -;i2c3: in a,(_io) -; bit _scl,a -; jr z,i2c3 -; ld a,d -; ENDC + out (I2C_BASE),a +#IF (SC126=0) + ld d,a +i2c3: in a,(I2C_BASE) + bit _scl,a + jr z,i2c3 + ld a,d +#ENDIF res _scl,a - out (_io),a + out (I2C_BASE),a djnz i2c1 set _sda,a - out (_io),a + out (I2C_BASE),a set _scl,a - out (_io),a + out (I2C_BASE),a ld d,a -i2c4: in a,(_io) -; COND SC126=0 -; bit _scl,a -; jr z,4b -; ENDC +i2c4: in a,(I2C_BASE) +#IF (SC126=0) + bit _scl,a + jr z,4b +#ENDIF ld c,a ld a,d res _scl,a - out (_io),a + out (I2C_BASE),a ld (oprval),a xor a @@ -514,8 +488,7 @@ i2c4: in a,(_io) inc a ret - - +#ENDIF oprval: .db 0 x: .db 0 y: .db 0 diff --git a/Source/Apps/I2C/RTCds7.asm b/Source/Apps/I2C/RTCds7.asm index c99d7123..045a1cd0 100644 --- a/Source/Apps/I2C/RTCds7.asm +++ b/Source/Apps/I2C/RTCds7.asm @@ -2,115 +2,11 @@ ; PCF8584 I2C Clock Driver ;================================================================================================== ; -PCF_BASE .EQU 0F0H -PCF_ID .EQU 0AAH -CPU_CLK .EQU 12 - -PCF_RS0 .EQU PCF_BASE -PCF_RS1 .EQU PCF_RS0+1 -PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE - -REGS0 .EQU PCF_BASE -REGS1 .EQU REGS0+1 -; -;T4LC512D .EQU 10100000B ; DEVICE IDENTIFIER -;T4LC512A1 .EQU 00000000B ; DEVICE ADDRESS -;T4LC512A2 .EQU 00001110B ; DEVICE ADDRESS -;T4LC512A3 .EQU 00000010B ; DEVICE ADDRESS -;T4LC512W .EQU 00000000B ; DEVICE WRITE -;T4LC512R .EQU 00000001B ; DEVICE READ -; -;I2CDEV1W .EQU (T4LC512D+T4LC512A1+T4LC512W) -;I2CDEV1R .EQU (T4LC512D+T4LC512A1+T4LC512R) -; -;I2CDEV2W .EQU (T4LC512D+T4LC512A2+T4LC512W) -;I2CDEV2R .EQU (T4LC512D+T4LC512A2+T4LC512R) -; -;I2CDEV3W .EQU (T4LC512D+T4LC512A3+T4LC512W) -;I2CDEV3R .EQU (T4LC512D+T4LC512A3+T4LC512R) -; -; CONTROL REGISTER BITS -; -PCF_PIN .EQU 10000000B -PCF_ES0 .EQU 01000000B -PCF_ES1 .EQU 00100000B -PCF_ES2 .EQU 00010000B -PCF_EN1 .EQU 00001000B -PCF_STA .EQU 00000100B -PCF_STO .EQU 00000010B -PCF_ACK .EQU 00000001B -; -PCF_START_ .EQU (PCF_PIN | PCF_ES0 | PCF_STA | PCF_ACK) -PCF_STOP_ .EQU (PCF_PIN | PCF_ES0 | PCF_STO | PCF_ACK) -PCF_REPSTART_ .EQU ( PCF_ES0 | PCF_STA | PCF_ACK) -PCF_IDLE_ .EQU (PCF_PIN | PCF_ES0 | PCF_ACK) -; -; STATUS REGISTER BITS -; -;PCF_PIN .EQU 10000000B -PCF_INI .EQU 01000000B ; 1 if not initialized -PCF_STS .EQU 00100000B -PCF_BER .EQU 00010000B -PCF_AD0 .EQU 00001000B -PCF_LRB .EQU 00001000B -PCF_AAS .EQU 00000100B -PCF_LAB .EQU 00000010B -PCF_BB .EQU 00000001B -; -; CLOCK CHIP FREQUENCIES -; -PCF_CLK3 .EQU 000H -PCF_CLK443 .EQU 010H -PCF_CLK6 .EQU 014H -PCF_CLK8 .EQU 018H -PCF_CLK12 .EQU 01cH -; -; TRANSMISSION FREQUENCIES -; -PCF_TRNS90 .EQU 000H ; 90 kHz */ -PCF_TRNS45 .EQU 001H ; 45 kHz */ -PCF_TRNS11 .EQU 002H ; 11 kHz */ -PCF_TRNS15 .EQU 003H ; 1.5 kHz */ -; -; TIMEOUT AND DELAY VALUES (ARBITRARY) -; -PCF_PINTO .EQU 65000 -PCF_ACKTO .EQU 65000 -PCF_BBTO .EQU 65000 -PCF_LABDLY .EQU 65000 -; -; DATA PORT REGISTERS -; -#IF (CPU_CLK = 443) -PCF_CLK .EQU PCF_CLK443 -#ELSE - #IF (CPU_CLK = 8) -PCF_CLK .EQU PCF_CLK8 - #ELSE - #IF (CPU_CLK = 12) -PCF_CLK .EQU PCF_CLK12 - #ELSE ***ERROR - #ENDIF - #ENDIF -#ENDIF -; -DS7_OUT .EQU 10000000B ; SELECT SQUARE WAVE FUNCTION -DS7_SQWE .EQU 00010000B ; ENABLE SQUARE WAVE OUTPUT -DS7_RATE .EQU 00000000B ; SET 1HZ OUPUT -; -DS7_DS1307 .EQU 11010000B ; DEVICE IDENTIFIER -DS7_W .EQU 00000000B ; DEVICE WRITE -DS7_R .EQU 00000001B ; DEVICE READ + .ECHO "rtcds7\n" ; -DS7_READ .EQU (DS7_DS1307 | DS7_R) ; READ -DS7_WRITE .EQU (DS7_DS1307 | DS7_W) ; WRITE +#INCLUDE "pcfi2c.inc" ; -DS7_CTL .EQU (DS7_OUT | DS7_SQWE | DS7_RATE) -; -CLIARGS .EQU $81 -RESTART .EQU $0000 ; CP/M restart vector -BDOS .EQU $0005 ; BDOS invocation vector -FCB .EQU $5C ; Location of default FCB + ; .ORG 100H ; @@ -654,132 +550,6 @@ PCF_BBFAIL .DB "BUS BUSY$" ; ;----------------------------------------------------------------------------- ; -;BDOS .EQU 5 ;ENTRY BDOS -BS .EQU 8 ;BACKSPACE -TAB .EQU 9 ;TABULATOR -LF .EQU 0AH ;LINE-FEED -CR .EQU 0DH ;CARRIAGE-RETURN -; -; OUTPUT TEXT AT HL -; -PRTSTR: LD A,(HL) - CP '$' - RET Z - CALL PRINP - INC HL - JR PRTSTR -; -;Output WORD -;*********** -; -;PARAMETER: Entry WORD IN HL -;********* -; -OUTW: LD A,H - CALL OUTB - LD A,L - CALL OUTB - RET -; -;Output BYTE -;*********** -; -;PARAMETER: Entry BYTE IN A -;********* -; -OUTB: PUSH AF - RRCA - RRCA - RRCA - RRCA - AND 0FH - CALL HBTHE ;Change Half-BYTE - POP AF - AND 0FH - CALL HBTHE - RET -; -;Output HALF-BYTE -;**************** -; -;PARAMETER: Entry Half-BYTE IN A (BIT 0 - 3) -;********* -; -HBTHE: CP 0AH - JR C,HBTHE1 - ADD A,7 ;Character to Letter -HBTHE1: ADD A,30H - LD E,A - CALL PCHAR - RET -; -; -;Output on Screen -;**************** -; -PRBS: LD E,BS - CALL PCHAR - RET -; -;Output CR+LF on Screen -;********************** -; -NEWLINE: -CRLF: LD E,CR - CALL PCHAR - LD E,LF - CALL PCHAR - RET -; -;Output ASCII-Character -;********************** -; -COUT: -PRINP: PUSH AF - PUSH DE - LD E,A - CALL PCHAR - POP DE - POP AF - RET -; -;CALL BDOS with Register Save -;**************************** -; -INCHA: LD C,1 ;INPUT CHARACTER TO A - JR BDO -PCHAR: LD C,2 ;PRINT CHARACTER IN E - JR BDO -PSTRIN: LD C,9 ;PRINT STRING - JR BDO -INBUFF: LD C,10 ;READ CONSOLE-BUFFER - JR BDO -CSTS: LD C,11 ;CONSOLE-STATUS - JR BDO -OPEN: LD C,15 ;OPEN FILE - JR BDO -CLOSE: LD C,16 ;CLOSE FILE - JR BDO -DELETE: LD C,19 ;DELETE FILE - JR BDO -READS: LD C,20 ;READ SEEK - JR BDO -WRITES: LD C,21 ;WRITE SEEK - JR BDO -MAKE: LD C,22 ;MAKE FILE - JR BDO -SETDMA: LD C,26 ;SET DMA-ADDRESS -BDO: PUSH HL - PUSH DE - PUSH BC - PUSH IX - PUSH IY - CALL BDOS - POP IY - POP IX - POP BC - POP DE - POP HL - RET +#INCLUDE "i2ccpm.inc" ; .END diff --git a/Source/Apps/I2C/i2ccpm.inc b/Source/Apps/I2C/i2ccpm.inc new file mode 100644 index 00000000..ee469e5d --- /dev/null +++ b/Source/Apps/I2C/i2ccpm.inc @@ -0,0 +1,132 @@ +;================================================================================================== +; GENERIC CP/M ROUTINES +;================================================================================================== +; +BDOS .EQU 5 ;ENTRY BDOS +BS .EQU 8 ;BACKSPACE +TAB .EQU 9 ;TABULATOR +LF .EQU 0AH ;LINE-FEED +CR .EQU 0DH ;CARRIAGE-RETURN +; +CLIARGS .EQU $81 +RESTART .EQU $0000 ; CP/M restart vector +FCB .EQU $5C ; Location of default FCB +; +; OUTPUT TEXT AT HL +; +PRTSTR: LD A,(HL) + CP '$' + RET Z + CALL COUT + INC HL + JR PRTSTR +; +;Output WORD +;*********** +; +;PARAMETER: Entry WORD IN HL +;********* +; +OUTW: LD A,H + CALL OUTB + LD A,L + CALL OUTB + RET +; +;Output BYTE +;*********** +; +;PARAMETER: Entry BYTE IN A +;********* +; +OUTB: PUSH AF + RRCA + RRCA + RRCA + RRCA + AND 0FH + CALL HBTHE ;Change Half-BYTE + POP AF + AND 0FH + CALL HBTHE + RET +; +;Output HALF-BYTE +;**************** +; +;PARAMETER: Entry Half-BYTE IN A (BIT 0 - 3) +;********* +; +HBTHE: CP 0AH + JR C,HBTHE1 + ADD A,7 ;Character to Letter +HBTHE1: ADD A,30H + LD E,A + CALL PCHAR + RET +; +; +;Output on Screen +;**************** +; +PRBS: LD E,BS + CALL PCHAR + RET +; +;Output CR+LF on Screen +;********************** +; +NEWLINE: + LD E,CR + CALL PCHAR + LD E,LF + CALL PCHAR + RET +; +;Output ASCII-Character +;********************** +; +COUT: PUSH AF + LD E,A + CALL PCHAR + POP AF + RET +; +;CALL BDOS with Register Save +;**************************** +; +INCHA: LD C,1 ;INPUT CHARACTER TO A + JR BDO +PCHAR: LD C,2 ;PRINT CHARACTER IN E + JR BDO +PSTRIN: LD C,9 ;PRINT STRING + JR BDO +INBUFF: LD C,10 ;READ CONSOLE-BUFFER + JR BDO +CSTS: LD C,11 ;CONSOLE-STATUS + JR BDO +OPEN: LD C,15 ;OPEN FILE + JR BDO +CLOSE: LD C,16 ;CLOSE FILE + JR BDO +DELETE: LD C,19 ;DELETE FILE + JR BDO +READS: LD C,20 ;READ SEEK + JR BDO +WRITES: LD C,21 ;WRITE SEEK + JR BDO +MAKE: LD C,22 ;MAKE FILE + JR BDO +SETDMA: LD C,26 ;SET DMA-ADDRESS +BDO: PUSH HL + PUSH DE + PUSH BC + PUSH IX + PUSH IY + CALL BDOS + POP IY + POP IX + POP BC + POP DE + POP HL + RET diff --git a/Source/Apps/I2C/i2clcd.asm b/Source/Apps/I2C/i2clcd.asm new file mode 100644 index 00000000..548895b2 --- /dev/null +++ b/Source/Apps/I2C/i2clcd.asm @@ -0,0 +1,517 @@ +;================================================================================================== +; PCF8584 HD44780 I2C LCD UTILITY +; +; SOME GENERAL INFORMATION ON LCDS CAN BE SEEN HERE : FOCUSLCDS.COM/PRODUCT-CATEGORY/CHARACTER-LCD/ +; +;================================================================================================== +; + .ECHO "i2clcd\n" +; +#INCLUDE "pcfi2c.inc" +; +; LCD COMMANDS +; +LCDFSET .EQU 00100000B ; 20H +LCD4BIT .EQU 00000000B ; 00H +LCD2LIN .EQU 00001000B ; 08H +LCDDON .EQU 00000100B ; 04H +LCDDMOV .EQU 00001000B ; 07H +LCDSGRA .EQU 01000000B ; 04H +LCDSDRA .EQU 10000000B ; 80H +LCDEMS .EQU 00000100B ; 04H +LCDELFT .EQU 00000010B ; 03H +; +LCDPINE .EQU 00000100B ; PIN 2 +LCDPIND .EQU 00000001B ; PIN O +; +; +; STANDARD FORMATS - 8X1, 8X2, 16X1, 16X2, 16X4, 20X1, 20X2, 20X4, 24X2, 40X1, 40X2, 40X4 +; +TIMEOUT .EQU 255 + + .ORG 100H + +;INIT: CALL PCF_INIT +; + LD A,0 + LD (DEBUGF),A +; + CALL LCDINIT ; SETUP THE LCD THROUGH THE PCF8574 + + LD HL,LCDDATA ; DISPLAY TEXT AT HL + PUSH HL + CALL LCDSTR + POP HL + + CALL STOP ; CLOSE I2C CONNECTION +; + RET + +;----------------------------------------------------------------------------- +; +LCDLITE .DB 00001000B +; +LCDINIT: +; CALL DEBUG +; + LD A,I2CLCDW ; SET SLAVE ADDRESS + OUT (REGS0),A +; + LD A,0C5H ; GENERATE START CONDITION + OUT (REGS1),A ; AND ISSUE THE SLAVE ADDRESS + CALL CHKPIN +; +; CALL DEBUG +; + LD HL,LCDINIT1 + LD B,2 + CALL WLN +; + CALL DELAY +; + LD HL,LCDINIT2 + LD B,2 + CALL WLN +; + CALL DELAY +; +; NOW WE ARE IN 4 BIT MODE +; + LD A,+(LCDFSET | LCD4BIT | LCD2LIN) + CALL LCDCMD + LD A,+(LCDDON | LCDDMOV) + CALL LCDCMD + LD A,+(LCDEMS | LCDELFT) + CALL LCDCMD + LD A,LCDSDRA + CALL LCDCMD +; + RET +; +;----------------------------------------------------------------------------- +; +WLN: LD A,(HL) + OUT (REGS0),A ; PUT DATA ON BUS + CALL CHKPIN + INC HL + DJNZ WLN + RET +; +;----------------------------------------------------------------------------- +; DISPLAY STRING AT HL, TERMINATED BY 0 +; +LCDSTR: POP BC ; GET THE POINTER OF + POP HL ; THE TEXT TO DISPLAY + PUSH HL ; OFF THE STACK AND + PUSH BC ; PUT IT IN HL. +; +LCDST0: LD A,(HL) ; GET NEXT CHARACTER TO + OR A ; DISPLAY BUT RETURN + RET Z ; WHEN TERMINATOR REACHED + PUSH HL +; + CALL LCDATA ; OUTPUT TO LCD + POP HL +; RET C ; POINT TO NEXT + INC HL ; AND REPEAT + JR LCDST0 +; +;----------------------------------------------------------------------------- +; SEND BYTE IN A TO LCD IN 4-BIT MODE +; +LCDATA: PUSH DE + LD D,A + LD A,(LCDLITE) + OR +(LCDPINE | LCDPIND) + JP LCDSND +LCDCMD: PUSH DE + LD D,A + LD A,(LCDLITE) + OR LCDPINE +LCDSND: LD E,A + LD A,D + PUSH BC + LD C,11110000B + AND C + OR E + LD (LCDBUF),A + AND ~LCDPINE + LD (LCDBUF+1),A + LD A,D + RLC A + RLC A + RLC A + RLC A + AND C + OR E + LD (LCDBUF+2),A + AND ~LCDPINE + LD (LCDBUF+3),A +; + LD HL,LCDBUF ; OUTPUT 1 BYTE WHICH + LD B,4 ; REQUIRES A FOUR + CALL WLN ; BYTE SEQUENCE +; + POP BC + POP DE + RET +; +LCDDATA: + .DB "TEST HOW BIG IS THIS LINE DOES IT WRAP",0 +; +LCDINIT1: + .DB 00110100B + .DB 00011000B +; +LCDINIT2: + .DB 00100100B + .DB 00100000B +; +LCDBUF: + .DB 0, 0, 0, 0 ; BUFFER TO HOLD 4 BYTE SEQUENCE + +; FLASH DEVICE READ +; + +DEVMADR .EQU 0 + +READR: LD B,255 +DLY1: DJNZ DLY1 +; + LD A,D ; SET SLAVE ADDRESS + OUT (REGS0),A +; + LD A,0C5H ; GENERATE START CONDITION + OUT (REGS1),A ; AND ISSUE THE SLAVE ADDRESS + CALL CHKPIN +; + LD A,+(DEVMADR/256) + OUT (REGS0),A ; PUT ADDRESS MSB ON BUS + CALL CHKPIN +; + LD A,+(DEVMADR&$00FF) + OUT (REGS0),A ; PUT ADDRESS LSB ON BUS + CALL CHKPIN +; + LD A,045H ; START + OUT (REGS1),A +; + LD A,E ; ISSUE CONTROL BYTE + READ + OUT (REGS0),A +; + CALL READI2C ; DUMMY READ + JR NZ,ERREXT +; +READLP1:CALL READI2C +; JR Z,ERREXT + CP 1AH + PUSH AF + CALL COUT + POP AF + JR NZ,READLP1 +; + LD A,PCF_ES0 + OUT (REGS1),A + CALL CHKPIN + IN A,(REGS0) + CALL READI2C + CALL STOP +; + CALL NEWLINE +; + RET +; +;----------------------------------------------------------------------------- +;----------------------------------------------------------------------------- +RESET: LD A,0C2H ; STOP + OUT (REGS1),A + LD B,255 +DLY2: DJNZ DLY2 + LD A,0C1H + OUT (REGS1),A + RET + + +RDSTAT: LD BC,-1 +STATLP: IN A,(REGS1) + AND 1 + RET Z + LD A,B + OR C + DEC BC + JR NZ,STATLP + LD A,'T' + JP ERREXTT +; +ERREXT: LD A,'Q' + JR ERR + +ERREXTT: POP HL +ERR: CALL COUT + CALL STOP + CALL RESET + RET +; +STOP: LD A,0C3H + OUT (REGS1),A + RET +; +DELAY: PUSH HL + LD HL,-1 +DLOOP: LD A,H + OR L + DEC HL + JR NZ,DLOOP + POP HL + RET +; +CHKPIN: IN A,(REGS1) ; POLL FOR + BIT 7,A ; TRANSMISSION + JP NZ,CHKPIN ; TO FINISH + +; IN A,(REGS1) ; CHECK FOR + BIT 3,A ; SLAVE + RET Z ; ACKNOWLEDGMENT + LD A,'A' + JP ERREXTT +; +; READ ONE BYTE FROM I2C +; RETURNS DATA IN A +; Z flag set is acknowledge received (correct operation) +; +READI2C: + IN A,(REGS1) ; READ S1 REGISTER + BIT 7,A ; CHECK PIN STATUS + JP NZ,READI2C + BIT 3,A ; CHECK LRB=0 + RET NZ + IN A,(REGS0) ; GET DATA + RET +; +DEBUG: PUSH AF + PUSH DE + LD A,'[' + CALL COUT + LD HL,DEBUGF + LD A,(HL) + INC (HL) + CALL HBTHE + LD A,']' + CALL COUT + POP DE + POP AF + RET +DEBUGF: .DB 00H +; +;----------------------------------------------------------------------------- +; +; LINUX DRIVER BASED CODE +; +; I2C_INB = IN A,(REGS0) +; I2C_OUTB = LD A,* | OUT (REGS0),A +; SET_PCF = LD A,* | OUT (REGS1),A +; GET_PCF = IN A,(REGS1) +; +;----------------------------------------------------------------------------- +I2C_START: + LD A,PCF_START_ + OUT (REGS1),A + RET +; +;----------------------------------------------------------------------------- +I2C_REPSTART: + LD A,PCF_START_ + OUT (REGS1),A + RET +; +;----------------------------------------------------------------------------- +I2C_STOP: + LD A,PCF_STOP_ + OUT (REGS1),A + RET +; +;----------------------------------------------------------------------------- +HANDLE_LAB: + +LABDLY .EQU 0F000H + + LD A,PCF_PIN + OUT (REGS1),A + LD A,PCF_ES0 + OUT (REGS1),A +; + LD HL,LABDLY +LABLP LD A,H + OR L + DEC HL + JR NZ,LABLP +; + IN A,(REGS1) + RET +; +;----------------------------------------------------------------------------- +WAIT_FOR_BB: +; +BBTIMO .EQU 255 +; + LD HL,BBTIMO +BBNOTO IN A,(REGS1) + AND PCF_BB + RET Z + DEC HL + LD A,H + OR A + JR NZ,BBNOTO + CPL ; RET NZ IF TIMEOUT +BBNOTB RET ; RET Z IF BUS IS BUSY +; +;----------------------------------------------------------------------------- +WAIT_FOR_PIN: +; +; RETURN A=00/Z IF SUCCESSFULL +; RETURN A=FF/NZ IF TIMEOUT +; RETURN A=01/NZ IF LOST ARBITRATION +; +PINTIMO .EQU 16000 +; + LD HL,PINTIMO +PINNOTO IN A,(REGS1) + LD (STATUS),A + LD B,A + AND PCF_PIN + RET Z + DEC HL + LD A,H + OR A + JR NZ,PINNOTO + CPL ; RET NZ IF TIMEOUT +PINNOTB RET ; RET Z IF BUS IS BUSY +; + LD B,A + AND PCF_LAB + CALL HANDLE_LAB + LD (STATUS),A + XOR A + INC A + RET +; +STATUS .DB 00H +; +;----------------------------------------------------------------------------- +PCF_INIT: + LD A,PCF_PIN ; S1=80H: S0 SELECTED, SERIAL + OUT (REGS1),A ; INTERFACE OFF + NOP + IN A,(REGS1) ; CHECK TO SEE S1 NOW USED AS R/W + AND 07FH ; CTRL. PCF8584 DOES THAT WHEN ESO + JR NZ,INIERR ; IS ZERO +; + LD A,PCF_OWN ; LOAD OWN ADDRESS IN S0, + OUT (REGS0),A ; EFFECTIVE ADDRESS IS (OWN <<1) + NOP + IN A,(REGS0) ; CHECK IT IS REALLY WRITTEN + CP PCF_OWN + JR NZ,SETERR +; + LD A,+(PCF_PIN | PCF_ES1) ; S1=0A0H + OUT (REGS1),A ; NEXT BYTE IN S2 + NOP + IN A,(REGS1) + AND 07FH + CP PCF_ES1 + JR NZ,REGERR +; + LD A,PCF_CLK ; LOAD CLOCK REGISTER S2 + OUT (REGS0),A + NOP + IN A,(REGS0) ; CHECK IT'S REALLY WRITTEN, ONLY + AND 1FH ; THE LOWER 5 BITS MATTER + CP PCF_CLK + JR NZ,CLKERR +; + LD A,PCF_IDLE_ + OUT (REGS1),A + NOP + IN A,(REGS1) + CP +(PCF_PIN | PCF_BB) + JR NZ,IDLERR + + RET +; +;----------------------------------------------------------------------------- +PCF_SENDBYTES: ; HL POINTS TO DATA, BC = COUNT, A = 0 LAST A=1 NOT LAST + ; + LD (LASTB),A +; +SB0: LD A,(HL) + OUT (REGS0),A + CALL WAIT_FOR_PIN + JR Z,SB1 + + CP 01H ; EXIT IF ARBITRATION ERROR + RET Z + + CALL I2C_STOP ; MUST BE TIMEOUT + LD A,055H ; ERROR + RET + +SB1: LD A,(STATUS) + AND PCF_LRB + JR NZ,SB2 + LD A,055H +; +SB2: LD A,B + OR C + INC HL + JR NZ,SB0 ; CHECK IF FINISHED +; +SBGOOD: LD A,(LASTB) + OR A + JR NZ,DB3 + CALL I2C_STOP + RET +DB3: CALL I2C_REPSTART + RET +; +LASTB .DB 00H +; + +; I2C_INB = IN A,(REGS0) +; I2C_OUTB = LD A,* | OUT (REGS0),A +; SET_PCF = LD A,* | OUT (REGS1),A +; GET_PCF = IN A,(REGS1) + + +; +;----------------------------------------------------------------------------- + +INIERR LD HL,NOPCF + CALL PRTSTR + RET +; +SETERR LD HL,WRTFAIL + CALL PRTSTR + RET +REGERR LD HL,REGFAIL + CALL PRTSTR + RET +; +CLKERR LD HL,CLKFAIL + CALL PRTSTR + RET +; +IDLERR LD HL,IDLFAIL + CALL PRTSTR + RET +; +NOPCF .DB "NO DEVICE FOUND",CR,LF,"$" +WRTFAIL .DB "SETTING DEVICE ID FAILED",CR,LF,"$" +REGFAIL .DB "CLOCK REGISTER SELECT ERROR",CR,LF,"$" +CLKFAIL .DB "CLOCK SET FAIL",CR,LF,"$" +IDLFAIL .DB "BUS IDLE FAILED",CR,LF,"$" +; +#INCLUDE "i2ccpm.inc" +; +BUFFER: .DS 256 +; + .END diff --git a/Source/HBIOS/ds7rtc.asm b/Source/HBIOS/ds7rtc.asm index ab105c9b..31a259df 100644 --- a/Source/HBIOS/ds7rtc.asm +++ b/Source/HBIOS/ds7rtc.asm @@ -18,6 +18,18 @@ DS7_WRITE .EQU (DS7_DS1307 | DS7_W) ; WRITE ; DS7_CTL .EQU (DS7_OUT | DS7_SQWE | DS7_RATE) ; + +; GENERIC CP/M STUFF +; +BS .EQU 8 ; BACKSPACE +TAB .EQU 9 ; TABULATOR +LF .EQU 0AH ; LINE-FEED +CR .EQU 0DH ; CARRIAGE-RETURN +CLIARGS .EQU $81 +RESTART .EQU $0000 ; CP/M restart vector +BDOS .EQU $0005 ; BDOS invocation vector +FCB .EQU $5C ; Location of default FCB +; ;----------------------------------------------------------------------------- ; DS1307 INITIALIZATION ; @@ -88,7 +100,7 @@ DS7_DISPATCH: ;----------------------------------------------------------------------------- ; DS1307 GET TIME ; -; HL POINT TO A BUFFER TO STORE THE CURRENT TIME AND DATE IN. +; HL POINTS TO A BUFFER TO STORE THE CURRENT TIME AND DATE IN. ; THE TIME AND DATE INFORMATION MUST BE TRANSLATED TO THE ; HBIOS FORMAT AND COPIED FROM THE HBIOS DRIVER BANK TO ; CALLER INVOKED BANK. @@ -143,10 +155,103 @@ DS7_GT0:LD A,(HL) ;----------------------------------------------------------------------------- ; DS1307 SET TIME ; +; A: RESULT (OUT), 0=OK, Z=OK, NZ=ERROR +; HL: DATE/TIME BUFFER (IN) +; +; HBIOS FORMAT = YYMMDDHHMMSS +; DS1307 FORMAT = SSMMHH..DDMMYY.. +; DS7_SETTIM: +; CALL PCF_DBG ; [0] + + + LD A, (HB_INVBNK) ; COPY FROM CURRENT USER BANK + LD (HB_SRCBNK), A ; SET IT + LD A, BID_BIOS ; COPY TO BIOS BANK + LD (HB_DSTBNK), A ; SET IT + LD DE, DS7_BUF ; DESTINATION ADDRESS + LD BC,6 ; LENGTH IS 6 BYTES +#IF (INTMODE == 1) + DI +#ENDIF + CALL HB_BNKCPY ; Copy the clock data +#IF (INTMODE == 1) + EI +#ENDIF +; +; CALL PCF_DBG ; [1] + + CALL PCF_WAIT_FOR_BB + JP NZ,PCF_BBERR +; + LD A,DS7_WRITE ; SET SLAVE ADDRESS + OUT (PCF_RS0),A +; + CALL PCF_START ; GENERATE START CONDITION + CALL PCF_WAIT_FOR_PIN; AND ISSUE THE SLAVE ADDRESS + CALL NZ,PCF_PINERR +; + LD A,00H ; REGISTER 00 + OUT (PCF_RS0),A ; PUT ADDRESS ON BUS + CALL PCF_WAIT_FOR_PIN + CALL NZ,PCF_PINERR ; + LD DE,5 + CALL DS7_SET3 ; STARTING AT REGISTER 0 +; + CALL PCF_STOP + + CALL PCF_WAIT_FOR_BB + JP NZ,PCF_BBERR + +; CALL PCF_DBG ; [2] +; + LD A,DS7_WRITE ; SET SLAVE ADDRESS + OUT (PCF_RS0),A +; + CALL PCF_START ; GENERATE START CONDITION + CALL PCF_WAIT_FOR_PIN; AND ISSUE THE SLAVE ADDRESS + CALL NZ,PCF_PINERR + +; CALL PCF_DBG ; [3] +; + LD A,04H ; REGISTER 04 + OUT (PCF_RS0),A ; PUT ADDRESS ON BUS + CALL PCF_WAIT_FOR_PIN + CALL NZ,PCF_PINERR +; + LD DE,2 + CALL DS7_SET3 + +; CALL PCF_DBG ; [4] +; + CALL PCF_STOP + XOR A RET ; +DS7_SET3: + LD B,3 + LD HL,DS7_BUF + ADD HL,DE +DS7_SC1:PUSH BC + + LD A,(HL) + +; CALL PRTHEXBYTE + + OUT (PCF_RS0),A ; PUT DATA ON BUS + CALL PCF_WAIT_FOR_ACK + CALL NZ,PCF_ACKERR + POP BC + DEC HL + DJNZ DS7_SC1 + RET +; +; HBIOS FORMAT = YYMMDDHHMMSS +; 991122083100 +; DS1307 FORMAT = SSMMHH..DDMMYY.. +; 003108..221199 +; ;----------------------------------------------------------------------------- ; FUNCTIONS THAT ARE NOT AVAILABLE OR IMPLEMENTED ; diff --git a/Source/HBIOS/pcf8584.asm b/Source/HBIOS/pcf8584.asm index e53a4adb..5f4c8330 100644 --- a/Source/HBIOS/pcf8584.asm +++ b/Source/HBIOS/pcf8584.asm @@ -79,7 +79,7 @@ PCF_LABDLY .EQU 65000 ; DATA PORT REGISTERS ; #IF (CPU_CLK = 443) -PCF_CLK .EQU PCF_CLK443 +PCF_CLK .EQU PCF_CLK4433 #ELSE #IF (CPU_CLK = 8) PCF_CLK .EQU PCF_CLK8 @@ -91,6 +91,19 @@ PCF_CLK .EQU PCF_CLK12 #ENDIF #ENDIF ; +; THE PCF8584 TARGETS A TOP I2C CLOCK SPEED OF 90KHZ AND SUPPORTS DIVIDERS FOR +; 3, 4.43, 6, 8 AND 12MHZ TO ACHEIVE THIS. +; +; +--------------------------------------------------------------------------------------------+ +; | div/clk | 2MHz | 4MHz | 6MHz | 7.38Mhz | 10MHz | 12MHz | 16MHz | 18.432Mhz | 20MHz | +; +----------------------------------------------------------------------------------+---------+ +; | 3MHz | 60Khz | 120Khz | | | | | | | | +; | 4.43MHz | | 81Khz | | | | | | | | +; | 6MHz | | | 90Khz | 110Khz | | | | | | +; | 8MHz | | | | 83Khz | 112Khz | | | | | +; | 12MHz | | | | | | 90Khz | 120Khz | 138Khz | 150Khz | +; +----------------------------------------------------------------------------------+---------+ +; PCF8584_INIT: CALL NEWLINE ; Formatting PRTS("I2C: IO=0x$") @@ -104,7 +117,7 @@ PCF8584_INIT: ; ; I2C_INB = IN A,(PCF_RS0) ; I2C_OUTB = LD A,* | OUT (PCF_RS0),A -; SET_PCF = LD A,* | OUT (PCF_RS1),A +; SET_PCF -= LD A,* | OUT (PCF_RS1),A ; GET_PCF = IN A,(PCF_RS1) ; ;----------------------------------------------------------------------------- @@ -446,14 +459,14 @@ PCF_PRTERR: ;----------------------------------------------------------------------------- ; DEBUG HELPER ; -#IF (0) -DS7_DBG: +#IF (1) +PCF_DBG: PUSH AF PUSH DE PUSH HL LD A,'[' CALL COUT - LD HL,DS7_DBGF + LD HL,PCF_DBGF LD A,(HL) ADD A,'0' INC (HL) @@ -464,7 +477,7 @@ DS7_DBG: POP DE POP AF RET -DS7_DBGF: +PCF_DBGF: .DB 0 ; DEBUG STAGE COUNTER #ENDIF ; From 1e1ad94b6dd937012e450014cc82a522a04e7e2c Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Fri, 2 Jul 2021 16:37:55 +0800 Subject: [PATCH 04/13] Minors --- Source/HBIOS/nascom.asm | 2 +- Source/HBIOS/pio.asm | 4 +-- Source/HBIOS/sn76489.asm | 57 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/Source/HBIOS/nascom.asm b/Source/HBIOS/nascom.asm index 6b9e7297..e9f6c1da 100644 --- a/Source/HBIOS/nascom.asm +++ b/Source/HBIOS/nascom.asm @@ -78,7 +78,7 @@ DEL .EQU 7FH ; Delete ; ; 0200H - 2000H BASIC EXECUTABLE ; 2000H - 2090H STACK -; 2090H - 20F8H BASIC EXECUTABLE VARAIABLES / WORKSPACE +; 2090H - 20F8H BASIC EXECUTABLE VARIABLES / WORKSPACE ; 20F9H - BASIC PROGRAM START WRKSPC .EQU BAS_END+90H ; BASIC Work space diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index c0d230f7..05f3e45b 100644 --- a/Source/HBIOS/pio.asm +++ b/Source/HBIOS/pio.asm @@ -36,7 +36,7 @@ ; Both port interrupt enable flip-flops are reset. ; Both port output registers are reset. ; -; Register addressing for ECB-ZP and ECB-4P assuming base address 90h and 88h respectively. +; Register addressing example for ECB-ZP and ECB-4P assuming base address 90h and 88h respectively. ; ; PIO ----ZP---- ----4P---- ; 0 DATA 0 90h DATA 0 B8h @@ -762,7 +762,7 @@ PPI_OST: RET ; ; PIO_INITDEV - Configure device. -; If DE = FFFF then extract the configuratio information from the table of devices and program the device using those settings. +; If DE = FFFF then extract the configuration information from the table of devices and program the device using those settings. ; Otherwise use the configuration information in DE to program those settings and save them in the device table PPI_INITDEV: diff --git a/Source/HBIOS/sn76489.asm b/Source/HBIOS/sn76489.asm index b65e9f5d..fa544064 100644 --- a/Source/HBIOS/sn76489.asm +++ b/Source/HBIOS/sn76489.asm @@ -15,6 +15,8 @@ SN76489_PORT_LEFT .EQU $FC ; PORTS FOR ACCESSING THE SN76489 CHIP (LEFT) SN76489_PORT_RIGHT .EQU $F8 ; PORTS FOR ACCESSING THE SN76489 CHIP (RIGHT) +;SN76489_PORT_LEFT .EQU $C7 ; PORTS FOR ACCESSING THE SN76489 CHIP (LEFT) +;SN76489_PORT_RIGHT .EQU $C8 ; PORTS FOR ACCESSING THE SN76489 CHIP (RIGHT) SN7_IDAT .EQU 0 SN7_TONECNT .EQU 3 ; COUNT NUMBER OF TONE CHANNELS SN7_NOISECNT .EQU 1 ; COUNT NUMBER OF NOISE CHANNELS @@ -68,6 +70,13 @@ SN7_RESET: SN7_VOLUME_OFF: AUDTRACE(SNT_VOLOFF) + +#IFDEF SBCV2004 + LD A,(RTCVAL) + OR %00001000 ; SBC-V2-004+ CHANGE + OUT (RTCIO),A ; TO HALF CLOCK SPEED +#ENDIF + LD A, CHANNEL_0_SILENT OUT (SN76489_PORT_LEFT), A OUT (SN76489_PORT_RIGHT), A @@ -84,6 +93,12 @@ SN7_VOLUME_OFF: OUT (SN76489_PORT_LEFT), A OUT (SN76489_PORT_RIGHT), A +#IFDEF SBCV2004 + LD A,(RTCVAL) + OR %11110111 ; SBC-V2-004+ CHANGE TO + OUT (RTCIO),A ; NORMAL CLOCK SPEED +#ENDIF + RET ; BIT MAPPING @@ -237,9 +252,23 @@ SN7_APPLY_VOL: ; APPLY VOLUME TO BOTH LEFT AND RIGHT CHANNELS AUDTRACE_A AUDTRACE_CR +#IFDEF SBCV2004 + PUSH AF + LD A,(RTCVAL) + OR %00001000 ; SBC-V2-004+ CHANGE + OUT (RTCIO),A ; TO HALF CLOCK SPEED + POP AF +#ENDIF + OUT (SN76489_PORT_LEFT), A OUT (SN76489_PORT_RIGHT), A +#IFDEF SBCV2004 + LD A,(RTCVAL) + OR %11110111 ; SBC-V2-004+ CHANGE TO + OUT (RTCIO),A ; NORMAL CLOCK SPEED +#ENDIF + POP AF POP BC RET @@ -268,9 +297,23 @@ SN7_APPLY_PRD: AUDTRACE_A AUDTRACE_CR +#IFDEF SBCV2004 + PUSH AF + LD A,(RTCVAL) + OR %00001000 ; SBC-V2-004+ CHANGE + OUT (RTCIO),A ; TO HALF CLOCK SPEED + POP AF +#ENDIF + OUT (SN76489_PORT_LEFT), A OUT (SN76489_PORT_RIGHT), A +#IFDEF SBCV2004 + LD A,(RTCVAL) + OR %11110111 ; SBC-V2-004+ CHANGE TO + OUT (RTCIO),A ; NORMAL CLOCK SPEED +#ENDIF + LD A, L ; RIGHT SHIFT OUT THE LOWER 4 BITS RRCA RRCA @@ -291,9 +334,23 @@ SN7_APPLY_PRD: AUDTRACE_A AUDTRACE_CR +#IFDEF SBCV2004 + PUSH AF + LD A,(RTCVAL) + OR %00001000 ; SBC-V2-004+ CHANGE + OUT (RTCIO),A ; TO HALF CLOCK SPEED + POP AF +#ENDIF + OUT (SN76489_PORT_LEFT), A OUT (SN76489_PORT_RIGHT), A +#IFDEF SBCV2004 + LD A,(RTCVAL) + OR %11110111 ; SBC-V2-004+ CHANGE TO + OUT (RTCIO),A ; NORMAL CLOCK SPEED +#ENDIF + POP AF POP BC POP DE From 0ebfebe8d17ecb76802a7035d8ebda44a25c67e1 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Fri, 9 Jul 2021 14:57:35 +0800 Subject: [PATCH 05/13] DMA updates Add hardware probe at initialization and status checks after DMA transfers --- Binary/SBC_std.upd | Bin 131072 -> 131072 bytes Source/HBIOS/cfg_dyno.asm | 2 +- Source/HBIOS/cfg_ezz80.asm | 2 +- Source/HBIOS/cfg_master.asm | 2 +- Source/HBIOS/cfg_mk4.asm | 2 +- Source/HBIOS/cfg_n8.asm | 2 +- Source/HBIOS/cfg_rcz180.asm | 2 +- Source/HBIOS/cfg_rcz280.asm | 2 +- Source/HBIOS/cfg_rcz80.asm | 2 +- Source/HBIOS/cfg_sbc.asm | 2 +- Source/HBIOS/cfg_scz180.asm | 2 +- Source/HBIOS/cfg_zeta.asm | 2 +- Source/HBIOS/cfg_zeta2.asm | 2 +- Source/HBIOS/dma.asm | 162 ++++++++++++++++++++++++++++++++---- Source/HBIOS/md.asm | 7 +- Source/HBIOS/rf.asm | 9 +- Source/HBIOS/std.asm | 2 +- 17 files changed, 165 insertions(+), 39 deletions(-) diff --git a/Binary/SBC_std.upd b/Binary/SBC_std.upd index 6c9791fbb4632db6790cbeb0653c771ab26e231a..2b85c08ead3a524bb86406471451baf3f1c08a50 100644 GIT binary patch delta 25 hcmZo@;Am*zm@uEwa^r%?07lE^Ujf^H1u(L$2LOOx3Nioy delta 25 hcmZo@;Am*zm@uEwXyby&07j$cUjf^H1u(L$2LOMl3M2pk diff --git a/Source/HBIOS/cfg_dyno.asm b/Source/HBIOS/cfg_dyno.asm index a3045890..6cc9baa1 100644 --- a/Source/HBIOS/cfg_dyno.asm +++ b/Source/HBIOS/cfg_dyno.asm @@ -191,4 +191,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_Z180 ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index f5dd41a4..58686d5b 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -226,4 +226,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_NONE ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index a03f4611..d3dbed94 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -294,4 +294,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_NONE ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index cc6e9b22..6fe370c2 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -226,4 +226,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_ECB ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index c27f2dca..9e06dcd5 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -226,4 +226,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_ECB ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index 6dbb8b77..85200727 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -239,4 +239,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_Z180 ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index 998cc0b2..e9145a9a 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -255,4 +255,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_Z280 ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index 03e42160..0a262c07 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -244,4 +244,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_RC ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index 87cab859..b4f3cadd 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -227,4 +227,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_ECB ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index e47254de..7a85c2e4 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -234,4 +234,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_Z180 ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index 879d479d..e5f04b71 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -162,4 +162,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_NONE ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index 01f6a2b9..37c96223 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -174,4 +174,4 @@ SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS -DMAMODE .EQU DMAMODE_WKD ; DMA: DMA MODE (NONE|WKD|Z180|Z280|RC) +DMAMODE .EQU DMAMODE_NONE ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/dma.asm b/Source/HBIOS/dma.asm index 60fc67ad..065c30e1 100644 --- a/Source/HBIOS/dma.asm +++ b/Source/HBIOS/dma.asm @@ -13,8 +13,10 @@ DMA_LOAD .equ $cf ; %11001111 DMA_ENABLE .equ $87 ; %10000111 DMA_FORCE_READY .equ $b3 DMA_DISABLE .equ $83 -; -;DMA_RESET .equ $c3 +DMA_START_READ_SEQUENCE .equ $a7 +DMA_READ_STATUS_BYTE .equ $bf +DMA_READ_MASK_FOLLOWS .equ $bb +DMA_RESET .equ $c3 ;DMA_RESET_PORT_A_TIMING .equ $c7 ;DMA_RESET_PORT_B_TIMING .equ $cb ;DMA_CONTINUE .equ $d3 @@ -22,10 +24,7 @@ DMA_DISABLE .equ $83 ;DMA_ENABLE_INTERUPTS .equ $ab ;DMA_RESET_DISABLE_INTERUPTS .equ $a3 ;DMA_ENABLE_AFTER_RETI .equ $b7 -;DMA_READ_STATUS_BYTE .equ $bf ;DMA_REINIT_STATUS_BYTE .equ $8b -;DMA_START_READ_SEQUENCE .equ $a7 -;DMA_WRITE_REGISTER_COMMAND .equ $bb ; ;================================================================================================== ; DMA INITIALIZATION CODE @@ -33,30 +32,87 @@ DMA_DISABLE .equ $83 ; DMA_INIT: CALL NEWLINE - PRTS("DMA: IO=0x$") + PRTS("DMA: IO=0x$") ; announce LD A, DMABASE CALL PRTHEXBYTE ; - ld a,0 + xor a out (DMABASE+1),a ; force ready off +; + ld a,(RTCVAL) + or %00001000 ; half + out (RTCIO),a ; clock +; + call DMAProbe ; do we have a dma? + jr nz,DMA_NOTFOUND ; ld hl,DMACode ; program the ld b,DMACode_Len ; dma command ld c,DMABASE ; block ; - ld a,(RTCVAL) - or %00001000 ; half - out (112),a ; clock di otir ; load dma ei + xor a ; set status +; +DMA_EXIT: + push af + ld a,(RTCVAL) and %11110111 ; full - out (112),a ; clock + out (RTCIO),a ; clock + pop af + ret +; +DMA_NOTFOUND: + push af + call PRTSTRD + .db " NOT PRESENT$" + pop af + jr DMA_EXIT + +; +;================================================================================================== +; DMA PROBE - WRITE TO ADDRESS REGISTER AND READ BACK +;================================================================================================== +; +DMAProbe: + ld a,DMA_RESET + out (DMABASE),a + ld a,%01111101 ; R0-Transfer mode, A -> B, start address follows + out (DMABASE),a + ld a,$cc + out (DMABASE),a + ld a,$dd + out (DMABASE),a + ld a,$e5 + out (DMABASE),a + ld a,$1a + out (DMABASE),a + ld a,DMA_LOAD + out (DMABASE),a +; + ld a,DMA_READ_MASK_FOLLOWS ; set up + out (DMABASE),a ; for + ld a,%00011000 ; register + out (DMABASE),a ; read + ld a,DMA_START_READ_SEQUENCE + out (DMABASE),a +; + in a,(DMABASE) ; read in + ld c,a ; address + in a,(DMABASE) + ld b,a +; + xor a ; is it + ld hl,$ddcc ; a match + sbc hl,bc ; return with + ret z ; status + cpl ret ; DMACode ;.db DMA_DISABLE ; R6-Command Disable DMA .db %01111101 ; R0-Transfer mode, A -> B, start address, block length follow - .dw 0 ; R0-Port A, Start address + .dw 0 ; R0-Port A, Start address .dw 0 ; R0-Block length .db %00010100 ; R1-No timing bytes follow, address increments, is memory .db %00010000 ; R2-No timing bytes follow, address increments, is memory @@ -86,12 +142,22 @@ DMALDIR: ; ld a,(RTCVAL) or %00001000 ; half - out (112),a ; clock + out (RTCIO),a ; clock di otir ; load and execute dma ei +; + ld a,DMA_READ_STATUS_BYTE ; check status + out (DMABASE),a ; of transfer + in a,(DMABASE) ; set non-zero + and %00111011 ; if failed + sub %00011011 + + push af + ld a,(RTCVAL) and %11110111 ; full - out (112),a ; clock + out (RTCIO),a ; clock + pop af ret ; DMACopy ;.db DMA_DISABLE ; R6-Command Disable DMA @@ -126,12 +192,22 @@ DMAOTIR: ; ld a,(RTCVAL) or %00001000 ; half - out (112),a ; clock + out (RTCIO),a ; clock di otir ; load and execute dma ei +; + ld a,DMA_READ_STATUS_BYTE ; check status + out (DMABASE),a ; of transfer + in a,(DMABASE) ; set non-zero + and %00111011 ; if failed + sub %00011011 +; + push af + ld a,(RTCVAL) and %11110111 ; full - out (112),a ; clock + out (RTCIO),a ; clock + pop af ret ; DMAOutCode ;.db DMA_DISABLE ; R6-Command Disable DMA @@ -171,12 +247,22 @@ DMAINIR: ; ld a,(RTCVAL) or %00001000 ; half - out (112),a ; clock + out (RTCIO),a ; clock di otir ; load and execute dma ei +; + ld a,DMA_READ_STATUS_BYTE ; check status + out (DMABASE),a ; of transfer + in a,(DMABASE) ; set non-zero + and %00111011 ; if failed + sub %00011011 +; + push af + ld a,(RTCVAL) and %11110111 ; full - out (112),a ; clock + out (RTCIO),a ; clock + pop af ret ; DMAInCode ;.db DMA_DISABLE ; R6-Command Disable DMA @@ -196,3 +282,43 @@ DMAInSource .db 0 ; R4-Port B, Destination port .db DMA_ENABLE ; R6-Command Enable DMA DMAIn_Len .equ $-DMAInCode +; +;================================================================================================== +; DEBUG - READ START, DESTINATION AN COUNT REGISTERS +;================================================================================================== +; +#IF (0) +; +DMARegDump: + ld a,DMA_READ_MASK_FOLLOWS + out (DMABASE),a + ld a,%01111110 + out (DMABASE),a + ld a,DMA_START_READ_SEQUENCE + out (DMABASE),a +; + in a,(DMABASE) + ld c,a + in a,(DMABASE) + ld b,a + call PRTHEXWORD + ld a,':' + call COUT +; + in a,(DMABASE) + ld c,a + in a,(DMABASE) + ld b,a + call PRTHEXWORD + ld a,':' + call COUT +; + in a,(DMABASE) + ld c,a + in a,(DMABASE) + ld b,a + call PRTHEXWORD +; + call NEWLINE + ret +#ENDIF diff --git a/Source/HBIOS/md.asm b/Source/HBIOS/md.asm index d7098c44..81f756e9 100644 --- a/Source/HBIOS/md.asm +++ b/Source/HBIOS/md.asm @@ -351,14 +351,14 @@ MD_SECM: ADD HL,DE ; WANT TO COPY LD DE,(MD_DSKBUF) ; -#IF (DMAENABLE) +#IF (DMAENABLE & (DMAMODE=DMAMODE_ECB)) LD BC,512-1 ; COPY ONE 512B SECTOR FROM THE CALL DMALDIR ; 4K SECTOR TO THE DISK BUFFER #ELSE LD BC,512 ; COPY ONE 512B SECTOR FROM THE LDIR ; 4K SECTOR TO THE DISK BUFFER -#ENDIF XOR A +#ENDIF RET ; ; SETUP DE:HL AS THE SECTOR ADDRESS TO READ OR WRITE @@ -471,9 +471,10 @@ MD_SECM1: ; DESIRED SECTOR IS IN BUFFER EX DE,HL ; LD HL,(MD_DSKBUF) -#IF (DMAENABLE) +#IF (DMAENABLE & (DMAMODE=DMAMODE_ECB)) LD BC,512-1 ; COPY ONE 512B SECTOR FROM THE CALL DMALDIR ; THE DISK BUFFER TO 4K SECTOR + RET NZ ; EXIT IF DMA COPY ERROR #ELSE LD BC,512 ; COPY ONE 512B SECTOR FROM THE LDIR ; THE DISK BUFFER TO 4K SECTOR diff --git a/Source/HBIOS/rf.asm b/Source/HBIOS/rf.asm index 263dadb1..04539646 100644 --- a/Source/HBIOS/rf.asm +++ b/Source/HBIOS/rf.asm @@ -272,7 +272,7 @@ RF_RDSEC: CALL RF_SETADR ; SEND SECTOR STARTING ADDRESS TO CARD LD HL,(RF_DSKBUF) ; HL := DISK BUFFER ADDRESS LD A,(RF_IO) ; GET IO PORT BASE -#IF (DMAENABLE) +#IF (DMAENABLE & (DMAMODE=DMAMODE_ECB)) LD BC,512-1 ; READ 512 BYTES CALL DMAINIR ; USING DMA #ELSE @@ -281,9 +281,8 @@ RF_RDSEC: LD B,0 ; INIT BYTE COUNTER INIR ; READ 256 BYTES INIR ; AND ANOTHER 256 BYTES FOR 512 TOTAL -#ENDIF - XOR A ; SIGNAL SUCCESS +#ENDIF RET ; AND DONE ; ; WRITE SECTOR @@ -293,7 +292,7 @@ RF_WRSEC: LD HL,(RF_DSKBUF) ; HL := DISK BUFFER ADDRESS LD A,(RF_IO) ; GET IO PORT BASE OR RF_DAT ; OFFSET TO DAT PORT -#IF (DMAENABLE==1) +#IF (DMAENABLE & (DMAMODE=DMAMODE_ECB)) LD BC,512-1 ; WRITE 512 BYTES CALL DMAOTIR ; USING DMA #ELSE @@ -301,8 +300,8 @@ RF_WRSEC: LD B,0 ; INIT BYTE COUNTER OTIR ; WRITE 256 BYTES OTIR ; AND ANOTHER 256 BYTES FOR 512 TOTAL -#ENDIF XOR A ; SIGNAL SUCCESS +#ENDIF RET ; AND DONE ; ; diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index fb944299..595676a3 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -206,7 +206,7 @@ TMSMODE_RCV9958 .EQU 4 ; RC2014 V9958 VIDEO BOARD ; DMA MODE SELECTIONS ; DMAMODE_NONE .EQU 0 -DMAMODE_WKD .EQU 1 ; ECB-DMA WOLFGANG KABATZKE'S Z80 DMA ECB BOARD +DMAMODE_ECB .EQU 1 ; ECB-DMA WOLFGANG KABATZKE'S Z80 DMA ECB BOARD DMAMODE_Z180 .EQU 2 ; Z180 INTEGRATED DMA DMAMODE_Z280 .EQU 3 ; Z280 INTEGRATED DMA DMAMODE_RC .EQU 4 ; RC2014 Z80 DMA From fe8425deef395ae487b9c5628ae3c7a98afa19ab Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Fri, 9 Jul 2021 15:25:35 +0800 Subject: [PATCH 06/13] resync --- Doc/ChangeLog.txt | 3 +++ Source/Apps/FAT/Build.cmd | 2 +- Source/Apps/FAT/Makefile | 4 ++-- Source/Apps/FDU/Build.cmd | 6 +++--- Source/Apps/FDU/Makefile | 4 ++-- Source/Apps/Tune/Makefile | 16 ++++++++-------- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Doc/ChangeLog.txt b/Doc/ChangeLog.txt index 4c990851..18bde264 100644 --- a/Doc/ChangeLog.txt +++ b/Doc/ChangeLog.txt @@ -36,6 +36,9 @@ Version 3.1.1 - L?N: Slightly enhanced ZCPRD&J w/ a couple bug fixes - L?N: UNZIPZ4 which handles most modern ZIP file compression algorithms - AJL: Preliminary support for MBC systems +- WBW: Added preliminary support for DSKYng +- WBW: Elevated MBC to a platform +- WBW: Added support for MBC user LEDs Version 3.1 ----------- diff --git a/Source/Apps/FAT/Build.cmd b/Source/Apps/FAT/Build.cmd index 34e25577..d4e7878d 100644 --- a/Source/Apps/FAT/Build.cmd +++ b/Source/Apps/FAT/Build.cmd @@ -4,4 +4,4 @@ setlocal REM FAT.com is currently distributed as a binary application, so REM it is not built here. -copy /Y FAT.com ..\..\..\Binary\Apps\ +copy /Y fat.com ..\..\..\Binary\Apps\ diff --git a/Source/Apps/FAT/Makefile b/Source/Apps/FAT/Makefile index 245385f2..2aef1f19 100644 --- a/Source/Apps/FAT/Makefile +++ b/Source/Apps/FAT/Makefile @@ -1,5 +1,5 @@ -OBJECTS = FAT.com -NODELETE = FAT.com +OBJECTS = fat.com +NODELETE = fat.com DEST = ../../../Binary/Apps TOOLS=../../../Tools diff --git a/Source/Apps/FDU/Build.cmd b/Source/Apps/FDU/Build.cmd index a7b9b9dd..414b1e49 100644 --- a/Source/Apps/FDU/Build.cmd +++ b/Source/Apps/FDU/Build.cmd @@ -5,9 +5,9 @@ set TOOLS=../../../Tools set PATH=%TOOLS%\tasm32;%PATH% set TASMTABS=%TOOLS%\tasm32 -tasm -t80 -b -fFF FDU.asm FDU.com FDU.lst +tasm -t80 -b -fFF fdu.asm fdu.com fdu.lst if errorlevel 1 goto :eof -copy /Y FDU.com ..\..\..\Binary\Apps\ -copy /Y FDU.txt ..\..\..\Doc\ \ No newline at end of file +copy /Y fdu.com ..\..\..\Binary\Apps\ +copy /Y fdu.txt ..\..\..\Doc\ \ No newline at end of file diff --git a/Source/Apps/FDU/Makefile b/Source/Apps/FDU/Makefile index ade7444a..caeb2ea3 100644 --- a/Source/Apps/FDU/Makefile +++ b/Source/Apps/FDU/Makefile @@ -1,5 +1,5 @@ -OBJECTS = FDU.com -DOCS = FDU.txt +OBJECTS = fdu.com +DOCS = fdu.txt DEST = ../../../Binary/Apps DOCDEST = ../../../Doc TOOLS = ../../../Tools diff --git a/Source/Apps/Tune/Makefile b/Source/Apps/Tune/Makefile index 3f6c8fdb..e01b796e 100644 --- a/Source/Apps/Tune/Makefile +++ b/Source/Apps/Tune/Makefile @@ -1,19 +1,19 @@ -OBJECTS = Tune.com Tunezx.com Tunemsx.com +OBJECTS = tune.com tunezx.com tunemsx.com DEST = ../../../Binary/Apps TOOLS = ../../../Tools include $(TOOLS)/Makefile.inc -DEPS := Tune.asm $(shell find . -name '*.inc') +DEPS := tune.asm $(shell find . -name '*.inc') -Tune.com: $(DEPS) - $(TASM) -dWBW Tune.asm Tune.com Tune.lst +tune.com: $(DEPS) + $(TASM) -dWBW tune.asm tune.com tune.lst -Tunezx.com: $(DEPS) - $(TASM) -dZX Tune.asm Tunezx.com Tunezx.lst +tunezx.com: $(DEPS) + $(TASM) -dZX tune.asm tunezx.com tunezx.lst -Tunemsx.com: $(DEPS) - $(TASM) -dMSX Tune.asm Tunemsx.com Tunemsx.lst +tunemsx.com: $(DEPS) + $(TASM) -dMSX tune.asm tunemsx.com tunemsx.lst all:: mkdir -p $(DEST)/Tunes From 2bd6158b36d1f26c980192bfdee861ea7f74b2cf Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sat, 10 Jul 2021 08:57:56 +0800 Subject: [PATCH 07/13] resync --- Source/Apps/{Decode.asm => decode.asm} | 0 Source/Apps/{Encode.asm => encode.asm} | 0 Source/Apps/{Format.asm => format.asm} | 0 Source/Apps/{IntTest.asm => inttest.asm} | 0 Source/Apps/{Mode.asm => mode.asm} | 0 Source/Apps/{RTC.asm => rtc.asm} | 0 Source/Apps/{Startup.asm => startup.asm} | 0 Source/Apps/{Survey.asm => survey.asm} | 0 Source/Apps/{SysCopy.asm => syscopy.asm} | 0 Source/Apps/{SysGen.z80 => sysgen.z80} | 0 Source/Apps/{Talk.asm => talk.asm} | 0 Source/Apps/{Timer.asm => timer.asm} | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename Source/Apps/{Decode.asm => decode.asm} (100%) rename Source/Apps/{Encode.asm => encode.asm} (100%) rename Source/Apps/{Format.asm => format.asm} (100%) rename Source/Apps/{IntTest.asm => inttest.asm} (100%) rename Source/Apps/{Mode.asm => mode.asm} (100%) rename Source/Apps/{RTC.asm => rtc.asm} (100%) rename Source/Apps/{Startup.asm => startup.asm} (100%) rename Source/Apps/{Survey.asm => survey.asm} (100%) rename Source/Apps/{SysCopy.asm => syscopy.asm} (100%) rename Source/Apps/{SysGen.z80 => sysgen.z80} (100%) rename Source/Apps/{Talk.asm => talk.asm} (100%) rename Source/Apps/{Timer.asm => timer.asm} (100%) diff --git a/Source/Apps/Decode.asm b/Source/Apps/decode.asm similarity index 100% rename from Source/Apps/Decode.asm rename to Source/Apps/decode.asm diff --git a/Source/Apps/Encode.asm b/Source/Apps/encode.asm similarity index 100% rename from Source/Apps/Encode.asm rename to Source/Apps/encode.asm diff --git a/Source/Apps/Format.asm b/Source/Apps/format.asm similarity index 100% rename from Source/Apps/Format.asm rename to Source/Apps/format.asm diff --git a/Source/Apps/IntTest.asm b/Source/Apps/inttest.asm similarity index 100% rename from Source/Apps/IntTest.asm rename to Source/Apps/inttest.asm diff --git a/Source/Apps/Mode.asm b/Source/Apps/mode.asm similarity index 100% rename from Source/Apps/Mode.asm rename to Source/Apps/mode.asm diff --git a/Source/Apps/RTC.asm b/Source/Apps/rtc.asm similarity index 100% rename from Source/Apps/RTC.asm rename to Source/Apps/rtc.asm diff --git a/Source/Apps/Startup.asm b/Source/Apps/startup.asm similarity index 100% rename from Source/Apps/Startup.asm rename to Source/Apps/startup.asm diff --git a/Source/Apps/Survey.asm b/Source/Apps/survey.asm similarity index 100% rename from Source/Apps/Survey.asm rename to Source/Apps/survey.asm diff --git a/Source/Apps/SysCopy.asm b/Source/Apps/syscopy.asm similarity index 100% rename from Source/Apps/SysCopy.asm rename to Source/Apps/syscopy.asm diff --git a/Source/Apps/SysGen.z80 b/Source/Apps/sysgen.z80 similarity index 100% rename from Source/Apps/SysGen.z80 rename to Source/Apps/sysgen.z80 diff --git a/Source/Apps/Talk.asm b/Source/Apps/talk.asm similarity index 100% rename from Source/Apps/Talk.asm rename to Source/Apps/talk.asm diff --git a/Source/Apps/Timer.asm b/Source/Apps/timer.asm similarity index 100% rename from Source/Apps/Timer.asm rename to Source/Apps/timer.asm From 1603556577fc4a215a5833408c912d6cffdd08bf Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sat, 10 Jul 2021 09:13:23 +0800 Subject: [PATCH 08/13] resync --- Source/Apps/Build.cmd | 20 ++++--- Source/Apps/mode.asm | 4 +- Source/Apps/{RTChb.asm => rtchb.asm} | 0 Source/HBIOS/hbios.asm | 86 ++++++++++++++++++---------- 4 files changed, 70 insertions(+), 40 deletions(-) rename Source/Apps/{RTChb.asm => rtchb.asm} (100%) diff --git a/Source/Apps/Build.cmd b/Source/Apps/Build.cmd index dc97b94d..ac3ed35c 100644 --- a/Source/Apps/Build.cmd +++ b/Source/Apps/Build.cmd @@ -12,15 +12,18 @@ set ZXBINDIR=%TOOLS%/cpm/bin/ set ZXLIBDIR=%TOOLS%/cpm/lib/ set ZXINCDIR=%TOOLS%/cpm/include/ -call :asm SysCopy || goto :eof -call :asm Assign || goto :eof -call :asm Format || goto :eof -call :asm Talk || goto :eof -call :asm Mode || goto :eof -call :asm RTC || goto :eof -call :asm Timer || goto :eof -call :asm180 IntTest || goto :eof +call :asm syscopy || goto :eof +call :asm assign || goto :eof +call :asm format || goto :eof +call :asm talk || goto :eof +call :asm mode || goto :eof +call :asm rtc || goto :eof +call :asm timer || goto :eof +call :asm180 inttest || goto :eof +call :asm rtcds7 || goto :eof call :asm rtchb || goto :eof +call :asm ppidetst || goto :eof +call :asm tstdskng || goto :eof zx Z80ASM -SYSGEN/F @@ -31,7 +34,6 @@ setlocal & cd XM && call Build || exit /b 1 & endlocal setlocal & cd FDU && call Build || exit /b 1 & endlocal setlocal & cd Tune && call Build || exit /b 1 & endlocal setlocal & cd FAT && call Build || exit /b 1 & endlocal -setlocal & cd I2C && call Build || exit /b 1 & endlocal copy *.com %APPBIN%\ diff --git a/Source/Apps/mode.asm b/Source/Apps/mode.asm index 08f00ba7..a9815f71 100644 --- a/Source/Apps/mode.asm +++ b/Source/Apps/mode.asm @@ -984,8 +984,8 @@ err2: ; without the string ; Utility modules ;=============================================================================== ; -#include "Encode.asm" -#include "Decode.asm" +#include "encode.asm" +#include "decode.asm" #include "bcd.asm" ; ;=============================================================================== diff --git a/Source/Apps/RTChb.asm b/Source/Apps/rtchb.asm similarity index 100% rename from Source/Apps/RTChb.asm rename to Source/Apps/rtchb.asm diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 33888bbe..369708b9 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -97,10 +97,21 @@ MODCNT .SET MODCNT + 1 #ENDIF ; #IF (LEDENABLE) -#DEFINE LED(N) PUSH AF - #DEFCONT \ LD A,~N - #DEFCONT \ OUT (LEDPORT),A - #DEFCONT \ POP AF + #IF (LEDMODE == LEDMODE_STD) +#DEFINE LED(N) PUSH AF + #DEFCONT \ LD A,~N + #DEFCONT \ OUT (LEDPORT),A + #DEFCONT \ POP AF + #ENDIF + #IF (LEDMODE == LEDMODE_RTC) +#DEFINE LED(N) PUSH AF + #DEFCONT \ LD A,(RTCVAL) + #DEFCONT \ AND %11111100 + #DEFCONT \ OR (N & %00000011) + #DEFCONT \ LD (RTCVAL),A + #DEFCONT \ OUT (LEDPORT),A + #DEFCONT \ POP AF + #ENDIF #ELSE #DEFINE LED(N) \; #ENDIF @@ -1050,6 +1061,16 @@ Z280_BOOTERR .TEXT "\r\n\r\n*** Application mode boot not supported under Z280 n LD A,%00000001 OUT (DIAGPORT),A #ENDIF +#IF (LEDENABLE) + #IF (LEDMODE == LEDMODE_STD) + XOR A ; LED IS INVERTED, TURN IT ON + #ENDIF + #IF (LEDMODE == LEDMODE_RTC) + LD A,%00000001 ; LED 0 + LD (RTCVAL),A ; SAVE TO SHADOW REGISTER + #ENDIF + OUT (LEDPORT),A +#ENDIF ; LD SP,HBX_LOC ; SETUP INITIAL STACK JUST BELOW HBIOS PROXY ; @@ -1222,7 +1243,6 @@ Z280_INITZ: #ENDIF ; DIAG(%00000011) - LED($00) ; ; CHECK BATTERY BACKUP STATUS BEFORE WE COPY PROXY TO UPPER MEMORY ; @@ -1307,6 +1327,7 @@ HB_RAMFLAG .DB FALSE ; INITIALLY FALSE, SET TO TRUE BELOW AFTER RAM TRANSITION HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK ; DIAG(%00000111) + LED(%00000010) ; LD A,(HBX_LOC - 1) ; RECALL BATTERY STATE AND SAVE LD (HB_BATCOND),A ; FOR FUTURE REFERENCE @@ -1365,7 +1386,7 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK LD A,1 ; SET FOR RECOVERY MODE LD (HB_BOOT_REC),A ; SAVE FOR LATER #ENDIF - #IF (PLATFORM == PLT_SBC) + #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_MBC)) #IF (BT_REC_TYPE == BT_REC_SBC01) LD A,%00100000 ; DISABLE RTC AND OUT (RTCIO),A ; DRQ DRIVER READ @@ -1398,13 +1419,17 @@ SAVE_REC_M: DIAG(%00001111) ; #IF (DSKYENABLE) + CALL DSKY_INIT + LD HL,MSG_HBVER + 5 LD A,(DSKY_NUMS + RMJ) - AND $7F + ;AND $7F + OR $80 LD (HL),A INC HL LD A,(DSKY_NUMS + RMN) - AND $7F + ;AND $7F + OR $80 LD (HL),A INC HL LD A,(DSKY_NUMS + RUP) @@ -1760,7 +1785,7 @@ NOT_REC_M0: #ENDIF ; DIAG(%01111111) - LED($FF) + LED(%00000011) ; ; PRIOR TO THIS POINT, CONSOLE I/O WAS NOT AVAILABLE UNLESS DIRECTED TO DEBUG OUTPUT I.E. XIO ; NOW THAT HBIOS IS READY, SET THE CONSOLE UNIT TO ACTIVATE CONSOLE I/O @@ -1978,6 +2003,9 @@ HB_Z280BUS1: #ENDIF #IF (MEMMGR == MM_ZRC) .TEXT "ZRC$" +#ENDIF +#IF (MEMMGR == MM_MBC) + .TEXT "MBC$" #ENDIF CALL PRTSTRD .TEXT " MMU$" @@ -2108,7 +2136,7 @@ HB_WDZ: ; IF PLATFORM HAS A CONFIG JUMPER, CHECK TO SEE IF IT IS JUMPERED. ; IF SO, BYPASS SWITCH TO CRT CONSOLE (FAILSAFE MODE) ; - #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA) | (PLATFORM == PLT_ZETA2)) + #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA) | (PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_MBC)) IN A,(RTCIO) ; RTC PORT, BIT 6 HAS STATE OF CONFIG JUMPER BIT 6,A ; BIT 6 HAS CONFIG JUMPER STATE JR Z,INITSYS3 ; Z=SHORTED, BYPASS CONSOLE SWITCH @@ -2214,14 +2242,14 @@ CALLDUMMY: #IF (BT_REC_TYPE != BT_REC_NONE) ; HB_PCINIT_REC: - #IF (PLATFORM == PLT_SBC) + #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_MBC)) .DW UART_PREINIT ; .DW CALLDUMMY #ENDIF HB_PCINITRLEN .EQU (($ - HB_PCINIT_REC) / 2) ; HB_INIT_REC: - #IF (PLATFORM == PLT_SBC) + #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_MBC)) .DW UART_INIT .DW MD_INIT .DW PPIDE_INIT @@ -2336,12 +2364,9 @@ HB_INITTBL: #IF (TMSENABLE) .DW TMS_INIT #ENDIF -#IF (DSKYENABLE) - .DW DSKY_INIT -#ENDIF -#IF (DMAENABLE) - .DW DMA_INIT -#ENDIF +;#IF (DSKYENABLE) +; .DW DSKY_INIT +;#ENDIF #IF (MDENABLE) .DW MD_INIT #ENDIF @@ -2789,7 +2814,7 @@ HB_DSKFN: OUT (DIAGPORT),A ; DISPLAY ON DIAG LEDS #ENDIF #IF (LEDENABLE & LEDDISKIO) - LED($FF) + LED(%00000001) #ENDIF LD E,1 ; ONE SECTOR HB_DSKFNADR .EQU $+1 @@ -4648,14 +4673,6 @@ SIZ_NEC .EQU $ - ORG_NEC .ECHO SIZ_NEC .ECHO " bytes.\n" #ENDIF -#IF (DMAENABLE) -ORG_DMA .EQU $ -#INCLUDE "dma.asm" -SIZ_DMA .EQU $ - ORG_DMA - .ECHO "DMA occupies " - .ECHO SIZ_DMA - .ECHO " bytes.\n" -#ENDIF ; ; FONTS AREA ; @@ -4825,7 +4842,7 @@ SIZ_SPK .EQU $ - ORG_SPK .ECHO " bytes.\n" #ENDIF ; -#IF (PIO_4P | PIO_ZP | PPI_SBC) +#IF (PIO_4P | PIO_ZP | PIO_SBC) ORG_PIO .EQU $ #INCLUDE "pio.asm" SIZ_PIO .EQU $ - ORG_PIO @@ -4891,7 +4908,12 @@ SIZ_AY38910 .EQU $ - ORG_AY38910 ; #IF (DSKYENABLE) #DEFINE DSKY_KBD + #IF (DSKYMODE == DSKYMODE_V1) #INCLUDE "dsky.asm" + #ENDIF + #IF (DSKYMODE == DSKYMODE_NG) +#INCLUDE "dskyng.asm" + #ENDIF #ENDIF ; ; INCLUDE LZSA2 decompression engine if required. @@ -4922,6 +4944,7 @@ HB_CPUSPD1: ; WAIT FOR AN INITIAL TICK TO ALIGN, THEN WAIT ; FOR SECOND TICK AND TO GET A FULL ONE SECOND LOOP COUNT + CALL DSRTC_START CALL HB_RDSEC ; GET SECONDS LD (HB_CURSEC),A ; AND INIT CURSEC CALL HB_WAITSEC ; WAIT FOR SECONDS TICK @@ -5907,7 +5930,12 @@ STR_SYSCHK .TEXT "\r\n>>> SYSCHK: $" STR_CONTINUE .TEXT "\r\nContinue (Y/N)? $" ; #IF (DSKYENABLE) ; 'H','B','I','O',' ',' ',' ',' ' -MSG_HBVER .DB $BE,$FF,$8A,$FB,$80,$80,$80,$80 ; "HBIO " + #IF (DSKYMODE == DSKYMODE_V1) +MSG_HBVER .DB $3E,$7F,$0A,$7B,$00,$00,$00,$00 ; "HBIO " + #ENDIF + #IF (DSKYMODE == DSKYMODE_NG) +MSG_HBVER .DB $76,$7F,$30,$3F,$00,$00,$00,$00 ; "HBIO " + #ENDIF #ENDIF ; HB_APPBNK .DB 0 ; START BANK WHEN RUN IN APP MODE From 1726744650c5baafda9058cc083edf8b2cefdc23 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sat, 10 Jul 2021 09:14:59 +0800 Subject: [PATCH 09/13] resync --- Source/Apps/rtchb.asm | 94 +++++-------------------------------------- 1 file changed, 10 insertions(+), 84 deletions(-) diff --git a/Source/Apps/rtchb.asm b/Source/Apps/rtchb.asm index 6103b551..cf4669bf 100644 --- a/Source/Apps/rtchb.asm +++ b/Source/Apps/rtchb.asm @@ -3,104 +3,24 @@ ;================================================================================================== ; ; HBIOS FORMAT = YYMMDDHHMMSS -; -;----------------------------------------------------------------------------- -; GENERIC CP/M STUFF -; -BS .EQU 8 ; BACKSPACE -TAB .EQU 9 ; TABULATOR -LF .EQU 0AH ; LINE-FEED -CR .EQU 0DH ; CARRIAGE-RETURN -CLIARGS .EQU $81 -RESTART .EQU $0000 ; CP/M restart vector -BDOS .EQU $0005 ; BDOS invocation vector -FCB .EQU $5C ; Location of default FCB -; -;----------------------------------------------------------------------------- ; .ORG 100H ; -HBC_START: - LD A,(FCB+1) ; GET FIRST CHAR - CP ' ' ; COMPARE TO BLANK. IF SO NO - JR Z,HBC_ST0 ; ARGUMENTS SO DISLAY TIME AND DATE -; - LD A,(FCB+1) ; GET FIRST CHAR - CP '/' ; IS IT INDICATING AN ARGUMENT - JR NZ,HBC_ST0 ; -; - LD A,(FCB+2) ; GET NEXT CHARACTER - CP 'D' ; - JR NZ,HBC_ST1 ; -; -; /D SET DATE DDMMYY -; - LD B,$21 ; WRITE CLOCK DATA INTO BUFFER - LD HL,HBC_BUF1 - RST 08 -; - LD HL,FCB+3 -; - LD A,(HL) - CP 0 -; JP HBC_ST4 ; EXIT IF END OF BUFFER - LD B,6 - - - - - JP HBC_ST0 -; -HBC_ST1: - LD A,(FCB+2) ; GET NEXT CHARACTER - CP 'T' ; - JR NZ,HBC_ST2 ; -; -; /T SET TIME HHMMSS -; - LD B,$21 ; WRITE CLOCK DATA INTO BUFFER - LD HL,HBC_BUF1 - RST 08 - JP HBC_ST0 -; -HBC_ST2: - LD A,(FCB+2) ; GET NEXT CHARACTER - CP 'S' ; - JR NZ,HBC_ST3 ; -; -; /S SET TIME AND DATE -; - JP HBC_ST0 ; -HBC_ST3: -; -; UNREGOGNIZED ARGUMENT -; - RET -; -HBC_ST0: - LD B,$20 ; READ CLOCK DATA INTO BUFFER - LD HL,HBC_BUF + LD B,$20 ; READ CLOCK DATA INTO BUFFER + LD HL,HBC_BUF ; DISPLAY TIME AND DATE FROM BUFFER RST 08 ; #IF (0) LD A,6 - LD DE,HBC_BUF ; DISLAY DATA READ + LD DE,HBC_BUF ; DISLAY DATA READ ; CALL PRTHEXBUF CALL NEWLINE #ENDIF ; CALL HBC_DISP RET -; -HBC_BUF1: - .DB 099H - .DB 011H - .DB 022H - .DB 008H - .DB 031H - .DB 000H -; + HBC_BUF .FILL 6,0 ; ;----------------------------------------------------------------------------- @@ -167,6 +87,12 @@ HBC_FAIL .DB "ERROR$" ;----------------------------------------------------------------------------- ; GENERIC CP/M ROUTINES ; +BDOS .EQU 5 ;ENTRY BDOS +BS .EQU 8 ;BACKSPACE +TAB .EQU 9 ;TABULATOR +LF .EQU 0AH ;LINE-FEED +CR .EQU 0DH ;CARRIAGE-RETURN +; ; OUTPUT TEXT AT HL ; PRTSTR: LD A,(HL) From e9ef9e0c93ad01451319b2e1c54a2fd7e7f3d851 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sat, 10 Jul 2021 12:01:32 +0800 Subject: [PATCH 10/13] dma & i2c changes Resync & cleanup --- Binary/RCZ80_std.upd | Bin 131072 -> 0 bytes Binary/SBC_std.upd | Bin 131072 -> 0 bytes Source/Apps/Build.cmd | 2 +- Source/Apps/I2C/Makefile | 17 ++- Source/Apps/I2C/{I2CSCAN.ASM => i2cscan.asm} | 0 Source/Apps/I2C/pcfi2c.inc | 116 +++++++++++++++++++ Source/Apps/I2C/{RTCds7.asm => rtcds7.asm} | 0 Source/HBIOS/hbios.asm | 12 ++ 8 files changed, 142 insertions(+), 5 deletions(-) delete mode 100644 Binary/RCZ80_std.upd delete mode 100644 Binary/SBC_std.upd rename Source/Apps/I2C/{I2CSCAN.ASM => i2cscan.asm} (100%) create mode 100644 Source/Apps/I2C/pcfi2c.inc rename Source/Apps/I2C/{RTCds7.asm => rtcds7.asm} (100%) diff --git a/Binary/RCZ80_std.upd b/Binary/RCZ80_std.upd deleted file mode 100644 index 2890b61dfc6fa891de363ae59de6c73f91170ed7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 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 Z01+SpM1Tko0U|&IhyW2F0*{fvzX8;h3U2@a diff --git a/Binary/SBC_std.upd b/Binary/SBC_std.upd deleted file mode 100644 index 2b85c08ead3a524bb86406471451baf3f1c08a50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 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 1) ; PCF'S ADDRESS IN SLAVE MODE + +REGS0 .EQU PCF_BASE +REGS1 .EQU REGS0+1 +; +;T4LC512D .EQU 10100000B ; DEVICE IDENTIFIER +;T4LC512A1 .EQU 00000000B ; DEVICE ADDRESS +;T4LC512A2 .EQU 00001110B ; DEVICE ADDRESS +;T4LC512A3 .EQU 00000010B ; DEVICE ADDRESS +;T4LC512W .EQU 00000000B ; DEVICE WRITE +;T4LC512R .EQU 00000001B ; DEVICE READ +; +;I2CDEV1W .EQU (T4LC512D+T4LC512A1+T4LC512W) +;I2CDEV1R .EQU (T4LC512D+T4LC512A1+T4LC512R) +; +;I2CDEV2W .EQU (T4LC512D+T4LC512A2+T4LC512W) +;I2CDEV2R .EQU (T4LC512D+T4LC512A2+T4LC512R) +; +;I2CDEV3W .EQU (T4LC512D+T4LC512A3+T4LC512W) +;I2CDEV3R .EQU (T4LC512D+T4LC512A3+T4LC512R) +; +; CONTROL REGISTER BITS +; +PCF_PIN .EQU 10000000B +PCF_ES0 .EQU 01000000B +PCF_ES1 .EQU 00100000B +PCF_ES2 .EQU 00010000B +PCF_EN1 .EQU 00001000B +PCF_STA .EQU 00000100B +PCF_STO .EQU 00000010B +PCF_ACK .EQU 00000001B +; +PCF_START_ .EQU (PCF_PIN | PCF_ES0 | PCF_STA | PCF_ACK) +PCF_STOP_ .EQU (PCF_PIN | PCF_ES0 | PCF_STO | PCF_ACK) +PCF_REPSTART_ .EQU ( PCF_ES0 | PCF_STA | PCF_ACK) +PCF_IDLE_ .EQU (PCF_PIN | PCF_ES0 | PCF_ACK) +; +; STATUS REGISTER BITS +; +;PCF_PIN .EQU 10000000B +PCF_INI .EQU 01000000B ; 1 if not initialized +PCF_STS .EQU 00100000B +PCF_BER .EQU 00010000B +PCF_AD0 .EQU 00001000B +PCF_LRB .EQU 00001000B +PCF_AAS .EQU 00000100B +PCF_LAB .EQU 00000010B +PCF_BB .EQU 00000001B +; +; CLOCK CHIP FREQUENCIES +; +PCF_CLK3 .EQU 000H +PCF_CLK443 .EQU 010H +PCF_CLK6 .EQU 014H +PCF_CLK8 .EQU 018H +PCF_CLK12 .EQU 01cH +; +; TRANSMISSION FREQUENCIES +; +PCF_TRNS90 .EQU 000H ; 90 kHz */ +PCF_TRNS45 .EQU 001H ; 45 kHz */ +PCF_TRNS11 .EQU 002H ; 11 kHz */ +PCF_TRNS15 .EQU 003H ; 1.5 kHz */ +; +; TIMEOUT AND DELAY VALUES (ARBITRARY) +; +PCF_PINTO .EQU 65000 +PCF_ACKTO .EQU 65000 +PCF_BBTO .EQU 65000 +PCF_LABDLY .EQU 65000 +; +; DATA PORT REGISTERS +; +#IF (CPU_CLK = 443) +PCF_CLK .EQU PCF_CLK443 +#ELSE + #IF (CPU_CLK = 8) +PCF_CLK .EQU PCF_CLK8 + #ELSE + #IF (CPU_CLK = 12) +PCF_CLK .EQU PCF_CLK12 + #ELSE ***ERROR + #ENDIF + #ENDIF +#ENDIF +; +DS7_OUT .EQU 10000000B ; SELECT SQUARE WAVE FUNCTION +DS7_SQWE .EQU 00010000B ; ENABLE SQUARE WAVE OUTPUT +DS7_RATE .EQU 00000000B ; SET 1HZ OUPUT +; +DS7_DS1307 .EQU 11010000B ; DEVICE IDENTIFIER +DS7_W .EQU 00000000B ; DEVICE WRITE +DS7_R .EQU 00000001B ; DEVICE READ +; +DS7_READ .EQU (DS7_DS1307 | DS7_R) ; READ +DS7_WRITE .EQU (DS7_DS1307 | DS7_W) ; WRITE +; +DS7_CTL .EQU (DS7_OUT | DS7_SQWE | DS7_RATE) +; +PCF8574 .EQU 01000000B ; DEVICE IDENTIFIER +PCF8574A .EQU 00001110B ; DEVICE ADDRESS +PCF8574W .EQU 00000000B ; DEVICE WRITE +PCF8574R .EQU 00000001B ; DEVICE READ +; +I2CLCDR .EQU (PCF8574+PCF8574A+PCF8574R) +I2CLCDW .EQU (PCF8574+PCF8574A+PCF8574W) diff --git a/Source/Apps/I2C/RTCds7.asm b/Source/Apps/I2C/rtcds7.asm similarity index 100% rename from Source/Apps/I2C/RTCds7.asm rename to Source/Apps/I2C/rtcds7.asm diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 369708b9..92a29c8a 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -2367,6 +2367,9 @@ HB_INITTBL: ;#IF (DSKYENABLE) ; .DW DSKY_INIT ;#ENDIF +#IF (DMAENABLE) + .DW DMA_INIT +#ENDIF #IF (MDENABLE) .DW MD_INIT #ENDIF @@ -4674,6 +4677,15 @@ SIZ_NEC .EQU $ - ORG_NEC .ECHO " bytes.\n" #ENDIF ; +#IF (DMAENABLE) +ORG_DMA .EQU $ +#INCLUDE "dma.asm" +SIZ_DMA .EQU $ - ORG_DMA + .ECHO "DMA occupies " + .ECHO SIZ_DMA + .ECHO " bytes.\n" +#ENDIF +; ; FONTS AREA ; ORG_FONTS .EQU $ From 90fac52c168beb0257d03aa0f66c1ed2a3420bf3 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sat, 10 Jul 2021 12:10:07 +0800 Subject: [PATCH 11/13] Delete rtcds7.asm --- Source/Apps/rtcds7.asm | 703 ----------------------------------------- 1 file changed, 703 deletions(-) delete mode 100644 Source/Apps/rtcds7.asm diff --git a/Source/Apps/rtcds7.asm b/Source/Apps/rtcds7.asm deleted file mode 100644 index a2ac01e5..00000000 --- a/Source/Apps/rtcds7.asm +++ /dev/null @@ -1,703 +0,0 @@ -;================================================================================================== -; PCF8584 I2C Clock Driver -;================================================================================================== -; -PCF_BASE .EQU 0F0H -PCF_ID .EQU 0AAH -CPU_CLK .EQU 12 - -REGS0 .EQU PCF_BASE -REGS1 .EQU REGS0+1 -PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE -; -;T4LC512D .EQU 10100000B ; DEVICE IDENTIFIER -;T4LC512A1 .EQU 00000000B ; DEVICE ADDRESS -;T4LC512A2 .EQU 00001110B ; DEVICE ADDRESS -;T4LC512A3 .EQU 00000010B ; DEVICE ADDRESS -;T4LC512W .EQU 00000000B ; DEVICE WRITE -;T4LC512R .EQU 00000001B ; DEVICE READ -; -;I2CDEV1W .EQU (T4LC512D+T4LC512A1+T4LC512W) -;I2CDEV1R .EQU (T4LC512D+T4LC512A1+T4LC512R) -; -;I2CDEV2W .EQU (T4LC512D+T4LC512A2+T4LC512W) -;I2CDEV2R .EQU (T4LC512D+T4LC512A2+T4LC512R) -; -;I2CDEV3W .EQU (T4LC512D+T4LC512A3+T4LC512W) -;I2CDEV3R .EQU (T4LC512D+T4LC512A3+T4LC512R) -; -; CONTROL REGISTER BITS -; -PCF_PIN .EQU 10000000B -PCF_ES0 .EQU 01000000B -PCF_ES1 .EQU 00100000B -PCF_ES2 .EQU 00010000B -PCF_EN1 .EQU 00001000B -PCF_STA .EQU 00000100B -PCF_STO .EQU 00000010B -PCF_ACK .EQU 00000001B -; -PCF_START_ .EQU (PCF_PIN | PCF_ES0 | PCF_STA | PCF_ACK) -PCF_STOP_ .EQU (PCF_PIN | PCF_ES0 | PCF_STO | PCF_ACK) -PCF_REPSTART_ .EQU ( PCF_ES0 | PCF_STA | PCF_ACK) -PCF_IDLE_ .EQU (PCF_PIN | PCF_ES0 | PCF_ACK) -; -; STATUS REGISTER BITS -; -;PCF_PIN .EQU 10000000B -PCF_INI .EQU 01000000B ; 1 if not initialized -PCF_STS .EQU 00100000B -PCF_BER .EQU 00010000B -PCF_AD0 .EQU 00001000B -PCF_LRB .EQU 00001000B -PCF_AAS .EQU 00000100B -PCF_LAB .EQU 00000010B -PCF_BB .EQU 00000001B -; -; CLOCK CHIP FREQUENCIES -; -PCF_CLK3 .EQU 000H -PCF_CLK443 .EQU 010H -PCF_CLK6 .EQU 014H -PCF_CLK8 .EQU 018H -PCF_CLK12 .EQU 01cH -; -; TRANSMISSION FREQUENCIES -; -PCF_TRNS90 .EQU 000H ; 90 kHz */ -PCF_TRNS45 .EQU 001H ; 45 kHz */ -PCF_TRNS11 .EQU 002H ; 11 kHz */ -PCF_TRNS15 .EQU 003H ; 1.5 kHz */ -; -; TIMEOUT AND DELAY VALUES (ARBITRARY) -; -PCF_PINTO .EQU 65000 -PCF_ACKTO .EQU 65000 -PCF_BBTO .EQU 65000 -PCF_LABDLY .EQU 65000 -; -; DATA PORT REGISTERS -; -#IF (CPU_CLK = 443) -PCF_CLK .EQU PCF_CLK443 -#ELSE - #IF (CPU_CLK = 8) -PCF_CLK .EQU PCF_CLK8 - #ELSE - #IF (CPU_CLK = 12) -PCF_CLK .EQU PCF_CLK12 - #ELSE ***ERROR - #ENDIF - #ENDIF -#ENDIF -; -DS7_OUT .EQU 10000000B ; SELECT SQUARE WAVE FUNCTION -DS7_SQWE .EQU 00010000B ; ENABLE SQUARE WAVE OUTPUT -DS7_RATE .EQU 00000000B ; SET 1HZ OUPUT -; -DS7_DS1307 .EQU 11010000B ; DEVICE IDENTIFIER -DS7_W .EQU 00000000B ; DEVICE WRITE -DS7_R .EQU 00000001B ; DEVICE READ -; -DS7_READ .EQU (DS7_DS1307 | DS7_R) ; READ -DS7_WRITE .EQU (DS7_DS1307 | DS7_W) ; WRITE -; -DS7_CTL .EQU (DS7_OUT | DS7_SQWE | DS7_RATE) -; - .ORG 100H -; -; - CALL DS7_RDC ; READ CLOCK DATA INTO BUFFER - CALL DS7_DISP ; DISPLAY TIME AND DATE FROM BUFFER - RET -; -;----------------------------------------------------------------------------- -; RTC READ -; -; 1. ISSUE SLAVE ADDRESS WITH START CONDITION AND WRITE STATUS -; 2. OUTPUT THE ADDRESS TO ACCESS. (00H = START OF DS1307 REGISTERS) -; 3. OUTPUT REPEAT START TO TRANSITION TO READ PROCESS -; 4. ISSUE SLAVE ADDRESS WITH READ STATUS -; 5. DO A DUMMY READ -; 6. READ 8 BYTES STARTING AT ADDRESS PREVIOUSLY SET -; 7. END READ WITH NON-ACKNOWLEDGE -; 8. ISSUE STOP AND RELEASE BUS -; -DS7_RDC:LD A,DS7_WRITE ; SET SLAVE ADDRESS - OUT (REGS0),A -; - CALL PCF_WAIT_FOR_BB - JP NZ,PCF_BBERR -; - CALL PCF_START ; GENERATE START CONDITION - CALL PCF_WAIT_FOR_PIN; AND ISSUE THE SLAVE ADDRESS - CALL NZ,PCF_PINERR -; - LD A,0 - OUT (REGS0),A ; PUT ADDRESS MSB ON BUS - CALL PCF_WAIT_FOR_PIN - CALL NZ,PCF_PINERR -; - CALL PCF_REPSTART ; REPEAT START -; - LD A,DS7_READ ; ISSUE CONTROL BYTE + READ - OUT (REGS0),A -; - CALL PCF_READI2C ; DUMMY READ -; - LD HL,DS7_BUF ; READ 8 BYTES INTO BUFFER - LD B,8 -DS7_RL1:CALL PCF_READI2C - LD (HL),A - INC HL - DJNZ DS7_RL1 -; -#IF (0) - LD A,8 - LD DE,DS7_BUF ; DISLAY DATA READ - CALL PRTHEXBUF ; - CALL NEWLINE -#ENDIF -; - LD A,PCF_ES0 ; END WITH NOT-ACKNOWLEDGE - OUT (REGS1),A ; AND RELEASE BUS - NOP - IN A,(REGS0) - NOP -DS7_WTPIN: - IN A,(REGS1) ; READ S1 REGISTER - BIT 7,A ; CHECK PIN STATUS - JP NZ,DS7_WTPIN - CALL PCF_STOP -; - IN A,(REGS0) - RET - -; -;----------------------------------------------------------------------------- -; DISPLAY CLOCK INFORMATION FROM DATA STORED IN BUFFER -; -DS7_DISP: - LD HL,DS7_CLKTBL -DS7_CLP:LD C,(HL) - INC HL - LD D,(HL) - CALL DS7_BCD - INC HL - LD A,(HL) - OR A - RET Z - CALL COUT - INC HL - JR DS7_CLP - RET -; -DS7_CLKTBL: - .DB 04H, 00111111B, '/' - .DB 05H, 00011111B, '/' - .DB 06H, 11111111B, ' ' - .DB 02H, 00011111B, ':' - .DB 01H, 01111111B, ':' - .DB 00H, 01111111B, 00H -; -DS7_BCD:PUSH HL - LD HL,DS7_BUF ; READ VALUE FROM - LD B,0 ; BUFFER, INDEXED BY A - ADD HL,BC - LD A,(HL) - AND D ; MASK OFF UNNEEDED - SRL A - SRL A - SRL A - SRL A - ADD A,30H - CALL COUT - LD A,(HL) - AND 00001111B - ADD A,30H - CALL COUT - POP HL - RET -; -DS7_BUF: .FILL 8,0 ; BUFFER FOR TIME, DATE AND CONTROL - -;----------------------------------------------------------------------------- -PCF_START: - LD A,PCF_START_ - OUT (REGS1),A - RET -; -;----------------------------------------------------------------------------- -PCF_REPSTART: - LD A,PCF_REPSTART_ - OUT (REGS1),A - RET -; -;----------------------------------------------------------------------------- -PCF_STOP: - LD A,PCF_STOP_ - OUT (REGS1),A - RET -; -;----------------------------------------------------------------------------- -;; -PCF_INIT: - LD A,PCF_PIN ; S1=80H: S0 SELECTED, SERIAL - OUT (REGS1),A ; INTERFACE OFF - NOP - IN A,(REGS1) ; CHECK TO SEE S1 NOW USED AS R/W - AND 07FH ; CTRL. PCF8584 DOES THAT WHEN ESO - JP NZ,PCF_INIERR ; IS ZERO -; - LD A,PCF_OWN ; LOAD OWN ADDRESS IN S0, - OUT (REGS0),A ; EFFECTIVE ADDRESS IS (OWN <<1) - NOP - IN A,(REGS0) ; CHECK IT IS REALLY WRITTEN - CP PCF_OWN - JP NZ,PCF_SETERR -; - LD A,+(PCF_PIN | PCF_ES1) ; S1=0A0H - OUT (REGS1),A ; NEXT BYTE IN S2 - NOP - IN A,(REGS1) - AND 07FH - CP PCF_ES1 - JP NZ,PCF_REGERR -; - LD A,PCF_CLK ; LOAD CLOCK REGISTER S2 - OUT (REGS0),A - NOP - IN A,(REGS0) ; CHECK IT'S REALLY WRITTEN, ONLY - AND 1FH ; THE LOWER 5 BITS MATTER - CP PCF_CLK - JP NZ,PCF_CLKERR -; - LD A,PCF_IDLE_ - OUT (REGS1),A - NOP - IN A,(REGS1) - CP +(PCF_PIN | PCF_BB) - JP NZ,PCF_IDLERR -; - RET -; -;----------------------------------------------------------------------------- -PCF_HANDLE_LAB: -; - LD A,PCF_PIN - OUT (REGS1),A - LD A,PCF_ES0 - OUT (REGS1),A -; - LD HL,PCF_LABDLY -PCF_LABLP: - LD A,H - OR L - DEC HL - JR NZ,PCF_LABLP -; - IN A,(REGS1) - RET -; -;----------------------------------------------------------------------------- -; -; RETURN A=00/Z IF SUCCESSFULL -; RETURN A=FF/NZ IF TIMEOUT -; RETURN A=01/NZ IF LOST ARBITRATION -; PCF_STATUS HOLDS LAST PCF STATUS -; -PCF_WAIT_FOR_PIN: - PUSH HL - LD HL,PCF_PINTO ; SET TIMEOUT VALUE - -PCF_WFP0: - IN A,(REGS1) ; GET BUS - LD (PCF_STATUS),A ; STATUS - LD B,A - - DEC HL ; HAVE WE - LD A,H ; TIMED OUT - OR L - JR Z,PCF_WFP1 ; YES WE HAVE, GO ACTION IT - - LD A,B ; - AND PCF_PIN ; IS TRANSMISSION COMPLETE? - JR NZ,PCF_WFP0 ; KEEP ASKING IF NOT OR - POP HL ; YES COMPLETE (PIN=0) RETURN WITH ZERO - RET -PCF_WFP1: - LD A,B ; DID WE LOSE ARBITRATION? - AND PCF_LAB ; IF A=0 THEN NO - CPL - JR NZ,PCF_WFP2 ; NO - CALL PCF_HANDLE_LAB ; YES GO HANDLE IT - LD (PCF_STATUS),A - XOR A ; RETURN NZ, A=01H - INC A -PCF_WFP2: - POP HL ; RET NZ, A=FF IF TIMEOUT - RET -; -PCF_STATUS .DB 00H - -;-------------------------------------------------------------------------------- -; -; RETURN NZ/FF IF TIMEOUT ERROR -; RETURN NZ/01 IF FAILED TO RECEIVE ACKNOWLEDGE -; RETURN Z/00 IF RECEIVED ACKNOWLEDGE -; -PCF_WAIT_FOR_ACK: - PUSH HL - LD HL,PCF_ACKTO -; -PCF_WFA0: - IN A,(REGS1) ; READ PIN - LD (PCF_STATUS),A ; STATUS - LD B,A -; - DEC HL ; SEE IF WE HAVE TIMED - LD A,H ; OUT WAITING FOR PIN - OR L ; EXIT IF - JR Z,PCF_WFA1 ; WE HAVE -; - LD A,B ; OTHERWISE KEEP LOOPING - AND PCF_PIN ; UNTIL WE GET PIN - JR NZ,PCF_WFA0 ; OR TIMEOUT -; - LD A,B ; WE GOT PIN SO NOW - AND PCF_LRB ; CHECK WE HAVE - LD A,1 - JR Z,PCF_WFA2 ; RECEIVED ACKNOWLEDGE - XOR A - JR PCF_WFA2 -PCF_WFA1: - CPL ; TIMOUT ERROR -PCF_WFA2: - POP HL ; EXIT WITH NZ = FF - RET -; -;-------------------------------------------------------------------------------- -; -; HL POINTS TO DATA -; DE = COUNT -; A = 0 LAST A=1 NOT LAST -; -; -;PCF_READBYTES: ; NOT FUNCTIONAL YET - - LD (PCF_LBF),A ; SAVE LAST BYTE FLAG -; - INC DE ; INCREMENT NUMBER OF BYTES TO READ BY ONE -- DUMMY READ BYTE - LD BC,0 ; SET BYTE COUNTER -; -PCF_RBL:PUSH BC - CALL PCF_WAIT_FOR_PIN ; DO WE HAVE THE BUS? - POP BC - JR Z,PCF_RB1 ; YES - CP 01H - JR Z,PCF_RB3 ; NO - LOST ARBITRATION - JR PCF_RB2 ; NO - TIMEOUT -; -PCF_RB1: - LD A,(PCF_STATUS) - AND PCF_LRB - - - ; IS THIS THE SECOND TO LAST BYTE TO GO? - - PUSH DE ; SAVE COUNT - DEC DE ; COUNT (DE) = NUMBER OF BYTES TO READ LESS 1 - EX DE,HL ; SAVE POINTER, PUT COUNT IN DE - XOR A ; CLEAR CARRY FLAG - SBC HL,BC ; DOES BYTE COUNTER = HL (NUMBER OF BYTES TO READ LESS 1) - EX DE,HL ; RESTORE POINTER - POP DE ; RESTORE COUNT - - ; Z = YES IT IS - ; NZ = NO IT ISN'T - JR NZ,PCF_RB4 -; -PCF_RB4:LD A,B ; IF FIRST READ DO A DUMMY - OR C ; READ OTHERWISE READ AND SAVE - JR NZ,PCF_RB5 - - IN A,(REGS0) ; DUMMY READ - JR PCF_RB6 - -PCF_RB5:IN A,(REGS0) ; READ AND SAVE - LD (HL),A -; -PCF_RB6: ; HAVE WE DONE ALL? - - PUSH DE ; SAVE COUNT - EX DE,HL ; SAVE POINTER, PUT COUNT IN DE - XOR A ; CLEAR CARRY FLAG - SBC HL,BC ; DOES BYTE COUNTER = HL (NUMBER OF BYTES TO READ) - EX DE,HL ; RESTORE POINTER - POP DE ; RESTORE COUNT -; - INC HL ; BUFFER POINTER - INC BC ; COUNT -; - JR NZ,PCF_RBL ; REPEAT UNTIL COUNTS MATCH - RET -; -PCF_RB2: ; TIMEOUT - CALL PCF_STOP - CALL PCF_TOERR - RET -; -PCF_RB3: ; LOST ARBITRATION - CALL PCF_ARBERR - RET -; -PCF_LBF: - .DB 0 ; LAST BYTE FLAG -; -;----------------------------------------------------------------------------- -; READ ONE BYTE FROM I2C -; RETURNS DATA IN A -; Z FLAG SET IS ACKNOWLEDGE RECEIVED (CORRECT OPERATION) -; -PCF_READI2C: - IN A,(REGS1) ; READ S1 REGISTER - BIT 7,A ; CHECK PIN STATUS - JP NZ,PCF_READI2C - BIT 3,A ; CHECK LRB=0 - JP NZ,PCF_RDERR - IN A,(REGS0) ; GET DATA - RET -;----------------------------------------------------------------------------- -; -; POLL THE BUS BUSY BIT TO DETERMINE IF BUS IS FREE. -; RETURN WITH A=00H/Z STATUS IF BUS IS FREE -; RETURN WITH A=FFH/NZ STATUS IF BUS -; -; AFTER RESET THE BUS BUSY BIT WILL BE SET TO 1 I.E. NOT BUSY -; -PCF_WAIT_FOR_BB: - LD HL,PCF_BBTO -PCF_WFBB0: - IN A,(REGS1) - AND PCF_BB - RET Z ; BUS IS FREE RETURN ZERO - DEC HL - LD A,H - OR L - JR NZ,PCF_WFBB0 ; REPEAT IF NOT TIMED OUT - CPL ; RET NZ IF TIMEOUT - RET -; -;----------------------------------------------------------------------------- -; DISPLAY ERROR MESSAGES -; -PCF_RDERR: - PUSH HL - LD HL,PCF_RDFAIL - JR PCF_PRTERR -; -PCF_INIERR: - PUSH HL - LD HL,PCF_NOPCF - JR PCF_PRTERR -; -PCF_SETERR: - PUSH HL - LD HL,PCF_WRTFAIL - JR PCF_PRTERR -; -PCF_REGERR: - PUSH HL - LD HL,PCF_REGFAIL - JR PCF_PRTERR -; -PCF_CLKERR: - PUSH HL - LD HL,PCF_CLKFAIL - JR PCF_PRTERR -; -PCF_IDLERR: - PUSH HL - LD HL,PCF_IDLFAIL - JR PCF_PRTERR -; -PCF_ACKERR: - PUSH HL - LD HL,PCF_ACKFAIL - JR PCF_PRTERR -; -PCF_RDBERR: - PUSH HL - LD HL,PCF_RDBFAIL - JR PCF_PRTERR -; -PCF_TOERR: - PUSH HL - LD HL,PCF_TOFAIL - JR PCF_PRTERR -; -PCF_ARBERR: - PUSH HL - LD HL,PCF_ARBFAIL - JR PCF_PRTERR -; -PCF_PINERR: - PUSH HL - LD HL,PCF_PINFAIL - JR PCF_PRTERR -; -PCF_BBERR: - PUSH HL - LD HL,PCF_BBFAIL - JR PCF_PRTERR -; -PCF_PRTERR: - CALL PRTSTR - CALL NEWLINE - POP HL - RET -; -PCF_NOPCF .DB "NO DEVICE FOUND$" -PCF_WRTFAIL .DB "SETTING DEVICE ID FAILED$" -PCF_REGFAIL .DB "CLOCK REGISTER SELECT ERROR$" -PCF_CLKFAIL .DB "CLOCK SET FAIL$" -PCF_IDLFAIL .DB "BUS IDLE FAILED$" -PCF_ACKFAIL .DB "FAILED TO RECEIVE ACKNOWLEDGE$" -PCF_RDFAIL .DB "READ FAILED$" -PCF_RDBFAIL .DB "READBYTES FAILED$" -PCF_TOFAIL .DB "TIMEOUT ERROR$" -PCF_ARBFAIL .DB "LOST ARBITRATION$" -PCF_PINFAIL .DB "PIN FAIL$" -PCF_BBFAIL .DB "BUS BUSY$" -; -;----------------------------------------------------------------------------- -; -BDOS .EQU 5 ;ENTRY BDOS -BS .EQU 8 ;BACKSPACE -TAB .EQU 9 ;TABULATOR -LF .EQU 0AH ;LINE-FEED -CR .EQU 0DH ;CARRIAGE-RETURN -; -; OUTPUT TEXT AT HL -; -PRTSTR: LD A,(HL) - OR A - RET Z - CALL PRINP - INC HL - JR PRTSTR -; -;Output WORD -;*********** -; -;PARAMETER: Entry WORD IN HL -;********* -; -OUTW: LD A,H - CALL OUTB - LD A,L - CALL OUTB - RET -; -;Output BYTE -;*********** -; -;PARAMETER: Entry BYTE IN A -;********* -; -OUTB: PUSH AF - RRCA - RRCA - RRCA - RRCA - AND 0FH - CALL HBTHE ;Change Half-BYTE - POP AF - AND 0FH - CALL HBTHE - RET -; -;Output HALF-BYTE -;**************** -; -;PARAMETER: Entry Half-BYTE IN A (BIT 0 - 3) -;********* -; -HBTHE: CP 0AH - JR C,HBTHE1 - ADD A,7 ;Character to Letter -HBTHE1: ADD A,30H - LD E,A - CALL PCHAR - RET -; -; -;Output on Screen -;**************** -; -PRBS: LD E,BS - CALL PCHAR - RET -; -;Output CR+LF on Screen -;********************** -; -NEWLINE: -CRLF: LD E,CR - CALL PCHAR - LD E,LF - CALL PCHAR - RET -; -;Output ASCII-Character -;********************** -; -COUT: -PRINP: PUSH AF - PUSH DE - LD E,A - CALL PCHAR - POP DE - POP AF - RET -; -;CALL BDOS with Register Save -;**************************** -; -INCHA: LD C,1 ;INPUT CHARACTER TO A - JR BDO -PCHAR: LD C,2 ;PRINT CHARACTER IN E - JR BDO -PSTRIN: LD C,9 ;PRINT STRING - JR BDO -INBUFF: LD C,10 ;READ CONSOLE-BUFFER - JR BDO -CSTS: LD C,11 ;CONSOLE-STATUS - JR BDO -OPEN: LD C,15 ;OPEN FILE - JR BDO -CLOSE: LD C,16 ;CLOSE FILE - JR BDO -DELETE: LD C,19 ;DELETE FILE - JR BDO -READS: LD C,20 ;READ SEEK - JR BDO -WRITES: LD C,21 ;WRITE SEEK - JR BDO -MAKE: LD C,22 ;MAKE FILE - JR BDO -SETDMA: LD C,26 ;SET DMA-ADDRESS -BDO: PUSH HL - PUSH DE - PUSH BC - PUSH IX - PUSH IY - CALL BDOS - POP IY - POP IX - POP BC - POP DE - POP HL - RET -; - .END From 9b9f9ded0893bf57e11a24c813787265b02a999d Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 11 Jul 2021 13:01:44 +0800 Subject: [PATCH 12/13] Add graceful fail to i2c clock driver --- Source/Apps/rtchb.asm | 29 +++-- Source/HBIOS/ds7rtc.asm | 32 +++--- Source/HBIOS/pcf8584.asm | 221 ++++++++++++++++++++------------------- 3 files changed, 158 insertions(+), 124 deletions(-) diff --git a/Source/Apps/rtchb.asm b/Source/Apps/rtchb.asm index cf4669bf..9fe4ff15 100644 --- a/Source/Apps/rtchb.asm +++ b/Source/Apps/rtchb.asm @@ -1,27 +1,40 @@ ;================================================================================================== ; GENERIC HBIOS DATE AND TIME ;================================================================================================== +; + .ECHO "rtchb\n" ; ; HBIOS FORMAT = YYMMDDHHMMSS ; .ORG 100H ; + LD (HBC_STK),SP ; SETUP A + LD SP,HBC_LOC ; LOCAL STACK ; LD B,$20 ; READ CLOCK DATA INTO BUFFER LD HL,HBC_BUF ; DISPLAY TIME AND DATE FROM BUFFER RST 08 +; + OR A ; EXIT IF NO + JR NZ,HBC_ERR ; DRIVER OR HARDWARE ; #IF (0) + PUSH AF LD A,6 LD DE,HBC_BUF ; DISLAY DATA READ ; CALL PRTHEXBUF CALL NEWLINE + POP AF #ENDIF ; - CALL HBC_DISP - RET - -HBC_BUF .FILL 6,0 + CALL HBC_DISP +; +HBC_EXIT: + LD SP,(HBC_STK) ; RESTORE STACK AND + RET ; RETURN TO CP/M +; +HBC_BUF .FILL 6,0 ; DATE AND TIME STORAGE +HBC_STK .DW 2 ; SAVE STACK ; ;----------------------------------------------------------------------------- ; DISPLAY CLOCK INFORMATION FROM DATA STORED IN BUFFER @@ -80,7 +93,7 @@ HBC_PRTERR: CALL PRTSTR CALL NEWLINE POP HL - RET + JP HBC_EXIT ; HBC_FAIL .DB "ERROR$" ; @@ -96,9 +109,9 @@ CR .EQU 0DH ;CARRIAGE-RETURN ; OUTPUT TEXT AT HL ; PRTSTR: LD A,(HL) - OR A + CP '$' RET Z - CALL PRINP + CALL COUT INC HL JR PRTSTR ; @@ -215,4 +228,6 @@ BDO: PUSH HL POP HL RET ; + .FILL 128,$FF +HBC_LOC: .END diff --git a/Source/HBIOS/ds7rtc.asm b/Source/HBIOS/ds7rtc.asm index 31a259df..262ca0af 100644 --- a/Source/HBIOS/ds7rtc.asm +++ b/Source/HBIOS/ds7rtc.asm @@ -18,18 +18,6 @@ DS7_WRITE .EQU (DS7_DS1307 | DS7_W) ; WRITE ; DS7_CTL .EQU (DS7_OUT | DS7_SQWE | DS7_RATE) ; - -; GENERIC CP/M STUFF -; -BS .EQU 8 ; BACKSPACE -TAB .EQU 9 ; TABULATOR -LF .EQU 0AH ; LINE-FEED -CR .EQU 0DH ; CARRIAGE-RETURN -CLIARGS .EQU $81 -RESTART .EQU $0000 ; CP/M restart vector -BDOS .EQU $0005 ; BDOS invocation vector -FCB .EQU $5C ; Location of default FCB -; ;----------------------------------------------------------------------------- ; DS1307 INITIALIZATION ; @@ -45,6 +33,10 @@ FCB .EQU $5C ; Location of default FCB DS7RTC_INIT: PRTS("DS1307: $") ; ANNOUNCE DRIVER ; + LD A,(PCF_FAIL_FLAG) ; CHECK IF THE + OR A ; I2C DRIVER + JR NZ,RTC_INIT_FAIL ; INITIALIZED + CALL DS7_RDC ; READ CLOCK DATA LD HL,DS7_BUF ; IF NOT RUNNING OR BIT 7,(HL) ; INVALID, RESTART @@ -66,6 +58,16 @@ DS7_CSET: XOR A ; SIGNAL SUCCESS RET ; +RTC_INIT_FAIL: ; EXIT + CALL PRTSTRD ; WITH + .DB "NO I2C DRIVER$" ; ERROR + PUSH AF ; MESSAGE +RTC_INIT_ERR: ; EXIT + POP AF ; WITH + LD A,ERR_NOHW ; ERROR + OR A ; STATUS + RET +; ;----------------------------------------------------------------------------- ; DS1307 HBIOS DISPATCHER ; @@ -73,6 +75,12 @@ DS7_CSET: ; B: FUNCTION (IN) ; DS7_DISPATCH: + PUSH AF ; CHECK IF WE + LD A,(PCF_FAIL_FLAG) ; HAVE HARDWARE + OR A ; AND ASSOCIATED + JR NZ,RTC_INIT_ERR ; DRIVER + POP AF +; LD A, B ; GET REQUESTED FUNCTION AND $0F ; ISOLATE SUB-FUNCTION JP Z, DS7_GETTIM ; GET TIME diff --git a/Source/HBIOS/pcf8584.asm b/Source/HBIOS/pcf8584.asm index 5f4c8330..507f1037 100644 --- a/Source/HBIOS/pcf8584.asm +++ b/Source/HBIOS/pcf8584.asm @@ -6,9 +6,9 @@ PCF_BASE .EQU 0F0H PCF_ID .EQU 0AAH CPU_CLK .EQU 12 -PCF_RS0 .EQU PCF_BASE -PCF_RS1 .EQU PCF_RS0+1 -PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE +PCF_RS0 .EQU PCF_BASE +PCF_RS1 .EQU PCF_RS0+1 +PCF_OWN .EQU (PCF_ID >> 1) ; PCF'S ADDRESS IN SLAVE MODE ; ;T4LC512D .EQU 10100000B ; DEVICE IDENTIFIER ;T4LC512A1 .EQU 00000000B ; DEVICE ADDRESS @@ -37,10 +37,10 @@ PCF_STA .EQU 00000100B PCF_STO .EQU 00000010B PCF_ACK .EQU 00000001B ; -PCF_START_ .EQU (PCF_PIN | PCF_ES0 | PCF_STA | PCF_ACK) -PCF_STOP_ .EQU (PCF_PIN | PCF_ES0 | PCF_STO | PCF_ACK) -PCF_REPSTART_ .EQU ( PCF_ES0 | PCF_STA | PCF_ACK) -PCF_IDLE_ .EQU (PCF_PIN | PCF_ES0 | PCF_ACK) +PCF_START_ .EQU (PCF_PIN | PCF_ES0 | PCF_STA | PCF_ACK) +PCF_STOP_ .EQU (PCF_PIN | PCF_ES0 | PCF_STO | PCF_ACK) +PCF_REPSTART_ .EQU ( PCF_ES0 | PCF_STA | PCF_ACK) +PCF_IDLE_ .EQU (PCF_PIN | PCF_ES0 | PCF_ACK) ; ; STATUS REGISTER BITS ; @@ -52,7 +52,7 @@ PCF_AD0 .EQU 00001000B PCF_LRB .EQU 00001000B PCF_AAS .EQU 00000100B PCF_LAB .EQU 00000010B -PCF_BB .EQU 00000001B +PCF_BB .EQU 00000001B ; ; CLOCK CHIP FREQUENCIES ; @@ -109,6 +109,7 @@ PCF8584_INIT: PRTS("I2C: IO=0x$") LD A, PCF_BASE CALL PRTHEXBYTE + CALL PC_SPACE CALL PCF_INIT CALL NEWLINE RET @@ -122,81 +123,91 @@ PCF8584_INIT: ; ;----------------------------------------------------------------------------- PCF_START: - LD A,PCF_START_ - OUT (PCF_RS1),A + LD A,PCF_START_ + OUT (PCF_RS1),A RET ; ;----------------------------------------------------------------------------- PCF_REPSTART: - LD A,PCF_REPSTART_ - OUT (PCF_RS1),A + LD A,PCF_REPSTART_ + OUT (PCF_RS1),A RET ; ;----------------------------------------------------------------------------- PCF_STOP: LD A,PCF_STOP_ - OUT (PCF_RS1),A - RET + OUT (PCF_RS1),A + RET ; ;----------------------------------------------------------------------------- ; PCF_INIT: - LD A,PCF_PIN ; S1=80H: S0 SELECTED, SERIAL - OUT (PCF_RS1),A ; INTERFACE OFF - NOP - IN A,(PCF_RS1) ; CHECK TO SEE S1 NOW USED AS R/W - AND 07FH ; CTRL. PCF8584 DOES THAT WHEN ESO - JP NZ,PCF_INIERR ; IS ZERO -; - LD A,PCF_OWN ; LOAD OWN ADDRESS IN S0, - OUT (PCF_RS0),A ; EFFECTIVE ADDRESS IS (OWN <<1) - NOP - IN A,(PCF_RS0) ; CHECK IT IS REALLY WRITTEN - CP PCF_OWN - JP NZ,PCF_SETERR -; - LD A,+(PCF_PIN | PCF_ES1) ; S1=0A0H - OUT (PCF_RS1),A ; NEXT BYTE IN S2 - NOP - IN A,(PCF_RS1) - AND 07FH - CP PCF_ES1 - JP NZ,PCF_REGERR -; - LD A,PCF_CLK ; LOAD CLOCK REGISTER S2 - OUT (PCF_RS0),A - NOP - IN A,(PCF_RS0) ; CHECK IT'S REALLY WRITTEN, ONLY - AND 1FH ; THE LOWER 5 BITS MATTER - CP PCF_CLK - JP NZ,PCF_CLKERR -; - LD A,PCF_IDLE_ - OUT (PCF_RS1),A - NOP - IN A,(PCF_RS1) - CP +(PCF_PIN | PCF_BB) - JP NZ,PCF_IDLERR -; - RET + LD A,PCF_PIN ; S1=80H: S0 SELECTED, SERIAL + OUT (PCF_RS1),A ; INTERFACE OFF + NOP + IN A,(PCF_RS1) ; CHECK TO SEE S1 NOW USED AS R/W + AND 07FH ; CTRL. PCF8584 DOES THAT WHEN ESO + JR NZ,PCF_FAIL ; IS ZERO +; + LD A,PCF_OWN ; LOAD OWN ADDRESS IN S0, + OUT (PCF_RS0),A ; EFFECTIVE ADDRESS IS (OWN <<1) + NOP + IN A,(PCF_RS0) ; CHECK IT IS REALLY WRITTEN + CP PCF_OWN + JP NZ,PCF_SETERR +; + LD A,+(PCF_PIN | PCF_ES1) ; S1=0A0H + OUT (PCF_RS1),A ; NEXT BYTE IN S2 + NOP + IN A,(PCF_RS1) + AND 07FH + CP PCF_ES1 + JP NZ,PCF_REGERR +; + LD A,PCF_CLK ; LOAD CLOCK REGISTER S2 + OUT (PCF_RS0),A + NOP + IN A,(PCF_RS0) ; CHECK IT'S REALLY WRITTEN, ONLY + AND 1FH ; THE LOWER 5 BITS MATTER + CP PCF_CLK + JP NZ,PCF_CLKERR +; + LD A,PCF_IDLE_ + OUT (PCF_RS1),A + NOP + IN A,(PCF_RS1) + CP +(PCF_PIN | PCF_BB) + JP NZ,PCF_IDLERR +; + XOR A + RET +; +PCF_FAIL: + CALL PCF_INIERR + LD A,ERR_NOHW + LD (PCF_FAIL_FLAG),A + RET +; +PCF_FAIL_FLAG: + .DB 0 ; ;----------------------------------------------------------------------------- PCF_HANDLE_LAB: ; - LD A,PCF_PIN - OUT (PCF_RS1),A - LD A,PCF_ES0 - OUT (PCF_RS1),A + LD A,PCF_PIN + OUT (PCF_RS1),A + LD A,PCF_ES0 + OUT (PCF_RS1),A ; - LD HL,PCF_LABDLY + LD HL,PCF_LABDLY PCF_LABLP: - LD A,H - OR L - DEC HL - JR NZ,PCF_LABLP + LD A,H + OR L + DEC HL + JR NZ,PCF_LABLP ; - IN A,(PCF_RS1) - RET + IN A,(PCF_RS1) + RET ; ;----------------------------------------------------------------------------- ; @@ -207,10 +218,10 @@ PCF_LABLP: ; PCF_WAIT_FOR_PIN: PUSH HL - LD HL,PCF_PINTO ; SET TIMEOUT VALUE + LD HL,PCF_PINTO ; SET TIMEOUT VALUE PCF_WFP0: - IN A,(PCF_RS1) ; GET BUS + IN A,(PCF_RS1) ; GET BUS LD (PCF_STATUS),A ; STATUS LD B,A @@ -220,8 +231,8 @@ PCF_WFP0: JR Z,PCF_WFP1 ; YES WE HAVE, GO ACTION IT LD A,B ; - AND PCF_PIN ; IS TRANSMISSION COMPLETE? - JR NZ,PCF_WFP0 ; KEEP ASKING IF NOT OR + AND PCF_PIN ; IS TRANSMISSION COMPLETE? + JR NZ,PCF_WFP0 ; KEEP ASKING IF NOT OR POP HL ; YES COMPLETE (PIN=0) RETURN WITH ZERO RET PCF_WFP1: @@ -234,7 +245,7 @@ PCF_WFP1: XOR A ; RETURN NZ, A=01H INC A PCF_WFP2: - POP HL ; RET NZ, A=FF IF TIMEOUT + POP HL ; RET NZ, A=FF IF TIMEOUT RET ; PCF_STATUS .DB 00H @@ -250,18 +261,18 @@ PCF_WAIT_FOR_ACK: LD HL,PCF_ACKTO ; PCF_WFA0: - IN A,(PCF_RS1) ; READ PIN - LD (PCF_STATUS),A ; STATUS - LD B,A -; - DEC HL ; SEE IF WE HAVE TIMED - LD A,H ; OUT WAITING FOR PIN - OR L ; EXIT IF - JR Z,PCF_WFA1 ; WE HAVE -; - LD A,B ; OTHERWISE KEEP LOOPING - AND PCF_PIN ; UNTIL WE GET PIN - JR NZ,PCF_WFA0 ; OR TIMEOUT + IN A,(PCF_RS1) ; READ PIN + LD (PCF_STATUS),A ; STATUS + LD B,A +; + DEC HL ; SEE IF WE HAVE TIMED + LD A,H ; OUT WAITING FOR PIN + OR L ; EXIT IF + JR Z,PCF_WFA1 ; WE HAVE +; + LD A,B ; OTHERWISE KEEP LOOPING + AND PCF_PIN ; UNTIL WE GET PIN + JR NZ,PCF_WFA0 ; OR TIMEOUT ; LD A,B ; WE GOT PIN SO NOW AND PCF_LRB ; CHECK WE HAVE @@ -375,16 +386,16 @@ PCF_READI2C: ; AFTER RESET THE BUS BUSY BIT WILL BE SET TO 1 I.E. NOT BUSY ; PCF_WAIT_FOR_BB: - LD HL,PCF_BBTO + LD HL,PCF_BBTO PCF_WFBB0: - IN A,(PCF_RS1) - AND PCF_BB - RET Z ; BUS IS FREE RETURN ZERO - DEC HL - LD A,H - OR L - JR NZ,PCF_WFBB0 ; REPEAT IF NOT TIMED OUT - CPL ; RET NZ IF TIMEOUT + IN A,(PCF_RS1) + AND PCF_BB + RET Z ; BUS IS FREE RETURN ZERO + DEC HL + LD A,H + OR L + JR NZ,PCF_WFBB0 ; REPEAT IF NOT TIMED OUT + CPL ; RET NZ IF TIMEOUT RET ; ;----------------------------------------------------------------------------- @@ -397,32 +408,32 @@ PCF_RDERR: ; PCF_INIERR: PUSH HL - LD HL,PCF_NOPCF + LD HL,PCF_NOPCF JR PCF_PRTERR ; PCF_SETERR: PUSH HL - LD HL,PCF_WRTFAIL + LD HL,PCF_WRTFAIL JR PCF_PRTERR ; PCF_REGERR: PUSH HL - LD HL,PCF_REGFAIL + LD HL,PCF_REGFAIL JR PCF_PRTERR ; PCF_CLKERR: PUSH HL - LD HL,PCF_CLKFAIL + LD HL,PCF_CLKFAIL JR PCF_PRTERR ; PCF_IDLERR: PUSH HL - LD HL,PCF_IDLFAIL + LD HL,PCF_IDLFAIL JR PCF_PRTERR ; PCF_ACKERR: PUSH HL - LD HL,PCF_ACKFAIL + LD HL,PCF_ACKFAIL JR PCF_PRTERR ; PCF_RDBERR: @@ -452,7 +463,7 @@ PCF_BBERR: ; PCF_PRTERR: CALL PRTSTR - CALL NEWLINE +; CALL NEWLINE POP HL RET ; @@ -462,8 +473,8 @@ PCF_PRTERR: #IF (1) PCF_DBG: PUSH AF - PUSH DE - PUSH HL + PUSH DE + PUSH HL LD A,'[' CALL COUT LD HL,PCF_DBGF @@ -473,19 +484,19 @@ PCF_DBG: CALL COUT LD A,']' CALL COUT - POP HL - POP DE - POP AF + POP HL + POP DE + POP AF RET PCF_DBGF: .DB 0 ; DEBUG STAGE COUNTER #ENDIF ; PCF_NOPCF .DB "NO DEVICE FOUND$" -PCF_WRTFAIL .DB "SETTING DEVICE ID FAILED$" -PCF_REGFAIL .DB "CLOCK REGISTER SELECT ERROR$" -PCF_CLKFAIL .DB "CLOCK SET FAIL$" -PCF_IDLFAIL .DB "BUS IDLE FAILED$" +PCF_WRTFAIL .DB "SETTING DEVICE ID FAILED$" +PCF_REGFAIL .DB "CLOCK REGISTER SELECT ERROR$" +PCF_CLKFAIL .DB "CLOCK SET FAIL$" +PCF_IDLFAIL .DB "BUS IDLE FAILED$" PCF_ACKFAIL .DB "FAILED TO RECEIVE ACKNOWLEDGE$" PCF_RDFAIL .DB "READ FAILED$" PCF_RDBFAIL .DB "READBYTES FAILED$" From 91c7c1dbba33f5a8cbee763a1ea65d2651827545 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 11 Jul 2021 22:52:23 +0800 Subject: [PATCH 13/13] Add graceful exit for DS1307 utility --- Source/Apps/I2C/rtcds7.asm | 243 +++++++++++++++++-------------------- Source/HBIOS/pcf8584.asm | 74 +++++------ 2 files changed, 151 insertions(+), 166 deletions(-) diff --git a/Source/Apps/I2C/rtcds7.asm b/Source/Apps/I2C/rtcds7.asm index 045a1cd0..2c05c96c 100644 --- a/Source/Apps/I2C/rtcds7.asm +++ b/Source/Apps/I2C/rtcds7.asm @@ -1,20 +1,21 @@ ;================================================================================================== -; PCF8584 I2C Clock Driver +; PCF8584/DS1307 I2C DATE AND TIME UTILITY ;================================================================================================== ; .ECHO "rtcds7\n" ; #INCLUDE "pcfi2c.inc" ; - -; - .ORG 100H + .ORG 100H ; DS7_START: - CALL DS7_PROBE ; PROBE FRO DEVICE - RET Z ; EXIT IF DEVICE NOT FOUND + LD (DS7_STK),SP ; SETUP A + LD SP,DS7_LOC ; LOCAL STACK ; - LD A,(FCB+1) ; GET FIRST CHAR + CALL DS7_INIT ; INITIALIZE AND + JR NZ,DS7_ERR ; RETURN WITH STATUS +; + LD A,(FCB+1) ; GET FIRST COMMAND LINE CHAR CP ' ' ; COMPARE TO BLANK. IF SO NO JR Z,DS7_ST0 ; ARGUMENTS SO DISLAY TIME AND DATE ; @@ -28,7 +29,7 @@ DS7_START: ; ; /D SET DATE ; - RET + JR DS7_EXIT ; DS7_ST1: LD A,(FCB+2) ; GET NEXT CHARACTER @@ -37,7 +38,7 @@ DS7_ST1: ; ; /T SET TIME ; - RET + JR DS7_EXIT ; DS7_ST2: LD A,(FCB+2) ; GET NEXT CHARACTER @@ -46,48 +47,27 @@ DS7_ST2: ; ; /S SET TIME AND DATE ; - RET + JR DS7_EXIT ; DS7_ST3: ; ; UNREGOGNIZED ARGUMENT ; - RET + JR DS7_EXIT ; DS7_ST0: - CALL DS7_RDC ; READ CLOCK DATA INTO BUFFER - CALL DS7_DISP ; DISPLAY TIME AND DATE FROM BUFFER - RET + CALL DS7_RDC ; READ CLOCK DATA INTO BUFFER + CALL DS7_DISP ; DISPLAY TIME AND DATE FROM BUFFER ; -;----------------------------------------------------------------------------- -; RETURN 00/Z IF NOT FOUND -; NZ IF FOUND +DS7_EXIT: + LD SP,(DS7_STK) ; RESTORE STACK + RET ; AND EXIT ; +DS7_ERR: + CALL PCF_INIERR ; DISPLAY ERROR + JR DS7_EXIT ; END EXIT ; -DS7_PROBE: - LD A,PCF_PIN ; SET PIN BIT - OUT (PCF_RS1),A - NOP - IN A,(PCF_RS1) ; CHECK IF SET - AND 07FH - JR NZ,DS7_PR0 ; ERROR IF NOT SET - - LD A,'%' - CALL COUT - - OR 0FFH ; SUCCESS - RET - -DS7_PR0: - LD A,PCF_OWN ; LOAD OWN ADDRESS IN S0, - OUT (PCF_RS0),A ; EFFECTIVE ADDRESS IS (OWN <<1) - - LD A,PCF_IDLE_ - OUT (PCF_RS1),A - - CALL PCF_INIERR ; DISLAY ERROR - XOR A ; SET ERROR - RET +DS7_STK .DW 2 ; SAVE STACK ; ;----------------------------------------------------------------------------- ; RTC READ @@ -101,25 +81,26 @@ DS7_PR0: ; 7. END READ WITH NON-ACKNOWLEDGE ; 8. ISSUE STOP AND RELEASE BUS ; -DS7_RDC:LD A,DS7_WRITE ; SET SLAVE ADDRESS - OUT (REGS0),A +DS7_RDC: + LD A,DS7_WRITE ; SET SLAVE ADDRESS + OUT (REGS0),A ; CALL PCF_WAIT_FOR_BB JP NZ,PCF_BBERR ; - CALL PCF_START ; GENERATE START CONDITION + CALL PCF_START ; GENERATE START CONDITION CALL PCF_WAIT_FOR_PIN; AND ISSUE THE SLAVE ADDRESS CALL NZ,PCF_PINERR ; - LD A,0 - OUT (REGS0),A ; PUT ADDRESS MSB ON BUS + LD A,0 + OUT (REGS0),A ; PUT ADDRESS MSB ON BUS CALL PCF_WAIT_FOR_PIN CALL NZ,PCF_PINERR ; CALL PCF_REPSTART ; REPEAT START ; - LD A,DS7_READ ; ISSUE CONTROL BYTE + READ - OUT (REGS0),A + LD A,DS7_READ ; ISSUE CONTROL BYTE + READ + OUT (REGS0),A ; CALL PCF_READI2C ; DUMMY READ ; @@ -149,7 +130,7 @@ DS7_WTPIN: CALL PCF_STOP ; IN A,(REGS0) - RET + RET ; ;----------------------------------------------------------------------------- @@ -165,7 +146,7 @@ DS7_CLP:LD C,(HL) LD A,(HL) OR A RET Z - CALL COUT + CALL COUT INC HL JR DS7_CLP RET @@ -180,10 +161,10 @@ DS7_CLKTBL: ; DS7_BCD:PUSH HL LD HL,DS7_BUF ; READ VALUE FROM - LD B,0 ; BUFFER, INDEXED BY A + LD B,0 ; BUFFER, INDEXED BY A ADD HL,BC LD A,(HL) - AND D ; MASK OFF UNNEEDED + AND D ; MASK OFF UNNEEDED SRL A SRL A SRL A @@ -201,81 +182,82 @@ DS7_BUF: .FILL 8,0 ; BUFFER FOR TIME, DATE AND CONTROL ;----------------------------------------------------------------------------- PCF_START: - LD A,PCF_START_ + LD A,PCF_START_ OUT (REGS1),A RET ; ;----------------------------------------------------------------------------- PCF_REPSTART: - LD A,PCF_REPSTART_ + LD A,PCF_REPSTART_ OUT (REGS1),A RET ; ;----------------------------------------------------------------------------- PCF_STOP: LD A,PCF_STOP_ - OUT (REGS1),A - RET + OUT (REGS1),A + RET ; ;----------------------------------------------------------------------------- -;; -PCF_INIT: - LD A,PCF_PIN ; S1=80H: S0 SELECTED, SERIAL - OUT (REGS1),A ; INTERFACE OFF - NOP - IN A,(REGS1) ; CHECK TO SEE S1 NOW USED AS R/W - AND 07FH ; CTRL. PCF8584 DOES THAT WHEN ESO - JP NZ,PCF_INIERR ; IS ZERO -; - LD A,PCF_OWN ; LOAD OWN ADDRESS IN S0, - OUT (REGS0),A ; EFFECTIVE ADDRESS IS (OWN <<1) - NOP - IN A,(REGS0) ; CHECK IT IS REALLY WRITTEN - CP PCF_OWN - JP NZ,PCF_SETERR -; - LD A,+(PCF_PIN | PCF_ES1) ; S1=0A0H - OUT (REGS1),A ; NEXT BYTE IN S2 - NOP - IN A,(REGS1) - AND 07FH - CP PCF_ES1 - JP NZ,PCF_REGERR -; - LD A,PCF_CLK ; LOAD CLOCK REGISTER S2 - OUT (REGS0),A - NOP - IN A,(REGS0) ; CHECK IT'S REALLY WRITTEN, ONLY - AND 1FH ; THE LOWER 5 BITS MATTER - CP PCF_CLK - JP NZ,PCF_CLKERR -; - LD A,PCF_IDLE_ - OUT (REGS1),A - NOP - IN A,(REGS1) - CP +(PCF_PIN | PCF_BB) - JP NZ,PCF_IDLERR -; - RET +; +DS7_INIT: + LD A,PCF_PIN ; S1=80H: S0 SELECTED, SERIAL + OUT (REGS1),A ; INTERFACE OFF + NOP + IN A,(REGS1) ; CHECK TO SEE S1 NOW USED AS R/W CTRL. + AND 07FH ; PCF8584 DOES THAT WHEN ESO IS ZERO + RET NZ ; PCF_INIERR +; + LD A,PCF_OWN ; LOAD OWN ADDRESS IN S0, + OUT (REGS0),A ; EFFECTIVE ADDRESS IS (OWN <<1) + NOP + IN A,(REGS0) ; CHECK IT IS REALLY WRITTEN + CP PCF_OWN + RET NZ ; PCF_SETERR +; + LD A,+(PCF_PIN | PCF_ES1) ; S1=0A0H + OUT (REGS1),A ; NEXT BYTE IN S2 + NOP + IN A,(REGS1) + AND 07FH + CP PCF_ES1 + RET NZ ; PCF_REGERR +; + LD A,PCF_CLK ; LOAD CLOCK REGISTER S2 + OUT (REGS0),A + NOP + IN A,(REGS0) ; CHECK IT'S REALLY WRITTEN, ONLY + AND 1FH ; THE LOWER 5 BITS MATTER + CP PCF_CLK + RET NZ ; PCF_CLKERR +; + LD A,PCF_IDLE_ + OUT (REGS1),A + NOP + IN A,(REGS1) + CP +(PCF_PIN | PCF_BB) + RET NZ ; PCF_IDLERR +; + XOR A + RET ; ;----------------------------------------------------------------------------- PCF_HANDLE_LAB: ; - LD A,PCF_PIN - OUT (REGS1),A - LD A,PCF_ES0 + LD A,PCF_PIN + OUT (REGS1),A + LD A,PCF_ES0 OUT (REGS1),A ; - LD HL,PCF_LABDLY + LD HL,PCF_LABDLY PCF_LABLP: LD A,H - OR L - DEC HL - JR NZ,PCF_LABLP + OR L + DEC HL + JR NZ,PCF_LABLP ; - IN A,(REGS1) - RET + IN A,(REGS1) + RET ; ;----------------------------------------------------------------------------- ; @@ -286,7 +268,7 @@ PCF_LABLP: ; PCF_WAIT_FOR_PIN: PUSH HL - LD HL,PCF_PINTO ; SET TIMEOUT VALUE + LD HL,PCF_PINTO ; SET TIMEOUT VALUE PCF_WFP0: IN A,(REGS1) ; GET BUS @@ -299,8 +281,8 @@ PCF_WFP0: JR Z,PCF_WFP1 ; YES WE HAVE, GO ACTION IT LD A,B ; - AND PCF_PIN ; IS TRANSMISSION COMPLETE? - JR NZ,PCF_WFP0 ; KEEP ASKING IF NOT OR + AND PCF_PIN ; IS TRANSMISSION COMPLETE? + JR NZ,PCF_WFP0 ; KEEP ASKING IF NOT OR POP HL ; YES COMPLETE (PIN=0) RETURN WITH ZERO RET PCF_WFP1: @@ -313,7 +295,7 @@ PCF_WFP1: XOR A ; RETURN NZ, A=01H INC A PCF_WFP2: - POP HL ; RET NZ, A=FF IF TIMEOUT + POP HL ; RET NZ, A=FF IF TIMEOUT RET ; PCF_STATUS .DB 00H @@ -330,17 +312,17 @@ PCF_WAIT_FOR_ACK: ; PCF_WFA0: IN A,(REGS1) ; READ PIN - LD (PCF_STATUS),A ; STATUS - LD B,A -; - DEC HL ; SEE IF WE HAVE TIMED - LD A,H ; OUT WAITING FOR PIN - OR L ; EXIT IF - JR Z,PCF_WFA1 ; WE HAVE -; - LD A,B ; OTHERWISE KEEP LOOPING - AND PCF_PIN ; UNTIL WE GET PIN - JR NZ,PCF_WFA0 ; OR TIMEOUT + LD (PCF_STATUS),A ; STATUS + LD B,A +; + DEC HL ; SEE IF WE HAVE TIMED + LD A,H ; OUT WAITING FOR PIN + OR L ; EXIT IF + JR Z,PCF_WFA1 ; WE HAVE +; + LD A,B ; OTHERWISE KEEP LOOPING + AND PCF_PIN ; UNTIL WE GET PIN + JR NZ,PCF_WFA0 ; OR TIMEOUT ; LD A,B ; WE GOT PIN SO NOW AND PCF_LRB ; CHECK WE HAVE @@ -454,16 +436,16 @@ PCF_READI2C: ; AFTER RESET THE BUS BUSY BIT WILL BE SET TO 1 I.E. NOT BUSY ; PCF_WAIT_FOR_BB: - LD HL,PCF_BBTO + LD HL,PCF_BBTO PCF_WFBB0: IN A,(REGS1) - AND PCF_BB - RET Z ; BUS IS FREE RETURN ZERO - DEC HL - LD A,H - OR L - JR NZ,PCF_WFBB0 ; REPEAT IF NOT TIMED OUT - CPL ; RET NZ IF TIMEOUT + AND PCF_BB + RET Z ; BUS IS FREE RETURN ZERO + DEC HL + LD A,H + OR L + JR NZ,PCF_WFBB0 ; REPEAT IF NOT TIMED OUT + CPL ; RET NZ IF TIMEOUT RET ; ;----------------------------------------------------------------------------- @@ -552,4 +534,7 @@ PCF_BBFAIL .DB "BUS BUSY$" ; #INCLUDE "i2ccpm.inc" ; - .END + .FILL 128 +DS7_LOC: +; + .END diff --git a/Source/HBIOS/pcf8584.asm b/Source/HBIOS/pcf8584.asm index 507f1037..54dfe6a4 100644 --- a/Source/HBIOS/pcf8584.asm +++ b/Source/HBIOS/pcf8584.asm @@ -123,21 +123,21 @@ PCF8584_INIT: ; ;----------------------------------------------------------------------------- PCF_START: - LD A,PCF_START_ + LD A,PCF_START_ OUT (PCF_RS1),A RET ; ;----------------------------------------------------------------------------- PCF_REPSTART: - LD A,PCF_REPSTART_ + LD A,PCF_REPSTART_ OUT (PCF_RS1),A RET ; ;----------------------------------------------------------------------------- PCF_STOP: LD A,PCF_STOP_ - OUT (PCF_RS1),A - RET + OUT (PCF_RS1),A + RET ; ;----------------------------------------------------------------------------- ; @@ -194,20 +194,20 @@ PCF_FAIL_FLAG: ;----------------------------------------------------------------------------- PCF_HANDLE_LAB: ; - LD A,PCF_PIN + LD A,PCF_PIN OUT (PCF_RS1),A - LD A,PCF_ES0 + LD A,PCF_ES0 OUT (PCF_RS1),A ; - LD HL,PCF_LABDLY + LD HL,PCF_LABDLY PCF_LABLP: LD A,H - OR L - DEC HL - JR NZ,PCF_LABLP + OR L + DEC HL + JR NZ,PCF_LABLP ; - IN A,(PCF_RS1) - RET + IN A,(PCF_RS1) + RET ; ;----------------------------------------------------------------------------- ; @@ -218,7 +218,7 @@ PCF_LABLP: ; PCF_WAIT_FOR_PIN: PUSH HL - LD HL,PCF_PINTO ; SET TIMEOUT VALUE + LD HL,PCF_PINTO ; SET TIMEOUT VALUE PCF_WFP0: IN A,(PCF_RS1) ; GET BUS @@ -231,8 +231,8 @@ PCF_WFP0: JR Z,PCF_WFP1 ; YES WE HAVE, GO ACTION IT LD A,B ; - AND PCF_PIN ; IS TRANSMISSION COMPLETE? - JR NZ,PCF_WFP0 ; KEEP ASKING IF NOT OR + AND PCF_PIN ; IS TRANSMISSION COMPLETE? + JR NZ,PCF_WFP0 ; KEEP ASKING IF NOT OR POP HL ; YES COMPLETE (PIN=0) RETURN WITH ZERO RET PCF_WFP1: @@ -262,17 +262,17 @@ PCF_WAIT_FOR_ACK: ; PCF_WFA0: IN A,(PCF_RS1) ; READ PIN - LD (PCF_STATUS),A ; STATUS - LD B,A + LD (PCF_STATUS),A ; STATUS + LD B,A ; - DEC HL ; SEE IF WE HAVE TIMED - LD A,H ; OUT WAITING FOR PIN - OR L ; EXIT IF - JR Z,PCF_WFA1 ; WE HAVE + DEC HL ; SEE IF WE HAVE TIMED + LD A,H ; OUT WAITING FOR PIN + OR L ; EXIT IF + JR Z,PCF_WFA1 ; WE HAVE ; - LD A,B ; OTHERWISE KEEP LOOPING - AND PCF_PIN ; UNTIL WE GET PIN - JR NZ,PCF_WFA0 ; OR TIMEOUT + LD A,B ; OTHERWISE KEEP LOOPING + AND PCF_PIN ; UNTIL WE GET PIN + JR NZ,PCF_WFA0 ; OR TIMEOUT ; LD A,B ; WE GOT PIN SO NOW AND PCF_LRB ; CHECK WE HAVE @@ -389,13 +389,13 @@ PCF_WAIT_FOR_BB: LD HL,PCF_BBTO PCF_WFBB0: IN A,(PCF_RS1) - AND PCF_BB - RET Z ; BUS IS FREE RETURN ZERO - DEC HL - LD A,H - OR L - JR NZ,PCF_WFBB0 ; REPEAT IF NOT TIMED OUT - CPL ; RET NZ IF TIMEOUT + AND PCF_BB + RET Z ; BUS IS FREE RETURN ZERO + DEC HL + LD A,H + OR L + JR NZ,PCF_WFBB0 ; REPEAT IF NOT TIMED OUT + CPL ; RET NZ IF TIMEOUT RET ; ;----------------------------------------------------------------------------- @@ -473,8 +473,8 @@ PCF_PRTERR: #IF (1) PCF_DBG: PUSH AF - PUSH DE - PUSH HL + PUSH DE + PUSH HL LD A,'[' CALL COUT LD HL,PCF_DBGF @@ -484,15 +484,15 @@ PCF_DBG: CALL COUT LD A,']' CALL COUT - POP HL - POP DE - POP AF + POP HL + POP DE + POP AF RET PCF_DBGF: .DB 0 ; DEBUG STAGE COUNTER #ENDIF ; -PCF_NOPCF .DB "NO DEVICE FOUND$" +PCF_NOPCF .DB "NOT PRESENT$" PCF_WRTFAIL .DB "SETTING DEVICE ID FAILED$" PCF_REGFAIL .DB "CLOCK REGISTER SELECT ERROR$" PCF_CLKFAIL .DB "CLOCK SET FAIL$"