Add Channel Frequency Calculator

This commit is contained in:
Sacha Weatherstone 2023-05-12 21:40:11 +10:00
parent 8c1e6b1960
commit ec4b42e3d5
2 changed files with 342 additions and 0 deletions

View file

@ -6,6 +6,8 @@ sidebar_label: Radio Settings
sidebar_position: 1 sidebar_position: 1
--- ---
import {FrequencyCalculator} from "/src/components/tools/FrequencyCalculator";
:::info :::info
Meshtastic is **not** LoRaWAN, Helium or TTN (TheThingsNetwork). Meshtastic uses the full spectrum frequency range designated to LoRa technology per region. This allows for several hundred possible frequency channels in the US region alone. Meshtastic is **not** LoRaWAN, Helium or TTN (TheThingsNetwork). Meshtastic uses the full spectrum frequency range designated to LoRa technology per region. This allows for several hundred possible frequency channels in the US region alone.
::: :::
@ -14,6 +16,10 @@ Meshtastic is **not** LoRaWAN, Helium or TTN (TheThingsNetwork). Meshtastic uses
Power limits will generally be lifted in the software if `is_licensed` is set to `true`. See [HAM Mode](/docs/faq#amateur-radio-ham) for more information. Power limits will generally be lifted in the software if `is_licensed` is set to `true`. See [HAM Mode](/docs/faq#amateur-radio-ham) for more information.
::: :::
## Channel Frequency Calculator
<FrequencyCalculator />
## Europe Frequency Bands ## Europe Frequency Bands
### 433 MHz ### 433 MHz

View file

@ -0,0 +1,336 @@
import React, { useEffect } from "react";
import { Protobuf, Types } from "@meshtastic/meshtasticjs";
interface Region {
freq_start: number;
freq_end: number;
duty_cycle: number;
spacing: number;
power_limit: number;
}
interface Modem {
bw: number;
cr: number;
sf: number;
}
const RegionData = new Map<Protobuf.Config_LoRaConfig_RegionCode, Region>([
[
Protobuf.Config_LoRaConfig_RegionCode.US,
{
freq_start: 902.0,
freq_end: 928.0,
duty_cycle: 100,
spacing: 0,
power_limit: 30,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.EU_433,
{
freq_start: 433.0,
freq_end: 434.0,
duty_cycle: 10,
spacing: 0,
power_limit: 12,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.EU_868,
{
freq_start: 869.4,
freq_end: 869.65,
duty_cycle: 10,
spacing: 0,
power_limit: 27,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.CN,
{
freq_start: 470.0,
freq_end: 510.0,
duty_cycle: 100,
spacing: 0,
power_limit: 19,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.JP,
{
freq_start: 920.8,
freq_end: 927.8,
duty_cycle: 100,
spacing: 0,
power_limit: 16,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.ANZ,
{
freq_start: 915.0,
freq_end: 928.0,
duty_cycle: 100,
spacing: 0,
power_limit: 30,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.RU,
{
freq_start: 868.7,
freq_end: 869.2,
duty_cycle: 100,
spacing: 0,
power_limit: 20,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.KR,
{
freq_start: 920.0,
freq_end: 923.0,
duty_cycle: 100,
spacing: 0,
power_limit: 0,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.TW,
{
freq_start: 920.0,
freq_end: 925.0,
duty_cycle: 100,
spacing: 0,
power_limit: 0,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.IN,
{
freq_start: 865.0,
freq_end: 867.0,
duty_cycle: 100,
spacing: 0,
power_limit: 30,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.NZ_865,
{
freq_start: 864.0,
freq_end: 868.0,
duty_cycle: 100,
spacing: 0,
power_limit: 36,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.TH,
{
freq_start: 920.0,
freq_end: 925.0,
duty_cycle: 100,
spacing: 0,
power_limit: 16,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.UA_433,
{
freq_start: 433.0,
freq_end: 434.7,
duty_cycle: 10,
spacing: 0,
power_limit: 10,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.UA_868,
{
freq_start: 868.0,
freq_end: 868.6,
duty_cycle: 1,
spacing: 0,
power_limit: 14,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.LORA_24,
{
freq_start: 2400.0,
freq_end: 2483.5,
duty_cycle: 100,
spacing: 0,
power_limit: 10,
},
],
[
Protobuf.Config_LoRaConfig_RegionCode.UNSET,
{
freq_start: 902.0,
freq_end: 928.0,
duty_cycle: 100,
spacing: 0,
power_limit: 30,
},
],
]);
const modemPresets = new Map<Protobuf.Config_LoRaConfig_ModemPreset, Modem>([
[
Protobuf.Config_LoRaConfig_ModemPreset.SHORT_FAST,
{
bw: 250,
cr: 8,
sf: 7,
},
],
[
Protobuf.Config_LoRaConfig_ModemPreset.SHORT_SLOW,
{
bw: 250,
cr: 8,
sf: 8,
},
],
[
Protobuf.Config_LoRaConfig_ModemPreset.MEDIUM_FAST,
{
bw: 250,
cr: 8,
sf: 9,
},
],
[
Protobuf.Config_LoRaConfig_ModemPreset.MEDIUM_SLOW,
{
bw: 250,
cr: 8,
sf: 10,
},
],
[
Protobuf.Config_LoRaConfig_ModemPreset.LONG_FAST,
{
bw: 250,
cr: 8,
sf: 11,
},
],
[
Protobuf.Config_LoRaConfig_ModemPreset.LONG_MODERATE,
{
bw: 125,
cr: 8,
sf: 11,
},
],
[
Protobuf.Config_LoRaConfig_ModemPreset.LONG_SLOW,
{
bw: 125,
cr: 8,
sf: 12,
},
],
[
Protobuf.Config_LoRaConfig_ModemPreset.VERY_LONG_SLOW,
{
bw: 62.5,
cr: 8,
sf: 12,
},
],
]);
export const FrequencyCalculator = (): JSX.Element => {
const [modemPreset, setModemPreset] =
React.useState<Protobuf.Config_LoRaConfig_ModemPreset>(
Protobuf.Config_LoRaConfig_ModemPreset.LONG_FAST,
);
const [region, setRegion] =
React.useState<Protobuf.Config_LoRaConfig_RegionCode>(
Protobuf.Config_LoRaConfig_RegionCode.US,
);
const [channel, setChannel] = React.useState<Types.ChannelNumber>(
Types.ChannelNumber.PRIMARY,
);
const [numChannels, setNumChannels] = React.useState<number>(0);
const [channelFrequency, setChannelFrequency] = React.useState<number>(0);
useEffect(() => {
const selectedRegion = RegionData.get(region);
const selectedModemPreset = modemPresets.get(modemPreset);
setNumChannels(
Math.floor(
(selectedRegion.freq_end - selectedRegion.freq_start) /
(selectedRegion.spacing + selectedModemPreset.bw / 1000),
),
);
setChannelFrequency(
selectedRegion.freq_start +
selectedModemPreset.bw / 2000 +
channel * (selectedModemPreset.bw / 1000),
);
}, [modemPreset, region, channel]);
return (
<div className="flex flex-col border-l-[5px] shadow-md my-4 border-accent rounded-lg p-4 bg-secondary gap-2">
<div className="flex gap-2">
<label>Modem Preset:</label>
<select
value={modemPreset}
onChange={(e) =>
setModemPreset(
parseInt(
e.target.value,
) as Protobuf.Config_LoRaConfig_ModemPreset,
)
}
>
{Array.from(modemPresets.keys()).map((key) => (
<option key={key} value={key}>
{Protobuf.Config_LoRaConfig_ModemPreset[key]}
</option>
))}
</select>
</div>
<div className="flex gap-2">
<label>Region:</label>
<select
value={region}
onChange={(e) => setRegion(parseInt(e.target.value))}
>
{Array.from(RegionData.keys()).map((key) => (
<option key={key} value={key}>
{Protobuf.Config_LoRaConfig_RegionCode[key]}
</option>
))}
</select>
</div>
<div className="flex gap-2">
<label>Channel:</label>
<select
value={channel}
onChange={(e) => setChannel(parseInt(e.target.value))}
>
{Array.from(Array(numChannels).keys()).map((key) => (
<option key={key} value={key}>
{key}
</option>
))}
</select>
</div>
<div className="flex gap-2">
<label className="font-semibold">Number of channels:</label>
<input type="number" disabled value={numChannels} />
</div>
<div className="flex gap-2">
<label className="font-semibold">Channel Frequency:</label>
<input type="number" disabled value={channelFrequency} />
</div>
</div>
);
};