diff --git a/src/MagSend-Website/scripts/Constants.js b/src/MagSend-Website/scripts/Constants.js index 389a088..9b1cd94 100644 --- a/src/MagSend-Website/scripts/Constants.js +++ b/src/MagSend-Website/scripts/Constants.js @@ -5,7 +5,7 @@ class Constants { * @type {Number} */ static get CLOCK_TIME() { - return 1000; + return 500; } /** diff --git a/src/MagSend/app/src/main/java/dev/kaderli/magsend/activity/BaseSensorActivity.kt b/src/MagSend/app/src/main/java/dev/kaderli/magsend/activity/BaseSensorActivity.kt index 1827142..427fc40 100644 --- a/src/MagSend/app/src/main/java/dev/kaderli/magsend/activity/BaseSensorActivity.kt +++ b/src/MagSend/app/src/main/java/dev/kaderli/magsend/activity/BaseSensorActivity.kt @@ -16,7 +16,7 @@ abstract class BaseSensorActivity : BaseActivity(), SensorEventListener { super.onResume() sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); - sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI); + sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME); } override fun onStop() { diff --git a/src/MagSend/app/src/main/java/dev/kaderli/magsend/activity/ReceiveActivity.kt b/src/MagSend/app/src/main/java/dev/kaderli/magsend/activity/ReceiveActivity.kt index 86e7690..491ed65 100644 --- a/src/MagSend/app/src/main/java/dev/kaderli/magsend/activity/ReceiveActivity.kt +++ b/src/MagSend/app/src/main/java/dev/kaderli/magsend/activity/ReceiveActivity.kt @@ -25,6 +25,9 @@ class ReceiveActivity : BaseSensorActivity() { */ private var signal = ArrayList>() + /** + * Flag that determines if the preamble was already received. + */ private var preambleReceived = false override fun onCreate(savedInstanceState: Bundle?) { @@ -50,19 +53,51 @@ class ReceiveActivity : BaseSensorActivity() { return getMidRangeOfData() + 3 } - return getMidRangeOfData(); + return getMidRangeOfData() + 2 + } + + private fun getThresholdForLowSignals(): Float { + if (getRangeOfData() < 3) { + return getMidRangeOfData() + 3 + } + + return getMidRangeOfData() - 2 } private fun getMidRangeOfData(): Float { val maxValue = samples.maxByOrNull { it.value } ?: Sample(0f) val minValue = samples.minByOrNull { it.value } ?: Sample(0f) - return (maxValue.value + minValue.value) / 2; + return (maxValue.value + minValue.value) / 2 } private fun isHigh(value: Float): Boolean { return value > getThresholdForHighSignals() } + private fun isLow(value: Float): Boolean { + return value < getThresholdForLowSignals() + } + + /** + * Check if the given sample should count as a high or low signal. If the sample is inside + * the threshold area it is not counted. + */ + private fun getSignalForSample(sample: Sample): Sample? { + if (isHigh(sample.value)) { + return Sample(Signal.High) + } + + if (isLow(sample.value)) { + return Sample(Signal.Low) + } + + return null + } + + /** + * Attempts to detect the preamble in the already received signal. If it can find the preamble it returns true and + * false otherwise. + */ private fun detectPreamble(): Boolean { val cleanedSignal = cleanSignal(signal) val compressedSignal = compressSignal(cleanedSignal) @@ -89,9 +124,11 @@ class ReceiveActivity : BaseSensorActivity() { return false } + /** + * This functions takes the signal and filters out samples that are only in a cluster of 3 or less of the same signal. + * This way we can remove single jumps that occur in the signal. + */ private fun cleanSignal(signal: List>): List> { - // TODO: Improve this method - // Remove outliers from the signal (single signal spikes or drops) val cleanSignal = signal.filterIndexed { index, sample -> var elementCount = 1 @@ -127,40 +164,51 @@ class ReceiveActivity : BaseSensorActivity() { private fun analyzePacketSignal(): List { val cleanedSignal = cleanSignal(signal) - val compressedSignal = compressSignal(cleanedSignal) - if (compressedSignal.size < 2) { - return listOf() - } - - val timeDifferences = ArrayList() - compressedSignal.forEachIndexed { index, sample -> - if (index == 0) { + var maxSamplesInARow = 0 + var count = 0 + cleanedSignal.forEachIndexed { index, sample -> + if(index == 0) { return@forEachIndexed } - timeDifferences.add(sample.timestamp - compressedSignal[index - 1].timestamp) + if(sample.value == cleanedSignal[index - 1].value) { + count ++ + if(count > maxSamplesInARow) { + maxSamplesInARow = count + } + } else { + count = 0 + } } - val clockTimeThreshold = 900//timeDifferences.max() * 0.75 val packetData = ArrayList() - compressedSignal.forEachIndexed { index, sample -> - if (index == 0) { - return@forEachIndexed + var lastSignal: Sample? = null + var isFirstSignal = true + var samplesSinceLastSignal = 0 + cleanedSignal.forEach { sample -> + if (lastSignal == null) { + lastSignal = sample } - val timeDifference = sample.timestamp - compressedSignal[index - 1].timestamp - if (timeDifference > clockTimeThreshold && timeDifference < 2500) { - if (sample.value == Signal.High) { - packetData.add(0) - } else { - packetData.add(1) + if (sample.value != lastSignal!!.value) { + if(samplesSinceLastSignal > (maxSamplesInARow * 0.75) || isFirstSignal) { + //Log.i(TAG, "$samplesSinceLastSignal") + if (sample.value == Signal.High) { + packetData.add(0) + } else { + packetData.add(1) + } + isFirstSignal = false + samplesSinceLastSignal=0 } + lastSignal = sample } + samplesSinceLastSignal++ } - Log.i(TAG, "$timeDifferences") + //Log.i(TAG, "$cleanSignal") return packetData @@ -171,15 +219,12 @@ class ReceiveActivity : BaseSensorActivity() { samples.add(Sample(magneticFieldStrength)) // Determine whether the sample is a high or low signal - val currentSignal: Sample = if (isHigh(magneticFieldStrength)) { - Sample(Signal.High) - } else { - Sample(Signal.Low) - } + val currentSignal = getSignalForSample(samples.last()) ?: return signal.add(currentSignal) // Try to detect the preamble in the signal if (!preambleReceived) { + // If we detect the preamble we change the status on the screen and clear the existing signal data. if (detectPreamble()) { preambleReceived = true preambleStatus.setText(R.string.preamble_status_detected) @@ -189,9 +234,12 @@ class ReceiveActivity : BaseSensorActivity() { } } + // After the preamble is detected we attempt to decode the packet. if (preambleReceived) { - val packet = analyzePacketSignal(); + // Get the decoded packet data + val packet = analyzePacketSignal() + // Get the payload length of in the data var payloadLength = 0 if (packet.size >= 4) { payloadLength = listToInteger(packet.take(4)) @@ -207,6 +255,7 @@ class ReceiveActivity : BaseSensorActivity() { receiveValue.text = payload + // TODO: CRC show and calculate if it's correct if (packet.size >= 4 + (8 * payloadLength) + 8) { // CRC Check val crc = listToInteger(packet.take(4 + (8 * payloadLength) + 8).takeLast(8)) @@ -217,7 +266,7 @@ class ReceiveActivity : BaseSensorActivity() { } private fun listToInteger(values: List): Int { - var value: Int = 0 + var value = 0 for (bit in values) { value = (value shl 1) + bit