Raspberry pi

 info@homebrew8088.com 
                    Home    8088 Programming    Raspberry pi   Arduino    Troubleshoot 

   

YouTube Video

YouTube Video


8088 SBC, Raspberry pi:

    The 8088 is connected to the Raspberry pi through the SPI bus. The Raspberry pi uploads the ROM provides the monitor, keyboard, hard drive, and floppy drive.

    The parts I used to build.

    1 - 8088-2
    1 - 8284A
    1 - 74LS245
    2 - 74LS138    3 - 74HC573
    2 - 74LS04
    2 - 512K RAM
    1 - 2K RAM
    1 - 8259
    3 - MCP23S17


    The operational processes:

    The Raspberry pi is connected to the 8088 in a similar way that I connected the Arduino. I am using 3-MCP23S17 chips through the Raspberry pi SPI bus to read and wirte to the 8088 ram and I/O ports. The 8088 has a full 1 MB of ram and the first 2K of I/O ports and 8 hardware interrupts. 

    Loading the Rom into memory  -  The Raspberry pi holds the 8088 and flashes the Rom.bin file to memory address 0xF4000 and the jump code to memory address 0xFFFF0. 

    Reading video ram  -  Every fraction of a second the Raspberry pi holds the 8088 and reads a bit of the video ram. The video ram is stored in a char array and updated on the Raspberry pi screen. The timing and length of read can be adjusted through the code.

    Drive read and writes -  Every fraction of a second the Raspberry pi holds the 8088 and checks the I/O ports for command bytes. The Raspberry pi reads and writes to drive image files which are used to simulate the A: floppy and C: hard drive. 

    Keyboard input  -  When a key stroke is detected the Raspberry pi holds the 8088 and writes the character codes and scan codes to port 0x60/0x61 then releases the 8088 and triggers a hardware interrupt IRQ1. The bios INT 0x09 puts the character codes and scan codes into the keyboard buffer.

    System timer  -  Hardware IRQ0 is trigger from the Raspberry pi.
 

    Booting DOS:

    Booting DOS allows you to load off the shelf programs on the 8088. It took a lot of trial and error to figure this out.

    The MINIMUM bios interrupts and sub interrupts required to boot and use DOS

        -INT 0x08, Hardware, System timer IRQ0
                -Sets value for INT 0x1A, The rate of change does not seem to matter just needs to change.
        -INT 0x09, Hardware, Keyboard IRQ1
                -Puts the character code and scan code in to the key board buffer
        -INT 0x10, Video
                -AH=0x0E  Teletype out
                -Ignore any other AH=0xXX
        -INT 0x11, Equipment Check
                -This I return video mode and number of floppy drives
        -INT 0x12, Memory 
                -Returns 0x0280-640K, 
        -INT 0x13, Disk operations
                -AH=0x00, Resets disk, Does nothing returns success 
                -AH=0x01, Get status of last operation, Does nothing returns success  
                -AH=0x02, Disk read
                -AH=0x03, Disk write 
                -AH=0x08, Disk parameters
                -AH=0x15, Disk type 
        -INT 0x14, Communications
                -Does not have to do anything but is called during start up 
        -INT 0x15
                -Returns not BIOS supported
        -INT 0x16
                -AH=0x00, Returns key character code and scan code
                -AH=0x01, Checks to see if key stroke is present
                -AH=0x02, Key shift board flags, does not do anything returns 0x0000
        -INT 0x17, Communications
                -Does not have to do anything but is called during start up 
        -INT 0x1A, Time of Day
                -Clicks based on INT 0x08

    BIOS:

    The BIOS for my project is custom written to interface with the Raspberry pi. Most of this code will not work on a standard pc.

BIOS ROM CODE

[BITS 16]
CPU 8086
ORG 0X0000
START:
MOV AX, CS
MOV SS, AX
MOV SP, 0XBFEE ;0XF400:0XBFEE = 0XFFFEE
CALL LOAD_INT_VECTOR_TABLE
CALL LOAD_BIOS_DATA_AREA
CALL SET_UP_INTERRUPT_CONTROLLER
CALL CLEAR_SCREEN
CALL MESSAGE_1
MOV AX, CS
MOV DS, AX
MOV ES, AX
LOOP1:
MOV AX, 0X07C0 ;0X07C0:0X0000
MOV ES, AX ;ES:BX = ADDRESS BUFFER
MOV AX, 0X0201 ;READ ONE SECTOR
MOV BX, 0X0000 ;ES:BX = ADDRESS BUFFER
MOV CX, 0X0001
MOV DX, 0X0080 ;DRIVE TO BOOT UP 0=A, 80=C
INT 0X13
MOV AX, 0X07C0
MOV DS, AX
MOV ES, AX
MOV AX, 0X0000
MOV BX, 0X0000
MOV CX, 0X0000
MOV DX, 0X0000
JMP 0X07C0:0X0000
JMP LOOP1
LOAD_INT_VECTOR_TABLE:
CLD
MOV AX, 0X0000
MOV ES, AX
MOV DI, 0X0000
MOV AX, CS
MOV DS, AX
MOV SI, INT_VECTOR_TABLE
MOV CX, INT_VECTOR_TABLE.END - INT_VECTOR_TABLE
REP MOVSB
RET

LOAD_BIOS_DATA_AREA:
MOV AX, 0X0040
MOV ES, AX
MOV DI, 0X0000
MOV AX, CS
MOV DS, AX
MOV SI, BIOS_DATA_AREA
MOV CX, BIOS_DATA_AREA.END - BIOS_DATA_AREA
REP MOVSB
RET

SET_UP_INTERRUPT_CONTROLLER:
CLI
   ICW1: 
MOV AL, 0X13 
OUT 0X20, AL  
   ICW2: 
MOV AL, 0X08
OUT 0X21, AL         
   ICW3: 
   ICW4: 
MOV AL, 0X01   
OUT 0X21, AL  
STI

MOV AX, 0XB800
MOV DS, AX
MOV BX, 0X0000
MOV AL, 0X00
MOV [BX], AL
RET

MESSAGE_1:
MOV AH, 0X0E
MOV AL, 'B'
INT 0X10
MOV AL, 'I'
INT 0X10
MOV AL, 'O'
INT 0X10
MOV AL, 'S'
INT 0X10
MOV AL, ''
INT 0X10
MOV AL, '0'
INT 0X10
MOV AL, '.'
INT 0X10
MOV AL, '2'
INT 0X10
MOV AL, 0x0A
INT 0X10
MOV AL, 0x0A
INT 0X10
MOV AL, 0X0D
INT 0X10
RET
CLEAR_SCREEN:
MOV AX, 0XB800
MOV DS, AX
MOV BX, 0X0000
MOV CX, 2080 ;YES NOT HEX
MOV AX, 0X0700
  .LOOP_CLS:
MOV WORD [BX], AX
ADD BX, 0X0002
LOOP .LOOP_CLS
RET

BIOS_DATA_AREA:
;0x0400 (4 words) IO ports for COM1-COM4 serial (each address is 1 word, zero if none)
DW 0X0000
DW 0X0000
DW 0X0000
DW 0X0000
;0x0408 (4 words) IO ports for LPT1-LPT4 parallel (each address is 1 word, zero if none)
DW 0X0000
DW 0X0000
DW 0X0000
DW 0X0000 ;!!
;0x0410 (word) (Equip Flag) packed bit flags for detected hardware
;look up number google, right now one floppy drive, 80x25 color, no coprocessor
DW 0X02D
;0x0412 (byte) MFG test
DB 0x01
;0x0413 (word) Memory Size
DW 0x0280 ;280 640K, 
;0x0415 (word) IO Ram Size
DW 0x0000
;0x0417 (byte) keyboard state flag 0
DB 0X00
;0x0418 (byte) keyboard state flag 1
DB 0X00
;0x0419 (byte) ALT_INPUT
DB 0X00
;0x041A (word) keyboard head 
DW 0x001E
;0x041C (word) keyboard tail
DW 0x001E 
;0x041E (32 bytes) keyboard buffer
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
;0x043E DISKETTE DATA AREAS
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00
;0x0449 (byte) Display Mode [VIDEO DISPLAY DATA AREA]
DB 0X03 ;80x25  8x8   640x200   16 Colors 0xB800 CGA
;0x044A (word) number of columns in text mode
DW 0X0050
;0X044C (word)
DW 0X0000
;0X044E (word)
DW 0X0000
;0X0450 (16 BYTE AS WORD) :CURSOR_POSN 8 PAGES   col, row
DW 0X0000, 0X0000
DW 0X0000, 0X0000
DW 0X0000, 0X0000
DW 0X0000, 0X0000
;0X0460 (word) Cursor Mode
DW 0X0000
;0x0462 Active Page
DB 0X00
;0x0463 (2 bytes, taken as a word) base IO port for video
DB 0X00
DB 0X00
;0x0465 (byte)
DB 0x00
;0x0466 (byte)
DB 0x00
;0x0467 (word)
DW 0x0000
;0x0469 (word)
DW 0x0000
;0x046B (byte)
DB 0x00
;0x046C (word) # of IRQ0 timer ticks since boot
DW 0X0000
;LATER 0x046E
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00
;
;0x0475 (byte) # of hard disk drives detected
DB 0X00
;LATER 0x0476
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00
;
;0x0480 (word) keyboard buffer start
DW 0X001E
;0x0482 (word) keyboard buffer end
DW 0X003E
;LATER 0x0484
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00, 0X00
DB 0X00, 0X00, 0X00
;0x0497 (byte) last keyboard LED/Shift key state
DB 0X00

