Skip to main content

Overview

The CL1 neural interface provides the bridge between digital game states and biological neural activity. The system uses electrical stimulation to encode game observations into neural activity, then reads out spike patterns to decode movement commands.

CL1 Hardware Architecture

Biological Neurons

The CL1 device contains living biological neurons cultured on a multi-electrode array (MEA):
  • 64 electrode channels for simultaneous recording and stimulation
  • 59 usable channels (5 reserved by hardware: 0, 4, 7, 56, 63)
  • Bidirectional interface: Both stimulate and record from same neurons
  • Real-time operation: Stimulation and recording occur simultaneously

Channel Organization

Functional Groups

Channels are organized into 8 functional groups for different purposes:
Each functional group contains multiple channels to provide redundancy and richer neural representations. The encoder learns which channels to stimulate for different game states.

Reserved Channels

These channels are reserved by the CL1 hardware for:
  • Internal calibration and reference signals
  • Hardware diagnostics
  • Quality control measurements
Attempting to stimulate reserved channels will raise a ValueError during configuration initialization. The system validates channel assignments in PPOConfig.__post_init__().

Stimulation Protocol

Biphasic Pulse Design

The CL1 interface uses charge-balanced biphasic pulses to safely stimulate neurons:
Why Biphasic?
  1. Charge balance: Equal positive and negative charge prevents electrode degradation
  2. Neural safety: Avoids DC current that could damage neurons
  3. Prevents polarization: Maintains stable electrode-electrolyte interface

Burst Stimulation

Stimulation is delivered in bursts at specified frequencies:
Burst Parameters:
  • Frequency range: 4-40 Hz
    • Low frequencies (4-10 Hz): Sparse, discrete stimulation
    • High frequencies (30-40 Hz): Dense, sustained stimulation
  • Burst count: 1 pulse per tick (CL1 device operates at 10 Hz)
  • Inter-pulse interval: Determined by frequency (25-250 ms)
The encoder learns to map different game states to different frequency/amplitude combinations. For example, seeing an enemy might trigger 35 Hz at 2.3 μA, while being alone might produce 8 Hz at 1.2 μA.

Stimulation Application

The CL1 device applies stimulation in a tight loop:
Key Design Decisions:
  1. Interrupt before stimulation: Ensures clean state, prevents overlapping bursts
  2. Per-channel stimulation: Each encoding channel gets unique frequency/amplitude
  3. Caching: Avoids recreating identical StimDesign objects (LRU cache, 2048 entries)

Spike Collection

Real-Time Spike Detection

The CL SDK continuously monitors all channels for action potentials:
Spike Aggregation:
  • Spikes are counted per functional group, not per channel
  • Example: If channels 8, 9, 10 (encoding group) each fire once, spike_counts[0] = 3
  • This pooling provides a more robust signal than individual channels

Channel Lookup Table

Hardware Loop

Main Loop Operation

The CL1 device runs a continuous loop synchronized to hardware tick rate:
Timing:
  • Default: 10 Hz (100 ms per tick)
  • Configurable via --tick-frequency flag
  • Higher frequencies = better temporal resolution, more network traffic
The 10 Hz tick rate balances several factors:
  1. Neural time constants: Biological neurons typically respond on ~10-100 ms timescales
  2. Game timestep: VizDoom updates at 35 Hz, but movement commands are valid for multiple frames
  3. Network latency: UDP packets take ~1-5 ms on local network; 100 ms tick allows headroom
  4. Stimulation duration: Burst stimulation needs time to evoke responses before next command
Faster rates (e.g., 100 Hz) could be used but provide diminishing returns given neural response times.

Non-Blocking UDP

The CL1 interface uses non-blocking sockets to prevent hardware loop stalls:
Benefits:
  1. Hardware loop never blocks waiting for packets
  2. Missing packets default to zero stimulation (safe fallback)
  3. Prevents network issues from disrupting neural recording

CL SDK Integration

Opening Connection

