package com.bg7yoz.ft8cn.rigs; /** * IcomRig是通用的Icom电台控制类。对于wifi模式,实际的控制是通过IComWifiConnector(继承于WifiConnector) * 在IComWifiConnector中,有IComWifiRig具体操作电台 */ import android.util.Log; 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.ft8transmit.GenerateFT8; import com.bg7yoz.ft8cn.icom.IComPacketTypes; import com.bg7yoz.ft8cn.ui.ToastMessage; import java.util.Timer; import java.util.TimerTask; public class IcomRig extends BaseRig { private static final String TAG = "IcomRig"; private final int ctrAddress = 0xE0;//接收地址,默认0xE0;电台回复命令有时也可以是0x00 private byte[] dataBuffer = new byte[0];//数据缓冲区 private int alc = 0; private int swr = 0; private boolean alcMaxAlert = false; private boolean swrAlert = false; private Timer meterTimer;//查询meter的Timer private boolean oldVersion=false;//针对老电台,可能不支持SWR查询 //private boolean isPttOn = false; @Override public void setPTT(boolean on) { super.setPTT(on); //isPttOn = on; alcMaxAlert = false; swrAlert = false; if (on) { //修正连接方式0x03是wlan,01是usb,0x02是usb+mic,确保声音能发送到电台 if (GeneralVariables.connectMode == ConnectMode.NETWORK) { sendCivData(IcomRigConstant.setConnectorDataMode(ctrAddress, getCivAddress(), (byte) 0x03)); } else if (GeneralVariables.connectMode == ConnectMode.USB_CABLE) { sendCivData(IcomRigConstant.setConnectorDataMode(ctrAddress, getCivAddress(), (byte) 0x01)); } else { sendCivData(IcomRigConstant.setConnectorDataMode(ctrAddress, getCivAddress(), (byte) 0x02)); } } if (getConnector() != null) { if (GeneralVariables.connectMode == ConnectMode.NETWORK) { getConnector().setPttOn(on); return; } switch (getControlMode()) { case ControlMode.CAT://以CIV指令 getConnector().setPttOn(IcomRigConstant.setPTTState(ctrAddress, getCivAddress() , on ? IcomRigConstant.PTT_ON : IcomRigConstant.PTT_OFF)); break; //case ControlMode.NETWORK: 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) { //因为担心老的ICOM电台不一定支持USB-D,所以,先做个一USB模式,再进入USB-D模式, // 这样,如果USB-D模式不支持,USB-D的指令就是无效的,电台就停留在USB模式下了 //getConnector().sendData(IcomRigConstant.setOperationMode(ctrAddress // , getCivAddress(), IcomRigConstant.USB));//usb getConnector().sendData(IcomRigConstant.setOperationDataMode(ctrAddress , getCivAddress(), IcomRigConstant.USB));//usb-d } } private void sendCivData(byte[] data) { if (getConnector() != null) { getConnector().sendData(data); } } @Override public void setFreqToRig() { if (getConnector() != null) { getConnector().sendData(IcomRigConstant.setOperationFrequency(ctrAddress , getCivAddress(), getFreq())); } } /** * 查找指令的结尾的位置,如果没找到,值是-1。 * * @param data 数据 * @return 位置 */ private int getCommandEnd(byte[] data) { for (int i = 0; i < data.length; i++) { if (data[i] == (byte) 0xFD) { return i; } } return -1; } /** * 查找指令头,没找到返回-1,找到返回FE FE的第一个位置 * * @param data 数据 * @return 位置 */ private int getCommandHead(byte[] data) { if (data.length < 2) return -1; for (int i = 0; i < data.length - 1; i++) { if (data[i] == (byte) 0xFE && data[i + 1] == (byte) 0xFE) { return i; } } return -1; } @Override public void sendWaveData(Ft8Message message) {//发送音频数据到电台,用于网络方式 if (getConnector() != null) {//把生成的具体音频数据传递到Connector, float[] data = GenerateFT8.generateFt8(message, GeneralVariables.getBaseFrequency() ,12000);//此处icom电台发射音频的采样率是12000 if (data==null){ setPTT(false); return; } getConnector().sendWaveData(data); } } private void analysisCommand(byte[] data) { int headIndex = getCommandHead(data); if (headIndex == -1) {//说明没有指令头 return; } IcomCommand icomCommand; if (headIndex == 0) { icomCommand = IcomCommand.getCommand(ctrAddress, getCivAddress(), data); } else { byte[] temp = new byte[data.length - headIndex]; System.arraycopy(data, headIndex, temp, 0, temp.length); icomCommand = IcomCommand.getCommand(ctrAddress, getCivAddress(), temp); } if (icomCommand == null) { return; } //目前只对频率和模式消息作反应 switch (icomCommand.getCommandID()) { case IcomRigConstant.CMD_SEND_FREQUENCY_DATA://获取到的是频率数据 case IcomRigConstant.CMD_READ_OPERATING_FREQUENCY: //获取频率 //ToastMessage.show(byteToStr(icomCommand.getData(false))); setFreq(icomCommand.getFrequency(false)); break; case IcomRigConstant.CMD_SEND_MODE_DATA://获取到的是模式数据 case IcomRigConstant.CMD_READ_OPERATING_MODE: break; case IcomRigConstant.CMD_READ_METER://读meter//此处的指令,只在网络模式实现,以后可能会在串口方面实现 if (icomCommand.getSubCommand() == IcomRigConstant.CMD_READ_METER_ALC) { alc = IcomRigConstant.twoByteBcdToInt(icomCommand.getData(true)); } if (icomCommand.getSubCommand() == IcomRigConstant.CMD_READ_METER_SWR) { swr = IcomRigConstant.twoByteBcdToInt(icomCommand.getData(true)); } showAlert();//检查meter值是否在告警范围 break; case IcomRigConstant.CMD_CONNECTORS: break; } } private void showAlert() { if (swr >= IcomRigConstant.swr_alert_max) { if (!swrAlert) { swrAlert = true; ToastMessage.show(GeneralVariables.getStringFromResource(R.string.swr_high_alert)); } } else { swrAlert = false; } if (alc > IcomRigConstant.alc_alert_max) {//网络模式下不警告ALC if (!alcMaxAlert) { alcMaxAlert = true; ToastMessage.show(GeneralVariables.getStringFromResource(R.string.alc_high_alert)); } } else { alcMaxAlert = false; } } @Override public void onReceiveData(byte[] data) { //ToastMessage.show(byteToStr(data)); int commandEnd = getCommandEnd(data); if (commandEnd <= -1) {//这是没有指令结尾 byte[] temp = new byte[dataBuffer.length + data.length]; System.arraycopy(dataBuffer, 0, temp, 0, dataBuffer.length); System.arraycopy(data, 0, temp, dataBuffer.length, data.length); dataBuffer = temp; } else { byte[] temp = new byte[dataBuffer.length + commandEnd + 1]; System.arraycopy(dataBuffer, 0, temp, 0, dataBuffer.length); dataBuffer = temp; System.arraycopy(data, 0, dataBuffer, dataBuffer.length - commandEnd - 1, commandEnd + 1); } if (commandEnd != -1) { analysisCommand(dataBuffer); } dataBuffer = new byte[0];//清空缓冲区 if (commandEnd <= -1 || commandEnd < data.length) { byte[] temp = new byte[data.length - commandEnd + 1]; for (int i = 0; i < data.length - commandEnd - 1; i++) { temp[i] = data[commandEnd + i + 1]; } dataBuffer = temp; } } @Override public void readFreqFromRig() { if (getConnector() != null) { getConnector().sendData(IcomRigConstant.setReadFreq(ctrAddress, getCivAddress())); } } @Override public String getName() { return "ICOM series"; } public void startMeterTimer() { meterTimer = new Timer(); meterTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { if (isPttOn() && !oldVersion) {//当Ptt被按下去的时候测量,并且不是老版本的电台 sendCivData(IcomRigConstant.getSWRState(ctrAddress, getCivAddress())); sendCivData(IcomRigConstant.getALCState(ctrAddress, getCivAddress())); } } }, 0, IComPacketTypes.METER_TIMER_PERIOD_MS); } public String getFrequencyStr() { return BaseRigOperation.getFrequencyStr(getFreq()); } public IcomRig(int civAddress,boolean newRig) { Log.d(TAG, "IcomRig: Create."); this.oldVersion = !newRig; setCivAddress(civAddress); startMeterTimer(); } }