FM Radio项目原创代码

来源:互联网 发布:制造业大数据解决方案 编辑:程序博客网 时间:2024/05/01 02:57

最近在做基于一款芯片的FM Radio.有了底层驱动,需要我做上层java代码,已经自己写jni调用驱动,实现FM Radio 的功能。

android NDK开发就不介绍了,这样的可以有很多参考。我只是把我写的部分代码拿出来与大家分享。有做FM Radio 的请参考,也可以提出意见。


首先要有功能代码:做了一个类

package com.mycompanyname.fm;

import android.util.Log;

public class FMFunction {
    private static final String TAG = "FMFunction";
    
    public FMFunction() {
        Log.i(TAG,"FMFunction created......");
    }
    
    public void openFm () {
        nativeOpenFM();
    }
    
    public void closeFm () {
        nativeCloseFM();
    }
    

    public int[] scanChannel() {
        return nativeScanChannel();
    }
    
    public void playChannel(int freq) {
        nativePlayChannel(freq);
    }
    
    public int getAudioVolume() {
        return nativeGetAudioVolume();
    }
    
    public void audioUp() {
        nativeAudioUp();
    }
    
    public void audioDown() {
        nativeAudioDown();
    }
    
    public void setMute() {
        nativeSetMute();
    }

    
    public int getRssiLevel() {
        return nativeGetRssiLevel();
    }
    
    //native function
    private native void nativeOpenFM();
    private native void nativeCloseFM();
    private native int [] nativeScanChannel();
    private native void nativePlayChannel(int freq);
    private native void nativeAudioUp();
    private native void nativeAudioDown();
    private native int nativeGetAudioVolume();
    private native void nativeSetMute();
    private native int nativeGetRssiLevel();

    static {
        Log.i(TAG,"loadLibrary carry out..............");
        System.loadLibrary("fmfunction-jni");
    }
}

这个类介绍了要用到的radio 功能。
openFm ():打开radio

closeFm ():关闭radio

scanChannel():扫描所有频道

playChannel(int freq):播放指定频率的频道

getAudioVolume():取得当前音量值

audioUp():提高音量

audioDown():降低音量

setMute():静音

getRssiLevel():取得信号强度


只是简单的写了这些功能,这些功能对播放应该就可以了。


下面还要就这些上层功能做jni实现,jni调用驱动实现上述功能。

jni 代码如下:

#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <android/log.h>
#define VIDIOC_S_HW_FREQ_SEEK 0x40305652

struct v4l2_hw_freq_seek {
    __u32              tuner;
    enum v4l2_tuner_type  type;
    __u32              seek_upward;
    __u32              wrap_around;
    __u32              reserved[8];
};

/* parameters for driver use */
static int fd;
int ret;
struct v4l2_capability cap;
struct v4l2_tuner tuner;
struct v4l2_audio a;
struct v4l2_frequency f;
struct v4l2_queryctrl q;
struct v4l2_control c;
struct v4l2_hw_freq_seek seek;
unsigned int i;
unsigned int mute=0;
unsigned int volume = 0;
unsigned int freq = 87500000;

void  Java_com_innofidei_fm_FMFunction_nativeOpenFM(JNIEnv* env,jobject thiz) {
    __android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeOpenFM init............");
    fd = open("/dev/radio0",O_RDONLY);
    if (fd < 0) {
         __android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeOpenFM init failed : %d  ",fd);
        
    } else {
         __android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeOpenFM init success");
        
    }    
}

void  Java_com_innofidei_fm_FMFunction_nativeCloseFM(JNIEnv* env,jobject thiz) {
    __android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeCloseFM .............");
    close(fd);  
    return;  
}

jintArray  Java_com_innofidei_fm_FMFunction_nativeScanChannel(JNIEnv* env,jobject thiz) {
    __android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeScanChannel..... .......");
    
    jintArray result;
    result = (*env)->NewIntArray(env, 20);
    if (result == NULL) {
        return NULL;
    }
    
    /*init original array for recording frequency info */
    jint num[20];  
    jint i = 0;
    for (;i<20;i++) {
        num[i] = 0;
    }
    
    /* set lowest frequency */  
    f.frequency = freq *2 /125;
    f.type = V4L2_TUNER_RADIO;
    f.tuner = 0;
    ret = ioctl(fd,VIDIOC_S_FREQUENCY,&f);
    if (ret < 0) {
        __android_log_write(ANDROID_LOG_INFO,"JNIMsg","search  frequency failed");        
    } else {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","search frequency success");
    }
    
    /*search channel,obtain frequency to enter array */
    jint j = 0;
    for (;j<20;j++) {        
        seek.wrap_around = 1;
        seek.seek_upward = 0;
        seek.tuner = 0;
        ret = ioctl(fd,VIDIOC_S_HW_FREQ_SEEK,&seek);
        if (ret == 0) {
            f.tuner = 0;
            ret = ioctl(fd,VIDIOC_G_FREQUENCY,&f);
            if (ret < 0) {
               __android_log_print(ANDROID_LOG_INFO,"JNIGetFrequency","get frequency failed");
               break;
            } else {
                __android_log_print(ANDROID_LOG_INFO,"JNIMsg","get freq is %d",f.frequency);
                num[j] = f.frequency;
            }
             
        } else {
            break;
        }  
    }
    
    (*env)->SetIntArrayRegion(env,result, 0, 20, num);  
    return result;
}

