logic-analyzer
logic_analyzer.h
1 
8 #pragma once
9 
10 #include "Arduino.h"
11 #include "config.h"
12 #include "network.h"
13 
14 // Max numbers of logged characters in a line
15 #ifndef LOG_BUFFER_SIZE
16 #define LOG_BUFFER_SIZE 80
17 #endif
18 
19 // Max size of buffered print
20 #ifndef DUMP_RECORD_SIZE
21 #define DUMP_RECORD_SIZE 1024*5
22 #endif
23 
24 // Supported Commands
25 #define SUMP_RESET 0x00
26 #define SUMP_ARM 0x01
27 #define SUMP_ID 0x02
28 #define SUMP_XON 0x11
29 #define SUMP_XOFF 0x13
30 #define SUMP_TRIGGER_MASK 0xC0
31 #define SUMP_TRIGGER_VALUES 0xC1
32 #define SUMP_TRIGGER_CONFIG 0xC2
33 #define SUMP_SET_DIVIDER 0x80
34 #define SUMP_SET_READ_DELAY_COUNT 0x81
35 #define SUMP_SET_FLAGS 0x82
36 #define SUMP_SET_RLE 0x0100
37 #define SUMP_GET_METADATA 0x04
38 
39 namespace logic_analyzer {
40 
42 class AbstractCapture;
43 class Capture;
44 class LogicAnalyzer;
45 class RingBuffer;
46 
47 
49 enum Status : uint8_t {STOPPED, ARMED, TRIGGERED};
50 
52 enum Event : uint8_t {RESET, STATUS, CAPUTRE_SIZE, CAPTURE_FREQUNCY,TRIGGER_VALUES,TRIGGER_MASK, READ_DLEAY_COUNT, FLAGS};
53 typedef void (*EventHandler)(Event event);
54 
55 PinReader *pin_reader_ptr = nullptr;
57 RingBuffer *buffer_ptr = nullptr;;
59 Stream *logger_ptr = nullptr;
61 Stream *stream_ptr = nullptr;
62 
64 void write(PinBitArray bits) {
65  // write 4 bytes
66  stream_ptr->write(htonl(bits));
67 }
68 // writes a buffer of uint32_t values
69 void write(uint32_t *buff, size_t n_samples) {
70  stream_ptr->write((const char*)buff, n_samples * sizeof(uint32_t));
71 }
72 // writes a buffer of PinBitArray
73 void write(PinBitArray *buff, size_t n_samples) {
74  // convert to uint32_t
75  uint32_t tmp[DUMP_RECORD_SIZE];
76  int idx = 0;
77  for (int j=0;j<n_samples;j++){
78  tmp[idx++] = htonl(buff[j]);
79  if (idx==DUMP_RECORD_SIZE){
80  write(tmp, idx);
81  idx = 0;
82  }
83  }
84  if (idx>0){
85  write(tmp, idx);
86  }
87 }
88 
89 
91 inline void log(const char* fmt, ...) {
92  if (logger_ptr!=nullptr) {
93  char serial_printf_buffer[LOG_BUFFER_SIZE] = {0};
94  va_list args;
95  va_start(args,fmt);
96  vsnprintf(serial_printf_buffer,LOG_BUFFER_SIZE, fmt, args);
97  logger_ptr->println(serial_printf_buffer);
98  va_end(args);
99  logger_ptr->flush();
100  }
101 }
102 
110  public:
112  uint8_t *getPtr() {
113  return uint8Values;
114  }
115 
117  uint16_t get16(int idx) {
118  return uint16Values[idx];
119  }
120 
122  uint32_t get32() {
123  return uint32Value[0];
124  }
125 
126  protected:
127  uint8_t uint8Values[4];
128  uint16_t* uint16Values = (uint16_t*) &uint8Values[0];
129  uint32_t* uint32Value = (uint32_t*) &uint8Values[0];
130 
131 };
132 
138 class RingBuffer {
139  public:
140  RingBuffer(size_t size){
141  this->size_count = size + 10;
142  data = new PinBitArray[this->size_count];
143  if (data==nullptr){
144  log("Requested capture size is too big");
145  this->size_count = 0;
146  }
147  }
148 
149  ~RingBuffer(){
150  if (data!=nullptr){
151  delete[] data;
152  }
153  }
154 
156  void write(PinBitArray value){
157  if (ignore_count > 0) {
158  ignore_count--;
159  return;
160  }
161  data[write_pos++] = value;
162  if (write_pos>size_count){
163  write_pos = 0;
164  }
165  if (available_count<size_count){
166  available_count++;
167  } else {
168  read_pos = write_pos+1;
169  }
170  }
171 
173  PinBitArray read() {
174  PinBitArray result = 0;
175  if (available_count>0){
176  if (read_pos>size_count){
177  read_pos = 0;
178  }
179  result = data[read_pos++];
180  available_count--;
181  }
182  return result;
183  }
184 
186  size_t readBuffer(uint32_t *result, size_t read_len){
187  size_t result_len;
188  for (size_t j=0; j<read_len; j++){
189  result[j] = read();
190  if (available()==0){
191  return j+1;
192  }
193  }
194  return read_len;
195  }
196 
198  void clear() {
199  ignore_count = 0;
200  available_count = 0;
201  write_pos = 0;
202  read_pos = 0;
203  }
204 
206  void clear(size_t count){
207  ignore_count = 0;
208  if (count>available_count){
209  // calculate number of future entries to ignore
210  ignore_count = count - available_count;
211  }
212  // remove count entries
213  for (int j=0;j<count && available()>0;j++){
214  read();
215  }
216  }
217 
219  size_t available() {
220  return available_count;
221  }
222 
224  void setAvailable(size_t avail){
225  available_count = avail;
226  }
227 
229  size_t size() {
230  return size_count;
231  }
232 
233  PinBitArray *data_ptr(){
234  return data;
235  }
236 
237  private:
238  size_t available_count = 0;
239  size_t size_count = 0;
240  size_t write_pos = 0;
241  size_t read_pos = 0;
242  size_t ignore_count = 0;
243  PinBitArray *data;
244 };
245 
253  public:
254  friend class AbstractCapture;
255  friend class LogicAnalyzer;
256  friend class Capture;
257 
259  void setStatus(Status status){
260  log("setStatus %d", status);
261  status_value = status;
262  raiseEvent(STATUS);
263  }
264 
265  Stream &stream() {
266  return *stream_ptr;
267  }
268 
269  protected:
270  volatile Status status_value;
271  bool is_continuous_capture = false; // => continous capture
272  uint32_t max_capture_size = 1000;
273  int trigger_pos = -1;
274  int read_count = 0;
275  int delay_count = 0;
276  int pin_start = 0;
277  int pin_numbers = 0;
278  uint64_t frequecy_value; // in hz
279  uint64_t delay_time_us;
280  PinBitArray trigger_mask = 0;
281  PinBitArray trigger_values = 0;
282  Sump4ByteComandArg cmd4;
283  EventHandler eventHandler = nullptr;
284 
285 
287  void raiseEvent(Event event){
288  if (eventHandler!=nullptr) eventHandler(event);
289  }
290 } la_state;
291 
292 
293 
301  public:
302  friend class LogicAnalyzer;
303 
306  }
307 
310  }
311 
314  return *logic_analyzer_ptr;
315  }
316 
318  virtual PinReader &pinReader() {
319  return *(pin_reader_ptr);
320  }
321 
323  virtual void setStatus(Status status){
324  la_state.setStatus(status);
325  }
326 
328  virtual void capture() = 0;
329 
331  virtual void captureAll() = 0;
332 
333 
334  protected:
335  LogicAnalyzer *logic_analyzer_ptr = nullptr;
336 
337  virtual void setLogicAnalyzer(LogicAnalyzer &la){
338  logic_analyzer_ptr = &la;
339  }
340 
341 };
342 
348 class Capture : public AbstractCapture {
349  public:
351  Capture(uint64_t maxCaptureFreq, uint64_t maxCaptureFreqThreshold ) : AbstractCapture(){
352  max_frequecy_value = maxCaptureFreq;
353  max_frequecy_threshold = maxCaptureFreqThreshold;
354  }
355 
357  virtual void capture(){
358  log("capture");
359  // no capture if request is well above max rate
360  if (la_state.frequecy_value > max_frequecy_value + (max_frequecy_value/2)){
361  setStatus(STOPPED);
362  // Send some dummy data to stop pulseview
363  write(0);
364  log("The frequency %u is not supported!", la_state.frequecy_value );
365  return;
366  }
367 
368  // if frequecy_value >= max_frequecy_value -> capture at max speed
369  capture(la_state.frequecy_value >= max_frequecy_threshold);
370  log("capture-end");
371  }
372 
374  void captureAll() {
375  log("captureAll %ld entries", la_state.read_count);
376  unsigned long delay_time_us = la_state.delay_time_us;
377  while(la_state.status_value == TRIGGERED && buffer_ptr->available() < la_state.read_count ){
379  delayMicroseconds(delay_time_us);
380  }
381  }
382 
385  log("captureAllMaxSpeed %ld entries",la_state.read_count);
386  while(la_state.status_value == TRIGGERED && buffer_ptr->available() < la_state.read_count ){
388  }
389  }
390 
393  log("captureAllContinous");
394  unsigned long delay_time_us = la_state.delay_time_us;
395  while(la_state.status_value == TRIGGERED){
397  delayMicroseconds(delay_time_us);
398  }
399  }
400 
403  log("captureAllContinousMaxSpeed");
404  while(la_state.status_value == TRIGGERED){
406  }
407  }
408 
411  buffer_ptr->write(pin_reader_ptr->readAll());
412  }
413 
416  write(pin_reader_ptr->readAll());
417  }
418 
420  PinBitArray captureSample() {
421  // actual state
422  PinBitArray actual = pin_reader_ptr->readAll();
423 
424  // buffer single capture cycle
425  if (la_state.is_continuous_capture) {
426  write(actual);
427  } else if (la_state.status_value==TRIGGERED) {
428  buffer_ptr->write(actual);
429  }
430  return actual;
431  }
432 
433 
434  protected:
435  uint64_t max_frequecy_value; // in hz
436  uint64_t max_frequecy_threshold; // in hz
437 
439  void capture(bool is_max_speed) {
440  log("capture is_max_speed: %s", is_max_speed ? "true":"false");
441  // waiting for trigger
442  if (la_state.trigger_mask) {
443  log("waiting for trigger");
444  while ((la_state.trigger_values ^ captureSample()) & la_state.trigger_mask)
445  ;
446  }
447  la_state.setStatus(TRIGGERED);
448  log("triggered");
449 
450  // remove unnecessary entries from buffer based on delayCount & readCount
451  long keep = la_state.read_count - la_state.delay_count;
452  if (keep > 0 && buffer_ptr->available()>keep) {
453  log("keeping last %ld entries",keep);
454  buffer_ptr->clear(buffer_ptr->available() - keep);
455  } else if (keep < 0) {
456  log("ignoring first %ld entries",abs(keep));
457  buffer_ptr->clear(buffer_ptr->available() + abs(keep));
458  } else if (keep==0l){
459  log("starting with clean buffer");
460  buffer_ptr->clear();
461  }
462 
463  // Start Capture
464  if (is_max_speed){
465  if (la_state.is_continuous_capture){
467  } else {
469  dumpData();
470  log("capture-done: %lu",buffer_ptr->available());
471  setStatus(STOPPED);
472  }
473  } else {
474  if (la_state.is_continuous_capture){
476  } else {
477  captureAll();
478  dumpData();
479  log("capture-done: %lu",buffer_ptr->available());
480  setStatus(STOPPED);
481  }
482  }
483  }
484 
486  virtual Stream &stream() {
487  return *stream_ptr;
488  }
489 
490 
492  void dumpData() {
493  log("dumpData: %lu",buffer_ptr->available());
494  // buffered write
495  uint32_t tmp[DUMP_RECORD_SIZE];
496  while(buffer_ptr->available()){
497  size_t len = buffer_ptr->readBuffer(tmp, DUMP_RECORD_SIZE);
498  write(tmp, len);
499  }
500  // flush final records - for backward compatibility
501  stream_ptr->flush();
502  log("dumpData-end");
503  }
504 };
505 
516  public:
519  log("LogicAnalyzer");
520  }
521 
524  log("~LogicAnalyzer");
525  if (buffer_ptr!=nullptr) {
526  delete buffer_ptr;
527  buffer_ptr = nullptr;
528  }
529  if (pin_reader_ptr!=nullptr){
530  delete pin_reader_ptr;
531  pin_reader_ptr = nullptr;
532  }
533  }
534 
547  void begin(Stream &procesingStream, AbstractCapture *capture, uint32_t maxCaptureSize, uint8_t pinStart=0, uint8_t numberOfPins=8, bool setup_pins=false){
548  log("begin");
549  stream_ptr = &procesingStream;
550  this->capture_ptr = capture;
551 
552  la_state.max_capture_size = maxCaptureSize;
553  la_state.read_count = maxCaptureSize;
554  la_state.delay_count = maxCaptureSize;
555  la_state.pin_start = pinStart;
556  la_state.pin_numbers = numberOfPins;
557 
558  // set initial status
559  setStatus(STOPPED);
560 
561  if (pin_reader_ptr==nullptr){
562  pin_reader_ptr = new PinReader(pinStart);
563  }
564 
565  if (do_allocate_buffer && buffer_ptr==nullptr) {
566  buffer_ptr = new RingBuffer(maxCaptureSize);
567  }
568 
569  // assign state to capture
570  if (capture!=nullptr) {
571  capture->setLogicAnalyzer(*this);
572  }
573 
574  // by default the pins are in read mode - so it is usually not really necesarry to set the mode to input
575  if (setup_pins){
576  // pinmode imput for requested pins
577  for (int j=pinStart;j<numberOfPins;j++){
578  pinMode(pinStart+j, INPUT);
579  }
580  }
581 
582  log("begin-end");
583  }
584 
586  uint16_t startPin() {
587  return la_state.pin_start;
588  }
589 
591  uint16_t numberOfPins() {
592  return la_state.pin_numbers;
593  }
594 
596  Stream &stream() {
597  return *(stream_ptr);
598  }
599 
601  Status status() {
602  return la_state.status_value;
603  }
604 
606  void setStatus(Status status){
607  la_state.setStatus(status);
608  }
609 
612  return *(buffer_ptr);
613  }
614 
617  if (hasCommand()){
618  int cmd = command();
619  log("processCommand %d", cmd);
620  processCommand(cmd);
621  }
622  }
623 
625  PinBitArray triggerValues() {
626  return la_state.trigger_values;
627  }
628 
630  void setTriggerValues(PinBitArray values){
631  la_state.trigger_values = values;
632  log("--> setTriggerValues: %u", (uint32_t) values);
633  raiseEvent(TRIGGER_VALUES);
634  }
635 
637  PinBitArray triggerMask() {
638  return la_state.trigger_mask;
639  }
640 
642  void setTriggerMask(PinBitArray values){
643  la_state.trigger_mask = values;
644  log("--> setTriggerValues: %u", (uint32_t) values);
645  raiseEvent(TRIGGER_MASK);
646  }
647 
649  int readCount() {
650  return la_state.read_count;
651  }
652 
654  void setReadCount(int count){
655  la_state.read_count = count;
656  }
657 
659  int delayCount() {
660  return la_state.delay_count;
661  }
662 
664  void setDelayCount(int count){
665  log("--> setDelayCount: %d", count);
666  la_state.delay_count = count;
667  }
668 
670  uint64_t captureFrequency() {
671  return la_state.frequecy_value;
672  }
673 
675  uint64_t delayTimeUs() {
676  return la_state.delay_time_us;
677  }
678 
680  void setCaptureFrequency(uint64_t value){
681  la_state.frequecy_value = value;
682  log("--> setCaptureFrequency: %lu", la_state.frequecy_value);
683  la_state.delay_time_us = (1000000.0 / value );
684  log("--> delay_time_us: %lu", la_state.delay_time_us);
685  raiseEvent(CAPTURE_FREQUNCY);
686  }
687 
690  return la_state.is_continuous_capture;
691  }
692 
694  void setContinuousCapture(bool cont){
695  la_state.is_continuous_capture = cont;
696  }
697 
699  void setEventHandler(EventHandler eh){
700  la_state.eventHandler = eh;
701  }
702 
704  void clear(){
705  log("clear");
706  setStatus(STOPPED);
707  if (buffer_ptr!=nullptr){
708  memset(buffer_ptr->data_ptr(),0x00, la_state.max_capture_size*sizeof(PinBitArray));
709  buffer_ptr->clear();
710  }
711  }
712 
714  size_t size() {
715  return buffer_ptr == nullptr ? 0 : buffer_ptr->size();
716  }
717 
719  size_t available() {
720  return buffer_ptr == nullptr ? 0 : buffer_ptr->available();
721  }
722 
724  void setLogger(Stream &logger){
725  logger_ptr = &logger;
726  }
727 
730  is_capture_on_arm = capture;
731  }
732 
733 
735  void setDescription(const char* name) {
736  description = name;
737  }
738 
740  void setAllocateBuffer(bool do_allocate){
741  do_allocate_buffer = do_allocate;
742  }
743 
745  void capture() {
746  if (capture_ptr!=nullptr)
747  capture_ptr->capture();
748  }
749 
750 
751  protected:
752  bool is_capture_on_arm = true;
753  bool do_allocate_buffer = true;
754  uint64_t sump_reset_igorne_timeout=0;
755  AbstractCapture *capture_ptr = nullptr;
756  const char* description = "ARDUINO";
757  const char* device_id = "1ALS";
758  const char* firmware_version = "01.0";
759  const char* protocol_version = "\x041\x002";
760 
763  return la_state;
764  }
765 
766 
768  bool hasCommand() {
769  return stream_ptr->available() > 0;
770  }
771 
773  uint8_t command() {
774  int command = stream().read();
775  return command;
776  }
777 
780  delay(10);
781  stream().readBytes(la_state.cmd4.getPtr(), 4);
782  return la_state.cmd4;
783  }
784 
786  void write(uint8_t cmd, uint32_t number){
787  stream().write(cmd);
788  uint32_t toSend = htonl(number);
789  stream().write((byte*)&toSend,sizeof(uint32_t));
790  stream().flush();
791  }
792 
794  void write(uint8_t cmd, const char* str){
795  stream().write(cmd);
796  stream().print(str);
797  stream().write("\x000",1);
798  stream().flush();
799  }
800 
802  PinBitArray commandExtPinBitArray() {
804  switch(sizeof(PinBitArray)) {
805  case 1:
806  return (PinBitArray) cmd.getPtr()[0];
807  case 2:
808  return (PinBitArray) cmd.get16(0);
809  default:
810  return (PinBitArray) cmd.get32();
811  }
812  }
813 
815  void raiseEvent(Event event){
816  la_state.raiseEvent(event);
817  }
818 
833  void setupDelay(uint32_t divider) {
834  // calculate frequency
835  setCaptureFrequency(100000000UL / (divider+1));
836  }
837 
843  void sendMetadata() {
844  log("sendMetadata");
845  write(0x01, description);
846  write(0x02, firmware_version);
847  // number of probes
848  write(0x20, la_state.pin_numbers);
849  // sample memory
850  write(0x21, la_state.max_capture_size);
851  // sample rate - We do not provide the real max sample rate since this does not have any impact on the gui and provides wrong results!
852  //write(0x23, la_state.max_frequecy_value);
853  // protocol version & end
854  stream().write(protocol_version, strlen(protocol_version)+1);
855  stream().flush();
856  }
857 
861  void processCommand(int cmd){
862 
863  switch (cmd) {
867  case SUMP_RESET:
868  // debounce reset
869  if (millis()>sump_reset_igorne_timeout){
870  log("=>SUMP_RESET");
871  setStatus(STOPPED);
872  clear();
873  sump_reset_igorne_timeout = millis()+ 500;
874  raiseEvent(RESET);
875  }
876  break;
877 
881  case SUMP_ID:
882  log("=>SUMP_ID");
883  stream().write(device_id, 4);
884  stream().flush();
885  break;
886 
887  /*
888  * We return a description of our capabilities.
889  * Check the function's comments below.
890  */
891  case SUMP_GET_METADATA:
892  log("=>SUMP_GET_METADATA");
893  sendMetadata();
894  break;
895 
896  /*
897  * Captures the data
898  */
899  case SUMP_ARM:
900  log("=>SUMP_ARM");
901  // clear current data
902  clear();
903  setStatus(ARMED);
904  if (is_capture_on_arm){
905  capture();
906  }
907  break;
908 
909  /*
910  * the trigger mask byte has a '1' for each enabled trigger so
911  * we can just use it directly as our trigger mask.
912  */
913  case SUMP_TRIGGER_MASK:
914  log("=>SUMP_TRIGGER_MASK");
916  break;
917 
918  /*
919  * trigger_values can be used directly as the value of each bit
920  * defines whether we're looking for it to be high or low.
921  */
922  case SUMP_TRIGGER_VALUES:
923  log("=>SUMP_TRIGGER_VALUES");
925  break;
926 
927 
928  /* read the rest of the command bytes but ignore them. */
929  case SUMP_TRIGGER_CONFIG:
930  log("=>SUMP_TRIGGER_CONFIG");
931  commandExt();
932  break;
933 
934  /*
935  * the shifting needs to be done on the 32bit unsigned long variable
936  * so that << 16 doesn't end up as zero.
937  */
938  case SUMP_SET_DIVIDER: {
939  log("=>SUMP_SET_DIVIDER");
941  uint32_t divider = cmd.get32();
942  log("-divider: %lu\n", divider);
943  setupDelay(divider);
944  }
945  break;
946 
947  /*
948  * this just sets up how many samples there should be before
949  * and after the trigger fires. The readCount is total samples
950  * to return and delayCount number of samples after the trigger.
951  * this sets the buffer splits like 0/100, 25/75, 50/50
952  * for example if readCount == delayCount then we should
953  * return all samples starting from the trigger point.
954  * if delayCount < readCount we return (readCount - delayCount) of
955  * samples from before the trigger fired.
956  */
957  case SUMP_SET_READ_DELAY_COUNT: {
959  log("=>SUMP_SET_READ_DELAY_COUNT %02X %02X",cmd.get16(0),cmd.get16(1));
960  la_state.read_count = (cmd.get16(0)+1) * 4;
961  la_state.delay_count = (cmd.get16(1)+1) * 4;
962  log("--> read_count: %d", la_state.read_count);
963  log("--> delay_count: %d", la_state.delay_count);
964  raiseEvent(READ_DLEAY_COUNT);
965  }
966  break;
967 
968  /* read the rest of the command bytes and check if RLE is enabled. */
969  case SUMP_SET_FLAGS: {
970  log("=>SUMP_SET_FLAGS");
972  la_state.is_continuous_capture = ((cmd.getPtr()[1] & 0B1000000) != 0);
973  log("--> is_continuous_capture: %d\n", la_state.is_continuous_capture);
974  raiseEvent(FLAGS);
975 
976  }
977  break;
978 
979  /* ignore any unrecognized bytes. */
980  default:
981  log("=>UNHANDLED command: %d", cmd);
982  break;
983 
984  };
985  }
986 };
987 
988 } // namespace
989 
990 
Abstract Class for Capturing Logic. Create your own subclass if you want to implement your own optimi...
Definition: logic_analyzer.h:300
~AbstractCapture()
Destructor.
Definition: logic_analyzer.h:309
virtual void captureAll()=0
Used to masure the speed - capture into memory w/o dump!
LogicAnalyzer & logicAnalyzer()
Provides access to the LogicAnalyzer.
Definition: logic_analyzer.h:313
AbstractCapture()
Default Constructor.
Definition: logic_analyzer.h:305
virtual void setStatus(Status status)
Sets the status.
Definition: logic_analyzer.h:323
virtual PinReader & pinReader()
Provides access to the PinReader.
Definition: logic_analyzer.h:318
virtual void capture()=0
Captures the data and dumps the result.
Default Implementation for the Capturing Logic.
Definition: logic_analyzer.h:348
void captureAll()
Generic Capturing of requested number of examples into the buffer.
Definition: logic_analyzer.h:374
void captureAllContinous()
Continuous capturing at the requested speed.
Definition: logic_analyzer.h:392
void captureSampleFastContinuous()
captures one singe entry for all pins and writes it to output stream
Definition: logic_analyzer.h:415
virtual Stream & stream()
Provides access to the SUMP command stream.
Definition: logic_analyzer.h:486
void captureAllMaxSpeed()
Capturing of requested number of examples into the buffer at maximum speed.
Definition: logic_analyzer.h:384
void capture(bool is_max_speed)
starts the capturing of the data
Definition: logic_analyzer.h:439
void dumpData()
dumps the caputred data to the recording device
Definition: logic_analyzer.h:492
virtual void capture()
starts the capturing of the data
Definition: logic_analyzer.h:357
Capture(uint64_t maxCaptureFreq, uint64_t maxCaptureFreqThreshold)
Default Constructor.
Definition: logic_analyzer.h:351
void captureAllContinousMaxSpeed()
Continuous capturing at max speed.
Definition: logic_analyzer.h:402
PinBitArray captureSample()
captures one single entry for all pins and provides the result - used by the trigger
Definition: logic_analyzer.h:420
void captureSampleFast()
captures one singe entry for all pins and writes it to the buffer
Definition: logic_analyzer.h:410
Main Logic Analyzer API using the SUMP Protocol. When you try to connect to the Logic Analzyer - SUMP...
Definition: logic_analyzer.h:515
PinBitArray triggerValues()
provides the trigger values
Definition: logic_analyzer.h:625
void setTriggerMask(PinBitArray values)
defines the trigger mask
Definition: logic_analyzer.h:642
size_t available()
returns the avialable buffer entries
Definition: logic_analyzer.h:719
void raiseEvent(Event event)
raises an event
Definition: logic_analyzer.h:815
void setDelayCount(int count)
defines the delay count
Definition: logic_analyzer.h:664
Stream & stream()
provides command output stream of capturing divice
Definition: logic_analyzer.h:596
void setEventHandler(EventHandler eh)
defines a event handler that gets notified on some defined events
Definition: logic_analyzer.h:699
uint64_t captureFrequency()
provides the caputring frequency
Definition: logic_analyzer.h:670
uint8_t command()
gets the next 1 byte command
Definition: logic_analyzer.h:773
PinBitArray commandExtPinBitArray()
Provides the command as PinBitArray.
Definition: logic_analyzer.h:802
Status status()
provides the actual Status
Definition: logic_analyzer.h:601
int delayCount()
provides the delay count
Definition: logic_analyzer.h:659
void clear()
Resets the status and buffer.
Definition: logic_analyzer.h:704
void setCaptureOnArm(bool capture)
Switch automatic capturing on ARMED status on/off.
Definition: logic_analyzer.h:729
void processCommand(int cmd)
Definition: logic_analyzer.h:861
void write(uint8_t cmd, uint32_t number)
writes a byte command with uint32_t number argument
Definition: logic_analyzer.h:786
void setReadCount(int count)
defines the read count
Definition: logic_analyzer.h:654
Sump4ByteComandArg & commandExt()
gets the next 4 byte command
Definition: logic_analyzer.h:779
void setContinuousCapture(bool cont)
defines the caputring as continuous
Definition: logic_analyzer.h:694
void setTriggerValues(PinBitArray values)
defines the trigger values
Definition: logic_analyzer.h:630
void setCaptureFrequency(uint64_t value)
defines the caputring frequency
Definition: logic_analyzer.h:680
uint16_t numberOfPins()
Provides the number of subsequent GPIO pins which will be used for capturing.
Definition: logic_analyzer.h:591
void capture()
starts the capturing
Definition: logic_analyzer.h:745
void sendMetadata()
Definition: logic_analyzer.h:843
uint16_t startPin()
Provides the GPIO number of the start pin which is used for capturing.
Definition: logic_analyzer.h:586
void setAllocateBuffer(bool do_allocate)
Allows to switch of the automatic buffer allocation - call before begin!
Definition: logic_analyzer.h:740
bool isContinuousCapture()
checks if the caputring is continuous
Definition: logic_analyzer.h:689
void setStatus(Status status)
Defines the actual status.
Definition: logic_analyzer.h:606
PinBitArray triggerMask()
provides the trigger mask
Definition: logic_analyzer.h:637
size_t size()
returns the max buffer size
Definition: logic_analyzer.h:714
LogicAnalyzer()
Default Constructor.
Definition: logic_analyzer.h:518
void processCommand()
process the next available command - Call this function from your Arduino loop()!
Definition: logic_analyzer.h:616
~LogicAnalyzer()
Destructor.
Definition: logic_analyzer.h:523
void setupDelay(uint32_t divider)
Definition: logic_analyzer.h:833
LogicAnalyzerState & state()
Provides a reference to the LogicAnalyzerState.
Definition: logic_analyzer.h:762
void begin(Stream &procesingStream, AbstractCapture *capture, uint32_t maxCaptureSize, uint8_t pinStart=0, uint8_t numberOfPins=8, bool setup_pins=false)
Starts the processing.
Definition: logic_analyzer.h:547
void setDescription(const char *name)
Defines the Description.
Definition: logic_analyzer.h:735
void write(uint8_t cmd, const char *str)
writes a byte command with char* argument
Definition: logic_analyzer.h:794
RingBuffer & buffer()
Provides access to the buffer.
Definition: logic_analyzer.h:611
uint64_t delayTimeUs()
Provides the delay time between measurements in microseconds.
Definition: logic_analyzer.h:675
int readCount()
provides the read count
Definition: logic_analyzer.h:649
void setLogger(Stream &logger)
Activate the logging by defining the logging output Stream.
Definition: logic_analyzer.h:724
bool hasCommand()
checks if there is a command available
Definition: logic_analyzer.h:768
Common State information for the Logic Analyzer - provides event handling on State change.
Definition: logic_analyzer.h:252
void setStatus(Status status)
Defines the actual status.
Definition: logic_analyzer.h:259
void raiseEvent(Event event)
raises an event
Definition: logic_analyzer.h:287
AVR specific implementation Logic for the PinReader.
Definition: config_avr.h:40
PinBitArray readAll()
reads all pins and provides the result as bitmask - PORTD:pins 0 to 7 / PORTB: pins 8 to 13
Definition: config_avr.h:47
Data is captured in a ring buffer. If the buffer is full we overwrite the oldest entries....
Definition: logic_analyzer.h:138
PinBitArray read()
reads the next available entry from the buffer
Definition: logic_analyzer.h:173
void setAvailable(size_t avail)
Usualy you must not use this function. However for the RP PIO it is quite usefull to indicated that t...
Definition: logic_analyzer.h:224
size_t size()
returns the max buffer size
Definition: logic_analyzer.h:229
void write(PinBitArray value)
adds an entry - if there is no more space we overwrite the oldest value
Definition: logic_analyzer.h:156
void clear()
clears all entries
Definition: logic_analyzer.h:198
size_t available()
returns the number of available entries
Definition: logic_analyzer.h:219
size_t readBuffer(uint32_t *result, size_t read_len)
1 SUMP record has 4 bytes - We privide the requested number of buffered values in the output format
Definition: logic_analyzer.h:186
void clear(size_t count)
clears n entries from the buffer - if the number is bigger then the available data we ignore some fut...
Definition: logic_analyzer.h:206
4 Byte SUMP Protocol Command. The uint8Values data is provided in network format (big endian) while t...
Definition: logic_analyzer.h:109
uint8_t * getPtr()
Provides a pointer to the memory.
Definition: logic_analyzer.h:112
uint16_t get16(int idx)
Provides a uint16_t value.
Definition: logic_analyzer.h:117
uint32_t get32()
Provides a uint32_t value.
Definition: logic_analyzer.h:122