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

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 */
1.1.1.2   root      165: #define        ACIA_CR_RECEIVE_INTERRUPT_ENABLE( CR )  ( ( CR >> 7 ) & 0x01 )  /* CR7 : Receive interrupt enable */
1.1       root      166: 
                    167: 
1.1.1.3 ! root      168: static const int ACIA_Counter_Divide[3] = { 1 , 16 , 64 };     /* Used to divide txclock/rxclock to get the correct baud rate */
1.1       root      169: 
                    170: 
                    171: /* Data size, parity and stop bits used for the transfer depending on CR_WORD_SELECT */
                    172: enum
                    173: {
                    174:        ACIA_PARITY_NONE ,
                    175:        ACIA_PARITY_EVEN ,
                    176:        ACIA_PARITY_ODD
                    177: };
                    178: 
                    179: 
                    180: static struct {
                    181:        int     DataBits;                                               /* 7 or 8 */
                    182:        int     Parity;                                                 /* EVEN or ODD or NONE */
                    183:        int     StopBits;                                               /* 1 or 2 */
                    184: } ACIA_Serial_Params [ 8 ] = {
                    185:   { 7 , ACIA_PARITY_EVEN , 2 },
                    186:   { 7 , ACIA_PARITY_ODD ,  2 },
                    187:   { 7 , ACIA_PARITY_EVEN , 1 },
                    188:   { 7 , ACIA_PARITY_ODD ,  1 },
                    189:   { 8 , ACIA_PARITY_NONE , 2 },
                    190:   { 8 , ACIA_PARITY_NONE , 1 },
                    191:   { 8 , ACIA_PARITY_EVEN , 1 },
                    192:   { 8 , ACIA_PARITY_ODD ,  1 }
                    193: };
                    194: 
                    195: 
                    196: 
                    197: /* Possible states when handling TX/RX interrupts */
                    198: enum
                    199: {
                    200:        ACIA_STATE_IDLE = 0,
                    201:        ACIA_STATE_DATA_BIT,
                    202:        ACIA_STATE_PARITY_BIT,
                    203:        ACIA_STATE_STOP_BIT
                    204: };
                    205: 
                    206: 
                    207: ACIA_STRUCT            ACIA_Array[ ACIA_MAX_NB ];
                    208: ACIA_STRUCT            *pACIA_IKBD;
                    209: ACIA_STRUCT            *pACIA_MIDI;
                    210: 
                    211: 
                    212: 
                    213: 
                    214: /*--------------------------------------------------------------*/
                    215: /* Local functions prototypes                                  */
                    216: /*--------------------------------------------------------------*/
                    217: 
                    218: static void            ACIA_Init_Pointers ( ACIA_STRUCT *pAllACIA );
                    219: 
                    220: static void            ACIA_Set_Line_IRQ_MFP ( int bit );
                    221: static Uint8           ACIA_Get_Line_CTS_Dummy ( void );
                    222: static Uint8           ACIA_Get_Line_DCD_Dummy ( void );
                    223: static void            ACIA_Set_Line_RTS_Dummy ( int bit );
                    224: 
                    225: static void            ACIA_Set_Timers_IKBD ( void *pACIA );
                    226: static void            ACIA_Start_InterruptHandler_IKBD ( ACIA_STRUCT *pACIA , int InternalCycleOffset );
                    227: 
                    228: static Uint8           ACIA_MasterReset ( ACIA_STRUCT *pACIA , Uint8 CR );
                    229: 
                    230: static void            ACIA_UpdateIRQ ( ACIA_STRUCT *pACIA );
                    231: 
                    232: static Uint8           ACIA_Read_SR ( ACIA_STRUCT *pACIA );
                    233: static void            ACIA_Write_CR ( ACIA_STRUCT *pACIA , Uint8 CR );
                    234: static Uint8           ACIA_Read_RDR ( ACIA_STRUCT *pACIA );
                    235: static void            ACIA_Write_TDR ( ACIA_STRUCT *pACIA , Uint8 TDR );
                    236: 
                    237: static void            ACIA_Prepare_TX ( ACIA_STRUCT *pACIA );
                    238: static void            ACIA_Prepare_RX ( ACIA_STRUCT *pACIA );
                    239: static void            ACIA_Clock_TX ( ACIA_STRUCT *pACIA );
                    240: static void            ACIA_Clock_RX ( ACIA_STRUCT *pACIA );
                    241: 
                    242: 
                    243: 
                    244: 
                    245: 
                    246: /*-----------------------------------------------------------------------*/
                    247: /**
                    248:  * Init the 2 ACIAs in an Atari ST.
                    249:  * Both ACIAs have a 500 MHZ TX/RX clock.
                    250:  * This is called only once, when the emulator starts.
                    251:  * NOTE : when testing EmuTos on real hardware, it seems the tx/rx is working
                    252:  * after a cold reset (ST switched on), even if Clock_Divider was not initialized yet.
                    253:  * The default behaviour is not described in the ACIA's ref doc, but bits
                    254:  * seem to be transmitted (maybe with errors ?). So we default
                    255:  * to 9600 bauds to avoid a lock if a program uses tx/rx after a reset.
                    256:  */
                    257: void   ACIA_Init ( ACIA_STRUCT *pAllACIA , Uint32 TX_Clock , Uint32 RX_Clock )
                    258: {
                    259:        int     i;
                    260: 
                    261: 
                    262:        LOG_TRACE ( TRACE_ACIA, "acia init tx_clock=%d rx_clock=%d\n" , TX_Clock , RX_Clock );
                    263: 
                    264:        for ( i=0 ; i<ACIA_MAX_NB ; i++ )
                    265:        {
                    266:                memset ( (void *)&(pAllACIA[ i ]) , 0 , sizeof ( ACIA_STRUCT) );
                    267: 
                    268:                pAllACIA[ i ].TX_Clock = TX_Clock;
                    269:                pAllACIA[ i ].RX_Clock = RX_Clock;
                    270:                pAllACIA[ i ].Clock_Divider = 0;                /* Divider not initialized yet */
                    271:                pAllACIA[ i ].FirstMasterReset = 1;
                    272:        }
                    273: 
                    274:        /* Set the default common callback functions + other pointers */
                    275:        ACIA_Init_Pointers ( pAllACIA );
                    276: }
                    277: 
                    278: 
                    279: 
                    280: /*-----------------------------------------------------------------------*/
                    281: /**
                    282:  * Init some functions/memory pointers for each ACIA.
                    283:  * This is called at Init and when restoring a memory snapshot.
                    284:  */
                    285: static void    ACIA_Init_Pointers ( ACIA_STRUCT *pAllACIA )
                    286: {
                    287:        int     i;
                    288: 
                    289: 
                    290:        for ( i=0 ; i<ACIA_MAX_NB ; i++ )
                    291:        {
                    292:                /* Set the default common callback functions */
                    293:                pAllACIA[ i ].Set_Line_IRQ = ACIA_Set_Line_IRQ_MFP;
                    294:                pAllACIA[ i ].Get_Line_CTS = ACIA_Get_Line_CTS_Dummy;
                    295:                pAllACIA[ i ].Get_Line_DCD = ACIA_Get_Line_DCD_Dummy;
                    296:                pAllACIA[ i ].Set_Line_RTS = ACIA_Set_Line_RTS_Dummy;
                    297:        }
                    298: 
                    299:        strcpy ( pAllACIA[ 0 ].ACIA_Name , "ikbd" );
                    300:        strcpy ( pAllACIA[ 1 ].ACIA_Name , "midi" );
                    301: 
                    302:        pACIA_IKBD = &(pAllACIA[ 0 ]);
                    303:        pACIA_MIDI = &(pAllACIA[ 1 ]);
                    304: 
                    305:        pACIA_IKBD->Set_Timers = ACIA_Set_Timers_IKBD;
                    306: //     pACIA_MIDI->Set_Timers = ACIA_Set_Timers_MIDI;                  /* Not used for now */
                    307: }
                    308: 
                    309: 
                    310: 
                    311: 
                    312: /*-----------------------------------------------------------------------*/
                    313: /**
                    314:  * There's no real hardware reset on the ACIA, but as the Reset_ST()
                    315:  * functions turns off all internal interrupts, we must restart the ACIA's
                    316:  * interrupt after a reset.
                    317:  */
                    318: void   ACIA_Reset ( ACIA_STRUCT *pAllACIA )
                    319: {
                    320:        int     i;
                    321: 
                    322: 
                    323:        LOG_TRACE ( TRACE_ACIA, "acia reset\n" );
                    324: 
                    325:        for ( i=0 ; i<ACIA_MAX_NB ; i++ )
                    326:        {
                    327:                if ( pAllACIA[ i ].Clock_Divider > 0 )                          /* Divider already initialized */
                    328:                        pAllACIA[ i ].Set_Timers ( &(pAllACIA[ i ]) );          /* Restart the timer */
                    329:        }
                    330: }
                    331: 
                    332: 
                    333: 
                    334: /*-----------------------------------------------------------------------*/
                    335: /**
                    336:  * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
                    337:  */
                    338: void   ACIA_MemorySnapShot_Capture ( bool bSave )
                    339: {
                    340:        MemorySnapShot_Store(&ACIA_Array, sizeof(ACIA_Array));
                    341: 
                    342:        if ( !bSave )                                           /* If restoring */
                    343:                ACIA_Init_Pointers ( ACIA_Array );              /* Restore pointers */
                    344: }
                    345: 
                    346: 
                    347: 
                    348: 
                    349: /*-----------------------------------------------------------------------*/
                    350: /**
                    351:  * Set or reset the ACIA's IRQ signal.
                    352:  * IRQ signal is inverted (0/low sets irq, 1/high resets irq)
1.1.1.3 ! root      353:  * In the ST, the 2 ACIA's IRQ pins are connected to the same MFP input,
        !           354:  * so they share the same IRQ bit in GPIP4.
1.1       root      355:  */
                    356: static void    ACIA_Set_Line_IRQ_MFP ( int bit )
                    357: {
                    358:        LOG_TRACE ( TRACE_ACIA, "acia set irq line val=%d VBL=%d HBL=%d\n" , bit , nVBLs , nHBL );
                    359: 
                    360:        if ( bit == 0 )
                    361:        {
                    362:                /* There's a small delay on a real ST between the point in time
                    363:                * the irq bit is set and the MFP interrupt is triggered - for example
                    364:                * the "V8 music system" demo depends on this behaviour.
                    365:                * This 4 cycle delay is handled in mfp.c */
1.1.1.3 ! root      366:                MFP_GPIP_Set_Line_Input ( MFP_GPIP_LINE_ACIA , MFP_GPIP_STATE_LOW );
1.1       root      367:        }
                    368:        else
                    369:        {
1.1.1.3 ! root      370:                MFP_GPIP_Set_Line_Input ( MFP_GPIP_LINE_ACIA , MFP_GPIP_STATE_HIGH );
1.1       root      371:        }
                    372: }
                    373: 
                    374: 
                    375: 
                    376: 
                    377: /*-----------------------------------------------------------------------*/
                    378: /**
                    379:  * Read the Clear To Send (CTS) pin
                    380:  * When CTS is high, TDRE should always be set to 0
                    381:  * Note : this is not connected on an ST, so we always return 0.
                    382:  */
                    383: static Uint8   ACIA_Get_Line_CTS_Dummy ( void )
                    384: {
                    385:        Uint8           bit;
                    386: 
                    387:        bit = 0;
                    388:        LOG_TRACE ( TRACE_ACIA, "acia get cts=%d VBL=%d HBL=%d\n" , bit , nVBLs , nHBL );
                    389:        return bit;
                    390: }
                    391: 
                    392: /*-----------------------------------------------------------------------*/
                    393: /**
                    394:  * Read the Data Carrier Detect (DCD) pin
                    395:  * Note : this is not connected on an ST, so we always return 0.
                    396:  */
                    397: static Uint8   ACIA_Get_Line_DCD_Dummy ( void )
                    398: {
                    399:        Uint8           bit;
                    400: 
                    401:        bit = 0;
                    402:        LOG_TRACE ( TRACE_ACIA, "acia get dcd=%d VBL=%d HBL=%d\n" , bit , nVBLs , nHBL );
                    403:        return bit;
                    404: }
                    405: 
                    406: /*-----------------------------------------------------------------------*/
                    407: /**
                    408:  * Set the Request To Send (RTS) pin.
                    409:  * Note : this is not connected on an ST, so we ignore it.
                    410:  */
                    411: static void    ACIA_Set_Line_RTS_Dummy ( int bit )
                    412: {
                    413:        LOG_TRACE ( TRACE_ACIA, "acia set rts val=%d VBL=%d HBL=%d\n" , bit , nVBLs , nHBL );
                    414: }
                    415: 
                    416: 
                    417: 
                    418: 
                    419: /*-----------------------------------------------------------------------*/
                    420: /**
                    421:  * Set the required timers to handle RX / TX, depending on the CR_DIVIDE
                    422:  * value.
                    423:  * When CR is changed with a new CR_DIVIDE value, we restart the timers.
                    424:  */
                    425: static void    ACIA_Set_Timers_IKBD ( void *pACIA )
                    426: {
                    427:        ACIA_Start_InterruptHandler_IKBD ( (ACIA_STRUCT *)pACIA , 0 );
                    428: }
                    429: 
                    430: 
                    431: 
                    432: 
                    433: /*-----------------------------------------------------------------------*/
                    434: /**
                    435:  * Set a timer to handle the RX / TX bits at the expected baud rate.
                    436:  * NOTE : on ST, TX_Clock and RX_Clock are the same, so the timer's freq will be
                    437:  * TX_Clock / Divider and we only need one timer interrupt to handle both RX and TX.
                    438:  * This freq should be converted to CPU_CYCLE : 1 ACIA cycle = 16 CPU cycles
                    439:  * (with cpu running at 8 MHz)
                    440:  * InternalCycleOffset allows to compensate for a != 0 value in PendingInterruptCount
                    441:  * to keep a constant baud rate.
                    442:  * TODO : we use a fixed 8 MHz clock and nCpuFreqShift to convert cycles for our
                    443:  * internal timers in cycInt.c. This should be replaced some days by using
                    444:  * MachineClocks.CPU_Freq and not using nCpuFreqShift anymore.
                    445:  */
                    446: static void    ACIA_Start_InterruptHandler_IKBD ( ACIA_STRUCT *pACIA , int InternalCycleOffset )
                    447: {
                    448:        int             Cycles;
                    449: 
                    450: 
                    451: //     Cycles = MachineClocks.CPU_Freq / pACIA->TX_Clock;              /* Convert ACIA cycles in CPU cycles */
                    452:        Cycles = 8021247 / pACIA->TX_Clock;                             /* Convert ACIA cycles in CPU cycles, for a 8 MHz STF reference */
                    453:        Cycles *= pACIA->Clock_Divider;
                    454:        Cycles <<= nCpuFreqShift;                                       /* Compensate for x2 or x4 cpu speed */
                    455: 
                    456:        LOG_TRACE ( TRACE_ACIA, "acia %s start timer divider=%d cpu_cycles=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name ,
                    457:                pACIA->Clock_Divider , Cycles , nVBLs , nHBL );
                    458: 
                    459:        CycInt_AddRelativeInterruptWithOffset ( Cycles, INT_CPU_CYCLE, INTERRUPT_ACIA_IKBD , InternalCycleOffset );
                    460: }
                    461: 
                    462: 
                    463: 
                    464: 
                    465: /*-----------------------------------------------------------------------*/
                    466: /**
                    467:  * Interrupt called each time a new bit must be sent / received with the IKBD.
                    468:  * This interrupt will be called at freq ( 500 MHz / ACIA_CR_COUNTER_DIVIDE )
                    469:  * On ST, RX_Clock = TX_Clock = 500 MHz.
                    470:  * We continuously restart the interrupt, taking into account PendingCyclesOver.
                    471:  */
                    472: void   ACIA_InterruptHandler_IKBD ( void )
                    473: {
                    474:        int     PendingCyclesOver;
                    475: 
                    476: 
                    477:        /* Number of internal cycles we went over for this timer ( <= 0 ) */
                    478:        /* Used to restart the next timer and keep a constant baud rate */
                    479:        PendingCyclesOver = -PendingInterruptCount;                     /* >= 0 */
                    480: 
                    481:        LOG_TRACE ( TRACE_ACIA, "acia ikbd interrupt handler pending_cyc=%d VBL=%d HBL=%d\n" , PendingCyclesOver , nVBLs , nHBL );
                    482: 
                    483:        /* Remove this interrupt from list and re-order */
                    484:        CycInt_AcknowledgeInterrupt();
                    485: 
                    486:        ACIA_Clock_TX ( pACIA_IKBD );
                    487:        ACIA_Clock_RX ( pACIA_IKBD );
                    488: 
                    489:        ACIA_Start_InterruptHandler_IKBD ( pACIA_IKBD , -PendingCyclesOver );   /* Compensate for a != 0 value of PendingCyclesOver */
                    490: }
                    491: 
                    492: 
                    493: 
                    494: 
                    495: /*-----------------------------------------------------------------------*/
                    496: /**
                    497:  * Interrupt called each time a new bit must be sent / received with the MIDI.
                    498:  * This interrupt will be called at freq ( 500 MHz / ACIA_CR_COUNTER_DIVIDE )
                    499:  * On ST, RX_Clock = TX_Clock = 500 MHz.
                    500:  */
                    501: void   ACIA_InterruptHandler_MIDI ( void )
                    502: {
                    503:        ACIA_Clock_TX ( pACIA_MIDI );
                    504:        ACIA_Clock_RX ( pACIA_MIDI );
                    505: }
                    506: 
                    507: 
                    508: 
                    509: 
                    510: /*-----------------------------------------------------------------------*/
                    511: /**
                    512:  * - For each access to an ACIA register, a 6 cycles delay is added to the
                    513:  *   normal 68000 timing for the current CPU instruction. If the instruction
                    514:  *   accesses several registers at once, the delays are cumulated.
                    515:  * - An additional delay will also be added to ensure the 68000 clock and
                    516:  *   the E clock are synchronised ; this delay can add between 0 and 8 cycles
                    517:  *   to reach the next multiple of 10 cycles. This delay is added only once
                    518:  *   per CPU instruction.
                    519:  * These delays are measured for an 8 MHz 68000 CPU.
                    520:  */
                    521: void   ACIA_AddWaitCycles ( void )
                    522: {
                    523:        int     cycles;
                    524: 
                    525:        /* Add a default of 6 cycles for each access */
                    526:        cycles = 6;
                    527: 
                    528:        /* Wait for E clock only if this is the first ACIA access for this instruction */
                    529:        /* (NOTE : in UAE, movep behaves like several bytes access with different IoAccessBaseAddress, */
                    530:        /* so only the first movep's access should wait for E Clock) */
                    531:        if ( ( ( MovepByteNbr == 0 ) && ( IoAccessBaseAddress == IoAccessCurrentAddress ) )
                    532:          || ( MovepByteNbr == 1 ) )                                    /* First access of a movep */
                    533:                cycles += M68000_WaitEClock ();
                    534:        
                    535:        M68000_WaitState ( cycles );
                    536: }
                    537: 
                    538: 
                    539: 
                    540: /*-----------------------------------------------------------------------*/
                    541: /**
                    542:  * Return SR for the IKBD's ACIA (0xfffc00)
                    543:  */
                    544: void   ACIA_IKBD_Read_SR ( void )
                    545: {
                    546:        ACIA_AddWaitCycles ();                                          /* Additional cycles when accessing the ACIA */
                    547: 
                    548:        IoMem[0xfffc00] = ACIA_Read_SR ( pACIA_IKBD );
                    549: 
                    550:        if (LOG_TRACE_LEVEL(TRACE_ACIA))
                    551:        {
                    552:                int FrameCycles, HblCounterVideo, LineCycles;
                    553:                Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    554:                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 ,
                    555:                                IoMem[0xfffc00], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
                    556:        }
                    557: }
                    558: 
                    559: 
                    560: 
                    561: 
                    562: /*-----------------------------------------------------------------------*/
                    563: /**
                    564:  * Return RDR for the IKBD's ACIA (0xfffc02) : receive a byte from the IKBD
                    565:  */
                    566: void   ACIA_IKBD_Read_RDR ( void )
                    567: {
                    568:        ACIA_AddWaitCycles ();                                          /* Additional cycles when accessing the ACIA */
                    569: 
                    570:        IoMem[0xfffc02] = ACIA_Read_RDR ( pACIA_IKBD );
                    571: 
                    572:        if (LOG_TRACE_LEVEL(TRACE_IKBD_ACIA))
                    573:        {
                    574:                int FrameCycles, HblCounterVideo, LineCycles;
                    575:                Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    576:                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 ,
                    577:                                IoMem[0xfffc02], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
                    578:        }
                    579: }
                    580: 
                    581: 
                    582: 
                    583: 
                    584: /*-----------------------------------------------------------------------*/
                    585: /**
                    586:  * Write to CR in the IKBD's ACIA (0xfffc00)
                    587:  */
                    588: void   ACIA_IKBD_Write_CR ( void )
                    589: {
                    590:        int FrameCycles, HblCounterVideo, LineCycles;
                    591: 
                    592:        ACIA_AddWaitCycles ();                                          /* Additional cycles when accessing the ACIA */
                    593: 
                    594:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    595:        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 ,
                    596:                                IoMem[0xfffc00], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
                    597: 
                    598:        ACIA_Write_CR ( pACIA_IKBD , IoMem[0xfffc00] );
                    599: }
                    600: 
                    601: 
                    602: 
                    603: 
                    604: /*-----------------------------------------------------------------------*/
                    605: /**
                    606:  * Write to TDR in the IKBD's ACIA (0xfffc02) : send a byte to the IKBD
                    607:  */
                    608: void   ACIA_IKBD_Write_TDR ( void )
                    609: {
                    610:        int FrameCycles, HblCounterVideo, LineCycles;
                    611: 
                    612:        ACIA_AddWaitCycles ();                                          /* Additional cycles when accessing the ACIA */
                    613: 
                    614:        Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
                    615:        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 ,
                    616:                                IoMem[0xfffc02], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
                    617: 
                    618:        ACIA_Write_TDR ( pACIA_IKBD , IoMem[0xfffc02] );
                    619: }
                    620: 
                    621: 
                    622: 
                    623: 
                    624: /*----------------------------------------------------------------------*/
                    625: /* The part below is the real core of the 6850's emulation.            */
                    626: /*                                                                     */
                    627: /* This core is not correlated to any specific machine. All the specific*/
                    628: /* code between the 6850 and the rest of Hatari is called through some */
                    629: /* callback functions (see above).                                     */
                    630: /*----------------------------------------------------------------------*/
                    631: 
                    632: 
                    633: 
                    634: /*-----------------------------------------------------------------------*/
                    635: /**
                    636:  * Reset an ACIA.
                    637:  * There's no RESET pin on the MC6850, so the only way to reset the ACIA
                    638:  * is to set bit 0 an 1 to 0x03 in the CR to force a master reset.
                    639:  * This will clear SR (except CTS and DCD) and halt/initialize both the
                    640:  * receiver and transmitter.
                    641:  * This also returns the new state of the RTS bit, that must be updated
                    642:  * in ACIA_Write_CR.
                    643:  */
                    644: static Uint8   ACIA_MasterReset ( ACIA_STRUCT *pACIA , Uint8 CR )
                    645: {
                    646:        Uint8           dcd_bit;
                    647:        Uint8           cts_bit;
                    648:        Uint8           rts_bit;
                    649: 
                    650: 
                    651:        LOG_TRACE ( TRACE_ACIA, "acia %s master reset VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
                    652:        
                    653:        dcd_bit = pACIA->Get_Line_DCD ();
                    654:        cts_bit = pACIA->Get_Line_CTS ();
                    655: 
                    656:        pACIA->SR = ACIA_SR_BIT_TDRE | ( dcd_bit << 2 ) | ( cts_bit << 3 );
                    657: 
                    658:        pACIA->TX_State = ACIA_STATE_IDLE;
                    659:        pACIA->TSR = 0;
                    660:        pACIA->TX_Size = 0;
                    661:        pACIA->TX_SendBrk = 0;
                    662: 
                    663:        pACIA->RX_State = ACIA_STATE_IDLE;
                    664:        pACIA->RSR = 0;
                    665:        pACIA->RX_Size = 0;
                    666:        pACIA->RX_Overrun = 0;
                    667: 
                    668:        /* On Master Reset, IRQ line is high */
                    669:        /* If it's the 1st reset, RTS should be high, else RTS depends on CR bit 5 and 6 */
                    670:        pACIA->Set_Line_IRQ ( 1 );                                      /* IRQ line goes high */
                    671:        if ( pACIA->FirstMasterReset == 1 )
                    672:        {
                    673:                pACIA->FirstMasterReset = 0;
                    674:                rts_bit = 1;                                            /* RTS line goes high */
                    675:        }
                    676:        else
                    677:                rts_bit = ( ACIA_CR_TRANSMITTER_CONTROL ( CR ) == 0x02 ) ? 1 : 0;
                    678: 
                    679:        return rts_bit;
                    680: }
                    681: 
                    682: 
                    683: 
                    684: 
                    685: /*-----------------------------------------------------------------------*/
                    686: /**
                    687:  * Check if the IRQ must be changed in SR.
                    688:  * When there's a change, we must change the IRQ line too.
                    689:  */
                    690: static void    ACIA_UpdateIRQ ( ACIA_STRUCT *pACIA )
                    691: {
                    692:        Uint8           irq_bit_new;
                    693: 
                    694:        irq_bit_new = 0;
                    695: 
                    696:        if ( ACIA_CR_RECEIVE_INTERRUPT_ENABLE ( pACIA->CR )             /* Check for RX causes of interrupt */
                    697:          && ( ( pACIA->SR & ( ACIA_SR_BIT_RDRF | ACIA_SR_BIT_DCD ) )
                    698:            || ( pACIA->RX_Overrun ) ) )
                    699:          irq_bit_new = ACIA_SR_BIT_IRQ;
1.1.1.2   root      700: //fprintf(stderr , "acia irq %x %x %x %d\n" , pACIA->CR , pACIA->SR , pACIA->RX_Overrun , irq_bit_new);
1.1       root      701: 
                    702:        if ( pACIA->TX_EnableInt                                        /* Check for TX causes of interrupt */
                    703:          && ( pACIA->SR & ACIA_SR_BIT_TDRE )
                    704:          && ( ( pACIA->SR & ACIA_SR_BIT_CTS ) == 0 ) )
                    705:          irq_bit_new = ACIA_SR_BIT_IRQ;
                    706:        
                    707:        /* Update SR and IRQ line if a change happened */
                    708:        if ( ( pACIA->SR & ACIA_SR_BIT_IRQ ) != irq_bit_new )
                    709:        {
                    710:                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 );
                    711: 
                    712:                if ( irq_bit_new )
                    713:                {
                    714:                        pACIA->SR |= ACIA_SR_BIT_IRQ;                   /* Set IRQ bit */
                    715:                        pACIA->Set_Line_IRQ ( 0 );                      /* IRQ line goes low */
                    716:                }
                    717:                else
                    718:                {
                    719:                        pACIA->SR &= ~ACIA_SR_BIT_IRQ;                  /* Clear IRQ bit */
                    720:                        pACIA->Set_Line_IRQ ( 1 );                      /* IRQ line goes high */
                    721:                }
                    722:        }
                    723: }
                    724: 
                    725: 
                    726: 
                    727: /*-----------------------------------------------------------------------*/
                    728: /**
                    729:  * Read SR.
                    730:  * Also update CTS ; when CTS is high, TDRE should always be masked to 0.
                    731:  */
                    732: static Uint8   ACIA_Read_SR ( ACIA_STRUCT *pACIA )
                    733: {
                    734:        Uint8   SR;
                    735: 
                    736: 
                    737:        if ( pACIA->Get_Line_CTS() == 1 )
                    738:                pACIA->SR |= ACIA_SR_BIT_CTS;
                    739:        else
                    740:                pACIA->SR &= ~ACIA_SR_BIT_CTS;
                    741: 
                    742:        SR = pACIA->SR;
                    743:        pACIA->SR_Read = 1;                                             /* Used in ACIA_Read_RDR to clear Overrun and DCD IRQ */
                    744: 
                    745:        if ( SR & ACIA_SR_BIT_CTS )
                    746:                SR &= ~ACIA_SR_BIT_TDRE;                                /* Inhibit TDRE when CTS is set */
                    747: 
                    748:        LOG_TRACE ( TRACE_ACIA, "acia %s read sr data=0x%02x VBL=%d HBL=%d\n" , pACIA->ACIA_Name , SR , nVBLs , nHBL );
                    749: 
                    750:        return SR;
                    751: }
                    752: 
                    753: 
                    754: 
                    755: 
                    756: /*-----------------------------------------------------------------------*/
                    757: /**
                    758:  * Write to CR.
                    759:  */
                    760: static void    ACIA_Write_CR ( ACIA_STRUCT *pACIA , Uint8 CR )
                    761: {
                    762:        int     Divide;
                    763:        int     Force_rts_bit;
                    764:        Uint8   rts_bit=0;
                    765: 
                    766:        LOG_TRACE ( TRACE_ACIA, "acia %s write cr data=0x%02x VBL=%d HBL=%d\n" , pACIA->ACIA_Name , CR , nVBLs , nHBL );
                    767: 
                    768:        /* Bit 0 and 1 : Counter Divide */
                    769:        Divide = ACIA_CR_COUNTER_DIVIDE ( CR );
                    770:        if ( Divide == 0x03 )
                    771:        {
                    772:                Force_rts_bit = ACIA_MasterReset ( pACIA , CR );        /* Special behaviour for RTS after a master reset */
                    773:        }
                    774:        else
                    775:        {
                    776:                if ( ACIA_CR_COUNTER_DIVIDE ( CR ) != ACIA_CR_COUNTER_DIVIDE ( pACIA->CR ) )
                    777:                {
                    778:                        pACIA->Clock_Divider = ACIA_Counter_Divide[ Divide ];
                    779:                        pACIA->Set_Timers ( pACIA );                    /* Set a timer at the baud rate computed from Clock_Divider */
                    780:                }
                    781:                Force_rts_bit = -1;                                     /* Don't force RTS bit, use bit 5/6 in CR */
                    782:        }
                    783: 
                    784:        /* Bits 2, 3 and 4 : word select */
                    785:        /* Don't do anything here, see ACIA_Prepare_TX and ACIA_Prepare_RX */
                    786: 
                    787:        /* Bits 5 and 6 : transmitter control */
                    788:        pACIA->TX_EnableInt = 0;
                    789:        pACIA->TX_SendBrk = 0;
                    790:        switch ( ACIA_CR_TRANSMITTER_CONTROL ( CR ) )
                    791:        {
                    792:          case 0x00 :
                    793:                rts_bit = 0;
                    794:                break;
                    795:          case 0x01 :
                    796:                rts_bit = 0;
                    797:                pACIA->TX_EnableInt = 1;
                    798:                break;
                    799:          case 0x02 :
                    800:                rts_bit = 1;
                    801:                break;
                    802:          case 0x03 :
                    803:                rts_bit = 0;
                    804:                pACIA->TX_SendBrk = 1;                                  /* We will send break bit until CR is changed */
                    805:                break;
                    806:        }
                    807: 
                    808:        if ( Force_rts_bit >= 0 )
                    809:                rts_bit = Force_rts_bit;                                /* Use the value from ACIA_MasterReset */
                    810:        pACIA->Set_Line_RTS ( rts_bit );
                    811: 
                    812:        /* Bits 7 : receive interrupt enable, see ACIA_UpdateIRQ */
                    813: 
                    814:        pACIA->CR = CR;
                    815: 
                    816:        ACIA_UpdateIRQ ( pACIA );
                    817: }
                    818: 
                    819: 
                    820: 
                    821: 
                    822: /*-----------------------------------------------------------------------*/
                    823: /**
                    824:  * Read RDR. This will clear RDRF and PE.
                    825:  * - OVRN / DCD bits are cleared if SR was read before reading RDR.
                    826:  * - OVRN bit is set only when reading RDR, not when the actual overrun happened
                    827:  *   during ACIA_Clock_RX.
                    828:  * - IRQ bit should be updated depending on the new values of BIT_RDRF,
                    829:  *   BIT_DCD and BIT_OVRN.
                    830:  */
                    831: static Uint8   ACIA_Read_RDR ( ACIA_STRUCT *pACIA )
                    832: {
                    833:        pACIA->SR &= ~( ACIA_SR_BIT_RDRF | ACIA_SR_BIT_PE );
                    834: 
                    835:        /* If we read RDR after reading SR, we clear OVRN / DCD bits */
                    836:        if ( pACIA->SR_Read == 1 )
                    837:        {
                    838:                pACIA->SR_Read = 0;
                    839:                pACIA->SR &= ~( ACIA_SR_BIT_DCD | ACIA_SR_BIT_OVRN );
                    840:                if ( pACIA->Get_Line_DCD () == 1 )
                    841:                        pACIA->SR |= ACIA_SR_BIT_DCD;
                    842:        }
                    843: 
                    844:        if ( pACIA->RX_Overrun )
                    845:        {  
                    846:                pACIA->SR |= ACIA_SR_BIT_OVRN;
                    847:                pACIA->RX_Overrun = 0;
                    848:        }
                    849: 
                    850:        ACIA_UpdateIRQ ( pACIA );
                    851: 
                    852:        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 ,
                    853:                pACIA->SR , ( pACIA->SR & ACIA_SR_BIT_OVRN ) ? "yes" : "no" , nVBLs , nHBL );
                    854: 
                    855:        return pACIA->RDR;
                    856: }
                    857: 
                    858: 
                    859: 
                    860: 
                    861: /*-----------------------------------------------------------------------*/
                    862: /**
                    863:  * Write to TDR.
                    864:  * If the TX process is idle, we should not prepare a new transfer
                    865:  * immediately, to ensure that BIT_TDRE remains clear until the next bit
                    866:  * is sent (BIT_TDRE will be set again in ACIA_Clock_TX).
                    867:  */
                    868: static void    ACIA_Write_TDR ( ACIA_STRUCT *pACIA , Uint8 TDR )
                    869: {
                    870:        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 ,
                    871:                ( pACIA->SR & ACIA_SR_BIT_TDRE ) ? "no" : "yes" , pACIA->TX_State , nVBLs , nHBL );
                    872: 
                    873:        pACIA->TDR = TDR;
                    874:        pACIA->SR &= ~ACIA_SR_BIT_TDRE;                                 /* TDR is not empty anymore */
                    875: 
                    876:        ACIA_UpdateIRQ ( pACIA );
                    877: }
                    878: 
                    879: 
                    880: 
                    881: 
                    882: /*-----------------------------------------------------------------------*/
                    883: /**
                    884:  * Prepare a new transfer. Copy TDR to TSR and initialize parity, data size
                    885:  * and stop bits.
                    886:  * Transfer will then start at the next call of ACIA_Clock_TX
                    887:  */
                    888: static void    ACIA_Prepare_TX ( ACIA_STRUCT *pACIA )
                    889: {
                    890:        pACIA->TSR = pACIA->TDR;
                    891:        pACIA->TX_Parity = 0;
                    892:        pACIA->TX_Size = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].DataBits;
                    893:        pACIA->TX_StopBits = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].StopBits;
                    894: 
                    895:        pACIA->SR |= ACIA_SR_BIT_TDRE;                                  /* TDR was copied to TSR. TDR is now empty */
                    896: 
                    897:        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 ,
                    898:                pACIA->TX_Size , pACIA->TX_StopBits , nVBLs , nHBL );
                    899: }
                    900: 
                    901: 
                    902: 
                    903: 
                    904: /*-----------------------------------------------------------------------*/
                    905: /**
                    906:  * Prepare a new reception. Initialize parity, data size and stop bits.
                    907:  */
                    908: static void    ACIA_Prepare_RX ( ACIA_STRUCT *pACIA )
                    909: {
                    910:        pACIA->RSR = 0;
                    911:        pACIA->RX_Parity = 0;
                    912:        pACIA->RX_Size = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].DataBits;
                    913:        pACIA->RX_StopBits = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].StopBits;
                    914: 
                    915:        LOG_TRACE ( TRACE_ACIA, "acia %s prepare rx size=%d stop=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name ,
                    916:                pACIA->RX_Size , pACIA->RX_StopBits , nVBLs , nHBL );
                    917: }
                    918: 
                    919: 
                    920: 
                    921: 
                    922: /*-----------------------------------------------------------------------*/
                    923: /**
                    924:  * Write a new bit on the TX line each time the TX clock expires.
                    925:  * This will send TDR over the serial line, using TSR, with additional
                    926:  * parity and start/stop bits.
                    927:  * We send bit 0 of TSR, then TSR is shifted to the right.
                    928:  */
                    929: static void    ACIA_Clock_TX ( ACIA_STRUCT *pACIA )
                    930: {
                    931:        int     StateNext;
                    932:        Uint8   tx_bit;
                    933: 
                    934: 
                    935:        LOG_TRACE ( TRACE_ACIA, "acia %s clock_tx tx_state=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name , pACIA->TX_State , nVBLs , nHBL );
                    936: 
                    937:        StateNext = -1;
                    938:        switch ( pACIA->TX_State )
                    939:        {
                    940:          case ACIA_STATE_IDLE :
                    941:                if ( pACIA->TX_SendBrk )
                    942:                {
                    943:                        pACIA->Set_Line_TX ( 0 );                       /* Send 1 break bit */
                    944:                        break;
                    945:                }
                    946: 
                    947:                /* If TDR is not empty when we are in idle state, */
                    948:                /* this means we have a new byte to send */
                    949:                if ( ( pACIA->SR & ACIA_SR_BIT_TDRE ) == 0 )
                    950:                        ACIA_Prepare_TX ( pACIA );
                    951: 
                    952:                if ( pACIA->TX_Size == 0 )                              /* TSR is empty */
                    953:                        pACIA->Set_Line_TX ( 1 );                       /* Send stop bits when idle */
                    954: 
                    955:                else                                                    /* TSR has some new bits to transfer */
                    956:                {
                    957:                        pACIA->Set_Line_TX ( 0 );                       /* Send 1 start bit */
                    958:                        StateNext = ACIA_STATE_DATA_BIT;
                    959:                }
                    960:                break;
                    961: 
                    962:          case ACIA_STATE_DATA_BIT :
                    963:                tx_bit = pACIA->TSR & 1;                                /* New bit to send */
                    964:                pACIA->Set_Line_TX ( tx_bit );
                    965:                pACIA->TX_Parity ^= tx_bit;
                    966:                pACIA->TSR >>= 1;
                    967:                pACIA->TX_Size--;
                    968: 
                    969:                if ( pACIA->TX_Size == 0 )
                    970:                {
                    971:                        if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity != ACIA_PARITY_NONE )
                    972:                                StateNext = ACIA_STATE_PARITY_BIT;
                    973:                        else
                    974:                                StateNext = ACIA_STATE_STOP_BIT;        /* No parity */
                    975:                }
                    976:                break;
                    977: 
                    978:          case ACIA_STATE_PARITY_BIT :
                    979:                if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity == ACIA_PARITY_EVEN )
                    980:                        pACIA->Set_Line_TX ( pACIA->TX_Parity );
                    981:                else
                    982:                        pACIA->Set_Line_TX ( ( ~pACIA->TX_Parity ) & 1 );
                    983: 
                    984:                StateNext = ACIA_STATE_STOP_BIT;
                    985:                break;
                    986: 
                    987:          case ACIA_STATE_STOP_BIT :
                    988:                pACIA->Set_Line_TX ( 1 );                               /* Send 1 stop bit */
                    989:                pACIA->TX_StopBits--;
                    990: 
                    991:                if ( pACIA->TX_StopBits == 0 )                          /* All stop bits were sent : transfer is complete */
                    992:                {
                    993:                        StateNext = ACIA_STATE_IDLE;                    /* Go to idle state to see if a new TDR need to be sent */
                    994:                }
                    995:                break;
                    996:        }
                    997: 
                    998:        ACIA_UpdateIRQ ( pACIA );
                    999: 
                   1000:        if ( StateNext >= 0 )
                   1001:                pACIA->TX_State = StateNext;                            /* Go to a new state */
                   1002: }
                   1003: 
                   1004: 
                   1005: 
                   1006: 
                   1007: /*-----------------------------------------------------------------------*/
                   1008: /**
                   1009:  * Handle a new bit on the RX line each time the RX clock expires.
                   1010:  * This will fill RDR with bits received from the serial line, using RSR.
                   1011:  * Incoming bits are stored in bit 7 of RSR, then RSR is shifted to the right.
                   1012:  */
                   1013: static void    ACIA_Clock_RX ( ACIA_STRUCT *pACIA )
                   1014: {
                   1015:        int     StateNext;
                   1016:        Uint8   rx_bit;
                   1017: 
                   1018: 
                   1019:        rx_bit = pACIA->Get_Line_RX();
                   1020: 
                   1021:        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 );
                   1022: 
                   1023:        StateNext = -1;
                   1024:        switch ( pACIA->RX_State )
                   1025:        {
                   1026:          case ACIA_STATE_IDLE :
                   1027:                if ( rx_bit == 0 )                                      /* Receive 1 start bit */
                   1028:                {
                   1029:                        ACIA_Prepare_RX ( pACIA );
                   1030:                        StateNext = ACIA_STATE_DATA_BIT;
                   1031:                }
                   1032:                break;                                                  /* If no start bit, we stay in idle state */
                   1033: 
                   1034:          case ACIA_STATE_DATA_BIT :
                   1035:                if ( rx_bit )
                   1036:                        pACIA->RSR |= 0x80;
                   1037:                pACIA->RX_Parity ^= rx_bit;
                   1038:                pACIA->RX_Size--;
                   1039: 
                   1040:                if ( pACIA->RX_Size > 0 )                               /* All bits were not received yet */
                   1041:                {
                   1042:                        pACIA->RSR >>= 1;
                   1043:                }
                   1044:                else
                   1045:                {
                   1046: // [NP] : MC6850 doc is not very clear "the overrun condition begins at the midpoint of the last bit
                   1047: // of the second character received [...]". Is it the last bit of the data word, or the stop bit ?
                   1048: // It makes more sense to check for overrun after the stop bit, when RSR should be copied to RDR,
                   1049: // because RDR could be read between the last data bit and the stop bit, so RX_Overrun and
                   1050: // ACIA_SR_BIT_OVRN would need to be cancelled.
                   1051: //                     if ( pACIA->SR & ACIA_SR_BIT_RDRF )
                   1052: //                     {
                   1053: //                             LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx overrun rsr=0x%02x VBL=%d HBL=%d\n" ,
                   1054: //                                     pACIA->ACIA_Name , pACIA->RSR , nVBLs , nHBL );
                   1055: //                             pACIA->RX_Overrun = 1;                  /* Bit in SR will be set when reading RDR */
                   1056: //                     }
                   1057:                        if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity != ACIA_PARITY_NONE )
                   1058:                                StateNext = ACIA_STATE_PARITY_BIT;
                   1059:                        else
                   1060:                                StateNext = ACIA_STATE_STOP_BIT;        /* No parity */
                   1061:                }
                   1062:                break;
                   1063: 
                   1064:          case ACIA_STATE_PARITY_BIT :
                   1065:                if ( ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity == ACIA_PARITY_EVEN )
                   1066:                    && ( pACIA->RX_Parity != rx_bit ) )
                   1067:                        pACIA->SR |= ACIA_SR_BIT_PE;
                   1068: 
                   1069:                else if ( pACIA->RX_Parity == rx_bit )                  /* Odd parity */
                   1070:                        pACIA->SR |= ACIA_SR_BIT_PE;
                   1071: 
                   1072:                if ( pACIA->SR & ACIA_SR_BIT_PE )
                   1073:                        LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx parity error VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
                   1074: 
                   1075:                StateNext = ACIA_STATE_STOP_BIT;
                   1076:                break;
                   1077: 
                   1078:          case ACIA_STATE_STOP_BIT :
                   1079:                if ( rx_bit == 1 )                                      /* Wait for 1 or 2 "1" stop bits */
                   1080:                {
                   1081:                        pACIA->RX_StopBits--;
                   1082:                        if ( pACIA->RX_StopBits == 0 )                  /* All stop bits were received : reception is complete */
                   1083:                        {
                   1084:                                pACIA->SR &= ~ACIA_SR_BIT_FE;
                   1085:                                
                   1086:                                if ( ( pACIA->SR & ACIA_SR_BIT_RDRF ) == 0 )
                   1087:                                {
                   1088:                                        pACIA->RDR = pACIA->RSR;
                   1089:                                        pACIA->SR |= ACIA_SR_BIT_RDRF;
                   1090:                                        LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx received rdr=0x%02x VBL=%d HBL=%d\n" ,
                   1091:                                                pACIA->ACIA_Name , pACIA->RDR , nVBLs , nHBL );
                   1092:                                }
                   1093:                                else
                   1094:                                {
                   1095:                                        LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx overrun rsr=0x%02x unread rdr=0x%02x VBL=%d HBL=%d\n" ,
                   1096:                                                pACIA->ACIA_Name , pACIA->RSR , pACIA->RDR , nVBLs , nHBL );
                   1097:                                        pACIA->RX_Overrun = 1;          /* Bit in SR will be set when reading RDR */
                   1098:                                }
                   1099:                                StateNext = ACIA_STATE_IDLE;            /* Go to idle state and wait for start bit */
                   1100:                        }
                   1101:                }
                   1102:                else                                                    /* Not a valid stop bit */
                   1103:                {
                   1104:                        LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx framing error VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
                   1105: 
                   1106:                        /* According to the A6850 doc, RSR is copied to RDR in case of a framing error */
                   1107:                        /* (Should be the same for the MC6850 ?) */
                   1108:                        pACIA->SR |= ACIA_SR_BIT_FE;
                   1109:                        pACIA->RDR = pACIA->RSR;
                   1110:                        StateNext = ACIA_STATE_IDLE;                    /* Go to idle state and wait for start bit */
                   1111:                }
                   1112:                break;
                   1113:        }
                   1114: 
                   1115:        ACIA_UpdateIRQ ( pACIA );
                   1116: 
                   1117:        if ( StateNext >= 0 )
                   1118:                pACIA->RX_State = StateNext;                            /* Go to a new state */
                   1119: }
                   1120: 
                   1121: 
                   1122: 

unix.superglobalmegacorp.com

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