void  Java_com_innofidei_fm_FMFunction_nativePlayChannel(JNIEnv* env,jobject thiz,jint freq){
    __android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativePlayChannel init......,freq is: %d",freq);
       
    f.frequency = freq;
    f.type = V4L2_TUNER_RADIO;
    f.tuner = 0;
    ret = ioctl(fd,VIDIOC_S_FREQUENCY,&f);    
    if (ret < 0) {
        __android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativePlay set frequency failed");
    } else {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativePlay carry out success");
    }
    
    /*unmute */
    mute = 0;
    c.id = V4L2_CID_AUDIO_MUTE;
    c.value = mute;
    ret = ioctl(fd,VIDIOC_S_CTRL,&c);
    if (ret < 0) {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativePlay can not unmute");
    } else {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativePlay unmute success ");        
    }    
    
    /*obtain current volume*/
    c.id = V4L2_CID_AUDIO_VOLUME;
    ret = ioctl(fd,VIDIOC_G_CTRL,&c);
    if (ret < 0) {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","get ctrl failed");
    } else {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","current volume is : %d",c.value);
    }    
}

void  Java_com_innofidei_fm_FMFunction_nativeAudioUp(JNIEnv* env,jobject thiz) {
    __android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeAudioUp...............");
    c.id = V4L2_CID_AUDIO_VOLUME;
    ret = ioctl(fd,VIDIOC_G_CTRL,&c);
    if (ret < 0) {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","get ctrl failed");
    } else {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","current volume is : %d",c.value);
        volume = c.value;
    }    
    c.id = V4L2_CID_AUDIO_VOLUME;
    if (volume < 15) {
        c.value = ++volume;
    }
    volume %=0x0f;
    ret = ioctl(fd,VIDIOC_S_CTRL,&c);
    if (ret < 0) {
        __android_log_write(ANDROID_LOG_INFO,"JNIMsg","set volume ctrl failed");
    }
    __android_log_print(ANDROID_LOG_INFO,"JNIMsg","after up, volume: %d",volume);
    return;
}

void  Java_com_innofidei_fm_FMFunction_nativeAudioDown(JNIEnv* env,jobject thiz) {
    __android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeAudioDown.............");
    c.id = V4L2_CID_AUDIO_VOLUME;
    ret = ioctl(fd,VIDIOC_G_CTRL,&c);
    if (ret < 0) {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","get ctrl failed");
    } else {
        __android_log_print(ANDROID_LOG_INFO,"JNIMsg","current volume is : %d",c.value);
        volume = c.value;
    }    
    c.id = V4L2_CID_AUDIO_VOLUME;
    if (volume > 0) {
        c.value = --volume;
    }
    volume %=0x0f;
    ret = ioctl(fd,VIDIOC_S_CTRL,&c);
    if (ret < 0) {
        __android_log_write(ANDROID_LOG_INFO,"JNIMsg","set volume ctrl failed");
    }
    __android_log_print(ANDROID_LOG_INFO,"JNIMsg","after down, volume: %d",volume);
    return;
}

void  Java_com_innofidei_fm_FMFunction_nativeSetMute(JNIEnv* env,jobject thiz) {
    __android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeSetMute init..................mute value is : %d",mute);
    if (mute == 0) {
           mute = 1;
    } else {
        mute = 0;
    }
    c.id = V4L2_CID_AUDIO_MUTE;
    c.value = mute;
    ret = ioctl(fd,VIDIOC_S_CTRL,&c);
    if (ret < 0) {
        __android_log_write(ANDROID_LOG_INFO,"JNIMsg","set mute ctrl failed");
    }
    __android_log_print(ANDROID_LOG_INFO,"JNIMsg","set mute ctrl success");
    return;
}

jint  Java_com_innofidei_fm_FMFunction_nativeGetAudioVolume(JNIEnv* env,jobject thiz) {
    __android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeGetAudioVolume............");
    c.id = V4L2_CID_AUDIO_VOLUME;
    ret = ioctl(fd,VIDIOC_G_CTRL,&c);
    if (ret < 0) {
        __android_log_write(ANDROID_LOG_INFO,"JNIMsg","get ctrl failed");
        return ret;
    }
    __android_log_print(ANDROID_LOG_INFO,"JNIMsg","volume is %d",c.value);
    return c.value;
}


jint  Java_com_innofidei_fm_FMFunction_nativeGetRssiLevel(JNIEnv* env,jobject thiz) {
    __android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeGetRssiLevel init................................");
    tuner.index = 0;    
    ret = ioctl(fd,VIDIOC_G_TUNER,&tuner);
    __android_log_print(ANDROID_LOG_INFO,"JNIMsg","rssi level is  %d",tuner.signal);
    return tuner.signal;
}


这个jni代码可以帮助你理解驱动,以及jni的写法,其中引人#include <android/log.h>头文件是为了用logcat查看代码流程用的。

因为网上的原创代码很少,所以将这些个人原创代码提供给android开发的朋友,为大家做参考。

如果你转载本代码,请注明出自本博客,违者必究!

原创粉丝点击