.END:
INT_VECTOR_TABLE:
DW INT00, 0XF400
DW INT01, 0XF400
DW INT02, 0XF400
DW INT03, 0XF400
DW INT04, 0XF400
DW INT05, 0XF400
DW INT06, 0XF400
DW INT07, 0XF400
DW INT08, 0XF400
DW INT09, 0XF400
DW INT0A, 0XF400
DW INT0B, 0XF400
DW INT0C, 0XF400
DW INT0D, 0XF400
DW INT0E, 0XF400
DW INT0F, 0XF400
DW INT10, 0XF400
DW INT11, 0XF400
DW INT12, 0XF400
DW INT13, 0XF400
DW INT14, 0XF400
DW INT15, 0XF400
DW INT16, 0XF400
DW INT17, 0XF400
DW INT18, 0XF400
DW INT19, 0XF400
DW INT1A, 0XF400
DW INT1B, 0XF400
DW INT1C, 0XF400
DW INT1D, 0XF400
DW INT1E, 0XF400
DW INT1F, 0XF400
   .END:

INT00: ;Divide by Zero
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '0' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '0' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT01: ;Single Step
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '0' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '1' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT02: ;Nonmaskable 
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '0' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '2' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT03: ;Breakpoint
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '0' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '3' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT04: ;Overflow
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '0' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '4' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT05: ;Print Screen
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '0' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '5' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT06: ;Reserved
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '0' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '6' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT07: ;Reserved
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '0' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '7' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT08: ;Time of Day
CLI
PUSH AX
PUSH DS
PUSH BX
MOV AX, 0X0040 ;BIOS DATA AREA
MOV DS, AX ;SET DS
MOV BX, 0X006C ;0X046C TIMER TICKS
INC WORD [BX] ;INC 1
MOV AL, 0X20 ;RESET 8295
OUT 0X20, AL ;OUT PORT
POP BX
POP DS
POP AX
STI
IRET
INT09: ;Keyboard
CLI ;CLEAR INTERRUPT FLAG
PUSH AX ;STORE AX
PUSH BX ;STORE BX
PUSH DX ;STORE DX
PUSH DS ;STORE DS
MOV AX, 0X0040 ;BIOS DATA AREA
MOV DS, AX ;SET DATA SEGMENT
MOV BX, [0X001C] ;GET KEYBOARD TAIL
IN AX, 0X60 ;GET CHAR CODE FROM PORT 0X60 AND SCAN CODE FROM 0X61
MOV WORD [BX], AX ;STORE CHAR AND SCAN
ADD BX, 0X0002 ;ADD BX PIONTER +2
CMP BX, [0X0082] ;CHECK TO SEE IF PIONTER IS AT THE END OF THE BUFFER
JB .NOT_END_OF_BUFFER ;JUMP OVER THE NEXT STEP IF IT IS NOT THE END
MOV BX, [0X0080] ;SET PIONTER BACK TO THE START OF BUFFER
 .NOT_END_OF_BUFFER:
MOV [0X001C], BX ;STORE POINTER
POP DS ;RESTORE DS
POP DX ;RESTORE DX
POP BX ;RESTORE BX
MOV AL, 0X20 ;COMMAND WORD
OUT 0X20, AL ;RESET 8259
POP AX ;RESTORE AX
STI ;SET INTERRUPT FLAG
IRET ;RETURN FROM INTERRUPT
INT0A: ;Reserved
PUSH AX ;STORE AX
MOV AL, 0X20 ;COMMAND WORD
OUT 0X20, AL ;RESET 8259
POP AX ;RESTORE AX
IRET ;RETURN FROM INTERRUPT
INT0B: ;Communications
PUSH AX ;STORE AX
MOV AL, 0X20 ;COMMAND WORD
OUT 0X20, AL ;RESET 8259
POP AX ;RESTORE AX
IRET ;RETURN FROM INTERRUPT
INT0C: ;Communications
PUSH AX ;STORE AX
MOV AL, 0X20 ;COMMAND WORD
OUT 0X20, AL ;RESET 8259
POP AX ;RESTORE AX
IRET ;RETURN FROM INTERRUPT
INT0D: ;Disk
PUSH AX ;STORE AX
MOV AL, 0X20 ;COMMAND WORD
OUT 0X20, AL ;RESET 8259
POP AX ;RESTORE AX
IRET ;RETURN FROM INTERRUPT
INT0E: ;Diskette
PUSH AX ;STORE AX
MOV AL, 0X20 ;COMMAND WORD
OUT 0X20, AL ;RESET 8259
POP AX ;RESTORE AX
IRET ;RETURN FROM INTERRUPT
INT0F: ;Printer
PUSH AX ;STORE AX
MOV AL, 0X20 ;COMMAND WORD
OUT 0X20, AL ;RESET 8259
POP AX ;RESTORE AX
IRET ;RETURN FROM INTERRUPT
INT10:  ;Video
;CLI
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH DS
PUSH ES
CMP AH, 0x0E               ;Check the AH to determine what function is being called.
JZ .TELETYPE               ;Jump if 0x0E   

JMP .END_INT10
   .TELETYPE: ;0X0450
PUSH AX
MOV AX, 0X0040
MOV DS, AX ;Set data segment
MOV AH, 0X00 ;ah=0
MOV AL, BYTE [0X51] ;Current Row
MOV CX, WORD [0x04A] ;number of cols per row
ADD CX, CX ;Double col for hidden char data
MUL CL ;mul Current row * cols
MOV BH, 0X00 ;BH=0
MOV BL, BYTE [0X50] ;Set current col
ADD BX, BX ;Double col for hidden char data
ADD BX, AX ;Add in row
MOV AX, 0XB800 ;
MOV DS, AX ;Set video segment
POP AX ;restore char
CMP AL, 0X0D ;Check for enter
JZ .ENTER ;return carrage
CMP AL, 0X0A ;Check for line feed
JZ .LINE_FEED ;line feed
CMP AL, 0X08 ;check for back space
JZ .BACKSPACE
MOV [BX], AL ;Char out
JMP .MOVE_CURSOR_FORWARD

 .MOVE_CURSOR_FORWARD:
MOV AX, 0X0040 ;Check col
MOV DS, AX ;Set data segment
MOV BX, 0X0050 ;Col
MOV AH, 0X00 ;AH=0
MOV AL, BYTE [BX] ;get current col
INC AL ;inc col
CMP AX, WORD [0x04A] ;number of cols per row
JB .NOT_END_OF_COL
  .END_OF_COL:
  MOV AX, 0X0040 ;Check col
MOV DS, AX ;Set data segment
  MOV BX, 0X0050 ;
MOV AL, 0X00 ;
MOV BYTE [BX], AL ;Set col to 0
MOV BX, 0X0051 ;Row
MOV AH, 0X00 ;AH=0
MOV AL, BYTE [BX] ;get current ROW
INC AL ;inc row
CMP AX, 0X19 ;cmp to 25
JB .NOT_END_OF_ROWS
  .SCROLL_UP:
CLD ;SCROLL UP
MOV AX, 0XB800
MOV ES, AX
MOV DI, 0X0000
MOV AX, 0XB800
MOV DS, AX
MOV SI, 0X00A0
MOV CX, 4000
REP MOVSB
JMP .END_INT10
 .NOT_END_OF_ROWS:
MOV BX, 0X0051 ;ROW
MOV BYTE [BX], AL ;STORE AL=ROW
JMP .END_INT10 ;END

.NOT_END_OF_COL:
MOV BX, 0X0050 ;Col
MOV BYTE [BX], AL ;STORE AL=COL
JMP .END_INT10 ;END

  .ENTER:
  MOV AX, 0X0040 ;Check col
MOV DS, AX ;Set data segment
  MOV BX, 0X0050 ;
MOV AL, 0X00 ;
MOV BYTE [BX], AL ;Set col to 0
JMP .END_INT10
  .LINE_FEED:
  MOV AX, 0X0040 ;Check col
MOV DS, AX ;Set data segment
MOV BX, 0X0051 ;Row
MOV AH, 0X00 ;AH=0
MOV AL, BYTE [BX] ;get current ROW
INC AL ;inc row
CMP AX, 0X19 ;cmp to 25
JB .NOT_END_OF_ROWS ;STORE AL IN ROW AND END
JMP .SCROLL_UP ;SCROLL UP
  .BACKSPACE:
    SUB BX, 0X0002 ;GO BACK A SPACE IN RAM
    MOV BYTE [BX], 0X00 ;Clear char
  MOV AX, 0X0040 ;Check col
MOV DS, AX ;Set data segment
MOV BX, 0X0050 ;Col
MOV AH, 0X00 ;AH=0
MOV AL, BYTE [BX] ;get current col
DEC AL ;
CMP AX, WORD [0x04A] ;number of cols per row
JB .NOT_BEGIN_OF_COL
  .BEGIN_OF_COL:
  MOV AX, 0X0040 ;Check col
MOV DS, AX ;Set data segment
  MOV BX, 0X0050 ;
MOV AL, 0X4F ;
MOV BYTE [BX], AL ;Set col to 49
MOV BX, 0X0051 ;Row
MOV AH, 0X00 ;AH=0
MOV AL, BYTE [BX] ;get current ROW
DEC AL ;dec row
CMP AX, 0X19 ;cmp to 25
JB .NOT_END_OF_ROWS
  .BEGIN_OF_ROW:
  MOV BX, 0X0050 ;col
MOV BYTE [BX], 0X00
MOV BX, 0X0051 ;ROW
MOV BYTE [BX], 0X00
JMP .END_INT10
 .NOT_BEGIN_OF_ROW:
