msobral commited on
Commit
de0bff3
1 Parent(s): e614a99

create package and added recent code

Browse files
pyproject.toml ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
setup.cfg ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [metadata]
2
+ name=portiloop
3
+ version=0.0.1
4
+ description="Library for portiloop"
5
+
6
+ [options]
7
+ package_dir=
8
+ =src
9
+ packages=find:
10
+ install_requires=
11
+ matplotlib
12
+ numpy
13
+ portilooplot
14
+
15
+ [options.packages.find]
16
+ where=src
setup.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name='portiloop',
5
+ version='0.0.1',
6
+ packages=[package for package in find_packages(where='src')],
7
+ description='Library for portiloop',
8
+ install_requires=['numpy',
9
+ 'matplotlib',
10
+ 'portilooplot']
11
+ )
src/__init__.py ADDED
File without changes
src/capture.py CHANGED
@@ -3,16 +3,40 @@ import threading
3
  import time
4
  import logging
5
  import random
6
- import Queue
7
 
8
- from frontend import Frontend
9
- from leds import LEDs, Color
10
  from portilooplot.jupyter_plot import ProgressPlot
11
 
12
  import ctypes
13
  import numpy as np
14
  import json
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  class Datapoint:
18
  '''
@@ -21,7 +45,7 @@ class Datapoint:
21
  def __init__(self, raw_datapoint, temperature=[], num_channels=8):
22
  # Initialize necessary data structures
23
  self.num_channels = num_channels
24
- self.reading = np.array(num_channels, dtype=float)
25
 
26
  assert len(temperature) <= len(raw_datapoint), "Temperature array length must be lesser or equal to number of channels"
27
  self.temperature = temperature
@@ -114,21 +138,24 @@ class CaptureThread(threading.Thread):
114
 
115
  # Read values and add to q
116
  values = self.frontend.read()
117
- self.q.put(values)
118
 
119
  # Wait until reading is fully ompleted
120
  while self.frontend.is_ready():
121
  pass
122
 
123
  # Check for timeout
124
- if time.time() - start_time > self.timeout:
125
- break
 
126
  return
127
 
128
  def init_checks(self):
129
  '''
130
  Run Initial threads to the registers to make sure we can start reading
131
  '''
 
 
132
  data = self.frontend.read_regs(0x00, len(FRONTEND_CONFIG))
133
  assert data == FRONTEND_CONFIG, f"Wrong config: {data} vs {FRONTEND_CONFIG}"
134
  self.frontend.start()
@@ -164,14 +191,15 @@ class FilterThread(threading.Thread):
164
  # Get an item from CaptureThread
165
  if not self.raw_q.empty():
166
  raw_data = self.raw_q.get()
167
- assert raw_data is not None, "Got a None item from CaptureThread in FilterThread"
168
-
 
169
  datapoint = Datapoint(raw_data, )
170
 
171
  # Put Item to all ConsumerThreads
172
  for q in self.qs:
173
  if not q.full():
174
- q.put(item)
175
  return
176
 
177
  def add_q(self, q):
@@ -279,9 +307,9 @@ class Capture:
279
  self.record = record
280
 
281
  # Initialize data structures for capture and filtering
282
- raw_q = Queue.Queue()
283
- self.capture_thread = CaptureThread(raw_q)
284
- self.filter_thread = FilterThread(raw_q)
285
 
286
  # Declare data structures for viz and record functionality
287
  self.viz_q = None
@@ -299,8 +327,8 @@ class Capture:
299
  self.start_record()
300
 
301
  def start_viz(self):
302
- self.viz_q = Queue.Queue()
303
- self.viz_thread = DisplayThread(self.viz_q)
304
  self.filter_thread.add_q(self.viz_q)
305
  self.viz_thread.start()
306
 
@@ -310,8 +338,8 @@ class Capture:
310
  self.viz_thread.raise_exception()
311
 
312
  def start_record(self):
313
- self.record_q = Queue.Queue()
314
- self.record_thread = SaveThread(self.record_q)
315
  self.filter_thread.add_q(self.record_q)
316
  self.record_thread.start()
317
 
 
3
  import time
4
  import logging
5
  import random
6
+ from queue import Queue
7
 
8
+ from hardware.frontend import Frontend
9
+ from hardware.leds import LEDs, Color
10
  from portilooplot.jupyter_plot import ProgressPlot
11
 
12
  import ctypes
13
  import numpy as np
14
  import json
15
 
16
+ FRONTEND_CONFIG = [
17
+ 0x3E, # ID (RO)
18
+ 0x95, # CONFIG1 [95] [1, DAISY_EN(bar), CLK_EN, 1, 0, DR[2:0]] : Datarate = 500 SPS
19
+ 0xD0, # CONFIG2 [C0] [1, 1, 0, INT_CAL, 0, CAL_AMP0, CAL_FREQ[1:0]]
20
+ 0xE0, # CONFIG3 [E0] [PD_REFBUF(bar), 1, 1, BIAS_MEAS, BIASREF_INT, PD_BIAS(bar), BIAS_LOFF_SENS, BIAS_STAT] : Power-down reference buffer, no bias
21
+ 0x00, # No lead-off
22
+ 0x03, # CH1SET [60] [PD1, GAIN1[2:0], SRB2, MUX1[2:0]] test signal
23
+ 0x00, # CH2SET
24
+ 0x00, # CH3SET
25
+ 0x00, # CH4SET voltage DVDD / 4
26
+ 0x03, # CH5SET voltage 0.5 × (AVDD + AVSS)
27
+ 0x03, # CH6SET
28
+ 0x05, # CH7SET test
29
+ 0x04, # CH8SET temperature
30
+ 0x00, # BIAS_SENSP
31
+ 0x00, # BIAS_SENSN
32
+ 0xFF, # LOFF_SENSP Lead-off on all positive pins?
33
+ 0xFF, # LOFF_SENSN Lead-off on all negative pins?
34
+ 0x00, # Normal lead-off
35
+ 0x00, # Lead-off positive status (RO)
36
+ 0x00, # Lead-off negative status (RO)
37
+ 0x00, # All GPIOs as output ?
38
+ 0x20, # Enable SRB1
39
+ ]
40
 
41
  class Datapoint:
42
  '''
 
