日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

gnuradio android手机,如何搭配USRP在安卓设备上搭建GNU Radio

發(fā)布時(shí)間:2025/3/19 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 gnuradio android手机,如何搭配USRP在安卓设备上搭建GNU Radio 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原標(biāo)題:如何搭配USRP在安卓設(shè)備上搭建GNU Radio

在這篇文章中,我們會(huì)使用安卓設(shè)備通過USB連接USRP。所以就需要USRP B2xx(B200, B210, 或者是 B200mini),這些都是經(jīng)過全面測(cè)試的。除了這些,我們還需要一個(gè)OTG(USB On-the-Go)線纜,它可以插入安卓設(shè)備的USB端口。準(zhǔn)備好這些,就可以按照下圖所示接線方法連接。

點(diǎn)擊這里查看已經(jīng)被測(cè)試證明可以正常工作的設(shè)備列表。

具有網(wǎng)絡(luò)連接的USRP似乎更容易在使用安卓設(shè)備的情況下正常工作。B2xx系列的USRP最大的問題在于每次開機(jī)時(shí)都必須對(duì)其固件和FPGA圖像進(jìn)行編程,而N200/N210這樣的的USRP是預(yù)編程的,所以不需要面臨某些USB設(shè)備的權(quán)限問題,聯(lián)網(wǎng)的USRP所需的權(quán)限只有“android.permission.INTERNET”,該權(quán)限用于訪問ControlPort。

RTL-SDR也可以用于安卓設(shè)備上的GNU Radio,與USRP B2xx差不多,這些設(shè)備也需要USB權(quán)限的替代辦法,不過不需要編程。我們可以將RTL-SDR庫(kù)和gr-osmosdr對(duì)其的支持構(gòu)建到Android依賴包的GR中。此外,增加對(duì)其他基于USB的設(shè)備(如BladeRF,HackRF,Airspy等)的支持也將是比較直接的。

點(diǎn)擊這里查看Github上完整的GrTemplateUSRP示例。

開始

我們現(xiàn)在要構(gòu)建一個(gè)新的應(yīng)用程序,首先,按照GRAndWalkthroughCP概述中的步驟創(chuàng)建一個(gè)新的應(yīng)用程序項(xiàng)目,不過這次暫且命名為GrTemplateUSRP,這為我們?cè)O(shè)置了一個(gè)支持ControlPort且有一個(gè)基本流圖的項(xiàng)目。在進(jìn)行下一步之前,確保應(yīng)用程序的構(gòu)建和運(yùn)行就像GrTemplateCP一樣。

其次,克隆并構(gòu)建GrHardwareService應(yīng)用程序,并將此應(yīng)用安裝到你的安卓設(shè)備上,如果你第一次啟動(dòng)時(shí)沒有連接USRP,應(yīng)用可能會(huì)崩潰。加載完成后,它會(huì)為B2xx設(shè)備安裝USRP固件和FPGA圖像,并開始偵聽USB連接。如果插入了供應(yīng)商和生產(chǎn)ID與任何已知的USRP匹配的設(shè)備,則開始對(duì)設(shè)備進(jìn)行編程。它會(huì)要求你授權(quán)兩次以使用該設(shè)備,一次對(duì)固件進(jìn)行編程,另一次是對(duì)FPGA圖像進(jìn)行編程。一旦完成,硬件即準(zhǔn)備就緒。

如果你在第一次插入U(xiǎn)SRP時(shí)導(dǎo)致了程序崩潰,則可能是權(quán)限問題。在Marshmallow(安卓6.0)上,需要進(jìn)入設(shè)置中的應(yīng)用程序部分,找到GrHardwareService,然后啟用存儲(chǔ)權(quán)限。這是安卓6.0中的新“功能”。

添加對(duì)USB設(shè)備的支持

我們必須與安卓設(shè)備交互才可以在Java應(yīng)用程序中獲取信息并將其傳遞給C++流圖,值得一提的是,安卓并不會(huì)將USB權(quán)限交給本地應(yīng)用程序,所以我們需要在Java中獲取文件描述符(fd)和USB文件系統(tǒng)路徑(usrpfs_path),并將其通過GNU Radio傳遞給libUHD,最終通過libUSB訪問。

接下來,我們需要添加一些支持以獲得USB許可,并找到我們需要連接到USRP的fd和usbfs_path信息。

首先,將這些變量添加到MainActivity類中:

public static Intent intent = null; private String usbfs_path = null; private int fd = -1; private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; private static final String DEFAULT_USBFS_PATH = "/dev/bus/usb"; private UsbManager mUsbManager; private UsbDevice mUsbDevice;