MOV BX, 0X0051 ;ROW
MOV BYTE [BX], AL
JMP .END_INT10

.NOT_BEGIN_OF_COL:
MOV BX, 0X0050 ;Col
MOV BYTE [BX], AL
JMP .END_INT10 
  
   .END_INT10:
    POP ES
POP DS
POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
;STI
IRET
INT11: ;Equipment Check
CLI ;CLEAR INTERRUPS FLAG
PUSH DS ;STORE DS
PUSH BX ;STORE BX
MOV AX, 0X0040 ;BIOS DATA AREA
MOV DS, AX ;SET DATA SEGMENT
MOV BX, 0X0010 ;OFFSET 0X10 EQUIPMENT LIST
MOV AX, WORD [BX] ;STORE EQUPMENT LIST AX
POP BX ;RESTORE BX
POP DS ;RESTORE DS
STI ;SET INTERRUPS FLAG
IRET ;RETRUN
INT12: ;Memory
CLI ;CLEAR INTERRUPS FLAG
PUSH DS ;STORE DS
PUSH BX ;STORE BX
MOV AX, 0X0040 ;BIOS DATA AREA
MOV DS, AX ;SET DATA SEGMENT
MOV BX, 0X0013 ;OFFSET 0X13 FOR MEMORY SIZE
MOV AX, WORD [BX] ;STORE MEMORY SIZE AX
POP BX ;RESTORE BX
POP DS ;RESTORE DS
STI ;SET INTERRUPS FLAG
IRET ;RETRUN
INT13: ;Diskette/Disk
;;;;;;JUMP TABLE;;;;;
;CLI
CMP DL, 0X00
JE .START_INT13
CMP DL, 0X80
JE .START_INT13
JNE .NOT_A_DRIVE
  .START_INT13:
CMP AH, 0X00
JE .RESET_DISK_SYSTEM ;GET STATUS OF LAST OPERATION
CMP AH, 0X01
JE .GET_STATUS_LAST_OPERATION
CMP AH, 0X02
JE .READ_WRITE_DISK
CMP AH, 0X03
JE .READ_WRITE_DISK
CMP AH, 0X08
JE .PARAMETERS
CMP AH, 0X15
JE .GET_DISK_TYPE
PUSH AX
MOV AH, 0X0E
MOV AL, 'I'
INT 0X10
MOV AL, '1'
INT 0X10
MOV AL, '3'
INT 0X10
POP AX
CALL DUMP_REGISTERS
HLT
  .NOT_A_DRIVE:
MOV AH, 0X01 ;STATUS 0X00 SUCCESSFULL
STC ;CLEAR CARRY FLAG SUCCESFUL
JMP .INT13_END_WITH_CARRY_FLAG
;;;;;;RESET;;;;;;
  .RESET_DISK_SYSTEM:
MOV AH, 0X00 ;STATUS 0X00 SUCCESSFULL
CLC ;CLEAR CARRY FLAG SUCCESFUL
JMP .INT13_END_WITH_CARRY_FLAG

;;;;;;GET STATUS OF LAST OPERATION;;;;;
  .GET_STATUS_LAST_OPERATION:
  MOV AH, 0X00 ;STATUS 0X00 SUCCESSFULL
CLC ;CLEAR CARRY FLAG SUCCESFUL
JMP .INT13_END_WITH_CARRY_FLAG

;;;;;;READ AND WRITE;;;;;;
  .READ_WRITE_DISK:
 
PUSH DS
PUSH ES
PUSH DX
PUSH CX
PUSH BX
PUSH AX
PUSH AX
OUT 0X01, AL ;NUMBER OF SECTORS
MOV AL, CH
OUT 0X02, AL ;CYLINDER 0-7
PUSH CX
MOV CH, CL
MOV CL, 0X06
SHR CH, CL
AND CH, 0X03
MOV AL, CH
OUT 0X03, AL ;CYLINDER 8-9
POP CX
AND CL, 0X3F
MOV AL, CL
OUT 0X04, AL ;SECTOR
MOV AL, DH
OUT 0X05, AL ;HEAD
MOV AL, DL
OUT 0X06, AL ;DRIVE
MOV AX, BX
OUT 0X07, AX ;BX
MOV AX, ES
OUT 0X09, AX ;ES
POP AX
MOV AL, AH ;AH IS THE COMMAND VALUE
OUT 0X00, AL ;OUT COMMAND PORT
  .READ_DISK_WAIT: ;WAIT FOR RASPBERRY PI LOOP
IN AL, 0X00 ;READ COMMAND PORT
CMP AL, 0XFF ;CHECK TO SEE IF RASPBERRY PI IS DONE
JNE .READ_DISK_WAIT ;LOOP UNTIL COMPLETE

POP AX ;AL NEED TO RETURN NUMBER OF SECTORS
POP BX ;RESTORE BX
POP CX ;RESTORE CX
POP DX ;RESTORE DX
POP ES ;RESTORE ES
POP DS ;RESTORE DS
MOV AH, 0X00 ;STATUS 0X00 SUCCESSFULL
CLC ;CLEAR CARRY FLAG SUCCESFUL
JMP .INT13_END_WITH_CARRY_FLAG
;;;;;;PARAMETERS;;;;;;
  .PARAMETERS: ;0x08 RETRUNS DISK PARAMETERS  
CMP DL, 0X80
JE .HARD_DRIVE_PARAMETERS
PUSH DS ;STORE DS
  PUSH AX ;STORE AX
MOV AX, CS ;GET CODE SEGMENT
MOV DS, AX ;SET DATA SEGMENT TO CS
MOV ES, AX ;FOR DRIVE PARAMETER TABLE ES:DI
POP AX  
MOV AL, DL ;SEND DRIVE NUMBER TO RASPBERRY PI 
OUT 0X06, AL ;DRIVE
MOV AL, AH ;AH IS THE COMMAND VALUE
OUT 0X00, AL ;OUT COMMAND PORT
  .PARAMETERS_WAIT: ;WAIT FOR RASPBERRY PI LOOP
IN AL, 0X00 ;READ COMMAND PORT
CMP AL, 0XFF ;CHECK TO SEE IF RASPBERRY PI IS DONE
JNE .PARAMETERS_WAIT ;LOOP UNTIL COMPLETE
IN AL, 0X0B ;DRIVE TYPE/MEDIA DESCRIPTOR 
MOV BL, AL ;BL RETURNS DRIVE TYPE
IN AL, 0X11 ;LOW 8 BITS CYLINDER
MOV CH, AL ;CH RETURNS LOW 8 BITS CYLINDER
IN AL, 0X10 ;SECTORS PER TRACK AND 2 HIGH BITS OF CYLINDER
MOV CL, AL ;CL RETURNS SECTORS PER TRACK AND 2 HIGH BITS OF CYLINDER
IN AL, 0X0C ;NUMBER OF HEADS/CLYINDER
DEC AL ;STARTS AT 0
MOV DH, AL ;DL RETURNS HEADS/CLYINDER
MOV DL, 0X01 ;NUMBER OF DRIVES
IN AL, 0X10 ;SECTORS PER TRACK AND 2 HIGH BITS OF CYLINDER
AND AL, 0X3F ;REMOVE CYLINDER BITS
DEC AL ;REDUCE BY ONE
MOV BYTE [.DISK_PARAMETER_TABLE + 4], AL ;FOR FLOPPY DRIVES DISK PARAMETER TABLE
IN AL, 0X0F ;BYTES PER SECTOR HIGH SIDE
MOV BYTE [.DISK_PARAMETER_TABLE + 3], AL ;FOR FLOPPY DRIVES DISK PARAMETER TABLE
MOV DI, INT13.DISK_PARAMETER_TABLE ;FOR DRIVE PARAMETER TABLE ES:DI

POP DS ;RESTORE DS
MOV AL, 0X00 ;ON SOME BIOS RETRUN ZERO
MOV AH, 0X00 ;STATUS 0X00 SUCCESSFULL 
CLC ;CLEAR CARRY FLAG SUCCESFUL
    JMP .INT13_END_WITH_CARRY_FLAG
  .DISK_PARAMETER_TABLE:
DB 0X00 ;00   specify byte 1; step-rate time, head unload time
DB 0X00 ;01   specify byte 2; head load time, DMA mode
DB 0X00 ;02   timer ticks to wait before disk motor shutoff
DB 0X00 ;03   bytes per sector code:
;0 - 128 bytes 2 - 512 bytes
;1 - 256 bytes 3 - 1024 bytes
DB 0X00 ;04   sectors per track (last sector number)
DB 0X00 ;05   inter-block gap length/gap between sectors
DB 0X00 ;06   data length, if sector length not specified
DB 0X00 ;07   gap length between sectors for format
DB 0X00 ;08   fill byte for formatted sectors
DB 0X00 ;09   head settle time in milliseconds
DB 0X00 ;0A   motor startup time in eighths of a second
;;;;;;HARD DRIVE PARAMETERS;;;;;;
.HARD_DRIVE_PARAMETERS:
MOV AL, DL ;SEND DRIVE NUMBER TO RASPBERRY PI
OUT 0X06, AL ;DRIVE
MOV AL, AH ;AH IS THE COMMAND VALUE
OUT 0X00, AL ;OUT COMMAND PORT
  .HARD_DRIVE_PARAMETERS_WAIT: ;WAIT FOR RASPBERRY PI LOOP
