refactor: add channel hash function

pull/810/head
andrekir 2024-01-10 05:33:19 -03:00
rodzic 505ba8a7d3
commit e9f63b4e80
4 zmienionych plików z 67 dodań i 48 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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()

Wyświetl plik

@ -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
}
}
}

Wyświetl plik

@ -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 }
})
}