diff --git a/ros_acomms/src/tdma_advanced_node.py b/ros_acomms/src/tdma_advanced_node.py
index 5f449ae2600683acb608533d455f7aaf2e4f9ee4..a11f10f3d17fd0ff91700d6f2304bdfb8a8cd159 100755
--- a/ros_acomms/src/tdma_advanced_node.py
+++ b/ros_acomms/src/tdma_advanced_node.py
@@ -1,15 +1,16 @@
 #!/usr/bin/env python3
 
 import rospy
-from ros_acomms_msgs.srv import PingModem, PingModemRequest, PingTransponders, PingTranspondersRequest
+from ros_acomms_msgs.srv import PingModem, PingModemRequest, PingModemResponse, PingTransponders, PingTranspondersRequest
 from ros_acomms_msgs.msg import TdmaAdvancedStatus
 from tdma_node import TdmaMacNode
-from std_msgs.msg import Header
+from std_msgs.msg import Header, UInt8
 
 from ros_acomms.cfg import tdma_advancedConfig
 from dynamic_reconfigure.server import Server as DynamicReconfigureServer
 
 import datetime
+import traceback
 
 from mac_utils import PSK_ROS_FDP_Rates, expanded_slots_as_ranges # pure python class for non-ros functionality
 
@@ -78,9 +79,15 @@ class TdmaAdvancedMacNode(TdmaMacNode):
         self.transponder_reply_timeout_sec = rospy.get_param('~transponder_reply_timeout_sec', 5)
 
         self.wait_for_ping_services(timeout=rospy.get_param('~wait_for_services_timeout_sec', None))
+        # setup our own ping_modem endpoint for sending pings in tdma
+        self.queued_ping_request = None
+        self.queued_ping_response = None
+        rospy.Service("~ping_modem", PingModem, self.handle_ping_modem)
 
         # set up subscriber to toggle software_mute without overhead of dynamic_reconfigure
         rospy.Subscriber('~toggle_software_mute', Header, self.on_toggle_software_mute)
+        # set up subscriber for setting auto ping modem src id (can also be set with dynamic reconfigure)
+        rospy.Subscriber('~change_auto_ping_modem_src', UInt8, self.on_change_auto_ping_modem_src)
 
         # this method is called everytime the slot changes. We reset modem ping flags here
         self.sent_modem_pings = False
@@ -106,12 +113,26 @@ class TdmaAdvancedMacNode(TdmaMacNode):
             rospy.loginfo("~*+^ tdma_advanced_mac node running.")
             self.spin()
 
+    def invalidate_dynamic_reconfigure_cache(self):
+        # hacky way of invalidating dynamic reconfigure cache. 
+        # this will confuse a user of rqt by seemingly ignoring the next config it passes
+        # .. but, it will be updated with the values from the class
+        self.first_dynamic_reconf = True
+
     def on_toggle_software_mute(self, msg):
+        # self.invalidate_dynamic_reconfigure_cache() # TODO we should probably add here... need to do more testing first
         # will flip whatever the bool value is
         self.software_mute ^= True
         rospy.set_param('~software_mute', self.software_mute)
         rospy.logwarn(f'NOTICE: on_toggle_software_mute() software_mute: {self.software_mute}')
 
+    def on_change_auto_ping_modem_src(self, msg):
+        if self.ping_modem_src != int(msg.data):
+            self.invalidate_dynamic_reconfigure_cache()
+        self.ping_modem_src = int(msg.data)
+        rospy.set_param('~ping_modem_src', self.ping_modem_src)
+        rospy.logwarn(f'NOTICE: on_change_auto_ping_modem_src() ping_modem_src: {self.ping_modem_src}')
+
     def cache_slot_ranges_for_status(self):
         self._active_slots_range = expanded_slots_as_ranges(slots=self.active_slots)
         self._comms_slots_range = expanded_slots_as_ranges(slots=self.comms_slots)
@@ -143,6 +164,40 @@ class TdmaAdvancedMacNode(TdmaMacNode):
                 rospy.logwarn(f'WARNING: Timed out waiting for transponder ping service. This will throw an error when user tries to ping a transponder.')
         self.send_transponder_ping = rospy.ServiceProxy('ping_transponders', PingTransponders)
 
