|
|
1.1 root 1: /*
2: Hatari - acia.c
3:
4: Copyright (C) 2012 by Nicolas Pomarède
5:
1.1.1.4 ! root 6: This file is distributed under the GNU General Public License, version 2
! 7: or at your option any later version. Read the file gpl.txt for details.
1.1 root 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.
1.1.1.4 ! root 442: * TODO : we use a fixed 8 MHz clock to convert cycles for our internal timers
! 443: * in cycInt.c. This should be replaced some days by using MachineClocks.CPU_Freq.
1.1 root 444: */
445: static void ACIA_Start_InterruptHandler_IKBD ( ACIA_STRUCT *pACIA , int InternalCycleOffset )
446: {
447: int Cycles;
448:
449:
450: // Cycles = MachineClocks.CPU_Freq / pACIA->TX_Clock; /* Convert ACIA cycles in CPU cycles */
451: Cycles = 8021247 / pACIA->TX_Clock; /* Convert ACIA cycles in CPU cycles, for a 8 MHz STF reference */
452: Cycles *= pACIA->Clock_Divider;
1.1.1.4 ! root 453: #ifdef OLD_CPU_SHIFT
1.1 root 454: Cycles <<= nCpuFreqShift; /* Compensate for x2 or x4 cpu speed */
1.1.1.4 ! root 455: #endif
1.1 root 456:
457: LOG_TRACE ( TRACE_ACIA, "acia %s start timer divider=%d cpu_cycles=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name ,
458: pACIA->Clock_Divider , Cycles , nVBLs , nHBL );
459:
1.1.1.4 ! root 460: #ifdef OLD_CPU_SHIFT
1.1 root 461: CycInt_AddRelativeInterruptWithOffset ( Cycles, INT_CPU_CYCLE, INTERRUPT_ACIA_IKBD , InternalCycleOffset );
1.1.1.4 ! root 462: #else
! 463: CycInt_AddRelativeInterruptWithOffset ( Cycles, INT_CPU8_CYCLE, INTERRUPT_ACIA_IKBD , InternalCycleOffset );
! 464: #endif
1.1 root 465: }
466:
467:
468:
469:
470: /*-----------------------------------------------------------------------*/
471: /**
472: * Interrupt called each time a new bit must be sent / received with the IKBD.
473: * This interrupt will be called at freq ( 500 MHz / ACIA_CR_COUNTER_DIVIDE )
474: * On ST, RX_Clock = TX_Clock = 500 MHz.
475: * We continuously restart the interrupt, taking into account PendingCyclesOver.
476: */
477: void ACIA_InterruptHandler_IKBD ( void )
478: {
479: int PendingCyclesOver;
480:
481:
482: /* Number of internal cycles we went over for this timer ( <= 0 ) */
483: /* Used to restart the next timer and keep a constant baud rate */
484: PendingCyclesOver = -PendingInterruptCount; /* >= 0 */
485:
486: LOG_TRACE ( TRACE_ACIA, "acia ikbd interrupt handler pending_cyc=%d VBL=%d HBL=%d\n" , PendingCyclesOver , nVBLs , nHBL );
487:
488: /* Remove this interrupt from list and re-order */
489: CycInt_AcknowledgeInterrupt();
490:
491: ACIA_Clock_TX ( pACIA_IKBD );
492: ACIA_Clock_RX ( pACIA_IKBD );
493:
494: ACIA_Start_InterruptHandler_IKBD ( pACIA_IKBD , -PendingCyclesOver ); /* Compensate for a != 0 value of PendingCyclesOver */
495: }
496:
497:
498:
499:
500: /*-----------------------------------------------------------------------*/
501: /**
502: * Interrupt called each time a new bit must be sent / received with the MIDI.
503: * This interrupt will be called at freq ( 500 MHz / ACIA_CR_COUNTER_DIVIDE )
504: * On ST, RX_Clock = TX_Clock = 500 MHz.
505: */
506: void ACIA_InterruptHandler_MIDI ( void )
507: {
508: ACIA_Clock_TX ( pACIA_MIDI );
509: ACIA_Clock_RX ( pACIA_MIDI );
510: }
511:
512:
513:
514:
515: /*-----------------------------------------------------------------------*/
516: /**
517: * - For each access to an ACIA register, a 6 cycles delay is added to the
518: * normal 68000 timing for the current CPU instruction. If the instruction
519: * accesses several registers at once, the delays are cumulated.
520: * - An additional delay will also be added to ensure the 68000 clock and
521: * the E clock are synchronised ; this delay can add between 0 and 8 cycles
522: * to reach the next multiple of 10 cycles. This delay is added only once
523: * per CPU instruction.
524: * These delays are measured for an 8 MHz 68000 CPU.
525: */
526: void ACIA_AddWaitCycles ( void )
527: {
528: int cycles;
529:
530: /* Add a default of 6 cycles for each access */
531: cycles = 6;
532:
533: /* Wait for E clock only if this is the first ACIA access for this instruction */
534: /* (NOTE : in UAE, movep behaves like several bytes access with different IoAccessBaseAddress, */
535: /* so only the first movep's access should wait for E Clock) */
1.1.1.4 ! root 536: if ( ( ( IoAccessInstrCount == 0 ) && ( IoAccessBaseAddress == IoAccessCurrentAddress ) )
! 537: || ( IoAccessInstrCount == 1 ) ) /* First access of a movep */
1.1 root 538: cycles += M68000_WaitEClock ();
539:
540: M68000_WaitState ( cycles );
541: }
542:
543:
544:
545: /*-----------------------------------------------------------------------*/
546: /**
547: * Return SR for the IKBD's ACIA (0xfffc00)
548: */
549: void ACIA_IKBD_Read_SR ( void )
550: {
551: ACIA_AddWaitCycles (); /* Additional cycles when accessing the ACIA */
552:
553: IoMem[0xfffc00] = ACIA_Read_SR ( pACIA_IKBD );
554:
555: if (LOG_TRACE_LEVEL(TRACE_ACIA))
556: {
557: int FrameCycles, HblCounterVideo, LineCycles;
558: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
559: 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 ,
560: IoMem[0xfffc00], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
561: }
562: }
563:
564:
565:
566:
567: /*-----------------------------------------------------------------------*/
568: /**
569: * Return RDR for the IKBD's ACIA (0xfffc02) : receive a byte from the IKBD
570: */
571: void ACIA_IKBD_Read_RDR ( void )
572: {
573: ACIA_AddWaitCycles (); /* Additional cycles when accessing the ACIA */
574:
575: IoMem[0xfffc02] = ACIA_Read_RDR ( pACIA_IKBD );
576:
577: if (LOG_TRACE_LEVEL(TRACE_IKBD_ACIA))
578: {
579: int FrameCycles, HblCounterVideo, LineCycles;
580: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
581: 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 ,
582: IoMem[0xfffc02], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
583: }
584: }
585:
586:
587:
588:
589: /*-----------------------------------------------------------------------*/
590: /**
591: * Write to CR in the IKBD's ACIA (0xfffc00)
592: */
593: void ACIA_IKBD_Write_CR ( void )
594: {
595: int FrameCycles, HblCounterVideo, LineCycles;
596:
597: ACIA_AddWaitCycles (); /* Additional cycles when accessing the ACIA */
598:
599: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
600: 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 ,
601: IoMem[0xfffc00], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
602:
603: ACIA_Write_CR ( pACIA_IKBD , IoMem[0xfffc00] );
604: }
605:
606:
607:
608:
609: /*-----------------------------------------------------------------------*/
610: /**
611: * Write to TDR in the IKBD's ACIA (0xfffc02) : send a byte to the IKBD
612: */
613: void ACIA_IKBD_Write_TDR ( void )
614: {
615: int FrameCycles, HblCounterVideo, LineCycles;
616:
617: ACIA_AddWaitCycles (); /* Additional cycles when accessing the ACIA */
618:
619: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
620: 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 ,
621: IoMem[0xfffc02], FrameCycles, LineCycles, HblCounterVideo, M68000_GetPC(), CurrentInstrCycles);
622:
623: ACIA_Write_TDR ( pACIA_IKBD , IoMem[0xfffc02] );
624: }
625:
626:
627:
628:
629: /*----------------------------------------------------------------------*/
630: /* The part below is the real core of the 6850's emulation. */
631: /* */
632: /* This core is not correlated to any specific machine. All the specific*/
633: /* code between the 6850 and the rest of Hatari is called through some */
634: /* callback functions (see above). */
635: /*----------------------------------------------------------------------*/
636:
637:
638:
639: /*-----------------------------------------------------------------------*/
640: /**
641: * Reset an ACIA.
642: * There's no RESET pin on the MC6850, so the only way to reset the ACIA
643: * is to set bit 0 an 1 to 0x03 in the CR to force a master reset.
644: * This will clear SR (except CTS and DCD) and halt/initialize both the
645: * receiver and transmitter.
646: * This also returns the new state of the RTS bit, that must be updated
647: * in ACIA_Write_CR.
648: */
649: static Uint8 ACIA_MasterReset ( ACIA_STRUCT *pACIA , Uint8 CR )
650: {
651: Uint8 dcd_bit;
652: Uint8 cts_bit;
653: Uint8 rts_bit;
654:
655:
656: LOG_TRACE ( TRACE_ACIA, "acia %s master reset VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
657:
658: dcd_bit = pACIA->Get_Line_DCD ();
659: cts_bit = pACIA->Get_Line_CTS ();
660:
661: pACIA->SR = ACIA_SR_BIT_TDRE | ( dcd_bit << 2 ) | ( cts_bit << 3 );
662:
663: pACIA->TX_State = ACIA_STATE_IDLE;
664: pACIA->TSR = 0;
665: pACIA->TX_Size = 0;
666: pACIA->TX_SendBrk = 0;
667:
668: pACIA->RX_State = ACIA_STATE_IDLE;
669: pACIA->RSR = 0;
670: pACIA->RX_Size = 0;
671: pACIA->RX_Overrun = 0;
672:
673: /* On Master Reset, IRQ line is high */
674: /* If it's the 1st reset, RTS should be high, else RTS depends on CR bit 5 and 6 */
675: pACIA->Set_Line_IRQ ( 1 ); /* IRQ line goes high */
676: if ( pACIA->FirstMasterReset == 1 )
677: {
678: pACIA->FirstMasterReset = 0;
679: rts_bit = 1; /* RTS line goes high */
680: }
681: else
682: rts_bit = ( ACIA_CR_TRANSMITTER_CONTROL ( CR ) == 0x02 ) ? 1 : 0;
683:
684: return rts_bit;
685: }
686:
687:
688:
689:
690: /*-----------------------------------------------------------------------*/
691: /**
692: * Check if the IRQ must be changed in SR.
693: * When there's a change, we must change the IRQ line too.
694: */
695: static void ACIA_UpdateIRQ ( ACIA_STRUCT *pACIA )
696: {
697: Uint8 irq_bit_new;
698:
699: irq_bit_new = 0;
700:
701: if ( ACIA_CR_RECEIVE_INTERRUPT_ENABLE ( pACIA->CR ) /* Check for RX causes of interrupt */
702: && ( ( pACIA->SR & ( ACIA_SR_BIT_RDRF | ACIA_SR_BIT_DCD ) )
703: || ( pACIA->RX_Overrun ) ) )
704: irq_bit_new = ACIA_SR_BIT_IRQ;
1.1.1.2 root 705: //fprintf(stderr , "acia irq %x %x %x %d\n" , pACIA->CR , pACIA->SR , pACIA->RX_Overrun , irq_bit_new);
1.1 root 706:
707: if ( pACIA->TX_EnableInt /* Check for TX causes of interrupt */
708: && ( pACIA->SR & ACIA_SR_BIT_TDRE )
709: && ( ( pACIA->SR & ACIA_SR_BIT_CTS ) == 0 ) )
710: irq_bit_new = ACIA_SR_BIT_IRQ;
711:
712: /* Update SR and IRQ line if a change happened */
713: if ( ( pACIA->SR & ACIA_SR_BIT_IRQ ) != irq_bit_new )
714: {
715: 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 );
716:
717: if ( irq_bit_new )
718: {
719: pACIA->SR |= ACIA_SR_BIT_IRQ; /* Set IRQ bit */
720: pACIA->Set_Line_IRQ ( 0 ); /* IRQ line goes low */
721: }
722: else
723: {
724: pACIA->SR &= ~ACIA_SR_BIT_IRQ; /* Clear IRQ bit */
725: pACIA->Set_Line_IRQ ( 1 ); /* IRQ line goes high */
726: }
727: }
728: }
729:
730:
731:
732: /*-----------------------------------------------------------------------*/
733: /**
734: * Read SR.
735: * Also update CTS ; when CTS is high, TDRE should always be masked to 0.
736: */
737: static Uint8 ACIA_Read_SR ( ACIA_STRUCT *pACIA )
738: {
739: Uint8 SR;
740:
741:
742: if ( pACIA->Get_Line_CTS() == 1 )
743: pACIA->SR |= ACIA_SR_BIT_CTS;
744: else
745: pACIA->SR &= ~ACIA_SR_BIT_CTS;
746:
747: SR = pACIA->SR;
748: pACIA->SR_Read = 1; /* Used in ACIA_Read_RDR to clear Overrun and DCD IRQ */
749:
750: if ( SR & ACIA_SR_BIT_CTS )
751: SR &= ~ACIA_SR_BIT_TDRE; /* Inhibit TDRE when CTS is set */
752:
753: LOG_TRACE ( TRACE_ACIA, "acia %s read sr data=0x%02x VBL=%d HBL=%d\n" , pACIA->ACIA_Name , SR , nVBLs , nHBL );
754:
755: return SR;
756: }
757:
758:
759:
760:
761: /*-----------------------------------------------------------------------*/
762: /**
763: * Write to CR.
764: */
765: static void ACIA_Write_CR ( ACIA_STRUCT *pACIA , Uint8 CR )
766: {
767: int Divide;
768: int Force_rts_bit;
769: Uint8 rts_bit=0;
770:
771: LOG_TRACE ( TRACE_ACIA, "acia %s write cr data=0x%02x VBL=%d HBL=%d\n" , pACIA->ACIA_Name , CR , nVBLs , nHBL );
772:
773: /* Bit 0 and 1 : Counter Divide */
774: Divide = ACIA_CR_COUNTER_DIVIDE ( CR );
775: if ( Divide == 0x03 )
776: {
777: Force_rts_bit = ACIA_MasterReset ( pACIA , CR ); /* Special behaviour for RTS after a master reset */
778: }
779: else
780: {
781: if ( ACIA_CR_COUNTER_DIVIDE ( CR ) != ACIA_CR_COUNTER_DIVIDE ( pACIA->CR ) )
782: {
783: pACIA->Clock_Divider = ACIA_Counter_Divide[ Divide ];
784: pACIA->Set_Timers ( pACIA ); /* Set a timer at the baud rate computed from Clock_Divider */
785: }
786: Force_rts_bit = -1; /* Don't force RTS bit, use bit 5/6 in CR */
787: }
788:
789: /* Bits 2, 3 and 4 : word select */
790: /* Don't do anything here, see ACIA_Prepare_TX and ACIA_Prepare_RX */
791:
792: /* Bits 5 and 6 : transmitter control */
793: pACIA->TX_EnableInt = 0;
794: pACIA->TX_SendBrk = 0;
795: switch ( ACIA_CR_TRANSMITTER_CONTROL ( CR ) )
796: {
797: case 0x00 :
798: rts_bit = 0;
799: break;
800: case 0x01 :
801: rts_bit = 0;
802: pACIA->TX_EnableInt = 1;
803: break;
804: case 0x02 :
805: rts_bit = 1;
806: break;
807: case 0x03 :
808: rts_bit = 0;
809: pACIA->TX_SendBrk = 1; /* We will send break bit until CR is changed */
810: break;
811: }
812:
813: if ( Force_rts_bit >= 0 )
814: rts_bit = Force_rts_bit; /* Use the value from ACIA_MasterReset */
815: pACIA->Set_Line_RTS ( rts_bit );
816:
817: /* Bits 7 : receive interrupt enable, see ACIA_UpdateIRQ */
818:
819: pACIA->CR = CR;
820:
821: ACIA_UpdateIRQ ( pACIA );
822: }
823:
824:
825:
826:
827: /*-----------------------------------------------------------------------*/
828: /**
829: * Read RDR. This will clear RDRF and PE.
830: * - OVRN / DCD bits are cleared if SR was read before reading RDR.
831: * - OVRN bit is set only when reading RDR, not when the actual overrun happened
832: * during ACIA_Clock_RX.
833: * - IRQ bit should be updated depending on the new values of BIT_RDRF,
834: * BIT_DCD and BIT_OVRN.
835: */
836: static Uint8 ACIA_Read_RDR ( ACIA_STRUCT *pACIA )
837: {
838: pACIA->SR &= ~( ACIA_SR_BIT_RDRF | ACIA_SR_BIT_PE );
839:
840: /* If we read RDR after reading SR, we clear OVRN / DCD bits */
841: if ( pACIA->SR_Read == 1 )
842: {
843: pACIA->SR_Read = 0;
844: pACIA->SR &= ~( ACIA_SR_BIT_DCD | ACIA_SR_BIT_OVRN );
845: if ( pACIA->Get_Line_DCD () == 1 )
846: pACIA->SR |= ACIA_SR_BIT_DCD;
847: }
848:
849: if ( pACIA->RX_Overrun )
850: {
851: pACIA->SR |= ACIA_SR_BIT_OVRN;
852: pACIA->RX_Overrun = 0;
853: }
854:
855: ACIA_UpdateIRQ ( pACIA );
856:
857: 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 ,
858: pACIA->SR , ( pACIA->SR & ACIA_SR_BIT_OVRN ) ? "yes" : "no" , nVBLs , nHBL );
859:
860: return pACIA->RDR;
861: }
862:
863:
864:
865:
866: /*-----------------------------------------------------------------------*/
867: /**
868: * Write to TDR.
869: * If the TX process is idle, we should not prepare a new transfer
870: * immediately, to ensure that BIT_TDRE remains clear until the next bit
871: * is sent (BIT_TDRE will be set again in ACIA_Clock_TX).
872: */
873: static void ACIA_Write_TDR ( ACIA_STRUCT *pACIA , Uint8 TDR )
874: {
875: 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 ,
876: ( pACIA->SR & ACIA_SR_BIT_TDRE ) ? "no" : "yes" , pACIA->TX_State , nVBLs , nHBL );
877:
878: pACIA->TDR = TDR;
879: pACIA->SR &= ~ACIA_SR_BIT_TDRE; /* TDR is not empty anymore */
880:
881: ACIA_UpdateIRQ ( pACIA );
882: }
883:
884:
885:
886:
887: /*-----------------------------------------------------------------------*/
888: /**
889: * Prepare a new transfer. Copy TDR to TSR and initialize parity, data size
890: * and stop bits.
891: * Transfer will then start at the next call of ACIA_Clock_TX
892: */
893: static void ACIA_Prepare_TX ( ACIA_STRUCT *pACIA )
894: {
895: pACIA->TSR = pACIA->TDR;
896: pACIA->TX_Parity = 0;
897: pACIA->TX_Size = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].DataBits;
898: pACIA->TX_StopBits = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].StopBits;
899:
900: pACIA->SR |= ACIA_SR_BIT_TDRE; /* TDR was copied to TSR. TDR is now empty */
901:
902: 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 ,
903: pACIA->TX_Size , pACIA->TX_StopBits , nVBLs , nHBL );
904: }
905:
906:
907:
908:
909: /*-----------------------------------------------------------------------*/
910: /**
911: * Prepare a new reception. Initialize parity, data size and stop bits.
912: */
913: static void ACIA_Prepare_RX ( ACIA_STRUCT *pACIA )
914: {
915: pACIA->RSR = 0;
916: pACIA->RX_Parity = 0;
917: pACIA->RX_Size = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].DataBits;
918: pACIA->RX_StopBits = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].StopBits;
919:
920: LOG_TRACE ( TRACE_ACIA, "acia %s prepare rx size=%d stop=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name ,
921: pACIA->RX_Size , pACIA->RX_StopBits , nVBLs , nHBL );
922: }
923:
924:
925:
926:
927: /*-----------------------------------------------------------------------*/
928: /**
929: * Write a new bit on the TX line each time the TX clock expires.
930: * This will send TDR over the serial line, using TSR, with additional
931: * parity and start/stop bits.
932: * We send bit 0 of TSR, then TSR is shifted to the right.
933: */
934: static void ACIA_Clock_TX ( ACIA_STRUCT *pACIA )
935: {
936: int StateNext;
937: Uint8 tx_bit;
938:
939:
940: LOG_TRACE ( TRACE_ACIA, "acia %s clock_tx tx_state=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name , pACIA->TX_State , nVBLs , nHBL );
941:
942: StateNext = -1;
943: switch ( pACIA->TX_State )
944: {
945: case ACIA_STATE_IDLE :
946: if ( pACIA->TX_SendBrk )
947: {
948: pACIA->Set_Line_TX ( 0 ); /* Send 1 break bit */
949: break;
950: }
951:
952: /* If TDR is not empty when we are in idle state, */
953: /* this means we have a new byte to send */
954: if ( ( pACIA->SR & ACIA_SR_BIT_TDRE ) == 0 )
955: ACIA_Prepare_TX ( pACIA );
956:
957: if ( pACIA->TX_Size == 0 ) /* TSR is empty */
958: pACIA->Set_Line_TX ( 1 ); /* Send stop bits when idle */
959:
960: else /* TSR has some new bits to transfer */
961: {
962: pACIA->Set_Line_TX ( 0 ); /* Send 1 start bit */
963: StateNext = ACIA_STATE_DATA_BIT;
964: }
965: break;
966:
967: case ACIA_STATE_DATA_BIT :
968: tx_bit = pACIA->TSR & 1; /* New bit to send */
969: pACIA->Set_Line_TX ( tx_bit );
970: pACIA->TX_Parity ^= tx_bit;
971: pACIA->TSR >>= 1;
972: pACIA->TX_Size--;
973:
974: if ( pACIA->TX_Size == 0 )
975: {
976: if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity != ACIA_PARITY_NONE )
977: StateNext = ACIA_STATE_PARITY_BIT;
978: else
979: StateNext = ACIA_STATE_STOP_BIT; /* No parity */
980: }
981: break;
982:
983: case ACIA_STATE_PARITY_BIT :
984: if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity == ACIA_PARITY_EVEN )
985: pACIA->Set_Line_TX ( pACIA->TX_Parity );
986: else
987: pACIA->Set_Line_TX ( ( ~pACIA->TX_Parity ) & 1 );
988:
989: StateNext = ACIA_STATE_STOP_BIT;
990: break;
991:
992: case ACIA_STATE_STOP_BIT :
993: pACIA->Set_Line_TX ( 1 ); /* Send 1 stop bit */
994: pACIA->TX_StopBits--;
995:
996: if ( pACIA->TX_StopBits == 0 ) /* All stop bits were sent : transfer is complete */
997: {
998: StateNext = ACIA_STATE_IDLE; /* Go to idle state to see if a new TDR need to be sent */
999: }
1000: break;
1001: }
1002:
1003: ACIA_UpdateIRQ ( pACIA );
1004:
1005: if ( StateNext >= 0 )
1006: pACIA->TX_State = StateNext; /* Go to a new state */
1007: }
1008:
1009:
1010:
1011:
1012: /*-----------------------------------------------------------------------*/
1013: /**
1014: * Handle a new bit on the RX line each time the RX clock expires.
1015: * This will fill RDR with bits received from the serial line, using RSR.
1016: * Incoming bits are stored in bit 7 of RSR, then RSR is shifted to the right.
1017: */
1018: static void ACIA_Clock_RX ( ACIA_STRUCT *pACIA )
1019: {
1020: int StateNext;
1021: Uint8 rx_bit;
1022:
1023:
1024: rx_bit = pACIA->Get_Line_RX();
1025:
1026: 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 );
1027:
1028: StateNext = -1;
1029: switch ( pACIA->RX_State )
1030: {
1031: case ACIA_STATE_IDLE :
1032: if ( rx_bit == 0 ) /* Receive 1 start bit */
1033: {
1034: ACIA_Prepare_RX ( pACIA );
1035: StateNext = ACIA_STATE_DATA_BIT;
1036: }
1037: break; /* If no start bit, we stay in idle state */
1038:
1039: case ACIA_STATE_DATA_BIT :
1040: if ( rx_bit )
1041: pACIA->RSR |= 0x80;
1042: pACIA->RX_Parity ^= rx_bit;
1043: pACIA->RX_Size--;
1044:
1045: if ( pACIA->RX_Size > 0 ) /* All bits were not received yet */
1046: {
1047: pACIA->RSR >>= 1;
1048: }
1049: else
1050: {
1051: // [NP] : MC6850 doc is not very clear "the overrun condition begins at the midpoint of the last bit
1052: // of the second character received [...]". Is it the last bit of the data word, or the stop bit ?
1053: // It makes more sense to check for overrun after the stop bit, when RSR should be copied to RDR,
1054: // because RDR could be read between the last data bit and the stop bit, so RX_Overrun and
1055: // ACIA_SR_BIT_OVRN would need to be cancelled.
1056: // if ( pACIA->SR & ACIA_SR_BIT_RDRF )
1057: // {
1058: // LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx overrun rsr=0x%02x VBL=%d HBL=%d\n" ,
1059: // pACIA->ACIA_Name , pACIA->RSR , nVBLs , nHBL );
1060: // pACIA->RX_Overrun = 1; /* Bit in SR will be set when reading RDR */
1061: // }
1062: if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity != ACIA_PARITY_NONE )
1063: StateNext = ACIA_STATE_PARITY_BIT;
1064: else
1065: StateNext = ACIA_STATE_STOP_BIT; /* No parity */
1066: }
1067: break;
1068:
1069: case ACIA_STATE_PARITY_BIT :
1070: if ( ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity == ACIA_PARITY_EVEN )
1071: && ( pACIA->RX_Parity != rx_bit ) )
1072: pACIA->SR |= ACIA_SR_BIT_PE;
1073:
1074: else if ( pACIA->RX_Parity == rx_bit ) /* Odd parity */
1075: pACIA->SR |= ACIA_SR_BIT_PE;
1076:
1077: if ( pACIA->SR & ACIA_SR_BIT_PE )
1078: LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx parity error VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
1079:
1080: StateNext = ACIA_STATE_STOP_BIT;
1081: break;
1082:
1083: case ACIA_STATE_STOP_BIT :
1084: if ( rx_bit == 1 ) /* Wait for 1 or 2 "1" stop bits */
1085: {
1086: pACIA->RX_StopBits--;
1087: if ( pACIA->RX_StopBits == 0 ) /* All stop bits were received : reception is complete */
1088: {
1089: pACIA->SR &= ~ACIA_SR_BIT_FE;
1090:
1091: if ( ( pACIA->SR & ACIA_SR_BIT_RDRF ) == 0 )
1092: {
1093: pACIA->RDR = pACIA->RSR;
1094: pACIA->SR |= ACIA_SR_BIT_RDRF;
1095: LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx received rdr=0x%02x VBL=%d HBL=%d\n" ,
1096: pACIA->ACIA_Name , pACIA->RDR , nVBLs , nHBL );
1097: }
1098: else
1099: {
1100: LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx overrun rsr=0x%02x unread rdr=0x%02x VBL=%d HBL=%d\n" ,
1101: pACIA->ACIA_Name , pACIA->RSR , pACIA->RDR , nVBLs , nHBL );
1102: pACIA->RX_Overrun = 1; /* Bit in SR will be set when reading RDR */
1103: }
1104: StateNext = ACIA_STATE_IDLE; /* Go to idle state and wait for start bit */
1105: }
1106: }
1107: else /* Not a valid stop bit */
1108: {
1109: LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx framing error VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
1110:
1111: /* According to the A6850 doc, RSR is copied to RDR in case of a framing error */
1112: /* (Should be the same for the MC6850 ?) */
1113: pACIA->SR |= ACIA_SR_BIT_FE;
1114: pACIA->RDR = pACIA->RSR;
1115: StateNext = ACIA_STATE_IDLE; /* Go to idle state and wait for start bit */
1116: }
1117: break;
1118: }
1119:
1120: ACIA_UpdateIRQ ( pACIA );
1121:
1122: if ( StateNext >= 0 )
1123: pACIA->RX_State = StateNext; /* Go to a new state */
1124: }
1125:
1126:
1127:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.