Overview
cl1_neural_interface.py is a minimal hardware interface server that runs directly on the CL1 device. It handles all neural hardware operations while the training logic runs remotely.
Responsibilities:
- Receive stimulation commands via UDP from training server
- Apply stimulation to biological neurons using CL SDK
- Collect spike responses from neural hardware
- Send spike counts back to training server via UDP
- Record neural activity to disk
- Log event metadata to CL DataStream
- Zero computation: No PyTorch, no game logic, no policy inference
- Pure I/O: UDP receive → hardware stimulation → spike collection → UDP send
- Real-time: Hardware loop runs at configurable tick frequency (typically 10-240 Hz)
source/cl1_neural_interface.py
Command-Line Arguments
Network Configuration
IP address of the remote training systemRequired parameter. The CL1 device sends spike data to this address.Example:
--training-host 192.168.1.50UDP port for receiving stimulation commands from training systemThe CL1 device listens on this port (bound to
0.0.0.0).Must match --cl1-stim-port on training server.UDP port for sending spike data to training systemThe CL1 device sends spike packets to
<training-host>:<spike-port>.Must match --cl1-spike-port on training server.UDP port for receiving event metadata from training systemEvents include episode completions, checkpoints, and training completion signals.Must match
--cl1-event-port on training server.UDP port for receiving feedback stimulation commands from training systemFeedback includes reward signals and event-based stimulation.Must match
--cl1-feedback-port on training server.Hardware Configuration
Frequency (Hz) to run the CL hardware loopControls the rate of:
- Applying neural stimulation
- Collecting spike responses
- Sending spike data to training system
10 Hz: Slow, stable, good for debugging30 Hz: Normal gameplay speed60 Hz: Fast gameplay120-240 Hz: Maximum performance (experimental)
--tick_frequency_hz on training server.Directory path for saving CL1 neural recordingsRecordings contain raw neural data (spikes, stimulation, events) captured during training.Example:
--recording-path /data/recordings/doom-neuronUsage Examples
Basic Setup
Custom Ports
High-Frequency Loop
Custom Recording Location
Architecture
CL1Config Class
Minimal configuration matching the training system:CL1NeuralInterface Class
Main interface class with methods:setup_sockets()
Create and bind UDP sockets for communication.
apply_stimulation(neurons, frequencies, amplitudes)
Apply stimulation to neural hardware based on received commands.
Parameters:
neurons: CL SDK neurons interfacefrequencies: np.ndarray of shape(num_channel_sets,)with Hz valuesamplitudes: np.ndarray of shape(num_channel_sets,)with μA values
- Interrupt ongoing stimulation on all channels
- For each encoding channel, create
StimDesignandBurstDesign - Apply stimulation via
neurons.stim() - Cache designs to avoid repeated object creation
collect_spikes(tick)
Collect and count spikes from CL SDK tick.
Parameters:
tick:cl.LoopTickobject fromneurons.loop()
spike_counts: np.ndarray of shape(num_channel_sets,)with spike counts per channel group
- Initialize zero array for spike counts
- Iterate through
tick.analysis.spikes - Map each spike’s channel to its group index
- Increment corresponding group counter
apply_feedback_command(neurons, feedback_type, channels, frequency, amplitude, pulses, unpredictable, event_name)
Apply feedback stimulation to neural hardware.
Parameters:
neurons: CL SDK neurons interfacefeedback_type:"interrupt","event", or"reward"channels: List of channel numbersfrequency: Stimulation frequency in Hzamplitude: Stimulation amplitude in μApulses: Number of pulses/burstsunpredictable: Whether this is unpredictable stimulationevent_name: Name of event (for logging)
interrupt: Stop ongoing stimulation on specified channelsevent: Apply event-based feedback (kills, damage, pickups)reward: Apply reward-based feedback (positive/negative)
run()
Main hardware loop:
Hardware Loop Details
Stimulation Design Caching
To avoid creating newStimDesign and BurstDesign objects every tick, designs are cached using an LRU cache:
Channel Mapping
Spikes are mapped to channel groups for counting:Non-Blocking I/O
All UDP sockets use non-blocking mode to prevent loop stalling:- No stimulation command → continue with previous stimulation
- No event → continue loop
- No feedback → continue loop
Recording & Logging
CL Recording
Neural recordings are saved to disk automatically:- Raw spike data (all channels)
- Stimulation commands
- Timestamps
- Metadata attributes
DataStream Events
Episode metadata is logged to a CL DataStream:Statistics Logging
Statistics are printed every 10 seconds:ticks: Total hardware loop iterations in this periodRecv: Stimulation packets received per secondSend: Spike packets sent per secondEvents: Event metadata packets receivedFeedback: Feedback command packets receivedAvg spikes: Average spike count per tick across all channel groups
Graceful Shutdown
The interface handles shutdown gracefully:Training Complete Event
When the training system sends atraining_complete event:
Keyboard Interrupt
When interrupted with Ctrl+C:Troubleshooting
CL SDK Connection Failed
- Ensure CL1 device is powered on
- Check USB connection
- Verify CL SDK is installed:
python -c "import cl" - Run with
sudoif permission denied
No Stimulation Commands Received
- Verify training system is running
- Check network connectivity:
ping <training-host> - Ensure firewall allows UDP on stim port
- Verify port numbers match on both systems
High Latency
- Use wired network instead of WiFi
- Reduce network traffic on shared network
- Check for CPU throttling on CL1 device
- Reduce tick frequency temporarily
Recording Failed to Save
- Ensure recording path exists:
mkdir -p /data/recordings/doom-neuron - Check disk space:
df -h - Verify write permissions:
ls -ld /data/recordings
See Also
- training_server.py - Remote training server
- udp_protocol.py - UDP packet formats
- ppo_doom.py - Direct CL1 training script