void SDRPostThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO); sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif std::cout << "SDR post-processing thread started.." << std::endl; iqDataInQueue = (SDRThreadIQDataQueue*)getInputQueue("IQDataInput"); iqDataOutQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQDataOutput"); iqVisualQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQVisualDataOutput"); iqActiveDemodVisualQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQActiveDemodVisualDataOutput"); iqDataInQueue->set_max_num_items(0); while (!terminated) { SDRThreadIQData *data_in; iqDataInQueue->pop(data_in); // std::lock_guard < std::mutex > lock(data_in->m_mutex); busy_demod.lock(); if (data_in && data_in->data.size()) { if(data_in->numChannels > 1) { runPFBCH(data_in); } else { runSingleCH(data_in); } } data_in->decRefCount(); bool doUpdate = false; for (size_t j = 0; j < nRunDemods; j++) { DemodulatorInstance *demod = runDemods[j]; if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) { doUpdate = true; } } if (doUpdate) { updateActiveDemodulators(); } busy_demod.unlock(); } if (iqVisualQueue && !iqVisualQueue->empty()) { DemodulatorThreadIQData *visualDataDummy; iqVisualQueue->pop(visualDataDummy); } // buffers.purge(); // visualDataBuffers.purge(); std::cout << "SDR post-processing thread done." << std::endl; }
void SDRPostThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO); sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif // std::cout << "SDR post-processing thread started.." << std::endl; iqDataInQueue = static_cast<SDRThreadIQDataQueue*>(getInputQueue("IQDataInput")); iqDataOutQueue = static_cast<DemodulatorThreadInputQueue*>(getOutputQueue("IQDataOutput")); iqVisualQueue = static_cast<DemodulatorThreadInputQueue*>(getOutputQueue("IQVisualDataOutput")); iqActiveDemodVisualQueue = static_cast<DemodulatorThreadInputQueue*>(getOutputQueue("IQActiveDemodVisualDataOutput")); while (!stopping) { SDRThreadIQData *data_in; iqDataInQueue->pop(data_in); // std::lock_guard < std::mutex > lock(data_in->m_mutex); std::lock_guard < std::mutex > lock(busy_demod); if (data_in && data_in->data.size()) { if(data_in->numChannels > 1) { runPFBCH(data_in); } else { runSingleCH(data_in); } } if (data_in) { data_in->decRefCount(); } bool doUpdate = false; for (size_t j = 0; j < nRunDemods; j++) { DemodulatorInstance *demod = runDemods[j]; if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) { doUpdate = true; } } //Only update the list of demodulators here if (doUpdate) { updateActiveDemodulators(); } } //end while //Be safe, remove as many elements as possible DemodulatorThreadIQData *visualDataDummy; while (iqVisualQueue && iqVisualQueue->try_pop(visualDataDummy)) { visualDataDummy->decRefCount(); } // buffers.purge(); // visualDataBuffers.purge(); // std::cout << "SDR post-processing thread done." << std::endl; }
IOReturn HoRNDIS::enable(IONetworkInterface *netif) { IONetworkMedium *medium; IOReturn rtn = kIOReturnSuccess; if (fNetifEnabled) { LOG(V_ERROR, "already enabled?"); return kIOReturnSuccess; } if (!allocateResources()) return kIOReturnNoMemory; if (!fMediumDict) if (!createMediumTables()) { rtn = kIOReturnNoMemory; goto bailout; } setCurrentMedium(IONetworkMedium::medium(kIOMediumEthernetAuto, 480 * 1000000)); /* Kick off the first read. */ inbuf.comp.target = this; inbuf.comp.action = dataReadComplete; inbuf.comp.parameter = NULL; rtn = fInPipe->Read(inbuf.mdp, &inbuf.comp, NULL); if (rtn != kIOReturnSuccess) goto bailout; /* Tell the world that the link is up... */ medium = IONetworkMedium::getMediumWithType(fMediumDict, kIOMediumEthernetAuto); setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 480 * 1000000); /* ... and then listen for packets! */ getOutputQueue()->setCapacity(TRANSMIT_QUEUE_SIZE); getOutputQueue()->start(); LOG(V_DEBUG, "txqueue started"); /* Tell the other end to start transmitting. */ if (!rndisSetPacketFilter(RNDIS_DEFAULT_FILTER)) goto bailout; /* Now we can say we're alive. */ fNetifEnabled = true; return kIOReturnSuccess; bailout: LOG(V_ERROR, "setting up the pipes failed"); releaseResources(); return rtn; }
void AudioThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_RR) - 1; sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_RR, &prio); #endif std::cout << "Audio thread initializing.." << std::endl; if (dac.getDeviceCount() < 1) { std::cout << "No audio devices found!" << std::endl; return; } setupDevice((outputDevice.load() == -1) ? (dac.getDefaultOutputDevice()) : outputDevice.load()); std::cout << "Audio thread started." << std::endl; inputQueue = (AudioThreadInputQueue *)getInputQueue("AudioDataInput"); threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); while (!terminated) { AudioThreadCommand command; cmdQueue.pop(command); if (command.cmd == AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE) { setupDevice(command.int_value); } if (command.cmd == AudioThreadCommand::AUDIO_THREAD_CMD_SET_SAMPLE_RATE) { setSampleRate(command.int_value); } } if (deviceController[parameters.deviceId] != this) { deviceController[parameters.deviceId]->removeThread(this); } else { try { if (dac.isStreamOpen()) { if (dac.isStreamRunning()) { dac.stopStream(); } dac.closeStream(); } } catch (RtAudioError& e) { e.printMessage(); } } if (threadQueueNotify != NULL) { DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); } std::cout << "Audio thread done." << std::endl; }
bool RTL8139::initEventSources( IOService *provider ) { ELG( 0, 0, 'InES', "RTL8139::initEventSources - " ); DEBUG_LOG( "initEventSources() ===>\n" ); IOWorkLoop *wl = getWorkLoop(); if ( 0 == wl ) return false; fTransmitQueue = getOutputQueue(); if ( 0 == fTransmitQueue ) return false; fTransmitQueue->setCapacity( kTransmitQueueCapacity ); // Create an interrupt event source to handle hardware interrupts. interruptSrc = IOInterruptEventSource::interruptEventSource( this, OSMemberFunctionCast( IOInterruptEventAction, this, &RTL8139::interruptOccurred ), provider ); if ( !interruptSrc || (wl->addEventSource( interruptSrc ) != kIOReturnSuccess) ) return false; // This is important. If the interrupt line is shared with other devices, // then the interrupt vector will be enabled only if all corresponding // interrupt event sources are enabled. To avoid masking interrupts for // other devices that are sharing the interrupt line, the event source // is enabled immediately. Hardware interrupt sources remain disabled. interruptSrc->enable(); // Register a timer event source used as a watchdog timer: timerSrc = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast( IOTimerEventSource::Action, this, &RTL8139::timeoutOccurred ) ); if ( !timerSrc || (wl->addEventSource( timerSrc ) != kIOReturnSuccess) ) return false; // Create a dictionary to hold IONetworkMedium objects: mediumDict = OSDictionary::withCapacity( 5 ); if ( 0 == mediumDict ) return false; DEBUG_LOG( "initEventSources() <===\n" ); return true; }/* end initEventSources */
void IOVideoSampleStream::postFreeInputBuffer(UInt64 vbiTime, UInt64 outputTime, UInt64 totalFrameCount, UInt64 droppedFrameCount,UInt64 lastDisplayedSequenceNumber) { IOStreamBuffer* buf = OSDynamicCast(IOStreamBuffer, _freeBuffers->getObject(0)); if (NULL == buf) { USBLog(1, "IOVideoSampleStream::postFreeInputBuffer - no free buffers\n"); if ((getOutputQueue())->entryCount > 0) { //all the free buffers are in the queue already so just alert the host (void) sendOutputNotification(); } return; } _freeBuffers->removeObject(0); IOMemoryDescriptor *ctrlDescriptor = OSDynamicCast(IOMemoryDescriptor, buf->getControlBuffer()); if (NULL != ctrlDescriptor) { USBLog(1, "IOVideoSampleStream got control buffer descriptor\n"); SampleVideoDeviceControlBuffer theBuffControl, readBackControl; USBLog(1, "IOVideoSampleStream::postFreeInputBuffer - passed in vbiTime = %lld outputTime = %lld framecount = %lld droppedframecount = %lld lastDisplayedSequenceNumber = %lld \n", vbiTime, outputTime, totalFrameCount, droppedFrameCount, lastDisplayedSequenceNumber); theBuffControl.vbiTime = vbiTime; theBuffControl.outputTime = outputTime; theBuffControl.totalFrameCount = totalFrameCount; theBuffControl.droppedFrameCount = droppedFrameCount; theBuffControl.firstVBITime = 0; theBuffControl.sequenceNumber = lastDisplayedSequenceNumber; theBuffControl.discontinuityFlags = 0; (void) ctrlDescriptor->prepare(); ctrlDescriptor->writeBytes(0, &theBuffControl, buf->getControlBuffer()->getLength()); ctrlDescriptor->readBytes(0, &readBackControl, buf->getControlBuffer()->getLength()); USBLog(1, "IOVideoSampleStream::postFreeInputBuffer - control buffer info vbiTime = %lld outputTime = %lld framecount = %lld droppedframecount = %lld sequencenumber = %lld\n", readBackControl.vbiTime, readBackControl.outputTime, readBackControl.totalFrameCount, readBackControl.droppedFrameCount,readBackControl.sequenceNumber); (void) ctrlDescriptor->complete(); } IOReturn result = enqueueOutputBuffer(buf, 0, buf->getDataBuffer()->getLength(), 0, buf->getControlBuffer()->getLength()); if (result != kIOReturnSuccess) { USBLog(1, "IOVideoSampleStream::postFreeInputBuffer help enqueueOutputBuffer failed! (%x)\n", result); return; } result = sendOutputNotification(); if (result != kIOReturnSuccess) { USBLog(1, "IOVideoSampleStream::postFreeInputBuffer help sendOutputNotification failed! (%x)\n", result); return; } }
IOReturn HoRNDIS::disable(IONetworkInterface * netif) { /* Disable the queue (no more outputPacket), and then flush everything in the queue. */ getOutputQueue()->stop(); getOutputQueue()->setCapacity(0); getOutputQueue()->flush(); /* Other end should stop xmitting, too. */ rndisSetPacketFilter(0); setLinkStatus(0, 0); /* Release all resources */ releaseResources(); fNetifEnabled = false; /* Terminates also close the device in 'disable'. */ if (fTerminate) { fpDevice->close(this); fpDevice = NULL; } return kIOReturnSuccess; }
void SDRThread::readLoop() { SDRThreadIQDataQueue* iqDataOutQueue = static_cast<SDRThreadIQDataQueue*>( getOutputQueue("IQDataOutput")); if (iqDataOutQueue == NULL) { return; } updateGains(); while (!stopping.load()) { updateSettings(); readStream(iqDataOutQueue); } buffers.purge(); }
//--------------------------------------------------------------------------- bool AgereET131x::initEventSources( IOService* provider ) { // Get a handle to our superclass' workloop. // IOWorkLoop* myWorkLoop = (IOWorkLoop *) getWorkLoop(); if (myWorkLoop == NULL) { IOLog(" myWorkLoop is NULL.\n"); return false; } transmitQueue = getOutputQueue(); if (transmitQueue == NULL) { IOLog("getOutputQueue failed.\n"); return false; } transmitQueue->setCapacity(NUM_TCB); interruptSource = IOFilterInterruptEventSource::filterInterruptEventSource( this, &AgereET131x::interruptHandler, &AgereET131x::interruptFilter, provider); if (!interruptSource || (myWorkLoop->addEventSource(interruptSource) != kIOReturnSuccess)) { IOLog("workloop add eventsource interrupt source.\n"); return false; } // This is important. If the interrupt line is shared with other devices, // then the interrupt vector will be enabled only if all corresponding // interrupt event sources are enabled. To avoid masking interrupts for // other devices that are sharing the interrupt line, the event source // is enabled immediately. interruptSource->enable(); // Register a timer event source. This is used as a watchdog timer. // watchdogSource = IOTimerEventSource::timerEventSource(this, &AgereET131x::timeoutHandler ); if (!watchdogSource || (myWorkLoop->addEventSource(watchdogSource) != kIOReturnSuccess)) { IOLog("watchdogSource create failed.\n"); return false; } mediumDict = OSDictionary::withCapacity(MEDIUM_INDEX_COUNT + 1); if (mediumDict == NULL) { return false; } return true; }
void FFTVisualDataThread::run() { DemodulatorThreadInputQueue *pipeIQDataIn = static_cast<DemodulatorThreadInputQueue *>(getInputQueue("IQDataInput")); SpectrumVisualDataQueue *pipeFFTDataOut = static_cast<SpectrumVisualDataQueue *>(getOutputQueue("FFTDataOutput")); fftQueue.set_max_num_items(100); pipeFFTDataOut->set_max_num_items(100); fftDistrib.setInput(pipeIQDataIn); fftDistrib.attachOutput(&fftQueue); wproc.setInput(&fftQueue); wproc.attachOutput(pipeFFTDataOut); wproc.setup(DEFAULT_FFT_SIZE); // std::cout << "FFT visual data thread started." << std::endl; while(!stopping) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); // std::this_thread::yield(); int fftSize = wproc.getDesiredInputSize(); if (fftSize) { fftDistrib.setFFTSize(fftSize); } else { fftDistrib.setFFTSize(DEFAULT_FFT_SIZE * SPECTRUM_VZM); } if (lpsChanged.load()) { fftDistrib.setLinesPerSecond(linesPerSecond.load()); // pipeIQDataIn->set_max_num_items(linesPerSecond.load()); lpsChanged.store(false); } fftDistrib.run(); while (!wproc.isInputEmpty()) { wproc.run(); } } // std::cout << "FFT visual data thread done." << std::endl; }
void FFTVisualDataThread::run() { DemodulatorThreadInputQueue *pipeIQDataIn = (DemodulatorThreadInputQueue *)getInputQueue("IQDataInput"); SpectrumVisualDataQueue *pipeFFTDataOut = (SpectrumVisualDataQueue *)getOutputQueue("FFTDataOutput"); fftDistrib.setInput(pipeIQDataIn); fftDistrib.attachOutput(&fftQueue); wproc.setInput(&fftQueue); wproc.attachOutput(pipeFFTDataOut); wproc.setup(2048); std::cout << "FFT visual data thread started." << std::endl; while(!terminated) { std::this_thread::sleep_for(std::chrono::milliseconds(12)); int fftSize = wproc.getDesiredInputSize(); if (fftSize) { fftDistrib.setFFTSize(fftSize); } else { fftDistrib.setFFTSize(DEFAULT_FFT_SIZE); } if (lpsChanged.load()) { fftDistrib.setLinesPerSecond(linesPerSecond.load()); pipeIQDataIn->set_max_num_items(linesPerSecond.load()); lpsChanged.store(false); } fftDistrib.run(); while (!wproc.isInputEmpty()) { wproc.run(); } } std::cout << "FFT visual data thread done." << std::endl; }
void DemodulatorPreThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO) - 1; sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif if (!initialized) { initialize(); } std::cout << "Demodulator preprocessor thread started.." << std::endl; t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread); ReBuffer<DemodulatorThreadPostIQData> buffers; iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput"); iqOutputQueue = (DemodulatorThreadPostInputQueue*)getOutputQueue("IQDataOutput"); threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); commandQueue = ( DemodulatorThreadCommandQueue*)getInputQueue("CommandQueue"); std::vector<liquid_float_complex> in_buf_data; std::vector<liquid_float_complex> out_buf_data; // liquid_float_complex carrySample; // Keep the stream count even to simplify some demod operations // bool carrySampleFlag = false; while (!terminated) { DemodulatorThreadIQData *inp; iqInputQueue->pop(inp); bool bandwidthChanged = false; bool rateChanged = false; DemodulatorThreadParameters tempParams = params; if (!commandQueue->empty()) { while (!commandQueue->empty()) { DemodulatorThreadCommand command; commandQueue->pop(command); switch (command.cmd) { case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH: if (command.llong_value < 1500) { command.llong_value = 1500; } if (command.llong_value > params.sampleRate) { tempParams.bandwidth = params.sampleRate; } else { tempParams.bandwidth = command.llong_value; } bandwidthChanged = true; break; case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY: params.frequency = tempParams.frequency = command.llong_value; break; case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE: tempParams.audioSampleRate = (int)command.llong_value; rateChanged = true; break; default: break; } } } if (inp->sampleRate != tempParams.sampleRate && inp->sampleRate) { tempParams.sampleRate = inp->sampleRate; rateChanged = true; } if (bandwidthChanged || rateChanged) { DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS); command.sampleRate = tempParams.sampleRate; command.audioSampleRate = tempParams.audioSampleRate; command.bandwidth = tempParams.bandwidth; command.frequency = tempParams.frequency; workerQueue->push(command); } if (!initialized) { inp->decRefCount(); continue; } // Requested frequency is not center, shift it into the center! if ((params.frequency - inp->frequency) != shiftFrequency || rateChanged) { shiftFrequency = params.frequency - inp->frequency; if (abs(shiftFrequency) <= (int) ((double) (inp->sampleRate / 2) * 1.5)) { nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) inp->sampleRate))); } } if (abs(shiftFrequency) > (int) ((double) (inp->sampleRate / 2) * 1.5)) { inp->decRefCount(); continue; } // std::lock_guard < std::mutex > lock(inp->m_mutex); std::vector<liquid_float_complex> *data = &inp->data; if (data->size() && (inp->sampleRate == params.sampleRate)) { int bufSize = data->size(); if (in_buf_data.size() != bufSize) { if (in_buf_data.capacity() < bufSize) { in_buf_data.reserve(bufSize); out_buf_data.reserve(bufSize); } in_buf_data.resize(bufSize); out_buf_data.resize(bufSize); } in_buf_data.assign(inp->data.begin(), inp->data.end()); liquid_float_complex *in_buf = &in_buf_data[0]; liquid_float_complex *out_buf = &out_buf_data[0]; liquid_float_complex *temp_buf = NULL; if (shiftFrequency != 0) { if (shiftFrequency < 0) { nco_crcf_mix_block_up(freqShifter, in_buf, out_buf, bufSize); } else { nco_crcf_mix_block_down(freqShifter, in_buf, out_buf, bufSize); } temp_buf = in_buf; in_buf = out_buf; out_buf = temp_buf; } DemodulatorThreadPostIQData *resamp = buffers.getBuffer(); int out_size = ceil((double) (bufSize) * iqResampleRatio) + 512; if (resampledData.size() != out_size) { if (resampledData.capacity() < out_size) { resampledData.reserve(out_size); } resampledData.resize(out_size); } unsigned int numWritten; msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten); resamp->setRefCount(1); resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten); // bool uneven = (numWritten % 2 != 0); // if (!carrySampleFlag && !uneven) { // resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten); // carrySampleFlag = false; // } else if (!carrySampleFlag && uneven) { // resamp->data.assign(resampledData.begin(), resampledData.begin() + (numWritten-1)); // carrySample = resampledData.back(); // carrySampleFlag = true; // } else if (carrySampleFlag && uneven) { // resamp->data.resize(numWritten+1); // resamp->data[0] = carrySample; // memcpy(&resamp->data[1],&resampledData[0],sizeof(liquid_float_complex)*numWritten); // carrySampleFlag = false; // } else if (carrySampleFlag && !uneven) { // resamp->data.resize(numWritten); // resamp->data[0] = carrySample; // memcpy(&resamp->data[1],&resampledData[0],sizeof(liquid_float_complex)*(numWritten-1)); // carrySample = resampledData.back(); // carrySampleFlag = true; // } resamp->audioResampleRatio = audioResampleRatio; resamp->audioResampler = audioResampler; resamp->audioSampleRate = params.audioSampleRate; resamp->stereoResampler = stereoResampler; resamp->firStereoLeft = firStereoLeft; resamp->firStereoRight = firStereoRight; resamp->iirStereoPilot = iirStereoPilot; resamp->sampleRate = params.bandwidth; iqOutputQueue->push(resamp); } inp->decRefCount(); if (!terminated && !workerResults->empty()) { while (!workerResults->empty()) { DemodulatorWorkerThreadResult result; workerResults->pop(result); switch (result.cmd) { case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS: msresamp_crcf_destroy(iqResampler); if (result.iqResampler) { iqResampler = result.iqResampler; iqResampleRatio = result.iqResampleRatio; } if (result.firStereoLeft) { firStereoLeft = result.firStereoLeft; } if (result.firStereoRight) { firStereoRight = result.firStereoRight; } if (result.iirStereoPilot) { iirStereoPilot = result.iirStereoPilot; } if (result.audioResampler) { audioResampler = result.audioResampler; audioResampleRatio = result.audioResamplerRatio; stereoResampler = result.stereoResampler; } if (result.audioSampleRate) { params.audioSampleRate = result.audioSampleRate; } if (result.bandwidth) { params.bandwidth = result.bandwidth; } if (result.sampleRate) { params.sampleRate = result.sampleRate; } break; default: break; } } } } buffers.purge(); DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); std::cout << "Demodulator preprocessor thread done." << std::endl; }
bool AtherosL1Ethernet::start(IOService *provider) { DbgPrint("start()\n"); at_adapter *adapter=&adapter_; if (!BASE::start(provider)) { ErrPrint("Couldn't start BASE\n"); return false; } adapter->pdev = OSDynamicCast(IOPCIDevice, provider); if (!adapter->pdev) { ErrPrint("Unable to cast provider\n"); return false; } adapter->pdev->retain(); adapter->pdev->open(this); //Adding Mac OS X PHY's mediumDict = OSDictionary::withCapacity(MEDIUM_INDEX_COUNT + 1); OSAddNetworkMedium(kIOMediumEthernetAuto, 0, MEDIUM_INDEX_AUTO); OSAddNetworkMedium(kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex, 10 * MBit, MEDIUM_INDEX_10HD); OSAddNetworkMedium(kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex, 10 * MBit, MEDIUM_INDEX_10FD); OSAddNetworkMedium(kIOMediumEthernet100BaseTX | kIOMediumOptionHalfDuplex, 100 * MBit, MEDIUM_INDEX_100HD); OSAddNetworkMedium(kIOMediumEthernet100BaseTX | kIOMediumOptionFullDuplex, 100 * MBit, MEDIUM_INDEX_100FD); OSAddNetworkMedium(kIOMediumEthernet1000BaseTX | kIOMediumOptionHalfDuplex, 1000 * MBit, MEDIUM_INDEX_1000HD); OSAddNetworkMedium(kIOMediumEthernet1000BaseTX | kIOMediumOptionFullDuplex, 1000 * MBit, MEDIUM_INDEX_1000FD); if (!publishMediumDictionary(mediumDict)) return false; if (!atProbe()) //Fix false reporting int probe function { ErrPrint("Couldn't probe adapter\n"); stop(provider); return false; } workLoop_ = getWorkLoop(); if (!workLoop_) { ErrPrint("workLoop is not exists\n"); stop(provider); return false; } transmitQueue_ = getOutputQueue(); if (!transmitQueue_) { ErrPrint("transmitQueue is not exists\n"); stop(provider); return false; } //Looking for MSI interrupt index int msi_index = -1; int intr_index = 0, intr_type = 0; IOReturn intr_ret; while (true) { intr_ret = provider->getInterruptType(intr_index, &intr_type); if (intr_ret != kIOReturnSuccess) break; if (intr_type & kIOInterruptTypePCIMessaged) msi_index = intr_index; intr_index++; } if (msi_index != -1) { DbgPrint("MSI interrupt index %d\n", msi_index); intSource_ = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventSource::Action, this, &AtherosL1Ethernet::atIntr), adapter->pdev, msi_index); } if (msi_index == -1 || intSource_ == NULL) { DbgPrint("MSI index was not found or MSI interrupt couldn't be enabled\n"); intSource_ = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventSource::Action, this, &AtherosL1Ethernet::atIntr), adapter->pdev); } //Adding interrupt to our workloop event sources if (!intSource_ || workLoop_->addEventSource(intSource_) != kIOReturnSuccess) { if (!intSource_) ErrPrint("Couldn't create interrupt source\n"); else ErrPrint("Couldn't attach interrupt source\n"); stop(provider); return false; } //Attaching dynamic link layer if (!this->attachInterface(reinterpret_cast<IONetworkInterface **>(&netIface_)), false) { DbgPrint("Failed to attach data link layer\n"); return false; } intSource_->enable(); /* allocate Tx / RX descriptor resources */ if (at_setup_ring_resources(adapter)) { ErrPrint("Couldn't allocate ring descriptors\n"); adapter->pdev->close(this); return kIOReturnError; } netIface_->registerService(); adapter->pdev->close(this); return true; }
void SDRPostThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO) - 1; sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif dcFilter = iirfilt_crcf_create_dc_blocker(0.0005); std::cout << "SDR post-processing thread started.." << std::endl; iqDataInQueue = (SDRThreadIQDataQueue*)getInputQueue("IQDataInput"); iqDataOutQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQDataOutput"); iqVisualQueue = (DemodulatorThreadInputQueue*)getOutputQueue("IQVisualDataOutput"); ReBuffer<DemodulatorThreadIQData> buffers; std::vector<liquid_float_complex> fpData; std::vector<liquid_float_complex> dataOut; iqDataInQueue->set_max_num_items(0); while (!terminated) { SDRThreadIQData *data_in; iqDataInQueue->pop(data_in); // std::lock_guard < std::mutex > lock(data_in->m_mutex); if (data_in && data_in->data.size()) { int dataSize = data_in->data.size()/2; if (dataSize > fpData.capacity()) { fpData.reserve(dataSize); dataOut.reserve(dataSize); } if (dataSize != fpData.size()) { fpData.resize(dataSize); dataOut.resize(dataSize); } if (swapIQ) { for (int i = 0; i < dataSize; i++) { fpData[i] = _lut_swap[*((uint16_t*)&data_in->data[2*i])]; } } else { for (int i = 0; i < dataSize; i++) { fpData[i] = _lut[*((uint16_t*)&data_in->data[2*i])]; } } iirfilt_crcf_execute_block(dcFilter, &fpData[0], dataSize, &dataOut[0]); if (iqVisualQueue != NULL && !iqVisualQueue->full()) { DemodulatorThreadIQData *visualDataOut = visualDataBuffers.getBuffer(); visualDataOut->setRefCount(1); int num_vis_samples = dataOut.size(); // if (visualDataOut->data.size() < num_vis_samples) { // if (visualDataOut->data.capacity() < num_vis_samples) { // visualDataOut->data.reserve(num_vis_samples); // } // visualDataOut->data.resize(num_vis_samples); // } // visualDataOut->frequency = data_in->frequency; visualDataOut->sampleRate = data_in->sampleRate; visualDataOut->data.assign(dataOut.begin(), dataOut.begin() + num_vis_samples); iqVisualQueue->push(visualDataOut); } busy_demod.lock(); int activeDemods = 0; bool pushedData = false; if (demodulators.size() || iqDataOutQueue != NULL) { std::vector<DemodulatorInstance *>::iterator demod_i; for (demod_i = demodulators.begin(); demod_i != demodulators.end(); demod_i++) { DemodulatorInstance *demod = *demod_i; if (demod->getFrequency() != data_in->frequency && abs(data_in->frequency - demod->getFrequency()) > (wxGetApp().getSampleRate() / 2)) { continue; } activeDemods++; } if (iqDataOutQueue != NULL) { activeDemods++; } DemodulatorThreadIQData *demodDataOut = buffers.getBuffer(); // std::lock_guard < std::mutex > lock(demodDataOut->m_mutex); demodDataOut->frequency = data_in->frequency; demodDataOut->sampleRate = data_in->sampleRate; demodDataOut->setRefCount(activeDemods); demodDataOut->data.assign(dataOut.begin(), dataOut.end()); for (demod_i = demodulators.begin(); demod_i != demodulators.end(); demod_i++) { DemodulatorInstance *demod = *demod_i; DemodulatorThreadInputQueue *demodQueue = demod->getIQInputDataPipe(); if (abs(data_in->frequency - demod->getFrequency()) > (wxGetApp().getSampleRate() / 2)) { if (demod->isActive() && !demod->isFollow() && !demod->isTracking()) { demod->setActive(false); DemodulatorThreadIQData *dummyDataOut = new DemodulatorThreadIQData; dummyDataOut->frequency = data_in->frequency; dummyDataOut->sampleRate = data_in->sampleRate; demodQueue->push(dummyDataOut); } if (demod->isFollow() && wxGetApp().getFrequency() != demod->getFrequency()) { wxGetApp().setFrequency(demod->getFrequency()); } } else if (!demod->isActive()) { demod->setActive(true); if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) { wxGetApp().getDemodMgr().setActiveDemodulator(demod); } } if (!demod->isActive()) { continue; } if (demod->isFollow()) { demod->setFollow(false); } demodQueue->push(demodDataOut); pushedData = true; } if (iqDataOutQueue != NULL) { if (!iqDataOutQueue->full()) { iqDataOutQueue->push(demodDataOut); pushedData = true; } else { demodDataOut->decRefCount(); } } if (!pushedData && iqDataOutQueue == NULL) { demodDataOut->setRefCount(0); } } busy_demod.unlock(); } data_in->decRefCount(); } // buffers.purge(); if (iqVisualQueue && !iqVisualQueue->empty()) { DemodulatorThreadIQData *visualDataDummy; iqVisualQueue->pop(visualDataDummy); } // visualDataBuffers.purge(); std::cout << "SDR post-processing thread done." << std::endl; }
bool CLASS::allocateSupportObjects( IOService * provider ) { fTransmitQueue = OSDynamicCast(IOOutputQueue, getOutputQueue()); if (fTransmitQueue == 0) return false; fKDPQueue = IOPacketQueue::withCapacity(~0); if (!fKDPQueue) return false; // Allocate two Mbuf Cursors. One dedicated for transmit and // the other for receive. NOTE types are different. fRxMbufCursor = IOMbufLittleMemoryCursor::withSpecification( kRxMaxBufferSize, 1); fTxMbufCursor = IOMbufNaturalMemoryCursor::withSpecification( kTxMaxBufferSize, 1); if (!fRxMbufCursor || !fTxMbufCursor) { ERROR_LOG("%s: mbuf cursor allocation error\n", getName()); return false; } IOWorkLoop * workLoop = (IOWorkLoop *) getWorkLoop(); if (!workLoop) { ERROR_LOG("%s: no work loop\n", getName()); return false; } // Create an interrupt event source to dispatch interrupts. // FIXME: Use interrupt filter event source fInterruptSource = IOInterruptEventSource::interruptEventSource( this, &AppleDP83816Ethernet::interruptHandler, provider); if (!fInterruptSource || (workLoop->addEventSource(fInterruptSource) != kIOReturnSuccess)) { ERROR_LOG("%s: IOInterruptEventSource error\n", getName()); return false; } fWatchdogTimer = IOTimerEventSource::timerEventSource( this, &AppleDP83816Ethernet::timeoutHandler); if (!fWatchdogTimer || (workLoop->addEventSource(fWatchdogTimer) != kIOReturnSuccess)) { ERROR_LOG("%s: IOTimerEventSource error\n", getName()); return false; } // Very important. If the interrupt line is shared with other devices, // then the interrupt vector will be enabled only if all corresponding // interrupt event sources are enabled. To avoid masking interrupts for // other devices that are sharing the interrupt line, the event source // is enabled immediately. fInterruptSource->enable(); return true; }
void DemodulatorWorkerThread::run() { std::cout << "Demodulator worker thread started.." << std::endl; commandQueue = (DemodulatorThreadWorkerCommandQueue *)getInputQueue("WorkerCommandQueue"); resultQueue = (DemodulatorThreadWorkerResultQueue *)getOutputQueue("WorkerResultQueue"); while (!terminated) { bool filterChanged = false; bool makeDemod = false; DemodulatorWorkerThreadCommand filterCommand, demodCommand; DemodulatorWorkerThreadCommand command; bool done = false; while (!done) { commandQueue->pop(command); switch (command.cmd) { case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS: filterChanged = true; filterCommand = command; break; case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD: makeDemod = true; demodCommand = command; break; default: break; } done = commandQueue->empty(); } if ((makeDemod || filterChanged) && !terminated) { DemodulatorWorkerThreadResult result(DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS); if (filterCommand.sampleRate) { result.sampleRate = filterCommand.sampleRate; } if (makeDemod) { cModem = Modem::makeModem(demodCommand.demodType); cModemName = cModem->getName(); cModemType = cModem->getType(); if (demodCommand.settings.size()) { cModem->writeSettings(demodCommand.settings); } result.sampleRate = demodCommand.sampleRate; wxGetApp().getAppFrame()->updateModemProperties(cModem->getSettings()); } result.modem = cModem; if (makeDemod && demodCommand.bandwidth && demodCommand.audioSampleRate) { if (cModem != nullptr) { result.bandwidth = cModem->checkSampleRate(demodCommand.bandwidth, demodCommand.audioSampleRate); cModemKit = cModem->buildKit(result.bandwidth, demodCommand.audioSampleRate); } else { cModemKit = nullptr; } } else if (filterChanged && filterCommand.bandwidth && filterCommand.audioSampleRate) { if (cModem != nullptr) { result.bandwidth = cModem->checkSampleRate(filterCommand.bandwidth, filterCommand.audioSampleRate); cModemKit = cModem->buildKit(result.bandwidth, filterCommand.audioSampleRate); } else { cModemKit = nullptr; } } else if (makeDemod) { cModemKit = nullptr; } if (cModem != nullptr) { cModem->clearRebuildKit(); } float As = 60.0f; // stop-band attenuation [dB] if (result.sampleRate && result.bandwidth) { result.bandwidth = cModem->checkSampleRate(result.bandwidth, makeDemod?demodCommand.audioSampleRate:filterCommand.audioSampleRate); result.iqResampleRatio = (double) (result.bandwidth) / (double) result.sampleRate; result.iqResampler = msresamp_crcf_create(result.iqResampleRatio, As); } result.modemKit = cModemKit; result.modemType = cModemType; result.modemName = cModemName; resultQueue->push(result); } } std::cout << "Demodulator worker thread done." << std::endl; }
void DemodulatorThread::run() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO )-1; sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif ReBuffer<AudioThreadInput> audioVisBuffers; std::cout << "Demodulator thread started.." << std::endl; iqInputQueue = (DemodulatorThreadPostInputQueue*)getInputQueue("IQDataInput"); audioOutputQueue = (AudioThreadInputQueue*)getOutputQueue("AudioDataOutput"); threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue"); threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); ModemIQData modemData; while (!terminated) { DemodulatorThreadPostIQData *inp; iqInputQueue->pop(inp); // std::lock_guard < std::mutex > lock(inp->m_mutex); audioSampleRate = demodInstance->getAudioSampleRate(); int bufSize = inp->data.size(); if (!bufSize) { inp->decRefCount(); continue; } if (inp->modemKit && inp->modemKit != cModemKit) { if (cModemKit != nullptr) { cModem->disposeKit(cModemKit); } cModemKit = inp->modemKit; } if (inp->modem && inp->modem != cModem) { delete cModem; cModem = inp->modem; } if (!cModem || !cModemKit) { inp->decRefCount(); continue; } float currentSignalLevel = 0; float accum = 0; for (std::vector<liquid_float_complex>::iterator i = inp->data.begin(); i != inp->data.end(); i++) { accum += abMagnitude(0.948059448969, 0.392699081699, i->real, i->imag); } currentSignalLevel = linearToDb(accum / float(inp->data.size())); if (currentSignalLevel < DEMOD_SIGNAL_MIN+1) { currentSignalLevel = DEMOD_SIGNAL_MIN+1; } std::vector<liquid_float_complex> *inputData; inputData = &inp->data; modemData.sampleRate = inp->sampleRate; modemData.data.assign(inputData->begin(), inputData->end()); modemData.setRefCount(1); AudioThreadInput *ati = NULL; ModemAnalog *modemAnalog = (cModem->getType() == "analog")?((ModemAnalog *)cModem):nullptr; // ModemDigital *modemDigital = (cModem->getType() == "digital")?((ModemDigital *)cModem):nullptr; if (modemAnalog != nullptr) { ati = outputBuffers.getBuffer(); ati->sampleRate = audioSampleRate; ati->inputRate = inp->sampleRate; ati->setRefCount(1); } cModem->demodulate(cModemKit, &modemData, ati); if (currentSignalLevel > signalLevel) { signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5; } else { signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05; } bool squelched = (squelchEnabled && (signalLevel < squelchLevel)); if (audioOutputQueue != NULL && ati && !squelched) { std::vector<float>::iterator data_i; ati->peak = 0; for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) { float p = fabs(*data_i); if (p > ati->peak) { ati->peak = p; } } } else if (ati) { ati->decRefCount(); ati = nullptr; } if (ati && audioVisOutputQueue != NULL && audioVisOutputQueue->empty()) { AudioThreadInput *ati_vis = audioVisBuffers.getBuffer(); ati_vis->setRefCount(1); ati_vis->sampleRate = inp->sampleRate; ati_vis->inputRate = inp->sampleRate; int num_vis = DEMOD_VIS_SIZE; if (ati->channels==2) { ati_vis->channels = 2; int stereoSize = ati->data.size(); if (stereoSize > DEMOD_VIS_SIZE * 2) { stereoSize = DEMOD_VIS_SIZE * 2; } ati_vis->data.resize(stereoSize); if (inp->modemType == "I/Q") { for (int i = 0; i < stereoSize / 2; i++) { ati_vis->data[i] = (*inputData)[i].real * 0.75; ati_vis->data[i + stereoSize / 2] = (*inputData)[i].imag * 0.75; } } else { for (int i = 0; i < stereoSize / 2; i++) { ati_vis->inputRate = audioSampleRate; ati_vis->sampleRate = 36000; ati_vis->data[i] = ati->data[i * 2]; ati_vis->data[i + stereoSize / 2] = ati->data[i * 2 + 1]; } } } else { int numAudioWritten = ati->data.size(); ati_vis->channels = 1; std::vector<float> *demodOutData = (modemAnalog != nullptr)?modemAnalog->getDemodOutputData():nullptr; if ((numAudioWritten > bufSize) || (demodOutData == nullptr)) { ati_vis->inputRate = audioSampleRate; if (num_vis > numAudioWritten) { num_vis = numAudioWritten; } ati_vis->data.assign(ati->data.begin(), ati->data.begin() + num_vis); } else { if (num_vis > demodOutData->size()) { num_vis = demodOutData->size(); } ati_vis->data.assign(demodOutData->begin(), demodOutData->begin() + num_vis); } } audioVisOutputQueue->push(ati_vis); } if (ati != NULL) { if (!muted.load()) { audioOutputQueue->push(ati); } else { ati->setRefCount(0); } } if (!threadQueueControl->empty()) { while (!threadQueueControl->empty()) { DemodulatorThreadControlCommand command; threadQueueControl->pop(command); switch (command.cmd) { case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON: squelchEnabled = true; break; case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF: squelchEnabled = false; break; default: break; } } } inp->decRefCount(); } // end while !terminated outputBuffers.purge(); if (audioVisOutputQueue && !audioVisOutputQueue->empty()) { AudioThreadInput *dummy_vis; audioVisOutputQueue->pop(dummy_vis); } audioVisBuffers.purge(); DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED); tCmd.context = this; threadQueueNotify->push(tCmd); std::cout << "Demodulator thread done." << std::endl; }
bool MolEnet::start( IOService * provider ) { IOPhysicalAddress tx_phys, rx_phys; IOPhysicalAddress tx_of_phys, rx_of_phys; int i, result; if( !super::start(provider) ) return false; if( OSI_Enet2Open() ) { is_open = 1; return false; } //transmitQueue = OSDynamicCast( IOGatedOutputQueue, getOutputQueue() ); transmitQueue = OSDynamicCast( IOBasicOutputQueue, getOutputQueue() ); if( !transmitQueue ) { printm("MolEnet: output queue initialization failed\n"); return false; } transmitQueue->retain(); // Allocate a IOMbufBigMemoryCursor instance. Currently, the maximum // number of segments is set to 2. The maximum length for each segment // is set to the maximum ethernet frame size (plus padding). txMBufCursor = IOMbufBigMemoryCursor::withSpecification( NETWORK_BUFSIZE, 2 ); rxMBufCursor = IOMbufBigMemoryCursor::withSpecification( NETWORK_BUFSIZE, 2 ); if( !txMBufCursor || !rxMBufCursor ) { printm("MolEnet: IOMbufBigMemoryCursor allocation failure\n"); return false; } // Get a reference to the IOWorkLoop in our superclass. IOWorkLoop * myWorkLoop = getWorkLoop(); assert(myWorkLoop); // Allocate a IOInterruptEventSources. _irq = IOInterruptEventSource::interruptEventSource( this, (IOInterruptEventAction)&MolEnet::rxIRQ, provider, 0); if( !_irq || (myWorkLoop->addEventSource(_irq) != kIOReturnSuccess )) { printm("MolEnet: _irq init failure\n"); return false; } // Allocate the ring descriptors rx_ring = (enet2_ring_t*)IOMallocContiguous( 2 * RX_NUM_EL * sizeof(enet2_ring_t), sizeof(enet2_ring_t), &rx_phys ); tx_ring = (enet2_ring_t*)IOMallocContiguous( 2 * TX_NUM_EL * sizeof(enet2_ring_t), sizeof(enet2_ring_t), &tx_phys ); if( !rx_ring || !tx_ring ) return false; rx_of_ring = rx_ring + RX_NUM_EL; tx_of_ring = tx_ring + TX_NUM_EL; rx_of_phys = rx_phys + sizeof(enet2_ring_t) * RX_NUM_EL; tx_of_phys = tx_phys + sizeof(enet2_ring_t) * TX_NUM_EL; // Allocate receive buffers for( i=0; i<RX_NUM_EL; i++ ) { if( !(rxMBuf[i]=allocatePacket( NETWORK_BUFSIZE )) ) { printm("MolEnet: packet allocation failed\n"); return false; } // reserve 2 bytes before the actual packet rxMBuf[i]->m_data += 2; rxMBuf[i]->m_len -= 2; } OSI_Enet2Cntrl( kEnet2Reset ); result = OSI_Enet2RingSetup( kEnet2SetupRXRing, rx_phys, RX_NUM_EL ) || OSI_Enet2RingSetup( kEnet2SetupTXRing, tx_phys, TX_NUM_EL ) || OSI_Enet2RingSetup( kEnet2SetupRXOverflowRing, rx_of_phys, RX_NUM_EL ) || OSI_Enet2RingSetup( kEnet2SetupTXOverflowRing, tx_of_phys, TX_NUM_EL ); if( result ) return false; if( !resetAndEnable(false) ) return false; // Create a table of supported media types. if( !createMediumTables() ) return false; // Attach an IOEthernetInterface client. if( !attachInterface( (IONetworkInterface**)&networkInterface, false ) ) return false; // Ready to service interface requests. networkInterface->registerService(); printm("Ethernet driver 1.1\n"); return true; }