Browse Source

Merge pull request #206 from b1ackmai1er/dev

ECB-DMA initial release. I2C rearrangement
pull/209/head
Wayne Warthen 5 years ago
committed by GitHub
parent
commit
40e94ebd99
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Source/Apps/Build.cmd
  2. 15
      Source/Apps/I2C/Build.cmd
  3. 5
      Source/Apps/I2C/Clean.cmd
  4. 21
      Source/Apps/I2C/Makefile
  5. 132
      Source/Apps/I2C/i2ccpm.inc
  6. 517
      Source/Apps/I2C/i2clcd.asm
  7. 500
      Source/Apps/I2C/i2cscan.asm
  8. 116
      Source/Apps/I2C/pcfi2c.inc
  9. 540
      Source/Apps/I2C/rtcds7.asm
  10. 2
      Source/Apps/Makefile
  11. 703
      Source/Apps/rtcds7.asm
  12. 29
      Source/Apps/rtchb.asm
  13. 4
      Source/HBIOS/cfg_dyno.asm
  14. 4
      Source/HBIOS/cfg_ezz80.asm
  15. 4
      Source/HBIOS/cfg_master.asm
  16. 4
      Source/HBIOS/cfg_mk4.asm
  17. 4
      Source/HBIOS/cfg_n8.asm
  18. 4
      Source/HBIOS/cfg_rcz180.asm
  19. 4
      Source/HBIOS/cfg_rcz280.asm
  20. 4
      Source/HBIOS/cfg_rcz80.asm
  21. 4
      Source/HBIOS/cfg_sbc.asm
  22. 4
      Source/HBIOS/cfg_scz180.asm
  23. 4
      Source/HBIOS/cfg_zeta.asm
  24. 5
      Source/HBIOS/cfg_zeta2.asm
  25. 324
      Source/HBIOS/dma.asm
  26. 115
      Source/HBIOS/ds7rtc.asm
  27. 12
      Source/HBIOS/hbios.asm
  28. 15
      Source/HBIOS/md.asm
  29. 2
      Source/HBIOS/nascom.asm
  30. 248
      Source/HBIOS/pcf8584.asm
  31. 4
      Source/HBIOS/pio.asm
  32. 16
      Source/HBIOS/rf.asm
  33. 57
      Source/HBIOS/sn76489.asm
  34. 8
      Source/HBIOS/std.asm

2
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%\

15
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\

5
Source/Apps/I2C/Clean.cmd

@ -0,0 +1,5 @@
@echo off
setlocal
if exist *.com del *.com
if exist *.lst del *.lst

21
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

132
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

517
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

500
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

116
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)

540
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

2
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

703
Source/Apps/rtcds7.asm

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

29
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

4
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)

4
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)

4
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)

4
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)

4
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)

4
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)

4
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)

4
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)

4
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)

4
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)

4
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)

5
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)

324
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

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

12
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 $

15
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)

2
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

248
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$"

4
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:

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

57
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

8
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

Loading…
Cancel
Save