+    def handle_ping_modem(self, req):
+        if self.queued_ping_request is not None:
+            rospy.logwarn(f'WARNING: Received a ping request while handling another! Returning as if we timed-out of this request!')
+            return PingModemResponse(timed_out=True)
+
+        try:
+            self.queued_ping_response = None
+            self.queued_ping_request = req
+            cycle_duration = self.slot_duration_seconds * self.num_slots
+            if cycle_duration < req.reply_timeout:
+                rospy.logwarn(f'WARNING: ping_modem request timeout is longer than cycle_duration! Using req.reply_timeout: {req.reply_timeout}')
+                max_timeout = req.reply_timeout
+            else:
+                max_timeout = cycle_duration
+            # now wait until we have a self.queued_ping_response
+            start_t = rospy.get_time()
+            while not rospy.is_shutdown():
+                if rospy.get_time() - start_t > (max_timeout):
+                    rospy.logerr(f'ERROR: we have waited max_timeout: {max_timeout} and have not gotten a ping_response. Timing out..')
+                    return PingModemResponse(timed_out=True)
+
+                if self.queued_ping_response is None:
+                    rospy.sleep(0.1)
+                else:
+                    break
+        except:
+            rospy.logerr(f'ERROR: threw exception in tdma::handle_ping_modem: {traceback.format_exc()}')
+            return PingModemResponse(timed_out=True)
+        else:
+            rospy.loginfo(f'INFO: Received a ping_response from ping_modem via tdma: {self.queued_ping_response}')
+            return self.queued_ping_response
+        finally:
+            self.queued_ping_request = None
+
     def config_slot_mask(self, slots=None, allow_empty=False):
         if slots is not None:
             slots = self.parse_slots_value(slots=slots)
@@ -188,7 +243,7 @@ class TdmaAdvancedMacNode(TdmaMacNode):
             config['miniframe_rate'] = self.miniframe_rate
             config['dataframe_rate'] = self.dataframe_rate
 
-            rospy.logdebug(f'DEBUG: First dynamic_reconfigure call, syncing config from init')
+            rospy.logdebug(f'DEBUG: First dynamic_reconfigure call, syncing config from init OR post invalidate cache')
             return config
 
         rospy.logdebug("DEBUG: tdma_advanced_mac dynamic reconfigure request received.")
@@ -347,7 +402,17 @@ class TdmaAdvancedMacNode(TdmaMacNode):
 
     def send_nav_ping(self, remaining_active_seconds, sent_modem_pings, sent_transponder_ping):
         nav_ping_duration_sec = 0
-        if self.ping_modems and not sent_modem_pings:
+        if self.queued_ping_request is not None:
+            start_t = rospy.get_time()
+            # handle in tdma ping_request
+            req = self.queued_ping_request
+            rospy.loginfo(f'Sending TWTT ping to modem_src: {req.dest}')
+            self.queued_ping_response = self.send_modem_ping(req)
+            self.queued_ping_request = None # for good measure so we don't send another ping with this request
+
+            nav_ping_duration_sec = rospy.get_time() - start_t
+
+        elif self.ping_modems and not sent_modem_pings:
             # fire off the modem pings
             start_t = rospy.get_time()
             for i in range(self.pings_per_slot):
@@ -361,13 +426,16 @@ class TdmaAdvancedMacNode(TdmaMacNode):
                 req = PingModemRequest(dest=self.ping_modem_src, rate=self.miniframe_rate, cdr=self.ping_cdr, hexdata=bytes(), reply_timeout=self.ping_modem_timeout_sec)
                 rospy.logdebug(f'[{i + 1}/{self.pings_per_slot}]: Sending TWTT ping to modem_src: {self.ping_modem_src}, request:\n{req}')
                 if self.roslog_level < rospy.DEBUG: rospy.loginfo(f'[{i + 1}/{self.pings_per_slot}]: Sending TWTT ping to modem_src: {self.ping_modem_src}')
+
                 resp = self.send_modem_ping(req)
+
                 rospy.logdebug(f'DEBUG: Response from send_modem_ping:\n{resp}')
                 if resp.timed_out:
                     if self.roslog_level < rospy.DEBUG: rospy.loginfo(f'INFO: Response from send_modem_ping TIMED OUT')
 
             sent_modem_pings = True
             nav_ping_duration_sec = rospy.get_time() - start_t
+
         elif self.ping_transponders and not sent_transponder_ping:
             # fire off transponder ping
             start_t = rospy.get_time()
