15 #ifndef LOG_BUFFER_SIZE
16 #define LOG_BUFFER_SIZE 80
20 #ifndef DUMP_RECORD_SIZE
21 #define DUMP_RECORD_SIZE 1024*5
25 #define SUMP_RESET 0x00
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
39 namespace logic_analyzer {
42 class AbstractCapture;
49 enum Status : uint8_t {STOPPED, ARMED, TRIGGERED};
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);
55 PinReader *pin_reader_ptr =
nullptr;
57 RingBuffer *buffer_ptr =
nullptr;;
59 Stream *logger_ptr =
nullptr;
61 Stream *stream_ptr =
nullptr;
64 void write(PinBitArray bits) {
66 stream_ptr->write(htonl(bits));
69 void write(uint32_t *buff,
size_t n_samples) {
70 stream_ptr->write((
const char*)buff, n_samples *
sizeof(uint32_t));
73 void write(PinBitArray *buff,
size_t n_samples) {
75 uint32_t tmp[DUMP_RECORD_SIZE];
77 for (
int j=0;j<n_samples;j++){
78 tmp[idx++] = htonl(buff[j]);
79 if (idx==DUMP_RECORD_SIZE){
91 inline void log(
const char* fmt, ...) {
92 if (logger_ptr!=
nullptr) {
93 char serial_printf_buffer[LOG_BUFFER_SIZE] = {0};
96 vsnprintf(serial_printf_buffer,LOG_BUFFER_SIZE, fmt, args);
97 logger_ptr->println(serial_printf_buffer);
118 return uint16Values[idx];
123 return uint32Value[0];
127 uint8_t uint8Values[4];
128 uint16_t* uint16Values = (uint16_t*) &uint8Values[0];
129 uint32_t* uint32Value = (uint32_t*) &uint8Values[0];
141 this->size_count =
size + 10;
142 data =
new PinBitArray[this->size_count];
144 log(
"Requested capture size is too big");
145 this->size_count = 0;
157 if (ignore_count > 0) {
161 data[write_pos++] = value;
162 if (write_pos>size_count){
165 if (available_count<size_count){
168 read_pos = write_pos+1;
174 PinBitArray result = 0;
175 if (available_count>0){
176 if (read_pos>size_count){
179 result = data[read_pos++];
188 for (
size_t j=0; j<read_len; j++){
208 if (count>available_count){
210 ignore_count = count - available_count;
213 for (
int j=0;j<count &&
available()>0;j++){
220 return available_count;
225 available_count = avail;
233 PinBitArray *data_ptr(){
238 size_t available_count = 0;
239 size_t size_count = 0;
240 size_t write_pos = 0;
242 size_t ignore_count = 0;
260 log(
"setStatus %d", status);
261 status_value = status;
270 volatile Status status_value;
271 bool is_continuous_capture =
false;
272 uint32_t max_capture_size = 1000;
273 int trigger_pos = -1;
278 uint64_t frequecy_value;
279 uint64_t delay_time_us;
280 PinBitArray trigger_mask = 0;
281 PinBitArray trigger_values = 0;
282 Sump4ByteComandArg cmd4;
283 EventHandler eventHandler =
nullptr;
288 if (eventHandler!=
nullptr) eventHandler(event);
314 return *logic_analyzer_ptr;
319 return *(pin_reader_ptr);
338 logic_analyzer_ptr = &la;
352 max_frequecy_value = maxCaptureFreq;
353 max_frequecy_threshold = maxCaptureFreqThreshold;
360 if (la_state.frequecy_value > max_frequecy_value + (max_frequecy_value/2)){
364 log(
"The frequency %u is not supported!", la_state.frequecy_value );
369 capture(la_state.frequecy_value >= max_frequecy_threshold);
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);
385 log(
"captureAllMaxSpeed %ld entries",la_state.read_count);
386 while(la_state.status_value == TRIGGERED && buffer_ptr->
available() < la_state.read_count ){
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);
403 log(
"captureAllContinousMaxSpeed");
404 while(la_state.status_value == TRIGGERED){
416 write(pin_reader_ptr->
readAll());
422 PinBitArray actual = pin_reader_ptr->
readAll();
425 if (la_state.is_continuous_capture) {
427 }
else if (la_state.status_value==TRIGGERED) {
428 buffer_ptr->
write(actual);
435 uint64_t max_frequecy_value;
436 uint64_t max_frequecy_threshold;
440 log(
"capture is_max_speed: %s", is_max_speed ?
"true":
"false");
442 if (la_state.trigger_mask) {
443 log(
"waiting for trigger");
444 while ((la_state.trigger_values ^
captureSample()) & la_state.trigger_mask)
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);
455 }
else if (keep < 0) {
456 log(
"ignoring first %ld entries",abs(keep));
458 }
else if (keep==0l){
459 log(
"starting with clean buffer");
465 if (la_state.is_continuous_capture){
470 log(
"capture-done: %lu",buffer_ptr->
available());
474 if (la_state.is_continuous_capture){
479 log(
"capture-done: %lu",buffer_ptr->
available());
493 log(
"dumpData: %lu",buffer_ptr->
available());
495 uint32_t tmp[DUMP_RECORD_SIZE];
497 size_t len = buffer_ptr->
readBuffer(tmp, DUMP_RECORD_SIZE);
519 log(
"LogicAnalyzer");
524 log(
"~LogicAnalyzer");
525 if (buffer_ptr!=
nullptr) {
527 buffer_ptr =
nullptr;
529 if (pin_reader_ptr!=
nullptr){
530 delete pin_reader_ptr;
531 pin_reader_ptr =
nullptr;
549 stream_ptr = &procesingStream;
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;
561 if (pin_reader_ptr==
nullptr){
562 pin_reader_ptr =
new PinReader(pinStart);
565 if (do_allocate_buffer && buffer_ptr==
nullptr) {
571 capture->setLogicAnalyzer(*
this);
578 pinMode(pinStart+j, INPUT);
587 return la_state.pin_start;
592 return la_state.pin_numbers;
597 return *(stream_ptr);
602 return la_state.status_value;
612 return *(buffer_ptr);
619 log(
"processCommand %d", cmd);
626 return la_state.trigger_values;
631 la_state.trigger_values = values;
632 log(
"--> setTriggerValues: %u", (uint32_t) values);
638 return la_state.trigger_mask;
643 la_state.trigger_mask = values;
644 log(
"--> setTriggerValues: %u", (uint32_t) values);
650 return la_state.read_count;
655 la_state.read_count = count;
660 return la_state.delay_count;
665 log(
"--> setDelayCount: %d", count);
666 la_state.delay_count = count;
671 return la_state.frequecy_value;
676 return la_state.delay_time_us;
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);
690 return la_state.is_continuous_capture;
695 la_state.is_continuous_capture = cont;
700 la_state.eventHandler = eh;
707 if (buffer_ptr!=
nullptr){
708 memset(buffer_ptr->data_ptr(),0x00, la_state.max_capture_size*
sizeof(PinBitArray));
715 return buffer_ptr ==
nullptr ? 0 : buffer_ptr->
size();
720 return buffer_ptr ==
nullptr ? 0 : buffer_ptr->
available();
725 logger_ptr = &logger;
741 do_allocate_buffer = do_allocate;
746 if (capture_ptr!=
nullptr)
752 bool is_capture_on_arm =
true;
753 bool do_allocate_buffer =
true;
754 uint64_t sump_reset_igorne_timeout=0;
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";
769 return stream_ptr->available() > 0;
782 return la_state.cmd4;
786 void write(uint8_t cmd, uint32_t number){
788 uint32_t toSend = htonl(number);
789 stream().write((
byte*)&toSend,
sizeof(uint32_t));
794 void write(uint8_t cmd,
const char* str){
797 stream().write(
"\x000",1);
804 switch(
sizeof(PinBitArray)) {
806 return (PinBitArray) cmd.
getPtr()[0];
808 return (PinBitArray) cmd.
get16(0);
810 return (PinBitArray) cmd.
get32();
845 write(0x01, description);
846 write(0x02, firmware_version);
848 write(0x20, la_state.pin_numbers);
850 write(0x21, la_state.max_capture_size);
854 stream().write(protocol_version, strlen(protocol_version)+1);
869 if (millis()>sump_reset_igorne_timeout){
873 sump_reset_igorne_timeout = millis()+ 500;
883 stream().write(device_id, 4);
891 case SUMP_GET_METADATA:
892 log(
"=>SUMP_GET_METADATA");
904 if (is_capture_on_arm){
913 case SUMP_TRIGGER_MASK:
914 log(
"=>SUMP_TRIGGER_MASK");
922 case SUMP_TRIGGER_VALUES:
923 log(
"=>SUMP_TRIGGER_VALUES");
929 case SUMP_TRIGGER_CONFIG:
930 log(
"=>SUMP_TRIGGER_CONFIG");
938 case SUMP_SET_DIVIDER: {
939 log(
"=>SUMP_SET_DIVIDER");
941 uint32_t divider = cmd.
get32();
942 log(
"-divider: %lu\n", divider);
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);
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);
981 log(
"=>UNHANDLED command: %d", cmd);
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