IN AL, 0X00 ;READ COMMAND PORT
CMP AL, 0XFF ;CHECK TO SEE IF RASPBERRY PI IS DONE
JNE .HARD_DRIVE_PARAMETERS_WAIT ;LOOP UNTIL COMPLETE
IN AL, 0X11 ;LOW 8 BITS CYLINDER
MOV CH, AL ;CH RETURNS LOW 8 BITS CYLINDER
IN AL, 0X10 ;SECTORS PER TRACK AND 2 HIGH BITS OF CYLINDER
MOV CL, AL ;CL RETURNS SECTORS PER TRACK AND 2 HIGH BITS OF CYLINDER
IN AL, 0X0C ;NUMBER OF HEADS/CLYINDER
DEC AL ;STARTS AT 0
MOV DH, AL ;DL RETURNS HEADS/CLYINDER
MOV DL, 0X01 ;NUMBER OF DRIVES
MOV AL, 0X00 ;ON SOME BIOS RETRUN ZERO
MOV AH, 0X00 ;STATUS 0X00 SUCCESSFULL 
CLC ;CLEAR CARRY FLAG SUCCESFUL
    JMP .INT13_END_WITH_CARRY_FLAG
;;;;;;GET_DISK_TYPE;;;;;;
  .GET_DISK_TYPE:
MOV AL, DL ;SEND DRIVE NUMBER TO RASPBERRY PI 
OUT 0X06, AL ;DRIVE
MOV AL, AH ;AH IS THE COMMAND VALUE
OUT 0X00, AL ;OUT COMMAND PORT
  .GET_DISK_TYPE_WAIT: ;WAIT FOR RASPBERRY PI LOOP
IN AL, 0X00 ;READ COMMAND PORT
CMP AL, 0XFF ;CHECK TO SEE IF RASPBERRY PI IS DONE
JNE .GET_DISK_TYPE_WAIT ;LOOP UNTIL COMPLETE
IN AL, 0X12
MOV DL, AL
IN AL, 0X13
MOV DL, AL
IN AL, 0X14
MOV DL, AL
IN AL, 0X15
MOV DL, AL
IN AL, 0X16
MOV AH, AL
MOV AL, 0X00 ;JUST BECUASE
CLC ;CLEAR CARRY FLAG SUCCESFUL
JMP .INT13_END_WITH_CARRY_FLAG
;;;;;;END;;;;;;;;
  .INT13_END_WITH_CARRY_FLAG: ;THIS IS HOW I RETURN THE CARRY FLAG
PUSH AX ;STORE AX
PUSHF ;STORE FLAGS
POP AX ;GET AX = FLAGS
PUSH BP ;STORE BP
MOV BP, SP              ;Copy SP to BP for use as index
ADD BP, 0X08 ;offset 8
AND WORD [BP], 0XFFFE ;CLEAR CF = ZER0
AND AX, 0X0001 ;ONLY CF 
OR WORD [BP], AX ;SET CF AX
POP BP                ;RESTORE BASE POINTER
POP AX ;RESTORE AX
;STI ;SET INTERRUPS FLAG
IRET ;RETRUN
INT14: ;Communications
IRET
INT15: ;Cassette
CLI ;CLEAR INTERRUPT FLAG
MOV AL, 0X00 ;AL = 0X00
MOV AH, 0X86 ;NO CASSETTE PRESENT
STC ;NOT BIOS SUPPORTED
;THIS IS HOW I RETURN THE CARRY FLAG
PUSH AX ;STORE AX
PUSHF ;STORE FLAGS
POP AX ;GET AX = FLAGS
PUSH BP ;STORE BP
MOV BP, SP              ;Copy SP to BP for use as index
ADD BP, 0X08 ;offset 8
AND WORD [BP], 0XFFFE ;CLEAR CF = ZER0
AND AX, 0X0001 ;ONLY CF 
OR WORD [BP], AX ;SET CF AX
POP BP                ;RESTORE BASE POINTER
POP AX ;RESTORE AX
STI ;SET INTERRUPS FLAG
IRET ;RETRUN
INT16: ;Keyboard
  CMP AH, 0X00 ;Check ah 
JZ .WAIT_FOR_KEY ;ah=0
CMP AH, 0X01
JZ .CHECK_ZERO_FLAG ;ah=1
CMP AH, 0X02
JZ .GET_SHIFT_FLAGS ;ah=2
IRET

  .WAIT_FOR_KEY:
PUSH BX
PUSH DS
  .WAIT_FOR_KEY_LOOP:
STI
MOV AX, 0X0040
MOV DS, AX
CLI
MOV BX, [0X001A] ;Tail
CMP BX, [0X001C] ;Head
JZ .WAIT_FOR_KEY_LOOP
MOV AX, [BX]
ADD BX, 0X0002 ;Mov bx forward through buffer
CMP BX, [0X0082] ;Check to see if at the end
JB .NOT_END_OF_BUFFER ;Jump oveR next step if not at the end
MOV BX, [0X0080] ;Set bx back to begining 
.NOT_END_OF_BUFFER:
MOV [0X001A], BX
POP DS
POP BX
STI
IRET

  .CHECK_ZERO_FLAG:
  PUSH BX
PUSH DS
MOV AX, 0X0040
MOV DS, AX

MOV BX, [0X001A] ;Tail
CMP BX, [0X001C] ;Head
MOV AX, [BX]
POP DS
POP BX
PUSH AX ;STORE AX
PUSHF ;STORE FLAGES
POP AX ;AX = FLAGS
    PUSH BP ;STORE BP
MOV BP, SP              ;Copy SP to BP for use as index
ADD BP, 0X08 ;offset 8
AND WORD [BP], 0XFFBF ;CLEAR ZF
AND AX, 0X0040 ;ONLY ZF
OR WORD [BP], AX ;SET ZF
POP BP                ;RESTORE BASE POINTER
POP AX ;RESTORE AX
IRET
  .GET_SHIFT_FLAGS:   
MOV AX, 0X0000 ;FOR NOW RETURNS NOTHING. 
IRET
INT17: ;Printer
IRET
INT18: ;Resident Basic
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '1' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '8' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT19: ;Bootstrap
JMP 0XFFFF:0X0000 ;JUMPS TO BOOT CODE
INT1A: ;Time of Day
;CLI
PUSH DS
  PUSH BX
MOV AX, 0X0040 ;BIOS DATA AREA
MOV DS, AX ;SET DS
MOV BX, 0X006C ;NUMBER OF CLICKS
MOV DX, WORD [BX] ;SET DX CLICKS
MOV CX, 0X0020 ;ZERO FOR NOW
MOV AX, 0X0000 ;
POP BX
POP DS
;STI
IRET
INT1B: ;Keyboard Break
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '1' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, 'B' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT1C: ;Timer Tick
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '1' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, 'C' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT1D: ;Video Initialization 
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '1' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, 'D' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT1E: ;Diskette Parameters
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '1' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, 'E' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
INT1F: ;Video Graphics Characters
MOV AH, 0X0E ;SET AH 0X0E FOR TELOTYPE
MOV AL, 'I' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, '1' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
MOV AL, 'F' ;SET AL TO CHAR
INT 0X10 ;CALL INTERRUPT 0X10
HLT ;HLT PROCESSOR NOT SUPPORTED INTERRUPT
IRET ;RETURN FROM INTERRUPT
DUMP_REGISTERS:
PUSH AX
PUSH DX
PUSH CX
PUSH BX
PUSH AX
MOV AH, 0X0E
MOV AL, ' '
INT 0X10
MOV AL, 'A'
INT 0X10
MOV AL, 'X'
INT 0X10
MOV AL, '='
INT 0X10
POP AX
PUSH AX
MOV AL, AH
CALL WIRTE_AL_INT10_E
POP AX
CALL WIRTE_AL_INT10_E
MOV AH, 0X0E
MOV AL, ' '
INT 0X10
MOV AL, 'B'
INT 0X10
MOV AL, 'X'
INT 0X10
MOV AL, '='
INT 0X10
POP AX
PUSH AX
MOV AL, AH
CALL WIRTE_AL_INT10_E
POP AX
CALL WIRTE_AL_INT10_E
MOV AH, 0X0E
MOV AL, ' '
INT 0X10
MOV AL, 'C'
INT 0X10
MOV AL, 'X'
INT 0X10
MOV AL, '='
INT 0X10
POP AX
PUSH AX
MOV AL, AH
CALL WIRTE_AL_INT10_E
POP AX
CALL WIRTE_AL_INT10_E
MOV AH, 0X0E
MOV AL, ' '
INT 0X10
MOV AL, 'D'
INT 0X10
MOV AL, 'X'
INT 0X10
MOV AL, '='
INT 0X10
POP AX
PUSH AX
MOV AL, AH
CALL WIRTE_AL_INT10_E
POP AX
CALL WIRTE_AL_INT10_E
MOV AH, 0X0E
MOV AL, 0X0D
INT 0X10
POP AX
RET
;;;;;;;;;;;;;;;;;;;;;;;
;WRITE TO SCREEN;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;
WIRTE_AL_INT10_E:

PUSH AX
PUSH BX
PUSH CX
PUSH DX

MOV BL, AL

MOV DH, AL
MOV CL, 0X04
SHR DH, CL

MOV AL, DH
AND AL, 0X0F
CMP AL, 0X09
JA LETTER_HIGH

ADD AL, 0X30
JMP PRINT_VALUE_HIGH

LETTER_HIGH:
ADD AL, 0X37

PRINT_VALUE_HIGH:
MOV AH, 0X0E
INT 0X10

MOV AL, BL
AND AL, 0X0F
CMP AL, 0X09
JA LETTER_LOW

ADD AL, 0X30
JMP PRINT_VALUE_LOW

LETTER_LOW:
ADD AL, 0X37

