|
|
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:
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;
1.1.1.2 ! root 704: //fprintf(stderr , "acia irq %x %x %x %d\n" , pACIA->CR , pACIA->SR , pACIA->RX_Overrun , irq_bit_new);
1.1 root 705:
706: if ( pACIA->TX_EnableInt /* Check for TX causes of interrupt */
707: && ( pACIA->SR & ACIA_SR_BIT_TDRE )
708: && ( ( pACIA->SR & ACIA_SR_BIT_CTS ) == 0 ) )
709: irq_bit_new = ACIA_SR_BIT_IRQ;
710:
711: /* Update SR and IRQ line if a change happened */
712: if ( ( pACIA->SR & ACIA_SR_BIT_IRQ ) != irq_bit_new )
713: {
714: 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 );
715:
716: if ( irq_bit_new )
717: {
718: pACIA->SR |= ACIA_SR_BIT_IRQ; /* Set IRQ bit */
719: pACIA->Set_Line_IRQ ( 0 ); /* IRQ line goes low */
720: }
721: else
722: {
723: pACIA->SR &= ~ACIA_SR_BIT_IRQ; /* Clear IRQ bit */
724: pACIA->Set_Line_IRQ ( 1 ); /* IRQ line goes high */
725: }
726: }
727: }
728:
729:
730:
731: /*-----------------------------------------------------------------------*/
732: /**
733: * Read SR.
734: * Also update CTS ; when CTS is high, TDRE should always be masked to 0.
735: */
736: static Uint8 ACIA_Read_SR ( ACIA_STRUCT *pACIA )
737: {
738: Uint8 SR;
739:
740:
741: if ( pACIA->Get_Line_CTS() == 1 )
742: pACIA->SR |= ACIA_SR_BIT_CTS;
743: else
744: pACIA->SR &= ~ACIA_SR_BIT_CTS;
745:
746: SR = pACIA->SR;
747: pACIA->SR_Read = 1; /* Used in ACIA_Read_RDR to clear Overrun and DCD IRQ */
748:
749: if ( SR & ACIA_SR_BIT_CTS )
750: SR &= ~ACIA_SR_BIT_TDRE; /* Inhibit TDRE when CTS is set */
751:
752: LOG_TRACE ( TRACE_ACIA, "acia %s read sr data=0x%02x VBL=%d HBL=%d\n" , pACIA->ACIA_Name , SR , nVBLs , nHBL );
753:
754: return SR;
755: }
756:
757:
758:
759:
760: /*-----------------------------------------------------------------------*/
761: /**
762: * Write to CR.
763: */
764: static void ACIA_Write_CR ( ACIA_STRUCT *pACIA , Uint8 CR )
765: {
766: int Divide;
767: int Force_rts_bit;
768: Uint8 rts_bit=0;
769:
770: LOG_TRACE ( TRACE_ACIA, "acia %s write cr data=0x%02x VBL=%d HBL=%d\n" , pACIA->ACIA_Name , CR , nVBLs , nHBL );
771:
772: /* Bit 0 and 1 : Counter Divide */
773: Divide = ACIA_CR_COUNTER_DIVIDE ( CR );
774: if ( Divide == 0x03 )
775: {
776: Force_rts_bit = ACIA_MasterReset ( pACIA , CR ); /* Special behaviour for RTS after a master reset */
777: }
778: else
779: {
780: if ( ACIA_CR_COUNTER_DIVIDE ( CR ) != ACIA_CR_COUNTER_DIVIDE ( pACIA->CR ) )
781: {
782: pACIA->Clock_Divider = ACIA_Counter_Divide[ Divide ];
783: pACIA->Set_Timers ( pACIA ); /* Set a timer at the baud rate computed from Clock_Divider */
784: }
785: Force_rts_bit = -1; /* Don't force RTS bit, use bit 5/6 in CR */
786: }
787:
788: /* Bits 2, 3 and 4 : word select */
789: /* Don't do anything here, see ACIA_Prepare_TX and ACIA_Prepare_RX */
790:
791: /* Bits 5 and 6 : transmitter control */
792: pACIA->TX_EnableInt = 0;
793: pACIA->TX_SendBrk = 0;
794: switch ( ACIA_CR_TRANSMITTER_CONTROL ( CR ) )
795: {
796: case 0x00 :
797: rts_bit = 0;
798: break;
799: case 0x01 :
800: rts_bit = 0;
801: pACIA->TX_EnableInt = 1;
802: break;
803: case 0x02 :
804: rts_bit = 1;
805: break;
806: case 0x03 :
807: rts_bit = 0;
808: pACIA->TX_SendBrk = 1; /* We will send break bit until CR is changed */
809: break;
810: }
811:
812: if ( Force_rts_bit >= 0 )
813: rts_bit = Force_rts_bit; /* Use the value from ACIA_MasterReset */
814: pACIA->Set_Line_RTS ( rts_bit );
815:
816: /* Bits 7 : receive interrupt enable, see ACIA_UpdateIRQ */
817:
818: pACIA->CR = CR;
819:
820: ACIA_UpdateIRQ ( pACIA );
821: }
822:
823:
824:
825:
826: /*-----------------------------------------------------------------------*/
827: /**
828: * Read RDR. This will clear RDRF and PE.
829: * - OVRN / DCD bits are cleared if SR was read before reading RDR.
830: * - OVRN bit is set only when reading RDR, not when the actual overrun happened
831: * during ACIA_Clock_RX.
832: * - IRQ bit should be updated depending on the new values of BIT_RDRF,
833: * BIT_DCD and BIT_OVRN.
834: */
835: static Uint8 ACIA_Read_RDR ( ACIA_STRUCT *pACIA )
836: {
837: pACIA->SR &= ~( ACIA_SR_BIT_RDRF | ACIA_SR_BIT_PE );
838:
839: /* If we read RDR after reading SR, we clear OVRN / DCD bits */
840: if ( pACIA->SR_Read == 1 )
841: {
842: pACIA->SR_Read = 0;
843: pACIA->SR &= ~( ACIA_SR_BIT_DCD | ACIA_SR_BIT_OVRN );
844: if ( pACIA->Get_Line_DCD () == 1 )
845: pACIA->SR |= ACIA_SR_BIT_DCD;
846: }
847:
848: if ( pACIA->RX_Overrun )
849: {
850: pACIA->SR |= ACIA_SR_BIT_OVRN;
851: pACIA->RX_Overrun = 0;
852: }
853:
854: ACIA_UpdateIRQ ( pACIA );
855:
856: 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 ,
857: pACIA->SR , ( pACIA->SR & ACIA_SR_BIT_OVRN ) ? "yes" : "no" , nVBLs , nHBL );
858:
859: return pACIA->RDR;
860: }
861:
862:
863:
864:
865: /*-----------------------------------------------------------------------*/
866: /**
867: * Write to TDR.
868: * If the TX process is idle, we should not prepare a new transfer
869: * immediately, to ensure that BIT_TDRE remains clear until the next bit
870: * is sent (BIT_TDRE will be set again in ACIA_Clock_TX).
871: */
872: static void ACIA_Write_TDR ( ACIA_STRUCT *pACIA , Uint8 TDR )
873: {
874: 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 ,
875: ( pACIA->SR & ACIA_SR_BIT_TDRE ) ? "no" : "yes" , pACIA->TX_State , nVBLs , nHBL );
876:
877: pACIA->TDR = TDR;
878: pACIA->SR &= ~ACIA_SR_BIT_TDRE; /* TDR is not empty anymore */
879:
880: ACIA_UpdateIRQ ( pACIA );
881: }
882:
883:
884:
885:
886: /*-----------------------------------------------------------------------*/
887: /**
888: * Prepare a new transfer. Copy TDR to TSR and initialize parity, data size
889: * and stop bits.
890: * Transfer will then start at the next call of ACIA_Clock_TX
891: */
892: static void ACIA_Prepare_TX ( ACIA_STRUCT *pACIA )
893: {
894: pACIA->TSR = pACIA->TDR;
895: pACIA->TX_Parity = 0;
896: pACIA->TX_Size = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].DataBits;
897: pACIA->TX_StopBits = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].StopBits;
898:
899: pACIA->SR |= ACIA_SR_BIT_TDRE; /* TDR was copied to TSR. TDR is now empty */
900:
901: 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 ,
902: pACIA->TX_Size , pACIA->TX_StopBits , nVBLs , nHBL );
903: }
904:
905:
906:
907:
908: /*-----------------------------------------------------------------------*/
909: /**
910: * Prepare a new reception. Initialize parity, data size and stop bits.
911: */
912: static void ACIA_Prepare_RX ( ACIA_STRUCT *pACIA )
913: {
914: pACIA->RSR = 0;
915: pACIA->RX_Parity = 0;
916: pACIA->RX_Size = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].DataBits;
917: pACIA->RX_StopBits = ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].StopBits;
918:
919: LOG_TRACE ( TRACE_ACIA, "acia %s prepare rx size=%d stop=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name ,
920: pACIA->RX_Size , pACIA->RX_StopBits , nVBLs , nHBL );
921: }
922:
923:
924:
925:
926: /*-----------------------------------------------------------------------*/
927: /**
928: * Write a new bit on the TX line each time the TX clock expires.
929: * This will send TDR over the serial line, using TSR, with additional
930: * parity and start/stop bits.
931: * We send bit 0 of TSR, then TSR is shifted to the right.
932: */
933: static void ACIA_Clock_TX ( ACIA_STRUCT *pACIA )
934: {
935: int StateNext;
936: Uint8 tx_bit;
937:
938:
939: LOG_TRACE ( TRACE_ACIA, "acia %s clock_tx tx_state=%d VBL=%d HBL=%d\n" , pACIA->ACIA_Name , pACIA->TX_State , nVBLs , nHBL );
940:
941: StateNext = -1;
942: switch ( pACIA->TX_State )
943: {
944: case ACIA_STATE_IDLE :
945: if ( pACIA->TX_SendBrk )
946: {
947: pACIA->Set_Line_TX ( 0 ); /* Send 1 break bit */
948: break;
949: }
950:
951: /* If TDR is not empty when we are in idle state, */
952: /* this means we have a new byte to send */
953: if ( ( pACIA->SR & ACIA_SR_BIT_TDRE ) == 0 )
954: ACIA_Prepare_TX ( pACIA );
955:
956: if ( pACIA->TX_Size == 0 ) /* TSR is empty */
957: pACIA->Set_Line_TX ( 1 ); /* Send stop bits when idle */
958:
959: else /* TSR has some new bits to transfer */
960: {
961: pACIA->Set_Line_TX ( 0 ); /* Send 1 start bit */
962: StateNext = ACIA_STATE_DATA_BIT;
963: }
964: break;
965:
966: case ACIA_STATE_DATA_BIT :
967: tx_bit = pACIA->TSR & 1; /* New bit to send */
968: pACIA->Set_Line_TX ( tx_bit );
969: pACIA->TX_Parity ^= tx_bit;
970: pACIA->TSR >>= 1;
971: pACIA->TX_Size--;
972:
973: if ( pACIA->TX_Size == 0 )
974: {
975: if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity != ACIA_PARITY_NONE )
976: StateNext = ACIA_STATE_PARITY_BIT;
977: else
978: StateNext = ACIA_STATE_STOP_BIT; /* No parity */
979: }
980: break;
981:
982: case ACIA_STATE_PARITY_BIT :
983: if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity == ACIA_PARITY_EVEN )
984: pACIA->Set_Line_TX ( pACIA->TX_Parity );
985: else
986: pACIA->Set_Line_TX ( ( ~pACIA->TX_Parity ) & 1 );
987:
988: StateNext = ACIA_STATE_STOP_BIT;
989: break;
990:
991: case ACIA_STATE_STOP_BIT :
992: pACIA->Set_Line_TX ( 1 ); /* Send 1 stop bit */
993: pACIA->TX_StopBits--;
994:
995: if ( pACIA->TX_StopBits == 0 ) /* All stop bits were sent : transfer is complete */
996: {
997: StateNext = ACIA_STATE_IDLE; /* Go to idle state to see if a new TDR need to be sent */
998: }
999: break;
1000: }
1001:
1002: ACIA_UpdateIRQ ( pACIA );
1003:
1004: if ( StateNext >= 0 )
1005: pACIA->TX_State = StateNext; /* Go to a new state */
1006: }
1007:
1008:
1009:
1010:
1011: /*-----------------------------------------------------------------------*/
1012: /**
1013: * Handle a new bit on the RX line each time the RX clock expires.
1014: * This will fill RDR with bits received from the serial line, using RSR.
1015: * Incoming bits are stored in bit 7 of RSR, then RSR is shifted to the right.
1016: */
1017: static void ACIA_Clock_RX ( ACIA_STRUCT *pACIA )
1018: {
1019: int StateNext;
1020: Uint8 rx_bit;
1021:
1022:
1023: rx_bit = pACIA->Get_Line_RX();
1024:
1025: 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 );
1026:
1027: StateNext = -1;
1028: switch ( pACIA->RX_State )
1029: {
1030: case ACIA_STATE_IDLE :
1031: if ( rx_bit == 0 ) /* Receive 1 start bit */
1032: {
1033: ACIA_Prepare_RX ( pACIA );
1034: StateNext = ACIA_STATE_DATA_BIT;
1035: }
1036: break; /* If no start bit, we stay in idle state */
1037:
1038: case ACIA_STATE_DATA_BIT :
1039: if ( rx_bit )
1040: pACIA->RSR |= 0x80;
1041: pACIA->RX_Parity ^= rx_bit;
1042: pACIA->RX_Size--;
1043:
1044: if ( pACIA->RX_Size > 0 ) /* All bits were not received yet */
1045: {
1046: pACIA->RSR >>= 1;
1047: }
1048: else
1049: {
1050: // [NP] : MC6850 doc is not very clear "the overrun condition begins at the midpoint of the last bit
1051: // of the second character received [...]". Is it the last bit of the data word, or the stop bit ?
1052: // It makes more sense to check for overrun after the stop bit, when RSR should be copied to RDR,
1053: // because RDR could be read between the last data bit and the stop bit, so RX_Overrun and
1054: // ACIA_SR_BIT_OVRN would need to be cancelled.
1055: // if ( pACIA->SR & ACIA_SR_BIT_RDRF )
1056: // {
1057: // LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx overrun rsr=0x%02x VBL=%d HBL=%d\n" ,
1058: // pACIA->ACIA_Name , pACIA->RSR , nVBLs , nHBL );
1059: // pACIA->RX_Overrun = 1; /* Bit in SR will be set when reading RDR */
1060: // }
1061: if ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity != ACIA_PARITY_NONE )
1062: StateNext = ACIA_STATE_PARITY_BIT;
1063: else
1064: StateNext = ACIA_STATE_STOP_BIT; /* No parity */
1065: }
1066: break;
1067:
1068: case ACIA_STATE_PARITY_BIT :
1069: if ( ( ACIA_Serial_Params[ ACIA_CR_WORD_SELECT ( pACIA->CR ) ].Parity == ACIA_PARITY_EVEN )
1070: && ( pACIA->RX_Parity != rx_bit ) )
1071: pACIA->SR |= ACIA_SR_BIT_PE;
1072:
1073: else if ( pACIA->RX_Parity == rx_bit ) /* Odd parity */
1074: pACIA->SR |= ACIA_SR_BIT_PE;
1075:
1076: if ( pACIA->SR & ACIA_SR_BIT_PE )
1077: LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx parity error VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
1078:
1079: StateNext = ACIA_STATE_STOP_BIT;
1080: break;
1081:
1082: case ACIA_STATE_STOP_BIT :
1083: if ( rx_bit == 1 ) /* Wait for 1 or 2 "1" stop bits */
1084: {
1085: pACIA->RX_StopBits--;
1086: if ( pACIA->RX_StopBits == 0 ) /* All stop bits were received : reception is complete */
1087: {
1088: pACIA->SR &= ~ACIA_SR_BIT_FE;
1089:
1090: if ( ( pACIA->SR & ACIA_SR_BIT_RDRF ) == 0 )
1091: {
1092: pACIA->RDR = pACIA->RSR;
1093: pACIA->SR |= ACIA_SR_BIT_RDRF;
1094: LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx received rdr=0x%02x VBL=%d HBL=%d\n" ,
1095: pACIA->ACIA_Name , pACIA->RDR , nVBLs , nHBL );
1096: }
1097: else
1098: {
1099: LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx overrun rsr=0x%02x unread rdr=0x%02x VBL=%d HBL=%d\n" ,
1100: pACIA->ACIA_Name , pACIA->RSR , pACIA->RDR , nVBLs , nHBL );
1101: pACIA->RX_Overrun = 1; /* Bit in SR will be set when reading RDR */
1102: }
1103: StateNext = ACIA_STATE_IDLE; /* Go to idle state and wait for start bit */
1104: }
1105: }
1106: else /* Not a valid stop bit */
1107: {
1108: LOG_TRACE ( TRACE_ACIA, "acia %s clock_rx framing error VBL=%d HBL=%d\n" , pACIA->ACIA_Name , nVBLs , nHBL );
1109:
1110: /* According to the A6850 doc, RSR is copied to RDR in case of a framing error */
1111: /* (Should be the same for the MC6850 ?) */
1112: pACIA->SR |= ACIA_SR_BIT_FE;
1113: pACIA->RDR = pACIA->RSR;
1114: StateNext = ACIA_STATE_IDLE; /* Go to idle state and wait for start bit */
1115: }
1116: break;
1117: }
1118:
1119: ACIA_UpdateIRQ ( pACIA );
1120:
1121: if ( StateNext >= 0 )
1122: pACIA->RX_State = StateNext; /* Go to a new state */
1123: }
1124:
1125:
1126:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.