From 3e7661761f6ea81b6a9732359edf4c5ada3e8e20 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Feb 2022 15:43:15 -0800 Subject: [PATCH] Allow TX power to be limited to 10mW This allows the radio power to be limited so that it doesn't generate more than 10mW. Signed-off-by: Keith Packard --- altoslib/AltosConfigData.java | 18 ++++++++++++ altoslib/AltosConfigValues.java | 4 +++ altosui/AltosConfigFCUI.java | 50 +++++++++++++++++++++++++++++++++ src/drivers/ao_cc1200.c | 13 +++++++++ src/kernel/ao_config.c | 32 ++++++++++++++++++++- src/kernel/ao_config.h | 8 ++++++ telegps/TeleGPSConfigUI.java | 50 +++++++++++++++++++++++++++++++++ 7 files changed, 174 insertions(+), 1 deletion(-) diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index b6105f92..cd649113 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -83,6 +83,9 @@ public class AltosConfigData { /* HAS_BEEP */ public int beep; + /* HAS_RADIO_10MW */ + public int radio_10mw; + /* Storage info replies */ public int storage_size; public int storage_erase_unit; @@ -315,6 +318,8 @@ public class AltosConfigData { beep = AltosLib.MISSING; + radio_10mw = AltosLib.MISSING; + tracker_motion = AltosLib.MISSING; tracker_interval = AltosLib.MISSING; @@ -505,6 +510,9 @@ public class AltosConfigData { /* HAS_BEEP */ try { beep = get_int(line, "Beeper setting:"); } catch (Exception e) {} + /* HAS_RADIO_10MW */ + try { radio_10mw = get_int(line, "Radio 10mw limit:"); } catch (Exception e) {} + /* HAS_TRACKER */ try { int[] values = get_values(line, "Tracker setting:"); @@ -730,6 +738,11 @@ public class AltosConfigData { /* HAS_BEEP */ if (beep != AltosLib.MISSING) beep = source.beep(); + + /* HAS_RADIO_10MW */ + if (radio_10mw != AltosLib.MISSING) + radio_10mw = source.radio_10mw(); + /* HAS_TRACKER */ if (tracker_motion != AltosLib.MISSING) tracker_motion = source.tracker_motion(); @@ -785,6 +798,7 @@ public class AltosConfigData { dest.set_aprs_format(aprs_format); dest.set_aprs_offset(aprs_offset); dest.set_beep(beep); + dest.set_radio_10mw(radio_10mw); dest.set_tracker_motion(tracker_motion); dest.set_tracker_interval(tracker_interval); } @@ -904,6 +918,10 @@ public class AltosConfigData { if (beep != AltosLib.MISSING) link.printf("c b %d\n", beep); + /* HAS_RADIO_10MW */ + if (radio_10mw != AltosLib.MISSING) + link.printf("c p %d\n", radio_10mw); + /* HAS_TRACKER */ if (tracker_motion != AltosLib.MISSING && tracker_interval != AltosLib.MISSING) link.printf("c t %d %d\n", tracker_motion, tracker_interval); diff --git a/altoslib/AltosConfigValues.java b/altoslib/AltosConfigValues.java index 8fa3fa41..65b5f001 100644 --- a/altoslib/AltosConfigValues.java +++ b/altoslib/AltosConfigValues.java @@ -119,4 +119,8 @@ public interface AltosConfigValues { public abstract int tracker_interval() throws AltosConfigDataException; public abstract void set_tracker_interval(int tracker_motion); + + public abstract int radio_10mw() throws AltosConfigDataException; + + public abstract void set_radio_10mw(int radio_10mw); } diff --git a/altosui/AltosConfigFCUI.java b/altosui/AltosConfigFCUI.java index 562c6952..75b294d9 100644 --- a/altosui/AltosConfigFCUI.java +++ b/altosui/AltosConfigFCUI.java @@ -42,6 +42,7 @@ public class AltosConfigFCUI JLabel radio_calibration_label; JLabel radio_frequency_label; JLabel radio_enable_label; + JLabel radio_10mw_label; JLabel rate_label; JLabel aprs_interval_label; JLabel aprs_ssid_label; @@ -69,6 +70,7 @@ public class AltosConfigFCUI AltosUIFreqList radio_frequency_value; JLabel radio_calibration_value; JRadioButton radio_enable_value; + JRadioButton radio_10mw_value; AltosUIRateList rate_value; JComboBox aprs_interval_value; JComboBox aprs_ssid_value; @@ -349,6 +351,13 @@ public class AltosConfigFCUI beep_value.setToolTipText("Older firmware could not select beeper frequency"); } + void set_radio_10mw_tool_tip() { + if (radio_10mw_value.isVisible()) + radio_10mw_value.setToolTipText("Should transmitter power be limited to 10mW"); + else + radio_10mw_value.setToolTipText("Older firmware could not limit radio power"); + } + /* Build the UI using a grid bag */ public AltosConfigFCUI(JFrame in_owner, boolean remote) { super (in_owner, title, false); @@ -582,6 +591,31 @@ public class AltosConfigFCUI set_radio_enable_tool_tip(); row++; + /* Radio 10mW limit */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + radio_10mw_label = new JLabel("Limit transmit to 10mW:"); + pane.add(radio_10mw_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_10mw_value = new JRadioButton("Limited"); + radio_10mw_value.addItemListener(this); + pane.add(radio_10mw_value, c); + set_radio_10mw_tool_tip(); + row++; + /* Telemetry Rate */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = row; @@ -1438,6 +1472,22 @@ public class AltosConfigFCUI return AltosLib.MISSING; } + public void set_radio_10mw(int new_radio_10mw) { + if (new_radio_10mw != AltosLib.MISSING) { + radio_10mw_value.setSelected(new_radio_10mw != 0); + } + radio_10mw_value.setVisible(new_radio_10mw != AltosLib.MISSING); + radio_10mw_label.setVisible(new_radio_10mw != AltosLib.MISSING); + set_radio_10mw_tool_tip(); + } + + public int radio_10mw() { + if (radio_10mw_value.isVisible()) + return radio_10mw_value.isSelected() ? 1 : 0; + else + return AltosLib.MISSING; + } + String[] tracker_motion_values() { if (AltosConvert.imperial_units) return tracker_motion_values_ft; diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 9d3b77cb..7ac32e18 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -716,6 +716,7 @@ ao_radio_get(uint8_t len) { static uint32_t last_radio_setting; static uint8_t last_radio_rate; + static uint8_t last_radio_10mw; ao_mutex_get(&ao_radio_mutex); @@ -732,6 +733,18 @@ ao_radio_get(uint8_t len) ao_radio_mode &= (uint16_t) ~AO_RADIO_MODE_BITS_PACKET; last_radio_rate = ao_config.radio_rate; } + if(ao_config.radio_10mw != last_radio_10mw) { + last_radio_10mw = ao_config.radio_10mw; + /* + * 0x37 "should" be 10dBm, but measurements on TBT + * v4.0 show that too hot by a about 1.5dB, so use + * 0x34 to make sure we're in spec. + */ + if (ao_config.radio_10mw) + ao_radio_reg_write(CC1200_PA_CFG1, 0x34); + else + ao_radio_reg_write(CC1200_PA_CFG1, 0x3f); + } ao_radio_set_len(len); } diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 52d25aec..84efb11c 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -54,6 +54,7 @@ uint8_t ao_force_freq; #define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL #define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP #define AO_CONFIG_DEFAULT_PYRO_TIME AO_MS_TO_TICKS(50) +#define AO_CONFIG_DEFAULT_RADIO_10MW 0 #if HAS_CONFIG_SAVE #ifndef USE_INTERNAL_FLASH #error Please define USE_INTERNAL_FLASH @@ -188,7 +189,7 @@ _ao_config_get(void) #if HAS_RADIO_POWER if (minor < 14) ao_config.radio_power = AO_CONFIG_DEFAULT_RADIO_POWER; - #endif +#endif #if HAS_RADIO_AMP if (minor < 14) ao_config.radio_amp = AO_CONFIG_DEFAULT_RADIO_AMP; @@ -245,6 +246,10 @@ _ao_config_get(void) #if HAS_APRS if (minor < 24) ao_config.aprs_offset = 0; +#endif +#if HAS_RADIO_10MW + if (minor < 25) + ao_config.radio_10mw = AO_CONFIG_DEFAULT_RADIO_10MW; #endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; @@ -853,6 +858,27 @@ ao_config_radio_power_set(void) #endif +#if HAS_RADIO_10MW + +static void +ao_config_radio_10mw_show(void) +{ + printf ("Radio 10mw limit: %d\n", ao_config.radio_10mw); +} + +static void +ao_config_radio_10mw_set(void) +{ + uint32_t r = ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_10mw = !!r; + _ao_config_edit_finish(); +} + +#endif + #if HAS_BEEP static void ao_config_beep_show(void) @@ -1099,6 +1125,10 @@ const struct ao_config_var ao_config_vars[] = { ao_config_pad_box_set, ao_config_pad_box_show }, { "i \0Set idle timeout (0 disable)", ao_config_pad_idle_set, ao_config_pad_idle_show }, +#endif +#if HAS_RADIO_10MW + { "p <0 no limit, 1 limit>\0Limit radio power to 10mW", + ao_config_radio_10mw_set, ao_config_radio_10mw_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index 1d5a0fb0..f43401be 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -60,6 +60,11 @@ #define AO_CONFIG_MAJOR 1 #define AO_CONFIG_MINOR 25 +/* All cc1200 devices support limiting TX power to 10mW */ +#if !defined(HAS_RADIO_10MW) && defined(AO_CC1200_SPI) +#define HAS_RADIO_10MW 1 +#endif + #define AO_AES_LEN 16 extern uint8_t ao_config_aes_seq; @@ -126,6 +131,9 @@ struct ao_config { #if HAS_APRS uint8_t aprs_offset; /* minor version 24 */ #endif +#if HAS_RADIO_10MW + uint8_t radio_10mw; /* minor version 25 */ +#endif }; struct ao_config_1_24 { diff --git a/telegps/TeleGPSConfigUI.java b/telegps/TeleGPSConfigUI.java index 465916ec..5617b8e4 100644 --- a/telegps/TeleGPSConfigUI.java +++ b/telegps/TeleGPSConfigUI.java @@ -39,6 +39,7 @@ public class TeleGPSConfigUI JLabel radio_calibration_label; JLabel radio_frequency_label; JLabel radio_enable_label; + JLabel radio_10mw_label; JLabel rate_label; JLabel aprs_interval_label; JLabel aprs_ssid_label; @@ -58,6 +59,7 @@ public class TeleGPSConfigUI AltosUIFreqList radio_frequency_value; JLabel radio_calibration_value; JRadioButton radio_enable_value; + JRadioButton radio_10mw_value; AltosUIRateList rate_value; JComboBox aprs_interval_value; JComboBox aprs_ssid_value; @@ -152,6 +154,13 @@ public class TeleGPSConfigUI radio_enable_value.setToolTipText("Firmware version does not support disabling radio"); } + void set_radio_10mw_tool_tip() { + if (radio_10mw_value.isVisible()) + radio_10mw_value.setToolTipText("Should transmitter power be limited to 10mW"); + else + radio_10mw_value.setToolTipText("Older firmware could not limit radio power"); + } + void set_rate_tool_tip() { if (rate_value.isVisible()) rate_value.setToolTipText("Select telemetry baud rate"); @@ -354,6 +363,31 @@ public class TeleGPSConfigUI set_radio_enable_tool_tip(); row++; + /* Radio 10mW limit */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + radio_10mw_label = new JLabel("Limit transmit to 10mW:"); + pane.add(radio_10mw_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_10mw_value = new JRadioButton("Limited"); + radio_10mw_value.addItemListener(this); + pane.add(radio_10mw_value, c); + set_radio_10mw_tool_tip(); + row++; + /* Telemetry Rate */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = row; @@ -811,6 +845,22 @@ public class TeleGPSConfigUI return AltosLib.MISSING; } + public void set_radio_10mw(int new_radio_10mw) { + if (new_radio_10mw != AltosLib.MISSING) { + radio_10mw_value.setSelected(new_radio_10mw != 0); + } + radio_10mw_value.setVisible(new_radio_10mw != AltosLib.MISSING); + radio_10mw_label.setVisible(new_radio_10mw != AltosLib.MISSING); + set_radio_10mw_tool_tip(); + } + + public int radio_10mw() { + if (radio_10mw_value.isVisible()) + return radio_10mw_value.isSelected() ? 1 : 0; + else + return AltosLib.MISSING; + } + public void set_telemetry_rate(int new_rate) { if (new_rate != AltosLib.MISSING) rate_value.set_rate(new_rate); -- 2.30.2