Forum Rule: Always post complete source code & details to reproduce any issue!
Page 7 of 8 FirstFirst ... 5 6 7 8 LastLast
Results 151 to 175 of 177

Thread: Circular_Buffer

  1. #151
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    I could add print(ln) to circular arrays, it just wasnt added because it was just implemented in the buffer instead. If i do add it, though, since text has an arbitrary size, you will need the length() method which gives the length of the text in the queue, and use that when dequeuing to a matching char array size. If there is a use for this I will implement it later..

    No thats correct, you have a 32 byte buffer, 0-31.
    You then have a for loop up to 33 (which includes 0) (34 bytes total)
    0 and 1 are overridden.
    The head of the first read is pushed 2 places ahead as 0 and 1 are written as 32 and 33 (which the tail resides at (33)).
    Therefore, your first byte is 2 and your last byte is 33


    The first byte is always the oldest. If you prefer LIFO, you can read from back to front, otherwise default is FIFO, oldest to newest data.
    Last edited by tonton81; 01-03-2020 at 05:18 AM.

  2. #152
    Quote Originally Posted by tonton81 View Post
    No thats correct, you have a 32 byte buffer, 0-31.
    You then have a for loop up to 33 (which includes 0) (34 bytes total)
    0 and 1 are overridden.
    The head of the first read is pushed 2 places ahead as 0 and 1 are written as 32 and 33 (which the tail resides at (33)).
    Therefore, your first byte is 2 and your last byte is 33


    The first byte is always the oldest. If you prefer LIFO, you can read from back to front, otherwise default is FIFO, oldest to newest data.
    Hmm, so I modified the c5 section of the example to obtain a more detailed printout, as follows

    Code:
      
    uint8_t idx = 0;
      Serial.printf("Idx\tdata\t\Head Idx\tTail Idx\n");
      while ( c5.size() > 0 ) 
      {
        //Serial.println(c5.read());
        Serial.printf("%d\t%d\t%d\t%d\n", 
            idx, c5.read(), c5.front(), c5.back());
        idx++;
      }
    and got the following printout

    Code:
    Idx	data	Head Idx	Tail Idx
    0	2	536897338	536897330
    1	3	536897342	536897330
    2	4	536897346	536897330
    3	5	536897350	536897330
    4	6	536897354	536897330
    5	7	536897358	536897330
    6	8	536897362	536897330
    7	9	536897366	536897330
    8	10	536897370	536897330
    9	11	536897374	536897330
    10	12	536897378	536897330
    11	13	536897382	536897330
    12	14	536897386	536897330
    13	15	536897390	536897330
    14	16	536897394	536897330
    15	17	536897398	536897330
    16	18	536897402	536897330
    17	19	536897406	536897330
    18	20	536897410	536897330
    19	21	536897414	536897330
    20	22	536897418	536897330
    21	23	536897422	536897330
    22	24	536897426	536897330
    23	25	536897430	536897330
    24	26	536897434	536897330
    25	27	536897438	536897330
    26	28	536897442	536897330
    27	29	536897446	536897330
    28	30	536897450	536897330
    29	31	536897326	536897330
    30	32	536897330	536897330
    31	33	536897334	536897330
    Where the head/tail values appear to be actual RAM addresses rather than relative buffer indices - why is that?

    So then I looked at the code a bit, but I got lost pretty quickly ;-(.

    So, I went back and modified the example code to show relative element indices rather than RAM addresses, and also printed out several buffer attributes, as shown below:

    Code:
      Serial.print("Clearing buffer..."); c5.clear(); Serial.print("Done.\n");
      uint16_t* buffstart = c5.front();
      Serial.printf("Writing 34 values to a 32 position circular buffer...\n");
      Serial.printf("Idx\tdata\t\Rd Ptr\tWr Ptr\tSize\tAvail\tCap\n");
      //for ( uint16_t i = 0; i < 34; i++ ) c5.write(i);
      for (uint16_t i = 0; i < 34; i++)
      {
          c5.write(i);
        Serial.printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n", 
            i, i, (c5.front() - buffstart) / sizeof(uint16_t),
            (c5.back() - buffstart) / sizeof(uint16_t),
            c5.size(),c5.available(),c5.capacity());
      }
      Serial.printf("Done. \n\n");
      Serial.printf("Reading the above values back out again.......\n");
      Serial.printf("Idx\tdata\t\Rd Ptr\tWr Ptr\tSize\tAvail\tCap\n");
      uint8_t idx = 0;
      while ( c5.size() > 0 ) 
      {
        //Serial.println(c5.read());
          Serial.printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
              idx, c5.read(), (c5.front() - buffstart) / sizeof(uint16_t),
              (c5.back() - buffstart) / sizeof(uint16_t),
              c5.size(), c5.available(), c5.capacity());
          idx++;
      } 
      Serial.printf("Done. \n\n");
      //Serial.println("OK");
      
      while (true)
      {
    
      }
    And this produced the following output:

    Code:
    Opening port
    Port open
    ----------------------
    Clearing buffer...Done.
    Writing 34 values to a 32 position circular buffer...
    Idx	data	Rd Ptr	Wr Ptr	Size	Avail	Cap
    0	0	0	0	1	1	32
    1	1	0	1	2	2	32
    2	2	0	2	3	3	32
    3	3	0	3	4	4	32
    4	4	0	4	5	5	32
    5	5	0	5	6	6	32
    6	6	0	6	7	7	32
    7	7	0	7	8	8	32
    8	8	0	8	9	9	32
    9	9	0	9	10	10	32
    10	10	0	10	11	11	32
    11	11	0	11	12	12	32
    12	12	0	12	13	13	32
    13	13	0	13	14	14	32
    14	14	0	14	15	15	32
    15	15	0	15	16	16	32
    16	16	0	16	17	17	32
    17	17	0	17	18	18	32
    18	18	0	18	19	19	32
    19	19	0	19	20	20	32
    20	20	0	20	21	21	32
    21	21	0	21	22	22	32
    22	22	0	22	23	23	32
    23	23	0	23	24	24	32
    24	24	0	24	25	25	32
    25	25	0	25	26	26	32
    26	26	0	26	27	27	32
    27	27	0	27	28	28	32
    28	28	0	28	29	29	32
    29	29	0	29	30	30	32
    30	30	0	30	31	31	32
    31	31	0	31	32	32	32
    32	32	1	0	32	32	32
    33	33	2	1	32	32	32
    Done. 
    
    Reading the above values back out again.......
    Idx	data	Rd Ptr	Wr Ptr	Size	Avail	Cap
    0	2	3	1	31	31	32
    1	3	4	1	30	30	32
    2	4	5	1	29	29	32
    3	5	6	1	28	28	32
    4	6	7	1	27	27	32
    5	7	8	1	26	26	32
    6	8	9	1	25	25	32
    7	9	10	1	24	24	32
    8	10	11	1	23	23	32
    9	11	12	1	22	22	32
    10	12	13	1	21	21	32
    11	13	14	1	20	20	32
    12	14	15	1	19	19	32
    13	15	16	1	18	18	32
    14	16	17	1	17	17	32
    15	17	18	1	16	16	32
    16	18	19	1	15	15	32
    17	19	20	1	14	14	32
    18	20	21	1	13	13	32
    19	21	22	1	12	12	32
    20	22	23	1	11	11	32
    21	23	24	1	10	10	32
    22	24	25	1	9	9	32
    23	25	26	1	8	8	32
    24	26	27	1	7	7	32
    25	27	28	1	6	6	32
    26	28	29	1	5	5	32
    27	29	30	1	4	4	32
    28	30	31	1	3	3	32
    29	31	0	1	2	2	32
    30	32	1	1	1	1	32
    31	33	2	1	0	0	32
    Done.
    Which leads me to ask the following questions:

    1. 'front()' returns the READ pointer, and 'back()' returns the WRITE pointer. Is this correct?
    2. 'size()' appears to return the number of elements written since the last 'clear()' operation; is this correct?
    3. 'available()' appears to be identical to 'size()'. Why have two functions that return identical results?
    4. 'capacity()' appears to return the original element capacity - correct?


    Sorry for all the too-basic questions, but I'm a circular buffer noob ;-)

    TIA,

    Frank

  3. #153
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    1 is correct, but back is a READ pointer as well. Thats how you pull LIFO.
    size and available are the same, due to common usages between programmers, spme may prefer one over the other. Capacity is the size given in the constructor, just for the user to check the size() doesnt exceed capacity() before adding, otherwise oldest entry will be overidden

  4. #154
    Thanks for the quick response! I'm going to try and use your circular buffer class for my I2C Sniffer project, and I'm sure I'll have more questions ;-).

  5. #155
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    Dont worry, theres more features there than you realize, which makes data entry and data lookups one of the excellent features of circular arrays.

  6. #156
    I created a small program to test the idea of using a circular buffer for my I2C Sniffer program. An ISR that triggers every microsecond from Timer1 reads an 8-bit value from a fixed array containing previously captured I2C bus transitions, and then writes the value to a circular buffer. Writes to the buffer pause when the last byte of the simulated data array is read. Reading and writing are re-enabled every 200 mSec by an interval timer in loop(). Code is shown below:

    Code:
    /*
        Name:       Teensy_I2C_Sniffer_V6.ino
        Created:	1/4/2020 8:40:20 AM
        Author:     FRANKNEWXPS15\Frank
    
        This is a port of my Excel VBA code into Arduino/Teensy C++ language.
        It parses the exact same sample data as the Excel program, so it should
        produce the exact same I2C sequences.
    
        The captured sample data to be parsed is held in the 'simdata' array.
    
        The original VBA code is saved in 'ExcelVBACode.txt'
    */
    
    /* 'Notes:
    
        A typical I2C sentence when communicating with a MPU6050 IMU module goes like:
            "I2C(68) wrote 1 byte to 75 - C0 Done."
            "I2C(68) wrote 3 bytes to 72 - C0 0C 10 Done."
            "I2C(68) read 5 bytes from 6A - C0 0C 10 14 03 Done."
    
        To form a sentence, we need:
            Device addr: 68 in the above examples
            Read/Write direction
            To/From register address:  75, 72 and 6A in the above examples
            Data:  C0, C0 0C 10, and C0 0C 10 14 03 in the above examples
            number of bytes written/read:  1,3 & 5 in the above examples
    
         Each I2C communication proceeds as follows (assuming a START from an IDLE condition):
             A START or RESTART condition, denoted by SDA & SCL HIGH, followed by SDA LOW, SCL HIGH
             A 7-bit device address, MSB first (0x8/0xC = 1, 0x0/0x4 = 0)
             A R/W bit (0x8/0xC = read, 0x0/0x4 = write)
             An ACK bit (0x8/0xC = NAK, 0x0/0x4 = ACK)
             If the bus direction is WRITE, then
                 A register address for read/write
                 zero or more additional data bytes
             Else (the bus direction is READ)
                One or more additional data bytes
             Endif
    */
    
    /*
    This version adds tonton81's circular buffer class (https://github.com/tonton81/Circular_Buffer)
    to simulate real-time processing and display of I2C bus activity.  The sample data is loaded into
    a FIFO by an ISR triggered every microsecond by a timer, and then the processing code pulls it out
    and parses it as fast as possible.  If this works, then the next version will eliminate the sample
    data and connect to a live I2C bus.
    */
    
    #include <TimerOne.h> //needed for ISR
    #include "circular_buffer.h"
    Circular_Buffer<uint8_t, 2048> cb_trans; //holds transition values from ISR
    
    #define MONITOR_OUT1 2 //so can monitor ISR activity with O'scope
    #define MONITOR_OUT2 3 //so can monitor ISR activity with O'scope
    
    const int SIM_DATA_ARRAY_SIZE = 928;
    byte simdata[SIM_DATA_ARRAY_SIZE] =
    {
        0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc,
        0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0xc,
        0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc,
        0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8,
        0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8,
        0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8,
        0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8,
        0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4,
        0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8,
        0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc,
        0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc,
        0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8,
        0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4,
        0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8,
        0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x8, 0xc
    };
    
    //#define PARSE_LOOP_DEBUG
    //#define GET_8BIT_DATABYTE_DEBUG
    const int BUFFER_CHECK_INTERVAL_MSEC = 200;
    #pragma region PROCESSING_VARIABLES
    uint8_t devAddr;
    uint8_t regAddr;
    
    //added for bus direction labels
    enum BUSDIR
    {
        WRITE,
        READ,
        UNKNOWN = -1
    } RWDir;
    BUSDIR BusDir = BUSDIR::UNKNOWN;
    
    int ACKNAKFlag; //can be negative
    uint8_t databyte_array[2048]; //holds multiple databytes for later output sentence construction
    uint16_t databyte_idx = 0; //index into databyte_array FIFO
    uint16_t numbytes = 0; //number of data bytes extracted from data stream
    #pragma endregion ProcVars
    
    #pragma region ISR_VARS
    uint16_t  write_index = 0;
    uint16_t  read_index = 0;
    uint8_t   current_portb = 0xFF;
    uint8_t   last_portb = 0xFF;
    bool bBufferFull = false;
    elapsedMillis mSecSinceLastBufferCheck;
    uint8_t* frontptr = 0;
    #pragma endregion ISRVars
    
    
    
    //-------------------------------------------------------------------------------
    //--------------------------------    ISR    ------------------------------------
    //-------------------------------------------------------------------------------
    //01/04/2020 modified to 'capture' data from simdata[]
    void capture_data(void)
    {
        last_portb = current_portb;
        current_portb = simdata[read_index]; //pull one transition value from simdata
        read_index++;
    
        if (last_portb != current_portb && !bBufferFull)
        {
            cb_trans.write(current_portb); //add current transition value to FIFO
            digitalWriteFast(MONITOR_OUT1, !digitalReadFast(MONITOR_OUT1));
        }
        
        //pause writing to cb_trans circular buffer
        if (read_index >= SIM_DATA_ARRAY_SIZE)
        {
            bBufferFull = true;
            read_index = 0;
            digitalWriteFast(MONITOR_OUT1, LOW);
        }
    }
    
    void setup()
    {
        Serial.begin(1); //rate value ignored
        unsigned long now = millis();
        int idx = 0;
        while (!Serial && (millis() - now) < 3000)
        {
            delay(500);
            idx++;
        }
        Serial.printf("Serial available after %lu mSec\n", millis() - now);
    
        pinMode(MONITOR_OUT1, OUTPUT);
        pinMode(MONITOR_OUT2, OUTPUT);
        pinMode(LED_BUILTIN, OUTPUT);
        Timer1.initialize(1); // run every mico second
        Timer1.attachInterrupt(capture_data);
    
        frontptr = cb_trans.front();
    
        mSecSinceLastBufferCheck = 0;
    }
    
    void loop()
    {
        if (mSecSinceLastBufferCheck > BUFFER_CHECK_INTERVAL_MSEC)
        {
            Serial.printf("%lu: cb_trans contains = %d elements\n", millis(), cb_trans.back()- frontptr);
            mSecSinceLastBufferCheck -= BUFFER_CHECK_INTERVAL_MSEC;
            cb_trans.clear();
            read_index = 0;
            bBufferFull = false;
            digitalWriteFast(MONITOR_OUT2, !digitalReadFast(MONITOR_OUT2));
        }
    }
    A partial output is as follows:

    Code:
    Opening port
    Port open
    Serial available after 1000 mSec
    1501: cb_trans contains = 1854 elements
    1701: cb_trans contains = 1852 elements
    1901: cb_trans contains = 1852 elements
    2101: cb_trans contains = 1852 elements
    2301: cb_trans contains = 1852 elements
    2501: cb_trans contains = 1852 elements
    2701: cb_trans contains = 1852 elements
    2901: cb_trans contains = 1852 elements
    3101: cb_trans contains = 1852 elements
    3301: cb_trans contains = 1852 elements
    3501: cb_trans contains = 1852 elements
    3701: cb_trans contains = 1852 elements
    3901: cb_trans contains = 1852 elements
    4101: cb_trans contains = 1852 elements
    4301: cb_trans contains = 1852 elements
    4501: cb_trans contains = 1852 elements
    
    Port closed
    I was a bit surprised to see that the number of elements in the circular buffer was almost exactly TWICE the value I expected. The simdata[] array contains 928 8-bit values, and the circular buffer is defined as containing uint8_t elements, so I don't understand the x2 factor.

    What am I doing wrong here?

    TIA,

    Frank

  7. #157
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    Have you checked .size() for number of elements? Perhaps your calculation is wrong, try size() to confirm

    back() and front(), by the way show the byte in either head or tail of the queue

    In printf, also, %d is signed, try %u?

  8. #158
    Tonton81,

    OK, size() returns 928, as expected. Changing the %d to %u for front()-frontptr doesn't change anything. Maybe

    Code:
    Circular_Buffer<uint8_t, 2048> cb_trans; //holds transition values from ISR
    is really defined as

    Code:
    Circular_Buffer<uint8_16, 2048> cb_trans;
    under the hood?

  9. #159
    Tonton81,

    OK, size() returns 928, as expected. Changing the %d to %u for front()-frontptr doesn't change anything. Maybe

    Code:
    Circular_Buffer<uint8_t, 2048> cb_trans; //holds transition values from ISR
    is really defined as

    Code:
    Circular_Buffer<uint8_16, 2048> cb_trans;
    under the hood?

  10. #160
    Changed the print line to

    Code:
            Serial.printf("%lu: cb_trans contains = %d elements\n", millis(), cb_trans.size());
    And now I get for output:

    Code:
    Opening port
    Port open
    5701: cb_trans contains = 928 elements
    5901: cb_trans contains = 927 elements
    6101: cb_trans contains = 928 elements
    6301: cb_trans contains = 928 elements
    6501: cb_trans contains = 928 elements
    6701: cb_trans contains = 928 elements
    6901: cb_trans contains = 928 elements
    7101: cb_trans contains = 928 elements
    7301: cb_trans contains = 928 elements
    7501: cb_trans contains = 928 elements
    7701: cb_trans contains = 928 elements
    7901: cb_trans contains = 927 elements
    8101: cb_trans contains = 928 elements
    8301: cb_trans contains = 928 elements
    8501: cb_trans contains = 928 elements
    8701: cb_trans contains = 928 elements
    8901: cb_trans contains = 927 elements
    9101: cb_trans contains = 928 elements
    9301: cb_trans contains = 928 elements
    9501: cb_trans contains = 928 elements
    9701: cb_trans contains = 928 elements
    9901: cb_trans contains = 928 elements
    10101: cb_trans contains = 928 elements
    10301: cb_trans contains = 928 elements
    10501: cb_trans contains = 928 elements
    10701: cb_trans contains = 928 elements
    10901: cb_trans contains = 928 elements
    11101: cb_trans contains = 928 elements
    11301: cb_trans contains = 928 elements
    11501: cb_trans contains = 928 elements
    11701: cb_trans contains = 927 elements
    
    Port closed
    Not quite sure why I occasionally get 927 elements, as the 200 mSec interval time is much much longer than the time required to read & write all 928 elements.

    If I reduce the interval time to zero, I get

    Code:
    Opening port
    Port open
    Serial available after 1000 mSec
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1300: cb_trans contains = 0 elements
    1303: cb_trans contains = 1856 elements
    1304: cb_trans contains = 2048 elements
    1305: cb_trans contains = 2048 elements
    1307: cb_trans contains = 2048 elements
    1308: cb_trans contains = 2048 elements
    1310: cb_trans contains = 2048 elements
    1311: cb_trans contains = 2048 elements
    1312: cb_trans contains = 2048 elements
    So size() is clearly working properly, and the time stamps show that it only takes 3-4 mSec to fill the 2048-element (still not sure if they are 8 or 16-bit elements though) circular buffer.

    So, assuming that my 928-transition (414 8-bit bytes) is representative of a typical I2C burst, and my intended application only produces one burst every 200 mSec, I should have essentially infinite time to decode the transitions & print results - yay!

    Frank


    Frank

  11. #161
    Sorry == forgot to mention that for the 'zero interval' output I also commented out the 'cb_trans.clear()' call to let the FIFO contents build up to max capacity.

    Frank

  12. #162
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    The type for the buffer, is guarenteed to be the type you used in the template constructor. uint8_t, it is impossible for the compiler to generate a different type than the one you specified to the template parameter. Even though it wasn't mentioned, I'm currently now working with a circular array of 74 uint64_t's, 64 levels

  13. #163
    So, the 2x factor between size, and the difference between the front() and back() values?

  14. #164
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    Front and back are just a pointer in CBA. Example:

    cb_trans.front()[2];

    This basically gives you the data stored in indice 2 of the front of the queue. Same goes for back(). This is just a pointer, basically, to your array in the front or end of the queue.

    I use the back() method to compare data on canbus between the last stored frame and the one that just came in. After the comparison, if data I choose to compare is different, then the new frame is stored in the list.

  15. #165
    I understand they are just pointers, but why is there a difference of 1852 between the front and back pointers of a 928-byte 8-bit-per-element circular buffer? The inference is that it takes 2 pointer locations to store one 8-bit byte, which doesn't make a whole lot of sense.

  16. #166
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    Serial.printf("%lu: cb_trans contains = %d elements\n", millis(), cb_trans.back()- frontptr);


    Have you tried using the now pointed to array as references? &frontptr &xxxx.back() etc

    https://stackoverflow.com/questions/...block-or-array

  17. #167
    I'm trying to use cb.ReadBytes() in a function, but it doesn't seem to be working the way I would expect. Here's the function

    Code:
    //uint8_t Get7BitDeviceAddr(byte * simdata, uint16_t & readidx)
    uint8_t Get7BitDeviceAddr(Circular_Buffer<uint8_t, 2048>& cb)
    {
        //Purpose: Construct a 7-bit address starting from next FIFO element
        //Inputs:
        //  cb = reference to cb_trans FIFO
        //Outputs:
        //  returns the address as an 8-bit value with the MSB = 0, or 0x0 if unsuccessful
        //  the 14 transitions associated with the 7-bit address removed from FIFO
        //Plan:
        //  Step1: Convert a pair of FIFO elements into a 0 or 1
        //  Step2: Add the appropriate value to an ongoing sum
        //  Step3: return the total.
        //Notes:
        //  A '0' is coded as a 0x0 followed by a 0x4
        //  A '1' is coded as a 0x8 followed by a 0xC
    
        uint8_t devAddr = 0x0; //failure return value
    
        //devAddr is exactly 7 bits long, so 8 bits with MSB = 0
        uint8_t data[2]; //holds one transition pair
        for (size_t i = 0; i < 7; i++)
        {
    
            //cb.readBytes(data, 2);
            data[0] = cb.read();
            data[1] = cb.read();
            Serial.printf("data[0] = %x, data[1] = %x\n", data[0], data[1]);
    
            if (data[0] == 0x8 && data[1] == 0xC)
            {
                Serial.printf("Get7BitDeviceAddr: '1' found at i = %d, adding %x to devAddr to get %x\n",
                    i, 1 << (7 - i), devAddr + (1 << (7 - i)));
    
                devAddr += (1 << (7 - i)); //add 2^(7-i) to sum
            }
        }
    
        devAddr = devAddr >> 1; //divide result by 2 to get 7-bit addr from 8 bits
        return devAddr;
    }
    With the code as shown above (readBytes() commented out, replaced by two calls to read(), I get the following (correct) output:

    Code:
    Opening port
    Port open
    Serial available after 1000 mSec
    1501: cb_trans contains = 928 elements
    1501: In DecodeAndPrintFIFOContents()
    Start sequence found, FIFO size = 926
    First 20 elements in the FIFO are
    0: 8
    1: c
    2: 8
    3: c
    4: 0
    5: 4
    6: 8
    7: c
    8: 0
    9: 4
    10: 0
    11: 4
    12: 0
    13: 4
    14: 0
    15: 4
    16: 0
    17: 4
    18: 0
    19: 4
    data[0] = 8, data[1] = c
    Get7BitDeviceAddr: '1' found at i = 0, adding 80 to devAddr to get 80
    data[0] = 8, data[1] = c
    Get7BitDeviceAddr: '1' found at i = 1, adding 40 to devAddr to get c0
    data[0] = 0, data[1] = 4
    data[0] = 8, data[1] = c
    Get7BitDeviceAddr: '1' found at i = 3, adding 10 to devAddr to get d0
    data[0] = 0, data[1] = 4
    data[0] = 0, data[1] = 4
    data[0] = 0, data[1] = 4
    devAddr = 68, FIFO size = 912
    However, if I comment out the two calls to read() and uncomment the call to readBytes(), I get the following output:

    Code:
    Opening port
    Port open
    Serial available after 1000 mSec
    1501: cb_trans contains = 928 elements
    1501: In DecodeAndPrintFIFOContents()
    Start sequence found, FIFO size = 926
    First 20 elements in the FIFO are
    0: 8
    1: c
    2: 8
    3: c
    4: 0
    5: 4
    6: 8
    7: c
    8: 0
    9: 4
    10: 0
    11: 4
    12: 0
    13: 4
    14: 0
    15: 4
    16: 0
    17: 4
    18: 0
    19: 4
    data[0] = c, data[1] = 4
    data[0] = c, data[1] = 4
    data[0] = c, data[1] = 4
    data[0] = c, data[1] = 4
    data[0] = c, data[1] = 4
    data[0] = c, data[1] = 4
    data[0] = c, data[1] = 4
    devAddr = 0, FIFO size = 912
    What am I doing wrong here?

    Frank

  18. #168
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    can you post a full sketch i can load it to a standalone teensy to test? Last post is a snippet

    EDIT, nevermind, I see the issue with readBytes. That will need to be fixed.
    Last edited by tonton81; 01-05-2020 at 01:36 AM.

  19. #169
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    Ok try the patch

    https://github.com/tonton81/Circular_Buffer

    Test example:

    Code:
    #include "circular_buffer.h"
    
    
    Circular_Buffer<uint8_t, 32> c5;
    
    void setup() {
      Serial.begin(1);
      delay(500);
      Serial.println("----------------------");
    
    
      for ( uint16_t i = 0; i < 34; i++ ) c5.write(i);
    
      if ( 1 ) {
        Serial.println(c5.read());
        Serial.println(c5.read());
      }
      else {
        uint8_t data[2];
        c5.readBytes(data, 2);
        Serial.println(data[0]);
        Serial.println(data[1]);
      }
    
    }
    
    void loop() {
    
    }
    Change the if value to 0 or 1 to try both ways

  20. #170
    It appears that peekbytes() might have an issue too. Here's my (somewhat messy, sorry) code in its entirety:

    Code:
    /*
        Name:       Teensy_I2C_Sniffer_V6.ino
        Created:	1/4/2020 8:40:20 AM
        Author:     FRANKNEWXPS15\Frank
    
        This is a port of my Excel VBA code into Arduino/Teensy C++ language.
        It parses the exact same sample data as the Excel program, so it should
        produce the exact same I2C sequences.
    
        The captured sample data to be parsed is held in the 'simdata' array.
    
        The original VBA code is saved in 'ExcelVBACode.txt'
    */
    
    /* 'Notes:
    
        A typical I2C sentence when communicating with a MPU6050 IMU module goes like:
            "I2C(68) wrote 1 byte to 75 - C0 Done."
            "I2C(68) wrote 3 bytes to 72 - C0 0C 10 Done."
            "I2C(68) read 5 bytes from 6A - C0 0C 10 14 03 Done."
    
        To form a sentence, we need:
            Device addr: 68 in the above examples
            Read/Write direction
            To/From register address:  75, 72 and 6A in the above examples
            Data:  C0, C0 0C 10, and C0 0C 10 14 03 in the above examples
            number of bytes written/read:  1,3 & 5 in the above examples
    
         Each I2C communication proceeds as follows (assuming a START from an IDLE condition):
             A START or RESTART condition, denoted by SDA & SCL HIGH, followed by SDA LOW, SCL HIGH
             A 7-bit device address, MSB first (0x8/0xC = 1, 0x0/0x4 = 0)
             A R/W bit (0x8/0xC = read, 0x0/0x4 = write)
             An ACK bit (0x8/0xC = NAK, 0x0/0x4 = ACK)
             If the bus direction is WRITE, then
                 A register address for read/write
                 zero or more additional data bytes
             Else (the bus direction is READ)
                One or more additional data bytes
             Endif
    */
    
    /*
    This version adds tonton81's circular buffer class (https://github.com/tonton81/Circular_Buffer)
    to simulate real-time processing and display of I2C bus activity.  The sample data is loaded into
    a FIFO by an ISR triggered every microsecond by a timer, and then the processing code pulls it out
    and parses it as fast as possible.  If this works, then the next version will eliminate the sample
    data and connect to a live I2C bus.
    */
    
    #include <TimerOne.h> //needed for ISR
    #include "circular_buffer.h"
    Circular_Buffer<uint8_t, 2048> cb_trans; //holds transition values from ISR
    
    #define MONITOR_OUT1 2 //so can monitor ISR activity with O'scope
    #define MONITOR_OUT2 3 //so can monitor ISR activity with O'scope
    
    const int SIM_DATA_ARRAY_SIZE = 928;
    byte simdata[SIM_DATA_ARRAY_SIZE] =
    {
        0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc,
        0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0xc,
        0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc,
        0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8,
        0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8,
        0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8,
        0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8,
        0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4,
        0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8,
        0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc,
        0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc,
        0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4,
        0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8,
        0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4,
        0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8,
        0xc, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0,
        0x4, 0x0, 0x4, 0x8, 0xc, 0x8, 0xc, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x0, 0x4, 0x0, 0x4, 0x8, 0xc, 0x0, 0x4, 0xc, 0x4, 0x8, 0xc, 0x8, 0xc, 0x0,
        0x4, 0x8, 0xc, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4,
        0x8, 0xc
    };
    
    #define PARSE_LOOP_DEBUG
    //#define GET_8BIT_DATABYTE_DEBUG
    const int BUFFER_CHECK_INTERVAL_MSEC = 200;
    //const int BUFFER_CHECK_INTERVAL_MSEC = 5;
    #pragma region PROCESSING_VARIABLES
    uint8_t devAddr;
    uint8_t regAddr;
    
    //added for bus direction labels
    enum BUSDIR
    {
        WRITE,
        READ,
        UNKNOWN = -1
    } RWDir;
    BUSDIR BusDir = BUSDIR::UNKNOWN;
    
    int ACKNAKFlag; //can be negative
    uint8_t databyte_array[2048]; //holds multiple databytes for later output sentence construction
    uint16_t databyte_idx = 0; //index into databyte_array
    uint16_t numbytes = 0; //number of data bytes extracted from data stream
    uint8_t killbuff[2]; //used to consume start/stop bytes
    
    #pragma endregion ProcVars
    
    #pragma region ISR_VARS
    uint16_t  write_index = 0;
    uint16_t  read_index = 0;
    uint8_t   current_portb = 0xFF;
    uint8_t   last_portb = 0xFF;
    bool bBufferFull = false;
    elapsedMillis mSecSinceLastBufferCheck;
    #pragma endregion ISRVars
    
    int DecodeAndPrintFIFOContents(Circular_Buffer<uint8_t, 2048>& cb); //need forward reference here
    
    
    //-------------------------------------------------------------------------------
    //--------------------------------    ISR    ------------------------------------
    //-------------------------------------------------------------------------------
    //01/04/2020 modified to 'capture' data from simdata[]
    void capture_data(void)
    {
        if (!bBufferFull) //for debug - writes only one set of data to FIFO
        {
            last_portb = current_portb;
            current_portb = simdata[read_index]; //pull one transition value from simdata
            read_index++;
    
            if (last_portb != current_portb && !bBufferFull)
            {
                cb_trans.write(current_portb); //add current transition value to FIFO
                digitalWriteFast(MONITOR_OUT1, !digitalReadFast(MONITOR_OUT1));
            }
        
            //pause writing to cb_trans circular buffer
            if (read_index >= SIM_DATA_ARRAY_SIZE)
            {
                bBufferFull = true;
                read_index = 0;
                digitalWriteFast(MONITOR_OUT1, LOW);
            }
        }
    }
    
    void setup()
    {
        Serial.begin(1); //rate value ignored
        unsigned long now = millis();
        int idx = 0;
        while (!Serial && (millis() - now) < 3000)
        {
            delay(500);
            idx++;
        }
        Serial.printf("Serial available after %lu mSec\n", millis() - now);
    
        pinMode(MONITOR_OUT1, OUTPUT);
        pinMode(MONITOR_OUT2, OUTPUT);
        pinMode(LED_BUILTIN, OUTPUT);
        Timer1.initialize(1); // run every mico second
        Timer1.attachInterrupt(capture_data);
    
        mSecSinceLastBufferCheck = 0;
    }
    
    void loop()
    {
        if (mSecSinceLastBufferCheck > BUFFER_CHECK_INTERVAL_MSEC)
        {
            Serial.printf("%lu: cb_trans contains = %d elements\n", millis(), cb_trans.size());
            mSecSinceLastBufferCheck -= BUFFER_CHECK_INTERVAL_MSEC;
            DecodeAndPrintFIFOContents(cb_trans); //decode and print everything captured so far
            //cb_trans.clear();
            read_index = 0;
            bBufferFull = false;
            digitalWriteFast(MONITOR_OUT2, !digitalReadFast(MONITOR_OUT2));
            while (true)
            {
    
            }
        }
    }
    
    void PrintNextFIFOBytes(Circular_Buffer<uint8_t, 2048>& cb, uint8_t numbytes)
    {
        Serial.printf("Next %d FIFO Bytes: ", numbytes);
        for (size_t i = 0; i < numbytes-1; i++)
        {
            Serial.printf("%x,", cb.peek(i));
        }
        Serial.printf("%x\n", cb.peek(numbytes-1));
    }
    bool IsStart(Circular_Buffer<uint8_t, 2048>& cb)
    {
        bool result = false;
    
        uint8_t data[2]; data[0] = data[1] = 0;
        //DEBUG!!
        Serial.printf("IsStart() just before cb.peekBytes(data, 2): data[0] = %x,data[1] = %x, size = %d, idx = %d\n",
            data[0],data[1], cb.size(), SIM_DATA_ARRAY_SIZE - cb.size());
        PrintNextFIFOBytes(cb, 10);
        //DEBUG!!
        cb.peekBytes(data, 2);
        //DEBUG!!
        Serial.printf("IsStart() just after cb.peekBytes(data, 2): data[0] = %x,data[1] = %x, size = %d, idx = %d\n",
            data[0],data[1], cb.size(), SIM_DATA_ARRAY_SIZE - cb.size());
        PrintNextFIFOBytes(cb, 10);
        //DEBUG!!
        if (data[0] == 0xC && data[1] == 0x4)
        {
            Serial.printf("Start detected at size = %d, data idx = %d\n", cb.size(), SIM_DATA_ARRAY_SIZE - cb.size());
            result = true;
        }
    
        return result;
    }
    
    bool IsStop(Circular_Buffer<uint8_t, 2048>& cb)
    {
        bool result = false;
    
        uint8_t data[2];
        cb.peekBytes(data, 2);
        if (data[0] == 0x4 && data[1] == 0xC)
        {
            //cb.readBytes(data, 2); //consume these bytes
            result = true;
        }
    
        return result;
    
    }
    
    uint8_t Get7BitDeviceAddr(Circular_Buffer<uint8_t, 2048>& cb)
    {
        //Purpose: Construct a 7-bit address starting from next FIFO element
        //Inputs:
        //  cb = reference to cb_trans FIFO
        //Outputs:
        //  returns the address as an 8-bit value with the MSB = 0, or 0x0 if unsuccessful
        //  the 14 transitions associated with the 7-bit address removed from FIFO
        //Plan:
        //  Step1: Convert a pair of FIFO elements into a 0 or 1
        //  Step2: Add the appropriate value to an ongoing sum
        //  Step3: return the total.
        //Notes:
        //  A '0' is coded as a 0x0 followed by a 0x4
        //  A '1' is coded as a 0x8 followed by a 0xC
    
        uint8_t devAddr = 0x0; //failure return value
    
        //devAddr is exactly 7 bits long, so 8 bits with MSB = 0
        uint8_t data[2]; //holds one transition pair
        for (size_t i = 0; i < 7; i++)
        {
    
            cb.readBytes(data, 2);
            //data[0] = cb.read();
            //data[1] = cb.read();
            //Serial.printf("data[0] = %x, data[1] = %x\n", data[0], data[1]);
    
            if (data[0] == 0x8 && data[1] == 0xC)
            {
                //Serial.printf("Get7BitDeviceAddr: '1' found at i = %d, adding %x to devAddr to get %x\n",
                    //i, 1 << (7 - i), devAddr + (1 << (7 - i)));
    
                devAddr += (1 << (7 - i)); //add 2^(7-i) to sum
            }
        }
    
        devAddr = devAddr >> 1; //divide result by 2 to get 7-bit addr from 8 bits
        return devAddr;
    }
    
    int GetReadWriteFlag(Circular_Buffer<uint8_t, 2048>& cb)
    {
        //Purpose: decode R/W byte pair
        //Inputs:
        //  cb = reference to cb_trans FIFO
        //Outputs:
        //  readidx = if successful, points to next byte pair in simdata
        //  returns 1 for Read (0x8/0xC), 0 for Write (0x0/0x4), -1 for failure
        //Notes:
        //  
    
        int result = 0;
        uint8_t data[2];
        data[0] = cb.read();
        data[1] = cb.read();
        //Serial.printf("data[0] = %x, data[1] = %x\n", data[0], data[1]);
    
        if (data[0] == 0x8 && data[1] == 0xC)
        {
            result = 1; //read detected
        }
    
        //else if (simdata[readidx] == 0x0 && simdata[readidx + 1] == 0x4)
        else if (data[0] == 0x0 && data[1] == 0x4)
        {
            result = 0; //write detected
        }
        else
        {
            result = -1; //failed to detect read or write
        }
    
        return result;
    }
    
    int GetACKNAKFlag(Circular_Buffer<uint8_t, 2048>& cb)
    {
        //Purpose: decode ACK/NAK byte pair
        //Inputs:
        //  cb = reference to cb_trans circular buffer holding transition values
        //Outputs:
        //  returns 1 for NAK (0x8/0xC), 0 for ACK (0x0/0x4), -1 for failure
        //Notes:
        //  this code is identical to the code for GetReadWriteFlag, so use it instead 
    
         return GetReadWriteFlag(cb_trans);
    
    }
    int Get8BitDataByte(Circular_Buffer<uint8_t, 2048>& cb)
    {
        //Purpose: Construct a 8-bit data byte starting from dataidx
        //Inputs:
        //  cb = reference to cb_trans circular buffer holding transition values
        //Outputs:
        //  returns the address as an 8-bit value, or -1 if unsuccessful
        //  dataidx = pointer to next simdata entry
        //Plan:
        //  Step1: Convert a pair of simdata entries into a 0 or 1
        //  Step2: Add the appropriate value to an ongoing sum
        //  Step3: return the total.
        //Notes:
        //  A '0' is coded as a 0x0 followed by a 0x4
        //  A '1' is coded as a 0x8 followed by a 0xC
        //  12/29/19 - changed return val to int, so can return -1 when a 'short byte' is detected
    
        int dataval = 0x0; 
    
        Serial.printf("Get8BitDataByte: cb.size = %d, index = %d\n",
            cb.size(), SIM_DATA_ARRAY_SIZE-cb.size());
        PrintNextFIFOBytes(cb, 20);
    
        //8 bits with MSB = 0
        int numbytes = 0;
        uint8_t data[2]; //holds one transition pair
    
        for (size_t i = 0; i < 8; i++)
        {
            cb.readBytes(data, 2);
            //Serial.printf("data[0] = %x, data[1] = %x\n", data[0], data[1]);
    
            if (data[0] == 0x0 && data[1] == 0x4)
            {
                numbytes++;
            }
    
            
            else if (data[0] == 0x8 && data[1] == 0xC)
            {
    #ifdef GET_8BIT_DATABYTE_DEBUG
                Serial.printf("Get8BitDataByte: '1' found at i = %d, adding %x to devAddr to get %x\n",
                    i, 1 << (7 - i), dataval + (1 << (7 - i)));
    #endif
                dataval += (1 << (7 - i)); //add 2^(8-i) to sum
                numbytes++;
            }
        }
    
    #ifdef GET_8BIT_DATABYTE_DEBUG
        Serial.printf("Get8BitDataByte: numbytes = %d\n", numbytes);
    #endif
        if (numbytes != 8)
        {
            dataval = -1; //error return value
        }
    
        return dataval;
    }
    
    int GetDataBytes(Circular_Buffer<uint8_t, 2048>& cb, uint8_t* databytes)
    {
        //Notes:
        //  01/01/2020: removed databyteidx from sig - always starts at zero
    
        uint16_t numbytes = 0;
        uint16_t databyte_idx = 0;
    
        bool StartFlag = false;
        bool StopFlag = false;
        int dataval;
    
        do
        {
            dataval = Get8BitDataByte(cb);
    //DEBUG!!
            Serial.printf("GetDataBytes() just after Get8BitDataByte(): datval = %x, size = %d, idx = %d\n", 
                dataval, cb.size(), SIM_DATA_ARRAY_SIZE-cb.size());
            PrintNextFIFOBytes(cb, 10);
    //DEBUG!!
    
            //watch out for 'short byte' reads
            if (dataval >= 0)
            {
                uint8_t databyte = (uint8_t)dataval;
                databyte_array[databyte_idx] = databyte;
                databyte_idx++;
                numbytes++;
            }
    
            ACKNAKFlag = GetACKNAKFlag(cb_trans);
    //DEBUG!!
            Serial.printf("GetDataBytes() just after GetACKNAKFlag(): ACKNAK = %d, size = %d, idx = %d\n", 
                ACKNAKFlag, cb.size(), SIM_DATA_ARRAY_SIZE-cb.size());
            PrintNextFIFOBytes(cb, 10);
    //DEBUG!!
            StartFlag = IsStart(cb_trans);
    //DEBUG!!
            Serial.printf("GetDataBytes() just after IsStart(): StartFlag = %d, size = %d, idx = %d\n", 
                StartFlag, cb.size(), SIM_DATA_ARRAY_SIZE-cb.size());
            PrintNextFIFOBytes(cb, 10);
    //DEBUG!!
            StopFlag = IsStop(cb_trans);
    
    #ifdef PARSE_LOOP_DEBUG
            Serial.printf("IsStart %d, IsStop  %d, next two bytes are %x, %x, data idx = %d\n",
                StartFlag, StopFlag, cb.peek(0), cb.peek(1), SIM_DATA_ARRAY_SIZE-cb.size());
    #endif
    
        } while (!StartFlag && !StopFlag && cb_trans.size() > 0);
    
        return numbytes;
    }
    
    void OutputFormattedSentence(int RW, uint8_t dev, uint8_t reg, uint8_t numbytes, uint8_t* bytearray, uint16_t startidx)
    {
        Serial.printf("I2C(%x) %s %d bytes %s %x... ",
            dev, (RW == 0 ? "writing" : "reading"), numbytes - startidx, (RW == 0 ? "to" : "from"), reg);
        for (size_t i = startidx; i < numbytes; i++)
        {
            Serial.printf("%x ", bytearray[i]);
        }
    
        Serial.printf(". Done\n");
    
    }
    
    int DecodeAndPrintFIFOContents(Circular_Buffer<uint8_t, 2048>& cb)
    {
        //Purpose:  decode and print I2C conversation held in cb_trans FIFO
        //Inputs:  
        //  cb = 2048 element FIFO
        //Outputs:
        //  returns number of bytes processed, or -1 for failure
        //  outputs structured I2C sentence to serial monitor
        //Plan:
        //  Step1: Determine if there is anything to do (have to have more than one transition in FIFO)
        //  Step2: Parse transitions into I2C sentence structure
        //  Step3: Output sentence to serial monitor
    
        if (cb.size() < 2)
        {
            return 0;
        }
    
    
        Serial.printf("%lu: In DecodeAndPrintFIFOContents()\n", millis());
    
        while (cb.size() > 0)
        {
    #ifdef PARSE_LOOP_DEBUG
            Serial.printf("At top of while (cb.size() > 0): size = %d\n", cb.size());
            Serial.printf("Next two bytes in FIFO are %x, %x\n", cb.peek(0), cb.peek(1));
    #endif
            //Find a START sequence (0xC followed by 0x4)
            while (!IsStart(cb))
            {
                Serial.printf("looking for start...\n");
            }
            cb.readBytes(killbuff,2); //01/05/20 moved START byte consume out of IsStart()
    
    
        #ifdef PARSE_LOOP_DEBUG
            Serial.printf("Start sequence found, FIFO size = %d\n", cb.size());
            PrintNextFIFOBytes(cb_trans, 20);
        #endif
    
            if (cb.size() > 14)//14 entries required for 7-bit address
            {
                //Get 7-bit device address
                devAddr = Get7BitDeviceAddr(cb);
        #ifdef PARSE_LOOP_DEBUG
                Serial.printf("devAddr = %x, FIFO size = %d\n", devAddr, cb.size());
                PrintNextFIFOBytes(cb_trans, 20);
        #endif
            }
    
            //get read/write flag  1 = Read, 0 = Write, -1 = error
            BusDir = (BUSDIR)GetReadWriteFlag(cb);
    
        #ifdef PARSE_LOOP_DEBUG
            Serial.printf("BusDir = %s\n", ((BusDir == BUSDIR::WRITE) ? "WRITE" : "READ"));
            PrintNextFIFOBytes(cb_trans, 20);
        #endif
    
            //get ACK/NAK flag
            ACKNAKFlag = GetACKNAKFlag(cb);
        #ifdef PARSE_LOOP_DEBUG
            Serial.printf("ACKNAK = %s\n", (ACKNAKFlag == 0) ? "ACK" : "NAK");
        #endif
    
            numbytes = GetDataBytes(cb, databyte_array); //terminates on a START, but the start bytes are not consumed
        #ifdef PARSE_LOOP_DEBUG
            Serial.printf("Got %d bytes from GetDataBytes()\n", numbytes);
            PrintNextFIFOBytes(cb_trans, 20);
        #endif
    
            while (true)
            {
    
            }
            //If the bus direction is WRITE, then extract
            //    A register address for read / write
            //    zero or more additional data bytes
            if (BusDir == BUSDIR::WRITE)
            {
                regAddr = databyte_array[0];
        #ifdef PARSE_LOOP_DEBUG
                Serial.printf("regAddr = %x, cb size = %d\n", regAddr, cb.size());
        #endif
    
                //check for additional data
                if (numbytes > 1)
                {
        #ifdef PARSE_LOOP_DEBUG
                    Serial.printf("Additional data found!\n");
                    for (size_t i = 0; i < numbytes; i++)
                    {
                        Serial.printf("data[%d] = %x\n", i, databyte_array[i]);
                    }
        #endif
                    //1st byte is register addr, subsequent bytes are data
                    OutputFormattedSentence(BusDir, devAddr, regAddr, numbytes, databyte_array, 1);
                }
            }
            else  //all bytes are data
            {
    #ifdef PARSE_LOOP_DEBUG
                Serial.printf("In data block:  got %d bytes of data\n", numbytes);
                for (size_t i = 0; i < numbytes; i++)
                {
                    Serial.printf("data[%d] = %x\n", i, databyte_array[i]);
                }
    #endif
                OutputFormattedSentence(BusDir, devAddr, regAddr, numbytes, databyte_array, 0);
            }
        #ifdef PARSE_LOOP_DEBUG
            Serial.printf("At end of while (cb.size() > 0): size = %d\n", cb.size());
            Serial.printf("Next two bytes in FIFO are %x, %x\n", cb.peek(0), cb.peek(1));
        #endif
    
        }//while (cb.size() > 0)
    
        return 1;
    }
    I have a function IsStart() that looks for the byte pair [c,4]. In this function I use peekbytes(cb,2) to look at (but not consume) the first two bytes of the FIFO, and use them for the match. However, it appears that peekbytes() may be skipping two bytes. If I replace peekBytes() with two calls to peek(), I get the expected results.

    Here's an edited output showing just the few relevant lines: The first set below is with peekBytes(data,2):

    Code:
    Get8BitDataByte: cb.size = 908, index = 20
    Next 20 FIFO Bytes: 0,4,8,c,8,c,8,c,0,4,8,c,0,4,8,c,0,4,0,4
    GetDataBytes() just after Get8BitDataByte(): datval = 75, size = 892, idx = 36
    Next 10 FIFO Bytes: 0,4,0,4,c,4,8,c,8,c
    GetDataBytes() just after GetACKNAKFlag(): ACKNAK = 0, size = 890, idx = 38
    Next 10 FIFO Bytes: 0,4,c,4,8,c,8,c,0,4
    IsStart() just before cb.peekBytes(data, 2): data[0] = 0,data[1] = 0, size = 890, idx = 38
    Next 10 FIFO Bytes: 0,4,c,4,8,c,8,c,0,4
    IsStart() just after cb.peekBytes(data, 2): data[0] = c,data[1] = 4, size = 890, idx = 38
    Next 10 FIFO Bytes: 0,4,c,4,8,c,8,c,0,4
    
    And after replacing peekBytes(data,2) with two peek() calls:

    Code:
    Get8BitDataByte: cb.size = 908, index = 20
    Next 20 FIFO Bytes: 0,4,8,c,8,c,8,c,0,4,8,c,0,4,8,c,0,4,0,4
    GetDataBytes() just after Get8BitDataByte(): datval = 75, size = 892, idx = 36
    Next 10 FIFO Bytes: 0,4,0,4,c,4,8,c,8,c
    GetDataBytes() just after GetACKNAKFlag(): ACKNAK = 0, size = 890, idx = 38
    Next 10 FIFO Bytes: 0,4,c,4,8,c,8,c,0,4
    IsStart() just before cb.peekBytes(data, 2): data[0] = 0,data[1] = 0, size = 890, idx = 38
    Next 10 FIFO Bytes: 0,4,c,4,8,c,8,c,0,4
    IsStart() just after cb.peekBytes(data, 2): data[0] = 0,data[1] = 4, size = 890, idx = 38
    Next 10 FIFO Bytes: 0,4,c,4,8,c,8,c,0,4
    
    You can see in the highlighted lines that peek(0) & peek(1) pick out the correct bytes, but peekByte(data,2) skips the first two bytes in the FIFO, loading the 3rd and 4th ones into data[0] and data[1] instead.

    If this is indeed a problem with peekBytes() and not just my fevered imagination, then it may be that other multiple-byte versions of FIFO operations could use another look

    Frank

  21. #171
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    Thank you, I will check into that and fix it when I get back home
    readBytes is good now?
    Last edited by tonton81; 01-06-2020 at 04:32 AM.

  22. #172
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    Ok, I corrected the offset needed of memmove on peekBytes, and readded it to readBytes, both function correctly. It's been updated on github, let me know if you still have issues

    My last example posted earlier works for testing readBytes and peekBytes

  23. #173
    The Teensy I2C sniffer project now works properly with tonton81's circular buffer library (although without the latest peekBytes() fix - I'm still using peek()). Here's the output from just one pass through the simulated burst data

    Code:
    Opening port
    Port open
    Port open
    Serial available after 2500 mSec
    3001: cb_trans contains = 928 elements
    I2C(68) reading 1 bytes from 75... 68 . Done
    I2C(68) reading 1 bytes from 6a... c0 . Done
    I2C(68) writing 1 bytes to 6a... c4 . Done
    I2C(68) reading 2 bytes from 72... 0 1c . Done
    I2C(68) reading 2 bytes from 72... 0 38 . Done
    I2C(68) reading 2 bytes from 72... 0 54 . Done
    I2C(68) reading 2 bytes from 72... 0 70 . Done
    I2C(68) reading 2 bytes from 72... 0 8c . Done
    I2C(68) reading 2 bytes from 72... 0 c4 . Done
    I2C(68) reading 2 bytes from 72... 0 e0 . Done
    3003: cb_trans contains = 0 elements
    So it takes a stock Teensy 3.2 about 3 mSec to parse and print results for a 928-byte I2C 'burst', so it should be able to keep up with a burst interval down to 10 mSec or so (my application uses a burst interval of 200 mSec).

    Frank

  24. #174
    tonton81,

    Have you verified that cb.remove(element) actually removes the element? Here's a partial output from my current program, where I parse through a capture buffer to remove invalid bytes, and I have included the function that executes the parsing algorithm

    Code:
    Code:
    uint16_t RemoveInvalidBytes(Circular_Buffer<uint8_t, 2048>& cb)
    {
        uint8_t previous_byte, current_byte;
    
        Serial.printf("cb_trans contains %d elements\n", cb.size());
        PrintNextFIFOBytes(cb, cb.size());
    
        uint16_t cullcount = 0;
        //OK, now go back through the array, excising invalid sequences
        uint rawidx = 0;
        for (uint16_t i = 0; i < cb.size();) //i gets incremented internally
        {
            previous_byte = cb.peek(i); //get the first byte
            current_byte = cb.peek(i+1); //get the next byte
            bool validpair =
                (
                (previous_byte == 0xC && current_byte == 0x4) //START or RESTART
                    || (previous_byte == 0x4 && current_byte == 0xC) //STOP
                    || (previous_byte == 0x0 && current_byte == 0x4) //0 OR ACK
                    || (previous_byte == 0x8 && current_byte == 0xC) //1 or NAK
                    );
    
            Serial.printf("idx %d: Considering dp = %x, dc = %x: validity = %d\n",
                rawidx, previous_byte, current_byte, validpair);
            if (validpair)
            {
                i += 2;
            }
            else
            {
                uint8_t rembyte = cb.peek(i);
                if (cb.remove(i))
                {
                    Serial.printf("successfully removed item %d = %x, leaving %d bytes\n", i, rembyte,cb.size());
                }
                else
                {
                    Serial.printf("Failed to remove item %d = %x\n", i, rembyte);
                }
                PrintNextFIFOBytes(cb, 10);
                bool res = cb.remove(i); //remove invalid byte
                cullcount++;
                i++;
            }
        }
    
        return cullcount;
    }
    And the (partial) output:

    Code:
    Next 20 FIFO Bytes: c,4,0,8,c,8,c,8,0,4,0,8,c,8,0,4,0,4,8,c
    cb_trans contains 165 elements
    Next 165 FIFO Bytes: c,4,0,8,c,8,c,8,0,4,0,8,c,8,0,4,0,4,8,c,8,0,4,0,4,8,0,4,8,c,8,c,8,c,0,4,0,4,8,c,0,4,0,4,0,4,c,4,0,8,c,8,c,0,4,0,8,c,0,4,0,4,8,c,8,c,0,4,0,4,0,4,0,4,0,4,0,4,0,c,8,0,4,0,4,0,4,0,4,0,4,8,c,0,4,8,c,0,4,0,4,8,c,8,0,4,c,4,0,8,c,8,c,8,0,4,0,8,c,8,0,4,0,4,0,8,c,8,0,4,0,4,8,0,4,8,c,8,c,0,4,8,c,0,4,8,c,0,4,0,4,0,4,c,4,0,8,c,8,c,0,4,8,c,0
    idx 0: Considering dp = c, dc = 4: validity = 1
    idx 0: Considering dp = 0, dc = 8: validity = 0
    Failed to remove item 2 = 0
    Next 10 FIFO Bytes: c,4,0,8,c,8,c,8,0,4
    idx 0: Considering dp = 8, dc = c: validity = 1
    idx 0: Considering dp = 8, dc = c: validity = 1
    idx 0: Considering dp = 8, dc = 0: validity = 0
    Failed to remove item 7 = 8
    Next 10 FIFO Bytes: c,4,0,8,c,8,c,8,0,4
    idx 0: Considering dp = 0, dc = 4: validity = 1
    idx 0: Considering dp = 0, dc = 8: validity = 0
    Failed to remove item 10 = 0
    Next 10 FIFO Bytes: c,4,0,8,c,8,c,8,0,4
    idx 0: Considering dp = 8, dc = c: validity = 1
    idx 0: Considering dp = 8, dc = 0: validity = 0
    Failed to remove item 13 = 8
    Am I doing something wrong with the 'cb.remove(i)' call?

    Frank

  25. #175
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,211
    Cb.remove is a unique feature implemented specifically for circular arrays, not circular buffers. The function only processes on circular arrays, and exits on buffers. It's used to drop an entire array out of a queue of arrays that match,provided the queue slot is specified. I do believe that is only specifically used when a user is manually running list() and removing an item line from the queue. A similar automatic find and remove version is findRemove, where it searches for indice matches before wiping the array out of the queue. Only one library has ever used this, Canquitto, although hasn't been used since in the updated version of that library

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •