diff --git a/Source/Apps/Build.cmd b/Source/Apps/Build.cmd index ac3ed35c..ee85be71 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 call :asm ppidetst || goto :eof call :asm tstdskng || goto :eof @@ -34,6 +33,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..60b6a312 --- /dev/null +++ b/Source/Apps/I2C/Build.cmd @@ -0,0 +1,15 @@ +@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 +tasm -t180 -g3 -fFF i2clcd.asm i2clcd.com i2clcd.lst + +if errorlevel 1 goto :eof + +copy /Y i2c*.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/Makefile b/Source/Apps/I2C/Makefile new file mode 100644 index 00000000..cdee4fdd --- /dev/null +++ b/Source/Apps/I2C/Makefile @@ -0,0 +1,21 @@ +OBJECTS = i2cscan.com, rtcds7.com, i2clcd.com +DEST = ../../../Binary/Apps +TOOLS = ../../../Tools + +include $(TOOLS)/Makefile.inc + +DEPS1 := i2cscan.asm $(shell find . -name '*.inc') +DEPS2 := rtcds7.asm $(shell find . -name '*.inc') +DEPS3 := i2clcd.asm $(shell find . -name '*.inc') + + +i2cscan.com: $(DEPS1) + $(TASM) -dWBW i2cscan.asm i2cscan.com i2cscan.lst + +rtcds7.com: $(DEPS2) + $(TASM) -dWBW rtcds7.asm rtcds7.com rtcds7.lst + +i2clcd.com: $(DEPS3) + $(TASM) -dWBW i2clcd.asm i2clcd.com i2clcd.lst + + 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/Apps/I2C/i2cscan.asm b/Source/Apps/I2C/i2cscan.asm new file mode 100644 index 00000000..5b594ef5 --- /dev/null +++ b/Source/Apps/I2C/i2cscan.asm @@ -0,0 +1,500 @@ +; + .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 +; +;----------------------------------------------------------------------------- +; + .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" +#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 + 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 + +;----------------------------------------------------------------------------- +#IF (PCF) +_i2c_start: +PCF_START: + LD A,PCF_START_ + OUT (PCF_RS1),A + RET +#ELSE +;_i2c_start: + ld a,_idle ; issue + out (I2C_BASE),a ; start + ; command + res _sda,a + out (I2C_BASE),a + nop + nop + res _scl,a + out (I2C_BASE),a + + ld (oprval),a + ret +#ENDIF +; +;----------------------------------------------------------------------------- +; +; 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 +; +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 +; +;----------------------------------------------------------------------------- +; 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$" +; +;----------------------------------------------------------------------------- +#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 (I2C_BASE),a + + set _scl,a + out (I2C_BASE),a + nop + nop + set _sda,a + out (I2C_BASE),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 (I2C_BASE),a + set _scl,a + 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 (I2C_BASE),a + djnz i2c1 + + set _sda,a + out (I2C_BASE),a + set _scl,a + out (I2C_BASE),a + + ld d,a +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 (I2C_BASE),a + ld (oprval),a + + xor a + bit _sda,c + ret z + inc a + + ret +#ENDIF +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/pcfi2c.inc b/Source/Apps/I2C/pcfi2c.inc new file mode 100644 index 00000000..c61dcb59 --- /dev/null +++ b/Source/Apps/I2C/pcfi2c.inc @@ -0,0 +1,116 @@ +;================================================================================================== +; PCF8584 Generic +;================================================================================================== +; +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 +; +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 new file mode 100644 index 00000000..2c05c96c --- /dev/null +++ b/Source/Apps/I2C/rtcds7.asm @@ -0,0 +1,540 @@ +;================================================================================================== +; PCF8584/DS1307 I2C DATE AND TIME UTILITY +;================================================================================================== +; + .ECHO "rtcds7\n" +; +#INCLUDE "pcfi2c.inc" +; + .ORG 100H +; +DS7_START: + LD (DS7_STK),SP ; SETUP A + LD SP,DS7_LOC ; LOCAL STACK +; + 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 +; + 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 +; + JR DS7_EXIT +; +DS7_ST1: + LD A,(FCB+2) ; GET NEXT CHARACTER + CP 'T' ; + JR NZ,DS7_ST2 ; +; +; /T SET TIME +; + JR DS7_EXIT +; +DS7_ST2: + LD A,(FCB+2) ; GET NEXT CHARACTER + CP 'S' ; + JR NZ,DS7_ST3 ; +; +; /S SET TIME AND DATE +; + JR DS7_EXIT +; +DS7_ST3: +; +; UNREGOGNIZED ARGUMENT +; + JR DS7_EXIT +; +DS7_ST0: + CALL DS7_RDC ; READ CLOCK DATA INTO BUFFER + CALL DS7_DISP ; DISPLAY TIME AND DATE FROM BUFFER +; +DS7_EXIT: + LD SP,(DS7_STK) ; RESTORE STACK + RET ; AND EXIT +; +DS7_ERR: + CALL PCF_INIERR ; DISPLAY ERROR + JR DS7_EXIT ; END EXIT +; +DS7_STK .DW 2 ; SAVE STACK +; +;----------------------------------------------------------------------------- +; 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 +; +;----------------------------------------------------------------------------- +; +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 + 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$" +; +;----------------------------------------------------------------------------- +; +#INCLUDE "i2ccpm.inc" +; + .FILL 128 +DS7_LOC: +; + .END diff --git a/Source/Apps/Makefile b/Source/Apps/Makefile index 88caf898..c2785b51 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 ppidetst.com tstdskng.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/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 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/cfg_dyno.asm b/Source/HBIOS/cfg_dyno.asm index e05d31b4..c83fa6a7 100644 --- a/Source/HBIOS/cfg_dyno.asm +++ b/Source/HBIOS/cfg_dyno.asm @@ -190,3 +190,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_Z180 ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_ezz80.asm b/Source/HBIOS/cfg_ezz80.asm index e8791d78..c858c2c7 100644 --- a/Source/HBIOS/cfg_ezz80.asm +++ b/Source/HBIOS/cfg_ezz80.asm @@ -225,3 +225,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_NONE ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_master.asm b/Source/HBIOS/cfg_master.asm index 18f7d6ff..4a198c10 100644 --- a/Source/HBIOS/cfg_master.asm +++ b/Source/HBIOS/cfg_master.asm @@ -297,3 +297,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_NONE ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index a5af36f4..726c33b9 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -230,3 +230,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_ECB ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index ad3f1f38..b5e2d87c 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -228,3 +228,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_ECB ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_rcz180.asm b/Source/HBIOS/cfg_rcz180.asm index e709bb45..a98fa0b8 100644 --- a/Source/HBIOS/cfg_rcz180.asm +++ b/Source/HBIOS/cfg_rcz180.asm @@ -238,3 +238,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_Z180 ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_rcz280.asm b/Source/HBIOS/cfg_rcz280.asm index a0786854..d807eb5a 100644 --- a/Source/HBIOS/cfg_rcz280.asm +++ b/Source/HBIOS/cfg_rcz280.asm @@ -254,3 +254,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_Z280 ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_rcz80.asm b/Source/HBIOS/cfg_rcz80.asm index 480e1dd5..c0b45afa 100644 --- a/Source/HBIOS/cfg_rcz80.asm +++ b/Source/HBIOS/cfg_rcz80.asm @@ -243,3 +243,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_RC ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index aae602e5..1ad20a3e 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -229,3 +229,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_ECB ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index 5e32a44b..939f8f88 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -233,3 +233,7 @@ AY_CLK .EQU CPUOSC / 4 ; DEFAULT TO CPUOSC / 4 AYMODE .EQU AYMODE_RCZ180 ; AY: DRIVER MODE: AYMODE_[SCG/N8/RCZ80/RCZ180] ; 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_Z180 ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index 8acd8239..79740aa2 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -165,3 +165,7 @@ UFENABLE .EQU FALSE ; UF: ENABLE ECB USB FIFO DRIVER (UF.ASM) SN76489ENABLE .EQU FALSE ; SN76489 SOUND DRIVER AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER 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_NONE ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index ba3d9758..5cbdb2eb 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -176,3 +176,8 @@ UFENABLE .EQU FALSE ; UF: ENABLE ECB USB FIFO DRIVER (UF.ASM) SN76489ENABLE .EQU FALSE ; SN76489 SOUND DRIVER AY38910ENABLE .EQU FALSE ; AY: AY-3-8910 / YM2149 SOUND DRIVER 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_NONE ; DMA: DMA MODE (NONE|ECB|Z180|Z280|RC) diff --git a/Source/HBIOS/dma.asm b/Source/HBIOS/dma.asm new file mode 100644 index 00000000..065c30e1 --- /dev/null +++ b/Source/HBIOS/dma.asm @@ -0,0 +1,324 @@ +;================================================================================================== +; Z80 DMA DRIVER FOR ECB-DMA +;================================================================================================== +; +; DUE TO LOW CLOCK SPEED CONTRAINTS OF Z80 DMA CHIP, THE HALF CLOCK FACILITY +; IS USED DURING DMA PROGRAMMING AND CONTINUOUS BLOCK TRANSFERS. +; TESTING CONDUCTED ON A SBC-V2-005 @ 10Mhz +; +DMA_CONTINUOUS .equ %10111101 ; + Pulse +DMA_BYTE .equ %10011101 ; + Pulse +DMA_BURST .equ %11011101 ; + Pulse +DMA_LOAD .equ $cf ; %11001111 +DMA_ENABLE .equ $87 ; %10000111 +DMA_FORCE_READY .equ $b3 +DMA_DISABLE .equ $83 +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 +;DMA_DISABLE_INTERUPTS .equ $af +;DMA_ENABLE_INTERUPTS .equ $ab +;DMA_RESET_DISABLE_INTERUPTS .equ $a3 +;DMA_ENABLE_AFTER_RETI .equ $b7 +;DMA_REINIT_STATUS_BYTE .equ $8b +; +;================================================================================================== +; DMA INITIALIZATION CODE +;================================================================================================== +; +DMA_INIT: + CALL NEWLINE + PRTS("DMA: IO=0x$") ; announce + LD A, DMABASE + CALL PRTHEXBYTE +; + 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 +; + di + otir ; load dma + ei + xor a ; set status +; +DMA_EXIT: + push af + ld a,(RTCVAL) + and %11110111 ; full + 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-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 (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 (RTCIO),a ; clock + pop af + 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 (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 (RTCIO),a ; clock + pop af + 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 (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 (RTCIO),a ; clock + pop af + 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 +; +;================================================================================================== +; 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/ds7rtc.asm b/Source/HBIOS/ds7rtc.asm index ab105c9b..262ca0af 100644 --- a/Source/HBIOS/ds7rtc.asm +++ b/Source/HBIOS/ds7rtc.asm @@ -33,6 +33,10 @@ DS7_CTL .EQU (DS7_OUT | DS7_SQWE | DS7_RATE) 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 @@ -54,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 ; @@ -61,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 @@ -88,7 +108,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 +163,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/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 $ diff --git a/Source/HBIOS/md.asm b/Source/HBIOS/md.asm index 8ef62440..81f756e9 100644 --- a/Source/HBIOS/md.asm +++ b/Source/HBIOS/md.asm @@ -350,10 +350,15 @@ MD_SECM: LD HL,MD_F4KBUF ; POINT TO THE SECTOR WE ADD HL,DE ; WANT TO COPY LD DE,(MD_DSKBUF) +; +#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 -; XOR A +#ENDIF RET ; ; SETUP DE:HL AS THE SECTOR ADDRESS TO READ OR WRITE @@ -466,8 +471,14 @@ MD_SECM1: ; DESIRED SECTOR IS IN BUFFER EX DE,HL ; LD HL,(MD_DSKBUF) +#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 +#ENDIF ; LD IX,MD_F4KBUF ; SET SOURCE ADDRESS LD HL,MD_FWRIT_R ; PUT ROUTINE TO CALL @@ -745,7 +756,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/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/pcf8584.asm b/Source/HBIOS/pcf8584.asm index e53a4adb..54dfe6a4 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 ; @@ -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,11 +91,25 @@ 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$") LD A, PCF_BASE CALL PRTHEXBYTE + CALL PC_SPACE CALL PCF_INIT CALL NEWLINE RET @@ -104,86 +118,96 @@ 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) ; ;----------------------------------------------------------------------------- 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 ; ;----------------------------------------------------------------------------- ; @@ -194,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 @@ -207,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: @@ -221,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 @@ -237,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 @@ -362,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 ; ;----------------------------------------------------------------------------- @@ -384,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: @@ -439,40 +463,40 @@ PCF_BBERR: ; PCF_PRTERR: CALL PRTSTR - CALL NEWLINE +; CALL NEWLINE POP HL RET ; ;----------------------------------------------------------------------------- ; DEBUG HELPER ; -#IF (0) -DS7_DBG: +#IF (1) +PCF_DBG: PUSH AF - PUSH DE - PUSH HL + PUSH DE + PUSH HL LD A,'[' CALL COUT - LD HL,DS7_DBGF + LD HL,PCF_DBGF LD A,(HL) ADD A,'0' INC (HL) CALL COUT LD A,']' CALL COUT - POP HL - POP DE - POP AF + POP HL + POP DE + POP AF RET -DS7_DBGF: +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_NOPCF .DB "NOT PRESENT$" +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$" diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index 73e99853..f198f25a 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/rf.asm b/Source/HBIOS/rf.asm index 282a962e..04539646 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,13 +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 & (DMAMODE=DMAMODE_ECB)) + 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 XOR A ; SIGNAL SUCCESS +#ENDIF RET ; AND DONE ; ; WRITE SECTOR @@ -285,13 +290,18 @@ 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 & (DMAMODE=DMAMODE_ECB)) + 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 XOR A ; SIGNAL SUCCESS +#ENDIF RET ; AND DONE ; ; 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 diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index bf9bff37..8fa32d99 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -215,6 +215,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_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 +; ; SERIAL DEVICE CONFIGURATION CONSTANTS ; SER_DATA5 .EQU 0 << 0