PRINT_VALUE_LOW:
MOV AH, 0X0E
INT 0X10

POP DX
POP CX
POP BX
POP AX

RET

DB 'END OF BIOS FILE'

    Raspberry pi code:

    The Raspberry pi interfaces with the 8088 through the SPI bus using MCP23S17 chips. 

Raspberry pi code

//g++ my8088.cpp -lwiringPi -pthread -lncurses -o my8088
#include <iostream>
#include <wiringPiSPI.h>
#include <unistd.h>
#include <fstream> 
#include <thread>
#include <stdio.h>
#include <ncurses.h>

using namespace std;

const char MCP23S17_WRITE_00 = 0b01000000;
const char MCP23S17_READ_00 =  0b01000001;
const char MCP23S17_WRITE_01 = 0b01000010;
const char MCP23S17_READ_01 =  0b01000011;
const char MCP23S17_WRITE_10 = 0b01000100;
const char MCP23S17_READ_10 =  0b01000101;
const char IOCON_0A = 0x0A;
const char IODIRA = 0x00;
const char IODIRB = 0x01;
const char GPIOA = 0x12;
const char GPIOB = 0X13;
const char ALL_OUT = 0x00;
const char ALL_IN = 0xFF;
unsigned char buffer[3];
char v_mem[2000]; 
char Char_Code_Scan_Code[2];
char Cursor_Position[2];
int Key_Buffer[0x100];
char Key_Head, Key_Tail;
bool Stop_Flag = false;
//The floppy drive image file A:
string drive_A = "Dos622.img";         
//The hard drive image file   C:      
string drive_C = "hdd622.img";
//Key board scan code table, the raspberry pi only sends one value for key inputs, the codes dont always match the 8088
char scan_codes[] = {
//     ,   ^A,   ^B,   ^C,    ^D,   ^E,   ^F,   ^G,     ^H,  TAB,  ENT,   ^K,    ^L,   ^M,   ^N,   ^O,
0X00, 0X1E, 0X30, 0X2E,  0X20, 0X12, 0X21, 0X22,   0X23, 0X0F, 0X1C, 0X25,  0X26, 0X32, 0X31, 0X18, //0x000
//   ^P,   ^Q,   ^R,   ^S,    ^T,   ^U,   ^V,   ^W,     ^X,   ^Y,   ^Z,  ESC,      ,     ,     ,     ,   
0X19, 0X10, 0X13, 0X1F,  0X14, 0X16, 0X2F, 0X11,   0X2D, 0X15, 0X2C,  0X01,  0X00, 0X00, 0X00, 0X00, //0x010
//  SPC,    !,    ",    #,     $,    %,    &,    ',      (,    ),    *,    +,     ,,    -,    .,    /,  
0X39, 0X02, 0X28, 0X04,  0X05, 0X06, 0X08, 0X27,   0X0A, 0X0B, 0X09, 0X0D,  0X33, 0X0C, 0X34, 0X35, //0x020
//    0,    1,    2,    3,     4,    5,    6,    7,      8,    9,    :,    ;,     <,    =,    >,    ?,  
0X0B, 0X02, 0X03, 0X04,  0X05, 0X06, 0X07, 0X08,   0X09, 0X3B, 0X27, 0X27,  0X33, 0X0D, 0X34, 0X35, //0x030
//    @,    A,    B,    C,     D,    E,    F,    G,      H,    I,    J,    K,     L,    M,    N,    O,
0X03, 0X1E, 0X30, 0X2E,  0X20, 0X12, 0X21, 0X22,   0X23, 0X17, 0X24, 0X25,  0X26, 0X32, 0X31, 0X18, //0x040
//    P,    Q,    R,    S,     T,    U,    V,    W,      X,    Y,    Z,    [,     \,    ],    ^,    _,
0X19, 0X10, 0X13, 0X1F,  0X14, 0X16, 0X2F, 0X11,   0X2D, 0X15, 0X2C, 0X1A,  0X2B, 0X1B, 0X07, 0X0C, //0x050
//    `,    a,    b,    c,     d,    e,    f,    g,      h,    i,    j,    k,     l,    m,    n,    o,
0X29, 0X1E, 0X30, 0X2E,  0X20, 0X12, 0X21, 0X22,   0X23, 0X17, 0X24, 0X25,  0X26, 0X32, 0X31, 0X18, //0x060
//    p,    q,    r,    s,     t,    u,    v,    w,      x,    y,    z,    {,     |,    },    ~,   BS,
0X19, 0X10, 0X13, 0X1F,  0X14, 0X16, 0X2F, 0X11,   0X2D, 0X15, 0X2C, 0X1A,  0X2B, 0X1B, 0X29, 0X0E, //0x070

   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x080 
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x080
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x0A0
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x0B0 

   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x0C0 
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x0D0
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x0E0
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x0F0 
//     ,     ,   DN,   UP,    LF,   RT,  HOM,   BS,       ,   F1,   F2,   F3,    F4,   F5,   F6,   F7,
   0X00, 0X00, 0X50, 0X48,  0X4B, 0X4D, 0X47, 0X0E,   0X00, 0X3B, 0X3C, 0X3D,  0X3E, 0X3F, 0X40, 0X41, //0x100 
//   F8,   F9,  F10,     ,      ,     ,     ,     ,       ,     ,     ,     ,      ,     ,     ,     ,
   0X42, 0X43, 0X44, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x110
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x120
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x130
//     ,     ,     ,     ,      ,     ,     ,     ,       ,     ,  DEL,     ,      ,     ,     ,     ,
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X53, 0X00,  0X00, 0X00, 0X00, 0X00, //0x140 
//     ,     , PGDN, PGUP,      ,     ,     ,     ,       ,     ,     ,     ,      ,     ,     ,     ,  
   0X00, 0X00, 0X51, 0X49,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x150
//     ,     ,     ,     ,      ,     ,     ,     ,    END,     ,     ,     ,      ,     ,     ,     ,    
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X4F, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x160
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x170

   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x180 
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x190
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1A0
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1B0
   
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1C0 
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1D0
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1E0
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1F0
//     ,     ,     ,     ,      ,     ,     , ^DEL,
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X93,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0X200
    };
//Key board character code table, the raspberry pi only sends one value for key inputs, the codes dont always match the 8088
char character_codes[] = {
//     ,   ^A,   ^B,   ^C,    ^D,   ^E,   ^F,   ^G,     ^H,  TAB,  ENT,   ^K,    ^L,   ^M,   ^N,   ^O,
0X00, 0X01, 0X02, 0X03,  0X04, 0X05, 0X06, 0X07,   0X08, 0X09, 0X0D, 0X0B,  0X0C, 0X0D, 0X0E, 0X0F, //0x000
//   ^P,   ^Q,   ^R,   ^S,    ^T,   ^U,   ^V,   ^W,     ^X,   ^Y,   ^Z,  ESC,      ,     ,     ,     ,
0X10, 0X11, 0X12, 0X13,  0X14, 0X15, 0X16, 0X17,   0X18, 0X19, 0X1A, 0X1B,  0X00, 0X00, 0X00, 0X00, //0x010
//  SPC,    !,    ",    #,     $,    %,    &,    ',      (,    ),    *,    +,     ,,    -,    .,    /,  
0X20, 0X21, 0X22, 0X23,  0X24, 0X25, 0X26, 0X27,   0X28, 0X29, 0X2A, 0X2B,  0X2C, 0X2D, 0X2E, 0X2F, //0x020
//    0,    1,    2,    3,     4,    5,    6,    7,      8,    9,    :,    ;,     <,    =,    >,    ?,     
0X30, 0X31, 0X32, 0X33,  0X34, 0X35, 0X36, 0X37,   0X38, 0X39, 0X3A, 0X3B,  0X3C, 0X3D, 0X3E, 0X3F, //0x030
//    @,    A,    B,    C,     D,    E,    F,    G,      H,    I,    J,    K,     L,    M,    N,    O,   
0X40, 0X41, 0X42, 0X43,  0X44, 0X45, 0X46, 0X47,   0X48, 0X49, 0X4A, 0X4B,  0X4C, 0X4D, 0X4E, 0X4F, //0x040
//    P,    Q,    R,    S,     T,    U,    V,    W,      X,    Y,    Z,    [,     \,    ],    ^,    _,
0X50, 0X51, 0X52, 0X53,  0X54, 0X55, 0X56, 0X57,   0X58, 0X59, 0X5A, 0X5B,  0X5C, 0X5D, 0X5E, 0X5F, //0x050
//    `,    a,    b,    c,     d,    e,    f,    g,      h,    i,    j,    k,     l,    m,    n,    o,
0X60, 0X61, 0X62, 0X63,  0X64, 0X65, 0X66, 0X67,   0X68, 0X69, 0X6A, 0X6B,  0X6C, 0X6D, 0X6E, 0X6F, //0x060
//    p,    q,    r,    s,     t,    u,    v,    w,      x,    y,    z,    {,     |,    },    ~,   BS,
0X70, 0X71, 0X72, 0X73,  0X74, 0X75, 0X76, 0X77,   0X78, 0X79, 0X7A, 0X7B,  0X7C, 0X7D, 0X7E, 0X08, //0x070

0X80, 0X81, 0X82, 0X83,  0X84, 0X85, 0X86, 0X87,   0X88, 0X89, 0X8A, 0X8B,  0X8C, 0X8D, 0X8E, 0X8F, //0x080
0X90, 0X91, 0X92, 0X93,  0X94, 0X95, 0X96, 0X97,   0X98, 0X99, 0X9A, 0X9B,  0X9C, 0X9D, 0X9E, 0X9F, //0x090
0XA0, 0XA1, 0XA2, 0XA3,  0XA4, 0XA5, 0XA6, 0XA7,   0XA8, 0XA9, 0XAA, 0XAB,  0XAC, 0XAD, 0XAE, 0XAF, //0x0A0
0XB0, 0XB1, 0XB2, 0XB3,  0XB4, 0XB5, 0XB6, 0XB7,   0XB8, 0XB9, 0XBA, 0XBB,  0XBC, 0XBD, 0XBE, 0XBF, //0x0B0 

0XC0, 0XC1, 0XC2, 0XC3,  0XC4, 0XC5, 0XC6, 0XC7,   0XC8, 0XC9, 0XCA, 0XCB,  0XCC, 0XCD, 0XCE, 0XCF, //0x0C0
0XD0, 0XD1, 0XD2, 0XD3,  0XD4, 0XD5, 0XD6, 0XD7,   0XD8, 0XD9, 0XDA, 0XDB,  0XDC, 0XDD, 0XDE, 0XDF, //0x0D0
0XE0, 0XE1, 0XE2, 0XE3,  0XE4, 0XE5, 0XE6, 0XE7,   0XE8, 0XE9, 0XEA, 0XEB,  0XEC, 0XED, 0XEE, 0XEF, //0x0E0
0XF0, 0XF1, 0XF2, 0XF3,  0XF4, 0XF5, 0XF6, 0XF7,   0XF8, 0XF9, 0XFA, 0XFB,  0XFC, 0XFD, 0XFE, 0XFF, //0x0F0  
//     ,     ,   DN,   UP,    LF,   RT,  HOM,   BS,       ,   F1,   F2,   F3,    F4,   F5,   F6,   F7,
   0X00, 0X00, 0XE0, 0XE0,  0XE0, 0XE0, 0XE0, 0X08,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x100 
//   F8,   F9,  F10,     ,      ,     ,     ,     ,       ,     ,     ,     ,      ,     ,     ,     ,
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x110
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x120
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x130
//     ,     ,     ,     ,      ,     ,     ,     ,       ,     ,  DEL,     ,      ,     ,     ,     ,   
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0XE0, 0X00,  0X00, 0X00, 0X00, 0X00, //0x140 
//     ,     , PGDN, PGUP,      ,     ,     ,     ,       ,     ,     ,     ,      ,     ,     ,     ,  
   0X00, 0X00, 0XE0, 0XE0,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x150
//     ,     ,     ,     ,      ,     ,     ,     ,    END,     ,     ,     ,      ,     ,     ,     ,    
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0XE0, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x160
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x170

   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x180 
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x190
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1A0
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1B0
   
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1C0 
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1D0
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1E0
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0x1F0
//     ,     ,     ,     ,      ,     ,     , ^DEL,
   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0XE0,   0X00, 0X00, 0X00, 0X00,  0X00, 0X00, 0X00, 0X00, //0X200
   };
