From eb0bc2b4a4943b648f5a020e10f61080640d2d80 Mon Sep 17 00:00:00 2001 From: Toreil Date: Fri, 11 Jul 2025 10:27:25 +0200 Subject: [PATCH 1/4] Expanded comments and removed duplicate variables --- src/console/spcm_control/tx_device.py | 54 ++++++++++++++++----------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/console/spcm_control/tx_device.py b/src/console/spcm_control/tx_device.py index 73574cb8..a4f9c2e4 100644 --- a/src/console/spcm_control/tx_device.py +++ b/src/console/spcm_control/tx_device.py @@ -345,8 +345,19 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: min_ring_buffer_size = int(np.ceil(self.data_buffer_size / notify_size.value) * notify_size.value) # Create page-aligned ring buffer ring_buffer = create_dma_buffer(min(self.max_ring_buffer_size.value, min_ring_buffer_size)) + # Get the size of the ring buffer ring_buffer_size = spcm.uint64(len(ring_buffer)) + try: + # Get the memory location of the data buffer and ring buffer + data_buffer_addr = ctypes.cast(data_buffer, ctypes.c_void_p).value + ring_buffer_addr = ctypes.cast(ring_buffer, ctypes.c_void_p).value + if not data_buffer_addr or not ring_buffer_addr: + raise RuntimeError("Could not get ring or data buffer position.") + except RuntimeError as err: + self.log.exception(err, exc_info=True) + raise err + try: # Check if ring buffer size is multiple of 2*num_ch (2 bytes per sample per channel) if ring_buffer_size.value % (self.num_ch * 2) != 0: @@ -359,6 +370,7 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: raise MemoryError( "Replay data size is not a multiple of enabled channels times 2 (bytes per sample)..." ) + except MemoryError as err: self.log.exception(err, exc_info=True) raise err @@ -370,22 +382,19 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: ) try: - # Perform initial memory transfer: Fill the whole ring buffer - if (_ring_buffer_pos := ctypes.cast(ring_buffer, ctypes.c_void_p).value) and \ - (_data_buffer_pos := ctypes.cast(data_buffer, ctypes.c_void_p).value): - if self.data_buffer_size < ring_buffer_size.value: - ctypes.memmove(_ring_buffer_pos, _data_buffer_pos, self.data_buffer_size) - transferred_bytes = self.data_buffer_size - else: - ctypes.memmove(_ring_buffer_pos, _data_buffer_pos, ring_buffer_size.value) - transferred_bytes = ring_buffer_size.value - else: - raise RuntimeError("Could not get ring or data buffer position.") + # Perform initial memory transfer + # If the data buffer fits in the ring buffer, copy the entire data buffer + if self.data_buffer_size < ring_buffer_size.value: + ctypes.memmove(ring_buffer_addr, data_buffer_addr, self.data_buffer_size) + transferred_bytes = self.data_buffer_size + else: # Otherwise fill the ring buffer completely with data + ctypes.memmove(ring_buffer_addr, data_buffer_addr, ring_buffer_size.value) + transferred_bytes = ring_buffer_size.value except RuntimeError as err: self.log.exception(err, exc_info=True) raise err - # Perform initial data transfer to completely fill continuous buffer + # Define the transfer buffer spcm.spcm_dwDefTransfer_i64( self.card, spcm.SPCM_BUF_DATA, @@ -396,9 +405,11 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: ring_buffer_size, ) + # Tell the card how much data is available self.handle_error(spcm.spcm_dwSetParam_i64(self.card, spcm.SPC_DATA_AVAIL_CARD_LEN, ring_buffer_size)) self.log.debug("Starting card memory transfer") + # Start data transfer from ring_buffer and wait until (buffer) data transfer completion self.handle_error(spcm.spcm_dwSetParam_i32( self.card, spcm.SPC_M2CMD, @@ -418,11 +429,12 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: transfer_count = 0 while (transferred_bytes < self.data_buffer_size) and not self.is_running.is_set(): - # Read available bytes and user position + # Read number of available bytes to write to on card spcm.spcm_dwGetParam_i32(self.card, spcm.SPC_DATA_AVAIL_USER_LEN, ctypes.byref(avail_bytes)) + # Read where those available bytes are located in memory spcm.spcm_dwGetParam_i32(self.card, spcm.SPC_DATA_AVAIL_USER_POS, ctypes.byref(usr_position)) - # Calculate new data for the transfer, when notify_size is available on continous buffer + # Only transfer when notify_size number of bytes are available if avail_bytes.value >= notify_size.value: transfer_count += 1 @@ -431,11 +443,10 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: ring_buffer, usr_position.value), ctypes.c_void_p ).value - current_data_buffer = ctypes.cast(data_buffer, ctypes.c_void_p).value - # Get new buffer positions - if ring_buffer_position and current_data_buffer: - data_buffer_position = current_data_buffer + transferred_bytes + if ring_buffer_position and data_buffer_addr: + # Calculate current position/progress in original data array + data_buffer_position = data_buffer_addr + transferred_bytes if (bytes_remaining := self.data_buffer_size - transferred_bytes) >= notify_size.value: # Enough data available -> copy notify size @@ -445,7 +456,7 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: notify_size.value, ) else: - # Not enough data availabe -> set remaining bytes to zero + # Not enough data availabe -> Copy available data, set remaining bytes to zero ctypes.memmove( ring_buffer_position, data_buffer_position, @@ -457,12 +468,13 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: notify_size.value - bytes_remaining, ) + # Tell card notify_size amount of data is available self.handle_error( spcm.spcm_dwSetParam_i32(self.card, spcm.SPC_DATA_AVAIL_CARD_LEN, notify_size) ) transferred_bytes += notify_size.value - + # Wait for data transfer to complete self.handle_error(spcm.spcm_dwSetParam_i32(self.card, spcm.SPC_M2CMD, spcm.M2CMD_DATA_WAITDMA)) - + # Wait for data transfer to complete, redundant? self.handle_error(spcm.spcm_dwSetParam_i32(self.card, spcm.SPC_M2CMD, spcm.M2CMD_DATA_WAITDMA)) self.log.debug("Card operation stopped") From e452e8ae411a1e8ba5dc53410ac2fb38f077786f Mon Sep 17 00:00:00 2001 From: Toreil Date: Fri, 11 Jul 2025 10:55:02 +0200 Subject: [PATCH 2/4] Simplified ring_buffer_position calculation --- src/console/spcm_control/tx_device.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/console/spcm_control/tx_device.py b/src/console/spcm_control/tx_device.py index a4f9c2e4..f23e8531 100644 --- a/src/console/spcm_control/tx_device.py +++ b/src/console/spcm_control/tx_device.py @@ -438,10 +438,8 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: if avail_bytes.value >= notify_size.value: transfer_count += 1 - ring_buffer_position = ctypes.cast(( - ctypes.c_char * (self.max_ring_buffer_size.value - usr_position.value)).from_buffer( - ring_buffer, usr_position.value), ctypes.c_void_p - ).value + # Calculate position withing ring buffer + ring_buffer_position = ring_buffer_addr + usr_position.value # Get new buffer positions if ring_buffer_position and data_buffer_addr: From 03454cb93bcebdd61e73478186e3a122e0b9083b Mon Sep 17 00:00:00 2001 From: Toreil Date: Fri, 11 Jul 2025 11:09:07 +0200 Subject: [PATCH 3/4] Linter fix --- src/console/spcm_control/tx_device.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/console/spcm_control/tx_device.py b/src/console/spcm_control/tx_device.py index f23e8531..95678bc8 100644 --- a/src/console/spcm_control/tx_device.py +++ b/src/console/spcm_control/tx_device.py @@ -387,7 +387,8 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: if self.data_buffer_size < ring_buffer_size.value: ctypes.memmove(ring_buffer_addr, data_buffer_addr, self.data_buffer_size) transferred_bytes = self.data_buffer_size - else: # Otherwise fill the ring buffer completely with data + else: + # Otherwise fill the ring buffer completely with data ctypes.memmove(ring_buffer_addr, data_buffer_addr, ring_buffer_size.value) transferred_bytes = ring_buffer_size.value except RuntimeError as err: @@ -438,7 +439,7 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: if avail_bytes.value >= notify_size.value: transfer_count += 1 - # Calculate position withing ring buffer + # Calculate position within ring buffer ring_buffer_position = ring_buffer_addr + usr_position.value # Get new buffer positions From 1771732f8f18e9e4f27cb9ecb36c5e2abb1db6cb Mon Sep 17 00:00:00 2001 From: Toreil Date: Tue, 15 Jul 2025 11:39:01 +0200 Subject: [PATCH 4/4] Removed unnecessary try/except statement --- src/console/spcm_control/tx_device.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/console/spcm_control/tx_device.py b/src/console/spcm_control/tx_device.py index 95678bc8..4333adbd 100644 --- a/src/console/spcm_control/tx_device.py +++ b/src/console/spcm_control/tx_device.py @@ -370,7 +370,6 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: raise MemoryError( "Replay data size is not a multiple of enabled channels times 2 (bytes per sample)..." ) - except MemoryError as err: self.log.exception(err, exc_info=True) raise err @@ -381,19 +380,15 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: notify_size.value, ) - try: - # Perform initial memory transfer - # If the data buffer fits in the ring buffer, copy the entire data buffer - if self.data_buffer_size < ring_buffer_size.value: - ctypes.memmove(ring_buffer_addr, data_buffer_addr, self.data_buffer_size) - transferred_bytes = self.data_buffer_size - else: - # Otherwise fill the ring buffer completely with data - ctypes.memmove(ring_buffer_addr, data_buffer_addr, ring_buffer_size.value) - transferred_bytes = ring_buffer_size.value - except RuntimeError as err: - self.log.exception(err, exc_info=True) - raise err + # Perform initial memory transfer + # If the data buffer fits in the ring buffer, copy the entire data buffer + if self.data_buffer_size < ring_buffer_size.value: + ctypes.memmove(ring_buffer_addr, data_buffer_addr, self.data_buffer_size) + transferred_bytes = self.data_buffer_size + else: + # Otherwise fill the ring buffer completely with data + ctypes.memmove(ring_buffer_addr, data_buffer_addr, ring_buffer_size.value) + transferred_bytes = ring_buffer_size.value # Define the transfer buffer spcm.spcm_dwDefTransfer_i64( @@ -474,6 +469,7 @@ def _fifo_stream_worker(self, data: np.ndarray) -> None: transferred_bytes += notify_size.value # Wait for data transfer to complete self.handle_error(spcm.spcm_dwSetParam_i32(self.card, spcm.SPC_M2CMD, spcm.M2CMD_DATA_WAITDMA)) - # Wait for data transfer to complete, redundant? + + # Wait for data transfer to complete self.handle_error(spcm.spcm_dwSetParam_i32(self.card, spcm.SPC_M2CMD, spcm.M2CMD_DATA_WAITDMA)) self.log.debug("Card operation stopped")