Allow TX power to be limited to 10mW
authorKeith Packard <keithp@keithp.com>
Fri, 25 Feb 2022 23:43:15 +0000 (15:43 -0800)
committerKeith Packard <keithp@keithp.com>
Sat, 26 Feb 2022 01:30:35 +0000 (17:30 -0800)
This allows the radio power to be limited so that it doesn't generate
more than 10mW.

Signed-off-by: Keith Packard <keithp@keithp.com>
altoslib/AltosConfigData.java
altoslib/AltosConfigValues.java
altosui/AltosConfigFCUI.java
src/drivers/ao_cc1200.c
src/kernel/ao_config.c
src/kernel/ao_config.h
telegps/TeleGPSConfigUI.java

index b6105f92fc3cb27265e087fb530d84da2f2f79e8..cd649113b1a6b8293b3766f05a74f97ae6f79d0b 100644 (file)
@@ -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);
index 8fa3fa41b697056ee271f76b1db6dddf1b2e2b0a..65b5f0018de5136fbc48b003c5ff52dd0ded9cf3 100644 (file)
@@ -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);
 }
index 562c695207613638bb3a61253d04bd3290964a1e..75b294d9b2c01d5acdd440d80a64350420580045 100644 (file)
@@ -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<String>       aprs_interval_value;
        JComboBox<Integer>      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;
index 9d3b77cbdf87561d56a8eb69b807927d4b041ce4..7ac32e188e1b46319f14c60b0c4b996517d29825 100644 (file)
@@ -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);
 }
 
index 52d25aec0b226aca40d6a281f3ef9415b91185c2..84efb11cd0e2e3474723e9bf51ea339f9130a2e1 100644 (file)
@@ -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 <seconds>\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 },
index 1d5a0fb022deab4964b97f857769adf66b867ece..f43401be6051a812f0c9854a408f832a64b83ed9 100644 (file)
 #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 {
index 465916ec81ea0c2efebdc26cef86f9ede96c81f9..5617b8e435e09818b53b7e94932819675a1d18e7 100644 (file)
@@ -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<String>       aprs_interval_value;
        JComboBox<Integer>      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);