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