SECTION "BBC/OS"



GET "LIBHDR"



STATIC
$(
    restartlev  =  0
    restartlab  =  0
$)



MANIFEST
$(
    c.reset     =  0
    c.osrdch    =  1
    c.oswrch    =  2
    c.oscli     =  3
    
    cbit        =  #X80

    f.cmd       =  cbit + 0
    f.cmdack    =  cbit + 1
    f.data4     =  cbit + 2
    f.data4ack  =  cbit + 3
    f.data7ack  =  cbit + 4
$)



LET osrdch()  =  VALOF
$(
//  Call OSRDCH to read a character from the BBC host.

    restartlev  :=  level()
    restartlab  :=  label

label:
    command( c.osrdch )

    RESULTIS  readdata()
$)



AND oswrch( ch )  BE
$(
//  Call OSWRCH to write a character to the BBC host.

    restartlev  :=  level()
    restartlab  :=  label

label:
    command( c.oswrch )

    writedata( ch )
$)



AND command( c )  BE
$(
//  Write a command to the BBC host.  This causes a synchronisation, with the
//  command being sent, with the correct acknowledgment being expected.

    bbc.write( f.cmd + c )

    UNLESS  bbc.read()  =  (f.cmdack + c)  DO  restart()
$)



AND readdata()  =  VALOF
$(
//  Read a byte of data from the BBC host.  This either comes as one 7 bit
//  data items, or as two 4 bit data items.

    LET byte  =  bbc.read()
    LET cmd   =  0
    LET top4  =  0
    LET bot4  =  0

    IF  simplebyte( byte )  THEN  
    $(
        bbc.write( f.data7ack )

        RESULTIS  byte
    $)

    //  If the byte is not a simple 7 bit value, then it should be the first
    //  part of two 4 bit numbers.
    
    cmd   :=  complexbyte( byte )
    top4  :=  result2

    UNLESS  cmd = f.data4  DO  restart()

    bbc.write( f.data4ack + top4 )

    cmd   :=  complexbyte( bbc.read() )
    bot4  :=  result2

    UNLESS  cmd = f.data4  DO  restart()

    bbc.write( f.data4ack + bot4 )

    RESULTIS  (top4 << 4)  +  bot4
$)



AND writedata( byte )  BE
$(
//  Write the byte to the BBC host, either as one 7 bit quantity, or as two
//  4 bit quantities.

    TEST  simplebyte( byte )  THEN
    $(
        bbc.write( byte )
        
        UNLESS  bbc.read()  =  (f.data7ack)  DO  restart()
    $)
    ELSE
    $(
        LET top4  =  (complexbyte( byte ) >> 4)
        LET bot4  =  result2
        
        bbc.write( f.data4 + top4 )
        
        UNLESS  bbc.read()  =  (f.data4ack + top4)  DO  restart()
        
        bbc.write( f.data4 + bot4 )
        
        UNLESS  bbc.read()  =  (f.data4ack + bot4)  DO  restart()
    $)
$)



AND simplebyte( byte )  =  (byte & cbit) = 0



AND complexbyte( byte )  =  VALOF
$(
//  Split the two halves of the byte.

    result2  :=  byte & #X0F

    RESULTIS  byte & #XF0
$)



AND restart()  BE
$(
//  Some error has occurred, so put ourselves into "reset" mode, and restart
//  the operation.

    reset()

    longjump( restartlev, restartlab )
$)



AND reset()  BE
$(
//  Attempt to reset the stream.

    bbc.get()
    bbc.put( f.cmd + c.reset )
    
    IF  bbc.read()  =  (f.cmdack + c.reset)  THEN  RETURN
$)
REPEAT



AND bbc.read()  =  0
AND bbc.write( byte )  BE  RETURN
AND bbc.get()  =  0
AND bbc.put( byte )  BE  RETURN


