--- hatari/src/falcon/crossbar.c 2019/04/09 08:48:46 1.1 +++ hatari/src/falcon/crossbar.c 2019/04/09 08:50:31 1.1.1.3 @@ -263,6 +263,8 @@ struct crossbar_s { Uint32 dmaRecord_CurrentFrameEnd; /* current DmaRecord Frame end ($ff890f $ff8911 $ff8913) */ Uint32 adc_dac_readBufferPosition; /* read position for direct adc->dac transfer */ Uint32 adc_dac_readBufferPosition_decimal; /* decimal part of read position for direct adc->dac transfer */ + + Uint32 save_special_transfer; /* Used in a special undocumented transfer mode (dsp sent is not in handshake mode and dsp receive is in handshake mode) */ }; struct codec_s { @@ -326,8 +328,8 @@ void Crossbar_Reset(bool bCold) dac.writePosition = 0; /* ADC inits */ - memset(adc.buffer_left, 0, sizeof(dac.buffer_left)); - memset(adc.buffer_right, 0, sizeof(dac.buffer_right)); + memset(adc.buffer_left, 0, sizeof(adc.buffer_left)); + memset(adc.buffer_right, 0, sizeof(adc.buffer_right)); adc.readPosition = 0; adc.readPosition_decimal = 0; adc.writePosition = 0; @@ -374,6 +376,9 @@ void Crossbar_Reset(bool bCold) crossbar.microphone_ADC_is_started = Microphone_Start((int)nAudioFrequency); } + /* Initialize special transfer mode */ + crossbar.save_special_transfer = 0; + /* Initialize Crossbar values after reboot */ IoMem_WriteByte(0xff8900,0x05); IoMem_WriteByte(0xff8903,0xff); @@ -447,14 +452,12 @@ void Crossbar_DmaCtrlReg_WriteByte(void) else if (dmaPlay.isRunning && ((sndCtrl & CROSSBAR_SNDCTRL_PLAY) == 0)) { /* Create samples up until this point with current values */ - Sound_Update(); + Sound_Update(false); /* Turning off DMA play sound emulation */ dmaPlay.isRunning = 0; dmaPlay.loopMode = 0; nCbar_DmaSoundControl = sndCtrl; - memset(dac.buffer_left, 0, sizeof(dac.buffer_left)); - memset(dac.buffer_right, 0, sizeof(dac.buffer_right)); } /* DMA Record mode */ @@ -462,16 +465,16 @@ void Crossbar_DmaCtrlReg_WriteByte(void) { /* Turning on DMA record sound emulation */ dmaRecord.isRunning = 1; - dmaRecord.loopMode = (sndCtrl & 0x20) >> 5; nCbar_DmaSoundControl = sndCtrl; + dmaRecord.loopMode = (sndCtrl & 0x20) >> 5; Crossbar_setDmaRecord_Settings(); } else if (dmaRecord.isRunning && ((sndCtrl & CROSSBAR_SNDCTRL_RECORD) == 0)) { /* Turning off DMA record sound emulation */ - nCbar_DmaSoundControl = sndCtrl; dmaRecord.isRunning = 0; dmaRecord.loopMode = 0; + nCbar_DmaSoundControl = sndCtrl; } } @@ -879,18 +882,15 @@ void Crossbar_SrcControler_WriteWord(voi crossbar.dspXmit_freq = (nCbSrc >> 5) & 0x3; crossbar.dmaPlay_freq = (nCbSrc >> 1) & 0x3; - - dmaPlay.isConnectedToDspInHandShakeMode = ((nCbSrc & 9) == 0 ? 1 : 0); } /** * Write word to Falcon Crossbar destination controller (0xff8932). Source: D/A Convertor BIT 15 14 13 12 - 00 - DMA output ------------------------------+--+ | - 01 - DSP output ------------------------------+--+ | - 10 - External input --------------------------+--+ | - 11 - ADC input -------------------------------+--' | - 0 - Handshake on, 1 - Handshake off ----------------' + 00 - DMA output ------------------------------+--+ + 01 - DSP output ------------------------------+--+ + 10 - External input --------------------------+--+ + 11 - ADC input -------------------------------+--' Source: External OutPut BIT 11 10 9 8 0 - DSP OUT, 1 - All others ---------------' | | | @@ -954,7 +954,9 @@ void Crossbar_DstControler_WriteWord(voi adc.isConnectedToDsp = (destCtrl & 0x60) == 0x60 ? 1 : 0; adc.isConnectedToDma = (destCtrl & 0x6) == 0x6 ? 1 : 0; - dmaPlay.isConnectedToDspInHandShakeMode = ((destCtrl & 7) == 2 ? 1 : 0); + dmaPlay.isConnectedToDspInHandShakeMode = (((destCtrl >> 4) & 7) == 0 ? 1 : 0); + dmaPlay.handshakeMode_Frame = dmaPlay.isConnectedToDspInHandShakeMode; + dmaRecord.isConnectedToDspInHandShakeMode = ((destCtrl & 0xf) == 2 ? 1 : 0); } @@ -1088,12 +1090,6 @@ static void Crossbar_Recalculate_Clocks_ cyclesClk = ((double)CPU_FREQ / Crossbar_DetectSampleRate(32)) / (double)(crossbar.playTracks) / 2.0; crossbar.clock32_cycles = (int)(cyclesClk); crossbar.clock32_cycles_decimal = (int)((cyclesClk - (double)(crossbar.clock32_cycles)) * (double)DECIMAL_PRECISION); - - /* Recalculate ratio between host's sound frequency and hatari's sound frequency */ - crossbar.frequence_ratio = (Uint32)((Crossbar_DetectSampleRate(25) / (double)nAudioFrequency) * (double)DECIMAL_PRECISION); - - /* Recalculate ratio between hatari's sound frequency and host's sound frequency */ - crossbar.frequence_ratio2 = (Uint32)(((double)nAudioFrequency / Crossbar_DetectSampleRate(25)) * (double)DECIMAL_PRECISION); LOG_TRACE(TRACE_CROSSBAR, "Crossbar : Recalculate_clock_Cycles\n"); LOG_TRACE(TRACE_CROSSBAR, " clock25 : %d\n", crossbar.clock25_cycles); @@ -1108,6 +1104,22 @@ static void Crossbar_Recalculate_Clocks_ (crossbar.int_freq_divider == 10) || (crossbar.int_freq_divider >= 12)) { crossbar.isDacMuted = 1; } + + // Compute Ratio between host computer sound frequency and Hatari's sound frequency. + Crossbar_Compute_Ratio(); +} + +/** + * Compute Ratio between host computer sound frequency and Hatari's sound frequency and + * ratio between hatari's sound frequency and host's sound frequency. + * Can be called by audio.c if a sound frequency value is changed in the parameter GUI. + */ +void Crossbar_Compute_Ratio(void) +{ + crossbar.frequence_ratio = (Uint32)((Crossbar_DetectSampleRate(25) / (double)nAudioFrequency) * (double)DECIMAL_PRECISION); + + /* Recompute ratio between hatari's sound frequency and host's sound frequency */ + crossbar.frequence_ratio2 = (Uint32)(((double)nAudioFrequency / Crossbar_DetectSampleRate(25)) * (double)DECIMAL_PRECISION); } /** @@ -1269,6 +1281,10 @@ static void Crossbar_Process_DSPXmit_Tra { Uint16 frame=0; Sint32 data; + + /* If DSP Xmit is tristated, do nothing */ + if (dspXmit.isTristated) + return; /* Is DSP Xmit connected to DMA Record in handshake mode ? */ if (dmaRecord.isConnectedToDspInHandShakeMode) { @@ -1374,6 +1390,7 @@ static void Crossbar_setDmaPlay_Settings */ static void Crossbar_Process_DMAPlay_Transfer(void) { + Uint16 temp, increment_frame; Sint16 value, eightBits; Sint8 *pFrameStart; Uint8 dmaCtrlReg; @@ -1381,38 +1398,54 @@ static void Crossbar_Process_DMAPlay_Tra /* if DMA play is not running, return */ if (dmaPlay.isRunning == 0) return; - - /* if handshake mode */ - if (dmaPlay.isConnectedToDspInHandShakeMode) { - if (dmaPlay.handshakeMode_Frame == 0) { - return; - } - } pFrameStart = (Sint8 *)&STRam[dmaPlay.frameStartAddr]; - + increment_frame = 0; + /* 16 bits stereo mode ? */ if (crossbar.is16Bits) { eightBits = 1; value = (Sint16)do_get_mem_word(&pFrameStart[dmaPlay.frameCounter]); - dmaPlay.frameCounter += 2; + increment_frame = 2; } /* 8 bits stereo ? */ else if (crossbar.isStereo) { eightBits = 64; value = (Sint16) pFrameStart[dmaPlay.frameCounter]; - dmaPlay.frameCounter ++; + increment_frame = 1; } /* 8 bits mono */ else { eightBits = 64; value = (Sint16) pFrameStart[dmaPlay.frameCounter]; if ((dmaPlay.currentFrame & 1) == 0) { - dmaPlay.frameCounter ++; + increment_frame = 1; + } + } + if (dmaPlay.isConnectedToDspInHandShakeMode) { + /* Handshake mode */ + if (dmaPlay.handshakeMode_Frame == 0) + return; + + dmaPlay.frameCounter += increment_frame; + + /* Special undocumented transfer mode : + When DMA Play --> DSP Receive is in HandShake mode at 32 Mhz, + datas are shifted 2 bits on the left after the transfer. + This occurs with all demos using the Mpeg2 player from nocrew (amanita, LostBlubb, Wait, ...) + */ + if (crossbar.dmaPlay_freq == CROSSBAR_FREQ_32MHZ) { + temp = (crossbar.save_special_transfer<<2) + ((value & 0xc000)>>14); + crossbar.save_special_transfer = value; + value = temp; } } - + else { + /* Non Handshake mode */ + dmaPlay.frameCounter += increment_frame; + } + /* Send sample to the DMA record ? */ if (dmaPlay.isConnectedToDma) { LOG_TRACE(TRACE_CROSSBAR, "Crossbar : DMA Play --> DMA record\n"); @@ -1445,10 +1478,7 @@ static void Crossbar_Process_DMAPlay_Tra /* Check if end-of-frame has been reached and raise interrupts if needed. */ if (dmaPlay.frameCounter >= dmaPlay.frameLen) - { - /* Update sound */ - //Sound_Update(); - + { /* Send a MFP15_Int (I7) at end of replay buffer if enabled */ if (dmaPlay.mfp15_int) { MFP_InputOnChannel(MFP_TIMER_GPIP7_BIT, MFP_IERA, &MFP_IPRA); @@ -1467,8 +1497,16 @@ static void Crossbar_Process_DMAPlay_Tra Crossbar_setDmaPlay_Settings(); } else { + /* Create samples up until this point with current values */ + Sound_Update(false); + dmaCtrlReg = IoMem_ReadByte(0xff8901) & 0xfe; - IoMem_bput(0xff8901, dmaCtrlReg); + IoMem_WriteByte(0xff8901, dmaCtrlReg); + + /* Turning off DMA play sound emulation */ + dmaPlay.isRunning = 0; + dmaPlay.loopMode = 0; + nCbar_DmaSoundControl = dmaCtrlReg; } } } @@ -1555,7 +1593,12 @@ void Crossbar_SendDataToDmaRecord(Sint16 } else { dmaCtrlReg = IoMem_ReadByte(0xff8901) & 0xef; - IoMem_bput(0xff8901, dmaCtrlReg); + IoMem_WriteByte(0xff8901, dmaCtrlReg); + + /* Turning off DMA record sound emulation */ + dmaRecord.isRunning = 0; + dmaRecord.loopMode = 0; + nCbar_DmaSoundControl = dmaCtrlReg; } } } @@ -1766,6 +1809,8 @@ void Crossbar_GenerateSamples(int nMixBu /* Crossbar->DAC sound only */ dac_LeftData = dac.buffer_left[dac.readPosition]; dac_RightData = dac.buffer_right[dac.readPosition]; + dac.buffer_left[dac.readPosition] = 0; + dac.buffer_right[dac.readPosition] = 0; break; case 3: /* Mixing Direct ADC sound with Crossbar->DMA sound */ @@ -1773,6 +1818,8 @@ void Crossbar_GenerateSamples(int nMixBu dac.buffer_left[dac.readPosition]; dac_RightData = ((adc_rightData * crossbar.gainSettingRight) >> 14) + dac.buffer_right[dac.readPosition]; + dac.buffer_left[dac.readPosition] = 0; + dac.buffer_right[dac.readPosition] = 0; break; }