The cl.open() context manager:
  • Establishes connection to CL1 hardware
  • Initializes electrode array
  • Provides neurons interface for stimulation and recording
  • Ensures cleanup on exit

Recording Neural Data

Recordings capture:
  • Spike times: Precise timestamps for each action potential
  • Channel IDs: Which electrode detected each spike
  • Stimulation events: When and how neurons were stimulated
  • Metadata: Experimental parameters, timestamps, attributes

Data Streams for Events

Data streams provide synchronized event logging:
  • Timestamped episode metadata
  • Reward signals for offline analysis
  • Training progress markers

Stimulation Design Caching

LRU Cache Implementation

Why Cache? Creating cl.StimDesign and cl.BurstDesign objects has overhead:
  • Object allocation
  • Parameter validation
  • Internal CL SDK setup
With 10 Hz stimulation and similar game states, many cache hits occur:
Cache Size: 2048 entries is sufficient because:
  • 8 channels × ~10 frequency values × ~15 amplitude values ≈ 1200 combinations
  • Rarely-used combinations naturally evict from LRU

Biological Considerations

Stimulation Safety

Stimulation parameters are carefully bounded to ensure neuron health:
  • Amplitude: 1.0-2.5 μA (microamperes)
    • Below: Insufficient to evoke spikes
    • Above: Risk of over-stimulation and neuron damage
  • Frequency: 4-40 Hz
    • Below: Too sparse for meaningful encoding
    • Above: Risk of depolarization block
  • Pulse duration: 120 μs per phase
    • Long enough to depolarize membrane
    • Short enough to avoid electrochemical damage

Neural Response Characteristics

Spike Generation:
  • Neurons fire when membrane potential exceeds threshold (~-55 mV)
  • Stimulation pulses inject current, causing depolarization
  • Response latency: ~2-10 ms after pulse onset
  • Refractory period: ~1-5 ms (limits max firing rate)
Adaptation:
  • Repeated stimulation can cause spike rate adaptation
  • Synaptic plasticity may alter response patterns over training
  • Encoder must learn to compensate for neural adaptation
Noise:
  • Spontaneous activity: Neurons fire even without stimulation (~0.1-5 Hz)
  • Response variability: Same stimulus can evoke different spike counts
  • Decoder must be robust to neural noise

Performance Monitoring

Statistics Logging

Key Metrics:
  • Packet rates: Should match tick frequency (10 pkt/s for 10 Hz)
  • Average spikes: Typical range 5-50 spikes/tick depending on stimulation
  • Events/feedback: Confirms training system communication

Latency Measurement

Typical latencies:
  • Local network: 1-5 ms
  • Same machine (localhost): < 1 ms
  • WiFi: 5-20 ms
If latency exceeds 50 ms, investigate network congestion or CPU overload on either system. High latency can cause stimulation-spike timing mismatches.

Troubleshooting

Common Issues

Possible causes:
  1. Stimulation amplitude too low (< 1.0 μA)
  2. Neurons not healthy (check CL1 viability indicators)
  3. Reserved channels being used (check channel configuration)
  4. Electrode impedance too high (check CL SDK diagnostics)
Solutions:
  • Increase min_amplitude in PPOConfig
  • Verify neuron culture health via CL SDK
  • Review channel assignments in encoding_channels
  • Run CL1 impedance test to check electrode quality
Possible causes:
  1. Stimulation amplitude too high (> 3.0 μA)
  2. Frequency too high (> 50 Hz)
  3. Overlapping stimulation bursts
Solutions:
  • Decrease max_amplitude in PPOConfig
  • Ensure burst_count = 1 for 10 Hz loop
  • Verify neurons.interrupt() called before stimulation
Symptoms:
  • Receive rate much less than tick frequency
  • Frequent “No packet available” warnings
Solutions:
  • Check network connectivity (ping CL1 device)
  • Reduce tick frequency if CPU overloaded
  • Increase socket buffer size: socket.setsockopt(SOL_SOCKET, SO_RCVBUF, 65536)
  • Use wired Ethernet instead of WiFi