147 lines
5.3 KiB
Python
147 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
|
import argparse
|
|
import yaml
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
|
|
def print_separator(char='-', length=70):
|
|
print(char * length)
|
|
|
|
|
|
def format_value(value, suffix=''):
|
|
if isinstance(value, float):
|
|
return f"{value:.3f}{suffix}"
|
|
return f"{value}{suffix}"
|
|
|
|
|
|
def display_results(yaml_file: Path):
|
|
with open(yaml_file, 'r') as f:
|
|
data = yaml.safe_load(f)
|
|
|
|
metadata = data['metadata']
|
|
results = data['test_results']
|
|
|
|
print("\n" + "=" * 70)
|
|
print(f" AUDIO TEST RESULTS")
|
|
print("=" * 70)
|
|
|
|
print("\n📋 Test Metadata:")
|
|
print_separator()
|
|
print(f" Test ID: {metadata['test_id']}")
|
|
print(f" Timestamp: {metadata['timestamp']}")
|
|
print(f" PCB Version: {metadata['pcb_version']}")
|
|
print(f" PCB Revision: {metadata['pcb_revision']}")
|
|
print(f" Software Version: {metadata['software_version']}")
|
|
if metadata.get('notes'):
|
|
print(f" Notes: {metadata['notes']}")
|
|
|
|
if 'latency_test' in data:
|
|
latency = data['latency_test']
|
|
print("\n🎯 Latency Test (Chirp):")
|
|
print_separator()
|
|
if 'error' in latency:
|
|
print(f" Error: {latency['error']}")
|
|
else:
|
|
print(f" Average: {latency['avg']:.3f} ms")
|
|
print(f" Min: {latency['min']:.3f} ms")
|
|
print(f" Max: {latency['max']:.3f} ms")
|
|
print(f" Std Dev: {latency['std']:.4f} ms")
|
|
|
|
print("\n📊 Frequency Sweep Results:")
|
|
print_separator()
|
|
|
|
header = f"{'Freq (Hz)':<12} {'THD CH1 (%)':<13} {'THD CH2 (%)':<13} {'SNR CH1 (dB)':<14} {'SNR CH2 (dB)':<14}"
|
|
print(header)
|
|
print(f"{'':12} {'(Loopback)':<13} {'(DUT)':<13} {'(Loopback)':<14} {'(DUT)':<14}")
|
|
print_separator()
|
|
|
|
for result in results:
|
|
if 'error' in result:
|
|
print(f"{result['frequency_hz']:<12} ERROR: {result['error']}")
|
|
else:
|
|
freq = result['frequency_hz']
|
|
thd_ch1 = format_value(result.get('thd_ch1_loopback_percent', result.get('thd_input_percent', 0)))
|
|
thd_ch2 = format_value(result.get('thd_ch2_dut_percent', result.get('thd_output_percent', 0)))
|
|
snr_ch1 = format_value(result.get('snr_ch1_loopback_db', result.get('snr_input_db', 0)))
|
|
snr_ch2 = format_value(result.get('snr_ch2_dut_db', result.get('snr_output_db', 0)))
|
|
|
|
print(f"{freq:<12} {thd_ch1:<13} {thd_ch2:<13} {snr_ch1:<14} {snr_ch2:<14}")
|
|
|
|
print_separator()
|
|
|
|
valid_results = [r for r in results if 'error' not in r]
|
|
if valid_results:
|
|
avg_thd_ch1 = sum(r.get('thd_ch1_loopback_percent', r.get('thd_input_percent', 0)) for r in valid_results) / len(valid_results)
|
|
avg_thd_ch2 = sum(r.get('thd_ch2_dut_percent', r.get('thd_output_percent', 0)) for r in valid_results) / len(valid_results)
|
|
avg_snr_ch1 = sum(r.get('snr_ch1_loopback_db', r.get('snr_input_db', 0)) for r in valid_results) / len(valid_results)
|
|
avg_snr_ch2 = sum(r.get('snr_ch2_dut_db', r.get('snr_output_db', 0)) for r in valid_results) / len(valid_results)
|
|
|
|
print("\n📈 Average Values:")
|
|
print_separator()
|
|
print(f" THD CH1 (Loopback): {avg_thd_ch1:.3f} %")
|
|
print(f" THD CH2 (DUT): {avg_thd_ch2:.3f} %")
|
|
print(f" SNR CH1 (Loopback): {avg_snr_ch1:.2f} dB")
|
|
print(f" SNR CH2 (DUT): {avg_snr_ch2:.2f} dB")
|
|
|
|
print("\n" + "=" * 70 + "\n")
|
|
|
|
|
|
def list_all_results(results_dir: Path):
|
|
yaml_files = sorted(results_dir.glob("*_results.yaml"))
|
|
|
|
if not yaml_files:
|
|
print("No test results found.")
|
|
return
|
|
|
|
print("\n" + "=" * 70)
|
|
print(" AVAILABLE TEST RESULTS")
|
|
print("=" * 70 + "\n")
|
|
|
|
for yaml_file in yaml_files:
|
|
try:
|
|
with open(yaml_file, 'r') as f:
|
|
data = yaml.safe_load(f)
|
|
|
|
metadata = data['metadata']
|
|
timestamp = datetime.fromisoformat(metadata['timestamp'])
|
|
|
|
print(f"📄 {yaml_file.name}")
|
|
print(f" Date: {timestamp.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
print(f" PCB: {metadata['pcb_version']} Rev {metadata['pcb_revision']}")
|
|
print(f" SW: {metadata['software_version']}")
|
|
if metadata.get('notes'):
|
|
print(f" Note: {metadata['notes']}")
|
|
print()
|
|
except Exception as e:
|
|
print(f"⚠️ {yaml_file.name} (corrupted - skipping)")
|
|
print()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='View PCB test results')
|
|
parser.add_argument('file', nargs='?', help='YAML results file to view')
|
|
parser.add_argument('--list', action='store_true', help='List all available test results')
|
|
parser.add_argument('--results-dir', default='test_results', help='Directory containing results')
|
|
|
|
args = parser.parse_args()
|
|
|
|
results_dir = Path(args.results_dir)
|
|
|
|
if args.list or not args.file:
|
|
list_all_results(results_dir)
|
|
else:
|
|
yaml_file = Path(args.file)
|
|
if not yaml_file.exists():
|
|
yaml_file = results_dir / args.file
|
|
|
|
if not yaml_file.exists():
|
|
print(f"Error: File not found: {yaml_file}")
|
|
return 1
|
|
|
|
display_results(yaml_file)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|