kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
refactor: add channel hash function
rodzic
505ba8a7d3
commit
e9f63b4e80
|
@ -4,6 +4,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||
import com.geeksville.mesh.model.Channel
|
||||
import com.geeksville.mesh.model.URL_PREFIX
|
||||
import com.geeksville.mesh.model.getChannelUrl
|
||||
import com.geeksville.mesh.model.numChannels
|
||||
import com.geeksville.mesh.model.toChannelSet
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
@ -23,6 +24,20 @@ class ChannelTest {
|
|||
Assert.assertEquals(channelUrl.toChannelSet(), ch)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun channelHashGood() {
|
||||
val ch = Channel.default
|
||||
|
||||
Assert.assertEquals(8, ch.hash)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun numChannelsGood() {
|
||||
val ch = Channel.default
|
||||
|
||||
Assert.assertEquals(104, ch.loraConfig.numChannels)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun channelNumGood() {
|
||||
val ch = Channel.default
|
||||
|
|
|
@ -89,24 +89,13 @@ data class Channel(
|
|||
}
|
||||
|
||||
/**
|
||||
* hash a string into an integer using the djb2 algorithm by Dan Bernstein
|
||||
* http://www.cse.yorku.ca/~oz/hash.html
|
||||
* Given a channel name and psk, return the (0 to 255) hash for that channel
|
||||
*/
|
||||
val hash: UInt // using UInt instead of Long to match RadioInterface.cpp results
|
||||
get() {
|
||||
var hash: UInt = 5381u
|
||||
for (c in name) {
|
||||
hash += (hash shl 5) + c.code.toUInt()
|
||||
print("$c ${c.code} $hash ")
|
||||
}
|
||||
return hash
|
||||
}
|
||||
val hash: Int get() = xorHash(name.toByteArray()) xor xorHash(psk.toByteArray())
|
||||
|
||||
val channelNum: Int
|
||||
get() = if (loraConfig.channelNum != 0) loraConfig.channelNum
|
||||
else (hash % RegionInfo.numChannels(loraConfig).toUInt()).toInt() + 1
|
||||
val channelNum: Int get() = loraConfig.channelNum(name)
|
||||
|
||||
val radioFreq: Float get() = RegionInfo.radioFreq(loraConfig, channelNum)
|
||||
val radioFreq: Float get() = loraConfig.radioFreq(channelNum)
|
||||
|
||||
override fun equals(other: Any?): Boolean = (other is Channel)
|
||||
&& psk.toByteArray() contentEquals other.psk.toByteArray()
|
||||
|
|
|
@ -5,9 +5,29 @@ import com.geeksville.mesh.ConfigProtos.Config.LoRaConfig.ModemPreset
|
|||
import com.geeksville.mesh.ConfigProtos.Config.LoRaConfig.RegionCode
|
||||
import com.geeksville.mesh.R
|
||||
|
||||
fun LoRaConfig.bandwidth() = if (usePreset) {
|
||||
/**
|
||||
* hash a string into an integer using the djb2 algorithm by Dan Bernstein
|
||||
* http://www.cse.yorku.ca/~oz/hash.html
|
||||
*/
|
||||
private fun hash(name: String): UInt { // using UInt instead of Long to match RadioInterface.cpp results
|
||||
var hash: UInt = 5381u
|
||||
for (c in name) {
|
||||
hash += (hash shl 5) + c.code.toUInt()
|
||||
}
|
||||
return hash
|
||||
}
|
||||
|
||||
private val ModemPreset.bandwidth: Float
|
||||
get() {
|
||||
for (option in ChannelOption.entries) {
|
||||
if (option.modemPreset == this) return option.bandwidth
|
||||
}
|
||||
return 0f
|
||||
}
|
||||
|
||||
private fun LoRaConfig.bandwidth() = if (usePreset) {
|
||||
val wideLora = region == RegionCode.LORA_24
|
||||
ChannelOption.bandwidth(modemPreset) * if (wideLora) 3.25f else 1f
|
||||
modemPreset.bandwidth * if (wideLora) 3.25f else 1f
|
||||
} else when (bandwidth) {
|
||||
31 -> .03125f
|
||||
62 -> .0625f
|
||||
|
@ -18,6 +38,28 @@ fun LoRaConfig.bandwidth() = if (usePreset) {
|
|||
else -> bandwidth / 1000f
|
||||
}
|
||||
|
||||
val LoRaConfig.numChannels: Int get() {
|
||||
for (option in RegionInfo.entries) {
|
||||
if (option.regionCode == region)
|
||||
return ((option.freqEnd - option.freqStart) / bandwidth()).toInt()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
internal fun LoRaConfig.channelNum(primaryName: String): Int {
|
||||
return if (channelNum != 0) channelNum
|
||||
else (hash(primaryName) % numChannels.toUInt()).toInt() + 1
|
||||
}
|
||||
|
||||
internal fun LoRaConfig.radioFreq(channelNum: Int): Float {
|
||||
if (overrideFrequency != 0f) return overrideFrequency + frequencyOffset
|
||||
for (option in RegionInfo.entries) {
|
||||
if (option.regionCode == region)
|
||||
return (option.freqStart + bandwidth() / 2) + (channelNum - 1) * bandwidth()
|
||||
}
|
||||
return 0f
|
||||
}
|
||||
|
||||
enum class RegionInfo(
|
||||
val regionCode: RegionCode,
|
||||
val freqStart: Float,
|
||||
|
@ -38,26 +80,8 @@ enum class RegionInfo(
|
|||
UA_433(RegionCode.UA_433, 433.0f, 434.7f),
|
||||
UA_868(RegionCode.UA_868, 868.0f, 868.6f),
|
||||
LORA_24(RegionCode.LORA_24, 2400.0f, 2483.5f),
|
||||
UNSET(RegionCode.UNSET, 902.0f, 928.0f);
|
||||
|
||||
companion object {
|
||||
fun numChannels(loraConfig: LoRaConfig): Int {
|
||||
for (option in values()) {
|
||||
if (option.regionCode == loraConfig.region)
|
||||
return ((option.freqEnd - option.freqStart) / loraConfig.bandwidth()).toInt()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
fun radioFreq(loraConfig: LoRaConfig, channelNum: Int): Float = with(loraConfig) {
|
||||
if (overrideFrequency != 0f) return overrideFrequency + frequencyOffset
|
||||
for (option in values()) {
|
||||
if (option.regionCode == region)
|
||||
return (option.freqStart + bandwidth() / 2) + (channelNum - 1) * bandwidth()
|
||||
}
|
||||
return 0f
|
||||
}
|
||||
}
|
||||
UNSET(RegionCode.UNSET, 902.0f, 928.0f),
|
||||
;
|
||||
}
|
||||
|
||||
enum class ChannelOption(
|
||||
|
@ -74,13 +98,4 @@ enum class ChannelOption(
|
|||
LONG_SLOW(ModemPreset.LONG_SLOW, R.string.modem_config_slow_long, .125f),
|
||||
VERY_LONG_SLOW(ModemPreset.VERY_LONG_SLOW, R.string.modem_config_very_long, .0625f),
|
||||
;
|
||||
|
||||
companion object {
|
||||
fun bandwidth(modemPreset: ModemPreset?): Float {
|
||||
for (option in values()) {
|
||||
if (option.modemPreset == modemPreset) return option.bandwidth
|
||||
}
|
||||
return 0f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import com.geeksville.mesh.ChannelProtos.ChannelSettings
|
|||
import com.geeksville.mesh.ConfigProtos.Config.LoRaConfig
|
||||
import com.geeksville.mesh.copy
|
||||
import com.geeksville.mesh.model.Channel
|
||||
import com.geeksville.mesh.model.RegionInfo
|
||||
import com.geeksville.mesh.model.numChannels
|
||||
import com.geeksville.mesh.ui.components.DropDownPreference
|
||||
import com.geeksville.mesh.ui.components.EditListPreference
|
||||
import com.geeksville.mesh.ui.components.EditTextPreference
|
||||
|
@ -136,7 +136,7 @@ fun LoRaConfigItemList(
|
|||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onFocusChanged = { isFocused = it.isFocused },
|
||||
onValueChanged = {
|
||||
if (it <= RegionInfo.numChannels(loraInput)) // max numChannels
|
||||
if (it <= loraInput.numChannels) // total num of LoRa channels
|
||||
loraInput = loraInput.copy { channelNum = it }
|
||||
})
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue