Annotation of hatari/src/acia.c, revision 1.1.1.1

1.1       root        1: /*
                      2:   Hatari - acia.c
                      3: 
                      4:   Copyright (C) 2012 by Nicolas Pomarède
                      5: 
                      6:   This file is distributed under the GNU Public License, version 2 or at
                      7:   your option any later version. Read the file gpl.txt for details.
                      8: 
                      9:   MC6850 ACIA emulation.
                     10: */
                     11: 
                     12: const char ACIA_fileid[] = "Hatari acia.c : " __DATE__ " " __TIME__;
                     13: 
                     14: 
                     15: /* 2012/09/28  [NP]    Start of the full rewrite of the MC6850 ACIA emulation, using the official      */
                     16: /*                     datasheets for maximum accuracy, as well as bit level serial transfers (start,  */
                     17: /*                     stop and parity bits).                                                          */
                     18: /* 2012/12/21  [NP]    Add accurate cycles delays when accessing an ACIA register, taking E Clock      */
                     19: /*                     into account.                                                                   */
                     20: /* 2013/04/24  [NP]    Remove INTERRUPT_ACIA_MFP used to add a 4 cycle delay when IRQ is set, as this  */
                     21: /*                     delay is now correctly handled directly in the MFP since 2013/03/01.            */
                     22: 
                     23: 
                     24: 
                     25: 
                     26: /*
                     27:   6850 ACIA (Asynchronous Communications Inferface Apdater)
                     28: 
                     29:   References :
                     30:    - MC6850 datasheet by Motorola (DS9493R4, 1985)
                     31:    - A6850 datasheet by Altera (A-DS-A6850-01, 1996) (nearly identical component)
                     32: 
                     33:   Others references :
                     34:    - MAME's 6850acia.c for RTS, CTS and DCD behaviour
                     35: 
                     36: 
                     37:   Pins :
                     38:     Vss
                     39:     RX DATA Receive Data
                     40:     RX CLK Receive Clock
                     41:     TX CLK Transmitter Clock
                     42:     RTS Request To Send
                     43:     TX DATA Transmitter Data
                     44:     IRQ Interrupt Request
                     45:     CS 0,1,2 Chip Select
                     46:     RS Register Select
                     47:     Vcc Voltage
                     48:     R/W Read/Write
                     49:     E Enable
                     50:     D0-D7 Data
                     51:     DCD Data Carrier Detect
                     52:     CTS Clear To Send
                     53: 
                     54:   Registers :
                     55:     0xfffc00 Keyboard ACIA Control (write)/Status(read)
                     56:     0xfffc02 Keyboard ACIA Data
                     57:     0xfffc04 MIDI ACIA Control (write)/Status(read)
                     58:     0xfffc06 MIDI ACIA Data
                     59: 
                     60:   Control Register (0xfffc00 write) :
                     61:     Bits 0,1 - These bits determine by which factor the transmitter and receiver
                     62:       clock will be divided. These bits also are joined with a master reset
                     63:       function. The 6850 has no separate reset line, so it must be
                     64:       accomplished though software.
                     65:         0 0    RXCLK/TXCLK without division
                     66:         0 1    RXCLK/TXCLK by 16 (MIDI)
                     67:         1 0    RXCLK/TXCLK by 64 (Keyboard)
                     68:         1 1    Master RESET
                     69:     Bits 2,3,4 - These so-called Word Select bits tell whether 7 or 8 data-bits are
                     70:       involved; whether 1 or 2 stop-bits are transferred; and the type of parity
                     71:     Bits 5,6 - These Transmitter Control bits set the RTS output pin, and allow or prevent
                     72:       an interrupt through the ACIA when the send register is emptied. Also, BREAK signals
                     73:       can be sent over the serial output by this line. A BREAK signal is nothing more than
                     74:       a long seqence of null bits
                     75:         0 0    RTS low, transmitter IRQ disabled
                     76:         0 1    RTS low, transmitter IRQ enabled
                     77:         1 0    RTS high, transmitter IRQ disabled
                     78:         1 1    RTS low, transmitter IRQ disabled, BREAK sent
                     79:     Bit 7 - The Receiver Interrupt Enable bit determines whether the receiver interrupt
                     80:       will be on. An interrupt can be caused by the DCD line chaning from low to high, or
                     81:       by the receiver data buffer filling. Besides that, an interrupt can occur from an
                     82:       OVERRUN (a received character isn't properly read from the processor).
                     83:         0 Interrupt disabled
                     84:         1 Interrupt enabled
                     85: 
                     86:   Status Register (0xfffc00 read) :
                     87:     Bit 0 - When this bit is high, the RX data register is full. The byte must be read
                     88:       before a new character is received (otherwise an OVERRUN happens)
                     89:     Bit 1 - This bit reflects the status of the TX data buffer. An empty register
                     90:       set the bit.
                     91:     Bit 2 - A low-high change in pin DCD sets bit 2. If the receiver interrupt is allowable, the IRQ
                     92:       is cancelled. The bit is cleared when the status register and the receiver register are
                     93:       read. This also cancels the IRQ. Bit 2 register remains highis the signal on the DCD pin
                     94:       is still high; Bit 2 register low if DCD becomes low.
                     95:     Bit 3 - This line shows the status of CTS. This signal cannot be altered by a mater reset,
                     96:       or by ACIA programming.
                     97:     Bit 4 - Shows 'Frame Errors'. Frame errors are when no stop-bit is recognized in receiver
                     98:       switching. It can be set with every new character.
                     99:     Bit 5 - This bit display the previously mentioned OVERRUN condition. Bit 5 is reset when the
                    100:       RX buffer is read.
                    101:     Bit 6 - This bit recognizes whether the parity of a received character is correct. The bit is
                    102:       set on an error.
                    103:     Bit 7 - This signals the state of the IRQ pins; this bit make it possible to switch several
                    104:       IRQ lines on one interrupt input. In cases where an interrupt is program-generated, bit 7
                    105:       can tell which IC cut off the interrupt.
                    106: 
                    107:   ST ACIA :
                    108:     CTS,DCD and RTS are not connected
                    109:     The keyboard ACIA addresses are 0xfffc000 and 0xfffc02.
                    110:     The MIDI ACIA addresses are 0xfffc004 and 0xfffc06.
                    111:     Default keyboard parameters are : 8-bit word, 1 stopbit, no parity, 7812.5 baud; 500KHz/64 (keyboard clock div)
                    112:     Default MIDI parameters are as above but : 31250 baud; 500KHz/16 (MIDI clock div)
                    113: 
                    114: 
                    115:   CPU cycles in the ST :
                    116:     When accessing an ACIA register, an additional delay will be added to the usual number of
                    117:     cycles for this CPU instruction. This delay is made of 2 parts (for a 68000 at 8 MHz) :
                    118:        - a fixed delay of 6 cycles.
                    119:        - a variable delay of 0 to 8 cycles to synchronise with the E Clock.
                    120: 
                    121:     Examples for some common instructions measured on a real 520 STF
                    122:     (with a0=$fffffc00 and 'n' the delay for E Clock) :
                    123:        move.b  (a0),d2 : 14 cycles = 8 + 6 + n
                    124:        move.w  (a0),d2 : 14 cycles = 8 + 6 + n
                    125:        move.l  (a0),d2 : 24 cycles = 12 + 6 + 6 + n
                    126:        movep.w (a0),d2 : 28 cycles = 16 + 6 + 6 + n
                    127:        movep.l (a0),d2 : 48 cycles = 24 + 6 + 6 + 6 + 6 + n
                    128:     (on ST, those values might be rounded to the next multiple of 4 cycles)
                    129: 
                    130:     When the ACIA's IRQ signal goes low, the resulting bit in the MFP is visible to the CPU only 4 cycles later.
                    131:     From the hardware point of view, the ACIA's irq signal is immediately propagated to the MFP,
                    132:     but the MFP will then add a 4 cycle delay before generating a 68000 interrupt.
                    133: 
                    134: */
                    135: 
                    136: /*-----------------------------------------------------------------------*/
                    137: 
                    138: 
                    139: #include "main.h"
                    140: #include "log.h"
                    141: #include "memorySnapShot.h"
                    142: #include "configuration.h"
                    143: #include "acia.h"
                    144: #include "m68000.h"
                    145: #include "cycInt.h"
                    146: #include "ioMem.h"
                    147: #include "clocks_timings.h"
                    148: #include "mfp.h"
                    149: #include "screen.h"
                    150: #include "video.h"
                    151: 
                    152: 
                    153: #define        ACIA_SR_BIT_RDRF                        0x01            /* Receive Data Register Full */
                    154: #define        ACIA_SR_BIT_TDRE                        0x02            /* Transmit Data Register Empty */
                    155: #define        ACIA_SR_BIT_DCD                         0x04            /* Data Carrier Detect */
                    156: #define        ACIA_SR_BIT_CTS                         0x08            /* Clear To Send */
                    157: #define        ACIA_SR_BIT_FE                          0x10            /* Framing Error */
                    158: #define        ACIA_SR_BIT_OVRN                        0x20            /* Receiver Overrun */
                    159: #define        ACIA_SR_BIT_PE                          0x40            /* Parity Error */
                    160: #define        ACIA_SR_BIT_IRQ                         0x80            /* IRQ */
                    161: 
                    162: #define        ACIA_CR_COUNTER_DIVIDE( CR )            ( CR & 0x03 )           /* CR1 + CR0 : 0x03 causes a master reset */
                    163: #define        ACIA_CR_WORD_SELECT( CR )               ( ( CR >> 2 ) & 0x07 )  /* CR4 + CR3 + CR2 : size, parity, stop bits */
                    164: #define        ACIA_CR_TRANSMITTER_CONTROL( CR )       ( ( CR >> 5 ) & 0x03 )  /* CR6 + CR5 : RTS + IRQ on send */
                    165: #define        ACIA_CR_RECEIVE_INTERRUPT_ENABLE( CR )  ( ( CR >> 7 ) & 0x01 )  /* CR7 : Reveive interrupt enable */
                    166: 
                    167: 
                    168: 
                    169: int    ACIA_Counter_Divide[ 3 ] = { 1 , 16 , 64 };             /* Used to divide txclock/rxclock to get the correct baud rate */
                    170: 
                    171: 
                    172: /* Data size, parity and stop bits used for the transfer depending on CR_WORD_SELECT */
                    173: enum
                    174: {
                    175:        ACIA_PARITY_NONE ,
                    176:        ACIA_PARITY_EVEN ,
                    177:        ACIA_PARITY_ODD
                    178: };
                    179: 
                    180: 
                    181: static struct {
                    182:        int     DataBits;                                               /* 7 or 8 */
                    183:        int     Parity;                                                 /* EVEN or ODD or NONE */
                    184:        int     StopBits;                                               /* 1 or 2 */
                    185: } ACIA_Serial_Params [ 8 ] = {
                    186:   { 7 , ACIA_PARITY_EVEN , 2 },
                    187:   { 7 , ACIA_PARITY_ODD ,  2 },
                    188:   { 7 , ACIA_PARITY_EVEN , 1 },
                    189:   { 7 , ACIA_PARITY_ODD ,  1 },
                    190:   { 8 , ACIA_PARITY_NONE , 2 },
                    191:   { 8 , ACIA_PARITY_NONE , 1 },
                    192:   { 8 , ACIA_PARITY_EVEN , 1 },
                    193:   { 8 , ACIA_PARITY_ODD ,  1 }
                    194: };
                    195: 
                    196: 
                    197: 
                    198: /* Possible states when handling TX/RX interrupts */
                    199: enum
                    200: {
                    201:        ACIA_STATE_IDLE = 0,
                    202:        ACIA_STATE_DATA_BIT,
                    203:        ACIA_STATE_PARITY_BIT,
                    204:        ACIA_STATE_STOP_BIT
                    205: };
                    206: 
                    207: 
                    208: ACIA_STRUCT            ACIA_Array[ ACIA_MAX_NB ];
                    209: ACIA_STRUCT            *pACIA_IKBD;
                    210: ACIA_STRUCT            *pACIA_MIDI;
                    211: 
                    212: 
                    213: 
                    214: 
                    215: /*--------------------------------------------------------------*/
                    216: /* Local functions prototypes                                  */
                    217: /*--------------------------------------------------------------*/
                    218: 
                    219: static void            ACIA_Init_Pointers ( ACIA_STRUCT *pAllACIA );
                    220: 
                    221: static void            ACIA_Set_Line_IRQ_MFP ( int bit );
                    222: static Uint8           ACIA_Get_Line_CTS_Dummy ( void );
                    223: static Uint8           ACIA_Get_Line_DCD_Dummy ( void );
                    224: static void            ACIA_Set_Line_RTS_Dummy ( int bit );
                    225: 
                    226: static void            ACIA_Set_Timers_IKBD ( void *pACIA );
                    227: static void            ACIA_Start_InterruptHandler_IKBD ( ACIA_STRUCT *pACIA , int InternalCycleOffset );
                    228: 
                    229: static Uint8           ACIA_MasterReset ( ACIA_STRUCT *pACIA , Uint8 CR );
                    230: 
                    231: static void            ACIA_UpdateIRQ ( ACIA_STRUCT *pACIA );
                    232: 
                    233: static Uint8           ACIA_Read_SR ( ACIA_STRUCT *pACIA );
                    234: static void            ACIA_Write_CR ( ACIA_STRUCT *pACIA , Uint8 CR );
                    235: static Uint8           ACIA_Read_RDR ( ACIA_STRUCT *pACIA );
                    236: static void            ACIA_Write_TDR ( ACIA_STRUCT *pACIA , Uint8 TDR );
                    237: 
                    238: static void            ACIA_Prepare_TX ( ACIA_STRUCT *pACIA );
                    239: static void            ACIA_Prepare_RX ( ACIA_STRUCT *pACIA );
                    240: static void            ACIA_Clock_TX ( ACIA_STRUCT *pACIA );
                    241: static void            ACIA_Clock_RX ( ACIA_STRUCT *pACIA );
                    242: 
                    243: 
                    244: 
                    245: 
                    246: 
                    247: /*-----------------------------------------------------------------------*/
                    248: /**
                    249:  * Init the 2 ACIAs in an Atari ST.
                    250:  * Both ACIAs have a 500 MHZ TX/RX clock.
                    251:  * This is called only once, when the emulator starts.
                    252:  * NOTE : when testing EmuTos on real hardware, it seems the tx/rx is working
                    253:  * after a cold reset (ST switched on), even if Clock_Divider was not initialized yet.
                    254:  * The default behaviour is not described in the ACIA's ref doc, but bits
                    255:  * seem to be transmitted (maybe with errors ?). So we default
                    256:  * to 9600 bauds to avoid a lock if a program uses tx/rx after a reset.
                    257:  */
                    258: void   ACIA_Init ( ACIA_STRUCT *pAllACIA , Uint32 TX_Clock , Uint32 RX_Clock )
                    259: {
                    260:        int     i;
                    261: 
                    262: 
                    263:        LOG_TRACE ( TRACE_ACIA, "acia init tx_clock=%d rx_clock=%d\n" , TX_Clock , RX_Clock );
                    264: 
                    265:        for ( i=0 ; i<ACIA_MAX_NB ; i++ )
                    266:        {
                    267:                memset ( (void *)&(pAllACIA[ i ]) , 0 , sizeof ( ACIA_STRUCT) );
                    268: 
                    269:                pAllACIA[ i ].TX_Clock = TX_Clock;
                    270:                pAllACIA[ i ].RX_Clock = RX_Clock;
                    271:                pAllACIA[ i ].Clock_Divider = 0;                /* Divider not initialized yet */
                    272:                pAllACIA[ i ].FirstMasterReset = 1;
                    273:        }
                    274: 
                    275:        /* Set the default common callback functions + other pointers */
                    276:        ACIA_Init_Pointers ( pAllACIA );
                    277: }
                    278: 
                    279: 
                    280: 
                    281: /*-----------------------------------------------------------------------*/
                    282: /**
                    283:  * Init some functions/memory pointers for each ACIA.
                    284:  * This is called at Init and when restoring a memory snapshot.
                    285:  */
                    286: static void    ACIA_Init_Pointers ( ACIA_STRUCT *pAllACIA )
                    287: {
                    288:        int     i;
                    289: 
                    290: 
                    291:        for ( i=0 ; i<ACIA_MAX_NB ; i++ )
                    292:        {
                    293:                /* Set the default common callback functions */
                    294:                pAllACIA[ i ].Set_Line_IRQ = ACIA_Set_Line_IRQ_MFP;
                    295:                pAllACIA[ i ].Get_Line_CTS = ACIA_Get_Line_CTS_Dummy;
                    296:                pAllACIA[ i ].Get_Line_DCD = ACIA_Get_Line_DCD_Dummy;
                    297:                pAllACIA[ i ].Set_Line_RTS = ACIA_Set_Line_RTS_Dummy;
                    298:        }
                    299: 
                    300:        strcpy ( pAllACIA[ 0 ].ACIA_Name , "ikbd" );
                    301:        strcpy ( pAllACIA[ 1 ].ACIA_Name , "midi" );
                    302: 
                    303:        pACIA_IKBD = &(pAllACIA[ 0 ]);
                    304:        pACIA_MIDI = &(pAllACIA[ 1 ]);
                    305: 
                    306:        pACIA_IKBD->Set_Timers = ACIA_Set_Timers_IKBD;
                    307: //     pACIA_MIDI->Set_Timers = ACIA_Set_Timers_MIDI;                  /* Not used for now */
                    308: }
                    309: 
                    310: 
                    311: 
                    312: 
                    313: /*-----------------------------------------------------------------------*/
                    314: /**
                    315:  * There's no real hardware reset on the ACIA, but as the Reset_ST()
                    316:  * functions turns off all internal interrupts, we must restart the ACIA's
                    317:  * interrupt after a reset.
                    318:  */
                    319: void   ACIA_Reset ( ACIA_STRUCT *pAllACIA )
                    320: {
                    321:        int     i;
                    322: 
                    323: 
                    324:        LOG_TRACE ( TRACE_ACIA, "acia reset\n" );
                    325: 
                    326:        for ( i=0 ; i<ACIA_MAX_NB ; i++ )
                    327:        {
                    328:                if ( pAllACIA[ i ].Clock_Divider > 0 )                          /* Divider already initialized */
                    329:                        pAllACIA[ i ].Set_Timers ( &(pAllACIA[ i ]) );          /* Restart the timer */
                    330:        }
                    331: }
                    332: 
                    333: 
                    334: 
                    335: /*-----------------------------------------------------------------------*/
                    336: /**
                    337:  * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
                    338:  */
                    339: void   ACIA_MemorySnapShot_Capture ( bool bSave )
                    340: {
                    341:        MemorySnapShot_Store(&ACIA_Array, sizeof(ACIA_Array));
                    342: 
                    343:        if ( !bSave )                                           /* If restoring */
                    344:                ACIA_Init_Pointers ( ACIA_Array );              /* Restore pointers */
                    345: }
                    346: 
                    347: 
                    348: 
                    349: 
                    350: /*-----------------------------------------------------------------------*/
                    351: /**
                    352:  * Set or reset the ACIA's IRQ signal.
                    353:  * IRQ signal is inverted (0/low sets irq, 1/high resets irq)
                    354:  * In the ST, the 2 ACIA's IRQ pins are connected to the same MFP pin,
                    355:  * so they share the same IRQ bit in the MFP.
                    356:  */
                    357: static void    ACIA_Set_Line_IRQ_MFP ( int bit )
                    358: {
                    359:        LOG_TRACE ( TRACE_ACIA, "acia set irq line val=%d VBL=%d HBL=%d\n" , bit , nVBLs , nHBL );
                    360: 
                    361:        if ( bit == 0 )
                    362:        {
                    363:                /* There's a small delay on a real ST between the point in time
                    364:                * the irq bit is set and the MFP interrupt is triggered - for example
                    365:                * the "V8 music system" demo depends on this behaviour.
                    366:                * This 4 cycle delay is handled in mfp.c */
                    367: 
                    368:                MFP_GPIP &= ~0x10;                              /* set IRQ signal for GPIP P4 */
                    369:                MFP_InputOnChannel ( MFP_INT_ACIA , 0 );
                    370:        }
                    371:        else
                    372:        {
                    373:                /* GPIP I4 - General Purpose Pin Keyboard/MIDI interrupt */
                    374:                MFP_GPIP |= 0x10;                               /* IRQ bit was reset */
                    375:        }
                    376: }
                    377: 
                    378: 
                    379: 
                    380: 
                    381: /*-----------------------------------------------------------------------*/
                    382: /**
                    383:  * Read the Clear To Send (CTS) pin
                    384:  * When CTS is high, TDRE should always be set to 0
                    385:  * Note : this is not connected on an ST, so we always return 0.
                    386:  */
                    387: static Uint8   ACIA_Get_Line_CTS_Dummy ( void )
                    388: {
                    389:        Uint8           bit;
                    390: 
                    391:        bit = 0;
                    392:        LOG_TRACE ( TRACE_ACIA, "acia get cts=%d VBL=%d HBL=%d\n" , bit , nVBLs , nHBL );
                    393:        return bit;
                    394: }
                    395: 
                    396: /*-----------------------------------------------------------------------*/
                    397: /**
                    398:  * Read the Data Carrier Detect (DCD) pin
                    399:  * Note : this is not connected on an ST, so we always return 0.
                    400:  */
                    401: static Uint8   ACIA_Get_Line_DCD_Dummy ( void )
                    402: {
                    403:        Uint8           bit;
                    404: 
                    405:        bit = 0;
                    406:        LOG_TRACE ( TRACE_ACIA, "acia get dcd=%d VBL=%d HBL=%d\n" , bit , nVBLs , nHBL );
                    407:        return bit;
                    408: }
                    409: 
                    410: /*-----------------------------------------------------------------------*/
                    411: /**
                    412:  * Set the Request To Send (RTS) pin.
                    413:  * Note : this is not connected on an ST, so we ignore it.
                    414:  */
                    415: static void    ACIA_Set_Line_RTS_Dummy ( int bit )
                    416: {
                    417:        LOG_TRACE ( TRACE_ACIA, "acia set rts val=%d VBL=%d HBL=%d\n" , bit , nVBLs , nHBL );
                    418: }
                    419: 
                    420: 
                    421: 
                    422: 
                    423: /*-----------------------------------------------------------------------*/
                    424: /**
                    425:  * Set the required timers to handle RX / TX, depending on the CR_DIVIDE
                    426:  * value.
                    427:  * When CR is changed with a new CR_DIVIDE value, we restart the timers.
                    428:  */
                    429: static void    ACIA_Set_Timers_IKBD ( void *pACIA )
                    430: {
                    431:        ACIA_Start_InterruptHandler_IKBD ( (ACIA_STRUCT *)pACIA , 0 );
                    432: }
                    433: 
                    434: 
                    435: 
                    436: 
                    437: /*-----------------------------------------------------------------------*/
                    438: /**
                    439:  * Set a timer to handle the RX / TX bits at the expected baud rate.
                    440:  * NOTE : on ST, TX_Clock and RX_Clock are the same, so the timer's freq will be
                    441:  * TX_Clock / Divider and we only need one timer interrupt to handle both RX and TX.
                    442:  * This freq should be converted to CPU_CYCLE : 1 ACIA cycle = 16 CPU cycles
                    443:  * (with cpu running at 8 MHz)
                    444:  * InternalCycleOffset allows to compensate for a != 0 value in PendingInterruptCount
                    445:  * to keep a constant baud rate.
                    446:  * TODO : we use a fixed 8 MHz clock and nCpuFreqShift to convert cycles for our
                    447:  * internal timers in cycInt.c. This should be replaced some days by using
                    448:  * MachineClocks.CPU_Freq and not using nCpuFreqShift anymore.
                    449:  */
                    450: static void    ACIA_Start_InterruptHandler_IKBD ( ACIA_STRUCT *pACIA , int InternalCycleOffset )
                    451: {
                    452:        int             Cycles;
                    453: 
                    454: 
                    455: //     Cycles = MachineClocks.CPU_Freq / pACIA->TX_Clock;              /* Convert ACIA cycles in CPU cycles */
                    456:        Cycles = 8021247 / pACIA->TX_Clock;                             /* Convert ACIA cycles in CPU cycles, for a 8 MHz STF reference */
                    457:        Cycles *= pACIA->Clock_Divider;
                    458:        Cycles <<= nCpuFreqShift;                                       /* Compensate for x2 or x4 cpu speed */
                    459: 
                    460:        LOG_TRACE ( TRACE_ACIA, "acia %s start timer divider=%d cpu_cycles=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name ,
                    461:                pACIA->Clock_Divider , Cycles , nVBLs , nHBL );
                    462: 
                    463:        CycInt_AddRelativeInterruptWithOffset ( Cycles, INT_CPU_CYCLE, INTERRUPT_ACIA_IKBD , InternalCycleOffset );
                    464: }
                    465: 
                    466: 
                    467: 
                    468: 
                    469: /*-----------------------------------------------------------------------*/
                    470: /**
                    471:  * Interrupt called each time a new bit must be sent / received with the IKBD.
                    472:  * This interrupt will be called at freq ( 500 MHz / ACIA_CR_COUNTER_DIVIDE )
                    473:  * On ST, RX_Clock = TX_Clock = 500 MHz.
                    474:  * We continuously restart the interrupt, taking into account PendingCyclesOver.
                    475:  */
                    476: void   ACIA_InterruptHandler_IKBD ( void )
                    477: {
                    478:        int     PendingCyclesOver;
                    479: 
                    480: 
                    481:        /* Number of internal cycles we went over for this timer ( <= 0 ) */
                    482:        /* Used to restart the next timer and keep a constant baud rate */
                    483:        PendingCyclesOver = -PendingInterruptCount;                     /* >= 0 */
                    484: 
                    485:        LOG_TRACE ( TRACE_ACIA, "acia ikbd interrupt handler pending_cyc=%d VBL=%d HBL=%d\n" , PendingCyclesOver , nVBLs , nHBL );
                    486: 
                    487:        /* Remove this interrupt from list and re-order */
                    488:        CycInt_AcknowledgeInterrupt();
                    489: 
                    490:        ACIA_Clock_TX ( pACIA_IKBD );
                    491:        ACIA_Clock_RX ( pACIA_IKBD );
                    492: 
                    493:        ACIA_Start_InterruptHandler_IKBD ( pACIA_IKBD , -PendingCyclesOver );   /* Compensate for a != 0 value of PendingCyclesOver */
                    494: }
                    495: 
                    496: 
                    497: 
                    498: 
                    499: /*-----------------------------------------------------------------------*/
                    500: /**
                    501:  * Interrupt called each time a new bit must be sent / received with the MIDI.
                    502:  * This interrupt will be called at freq ( 500 MHz / ACIA_CR_COUNTER_DIVIDE )
                    503:  * On ST, RX_Clock = TX_Clock = 500 MHz.
                    504:  */
                    505: void   ACIA_InterruptHandler_MIDI ( void )
                    506: {
                    507:        ACIA_Clock_TX ( pACIA_MIDI );
                    508:        ACIA_Clock_RX ( pACIA_MIDI );
                    509: }
                    510: 
                    511: 
                    512: 
                    513: 
                    514: /*-----------------------------------------------------------------------*/
                    515: /**
                    516:  * - For each access to an ACIA register, a 6 cycles delay is added to the
                    517:  *   normal 68000 timing for the current CPU instruction. If the instruction
                    518:  *   accesses several registers at once, the delays are cumulated.
                    519:  * - An additional delay will also be added to ensure the 68000 clock and
                    520:  *   the E clock are synchronised ; this delay can add between 0 and 8 cycles
                    521:  *   to reach the next multiple of 10 cycles. This delay is added only once
                    522:  *   per CPU instruction.
                    523:  * These delays are measured for an 8 MHz 68000 CPU.
                    524:  */
                    525: void   ACIA_AddWaitCycles ( void )
                    526: {
                    527:        int     cycles;
                    528: 
                    529:        /* Add a default of 6 cycles for each access */
                    530:        cycles = 6;
                    531: 
                    532:        /* Wait for E clock only if this is the first ACIA access for this instruction */
                    533:        /* (NOTE : in UAE, movep behaves like several bytes access with different IoAccessBaseAddress, */
                    534:        /* so only the first movep's access should wait for E Clock) */
                    535:        if ( ( ( MovepByteNbr == 0 ) && ( IoAccessBaseAddress == IoAccessCurrentAddress ) )
                    536:          || ( MovepByteNbr == 1 ) )                                    /* First access of a movep */
                    537:                cycles += M68000_WaitEClock ();
                    538:        
                    539:        M68000_WaitState ( cycles );
                    540: }
                    541: 
                    542: 
                    543: 
                    544: /*-----------------------------------------------------------------------*/
                    545: /**
                    546:  * Return SR for the IKBD's ACIA (0xfffc00)
                    547:  */
                    548: void   ACIA_IKBD_Read_SR ( void )
                    549: {
                    550:        ACIA_AddWaitCycles ();                                          /* Additional cycles when accessing the ACIA */
                    551: 
                    552:        IoMem[0xfffc00] = ACIA_Read_SR ( pACIA_IKBD );
                    553: 
                    554:        if (LOG_TRACE_LEVEL(TRACE_ACIA))
                    555:        {
                    556:                int FrameCycles, HblCounterVideo, LineCycles;
                    557:                Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    558:                LOG_TRACE_PRINT("acia %s read fffc00 sr=0x%02x video_cyc=%d %d@%d pc=%x instr_cycle %d\n", pACIA_IKBD->ACIA_Name ,
                    559:                                IoMem[0xfffc00], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
                    560:        }
                    561: }
                    562: 
                    563: 
                    564: 
                    565: 
                    566: /*-----------------------------------------------------------------------*/
                    567: /**
                    568:  * Return RDR for the IKBD's ACIA (0xfffc02) : receive a byte from the IKBD
                    569:  */
                    570: void   ACIA_IKBD_Read_RDR ( void )
                    571: {
                    572:        ACIA_AddWaitCycles ();                                          /* Additional cycles when accessing the ACIA */
                    573: 
                    574:        IoMem[0xfffc02] = ACIA_Read_RDR ( pACIA_IKBD );
                    575: 
                    576:        if (LOG_TRACE_LEVEL(TRACE_IKBD_ACIA))
                    577:        {
                    578:                int FrameCycles, HblCounterVideo, LineCycles;
                    579:                Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    580:                LOG_TRACE_PRINT("acia %s read fffc02 rdr=0x%02x video_cyc=%d %d@%d pc=%x instr_cycle %d\n", pACIA_IKBD->ACIA_Name ,
                    581:                                IoMem[0xfffc02], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
                    582:        }
                    583: }
                    584: 
                    585: 
                    586: 
                    587: 
                    588: /*-----------------------------------------------------------------------*/
                    589: /**
                    590:  * Write to CR in the IKBD's ACIA (0xfffc00)
                    591:  */
                    592: void   ACIA_IKBD_Write_CR ( void )
                    593: {
                    594:        int FrameCycles, HblCounterVideo, LineCycles;
                    595: 
                    596:        ACIA_AddWaitCycles ();                                          /* Additional cycles when accessing the ACIA */
                    597: 
                    598:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    599:        LOG_TRACE(TRACE_IKBD_ACIA, "acia %s write fffc00 cr=0x%02x video_cyc=%d %d@%d pc=%x instr_cycle %d\n", pACIA_IKBD->ACIA_Name ,
                    600:                                IoMem[0xfffc00], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
                    601: 
                    602:        ACIA_Write_CR ( pACIA_IKBD , IoMem[0xfffc00] );
                    603: }
                    604: 
                    605: 
                    606: 
                    607: 
                    608: /*-----------------------------------------------------------------------*/
                    609: /**
                    610:  * Write to TDR in the IKBD's ACIA (0xfffc02) : send a byte to the IKBD
                    611:  */
                    612: void   ACIA_IKBD_Write_TDR ( void )
                    613: {
                    614:        int FrameCycles, HblCounterVideo, LineCycles;
                    615: 
                    616:        ACIA_AddWaitCycles ();                                          /* Additional cycles when accessing the ACIA */
                    617: 
                    618:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    619:        LOG_TRACE(TRACE_IKBD_ACIA, "acia %s write fffc02 tdr=0x%02x video_cyc=%d %d@%d pc=%x instr_cycle %d\n", pACIA_IKBD->ACIA_Name ,
                    620:                                IoMem[0xfffc02], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
                    621: 
                    622:        ACIA_Write_TDR ( pACIA_IKBD , IoMem[0xfffc02] );
                    623: }
                    624: 
                    625: 
                    626: 
                    627: 
                    628: /*----------------------------------------------------------------------*/
                    629: /* The part below is the real core of the 6850's emulation.            */
                    630: /*                                                                     */
                    631: /* This core is not correlated to any specific machine. All the specific*/
                    632: /* code between the 6850 and the rest of Hatari is called through some */
                    633: /* callback functions (see above).                                     */
                    634: /*----------------------------------------------------------------------*/
                    635: 
                    636: 
                    637: 
                    638: /*-----------------------------------------------------------------------*/
                    639: /**
                    640:  * Reset an ACIA.
                    641:  * There's no RESET pin on the MC6850, so the only way to reset the ACIA
                    642:  * is to set bit 0 an 1 to 0x03 in the CR to force a master reset.
                    643:  * This will clear SR (except CTS and DCD) and halt/initialize both the
                    644:  * receiver and transmitter.
                    645:  * This also returns the new state of the RTS bit, that must be updated
                    646:  * in ACIA_Write_CR.
                    647:  */
                    648: static Uint8   ACIA_MasterReset ( ACIA_STRUCT *pACIA , Uint8 CR )
                    649: {
                    650:        Uint8           dcd_bit;
                    651:        Uint8           cts_bit;
                    652:        Uint8           rts_bit;
                    653: 
                    654: 
                    655:        LOG_TRACE ( TRACE_ACIA, "acia %s master reset VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
                    656:        
                    657:        dcd_bit = pACIA->Get_Line_DCD ();
                    658:        cts_bit = pACIA->Get_Line_CTS ();
                    659: 
                    660:        pACIA->SR = ACIA_SR_BIT_TDRE | ( dcd_bit << 2 ) | ( cts_bit << 3 );
                    661: 
                    662:        pACIA->TX_State = ACIA_STATE_IDLE;
                    663:        pACIA->TSR = 0;
                    664:        pACIA->TX_Size = 0;
                    665:        pACIA->TX_SendBrk = 0;
                    666: 
                    667:        pACIA->RX_State = ACIA_STATE_IDLE;
                    668:        pACIA->RSR = 0;
                    669:        pACIA->RX_Size = 0;
                    670:        pACIA->RX_Overrun = 0;
                    671: 
                    672:        /* On Master Reset, IRQ line is high */
                    673:        /* If it's the 1st reset, RTS should be high, else RTS depends on CR bit 5 and 6 */
                    674:        pACIA->Set_Line_IRQ ( 1 );                                      /* IRQ line goes high */
                    675:        if ( pACIA->FirstMasterReset == 1 )
                    676:        {
                    677:                pACIA->FirstMasterReset = 0;
                    678:                rts_bit = 1;                                            /* RTS line goes high */
                    679:        }
                    680:        else
                    681:                rts_bit = ( ACIA_CR_TRANSMITTER_CONTROL ( CR ) == 0x02 ) ? 1 : 0;
                    682: 
                    683:        return rts_bit;
                    684: }
                    685: 
                    686: 
                    687: 
                    688: 
                    689: /*-----------------------------------------------------------------------*/
                    690: /**
                    691:  * Check if the IRQ must be changed in SR.
                    692:  * When there's a change, we must change the IRQ line too.
                    693:  */
                    694: static void    ACIA_UpdateIRQ ( ACIA_STRUCT *pACIA )
                    695: {
                    696:        Uint8           irq_bit_new;
                    697: 
                    698:        irq_bit_new = 0;
                    699: 
                    700:        if ( ACIA_CR_RECEIVE_INTERRUPT_ENABLE ( pACIA->CR )             /* Check for RX causes of interrupt */
                    701:          && ( ( pACIA->SR & ( ACIA_SR_BIT_RDRF | ACIA_SR_BIT_DCD ) )
                    702:            || ( pACIA->RX_Overrun ) ) )
                    703:          irq_bit_new = ACIA_SR_BIT_IRQ;
                    704: 
                    705:        if ( pACIA->TX_EnableInt                                        /* Check for TX causes of interrupt */
                    706:          && ( pACIA->SR & ACIA_SR_BIT_TDRE )
                    707:          && ( ( pACIA->SR & ACIA_SR_BIT_CTS ) == 0 ) )
                    708:          irq_bit_new = ACIA_SR_BIT_IRQ;
                    709:        
                    710:        /* Update SR and IRQ line if a change happened */
                    711:        if ( ( pACIA->SR & ACIA_SR_BIT_IRQ ) != irq_bit_new )
                    712:        {
                    713:                LOG_TRACE ( TRACE_ACIA, "acia %s update irq irq_new=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name , irq_bit_new?1:0 , nVBLs , nHBL );
                    714: 
                    715:                if ( irq_bit_new )
                    716:                {
                    717:                        pACIA->SR |= ACIA_SR_BIT_IRQ;                   /* Set IRQ bit */
                    718:                        pACIA->Set_Line_IRQ ( 0 );                      /* IRQ line goes low */
                    719:                }
                    720:                else
                    721:                {
                    722:                        pACIA->SR &= ~ACIA_SR_BIT_IRQ;                  /* Clear IRQ bit */
                    723:                        pACIA->Set_Line_IRQ ( 1 );                      /* IRQ line goes high */
                    724:                }
                    725:        }
                    726: }
                    727: 
                    728: 
                    729: 
                    730: /*-----------------------------------------------------------------------*/
                    731: /**
                    732:  * Read SR.
                    733:  * Also update CTS ; when CTS is high, TDRE should always be masked to 0.
                    734:  */
                    735: static Uint8   ACIA_Read_SR ( ACIA_STRUCT *pACIA )
                    736: {
                    737:        Uint8   SR;
                    738: 
                    739: 
                    740:        if ( pACIA->Get_Line_CTS() == 1 )
                    741:                pACIA->SR |= ACIA_SR_BIT_CTS;
                    742:        else
                    743:                pACIA->SR &= ~ACIA_SR_BIT_CTS;
                    744: 
                    745:        SR = pACIA->SR;
                    746:        pACIA->SR_Read = 1;                                             /* Used in ACIA_Read_RDR to clear Overrun and DCD IRQ */
                    747: 
                    748:        if ( SR & ACIA_SR_BIT_CTS )
                    749:                SR &= ~ACIA_SR_BIT_TDRE;                                /* Inhibit TDRE when CTS is set */
                    750: 
                    751:        LOG_TRACE ( TRACE_ACIA, "acia %s read sr data=0x%02x VBL=%d HBL=%d\n" , pACIA->ACIA_Name , SR , nVBLs , nHBL );
                    752: 
                    753:        return SR;
                    754: }
                    755: 
                    756: 
                    757: 
                    758: 
                    759: /*-----------------------------------------------------------------------*/
                    760: /**
                    761:  * Write to CR.
                    762:  */
                    763: static void    ACIA_Write_CR ( ACIA_STRUCT *pACIA , Uint8 CR )
                    764: {
                    765:        int     Divide;
                    766:        int     Force_rts_bit;
                    767:        Uint8   rts_bit=0;
                    768: 
                    769:        LOG_TRACE ( TRACE_ACIA, "acia %s write cr data=0x%02x VBL=%d HBL=%d\n" , pACIA->ACIA_Name , CR , nVBLs , nHBL );
                    770: 
                    771:        /* Bit 0 and 1 : Counter Divide */
                    772:        Divide = ACIA_CR_COUNTER_DIVIDE ( CR );
                    773:        if ( Divide == 0x03 )
                    774:        {
                    775:                Force_rts_bit = ACIA_MasterReset ( pACIA , CR );        /* Special behaviour for RTS after a master reset */
                    776:        }
                    777:        else
                    778:        {
                    779:                if ( ACIA_CR_COUNTER_DIVIDE ( CR ) != ACIA_CR_COUNTER_DIVIDE ( pACIA->CR ) )
                    780:                {
                    781:                        pACIA->Clock_Divider = ACIA_Counter_Divide[ Divide ];
                    782:                        pACIA->Set_Timers ( pACIA );                    /* Set a timer at the baud rate computed from Clock_Divider */
                    783:                }
                    784:                Force_rts_bit = -1;                                     /* Don't force RTS bit, use bit 5/6 in CR */
                    785:        }
                    786: 
                    787:        /* Bits 2, 3 and 4 : word select */
                    788:        /* Don't do anything here, see ACIA_Prepare_TX and ACIA_Prepare_RX */
                    789: 
                    790:        /* Bits 5 and 6 : transmitter control */
                    791:        pACIA->TX_EnableInt = 0;
                    792:        pACIA->TX_SendBrk = 0;
                    793:        switch ( ACIA_CR_TRANSMITTER_CONTROL ( CR ) )
                    794:        {
                    795:          case 0x00 :
                    796:                rts_bit = 0;
                    797:                break;
                    798:          case 0x01 :
                    799:                rts_bit = 0;
                    800:                pACIA->TX_EnableInt = 1;
                    801:                break;
                    802:          case 0x02 :
                    803:                rts_bit = 1;
                    804:                break;
                    805:          case 0x03 :
                    806:                rts_bit = 0;
                    807:                pACIA->TX_SendBrk = 1;                                  /* We will send break bit until CR is changed */
                    808:                break;
                    809:        }
                    810: 
                    811:        if ( Force_rts_bit >= 0 )
                    812:                rts_bit = Force_rts_bit;                                /* Use the value from ACIA_MasterReset */
                    813:        pACIA->Set_Line_RTS ( rts_bit );
                    814: 
                    815:        /* Bits 7 : receive interrupt enable, see ACIA_UpdateIRQ */
                    816: 
                    817:        pACIA->CR = CR;
                    818: 
                    819:        ACIA_UpdateIRQ ( pACIA );
                    820: }
                    821: 
                    822: 
                    823: 
                    824: 
                    825: /*-----------------------------------------------------------------------*/
                    826: /**
                    827:  * Read RDR. This will clear RDRF and PE.
                    828:  * - OVRN / DCD bits are cleared if SR was read before reading RDR.
                    829:  * - OVRN bit is set only when reading RDR, not when the actual overrun happened
                    830:  *   during ACIA_Clock_RX.
                    831:  * - IRQ bit should be updated depending on the new values of BIT_RDRF,
                    832:  *   BIT_DCD and BIT_OVRN.
                    833:  */
                    834: static Uint8   ACIA_Read_RDR ( ACIA_STRUCT *pACIA )
                    835: {
                    836:        pACIA->SR &= ~( ACIA_SR_BIT_RDRF | ACIA_SR_BIT_PE );
                    837: 
                    838:        /* If we read RDR after reading SR, we clear OVRN / DCD bits */
                    839:        if ( pACIA->SR_Read == 1 )
                    840:        {
                    841:                pACIA->SR_Read = 0;
                    842:                pACIA->SR &= ~( ACIA_SR_BIT_DCD | ACIA_SR_BIT_OVRN );
                    843:                if ( pACIA->Get_Line_DCD () == 1 )
                    844:                        pACIA->SR |= ACIA_SR_BIT_DCD;
                    845:        }
                    846: 
                    847:        if ( pACIA->RX_Overrun )
                    848:        {  
                    849:                pACIA->SR |= ACIA_SR_BIT_OVRN;
                    850:                pACIA->RX_Overrun = 0;
                    851:        }
                    852: 
                    853:        ACIA_UpdateIRQ ( pACIA );
                    854: 
                    855:        LOG_TRACE ( TRACE_ACIA, "acia %s read rdr data=0x%02x new sr=0x%02x overrun=%s VBL=%d HBL=%d\n" , pACIA->ACIA_Name , pACIA->RDR ,
                    856:                pACIA->SR , ( pACIA->SR & ACIA_SR_BIT_OVRN ) ? "yes" : "no" , nVBLs , nHBL );
                    857: 
                    858:        return pACIA->RDR;
                    859: }
                    860: 
                    861: 
                    862: 
                    863: 
                    864: /*-----------------------------------------------------------------------*/
                    865: /**
                    866:  * Write to TDR.
                    867:  * If the TX process is idle, we should not prepare a new transfer
                    868:  * immediately, to ensure that BIT_TDRE remains clear until the next bit
                    869:  * is sent (BIT_TDRE will be set again in ACIA_Clock_TX).
                    870:  */
                    871: static void    ACIA_Write_TDR ( ACIA_STRUCT *pACIA , Uint8 TDR )
                    872: {
                    873:        LOG_TRACE ( TRACE_ACIA, "acia %s write tdr data=0x%02x overwrite=%s tx_state=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name , TDR ,
                    874:                ( pACIA->SR & ACIA_SR_BIT_TDRE ) ? "no" : "yes" , pACIA->TX_State , nVBLs , nHBL );
                    875: 
                    876:        pACIA->TDR = TDR;
                    877:        pACIA->SR &= ~ACIA_SR_BIT_TDRE;                                 /* TDR is not empty anymore */
                    878: 
                    879:        ACIA_UpdateIRQ ( pACIA );
                    880: }
                    881: 
                    882: 
                    883: 
                    884: 
                    885: /*-----------------------------------------------------------------------*/
                    886: /**
                    887:  * Prepare a new transfer. Copy TDR to TSR and initialize parity, data size
                    888:  * and stop bits.
                    889:  * Transfer will then start at the next call of ACIA_Clock_TX
                    890:  */
                    891: static void    ACIA_Prepare_TX ( ACIA_STRUCT *pACIA )
                    892: {
                    893:        pACIA->TSR = pACIA->TDR;
                    894:        pACIA->TX_Parity = 0;
                    895:        pACIA->TX_Size = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].DataBits;
                    896:        pACIA->TX_StopBits = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].StopBits;
                    897: 
                    898:        pACIA->SR |= ACIA_SR_BIT_TDRE;                                  /* TDR was copied to TSR. TDR is now empty */
                    899: 
                    900:        LOG_TRACE ( TRACE_ACIA, "acia %s prepare tx tsr=0x%02x size=%d stop=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name , pACIA->TSR ,
                    901:                pACIA->TX_Size , pACIA->TX_StopBits , nVBLs , nHBL );
                    902: }
                    903: 
                    904: 
                    905: 
                    906: 
                    907: /*-----------------------------------------------------------------------*/
                    908: /**
                    909:  * Prepare a new reception. Initialize parity, data size and stop bits.
                    910:  */
                    911: static void    ACIA_Prepare_RX ( ACIA_STRUCT *pACIA )
                    912: {
                    913:        pACIA->RSR = 0;
                    914:        pACIA->RX_Parity = 0;
                    915:        pACIA->RX_Size = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].DataBits;
                    916:        pACIA->RX_StopBits = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].StopBits;
                    917: 
                    918:        LOG_TRACE ( TRACE_ACIA, "acia %s prepare rx size=%d stop=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name ,
                    919:                pACIA->RX_Size , pACIA->RX_StopBits , nVBLs , nHBL );
                    920: }
                    921: 
                    922: 
                    923: 
                    924: 
                    925: /*-----------------------------------------------------------------------*/
                    926: /**
                    927:  * Write a new bit on the TX line each time the TX clock expires.
                    928:  * This will send TDR over the serial line, using TSR, with additional
                    929:  * parity and start/stop bits.
                    930:  * We send bit 0 of TSR, then TSR is shifted to the right.
                    931:  */
                    932: static void    ACIA_Clock_TX ( ACIA_STRUCT *pACIA )
                    933: {
                    934:        int     StateNext;
                    935:        Uint8   tx_bit;
                    936: 
                    937: 
                    938:        LOG_TRACE ( TRACE_ACIA, "acia %s clock_tx tx_state=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name , pACIA->TX_State , nVBLs , nHBL );
                    939: 
                    940:        StateNext = -1;
                    941:        switch ( pACIA->TX_State )
                    942:        {
                    943:          case ACIA_STATE_IDLE :
                    944:                if ( pACIA->TX_SendBrk )
                    945:                {
                    946:                        pACIA->Set_Line_TX ( 0 );                       /* Send 1 break bit */
                    947:                        break;
                    948:                }
                    949: 
                    950:                /* If TDR is not empty when we are in idle state, */
                    951:                /* this means we have a new byte to send */
                    952:                if ( ( pACIA->SR & ACIA_SR_BIT_TDRE ) == 0 )
                    953:                        ACIA_Prepare_TX ( pACIA );
                    954: 
                    955:                if ( pACIA->TX_Size == 0 )                              /* TSR is empty */
                    956:                        pACIA->Set_Line_TX ( 1 );                       /* Send stop bits when idle */
                    957: 
                    958:                else                                                    /* TSR has some new bits to transfer */
                    959:                {
                    960:                        pACIA->Set_Line_TX ( 0 );                       /* Send 1 start bit */
                    961:                        StateNext = ACIA_STATE_DATA_BIT;
                    962:                }
                    963:                break;
                    964: 
                    965:          case ACIA_STATE_DATA_BIT :
                    966:                tx_bit = pACIA->TSR & 1;                                /* New bit to send */
                    967:                pACIA->Set_Line_TX ( tx_bit );
                    968:                pACIA->TX_Parity ^= tx_bit;
                    969:                pACIA->TSR >>= 1;
                    970:                pACIA->TX_Size--;
                    971: 
                    972:                if ( pACIA->TX_Size == 0 )
                    973:                {
                    974:                        if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity != ACIA_PARITY_NONE )
                    975:                                StateNext = ACIA_STATE_PARITY_BIT;
                    976:                        else
                    977:                                StateNext = ACIA_STATE_STOP_BIT;        /* No parity */
                    978:                }
                    979:                break;
                    980: 
                    981:          case ACIA_STATE_PARITY_BIT :
                    982:                if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity == ACIA_PARITY_EVEN )
                    983:                        pACIA->Set_Line_TX ( pACIA->TX_Parity );
                    984:                else
                    985:                        pACIA->Set_Line_TX ( ( ~pACIA->TX_Parity ) & 1 );
                    986: 
                    987:                StateNext = ACIA_STATE_STOP_BIT;
                    988:                break;
                    989: 
                    990:          case ACIA_STATE_STOP_BIT :
                    991:                pACIA->Set_Line_TX ( 1 );                               /* Send 1 stop bit */
                    992:                pACIA->TX_StopBits--;
                    993: 
                    994:                if ( pACIA->TX_StopBits == 0 )                          /* All stop bits were sent : transfer is complete */
                    995:                {
                    996:                        StateNext = ACIA_STATE_IDLE;                    /* Go to idle state to see if a new TDR need to be sent */
                    997:                }
                    998:                break;
                    999:        }
                   1000: 
                   1001:        ACIA_UpdateIRQ ( pACIA );
                   1002: 
                   1003:        if ( StateNext >= 0 )
                   1004:                pACIA->TX_State = StateNext;                            /* Go to a new state */
                   1005: }
                   1006: 
                   1007: 
                   1008: 
                   1009: 
                   1010: /*-----------------------------------------------------------------------*/
                   1011: /**
                   1012:  * Handle a new bit on the RX line each time the RX clock expires.
                   1013:  * This will fill RDR with bits received from the serial line, using RSR.
                   1014:  * Incoming bits are stored in bit 7 of RSR, then RSR is shifted to the right.
                   1015:  */
                   1016: static void    ACIA_Clock_RX ( ACIA_STRUCT *pACIA )
                   1017: {
                   1018:        int     StateNext;
                   1019:        Uint8   rx_bit;
                   1020: 
                   1021: 
                   1022:        rx_bit = pACIA->Get_Line_RX();
                   1023: 
                   1024:        LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx rx_state=%d bit=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name , pACIA->RX_State , rx_bit , nVBLs , nHBL );
                   1025: 
                   1026:        StateNext = -1;
                   1027:        switch ( pACIA->RX_State )
                   1028:        {
                   1029:          case ACIA_STATE_IDLE :
                   1030:                if ( rx_bit == 0 )                                      /* Receive 1 start bit */
                   1031:                {
                   1032:                        ACIA_Prepare_RX ( pACIA );
                   1033:                        StateNext = ACIA_STATE_DATA_BIT;
                   1034:                }
                   1035:                break;                                                  /* If no start bit, we stay in idle state */
                   1036: 
                   1037:          case ACIA_STATE_DATA_BIT :
                   1038:                if ( rx_bit )
                   1039:                        pACIA->RSR |= 0x80;
                   1040:                pACIA->RX_Parity ^= rx_bit;
                   1041:                pACIA->RX_Size--;
                   1042: 
                   1043:                if ( pACIA->RX_Size > 0 )                               /* All bits were not received yet */
                   1044:                {
                   1045:                        pACIA->RSR >>= 1;
                   1046:                }
                   1047:                else
                   1048:                {
                   1049: // [NP] : MC6850 doc is not very clear "the overrun condition begins at the midpoint of the last bit
                   1050: // of the second character received [...]". Is it the last bit of the data word, or the stop bit ?
                   1051: // It makes more sense to check for overrun after the stop bit, when RSR should be copied to RDR,
                   1052: // because RDR could be read between the last data bit and the stop bit, so RX_Overrun and
                   1053: // ACIA_SR_BIT_OVRN would need to be cancelled.
                   1054: //                     if ( pACIA->SR & ACIA_SR_BIT_RDRF )
                   1055: //                     {
                   1056: //                             LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx overrun rsr=0x%02x VBL=%d HBL=%d\n" ,
                   1057: //                                     pACIA->ACIA_Name , pACIA->RSR , nVBLs , nHBL );
                   1058: //                             pACIA->RX_Overrun = 1;                  /* Bit in SR will be set when reading RDR */
                   1059: //                     }
                   1060:                        if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity != ACIA_PARITY_NONE )
                   1061:                                StateNext = ACIA_STATE_PARITY_BIT;
                   1062:                        else
                   1063:                                StateNext = ACIA_STATE_STOP_BIT;        /* No parity */
                   1064:                }
                   1065:                break;
                   1066: 
                   1067:          case ACIA_STATE_PARITY_BIT :
                   1068:                if ( ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity == ACIA_PARITY_EVEN )
                   1069:                    && ( pACIA->RX_Parity != rx_bit ) )
                   1070:                        pACIA->SR |= ACIA_SR_BIT_PE;
                   1071: 
                   1072:                else if ( pACIA->RX_Parity == rx_bit )                  /* Odd parity */
                   1073:                        pACIA->SR |= ACIA_SR_BIT_PE;
                   1074: 
                   1075:                if ( pACIA->SR & ACIA_SR_BIT_PE )
                   1076:                        LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx parity error VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
                   1077: 
                   1078:                StateNext = ACIA_STATE_STOP_BIT;
                   1079:                break;
                   1080: 
                   1081:          case ACIA_STATE_STOP_BIT :
                   1082:                if ( rx_bit == 1 )                                      /* Wait for 1 or 2 "1" stop bits */
                   1083:                {
                   1084:                        pACIA->RX_StopBits--;
                   1085:                        if ( pACIA->RX_StopBits == 0 )                  /* All stop bits were received : reception is complete */
                   1086:                        {
                   1087:                                pACIA->SR &= ~ACIA_SR_BIT_FE;
                   1088:                                
                   1089:                                if ( ( pACIA->SR & ACIA_SR_BIT_RDRF ) == 0 )
                   1090:                                {
                   1091:                                        pACIA->RDR = pACIA->RSR;
                   1092:                                        pACIA->SR |= ACIA_SR_BIT_RDRF;
                   1093:                                        LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx received rdr=0x%02x VBL=%d HBL=%d\n" ,
                   1094:                                                pACIA->ACIA_Name , pACIA->RDR , nVBLs , nHBL );
                   1095:                                }
                   1096:                                else
                   1097:                                {
                   1098:                                        LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx overrun rsr=0x%02x unread rdr=0x%02x VBL=%d HBL=%d\n" ,
                   1099:                                                pACIA->ACIA_Name , pACIA->RSR , pACIA->RDR , nVBLs , nHBL );
                   1100:                                        pACIA->RX_Overrun = 1;          /* Bit in SR will be set when reading RDR */
                   1101:                                }
                   1102:                                StateNext = ACIA_STATE_IDLE;            /* Go to idle state and wait for start bit */
                   1103:                        }
                   1104:                }
                   1105:                else                                                    /* Not a valid stop bit */
                   1106:                {
                   1107:                        LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx framing error VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
                   1108: 
                   1109:                        /* According to the A6850 doc, RSR is copied to RDR in case of a framing error */
                   1110:                        /* (Should be the same for the MC6850 ?) */
                   1111:                        pACIA->SR |= ACIA_SR_BIT_FE;
                   1112:                        pACIA->RDR = pACIA->RSR;
                   1113:                        StateNext = ACIA_STATE_IDLE;                    /* Go to idle state and wait for start bit */
                   1114:                }
                   1115:                break;
                   1116:        }
                   1117: 
                   1118:        ACIA_UpdateIRQ ( pACIA );
                   1119: 
                   1120:        if ( StateNext >= 0 )
                   1121:                pACIA->RX_State = StateNext;                            /* Go to a new state */
                   1122: }
                   1123: 
                   1124: 
                   1125: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.