; ;================================================================================================== ; ESP32 DRIVER ; ; SUPPORTS DAN WERNER'S NHYODYNE (MBC) ESP32 MODULE ; https://github.com/danwerner21/nhyodyne/tree/main/Z80ESP ;================================================================================================== ; ; TODO: ; - CLEAR CONSOLE SCREEN AT INITIALIZATION ; - INITIALIZE BAUD/MODE OF SERIAL INTERFACES AT INITIALIZATION? ; ESP_IOBASE .EQU $9C ESP_0_IO .EQU ESP_IOBASE + 0 ESP_1_IO .EQU ESP_IOBASE + 1 ESP_STAT .EQU ESP_IOBASE + 2 ; ; ESP STATUS PORT ; MSB X X S S S S S S ; | | | | | +- ESP0 READY OUTPUT ; | | | | +--- ESP0 BUSY ; | | | +----- ESP0 SPARE ; | | +------- ESP1 READY OUTPUT ; | +--------- ESP1 BUSY ; +----------- ESP1 SPARE ; ESP_0_RDY .EQU %00000001 ESP_0_BUSY .EQU %00000010 ESP_0_SPARE .EQU %00000100 ESP_1_RDY .EQU %00001000 ESP_1_BUSY .EQU %00010000 ESP_1_SPARE .EQU %00100000 ; ; COMMAND OPCODES ; ESP_CMD_NOP .EQU 0 ; NO OP/SYNC ESP_CMD_SYNC .EQU 0 ; NO OP/SYNC ESP_0_CMD_COUT .EQU 1 ; CHAR OUT ESP_0_CMD_CSTR .EQU 2 ; STRING OUT ESP_0_CMD_KIN .EQU 3 ; KEY IN ESP_0_CMD_KST .EQU 4 ; KBD BUF STATUS ESP_CMD_SBAUD .EQU 6 ; SET SERIAL BAUD RATE ESP_CMD_SMODE .EQU 7 ; SET SERIAL LINE MODE ESP_CMD_SOUT .EQU 8 ; SERIAL BYTE OUT ESP_CMD_SIN .EQU 10 ; SERIAL BYTE IN ESP_CMD_SST .EQU 11 ; SERIAL INPUT STATUS ESP_CMD_DISC .EQU $FF ; DISCOVER ; ; ESP CONFIG TABLE ENTRY OFFSETS ; ESP_CFG_DEV .EQU 0 ; DEVICE NUMBER ESP_CFG_IO .EQU 1 ; ESP I/O PORT ESP_CFG_ST .EQU 2 ; ESP STATUS PORT ESP_CFG_RDYMSK .EQU 3 ; ESP READY MASK ESP_CFG_BSYMSK .EQU 4 ; ESP BUSY MASK ; DEVECHO "ESP: IO=" DEVECHO ESP_IOBASE DEVECHO "\n" ; ;-------------------------------------------------------------------------------------------------- ; HBIOS MODULE HEADER ;-------------------------------------------------------------------------------------------------- ; ORG_ESP .EQU $ ; .DW SIZ_ESP ; MODULE SIZE .DW ESP_INITPHASE ; ADR OF INIT PHASE HANDLER ; ESP_INITPHASE: ; INIT PHASE HANDLER, A=PHASE ;CP HB_PHASE_PREINIT ; PREINIT PHASE? ;JP Z,ESP_PREINIT ; DO PREINIT CP HB_PHASE_INIT ; INIT PHASE? JP Z,ESP_INIT ; DO INIT RET ; DONE ; ; GLOBAL ESP INITIALIZATION ; ESP_INIT: ; CALL NEWLINE ; FORMATTING PRTS("ESP: IO=0x$") LD A,ESP_IOBASE CALL PRTHEXBYTE ; XOR A ; ZERO ACCUM LD (ESP_PRES),A ; CLEAR MODULE PRESENCE BITS ; ; DETECT FIRST ESP32 MODULE PRTS(" A=$") LD IY,ESPSER0_CFG CALL ESP_DETECT JR Z,ESP_INIT1 ; FOUND LD DE,ESP_STR_NOHW CALL WRITESTR JR ESP_INIT2 ; ESP_INIT1: CALL ESP_PRTVER LD A,(ESP_PRES) SET 0,A LD (ESP_PRES),A ; ESP_INIT2: ; DETECT SECOND ESP32 MODULE PRTS(" B=$") LD IY,ESPSER1_CFG CALL ESP_DETECT JR Z,ESP_INIT3 ; FOUND LD DE,ESP_STR_NOHW CALL WRITESTR JR ESP_INIT4 ; ESP_INIT3: CALL ESP_PRTVER LD A,(ESP_PRES) SET 1,A LD (ESP_PRES),A ; ESP_INIT4: ; INITIALIZE FIRST MODULE CHILD DRIVERS LD A,(ESP_PRES) BIT 0,A JR Z,ESP_INIT5 LD IY,ESPSER0_CFG CALL ESPSER_INIT ; SERIAL INITIALIZATION LD IY,ESPCON0_CFG CALL ESPCON_INIT ; CONSOLE INITIALIZATION ; ESP_INIT5: ; INITIALIZE SECOND MODULE CHILD DRIVERS LD A,(ESP_PRES) BIT 1,A JR Z,ESP_INIT6 LD IY,ESPSER1_CFG CALL ESPSER_INIT ; SERIAL INITIALIZATION ; ESP_INIT6: RET ; ;================================================================================================== ; ESP32 INTERFACE FUNCTIONS ;================================================================================================== ; ESP_DETECT: ; TRY TO DETECT IF PORT IS FLOATING AND ; FAIL DETECTION IF SO LD C,(IY+ESP_CFG_ST) ; ESP STATUS PORT IN A,(C) ; READ IT ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* AND %11100000 ; ISOLATE TOP 3 BITS CP $00 ; ALWAYS ZERO IF PRESENT RET NZ ; ABORT ON FAILURE ; ; ESP32 PROCESSOR MAY TAKE A FEW SECONDS TO START UP, SO ; HERE WE WAIT FOR BUSY TO CLEAR WITH ABOUT A 5 SECOND TIMEOUT LD B,0 ; LOOP UP TO 256 TIMES LD C,(IY+ESP_CFG_ST) ; ESP STATUS PORT ESP_DETECT1: IN A,(C) ; GET STATUS AND (IY+ESP_CFG_BSYMSK) ; IS ESP BUSY? JR Z,ESP_DETECT2 ; MOVE ALONG IF NOT BUSY LD DE,1500 ; 1500 * 16US = 24MS CALL VDELAY ; DELAY DJNZ ESP_DETECT1 ; LOOP OR $FF ; SIGNAL FAILURE RET ; DONE ; ESP_DETECT2: CALL ESP_SYNC ;LD A,B ; *DEBUG* ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* CALL ESP_CLR ; CLEAR ANY PENDING DATA LD A,ESP_CMD_DISC ; DISCOVER COMMAND CALL ESP_OUT ; SEND IT ; ; LOOK FOR SIGNATURE STARTING WITH "ESP" CALL ESP_INWAIT ; ATTEMPT TO GET CHAR ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* CP 'E' RET NZ CALL ESP_INWAIT ; ATTEMPT TO GET CHAR ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* CP 'S' RET NZ CALL ESP_INWAIT ; ATTEMPT TO GET CHAR ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* CP 'P' RET ; ; CLEAR ESP INPUT QUEUE ; ESP_CLR: ; LD B,0 ; MAX CHARS TO READ /Removed DDW ;ESP_CLR0: /Removed DDW CALL ESP_WTNBSY ; WAIT TILL NOT BUSY RET NZ ; BAIL OUT IF TIMEOUT IN A,(ESP_STAT) ; GET STATUS AND (IY+ESP_CFG_RDYMSK) ; IS THERE MORE DATA? RET Z ; IF NOT, DONE LD C,(IY+ESP_CFG_IO) ; ESP I/O PORT IN A,(C) ; GET BYTE JP ESP_CLR ; DJNZ ESP_CLR0 ; LOOP TILL DONE /Removed DDW ; OR $FF ; SIGNAL FAILURE /Removed DDW ; RET /Removed DDW ; ; RE-SYNC ESP (added DDW) ; ESP_SYNC: LD B,0 ; sync count -- WORST CASE PERFORMACE COULD BE IMPROVED BY REDUCING THIS VALUE ESP_SYNC0: PUSH BC LD A,ESP_CMD_SYNC ; Sync ESP CALL ESP_OUT ; SEND CMD OPCODE POP BC DJNZ ESP_SYNC0 ; LOOP TILL DONE RET ; ; PRINT ESP VERSION STRING TO CONSOLE ; ESP_PRTVER: CALL ESP_SYNC CALL ESP_CLR ; CLEAR ANY PENDING DATA ;LD DE,1000 ; SMALL DELAY HERE ;CALL VDELAY ; ... SEEMS TO HELP RELIABILITY LD A,ESP_CMD_DISC ; DISCOVER COMMAND CALL ESP_OUT ; SEND IT CALL ESP_WTRDY ; WAIT FOR READY TO OUTPUT ESP_PRTVER1: CALL ESP_WTNBSY ; WAIT TILL NOT BUSY IN A,(ESP_STAT) ; GET STATUS AND (IY+ESP_CFG_RDYMSK) ; ISOLATE OUTPUT READY BIT RET Z ; DONE IF NOTHING READY CALL ESP_IN ; GET NEXT CHAR CALL COUT ; PRINT CHAR JR ESP_PRTVER1 ; LOOP ; ; SEND BYTE TO ESP ; ESP_OUT: PUSH AF ; SAVE VALUE CALL ESP_WTNBSY ; WAIT TILL NOT BUSY POP AF ; POP VALUE LD C,(IY+ESP_CFG_IO) ; ESP I/O PORT OUT (C),A ; SEND BYTE JR ESP_WTBSY ; RETURN VIA WTBSY ; ; GET BYTE FROM ESP (BLOCKING) ; ESP_INWAIT: CALL ESP_WTNBSY ; WAIT TILL NOT BUSY CALL ESP_WTRDY ; WAIT FOR READY TO OUTPUT JP ESP_IN1 ; Added DDW ; ; GET BYTE FROM ESP (NON BLOCKING) ; ESP_IN: CALL ESP_WTNBSY ; WAIT TILL NOT BUSY ESP_IN1: LD C,(IY+ESP_CFG_IO) ; ESP I/O PORT IN A,(C) ; GET BYTE PUSH AF ; SAVE VALUE CALL ESP_WTBSY ; WAIT TILL BUSY POP AF ; RESTORE VALUE RET ; AND RETURN ; ; WAIT FOR ESP TO BE NOT BUSY ; ESP_WTNBSY: LD B,0 ; MAX TRIES ;PUSH HL ; SAVE HL ;LD HL,0 ; MAX TRIES ESP_WTNBSY1: LD C,(IY+ESP_CFG_ST) ; ESP STATUS PORT IN A,(C) ; GET STATUS AND (IY+ESP_CFG_BSYMSK) ; IS ESP BUSY? RET Z ; RETURN IF NOT BUSY ;JR Z,ESP_WTNBSY_Z ; RETURN IF NOT BUSY DJNZ ESP_WTNBSY1 ; ELSE LOOP ;DEC HL ; DEC LOOP COUNTER ;LD A,H ; CHECK FOR ;OR L ; ... TIMEOUT ;JR NZ,ESP_WTNBSY1 ; LOOP AS NEEDED ;CALL PC_ASTERISK ; *DEBUG* OR $FF ; SIGNAL TIMEOUT ;ESP_WTNBSY_Z: ;POP HL ; RECOVER HL RET ; AND RETURN ; ; WAIT FOR ESP TO BE BUSY ; ESP_WTBSY: LD B,3 ; MAX TRIES ESP_WTBSY1: LD C,(IY+ESP_CFG_ST) ; ESP STATUS PORT IN A,(C) ; GET STATUS XOR $FF ; INVERT SO 0=BUSY AND (IY+ESP_CFG_BSYMSK) ; IS ESP BUSY? RET Z ; RETURN IF BUSY DJNZ ESP_WTBSY1 ; ELSE LOOP OR $FF ; SIGNAL TIMEOUT RET ; AND RETURN ;;;; ;;;; WAIT FOR ESP TO BE READY TO OUTPUT ;;;; ;;;ESP_WTRDY: ;;; PUSH HL ; SAVE HL ;;; LD HL,0 ; MAX TRIES ;;;ESP_WTRDY1: ;;; LD C,(IY+ESP_CFG_ST) ; ESP STATUS PORT ;;; IN A,(C) ; GET STATUS ;;; XOR $FF ; INVERT SO 0=READY ;;; AND (IY+ESP_CFG_RDYMSK) ; IS ESP READY TO OUTPUT ;;; JR Z,ESP_WTRDY_Z ; RETURN IF READY ;;; DEC HL ; DEC LOOP COUNTER ;;; LD A,H ; CHECK FOR ;;; OR L ; ... TIMEOUT ;;; JR NZ,ESP_WTRDY1 ; LOOP AS NEEDED ;;; CALL PC_PERIOD ; *DEBUG* ;;; OR $FF ; SIGNAL TIMEOUT ;;;ESP_WTRDY_Z: ;;; POP HL ; RECOVER HL ;;; RET ; AND RETURN ; ; WAIT FOR ESP TO BE READY TO OUTPUT ; ESP_WTRDY: LD B,0 ; MAX TRIES ESP_WTRDY1: LD C,(IY+ESP_CFG_ST) ; ESP STATUS PORT IN A,(C) ; GET STATUS XOR $FF ; INVERT SO 0=READY AND (IY+ESP_CFG_RDYMSK) ; IS ESP READY TO OUTPUT RET Z ; RETURN IF READY DJNZ ESP_WTRDY1 ; ELSE LOOP ;CALL PC_PERIOD ; *DEBUG* CALL ESP_SYNC ; SOMETHING WENT WRONG, ENSURE SYNC (Added DDW) OR $FF ; SIGNAL TIMEOUT RET ; AND RETURN ; ; ; ESP_PRES .DB 0 ; MODULE PRESENCE BITS ; ESP_STR_NOHW .TEXT "NOT PRESENT$" ESP_STR_UPGRADE .TEXT "!!!UPGRADE REQUIRED!!!$" ; ;================================================================================================== ; ESP32 CONSOLE DRIVER ;================================================================================================== ; ; ESPCON_ROWS .EQU 25 ; VGA DISPLAY ROWS ESPCON_COLS .EQU 80 ; VGA DISPLAY COLS ; DEVECHO "ESPCON: ENABLED\n" ; ; ; ESPCON_INIT: LD A,(ESPCON_DEVCNT) ; GET ESPCON PHYSICAL DEVICE COUNT LD (IY+ESP_CFG_DEV),A ; SAVE PHYSICAL UNIT NUMBER INC A ; UPDATE COUNT LD (ESPCON_DEVCNT),A ; SAVE COUNT ; ; ADD OURSELVES TO CIO DISPATCH TABLE ; LD BC,ESPCON_FNTBL ; BC := FUNCTION TABLE ADDRESS PUSH IY ; COPY CONFIG ENTRY PTR POP DE ; ... TO DE CALL CIO_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED ;;;LD (HCB + HCB_CRTDEV),A ; SET OURSELVES AS THE CRT DEVICE CALL CIO_SETCRT ; SET OURSELVES AS THE CRT DEVICE ; ; ANNOUNCE OURSLEVES ; CALL NEWLINE ; FORMATTING PRTS("ESPCON$") ; NAME LD A,(IY+ESP_CFG_DEV) ; GET PHYSICAL UNIT NUMBER CALL PRTDECB ; UNIT STILL IN A FROM ABOVE CALL PC_COLON ; FORMATTING ; ; DISPLAY CONSOLE DIMENSIONS CALL PC_SPACE LD A,ESPCON_COLS CALL PRTDECB LD A,'X' CALL COUT LD A,ESPCON_ROWS CALL PRTDECB CALL PRTSTRD .TEXT " TEXT (ANSI)$" ; XOR A ; SIGNAL SUCCESS RET ; ; DRIVER FUNCTION TABLE ; ESPCON_FNTBL: .DW ESPCON_IN .DW ESPCON_OUT .DW ESPCON_IST .DW ESPCON_OST .DW ESPCON_INITDEV .DW ESPCON_QUERY .DW ESPCON_DEVICE #IF (($ - ESPCON_FNTBL) != (CIO_FNCNT * 2)) .ECHO "*** INVALID ESPCON FUNCTION TABLE ***\n" #ENDIF ; ; ; ESPCON_IN: CALL ESPCON_IST JR Z,ESPCON_IN LD A,ESP_0_CMD_KIN ; KBD INPUT CALL ESP_OUT ; SEND CMD OPCODE CALL ESP_INWAIT ; GET KEY LD E,A ; PUT IN E XOR A ; SIGNAL SUCCES RET ; AND DONE ; ; ; ESPCON_IST: CALL ESP_CLR ; CLEAR ANY PENDING DATA (Added DDW) LD A,ESP_0_CMD_KST ; KBD BUF STATUS CALL ESP_OUT ; SEND CMD OPCODE CALL ESP_INWAIT ; GET BUF SIZE OR A ; SET FLAGS RET Z ; AND DONE OR A RET ; ; ; ESPCON_OUT: PUSH DE LD A,ESP_0_CMD_COUT ; CHAR OUT OPCODE CALL ESP_OUT POP DE LD A,E CALL ESP_OUT ; SEND CHAR VALUE XOR A ; SIGNAL SUCCESS RET ; ; ; ESPCON_OST: XOR A ; ZERO ACCUM INC A ; ACCUM := 1 TO SIGNAL 1 BUFFER POSITION RET ; RETURN ; ; ; ESPCON_INITDEV: CALL ESP_CLR CALL ESP_SYNC ; SYSCHKERR(ERR_NOTIMPL) Removed DDW RET ; ; ; ESPCON_QUERY: LD DE,0 LD HL,0 XOR A RET ; ; ; ESPCON_DEVICE: LD D,CIODEV_ESPCON ; D := DEVICE TYPE LD E,(IY+ESP_CFG_DEV) ; E := DEVICE NUM LD C,$BF ; C := DEVICE TYPE, 0xBF IS PROP TERM LD H,0 ; H := 0, DRIVER HAS NO MODES LD L,(IY+ESP_CFG_IO) ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ; ESPCON CONFIGURATION ; ESPCON_CFG: ESPCON0_CFG: .DB 0 ; DEVICE NUMBER (UPDATED DURING INIT) .DB ESP_0_IO ; ESP DATA PORT .DB ESP_STAT ; ESP STATUS PORT .DB ESP_0_RDY ; ESP READY BIT MASK .DB ESP_0_BUSY ; ESP BUSY BIT MASK ; ; ; ESPCON_DEVCNT .DB 0 ; ESPCON DEVICES COUNT ; ;================================================================================================== ; ESP32 SERIAL DRIVER ;================================================================================================== ; ESPSER_LINECFG .EQU SER_115200_8N1 ; ESPSER_CFG_LINE .EQU 5 ; ; ; ESPSER_INIT: LD A,(ESPSER_DEVCNT) ; GET ESPSER PHYSICAL DEVICE COUNT LD (IY+ESP_CFG_DEV),A ; SAVE PHYSICAL UNIT NUMBER INC A ; UPDATE COUNT LD (ESPSER_DEVCNT),A ; SAVE COUNT ; ; ADD OURSELVES TO CIO DISPATCH TABLE ; LD BC,ESPSER_FNTBL ; BC := FUNCTION TABLE ADDRESS PUSH IY ; COPY CONFIG ENTRY PTR POP DE ; ... TO DE CALL CIO_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED ; ; ANNOUNCE OURSLEVES ; CALL NEWLINE ; FORMATTING PRTS("ESPSER$") ; NAME LD A,(IY+ESP_CFG_DEV) ; GET PHYSICAL UNIT NUMBER CALL PRTDECB ; UNIT STILL IN A FROM ABOVE CALL PC_COLON ; FORMATTING ; PRTS(" MODE=$") ; FORMATTING LD E,(IY+ESPSER_CFG_LINE+0) ; FIRST CONFIG BYTE TO E LD D,(IY+ESPSER_CFG_LINE+1) ; SECOND CONFIG BYTE TO D CALL PS_PRTSC0 ; PRINT CONFIG ; ; TODO: PRINT SERIAL CONFIG ; XOR A ; SIGNAL SUCCESS RET ; ; DRIVER FUNCTION TABLE ; ESPSER_FNTBL: .DW ESPSER_IN .DW ESPSER_OUT .DW ESPSER_IST .DW ESPSER_OST .DW ESPSER_INITDEV .DW ESPSER_QUERY .DW ESPSER_DEVICE #IF (($ - ESPSER_FNTBL) != (CIO_FNCNT * 2)) .ECHO "*** INVALID ESPSER FUNCTION TABLE ***\n" #ENDIF ; ; ; ESPSER_IN: CALL ESPSER_IST JR Z,ESPSER_IN LD A,ESP_CMD_SIN ; SERIAL INPUT CALL ESP_OUT ; SEND CMD OPCODE CALL ESP_INWAIT ; GET KEY LD E,A ; PUT IN E XOR A ; SIGNAL SUCCES RET ; AND DONE ; ; ; ESPSER_IST: CALL ESP_CLR ; CLEAR ANY PENDING DATA (Added DDW) LD A,ESP_CMD_SST ; SERIAL STATUS CALL ESP_OUT ; SEND CMD OPCODE CALL ESP_INWAIT ; GET BUF SIZE OR A ; SET FLAGS RET Z ; AND DONE OR A RET ; ; ; ESPSER_OUT: PUSH DE LD A,ESP_CMD_SOUT ; CHAR OUT OPCODE CALL ESP_OUT POP DE LD A,E CALL ESP_OUT ; SEND CHAR VALUE XOR A ; SIGNAL SUCCESS RET ; ; ; ESPSER_OST: XOR A ; ZERO ACCUM INC A ; ACCUM := 1 TO SIGNAL 1 BUFFER POSITION RET ; RETURN ; ; ; ESPSER_INITDEV: CALL ESP_CLR CALL ESP_SYNC PUSH DE ; SAVE INCOMING CONFIG WORD ; ; XLATE NEW LINE MODE INTO C LD A,E AND %00111111 ; ISOLATE MODE BITS LD C,0 ; 8N1 = 0 CP SER_DATA8 | SER_PARNONE | SER_STOP1 JR Z,ESPSER_INITDEV1 ; IF MATCH, DO IT INC C ; 8E1 = 1 CP SER_DATA8 | SER_PAREVEN | SER_STOP1 JR Z,ESPSER_INITDEV1 ; IF MATCH, DO IT INC C ; 8O1 = 2 CP SER_DATA8 | SER_PARODD | SER_STOP1 JR Z,ESPSER_INITDEV1 ; IF MATCH, DO IT INC C ; 7N1 = 3 CP SER_DATA7 | SER_PARNONE | SER_STOP1 JR Z,ESPSER_INITDEV1 ; IF MATCH, DO IT INC C ; 7E1 = 4 CP SER_DATA7 | SER_PAREVEN | SER_STOP1 JR Z,ESPSER_INITDEV1 ; IF MATCH, DO IT INC C ; 7O1 = 5 CP SER_DATA7 | SER_PARODD | SER_STOP1 JR Z,ESPSER_INITDEV1 ; IF MATCH, DO IT JR NZ,ESPSER_INITDEV_ERR ; ELSE FAIL ; ESPSER_INITDEV1: ; DECODE NEW BAUD RATE INTO DE:HL LD H,0 LD A,D AND %00011111 LD L,A LD DE,75 PUSH BC ; SAVE NEW LINE MODE CALL DECODE ; DE:HL IS DECODED BAUD RATE POP BC ; RESTORE NEW LINE MODE JR NZ,ESPSER_INITDEV_ERR ; IF ERROR, FAIL ; ; PROGRAM NEW LINE MODE PUSH BC LD A,ESP_CMD_SMODE CALL ESP_OUT POP BC LD A,C ;CALL PRTHEXBYTE ;CALL LDELAY CALL ESP_OUT ; ; PROGRAM NEW BAUD RATE LD A,ESP_CMD_SBAUD CALL ESP_OUT LD A,L CALL ESP_OUT LD A,H CALL ESP_OUT LD A,E CALL ESP_OUT LD A,D CALL ESP_OUT ; ; SAVE NEW LINE CONFIG WORD POP DE ; RESTORE CONFIG WORD LD (IY+ESPSER_CFG_LINE+0),E ; FIRST CONFIG BYTE LD (IY+ESPSER_CFG_LINE+1),D ; SECOND CONFIG BYTE ; XOR A RET ; ESPSER_INITDEV_ERR: POP DE ; THROW AWAY CONFIG WORD ON STACK OR $FF RET ; ; ; ESPSER_QUERY: LD E,(IY+ESPSER_CFG_LINE+0) ; FIRST CONFIG BYTE TO E LD D,(IY+ESPSER_CFG_LINE+1) ; SECOND CONFIG BYTE TO D LD HL,0 XOR A RET ; ; ; ESPSER_DEVICE: LD D,CIODEV_ESPSER ; D := DEVICE TYPE LD E,(IY+ESP_CFG_DEV) ; E := DEVICE NUM LD C,$00 ; C := DEVICE TYPE, 0x00 IS RS-232 LD H,0 ; H := 0, DRIVER HAS NO MODES LD L,(IY+ESP_CFG_IO) ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ; ESPSER CONFIGURATION ; ESPSER_CFG: ESPSER0_CFG: .DB 0 ; DEVICE NUMBER (UPDATED DURING INIT) .DB ESP_0_IO ; ESP DATA PORT .DB ESP_STAT ; ESP STATUS PORT .DB ESP_0_RDY ; ESP READY BIT MASK .DB ESP_0_BUSY ; ESP BUSY BIT MASK .DW ESPSER_LINECFG ; LINE CONFIGURATION ; DEVECHO "ESPSER: DEVICE=0\n" ; ESPSER1_CFG: .DB 0 ; DEVICE NUMBER (UPDATED DURING INIT) .DB ESP_1_IO ; ESP DATA PORT .DB ESP_STAT ; ESP STATUS PORT .DB ESP_1_RDY ; ESP READY BIT MASK .DB ESP_1_BUSY ; ESP BUSY BIT MASK .DW ESPSER_LINECFG ; LINE CONFIGURATION ; DEVECHO "ESPSER: DEVICE=1\n" ; ; ; ESPSER_DEVCNT .DB 0 ; ESPSER DEVICES COUNT ; ;-------------------------------------------------------------------------------------------------- ; HBIOS MODULE TRAILER ;-------------------------------------------------------------------------------------------------- ; END_ESP .EQU $ SIZ_ESP .EQU END_ESP - ORG_ESP ; MEMECHO "ESP occupies " MEMECHO SIZ_ESP MEMECHO " bytes.\n"