diff --git a/ros_acomms_tests/launch/test_use_ping_payload.launch b/ros_acomms_tests/launch/test_use_ping_payload.launch
index 3a5a455d415f643e1f82f8ebb15f76c85d4d71cb..3281bd00fa13ed4bf3281861efc3270fa730f04c 100644
--- a/ros_acomms_tests/launch/test_use_ping_payload.launch
+++ b/ros_acomms_tests/launch/test_use_ping_payload.launch
@@ -106,6 +106,31 @@
         <node name="modem_location_sim" pkg="ros_acomms_modeling" type="modem_location_sim_node.py" />
     </group>
 
+    <group ns="modem2">
+        <node unless="$(arg sim)" name="acomms_driver_node" pkg="ros_acomms" type="acomms_driver_node.py" output="screen" >
+            <param name="modem_serial_port" value="/dev/ttyUSB2" type="str" />
+            <param name="modem_baud_rate" value="19200" type="int" />
+            <param name="pwramp_txlevel" value="3" type="int" />
+            <param name="use_ping_payload" value="true" type="bool" />
+            <rosparam param="modem_config">
+                SRC: 2
+                BND: 0
+                FC0: 25000
+                BW0: 5000
+                psk.packet.mod_hdr_version: 1
+            </rosparam>
+        </node>
+
+        <node if="$(arg sim)" name="modem_sim_node" pkg="ros_acomms_modeling" type="modem_sim_node.py" output="screen" >
+            <param name="center_frequency_hz" value="25000" type="int" />
+            <param name="bandwidth_hz" value="5000" type="int" />
+            <param name="SRC" value="2" type="int" />
+            <param name="use_ping_payload" value="true" type="bool" />
+        </node>
+
+        <node name="modem_location_sim" pkg="ros_acomms_modeling" type="modem_location_sim_node.py" />
+    </group>
+
     <node name="sim_packet_performance_node" pkg="ros_acomms_modeling" type="sim_packet_performance_node.py" />
 
     <node name="sim_transmission_loss_node" pkg="ros_acomms_modeling" type="sim_transmission_loss_node.py"  >
diff --git a/ros_acomms_tests/src/test_use_ping_payload.py b/ros_acomms_tests/src/test_use_ping_payload.py
index 0aea4f7fed48ffb4a7d07aaf1e73541c35af1298..1c9716046a215b37bb10b02c9af752f7f785dc46 100755
--- a/ros_acomms_tests/src/test_use_ping_payload.py
+++ b/ros_acomms_tests/src/test_use_ping_payload.py
@@ -18,9 +18,11 @@ import rospkg
 import roslaunch
 
 from std_msgs.msg import Header, Bool, UInt8
+from ros_acomms_msgs.srv import PingModem, PingModemRequest, PingModemResponse
+from ros_acomms_msgs.msg import PingReply
 
 class TestUsePingPayload:
