TrUSDXRig: Send TX streaming

IDK reason, generated packet was broken.
it send signal in multiple positions.
pull/67/head
Sunguk Lee 2023-08-07 22:27:13 +09:00
rodzic ca08aa3479
commit 8bbcc2be6f
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 20A74A5D37EEA757
7 zmienionych plików z 188 dodań i 34 usunięć

Wyświetl plik

@ -410,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() {//当通联成功时
@Override
public void doAfterTransmit(QSLRecord qslRecord) {

Wyświetl plik

@ -74,6 +74,14 @@ public class BaseRigConnector {
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){
//留给网络方式发送音频流
}

Wyświetl plik

@ -67,11 +67,16 @@ public class CableConnector extends BaseRigConnector {
cableSerialPort.sendData(command);//以CAT指令发送PTT
}
@Override
public void sendWaveData(byte[] data) {
sendData(data);
}
@Override
public void sendWaveData(float[] data) {
// TODO float to byte
// TODO replace `;` to ':'
// sendData(wave);
byte[] wave = new byte[data.length * 2];
sendWaveData(data);
}
@Override

Wyświetl plik

@ -20,6 +20,7 @@ import com.bg7yoz.ft8cn.Ft8Message;
import com.bg7yoz.ft8cn.GeneralVariables;
import com.bg7yoz.ft8cn.R;
import com.bg7yoz.ft8cn.connector.ConnectMode;
import com.bg7yoz.ft8cn.database.ControlMode;
import com.bg7yoz.ft8cn.database.DatabaseOpr;
import com.bg7yoz.ft8cn.log.QSLRecord;
import com.bg7yoz.ft8cn.rigs.BaseRigOperation;
@ -413,6 +414,32 @@ public class FT8TransmitSignal {
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: 退出网络音频发送。");
afterPlayAudio();
return;
}
}
}
//进入声卡模式
float[] buffer;

Wyświetl plik

@ -11,4 +11,6 @@ public interface OnDoTransmitted {
void onBeforeTransmit(Ft8Message message,int functionOder);
void onAfterTransmit(Ft8Message message, int functionOder);
void onTransmitByWifi(Ft8Message message);
boolean supportTransmitOverCAT();
void onTransmitOverCAT(Ft8Message message);
}

Wyświetl plik

@ -144,4 +144,12 @@ public class KenwoodTK90RigConstant {
return TRUSDX_STREAMING_OFF.getBytes();
}
}
public static byte[] setTrUSDXPTTState(boolean on) {
if (on) {
return ";TX0;".getBytes();
} else {
return ";RX;".getBytes();
}
}
}

Wyświetl plik

@ -6,15 +6,18 @@ 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;
@ -24,8 +27,12 @@ import java.util.TimerTask;
*/
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 final Resample rxResample = new Resample(Resample.ConverterType.SRC_LINEAR, 1, rxSampling, 12000);
//private final Resample txResample = new Resample(Resample.ConverterType.SRC_SINC_FASTEST, 1, 48000, txSampling);
private Timer readFreqTimer = new Timer();
private int swr=0;
@ -33,8 +40,6 @@ public class TrUSDXRig extends BaseRig {
private boolean alcMaxAlert = false;
private boolean swrAlert = false;
private boolean rxStreaming = false;
private int rxSampling = 7812;
private int txSampling = 11520;
private TimerTask readTask() {
return new TimerTask() {
@ -48,7 +53,7 @@ public class TrUSDXRig extends BaseRig {
return;
}
if (isPttOn()){
readMeters();//读METER
clearBufferData();
}else {
readFreqFromRig();//读频率
}
@ -60,16 +65,6 @@ public class TrUSDXRig extends BaseRig {
};
}
/**
* Meter RM;
*/
private void readMeters(){
if (getConnector() != null) {
clearBufferData();//清空一下缓存
getConnector().sendData(KenwoodTK90RigConstant.setRead590Meters());
}
}
/**
*
*/
@ -82,11 +77,11 @@ public class TrUSDXRig extends BaseRig {
super.setPTT(on);
if (getConnector() != null) {
switch (getControlMode()) {
case ControlMode.CAT://以CIV指令
case ControlMode.CAT:
if (on) {
rxStreaming = false;
}
getConnector().setPttOn(KenwoodTK90RigConstant.setTS590PTTState(on));
getConnector().setPttOn(KenwoodTK90RigConstant.setTrUSDXPTTState(on));
break;
case ControlMode.RTS:
case ControlMode.DTR:
@ -149,14 +144,6 @@ public class TrUSDXRig extends BaseRig {
if (tempFreq!=0) {//如果tempFreq==0说明频率不正常
setFreq(Yaesu3Command.getFrequency(yaesu3Command));
}
}else if (cmd.equalsIgnoreCase("RM")){//meter
if (Yaesu3Command.is590MeterSWR(yaesu3Command)) {
swr = Yaesu3Command.get590ALCOrSWR(yaesu3Command);
}
if (Yaesu3Command.is590MeterALC(yaesu3Command)) {
alc = Yaesu3Command.get590ALCOrSWR(yaesu3Command);
}
showAlert();
}else if (cmd.equalsIgnoreCase("US")){
rxStreaming = true;
byte[] wave = Arrays.copyOfRange(cutted, 2, cutted.length);
@ -201,6 +188,8 @@ public class TrUSDXRig extends BaseRig {
public void readFreqFromRig() {
if (getConnector() != null) {
clearBufferData();//清空一下缓存
// force reset
getConnector().sendData(KenwoodTK90RigConstant.setTrUSDXPTTState(false));
getConnector().sendData(KenwoodTK90RigConstant.setTS590ReadOperationFreq());
}
}
@ -234,18 +223,63 @@ public class TrUSDXRig extends BaseRig {
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) {
Resample resample = new Resample(Resample.ConverterType.SRC_LINEAR, 1, rxSampling, 12000);
try {
byte[] resampled = resample.processCopy(toWaveSamples8To16(rxStreamBuffer.toByteArray()));
rxStreamBuffer.reset();
getConnector().receiveWaveData(resampled);
} finally {
resample.close();
}
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);
// ,48000);
//Log.i(TAG, String.format("wave length: %d", wave.length));
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);
//byte[] pcm8 = resampled;
//byte[] pcm8 = toWaveFloatToPCM8(wave);
Log.i(TAG, String.format("pcm8 length: %d", pcm8.length));
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);
}
}
/*
for (int i = 0; i < pcm8.length; i += 64) {
if (!isPttOn()) {
return;
}
getConnector().sendData(Arrays.copyOfRange(pcm8, i, Math.min(i + 64, pcm8.length)));
//try {
// Thread.sleep(1);
//} catch (InterruptedException e) {
// e.printStackTrace();
//}
}
*/
}
private static byte[] toWaveSamples8To16(byte[] in) {
@ -257,6 +291,37 @@ public class TrUSDXRig extends BaseRig {
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
@ -269,4 +334,18 @@ public class TrUSDXRig extends BaseRig {
},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);
}
}