在我們收發(fā)無線電之前,我們需要確保已經(jīng)擁有USB權(quán)限。因此,和我們之前一直在OnCreate中做事情不同,我們會(huì)將其分成不同部分,首先在OnCreate中,我們需要獲取USB設(shè)備,設(shè)置無線電接收器,然后詢問用戶是否允許使用該設(shè)備。當(dāng)用戶同意時(shí),無線電接收器啟動(dòng)。 即完成對(duì)USB設(shè)備的訪問,現(xiàn)在我們可以對(duì)USB設(shè)備進(jìn)行操作,以便我們從中獲取需要的信息。這就是OnCreate函數(shù):

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create the seekBar to move update the amplitude SeekBar ampSeekBar = (SeekBar) findViewById(R.id.seekBar); ampSeekBar.setMax(100); // max value -> 1.0 ampSeekBar.setProgress(50); // match 0.5 starting value ampSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { Double amp = progress / 100.0; // rescale by 100 RPCConnection.KnobInfo _k = new RPCConnection.KnobInfo(mult_knob_name, amp, BaseTypes.DOUBLE); HashMap _map = new HashMap<>(); _map.put(mult_knob_name, _k); postSetKnobMessage(_map); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); // Start setting up for USB permission request intent = getIntent(); mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); registerReceiver(mUsbReceiver, filter); mUsbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (mUsbDevice == null) { Log.d("GrTemplateUSRP", "Didn't get a device; finding it now."); final HashSet allowed_devices = getAllowedDevices(this); final HashMap usb_device_list = mUsbManager.getDeviceList(); for (UsbDevice candidate : usb_device_list.values()) { String candstr = "v" + candidate.getVendorId() + "p" + candidate.getProductId(); if (allowed_devices.contains(candstr)) { // Need to handle case where we have more than one device connected mUsbDevice = candidate; } } } Log.d("GrTemplateUSRP", "Selected Device: " + mUsbDevice); PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); // Launch dialog to ask for permission. // If use hits OK, the broadcast receiver will be launched. mUsbManager.requestPermission(mUsbDevice, permissionIntent); }

需要注意的是,我們?nèi)砸诖颂巹?chuàng)建Seek Bar作為GUI設(shè)置。

我們還調(diào)用了一個(gè)名為getAllowedDevices的新函數(shù)。 該函數(shù)能夠解析目標(biāo)通信設(shè)備的XML文件。因此,如果存在于此文件中列出的設(shè)備(基于供應(yīng)商和產(chǎn)品ID),無線電接收器才會(huì)被觸發(fā)。

現(xiàn)在需要?jiǎng)?chuàng)建device_filter.xml文件。 在res目錄中,添加一個(gè)名為xml的新目錄。在xml目錄中,創(chuàng)建一個(gè)名為device_filter.xml的新文件。 這個(gè)文件如下所示:

將來可能需要在此添加更多設(shè)備以用于其他硬件支持。

getAllowedDevices函數(shù)如下所示:

private static HashSet getAllowedDevices(final Context ctx) { final HashSet ans = new HashSet(); try { final XmlResourceParser xml = ctx.getResources().getXml(R.xml.device_filter); xml.next(); int eventType; while ((eventType = xml.getEventType()) != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_TAG: if (xml.getName().equals("usb-device")) { final AttributeSet as = Xml.asAttributeSet(xml); final Integer vendorId = Integer.valueOf(as.getAttributeValue(null, "vendor-id"), 10); final Integer productId = Integer.valueOf(as.getAttributeValue(null, "product-id"), 10); ans.add("v" + vendorId + "p" + productId); } break; } xml.next(); } } catch (Exception e) { e.printStackTrace(); } return ans; }

我們所注冊(cè)的無線電接收器mUsbReceiver(點(diǎn)此查看更多信息),如下所示:

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if(device != null){ mUsbDevice = device; SetupUSB(); } } else { Log.d("GrTemplateUSRP", "Permission denied for device " + device); } } } } };

如果設(shè)備注冊(cè)并且無錯(cuò)誤產(chǎn)生,即將其分配給我們的類對(duì)象mUsbDevice,并通過調(diào)用SetupUSB開始啟動(dòng)應(yīng)用程序的下一個(gè)階段。

