|
|
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 */
266: };
267:
268: struct codec_s {
269: Sint16 buffer_left[DACBUFFER_SIZE];
270: Sint16 buffer_right[DACBUFFER_SIZE];
271: Uint32 readPosition;
272: Uint32 readPosition_decimal;
273: Uint32 writePosition;
274: Uint32 isConnectedToCodec;
275: Uint32 isConnectedToDsp;
276: Uint32 isConnectedToDma;
277: Uint32 wordCount;
278: };
279:
280: struct dsp_s {
281: Uint32 isTristated; /* 0 = DSP is not tristated; 1 = DSP is tristated */
282: Uint32 isInHandshakeMode; /* 0 = not in hanshake mode; 1 = in hanshake mode */
283: Uint32 isConnectedToCodec;
284: Uint32 isConnectedToDsp;
285: Uint32 isConnectedToDma;
286: Uint32 wordCount; /* count number of words received from DSP transmitter (for TX frame computing) */
287: };
288:
289: static struct crossbar_s crossbar;
290: static struct dma_s dmaPlay;
291: static struct dma_s dmaRecord;
292: static struct codec_s dac;
293: static struct codec_s adc;
294: static struct dsp_s dspXmit;
295: static struct dsp_s dspReceive;
296:
297: /**
298: * Reset Crossbar variables.
299: */
300: void Crossbar_Reset(bool bCold)
301: {
302: nCbar_DmaSoundControl = 0;
303:
304: if (bCold)
305: {
306: }
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));
324: dac.readPosition = 0;
325: dac.readPosition_decimal = 0;
326: dac.writePosition = 0;
327:
328: /* ADC inits */
329: memset(adc.buffer_left, 0, sizeof(dac.buffer_left));
330: memset(adc.buffer_right, 0, sizeof(dac.buffer_right));
331: adc.readPosition = 0;
332: adc.readPosition_decimal = 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;
364: crossbar.adc_dac_readBufferPosition = 0;
365: crossbar.adc_dac_readBufferPosition_decimal = 0;
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 */
373: if (crossbar.microphone_ADC_is_started == 0) {
374: crossbar.microphone_ADC_is_started = Microphone_Start((int)nAudioFrequency);
375: }
376:
377: /* Initialize Crossbar values after reboot */
378: IoMem_WriteByte(0xff8900,0x05);
379: IoMem_WriteByte(0xff8903,0xff);
380: IoMem_WriteByte(0xff8905,0xff);
381: IoMem_WriteByte(0xff8907,0xfe);
382: IoMem_WriteByte(0xff8909,0xff);
383: IoMem_WriteByte(0xff890b,0xff);
384: IoMem_WriteByte(0xff890d,0xfe);
385: IoMem_WriteByte(0xff890f,0xff);
386: IoMem_WriteByte(0xff8911,0xff);
387: IoMem_WriteByte(0xff8913,0xfe);
388: IoMem_WriteWord(0xff893c,0x2401);
389: }
390:
391: /**
392: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
393: */
394: void Crossbar_MemorySnapShot_Capture(bool bSave)
395: {
396: /* Save/Restore details */
397: MemorySnapShot_Store(&nCbar_DmaSoundControl, sizeof(nCbar_DmaSoundControl));
398: MemorySnapShot_Store(&dmaPlay, sizeof(dmaPlay));
399: MemorySnapShot_Store(&dmaRecord, sizeof(dmaRecord));
400: MemorySnapShot_Store(&crossbar, sizeof(crossbar));
401: MemorySnapShot_Store(&dac, sizeof(dac));
402: MemorySnapShot_Store(&adc, sizeof(adc));
403: MemorySnapShot_Store(&dspXmit, sizeof(dspXmit));
404: MemorySnapShot_Store(&dspReceive, sizeof(dspReceive));
405: }
406:
407:
408: /*----------------------------------------------------------------------*/
409: /* Hardware I/O functions */
410: /*----------------------------------------------------------------------*/
411:
412: /**
413: * Write byte to buffer interrupts (0xff8900).
414: */
415: void Crossbar_BufferInter_WriteByte(void)
416: {
417: Uint8 dmaCtrl = IoMem_ReadByte(0xff8900);
418:
419: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8900 (Sound DMA control) write: 0x%02x\n", dmaCtrl);
420:
421: dmaPlay.timerA_int = (dmaCtrl & 0x4) >> 2;
422: dmaPlay.mfp15_int = (dmaCtrl & 0x1);
423: dmaRecord.timerA_int = (dmaCtrl & 0x8) >> 3;
424: dmaRecord.mfp15_int = (dmaCtrl & 0x2) >> 1;
425: }
426:
427: /**
428: * Write byte from DMA control register (0xff8901).
429: */
430: void Crossbar_DmaCtrlReg_WriteByte(void)
431: {
432: Uint8 sndCtrl = IoMem_ReadByte(0xff8901);
433:
434: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8901 (additional Sound DMA control) write: 0x%02x\n", sndCtrl);
435:
436: crossbar.dmaSelected = (sndCtrl & 0x80) >> 7;
437:
438: /* DMA Play mode */
439: if ((dmaPlay.isRunning == 0) && (sndCtrl & CROSSBAR_SNDCTRL_PLAY))
440: {
441: /* Turning on DMA Play sound emulation */
442: dmaPlay.isRunning = 1;
443: nCbar_DmaSoundControl = sndCtrl;
444: dmaPlay.loopMode = (sndCtrl & 0x2) >> 1;
445: Crossbar_setDmaPlay_Settings();
446: }
447: else if (dmaPlay.isRunning && ((sndCtrl & CROSSBAR_SNDCTRL_PLAY) == 0))
448: {
449: /* Create samples up until this point with current values */
450: Sound_Update();
451:
452: /* Turning off DMA play sound emulation */
453: dmaPlay.isRunning = 0;
454: dmaPlay.loopMode = 0;
455: nCbar_DmaSoundControl = sndCtrl;
456: memset(dac.buffer_left, 0, sizeof(dac.buffer_left));
457: memset(dac.buffer_right, 0, sizeof(dac.buffer_right));
458: }
459:
460: /* DMA Record mode */
461: if ((dmaRecord.isRunning == 0) && (sndCtrl & CROSSBAR_SNDCTRL_RECORD))
462: {
463: /* Turning on DMA record sound emulation */
464: dmaRecord.isRunning = 1;
465: dmaRecord.loopMode = (sndCtrl & 0x20) >> 5;
466: nCbar_DmaSoundControl = sndCtrl;
467: Crossbar_setDmaRecord_Settings();
468: }
469: else if (dmaRecord.isRunning && ((sndCtrl & CROSSBAR_SNDCTRL_RECORD) == 0))
470: {
471: /* Turning off DMA record sound emulation */
472: nCbar_DmaSoundControl = sndCtrl;
473: dmaRecord.isRunning = 0;
474: dmaRecord.loopMode = 0;
475: }
476: }
477:
478:
479: /**
480: * Read byte from sound frame start high register (0xff8903).
481: */
482: void Crossbar_FrameStartHigh_ReadByte(void)
483: {
484: if (crossbar.dmaSelected == 0) {
485: /* DMA Play selected */
486: IoMem_WriteByte(0xff8903, crossbar.dmaPlay_CurrentFrameStart >> 16);
487: }
488: else {
489: /* DMA Record selected */
490: IoMem_WriteByte(0xff8903, crossbar.dmaRecord_CurrentFrameStart >> 16);
491: }
492: }
493:
494: /**
495: * Write byte to sound frame start high register (0xff8903).
496: */
497: void Crossbar_FrameStartHigh_WriteByte(void)
498: {
499: Uint32 addr;
500:
501: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8903 (Sound frame start high) write: 0x%02x\n", IoMem_ReadByte(0xff8903));
502:
503: addr = (IoMem_ReadByte(0xff8903) << 16) + (IoMem_ReadByte(0xff8905) << 8) + IoMem_ReadByte(0xff8907);
504:
505: if (crossbar.dmaSelected == 0) {
506: /* DMA Play selected */
507: crossbar.dmaPlay_CurrentFrameStart = addr & ~1;
508: }
509: else {
510: /* DMA Record selected */
511: crossbar.dmaRecord_CurrentFrameStart = addr & ~1;
512: }
513: }
514:
515: /**
516: * Read byte from sound frame start medium register (0xff8905).
517: */
518: void Crossbar_FrameStartMed_ReadByte(void)
519: {
520: if (crossbar.dmaSelected == 0) {
521: /* DMA Play selected */
522: IoMem_WriteByte(0xff8905, crossbar.dmaPlay_CurrentFrameStart >> 8);
523: }
524: else {
525: /* DMA Record selected */
526: IoMem_WriteByte(0xff8905, crossbar.dmaRecord_CurrentFrameStart >> 8);
527: }
528: }
529:
530: /**
531: * Write byte to sound frame start medium register (0xff8905).
532: */
533: void Crossbar_FrameStartMed_WriteByte(void)
534: {
535: Uint32 addr;
536:
537: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8905 (Sound frame start med) write: 0x%02x\n", IoMem_ReadByte(0xff8905));
538:
539: addr = (IoMem_ReadByte(0xff8903) << 16) + (IoMem_ReadByte(0xff8905) << 8) + IoMem_ReadByte(0xff8907);
540:
541: if (crossbar.dmaSelected == 0) {
542: /* DMA Play selected */
543: crossbar.dmaPlay_CurrentFrameStart = addr & ~1;
544: }
545: else {
546: /* DMA Record selected */
547: crossbar.dmaRecord_CurrentFrameStart = addr & ~1;
548: }
549: }
550:
551: /**
552: * Read byte from sound frame start low register (0xff8907).
553: */
554: void Crossbar_FrameStartLow_ReadByte(void)
555: {
556: if (crossbar.dmaSelected == 0) {
557: /* DMA Play selected */
558: IoMem_WriteByte(0xff8907, crossbar.dmaPlay_CurrentFrameStart);
559: }
560: else {
561: /* DMA Record selected */
562: IoMem_WriteByte(0xff8907, crossbar.dmaRecord_CurrentFrameStart);
563: }
564: }
565:
566: /**
567: * Write byte to sound frame start low register (0xff8907).
568: */
569: void Crossbar_FrameStartLow_WriteByte(void)
570: {
571: Uint32 addr;
572:
573: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8907 (Sound frame start low) write: 0x%02x\n", IoMem_ReadByte(0xff8907));
574:
575: addr = (IoMem_ReadByte(0xff8903) << 16) + (IoMem_ReadByte(0xff8905) << 8) + IoMem_ReadByte(0xff8907);
576:
577: if (crossbar.dmaSelected == 0) {
578: /* DMA Play selected */
579: crossbar.dmaPlay_CurrentFrameStart = addr & ~1;
580: }
581: else {
582: /* DMA Record selected */
583: crossbar.dmaRecord_CurrentFrameStart = addr & ~1;
584: }
585: }
586:
587: /*-----------------------------------------------------------------------*/
588:
589: /**
590: * Read byte from sound frame count high register (0xff8909).
591: */
592: void Crossbar_FrameCountHigh_ReadByte(void)
593: {
594: if (crossbar.dmaSelected == 0) {
595: /* DMA Play selected */
596: IoMem_WriteByte(0xff8909, (dmaPlay.frameStartAddr + dmaPlay.frameCounter) >> 16);
597: }
598: else {
599: /* DMA Record selected */
600: IoMem_WriteByte(0xff8909, (dmaRecord.frameStartAddr + dmaRecord.frameCounter) >> 16);
601: }
602: }
603:
604: /**
605: * Write byte to sound frame count high register (0xff8909).
606: */
607: void Crossbar_FrameCountHigh_WriteByte(void)
608: {
609: Uint32 addr;
610:
611: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8909 (Sound frame count high) write: 0x%02x\n", IoMem_ReadByte(0xff8909));
612:
613: /* Compute frameCounter current address */
614: addr = (IoMem_ReadByte(0xff8909) << 16) + (IoMem_ReadByte(0xff890b) << 8) + IoMem_ReadByte(0xff890d);
615:
616: if (crossbar.dmaSelected == 0) {
617: /* DMA Play selected */
618: crossbar.dmaPlay_CurrentFrameCount = addr;
619: }
620: else {
621: /* DMA Record selected */
622: crossbar.dmaRecord_CurrentFrameCount = addr;
623: }
624: }
625:
626: /**
627: * Read byte from sound frame count medium register (0xff890b).
628: */
629: void Crossbar_FrameCountMed_ReadByte(void)
630: {
631: if (crossbar.dmaSelected == 0) {
632: /* DMA Play selected */
633: IoMem_WriteByte(0xff890b, (dmaPlay.frameStartAddr + dmaPlay.frameCounter) >> 8);
634: }
635: else {
636: /* DMA Record selected */
637: IoMem_WriteByte(0xff890b, (dmaRecord.frameStartAddr + dmaRecord.frameCounter) >> 8);
638: }
639: }
640:
641: /**
642: * Write byte to sound frame count medium register (0xff890b).
643: */
644: void Crossbar_FrameCountMed_WriteByte(void)
645: {
646: Uint32 addr;
647:
648: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff890b (Sound frame count med) write: 0x%02x\n", IoMem_ReadByte(0xff890b));
649:
650: /* Compute frameCounter current address */
651: addr = (IoMem_ReadByte(0xff8909) << 16) + (IoMem_ReadByte(0xff890b) << 8) + IoMem_ReadByte(0xff890d);
652:
653: if (crossbar.dmaSelected == 0) {
654: /* DMA Play selected */
655: crossbar.dmaPlay_CurrentFrameCount = addr;
656: }
657: else {
658: /* DMA Record selected */
659: crossbar.dmaRecord_CurrentFrameCount = addr;
660: }
661: }
662:
663: /**
664: * Read byte from sound frame count low register (0xff890d).
665: */
666: void Crossbar_FrameCountLow_ReadByte(void)
667: {
668: if (crossbar.dmaSelected == 0) {
669: /* DMA Play selected */
670: IoMem_WriteByte(0xff890d, (dmaPlay.frameStartAddr + dmaPlay.frameCounter));
671: }
672: else {
673: /* DMA Record selected */
674: IoMem_WriteByte(0xff890d, (dmaRecord.frameStartAddr + dmaRecord.frameCounter));
675: }
676: }
677:
678: /**
679: * Write byte to sound frame count low register (0xff890d).
680: */
681: void Crossbar_FrameCountLow_WriteByte(void)
682: {
683: Uint32 addr;
684:
685: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff890d (Sound frame count low) write: 0x%02x\n", IoMem_ReadByte(0xff890d));
686:
687: /* Compute frameCounter current address */
688: addr = (IoMem_ReadByte(0xff8909) << 16) + (IoMem_ReadByte(0xff890b) << 8) + IoMem_ReadByte(0xff890d);
689:
690: if (crossbar.dmaSelected == 0) {
691: /* DMA Play selected */
692: crossbar.dmaPlay_CurrentFrameCount = addr;
693: }
694: else {
695: /* DMA Record selected */
696: crossbar.dmaRecord_CurrentFrameCount = addr;
697: }
698: }
699:
700: /*-----------------------------------------------------------------------*/
701:
702: /**
703: * Read byte from sound frame end high register (0xff890f).
704: */
705: void Crossbar_FrameEndHigh_ReadByte(void)
706: {
707: if (crossbar.dmaSelected == 0) {
708: /* DMA Play selected */
709: IoMem_WriteByte(0xff890f, crossbar.dmaPlay_CurrentFrameEnd >> 16);
710: }
711: else {
712: /* DMA Record selected */
713: IoMem_WriteByte(0xff890f, crossbar.dmaRecord_CurrentFrameEnd >> 16);
714: }
715: }
716:
717: /**
718: * Write byte to sound frame end high register (0xff890f).
719: */
720: void Crossbar_FrameEndHigh_WriteByte(void)
721: {
722: Uint32 addr;
723:
724: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff890f (Sound frame end high) write: 0x%02x\n", IoMem_ReadByte(0xff890f));
725:
726: addr = (IoMem_ReadByte(0xff890f) << 16) + (IoMem_ReadByte(0xff8911) << 8) + IoMem_ReadByte(0xff8913);
727:
728: if (crossbar.dmaSelected == 0) {
729: /* DMA Play selected */
730: crossbar.dmaPlay_CurrentFrameEnd = addr & ~1;
731: }
732: else {
733: /* DMA Record selected */
734: crossbar.dmaRecord_CurrentFrameEnd = addr & ~1;
735: }
736: }
737:
738: /**
739: * Read byte from sound frame end medium register (0xff8911).
740: */
741: void Crossbar_FrameEndMed_ReadByte(void)
742: {
743: if (crossbar.dmaSelected == 0) {
744: /* DMA Play selected */
745: IoMem_WriteByte(0xff8911, crossbar.dmaPlay_CurrentFrameEnd >> 8);
746: }
747: else {
748: /* DMA Record selected */
749: IoMem_WriteByte(0xff8911, crossbar.dmaRecord_CurrentFrameEnd >> 8);
750: }
751: }
752:
753: /**
754: * Write byte to sound frame end medium register (0xff8911).
755: */
756: void Crossbar_FrameEndMed_WriteByte(void)
757: {
758: Uint32 addr;
759:
760: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8911 (Sound frame end med) write: 0x%02x\n", IoMem_ReadByte(0xff8911));
761:
762: addr = (IoMem_ReadByte(0xff890f) << 16) + (IoMem_ReadByte(0xff8911) << 8) + IoMem_ReadByte(0xff8913);
763:
764: if (crossbar.dmaSelected == 0) {
765: /* DMA Play selected */
766: crossbar.dmaPlay_CurrentFrameEnd = addr & ~1;
767: }
768: else {
769: /* DMA Record selected */
770: crossbar.dmaRecord_CurrentFrameEnd = addr & ~1;
771: }
772: }
773:
774: /**
775: * Read byte from sound frame end low register (0xff8913).
776: */
777: void Crossbar_FrameEndLow_ReadByte(void)
778: {
779: if (crossbar.dmaSelected == 0) {
780: /* DMA Play selected */
781: IoMem_WriteByte(0xff8913, crossbar.dmaPlay_CurrentFrameEnd);
782: }
783: else {
784: /* DMA Record selected */
785: IoMem_WriteByte(0xff8913, crossbar.dmaRecord_CurrentFrameEnd);
786: }
787: }
788:
789: /**
790: * Write byte to sound frame end low register (0xff8913).
791: */
792: void Crossbar_FrameEndLow_WriteByte(void)
793: {
794: Uint32 addr;
795:
796: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8913 (Sound frame end low) write: 0x%02x\n", IoMem_ReadByte(0xff8913));
797:
798: addr = (IoMem_ReadByte(0xff890f) << 16) + (IoMem_ReadByte(0xff8911) << 8) + IoMem_ReadByte(0xff8913);
799:
800: if (crossbar.dmaSelected == 0) {
801: /* DMA Play selected */
802: crossbar.dmaPlay_CurrentFrameEnd = addr & ~1;
803: }
804: else {
805: /* DMA Record selected */
806: crossbar.dmaRecord_CurrentFrameEnd = addr & ~1;
807: }
808: }
809:
810: /*-----------------------------------------------------------------------*/
811: /**
812: * Write byte to DMA track control (0xff8920).
813: */
814: void Crossbar_DmaTrckCtrl_WriteByte(void)
815: {
816: Uint8 sndCtrl = IoMem_ReadByte(0xff8920);
817:
818: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8920 (sound mode control) write: 0x%02x\n", sndCtrl);
819:
820: crossbar.playTracks = (sndCtrl & 3) + 1;
821: crossbar.track_monitored = (sndCtrl & 30) >> 4;
822: }
823:
824: /**
825: * Write word to sound mode register (0xff8921).
826: */
827: void Crossbar_SoundModeCtrl_WriteByte(void)
828: {
829: Uint8 sndCtrl = IoMem_ReadByte(0xff8921);
830:
831: LOG_TRACE(TRACE_CROSSBAR, "crossbar : $ff8921 (additional sound mode control) write: 0x%02x\n", sndCtrl);
832:
833: crossbar.is16Bits = (sndCtrl & 0x40) >> 6;
834: crossbar.isStereo = 1 - ((sndCtrl & 0x80) >> 7);
835: crossbar.steFreq = sndCtrl & 0x3;
836:
837: Crossbar_Recalculate_Clocks_Cycles();
838: }
839:
840: /**
841: * Write word to Falcon Crossbar source controller (0xff8930).
842: Source: A/D Convertor BIT 15 14 13 12
843: 00 - 25.175Mhz clock -------------------------+--+
844: 01 - External clock --------------------------+--+
845: 10 - 32Mhz clock (Don't use) -----------------+--'
846:
847: Source: External Input BIT 11 10 9 8
848: 0 - DSP IN, 1 - All others ----------------' | | |
849: 00 - 25.175Mhz clock -------------------------+--+ |
850: 01 - External clock --------------------------+--+ |
851: 10 - 32Mhz clock -----------------------------+--' |
852: 0 - Handshake on, 1 - Handshake off ----------------'
853:
854: Source: DSP-XMIT BIT 7 6 5 4
855: 0 - Tristate and disconnect DSP -----------+ | | |
856: (Only for external SSI use) | | | |
857: 1 - Connect DSP to multiplexer ------------' | | |
858: 00 - 25.175Mhz clock -------------------------+--+ |
859: 01 - External clock --------------------------+--+ |
860: 10 - 32Mhz clock -----------------------------+--' |
861: 0 - Handshake on, 1 - Handshake off ----------------'
862:
863: Source: DMA-PLAYBACK BIT 3 2 1 0
864: 0 - Handshaking on, dest DSP-REC ----------+ | | |
865: 1 - Destination is not DSP-REC ------------' | | |
866: 00 - 25.175Mhz clock -------------------------+--+ |
867: 01 - External clock --------------------------+--+ |
868: 10 - 32Mhz clock -----------------------------+--' |
869: 0 - Handshake on, 1 - Handshake off ----------------'
870: */
871: void Crossbar_SrcControler_WriteWord(void)
872: {
873: Uint16 nCbSrc = IoMem_ReadWord(0xff8930);
874:
875: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8930 (source device) write: 0x%04x\n", nCbSrc);
876:
877: dspXmit.isTristated = 1 - ((nCbSrc >> 7) & 0x1);
878: dspXmit.isInHandshakeMode = 1 - ((nCbSrc >> 4) & 0x1);
879:
880: crossbar.dspXmit_freq = (nCbSrc >> 5) & 0x3;
881: crossbar.dmaPlay_freq = (nCbSrc >> 1) & 0x3;
882:
883: dmaPlay.isConnectedToDspInHandShakeMode = ((nCbSrc & 9) == 0 ? 1 : 0);
884: }
885:
886: /**
887: * Write word to Falcon Crossbar destination controller (0xff8932).
888: Source: D/A Convertor BIT 15 14 13 12
889: 00 - DMA output ------------------------------+--+ |
890: 01 - DSP output ------------------------------+--+ |
891: 10 - External input --------------------------+--+ |
892: 11 - ADC input -------------------------------+--' |
893: 0 - Handshake on, 1 - Handshake off ----------------'
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:
957: dmaPlay.isConnectedToDspInHandShakeMode = ((destCtrl & 7) == 2 ? 1 : 0);
958: dmaRecord.isConnectedToDspInHandShakeMode = ((destCtrl & 0xf) == 2 ? 1 : 0);
959: }
960:
961: /**
962: * Write byte to external clock divider register (0xff8934).
963: */
964: void Crossbar_FreqDivExt_WriteByte(void)
965: {
966: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8934 (ext. clock divider) write: 0x%02x\n", IoMem_ReadByte(0xff8934));
967: }
968:
969: /**
970: * Write byte to internal clock divider register (0xff8935).
971: */
972: void Crossbar_FreqDivInt_WriteByte(void)
973: {
974: Uint8 clkDiv = IoMem_ReadByte(0xff8935);
975:
976: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8935 (int. clock divider) write: 0x%02x\n", clkDiv);
977:
978: crossbar.int_freq_divider = clkDiv & 0xf;
979: Crossbar_Recalculate_Clocks_Cycles();
980: }
981:
982: /**
983: * Write byte to record track select register (0xff8936).
984: * 0 = Record 1 track
985: * 1 = Record 2 tracks
986: * 2 = Record 3 tracks
987: * 3 = Record 4 tracks
988: */
989: void Crossbar_TrackRecSelect_WriteByte(void)
990: {
991: Uint8 recTrack = IoMem_ReadByte(0xff8936);
992:
993: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8936 (record track select) write: 0x%02x\n", recTrack);
994:
995: crossbar.recordTracks = recTrack & 3;
996: }
997:
998: /**
999: * Write byte to CODEC input source from 16 bit adder (0xff8937).
1000: * Bit 1 : source = multiplexer
1001: * Bit 0 : source = A/D convertor
1002: */
1003: void Crossbar_CodecInput_WriteByte(void)
1004: {
1005: Uint8 inputSource = IoMem_ReadByte(0xff8937);
1006:
1007: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8937 (CODEC input) write: 0x%02x\n", IoMem_ReadByte(0xff8937));
1008:
1009: crossbar.codecInputSource = inputSource & 3;
1010: }
1011:
1012: /**
1013: * Write byte to A/D converter input for L+R channel (0xff8938).
1014: * Bit 1 : Left (0 = Microphone ; 1 = PSG soundchip)
1015: * Bit 0 : Right (0 = Microphone ; 1 = PSG soundchip)
1016: */
1017: void Crossbar_AdcInput_WriteByte(void)
1018: {
1019: Uint8 input = IoMem_ReadByte(0xff8938);
1020:
1021: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8938 (ADC input) write: 0x%02x\n", IoMem_ReadByte(0xff8938));
1022:
1023: crossbar.codecAdcInput = input & 3;
1024: }
1025:
1026: /**
1027: * Write byte to input amplifier register (amplification for ADC device) (0xff8939).
1028: * Bits LLLLRRRR
1029: * Amplification is in +1.5 dB steps
1030: */
1031: void Crossbar_InputAmp_WriteByte(void)
1032: {
1033: Uint8 amplification = IoMem_ReadByte(0xff8939);
1034:
1035: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff8939 (CODEC channel amplification) write: 0x%02x\n", IoMem_ReadByte(0xff8939));
1036:
1037: crossbar.gainSettingLeft = Crossbar_ADC_volume_table[amplification >> 4];
1038: crossbar.gainSettingRight = Crossbar_ADC_volume_table[amplification & 0xf];
1039: }
1040:
1041: /**
1042: * Write byte to channel reduction register (attenuation for DAC device) (0xff893a).
1043: * Bits LLLLRRRR
1044: * Reduction is in -1.5 dB steps
1045: */
1046: void Crossbar_OutputReduct_WriteByte(void)
1047: {
1048: Uint8 reduction = IoMem_ReadByte(0xff893a);
1049:
1050: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff893a (CODEC channel attenuation) write: 0x%02x\n", IoMem_ReadByte(0xff893a));
1051:
1052: crossbar.attenuationSettingLeft = Crossbar_DAC_volume_table[reduction >> 4];
1053: crossbar.attenuationSettingRight = Crossbar_DAC_volume_table[reduction & 0xf];
1054: }
1055:
1056: /**
1057: * Write word to CODEC status register (0xff893c).
1058: * Bit 1 : Left Channel Overflow (0/1)
1059: * Bit 0 : Right Channel Overflow (0/1)
1060: */
1061: void Crossbar_CodecStatus_WriteWord(void)
1062: {
1063: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : $ff893c (CODEC status) write: 0x%04x\n", IoMem_ReadWord(0xff893c));
1064: }
1065:
1066:
1067:
1068: /*----------------------------------------------------------------------*/
1069: /*------------------------- Crossbar functions -------------------------*/
1070: /*----------------------------------------------------------------------*/
1071:
1072: /**
1073: * Recalculates internal clocks 25 Mhz and 32 Mhz cycles
1074: */
1075: static void Crossbar_Recalculate_Clocks_Cycles(void)
1076: {
1077: double cyclesClk;
1078:
1079: crossbar.clock25_cycles_counter = 0;
1080: crossbar.clock32_cycles_counter = 0;
1081:
1082: /* Calculate 25 Mhz clock cycles */
1083: cyclesClk = ((double)CPU_FREQ / Crossbar_DetectSampleRate(25)) / (double)(crossbar.playTracks) / 2.0;
1084: crossbar.clock25_cycles = (int)(cyclesClk);
1085: crossbar.clock25_cycles_decimal = (int)((cyclesClk - (double)(crossbar.clock25_cycles)) * (double)DECIMAL_PRECISION);
1086:
1087: /* Calculate 32 Mhz clock cycles */
1088: cyclesClk = ((double)CPU_FREQ / Crossbar_DetectSampleRate(32)) / (double)(crossbar.playTracks) / 2.0;
1089: crossbar.clock32_cycles = (int)(cyclesClk);
1090: crossbar.clock32_cycles_decimal = (int)((cyclesClk - (double)(crossbar.clock32_cycles)) * (double)DECIMAL_PRECISION);
1091:
1092: /* Recalculate ratio between host's sound frequency and hatari's sound frequency */
1093: crossbar.frequence_ratio = (Uint32)((Crossbar_DetectSampleRate(25) / (double)nAudioFrequency) * (double)DECIMAL_PRECISION);
1094:
1095: /* Recalculate ratio between hatari's sound frequency and host's sound frequency */
1096: crossbar.frequence_ratio2 = (Uint32)(((double)nAudioFrequency / Crossbar_DetectSampleRate(25)) * (double)DECIMAL_PRECISION);
1097:
1098: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : Recalculate_clock_Cycles\n");
1099: LOG_TRACE(TRACE_CROSSBAR, " clock25 : %d\n", crossbar.clock25_cycles);
1100: LOG_TRACE(TRACE_CROSSBAR, " clock32 : %d\n", crossbar.clock32_cycles);
1101:
1102: /* Verify if the new frequency doesn't mute the DAC */
1103: crossbar.isDacMuted = 0;
1104: if ((crossbar.int_freq_divider == 0) && (crossbar.steFreq == 0))
1105: crossbar.isDacMuted = 1;
1106:
1107: if ((crossbar.int_freq_divider == 6) || (crossbar.int_freq_divider == 8) ||
1108: (crossbar.int_freq_divider == 10) || (crossbar.int_freq_divider >= 12)) {
1109: crossbar.isDacMuted = 1;
1110: }
1111: }
1112:
1113: /**
1114: * Detect sample rate frequency
1115: * clock : value of the internal clock (25 or 32).
1116: */
1117: static double Crossbar_DetectSampleRate(Uint16 clock)
1118: {
1119: /* Ste compatible sound */
1120: if (crossbar.int_freq_divider == 0) {
1121: crossbar.isInSteFreqMode = 1;
1122: return Ste_SampleRates[crossbar.steFreq];
1123: }
1124:
1125: crossbar.isInSteFreqMode = 0;
1126:
1127: /* 25 Mhz internal clock */
1128: if (clock == 25)
1129: return Falcon_SampleRates_25Mhz[crossbar.int_freq_divider - 1];
1130:
1131: /* 32 Mhz internal clock */
1132: return Falcon_SampleRates_32Mhz[crossbar.int_freq_divider - 1];
1133: }
1134:
1135: /**
1136: * Start internal 25 Mhz clock interrupt.
1137: */
1138: static void Crossbar_Start_InterruptHandler_25Mhz(void)
1139: {
1140: Uint32 cycles_25;
1141:
1142: cycles_25 = crossbar.clock25_cycles;
1143: crossbar.clock25_cycles_counter += crossbar.clock25_cycles_decimal;
1144:
1145: if (crossbar.clock25_cycles_counter >= DECIMAL_PRECISION) {
1146: crossbar.clock25_cycles_counter -= DECIMAL_PRECISION;
1147: cycles_25 ++;
1148: }
1149:
1150: if (crossbar.pendingCyclesOver25 >= cycles_25) {
1151: crossbar.pendingCyclesOver25 -= cycles_25;
1152: cycles_25 = 0;
1153: }
1154: else {
1155: cycles_25 -= crossbar.pendingCyclesOver25;
1156: crossbar.pendingCyclesOver25 = 0;
1157: }
1158:
1159: CycInt_AddRelativeInterrupt(cycles_25, INT_CPU_CYCLE, INTERRUPT_CROSSBAR_25MHZ);
1160: }
1161:
1162: /**
1163: * Start internal 32 Mhz clock interrupt.
1164: */
1165: static void Crossbar_Start_InterruptHandler_32Mhz(void)
1166: {
1167: Uint32 cycles_32;
1168:
1169: cycles_32 = crossbar.clock32_cycles;
1170: crossbar.clock32_cycles_counter += crossbar.clock32_cycles_decimal;
1171:
1172: if (crossbar.clock32_cycles_counter >= DECIMAL_PRECISION) {
1173: crossbar.clock32_cycles_counter -= DECIMAL_PRECISION;
1174: cycles_32 ++;
1175: }
1176:
1177: if (crossbar.pendingCyclesOver32 >= cycles_32){
1178: crossbar.pendingCyclesOver32 -= cycles_32;
1179: cycles_32 = 0;
1180: }
1181: else {
1182: cycles_32 -= crossbar.pendingCyclesOver32;
1183: crossbar.pendingCyclesOver32 = 0;
1184: }
1185:
1186: CycInt_AddRelativeInterrupt(cycles_32, INT_CPU_CYCLE, INTERRUPT_CROSSBAR_32MHZ);
1187: }
1188:
1189:
1190: /**
1191: * Execute transfers for internal 25 Mhz clock.
1192: */
1193: void Crossbar_InterruptHandler_25Mhz(void)
1194: {
1195: /* How many cycle was this sound interrupt delayed (>= 0) */
1196: crossbar.pendingCyclesOver25 += -INT_CONVERT_FROM_INTERNAL ( PendingInterruptCount , INT_CPU_CYCLE );
1197:
1198: /* Remove this interrupt from list and re-order */
1199: CycInt_AcknowledgeInterrupt();
1200:
1201: /* If transfer mode is in Ste mode, use only this clock for all the transfers */
1202: if (crossbar.isInSteFreqMode) {
1203: Crossbar_Process_DSPXmit_Transfer();
1204: Crossbar_Process_DMAPlay_Transfer();
1205: Crossbar_Process_ADCXmit_Transfer();
1206:
1207: /* Restart the 25 Mhz clock interrupt */
1208: Crossbar_Start_InterruptHandler_25Mhz();
1209: return;
1210: }
1211:
1212: Crossbar_Process_ADCXmit_Transfer();
1213:
1214: /* DSP Play transfer ? */
1215: if (crossbar.dspXmit_freq == CROSSBAR_FREQ_25MHZ) {
1216: Crossbar_Process_DSPXmit_Transfer();
1217: }
1218:
1219: /* DMA Play transfer ? */
1220: if (crossbar.dmaPlay_freq == CROSSBAR_FREQ_25MHZ) {
1221: Crossbar_Process_DMAPlay_Transfer();
1222: }
1223:
1224: /* Restart the 25 Mhz clock interrupt */
1225: Crossbar_Start_InterruptHandler_25Mhz();
1226: }
1227:
1228: /**
1229: * Execute transfers for internal 32 Mhz clock.
1230: */
1231: void Crossbar_InterruptHandler_32Mhz(void)
1232: {
1233: /* How many cycle was this sound interrupt delayed (>= 0) */
1234: crossbar.pendingCyclesOver32 += -INT_CONVERT_FROM_INTERNAL ( PendingInterruptCount , INT_CPU_CYCLE );
1235:
1236: /* Remove this interrupt from list and re-order */
1237: CycInt_AcknowledgeInterrupt();
1238:
1239: /* If transfer mode is in Ste mode, don't use this clock for all the transfers */
1240: if (crossbar.isInSteFreqMode) {
1241: /* Restart the 32 Mhz clock interrupt */
1242: Crossbar_Start_InterruptHandler_32Mhz();
1243: return;
1244: }
1245:
1246: /* DSP Play transfer ? */
1247: if (crossbar.dspXmit_freq == CROSSBAR_FREQ_32MHZ) {
1248: Crossbar_Process_DSPXmit_Transfer();
1249: }
1250:
1251: /* DMA Play transfer ? */
1252: if (crossbar.dmaPlay_freq == CROSSBAR_FREQ_32MHZ) {
1253: Crossbar_Process_DMAPlay_Transfer();
1254: }
1255:
1256: /* Restart the 32 Mhz clock interrupt */
1257: Crossbar_Start_InterruptHandler_32Mhz();
1258: }
1259:
1260:
1261: /*----------------------------------------------------------------------*/
1262: /*--------------------- DSP Xmit processing ----------------------------*/
1263: /*----------------------------------------------------------------------*/
1264:
1265: /**
1266: * Process DSP xmit to crossbar transfer
1267: */
1268: static void Crossbar_Process_DSPXmit_Transfer(void)
1269: {
1270: Uint16 frame=0;
1271: Sint32 data;
1272:
1273: /* Is DSP Xmit connected to DMA Record in handshake mode ? */
1274: if (dmaRecord.isConnectedToDspInHandShakeMode) {
1275: Crossbar_Process_DMARecord_HandshakeMode();
1276: return;
1277: }
1278:
1279: /* Is DSP Xmit connected to something ? */
1280: if (!dspXmit.isConnectedToCodec && !dspXmit.isConnectedToDma && !dspXmit.isConnectedToDsp)
1281: return;
1282:
1283: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : DSP --> Crossbar transfer\n");
1284:
1285: if (dspXmit.wordCount == 0) {
1286: frame = 1;
1287: }
1288:
1289: /* Send the frame status to the DSP SSI Xmit */
1290: DSP_SsiReceive_SC2(frame);
1291:
1292: /* Send the clock to the DSP SSI Xmit */
1293: DSP_SsiReceive_SCK();
1294:
1295: /* read data from DSP Xmit */
1296: data = DSP_SsiReadTxValue();
1297:
1298: /* Send DSP data to the DAC ? */
1299: if (dspXmit.isConnectedToCodec) {
1300: Crossbar_SendDataToDAC(data, dspXmit.wordCount);
1301: }
1302:
1303: /* Send DSP data to the DMA record ? */
1304: if (dspXmit.isConnectedToDma) {
1305: Crossbar_SendDataToDmaRecord(data);
1306: }
1307:
1308: /* Send DSP data to the DSP in ? */
1309: if (dspXmit.isConnectedToDsp) {
1310: Crossbar_SendDataToDspReceive(data, frame);
1311: }
1312:
1313: /* increase dspXmit.wordCount for next sample */
1314: dspXmit.wordCount++;
1315: if (dspXmit.wordCount >= (crossbar.playTracks * 2)) {
1316: dspXmit.wordCount = 0;
1317: }
1318: }
1319:
1320: /*----------------------------------------------------------------------*/
1321: /*--------------------- DSP Receive processing -------------------------*/
1322: /*----------------------------------------------------------------------*/
1323:
1324: /**
1325: * Transmit data from crossbar to DSP receive.
1326: */
1327: static void Crossbar_SendDataToDspReceive(Uint32 value, Uint16 frame)
1328: {
1329: /* Verify that DSP IN is not tristated */
1330: if (dspReceive.isTristated) {
1331: return;
1332: }
1333:
1334: /* Send sample to DSP receive */
1335: DSP_SsiWriteRxValue(value);
1336:
1337: /* Send the frame status to the DSP SSI receive */
1338: /* only in non hanshake mode */
1339: if (dmaPlay.handshakeMode_Frame == 0) {
1340: DSP_SsiReceive_SC1(frame);
1341: }
1342:
1343: dmaPlay.handshakeMode_Frame = 0;
1344:
1345: /* Send the clock to the DSP SSI receive */
1346: DSP_SsiReceive_SC0();
1347: }
1348:
1349: /*----------------------------------------------------------------------*/
1350: /*--------------------- DMA PLAY sound processing ----------------------*/
1351: /*----------------------------------------------------------------------*/
1352:
1353: /**
1354: * Set DMA Play sound start frame buffer, stop frame buffer, frame length
1355: */
1356: static void Crossbar_setDmaPlay_Settings(void)
1357: {
1358: /* DMA setings */
1359: dmaPlay.frameStartAddr = crossbar.dmaPlay_CurrentFrameStart;
1360: dmaPlay.frameEndAddr = crossbar.dmaPlay_CurrentFrameEnd;
1361: dmaPlay.frameLen = dmaPlay.frameEndAddr - dmaPlay.frameStartAddr;
1362: // dmaPlay.frameCounter = crossbar.dmaPlay_CurrentFrameCount - crossbar.dmaPlay_CurrentFrameStart;
1363: dmaPlay.frameCounter = 0;
1364:
1365: if (dmaPlay.frameEndAddr <= dmaPlay.frameStartAddr)
1366: {
1367: Log_Printf(LOG_WARN, "crossbar DMA Play: Illegal buffer size (from 0x%06x to 0x%06x)\n",
1368: dmaPlay.frameStartAddr, dmaPlay.frameEndAddr);
1369: }
1370: }
1371:
1372: /**
1373: * Process DMA Play transfer to crossbar
1374: */
1375: static void Crossbar_Process_DMAPlay_Transfer(void)
1376: {
1377: Sint16 value, eightBits;
1378: Sint8 *pFrameStart;
1379: Uint8 dmaCtrlReg;
1380:
1381: /* if DMA play is not running, return */
1382: if (dmaPlay.isRunning == 0)
1383: return;
1384:
1385: /* if handshake mode */
1386: if (dmaPlay.isConnectedToDspInHandShakeMode) {
1387: if (dmaPlay.handshakeMode_Frame == 0) {
1388: return;
1389: }
1390: }
1391:
1392: pFrameStart = (Sint8 *)&STRam[dmaPlay.frameStartAddr];
1393:
1394: /* 16 bits stereo mode ? */
1395: if (crossbar.is16Bits) {
1396: eightBits = 1;
1397: value = (Sint16)do_get_mem_word(&pFrameStart[dmaPlay.frameCounter]);
1398: dmaPlay.frameCounter += 2;
1399: }
1400: /* 8 bits stereo ? */
1401: else if (crossbar.isStereo) {
1402: eightBits = 64;
1403: value = (Sint16) pFrameStart[dmaPlay.frameCounter];
1404: dmaPlay.frameCounter ++;
1405: }
1406: /* 8 bits mono */
1407: else {
1408: eightBits = 64;
1409: value = (Sint16) pFrameStart[dmaPlay.frameCounter];
1410: if ((dmaPlay.currentFrame & 1) == 0) {
1411: dmaPlay.frameCounter ++;
1412:
1413: }
1414: }
1415:
1416: /* Send sample to the DMA record ? */
1417: if (dmaPlay.isConnectedToDma) {
1418: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : DMA Play --> DMA record\n");
1419: Crossbar_SendDataToDmaRecord(value);
1420: }
1421:
1422: /* Send sample to the DAC ? */
1423: if (dmaPlay.isConnectedToCodec) {
1424: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : DMA Play --> DAC\n");
1425: Crossbar_SendDataToDAC(value * eightBits, dmaPlay.currentFrame);
1426: }
1427:
1428: /* Send sample to the DSP in ? */
1429: if (dmaPlay.isConnectedToDsp) {
1430: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : DMA Play --> DSP record\n");
1431: /* New frame ? */
1432: if (dmaPlay.currentFrame == 0) {
1433: Crossbar_SendDataToDspReceive(value, 1);
1434: }
1435: else {
1436: Crossbar_SendDataToDspReceive(value, 0);
1437: }
1438: }
1439:
1440: /* increase dmaPlay.currentFrame for next sample */
1441: dmaPlay.currentFrame ++;
1442: if (dmaPlay.currentFrame >= (crossbar.playTracks * 2)) {
1443: dmaPlay.currentFrame = 0;
1444: }
1445:
1446: /* Check if end-of-frame has been reached and raise interrupts if needed. */
1447: if (dmaPlay.frameCounter >= dmaPlay.frameLen)
1448: {
1449: /* Update sound */
1450: //Sound_Update();
1451:
1452: /* Send a MFP15_Int (I7) at end of replay buffer if enabled */
1453: if (dmaPlay.mfp15_int) {
1454: MFP_InputOnChannel(MFP_TIMER_GPIP7_BIT, MFP_IERA, &MFP_IPRA);
1455: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : MFP15 (IT7) interrupt from DMA play\n");
1456: }
1457:
1458: /* Send a TimerA_Int at end of replay buffer if enabled */
1459: if (dmaPlay.timerA_int) {
1460: if (MFP_TACR == 0x08) { /* Is timer A in Event Count mode? */
1461: MFP_TimerA_EventCount_Interrupt();
1462: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : MFP Timer A interrupt from DMA play\n");
1463: }
1464: }
1465:
1466: if (dmaPlay.loopMode) {
1467: Crossbar_setDmaPlay_Settings();
1468: }
1469: else {
1470: dmaCtrlReg = IoMem_ReadByte(0xff8901) & 0xfe;
1471: IoMem_bput(0xff8901, dmaCtrlReg);
1472: }
1473: }
1474: }
1475:
1476: /**
1477: * Function called when DmaPlay is in handshake mode */
1478: void Crossbar_DmaPlayInHandShakeMode(void)
1479: {
1480: dmaPlay.handshakeMode_Frame = 1;
1481: }
1482:
1483: /*----------------------------------------------------------------------*/
1484: /*--------------------- DMA Record processing --------------------------*/
1485: /*----------------------------------------------------------------------*/
1486:
1487: /**
1488: * Set DMA Record sound start frame buffer, stop frame buffer, frame length
1489: */
1490: static void Crossbar_setDmaRecord_Settings(void)
1491: {
1492: /* DMA setings */
1493: dmaRecord.frameStartAddr = crossbar.dmaRecord_CurrentFrameStart;
1494: dmaRecord.frameEndAddr = crossbar.dmaRecord_CurrentFrameEnd;
1495: dmaRecord.frameLen = dmaRecord.frameEndAddr - dmaRecord.frameStartAddr;
1496: // dmaRecord.frameCounter = crossbar.dmaRecord_CurrentFrameCount - crossbar.dmaRecord_CurrentFrameStart;
1497: dmaRecord.frameCounter = 0;
1498:
1499: if (dmaRecord.frameEndAddr <= dmaRecord.frameStartAddr) {
1500: Log_Printf(LOG_WARN, "crossbar DMA Record: Illegal buffer size (from 0x%06x to 0x%06x)\n",
1501: dmaRecord.frameStartAddr, dmaRecord.frameEndAddr);
1502: }
1503: }
1504:
1505: /**
1506: * DMA Record processing
1507: */
1508: void Crossbar_SendDataToDmaRecord(Sint16 value)
1509: {
1510: Sint8 *pFrameStart;
1511: Uint8 dmaCtrlReg;
1512:
1513: if (dmaRecord.isRunning == 0) {
1514: return;
1515: }
1516:
1517: pFrameStart = (Sint8 *)&STRam[dmaRecord.frameStartAddr];
1518:
1519: /* 16 bits stereo mode ? */
1520: if (crossbar.is16Bits) {
1521: do_put_mem_word(&pFrameStart[dmaRecord.frameCounter], value);
1522: dmaRecord.frameCounter += 2;
1523: }
1524: /* 8 bits stereo ? */
1525: else if (crossbar.isStereo) {
1526: do_put_mem_word(&pFrameStart[dmaRecord.frameCounter], value);
1527: dmaRecord.frameCounter += 2;
1528: // pFrameStart[dmaRecord.frameCounter] = (Uint8)value;
1529: // dmaRecord.frameCounter ++;
1530: }
1531: /* 8 bits mono */
1532: else {
1533: pFrameStart[dmaRecord.frameCounter] = (Uint8)value;
1534: dmaRecord.frameCounter ++;
1535: }
1536:
1537: /* Check if end-of-frame has been reached and raise interrupts if needed. */
1538: if (dmaRecord.frameCounter >= dmaRecord.frameLen)
1539: {
1540: /* Send a MFP15_Int (I7) at end of record buffer if enabled */
1541: if (dmaRecord.mfp15_int) {
1542: MFP_InputOnChannel(MFP_TIMER_GPIP7_BIT, MFP_IERA, &MFP_IPRA);
1543: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : MFP15 (IT7) interrupt from DMA record\n");
1544: }
1545:
1546: /* Send a TimerA_Int at end of record buffer if enabled */
1547: if (dmaRecord.timerA_int) {
1548: if (MFP_TACR == 0x08) /* Is timer A in Event Count mode? */
1549: MFP_TimerA_EventCount_Interrupt();
1550: LOG_TRACE(TRACE_CROSSBAR, "Crossbar : MFP Timer A interrupt from DMA record\n");
1551: }
1552:
1553: if (dmaRecord.loopMode) {
1554: Crossbar_setDmaRecord_Settings();
1555: }
1556: else {
1557: dmaCtrlReg = IoMem_ReadByte(0xff8901) & 0xef;
1558: IoMem_bput(0xff8901, dmaCtrlReg);
1559: }
1560: }
1561: }
1562:
1563:
1564: /**
1565: * Process DMA Record connected to DSP Xmit in HandShake mode.
1566: * In this special case, DMA Record is the "master" and Dsp Xmit is the "slave".
1567: */
1568: static void Crossbar_Process_DMARecord_HandshakeMode(void)
1569: {
1570: Sint16 data;
1571:
1572: /* If DMA record is activated and is running */
1573: if (dmaRecord.isRunning == 0) {
1574: return;
1575: }
1576:
1577: /* If DSP frame is activated (SC2 pin of the SSI port) */
1578: if (dmaRecord.handshakeMode_Frame == 0) {
1579: return;
1580: }
1581:
1582: /* Send the clock to the DSP SSI Xmit */
1583: DSP_SsiReceive_SCK();
1584:
1585: /* read data from DSP Xmit */
1586: data = DSP_SsiReadTxValue();
1587: dmaRecord.handshakeMode_Frame = 0;
1588:
1589: Crossbar_SendDataToDmaRecord(data);
1590: }
1591:
1592: /**
1593: * Get the frame value from DSP SSI (handshake mode only)
1594: */
1595: void Crossbar_DmaRecordInHandShakeMode_Frame(Uint32 frame)
1596: {
1597: dmaRecord.handshakeMode_Frame = frame;
1598: }
1599:
1600:
1601: /*----------------------------------------------------------------------*/
1602: /*-------------------------- ADC processing ----------------------------*/
1603: /*----------------------------------------------------------------------*/
1604:
1605: /**
1606: * Get datas recorded by the microphone and convert them into falcon internal frequency
1607: * - micro_bufferL : left track recorded by the microphone
1608: * - micro_bufferR : right track recorded by the microphone
1609: * - microBuffer_size : buffers size
1610: */
1611: void Crossbar_GetMicrophoneDatas(Sint16 *micro_bufferL, Sint16 *micro_bufferR, Uint32 microBuffer_size)
1612: {
1613: Uint32 i, size, bufferIndex, indexPos, intPart;
1614:
1615: size = (microBuffer_size * crossbar.frequence_ratio) >> 16;
1616: bufferIndex = 0;
1617: indexPos = 0;
1618:
1619: for (i = 0; i < size; i++) {
1620: adc.writePosition = (adc.writePosition + 1) % DACBUFFER_SIZE;
1621:
1622: adc.buffer_left[adc.writePosition] = micro_bufferL[bufferIndex];
1623: adc.buffer_right[adc.writePosition] = micro_bufferR[bufferIndex];
1624:
1625: indexPos += crossbar.frequence_ratio2;
1626: if (indexPos >= DECIMAL_PRECISION) {
1627: intPart = indexPos >> 16;
1628: bufferIndex += intPart;
1629: indexPos -= intPart * DECIMAL_PRECISION;
1630: }
1631: }
1632: }
1633:
1634: /**
1635: * Process ADC transfer to crossbar
1636: */
1637: static void Crossbar_Process_ADCXmit_Transfer(void)
1638: {
1639: Sint16 sample;
1640: Uint16 frame;
1641:
1642: /* swap from left to right channel or right to left channel */
1643: adc.wordCount = 1 - adc.wordCount;
1644:
1645: /* Left Channel */
1646: if (adc.wordCount == 0) {
1647: sample = adc.buffer_left[adc.readPosition];
1648: frame = 1;
1649: }
1650: else {
1651: sample = adc.buffer_right[adc.readPosition];
1652: adc.readPosition = (adc.readPosition + 1) % DACBUFFER_SIZE;
1653: frame = 0;
1654: }
1655:
1656: /* Send sample to DSP receive ? */
1657: if (adc.isConnectedToDsp) {
1658: Crossbar_SendDataToDspReceive(sample, frame);
1659: }
1660:
1661: /* Send sample to DMA record ? */
1662: if (adc.isConnectedToDma) {
1663: Crossbar_SendDataToDmaRecord(sample);
1664: }
1665:
1666: /* Send sample to DAC ? */
1667: if (adc.isConnectedToCodec) {
1668: Crossbar_SendDataToDAC(sample, adc.wordCount);
1669: }
1670: }
1671:
1672:
1673: /*----------------------------------------------------------------------*/
1674: /*-------------------------- DAC processing ----------------------------*/
1675: /*----------------------------------------------------------------------*/
1676:
1677: /**
1678: * Put sample from crossbar into the DAC buffer.
1679: * - value : sample value to play
1680: * - sample_pos : position of the sample in the track (used to play the monitored track)
1681: */
1682: static void Crossbar_SendDataToDAC(Sint16 value, Uint16 sample_pos)
1683: {
1684: Uint16 track = crossbar.track_monitored * 2;
1685:
1686: if (sample_pos == track) {
1687: /* Left channel */
1688: dac.buffer_left[dac.writePosition] = value;
1689: }
1690: else if (sample_pos == track + 1) {
1691: /* Right channel */
1692: dac.buffer_right[dac.writePosition] = value;
1693: dac.writePosition = (dac.writePosition + 1) % (DACBUFFER_SIZE);
1694: }
1695: }
1696:
1697: /**
1698: * Mix PSG sound with microphone sound in ADC.
1699: * Also mix ADC sound sample with the crossbar DAC samples.
1700: * (Called by sound.c)
1701: */
1702: void Crossbar_GenerateSamples(int nMixBufIdx, int nSamplesToGenerate)
1703: {
1704: int i, nBufIdx;
1705: Uint32 intPart;
1706: Sint16 adc_leftData, adc_rightData, dac_LeftData, dac_RightData;
1707:
1708: if (crossbar.isDacMuted) {
1709: /* Output sound = 0 */
1710: for (i = 0; i < nSamplesToGenerate; i++) {
1711: nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
1712: MixBuffer[nBufIdx][0] = 0;
1713: MixBuffer[nBufIdx][1] = 0;
1714: }
1715:
1716: /* Counters are refreshed for when DAC becomes unmuted */
1717: dac.readPosition = dac.writePosition;
1718: dac.readPosition_decimal = 0;
1719: crossbar.adc_dac_readBufferPosition = adc.writePosition;
1720: return;
1721: }
1722:
1723: for (i = 0; i < nSamplesToGenerate; i++)
1724: {
1725: nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
1726:
1727: /* ADC mixing (PSG sound or microphone sound for left and right channels) */
1728: switch (crossbar.codecAdcInput) {
1729: case 0:
1730: default: /* Just here to remove compiler's warnings */
1731: /* Microphone sound for left and right channels */
1732: adc_leftData = adc.buffer_left[crossbar.adc_dac_readBufferPosition];
1733: adc_rightData = adc.buffer_right[crossbar.adc_dac_readBufferPosition];
1734: break;
1735: case 1:
1736: /* Microphone sound for left channel, PSG sound for right channel */
1737: adc_leftData = adc.buffer_left[crossbar.adc_dac_readBufferPosition];
1738: adc_rightData = MixBuffer[nBufIdx][1];
1739: break;
1740: case 2:
1741: /* PSG sound for left channel, microphone sound for right channel */
1742: adc_leftData = MixBuffer[nBufIdx][0];
1743: adc_rightData = adc.buffer_right[crossbar.adc_dac_readBufferPosition];
1744: break;
1745: case 3:
1746: /* PSG sound for left and right channels */
1747: adc_leftData = MixBuffer[nBufIdx][0];
1748: adc_rightData = MixBuffer[nBufIdx][1];
1749: break;
1750: }
1751:
1752: /* DAC mixing (direct ADC + crossbar) */
1753: switch (crossbar.codecInputSource) {
1754: case 0:
1755: default: /* Just here to remove compiler's warnings */
1756: /* No sound */
1757: dac_LeftData = 0;
1758: dac_RightData = 0;
1759: break;
1760: case 1:
1761: /* direct ADC->DAC sound only ADC*4/65536 */
1762: dac_LeftData = (adc_leftData * crossbar.gainSettingLeft) >> 14;
1763: dac_RightData = (adc_rightData * crossbar.gainSettingRight) >> 14;
1764: break;
1765: case 2:
1766: /* Crossbar->DAC sound only */
1767: dac_LeftData = dac.buffer_left[dac.readPosition];
1768: dac_RightData = dac.buffer_right[dac.readPosition];
1769: break;
1770: case 3:
1771: /* Mixing Direct ADC sound with Crossbar->DMA sound */
1772: dac_LeftData = ((adc_leftData * crossbar.gainSettingLeft) >> 14) +
1773: dac.buffer_left[dac.readPosition];
1774: dac_RightData = ((adc_rightData * crossbar.gainSettingRight) >> 14) +
1775: dac.buffer_right[dac.readPosition];
1776: break;
1777: }
1778:
1779: MixBuffer[nBufIdx][0] = (dac_LeftData * crossbar.attenuationSettingLeft) >> 16;
1780: MixBuffer[nBufIdx][1] = (dac_RightData * crossbar.attenuationSettingRight) >> 16;
1781:
1782: /* Upgrade dac's buffer read pointer */
1783: dac.readPosition_decimal += crossbar.frequence_ratio;
1784: if (dac.readPosition_decimal >= DECIMAL_PRECISION) {
1785: intPart = (dac.readPosition_decimal >> 16);
1786: dac.readPosition = (dac.readPosition + intPart) % DACBUFFER_SIZE;
1787: dac.readPosition_decimal -= intPart * DECIMAL_PRECISION;
1788: }
1789:
1790: /* Upgrade adc->dac's buffer read pointer */
1791: crossbar.adc_dac_readBufferPosition_decimal += crossbar.frequence_ratio;
1792: if (crossbar.adc_dac_readBufferPosition_decimal >= DECIMAL_PRECISION) {
1793: intPart = (crossbar.adc_dac_readBufferPosition_decimal >> 16);
1794: crossbar.adc_dac_readBufferPosition = (crossbar.adc_dac_readBufferPosition + intPart) % DACBUFFER_SIZE;
1795: crossbar.adc_dac_readBufferPosition_decimal -= intPart * DECIMAL_PRECISION;
1796: }
1797: }
1798: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.