	LIST E,CASE
     
      	CSEG

;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;
;	Questo file contiene le routine di I/O hardware dipendenti
;
;	per il compilatore Microtec C - linkare con l'oggetto prima della
;
;	libreria o sostituire modulo originale di libreria
;
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------

;----------------------------------------------------------------------------
;	(C) ing. G. Becattini - Firenze (1989-90)
;----------------------------------------------------------------------------

;	Nuova versione prevista per uso futuro piu' intensivo del C
;	NON ha nulla a che vedere con il CSYSZ80 usato per il LOGIP
;	che resta un programma a se' stante

;	E' una base minima dalla quale costruire gli CSYSZ80 futuri

;	Usa semplici routines (senza interrupt) come minimo driver
;	per la console

;----------------------------------------------------------------------------
;	Definizioni varie
;----------------------------------------------------------------------------
FALSE   EQU    	0
TRUE 	EQU     1

ASCIICR	EQU	13		;ritorno carrello
ASCIILF	EQU	10		;line feed
 
CPM_EOF	EQU	01AH		;Control-Z
C_EOF	EQU	-1		;must agree with C's stdio.h
 
stdin	EQU	0		;must equal values in CTYPE.H	7/26/85 mjf
stdout	EQU	1
stderr	EQU	2

;----------------------------------------------------------------------------
;	Definizioni indirizzi fisici porte
;----------------------------------------------------------------------------

SIOAD	EQU	044H
SIOAC	EQU	SIOAD+2

;----------------------------------------------------------------------------
;	PUBLICs
;----------------------------------------------------------------------------

; <-NB!	PUBLIC	ENT(Z)n_	;Program Prologue
        PUBLIC	ENTZ2_
        PUBLIC	XIT_		;Program Epilogue
        PUBLIC	exit,exit_	;synonyms for XIT_
        PUBLIC	ActPt_		;Activation rec pointer
        PUBLIC	ActLn_		;Active Line Number
        PUBLIC	readb		;Binary read
 	PUBLIC	writeb		;Binary write
        PUBLIC	getc
        PUBLIC	putc
        PUBLIC	stdin
        PUBLIC	stdout
        PUBLIC	stderr		;mjf 7/26/85
        PUBLIC	ungetc
	PUBLIC	HEAPORG_,HEAPEND_,HEAPFRE_,HEAPLIM_
	PUBLIC	membase_,avail_,badlist_,lastp_

;----------------------------------------------------------------------------
;	EXTERNALs
;----------------------------------------------------------------------------
        
        EXTRN	STKSZ		;Undocumented symbol, defined by
    				;the linker to equal the stack length.
    				;Does NOT control stack length; STKLN does.
        EXTRN	MAIN_		;entry point to main program

;----------------------------------------------------------------------------
;	Programma principale
;----------------------------------------------------------------------------

;	le istruzioni che seguono sono tutto il programma
;	chiamando main() viene infatti eseguito il programma C

ENTZ2_:
CSTART:	DI
	LD    	SP,STACK     	;point SP to new stack
    	CALL	INISIO
        CALL    INIT_        	;initialize environment
        CALL    MAIN_		;chiama la funzione main()
        LD      HL,0

exit:
exit_:
XIT_:	LD	L,'$'		;emette un '$' per indicare fine lavoro
	CALL	CPUT_ 		;XIT_ e' chiamabile anche dall'esterno
SELF:	JR	SELF		;(anche con nomi exit ed exit_)


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;	Adesso seguono le routines usate dal programma principale
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------

;----------------------------------------------------------------------------
;	Initialize the run time environment starting with the Heap.
;----------------------------------------------------------------------------

;	chiamata da CSTART

; 	Allocate the entire stack space as the heap and set it to look
; 	like a single large block on the free space list.

