Part B: Here is one solution, where the interrupt service routines themselves do everything involved in handshaking and retransmission.
asynch_input_interrupt_service:
get ch from UART data input register
if ch = ACK
mode = normal
enable output interrupt requests from UART
else if ch = NAK
mode = retransmit
enable output interrupt requests from UART
else
character must be part of some other data flow
endif
asynch_output_interrupt_service:
if mode = normal
ch = dequeue( output_queue )
buffer[ptr] = ch
ptr++
put ch in UART output data register
if ptr = 1K then
mode = sendenq
else if empty( output_queue )
disable output interrupt requests from UART
endif
else if mode = sendenq
put ENQ in UART output data register
ptr = 0
disable output interrupt requests from UART
else if mode = retransmit
ch = buffer[ptr]
ptr++
if ptr = 1K then
mode = sendenq
endif
put_byte(ch):
disable output interrupt request from UART
enqueue( output_queue, ch )
enable output interrupt request from UART
Part B: Here is a proposal for a canonical data representation for data sent by a C program on one machine to a C program on another.