void Start_SPI()
{
   //Setup SPI BUS chip enable 0, clock speed mHz-10
   wiringPiSPISetup(0, 10000000); 
   //Enable address pins for the MCP23S17
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = IOCON_0A; buffer[2] = 0b00001000;    
   wiringPiSPIDataRW(0, buffer, 3);
   //Port set up
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);
   //ADDRESS 0-7
    buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRB; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);
   //ADDRESS 8-15
   buffer[0] = MCP23S17_WRITE_01; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);
   //ADDRESS 16-19
   buffer[0] = MCP23S17_WRITE_01; buffer[1] = IODIRB; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);
   //Interrrupt 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = IODIRA; buffer[2] = ALL_OUT;  
   wiringPiSPIDataRW(0, buffer, 3);
   //Command 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = IODIRB; buffer[2] = 0b00111111;   
   wiringPiSPIDataRW(0, buffer, 3);
}
/*This resets the 8088, the MCP23S17 at address 010 GPIOB pin 7 is coneceted
to the reset pin on the 8284 clock. */
void Reset()
{
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b00000000;   
   wiringPiSPIDataRW(0, buffer, 3);   
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b10000000;   
   wiringPiSPIDataRW(0, buffer, 3);  
}
void Hold(bool val)
{
    if(val == true)
    {
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
         wiringPiSPIDataRW(0, buffer, 3);
        
         buffer[0] = MCP23S17_READ_10; buffer[1] = GPIOB; 0;   
         wiringPiSPIDataRW(0, buffer, 3);   
         buffer[2] = buffer[2] & 0b00100000; 
         while( buffer[2] != 0b00100000)
         {
               buffer[0] = MCP23S17_READ_10; buffer[1] = GPIOB; 0;   
               wiringPiSPIDataRW(0, buffer, 3);  
               buffer[2] = buffer[2] & 0b00100000;   
         }       
      
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = IODIRB; buffer[2] = 0b00111000;   
         wiringPiSPIDataRW(0, buffer, 3);    

         buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_OUT;   
         wiringPiSPIDataRW(0, buffer, 3);
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRB; buffer[2] = ALL_OUT;   
         wiringPiSPIDataRW(0, buffer, 3);
   
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = IODIRA; buffer[2] = ALL_OUT;   
         wiringPiSPIDataRW(0, buffer, 3);
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = IODIRB; buffer[2] = ALL_OUT;   
         wiringPiSPIDataRW(0, buffer, 3);    
    }
    else if(val ==false)
    {
        
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
         wiringPiSPIDataRW(0, buffer, 3);
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRB; buffer[2] = ALL_IN;   
         wiringPiSPIDataRW(0, buffer, 3);
   
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
         wiringPiSPIDataRW(0, buffer, 3);
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = IODIRB; buffer[2] = ALL_IN;   
         wiringPiSPIDataRW(0, buffer, 3);
      
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = IODIRB; buffer[2] = 0b00111111;   
         wiringPiSPIDataRW(0, buffer, 3);            
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b10000111; // or 0b10000000??? 
         wiringPiSPIDataRW(0, buffer, 3);  
    }
}