-    '''tdma Extended test class
+    '''tdma and modem_driver ping and auto ping test class
 
     test cases:
     '''
@@ -60,13 +62,29 @@ class TestUsePingPayload:
         self.launch = roslaunch.parent.ROSLaunchParent(uuid, roslaunch_file_param)
         self.launch.start()
 
-        rospy.sleep(30.0)
+        rospy.sleep(5.0)
         self.logger.warning('Node: test_use_ping_payload running!')
 
+    def test_modem0_disabled(self):
+        self.logger.warning(f'Testing use ping payload on modem0 which has ~use_ping_payload set to false')
+
+        publisher = rospy.Publisher('/modem0/test_msg', UInt8, queue_size=5, latch=True)
+        time.sleep(2)
+        msg = UInt8(data=1)
+        publisher.publish(msg)
+
+        try:
+            ret = rospy.wait_for_message(f'/modem1/from_acomms/test_msg', UInt8, timeout=30)
+        except rospy.exceptions.ROSException:
+            self.logger.warning("Success! timed out while waiting for /modem1/from_acomms/test_msg")
+        else:
+            self.logger.warning("Got test_msg from modem0 which has ~use_ping_payload:False and no comms_slots.")
+            pytest.fail("Got test_msg from modem0 which has ~use_ping_payload:False and no comms_slots.")
+
     def test_modem1_enabled(self):
         self.logger.warning(f'Testing use ping payload on modem1 which has ~use_ping_payload set to true')
 
-        publisher = rospy.Publisher('/modem1/test_msg', UInt8, queue_size=5)
+        publisher = rospy.Publisher('/modem1/test_msg', UInt8, queue_size=5, latch=True)
         time.sleep(2)
         msg = UInt8(data=1)
         publisher.publish(msg)
@@ -80,22 +98,78 @@ class TestUsePingPayload:
             if ret.data == 1:
                 self.logger.warning("Success! Got msg on /modem0/from_acomms/test_msg from modem1 which has ~use_ping_payload:True and no comms_slots")
 
-    def test_modem0_disabled(self):
-        self.logger.warning(f'Testing use ping payload on modem0 which has ~use_ping_payload set to false')
+    def test_modem0_ping_modem(self):
+        self.logger.warning(f'Testing ping_modem service endpoint in modem_driver')
 
-        publisher = rospy.Publisher('/modem0/test_msg', UInt8, queue_size=5)
-        time.sleep(2)
-        msg = UInt8(data=1)
-        publisher.publish(msg)
+        rospy.wait_for_service('/modem0/ping_modem', timeout=100)
+        send_modem_ping = rospy.ServiceProxy('/modem0/ping_modem', PingModem)
 
         try:
-            ret = rospy.wait_for_message(f'/modem1/from_acomms/test_msg', UInt8, timeout=30)
+            req = PingModemRequest(dest=2, rate=1, reply_timeout=1000.0)
+            resp = send_modem_ping(req)
         except rospy.exceptions.ROSException:
-            self.logger.warning("Success! timed out while waiting for /modem1/from_acomms/test_msg")
+            err = "timed-out during request?"
+            self.logger.warning(err)
+            pytest.fail(err)
         else:
-            self.logger.warning("Got test_msg from modem0 which has ~use_ping_payload:False and no comms_slots.")
-            pytest.fail("Got test_msg from modem0 which has ~use_ping_payload:False and no comms_slots.")
+            if resp.timed_out:
+                err = "response timed out!"
+                self.logger.warning(err)
+                pytest.fail(err)
 
+            self.logger.warning(f"Success! we got a ping_reply via the modem_driver service endpoint: resp: {resp}")
+
+    def test_modem0_tdma_ping_modem(self):
+        self.logger.warning(f'Testing ping_modem service endpoint in tdma')
+
+        rospy.wait_for_service('/modem0/tdma/ping_modem', timeout=100)
+        send_modem_ping = rospy.ServiceProxy('/modem0/tdma/ping_modem', PingModem)
+
+        try:
+            req = PingModemRequest(dest=2, rate=1, reply_timeout=1000.0)
+            resp = send_modem_ping(req)
+        except rospy.exceptions.ROSException:
+            err = "timed-out during request?"
+            self.logger.warning(err)
+            pytest.fail(err)
+        else:
+            if resp.timed_out:
+                err = "response timed out!"
+                self.logger.warning(err)
+                pytest.fail(err)
+
+            self.logger.warning(f"Success! we got a ping_reply via the tdma service endpoint: resp: {resp}")
+
+    def test_modem1_change_auto_ping_src(self):
+        self.logger.warning(f'Testing change_auto_ping_src')
+
+        publisher = rospy.Publisher('/modem1/tdma/change_auto_ping_modem_src', UInt8, queue_size=5, latch=True)
+        msg = UInt8(data=2)
+        publisher.publish(msg)
+        time.sleep(2.0)
+        self.logger.warning(f'Published to /modem1/tdma/change_auto_ping_modem_src, msg: {msg}')
+        ping_modem_src = rospy.get_param('/modem1/tdma/ping_modem_src')
+        self.logger.warning(f'Query param server, ping_modem_src: {ping_modem_src}')
+        if ping_modem_src != 2:
+            err = f"Failed setting auto ping_modem_src to 2!"
+            self.logger.warning(err)
+            pytest.fail(err)
+
+        try:
+            ret = rospy.wait_for_message(f'/modem1/ping_reply', PingReply, timeout=1000)
+            # incase we got the last ping_reply from our prior auto ping src
+            ret = rospy.wait_for_message(f'/modem1/ping_reply', PingReply, timeout=1000)
+        except rospy.exceptions.ROSException:
+            err = f"Failed! Timed-out waiting for ping_reply on modem1 from modem2"
+            self.logger.warning(err)
+            pytest.fail(err)
+        else:
+            if ret.src == 2:
+                self.logger.warning("Success! got ping_reply for modem1 from modem2")
+            else:
+                err = f"Failed! Got ping_reply from ret.src: {ret.src} not modem2"
+                self.logger.warning(err)
+                pytest.fail(err)
 
     @classmethod
     def teardown_class(self):