diff --git a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java index 34129322e..8d269c7d1 100644 --- a/app/src/main/java/io/pslab/activity/DataLoggerActivity.java +++ b/app/src/main/java/io/pslab/activity/DataLoggerActivity.java @@ -35,6 +35,7 @@ import io.pslab.models.BaroData; import io.pslab.models.CompassData; import io.pslab.models.GyroData; +import io.pslab.models.LogicAnalyzerData; import io.pslab.models.LuxData; import io.pslab.models.OscilloscopeData; import io.pslab.models.PowerSourceData; @@ -120,6 +121,9 @@ protected void onCreate(Bundle savedInstanceState) { case "Power Source": categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getResources().getString(R.string.power_source)); break; + case "Logic Analyzer": + categoryData = LocalDataLog.with().getTypeOfSensorBlocks(getResources().getString(R.string.logical_analyzer)); + break; default: categoryData = LocalDataLog.with().getAllSensorBlocks(); getSupportActionBar().setTitle(getString(R.string.logged_data)); @@ -279,6 +283,9 @@ private RealmObject getObject(String objectType, String[] data, long time, long case "Power Source": returnObject = new PowerSourceData(time, block, Float.valueOf(data[2]), Float.valueOf(data[3]), Float.valueOf(data[4]), Float.valueOf(data[5]), Float.valueOf(data[6]), Float.valueOf(data[7])); break; + case "Logic Analyzer": + returnObject = new LogicAnalyzerData(time, block, data[2], Integer.valueOf(data[3]), data[4], data[5], Float.valueOf(data[6]), Float.valueOf(data[7])); + break; default: returnObject = null; break; diff --git a/app/src/main/java/io/pslab/activity/LogicalAnalyzerActivity.java b/app/src/main/java/io/pslab/activity/LogicalAnalyzerActivity.java index d5152d553..31efdc317 100644 --- a/app/src/main/java/io/pslab/activity/LogicalAnalyzerActivity.java +++ b/app/src/main/java/io/pslab/activity/LogicalAnalyzerActivity.java @@ -9,7 +9,6 @@ import android.support.design.widget.BottomSheetBehavior; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; -import android.support.v7.widget.TooltipCompat; import android.view.GestureDetector; import android.view.MenuItem; import android.view.MotionEvent; @@ -23,12 +22,15 @@ import io.pslab.R; import io.pslab.communication.ScienceLab; import io.pslab.fragment.LALogicLinesFragment; +import io.pslab.models.LogicAnalyzerData; +import io.pslab.others.LocalDataLog; import io.pslab.others.MathUtils; import io.pslab.others.ScienceLabCommon; import butterknife.BindView; import butterknife.ButterKnife; import io.pslab.others.SwipeGestureDetector; +import io.realm.RealmResults; /** * Created by viveksb007 on 10/5/17. @@ -56,6 +58,11 @@ public class LogicalAnalyzerActivity extends AppCompatActivity { private GestureDetector gestureDetector; private TextView showText; private boolean btnLongpressed; + private final String KEY_LOG = "has_log"; + private final String DATA_BLOCK = "data_block"; + public boolean isPlayback = false; + public RealmResults recordedLAData; + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -124,6 +131,12 @@ public boolean onTouch(View v, MotionEvent event) { return true; } }); + + if (getIntent().getExtras() != null && getIntent().getExtras().getBoolean(KEY_LOG)) { + recordedLAData = LocalDataLog.with() + .getBlockOfLARecords(getIntent().getExtras().getLong(DATA_BLOCK)); + isPlayback = true; + } } @Override diff --git a/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java b/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java index 64bd68402..bf316c5aa 100644 --- a/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java +++ b/app/src/main/java/io/pslab/adapters/SensorLoggerListAdapter.java @@ -27,6 +27,7 @@ import io.pslab.activity.BarometerActivity; import io.pslab.activity.CompassActivity; import io.pslab.activity.GyroscopeActivity; +import io.pslab.activity.LogicalAnalyzerActivity; import io.pslab.activity.LuxMeterActivity; import io.pslab.activity.MapsActivity; import io.pslab.activity.MultimeterActivity; @@ -39,6 +40,7 @@ import io.pslab.models.BaroData; import io.pslab.models.GyroData; import io.pslab.models.CompassData; +import io.pslab.models.LogicAnalyzerData; import io.pslab.models.LuxData; import io.pslab.models.MultimeterData; import io.pslab.models.OscilloscopeData; @@ -125,6 +127,10 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { holder.sensor.setText(R.string.multimeter); holder.tileIcon.setImageDrawable(context.getResources().getDrawable(R.drawable.tile_icon_multimeter)); break; + case PSLabSensor.LOGIC_ANALYZER: + holder.sensor.setText(R.string.logical_analyzer); + holder.tileIcon.setImageDrawable(context.getResources().getDrawable(R.drawable.tile_icon_logic_analyzer)); + break; default: break; } @@ -205,6 +211,11 @@ private void handleCardViewClick(SensorDataBlock block) { multimeter.putExtra(KEY_LOG, true); multimeter.putExtra(DATA_BLOCK, block.getBlock()); context.startActivity(multimeter); + } else if (block.getSensorType().equalsIgnoreCase(context.getResources().getString(R.string.logical_analyzer))) { + Intent laIntent = new Intent(context, LogicalAnalyzerActivity.class); + laIntent.putExtra(KEY_LOG, true); + laIntent.putExtra(DATA_BLOCK, block.getBlock()); + context.startActivity(laIntent); } } @@ -244,6 +255,8 @@ public void onClick(DialogInterface dialog, int whichButton) { LocalDataLog.with().clearBlockOfPowerRecords(block.getBlock()); } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.MULTIMETER)) { LocalDataLog.with().clearBlockOfMultimeterRecords(block.getBlock()); + } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.LOGIC_ANALYZER)) { + LocalDataLog.with().clearBlockOfLARecords(block.getBlock()); } LocalDataLog.with().clearSensorBlock(block.getBlock()); dialog.dismiss(); @@ -461,6 +474,25 @@ private void populateMapData(SensorDataBlock block) { } } setMapDataToIntent(array); + } else if (block.getSensorType().equalsIgnoreCase(PSLabSensor.LOGIC_ANALYZER)) { + RealmResults data = LocalDataLog.with().getBlockOfLARecords(block.getBlock()); + JSONArray array = new JSONArray(); + for (LogicAnalyzerData d : data) { + try { + JSONObject i = new JSONObject(); + i.put("date", CSVLogger.FILE_NAME_FORMAT.format(d.getTime())); + i.put("channel", d.getChannel()); + i.put("channel_mode", d.getChannelMode()); + i.put("xaxis", d.getDataX()); + i.put("yaxis", d.getDataY()); + i.put("lat", d.getLat()); + i.put("lon", d.getLon()); + if (d.getLat() != 0.0 && d.getLon() != 0.0) array.put(i); + } catch (JSONException e) { + e.printStackTrace(); + } + } + setMapDataToIntent(array); } } diff --git a/app/src/main/java/io/pslab/fragment/LALogicLinesFragment.java b/app/src/main/java/io/pslab/fragment/LALogicLinesFragment.java index f4c06a8f8..a59656ac5 100644 --- a/app/src/main/java/io/pslab/fragment/LALogicLinesFragment.java +++ b/app/src/main/java/io/pslab/fragment/LALogicLinesFragment.java @@ -1,22 +1,21 @@ package io.pslab.fragment; import android.app.Activity; -import android.content.SharedPreferences; +import android.content.Context; +import android.content.Intent; import android.graphics.Color; +import android.location.Location; +import android.location.LocationManager; import android.os.AsyncTask; import android.os.Bundle; -import android.os.Handler; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.util.DisplayMetrics; import android.util.Log; -import android.view.GestureDetector; import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -40,25 +39,32 @@ import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import io.pslab.DataFormatter; -import io.pslab.R; -import io.pslab.activity.LogicalAnalyzerActivity; -import io.pslab.communication.ScienceLab; -import io.pslab.communication.digitalChannel.DigitalChannel; -import io.pslab.others.LogicAnalyzerAxisFormatter; -import io.pslab.others.MathUtils; -import io.pslab.others.ScienceLabCommon; -import io.pslab.others.SwipeGestureDetector; - import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import butterknife.ButterKnife; import in.goodiebag.carouselpicker.CarouselPicker; - -import static android.content.Context.MODE_PRIVATE; +import io.pslab.DataFormatter; +import io.pslab.R; +import io.pslab.activity.DataLoggerActivity; +import io.pslab.activity.LogicalAnalyzerActivity; +import io.pslab.communication.ScienceLab; +import io.pslab.communication.digitalChannel.DigitalChannel; +import io.pslab.models.LogicAnalyzerData; +import io.pslab.models.SensorDataBlock; +import io.pslab.others.CSVLogger; +import io.pslab.others.CustomSnackBar; +import io.pslab.others.GPSLogger; +import io.pslab.others.LocalDataLog; +import io.pslab.others.LogicAnalyzerAxisFormatter; +import io.pslab.others.ScienceLabCommon; +import io.realm.Realm; +import io.realm.RealmObject; +import io.realm.RealmResults; /** * Created by viveksb007 on 9/6/17. @@ -102,6 +108,18 @@ public class LALogicLinesFragment extends Fragment { private TextView tvTimeUnit, xCoordinateText; private ImageView ledImageView; private Runnable logicAnalysis; + private Realm realm; + private ImageView recordButton; + private GPSLogger gpsLogger; + private CSVLogger csvLogger; + private ArrayList recordXAxis; + private ArrayList recordYAxis; + private ArrayList recordChannelMode; + private String[] channels = new String[]{"ID1", "ID2", "ID3", "ID4"}; + private HashMap channelMap; + private String csvHeader = "Timestamp,DateTime,Channel,ChannelMode,xData,yData,lat,lon"; + private ArrayList channelSelectSpinners; + private ArrayList edgeSelectSpinners; public static LALogicLinesFragment newInstance(Activity activity) { LALogicLinesFragment laLogicLinesFragment = new LALogicLinesFragment(); @@ -114,7 +132,14 @@ public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ButterKnife.bind(getActivity()); scienceLab = ScienceLabCommon.scienceLab; - + realm = LocalDataLog.with().getRealm(); + gpsLogger = new GPSLogger(getContext(), (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE)); + csvLogger = new CSVLogger(getString(R.string.logical_analyzer)); + recordXAxis = new ArrayList<>(); + recordYAxis = new ArrayList<>(); + recordChannelMode = new ArrayList<>(); + channelSelectSpinners = new ArrayList<>(); + edgeSelectSpinners = new ArrayList<>(); logicAnalysis = new Runnable() { @Override public void run() { @@ -149,7 +174,6 @@ public void run() { @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View v = inflater.inflate(R.layout.logic_analyzer_logic_lines, container, false); - // LED Indicator ledImageView = v.findViewById(R.id.imageView_led_la); @@ -157,6 +181,52 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, tvTimeUnit = v.findViewById(R.id.la_tv_time_unit); tvTimeUnit.setText(getString(R.string.time_unit_la)); + //recordButton + + recordButton = v.findViewById(R.id.la_record_button); + recordButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + long block = System.currentTimeMillis(); + double lat; + double lon; + if (gpsLogger.isGPSEnabled()) { + Location location = gpsLogger.getDeviceLocation(); + if (location != null) { + lat = location.getLatitude(); + lon = location.getLongitude(); + } else { + lat = 0.0; + lon = 0.0; + } + } else { + lat = 0.0; + lon = 0.0; + } + csvLogger.prepareLogFile(); + csvLogger.writeMetaData(getContext().getResources().getString(R.string.logical_analyzer)); + csvLogger.writeCSVFile(csvHeader); + recordSensorDataBlockID(new SensorDataBlock(block, getResources().getString(R.string.logical_analyzer))); + long timestamp = System.currentTimeMillis(); + String timeData = timestamp + "," + CSVLogger.FILE_NAME_FORMAT.format(new Date(timestamp)); + String locationData = lat + "," + lon; + for (int i = 0; i < recordXAxis.size(); i++) { + recordSensorData(new LogicAnalyzerData(timestamp + i, block, channels[i], recordChannelMode.get(i), recordXAxis.get(i), recordYAxis.get(i), lat, lon)); + String data = timeData + "," + channels[i] + "," + recordChannelMode.get(i) + "," + recordXAxis.get(i) + "," + recordYAxis.get(i) + "," + locationData; + csvLogger.writeCSVFile(data); + } + CustomSnackBar.showSnackBar(v, + getString(R.string.csv_store_text) + " " + csvLogger.getCurrentFilePath() + , getString(R.string.open), new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getContext(), DataLoggerActivity.class); + intent.putExtra(DataLoggerActivity.CALLER_ACTIVITY, getResources().getString(R.string.logical_analyzer)); + startActivity(intent); + } + }, Snackbar.LENGTH_SHORT); + } + }); // Carousel View carouselPicker = v.findViewById(R.id.carouselPicker); llChannel1 = v.findViewById(R.id.ll_chart_channel_1); @@ -177,7 +247,20 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, edgeSelectSpinner4 = v.findViewById(R.id.edge_select_spinner_4); analyze_button = v.findViewById(R.id.analyze_button); channelMode = 1; - + channelSelectSpinners.add(channelSelectSpinner1); + channelSelectSpinners.add(channelSelectSpinner2); + channelSelectSpinners.add(channelSelectSpinner3); + channelSelectSpinners.add(channelSelectSpinner4); + + edgeSelectSpinners.add(edgeSelectSpinner1); + edgeSelectSpinners.add(edgeSelectSpinner2); + edgeSelectSpinners.add(edgeSelectSpinner3); + edgeSelectSpinners.add(edgeSelectSpinner4); + channelMap = new HashMap<>(); + channelMap.put(channels[0], 0); + channelMap.put(channels[1], 1); + channelMap.put(channels[2], 2); + channelMap.put(channels[3], 3); // Axis Indicator xCoordinateText = v.findViewById(R.id.x_coordinate_text); xCoordinateText.setText("Time: 0.0 mS"); @@ -200,9 +283,67 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, setCarouselPicker(); setAdapters(); + LogicalAnalyzerActivity laActivity = (LogicalAnalyzerActivity)getActivity(); + if (laActivity.isPlayback) { + setPlayBackData(laActivity.recordedLAData); + } return v; } + private void setPlayBackData(RealmResults data) { + analyze_button.setVisibility(View.GONE); + recordButton.setVisibility(View.GONE); + currentChannel = 0; + setViewVisibility(data.size() - 1); + channelNames.clear(); + disableSpinners(); + carouselPicker.setCurrentItem(data.size() -1); + for (int i = 0; i < data.size(); i ++) { + LogicAnalyzerData laData = data.get(i); + channelNames.add(laData.getChannel()); + edgeSelectSpinners.get(i).setSelection(laData.getChannelMode() - 1); + channelSelectSpinners.get(i).setSelection(channelMap.get(laData.getChannel())); + String[] xPoints = laData.getDataX().split(" "); + String[] yPoints = laData.getDataY().split(" "); + int n = Math.min(xPoints.length, yPoints.length); + double[] xaxis = new double[n]; + double[] yaxis = new double[n]; + for (int j = 0; j < n; j ++) { + xaxis[j] = Double.valueOf(xPoints[j]); + yaxis[j] = Double.valueOf(yPoints[j]); + } + switch (laData.getChannelMode()) { + case 1: + singleChannelEveryEdge(xaxis, yaxis); + break; + case 4: + singleChannelFourthRisingEdge(xaxis); + break; + case 3: + singleChannelRisingEdges(xaxis, yaxis); + break; + case 2: + singleChannelFallingEdges(xaxis, yaxis); + break; + default: + singleChannelOtherEdges(xaxis, yaxis); + break; + } + currentChannel ++; + } + logicLinesChart.setData(new LineData(dataSets)); + logicLinesChart.invalidate(); + + YAxis left = logicLinesChart.getAxisLeft(); + left.setValueFormatter(new LogicAnalyzerAxisFormatter(channelNames)); + left.setTextColor(Color.WHITE); + left.setGranularity(1f); + left.setTextSize(12f); + logicLinesChart.getAxisRight().setDrawLabels(false); + logicLinesChart.getDescription().setEnabled(false); + logicLinesChart.setScaleYEnabled(false); + } + @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); @@ -222,66 +363,7 @@ public void onPageSelected(int position) { @Override public void onPageScrollStateChanged(int state) { if (state == 0) { - switch (carouselPicker.getCurrentItem()) { - case 0: - channelMode = 1; - setAdapters(); - llChannel1.setVisibility(View.VISIBLE); - llChannel2.setVisibility(View.GONE); - llChannel3.setVisibility(View.GONE); - llChannel4.setVisibility(View.GONE); - channelSelectSpinner1.setEnabled(true); - break; - case 1: - channelMode = 2; - setAdapterForTwoChannelMode(); - llChannel1.setVisibility(View.VISIBLE); - llChannel2.setVisibility(View.VISIBLE); - llChannel3.setVisibility(View.GONE); - llChannel4.setVisibility(View.GONE); - channelSelectSpinner1.setEnabled(true); - channelSelectSpinner2.setEnabled(true); - break; - case 2: - channelMode = 3; - setAdapters(); - llChannel1.setVisibility(View.VISIBLE); - llChannel2.setVisibility(View.VISIBLE); - llChannel3.setVisibility(View.VISIBLE); - llChannel4.setVisibility(View.GONE); - channelSelectSpinner1.setSelection(0); - channelSelectSpinner2.setSelection(1); - channelSelectSpinner3.setSelection(2); - channelSelectSpinner1.setEnabled(false); - channelSelectSpinner2.setEnabled(false); - channelSelectSpinner3.setEnabled(false); - break; - case 3: - channelMode = 4; - setAdapters(); - llChannel1.setVisibility(View.VISIBLE); - llChannel2.setVisibility(View.VISIBLE); - llChannel3.setVisibility(View.VISIBLE); - llChannel4.setVisibility(View.VISIBLE); - channelSelectSpinner1.setSelection(0); - channelSelectSpinner2.setSelection(1); - channelSelectSpinner3.setSelection(2); - channelSelectSpinner4.setSelection(3); - channelSelectSpinner1.setEnabled(false); - channelSelectSpinner2.setEnabled(false); - channelSelectSpinner3.setEnabled(false); - channelSelectSpinner4.setEnabled(false); - break; - default: - channelMode = 1; - setAdapters(); - llChannel1.setVisibility(View.VISIBLE); - llChannel2.setVisibility(View.GONE); - llChannel3.setVisibility(View.GONE); - llChannel4.setVisibility(View.GONE); - channelSelectSpinner1.setEnabled(true); - break; - } + setViewVisibility(carouselPicker.getCurrentItem()); } } }); @@ -464,6 +546,80 @@ public void onNothingSelected() { }); } + private void disableSpinners() { + channelSelectSpinner1.setEnabled(false); + channelSelectSpinner2.setEnabled(false); + channelSelectSpinner3.setEnabled(false); + channelSelectSpinner4.setEnabled(false); + edgeSelectSpinner1.setEnabled(false); + edgeSelectSpinner2.setEnabled(false); + edgeSelectSpinner3.setEnabled(false); + edgeSelectSpinner4.setEnabled(false); + carouselPicker.setEnabled(false); + } + + private void setViewVisibility(int mode) { + switch (mode) { + case 0: + channelMode = 1; + setAdapters(); + llChannel1.setVisibility(View.VISIBLE); + llChannel2.setVisibility(View.GONE); + llChannel3.setVisibility(View.GONE); + llChannel4.setVisibility(View.GONE); + channelSelectSpinner1.setEnabled(true); + break; + case 1: + channelMode = 2; + setAdapterForTwoChannelMode(); + llChannel1.setVisibility(View.VISIBLE); + llChannel2.setVisibility(View.VISIBLE); + llChannel3.setVisibility(View.GONE); + llChannel4.setVisibility(View.GONE); + channelSelectSpinner1.setEnabled(true); + channelSelectSpinner2.setEnabled(true); + break; + case 2: + channelMode = 3; + setAdapters(); + llChannel1.setVisibility(View.VISIBLE); + llChannel2.setVisibility(View.VISIBLE); + llChannel3.setVisibility(View.VISIBLE); + llChannel4.setVisibility(View.GONE); + channelSelectSpinner1.setSelection(0); + channelSelectSpinner2.setSelection(1); + channelSelectSpinner3.setSelection(2); + channelSelectSpinner1.setEnabled(true); + channelSelectSpinner2.setEnabled(true); + channelSelectSpinner3.setEnabled(true); + break; + case 3: + channelMode = 4; + setAdapters(); + llChannel1.setVisibility(View.VISIBLE); + llChannel2.setVisibility(View.VISIBLE); + llChannel3.setVisibility(View.VISIBLE); + llChannel4.setVisibility(View.VISIBLE); + channelSelectSpinner1.setSelection(0); + channelSelectSpinner2.setSelection(1); + channelSelectSpinner3.setSelection(2); + channelSelectSpinner4.setSelection(3); + channelSelectSpinner1.setEnabled(true); + channelSelectSpinner2.setEnabled(true); + channelSelectSpinner3.setEnabled(true); + channelSelectSpinner4.setEnabled(true); + break; + default: + channelMode = 1; + setAdapters(); + llChannel1.setVisibility(View.VISIBLE); + llChannel2.setVisibility(View.GONE); + llChannel3.setVisibility(View.GONE); + llChannel4.setVisibility(View.GONE); + channelSelectSpinner1.setEnabled(true); + break; + } + } /** * Plots every edge of a digital pulse for one channel at a time * @@ -655,8 +811,8 @@ private void setAdapterForTwoChannelMode() { final String[] channels = getResources().getStringArray(R.array.channel_choices); final String[] edges = getResources().getStringArray(R.array.edge_choices); - final List channel_one_list = new ArrayList<>( Arrays.asList(channels)); - final List channel_two_list = new ArrayList<>( Arrays.asList(channels)); + final List channel_one_list = new ArrayList<>(Arrays.asList(channels)); + final List channel_two_list = new ArrayList<>(Arrays.asList(channels)); final ArrayAdapter channel_one_adapter = new ArrayAdapter<>(getContext(), R.layout.modified_spinner_dropdown_list, channel_one_list); final ArrayAdapter channel_two_adapter = new ArrayAdapter<>(getContext(), R.layout.modified_spinner_dropdown_list, channel_two_list); @@ -673,8 +829,8 @@ private void setAdapterForTwoChannelMode() { public void onItemSelected(AdapterView parent, View view, int position, long id) { String selection = channelSelectSpinner1.getItemAtPosition(position).toString(); channel_two_list.clear(); - for(int i = 0; i < channels.length; i++) { - if(!channels[i].equals(selection)) { + for (int i = 0; i < channels.length; i++) { + if (!channels[i].equals(selection)) { channel_two_list.add(channels[i]); } } @@ -692,8 +848,8 @@ public void onNothingSelected(AdapterView parent) { public void onItemSelected(AdapterView parent, View view, int position, long id) { String selection = channelSelectSpinner2.getItemAtPosition(position).toString(); channel_one_list.clear(); - for(int i = 0; i < channels.length; i++) { - if(!channels[i].equals(selection)) { + for (int i = 0; i < channels.length; i++) { + if (!channels[i].equals(selection)) { channel_one_list.add(channels[i]); } } @@ -756,6 +912,7 @@ public void onStop() { /** * Used to delay a thread by some given time in milliseconds + * * @param delay Time to delay in milliseconds */ @@ -767,6 +924,32 @@ public void delayThread(long delay) { } } + private void storeAxisValues(double[] xaxis, double[] yaxis, int mode) { + StringBuilder stringBuilder1 = new StringBuilder(); + StringBuilder stringBuilder2 = new StringBuilder(); + for (int i = 0; i < xaxis.length; i++) { + stringBuilder1.append(DataFormatter.formatDouble(xaxis[i], DataFormatter.LOW_PRECISION_FORMAT)); + stringBuilder2.append(DataFormatter.formatDouble(yaxis[i], DataFormatter.LOW_PRECISION_FORMAT)); + stringBuilder1.append(" "); + stringBuilder2.append(" "); + } + recordXAxis.add(stringBuilder1.toString()); + recordYAxis.add(stringBuilder2.toString()); + recordChannelMode.add(mode); + } + + public void recordSensorDataBlockID(SensorDataBlock block) { + realm.beginTransaction(); + realm.copyToRealm(block); + realm.commitTransaction(); + } + + public void recordSensorData(RealmObject sensorData) { + realm.beginTransaction(); + realm.copyToRealm((LogicAnalyzerData) sensorData); + realm.commitTransaction(); + } + private class CaptureOne extends AsyncTask { private String edgeOption = ""; private boolean holder; @@ -774,6 +957,8 @@ private class CaptureOne extends AsyncTask { @Override protected Void doInBackground(String... params) { try { + channels[0] = params[0]; + int channelNumber = scienceLab.calculateDigitalChannel(params[0]); digitalChannel = scienceLab.getDigitalChannel(channelNumber); edgeOption = params[1]; @@ -830,6 +1015,10 @@ protected void onPostExecute(Void aVoid) { Log.v("x Axis", stringBuilder1.toString()); Log.v("y Axis", stringBuilder2.toString()); + recordXAxis.clear(); + recordXAxis.add(stringBuilder1.toString()); + recordYAxis.add(stringBuilder2.toString()); + recordChannelMode.add(digitalChannel.mode); // Plot the fetched data switch (edgeOption) { case "EVERY EDGE": @@ -886,6 +1075,9 @@ private class CaptureTwo extends AsyncTask, ArrayList, @Override protected final Void doInBackground(ArrayList... arrayLists) { try { + channels[0] = arrayLists[0].get(0); + channels[1] = arrayLists[0].get(1); + int channelNumber1 = scienceLab.calculateDigitalChannel(arrayLists[0].get(0)); int channelNumber2 = scienceLab.calculateDigitalChannel(arrayLists[0].get(1)); @@ -951,8 +1143,12 @@ protected void onPostExecute(Void aVoid) { yaxis.add(digitalChannelArray.get(0).getYAxis()); yaxis.add(digitalChannelArray.get(1).getYAxis()); + recordXAxis.clear(); + recordYAxis.clear(); + recordChannelMode.clear(); // Plot the fetched data for (int i = 0; i < channelMode; i++) { + storeAxisValues(xaxis.get(i), yaxis.get(i), digitalChannelArray.get(i).mode); switch (edgeOption[i]) { case "EVERY EDGE": singleChannelEveryEdge(xaxis.get(i), yaxis.get(i)); @@ -1009,6 +1205,10 @@ private class CaptureThree extends AsyncTask, ArrayList... arrayLists) { try { + channels[0] = arrayLists[0].get(0); + channels[1] = arrayLists[0].get(1); + channels[2] = arrayLists[0].get(2); + int channelNumber1 = scienceLab.calculateDigitalChannel(arrayLists[0].get(0)); int channelNumber2 = scienceLab.calculateDigitalChannel(arrayLists[0].get(1)); int channelNumber3 = scienceLab.calculateDigitalChannel(arrayLists[0].get(2)); @@ -1081,8 +1281,12 @@ protected void onPostExecute(Void aVoid) { yaxis.add(digitalChannelArray.get(1).getYAxis()); yaxis.add(digitalChannelArray.get(2).getYAxis()); + recordXAxis.clear(); + recordYAxis.clear(); + recordChannelMode.clear(); // Plot the fetched data for (int i = 0; i < channelMode; i++) { + storeAxisValues(xaxis.get(i), yaxis.get(i), digitalChannelArray.get(i).mode); switch (edgeOption[i]) { case "EVERY EDGE": singleChannelEveryEdge(xaxis.get(i), yaxis.get(i)); @@ -1138,6 +1342,11 @@ private class CaptureFour extends AsyncTask, ArrayList @Override protected Void doInBackground(ArrayList... arrayLists) { try { + channels[0] = arrayLists[0].get(0); + channels[1] = arrayLists[0].get(1); + channels[2] = arrayLists[0].get(2); + channels[3] = arrayLists[0].get(3); + int channelNumber1 = scienceLab.calculateDigitalChannel(arrayLists[0].get(0)); int channelNumber2 = scienceLab.calculateDigitalChannel(arrayLists[0].get(1)); int channelNumber3 = scienceLab.calculateDigitalChannel(arrayLists[0].get(2)); @@ -1221,8 +1430,12 @@ protected void onPostExecute(Void aVoid) { yaxis.add(digitalChannelArray.get(2).getYAxis()); yaxis.add(digitalChannelArray.get(3).getYAxis()); + recordXAxis.clear(); + recordYAxis.clear(); + recordChannelMode.clear(); // Plot the fetched data for (int i = 0; i < channelMode; i++) { + storeAxisValues(xaxis.get(i), yaxis.get(i), digitalChannelArray.get(i).mode); switch (edgeOption[i]) { case "EVERY EDGE": singleChannelEveryEdge(xaxis.get(i), yaxis.get(i)); diff --git a/app/src/main/java/io/pslab/interfaces/sensorloggers/LogicAnalyzerRecordables.java b/app/src/main/java/io/pslab/interfaces/sensorloggers/LogicAnalyzerRecordables.java new file mode 100644 index 000000000..266e68af1 --- /dev/null +++ b/app/src/main/java/io/pslab/interfaces/sensorloggers/LogicAnalyzerRecordables.java @@ -0,0 +1,12 @@ +package io.pslab.interfaces.sensorloggers; + +import io.pslab.models.LogicAnalyzerData; +import io.realm.RealmResults; + +public interface LogicAnalyzerRecordables { + LogicAnalyzerData getLAData(long timeStamp); + void clearAllLARecords(); + void clearBlockOfLARecords(long block); + RealmResults getAllLARecords(); + RealmResults getBlockOfLARecords(long block); +} diff --git a/app/src/main/java/io/pslab/models/LogicAnalyzerData.java b/app/src/main/java/io/pslab/models/LogicAnalyzerData.java new file mode 100644 index 000000000..7f00bdf11 --- /dev/null +++ b/app/src/main/java/io/pslab/models/LogicAnalyzerData.java @@ -0,0 +1,95 @@ +package io.pslab.models; + +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; + +public class LogicAnalyzerData extends RealmObject { + @PrimaryKey + private long time; + private long block; + private String dataX, dataY, channel; + private double lat, lon; + private int channelMode; + + public LogicAnalyzerData() {/**/} + + public LogicAnalyzerData(long time, long block, String channel, int channelMode, String dataX, String dataY, double lat, double lon) { + this.time = time; + this.block = block; + this.channel = channel; + this.channelMode = channelMode; + this.dataX = dataX; + this.dataY = dataY; + this.lat = lat; + this.lon = lon; + } + + public long getBlock() { + return block; + } + + public void setBlock(long block) { + this.block = block; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public String getChannel() { + return channel; + } + + public void setChannel(String channel) { + this.channel = channel; + } + + public int getChannelMode() { + return channelMode; + } + + public void setChannelMode(int channelMode) { + this.channelMode = channelMode; + } + + public String getDataY() { + return dataY; + } + + public void setDataY(String dataY) { + this.dataY = dataY; + } + + public String getDataX() { + return dataX; + } + + public void setDataX(String dataX) { + this.dataX = dataX; + } + + public double getLon() { + return lon; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public double getLat() { + return lat; + } + + public void setLat(double lat) { + this.lat = lat; + } + + @Override + public String toString() { + return "Block - " + block + ", Time - " + time + ", Channel - " + channel + ", ChannelMode - " + channelMode + ", dataX - " + dataX + ", dataY - " + dataY + ", Lat - " + lat + ", Lon - " + lon; + } +} diff --git a/app/src/main/java/io/pslab/models/PSLabSensor.java b/app/src/main/java/io/pslab/models/PSLabSensor.java index 12def913c..6bf1f89a3 100644 --- a/app/src/main/java/io/pslab/models/PSLabSensor.java +++ b/app/src/main/java/io/pslab/models/PSLabSensor.java @@ -111,6 +111,7 @@ public abstract class PSLabSensor extends AppCompatActivity { public static final String OSCILLOSCOPE = "Oscilloscope"; public static final String POWER_SOURCE = "Power Source"; public static final String MULTIMETER = "Multimeter"; + public static final String LOGIC_ANALYZER = "Logic Analyzer"; @BindView(R.id.sensor_toolbar) Toolbar sensorToolBar; diff --git a/app/src/main/java/io/pslab/others/LocalDataLog.java b/app/src/main/java/io/pslab/others/LocalDataLog.java index 90929b6c0..19745dbb1 100644 --- a/app/src/main/java/io/pslab/others/LocalDataLog.java +++ b/app/src/main/java/io/pslab/others/LocalDataLog.java @@ -4,6 +4,7 @@ import io.pslab.interfaces.sensorloggers.BaroMeterRecordables; import io.pslab.interfaces.sensorloggers.CompassRecordables; import io.pslab.interfaces.sensorloggers.GyroscopeRecordables; +import io.pslab.interfaces.sensorloggers.LogicAnalyzerRecordables; import io.pslab.interfaces.sensorloggers.LuxMeterRecordables; import io.pslab.interfaces.sensorloggers.MultimeterRecordables; import io.pslab.interfaces.sensorloggers.OscilloscopeRecordables; @@ -16,6 +17,7 @@ import io.pslab.models.BaroData; import io.pslab.models.CompassData; import io.pslab.models.GyroData; +import io.pslab.models.LogicAnalyzerData; import io.pslab.models.LuxData; import io.pslab.models.MultimeterData; import io.pslab.models.OscilloscopeData; @@ -32,7 +34,7 @@ * Created by Padmal on 11/5/18. */ -public class LocalDataLog implements LuxMeterRecordables, BaroMeterRecordables, SensorRecordables, CompassRecordables, AccelerometerRecordables, GyroscopeRecordables, ThermometerRecordables, ServoRecordables, WaveGeneratorRecordables, OscilloscopeRecordables, PowerSourceRecordables, MultimeterRecordables { +public class LocalDataLog implements LuxMeterRecordables, BaroMeterRecordables, SensorRecordables, CompassRecordables, AccelerometerRecordables, GyroscopeRecordables, ThermometerRecordables, ServoRecordables, WaveGeneratorRecordables, OscilloscopeRecordables, PowerSourceRecordables, MultimeterRecordables, LogicAnalyzerRecordables { private static LocalDataLog instance; private final Realm realm; @@ -499,4 +501,42 @@ public RealmResults getBlockOfMultimeterRecords(long block) { .equalTo("block", block) .findAll(); } + + /*********************************************************************************************** + * Logic Analyzer Section + ***********************************************************************************************/ + + @Override + public LogicAnalyzerData getLAData(long timeStamp) { + return realm.where(LogicAnalyzerData.class) + .equalTo("time", timeStamp) + .findFirst(); + } + + @Override + public void clearAllLARecords() { + realm.beginTransaction(); + realm.delete(LogicAnalyzerData.class); + realm.commitTransaction(); + } + + @Override + public void clearBlockOfLARecords(long block) { + realm.beginTransaction(); + RealmResults data = getBlockOfLARecords(block); + data.deleteAllFromRealm(); + realm.commitTransaction(); + } + + @Override + public RealmResults getAllLARecords() { + return realm.where(LogicAnalyzerData.class).findAll(); + } + + @Override + public RealmResults getBlockOfLARecords(long block) { + return realm.where(LogicAnalyzerData.class) + .equalTo("block", block) + .findAll(); + } } diff --git a/app/src/main/res/layout-land/logic_analyzer_logic_lines.xml b/app/src/main/res/layout-land/logic_analyzer_logic_lines.xml index a0d9c161c..a371cd2ee 100644 --- a/app/src/main/res/layout-land/logic_analyzer_logic_lines.xml +++ b/app/src/main/res/layout-land/logic_analyzer_logic_lines.xml @@ -21,14 +21,29 @@ android:gravity="center" android:orientation="vertical"> - + android:orientation="horizontal"> + + + + + @@ -95,8 +110,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/heading" - android:layout_marginBottom="@dimen/carousel_margin_bottom" android:layout_marginTop="@dimen/carousel_margin_top" + android:layout_marginBottom="@dimen/carousel_margin_bottom" android:background="@drawable/carousel_view_background" app:items_visible="three" /> @@ -104,9 +119,9 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/carouselPicker" - android:layout_marginBottom="@dimen/chart_layout_margin_bottom" android:layout_marginEnd="@dimen/recycler_view_margin_end" - android:layout_marginRight="@dimen/recycler_view_margin_end"> + android:layout_marginRight="@dimen/recycler_view_margin_end" + android:layout_marginBottom="@dimen/chart_layout_margin_bottom"> + android:paddingBottom="@dimen/ll_padding_bottom"> + android:paddingBottom="@dimen/ll_padding_bottom"> + android:paddingBottom="@dimen/ll_padding_bottom"> + android:paddingBottom="@dimen/ll_padding_bottom">