Annotation of Examples/DriverKit/ProAudioSpectrum16/ProAudioSpectrum16_reloc.tproj/ProAudioSpectrum16.m, revision 1.1.1.1

1.1       root        1: /*     Copyright (c) 1993 NeXT Computer, Inc.  All rights reserved. 
                      2:  *
                      3:  */
                      4: #import "ProAudioSpectrum16.h"
                      5: #import "ProAudioSpectrum16Registers.h"
                      6: #import "ProAudioSpectrum16Inline.h"
                      7: 
                      8: #import <driverkit/generalFuncs.h>
                      9: 
                     10: static char pasDeviceName[] = "ProAudioSpectrum16";
                     11: static char pasDeviceKind[] = "Audio";
                     12: 
                     13: @implementation ProAudioSpectrum16
                     14: 
                     15: /*
                     16:  *  Probe and initialize new instance
                     17:  */
                     18: + (BOOL) probe:description
                     19: {
                     20:     ProAudioSpectrum16 *dev;
                     21:     
                     22:     dev = [self alloc];
                     23:     if (dev == nil)
                     24:         return NO;
                     25:     
                     26:     /*
                     27:      * Sets the base IO address (needs to be performed before any other
                     28:      * hardware access)
                     29:      */
                     30:     setBaseAddress(DEFAULT_BASE_ADDRESS);
                     31: 
                     32:     return [dev initFromDeviceDescription:description] != nil;
                     33: }
                     34: 
                     35: - (BOOL) reset
                     36: {
                     37:     IOReturn   ioReturn;
                     38:     unsigned int dmaChannel    = [[self deviceDescription] channel];
                     39:     unsigned int interrupt     = [[self deviceDescription] interrupt];
                     40:     IOEISADMATransferWidth     transferWidth = IO_16BitByteCount;
                     41:     
                     42:     [self setName: pasDeviceName];
                     43:     [self setDeviceKind: pasDeviceKind];
                     44:     
                     45:     if (! (resetHardware())) {
                     46:         IOLog("%s: hardware failed verification\n", [self name]);
                     47:         return NO;
                     48:     }
                     49:     
                     50:     /*
                     51:      * The irq and dma channel are software selectable on the 
                     52:      * ProAudioSpectrum16.
                     53:      */
                     54:     if (! (setDMAChannel(dmaChannel))) {
                     55:         IOLog("%s: %d is an invalid dma setting\n",
                     56:            [self name], dmaChannel);
                     57:        return NO;
                     58:     }
                     59: 
                     60:     if (! (setInterrupt(interrupt))) {
                     61:         IOLog("%s: %d is an invalid irq setting\n",
                     62:            [self name], interrupt);
                     63:        return NO;
                     64:     }
                     65: 
                     66:     /*
                     67:      * The DMA controller is initialized.
                     68:      */
                     69:     [self disableChannel: 0];
                     70: 
                     71:     /*
                     72:      * On both ISA and EISA machines, the ProAudioSpectrum16 hardware
                     73:      * requires that DMA channels 0-4 are set to an 8-bit transfer width. 
                     74:      */
                     75:     if ([self isEISAPresent]) {
                     76:         if (dmaChannel < 5)
                     77:            transferWidth = IO_8Bit;
                     78:            
                     79:         ioReturn = [self setDMATransferWidth: transferWidth forChannel: 0];
                     80:        if (ioReturn != IO_R_SUCCESS) {
                     81:            IOLog("%s: dma transfer width error %d\n", [self name], ioReturn);
                     82:            return NO;
                     83:        }
                     84:     }
                     85: 
                     86:     ioReturn = [self setTransferMode: IO_Single forChannel: 0];
                     87: 
                     88:     if (ioReturn != IO_R_SUCCESS)  {
                     89:        IOLog("%s: dma transfer mode error %d\n", [self name], ioReturn);
                     90:        return NO;
                     91:     }
                     92: 
                     93:     ioReturn = [self setAutoinitialize: YES forChannel: 0];
                     94:     if (ioReturn != IO_R_SUCCESS) {
                     95:        IOLog("%s: dma auto initialize error %d", [self name], ioReturn);
                     96:        return NO;
                     97:     }
                     98: 
                     99:     return YES;
                    100: }
                    101: 
                    102: /*
                    103:  * converts gain (0 - 32768) into attenuation (0 - 31)
                    104:  */
                    105: 
                    106: - (void) updateInputGainLeft
                    107: {
                    108:     unsigned int gain = [self inputGainLeft] / 1057;
                    109:     
                    110:     setInputAttenuation(MICROPHONE, LEFT_CHANNEL, (unsigned char) gain);
                    111:     setInputAttenuation(EXTERNAL_LINE_IN, LEFT_CHANNEL, (unsigned char) gain);
                    112: }
                    113: 
                    114: - (void)updateInputGainRight
                    115: {
                    116:     unsigned int gain = [self inputGainRight] / 1057;
                    117:     
                    118:     setInputAttenuation(MICROPHONE, RIGHT_CHANNEL, (unsigned char) gain);
                    119:     setInputAttenuation(EXTERNAL_LINE_IN, RIGHT_CHANNEL, (unsigned char) gain);
                    120: }
                    121: 
                    122: - (void)updateOutputMute
                    123: {
                    124:     enableAudioOutput(! [self isOutputMuted]);
                    125: }
                    126: 
                    127: - (void)updateLoudnessEnhanced
                    128: {
                    129:     setLoudnessFilter([self isLoudnessEnhanced]);
                    130: }
                    131: 
                    132: /*
                    133:  * (0) - (-84) needs to be converted to (0) - (31)
                    134:  */
                    135: - (void) updateOutputAttenuationLeft
                    136: {
                    137:    unsigned int attenuation = [self outputAttenuationLeft] + 84;
                    138:    attenuation = ((attenuation * 10)/27);
                    139:     
                    140:     setOutputAttenuation(PCM, LEFT_CHANNEL, (unsigned char) attenuation);
                    141: }
                    142: 
                    143: /*
                    144:  * (0) - (-84) needs to be converted to (0) - (32)
                    145:  */
                    146: - (void) updateOutputAttenuationRight
                    147: {
                    148:    unsigned int attenuation = [self outputAttenuationRight] + 84;
                    149:    attenuation = ((attenuation * 10)/27);
                    150: 
                    151:     setOutputAttenuation(PCM, RIGHT_CHANNEL, (unsigned char) attenuation);
                    152: }
                    153: 
                    154: - (IOReturn) enableAllInterrupts
                    155: {
                    156:     interruptStatus_t  interruptStatus = {0};
                    157:     interruptControl_t interruptControl = {0};
                    158:     
                    159:     /*
                    160:      * clear all interrupts
                    161:      */
                    162:     setInterruptStatus(interruptStatus);
                    163: 
                    164:     interruptControl.enableSampleBufferInterrupt = YES;
                    165:     setInterruptControl(interruptControl);
                    166:     
                    167:     return [super enableAllInterrupts];
                    168: }
                    169: 
                    170: - (void) disableAllInterrupts
                    171: {
                    172:     interruptControl_t interruptControl = {0};
                    173: 
                    174:     setInterruptControl(interruptControl);
                    175:     
                    176:     [super disableAllInterrupts];
                    177: }
                    178: 
                    179: 
                    180: - (BOOL) startDMAForChannel: (unsigned int) localChannel
                    181:                        read: (BOOL) isRead
                    182:                      buffer: (IOEISADMABuffer) buffer
                    183:     bufferSizeForInterrupts: (unsigned int) bufferSize
                    184: {
                    185: 
                    186:     IOReturn ioReturn;
                    187:     unsigned int rate = [self sampleRate];
                    188:     
                    189:     IOEISADMATransferWidth     transferWidth;
                    190:     
                    191:     filterControl_t            filterControl           = {0};
                    192:     crossChannelControl_t      crossChannelControl     = {0};
                    193:     systemConfiguration2_t     systemConfiguration2    = {0};
                    194: 
                    195: 
                    196:     /*
                    197:      * Before enabling the DMA channel, "secure" the channel via the DRQ
                    198:      * bit in the Cross Channel register (0xf8a). This causes the
                    199:      * ProAudioSpectrum16 to drive the DMA channel from a floating state to
                    200:      * a known good state. If you enable the DMA channel with an unsecured
                    201:      * DRQ line, the DMA will perform a rapid-fire data tranfer due to the
                    202:      * floating DRQ line.
                    203:      */
                    204:     crossChannelControl = getCrossChannelControl();
                    205:     crossChannelControl.enableDMA = YES;
                    206:     setCrossChannelControl(crossChannelControl);
                    207:     
                    208:     ioReturn = [self startDMAForBuffer: buffer channel: localChannel];
                    209: 
                    210:     if (ioReturn != IO_R_SUCCESS) {
                    211:         IOLog("%s: could not start DMA channel error %d\n",
                    212:                [self name], ioReturn);
                    213:        return NO;
                    214:     }
                    215:         
                    216:     ioReturn = [self enableChannel: localChannel];
                    217:     
                    218:     if (ioReturn != IO_R_SUCCESS) {
                    219:         IOLog("%s: could not enable DMA channel error %d\n",
                    220:                [self name], ioReturn);
                    221:        return NO;
                    222:     }
                    223: 
                    224:     (void) [self enableAllInterrupts];
                    225: 
                    226:     setSampleRateTimer(rate);
                    227:    
                    228:     /*
                    229:      * Use the Sample Buffer Count register to set the number of bytes in the
                    230:      * DMA buffer division. This register holds a 16-bit value. When using a
                    231:      * 16-bit DMA channel, the Sample Buffer Count must be divided by two.
                    232:      */
                    233:     (void) [self getDMATransferWidth: &transferWidth forChannel: localChannel];
                    234:     if (transferWidth == IO_16BitByteCount ||
                    235:        transferWidth == IO_16BitWordCount)
                    236:        setSampleBufferCounter(bufferSize / 2);
                    237:     else
                    238:        setSampleBufferCounter(bufferSize);
                    239:         
                    240: 
                    241:     if ([self dataEncoding] == NX_SoundStreamDataEncoding_Linear16)
                    242:        systemConfiguration2.dataEncoding = LINEAR_16;
                    243:     else
                    244:        systemConfiguration2.dataEncoding = LINEAR_8;
                    245:        
                    246:     setSystemConfiguration2(systemConfiguration2);
                    247:     
                    248:     crossChannelControl.rightToRight = YES;
                    249:     crossChannelControl.leftToLeft = YES;
                    250: 
                    251:     crossChannelControl.direction = !isRead;
                    252:        
                    253:     /*
                    254:      * The mixer has feedback problems. MediaVision advised us to mute
                    255:      * the PCM output channel when recording.
                    256:      */
                    257:     if (isRead)
                    258:         setOutputAttenuation(PCM, BOTH_CHANNELS, 0);
                    259:        
                    260:     if ([self channelCount] == 1) 
                    261:         crossChannelControl.isMono = YES;
                    262:     else
                    263:         crossChannelControl.isMono = NO;
                    264:        
                    265:     setCrossChannelControl(crossChannelControl);
                    266:     crossChannelControl.enablePCM = YES;
                    267:     crossChannelControl.enableDMA = YES;
                    268:     setCrossChannelControl(crossChannelControl);
                    269:     
                    270:     filterControl = getFilterControl();
                    271:     filterControl.enableSampleRateTimer = YES;
                    272:     filterControl.enableSampleBufferCounter = YES;
                    273:     setFilterControl(filterControl);
                    274: 
                    275:     return YES;
                    276: }
                    277: 
                    278: - (void) stopDMAForChannel: (unsigned int) localChannel read: (BOOL) isRead
                    279: {
                    280:     filterControl_t            filterControl           = {0};
                    281:     crossChannelControl_t      crossChannelControl     = {0};
                    282: 
                    283:     [self disableChannel: localChannel];
                    284:     
                    285:     filterControl = getFilterControl();
                    286:     filterControl.enableSampleRateTimer = NO;
                    287:     filterControl.enableSampleBufferCounter = NO;
                    288:     setFilterControl(filterControl);
                    289:  
                    290:     (void)[self disableAllInterrupts];   
                    291:  
                    292:     crossChannelControl = getCrossChannelControl();
                    293:     crossChannelControl.enablePCM = NO;
                    294:     setCrossChannelControl(crossChannelControl);
                    295:     crossChannelControl.enableDMA = NO;
                    296:     setCrossChannelControl(crossChannelControl);
                    297:     
                    298:     /*
                    299:      * Due to mixer feedback problems, the PCM channels are muted during
                    300:      * recording. Their current values are restored here.
                    301:      */
                    302:     if (isRead) {
                    303:         [self updateOutputAttenuationLeft];
                    304:        [self updateOutputAttenuationRight];
                    305:     }
                    306: }
                    307: 
                    308: static void clearInterrupts(void)
                    309: {
                    310:     interruptStatus_t  interruptStatus = {0};
                    311: 
                    312:     /*
                    313:      * clear the hardware interrupt register
                    314:      */
                    315:     interruptStatus = getInterruptStatus();
                    316:     if (! interruptStatus.sampleBufferInterruptPending)
                    317:        return;
                    318:     
                    319:     /*
                    320:      * The chip specification states that a write to this register
                    321:      * will clear the clip status and sample interrupts.
                    322:      */
                    323:     interruptStatus.sampleBufferInterruptPending = NO;
                    324:     setInterruptStatus(interruptStatus);
                    325: }
                    326: 
                    327: - (IOAudioInterruptClearFunc) interruptClearFunc
                    328: {
                    329:     return clearInterrupts;
                    330: }
                    331: 
                    332: - (void) interruptOccurredForInput: (BOOL*)serviceInput
                    333:                          forOutput:(BOOL*)serviceOutput
                    334: {
                    335:     interruptStatus_t  interruptStatus = {0};
                    336: 
                    337:     /*
                    338:      * clear the hardware interrupt register
                    339:      */
                    340:     interruptStatus = getInterruptStatus();
                    341:     if (! interruptStatus.sampleBufferInterruptPending) {
                    342:        IOLog("ProAudioSpectrum16: spurious dma interrupt\n");
                    343:        return;
                    344:     }
                    345:     
                    346:     /*
                    347:      * The chip specification states that a write to this register
                    348:      * will clear the clip status and sample interrupts.
                    349:      */
                    350:     interruptStatus.sampleBufferInterruptPending = NO;
                    351:     setInterruptStatus(interruptStatus);
                    352: 
                    353:     if ([self isInputActive])
                    354:         *serviceInput = YES;
                    355:     else
                    356:         *serviceOutput = YES;
                    357: }
                    358: 
                    359: - (void) timeoutOccurred
                    360: {
                    361:     crossChannelControl_t      crossChannelControl     = {0};
                    362: 
                    363:     crossChannelControl = getCrossChannelControl();
                    364:     crossChannelControl.enablePCM = NO;
                    365:     setCrossChannelControl(crossChannelControl);
                    366:     crossChannelControl.enablePCM = YES;
                    367:     setCrossChannelControl(crossChannelControl);
                    368: }
                    369: 
                    370: /*
                    371:  * Parameter access.
                    372:  */
                    373: 
                    374: - (BOOL)acceptsContinuousSamplingRates
                    375: {
                    376:     return YES;
                    377: }
                    378: 
                    379: - (void)getSamplingRatesLow: (int *)lowRate
                    380:                        high: (int *)highRate
                    381: {
                    382:     *lowRate = 2000;
                    383:     *highRate = 44100;
                    384: }
                    385: 
                    386: - (void)getSamplingRates: (int *)rates
                    387:                    count: (unsigned int *)numRates
                    388: {
                    389:     /* Return a few common rates */
                    390:     rates[0] = 2000;
                    391:     rates[1] = 8000;
                    392:     rates[2] = 11025;
                    393:     rates[3] = 16000;
                    394:     rates[4] = 22050;
                    395:     rates[5] = 32000;
                    396:     rates[6] = 44100;
                    397:     *numRates = 7;
                    398: }
                    399: 
                    400: - (void)getDataEncodings: (NXSoundParameterTag *)encodings
                    401:                    count: (unsigned int *)numEncodings
                    402: {
                    403:     IOEISADMATransferWidth transferWidth;
                    404: 
                    405:     encodings[0] = NX_SoundStreamDataEncoding_Linear8;
                    406:     encodings[1] = NX_SoundStreamDataEncoding_Linear16;
                    407:     *numEncodings = 2;
                    408: 
                    409:     /*
                    410:      * For EISA machines, the driver is unable to handle 16-bit linear data
                    411:      * when the DMA transfer width is 8 bits.
                    412:      */
                    413:     if ([self isEISAPresent]) {
                    414:         (void)[self getDMATransferWidth: &transferWidth forChannel: 0];
                    415:        if (transferWidth == IO_8Bit) {
                    416:            encodings[1] = 0;
                    417:            *numEncodings = 1;
                    418:        }
                    419:     }
                    420: }
                    421: 
                    422: - (unsigned int) channelCountLimit
                    423: {
                    424:     return 2;  /* stereo and mono */
                    425: }
                    426: 
                    427: @end

unix.superglobalmegacorp.com

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