Skip to content

Commit

Permalink
Add support for bias updates
Browse files Browse the repository at this point in the history
  • Loading branch information
aMarcireau committed Jul 7, 2023
1 parent 45e3f92 commit 690aa14
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 57 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ neuromorphic_drivers is a library to interact with USB Neuromorphic devices. The
- [Python](#python)
- [Get started](#get-started)
- [Device configuration](#device-configuration)
- [Rate limiter](#rate-limiter)
- [Raw mode](#raw-mode)
- [Other open options](#other-open-options)
- [More examples](#more-examples)
Expand Down Expand Up @@ -82,6 +83,24 @@ with nd.open(configuration=configuration) as device:

`nd.open` may open any supported device. However, it only considers matching devices if a configuration is specified. Passing the wrong configuration type to `update_configuration` raises an error.

## Rate limiter

Prophesee's EVK4 has a hardware event-rate limiter that randomly drops events when the sensor generates more than a given number per second. The limiter has two parameters. `reference_period_us` defines a count period in µs (maximum 200). `maximum_events_per_period` defines the number of events per period beyond which the limiter activates. The effective limit is `maximum_events_per_period / reference_period_us` in events/µs.

```py
import neuromorphic_drivers as nd

configuration = nd.prophesee_evk4.Configuration(
rate_limiter=nd.prophesee_evk4.RateLimiter(
reference_period_us=200,
maximum_events_per_period=4000,
)
)

with nd.open(configuration=configuration) as device:
...
```

## Raw mode

Converting the raw USB data into events can be an expensive operation if the data rate is high. Raw mode skips parsing and can be useful if one simply wishes to store the data into a file to be processed offline.
Expand Down
2 changes: 1 addition & 1 deletion drivers/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub trait Usb: Sized {
where
IntoError: From<Self::Error> + Clone + Send + 'static;

fn next_with_timeout(&mut self, timeout: &std::time::Duration) -> Option<usb::BufferView>;
fn next_with_timeout(&self, timeout: &std::time::Duration) -> Option<usb::BufferView>;

fn serial(&self) -> String;

Expand Down
33 changes: 32 additions & 1 deletion drivers/src/devices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ macro_rules! register {
)+
}
}

pub fn type_name(&self) -> &'static str {
match self {
$(
Configuration::[<$module:camel>](_) => Type::[<$module:camel>].name(),
)+
}
}
}

pub enum Device {
Expand Down Expand Up @@ -165,7 +173,7 @@ macro_rules! register {
}
}

pub fn next_with_timeout(&mut self, timeout: &std::time::Duration) -> Option<usb::BufferView> {
pub fn next_with_timeout(&self, timeout: &std::time::Duration) -> Option<usb::BufferView> {
match self {
$(
Self::[<$module:camel>](device) => device.next_with_timeout(timeout),
Expand Down Expand Up @@ -204,6 +212,23 @@ macro_rules! register {
)+
}
}

pub fn update_configuration(&self, configuration: Configuration) -> Result<(), Error> {
match self {
$(
Self::[<$module:camel>](device) => match configuration {
Configuration::[<$module:camel>](configuration) => {
device.update_configuration(configuration);
Ok(())
},
configuration => Err(Error::UpdateMismatch {
configuration: configuration.type_name().to_owned(),
device: $module::Device::PROPERTIES.name.to_owned(),
})
},
)+
}
}
}

#[derive(Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -250,6 +275,12 @@ macro_rules! register {
#[error("control transfer error (expected {expected:?}, read {read:?})")]
Mismatch { expected: Vec<u8>, read: Vec<u8> },

#[error("configuration for {configuration:?} is not compatible with device {device:?}")]
UpdateMismatch {
configuration: String,
device: String,
},

$(
#[error(transparent)]
[<$module:camel>](#[from] $module::Error),
Expand Down
2 changes: 1 addition & 1 deletion drivers/src/devices/prophesee_evk3_hd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ impl device::Usb for Device {
})
}

fn next_with_timeout(&mut self, timeout: &std::time::Duration) -> Option<usb::BufferView> {
fn next_with_timeout(&self, timeout: &std::time::Duration) -> Option<usb::BufferView> {
self.ring.next_with_timeout(timeout)
}

Expand Down
5 changes: 3 additions & 2 deletions drivers/src/devices/prophesee_evk4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ impl device::Usb for Device {
})
}

fn next_with_timeout(&mut self, timeout: &std::time::Duration) -> Option<usb::BufferView> {
fn next_with_timeout(&self, timeout: &std::time::Duration) -> Option<usb::BufferView> {
self.ring.next_with_timeout(timeout)
}

Expand Down Expand Up @@ -826,7 +826,8 @@ fn update_configuration(
Some(previous_configuration) => {
previous_configuration.x_mask != configuration.x_mask
|| previous_configuration.y_mask != configuration.y_mask
|| previous_configuration.mask_intersection_only != configuration.mask_intersection_only
|| previous_configuration.mask_intersection_only
!= configuration.mask_intersection_only
}
None => true,
} {
Expand Down
25 changes: 21 additions & 4 deletions drivers/src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,15 @@ impl LibusbTransfer {
pub struct Ring {
transfers: Vec<LibusbTransfer>,
handle: std::sync::Arc<rusb::DeviceHandle<rusb::Context>>,
active_buffer_view: std::sync::Arc<std::sync::atomic::AtomicBool>,
#[allow(dead_code)]
event_loop: std::sync::Arc<EventLoop>,
context: std::sync::Arc<RingContext>,
}

unsafe impl Send for Ring {}
unsafe impl Sync for Ring {}

pub enum TransferType {
Control(std::time::Duration),
Isochronous {
Expand Down Expand Up @@ -593,6 +597,7 @@ impl Ring {
let result = Self {
transfers,
handle,
active_buffer_view: std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)),
event_loop,
context,
};
Expand Down Expand Up @@ -645,8 +650,7 @@ pub struct BufferView<'a> {
pub read: usize,
pub write_range: (usize, usize),
pub ring_length: usize,
#[allow(dead_code)]
ring: &'a mut Ring,
active: std::sync::Arc<std::sync::atomic::AtomicBool>,
}

impl BufferView<'_> {
Expand All @@ -661,8 +665,21 @@ impl BufferView<'_> {
}
}

impl Drop for BufferView<'_> {
fn drop(&mut self) {
self.active
.store(false, std::sync::atomic::Ordering::Release);
}
}

impl Ring {
pub fn next_with_timeout(&mut self, duration: &std::time::Duration) -> Option<BufferView> {
pub fn next_with_timeout(&self, duration: &std::time::Duration) -> Option<BufferView> {
if self
.active_buffer_view
.swap(true, std::sync::atomic::Ordering::AcqRel)
{
panic!("the buffer returned by a previous call of next_with_timeout must be dropped before calling next_with_timeout again");
}
let (system_time, slice, read, write_range, ring_length) = {
let start = std::time::Instant::now();
// unwrap: mutex is not poisonned
Expand Down Expand Up @@ -709,7 +726,7 @@ impl Ring {
read,
write_range,
ring_length,
ring: self,
active: self.active_buffer_view.clone(),
})
}
}
Expand Down
4 changes: 2 additions & 2 deletions python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ crate-type = ["cdylib"]

[dependencies]
bincode = "1.3.3"
neuromorphic-drivers = "0.4"
neuromorphic-drivers = {path = "../drivers"}
numpy = "0.19"
paste = "1.0"
pyo3 = {version = "0.19", features = ["extension-module"]}

[build-dependencies]
cc = "1.0"
neuromorphic-drivers = "0.4"
neuromorphic-drivers = {path = "../drivers"}
paste = "1.0"
serde = {version = "1.0", features = ["derive"]}
serde_json = "1.0"
Expand Down
6 changes: 6 additions & 0 deletions python/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,9 @@ macro_rules! generate {
" ...\n",
"\n",
" def speed(self) -> enums.Speed:\n",
" ...\n",
"\n",
" def update_configuration(self, configuration: Configuration):\n",
" ...",
),
class_name,
Expand Down Expand Up @@ -686,6 +689,9 @@ macro_rules! generate {
" ...\n",
"\n",
" def speed(self) -> Speed:\n",
" ...\n",
"\n",
" def update_configuration(self, configuration: Configuration):\n",
" ...",
),
class_name,
Expand Down
5 changes: 5 additions & 0 deletions python/python/neuromorphic_drivers/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,8 @@ def __next__(self):
),
packet,
)

def update_configuration(self, configuration: unions.Configuration) -> None:
return ExtensionDevice.update_configuration(
self, (configuration.type(), configuration.serialize())
)
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ def serial(self) -> str:
def speed(self) -> enums.Speed:
...

def update_configuration(self, configuration: Configuration):
...


class DeviceOptional(typing.Protocol):
def __enter__(self) -> "DeviceOptional":
Expand Down Expand Up @@ -172,6 +175,9 @@ def serial(self) -> str:
def speed(self) -> enums.Speed:
...

def update_configuration(self, configuration: Configuration):
...


class DeviceRaw(typing.Protocol):
def __enter__(self) -> "DeviceRaw":
Expand Down Expand Up @@ -206,6 +212,9 @@ def serial(self) -> str:
def speed(self) -> enums.Speed:
...

def update_configuration(self, configuration: Configuration):
...


class DeviceRawOptional(typing.Protocol):
def __enter__(self) -> "DeviceRawOptional":
Expand Down Expand Up @@ -239,3 +248,6 @@ def serial(self) -> str:

def speed(self) -> enums.Speed:
...

def update_configuration(self, configuration: Configuration):
...
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ def serial(self) -> str:
def speed(self) -> enums.Speed:
...

def update_configuration(self, configuration: Configuration):
...


class DeviceOptional(typing.Protocol):
def __enter__(self) -> "DeviceOptional":
Expand Down Expand Up @@ -186,6 +189,9 @@ def serial(self) -> str:
def speed(self) -> enums.Speed:
...

def update_configuration(self, configuration: Configuration):
...


class DeviceRaw(typing.Protocol):
def __enter__(self) -> "DeviceRaw":
Expand Down Expand Up @@ -220,6 +226,9 @@ def serial(self) -> str:
def speed(self) -> enums.Speed:
...

def update_configuration(self, configuration: Configuration):
...


class DeviceRawOptional(typing.Protocol):
def __enter__(self) -> "DeviceRawOptional":
Expand Down Expand Up @@ -253,3 +262,6 @@ def serial(self) -> str:

def speed(self) -> enums.Speed:
...

def update_configuration(self, configuration: Configuration):
...
12 changes: 12 additions & 0 deletions python/python/neuromorphic_drivers/generated/devices_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ def serial(self) -> str:
def speed(self) -> Speed:
...

def update_configuration(self, configuration: Configuration):
...


class GenericDeviceOptional(typing.Protocol):
def __enter__(self) -> "GenericDeviceOptional":
Expand Down Expand Up @@ -81,6 +84,9 @@ def serial(self) -> str:
def speed(self) -> Speed:
...

def update_configuration(self, configuration: Configuration):
...


class GenericDeviceRaw(typing.Protocol):
def __enter__(self) -> "GenericDeviceRaw":
Expand Down Expand Up @@ -115,6 +121,9 @@ def serial(self) -> str:
def speed(self) -> Speed:
...

def update_configuration(self, configuration: Configuration):
...


class GenericDeviceRawOptional(typing.Protocol):
def __enter__(self) -> "GenericDeviceRawOptional":
Expand Down Expand Up @@ -149,6 +158,9 @@ def serial(self) -> str:
def speed(self) -> Speed:
...

def update_configuration(self, configuration: Configuration):
...


@typing.overload
def open(
Expand Down
Loading

0 comments on commit 690aa14

Please sign in to comment.