package com.multiwii.multiwiiremote; import view.joystick.DualJoystickView; import view.joystick.JoystickView; import com.multiwii.Utilities.Utilities; import com.multiwii.communication.DeviceListActivity; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.util.Log; import android.view.KeyEvent; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; import android.widget.ToggleButton; import static com.multiwii.multiwiiremote.RCSignals.*; public class MainActivity extends BaseActivity { private long requestStartTime; private boolean isReceived = true; private long lastRequestTime = 0; private enum InputMode { ACCELEROMETER, TOUCH } private InputMode inputMode = InputMode.TOUCH; private DualJoystickView dualJoystickView; private ToggleButton auxBtn[] = new ToggleButton[4]; private TextView txtHeader; private TextView txtStatus; private TextView txtUIDebug; private long lastHeadingRefreshTime = 0; private int thisHeading = 0; private int mwcHeading = 0; private int lastValidateHeading =0; private String debugTextTemplate = "%sPhone Heading: %d\nMWC Heading:%d\nDelay: %dms"; private long delayTime = 0; private long [] delayTimeRaw = new long[5]; private boolean isDelayTimeAvailable = false; private int delayTimeIdx = 0; public CheckBox getChkUsePhoneHeading() { return chkUsePhoneHeading; } public void setChkUsePhoneHeading(CheckBox chkUsePhoneHeading) { this.chkUsePhoneHeading = chkUsePhoneHeading; } private CheckBox chkUsePhoneHeading; public RCSignals rc; // private byte timer = 0; // private Camera mCam; MainActivityEvents mEvents; private MainActivityCommunicationHandler mHandler; private final int BLUETOOTH_SEARCH_RETURN = 1; private final int SETTINGS_MODIFY = 2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //KeepScreenOn(app.KeepScreenOn); KeepScreenOn(true); rc = new RCSignals(); // mCam = new Camera((MjpegView) this.findViewById(R.id.webcamView)); mEvents = new MainActivityEvents(this); mHandler = new MainActivityCommunicationHandler(this); txtStatus = (TextView) findViewById(R.id.status); txtHeader = (TextView) findViewById(R.id.throttleView); txtUIDebug = (TextView) findViewById(R.id.debugTxt); for (int x = 0; x < auxBtn.length; x++) auxBtn[x] = (ToggleButton) findViewById(getResources().getIdentifier("aux" + (x + 1) + "Btn", "id", getPackageName())); dualJoystickView = (DualJoystickView) findViewById(R.id.DualJoystickView); chkUsePhoneHeading = (CheckBox) findViewById(R.id.chkUsePhoneHeading); Init(); } private void Init() { app.SetHandler(mHandler); //App class will automatically bind to commMW app.setMainActivity(this); chkUsePhoneHeading.setOnCheckedChangeListener(mEvents.mCheckChangeListener); ((Button) findViewById(R.id.switchModes)).setOnClickListener(mEvents.mClickListener); //joystick.setOnJostickMovedListener(mEvents._listener); dualJoystickView.stickR.setOnJostickMovedListener(mEvents._listener); dualJoystickView.stickL.setOnJostickMovedListener(mEvents._throttleListener); dualJoystickView.stickL.setAutoReturnToCenter(false); dualJoystickView.stickL.setAutoReturnToMid(true); for (int x = 0; x < auxBtn.length; x++) auxBtn[x].setOnClickListener(mEvents.mClickListener); settingsModified(); } public void FrequentTasks() { mHandler.sendEmptyMessage(7); //send RC signal if(app.commMW.Connected) { //Create payload TODO //new cycle begin if an ATTITUDE ACK is received or 300ms passed(package lost) long currentTime = System.currentTimeMillis(); if(app.protocol.isIs_ATTITUDE_received() == true){ app.protocol.setIs_ATTITUDE_received(false); delayTimeRaw[delayTimeIdx++] = app.protocol.attitudeReceivedTime - lastRequestTime; if(delayTimeIdx == delayTimeRaw.length){ delayTimeIdx = 0; isDelayTimeAvailable = true; } if(isDelayTimeAvailable == true){ long sum = 0; for(long i : delayTimeRaw){ sum += i; } delayTime = sum / delayTimeRaw.length; } lastRequestTime = currentTime; app.protocol.SendRequestMSP_ATTITUDE(); mwcHeading = app.protocol.head; } //we consider it as a package lost, resend package else if(currentTime - lastRequestTime > 300){ app.protocol.SendRequestMSP_ATTITUDE(); } app.protocol.SendRequestMSP_SET_RAW_RC(rc.get()); //TODO Check that delay isnt too big from other tasks if (chkUsePhoneHeading.isChecked()){ //refresh heading in every 500 mili seconds if( currentTime - lastHeadingRefreshTime > 500 ){ thisHeading = app.sensors.heading; app.protocol.SendRequestMSP_SET_HEAD(thisHeading); lastHeadingRefreshTime = currentTime; } } //SONG BO ADD BEGIN--------------------------------- //data transmitted from MWC to Phone is processed in ProcessSerialData() in ConnectedThread // while(!app.protocol.is_SET_RAW_RC_received ){ // app.protocol.ProcessSerialData(false); // if (app.protocol.is_SET_HEAD_received){ // lastValidateHeading = thisHeading; // app.protocol.is_SET_HEAD_received = false; // } // delayTime = System.currentTimeMillis() - requestStartTime; // } // app.protocol.is_SET_RAW_RC_received = false; //SONG BO ADD END } app.FrequentTasks(); } public void setStatus(String status) { this.txtStatus.setText(status); app.Status = status; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case BLUETOOTH_SEARCH_RETURN: if (resultCode == Activity.RESULT_OK) { String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); app.protocol.Connect(address, app.BaudRate, app.BluetoothConnectionStartDelay); } break; case SETTINGS_MODIFY: settingsModified(); break; } } private void settingsModified() { rc.ThrottleResolution = app.ThrottleResolution; rc.TrimRoll = app.TrimRoll; rc.TrimPitch = app.TrimPitch; rc.RollPitchLimit = app.RollPitchLimit; if (app.AuxTextChanged) { setAuxbtnTxt(auxBtn[0], app.Aux1Txt); setAuxbtnTxt(auxBtn[1], app.Aux2Txt); setAuxbtnTxt(auxBtn[2], app.Aux3Txt); setAuxbtnTxt(auxBtn[3], app.Aux4Txt); app.AuxTextChanged = false; } setStatus("Ready " + app.comMode.toString()); } private void setAuxbtnTxt(ToggleButton mButton, String text) { mButton.setText(text); mButton.setTextOn(text); mButton.setTextOff(text); } public void Connect() { switch (app.comMode) { case BLUETOOTH: Intent searchBtDevices = new Intent(this, DeviceListActivity.class); startActivityForResult(searchBtDevices, BLUETOOTH_SEARCH_RETURN); break; case WIFI: app.protocol.Connect(app.IpAddress, app.IpPort, app.WifiConnectionStartDelay); break; } } public void UpdateUI() { txtHeader.setText(rc.adjustMode.getValue() + rc.get(rc.adjustMode.getId())); txtUIDebug.setText(app.UIDebug ? String.format(debugTextTemplate, rc.toStringNoThrottle(), app.sensors.heading, mwcHeading, delayTime) : ""); txtStatus.setText(app.Status); } // int requests[] = new int[] { MultirotorData.MSP_DEBUG, // MultirotorData.MSP_ALTITUDE, MultirotorData.MSP_RC }; public void onSensorsStateChangeRotate() { if (inputMode == InputMode.ACCELEROMETER) { float xCoordinate = (float) Utilities.mapCons(-app.sensors.pitch, app.sensors.getMinValue(), app.sensors.getMaxValue(), -dualJoystickView.stickR.getMovementRange()/2, dualJoystickView.stickR.getMovementRange()/2); float yCoordinate = (float) Utilities.mapCons(-app.sensors.roll, app.sensors.getMinValue(), app.sensors.getMaxValue(), -dualJoystickView.stickR.getMovementRange()/2, dualJoystickView.stickR.getMovementRange()/2); dualJoystickView.stickR.setCoordinates(xCoordinate, yCoordinate); } } public void aux1_Click(View v) { // Replaced with When Throttle >= 1030 rc.set(AUX1, ((ToggleButton) v).isChecked()); } public void aux2_Click(View v) { rc.set(AUX2, ((ToggleButton) v).isChecked()); } public void aux3_Click(View v) { rc.set(AUX3, ((ToggleButton) v).isChecked()); } public void aux4_Click(View v) { rc.set(AUX4, ((ToggleButton) v).isChecked()); } @Override protected void onStop() { super.onStop(); app.stop(); } // ///////////////////Menu/////////////////// @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.connect: Connect(); break; case R.id.accelOn: if (!app.sensors.isRotateSensorSupported()) Utilities.showToast("Sorry, your device does not have an accelerometer", this); else { switch (inputMode) { case TOUCH: inputMode = InputMode.ACCELEROMETER; break; case ACCELEROMETER: inputMode = InputMode.TOUCH; dualJoystickView.stickR.returnHandleToCenter(); break; } } break; case R.id.menu_settings: if (rc.isFlying()) { Utilities.showToast( "Set throttle under 1100 to access settings", this); } else { this.startActivityForResult(new Intent(this, Settings.class), SETTINGS_MODIFY); } break; } return super.onContextItemSelected(item); } // /////////////////////////////End Menu///////////////////////////// @Override public boolean dispatchKeyEvent(KeyEvent event) { if(app.PreventExitWhenFlying && rc.isFlying() && (event.getKeyCode() == KeyEvent.KEYCODE_BACK || event.getKeyCode() == KeyEvent.KEYCODE_APP_SWITCH || event.getKeyCode() == KeyEvent.KEYCODE_HOME)) { Utilities.showToast("Detected flying. Please put throttle under 1100.", this); return true; } if (event.getAction() == KeyEvent.ACTION_DOWN) switch (event.getKeyCode()) { case KeyEvent.KEYCODE_VOLUME_UP: rc.adjustRcValue(-1); return true; case KeyEvent.KEYCODE_VOLUME_DOWN: rc.adjustRcValue(1); return true; case KeyEvent.KEYCODE_SEARCH: app.setManualModeOn(!app.getManualMode()); return true; } return super.dispatchKeyEvent(event); } }