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