This is a my project of 15 years ago based on Z80 chipset. The project aimed to buid a system to receive and transmit packets
throught a PCM-30 8bit timeslot using a SIO device. The Z80 CPU was connected to an host throught a dual port RAM.
You can find more informations about Zilog Z80 on this website
This is a include file to define common symbols for other modules
NLIST
;
;*******************
;** STARLET.INC **
;*******************
;
;Define phisical devices I/O address indirizzi fisici periferiche
;
PIODA: EQU 0
PIODB: EQU 1
PIOCA: EQU 2
PIOCB: EQU 3
SIODA: EQU 4
SIODB: EQU 5
SIOCA: EQU 6
SIOCB: EQU 7
CTC0: EQU 0CH
CTC1: EQU 0DH
CTC2: EQU 0EH
CTC3: EQU 0FH
DPRAM1: EQU 4000H
;
SIOA$SIOD: EQU SIODA
SIOA$SIOC: EQU SIOCA
SIOB$SIOD: EQU SIODB
SIOB$SIOC: EQU SIOCB
SIOA$CTCB: EQU CTC0
SIOA$CTCI: EQU CTC2
SIOB$CTCB: EQU CTC1
SIOB$CTCI: EQU CTC3
;
;Definizioni per baud rate
;
BR19200: EQU 1
BR9600: EQU 2
BR4800: EQU 4
BR2400: EQU 8
BR1200: EQU 16
BR600: EQU 32
;
;Definizioni per pacchetto del tipo I/O request
;
IRP$DISPL: EQU 8
IRP$SOH: EQU 1
IRP$STX: EQU 2
IRP$ETX: EQU 3
IRP$EOT: EQU 04H
IRP$ACK: EQU 06H
IRP$BEL: EQU 07H
IRP$NAK: EQU 15H
IRP$CAN: EQU 18H
;
;Definizioni tipi di struttura
;
IRP$SIO: EQU 20H ;pacchetto per sio
IRP$TIMER: EQU 30H ;pacchetto per timer
;
;Definizioni pacchetti di I/O
;
NUM_SRP:EQU 1 ;Number of small request packets
SIZ_SRP:EQU 32 ;Size of small request packets
NUM_MRP:EQU 1 ;Number of medium request packets
SIZ_MRP:EQU 64 ;Size of medium request packets
NUM_LRP:EQU 90 ;Number of large request packets
SIZ_LRP:EQU 80 ;Size of large request packets
;
LIST
This is the main module, where there are initialization of devices and the scheduling of processes.
;
;# Module : MAIN
;# Date : August 28, 1992
;# Author : Pompeo Riccardo
;
PUBLIC EXE$RAM,EXE$START,EXE$MAIN
PUBLIC EXE$PROCESS,EXE$PROCESSI
EXTRN EQM$INIT,MBX$INIT
EXTRN CTC$CONNECT,CTC$INTA,CTC$INTB
EXTRN SIOA$CONNECT,SIOA$INT
;
INCLUDE STARLET.INC
;
CSEG
;
DI
JP EXE$START
;
;# Interrupt dispatch table
;
ORG 10H
IDT$CTC:
DW NOINT
DW NOINT
DW CTC$INTA
DW CTC$INTB
;
ORG 20H
IDT$PIO:
DW SIOA$INT
;
NOINT: EI
DEVRES: RETI
RET
;
EXE$START:
LD SP,STACK ;Inizializza ram
LD HL,EXE$RAM ;
LD DE,EXE$RAM+1 ;
LD BC,1FFEH ;
LD (HL),0 ;
LDIR ;
;
;# Queues initialization
;
CALL EQM$INIT ;Inizializza code dei vuoti
LD HL,PROCESS_QUEUE ;Inizializza coda dei processi
LD (QUEPTR),HL ;
LD (SCHPTR),HL ;
;
;# Drivers initialization
;
LD A,IDT$CTC ;Inizializza driver
CALL CTC$CONNECT ;
LD A,IDT$PIO ;Attivazione seriale
CALL SIOA$CONNECT ;
;
;# Other initialization
;
LD B,5 ;Abbatte eventuali interrupt
C10: CALL DEVRES ;sulle periferiche
DJNZ C10 ;
IM 2 ;Attiva interrupt
LD A,0 ;
LD I,A ;
EI ;
;
;# Process activation
;
CALL MBX$INIT ;
;
;# Process scheduling
;
EXE$MAIN:
OUT (8),A ;Strobe
LD HL,(SCHPTR) ;Sconfinamento puntatore ?
LD DE,(QUEPTR) ;
OR A ;
SBC HL,DE ;
JR Z,EXE$MAIN ;
LD HL,(SCHPTR) ;
LD E,(HL) ;
INC L ;
LD D,(HL) ;
INC L ;
LD (SCHPTR),HL ;
EX DE,HL ;
LD DE,EXE$MAIN ;Setta indirizzo di ritorno
PUSH DE ;
JP (HL) ;Lancia processo
;
;# Enqueue a process (DE = process pointer)
;
EXE$PROCESS:
DI
LD HL,(QUEPTR)
LD (HL),E
INC L
LD (HL),D
INC L
LD (QUEPTR),HL
EI
RET
;
;# Entry point for interrupt (process whaking)
;
EXE$PROCESSI:
LD HL,(QUEPTR)
LD (HL),E
INC L
LD (HL),D
INC L
LD (QUEPTR),HL
RET
;
DSEG
;
EXE$RAM:
DS 100H ;Stack
STACK: ;
PROCESS_QUEUE: DS 100H ;No relocable
SCHPTR: DS 2 ;Scheduler pointer
QUEPTR: DS 2 ;Queuer pointer
;
END
This is a library that includes several basic functions
;
;# Program : Z80 library
;# Date : April 22, 1992
;# Author : Pompeo Riccardo
;
PUBLIC LIB$INSQH,LIB$INSQT,LIB$REMQH,LIB$REMQT
PUBLIC LIB$INSQHI,LIB$INSQTI,LIB$REMQHI,LIB$REMQTI
PUBLIC LIB$INIT_QUEUE,LIB$INIT_HEADER
PUBLIC LIB$HVAL,LIB$HSTR,LIB$DVAL,LIB$DSTR,LIB$NIBBLE
PUBLIC LIB$IDIV,LIB$IMUL,LIB$BCDBIN,LIB$BINBCD
PUBLIC LIB$BIN$,LIB$BCD$,LIB$BCD$Z?,LIB$CPHLDE,LIB$ADHLA
PUBLIC LIB$ONCALL,LIB$ONJUMP
PUBLIC LIB$DPRINT,LIB$HPRINT,LIB$COPY,LIB$INDEX
PUBLIC LIB$ASC_BIN,LIB$STR_HVAL,LIB$BIT_SUM,LIB$BIT_TEST
PUBLIC LIB$BINBCD3,LIB$PCKPTR,LIB$ADDBCD,LIB$BINASC2
;
;# Queue structure header
;
;00 - FORWARD POINTER (LOW BYTE)
;01 - FORWARD POINTER (HIGH BYTE)
;02 - BACKWARD POINTER (LOW BYTE)
;03 - BACKWARD POINTER (HIGH BYTE)
;04 - FLAGS (LOW BYTE)
;05 - FLAGS (HIGHT BYTE)
;
;# Packet structure header
;
;00 - FORWARD POINTER (LOW BYTE)
;01 - FORWARD POINTER (HIGH BYTE)
;02 - BACKWARD POINTER (LOW BYTE)
;03 - BACKWARD POINTER (HIGH BYTE)
;04 - FLAGS (LOW BYTE)
;05 - FLAGS (HIGHT BYTE)
;06 - PACKET SIZE
;07 - TYPE OF STRUCTURE
;
;# Target : Get the pointer after the header
;# Input : IY = packet pointer
;# Output : DE = pointer inside the pachet
;# Used : A
;
LIB$PCKPTR:
PUSH IY
POP DE
LD A,8
ADD A,E
LD E,A
LD A,0
ADC A,D
LD D,A
RET
;
;# Target : Insert an element in the head of queue
;# Input : IX = queue header pointer
;# IY = packet pointer to add in the queue
;# Output : none
;# Used : all
;
LIB$INSQH:
DI
CALL LIB$INSQHI
EI
RET
;
LIB$INSQHI:
LD C,(IX+0) ;BC=H_F=L
LD B,(IX+1)
PUSH IX
POP HL
LD E,L ;IX=DE=H
LD D,H
XOR A ;SE H_F=H CODA VUOTA
SBC HL,BC
JR Z,INSQEMP
LD (IY+0),C ;E_F=L=BC
LD (IY+1),B
LD (IY+2),E ;E_B=H=DE
LD (IY+3),D
PUSH IY
POP HL
LD (IX+0),L ;H_F=E=HL=IY
LD (IX+1),H
PUSH BC
POP IX ;IX=L
LD (IX+2),L ;L_B=E=HL
LD (IX+3),H
RET
;
;Coda vuota
;
INSQEMP:
LD (IY+0),E ;E_F=H=DE
LD (IY+1),D
LD (IY+2),E ;E_B=H=DE
LD (IY+3),D
;
PUSH IY
POP HL
LD (IX+0),L ;H_F=E=HL=IY
LD (IX+1),H
LD (IX+2),L ;H_B=E=HL=IY
LD (IX+3),H
RET
;
;# Target : Insert a packet in the tail of queue
;# Input : IX = queue header pointer
;# IY = packet pointer to add to the queue
;# Output : none
;# Used : all
;
LIB$INSQT:
DI
CALL LIB$INSQTI
EI
RET
;
LIB$INSQTI:
LD C,(IX+2) ;BC=H_B=L
LD B,(IX+3)
PUSH IX
POP HL
LD E,L ;IX=DE=H
LD D,H
XOR A ;SE H_B=H CODA VUOTA
SBC HL,BC
JR Z,INSQEMP
LD (IY+0),E ;E_F=H=DE
LD (IY+1),D
LD (IY+2),C ;E_B=L=BC
LD (IY+3),B
PUSH IY
POP HL
LD (IX+2),L ;H_B=E=HL=IY
LD (IX+3),H
PUSH BC
POP IX ;IX=L
LD (IX+0),L ;L_F=E=HL
LD (IX+1),H
RET
;
;# Target : Remove an element from head of queue
;# Input : IX = header queue pointer
;# Output : IY = removed packet pointer
;# CY = if 1 queue empty
;# Used : all
;
LIB$REMQH:
DI
CALL LIB$REMQHI
EI
RET
;
LIB$REMQHI:
LD C,(IX+0) ;BC=H_F=R
LD B,(IX+1)
PUSH IX
POP HL
LD E,L ;IX=DE=H
LD D,H
XOR A ;SE H_F=H CODA VUOTA
SBC HL,BC
JR Z,REMQEMPTY
PUSH BC
POP IY ;IY=BC=R
LD L,(IY+0) ;H_F=R_F=L=HL
LD H,(IY+1)
LD (IX+0),L
LD (IX+1),H
PUSH HL
POP IX ;IX=HL=L
LD (IX+2),E ;L_B=H=DE
LD (IX+3),D
XOR A ;CY=0
RET
;
;Coda vuota
;
REMQEMPTY:
SCF ;CY=1
RET
;
;# Target : Remove an element fomr the end of queue
;# Input : IX = queue header pointer
;# Output : IY = removed packet pointer
;# CY = if 1 queue empty
;# Used : all
;
LIB$REMQT:
DI
CALL LIB$REMQTI
EI
RET
;
LIB$REMQTI:
LD C,(IX+2) ;BC=H_B=R
LD B,(IX+3)
PUSH IX
POP HL
LD E,L ;IX=DE=H
LD D,H
XOR A ;SE H_B=H CODA VUOTA
SBC HL,BC
JR Z,REMQEMPTY
PUSH BC
POP IY ;IY=BC=R
LD L,(IY+2) ;H_B=R_B=L=HL
LD H,(IY+3)
LD (IX+2),L
LD (IX+3),H
PUSH HL
POP IX ;IX=HL=L
LD (IX+0),E ;L_F=H=DE
LD (IX+1),D
XOR A ;CY=0
RET
;
;# Target : Initialize a queue
;# Input : IX = queue header pointer
;# IY = buffer pointer (first element of queue of empty packets)
;# HL = state flag
;# A = type fo structure
;# B = packets count
;# C = lenght of packets
;# Output : none
;# Used : all
;
LIB$INIT_QUEUE:
PUSH IX
PUSH IY
PUSH HL
PUSH BC
PUSH AF
CALL LIB$INSQTI
POP AF
POP BC
POP HL
POP IY
POP IX
LD (IY+4),L
LD (IY+5),H
LD (IY+6),C
LD (IY+7),A
LD E,C
LD D,0
ADD IY,DE
DJNZ LIB$INIT_QUEUE
RET
;
;# Target : Initialize an header
;# Input : IX = queue header pointer
;# HL = state flags
;# Output : none
;# Used : DE
;
LIB$INIT_HEADER:
PUSH IX
POP DE
LD (IX+0),E ;INIT HEADER FORWARD POINTER
LD (IX+1),D
LD (IX+2),E ;INIT HEADER BACKWARD POINTER
LD (IX+3),D
LD (IX+4),L ;INIT FLAGS
LD (IX+5),H
RET
;
;# Target : Displace over an array of words (16bit)
;# Input : HL = array pointer
;# A = index
;# Output : HL = word
;# Used : DE
;
LIB$INDEX:
RLCA
LD E,A
LD D,0
ADD HL,DE
LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL
RET
;
;# Target : Copy a string
;# Input : HL = string pointer
;# DE = destination buffer pointer
;# B = stop character (included)
;# Output : none
;# Used : none
;
LIB$COPY:
LD A,(HL)
LD (DE),A
CP B
RET Z
INC HL
INC DE
JR LIB$COPY
;
;# Target : Indexed jump
;# Input : IX = pointer to index to test
;# DE = values table
;# HL = jump table pointer
;# Output : none
;# Used : A
;
LIB$ONJUMP:
LD A,(DE)
OR A
RET Z
CP (IX)
JR Z,RUNJMP
INC DE
INC HL
INC HL
JR LIB$ONJUMP
RUNJMP: LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL
POP DE ;PULISCE DALL'ULTIMA CALL
JP (HL)
;
;# Target : Indexed call
;# Input : IX = pointer to index to test
;# DE = values table
;# HL = jump table pointer
;# Output : none
;# Used : A
;
LIB$ONCALL:
LD A,(DE)
OR A
RET Z
CP (IX)
JR Z,RUNCALL
INC DE
INC HL
INC HL
JR LIB$ONCALL
RUNCALL:LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL
JP (HL)
;
;# Target : Add HL with A
;# Input : HL A
;# Output : HL = HL+A
;# Used : none
;
LIB$ADHLA:
ADD A,L
LD L,A
LD A,0
ADC A,H
LD H,A
RET
;
;# Target : Compare HL with DE
;# Input : HL DE
;# Output : CY Z
;# Used : none
;
LIB$CPHLDE:
PUSH HL
OR A
SBC HL,DE
POP HL
RET
;
;# Target : Convert binary to ascii
;# Input : A = binary nibble
;# Output : A = ascii
;# Used : none
;
LIB$BIN$:
AND 0FH
OR 30H
CP 3AH
RET C
ADD A,7
RET
;
;# Target : Convert bcd to ascii
;# Input : A = bcd nibble
;# Output : A = ascii
;# Used : none
;
LIB$BCD$:
AND 0FH
OR 30H
CP 3AH
JR NC,CBLK
RET
;
;# Target : Convert bcd to ascii
;# if 0 return a space character
;# Input : A = bcd nibble
;# Output : A = ascii
;# Used : none
;
LIB$BCD$Z?:
AND 0FH
OR 30H
CP 30H
JR Z,CBLK
CP 3AH
JR NC,CBLK
RET
CBLK: LD A,' '
RET
;
;# Target : Convert binary to ascii 2 bytes
;# Input : A = bunary byte
;# Output : E = ascii low nibble
; D = ascii high nibble
;# Used : none
;
LIB$BINASC2:
CALL LIB$NIBBLE
LD A,D
CALL LIB$BIN$
LD D,A
LD A,E
CALL LIB$BIN$
LD E,A
RET
;
;# Target : Convert 4 binary nibbles in compacted binary
;# Input : IX = nibbles pointer
;# Output : HL = output buffer pointer
;# Used : A
;
LIB$HVAL:
LD A,(IX+0)
AND 0FH
RLCA
RLCA
RLCA
RLCA
LD H,A
LD A,(IX+1)
AND 0FH
OR H
LD H,A
LD A,(IX+2)
AND 0FH
RLCA
RLCA
RLCA
RLCA
LD L,A
LD A,(IX+3)
AND 0FH
OR L
LD L,A
RET
;
;# Target : Convert compacted binary to 4 binary nibbles
;# Input : HL = compacted binary
;# IX = nibbles pointer
;# Output : none
;# Used : A
;
LIB$HSTR:
LD A,H
RRCA
RRCA
RRCA
RRCA
AND 0FH
LD (IX+0),A
LD A,H
AND 0FH
LD (IX+1),A
LD A,L
RRCA
RRCA
RRCA
RRCA
AND 0FH
LD (IX+2),A
LD A,L
AND 0FH
LD (IX+3),A
RET
;
;# Target : Convert 5 nibbles to binary bcd
;# Input : IX = nibbles pointer
;# Output : HL = compacted binary
;# Used : all
;
LIB$DVAL:
LD DE,10000D
LD C,(IX+0)
CALL LIB$IMUL
PUSH HL
LD DE,1000D
LD C,(IX+1)
CALL LIB$IMUL
EX DE,HL
POP HL
ADD HL,DE
PUSH HL
LD DE,100D
LD C,(IX+2)
CALL LIB$IMUL
EX DE,HL
POP HL
ADD HL,DE
PUSH HL
LD DE,10D
LD C,(IX+3)
CALL LIB$IMUL
EX DE,HL
POP HL
ADD HL,DE
LD E,(IX+4)
LD D,0
ADD HL,DE
RET
;
;# Target : Convert a binary to 5 bcd nibbles
;# Input : HL = compacted binary
;# IX = nibbles binary pointer
;# Output : none
;# Used : all
;
LIB$DSTR:
PUSH HL
LD DE,10000D
CALL LIB$IDIV
LD (IX+0),C
LD DE,10000D
CALL LIB$IMUL
EX DE,HL
POP HL
OR A
SBC HL,DE
PUSH HL
LD DE,1000D
CALL LIB$IDIV
LD (IX+1),C
LD DE,1000D
CALL LIB$IMUL
EX DE,HL
POP HL
OR A
SBC HL,DE
PUSH HL
LD DE,100D
CALL LIB$IDIV
LD (IX+2),C
LD DE,100D
CALL LIB$IMUL
EX DE,HL
POP HL
OR A
SBC HL,DE
PUSH HL
LD DE,10D
CALL LIB$IDIV
LD (IX+3),C
LD DE,10D
CALL LIB$IMUL
EX DE,HL
POP HL
OR A
SBC HL,DE
LD (IX+4),L
RET
;
;# Target : Convert bcd to binary
;# Input : D = decimal
;# E = units
;# Output : A = binary
;# Used : none
;
LIB$BCDBIN:
LD A,D
ADD A,A
LD D,A
ADD A,A
ADD A,A
ADD A,D
ADD A,E
RET
;
;# Target : Convert binary to bcd
;# Input : A = binary
;# Output : D = decimal
;# E = unit
;# Used : none
;
LIB$BINBCD:
LD DE,0
BLOOP: SUB 10D
JR C,BCONT
INC D
JR BLOOP
BCONT: ADD A,10D
LD E,A
RET
;
;# Target : Divide a byte in two nibble
;# Input : A = binary
;# Output : D = high nibble of A
;# E = low nibble of A
;# Used : none
;
LIB$NIBBLE:
LD D,A
AND 0FH
LD E,A
LD A,D
AND 0F0H
RRCA
RRCA
RRCA
RRCA
LD D,A
RET
;
;# Target : Unsigned multiplication
;# Input : DE = multiplicand
;# C = multiplier
;# Output : HL = result
;# CY = if 1 overflow
;# Used : B
;
LIB$IMUL:
LD HL,0
LD B,8
MLOOP: RR C
JR NC,MCONT
ADD HL,DE
RET C
MCONT: SLA E
RL D
DJNZ MLOOP
OR A ;CY=0
RET
;
;# Target : Unsigned division
;# Input : HL = dividend
;# DE = divisor
;# Output : HL = result
;# CY = if 1 division by 0
;# Used : BC AF
;
LIB$IDIV:
LD A,E
OR D
SCF
RET Z
LD A,0
LD C,L
LD B,H
ADJ: OR A
SBC HL,DE
JR C,ENDADJ
SLA E
RL D
LD L,C
LD H,B
INC A
JR ADJ
ENDADJ: LD L,C
LD H,B
LD BC,0
OR A
RET Z
SRL D
RR E
DLOOP: OR A
SBC HL,DE
JR NC,DVSBL
ADD HL,DE
SCF
DVSBL: CCF
RL C
RL B
SRL D
RR E
DEC A
JR NZ,DLOOP
OR A
RET
;
;# Target : Convert a binary to an ascii string
;# Input : HL = binary
;# IX = destination buffer pointer
;# Output : none
;# Used : DE BC AF
;
LIB$DPRINT:
CALL LIB$DSTR
LD A,(IX+0)
CALL LIB$BCD$Z?
LD (IX+0),A
LD B,(IX+1)
CALL CONV
LD (IX+1),A
LD B,(IX+2)
CALL CONV
LD (IX+2),A
LD B,(IX+3)
CALL CONV
LD (IX+3),A
LD A,(IX+4)
CALL LIB$BCD$
LD (IX+4),A
RET
;
CONV: CP ' '
JR Z,CN00
LD A,B
CALL LIB$BCD$
RET
CN00: LD A,B
CALL LIB$BCD$Z?
RET
;
;# Target : Convert binary to exadecimal ascii string
;# Input : HL = binary
;# IX = destination buffer pointer
;# Output : none
;# Used : DE BC AF
;
LIB$HPRINT:
CALL LIB$HSTR
LD A,(IX+0)
CALL LIB$BIN$
LD (IX+0),A
LD A,(IX+1)
CALL LIB$BIN$
LD (IX+1),A
LD A,(IX+2)
CALL LIB$BIN$
LD (IX+2),A
LD A,(IX+3)
CALL LIB$BIN$
LD (IX+3),A
RET
;
;# Target : Convert ascii to binary
;# Input : A = ascii exadecimal
;# Output : A = binary nibble
;# Used : none
;
LIB$ASC_BIN:
CP 40H
JR C,CONT
SUB 7
CONT: AND 0FH
RET
;
;# Target : Convert an ascii exadecimal string to binary
;# Input : IX = source buffer pointer
;# Output : HL = binary
;# Used : DE BC AF
;
LIB$STR_HVAL:
LD A,(IX+0)
CALL LIB$ASC_BIN
LD (IX+0),A
LD A,(IX+1)
CALL LIB$ASC_BIN
LD (IX+1),A
LD A,(IX+2)
CALL LIB$ASC_BIN
LD (IX+2),A
LD A,(IX+3)
CALL LIB$ASC_BIN
LD (IX+3),A
CALL LIB$HVAL
RET
;
;# Target : Count how many bits are 1
;# Input : A = binary
;# Output : A = bit count
;# Used : HL
;
LIB$BIT_SUM:
LD HL,SUMTAV
ADD A,L
LD L,A
LD A,0
ADC A,H
LD H,A
LD A,(HL)
RET
;
;# Target : Test a bit
;# Input : A = binary
;# E = bit index
;# Output : Z
;# Used : HL DE
;
LIB$BIT_TEST:
LD D,0
LD HL,BITTAV
ADD HL,DE
AND (HL)
RET
;
;# Target : Convert binary to compacted bcd (3 nibble)
;# Input : A = binary
;# Output : HL = result
;# Used : DE BC
;
LIB$BINBCD3:
CALL LIB$NIBBLE
LD A,E
CP 10
JR C,C70
ADD A,6
LD E,A
C70: LD C,D
LD B,0
SLA C
LD HL,TBCD
ADD HL,BC
LD C,(HL)
INC HL
LD B,(HL)
LD A,E
ADD A,C
DAA
LD L,A
LD A,0
ADC A,B
DAA
LD H,A
RET
;
;# Target : Sum a BCD counter with accumulator
;# Input : IX = counter pointer
;# HL = accumulator BCD
;# Output : HL = HL+(IX)
;# IX = IX+2
;# Used : A
;
LIB$ADDBCD:
LD A,L ;somma i nibble meno significativi
ADD A,(IX+0)
DAA
LD L,A
LD A,H
ADC A,(IX+1) ;somma con riporto i nibble piu' significativi
DAA
LD H,A
INC IX ;IX=IX+2
INC IX
RET
;
;# Data
;
SUMTAV: DB 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4
DB 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5
DB 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5
DB 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6
DB 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5
DB 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6
DB 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6
DB 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7
DB 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5
DB 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6
DB 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6
DB 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7
DB 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6
DB 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7
DB 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7
DB 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
;
BITTAV: DB 00000001B
DB 00000010B
DB 00000100B
DB 00001000B
DB 00010000B
DB 00100000B
DB 01000000B
DB 10000000B
;
TBCD: DW 0H,16H,32H,48H,64H,80H,96H,112H
DW 128H,144H,160H,176H,192H,208H,224H,240H
;
END
This module implements a driver for packet oriented Rx/Tx
;
;# Module : SIOA driver - Sync protocol -
;# Date : August 28, 1992
;# Author : Pompeo Riccardo
;
PUBLIC SIOA$RAM,SIOA$CONNECT,SIOA$QIOR,SIOA$QIOW,SIOA$INT
PUBLIC SIOA$IOCR,SIOA$IOCW,SIOA$FLUSHR,SIOA$FLUSHW
EXTRN LIB$INSQT,LIB$REMQH,LIB$INSQTI,LIB$REMQHI,LIB$INIT_HEADER
EXTRN EQM$REQUEST,EQM$RELEASE,EQM$REQUESTI,EQM$RELEASEI
;
INCLUDE STARLET.INC
;
SIOD: EQU SIOA$SIOD
ENDTX: EQU 0
;
CSEG
;
;# Target : Driver inizialization
;# Input : A = interrupt vector
;# Output : none
;# Used : all
;
SIOA$CONNECT:
RES 0,A ;Init. PIO channel B
OUT (PIOCB),A ;
LD A,11001111B ;select control mode
OUT (PIOCB),A ;
LD A,11111111B ;i/o bit mask
OUT (PIOCB),A ;
LD A,10010111B ;int.en.,mask follow,active low,or func.
OUT (PIOCB),A ;
LD A,11111110B ;load mask
OUT (PIOCB),A ;
LD HL,0 ;Init. pointers
LD (TXPTR),HL ;
LD (RXPTR),HL ;
LD HL,0 ;TX queue flags
LD IX,SIOA$TX_QUEUE
CALL LIB$INIT_HEADER
LD HL,0 ;RX queue flags
LD IX,SIOA$RX_QUEUE
CALL LIB$INIT_HEADER
RETI
;
;# Target : Enqueue a packet for transmition
;# Input : IY = packet pointer
;# Output : none
;# Used : all
;
SIOA$QIOW:
LD A,IRP$SIO ;Pacchetto di tipo elaborabile ?
CP (IY+7) ;
JR Z,C20 ;
CALL EQM$RELEASE ;Riaccoda il pacchetto nei vuoti
RET
C20:LD IX,SIOA$TX_QUEUE
CALL LIB$INSQT ;Accoda il pacchetto corrente
RET
;
;# Target : Dequeue a packet from Rx buffer
;# Input : none
;# Output : IY = packet pointer
;# CY = if 1 the queue is empty
;# Used : all
;
SIOA$QIOR:
LD IX,SIOA$RX_QUEUE
CALL LIB$REMQH
RET
;
;# Target : Read flags code
;# Input : none
;# Output : +--7--+--6--+--5--+--4--+--3--+--2--+--1--+--0--+
; H = | X | X | X | X | X | X | X | X |
; +-----+-----+-----+-----+-----+-----+-----+-----+
; L = | X | X | X | X | X | X | X | X |
; +-----+-----+-----+-----+-----+-----+-----+-----+
;# Used : all
;
SIOA$IOCR:
LD IX,SIOA$TX_QUEUE
LD H,(IX+4)
LD IX,SIOA$RX_QUEUE
LD L,(IX+4)
RET
;
;# Target : Write flags code
;# Input : +--7--+--6--+--5--+--4--+--3--+--2--+--1--+--0--+
; H = | X | X | X | X | X | X | X | X |
; +-----+-----+-----+-----+-----+-----+-----+-----+
; L = | X | X | X | X | X | X | X | X |
; +-----+-----+-----+-----+-----+-----+-----+-----+
;# Output : none
;# Used : all
;
SIOA$IOCW:
LD IX,SIOA$TX_QUEUE
LD (IX+5),H
LD IX,SIOA$RX_QUEUE
LD (IX+5),L
RET
;
;# Target : Free Rx queue
;# Input : none
;# Output : none
;# Used : all
;
SIOA$FLUSHR:
LD IX,SIOA$RX_QUEUE
CALL LIB$REMQH
RET C
CALL EQM$RELEASE
JR SIOA$FLUSHR
;
;# Target : Free Tx queue
;# Input : none
;# Output : none
;# Used : all
;
SIOA$FLUSHW:
LD IX,SIOA$TX_QUEUE
CALL LIB$REMQH
RET C
CALL EQM$RELEASE
JR SIOA$FLUSHW
;
;# Interrupt entry point
;
SIOA$INT:
EX AF,AF'
EXX
PUSH IX
PUSH IY
CALL SIOA$TX
CALL SIOA$RX
POP IY
POP IX
EXX
EX AF,AF'
EI
RETI
;
PAGE
;
;# Rx
;
SIOA$RX:
LD HL,(RXPTR) ;Gia' in ricezione ?
LD A,H
OR L
JR NZ,SIOA$RX_SELECT
LD A,75 ;Richiede un pacchetto
CALL EQM$REQUESTI
JR C,SIOA$RX_CLEAR ;Pacchetto non disponibile ?
SIOA$RX_NEWPCK:
LD (IY+7),IRP$SIO ;Tipo struttura
LD (RXPCK),IY ;Salva puntatore al pacchetto
CALL SIOA$RX_INIT
SIOA$RX_SELECT:
LD IX,SIOA$RX_QUEUE
LD (IX+4),0 ;
LD IY,(RXPCK) ;
LD HL,(RXSTEP) ;Avvia il passo di ricezione corrente
JP (HL) ;
SIOA$RX_CLEAR: ;Nell'impossibilita' di allocare un
IN A,(SIOD) ;pacchetto il carattere viene
RET ;ricevuto ma non gestito
SIOA$RX_INIT:
PUSH IY ;Inizializza puntatori per ricezione
POP HL
LD DE,IRP$DISPL
ADD HL,DE
LD (RXPTR),HL
LD HL,SIOA$RX00
LD (RXSTEP),HL
LD A,0
LD (RXNUM),A
LD (RXBCC),A
RET
;
;Riceve header of trasmission
;
SIOA$RX00:
IN A,(SIOD)
CP IRP$SOH
RET NZ
LD HL,SIOA$RX01
LD (RXSTEP),HL
RET
;
;Rx Address
;
SIOA$RX01:
IN A,(SIOD)
LD HL,(RXPTR)
LD (HL),A
INC HL
LD (RXPTR),HL
LD (RXBCC),A
LD HL,RXNUM
INC (HL)
LD HL,SIOA$RX02
LD (RXSTEP),HL
RET
;
;Rx until ETX or overflow
;
SIOA$RX02:
IN A,(SIOD)
LD HL,(RXPTR)
LD (HL),A
INC HL
LD (RXPTR),HL
CP IRP$ETX
JR NZ,C01
LD HL,SIOA$RX03
LD (RXSTEP),HL
C01: LD HL,RXBCC
ADD A,(HL)
LD (HL),A
LD A,66
LD HL,RXNUM
INC (HL)
CP (HL)
RET NC
CALL SIOA$RX_INIT
RET
;
;Rx BCC
;
SIOA$RX03:
IN A,(SIOD)
LD HL,RXBCC
CP (HL)
JR NZ,C03
LD HL,0
LD (RXPTR),HL
CALL LIB$INSQTI
RET
C03:CALL SIOA$RX_INIT
RET
;
PAGE
;
;# Tx
;
SIOA$TX:
LD HL,(TXPTR) ;Pacchetto gia' disponibile ?
LD A,H
OR L
JR NZ,SIOA$TX_SELECT
LD IX,SIOA$TX_QUEUE
CALL LIB$REMQHI ;Scoda un pacchetto
JR NC,SIOA$TX_NEWPCK ;Pacchetto presente ?
LD A,16H
OUT (SIOD),A ;Trasmette SYNC
RET
SIOA$TX_NEWPCK: ;
LD (TXPCK),IY ;Inizializza puntatori
CALL SIOA$TX_INIT
SIOA$TX_SELECT:
LD IX,SIOA$TX_QUEUE
LD IY,(TXPCK)
LD HL,(TXSTEP) ;Avvia il passo di trasmissione corrente
JP (HL)
SIOA$TX_INIT:
PUSH IY ;Inizializza puntatori per trasmissione
POP HL
LD DE,IRP$DISPL
ADD HL,DE
LD (TXPTR),HL
LD HL,SIOA$TX00
LD (TXSTEP),HL
LD A,0
LD (TXBCC),A
LD (TXNUM),A
RET
;
;Tx header of trasmission
;
SIOA$TX00:
LD A,IRP$SOH
OUT (SIOD),A
LD HL,SIOA$TX01
LD (TXSTEP),HL
RET
;
;Tx Address
;
SIOA$TX01:
LD HL,(TXPTR)
LD A,(HL)
OUT (SIOD),A
INC HL
LD (TXPTR),HL
LD (TXBCC),A
LD HL,TXNUM
INC (HL)
LD HL,SIOA$TX02
LD (TXSTEP),HL
RET
;
;Tx until ETX
;
SIOA$TX02:
LD HL,(TXPTR)
LD A,(HL)
OUT (SIOD),A
INC HL
LD (TXPTR),HL
CP IRP$ETX
JR NZ,C15
LD HL,SIOA$TX03
LD (TXSTEP),HL
C15:LD HL,TXBCC
ADD A,(HL)
LD (HL),A
LD A,66
LD HL,TXNUM
INC (HL)
CP (HL)
RET NC
LD HL,SIOA$TX04
LD (TXSTEP),HL
RET
;
;Tx BCC
;
SIOA$TX03:
LD A,(TXBCC)
OUT (SIOD),A
LD HL,0
LD (TXPTR),HL
CALL EQM$RELEASEI ;RIACCODA IL PACCHETTO NEI VUOTI
RET
;
;Tx ETX
;
SIOA$TX04:
LD A,IRP$ETX
OUT (SIOD),A
LD HL,TXBCC
ADD A,(HL)
LD (HL),A
LD HL,SIOA$TX03
LD (TXSTEP),HL
RET
;
DSEG
;
SIOA$RAM:
;
SIOA$TX_QUEUE:
DS 6
SIOA$RX_QUEUE:
DS 6
;
TXPTR: DS 2
TXPCK: DS 2
TXBCC: DS 1
TXSTEP: DS 2
TXNUM: DS 1
;
RXPTR: DS 2
RXPCK: DS 2
RXBCC: DS 1
RXSTEP: DS 2
RXNUM: DS 1
;
END
This module controls CTC
;
;# Module : CTC driver
;# Date : August 28, 1992
;# Author : Pompeo Riccardo
;
PUBLIC CTC$CONNECT,CTC$INTA,CTC$INTB
EXTRN SIOA$INT_TX,SIOA$INT_RX
EXTRN SIOB$INT_TX,SIOB$INT_RX
;
INCLUDE STARLET.INC
;
BRATE1: EQU BR1200
BRATE2: EQU BR9600
TIMER1: EQU 19 ;1 ms
TIMER2: EQU 192 ;10 ms
;
CSEG
;
;# CTC initilization (A = interrupt vector)
;
CTC$CONNECT:
RES 0,A ;set interrupt vector
OUT (CTC0),A ;
LD A,00000101B ;int disab.,timer mode,*16,time cost.
OUT (CTC0),A ;
LD A,BRATE1 ;
OUT (CTC0),A ;
LD A,00100101B ;int disab.,timer mode,*256,time cost.
OUT (CTC2),A ;
LD A,TIMER1 ;
OUT (CTC2),A ;
LD A,00000101B ;int disab.,timer mode,*16,time cost.
OUT (CTC1),A ;
LD A,BRATE2 ;
OUT (CTC1),A ;
LD A,00100101B ;int disab.,timer mode,*256,time cost.
OUT (CTC3),A ;
LD A,TIMER2 ;N.B.
OUT (CTC3),A ;interrupt -> bit 7 0 = dis , 1 = enab
RETI ;prescaler -> bit 5 0 = *16 , 1 = *256
;
;# Channel A interrupt entry point
;
CTC$INTA:
EX AF,AF'
EXX
;
EXX
EX AF,AF'
EI
RETI
;
;# Channel B interrupt entry point
;
CTC$INTB:
EX AF,AF'
EXX
;
EXX
EX AF,AF'
EI
RETI
;
END
This module controls a scratch area filled by empty packets
;
;# Module : Queue Manager
;# Date : December 5, 1991
;# Author : Pompeo Riccardo
;
PUBLIC EQM$RAM,EQM$INIT,EQM$STATUS
PUBLIC EQM$REQUEST,EQM$RELEASE,EQM$REQUESTI,EQM$RELEASEI
EXTRN LIB$INIT_QUEUE,LIB$INIT_HEADER
EXTRN LIB$REMQH,LIB$INSQH,LIB$REMQHI,LIB$INSQHI
;
INCLUDE STARLET.INC
;
OVRFL: EQU 0
;
CSEG
;
;# Target : Initialization
;# Input : none
;# Output : none
;# Used : all
;
EQM$INIT:
LD HL,0
LD IX,EQM$SRP_QUEUE
CALL LIB$INIT_HEADER
LD IX,EQM$MRP_QUEUE
CALL LIB$INIT_HEADER
LD IX,EQM$LRP_QUEUE
CALL LIB$INIT_HEADER
;
LD A,0
LD B,NUM_SRP
LD C,SIZ_SRP
LD HL,0
LD IX,EQM$SRP_QUEUE
LD IY,EQM$SRP
CALL LIB$INIT_QUEUE
;
LD A,0
LD B,NUM_MRP
LD C,SIZ_MRP
LD HL,0
LD IX,EQM$MRP_QUEUE
LD IY,EQM$MRP
CALL LIB$INIT_QUEUE
;
LD A,0
LD B,NUM_LRP
LD C,SIZ_LRP
LD HL,0
LD IX,EQM$LRP_QUEUE
LD IY,EQM$LRP
CALL LIB$INIT_QUEUE
;
RET
;
;# Target : Get a packet
;# Input : A = packet size
;# Output : IY = packet pointer
;# CY = if 1 packet not available
;# Used : all
;
EQM$REQUEST:
CP SIZ_SRP
JR NC,C00
LD IX,EQM$SRP_QUEUE
CALL LIB$REMQH
RET NC
LD IX,EQM$SRP_QUEUE
SET OVRFL,(IX+4)
RET
C00:
CP SIZ_MRP
JR NC,C01
LD IX,EQM$MRP_QUEUE
CALL LIB$REMQH
RET NC
LD IX,EQM$MRP_QUEUE
SET OVRFL,(IX+4)
RET
C01:
CP SIZ_LRP
JR NC,C02
LD IX,EQM$LRP_QUEUE
CALL LIB$REMQH
RET NC
LD IX,EQM$LRP_QUEUE
SET OVRFL,(IX+4)
RET
C02:
SCF
RET
;
;# Entry point for interrupt
;
EQM$REQUESTI:
CP SIZ_SRP
JR NC,C20
LD IX,EQM$SRP_QUEUE
CALL LIB$REMQHI
RET NC
LD IX,EQM$SRP_QUEUE
SET OVRFL,(IX+4)
RET
C20:
CP SIZ_MRP
JR NC,C21
LD IX,EQM$MRP_QUEUE
CALL LIB$REMQHI
RET NC
LD IX,EQM$MRP_QUEUE
SET OVRFL,(IX+4)
RET
C21:
CP SIZ_LRP
JR NC,C22
LD IX,EQM$LRP_QUEUE
CALL LIB$REMQHI
RET NC
LD IX,EQM$LRP_QUEUE
SET OVRFL,(IX+4)
RET
C22:
SCF
RET
;
;# Target : Release a packet
;# Input : none
;# Output : IY = packet pointer
;# Used : all
;
EQM$RELEASE:
LD A,(IY+6)
CP SIZ_SRP
JR NZ,C10
LD IX,EQM$SRP_QUEUE
RES OVRFL,(IX+4)
CALL LIB$INSQH
RET
C10:
CP SIZ_MRP
JR NZ,C11
LD IX,EQM$MRP_QUEUE
RES OVRFL,(IX+4)
CALL LIB$INSQH
RET
C11:
LD IX,EQM$LRP_QUEUE
RES OVRFL,(IX+4)
CALL LIB$INSQH
RET
;
;# Entry point for interrupt
;
EQM$RELEASEI:
LD A,(IY+6)
CP SIZ_SRP
JR NZ,C30
LD IX,EQM$SRP_QUEUE
RES OVRFL,(IX+4)
CALL LIB$INSQHI
RET
C30:
CP SIZ_MRP
JR NZ,C31
LD IX,EQM$MRP_QUEUE
RES OVRFL,(IX+4)
CALL LIB$INSQHI
RET
C31:
LD IX,EQM$LRP_QUEUE
RES OVRFL,(IX+4)
CALL LIB$INSQHI
RET
;
;# Target : Read status
;# Input : none
;# Output : +--7--+--6--+--5--+--4--+--3--+--2--+--1--+--0--+
;# A = | X | X | X | X | X |LRPOV|MRPOV|SRPOV|
;# +-----+-----+-----+-----+-----+-----+-----+-----+
;# Used : B
;
EQM$STATUS:
LD A,(EQM$SRP_QUEUE+4)
AND 00000001B
LD B,A
LD A,(EQM$MRP_QUEUE+4)
AND 00000001B
RLCA
OR B
LD B,A
LD A,(EQM$LRP_QUEUE+4)
AND 00000001B
RLCA
RLCA
OR B
RET
;
DSEG
;
EQM$RAM:
;
EQM$SRP_QUEUE: DS 6
EQM$MRP_QUEUE: DS 6
EQM$LRP_QUEUE: DS 6
;
EQM$SRP: DS NUM_SRP*SIZ_SRP
EQM$MRP: DS NUM_MRP*SIZ_MRP
EQM$LRP: DS NUM_LRP*SIZ_LRP
;
END
This module controls the exchange of informations between Z80 and the host system
;
;# Module : Mailbox controller
;# Date : August 28, 1992
;# Author : Pompeo Riccardo
;
PUBLIC MBX$INIT,MBX$CONTROLLER
EXTRN EXE$PROCESS
EXTRN SIOA$QIOW,SIOA$QIOR,SIOA$IOCR,SIOA$IOCW,SIOA$FLUSHW,SIOA$FLUSHR
EXTRN EQM$REQUEST,EQM$RELEASE
;
INCLUDE STARLET.INC
INCLUDE HSKCODE.INC
;
STRSZ EQU 67 ;String size
PCKSZ EQU STRSZ+IRP$DISPL ;Packet size
PIOD EQU PIODA ;PIO data address
PIOC EQU PIOCA ;PIO control address
FLGADD EQU DPRAM1 ;Flag address
LENADD EQU DPRAM1+1 ;Length address
STRADD EQU DPRAM1+2 ;String address
;
CSEG
;
;# Initialize mail box
;
MBX$INIT:
;
;Programmazione PIO A
;
LD A,11001111B ;select control mode
OUT (PIOC),A ;
LD A,11110000B ;i/o bit mask
OUT (PIOC),A ;
LD A,00000111B ;interrupt disabled
OUT (PIOC),A ;
LD A,MP$NULL ;
OUT (PIOD),A ;
;
;# Inizializzazione dual port ram
;
LD HL,DPRAM1
LD DE,DPRAM1+1
LD BC,3FCH
LD (HL),0
LDIR
;
;# Attivazione processi
;
LD DE,MBX$CONTROLLER
CALL EXE$PROCESS
RET
;
;# Mailbox controller
;
MBX$CONTROLLER:
IN A,(PIOD)
AND HS$RWRQ
JR Z,NORQ
IN A,(PIOD)
AND HS$MASK
CP HS$READ
JP Z,MBX$RDSIOA
CP HS$WRIT
JP Z,MBX$WRSIOA
CP HS$FLSH
JP Z,MBX$FLUSH
NORQ: LD DE,MBX$CONTROLLER
CALL EXE$PROCESS
RET
;
;# Flush Rx/Tx buffers
;
MBX$FLUSH:
CALL SIOA$FLUSHR
LD A,MP$RWOK
CALL COMPLETION
LD DE,MBX$CONTROLLER
CALL EXE$PROCESS
RET
;
;# Tx to RS422
;
MBX$WRSIOA:
LD A,(LENADD) ;Controllo lunghezza stringa
CP STRSZ ;
JR NC,NOPCK ;
LD A,PCKSZ ;Richiede un pacchetto
CALL EQM$REQUEST
JR C,NOPCK ;Pacchetto non disponibile ?
LD (IY+7),IRP$SIO ;Tipo struttura
LD A,(FLGADD) ;Traferisce indirizzo
LD (IY+8),A ;
LD (IY+9),IRP$STX
PUSH IY ;Si spiazza sul pacchetto
POP HL
LD DE,IRP$DISPL+2
ADD HL,DE ;
EX DE,HL ;
LD HL,STRADD ;Trasferisce la stringa
LD A,(LENADD) ;
LD C,A
LD B,0
LDIR ;
LD A,IRP$ETX ;
LD (DE),A ;
CALL SIOA$QIOW ;Trasmissione
LD A,MP$RWOK ;
CALL COMPLETION
LD DE,MBX$CONTROLLER
CALL EXE$PROCESS
RET
NOPCK:
LD A,MP$RWOK ;Buffer full
OR MP$FULL
CALL COMPLETION
LD DE,MBX$CONTROLLER
CALL EXE$PROCESS
RET
;
;# Rx from RS422
;
MBX$RDSIOA:
CALL SIOA$QIOR ;Pacchetto presente
JR C,NODATA ;
LD A,(IY+8) ;Trasferisce indirizzo
LD (FLGADD),A ;
PUSH IY ;Si spiazza sul pacchetto
POP HL
LD DE,IRP$DISPL+2
ADD HL,DE ;HL - source buffer address
LD DE,STRADD ;DE - destin. " "
LD B,0 ;B - length
C20: ;
LD A,(HL) ;Trasferisce la stringa
CP IRP$ETX ;Fine stringa ?
JR Z,C21
LD (DE),A
INC HL
INC DE
INC B
JR C20
C21: ;
LD A,B ;Trasferisce lunghezza
LD (LENADD),A
CALL EQM$RELEASE ;Riaccoda il pacchetto nei vuoti
LD A,MP$RWOK
CALL COMPLETION
LD DE,MBX$CONTROLLER
CALL EXE$PROCESS
RET
NODATA:
LD A,MP$RWOK ;Buffer empty
OR MP$EMPT
CALL COMPLETION
LD DE,MBX$CONTROLLER
CALL EXE$PROCESS
RET
;
;# Target : Signaling I/O completion
;# Input : A = code (MP$xxxx)
;# Output : none
;# Used : A
;
COMPLETION:
OUT (PIOD),A
C50: IN A,(PIOD)
AND HS$RWRQ
JR NZ,C50
LD A,MP$NULL
OUT (PIOD),A
RET
;
END