kopia lustrzana https://github.com/N0BOY/FT8CN
Merge pull request #67 from d3m3vilurr/trusdx
Support audio streaming over CAT of (tr)uSDXpull/74/head
commit
68e1c79b6a
|
@ -65,6 +65,12 @@ android {
|
||||||
// version '3.18.1'
|
// version '3.18.1'
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
jniLibs.srcDirs = ['libs']
|
||||||
|
}
|
||||||
|
}
|
||||||
namespace 'com.bg7yoz.ft8cn'
|
namespace 'com.bg7yoz.ft8cn'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,4 +94,5 @@ dependencies {
|
||||||
implementation files('src/libs/MPAndroidChartv_3.1.0.jar')
|
implementation files('src/libs/MPAndroidChartv_3.1.0.jar')
|
||||||
implementation files('src/libs/nanohttpd-2.2.0.jar')
|
implementation files('src/libs/nanohttpd-2.2.0.jar')
|
||||||
implementation files('src/libs/osmdroid-android-6.1.14.aar')//地图控件
|
implementation files('src/libs/osmdroid-android-6.1.14.aar')//地图控件
|
||||||
|
implementation files('src/libs/resample-release.aar')
|
||||||
}
|
}
|
Plik binarny nie jest wyświetlany.
|
@ -51,3 +51,4 @@ FX-4CR,00,115200,7
|
||||||
Qrp Labs QDX,00,9600,7
|
Qrp Labs QDX,00,9600,7
|
||||||
UA3REO Wolf SDR(DIGU),00,4800,15
|
UA3REO Wolf SDR(DIGU),00,4800,15
|
||||||
UA3REO Wolf SDR(USB),00,4800,16
|
UA3REO Wolf SDR(USB),00,4800,16
|
||||||
|
(tr)uSDX,00,115200,17
|
||||||
|
|
|
@ -79,6 +79,7 @@ import com.bg7yoz.ft8cn.rigs.Yaesu38Rig;
|
||||||
import com.bg7yoz.ft8cn.rigs.Yaesu38_450Rig;
|
import com.bg7yoz.ft8cn.rigs.Yaesu38_450Rig;
|
||||||
import com.bg7yoz.ft8cn.rigs.Yaesu39Rig;
|
import com.bg7yoz.ft8cn.rigs.Yaesu39Rig;
|
||||||
import com.bg7yoz.ft8cn.rigs.YaesuDX10Rig;
|
import com.bg7yoz.ft8cn.rigs.YaesuDX10Rig;
|
||||||
|
import com.bg7yoz.ft8cn.rigs.TrUSDXRig;
|
||||||
import com.bg7yoz.ft8cn.spectrum.SpectrumListener;
|
import com.bg7yoz.ft8cn.spectrum.SpectrumListener;
|
||||||
import com.bg7yoz.ft8cn.timer.OnUtcTimer;
|
import com.bg7yoz.ft8cn.timer.OnUtcTimer;
|
||||||
import com.bg7yoz.ft8cn.timer.UtcTimer;
|
import com.bg7yoz.ft8cn.timer.UtcTimer;
|
||||||
|
@ -354,13 +355,26 @@ public class MainViewModel extends ViewModel {
|
||||||
|
|
||||||
//创建发射对象,回调:发射前,发射后、QSL成功后。
|
//创建发射对象,回调:发射前,发射后、QSL成功后。
|
||||||
ft8TransmitSignal = new FT8TransmitSignal(databaseOpr, new OnDoTransmitted() {
|
ft8TransmitSignal = new FT8TransmitSignal(databaseOpr, new OnDoTransmitted() {
|
||||||
|
private boolean needControlSco() {
|
||||||
|
if (GeneralVariables.connectMode == ConnectMode.NETWORK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (GeneralVariables.controlMode != ControlMode.CAT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (baseRig != null && !baseRig.supportWaveOverCAT()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBeforeTransmit(Ft8Message message, int functionOder) {
|
public void onBeforeTransmit(Ft8Message message, int functionOder) {
|
||||||
if (GeneralVariables.controlMode == ControlMode.CAT
|
if (GeneralVariables.controlMode == ControlMode.CAT
|
||||||
|| GeneralVariables.controlMode == ControlMode.RTS
|
|| GeneralVariables.controlMode == ControlMode.RTS
|
||||||
|| GeneralVariables.controlMode == ControlMode.DTR) {
|
|| GeneralVariables.controlMode == ControlMode.DTR) {
|
||||||
if (baseRig != null) {
|
if (baseRig != null) {
|
||||||
if (GeneralVariables.connectMode != ConnectMode.NETWORK) stopSco();
|
if (needControlSco()) stopSco();
|
||||||
baseRig.setPTT(true);
|
baseRig.setPTT(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +392,7 @@ public class MainViewModel extends ViewModel {
|
||||||
|| GeneralVariables.controlMode == ControlMode.DTR) {
|
|| GeneralVariables.controlMode == ControlMode.DTR) {
|
||||||
if (baseRig != null) {
|
if (baseRig != null) {
|
||||||
baseRig.setPTT(false);
|
baseRig.setPTT(false);
|
||||||
if (GeneralVariables.connectMode != ConnectMode.NETWORK) startSco();
|
if (needControlSco()) startSco();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,6 +410,31 @@ public class MainViewModel extends ViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportTransmitOverCAT() {
|
||||||
|
if (GeneralVariables.controlMode != ControlMode.CAT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (baseRig == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!baseRig.isConnected() || !baseRig.supportWaveOverCAT()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransmitOverCAT(Ft8Message msg) {
|
||||||
|
if (!supportTransmitOverCAT()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendWaveDataRunnable.baseRig = baseRig;
|
||||||
|
sendWaveDataRunnable.message = msg;
|
||||||
|
sendWaveDataThreadPool.execute(sendWaveDataRunnable);
|
||||||
|
}
|
||||||
|
|
||||||
}, new OnTransmitSuccess() {//当通联成功时
|
}, new OnTransmitSuccess() {//当通联成功时
|
||||||
@Override
|
@Override
|
||||||
public void doAfterTransmit(QSLRecord qslRecord) {
|
public void doAfterTransmit(QSLRecord qslRecord) {
|
||||||
|
@ -599,7 +638,14 @@ public class MainViewModel extends ViewModel {
|
||||||
}
|
}
|
||||||
baseRig.setControlMode(GeneralVariables.controlMode);
|
baseRig.setControlMode(GeneralVariables.controlMode);
|
||||||
CableConnector connector = new CableConnector(context, port, GeneralVariables.baudRate
|
CableConnector connector = new CableConnector(context, port, GeneralVariables.baudRate
|
||||||
, GeneralVariables.controlMode);
|
, GeneralVariables.controlMode, baseRig);
|
||||||
|
connector.setOnCableDataReceived(new CableConnector.OnCableDataReceived() {
|
||||||
|
@Override
|
||||||
|
public void OnWaveReceived(int bufferLen, float[] buffer) {
|
||||||
|
Log.i(TAG, "call hamRecorder.doOnWaveDataReceived");
|
||||||
|
hamRecorder.doOnWaveDataReceived(bufferLen, buffer);
|
||||||
|
}
|
||||||
|
});
|
||||||
baseRig.setOnRigStateChanged(onRigStateChanged);
|
baseRig.setOnRigStateChanged(onRigStateChanged);
|
||||||
baseRig.setConnector(connector);
|
baseRig.setConnector(connector);
|
||||||
connector.connect();
|
connector.connect();
|
||||||
|
@ -713,13 +759,6 @@ public class MainViewModel extends ViewModel {
|
||||||
* 根据指令集创建不同型号的电台
|
* 根据指令集创建不同型号的电台
|
||||||
*/
|
*/
|
||||||
private void connectRig() {
|
private void connectRig() {
|
||||||
if ((GeneralVariables.instructionSet == InstructionSet.FLEX_NETWORK)
|
|
||||||
|| (GeneralVariables.instructionSet == InstructionSet.ICOM
|
|
||||||
&& GeneralVariables.connectMode == ConnectMode.NETWORK)) {
|
|
||||||
hamRecorder.setDataFromLan();
|
|
||||||
} else {
|
|
||||||
hamRecorder.setDataFromMic();
|
|
||||||
}
|
|
||||||
baseRig = null;
|
baseRig = null;
|
||||||
//此处判断是用什么类型的电台,ICOM,YAESU 2,YAESU 3
|
//此处判断是用什么类型的电台,ICOM,YAESU 2,YAESU 3
|
||||||
switch (GeneralVariables.instructionSet) {
|
switch (GeneralVariables.instructionSet) {
|
||||||
|
@ -773,9 +812,23 @@ public class MainViewModel extends ViewModel {
|
||||||
break;
|
break;
|
||||||
case InstructionSet.WOLF_SDR_USB:
|
case InstructionSet.WOLF_SDR_USB:
|
||||||
baseRig = new Wolf_sdr_450Rig(true);
|
baseRig = new Wolf_sdr_450Rig(true);
|
||||||
|
case InstructionSet.TRUSDX:
|
||||||
|
baseRig = new TrUSDXRig();//(tr)uSDX
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((GeneralVariables.instructionSet == InstructionSet.FLEX_NETWORK)
|
||||||
|
|| (GeneralVariables.instructionSet == InstructionSet.ICOM
|
||||||
|
&& GeneralVariables.connectMode == ConnectMode.NETWORK)) {
|
||||||
|
hamRecorder.setDataFromLan();
|
||||||
|
} else {
|
||||||
|
if (GeneralVariables.controlMode != ControlMode.CAT || baseRig == null || !baseRig.supportWaveOverCAT()) {
|
||||||
|
hamRecorder.setDataFromMic();
|
||||||
|
} else {
|
||||||
|
hamRecorder.setDataFromLan();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutableIsFlexRadio.postValue(GeneralVariables.instructionSet == InstructionSet.FLEX_NETWORK);
|
mutableIsFlexRadio.postValue(GeneralVariables.instructionSet == InstructionSet.FLEX_NETWORK);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,10 +74,30 @@ public class BaseRigConnector {
|
||||||
onConnectReceiveData=receiveData;
|
onConnectReceiveData=receiveData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendWaveData(byte[] data){
|
||||||
|
float[] waveFloat=new float[data.length/2];
|
||||||
|
for (int i = 0; i <waveFloat.length ; i++) {
|
||||||
|
waveFloat[i]=readShortBigEndianData(data,i*2)/32768.0f;
|
||||||
|
}
|
||||||
|
sendWaveData(waveFloat);
|
||||||
|
}
|
||||||
|
|
||||||
public void sendWaveData(float[] data){
|
public void sendWaveData(float[] data){
|
||||||
//留给网络方式发送音频流
|
//留给网络方式发送音频流
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void receiveWaveData(byte[] data){
|
||||||
|
|
||||||
|
float[] waveFloat=new float[data.length/2];
|
||||||
|
for (int i = 0; i <waveFloat.length ; i++) {
|
||||||
|
waveFloat[i]=readShortBigEndianData(data,i*2)/32768.0f;
|
||||||
|
}
|
||||||
|
receiveWaveData(waveFloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void receiveWaveData(float[] data){
|
||||||
|
}
|
||||||
|
|
||||||
public OnConnectReceiveData getOnConnectReceiveData() {
|
public OnConnectReceiveData getOnConnectReceiveData() {
|
||||||
return onConnectReceiveData;
|
return onConnectReceiveData;
|
||||||
}
|
}
|
||||||
|
@ -100,4 +120,17 @@ public class BaseRigConnector {
|
||||||
public boolean isConnected(){
|
public boolean isConnected(){
|
||||||
return connected;
|
return connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从流数据中读取小端模式的Short
|
||||||
|
*
|
||||||
|
* @param data 流数据
|
||||||
|
* @param start 起始点
|
||||||
|
* @return Int16
|
||||||
|
*/
|
||||||
|
public static short readShortBigEndianData(byte[] data, int start) {
|
||||||
|
if (data.length - start < 2) return 0;
|
||||||
|
return (short) ((short) data[start] & 0xff
|
||||||
|
| ((short) data[start + 1] & 0xff) << 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.bg7yoz.ft8cn.database.ControlMode;
|
import com.bg7yoz.ft8cn.database.ControlMode;
|
||||||
|
import com.bg7yoz.ft8cn.rigs.BaseRig;
|
||||||
import com.bg7yoz.ft8cn.serialport.util.SerialInputOutputManager;
|
import com.bg7yoz.ft8cn.serialport.util.SerialInputOutputManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,13 +15,18 @@ import com.bg7yoz.ft8cn.serialport.util.SerialInputOutputManager;
|
||||||
*/
|
*/
|
||||||
public class CableConnector extends BaseRigConnector {
|
public class CableConnector extends BaseRigConnector {
|
||||||
private static final String TAG="CableConnector";
|
private static final String TAG="CableConnector";
|
||||||
|
public interface OnCableDataReceived {
|
||||||
|
void OnWaveReceived(int bufferLen,float[] buffer);
|
||||||
|
}
|
||||||
|
|
||||||
private final CableSerialPort cableSerialPort;
|
private final CableSerialPort cableSerialPort;
|
||||||
|
private final BaseRig cableConnectedRig;
|
||||||
|
private OnCableDataReceived onCableDataReceived;
|
||||||
|
|
||||||
public CableConnector(Context context,CableSerialPort.SerialPort serialPort, int baudRate
|
public CableConnector(Context context,CableSerialPort.SerialPort serialPort, int baudRate
|
||||||
, int controlMode) {
|
, int controlMode, BaseRig cableConnectedRig) {
|
||||||
super(controlMode);
|
super(controlMode);
|
||||||
|
this.cableConnectedRig = cableConnectedRig;
|
||||||
cableSerialPort= new CableSerialPort(context,serialPort,baudRate,getOnConnectorStateChanged());
|
cableSerialPort= new CableSerialPort(context,serialPort,baudRate,getOnConnectorStateChanged());
|
||||||
cableSerialPort.ioListener=new SerialInputOutputManager.Listener() {
|
cableSerialPort.ioListener=new SerialInputOutputManager.Listener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,6 +67,32 @@ public class CableConnector extends BaseRigConnector {
|
||||||
cableSerialPort.sendData(command);//以CAT指令发送PTT
|
cableSerialPort.sendData(command);//以CAT指令发送PTT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendWaveData(byte[] data) {
|
||||||
|
sendData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendWaveData(float[] data) {
|
||||||
|
// TODO float to byte
|
||||||
|
byte[] wave = new byte[data.length * 2];
|
||||||
|
sendWaveData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveWaveData(float[] data){
|
||||||
|
Log.i(TAG, "received wave data");
|
||||||
|
|
||||||
|
if (onCableDataReceived!=null){
|
||||||
|
Log.i(TAG, "call onCableDataReceived.OnWaveReceived");
|
||||||
|
onCableDataReceived.OnWaveReceived(data.length,data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnCableDataReceived(OnCableDataReceived onCableDataReceived) {
|
||||||
|
this.onCableDataReceived = onCableDataReceived;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connect() {
|
public void connect() {
|
||||||
super.connect();
|
super.connect();
|
||||||
|
@ -69,6 +101,7 @@ public class CableConnector extends BaseRigConnector {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnect() {
|
public void disconnect() {
|
||||||
|
cableConnectedRig.onDisconnecting();
|
||||||
super.disconnect();
|
super.disconnect();
|
||||||
cableSerialPort.disconnect();
|
cableSerialPort.disconnect();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import com.bg7yoz.ft8cn.Ft8Message;
|
||||||
import com.bg7yoz.ft8cn.GeneralVariables;
|
import com.bg7yoz.ft8cn.GeneralVariables;
|
||||||
import com.bg7yoz.ft8cn.R;
|
import com.bg7yoz.ft8cn.R;
|
||||||
import com.bg7yoz.ft8cn.connector.ConnectMode;
|
import com.bg7yoz.ft8cn.connector.ConnectMode;
|
||||||
|
import com.bg7yoz.ft8cn.database.ControlMode;
|
||||||
import com.bg7yoz.ft8cn.database.DatabaseOpr;
|
import com.bg7yoz.ft8cn.database.DatabaseOpr;
|
||||||
import com.bg7yoz.ft8cn.log.QSLRecord;
|
import com.bg7yoz.ft8cn.log.QSLRecord;
|
||||||
import com.bg7yoz.ft8cn.rigs.BaseRigOperation;
|
import com.bg7yoz.ft8cn.rigs.BaseRigOperation;
|
||||||
|
@ -413,6 +414,32 @@ public class FT8TransmitSignal {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GeneralVariables.controlMode == ControlMode.CAT) {
|
||||||
|
Log.d(TAG, "playFT8Signal: try to transmit over CAT");
|
||||||
|
|
||||||
|
if (onDoTransmitted != null) {//处理音频数据,可以给ICOM的网络模式发送
|
||||||
|
if (onDoTransmitted.supportTransmitOverCAT()) {
|
||||||
|
onDoTransmitted.onTransmitOverCAT(msg);
|
||||||
|
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
while (isTransmitting) {//等待音频数据包发送完毕再退出,以触发afterTransmitting
|
||||||
|
try {
|
||||||
|
Thread.sleep(1);
|
||||||
|
long current = System.currentTimeMillis() - now;
|
||||||
|
if (current > 13000) {//实际发射的时长
|
||||||
|
isTransmitting = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d(TAG, "playFT8Signal: transmitting over CAT is finished.");
|
||||||
|
afterPlayAudio();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//进入声卡模式
|
//进入声卡模式
|
||||||
float[] buffer;
|
float[] buffer;
|
||||||
|
|
|
@ -11,4 +11,6 @@ public interface OnDoTransmitted {
|
||||||
void onBeforeTransmit(Ft8Message message,int functionOder);
|
void onBeforeTransmit(Ft8Message message,int functionOder);
|
||||||
void onAfterTransmit(Ft8Message message, int functionOder);
|
void onAfterTransmit(Ft8Message message, int functionOder);
|
||||||
void onTransmitByWifi(Ft8Message message);
|
void onTransmitByWifi(Ft8Message message);
|
||||||
|
boolean supportTransmitOverCAT();
|
||||||
|
void onTransmitOverCAT(Ft8Message message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,4 +130,11 @@ public abstract class BaseRig {
|
||||||
public boolean isPttOn() {
|
public boolean isPttOn() {
|
||||||
return isPttOn;
|
return isPttOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportWaveOverCAT() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDisconnecting() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,5 +18,5 @@ public class InstructionSet {
|
||||||
public static final int KENWOOD_TS2000=14;//建武TS2000,发射指令是TX0;
|
public static final int KENWOOD_TS2000=14;//建武TS2000,发射指令是TX0;
|
||||||
public static final int WOLF_SDR_DIGU=15;//UA3REO Wolf SDR,DIG-U模式,兼容YAESU 450D;
|
public static final int WOLF_SDR_DIGU=15;//UA3REO Wolf SDR,DIG-U模式,兼容YAESU 450D;
|
||||||
public static final int WOLF_SDR_USB=16;//UA3REO Wolf SDR,USB模式,兼容YAESU 450D;
|
public static final int WOLF_SDR_USB=16;//UA3REO Wolf SDR,USB模式,兼容YAESU 450D;
|
||||||
|
public static final int TRUSDX=17;//(tr)USDX;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,11 @@ public class KenwoodTK90RigConstant {
|
||||||
private static final String TS590_READ_FREQ = "FA;";//KENWOOD 读频率
|
private static final String TS590_READ_FREQ = "FA;";//KENWOOD 读频率
|
||||||
private static final String TS590_READ_METERS = "RM;";//KENWOOD 读METER
|
private static final String TS590_READ_METERS = "RM;";//KENWOOD 读METER
|
||||||
|
|
||||||
|
// (tr)uSDX extensions
|
||||||
|
private static final String TRUSDX_STREAMING_OFF="UA0;";
|
||||||
|
private static final String TRUSDX_STREAMING_ON_SPEAKER_ON="UA1;";
|
||||||
|
private static final String TRUSDX_STREAMING_ON_SPEAKER_OFF="UA2;";
|
||||||
|
private static final String TRUSDX_STREAMING_AUDIO="US";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,4 +137,19 @@ public class KenwoodTK90RigConstant {
|
||||||
return TS590_READ_FREQ.getBytes();
|
return TS590_READ_FREQ.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] setTrUSDXStreaming(boolean on) {
|
||||||
|
if (on) {
|
||||||
|
return TRUSDX_STREAMING_ON_SPEAKER_OFF.getBytes();
|
||||||
|
} else {
|
||||||
|
return TRUSDX_STREAMING_OFF.getBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] setTrUSDXPTTState(boolean on) {
|
||||||
|
if (on) {
|
||||||
|
return ";TX0;".getBytes();
|
||||||
|
} else {
|
||||||
|
return ";RX;".getBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,329 @@
|
||||||
|
package com.bg7yoz.ft8cn.rigs;
|
||||||
|
|
||||||
|
import static com.bg7yoz.ft8cn.GeneralVariables.QUERY_FREQ_TIMEOUT;
|
||||||
|
import static com.bg7yoz.ft8cn.GeneralVariables.START_QUERY_FREQ_DELAY;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.bg7yoz.ft8cn.Ft8Message;
|
||||||
|
import com.bg7yoz.ft8cn.GeneralVariables;
|
||||||
|
import com.bg7yoz.ft8cn.R;
|
||||||
|
import com.bg7yoz.ft8cn.database.ControlMode;
|
||||||
|
import com.bg7yoz.ft8cn.ft8transmit.GenerateFT8;
|
||||||
|
import com.bg7yoz.ft8cn.ui.ToastMessage;
|
||||||
|
|
||||||
|
import com.jackz314.resample.Resample;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (tr)uSDX, fork from KENWOOD TS590.
|
||||||
|
*/
|
||||||
|
public class TrUSDXRig extends BaseRig {
|
||||||
|
private static final String TAG = "TrUSDXRig";
|
||||||
|
private static final int rxSampling = 7812;
|
||||||
|
private static final int txSampling = 11520;
|
||||||
|
private final StringBuilder buffer = new StringBuilder();
|
||||||
|
private final ByteArrayOutputStream rxStreamBuffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
private Timer readFreqTimer = new Timer();
|
||||||
|
private int swr=0;
|
||||||
|
private int alc=0;
|
||||||
|
private boolean alcMaxAlert = false;
|
||||||
|
private boolean swrAlert = false;
|
||||||
|
private boolean rxStreaming = false;
|
||||||
|
|
||||||
|
private TimerTask readTask() {
|
||||||
|
return new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
if (!isConnected()) {
|
||||||
|
readFreqTimer.cancel();
|
||||||
|
readFreqTimer.purge();
|
||||||
|
readFreqTimer = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isPttOn()){
|
||||||
|
clearBufferData();
|
||||||
|
}else {
|
||||||
|
readFreqFromRig();//读频率
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "readFreq error:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空缓存数据
|
||||||
|
*/
|
||||||
|
private void clearBufferData() {
|
||||||
|
buffer.setLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPTT(boolean on) {
|
||||||
|
super.setPTT(on);
|
||||||
|
if (getConnector() != null) {
|
||||||
|
switch (getControlMode()) {
|
||||||
|
case ControlMode.CAT:
|
||||||
|
if (on) {
|
||||||
|
rxStreaming = false;
|
||||||
|
}
|
||||||
|
getConnector().setPttOn(KenwoodTK90RigConstant.setTrUSDXPTTState(on));
|
||||||
|
break;
|
||||||
|
case ControlMode.RTS:
|
||||||
|
case ControlMode.DTR:
|
||||||
|
getConnector().setPttOn(on);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConnected() {
|
||||||
|
if (getConnector() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return getConnector().isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUsbModeToRig() {
|
||||||
|
if (getConnector() != null) {
|
||||||
|
getConnector().sendData(KenwoodTK90RigConstant.setTS590OperationUSBMode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFreqToRig() {
|
||||||
|
if (getConnector() != null) {
|
||||||
|
getConnector().sendData(KenwoodTK90RigConstant.setTS590OperationFreq(getFreq()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceiveData(byte[] data) {
|
||||||
|
byte[] remain = data;
|
||||||
|
String s = new String(data);
|
||||||
|
while (s.contains(";")) { // ;
|
||||||
|
// TODO apply effective way
|
||||||
|
int idx = s.indexOf(";");
|
||||||
|
byte[] cutted = Arrays.copyOf(remain, idx);
|
||||||
|
remain = Arrays.copyOfRange(remain, idx + 1, remain.length);
|
||||||
|
s = new String(remain);
|
||||||
|
|
||||||
|
if (rxStreaming) {
|
||||||
|
onReceivedWaveData(cutted, true);
|
||||||
|
rxStreaming = false;
|
||||||
|
} else {
|
||||||
|
buffer.append(new String(cutted));
|
||||||
|
//开始分析数据
|
||||||
|
Yaesu3Command yaesu3Command = Yaesu3Command.getCommand(buffer.toString());
|
||||||
|
clearBufferData();//清一下缓存
|
||||||
|
|
||||||
|
if (yaesu3Command == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String cmd=yaesu3Command.getCommandID();
|
||||||
|
if (cmd.equalsIgnoreCase("FA")) {//频率
|
||||||
|
long tempFreq=Yaesu3Command.getFrequency(yaesu3Command);
|
||||||
|
if (tempFreq!=0) {//如果tempFreq==0,说明频率不正常
|
||||||
|
setFreq(Yaesu3Command.getFrequency(yaesu3Command));
|
||||||
|
}
|
||||||
|
}else if (cmd.equalsIgnoreCase("US")){
|
||||||
|
rxStreaming = true;
|
||||||
|
byte[] wave = Arrays.copyOfRange(cutted, 2, cutted.length);
|
||||||
|
onReceivedWaveData(wave);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remain.length <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rxStreaming) {
|
||||||
|
onReceivedWaveData(remain);
|
||||||
|
} else if (remain.length >= 2 && remain[0] == 0x55 && remain[1] == 0x53) {// US
|
||||||
|
clearBufferData();
|
||||||
|
rxStreaming = true;
|
||||||
|
byte[] wave = Arrays.copyOfRange(remain, 2, remain.length);
|
||||||
|
onReceivedWaveData(wave);
|
||||||
|
} else {
|
||||||
|
buffer.append(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void showAlert() {
|
||||||
|
if (swr >= KenwoodTK90RigConstant.ts_590_swr_alert_max) {
|
||||||
|
if (!swrAlert) {
|
||||||
|
swrAlert = true;
|
||||||
|
ToastMessage.show(GeneralVariables.getStringFromResource(R.string.swr_high_alert));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
swrAlert = false;
|
||||||
|
}
|
||||||
|
if (alc > KenwoodTK90RigConstant.ts_590_alc_alert_max) {//网络模式下不警告ALC
|
||||||
|
if (!alcMaxAlert) {
|
||||||
|
alcMaxAlert = true;
|
||||||
|
ToastMessage.show(GeneralVariables.getStringFromResource(R.string.alc_high_alert));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alcMaxAlert = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void readFreqFromRig() {
|
||||||
|
if (getConnector() != null) {
|
||||||
|
clearBufferData();//清空一下缓存
|
||||||
|
// force reset
|
||||||
|
getConnector().sendData(KenwoodTK90RigConstant.setTrUSDXPTTState(false));
|
||||||
|
getConnector().sendData(KenwoodTK90RigConstant.setTS590ReadOperationFreq());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "(tr)uSDX";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportWaveOverCAT() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisconnecting() {
|
||||||
|
if (getConnector() != null) {
|
||||||
|
clearBufferData();
|
||||||
|
getConnector().sendData(KenwoodTK90RigConstant.setTrUSDXStreaming(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onReceivedWaveData(byte[] data) {
|
||||||
|
onReceivedWaveData(data, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onReceivedWaveData(byte[] data, boolean force) {
|
||||||
|
if (data.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (getConnector() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Resample rxResample = new Resample(Resample.ConverterType.SRC_LINEAR, 1, rxSampling, 12000);
|
||||||
|
rxStreamBuffer.write(data, 0, data.length);
|
||||||
|
if (rxStreamBuffer.size() >= 256 || force) {
|
||||||
|
byte[] resampled = rxResample.processCopy(toWaveSamples8To16(rxStreamBuffer.toByteArray()));
|
||||||
|
rxStreamBuffer.reset();
|
||||||
|
getConnector().receiveWaveData(resampled);
|
||||||
|
}
|
||||||
|
rxResample.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendWaveData(Ft8Message message) {
|
||||||
|
if (getConnector() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float[] wave = GenerateFT8.generateFt8(message, GeneralVariables.getBaseFrequency()
|
||||||
|
// ,txSampling);
|
||||||
|
, 24000);
|
||||||
|
if (wave == null){
|
||||||
|
setPTT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] pcm16 = toWaveFloatToPCM16(wave);
|
||||||
|
Resample txResample = new Resample(Resample.ConverterType.SRC_SINC_FASTEST, 1, 24000, txSampling);
|
||||||
|
byte[] resampled = txResample.processCopy(pcm16);
|
||||||
|
txResample.close();
|
||||||
|
byte[] pcm8 = toWaveSamples16To8(resampled);
|
||||||
|
for (int i = 0; i < pcm8.length; i++) {
|
||||||
|
if (pcm8[i] == 0x3B) pcm8[i] = 0x3A; // ; to :
|
||||||
|
}
|
||||||
|
while (pcm8.length > 0) {
|
||||||
|
if (pcm8.length <= 256) {
|
||||||
|
getConnector().sendData(pcm8);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
getConnector().sendData(Arrays.copyOfRange(pcm8, 0, 256));
|
||||||
|
pcm8 = Arrays.copyOfRange(pcm8, 256, pcm8.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] toWaveSamples8To16(byte[] in) {
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate(in.length * 2);
|
||||||
|
for (int i = 0; i < in.length; i++) {
|
||||||
|
short v = (short)(((short)in[i] - 128) << 8);
|
||||||
|
buf.putShort(v);
|
||||||
|
}
|
||||||
|
return buf.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] toWaveFloatToPCM16(float[] in) {
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate(in.length * 2);
|
||||||
|
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
for (int i = 0; i < in.length; i++) {
|
||||||
|
float x = in[i];
|
||||||
|
short v = (short)(x * 32767.0f);
|
||||||
|
buf.putShort(v);
|
||||||
|
}
|
||||||
|
return buf.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] toWaveFloatToPCM8(float[] in) {
|
||||||
|
byte[] out = new byte[in.length];
|
||||||
|
for (int i = 0; i < in.length; i++) {
|
||||||
|
float x = in[i];
|
||||||
|
short v = (short)(x * 32767.0f);
|
||||||
|
out[i] = (byte)((byte)(v >> 8) + 128);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] toWaveSamples16To8(byte[] in) {
|
||||||
|
byte[] out = new byte[in.length / 2];
|
||||||
|
for (int i = 0; i < out.length; i++) {
|
||||||
|
short v = readShortBigEndianData(in, i * 2);
|
||||||
|
//short v = (short)(((short)in[i*2] & 0xFF) << 8 | (short)in[i*2+1] & 0xFF);
|
||||||
|
out[i] = (byte)(((byte)(v >> 8)) + 128);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrUSDXRig() {
|
||||||
|
new Handler().postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (getConnector()!=null){
|
||||||
|
getConnector().sendData(KenwoodTK90RigConstant.setTS590VFOMode());
|
||||||
|
getConnector().sendData(KenwoodTK90RigConstant.setTrUSDXStreaming(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},START_QUERY_FREQ_DELAY-500);
|
||||||
|
readFreqTimer.schedule(readTask(), START_QUERY_FREQ_DELAY,QUERY_FREQ_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从流数据中读取小端模式的Short
|
||||||
|
*
|
||||||
|
* @param data 流数据
|
||||||
|
* @param start 起始点
|
||||||
|
* @return Int16
|
||||||
|
*/
|
||||||
|
public static short readShortBigEndianData(byte[] data, int start) {
|
||||||
|
if (data.length - start < 2) return 0;
|
||||||
|
return (short) ((short) data[start] & 0xff
|
||||||
|
| ((short) data[start + 1] & 0xff) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Ładowanie…
Reference in New Issue