1# Copyright (c) 2023-2024 Intel Corporation 2# 3# SPDX-License-Identifier: Apache-2.0 4 5# Sample code showing an external tool Python module helper for Saleae Logic 2 6# compatible logic analyzer. 7# To use it, the Saleae Logic 2 Automation server must be enabled. For more 8# information on it, check 9# https://saleae.github.io/logic2-automation/getting_started.html 10 11import numpy as np 12import tempfile 13 14from pathlib import Path 15from saleae import automation 16from saleae.automation import (CaptureConfiguration, LogicDeviceConfiguration, 17DigitalTriggerCaptureMode, DigitalTriggerType) 18 19def do_collection(device_id, address, port, channel, sample_rate, threshold_volts, 20 seconds, output_dir): 21 with automation.Manager.connect(address=address, port=port) as manager: 22 23 device_configuration = LogicDeviceConfiguration( 24 enabled_digital_channels=[channel], 25 digital_sample_rate=sample_rate, 26 digital_threshold_volts=threshold_volts, 27 ) 28 29 capture_mode = DigitalTriggerCaptureMode(DigitalTriggerType.RISING, 30 channel, 31 after_trigger_seconds=seconds) 32 capture_configuration = CaptureConfiguration(capture_mode=capture_mode) 33 34 with manager.start_capture( 35 device_id=device_id, 36 device_configuration=device_configuration, 37 capture_configuration=capture_configuration) as capture: 38 39 capture.wait() 40 41 capture.export_raw_data_csv(directory=output_dir, 42 digital_channels=[channel]) 43 44def do_analysis(output_dir): 45 file_name = Path(output_dir) / 'digital.csv' 46 all_data = np.loadtxt(file_name, delimiter=',', skiprows=1, usecols=0) 47 48 # Pre trigger data is negative on CSV 49 non_negative = all_data[all_data >= 0] 50 51 # Last sample is just captured at last moment of capture, not related 52 # to gpio toggle. Discard it 53 data = non_negative[:-1] 54 55 diff = np.diff(data) 56 57 mean = np.mean(diff) 58 std = np.std(diff) 59 var = np.var(diff) 60 minimum = np.min(diff) 61 maximum = np.max(diff) 62 total_time = data[-1] 63 64 return {'mean': mean, 'stddev': std, 'var': var, 'min': minimum, 65 'max': maximum, 'total_time': total_time}, len(diff) 66 67 68# options should be a string of the format: 69# [device-id=<device_id>,]port=<saleae_logic2_server_port>, 70# channel=<channel_number>,sample-rate=<sample-rate>, 71# threshold-volts=<threshold-volts> 72def run(seconds, options): 73 options = [i for p in options.split(',') for i in p.split('=')] 74 options = dict(zip(options[::2], options[1::2])) 75 76 device_id = options.get('device-id') 77 address = str(options.get('address')) 78 port = int(options.get('port')) 79 channel = int(options.get('channel')) 80 sample_rate = int(options.get('sample-rate')) 81 threshold_volts = float(options.get('threshold-volts')) 82 83 with tempfile.TemporaryDirectory() as output_dir: 84 output_dir = tempfile.mkdtemp() 85 # Add one second to ensure all data is captured 86 do_collection(device_id, address, port, channel, sample_rate, threshold_volts, 87 seconds + 1, output_dir) 88 89 return do_analysis(output_dir) 90