|
|
1.1 root 1: /*
2: Hatari - Crossbar.c
3:
1.1.1.5 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: Falcon Crossbar (Matrice) emulation.
1.1.1.7 root 8: input device:
1.1 root 9: - DSP transmit (SSI)
10: - external DSP connector
11: - ADC (micro + PSG chip)
12: - DMA playback
13:
14: output device:
15: - external DSP connector
16: - DSP receive (SSI)
17: - DAC (headphone, loudspeaker and monitor sound)
18: - DMA record
19:
20: There are 3 possible clocks :
21: - internal clock 25,175 MHz (Ste compatible)
22: - internal clock 32 MHz
23: - external clock (DSP external port, up to 32 Mhz)
24:
1.1.1.7 root 25: Transfers between 2 devices can use handshaking or continuous mode
1.1 root 26:
27: Hardware I/O registers:
28: $FF8900 (byte) : Sound DMA control
29: $FF8901 (byte) : Sound DMA control
30: $FF8903 (byte) : Frame Start Hi
31: $FF8905 (byte) : Frame Start Mi
32: $FF8907 (byte) : Frame Start Lo
33: $FF8909 (byte) : Frame Count Hi
34: $FF890B (byte) : Frame Count Mi
35: $FF890D (byte) : Frame Count Lo
36: $FF890F (byte) : Frame End Hi
37: $FF8911 (byte) : Frame End Mi
38: $FF8913 (byte) : Frame End Lo
39: $FF8920 (byte) : Sound Mode Control
40: $FF8921 (byte) : Sound Mode Control
41: $FF8930 (word) : DMA Crossbar Input Select Controller
42: $FF8932 (word) : DMA Crossbar Output Select Controller
43: $FF8934 (byte) : External Sync Frequency Divider
44: $FF8935 (byte) : Internal Sync Frequency Divider
45: $FF8936 (byte) : Record Track select
46: $FF8937 (byte) : Codec Input Source
47: $FF8938 (byte) : Codec ADC Input
48: $FF8939 (byte) : Gain Settings Per Channel
1.1.1.5 root 49: $FF893A (word) : Attenuation Settings Per Channel
1.1 root 50: $FF893C (word) : Codec Status
51: $FF8940 (word) : GPIO Data Direction
52: $FF8942 (word) : GPIO Data
53:
54:
55: Crossbar schematics:
1.1.1.7 root 56:
1.1 root 57: - one receiving device can be connected to only one source device
58: - one source device can be connected to multiple receiving device
59:
60: Source devices
61: CROSSBAR
62: EXT INPUT ---O------O------O-----O
63: CHANNEL | | | |
64: | | | |
65: DSP ---O------O------O-----O
66: TRANSMIT | | | |
67: | | | |
68: Mic L -----| DMA ---O------O------O-----O
1.1.1.7 root 69: /---|XOR ----|\ PLAYBACK | | | |
1.1 root 70: PSG --| | \ | | | |
71: \---| | /-------X--------O------O------O-----O
72: Mic R -----|XOR ----|/ | | | | |
73: ADC | | DMA DSP EXT OUTPUT Receiving Devices
74: | | RECEIVE CHANNEL
75: | |
76: -----------------
77: \ + /
78: \-----------/
79: |
80: |
81: -----
82: \ / DAC
83: \ /
84: |
85: |
86: Output to:
1.1.1.7 root 87: - header,
88: - internal speaker,
89: - monitor speaker
1.1 root 90: */
91:
92: const char crossbar_fileid[] = "Hatari Crossbar.c : " __DATE__ " " __TIME__;
93:
94: #include "main.h"
95: #include "audio.h"
96: #include "configuration.h"
97: #include "cycInt.h"
1.1.1.8 ! root 98: #include "m68000.h"
1.1 root 99: #include "ioMem.h"
100: #include "log.h"
101: #include "memorySnapShot.h"
102: #include "mfp.h"
103: #include "sound.h"
104: #include "crossbar.h"
105: #include "microphone.h"
106: #include "stMemory.h"
107: #include "dsp.h"
1.1.1.8 ! root 108: #include "clocks_timings.h"
! 109:
1.1 root 110:
111:
112: #define DACBUFFER_SIZE 2048
113: #define DECIMAL_PRECISION 65536
114:
115:
116: /* Crossbar internal functions */
1.1.1.4 root 117: static int Crossbar_DetectSampleRate(Uint16 clock);
1.1 root 118: static void Crossbar_Start_InterruptHandler_25Mhz(void);
119: static void Crossbar_Start_InterruptHandler_32Mhz(void);
120:
121: /* Dma_Play sound functions */
122: static void Crossbar_setDmaPlay_Settings(void);
123: static void Crossbar_Process_DMAPlay_Transfer(void);
124:
125: /* Dma_Record sound functions */
126: static void Crossbar_setDmaRecord_Settings(void);
127: void Crossbar_SendDataToDmaRecord(Sint16 value);
128: static void Crossbar_Process_DMARecord_HandshakeMode(void);
129:
130: /* Dsp Xmit functions */
131: static void Crossbar_SendDataToDspReceive(Uint32 value, Uint16 frame);
132: static void Crossbar_Process_DSPXmit_Transfer(void);
133:
134: /* DAC functions */
135: static void Crossbar_SendDataToDAC(Sint16 value, Uint16 sample_pos);
136:
137: /* ADC functions */
138: static void Crossbar_Process_ADCXmit_Transfer(void);
139:
140: /* external data used by the MFP */
141: Uint16 nCbar_DmaSoundControl;
142:
143: /* internal datas */
144:
145: /* dB = 20log(gain) : gain = antilog(dB/20) */
146: /* Table gain values = (int)(powf(10.0, dB/20.0)*65536.0 + 0.5) 1.5dB steps */
147:
148: /* Values for Codec's ADC volume control (* DECIMAL_PRECISION) */
149: /* PSG must be amplified by 2.66.. before mixing with crossbar */
150: /* The ADC table values are multiplied by 2'2/3 and divided */
151: /* by 4 (later multplied by 4) eg 43691 = 65536 * 2.66.. / 4.0 */
152: static const Uint16 Crossbar_ADC_volume_table[16] =
153: {
154: 3276, 3894, 4628, 5500, 6537, 7769, 9234, 10975,
155: 13043, 15502, 18424, 21897, 26025, 30931, 36761, 43691
156: };
157:
158: /* Values for Codec's DAC volume control (* DECIMAL_PRECISION) */
159: static const Uint16 Crossbar_DAC_volume_table[16] =
160: {
161: 65535, 55142, 46396, 39037, 32846, 27636, 23253, 19565,
162: 16462, 13851, 11654, 9806, 8250, 6942, 5841, 4915
163: };
164:
1.1.1.4 root 165: static const int Ste_SampleRates[4] =
1.1 root 166: {
1.1.1.4 root 167: 6258,
168: 12517,
169: 25033,
170: 50066
1.1 root 171: };
172:
1.1.1.4 root 173: static const int Falcon_SampleRates_25Mhz[15] =
1.1 root 174: {
1.1.1.4 root 175: 49170,
176: 32780,
177: 24585,
178: 19668,
179: 16390,
180: 14049,
181: 12292,
182: 10927,
183: 9834,
184: 8940,
185: 8195,
186: 7565,
187: 7024,
188: 6556,
189: 6146
1.1 root 190: };
191:
1.1.1.4 root 192: static const int Falcon_SampleRates_32Mhz[15] =
1.1 root 193: {
1.1.1.4 root 194: 62500,
195: 41666,
196: 31250,
197: 25000,
198: 20833,
199: 17857,
200: 15624,
201: 13889,
202: 12500,
203: 11363,
204: 10416,
205: 9615,
206: 8928,
207: 8333,
208: 7812
1.1 root 209: };
210:
211: struct dma_s {
212: Uint32 frameStartAddr; /* Sound frame start */
213: Uint32 frameEndAddr; /* Sound frame end */
214: Uint32 frameCounter; /* Counter in current sound frame */
215: Uint32 frameLen; /* Length of the frame */
216: Uint32 isRunning; /* Is Playing / Recording ? */
217: Uint32 loopMode; /* Loop mode enabled ? */
218: Uint32 currentFrame; /* Current Frame Played / Recorded (in stereo, 2 frames = 1 track) */
219: Uint32 timerA_int; /* Timer A interrupt at end of Play / Record ? */
220: Uint32 mfp15_int; /* MFP-15 interrupt at end of Play / Record ? */
221: Uint32 isConnectedToCodec;
222: Uint32 isConnectedToDsp;
223: Uint32 isConnectedToDspInHandShakeMode;
224: Uint32 isConnectedToDma;
225: Uint32 handshakeMode_Frame; /* state of the frame in handshake mode */
226: };
227:
228: struct crossbar_s {
229: Uint32 dmaSelected; /* 1 = DMA Record; 0 = DMA Play */
230: Uint32 playTracks; /* number of tracks played */
231: Uint32 recordTracks; /* number of tracks recorded */
232: Uint16 track_monitored; /* track monitored by the DAC */
233: Uint32 is16Bits; /* 0 = 8 bits; 1 = 16 bits */
234: Uint32 isStereo; /* 0 = mono; 1 = stereo */
235: Uint32 steFreq; /* from 0 (6258 Hz) to 3 (50066 Hz) */
236: Uint32 isInSteFreqMode; /* 0 = Falcon frequency mode ; 1 = Ste frequency mode */
237: Uint32 int_freq_divider; /* internal frequency divider */
238: Uint32 isDacMuted; /* 0 = DAC is running; 1 = DAC is muted */
239: Uint32 dspXmit_freq; /* 0 = 25 Mhz ; 1 = external clock ; 2 = 32 Mhz */
240: Uint32 dmaPlay_freq; /* 0 = 25 Mhz ; 1 = external clock ; 2 = 32 Mhz */
241: Uint16 codecInputSource; /* codec input source */
242: Uint16 codecAdcInput; /* codec ADC input */
243: Uint16 gainSettingLeft; /* Left channel gain for ADC */
244: Uint16 gainSettingRight; /* Right channel gain for ADC */
245: Uint16 attenuationSettingLeft; /* Left channel attenuation for DAC */
246: Uint16 attenuationSettingRight; /* Right channel attenuation for DAC */
247: Uint16 microphone_ADC_is_started;
1.1.1.7 root 248:
1.1 root 249: Uint32 clock25_cycles; /* cycles for 25 Mzh interrupt */
250: Uint32 clock25_cycles_decimal; /* decimal part of cycles counter for 25 Mzh interrupt (*DECIMAL_PRECISION) */
251: Uint32 clock25_cycles_counter; /* Cycle counter for 25 Mhz interrupts */
252: Uint32 pendingCyclesOver25; /* Number of delayed cycles for the interrupt */
253: Uint32 clock32_cycles; /* cycles for 32 Mzh interrupt */
254: Uint32 clock32_cycles_decimal; /* decimal part of cycles counter for 32 Mzh interrupt (*DECIMAL_PRECISION) */
255: Uint32 clock32_cycles_counter; /* Cycle counter for 32 Mhz interrupts */
256: Uint32 pendingCyclesOver32; /* Number of delayed cycles for the interrupt */
1.1.1.4 root 257: Sint64 frequence_ratio; /* Ratio between host computer's sound frequency and hatari's sound frequency */
258: Sint64 frequence_ratio2; /* Ratio between hatari's sound frequency and host computer's sound frequency */
1.1.1.7 root 259:
1.1 root 260: Uint32 dmaPlay_CurrentFrameStart; /* current DmaPlay Frame start ($ff8903 $ff8905 $ff8907) */
261: Uint32 dmaPlay_CurrentFrameCount; /* current DmaRecord Frame start ($ff8903 $ff8905 $ff8907) */
262: Uint32 dmaPlay_CurrentFrameEnd; /* current DmaRecord Frame start ($ff8903 $ff8905 $ff8907) */
263: Uint32 dmaRecord_CurrentFrameStart; /* current DmaPlay Frame end ($ff890f $ff8911 $ff8913) */
264: Uint32 dmaRecord_CurrentFrameCount; /* current DmaRecord Frame start ($ff8903 $ff8905 $ff8907) */
265: Uint32 dmaRecord_CurrentFrameEnd; /* current DmaRecord Frame end ($ff890f $ff8911 $ff8913) */
1.1.1.4 root 266: Uint32 adc2dac_readBufferPosition; /* read position for direct adc->dac transfer */
267: Sint64 adc2dac_readBufferPosition_float; /* float value of read position for direct adc->dac transfer index */
1.1.1.7 root 268:
1.1.1.2 root 269: Uint32 save_special_transfer; /* Used in a special undocumented transfer mode (dsp sent is not in handshake mode and dsp receive is in handshake mode) */
1.1 root 270: };
271:
272: struct codec_s {
273: Sint16 buffer_left[DACBUFFER_SIZE];
274: Sint16 buffer_right[DACBUFFER_SIZE];
1.1.1.4 root 275: Sint64 readPosition_float;
1.1 root 276: Uint32 readPosition;
277: Uint32 writePosition;
278: Uint32 isConnectedToCodec;
279: Uint32 isConnectedToDsp;
280: Uint32 isConnectedToDma;
281: Uint32 wordCount;
282: };
283:
284: struct dsp_s {
285: Uint32 isTristated; /* 0 = DSP is not tristated; 1 = DSP is tristated */
286: Uint32 isInHandshakeMode; /* 0 = not in hanshake mode; 1 = in hanshake mode */
287: Uint32 isConnectedToCodec;
288: Uint32 isConnectedToDsp;
289: Uint32 isConnectedToDma;
290: Uint32 wordCount; /* count number of words received from DSP transmitter (for TX frame computing) */
291: };
292:
293: static struct crossbar_s crossbar;
294: static struct dma_s dmaPlay;
295: static struct dma_s dmaRecord;
296: static struct codec_s dac;
297: static struct codec_s adc;
298: static struct dsp_s dspXmit;
299: static struct dsp_s dspReceive;
300:
301: /**
302: * Reset Crossbar variables.
303: */
304: void Crossbar_Reset(bool bCold)
305: {
306: nCbar_DmaSoundControl = 0;
307:
308: /* Stop DMA sound playing / record */
309: IoMem_WriteByte(0xff8901,0);
310: dmaPlay.isRunning = 0;
311: dmaPlay.loopMode = 0;
312: dmaPlay.currentFrame = 0;
313: dmaPlay.isConnectedToDspInHandShakeMode = 0;
314: dmaPlay.handshakeMode_Frame = 0;
315: dmaRecord.isRunning = 0;
316: dmaRecord.loopMode = 0;
317: dmaRecord.currentFrame = 0;
318: dmaRecord.isConnectedToDspInHandShakeMode = 0;
319: dmaRecord.handshakeMode_Frame = 0;
320:
321: /* DAC inits */
322: memset(dac.buffer_left, 0, sizeof(dac.buffer_left));
323: memset(dac.buffer_right, 0, sizeof(dac.buffer_right));
1.1.1.4 root 324: dac.readPosition_float = 0;
1.1 root 325: dac.readPosition = 0;
1.1.1.8 ! root 326: dac.writePosition = (dac.readPosition+DACBUFFER_SIZE/2)%DACBUFFER_SIZE;
1.1 root 327:
328: /* ADC inits */
1.1.1.2 root 329: memset(adc.buffer_left, 0, sizeof(adc.buffer_left));
330: memset(adc.buffer_right, 0, sizeof(adc.buffer_right));
1.1.1.4 root 331: adc.readPosition_float = 0;
1.1 root 332: adc.readPosition = 0;
333: adc.writePosition = 0;
334:
335: /* DSP inits */
336: dspXmit.wordCount = 0;
337:
338: /* Crossbar inits */
339: crossbar.clock25_cycles = 160;
340: crossbar.clock25_cycles_decimal = 0;
341: crossbar.clock25_cycles_counter = 0;
342: crossbar.pendingCyclesOver25 = 0;
343: crossbar.clock32_cycles = 160;
344: crossbar.clock32_cycles_decimal = 0;
345: crossbar.clock32_cycles_counter = 0;
346: crossbar.pendingCyclesOver32 = 0;
347: crossbar.frequence_ratio = 0;
348: crossbar.frequence_ratio2 = 0;
349:
350: crossbar.dmaSelected = 0;
351: crossbar.track_monitored = 0;
352: crossbar.isInSteFreqMode = 1;
353: crossbar.int_freq_divider = 0;
354: crossbar.steFreq = 3;
355: crossbar.playTracks = 1;
356: crossbar.is16Bits = 0;
357: crossbar.isStereo = 1;
358: crossbar.codecInputSource = 3;
359: crossbar.codecAdcInput = 3;
360: crossbar.gainSettingLeft = 3276;
361: crossbar.gainSettingRight = 3276;
362: crossbar.attenuationSettingLeft = 65535;
363: crossbar.attenuationSettingRight = 65535;
1.1.1.4 root 364: crossbar.adc2dac_readBufferPosition = 0;
365: crossbar.adc2dac_readBufferPosition_float = 0;
1.1 root 366:
367: /* Start 25 Mhz and 32 Mhz Clocks */
368: Crossbar_Recalculate_Clocks_Cycles();
369: Crossbar_Start_InterruptHandler_25Mhz();
370: Crossbar_Start_InterruptHandler_32Mhz();
371:
372: /* Start Microphone jack emulation */
1.1.1.7 root 373: if (crossbar.microphone_ADC_is_started == 0) {
1.1 root 374: crossbar.microphone_ADC_is_started = Microphone_Start((int)nAudioFrequency);
375: }
376:
1.1.1.2 root 377: /* Initialize special transfer mode */
378: crossbar.save_special_transfer = 0;
1.1.1.7 root 379:
1.1 root 380: /* Initialize Crossbar values after reboot */
381: IoMem_WriteByte(0xff8900,0x05);
382: IoMem_WriteByte(0xff8903,0xff);
383: IoMem_WriteByte(0xff8905,0xff);
384: IoMem_WriteByte(0xff8907,0xfe);
385: IoMem_WriteByte(0xff8909,0xff);
386: IoMem_WriteByte(0xff890b,0xff);
387: IoMem_WriteByte(0xff890d,0xfe);
388: IoMem_WriteByte(0xff890f,0xff);
389: IoMem_WriteByte(0xff8911,0xff);
390: IoMem_WriteByte(0xff8913,0xfe);
391: IoMem_WriteWord(0xff893c,0x2401);
392: }
393:
394: /**
395: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
396: */
397: void Crossbar_MemorySnapShot_Capture(bool bSave)
398: {
399: /* Save/Restore details */
400: MemorySnapShot_Store(&nCbar_DmaSoundControl, sizeof(nCbar_DmaSoundControl));
401: MemorySnapShot_Store(&dmaPlay, sizeof(dmaPlay));
402: MemorySnapShot_Store(&dmaRecord, sizeof(dmaRecord));
403: MemorySnapShot_Store(&crossbar, sizeof(crossbar));
404: MemorySnapShot_Store(&dac, sizeof(dac));
405: MemorySnapShot_Store(&adc, sizeof(adc));
406: MemorySnapShot_Store(&dspXmit, sizeof(dspXmit));
407: MemorySnapShot_Store(&dspReceive, sizeof(dspReceive));
1.1.1.8 ! root 408:
! 409: /* After restoring, update the clock/freq counters */
! 410: if ( !bSave )
! 411: Crossbar_Recalculate_Clocks_Cycles();
1.1 root 412: }
413:
414:
415: /*----------------------------------------------------------------------*/
416: /* Hardware I/O functions */
417: /*----------------------------------------------------------------------*/
418:
419: /**
1.1.1.4 root 420: * Write byte to Microwire Mask register(0xff8924).
421: * Note: On Falcon, the Microwire is not present.
422: * But for compatibility with the STe, Atari implemented the Microwire
1.1.1.7 root 423: * as follow (when one writes at the following address):
1.1.1.4 root 424: * $ff8922: always reads 0 for any value written at this address
425: * $ff8924: NOT the value, then 8 cycles later, NOT the value again to its initial value.
426: */
427: void Crossbar_Microwire_WriteWord(void)
428: {
429: Uint16 microwire = IoMem_ReadWord(0xff8924);
430: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8924 (MicroWire Mask) write: 0x%04x\n", microwire);
431:
432: /* NOT the value and store it */
433: microwire = ~microwire;
434: IoMem_WriteWord(0xff8924, microwire);
435: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8924 (MicroWire Mask) NOT value: 0x%04x\n", microwire);
436:
437: /* Start a new Microwire interrupt */
438: CycInt_AddRelativeInterrupt(8, INT_CPU_CYCLE, INTERRUPT_DMASOUND_MICROWIRE);
439: }
440:
441: /**
442: * Crossbar Microwire mask interrupt, called from dmaSnd.c
443: */
444: void Crossbar_InterruptHandler_Microwire(void)
445: {
446: Uint16 microwire = IoMem_ReadWord(0xff8924);
447:
448: /* Remove this interrupt from list and re-order */
449: CycInt_AcknowledgeInterrupt();
450:
451: /* NOT the value again to it's original value and store it */
452: microwire = ~microwire;
453: IoMem_WriteWord(0xff8924, microwire);
454: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8924 (MicroWire Mask) NOT value to original: 0x%04x\n", microwire);
455: }
456:
457: /**
1.1 root 458: * Write byte to buffer interrupts (0xff8900).
459: */
460: void Crossbar_BufferInter_WriteByte(void)
461: {
462: Uint8 dmaCtrl = IoMem_ReadByte(0xff8900);
463:
464: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8900 (Sound DMA control) write: 0x%02x\n", dmaCtrl);
465:
466: dmaPlay.timerA_int = (dmaCtrl & 0x4) >> 2;
467: dmaPlay.mfp15_int = (dmaCtrl & 0x1);
468: dmaRecord.timerA_int = (dmaCtrl & 0x8) >> 3;
469: dmaRecord.mfp15_int = (dmaCtrl & 0x2) >> 1;
470: }
471:
472: /**
473: * Write byte from DMA control register (0xff8901).
474: */
475: void Crossbar_DmaCtrlReg_WriteByte(void)
476: {
477: Uint8 sndCtrl = IoMem_ReadByte(0xff8901);
478:
479: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8901 (additional Sound DMA control) write: 0x%02x\n", sndCtrl);
480:
481: crossbar.dmaSelected = (sndCtrl & 0x80) >> 7;
482:
483: /* DMA Play mode */
484: if ((dmaPlay.isRunning == 0) && (sndCtrl & CROSSBAR_SNDCTRL_PLAY))
485: {
486: /* Turning on DMA Play sound emulation */
487: dmaPlay.isRunning = 1;
488: nCbar_DmaSoundControl = sndCtrl;
489: dmaPlay.loopMode = (sndCtrl & 0x2) >> 1;
490: Crossbar_setDmaPlay_Settings();
491: }
492: else if (dmaPlay.isRunning && ((sndCtrl & CROSSBAR_SNDCTRL_PLAY) == 0))
493: {
494: /* Create samples up until this point with current values */
1.1.1.2 root 495: Sound_Update(false);
1.1 root 496:
497: /* Turning off DMA play sound emulation */
498: dmaPlay.isRunning = 0;
499: dmaPlay.loopMode = 0;
500: nCbar_DmaSoundControl = sndCtrl;
501: }
502:
503: /* DMA Record mode */
504: if ((dmaRecord.isRunning == 0) && (sndCtrl & CROSSBAR_SNDCTRL_RECORD))
505: {
506: /* Turning on DMA record sound emulation */
507: dmaRecord.isRunning = 1;
508: nCbar_DmaSoundControl = sndCtrl;
1.1.1.2 root 509: dmaRecord.loopMode = (sndCtrl & 0x20) >> 5;
1.1 root 510: Crossbar_setDmaRecord_Settings();
511: }
512: else if (dmaRecord.isRunning && ((sndCtrl & CROSSBAR_SNDCTRL_RECORD) == 0))
513: {
514: /* Turning off DMA record sound emulation */
515: dmaRecord.isRunning = 0;
516: dmaRecord.loopMode = 0;
1.1.1.2 root 517: nCbar_DmaSoundControl = sndCtrl;
1.1 root 518: }
519: }
520:
521:
522: /**
523: * Read byte from sound frame start high register (0xff8903).
524: */
525: void Crossbar_FrameStartHigh_ReadByte(void)
526: {
527: if (crossbar.dmaSelected == 0) {
528: /* DMA Play selected */
529: IoMem_WriteByte(0xff8903, crossbar.dmaPlay_CurrentFrameStart >> 16);
530: }
531: else {
532: /* DMA Record selected */
533: IoMem_WriteByte(0xff8903, crossbar.dmaRecord_CurrentFrameStart >> 16);
534: }
535: }
536:
537: /**
538: * Write byte to sound frame start high register (0xff8903).
539: */
540: void Crossbar_FrameStartHigh_WriteByte(void)
541: {
542: Uint32 addr;
543:
544: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8903 (Sound frame start high) write: 0x%02x\n", IoMem_ReadByte(0xff8903));
545:
546: addr = (IoMem_ReadByte(0xff8903) << 16) + (IoMem_ReadByte(0xff8905) << 8) + IoMem_ReadByte(0xff8907);
547:
548: if (crossbar.dmaSelected == 0) {
549: /* DMA Play selected */
550: crossbar.dmaPlay_CurrentFrameStart = addr & ~1;
551: }
552: else {
553: /* DMA Record selected */
554: crossbar.dmaRecord_CurrentFrameStart = addr & ~1;
555: }
556: }
557:
558: /**
559: * Read byte from sound frame start medium register (0xff8905).
560: */
561: void Crossbar_FrameStartMed_ReadByte(void)
562: {
563: if (crossbar.dmaSelected == 0) {
564: /* DMA Play selected */
565: IoMem_WriteByte(0xff8905, crossbar.dmaPlay_CurrentFrameStart >> 8);
566: }
567: else {
568: /* DMA Record selected */
569: IoMem_WriteByte(0xff8905, crossbar.dmaRecord_CurrentFrameStart >> 8);
570: }
571: }
572:
573: /**
574: * Write byte to sound frame start medium register (0xff8905).
575: */
576: void Crossbar_FrameStartMed_WriteByte(void)
577: {
578: Uint32 addr;
579:
580: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8905 (Sound frame start med) write: 0x%02x\n", IoMem_ReadByte(0xff8905));
581:
582: addr = (IoMem_ReadByte(0xff8903) << 16) + (IoMem_ReadByte(0xff8905) << 8) + IoMem_ReadByte(0xff8907);
583:
584: if (crossbar.dmaSelected == 0) {
585: /* DMA Play selected */
586: crossbar.dmaPlay_CurrentFrameStart = addr & ~1;
587: }
588: else {
589: /* DMA Record selected */
590: crossbar.dmaRecord_CurrentFrameStart = addr & ~1;
591: }
592: }
593:
594: /**
595: * Read byte from sound frame start low register (0xff8907).
596: */
597: void Crossbar_FrameStartLow_ReadByte(void)
598: {
599: if (crossbar.dmaSelected == 0) {
600: /* DMA Play selected */
601: IoMem_WriteByte(0xff8907, crossbar.dmaPlay_CurrentFrameStart);
602: }
603: else {
604: /* DMA Record selected */
605: IoMem_WriteByte(0xff8907, crossbar.dmaRecord_CurrentFrameStart);
606: }
607: }
608:
609: /**
610: * Write byte to sound frame start low register (0xff8907).
611: */
612: void Crossbar_FrameStartLow_WriteByte(void)
613: {
614: Uint32 addr;
615:
616: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8907 (Sound frame start low) write: 0x%02x\n", IoMem_ReadByte(0xff8907));
617:
618: addr = (IoMem_ReadByte(0xff8903) << 16) + (IoMem_ReadByte(0xff8905) << 8) + IoMem_ReadByte(0xff8907);
619:
620: if (crossbar.dmaSelected == 0) {
621: /* DMA Play selected */
622: crossbar.dmaPlay_CurrentFrameStart = addr & ~1;
623: }
624: else {
625: /* DMA Record selected */
626: crossbar.dmaRecord_CurrentFrameStart = addr & ~1;
627: }
628: }
629:
630: /*-----------------------------------------------------------------------*/
631:
632: /**
633: * Read byte from sound frame count high register (0xff8909).
634: */
635: void Crossbar_FrameCountHigh_ReadByte(void)
636: {
637: if (crossbar.dmaSelected == 0) {
638: /* DMA Play selected */
639: IoMem_WriteByte(0xff8909, (dmaPlay.frameStartAddr + dmaPlay.frameCounter) >> 16);
640: }
641: else {
642: /* DMA Record selected */
643: IoMem_WriteByte(0xff8909, (dmaRecord.frameStartAddr + dmaRecord.frameCounter) >> 16);
644: }
645: }
646:
647: /**
648: * Write byte to sound frame count high register (0xff8909).
649: */
650: void Crossbar_FrameCountHigh_WriteByte(void)
651: {
652: Uint32 addr;
653:
654: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8909 (Sound frame count high) write: 0x%02x\n", IoMem_ReadByte(0xff8909));
655:
656: /* Compute frameCounter current address */
657: addr = (IoMem_ReadByte(0xff8909) << 16) + (IoMem_ReadByte(0xff890b) << 8) + IoMem_ReadByte(0xff890d);
658:
659: if (crossbar.dmaSelected == 0) {
660: /* DMA Play selected */
661: crossbar.dmaPlay_CurrentFrameCount = addr;
662: }
663: else {
664: /* DMA Record selected */
665: crossbar.dmaRecord_CurrentFrameCount = addr;
666: }
667: }
668:
669: /**
670: * Read byte from sound frame count medium register (0xff890b).
671: */
672: void Crossbar_FrameCountMed_ReadByte(void)
673: {
674: if (crossbar.dmaSelected == 0) {
675: /* DMA Play selected */
676: IoMem_WriteByte(0xff890b, (dmaPlay.frameStartAddr + dmaPlay.frameCounter) >> 8);
677: }
678: else {
679: /* DMA Record selected */
680: IoMem_WriteByte(0xff890b, (dmaRecord.frameStartAddr + dmaRecord.frameCounter) >> 8);
681: }
682: }
683:
684: /**
685: * Write byte to sound frame count medium register (0xff890b).
686: */
687: void Crossbar_FrameCountMed_WriteByte(void)
688: {
689: Uint32 addr;
690:
691: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff890b (Sound frame count med) write: 0x%02x\n", IoMem_ReadByte(0xff890b));
692:
693: /* Compute frameCounter current address */
694: addr = (IoMem_ReadByte(0xff8909) << 16) + (IoMem_ReadByte(0xff890b) << 8) + IoMem_ReadByte(0xff890d);
695:
696: if (crossbar.dmaSelected == 0) {
697: /* DMA Play selected */
698: crossbar.dmaPlay_CurrentFrameCount = addr;
699: }
700: else {
701: /* DMA Record selected */
702: crossbar.dmaRecord_CurrentFrameCount = addr;
703: }
704: }
705:
706: /**
707: * Read byte from sound frame count low register (0xff890d).
708: */
709: void Crossbar_FrameCountLow_ReadByte(void)
710: {
711: if (crossbar.dmaSelected == 0) {
712: /* DMA Play selected */
713: IoMem_WriteByte(0xff890d, (dmaPlay.frameStartAddr + dmaPlay.frameCounter));
714: }
715: else {
716: /* DMA Record selected */
717: IoMem_WriteByte(0xff890d, (dmaRecord.frameStartAddr + dmaRecord.frameCounter));
718: }
719: }
720:
721: /**
722: * Write byte to sound frame count low register (0xff890d).
723: */
724: void Crossbar_FrameCountLow_WriteByte(void)
725: {
726: Uint32 addr;
727:
728: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff890d (Sound frame count low) write: 0x%02x\n", IoMem_ReadByte(0xff890d));
729:
730: /* Compute frameCounter current address */
731: addr = (IoMem_ReadByte(0xff8909) << 16) + (IoMem_ReadByte(0xff890b) << 8) + IoMem_ReadByte(0xff890d);
732:
733: if (crossbar.dmaSelected == 0) {
734: /* DMA Play selected */
735: crossbar.dmaPlay_CurrentFrameCount = addr;
736: }
737: else {
738: /* DMA Record selected */
739: crossbar.dmaRecord_CurrentFrameCount = addr;
740: }
741: }
742:
743: /*-----------------------------------------------------------------------*/
744:
745: /**
746: * Read byte from sound frame end high register (0xff890f).
747: */
748: void Crossbar_FrameEndHigh_ReadByte(void)
749: {
750: if (crossbar.dmaSelected == 0) {
751: /* DMA Play selected */
752: IoMem_WriteByte(0xff890f, crossbar.dmaPlay_CurrentFrameEnd >> 16);
753: }
754: else {
755: /* DMA Record selected */
756: IoMem_WriteByte(0xff890f, crossbar.dmaRecord_CurrentFrameEnd >> 16);
757: }
758: }
759:
760: /**
761: * Write byte to sound frame end high register (0xff890f).
762: */
763: void Crossbar_FrameEndHigh_WriteByte(void)
764: {
765: Uint32 addr;
766:
767: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff890f (Sound frame end high) write: 0x%02x\n", IoMem_ReadByte(0xff890f));
768:
769: addr = (IoMem_ReadByte(0xff890f) << 16) + (IoMem_ReadByte(0xff8911) << 8) + IoMem_ReadByte(0xff8913);
770:
771: if (crossbar.dmaSelected == 0) {
772: /* DMA Play selected */
773: crossbar.dmaPlay_CurrentFrameEnd = addr & ~1;
774: }
775: else {
776: /* DMA Record selected */
777: crossbar.dmaRecord_CurrentFrameEnd = addr & ~1;
778: }
779: }
780:
781: /**
782: * Read byte from sound frame end medium register (0xff8911).
783: */
784: void Crossbar_FrameEndMed_ReadByte(void)
785: {
786: if (crossbar.dmaSelected == 0) {
787: /* DMA Play selected */
788: IoMem_WriteByte(0xff8911, crossbar.dmaPlay_CurrentFrameEnd >> 8);
789: }
790: else {
791: /* DMA Record selected */
792: IoMem_WriteByte(0xff8911, crossbar.dmaRecord_CurrentFrameEnd >> 8);
793: }
794: }
795:
796: /**
797: * Write byte to sound frame end medium register (0xff8911).
798: */
799: void Crossbar_FrameEndMed_WriteByte(void)
800: {
801: Uint32 addr;
802:
803: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8911 (Sound frame end med) write: 0x%02x\n", IoMem_ReadByte(0xff8911));
804:
805: addr = (IoMem_ReadByte(0xff890f) << 16) + (IoMem_ReadByte(0xff8911) << 8) + IoMem_ReadByte(0xff8913);
806:
807: if (crossbar.dmaSelected == 0) {
808: /* DMA Play selected */
809: crossbar.dmaPlay_CurrentFrameEnd = addr & ~1;
810: }
811: else {
812: /* DMA Record selected */
813: crossbar.dmaRecord_CurrentFrameEnd = addr & ~1;
814: }
815: }
816:
817: /**
818: * Read byte from sound frame end low register (0xff8913).
819: */
820: void Crossbar_FrameEndLow_ReadByte(void)
821: {
822: if (crossbar.dmaSelected == 0) {
823: /* DMA Play selected */
824: IoMem_WriteByte(0xff8913, crossbar.dmaPlay_CurrentFrameEnd);
825: }
826: else {
827: /* DMA Record selected */
828: IoMem_WriteByte(0xff8913, crossbar.dmaRecord_CurrentFrameEnd);
829: }
830: }
831:
832: /**
833: * Write byte to sound frame end low register (0xff8913).
834: */
835: void Crossbar_FrameEndLow_WriteByte(void)
836: {
837: Uint32 addr;
838:
839: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8913 (Sound frame end low) write: 0x%02x\n", IoMem_ReadByte(0xff8913));
840:
841: addr = (IoMem_ReadByte(0xff890f) << 16) + (IoMem_ReadByte(0xff8911) << 8) + IoMem_ReadByte(0xff8913);
842:
843: if (crossbar.dmaSelected == 0) {
844: /* DMA Play selected */
845: crossbar.dmaPlay_CurrentFrameEnd = addr & ~1;
846: }
847: else {
848: /* DMA Record selected */
849: crossbar.dmaRecord_CurrentFrameEnd = addr & ~1;
850: }
851: }
852:
853: /*-----------------------------------------------------------------------*/
854: /**
855: * Write byte to DMA track control (0xff8920).
856: */
857: void Crossbar_DmaTrckCtrl_WriteByte(void)
858: {
859: Uint8 sndCtrl = IoMem_ReadByte(0xff8920);
860:
861: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8920 (sound mode control) write: 0x%02x\n", sndCtrl);
862:
863: crossbar.playTracks = (sndCtrl & 3) + 1;
864: crossbar.track_monitored = (sndCtrl & 30) >> 4;
865: }
866:
867: /**
868: * Write word to sound mode register (0xff8921).
869: */
870: void Crossbar_SoundModeCtrl_WriteByte(void)
871: {
872: Uint8 sndCtrl = IoMem_ReadByte(0xff8921);
873:
874: LOG_TRACE(TRACE_CROSSBAR, "crossbar : $ff8921 (additional sound mode control) write: 0x%02x\n", sndCtrl);
875:
876: crossbar.is16Bits = (sndCtrl & 0x40) >> 6;
877: crossbar.isStereo = 1 - ((sndCtrl & 0x80) >> 7);
878: crossbar.steFreq = sndCtrl & 0x3;
879:
880: Crossbar_Recalculate_Clocks_Cycles();
881: }
882:
883: /**
884: * Write word to Falcon Crossbar source controller (0xff8930).
885: Source: A/D Convertor BIT 15 14 13 12
886: 00 - 25.175Mhz clock -------------------------+--+
887: 01 - External clock --------------------------+--+
888: 10 - 32Mhz clock (Don't use) -----------------+--'
889:
890: Source: External Input BIT 11 10 9 8
891: 0 - DSP IN, 1 - All others ----------------' | | |
892: 00 - 25.175Mhz clock -------------------------+--+ |
893: 01 - External clock --------------------------+--+ |
894: 10 - 32Mhz clock -----------------------------+--' |
895: 0 - Handshake on, 1 - Handshake off ----------------'
896:
897: Source: DSP-XMIT BIT 7 6 5 4
898: 0 - Tristate and disconnect DSP -----------+ | | |
899: (Only for external SSI use) | | | |
900: 1 - Connect DSP to multiplexer ------------' | | |
901: 00 - 25.175Mhz clock -------------------------+--+ |
902: 01 - External clock --------------------------+--+ |
903: 10 - 32Mhz clock -----------------------------+--' |
904: 0 - Handshake on, 1 - Handshake off ----------------'
905:
906: Source: DMA-PLAYBACK BIT 3 2 1 0
907: 0 - Handshaking on, dest DSP-REC ----------+ | | |
908: 1 - Destination is not DSP-REC ------------' | | |
909: 00 - 25.175Mhz clock -------------------------+--+ |
910: 01 - External clock --------------------------+--+ |
911: 10 - 32Mhz clock -----------------------------+--' |
912: 0 - Handshake on, 1 - Handshake off ----------------'
913: */
914: void Crossbar_SrcControler_WriteWord(void)
915: {
916: Uint16 nCbSrc = IoMem_ReadWord(0xff8930);
917:
918: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8930 (source device) write: 0x%04x\n", nCbSrc);
919:
920: dspXmit.isTristated = 1 - ((nCbSrc >> 7) & 0x1);
921: dspXmit.isInHandshakeMode = 1 - ((nCbSrc >> 4) & 0x1);
1.1.1.7 root 922:
1.1 root 923: crossbar.dspXmit_freq = (nCbSrc >> 5) & 0x3;
924: crossbar.dmaPlay_freq = (nCbSrc >> 1) & 0x3;
925: }
926:
927: /**
928: * Write word to Falcon Crossbar destination controller (0xff8932).
929: Source: D/A Convertor BIT 15 14 13 12
1.1.1.2 root 930: 00 - DMA output ------------------------------+--+
931: 01 - DSP output ------------------------------+--+
932: 10 - External input --------------------------+--+
933: 11 - ADC input -------------------------------+--'
1.1 root 934:
935: Source: External OutPut BIT 11 10 9 8
936: 0 - DSP OUT, 1 - All others ---------------' | | |
937: 00 - DMA output ------------------------------+--+ |
938: 01 - DSP output ------------------------------+--+ |
939: 10 - External input --------------------------+--+ |
940: 11 - ADC input -------------------------------+--' |
941: 0 - Handshake on, 1 - Handshake off ----------------'
942:
943: Source: DSP-RECEIVE BIT 7 6 5 4
944: 0 - Tristate and disconnect DSP -----------+ | | |
945: (Only for external SSI use) | | | |
946: 1 - Connect DSP to multiplexer ------------' | | |
947: 00 - DMA output ------------------------------+--+ |
948: 01 - DSP output ------------------------------+--+ |
949: 10 - External input --------------------------+--+ |
950: 11 - ADC input -------------------------------+--' |
951: 0 - Handshake on, 1 - Handshake off ----------------'
952:
953: Source: DMA-RECORD BIT 3 2 1 0
954: 0 - Handshaking on, dest DSP-XMIT ---------+ | | |
955: 1 - All -----------------------------------' | | |
956: 00 - DMA output ------------------------------+--+ |
957: 01 - DSP output ------------------------------+--+ |
958: 10 - External input --------------------------+--+ |
959: 11 - ADC input -------------------------------+--' |
960: 0 - Handshake on, 1 - Handshake off ----------------'
961: */
962: void Crossbar_DstControler_WriteWord(void)
963: {
964: Uint16 destCtrl = IoMem_ReadWord(0xff8932);
965:
966: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8932 (destination device) write: 0x%04x\n", destCtrl);
967:
968: dspReceive.isTristated = 1 - ((destCtrl & 0x80) >> 7);
969: dspReceive.isInHandshakeMode = 1 - ((destCtrl & 0x10) >> 4);
970:
971: /* destinations devices connexions */
972: dspReceive.isConnectedToCodec = (destCtrl & 0x60) == 0x60 ? 1 : 0;
973: dspReceive.isConnectedToDsp = (destCtrl & 0x60) == 0x20 ? 1 : 0;
974: dspReceive.isConnectedToDma = (destCtrl & 0x60) == 0x00 ? 1 : 0;
975:
976: dmaRecord.isConnectedToCodec = (destCtrl & 0x6) == 0x6 ? 1 : 0;
977: dmaRecord.isConnectedToDsp = (destCtrl & 0x6) == 0x2 ? 1 : 0;
978: dmaRecord.isConnectedToDma = (destCtrl & 0x6) == 0x0 ? 1 : 0;
979:
980: dac.isConnectedToCodec = (destCtrl & 0x6000) == 0x6000 ? 1 : 0;
981: dac.isConnectedToDsp = (destCtrl & 0x6000) == 0x2000 ? 1 : 0;
982: dac.isConnectedToDma = (destCtrl & 0x6000) == 0x0000 ? 1 : 0;
983:
984: /* sources devices connexions */
985: dspXmit.isConnectedToCodec = (destCtrl & 0x6000) == 0x2000 ? 1 : 0;
986: dspXmit.isConnectedToDsp = (destCtrl & 0x60) == 0x20 ? 1 : 0;
987: dspXmit.isConnectedToDma = (destCtrl & 0x6) == 0x2 ? 1 : 0;
988:
989: dmaPlay.isConnectedToCodec = (destCtrl & 0x6000) == 0x0000 ? 1 : 0;
990: dmaPlay.isConnectedToDsp = (destCtrl & 0x60) == 0x00 ? 1 : 0;
991: dmaPlay.isConnectedToDma = (destCtrl & 0x6) == 0x0 ? 1 : 0;
992:
993: adc.isConnectedToCodec = (destCtrl & 0x6000) == 0x6000 ? 1 : 0;
994: adc.isConnectedToDsp = (destCtrl & 0x60) == 0x60 ? 1 : 0;
995: adc.isConnectedToDma = (destCtrl & 0x6) == 0x6 ? 1 : 0;
996:
1.1.1.2 root 997: dmaPlay.isConnectedToDspInHandShakeMode = (((destCtrl >> 4) & 7) == 0 ? 1 : 0);
1.1.1.3 root 998: dmaPlay.handshakeMode_Frame = dmaPlay.isConnectedToDspInHandShakeMode;
999:
1.1 root 1000: dmaRecord.isConnectedToDspInHandShakeMode = ((destCtrl & 0xf) == 2 ? 1 : 0);
1001: }
1002:
1003: /**
1004: * Write byte to external clock divider register (0xff8934).
1005: */
1006: void Crossbar_FreqDivExt_WriteByte(void)
1007: {
1008: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8934 (ext. clock divider) write: 0x%02x\n", IoMem_ReadByte(0xff8934));
1009: }
1010:
1011: /**
1012: * Write byte to internal clock divider register (0xff8935).
1013: */
1014: void Crossbar_FreqDivInt_WriteByte(void)
1015: {
1016: Uint8 clkDiv = IoMem_ReadByte(0xff8935);
1017:
1018: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8935 (int. clock divider) write: 0x%02x\n", clkDiv);
1019:
1020: crossbar.int_freq_divider = clkDiv & 0xf;
1021: Crossbar_Recalculate_Clocks_Cycles();
1022: }
1023:
1024: /**
1025: * Write byte to record track select register (0xff8936).
1026: * 0 = Record 1 track
1027: * 1 = Record 2 tracks
1028: * 2 = Record 3 tracks
1029: * 3 = Record 4 tracks
1030: */
1031: void Crossbar_TrackRecSelect_WriteByte(void)
1032: {
1033: Uint8 recTrack = IoMem_ReadByte(0xff8936);
1034:
1035: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8936 (record track select) write: 0x%02x\n", recTrack);
1036:
1037: crossbar.recordTracks = recTrack & 3;
1038: }
1039:
1040: /**
1041: * Write byte to CODEC input source from 16 bit adder (0xff8937).
1042: * Bit 1 : source = multiplexer
1.1.1.7 root 1043: * Bit 0 : source = A/D convertor
1.1 root 1044: */
1045: void Crossbar_CodecInput_WriteByte(void)
1046: {
1047: Uint8 inputSource = IoMem_ReadByte(0xff8937);
1048:
1049: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8937 (CODEC input) write: 0x%02x\n", IoMem_ReadByte(0xff8937));
1050:
1051: crossbar.codecInputSource = inputSource & 3;
1052: }
1053:
1054: /**
1055: * Write byte to A/D converter input for L+R channel (0xff8938).
1056: * Bit 1 : Left (0 = Microphone ; 1 = PSG soundchip)
1057: * Bit 0 : Right (0 = Microphone ; 1 = PSG soundchip)
1058: */
1059: void Crossbar_AdcInput_WriteByte(void)
1060: {
1061: Uint8 input = IoMem_ReadByte(0xff8938);
1062:
1063: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8938 (ADC input) write: 0x%02x\n", IoMem_ReadByte(0xff8938));
1064:
1065: crossbar.codecAdcInput = input & 3;
1066: }
1067:
1068: /**
1069: * Write byte to input amplifier register (amplification for ADC device) (0xff8939).
1070: * Bits LLLLRRRR
1071: * Amplification is in +1.5 dB steps
1072: */
1073: void Crossbar_InputAmp_WriteByte(void)
1074: {
1075: Uint8 amplification = IoMem_ReadByte(0xff8939);
1076:
1077: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8939 (CODEC channel amplification) write: 0x%02x\n", IoMem_ReadByte(0xff8939));
1078:
1079: crossbar.gainSettingLeft = Crossbar_ADC_volume_table[amplification >> 4];
1080: crossbar.gainSettingRight = Crossbar_ADC_volume_table[amplification & 0xf];
1081: }
1082:
1083: /**
1084: * Write byte to channel reduction register (attenuation for DAC device) (0xff893a).
1.1.1.5 root 1085: * Bits XXXXLLLL RRRRXXXX
1.1 root 1086: * Reduction is in -1.5 dB steps
1087: */
1.1.1.5 root 1088: void Crossbar_OutputReduct_WriteWord(void)
1.1 root 1089: {
1.1.1.5 root 1090: Uint16 reduction = IoMem_ReadWord(0xff893a);
1.1 root 1091:
1.1.1.5 root 1092: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff893a (CODEC channel attenuation) write: 0x%04x\n", reduction);
1.1 root 1093:
1.1.1.5 root 1094: crossbar.attenuationSettingLeft = Crossbar_DAC_volume_table[(reduction >> 8) & 0x0f];
1095: crossbar.attenuationSettingRight = Crossbar_DAC_volume_table[(reduction >> 4) & 0x0f];
1.1 root 1096: }
1097:
1098: /**
1099: * Write word to CODEC status register (0xff893c).
1100: * Bit 1 : Left Channel Overflow (0/1)
1101: * Bit 0 : Right Channel Overflow (0/1)
1102: */
1103: void Crossbar_CodecStatus_WriteWord(void)
1104: {
1105: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff893c (CODEC status) write: 0x%04x\n", IoMem_ReadWord(0xff893c));
1106: }
1107:
1108:
1109:
1110: /*----------------------------------------------------------------------*/
1111: /*------------------------- Crossbar functions -------------------------*/
1112: /*----------------------------------------------------------------------*/
1113:
1114: /**
1115: * Recalculates internal clocks 25 Mhz and 32 Mhz cycles
1116: */
1.1.1.8 ! root 1117: void Crossbar_Recalculate_Clocks_Cycles(void)
1.1 root 1118: {
1119: double cyclesClk;
1120:
1121: crossbar.clock25_cycles_counter = 0;
1122: crossbar.clock32_cycles_counter = 0;
1123:
1124: /* Calculate 25 Mhz clock cycles */
1.1.1.8 ! root 1125: #ifdef OLD_CPU_SHIFT
1.1 root 1126: cyclesClk = ((double)CPU_FREQ / Crossbar_DetectSampleRate(25)) / (double)(crossbar.playTracks) / 2.0;
1.1.1.8 ! root 1127: #else
! 1128: /* Take nCpuFreqShift into account to keep a constant sound rate at all cpu freq */
! 1129: cyclesClk = ((double)( ( CPU_FREQ << nCpuFreqShift ) ) / Crossbar_DetectSampleRate(25)) / (double)(crossbar.playTracks) / 2.0;
! 1130: #endif
1.1 root 1131: crossbar.clock25_cycles = (int)(cyclesClk);
1132: crossbar.clock25_cycles_decimal = (int)((cyclesClk - (double)(crossbar.clock25_cycles)) * (double)DECIMAL_PRECISION);
1133:
1134: /* Calculate 32 Mhz clock cycles */
1.1.1.8 ! root 1135: #ifdef OLD_CPU_SHIFT
1.1 root 1136: cyclesClk = ((double)CPU_FREQ / Crossbar_DetectSampleRate(32)) / (double)(crossbar.playTracks) / 2.0;
1.1.1.8 ! root 1137: #else
! 1138: /* Take nCpuFreqShift into account to keep a constant sound rate at all cpu freq */
! 1139: cyclesClk = ((double)( ( CPU_FREQ << nCpuFreqShift ) ) / Crossbar_DetectSampleRate(32)) / (double)(crossbar.playTracks) / 2.0;
! 1140: #endif
1.1 root 1141: crossbar.clock32_cycles = (int)(cyclesClk);
1142: crossbar.clock32_cycles_decimal = (int)((cyclesClk - (double)(crossbar.clock32_cycles)) * (double)DECIMAL_PRECISION);
1.1.1.7 root 1143:
1.1 root 1144: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : Recalculate_clock_Cycles\n");
1145: LOG_TRACE(TRACE_CROSSBAR, " clock25 : %d\n", crossbar.clock25_cycles);
1146: LOG_TRACE(TRACE_CROSSBAR, " clock32 : %d\n", crossbar.clock32_cycles);
1147:
1148: /* Verify if the new frequency doesn't mute the DAC */
1149: crossbar.isDacMuted = 0;
1150: if ((crossbar.int_freq_divider == 0) && (crossbar.steFreq == 0))
1151: crossbar.isDacMuted = 1;
1152:
1.1.1.7 root 1153: if ((crossbar.int_freq_divider == 6) || (crossbar.int_freq_divider == 8) ||
1.1 root 1154: (crossbar.int_freq_divider == 10) || (crossbar.int_freq_divider >= 12)) {
1155: crossbar.isDacMuted = 1;
1.1.1.4 root 1156: LOG_TRACE(TRACE_CROSSBAR, " DAC is muted\n");
1.1 root 1157: }
1.1.1.2 root 1158:
1159: // Compute Ratio between host computer sound frequency and Hatari's sound frequency.
1160: Crossbar_Compute_Ratio();
1.1.1.8 ! root 1161:
! 1162: // Ensure dac.writePosition is correctly set based on current dac.readPosition
! 1163: // -> force dac.wordCount=0 to update dac.writePosition on next call to Crossbar_GenerateSamples()
! 1164: dac.wordCount = 0;
1.1.1.2 root 1165: }
1166:
1167: /**
1.1.1.7 root 1168: * Compute Ratio between host computer sound frequency and Hatari's DAC sound frequency and
1.1.1.4 root 1169: * ratio between hatari's DAC sound frequency and host's sound frequency.
1170: * Both values use << 32 to simulate floating point precision
1.1.1.2 root 1171: * Can be called by audio.c if a sound frequency value is changed in the parameter GUI.
1172: */
1173: void Crossbar_Compute_Ratio(void)
1174: {
1.1.1.4 root 1175: crossbar.frequence_ratio = ( ((Sint64)Crossbar_DetectSampleRate(25)) << 32) / nAudioFrequency;
1176: crossbar.frequence_ratio2 = ( ((Sint64)nAudioFrequency) << 32) / Crossbar_DetectSampleRate(25);
1.1 root 1177: }
1178:
1179: /**
1180: * Detect sample rate frequency
1181: * clock : value of the internal clock (25 or 32).
1182: */
1.1.1.4 root 1183: static int Crossbar_DetectSampleRate(Uint16 clock)
1.1 root 1184: {
1185: /* Ste compatible sound */
1186: if (crossbar.int_freq_divider == 0) {
1187: crossbar.isInSteFreqMode = 1;
1188: return Ste_SampleRates[crossbar.steFreq];
1189: }
1190:
1191: crossbar.isInSteFreqMode = 0;
1192:
1193: /* 25 Mhz internal clock */
1194: if (clock == 25)
1195: return Falcon_SampleRates_25Mhz[crossbar.int_freq_divider - 1];
1196:
1197: /* 32 Mhz internal clock */
1198: return Falcon_SampleRates_32Mhz[crossbar.int_freq_divider - 1];
1199: }
1200:
1201: /**
1202: * Start internal 25 Mhz clock interrupt.
1203: */
1204: static void Crossbar_Start_InterruptHandler_25Mhz(void)
1205: {
1206: Uint32 cycles_25;
1.1.1.7 root 1207:
1.1.1.8 ! root 1208: //fprintf ( stderr , "start int25 %x %x %x %x\n" , crossbar.clock25_cycles, crossbar.clock25_cycles_counter, crossbar.clock25_cycles_decimal, crossbar.pendingCyclesOver25 );
1.1 root 1209: cycles_25 = crossbar.clock25_cycles;
1210: crossbar.clock25_cycles_counter += crossbar.clock25_cycles_decimal;
1.1.1.7 root 1211:
1.1 root 1212: if (crossbar.clock25_cycles_counter >= DECIMAL_PRECISION) {
1213: crossbar.clock25_cycles_counter -= DECIMAL_PRECISION;
1214: cycles_25 ++;
1215: }
1216:
1217: if (crossbar.pendingCyclesOver25 >= cycles_25) {
1218: crossbar.pendingCyclesOver25 -= cycles_25;
1219: cycles_25 = 0;
1220: }
1221: else {
1222: cycles_25 -= crossbar.pendingCyclesOver25;
1223: crossbar.pendingCyclesOver25 = 0;
1224: }
1225:
1226: CycInt_AddRelativeInterrupt(cycles_25, INT_CPU_CYCLE, INTERRUPT_CROSSBAR_25MHZ);
1227: }
1228:
1229: /**
1230: * Start internal 32 Mhz clock interrupt.
1231: */
1232: static void Crossbar_Start_InterruptHandler_32Mhz(void)
1233: {
1234: Uint32 cycles_32;
1.1.1.7 root 1235:
1.1.1.8 ! root 1236: //fprintf ( stderr , "start int32 %x %x %x %x\n" , crossbar.clock32_cycles, crossbar.clock32_cycles_counter, crossbar.clock32_cycles_decimal, crossbar.pendingCyclesOver32 );
1.1 root 1237: cycles_32 = crossbar.clock32_cycles;
1238: crossbar.clock32_cycles_counter += crossbar.clock32_cycles_decimal;
1239:
1240: if (crossbar.clock32_cycles_counter >= DECIMAL_PRECISION) {
1241: crossbar.clock32_cycles_counter -= DECIMAL_PRECISION;
1242: cycles_32 ++;
1243: }
1244:
1245: if (crossbar.pendingCyclesOver32 >= cycles_32){
1246: crossbar.pendingCyclesOver32 -= cycles_32;
1247: cycles_32 = 0;
1248: }
1249: else {
1250: cycles_32 -= crossbar.pendingCyclesOver32;
1251: crossbar.pendingCyclesOver32 = 0;
1252: }
1253:
1254: CycInt_AddRelativeInterrupt(cycles_32, INT_CPU_CYCLE, INTERRUPT_CROSSBAR_32MHZ);
1255: }
1256:
1257:
1258: /**
1259: * Execute transfers for internal 25 Mhz clock.
1260: */
1261: void Crossbar_InterruptHandler_25Mhz(void)
1262: {
1.1.1.8 ! root 1263: //fprintf ( stderr , "int25 %x\n" , crossbar.pendingCyclesOver25 );
1.1 root 1264: /* How many cycle was this sound interrupt delayed (>= 0) */
1265: crossbar.pendingCyclesOver25 += -INT_CONVERT_FROM_INTERNAL ( PendingInterruptCount , INT_CPU_CYCLE );
1266:
1267: /* Remove this interrupt from list and re-order */
1268: CycInt_AcknowledgeInterrupt();
1269:
1270: /* If transfer mode is in Ste mode, use only this clock for all the transfers */
1271: if (crossbar.isInSteFreqMode) {
1272: Crossbar_Process_DSPXmit_Transfer();
1273: Crossbar_Process_DMAPlay_Transfer();
1274: Crossbar_Process_ADCXmit_Transfer();
1.1.1.7 root 1275:
1.1 root 1276: /* Restart the 25 Mhz clock interrupt */
1277: Crossbar_Start_InterruptHandler_25Mhz();
1278: return;
1279: }
1280:
1281: Crossbar_Process_ADCXmit_Transfer();
1.1.1.7 root 1282:
1.1 root 1283: /* DSP Play transfer ? */
1284: if (crossbar.dspXmit_freq == CROSSBAR_FREQ_25MHZ) {
1285: Crossbar_Process_DSPXmit_Transfer();
1286: }
1.1.1.7 root 1287:
1.1 root 1288: /* DMA Play transfer ? */
1289: if (crossbar.dmaPlay_freq == CROSSBAR_FREQ_25MHZ) {
1290: Crossbar_Process_DMAPlay_Transfer();
1291: }
1292:
1293: /* Restart the 25 Mhz clock interrupt */
1294: Crossbar_Start_InterruptHandler_25Mhz();
1295: }
1296:
1297: /**
1298: * Execute transfers for internal 32 Mhz clock.
1299: */
1300: void Crossbar_InterruptHandler_32Mhz(void)
1301: {
1.1.1.8 ! root 1302: //fprintf ( stderr , "int32 %x\n" , crossbar.pendingCyclesOver32 );
1.1 root 1303: /* How many cycle was this sound interrupt delayed (>= 0) */
1304: crossbar.pendingCyclesOver32 += -INT_CONVERT_FROM_INTERNAL ( PendingInterruptCount , INT_CPU_CYCLE );
1305:
1306: /* Remove this interrupt from list and re-order */
1307: CycInt_AcknowledgeInterrupt();
1308:
1309: /* If transfer mode is in Ste mode, don't use this clock for all the transfers */
1310: if (crossbar.isInSteFreqMode) {
1311: /* Restart the 32 Mhz clock interrupt */
1312: Crossbar_Start_InterruptHandler_32Mhz();
1313: return;
1314: }
1.1.1.7 root 1315:
1.1 root 1316: /* DSP Play transfer ? */
1317: if (crossbar.dspXmit_freq == CROSSBAR_FREQ_32MHZ) {
1318: Crossbar_Process_DSPXmit_Transfer();
1319: }
1.1.1.7 root 1320:
1.1 root 1321: /* DMA Play transfer ? */
1322: if (crossbar.dmaPlay_freq == CROSSBAR_FREQ_32MHZ) {
1323: Crossbar_Process_DMAPlay_Transfer();
1324: }
1325:
1326: /* Restart the 32 Mhz clock interrupt */
1327: Crossbar_Start_InterruptHandler_32Mhz();
1328: }
1329:
1330:
1331: /*----------------------------------------------------------------------*/
1332: /*--------------------- DSP Xmit processing ----------------------------*/
1333: /*----------------------------------------------------------------------*/
1334:
1335: /**
1336: * Process DSP xmit to crossbar transfer
1337: */
1338: static void Crossbar_Process_DSPXmit_Transfer(void)
1339: {
1340: Uint16 frame=0;
1341: Sint32 data;
1.1.1.7 root 1342:
1.1.1.2 root 1343: /* If DSP Xmit is tristated, do nothing */
1344: if (dspXmit.isTristated)
1345: return;
1.1 root 1346:
1347: /* Is DSP Xmit connected to DMA Record in handshake mode ? */
1348: if (dmaRecord.isConnectedToDspInHandShakeMode) {
1349: Crossbar_Process_DMARecord_HandshakeMode();
1350: return;
1351: }
1352:
1353: /* Is DSP Xmit connected to something ? */
1354: if (!dspXmit.isConnectedToCodec && !dspXmit.isConnectedToDma && !dspXmit.isConnectedToDsp)
1355: return;
1356:
1357: if (dspXmit.wordCount == 0) {
1358: frame = 1;
1359: }
1360:
1361: /* Send the frame status to the DSP SSI Xmit */
1362: DSP_SsiReceive_SC2(frame);
1363:
1364: /* Send the clock to the DSP SSI Xmit */
1365: DSP_SsiReceive_SCK();
1366:
1367: /* read data from DSP Xmit */
1368: data = DSP_SsiReadTxValue();
1369:
1.1.1.4 root 1370: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : DSP --> Crossbar transfer\t0x%06x\n", data);
1371:
1.1 root 1372: /* Send DSP data to the DAC ? */
1373: if (dspXmit.isConnectedToCodec) {
1374: Crossbar_SendDataToDAC(data, dspXmit.wordCount);
1375: }
1376:
1377: /* Send DSP data to the DMA record ? */
1378: if (dspXmit.isConnectedToDma) {
1379: Crossbar_SendDataToDmaRecord(data);
1380: }
1381:
1382: /* Send DSP data to the DSP in ? */
1383: if (dspXmit.isConnectedToDsp) {
1384: Crossbar_SendDataToDspReceive(data, frame);
1385: }
1386:
1387: /* increase dspXmit.wordCount for next sample */
1388: dspXmit.wordCount++;
1389: if (dspXmit.wordCount >= (crossbar.playTracks * 2)) {
1390: dspXmit.wordCount = 0;
1391: }
1392: }
1393:
1394: /*----------------------------------------------------------------------*/
1395: /*--------------------- DSP Receive processing -------------------------*/
1396: /*----------------------------------------------------------------------*/
1397:
1398: /**
1399: * Transmit data from crossbar to DSP receive.
1400: */
1401: static void Crossbar_SendDataToDspReceive(Uint32 value, Uint16 frame)
1402: {
1403: /* Verify that DSP IN is not tristated */
1404: if (dspReceive.isTristated) {
1405: return;
1406: }
1407:
1408: /* Send sample to DSP receive */
1409: DSP_SsiWriteRxValue(value);
1410:
1411: /* Send the frame status to the DSP SSI receive */
1412: /* only in non hanshake mode */
1413: if (dmaPlay.handshakeMode_Frame == 0) {
1414: DSP_SsiReceive_SC1(frame);
1415: }
1416:
1417: dmaPlay.handshakeMode_Frame = 0;
1.1.1.7 root 1418:
1.1 root 1419: /* Send the clock to the DSP SSI receive */
1420: DSP_SsiReceive_SC0();
1421: }
1422:
1423: /*----------------------------------------------------------------------*/
1424: /*--------------------- DMA PLAY sound processing ----------------------*/
1425: /*----------------------------------------------------------------------*/
1426:
1427: /**
1428: * Set DMA Play sound start frame buffer, stop frame buffer, frame length
1429: */
1430: static void Crossbar_setDmaPlay_Settings(void)
1431: {
1432: /* DMA setings */
1433: dmaPlay.frameStartAddr = crossbar.dmaPlay_CurrentFrameStart;
1434: dmaPlay.frameEndAddr = crossbar.dmaPlay_CurrentFrameEnd;
1435: dmaPlay.frameLen = dmaPlay.frameEndAddr - dmaPlay.frameStartAddr;
1436: // dmaPlay.frameCounter = crossbar.dmaPlay_CurrentFrameCount - crossbar.dmaPlay_CurrentFrameStart;
1437: dmaPlay.frameCounter = 0;
1438:
1439: if (dmaPlay.frameEndAddr <= dmaPlay.frameStartAddr)
1440: {
1441: Log_Printf(LOG_WARN, "crossbar DMA Play: Illegal buffer size (from 0x%06x to 0x%06x)\n",
1442: dmaPlay.frameStartAddr, dmaPlay.frameEndAddr);
1443: }
1444: }
1445:
1446: /**
1447: * Process DMA Play transfer to crossbar
1448: */
1449: static void Crossbar_Process_DMAPlay_Transfer(void)
1450: {
1.1.1.2 root 1451: Uint16 temp, increment_frame;
1.1 root 1452: Sint16 value, eightBits;
1453: Sint8 *pFrameStart;
1454: Uint8 dmaCtrlReg;
1.1.1.7 root 1455:
1.1 root 1456: /* if DMA play is not running, return */
1457: if (dmaPlay.isRunning == 0)
1458: return;
1459:
1460: pFrameStart = (Sint8 *)&STRam[dmaPlay.frameStartAddr];
1.1.1.2 root 1461: increment_frame = 0;
1.1.1.7 root 1462:
1.1 root 1463: /* 16 bits stereo mode ? */
1464: if (crossbar.is16Bits) {
1465: eightBits = 1;
1466: value = (Sint16)do_get_mem_word(&pFrameStart[dmaPlay.frameCounter]);
1.1.1.2 root 1467: increment_frame = 2;
1.1 root 1468: }
1469: /* 8 bits stereo ? */
1470: else if (crossbar.isStereo) {
1471: eightBits = 64;
1472: value = (Sint16) pFrameStart[dmaPlay.frameCounter];
1.1.1.2 root 1473: increment_frame = 1;
1.1 root 1474: }
1475: /* 8 bits mono */
1476: else {
1477: eightBits = 64;
1478: value = (Sint16) pFrameStart[dmaPlay.frameCounter];
1479: if ((dmaPlay.currentFrame & 1) == 0) {
1.1.1.2 root 1480: increment_frame = 1;
1.1 root 1481: }
1482: }
1.1.1.2 root 1483:
1.1.1.8 ! root 1484: //fprintf ( stderr , "cbar %x %x %x\n" , dmaPlay.frameCounter , value , increment_frame );
1.1.1.3 root 1485: if (dmaPlay.isConnectedToDspInHandShakeMode) {
1486: /* Handshake mode */
1.1.1.2 root 1487: if (dmaPlay.handshakeMode_Frame == 0)
1488: return;
1489:
1490: dmaPlay.frameCounter += increment_frame;
1491:
1.1.1.7 root 1492: /* Special undocumented transfer mode :
1.1.1.3 root 1493: When DMA Play --> DSP Receive is in HandShake mode at 32 Mhz,
1.1.1.2 root 1494: datas are shifted 2 bits on the left after the transfer.
1.1.1.7 root 1495: This occurs with all demos using the Mpeg2 player from nocrew (amanita, LostBlubb, Wait, ...)
1.1.1.2 root 1496: */
1.1.1.3 root 1497: if (crossbar.dmaPlay_freq == CROSSBAR_FREQ_32MHZ) {
1498: temp = (crossbar.save_special_transfer<<2) + ((value & 0xc000)>>14);
1499: crossbar.save_special_transfer = value;
1500: value = temp;
1501: }
1.1.1.2 root 1502: }
1503: else {
1.1.1.3 root 1504: /* Non Handshake mode */
1.1.1.2 root 1505: dmaPlay.frameCounter += increment_frame;
1506: }
1507:
1.1 root 1508: /* Send sample to the DMA record ? */
1509: if (dmaPlay.isConnectedToDma) {
1510: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : DMA Play --> DMA record\n");
1511: Crossbar_SendDataToDmaRecord(value);
1512: }
1513:
1514: /* Send sample to the DAC ? */
1515: if (dmaPlay.isConnectedToCodec) {
1516: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : DMA Play --> DAC\n");
1517: Crossbar_SendDataToDAC(value * eightBits, dmaPlay.currentFrame);
1518: }
1519:
1520: /* Send sample to the DSP in ? */
1521: if (dmaPlay.isConnectedToDsp) {
1522: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : DMA Play --> DSP record\n");
1523: /* New frame ? */
1524: if (dmaPlay.currentFrame == 0) {
1525: Crossbar_SendDataToDspReceive(value, 1);
1526: }
1527: else {
1528: Crossbar_SendDataToDspReceive(value, 0);
1529: }
1530: }
1531:
1532: /* increase dmaPlay.currentFrame for next sample */
1533: dmaPlay.currentFrame ++;
1534: if (dmaPlay.currentFrame >= (crossbar.playTracks * 2)) {
1535: dmaPlay.currentFrame = 0;
1536: }
1537:
1538: /* Check if end-of-frame has been reached and raise interrupts if needed. */
1539: if (dmaPlay.frameCounter >= dmaPlay.frameLen)
1.1.1.7 root 1540: {
1.1 root 1541: /* Send a MFP15_Int (I7) at end of replay buffer if enabled */
1542: if (dmaPlay.mfp15_int) {
1.1.1.5 root 1543: MFP_InputOnChannel ( MFP_INT_GPIP7 , 0 );
1.1 root 1544: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : MFP15 (IT7) interrupt from DMA play\n");
1545: }
1546:
1547: /* Send a TimerA_Int at end of replay buffer if enabled */
1548: if (dmaPlay.timerA_int) {
1549: if (MFP_TACR == 0x08) { /* Is timer A in Event Count mode? */
1550: MFP_TimerA_EventCount_Interrupt();
1551: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : MFP Timer A interrupt from DMA play\n");
1552: }
1553: }
1554:
1555: if (dmaPlay.loopMode) {
1556: Crossbar_setDmaPlay_Settings();
1.1.1.7 root 1557: }
1.1 root 1558: else {
1.1.1.2 root 1559: /* Create samples up until this point with current values */
1560: Sound_Update(false);
1561:
1.1 root 1562: dmaCtrlReg = IoMem_ReadByte(0xff8901) & 0xfe;
1.1.1.2 root 1563: IoMem_WriteByte(0xff8901, dmaCtrlReg);
1564:
1565: /* Turning off DMA play sound emulation */
1566: dmaPlay.isRunning = 0;
1567: dmaPlay.loopMode = 0;
1568: nCbar_DmaSoundControl = dmaCtrlReg;
1.1 root 1569: }
1570: }
1571: }
1572:
1573: /**
1574: * Function called when DmaPlay is in handshake mode */
1575: void Crossbar_DmaPlayInHandShakeMode(void)
1576: {
1577: dmaPlay.handshakeMode_Frame = 1;
1578: }
1579:
1580: /*----------------------------------------------------------------------*/
1581: /*--------------------- DMA Record processing --------------------------*/
1582: /*----------------------------------------------------------------------*/
1583:
1584: /**
1585: * Set DMA Record sound start frame buffer, stop frame buffer, frame length
1586: */
1587: static void Crossbar_setDmaRecord_Settings(void)
1588: {
1589: /* DMA setings */
1590: dmaRecord.frameStartAddr = crossbar.dmaRecord_CurrentFrameStart;
1591: dmaRecord.frameEndAddr = crossbar.dmaRecord_CurrentFrameEnd;
1592: dmaRecord.frameLen = dmaRecord.frameEndAddr - dmaRecord.frameStartAddr;
1593: // dmaRecord.frameCounter = crossbar.dmaRecord_CurrentFrameCount - crossbar.dmaRecord_CurrentFrameStart;
1594: dmaRecord.frameCounter = 0;
1595:
1596: if (dmaRecord.frameEndAddr <= dmaRecord.frameStartAddr) {
1597: Log_Printf(LOG_WARN, "crossbar DMA Record: Illegal buffer size (from 0x%06x to 0x%06x)\n",
1598: dmaRecord.frameStartAddr, dmaRecord.frameEndAddr);
1599: }
1600: }
1601:
1602: /**
1603: * DMA Record processing
1604: */
1605: void Crossbar_SendDataToDmaRecord(Sint16 value)
1606: {
1607: Sint8 *pFrameStart;
1608: Uint8 dmaCtrlReg;
1609:
1610: if (dmaRecord.isRunning == 0) {
1611: return;
1612: }
1.1.1.7 root 1613:
1.1 root 1614: pFrameStart = (Sint8 *)&STRam[dmaRecord.frameStartAddr];
1615:
1616: /* 16 bits stereo mode ? */
1617: if (crossbar.is16Bits) {
1618: do_put_mem_word(&pFrameStart[dmaRecord.frameCounter], value);
1619: dmaRecord.frameCounter += 2;
1620: }
1621: /* 8 bits stereo ? */
1622: else if (crossbar.isStereo) {
1623: do_put_mem_word(&pFrameStart[dmaRecord.frameCounter], value);
1624: dmaRecord.frameCounter += 2;
1625: // pFrameStart[dmaRecord.frameCounter] = (Uint8)value;
1626: // dmaRecord.frameCounter ++;
1627: }
1628: /* 8 bits mono */
1629: else {
1630: pFrameStart[dmaRecord.frameCounter] = (Uint8)value;
1631: dmaRecord.frameCounter ++;
1632: }
1633:
1634: /* Check if end-of-frame has been reached and raise interrupts if needed. */
1635: if (dmaRecord.frameCounter >= dmaRecord.frameLen)
1636: {
1637: /* Send a MFP15_Int (I7) at end of record buffer if enabled */
1638: if (dmaRecord.mfp15_int) {
1.1.1.5 root 1639: MFP_InputOnChannel ( MFP_INT_GPIP7 , 0 );
1.1 root 1640: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : MFP15 (IT7) interrupt from DMA record\n");
1641: }
1.1.1.7 root 1642:
1.1 root 1643: /* Send a TimerA_Int at end of record buffer if enabled */
1644: if (dmaRecord.timerA_int) {
1645: if (MFP_TACR == 0x08) /* Is timer A in Event Count mode? */
1646: MFP_TimerA_EventCount_Interrupt();
1.1.1.7 root 1647: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : MFP Timer A interrupt from DMA record\n");
1.1 root 1648: }
1649:
1650: if (dmaRecord.loopMode) {
1651: Crossbar_setDmaRecord_Settings();
1652: }
1653: else {
1654: dmaCtrlReg = IoMem_ReadByte(0xff8901) & 0xef;
1.1.1.2 root 1655: IoMem_WriteByte(0xff8901, dmaCtrlReg);
1656:
1657: /* Turning off DMA record sound emulation */
1658: dmaRecord.isRunning = 0;
1659: dmaRecord.loopMode = 0;
1660: nCbar_DmaSoundControl = dmaCtrlReg;
1.1 root 1661: }
1662: }
1663: }
1664:
1665:
1666: /**
1667: * Process DMA Record connected to DSP Xmit in HandShake mode.
1668: * In this special case, DMA Record is the "master" and Dsp Xmit is the "slave".
1669: */
1670: static void Crossbar_Process_DMARecord_HandshakeMode(void)
1671: {
1672: Sint16 data;
1673:
1674: /* If DMA record is activated and is running */
1675: if (dmaRecord.isRunning == 0) {
1676: return;
1677: }
1678:
1679: /* If DSP frame is activated (SC2 pin of the SSI port) */
1680: if (dmaRecord.handshakeMode_Frame == 0) {
1681: return;
1682: }
1683:
1684: /* Send the clock to the DSP SSI Xmit */
1685: DSP_SsiReceive_SCK();
1686:
1687: /* read data from DSP Xmit */
1688: data = DSP_SsiReadTxValue();
1689: dmaRecord.handshakeMode_Frame = 0;
1.1.1.7 root 1690:
1.1 root 1691: Crossbar_SendDataToDmaRecord(data);
1692: }
1693:
1694: /**
1695: * Get the frame value from DSP SSI (handshake mode only)
1696: */
1697: void Crossbar_DmaRecordInHandShakeMode_Frame(Uint32 frame)
1698: {
1699: dmaRecord.handshakeMode_Frame = frame;
1700: }
1701:
1702:
1703: /*----------------------------------------------------------------------*/
1704: /*-------------------------- ADC processing ----------------------------*/
1705: /*----------------------------------------------------------------------*/
1706:
1707: /**
1708: * Get datas recorded by the microphone and convert them into falcon internal frequency
1709: * - micro_bufferL : left track recorded by the microphone
1710: * - micro_bufferR : right track recorded by the microphone
1711: * - microBuffer_size : buffers size
1712: */
1713: void Crossbar_GetMicrophoneDatas(Sint16 *micro_bufferL, Sint16 *micro_bufferR, Uint32 microBuffer_size)
1714: {
1.1.1.4 root 1715: Uint32 i, size, bufferIndex;
1716: Sint64 idxPos;
1.1 root 1717:
1.1.1.4 root 1718: size = (microBuffer_size * crossbar.frequence_ratio>>32);
1.1 root 1719: bufferIndex = 0;
1.1.1.4 root 1720: idxPos = 0;
1721:
1.1 root 1722: for (i = 0; i < size; i++) {
1723: adc.writePosition = (adc.writePosition + 1) % DACBUFFER_SIZE;
1724:
1725: adc.buffer_left[adc.writePosition] = micro_bufferL[bufferIndex];
1.1.1.7 root 1726: adc.buffer_right[adc.writePosition] = micro_bufferR[bufferIndex];
1.1 root 1727:
1.1.1.4 root 1728: idxPos += crossbar.frequence_ratio2;
1.1.1.7 root 1729: bufferIndex += idxPos>>32;
1.1.1.4 root 1730: idxPos &= 0xffffffff; /* only keep the fractional part */
1.1 root 1731: }
1732: }
1733:
1734: /**
1735: * Process ADC transfer to crossbar
1736: */
1737: static void Crossbar_Process_ADCXmit_Transfer(void)
1738: {
1739: Sint16 sample;
1740: Uint16 frame;
1.1.1.7 root 1741:
1.1 root 1742: /* swap from left to right channel or right to left channel */
1743: adc.wordCount = 1 - adc.wordCount;
1.1.1.7 root 1744:
1.1 root 1745: /* Left Channel */
1746: if (adc.wordCount == 0) {
1747: sample = adc.buffer_left[adc.readPosition];
1748: frame = 1;
1749: }
1750: else {
1751: sample = adc.buffer_right[adc.readPosition];
1752: adc.readPosition = (adc.readPosition + 1) % DACBUFFER_SIZE;
1753: frame = 0;
1754: }
1.1.1.7 root 1755:
1.1 root 1756: /* Send sample to DSP receive ? */
1757: if (adc.isConnectedToDsp) {
1758: Crossbar_SendDataToDspReceive(sample, frame);
1759: }
1.1.1.7 root 1760:
1.1 root 1761: /* Send sample to DMA record ? */
1762: if (adc.isConnectedToDma) {
1763: Crossbar_SendDataToDmaRecord(sample);
1764: }
1765:
1766: /* Send sample to DAC ? */
1767: if (adc.isConnectedToCodec) {
1768: Crossbar_SendDataToDAC(sample, adc.wordCount);
1769: }
1770: }
1771:
1772:
1773: /*----------------------------------------------------------------------*/
1774: /*-------------------------- DAC processing ----------------------------*/
1775: /*----------------------------------------------------------------------*/
1776:
1777: /**
1778: * Put sample from crossbar into the DAC buffer.
1779: * - value : sample value to play
1780: * - sample_pos : position of the sample in the track (used to play the monitored track)
1781: */
1782: static void Crossbar_SendDataToDAC(Sint16 value, Uint16 sample_pos)
1783: {
1784: Uint16 track = crossbar.track_monitored * 2;
1785:
1.1.1.8 ! root 1786: //fprintf ( stderr , "datadac %x %x\n" , value , dac.writePosition );
! 1787: /* Increase counter for each sample received by the DAC */
! 1788: dac.wordCount++;
! 1789:
1.1 root 1790: if (sample_pos == track) {
1791: /* Left channel */
1792: dac.buffer_left[dac.writePosition] = value;
1793: }
1794: else if (sample_pos == track + 1) {
1795: /* Right channel */
1796: dac.buffer_right[dac.writePosition] = value;
1797: dac.writePosition = (dac.writePosition + 1) % (DACBUFFER_SIZE);
1798: }
1799: }
1800:
1801: /**
1.1.1.7 root 1802: * Mix PSG sound with microphone sound in ADC.
1.1 root 1803: * Also mix ADC sound sample with the crossbar DAC samples.
1804: * (Called by sound.c)
1805: */
1806: void Crossbar_GenerateSamples(int nMixBufIdx, int nSamplesToGenerate)
1807: {
1.1.1.8 ! root 1808: int i, nBufIdx;
1.1.1.6 root 1809: int n;
1.1 root 1810: Sint16 adc_leftData, adc_rightData, dac_LeftData, dac_RightData;
1.1.1.8 ! root 1811: Sint16 dac_read_left, dac_read_right;
! 1812:
! 1813: //fprintf ( stderr , "gen %03x %03x %03x %03x\n" , dac.writePosition , dac.readPosition , (dac.writePosition-dac.readPosition)%DACBUFFER_SIZE , nSamplesToGenerate );
1.1.1.7 root 1814:
1.1 root 1815: if (crossbar.isDacMuted) {
1816: /* Output sound = 0 */
1817: for (i = 0; i < nSamplesToGenerate; i++) {
1818: nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
1819: MixBuffer[nBufIdx][0] = 0;
1820: MixBuffer[nBufIdx][1] = 0;
1821: }
1822:
1823: /* Counters are refreshed for when DAC becomes unmuted */
1.1.1.8 ! root 1824: dac.readPosition = (dac.writePosition-DACBUFFER_SIZE/2)%DACBUFFER_SIZE;
1.1.1.4 root 1825: crossbar.adc2dac_readBufferPosition = adc.writePosition;
1.1 root 1826: return;
1827: }
1828:
1829: for (i = 0; i < nSamplesToGenerate; i++)
1830: {
1831: nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
1832:
1833: /* ADC mixing (PSG sound or microphone sound for left and right channels) */
1834: switch (crossbar.codecAdcInput) {
1835: case 0:
1836: default: /* Just here to remove compiler's warnings */
1837: /* Microphone sound for left and right channels */
1.1.1.4 root 1838: adc_leftData = adc.buffer_left[crossbar.adc2dac_readBufferPosition];
1839: adc_rightData = adc.buffer_right[crossbar.adc2dac_readBufferPosition];
1.1 root 1840: break;
1841: case 1:
1842: /* Microphone sound for left channel, PSG sound for right channel */
1.1.1.4 root 1843: adc_leftData = adc.buffer_left[crossbar.adc2dac_readBufferPosition];
1.1 root 1844: adc_rightData = MixBuffer[nBufIdx][1];
1845: break;
1846: case 2:
1847: /* PSG sound for left channel, microphone sound for right channel */
1848: adc_leftData = MixBuffer[nBufIdx][0];
1.1.1.4 root 1849: adc_rightData = adc.buffer_right[crossbar.adc2dac_readBufferPosition];
1.1 root 1850: break;
1851: case 3:
1852: /* PSG sound for left and right channels */
1853: adc_leftData = MixBuffer[nBufIdx][0];
1854: adc_rightData = MixBuffer[nBufIdx][1];
1855: break;
1856: }
1857:
1858: /* DAC mixing (direct ADC + crossbar) */
1.1.1.8 ! root 1859: /* If DAC didn't receive any data, we force left/right value to 0 */
! 1860: if ( dac.wordCount == 0 ) /* Nothing received */
! 1861: {
! 1862: dac_read_left = 0;
! 1863: dac_read_right = 0;
! 1864: }
! 1865: else
! 1866: {
! 1867: dac_read_left = dac.buffer_left[dac.readPosition];
! 1868: dac_read_right = dac.buffer_right[dac.readPosition];
! 1869: }
1.1 root 1870: switch (crossbar.codecInputSource) {
1871: case 0:
1872: default: /* Just here to remove compiler's warnings */
1873: /* No sound */
1874: dac_LeftData = 0;
1875: dac_RightData = 0;
1876: break;
1877: case 1:
1878: /* direct ADC->DAC sound only ADC*4/65536 */
1879: dac_LeftData = (adc_leftData * crossbar.gainSettingLeft) >> 14;
1880: dac_RightData = (adc_rightData * crossbar.gainSettingRight) >> 14;
1881: break;
1882: case 2:
1883: /* Crossbar->DAC sound only */
1.1.1.8 ! root 1884: dac_LeftData = dac_read_left;
! 1885: dac_RightData = dac_read_right;
1.1 root 1886: break;
1887: case 3:
1888: /* Mixing Direct ADC sound with Crossbar->DMA sound */
1889: dac_LeftData = ((adc_leftData * crossbar.gainSettingLeft) >> 14) +
1.1.1.8 ! root 1890: dac_read_left;
! 1891: dac_RightData = ((adc_rightData * crossbar.gainSettingRight) >> 14) +
! 1892: dac_read_right;
1.1 root 1893: break;
1894: }
1.1.1.7 root 1895:
1.1 root 1896: MixBuffer[nBufIdx][0] = (dac_LeftData * crossbar.attenuationSettingLeft) >> 16;
1897: MixBuffer[nBufIdx][1] = (dac_RightData * crossbar.attenuationSettingRight) >> 16;
1898:
1.1.1.7 root 1899: /* Upgrade dac's buffer read pointer */
1.1.1.4 root 1900: dac.readPosition_float += crossbar.frequence_ratio;
1901: n = dac.readPosition_float >> 32; /* number of samples to skip */
1.1.1.6 root 1902:
1.1.1.8 ! root 1903: #if 0
1.1.1.6 root 1904: if (n) {
1905: // It becomes safe to zero old data if tail has moved
1906: for (j=0; j<n; j++) {
1907: dac.buffer_left[(dac.readPosition+j) % DACBUFFER_SIZE] = 0;
1908: dac.buffer_right[(dac.readPosition+j) % DACBUFFER_SIZE] = 0;
1909: }
1910: }
1.1.1.8 ! root 1911: #endif
1.1.1.6 root 1912:
1.1.1.4 root 1913: dac.readPosition = (dac.readPosition + n) % DACBUFFER_SIZE;
1914: dac.readPosition_float &= 0xffffffff; /* only keep the fractional part */
1.1.1.7 root 1915:
1916: /* Upgrade adc->dac's buffer read pointer */
1.1.1.4 root 1917: crossbar.adc2dac_readBufferPosition_float += crossbar.frequence_ratio;
1918: n = crossbar.adc2dac_readBufferPosition_float >> 32; /* number of samples to skip */
1919: crossbar.adc2dac_readBufferPosition = (crossbar.adc2dac_readBufferPosition + n) % DACBUFFER_SIZE;
1920: crossbar.adc2dac_readBufferPosition_float &= 0xffffffff; /* only keep the fractional part */
1.1 root 1921: }
1.1.1.8 ! root 1922:
! 1923: /* If the DAC didn't receive any data since last call to Crossbar_GenerateSamples() */
! 1924: /* then we need to adjust dac.writePosition to be always ahead of dac.readPosition */
! 1925: if ( dac.wordCount == 0 )
! 1926: {
! 1927: // fprintf ( stderr , "fix writepos %x (readpos %x)\n" , (dac.readPosition+DACBUFFER_SIZE/2)%DACBUFFER_SIZE , dac.readPosition );
! 1928: dac.writePosition = (dac.readPosition+DACBUFFER_SIZE/2)%DACBUFFER_SIZE;
! 1929: }
! 1930: dac.wordCount = 0;
1.1 root 1931: }
1.1.1.6 root 1932:
1933:
1934: /**
1935: * display the Crossbar registers values (for debugger info command)
1936: */
1.1.1.7 root 1937: void Crossbar_Info(FILE *fp, Uint32 dummy)
1.1.1.6 root 1938: {
1.1.1.8 ! root 1939: const char *matrixDMA, *matrixDSP, *matrixEXT, *matrixDAC;
1.1.1.6 root 1940: char frqDMA[11], frqDAC[11], frqDSP[11], frqEXT[11];
1941: char frqSTE[30], frq25Mhz[30], frq32Mhz[30];
1942: char dataSize[15];
1.1.1.8 ! root 1943: static const char *matrix_tab[8] = {
! 1944: "OOHO",
! 1945: "OOXO",
! 1946: "OHOO",
! 1947: "OXOO",
! 1948: "HOOO",
! 1949: "XOOO",
! 1950: "OOOH",
! 1951: "OOOX"
1.1.1.6 root 1952: };
1953:
1954: if (ConfigureParams.System.nMachineType != MACHINE_FALCON) {
1.1.1.7 root 1955: fprintf(fp, "Not Falcon - no Crossbar!\n");
1.1.1.6 root 1956: return;
1957: }
1958:
1.1.1.7 root 1959: fprintf(fp, "$FF8900.b : Sound DMA control : %02x\n", IoMem_ReadByte(0xff8900));
1960: fprintf(fp, "$FF8901.b : Sound DMA control : %02x\n", IoMem_ReadByte(0xff8901));
1961: fprintf(fp, "$FF8903.b : Frame Start High : %02x\n", IoMem_ReadByte(0xff8903));
1962: fprintf(fp, "$FF8905.b : Frame Start middle : %02x\n", IoMem_ReadByte(0xff8905));
1963: fprintf(fp, "$FF8907.b : Frame Start low : %02x\n", IoMem_ReadByte(0xff8907));
1964: fprintf(fp, "$FF8909.b : Frame Count High : %02x\n", IoMem_ReadByte(0xff8909));
1965: fprintf(fp, "$FF890B.b : Frame Count middle : %02x\n", IoMem_ReadByte(0xff890b));
1966: fprintf(fp, "$FF890D.b : Frame Count low : %02x\n", IoMem_ReadByte(0xff890d));
1967: fprintf(fp, "$FF890F.b : Frame End High : %02x\n", IoMem_ReadByte(0xff890f));
1968: fprintf(fp, "$FF8911.b : Frame End middle : %02x\n", IoMem_ReadByte(0xff8911));
1969: fprintf(fp, "$FF8913.b : Frame End low : %02x\n", IoMem_ReadByte(0xff8913));
1970: fprintf(fp, "\n");
1971: fprintf(fp, "$FF8920.b : Sound Mode Control : %02x\n", IoMem_ReadByte(0xff8920));
1972: fprintf(fp, "$FF8921.b : Sound Mode Control : %02x\n", IoMem_ReadByte(0xff8921));
1973: fprintf(fp, "$FF8930.w : DMA Crossbar Input Select Controller : %04x\n", IoMem_ReadWord(0xff8930));
1974: fprintf(fp, "$FF8932.w : DMA Crossbar Output Select Controller : %04x\n", IoMem_ReadWord(0xff8932));
1975: fprintf(fp, "\n");
1976: fprintf(fp, "$FF8934.b : External Sync Frequency Divider : %02x\n", IoMem_ReadByte(0xff8934));
1977: fprintf(fp, "$FF8935.b : Internal Sync Frequency Divider : %02x\n", IoMem_ReadByte(0xff8935));
1978: fprintf(fp, "$FF8936.b : Record Track select : %02x\n", IoMem_ReadByte(0xff8936));
1979: fprintf(fp, "$FF8937.b : Codec Input Source : %02x\n", IoMem_ReadByte(0xff8937));
1980: fprintf(fp, "$FF8938.b : Codec ADC Input : %02x\n", IoMem_ReadByte(0xff8938));
1981: fprintf(fp, "$FF8939.b : Gain Settings Per Channel : %02x\n", IoMem_ReadByte(0xff8939));
1982: fprintf(fp, "$FF893A.b : Attenuation Settings Per Channel : %02x\n", IoMem_ReadByte(0xff893a));
1983: fprintf(fp, "$FF893C.w : Codec Status : %04x\n", IoMem_ReadWord(0xff893c));
1984: fprintf(fp, "$FF8940.w : GPIO Data Direction : %04x\n", IoMem_ReadWord(0xff8940));
1985: fprintf(fp, "$FF8942.w : GPIO Data : %04x\n", IoMem_ReadWord(0xff8942));
1986: fprintf(fp, "\n");
1987:
1.1.1.6 root 1988: /* DAC connexion */
1989: switch ((IoMem_ReadWord(0xff8932) >> 13) & 0x3) {
1.1.1.7 root 1990: case 0 :
1.1.1.6 root 1991: /* DAC connexion with DMA Playback */
1992: if ((IoMem_ReadWord(0xff8930) & 0x1) == 1)
1.1.1.8 ! root 1993: matrixDAC = "OOXO";
1.1.1.6 root 1994: else
1.1.1.8 ! root 1995: matrixDAC = "OOHO";
1.1.1.6 root 1996: break;
1997: case 1 :
1998: /* DAC connexion with DSP Transmit */
1999: if ((IoMem_ReadWord(0xff8930) & 0x10) == 0x10)
1.1.1.8 ! root 2000: matrixDAC = "OXOO";
1.1.1.6 root 2001: else
1.1.1.8 ! root 2002: matrixDAC = "OHOO";
1.1.1.6 root 2003: break;
2004: case 2 :
2005: /* DAC connexion with External Input */
2006: if ((IoMem_ReadWord(0xff8930) & 0x100) == 0x100)
1.1.1.8 ! root 2007: matrixDAC = "XOOO";
1.1.1.6 root 2008: else
1.1.1.8 ! root 2009: matrixDAC = "HOOO";
1.1.1.6 root 2010: break;
1.1.1.8 ! root 2011: default: /* case 3 */
1.1.1.6 root 2012: /* DAC connexion with ADC */
1.1.1.8 ! root 2013: matrixDAC = "OOOX";
1.1.1.6 root 2014: break;
2015: }
2016:
2017: /* DMA connexion */
1.1.1.8 ! root 2018: matrixDMA = matrix_tab[IoMem_ReadWord(0xff8932) & 0x7];
1.1.1.6 root 2019:
2020: /* DSP connexion */
1.1.1.8 ! root 2021: matrixDSP = matrix_tab[(IoMem_ReadWord(0xff8932) >> 4) & 0x7];
1.1.1.6 root 2022:
2023: /* External input connexion */
1.1.1.8 ! root 2024: matrixEXT = matrix_tab[(IoMem_ReadWord(0xff8932) >> 8) & 0x7];
1.1.1.6 root 2025:
2026: if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) {
2027: strcpy(frqDSP, "(STe Freq)");
2028: strcpy(frqDMA, "(STe Freq)");
2029: strcpy(frqEXT, "(STe Freq)");
2030: strcpy(frqDAC, "(STe Freq)");
2031: }
2032: else {
2033: /* DSP Clock */
2034: switch ((IoMem_ReadWord(0xff8930) >> 5) & 0x3) {
2035: case 0: strcpy(frqDSP, " (25 Mhz) "); break;
2036: case 1: strcpy(frqDSP, "(External)"); break;
2037: case 2: strcpy(frqDSP, " (32 Mhz) "); break;
2038: default: strcpy(frqDSP, "undefined "); break;
2039: }
2040:
2041: /* DMA Clock */
2042: switch ((IoMem_ReadWord(0xff8930) >> 1) & 0x3) {
2043: case 0: strcpy(frqDMA, " (25 Mhz) "); break;
2044: case 1: strcpy(frqDMA, "(External)"); break;
2045: case 2: strcpy(frqDMA, " (32 Mhz) "); break;
2046: default: strcpy(frqDMA, "undefined "); break;
2047: }
2048:
2049: /* External Clock */
2050: switch ((IoMem_ReadWord(0xff8930) >> 9) & 0x3) {
2051: case 0: strcpy(frqEXT, " (25 Mhz) "); break;
2052: case 1: strcpy(frqEXT, "(External)"); break;
2053: case 2: strcpy(frqEXT, " (32 Mhz) "); break;
2054: default: strcpy(frqEXT, "undefined "); break;
2055: }
2056:
2057: /* DAC Clock */
2058: strcpy(frqDAC, " (25 Mhz) ");
2059: }
2060:
2061: /* data size */
2062: switch ((IoMem_ReadByte(0xff8921) >> 6) & 0x3) {
2063: case 0: strcpy (dataSize, "8 bits stereo"); break;
2064: case 1: strcpy (dataSize, "16 bits stereo"); break;
2065: case 2: strcpy (dataSize, "8 bits mono"); break;
2066: default: strcpy (dataSize, "undefined"); break;
2067: }
2068:
2069: /* STE, 25Mhz and 32 Mhz sound frequencies */
2070: if ((IoMem_ReadByte(0xff8935) & 0xf) == 0) {
2071: sprintf(frqSTE, "Ste Freq : %d Khz", Ste_SampleRates[IoMem_ReadByte(0xff8921) & 0x3]);
2072: strcpy (frq25Mhz, "25 Mhz Freq : - Khz");
2073: strcpy (frq32Mhz, "32 Mzh Freq : - Khz");
2074: }
2075: else {
2076: strcpy (frqSTE, "Ste Freq : - Khz");
2077: sprintf(frq25Mhz, "25 Mhz Freq : %d Khz", Falcon_SampleRates_25Mhz[(IoMem_ReadByte(0xff8935) & 0xf) - 1]);
2078: sprintf(frq32Mhz, "32 Mzh Freq : %d Khz", Falcon_SampleRates_32Mhz[(IoMem_ReadByte(0xff8935) & 0xf) - 1]);
2079: }
2080:
2081: /* Display the crossbar Matrix */
1.1.1.7 root 2082: fprintf(fp, " INPUT\n");
2083: fprintf(fp, "External Imp ---%c------%c------%c------%c\n", matrixDAC[0], matrixDMA[0], matrixDSP[0], matrixEXT[0]);
2084: fprintf(fp, "%s | | | | O = no connexion\n", frqEXT);
2085: fprintf(fp, " | | | | X = connexion\n");
2086: fprintf(fp, "Dsp Transmit ---%c------%c------%c------%c H = Handshake connexion\n", matrixDAC[1], matrixDMA[1], matrixDSP[1], matrixEXT[1]);
2087: fprintf(fp, "%s | | | |\n", frqDSP);
2088: fprintf(fp, " | | | | %s\n", dataSize);
2089: fprintf(fp, "DMA PlayBack ---%c------%c------%c------%c\n", matrixDAC[2], matrixDMA[2], matrixDSP[2], matrixEXT[2]);
2090: fprintf(fp, "%s | | | | Sound Freq :\n", frqDMA);
2091: fprintf(fp, " | | | | %s\n", frqSTE);
2092: fprintf(fp, "ADC ---%c------%c------%c------%c %s\n", matrixDAC[3], matrixDMA[3], matrixDSP[3], matrixEXT[3], frq25Mhz);
2093: fprintf(fp, "%s | | | | %s\n", frqDAC, frq32Mhz);
2094: fprintf(fp, " | | | |\n");
2095: fprintf(fp, " DAC DMA DSP External OUTPUT\n");
2096: fprintf(fp, " Record Record Out\n");
2097: fprintf(fp, "\n");
1.1.1.6 root 2098: }
2099:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.