#!/usr/bin/env python3
"""
Decode SPI data from 4 digital channels
Typical SPI uses: CLK, MOSI, MISO, CS/SS
"""
import struct

def read_saleae_digital(filename):
    """Read Saleae digital channel file"""
    with open(filename, 'rb') as f:
        data = f.read()
    
    # Skip header (look for the pattern after <SALEAE> header)
    # The actual data starts after the metadata
    header_end = data.find(b'<SALEAE>') + 100
    return data[header_end:]

def extract_bytes_from_channels():
    """Try to extract byte data by combining the 4 channels"""
    
    # Read all 4 channels
    channels = []
    for i in range(4):
        data = read_saleae_digital(f"extracted/digital-{i}.bin")
        print(f"[+] Channel {i}: {len(data)} bytes")
        channels.append(data)
    
    # Try to find synchronization and extract bytes
    # Take the shortest length
    min_len = min(len(ch) for ch in channels)
    
    print(f"\n[*] Processing {min_len} bytes...")
    
    # Try simple approach: treat each channel as a bit
    # and reconstruct bytes
    extracted = []
    
    for i in range(min_len):
        # Combine 4 bits from 4 channels
        byte_val = 0
        for ch_idx in range(4):
            if channels[ch_idx][i] & 1:  # Check LSB
                byte_val |= (1 << ch_idx)
        
        extracted.append(byte_val)
    
    return extracted

def find_UID_in_data(data):
    """Look for UID pattern - typically 4 bytes starting with 0x04 or 0x08"""
    print("\n[*] Searching for UID patterns...")
    
    for i in range(len(data) - 8):
        # Check for UID-like patterns
        if data[i] in [0x04, 0x08]:
            # Get potential UID
            potential_uid = data[i:i+4]
            if len(set(potential_uid)) >= 2:  # At least 2 different bytes
                uid_hex = ''.join(f'{b:02x}' for b in potential_uid)
                
                # Check surrounding data
                context = data[max(0, i-8):i+20]
                context_hex = ' '.join(f'{b:02x}' for b in context)
                print(f"\n  Position {i:06x}: UID={uid_hex}")
                print(f"  Context: {context_hex}")

def find_ascii_blocks(data):
    """Find blocks that look like ASCII text (names)"""
    print("\n[*] Searching for ASCII text blocks...")
    
    i = 0
    while i < len(data) - 16:
        block = data[i:i+16]
        ascii_count = sum(1 for b in block if 32 <= b < 127)
        
        if ascii_count >= 6:  # At least 6 printable characters
            hex_str = ' '.join(f'{b:02x}' for b in block)
            ascii_str = ''.join(chr(b) if 32 <= b < 127 else '.' for b in block)
            print(f"\n  Position {i:06x}:")
            print(f"  Hex:   {hex_str}")
            print(f"   ASCII: {ascii_str}")
        i += 1

# Main execution
print("="*70)
print("RFID Data Extraction from Saleae Capture")
print("="*70)

extracted_data = extract_bytes_from_channels()

print(f"\n[+] Extracted {len(extracted_data)} bytes")

# Show first 256 bytes as hex
print("\n[*] First 256 bytes:")
for i in range(0, min(256, len(extracted_data)), 16):
    chunk = extracted_data[i:i+16]
    hex_str = ' '.join(f'{b:02x}' for b in chunk)
    ascii_str = ''.join(chr(b) if 32 <= b < 127 else '.' for b in chunk)
    print(f'{i:04x}  {hex_str:<48}  {ascii_str}')

# Search for UID
find_UID_in_data(extracted_data)

# Search for ASCII (potential names)
find_ascii_blocks(extracted_data)
