|
|
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.