void Write_Memory_Array(long long Address, char code_for_8088[], int Length)
{  
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_OUT;   
   wiringPiSPIDataRW(0, buffer, 3);
    for(int i = 0; i < Length; i++) 
    {
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOA; buffer[2] = code_for_8088[i];   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000001;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
         wiringPiSPIDataRW(0, buffer, 3);  
         Address++;
    } 
}
void Write_Memory_Array(long long Address, char code_for_8088[], int offset, int Length)
{  
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_OUT;   
   wiringPiSPIDataRW(0, buffer, 3);
    for(int i = 0; i < Length; i++) 
    {
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOA; buffer[2] = code_for_8088[i + offset];   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000001;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
         wiringPiSPIDataRW(0, buffer, 3);  
         Address++;
    } 
}
void Read_Memory_Array(long long Address, char* char_Array, int Length)
{
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);
    for(int i=0; i < Length; ++i)
    {
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000010;   
         wiringPiSPIDataRW(0, buffer, 3);  
         
         buffer[0] = MCP23S17_READ_00; buffer[1] = GPIOA; 0;   
         wiringPiSPIDataRW(0, buffer, 3);         
         char_Array[i] = buffer[2];
         
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
         wiringPiSPIDataRW(0, buffer, 3);         
        
 Address++;
      }
}
void Read_Memory_Array(long long Address, char* char_Array, int offset, int Length)
{
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);
    for(int i=0; i < Length; ++i)
    {
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000010;   
         wiringPiSPIDataRW(0, buffer, 3);  
         
         buffer[0] = MCP23S17_READ_00; buffer[1] = GPIOA; 0;   
         wiringPiSPIDataRW(0, buffer, 3);         
         char_Array[i + offset] = buffer[2];
         
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
         wiringPiSPIDataRW(0, buffer, 3);         
         Address++;
      }
}
//Writes a single byte to IO port
void Write_IO_Byte(long long Address, char byte_for_8088) 
   //Set 8 bit Data port out 
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_OUT;   
   wiringPiSPIDataRW(0, buffer, 3);

   buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOA; buffer[2] = byte_for_8088;   
   wiringPiSPIDataRW(0, buffer, 3);  
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
   wiringPiSPIDataRW(0, buffer, 3);  
   buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
   wiringPiSPIDataRW(0, buffer, 3);  
   buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
   wiringPiSPIDataRW(0, buffer, 3);  
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000101;   
   wiringPiSPIDataRW(0, buffer, 3);  
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
   wiringPiSPIDataRW(0, buffer, 3);  
}
void Write_IO_Array(long long Address, char code_for_8088[], int Length)
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_OUT;   
   wiringPiSPIDataRW(0, buffer, 3);
    for(int i = 0; i < Length; i++) 
    {
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOA; buffer[2] = code_for_8088[i];   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000101;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
         wiringPiSPIDataRW(0, buffer, 3);  
         Address++;
    } 
}
void Read_IO_Array(long long Address, char* char_Array, int Length)
{
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);
    for(int i=0; i < Length; ++i)
    {
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000110;   
         wiringPiSPIDataRW(0, buffer, 3);  
         
         buffer[0] = MCP23S17_READ_00; buffer[1] = GPIOA; 0;   
         wiringPiSPIDataRW(0, buffer, 3);         
         char_Array[i] = buffer[2];
         
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
         wiringPiSPIDataRW(0, buffer, 3);         
         Address++;
      }
}
char Read_IO_Char(long long Address)
{
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);

   buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
   wiringPiSPIDataRW(0, buffer, 3);  
   buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
   wiringPiSPIDataRW(0, buffer, 3);  
   buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
   wiringPiSPIDataRW(0, buffer, 3);  
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000110;   
   wiringPiSPIDataRW(0, buffer, 3);  
   
   buffer[0] = MCP23S17_READ_00; buffer[1] = GPIOA; 0;   
   wiringPiSPIDataRW(0, buffer, 3);         
   char char_byte = buffer[2];
   
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
   wiringPiSPIDataRW(0, buffer, 3);   
   return char_byte;   
}
void Read_Memory_Array_2(long long Address, char* char_Array, int Length)
{
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);
    for(int i=0; i < Length; ++i)
    {
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000010;   
         wiringPiSPIDataRW(0, buffer, 3);  
         
         buffer[0] = MCP23S17_READ_00; buffer[1] = GPIOA; 0;   
         wiringPiSPIDataRW(0, buffer, 3);         
         char_Array[i] = buffer[2];
         
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
         wiringPiSPIDataRW(0, buffer, 3);         
         Address++;
         Address++;
      }
}
void Read_Memory_Array_2(long long Address, char* char_Array, int array_offset, int Length)
{
   //8 bit Data
   buffer[0] = MCP23S17_WRITE_00; buffer[1] = IODIRA; buffer[2] = ALL_IN;   
   wiringPiSPIDataRW(0, buffer, 3);
    for(int i=0; i < Length; ++i)
    {
         buffer[0] = MCP23S17_WRITE_00; buffer[1] = GPIOB; buffer[2] = Address;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOA; buffer[2] = Address >> 8;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_01; buffer[1] = GPIOB; buffer[2] = Address >> 16;   
         wiringPiSPIDataRW(0, buffer, 3);  
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000010;   
         wiringPiSPIDataRW(0, buffer, 3);  
         
         buffer[0] = MCP23S17_READ_00; buffer[1] = GPIOA; 0;   
         wiringPiSPIDataRW(0, buffer, 3);         
         char_Array[i + array_offset] = buffer[2];
         
         buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOB; buffer[2] = 0b11000111;   
         wiringPiSPIDataRW(0, buffer, 3);         
         Address++;
         Address++;
      }
}
void Interrupt_8()
{
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000001;   
   wiringPiSPIDataRW(0, buffer, 3); 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000000;   
   wiringPiSPIDataRW(0, buffer, 3);
}
void Interrupt_9()
{
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000010;   
   wiringPiSPIDataRW(0, buffer, 3); 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000000;   
   wiringPiSPIDataRW(0, buffer, 3);
}
void Interrupt_A()
{
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000100;   
   wiringPiSPIDataRW(0, buffer, 3); 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000000;   
   wiringPiSPIDataRW(0, buffer, 3);
}
void Interrupt_B()
{
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00001000;   
   wiringPiSPIDataRW(0, buffer, 3); 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000000;   
   wiringPiSPIDataRW(0, buffer, 3);
}
void Interrupt_C()
{
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00010000;   
   wiringPiSPIDataRW(0, buffer, 3); 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000000;   
   wiringPiSPIDataRW(0, buffer, 3);
}
void Interrupt_D()
{
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00100000;   
   wiringPiSPIDataRW(0, buffer, 3); 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000000;   
   wiringPiSPIDataRW(0, buffer, 3);
}
void Interrupt_E()
{
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b01000000;   
   wiringPiSPIDataRW(0, buffer, 3); 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000000;   
   wiringPiSPIDataRW(0, buffer, 3);
}
void Interrupt_F()
{
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b10000000;   
   wiringPiSPIDataRW(0, buffer, 3); 
   buffer[0] = MCP23S17_WRITE_10; buffer[1] = GPIOA; buffer[2] = 0b00000000;   
   wiringPiSPIDataRW(0, buffer, 3);
}
void up_date_screen()
{
   
   system("clear");
   int rows = 25; 
   int cols = 80;
   WINDOW * win = newwin(rows, cols, 0, 0);
   refresh();
   while (Stop_Flag != true) 
   {
      char char1[1] ={0x00}; 
      int v_out = 0;
      for(int i=0; i < rows; ++i)
      { 
         for(int j=0; j < cols; ++j)
         {
            char1[0] = v_mem[v_out];

            if(char1[0] < 0x20)
            {
               char1[0] = 0x20;
            }  
            if(char1[0] > 0x7E)
            {
               char1[0] = 0x20;
            }
            wmove(win, i, j);
            wprintw(win, char1); 
            v_out++;
         }
      }
      wmove(win, Cursor_Position[1], Cursor_Position[0]);
      wrefresh(win); 
      usleep(500);    
   }
}
void Get_Disk_Parameters_A()
{
   std::fstream MemoryFile;                  //This opens the drive img
   MemoryFile.open(drive_A);                 //File to open
   MemoryFile.seekg (0, MemoryFile.beg);     //Moves back to the begining
   char Floppy[0x200];                       //Char array to hold the data only reading first sector
   MemoryFile.read(Floppy, sizeof(Floppy));  //Read the file into the array
   MemoryFile.close();                       //Close the file
   
   char Media_Descriptor[0x10] = {0x04, 0, 0, 0, 0, 0, 0, 0, 0xF8, 0x02, 0, 0, 0, 0x01, 0, 0};
   //Start at port 11  
   Write_IO_Byte(0x0B, Media_Descriptor[Floppy[0x15] & 0x0F]);    //Media Descriptor - BL

   Write_IO_Byte(0x0C, Floppy[0x1A]);                             //Low byte heads per cylinder - DH -1
   Write_IO_Byte(0x0D, Floppy[0x1B]);                             //High byte heads per cylinder
            
   Write_IO_Byte(0x0E, Floppy[0x0B]);                             //Low bytes per sector - uS
   Write_IO_Byte(0x0F, Floppy[0x0C]);                             //High bytes per sector
   
   int Head_Per_Cylinder = (Floppy[0x1B] << 8) + Floppy[0x1A];    
   int Sector_Per_Track = (Floppy[0x19] << 8) + Floppy[0x18]; 
   int Number_Of_Sectors = (Floppy[0x14] << 8) + Floppy[0x13]; 
   
   int Number_Of_Cylinders = Number_Of_Sectors / Sector_Per_Track / Head_Per_Cylinder;
   Write_IO_Byte(0x11, Number_Of_Cylinders);                      //CH
   
   Number_Of_Cylinders = (Number_Of_Cylinders >> 2) & 0xC0;
   Sector_Per_Track = Sector_Per_Track & 0X3F;                    //CL
   Write_IO_Byte(0x10, Number_Of_Cylinders + Sector_Per_Track);
   Write_IO_Byte(0x12, 0x00);             //Always zero for floppy
   Write_IO_Byte(0x13, 0x00);             //Always zero for floppy
   Write_IO_Byte(0x14, 0x00);             //Always zero for floppy
   Write_IO_Byte(0x15, 0x00);             //Always zero for floppy
   Write_IO_Byte(0x16, 0X01);             //Drive type
}
void Get_Disk_Parameters_C()
{
   std::fstream MemoryFile;                  //This opens the drive img
   MemoryFile.open(drive_C);                 //File to open
   MemoryFile.seekg (0, MemoryFile.beg);     //Moves back to the begining
   char drive[0x200];                       //Char array to hold the data only reading first sector
   MemoryFile.read(drive, sizeof(drive));  //Read MBR
   int Hidden_Sectors;
   //Locates boot partition
   if(drive[0x1BE] == 0x80){Hidden_Sectors = drive[0x1C6] + (drive[0x1C7] << 8) + (drive[0x1C8] << 16) + (drive[0x1C9] << 24);}
   else if(drive[0x1CE] == 0x80){Hidden_Sectors = drive[0x1D6] + (drive[0x1D7] << 8) + (drive[0x1D8] << 16) + (drive[0x1D9] << 24);}
   else if(drive[0x1DE] == 0x80){Hidden_Sectors = drive[0x1E6] + (drive[0x1E7] << 8) + (drive[0x1E8] << 16) + (drive[0x1E9] << 24);}
   else if(drive[0x1EE] == 0x80){Hidden_Sectors = drive[0x1F6] + (drive[0x1F7] << 8) + (drive[0x1F8] << 16) + (drive[0x1F9] << 24);}
   //No boot partion MBR
   else{MemoryFile.close(); Stop_Flag = true; usleep(20000); printf("No boot partion in MBR C: \n");}
   //Read volume boot record
   MemoryFile.seekg (0x200 * Hidden_Sectors, MemoryFile.beg);
   MemoryFile.read(drive, sizeof(drive));
   MemoryFile.close();                       //Close the file
   
   //char Media_Descriptor[0x10] = {0x04, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x02, 0, 0, 0, 0x01, 0, 0};
   //Start at port 11  
   //Write_IO_Byte(0x0B, Media_Descriptor[drive[0x15] & 0x0F]);    //Media Descriptor - BL

   Write_IO_Byte(0x0C, drive[0x1A]);                             //Low byte heads per cylinder - DH -1
   Write_IO_Byte(0x0D, drive[0x1B]);                             //High byte heads per cylinder
            
   Write_IO_Byte(0x0E, drive[0x0B]);                             //Low bytes per sector - uS
   Write_IO_Byte(0x0F, drive[0x0C]);                             //High bytes per sector
   
   int Head_Per_Cylinder = (drive[0x1B] << 8) + drive[0x1A];    
   int Sector_Per_Track = (drive[0x19] << 8) + drive[0x18]; 
   int Number_Of_Sectors = (drive[0x14] << 8) + drive[0x13]; 
   
   int Number_Of_Cylinders = Number_Of_Sectors / Sector_Per_Track / Head_Per_Cylinder;
   Write_IO_Byte(0x11, Number_Of_Cylinders);                      //CH
   
   Number_Of_Cylinders = (Number_Of_Cylinders >> 2) & 0xC0;
   Sector_Per_Track = Sector_Per_Track & 0X3F;                    //CL
   Write_IO_Byte(0x10, Number_Of_Cylinders + Sector_Per_Track);
   
   int Small_Sectors = (drive[0x14] << 8) + drive[0x13];
   if(Small_Sectors == 0x0000)
   {
      Write_IO_Byte(0x12, drive[0x20]);   //Big sector
      Write_IO_Byte(0x13, drive[0x21]);
      Write_IO_Byte(0x14, drive[0x22]);
      Write_IO_Byte(0x15, drive[0x23]);
   }
   else
   {
      Write_IO_Byte(0x12, drive[0x13]);   //Small sector
      Write_IO_Byte(0x13, drive[0x14]);
      Write_IO_Byte(0x14, 0x00);
      Write_IO_Byte(0x15, 0x00);
   }
   Write_IO_Byte(0x16, 0X03);
}
void Check_Int13()
{
   Hold(true); 
   char Int13_Command = Read_IO_Char(0X00);
   char Drive = Read_IO_Char(0X06);
   Hold(false);

   if(Int13_Command != 0xFF)
   {
      Hold(true);
      if(Drive == 0x00){Get_Disk_Parameters_A();}   //File to open
      if(Drive == 0x80){Get_Disk_Parameters_C();}
      char int13_data[0X20];
      Read_IO_Array(0X00, int13_data, 0X20);
      
      if(Int13_Command == 0x00)
      {
         //BIOS DOES ALL THE WORK
         //RESET DISK SYSTEM
         //NOTHING TO RESET
      }
      if(Int13_Command == 0x01)
      {
         //BIOS DOES ALL THE WORK
         //GET STATUS OF LAST OPERATION
      }  
      if(Int13_Command == 0x02) //read
      {
         int Cylinder = (int13_data[3] << 8) + int13_data[2];
         int Sector = int13_data[4];
         int Head = int13_data[5];
         int Bytes_Per_Sector = (int13_data[0x0F] << 8) + int13_data[0x0E];
         int Sector_Per_Track = (int13_data[0x10] & 0X3F) ;
         int Head_Per_Cylinder = (int13_data[0x0D] << 8) + int13_data[0x0C];
         int Number_Of_Sectors = int13_data[1];
         int LBA = (Cylinder * Head_Per_Cylinder + Head) * Sector_Per_Track + (Sector - 1);
         int Buffer_Address = (int13_data[10] << 12) + (int13_data[9] << 4) + (int13_data[8] << 8) + int13_data[7];
         
         std::fstream MemoryFile;                                    //This opens the drive img
         if(Drive == 0x00){MemoryFile.open(drive_A);}   //File to open
         if(Drive == 0x80){MemoryFile.open(drive_C);}
         MemoryFile.seekg (LBA * Bytes_Per_Sector, MemoryFile.beg);  //Set position 
         char drive[Number_Of_Sectors * Bytes_Per_Sector];          //Char array to hold the data
         MemoryFile.read(drive, sizeof(drive));                    //Read the file into the array
         MemoryFile.close();                                         //Close the file

         Write_Memory_Array(Buffer_Address, drive, sizeof(drive));
        
      }
      if(Int13_Command == 0x03)
      {
         int Cylinder = (int13_data[3] << 8) + int13_data[2];
         int Sector = int13_data[4];
         int Head = int13_data[5];
         int Bytes_Per_Sector = (int13_data[0x0F] << 8) + int13_data[0x0E];
         int Sector_Per_Track = (int13_data[0x10] & 0X3F) ;
         int Head_Per_Cylinder = (int13_data[0x0D] << 8) + int13_data[0x0C];
         int Number_Of_Sectors = int13_data[1];
         int LBA = (Cylinder * Head_Per_Cylinder + Head) * Sector_Per_Track + (Sector - 1);
         int Buffer_Address = (int13_data[10] << 12) + (int13_data[9] << 4) + (int13_data[8] << 8) + int13_data[7];
         char drive[Number_Of_Sectors * Bytes_Per_Sector];    //Char array to hold the data
         
         Read_Memory_Array(Buffer_Address, drive, sizeof(drive));

         std::fstream MemoryFile;                                    //This opens the drive img
         if(Drive == 0x00){MemoryFile.open(drive_A);}   //File to open
         if(Drive == 0x80){MemoryFile.open(drive_C);}
         MemoryFile.seekp (LBA * Bytes_Per_Sector, MemoryFile.beg);  //Sets position to write to           
         MemoryFile.write(drive, sizeof(drive));                   //Writes only new data
         MemoryFile.close();                                         //Close img
      }
      if(Int13_Command == 0x08)//PARAMETERS
      {
         if(int13_data[6] == 0x00){Get_Disk_Parameters_A();}   
         if(int13_data[6] == 0x80){Get_Disk_Parameters_C();}
      }  
      if(Int13_Command == 0x15)//GET DISK TYPE
      {
         if(int13_data[6] == 0x00){Get_Disk_Parameters_A();}   
         if(int13_data[6] == 0x80){Get_Disk_Parameters_C();}
      }  
      Write_IO_Byte(0x0000, 0xFF);  
      Hold(false);
   }
}
void Read_Write_Ram()
{
   char stop_byte;
   char Int13_Command;
   while (Stop_Flag != true)
   {
      int step_rate = 40;
      int address = 0xB8000;
      int offset = 0x0000;
      for(int i=0; i < 2000; i)
      { 
         Hold(true); 
         Read_Memory_Array_2(address, v_mem, offset, step_rate); 
         Read_Memory_Array(0x00450, Cursor_Position, 2);
         stop_byte = Read_IO_Char(0x0050);
         Hold(false);
         if(stop_byte == 0X00)
         {
            Stop_Flag = true;
         }
         usleep(100); 
         for(int ii=0; ii < 5; ++ii)
         { 
            Interrupt_8();
            usleep(400); 
            if(Key_Head != Key_Tail)
            {  
               Hold(true);
               Write_IO_Byte(0x60, character_codes[Key_Buffer[Key_Head]]);
               Write_IO_Byte(0x61, scan_codes[Key_Buffer[Key_Head]]);
               Hold(false);
               Interrupt_9();
               Key_Head++;
            } 
            usleep(400); 
            Hold(true);
            Int13_Command = Read_IO_Char(0X00);
            Hold(false);
            //usleep(200);
            if(Int13_Command != 0XFF)
            {
               Check_Int13();
            }
            usleep(400);
         }
         address = address + step_rate + step_rate; 
         offset = offset + step_rate;
         i = i + step_rate;
      }
   }
}

