words[]: const bool yes = 1 , no = 0 , true = 1 , false = 0 ; const uint ok = 0 ; void out ( uint8 addr , uint8 value ) = opcode out , reverted void out_w ( uint8 addr , uint16 value ) = opcode out , reverted void out ( uint8 [ ] , uint i , uint n , uint8 addr ) = opcode out void out ( uint16 [ ] , uint i , uint n , uint8 addr ) = opcode out uint8 in ( uint8 addr ) = opcode in uint16 in_w ( uint8 addr ) = opcode in void in ( uint8 [ ] , uint i , uint n , uint8 addr ) = opcode out void in ( uint16 [ ] , uint a , uint n , uint8 addr ) = opcode out void ei ( ) = opcode ei void di ( ) = opcode di void wait ( ) = opcode wait void timer ( ) = opcode timer uint systemtime ( ) = opcode systemtime uint swap ( uint ) = opcode swap uint8 get_lo ( uint ) = opcode lo uint8 get_hi ( uint ) = opcode hi uint min ( uint , uint ) = opcode min uint8 msbit ( uint ) = opcode msbit void copy ( uint8 [ ] ¢ , uint i1 , uint8 [ ] ¢ , uint i2 , uint n ) = opcode copy void copy ( uint16 [ ] ¢ , uint i1 , uint16 [ ] ¢ , uint i2 , uint n ) = opcode copy enum uint8 { MR0A = 0 , MR1A = 0 , MR2A = 0 , SRA = 1 , UNUSED1 , RXA = 3 , IPCR = 4 , ISR = 5 , CUR = 6 , CLR = 7 , MR0B = 8 , MR1B = 8 , MR2B = 8 , SRB = 9 , UNUSED2 , RXB = 11 , GPR = 12 , IPR = 13 , STCR = 14 , SPCR = 15 } ; enum uint8 { MR0A = 0 , CSRA = 1 , CRA = 2 , TXA = 3 , ACR = 4 , IMR = 5 , CTPU = 6 , CTPL = 7 , MR0B = 8 , CSRB = 9 , CRB = 10 , TXB = 11 , GPR = 12 , OPCR = 13 , SOPR = 14 , ROPR = 15 } ; enum uint8 { mSR_RX_ready = 1 , mSR_RX_full = 2 , mSR_TX_ready = 4 , mSR_TX_empty = 8 , mSR_RX_overrun = 16 , mSR_RX_parity = 32 , mSR_RX_framing = 64 , mSR_RX_break = 128 , mIMR_TXA_ready = 1 , mIMR_RXA_ready = 2 , mIMR_RXA_break = 4 , mIMR_CT_ready = 8 , mIMR_TXB_ready = 16 , mIMR_RXB_ready = 32 , mIMR_RXB_break = 64 , mIMR_IP_changed = 128 , mOPR_RTSA = 1 , mOPR_RTSB = 2 , mOPR_CLKA = 4 , mOPR_CLKB = 8 , mOPR_CTLA = 16 , mOPR_CTLB = 32 , mOPR_INVA = 64 , mOPR_INVB = 128 } ; const uint8 OPCR_value = 0 << 0 + 0 << 2 + 0 << 4 ; const uint8 SOPR_value = mOPR_RTSA + mOPR_RTSB + mOPR_CLKA + mOPR_CLKB + mOPR_CTLA + mOPR_CTLB + mOPR_INVA + mOPR_INVB ; const uint8 ROPR_value = 0 ; const uint8 IMR_value = mIMR_TXA_ready + mIMR_RXA_ready + ! mIMR_RXA_break + mIMR_CT_ready + mIMR_TXB_ready + mIMR_RXB_ready + ! mIMR_RXB_break + ! mIMR_IP_changed ; const uint8 ACR_value = 0 + 7 << 4 + 0 << 7 ; const uint8 MR0_value = 0 << 0 + 0 << 1 + 0 << 2 + 0 << 3 + 2 << 4 + 0 << 6 + 1 << 7 ; const uint8 MR1_value = 3 << 0 + 0 << 2 + 2 << 3 + 0 << 5 + 1 << 6 + 0 << 7 ; const uint8 MR2_value = 7 << 0 + 0 << 4 + 0 << 5 + 0 << 6 ; const { uint8 obusz = 1 << 4 ; uint8 ibusz = 1 << 4 ; uint8 obumask = obusz - 1 ; uint8 ibumask = ibusz - 1 ; uint8 xon = 17 ; uint8 xoff = 19 ; uint8 baud_9600 = 9600 / 2400 ; uint8 baud_57k6 = 57600 / 2400 ; uint8 c_reset = 0 ; uint8 c_speed = 1 ; uint8 c_hwhsk = 2 ; uint8 c_swhsk = 3 ; uint8 c_flushin = 4 ; uint8 c_availin = 4 ; uint8 c_flushout = 5 ; uint8 c_availout = 5 ; uint8 c_reserved = 6 ; uint8 c_pinhdrctl = 7 ; uint8 c_clk_hsk = 8 ; } ; type SioData = { uint8 [ ] ibu ; uint8 [ ] obu ; uint8 ibuwi ; uint8 iburi ; uint8 obuwi ; uint8 oburi ; bool hw_handshake ; bool sw_handshake ; bool xoff_received ; bool xoff_sent ; uint8 channel ; uint8 baudrate ; uint8 clk_handshake ; } extern { SioData channel_A ; SioData channel_B ; uint8 imr_value ; uint8 opcr_value ; uint16 [ 16 ] uart_values_for_baudrate ; } ; scope SioData { uint avail_in ( SioData ¢ channel ) { return channel . ibuwi - channel . iburi ; } uint avail_out ( SioData ¢ channel ) { return obusz - ( channel . obuwi - channel . oburi ) ; } void irpt ( SioData ¢ this , uint8 SR , uint8 IO , uint8 mIMR_RX_ready , uint8 mIMR_TX_ready ) { uint8 c ; do { while ( in ( SR ) & mSR_RX_ready && this . ibuwi - this . iburi < ibusz ) ; c = in ( IO ) ; if ( this . sw_handshake && ( c == xon || c == xoff ) ) this . xoff_received = c == xoff ; else this . ibu [ ( this . ibuwi ++ ) & ibumask ] = c ; } if ( this . sw_handshake && in ( SR ) & mSR_TX_ready ) { if ( this . ibuwi - this . iburi == ibusz ) { if ( ! this . xoff_sent ) { out ( IO , xoff ) ; this . xoff_sent = true ; } } else { if ( this . xoff_sent ) { out ( IO , xon ) ; this . xoff_sent = false ; } } } do { while ( in ( SR ) & mSR_TX_ready && this . obuwi != this . oburi && ! this . xoff_received ) ; out ( IO , this . obu [ ( this . oburi ++ ) & obumask ] ) ; } if ( this . ibuwi - this . iburi == ibusz ) imr_value &= ~ mIMR_RX_ready ; else imr_value |= mIMR_RX_ready ; if ( this . obuwi == this . oburi || this . xoff_received ) imr_value &= ~ mIMR_TX_ready ; else imr_value |= mIMR_TX_ready ; out ( IMR , imr_value ) ; } void set_baudrate ( SioData ¢ this , uint8 baudrate ) { uint8 chx8 = this . channel << 3 ; uint8 i = msbit ( baudrate ) ; uint8 t = i && baudrate >> ( i - 1 ) & 1 ; uint v = uart_values_for_baudrate [ t << 3 + i ] ; this . baudrate = t ? 3 << ( i - 1 ) : i < 6 ? 1 << i : baud_9600 ; uint8 csr_mask = 0 ; if ( this . clk_handshake ) { if ( this . clk_handshake & 1 ) csr_mask |= 15 ; if ( this . clk_handshake & 2 ) csr_mask |= 240 ; } out ( chx8 + CRA , 176 ) ; out ( chx8 + MR0A , get_hi ( v ) ) ; out ( chx8 + CSRA , get_lo ( v ) | csr_mask ) ; } void set_sw_handshake ( SioData ¢ this , bool f ) { if ( this . sw_handshake != f ) { this . sw_handshake = f ; this . xoff_received = false ; this . xoff_sent = false ; } } void set_hw_handshake ( SioData ¢ this , bool f ) { uint chx8 = this . channel << 3 ; if ( this . hw_handshake != f ) { this . hw_handshake = f ; out ( chx8 + CRA , 16 ) ; out ( chx8 + MR1A , MR1_value + f << 7 ) ; out ( chx8 + MR2A , MR2_value + f << 4 ) ; } } void set_clock_handshake ( SioData ¢ this , uint8 flags ) { uint8 ch = this . channel ; uint8 chx2 = ch << 1 ; if ( this . clk_handshake != flags ) { this . clk_handshake = flags ; if ( flags & 3 ) opcr_value |= 3 << chx2 ; else opcr_value &= ~ ( 3 << chx2 ) ; out ( OPCR , opcr_value ) ; out ( SOPR , ( 1 << 0 + 1 << 2 + 1 << 6 ) << ch ) ; if ( flags & 4 ) out ( ROPR , ( 65 << ch ) ) ; this . set_baudrate ( this . baudrate ) ; } } void reset ( SioData ¢ this , bool tx , bool rx ) { uint8 CR = CRA + this . channel << 3 ; if ( rx ) { out ( CR , 32 ) ; this . xoff_sent = false ; this . ibuwi = this . iburi ; } if ( tx ) { out ( CR , 48 ) ; this . xoff_received = false ; this . oburi = this . obuwi ; } out ( CR , 64 ) ; out ( CR , 1 << 0 + 1 << 2 ) ; } void init ( SioData ¢ this , uint8 ch ) { this . channel = ch ; this . ibu := alloc uint8 [ ibusz ] ( ) ; this . obu := alloc uint8 [ obusz ] ( ) ; this . set_baudrate ( baud_57k6 ) ; uint8 chx8 = ch << 3 ; out ( chx8 + CRA , 16 ) ; out ( chx8 + MR1A , MR1_value ) ; out ( chx8 + MR2A , MR2_value ) ; this . reset ( yes , yes ) ; } } void irpt ( ) { if ( in ( ISR ) & mIMR_CT_ready ) { if ( in ( SPCR ) ) { } timer ( ) ; } channel_A . irpt ( SRA , RXA , mIMR_RXA_ready , mIMR_TXA_ready ) ; channel_B . irpt ( SRB , RXB , mIMR_RXB_ready , mIMR_TXB_ready ) ; } void setctl ( SioData ¢ channel , uint8 fu , uint value ) { di ( ) ; switch ( fu ) { case c_clk_hsk : channel . set_clock_handshake ( value ) ; break ; case c_reset : channel . reset ( yes , yes ) ; break ; case c_speed : channel . set_baudrate ( value / 24 ) ; break ; case c_hwhsk : channel . set_hw_handshake ( value != 0 ) ; break ; case c_swhsk : channel . set_sw_handshake ( value != 0 ) ; break ; case c_flushin : channel . reset ( no , yes ) ; break ; case c_flushout : channel . reset ( yes , no ) ; break ; } ei ( ) ; } uint getctl ( SioData ¢ channel , uint8 fu ) { switch ( fu ) { case c_speed : return channel . baudrate * 24 ; case c_hwhsk : return channel . hw_handshake ; case c_swhsk : return channel . sw_handshake ; case c_clk_hsk : return channel . clk_handshake ; case c_availin : return channel . avail_in ( ) ; case c_availout : return channel . avail_out ( ) ; default : return 0 ; } } uint getc ( SioData ¢ channel ) { do { until channel . avail_in ( ) ; wait ( ) ; } uint c = channel . ibu [ channel . iburi & ibumask ] ; if ( channel . iburi ++ == channel . ibuwi - ibusz ) irpt ( ) ; return c ; } void putc ( SioData ¢ channel , uint8 c ) { do { until channel . avail_out ( ) ; wait ( ) ; } channel . obu [ channel . obuwi & obumask ] = c ; if ( channel . obuwi ++ == channel . oburi ) irpt ( ) ; } uint gets ( SioData ¢ channel , uint8 [ ] ¢ bu , uint a , uint e ) { uint n = min ( e - a , channel . avail_in ( ) ) ; copy ( channel . ibu , channel . iburi & ibumask , bu , a , n ) ; channel . iburi += n ; if ( channel . iburi - n == channel . ibuwi - ibusz ) irpt ( ) ; return n ; } uint puts ( SioData ¢ channel , uint8 [ ] ¢ bu , uint a , uint e ) { uint n = min ( e - a , channel . avail_out ( ) ) ; copy ( bu , a , channel . obu , channel . obuwi & obumask , n ) ; channel . obuwi += n ; if ( channel . obuwi - n == channel . oburi ) irpt ( ) ; return n ; } uint systemtimer ( uint value ) { value = swap ( get_lo ( value ) ) / ( uint ) ( 0.5 + 256 * ( 32000000 / 7372000 ) ) + get_hi ( value ) * ( uint ) ( 0.5 + 256 / ( 32000000 / 7372000 ) * 8 ) / 8 ; out ( CTPU , get_hi ( value ) ) ; out ( CTPL , get_lo ( value ) ) ; uint foo = in ( STCR ) ; return get_lo ( value ) * get_hi ( ( uint ) ( 32000000 / 7372000 * 256 + 0.5 ) ) + get_hi ( value ) * ( uint ) ( 32000000 / 7372000 * 256 + 0.5 ) ; } void init ( ) { uart_values_for_baudrate := ( uint16 [ ] ) { ( MR0_value + 0 ) * 256 + 6 * 17 , ( MR0_value + 0 ) * 256 + 8 * 17 , ( MR0_value + 0 ) * 256 + 9 * 17 , ( MR0_value + 0 ) * 256 + 11 * 17 , ( MR0_value + 4 ) * 256 + 3 * 17 , ( MR0_value + 0 ) * 256 + 12 * 17 , ( MR0_value + 0 ) * 256 + 9 * 17 , ( MR0_value + 0 ) * 256 + 9 * 17 , ( MR0_value + 0 ) * 256 + 0 * 17 , ( MR0_value + 1 ) * 256 + 5 * 17 , ( MR0_value + 1 ) * 256 + 6 * 17 , ( MR0_value + 1 ) * 256 + 8 * 17 , ( MR0_value + 1 ) * 256 + 9 * 17 , ( MR0_value + 1 ) * 256 + 11 * 17 , ( MR0_value + 4 ) * 256 + 6 * 17 , ( MR0_value + 1 ) * 256 + 12 * 17 } ; imr_value = IMR_value ; opcr_value = OPCR_value ; if ( OPCR_value ) out ( OPCR , OPCR_value ) ; if ( SOPR_value ) out ( SOPR , SOPR_value ) ; if ( ROPR_value ) out ( ROPR , ROPR_value ) ; if ( ACR_value ) out ( ACR , ACR_value ) ; channel_A := alloc SioData ( ) ; channel_B := alloc SioData ( ) ; channel_A . init ( 0 ) ; channel_B . init ( 1 ) ; out ( IMR , IMR_value ) ; } ""