private void SetupUSB() { final UsbDeviceConnection connection = mUsbManager.openDevice(mUsbDevice); if (connection != null) { fd = connection.getFileDeor(); } else { Log.d("GrTemplateUSRP", "Didn't get a USB Device Connection"); finish(); } if (mUsbDevice != null) { usbfs_path = properDeviceName(mUsbDevice.getDeviceName()); } else { Log.d("GrTemplateUSRP", "Didn't get a USB Device"); finish(); } int vid = mUsbDevice.getVendorId(); int pid = mUsbDevice.getProductId(); Log.d("GrTemplateUSRP", "Found fd: " + fd + " usbfs_path: " + usbfs_path); Log.d("GrTemplateUSRP", "Found vid: " + vid + " pid: " + pid); StartRadio(); }

該函數(shù)從USB設(shè)備獲取信息,將其記錄到logcat,然后調(diào)用StartRadio。我們使用稱為properDeviceName的解析函數(shù)從設(shè)備本身提取USB設(shè)備路徑:

public final static String properDeviceName(String deviceName) { if (deviceName == null) return DEFAULT_USBFS_PATH; deviceName = deviceName.trim(); if (deviceName.isEmpty()) return DEFAULT_USBFS_PATH; final String[] paths = deviceName.split("/"); final StringBuilder sb = new StringBuilder(); for (int i = 0; i < paths.length - 2; i++) if (i == 0) sb.append(paths[i]); else sb.append("/").append(paths[i]); final String stripped_name = sb.toString().trim(); if (stripped_name.isEmpty()) return DEFAULT_USBFS_PATH; else return stripped_name; }

路徑似乎每次都是”/dev/bus/usb”,但這個(gè)步驟是必要的,為的是防止某些特殊情況。

最后,我們調(diào)用StartRadio,這實(shí)際上是我們之前完成的其他的OnCreate工作,但現(xiàn)在我們正在等待USB設(shè)備被正確分配。

當(dāng)我們?cè)谘b有USRP的設(shè)備上構(gòu)建并運(yùn)行這個(gè)程序時(shí),會(huì)彈出一個(gè)對(duì)話框,詢問我們是否要授予USB設(shè)備權(quán)限。單擊確定,但不要單擊復(fù)選框。因?yàn)槲覀儾幌M@個(gè)應(yīng)用程序默認(rèn)與USRP關(guān)聯(lián),我們希望這是由GrHardwareService應(yīng)用程序完成的。點(diǎn)擊確定后,我們應(yīng)該看到logcat中的日志消息,它提供了fd,usbfs_path以及發(fā)現(xiàn)設(shè)備的vid和pid。這確保我們正確地與Java中的USRP交互。然后,我們會(huì)將這些信息傳遞給流圖,以創(chuàng)建UHD USRP block。你應(yīng)該在logcat中看到類似這樣的內(nèi)容:

04-22 11:30:01.624 14537 14537 D GrTemplateUSRP: Didn't get a device; finding it now. 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: Selected Device: UsbDevice[mName=/dev/bus/usb/002/003,mVendorId=9472,mProductId=34,mClass=255,mSubclass=0,mProtocol=0,mManufacturerName=Ettus Research LLC,mProductName=USRP B200,mVersion=2.16,mSerialNumber=30BFC51,mConfigurations=[ 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbConfiguration[mId=1,mName=null,mAttributes=128,mMaxPower=1,mInterfaces=[ 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbInterface[mId=0,mAlternateSetting=0,mName=USRP B200,mClass=255,mSubclass=0,mProtocol=0,mEndpoints=[] 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbInterface[mId=1,mAlternateSetting=0,mName=USRP B200,mClass=255,mSubclass=0,mProtocol=0,mEndpoints=[ 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbEndpoint[mAddress=2,mAttributes=2,mMaxPacketSize=512,mInterval=0]] 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbInterface[mId=2,mAlternateSetting=0,mName=USRP B200,mClass=255,mSubclass=0,mProtocol=0,mEndpoints=[ 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbEndpoint[mAddress=134,mAttributes=2,mMaxPacketSize=512,mInterval=0]] 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbInterface[mId=3,mAlternateSetting=0,mName=USRP B200,mClass=255,mSubclass=0,mProtocol=0,mEndpoints=[ 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbEndpoint[mAddress=4,mAttributes=2,mMaxPacketSize=512,mInterval=0]] 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbInterface[mId=4,mAlternateSetting=0,mName=USRP B200,mClass=255,mSubclass=0,mProtocol=0,mEndpoints=[ 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: UsbEndpoint[mAddress=136,mAttributes=2,mMaxPacketSize=512,mInterval=0]]]] 04-22 11:30:01.626 14537 14537 D GrTemplateUSRP: Called Request Permission 04-22 11:30:01.627 14537 14537 D GrTemplateUSRP: Found fd: 22 usbfs_path: /dev/bus/usb 04-22 11:30:01.627 14537 14537 D GrTemplateUSRP: Found vid: 9472 pid: 34 創(chuàng)建UHD USRP Source

