Annotation of hatari/src/falcon/crossbar.c, revision 1.1.1.8

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.