INIT_:
	LD	HL,0
	LD	(ActLn_),HL	;clear current line number field
	LD	(ActPt_),HL     ;and activation record pointer
 
	LD	HL,STACK
	LD	(HEAPEND_),HL  	;set heap end ptr, reset at entry
	LD	DE,STKSZ       	;stack length -- see extrn decl above

	XOR	A
	SBC	HL,DE

	LD  	(HEAPORG_),HL
	LD	(HEAPFRE_),HL
	LD	(HEAPLIM_),HL  	;indicate heap is empty

	LD	HL,membase_    	;C:
	LD	(avail_),HL    	;avail_ = &membase
	LD	(membase_),HL  	;membase.next = &membase
	INC	HL             	;membase.size = 0
	INC	HL
	LD	(HL),A
	INC	HL
	LD	(HL),A
	INC	HL             	;badlist_ = 0
	LD	(HL),A
	INC	HL             	;lastp_ = NULLPTR
	LD	(HL),A
	INC	HL
	LD	(HL),A
	DEC	A
	LD	(UGFL),A	;initialize flag for ungetc
	RET                     ;end of the INIT routine

         
;----------------------------------------------------------------------------
;	Inizializza la porta seriale programmando la SIO
;----------------------------------------------------------------------------
	
INISIO:	LD	HL,TABSIOA
	LD	C,SIOAC
	LD	B,11
	OTIR
	RET

TABSIOA:
	DB	18H,10H		;CHANNEL RESET
				;RESET EXT/STATUS INT
	DB	4,44H		;CLOCK X 16 - NO SYNC - 1 STOP BIT
				;NO PARITY
	DB	3,0C1H		;RX ENABLE - 8 BIT CHAR
				;
	DB	5,6AH		;8 BIT CHAR - TX ENABLE - RTS
				;
	DB	10H		;RESET EXT/STATUS INT
	DB	1,0		;NO INTERRUPTS

		
	
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------

;	In questa sezione sono riportate varie routines di I/O
;	hardware dipendenti usate dal C

;	Si tratta di:

;	1) CGET_  	- attende un carattere dalla console
; 	2) CPUTC_ 	- emette  un carattere verso la console
;	3) putc ()	- per adesso come CPUTC_
;	4) getc ()
;	5) ungetc ()
;	6) readb ()
;	7) writeb ()

;----------------------------------------------------------------------------
;----------------------------------------------------------------------------

;----------------------------------------------------------------------------
;	1) CGET_  - attende un carattere dalla console
;----------------------------------------------------------------------------

;	lavora in polling

CGET_:	LD	A,5
	OUT	(SIOAC),A
	LD	A,6AH		;RTS
	OUT	(SIOAC),A
RX:	IN	A,(SIOAC)
	BIT	0,A
	JR	Z,RX
	LD	A,5
	OUT	(SIOAC),A
	LD	A,68H		;VIA RTS
	OUT	(SIOAC),A
	IN	A,(SIOAD)
	CALL	SIOTX2		;eco
        AND     07FH         	;rimuovi ottavo bit
        CP     	ASCIICR		;converti <CR> in <LF>
        JR	NZ,CGET_20
        LD     	A,ASCIILF
CGET_20:LD     	H,0
        LD      L,A		;il carattere ritorna in l
        
        CP      CPM_EOF		;converti i CTRL/Z in ffh
        JR	NZ,CGET_30
        LD      HL,C_EOF

CGET_30:POP     DE         	;ret addr
        POP     BC            	;"hole"
        PUSH    DE            	;risultato in hl e acc
        RET


;----------------------------------------------------------------------------
; 	2) CPUTC_ - emette  un carattere verso la console
;----------------------------------------------------------------------------

;	emette il carattere contenuto nel registro l

CPUT_:	PUSH  	BC
        PUSH    DE
        PUSH    HL

        LD      A,L
        CP      ASCIILF		;non emettere LF ma convertilo in CR
        JR	NZ,ROLF
        LD      L,ASCIICR

ROLF:	PUSH    HL
	CALL	SIOTX		;trasmissione fisica
        POP     HL
         
        LD      A,L		;se CR emetti anche LF
        CP      ASCIICR
        LD      L,ASCIILF
        JR	Z,ROLF
        
        POP     HL
        POP     DE
        POP     BC
        RET


;----------------------------------------------------------------------------
;	putc ()
;----------------------------------------------------------------------------

putc:   PUSH 	HL             	;putc(c,fp) is defined as
        CALL    CPUT_          	;returning c as its value,
        POP     HL             	;otherwise we could simply use
        LD      A,L            	;putc  EQU  CPUT_
        RET


