Skip to content

Knight Board Firmware

The NeuroPawn library provides the acquisition core as a precompiled Arduino library for the ATmega328P Knight Board. Your firmware owns the normal Arduino setup() and loop() functions while the library configures the EEG front-end, collects samples, emits binary frames, and services host commands.

For installation and upload instructions, start with Uploading Custom Firmware.

#include <NeuroPawn.h>
void setup() {
neuropawn.setup(NP_DEFAULT);
}
void loop() {
neuropawn.acquire_data();
// Run short, non-blocking application tasks here.
}

setup() starts serial at 115200 baud and configures the acquisition hardware. acquire_data() is non-blocking and sends one frame whenever a new sample is ready. It must run on every loop iteration.

CallPurpose
neuropawn.init_globals(mode)Reset internal state. Optional because setup() calls it automatically
neuropawn.setup(mode)Initialize serial, EEG, and optional IMU; returns front-end readiness
neuropawn.acquire_data(mode)Emit new samples and service host commands without blocking
neuropawn.quiet(true)Suppress human-readable boot messages; call before setup()
neuropawn.ready()Report whether the EEG front-end was detected and configured
neuropawn.imu_present()Report whether the IMU responded on I2C
neuropawn.mode()Return the configured mode
neuropawn.frame_counter()Return the rolling 0-255 frame counter
NeuroPawnBoard::pin_available(pin)Check whether a pin is available in the current mode

acquire_data() defaults to NP_AS_CONFIGURED, which reuses the mode passed to setup().

ModeFrame sizeBehavior
NP_DEFAULT21 bytesEight EEG channels; I2C is not initialized and A4/A5 remain free
NP_IMU57 bytesEEG plus acceleration, gyroscope, and magnetometer data
NP_AS_CONFIGURED-Reuse the mode selected by setup()

NP_IMU also requires a firmware build compiled with NEUROPAWN_IMU. Without that build flag it behaves like NP_DEFAULT. When IMU support is compiled in but no sensor responds, the firmware preserves the 57-byte layout and fills the 36-byte IMU payload with zeroes.

See Knight Board Data Format for byte-level packet layouts and Creating a Custom Data Parser for a complete host parser.

The acquisition core owns the following resources. Do not reconfigure or drive them from application code.

PinUse
D0, D1USB serial data link
D3EEG acquisition
D8-D13EEG acquisition and SPI; D13 LED is not available
A4, A5I2C in NP_IMU mode
PinCapability
D2Digital I/O and INT0
D4Digital I/O
D5, D6Digital I/O and Timer0 PWM
D7Digital I/O
A0-A3Analog input or digital I/O
A6, A7Analog input only
A4, A5Available only in NP_DEFAULT

Call NeuroPawnBoard::pin_available(pin) before configuring a pin whose availability depends on the selected mode.

ResourceConstraint
SerialLibrary-owned binary link; never write application text to it
SPILibrary-owned; do not attach another SPI device
I2CMay be shared in IMU mode except at IMU addresses 0x68 and 0x69
Timer0Used by millis(), micros(), and delay(); do not reprogram it
Timer1, Timer2Available, although Arduino tone() uses Timer2
RAMAbout 280 B for EEG-only or 920 B for an IMU build, out of 2048 B
FlashAbout 7.5 kB for EEG-only or 21 kB for an IMU build, out of 30.7 kB

After startup, all EEG channels are powered down and the right-leg-drive (RLD) derivation is empty. acquire_data() listens for ASCII commands on the same serial link to enable channels, choose gains, and configure RLD. The binary stream continues around those commands.

See the Command Set for supported commands and the custom firmware guide for the timing and serial rules application code must follow.