import { Protobuf, Types } from "@meshtastic/js"; import React, { useEffect, useState } from "react"; interface Region { freqStart: number; freqEnd: number; dutyCycle: number; spacing: number; powerLimit: number; } interface Modem { bw: number; cr: number; sf: number; } const RegionData = new Map< Protobuf.Config.Config_LoRaConfig_RegionCode, Region >([ [ Protobuf.Config.Config_LoRaConfig_RegionCode.US, { freqStart: 902.0, freqEnd: 928.0, dutyCycle: 100, spacing: 0, powerLimit: 30, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.EU_433, { freqStart: 433.0, freqEnd: 434.0, dutyCycle: 10, spacing: 0, powerLimit: 12, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.EU_868, { freqStart: 869.4, freqEnd: 869.65, dutyCycle: 10, spacing: 0, powerLimit: 27, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.CN, { freqStart: 470.0, freqEnd: 510.0, dutyCycle: 100, spacing: 0, powerLimit: 19, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.JP, { freqStart: 920.8, freqEnd: 927.8, dutyCycle: 100, spacing: 0, powerLimit: 16, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.ANZ, { freqStart: 915.0, freqEnd: 928.0, dutyCycle: 100, spacing: 0, powerLimit: 30, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.RU, { freqStart: 868.7, freqEnd: 869.2, dutyCycle: 100, spacing: 0, powerLimit: 20, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.KR, { freqStart: 920.0, freqEnd: 923.0, dutyCycle: 100, spacing: 0, powerLimit: 0, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.TW, { freqStart: 920.0, freqEnd: 925.0, dutyCycle: 100, spacing: 0, powerLimit: 0, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.IN, { freqStart: 865.0, freqEnd: 867.0, dutyCycle: 100, spacing: 0, powerLimit: 30, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.NZ_865, { freqStart: 864.0, freqEnd: 868.0, dutyCycle: 100, spacing: 0, powerLimit: 36, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.TH, { freqStart: 920.0, freqEnd: 925.0, dutyCycle: 100, spacing: 0, powerLimit: 16, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.UA_433, { freqStart: 433.0, freqEnd: 434.7, dutyCycle: 10, spacing: 0, powerLimit: 10, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.UA_868, { freqStart: 868.0, freqEnd: 868.6, dutyCycle: 1, spacing: 0, powerLimit: 14, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.MY_433, { freqStart: 433.0, freqEnd: 435.0, dutyCycle: 100, spacing: 0, powerLimit: 20, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.MY_919, { freqStart: 919.0, freqEnd: 924.0, dutyCycle: 100, spacing: 0, powerLimit: 27, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.SG_923, { freqStart: 917.0, freqEnd: 925.0, dutyCycle: 100, spacing: 0, powerLimit: 20, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.LORA_24, { freqStart: 2400.0, freqEnd: 2483.5, dutyCycle: 100, spacing: 0, powerLimit: 10, }, ], [ Protobuf.Config.Config_LoRaConfig_RegionCode.UNSET, { freqStart: 902.0, freqEnd: 928.0, dutyCycle: 100, spacing: 0, powerLimit: 30, }, ], ]); const modemPresets = new Map< Protobuf.Config.Config_LoRaConfig_ModemPreset, Modem >([ [ Protobuf.Config.Config_LoRaConfig_ModemPreset.SHORT_FAST, { bw: 250, cr: 8, sf: 7, }, ], [ Protobuf.Config.Config_LoRaConfig_ModemPreset.SHORT_SLOW, { bw: 250, cr: 8, sf: 8, }, ], [ Protobuf.Config.Config_LoRaConfig_ModemPreset.MEDIUM_FAST, { bw: 250, cr: 8, sf: 9, }, ], [ Protobuf.Config.Config_LoRaConfig_ModemPreset.MEDIUM_SLOW, { bw: 250, cr: 8, sf: 10, }, ], [ Protobuf.Config.Config_LoRaConfig_ModemPreset.LONG_FAST, { bw: 250, cr: 8, sf: 11, }, ], [ Protobuf.Config.Config_LoRaConfig_ModemPreset.LONG_MODERATE, { bw: 125, cr: 8, sf: 11, }, ], [ Protobuf.Config.Config_LoRaConfig_ModemPreset.LONG_SLOW, { bw: 125, cr: 8, sf: 12, }, ], [ Protobuf.Config.Config_LoRaConfig_ModemPreset.VERY_LONG_SLOW, { bw: 62.5, cr: 8, sf: 12, }, ], ]); export const FrequencyCalculator = (): JSX.Element => { const [modemPreset, setModemPreset] = useState( Protobuf.Config.Config_LoRaConfig_ModemPreset.LONG_FAST, ); const [region, setRegion] = useState( Protobuf.Config.Config_LoRaConfig_RegionCode.US, ); const [channel, setChannel] = useState( Types.ChannelNumber.Primary, ); const [numChannels, setNumChannels] = useState(0); const [channelFrequency, setChannelFrequency] = useState(0); useEffect(() => { const selectedRegion = RegionData.get(region); const selectedModemPreset = modemPresets.get(modemPreset); const calculatedNumChannels = Math.floor( (selectedRegion.freqEnd - selectedRegion.freqStart) / (selectedRegion.spacing + selectedModemPreset.bw / 1000), ); setNumChannels(calculatedNumChannels); let updatedChannel = channel; if (updatedChannel >= calculatedNumChannels) { updatedChannel = 0; } setChannel(updatedChannel); setChannelFrequency( selectedRegion.freqStart + selectedModemPreset.bw / 2000 + updatedChannel * (selectedModemPreset.bw / 1000), ); }, [modemPreset, region, channel]); return (
); };