;----------------------------------------------------------------------------
;	getc ()
;----------------------------------------------------------------------------
 
getc:

; 	Here, the HL register contains a file pointer
; 	However, we ignore it and do I/O with the terminal
         
    	LD 	HL,UGFL		;test ungetc flag
;	DI			;needed if using ungetc and need 
				;getc re-entrant
        LD      A,(HL)        	;load "ungotten" character
        LD      (HL),0FFh     	;erase flag
        CP      (HL)
;	EI			;needed if using ungetc and need 
				;getc re-entrant
        RET     NZ            	;return if character from ungetc
        POP     HL            	;make calling sequence compatible
        PUSH    HL
        PUSH    HL
        JP      CGET_         	;get new character

;----------------------------------------------------------------------------
;	ungetc ()
;----------------------------------------------------------------------------

ungetc: LD        A,L
        LD        (UGFL),A       ;save character in ungetc flag
        RET

;----------------------------------------------------------------------------
; 	readb: high-speed binary input
;----------------------------------------------------------------------------

; 	C definition:
;		void readb(str, len)
;		char *str;
;		unsigned int len;
;
; 	Registers:
;		HL - str
;		DE - len
; 	Read len bytes (from some device) into str

readb:
         LD        A,E
         OR        D
         RET       Z              ; quit if 0
         DEC       E
         INC       E
         JP        Z,READB2       ; D decrements when E next becomes 0
         INC       D              ; quit when D returns to 0
READB2:
         IN        A,(1)          ; input -- subject to user modification!
         LD        (HL),A
         INC       HL
         DEC       E
         JP        NZ,READB2
         DEC       D              ; decrement high byte of count
         JP        NZ,READB2
         RET
 
;----------------------------------------------------------------------------
; writeb: high-speed binary output
;----------------------------------------------------------------------------

; 	C definition:
;		void writeb(str, len)
;		char *str;
;		unsigned int len;
;
; 	Registers:
;		HL - str
;		DE - len
; 	Write len bytes from str to some device.

writeb:
         LD        A,E
         OR        D
         RET       Z              ; quit if 0
         DEC       E
         INC       E
         JP        Z,WRITEB2      ; D decrements when E next becomes 0
         INC       D              ; quit when D returns to 0
WRITEB2:
         LD        A,(HL)
         OUT       (2),A          ; output -- subject to user modification!
         INC       HL
         DEC       E
         JP        NZ,WRITEB2
         DEC       D              ; decrement high byte of count
         JP        NZ,WRITEB2
         RET
         
;----------------------------------------------------------------------------
;	SIOTX - emissione fisica di un carattere su linea seriale
;----------------------------------------------------------------------------

SIOTX:	LD	A,L
SIOTX2:	PUSH    AF
SIOT1:	IN	A,(SIOAC)
	BIT	2,A		;test se tx e' libero
	JR	Z,SIOT1
        POP     AF
	OUT	(SIOAD),A
	RET

;----------------------------------------------------------------------------
;	DATA SEGMENT
;----------------------------------------------------------------------------

 	DSEG

ActPt_:	DEFS    2	;Activation record ptr = Disp_[0]; init 0
Disp_:	DEFS    20      ;Display registers, 10 entries
ActLn_:	DEFS    2       ;Current Line Number

HEAPORG_ DEFS	2       ;DW MEMORY  begining of heap, end of stack
HEAPEND_ DEFS   2       ;DW STACK   end of heap, init value of SP
HEAPFRE_ DEFS   2       ;DW MEMORY  starting block of free list
			;(used differently for C)
HEAPLIM_ DEFS 	2       ;DW MEMORY  current limit of allocated heap

avail_   DEFS   2 	;HEADER *avail_ = &membase_
			;ptr to free block list
membase_ DEFS 	4    	;{HEADER *next; unsigned size;}
    			;= {&membase_, 0}; head of free block list
badlist_ DEFS   1    	;char badlist_ = 0;  non-zero if list is
			;corrupted
lastp_   DEFS   2    	;char *lastp_ = NULLPTR (strtok in CSTRX)
 
UGFL:	 DEFS   1	;FF: empty;  otherwise: char from ungetc
	
	
         END  	CSTART 	;(system-depENDent) support module
