|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.