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

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

unix.superglobalmegacorp.com

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