void keyboard()
{
   initscr();              //The very first thing to do: Before you use any other curses routines, the initscr() routine must be called first.
   noecho();               //No echo. To suppress the automatic echoing of typed characters, you need to call
   keypad(stdscr, TRUE);   //Special keys. In order to capture special keystrokes like Backspace, Delete and the four arrow keys by getch(), you need to call
   nodelay(stdscr, TRUE);
   //curs_set(0);            //show no cur
   //cbreak();               //
   raw();
   int Key_Pressed = 0;
   while (Stop_Flag != true)
   {     
      Key_Pressed = getch();
      if(Key_Pressed != ERR)
      {
         Key_Buffer[Key_Tail] = Key_Pressed; 
         Key_Tail++;
      }  
   }
}
int main()
{
   Start_SPI();                              //My function to start SPI interface

   std::ifstream MemoryFile;                 //New ifstream
   MemoryFile.open("Rom.bin");               //Open Rom.bin
   MemoryFile.seekg (0, ios::end);           //Find the end of the file
   int FileSize = MemoryFile.tellg();        //Get the size of the file
   MemoryFile.seekg (0, MemoryFile.beg);     //Start reading at the begining
   char Rom[FileSize];                       //New char array the size of the rom file
   MemoryFile.read(Rom, FileSize);           //Read the file
   MemoryFile.close();                       //Close the file

   //Jump code, JMP FAR 0XF400:0X0100
   char FFFF0[] = {0XEA, 0X00, 0X00, 0X00, 0XF4, 'E', 'M', ' ', '1', '1', '/', '0', '4', '/', '1', '9'};

   
   Hold(true);                                        //the 8088 must be held proir to all read writes. Mem/IO
   Write_Memory_Array(0xFFFF0, FFFF0, sizeof(FFFF0)); //Jump Code
   Write_Memory_Array(0xF4000, Rom, sizeof(Rom));     //The Rom file
   Write_IO_Byte(0x0050, 0xFF);                       //Make sure STOP byte at port 0x50 is zero 0x00 = Stop
   Write_IO_Byte(0x0000, 0xFF);                       //Make sure int13 command port is 0xFF
   Hold(false);                                       //Stop hold
   Reset();                                           //Reset the 80888
                                                      //Start threads
   thread screen_loop(up_date_screen);                //Start screen
   thread ram_loop(Read_Write_Ram);                   //Start access to memory/IO
   thread keyboard_loop(keyboard);                    //Start Keyboard 
   while (Stop_Flag != true)                          //do nothing while progaming is running
   {
      usleep(1000);            
   }
   screen_loop.join();                                //Wait for threads to join
   ram_loop.join();
   keyboard_loop.join();

   endwin();                                          //ncurses end
   system("clear");                                   //Clear screen
   //printf("\033[%d;%dH", 1, 0);                       //Move cursor position
   return 0;
}