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