現(xiàn)在我們有權(quán)限與我們需要與USRP傳遞的所有信息。 所以現(xiàn)在可以改變流圖了,我們可以使用UHD USRP Source block作為源代替sig_source_f。

首先,我們需要將fd和usrpfs_path值傳遞給流圖。將fg.cpp中的函數(shù)簽名更改為:

JNIEXPORT void JNICALL Java_org_gnuradio_grtemplateusrp_MainActivity_FgInit(JNIEnv* env, jobject thiz, int fd, jstring devname)

在聲明JNI函數(shù)的MainActivity.java中,我們需要添加兩個(gè)參數(shù):

public native void FgInit(int fd, String usbfs_path);

在SetupRadio中,確保將這些信息作為“FgInit(fd,usbfs_path)”傳遞。

然后我們提取信息并為usrp_source block格式化設(shè)備參數(shù)字符串:

#include .... const char *usbfs_path = env->GetStringUTFChars(devname, NULL); std::stringstream args; args << "uhd,fd=" << fd << ",usbfs_path=" << usbfs_path; GR_INFO("fg", boost::str(boost::format("Using UHD args=%1%") % args.str())); uhd::stream_args_t stream_args; stream_args.cpu_format = "fc32"; stream_args.otw_format = "sc16"; .... gr::uhd::usrp_source::sptr src; .... src = gr::uhd::usrp_source::make(args.str(), stream_args); src->set_samp_rate(200e3); src->set_center_freq(101.1e6); src->set_gain(20); // adjust as needed

src現(xiàn)在是一個(gè)復(fù)雜的源。 所以現(xiàn)在要做的是創(chuàng)建一個(gè)簡(jiǎn)單的流圖,如下所示:

usrp_source -> complex_to_real -> multiply_const_ff -> opensl_sink

完整的流圖FgInit如下所示:

// Get any GNU Radio headers #include #include #include #include #include // Declare the global virtual machine and top-block objects JavaVM *vm; gr::top_block_sptr tb; extern "C" { JNIEXPORT void JNICALL Java_org_gnuradio_grtemplateusrp_MainActivity_FgInit(JNIEnv* env, jobject thiz, int fd, jstring devname) { GR_INFO("fg", "FgInit Called"); const char *usbfs_path = env->GetStringUTFChars(devname, NULL); std::stringstream args; args << "uhd,fd=" << fd << ",usbfs_path=" << usbfs_path; GR_INFO("fg", boost::str(boost::format("Using UHD args=%1%") % args.str())); uhd::stream_args_t stream_args; stream_args.cpu_format = "fc32"; stream_args.otw_format = "sc16"; float samp_rate = 48e3; // 48 kHz // Declare our GNU Radio blocks gr::uhd::usrp_source::sptr src; gr::blocks::complex_to_real::sptr c2r; gr::blocks::multiply_const_ff::sptr mult; gr::grand::opensl_sink::sptr snk; // Construct the objects for every block in the flowgraph tb = gr::make_top_block("fg"); src = gr::uhd::usrp_source::make(args.str(), stream_args); c2r = gr::blocks::complex_to_real::make(); mult = gr::blocks::multiply_const_ff::make(0.0); snk = gr::grand::opensl_sink::make(int(samp_rate)); src->set_samp_rate(200e3); src->set_center_freq(101.1e6); src->set_gain(20); // adjust as needed // Connect up the flowgraph tb->connect(src, 0, c2r, 0); tb->connect(c2r, 0, mult, 0); tb->connect(mult, 0, snk, 0); } ....

這個(gè)流圖對(duì)USRP沒有任何特別的用處,但是應(yīng)該可以接收靜態(tài)的了。由于沒有設(shè)置采樣率,頻率或增益值的事件,因此傳入的與任何真實(shí)的東西都沒有關(guān)系。有關(guān)USRP應(yīng)用更復(fù)雜的用法,請(qǐng)查看GrRxFM,它使用USRP接收和解調(diào)FM廣播信號(hào)。且設(shè)置滑塊來調(diào)整頻率和增益,以及處理流圖中的采樣率和比率變化。

*參考來源:gnuradio,FB小編Covfefe編譯,轉(zhuǎn)載請(qǐng)注明來自FreeBuf.COM返回搜狐,查看更多

責(zé)任編輯:

總結(jié)

以上是生活随笔為你收集整理的gnuradio android手机,如何搭配USRP在安卓设备上搭建GNU Radio的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。