|
1 | 1 | from __future__ import print_function
|
2 |
| -import PSL.commands_proto as CP |
| 2 | +import commands_proto as CP |
3 | 3 | import numpy as np
|
4 | 4 | import time, inspect
|
5 | 5 |
|
@@ -33,7 +33,11 @@ class I2C():
|
33 | 33 | >>> print (x,y,z)
|
34 | 34 |
|
35 | 35 | """
|
36 |
| - |
| 36 | + samples = 0 |
| 37 | + total_bytes=0 |
| 38 | + channels = 0 |
| 39 | + tg=100 |
| 40 | + MAX_SAMPLES = 10000 |
37 | 41 | def __init__(self, H):
|
38 | 42 | self.H = H
|
39 | 43 | from PSL import sensorlist
|
@@ -375,6 +379,123 @@ def scan(self, frequency=100000, verbose=False):
|
375 | 379 | self.stop()
|
376 | 380 | return addrs
|
377 | 381 |
|
| 382 | + def __captureStart__(self,address,location,sample_length,total_samples,tg): |
| 383 | + """ |
| 384 | + Blocking call that starts fetching data from I2C sensors like an oscilloscope fetches voltage readings |
| 385 | + You will then have to call `__retrievebuffer__` to fetch this data, and `__dataProcessor` to process and return separate channels |
| 386 | + refer to `capture` if you want a one-stop solution. |
| 387 | + |
| 388 | + .. tabularcolumns:: |p{3cm}|p{11cm}| |
| 389 | + ================== ============================================================================================ |
| 390 | + **Arguments** |
| 391 | + ================== ============================================================================================ |
| 392 | + address Address of the I2C sensor |
| 393 | + location Address of the register to read from |
| 394 | + sample_length Each sample can be made up of multiple bytes startng from <location> . such as 3-axis data |
| 395 | + total_samples Total samples to acquire. Total bytes fetched = total_samples*sample_length |
| 396 | + tg timegap between samples (in uS) |
| 397 | + ================== ============================================================================================ |
| 398 | +
|
| 399 | + :return: Arrays X(timestamps),Y1,Y2 ... |
| 400 | +
|
| 401 | + """ |
| 402 | + if(tg<20):tg=20 |
| 403 | + total_bytes = total_samples*sample_length |
| 404 | + print ('total bytes calculated : ',total_bytes) |
| 405 | + if(total_bytes>self.MAX_SAMPLES*2): |
| 406 | + print ('Sample limit exceeded. 10,000 int / 20000 bytes total') |
| 407 | + total_bytes = self.MAX_SAMPLES*2 |
| 408 | + total_samples = total_bytes/sample_length #2* because sample array is in Integers, and we're using it to store bytes |
| 409 | + |
| 410 | + |
| 411 | + print ('length of each channel : ',sample_length) |
| 412 | + self.total_bytes = total_bytes |
| 413 | + self.channels = sample_length |
| 414 | + self.samples = total_samples |
| 415 | + self.tg = tg |
| 416 | + |
| 417 | + self.H.__sendByte__(CP.I2C_HEADER) |
| 418 | + self.H.__sendByte__(CP.I2C_START_SCOPE) |
| 419 | + self.H.__sendByte__(address) |
| 420 | + self.H.__sendByte__(location) |
| 421 | + self.H.__sendByte__(sample_length) |
| 422 | + self.H.__sendInt__(total_samples) #total number of samples to record |
| 423 | + self.H.__sendInt__(tg) #Timegap between samples. 1MHz timer clock |
| 424 | + self.H.__get_ack__() |
| 425 | + return 1e-6*self.samples*self.tg+.01 |
| 426 | + |
| 427 | + def __retrievebuffer__(self): |
| 428 | + ''' |
| 429 | + Fetch data acquired by the I2C scope. refer to :func:`__captureStart__` |
| 430 | + |
| 431 | + ''' |
| 432 | + total_int_samples = self.total_bytes/2 |
| 433 | + DATA_SPLITTING = 500 |
| 434 | + print ('fetchin samples : ',total_int_samples,' split',DATA_SPLITTING) |
| 435 | + data=b'' |
| 436 | + for i in range(int(total_int_samples/DATA_SPLITTING)): |
| 437 | + self.H.__sendByte__(CP.ADC) |
| 438 | + self.H.__sendByte__(CP.GET_CAPTURE_CHANNEL) |
| 439 | + self.H.__sendByte__(0) #starts with A0 on PIC |
| 440 | + self.H.__sendInt__(DATA_SPLITTING) |
| 441 | + self.H.__sendInt__(i*DATA_SPLITTING) |
| 442 | + rem = DATA_SPLITTING*2+1 |
| 443 | + for a in range(200): |
| 444 | + partial = self.H.fd.read(rem) #reading int by int sometimes causes a communication error. this works better. |
| 445 | + rem -=len(partial) |
| 446 | + data+=partial |
| 447 | + #print ('partial: ',len(partial), end=",") |
| 448 | + if rem<=0: |
| 449 | + break |
| 450 | + data=data[:-1] |
| 451 | + #print ('Pass : len=',len(data), ' i = ',i) |
| 452 | + |
| 453 | + if total_int_samples%DATA_SPLITTING: |
| 454 | + self.H.__sendByte__(CP.ADC) |
| 455 | + self.H.__sendByte__(CP.GET_CAPTURE_CHANNEL) |
| 456 | + self.H.__sendByte__(0) #starts with A0 on PIC |
| 457 | + self.H.__sendInt__(total_int_samples%DATA_SPLITTING) |
| 458 | + self.H.__sendInt__(total_int_samples-total_int_samples%DATA_SPLITTING) |
| 459 | + rem = 2*(total_int_samples%DATA_SPLITTING)+1 |
| 460 | + for a in range(20): |
| 461 | + partial = self.H.fd.read(rem) #reading int by int sometimes causes a communication error. this works better. |
| 462 | + rem -=len(partial) |
| 463 | + data+=partial |
| 464 | + #print ('partial: ',len(partial), end="") |
| 465 | + if rem<=0: |
| 466 | + break |
| 467 | + data=data[:-1] |
| 468 | + print ('Final Pass : len=',len(data)) |
| 469 | + return data |
| 470 | + |
| 471 | + def __dataProcessor__(self,data,*args): |
| 472 | + ''' |
| 473 | + Interpret data acquired by the I2C scope. refer to :func:`__retrievebuffer__` to fetch data |
| 474 | + |
| 475 | + ================== ============================================================================================ |
| 476 | + **Arguments** |
| 477 | + ================== ============================================================================================ |
| 478 | + data byte array returned by :func:`__retrievebuffer__` |
| 479 | + *args supply optional argument 'int' if consecutive bytes must be combined to form short integers |
| 480 | + ================== ============================================================================================ |
| 481 | +
|
| 482 | + ''' |
| 483 | + |
| 484 | + try: |
| 485 | + data = [ord(a) for a in data] |
| 486 | + if('int' in args): |
| 487 | + for a in range(self.channels*self.samples/2): self.buff[a] = np.int16((data[a*2]<<8)|data[a*2+1]) |
| 488 | + else: |
| 489 | + for a in range(self.channels*self.samples): self.buff[a] = data[a] |
| 490 | + |
| 491 | + yield np.linspace(0,self.tg*(self.samples-1),self.samples) |
| 492 | + for a in range(int(self.channels/2)): |
| 493 | + yield self.buff[a:self.samples*self.channels/2][::self.channels/2] |
| 494 | + except Exception as ex: |
| 495 | + msg = "Incorrect number of bytes received",ex |
| 496 | + raise RuntimeError(msg) |
| 497 | + |
| 498 | + |
378 | 499 | def capture(self, address, location, sample_length, total_samples, tg, *args):
|
379 | 500 | """
|
380 | 501 | Blocking call that fetches data from I2C sensors like an oscilloscope fetches voltage readings
|
|
0 commit comments