45
  def __init__(self, raw_datapoint, temperature=[], num_channels=8):
46
  # Initialize necessary data structures
47
  self.num_channels = num_channels
48
+ self.reading = np.empty(num_channels, dtype=float)
49
 
50
  assert len(temperature) <= len(raw_datapoint), "Temperature array length must be lesser or equal to number of channels"
51
  self.temperature = temperature
 
138
 
139
  # Read values and add to q
140
  values = self.frontend.read()
141
+ self.q.put(values.channels())
142
 
143
  # Wait until reading is fully ompleted
144
  while self.frontend.is_ready():
145
  pass
146
 
147
  # Check for timeout
148
+ if self.timeout is not None:
149
+ if time.time() - start_time > self.timeout:
150
+ break
151
  return
152
 
153
  def init_checks(self):
154
  '''
155
  Run Initial threads to the registers to make sure we can start reading
156
  '''
157
+ print("Configuring EEG Frontend")
158
+ self.frontend.write_regs(0x00, FRONTEND_CONFIG)
159
  data = self.frontend.read_regs(0x00, len(FRONTEND_CONFIG))
160
  assert data == FRONTEND_CONFIG, f"Wrong config: {data} vs {FRONTEND_CONFIG}"
161
  self.frontend.start()
 
191
  # Get an item from CaptureThread
192
  if not self.raw_q.empty():
193
  raw_data = self.raw_q.get()
194
+ # assert raw_data is not None, "Got a None item from CaptureThread in FilterThread"
195
+ if raw_data is None:
196
+ continue
197
  datapoint = Datapoint(raw_data, )
198
 
199
  # Put Item to all ConsumerThreads
200
  for q in self.qs:
201
  if not q.full():
202
+ q.put(datapoint)
203
  return
204
 
205
  def add_q(self, q):
 
307
  self.record = record
308
 
309
  # Initialize data structures for capture and filtering
310
+ raw_q = Queue()
311
+ self.capture_thread = CaptureThread(raw_q, name='CapThread')
312
+ self.filter_thread = FilterThread(raw_q, name='FilterThread')
313
 
314
  # Declare data structures for viz and record functionality
315
  self.viz_q = None
 
327
  self.start_record()
328
 
329
  def start_viz(self):
330
+ self.viz_q = Queue()
331
+ self.viz_thread = DisplayThread(self.viz_q, name='VizThread')
332
  self.filter_thread.add_q(self.viz_q)
333
  self.viz_thread.start()
334
 
 
338
  self.viz_thread.raise_exception()
339
 
340
  def start_record(self):
341
+ self.record_q = Queue()
342
+ self.record_thread = SaveThread(self.record_q, name='RecThread')
343
  self.filter_thread.add_q(self.record_q)
344
  self.record_thread.start()
345
 
src/hardware/__init__.py ADDED
File without changes
src/hardware/frontend.py CHANGED
@@ -51,6 +51,7 @@ class Frontend:
51
  self.pwdn = GPIO("/dev/gpiochip2", 12, "out")
52
  self._start = GPIO("/dev/gpiochip3", 29, "out")
53
  self.drdy = GPIO("/dev/gpiochip3", 28, "in")
 
54
  self.dev = SpiDev()
55
  self.dev.open(0, 0)
56
  self.dev.max_speed_hz = 1000000
@@ -105,6 +106,11 @@ class Frontend:
105
 
106
  def is_ready(self):
107
  return not self.drdy.read()
 
 
 
 
 
108
 
109
  def close(self):
110
- self.dev.close()
 
51
  self.pwdn = GPIO("/dev/gpiochip2", 12, "out")
52
  self._start = GPIO("/dev/gpiochip3", 29, "out")
53
  self.drdy = GPIO("/dev/gpiochip3", 28, "in")
54
+ self.drdy.edge = "falling"
55
  self.dev = SpiDev()
56
  self.dev.open(0, 0)
57
  self.dev.max_speed_hz = 1000000
 
106
 
107
  def is_ready(self):
108
  return not self.drdy.read()
109
+
110
+ def wait_new_data(self):
111
+ self.drdy.poll(timeout=None) # poll the falling edge event
112
+ self.drdy.read_event() # consume the event
113
+ return self.read() # read SPI with RDATA
114
 
115
  def close(self):
116
+ self.dev.close()
src/notebooks/test_capture.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
src/notebooks/tests.ipynb CHANGED
The diff for this file is too large to render. See raw diff