Project: SPI_MSTransfer

awesome! my day has been booked with shipping and transport gate system repairs, so heading home now for a few hours break before next shift, gonna be a busy week for me
 
woah mike, i forgot about your sketch running since yesturday, i got home now and:...still running :)

Code:
0 0 4700 40E8 0 0 4720 40E8 0 0 4740 40E8 0 0 4760 40E8 0 0 4780 40E8 0 0 47A0 40E8 0 0 47C0 40E8 0 0 47E0 40E8 0 0 4800 40E8 0 0 4820 40E8 0 0 4840 40E8 0 0 4860 40E8 
F&F (OT=0)micros() _time==74
PacketID: 55
Length: 48
0 0 4880 40E8 0 0 48A0 40E8

hehehehehe
 
Boy oh boy. Talk about stability. :) and no errors !!! Still not sure why it works for you and not for my setup.. arrgh
 
Ok. Been testing the T3.5/T3.1 combination. There must be something about SPI and the T3.5. No matter what combination I tried at lower than 30Mhz (CPU speeds) it just did not work. Would always hang at some point. When I went up it got better and the optimum bus speed seems to be 36Mhz. Playing around a little more I am now running the Master(T3.5) at 144Mhz set 36Mhz SPI and the T3.1 at 120Mhz. It has now been running for about 1.5 hours and up to 310 Transfers on the slave with no errors. The master shows OT=8 but those were on start up.

Finally got something to work. If I ever go back to the T3.5/T3.5 combo I will have to check this combination. Still interesting that only I have this problem with the T3.5's.

EDIT: Spoke too soon. Just shy of 2 hours it hung up again. Got to, on the slave:
Code:
14764.00, #, #, #, #, #, #, #, #, #, #, #,339826,0
Click reset on tyCommander and it started right up again. :)
 
Last edited:
Updated the github.com SPI_MSTransfer with Pull request from Mike - the lib code there is only the older V_0.1.0 ? that I last worked with.

BTW: coming up on 3 days (?) since I restarted that on the noted Pair of T_3.6 and T_3.1 and it is still blinking and showing : F&F (OT=3)micros() _time==55
 
I have been using 0.1.5...... thanks for merging. Figured this way we have the same sketches. Hey, I am happy finally got it running for more that 15 minutes :)

What config are you using again for the T3.6/T3.1 combo?
 
I have been using 0.1.5...... thanks for merging. Figured this way we have the same sketches. Hey, I am happy finally got it running for more that 15 minutes :)

What config are you using again for the T3.6/T3.1 combo?

from post #657 I think it is this:
My T_3.1 at 96 MHz is running seemingly fine [ F&F @500 Hz and 10 Hz Toggle] against the T_3.6 pushing 30 MHz SPI - for long times - ran 24+ hours and still running since the earlier noted reset. Maybe this is running on the hairy edge - and why it only works setting PRI to Max/0 - and goes bad when USB consumes any bandwidth?

I've been otherwise occupied - waiting to see TD 1.42 b4 drop to test with updated code.

If you wanted to do a pull to perhaps a subdirectory of the best/tested current V_0.1.5 I'll restart with that to make sure it works with the fast F&F as I'm using it. Last time I used the updated to provide Slave push back it failed. When I see it working I can move to the main folder with update to that version?
 
if you dont use slave send any version is fine, 0.1.5 at least is functional to an extent till i get some time to work on it more
 
Indeed - wanted to see if my testing likes the V_0.1.5 then I'll make it the current on github and progress from there. I can grab then when I get back to it with TD 1.42b4.

BTW: WRT to FASTRUN - There is a CACHE note here on the Teensy variants: pjrc.com/teensy/techspecs.html.

Teensy LC :: 64 bytes
Teensy 3.2 :: 256 Bytes
Teensy 3.5 :: 256 Bytes
Teensy 3.6 :: 8192 Bytes

It also notes the FLASH bandwidth is over double on the T_3.6.
 
Last edited:
Yeah. Send only works no problem either way. Toggle is the LED? 2Way is the challenge for me. Think you got the cache sized listed in p684
Teensy LC :: 96 Mbytes/sec
Teensy 3.2 :: 192
Teensy 3.5 :: 192
Teensy 3.6 :: 411

Big difference between 3.5 and 3.6.
 
Good evening Tim & Mike, I'm currently working on a templated version of a FIFO library that has or will have quite a unique feature

I currently implemented the following public functions:

void write(T value);
T peek(uint16_t pos = 0);
T peekBytes(T *buffer, uint16_t length);
T read();
T readBytes(T *buffer, uint16_t length);
uint16_t available();

The templated constructor allows you to define the size of the circular buffers of any given type and size, and supports multiple buffers!

Circular_Buffer<uint16_t, 2048> cb; // 2K U16 FIFO with overwrite when full
Circular_Buffer<uint8_t, 16> cb2; // 16 entry U8 FIFO with overwrite when full

The readBytes & peekBytes use memmove for fast transfers of the circular buffer, then move the position of the head the length amount of times!
This has gotta get big performance than reading 1 byte at a time! :)
I'm still working on it and pondering new features so I could add it to the library, but if theres more things i could slip in let me know!, it doesnt use malloc or new either!
the peek is overloaded at 0 default, which peeks the first byte, specifying a value (lets say 2) gets you the 3rd Type value in the FIFO, without modifying the head
read does the same, except it pushes the head forward

peekbytes and readbytes are the same, except, readbytes adjusts the head after memmove, which i think is the fastest way to copy out the entries for MSTransfer!

Benefit?

Sure! How about if you have 2 similar data packets, and want to differentiate them before pulling, you could peek into the buffer and know how to handle the situation accordingly

in the case of SPI_MSTransfer, where:

HEADER, LEN, blah blah blah.... lets say 20 bytes len

We check the circular buffer for a header ID, so we do a peek(1) for the length to capture the entire array via memove!

uint16_t MST_array[cb.peek(1)];
if ( cb.readBytes(MST_array,cb.peek(1)) == cb.peek(1)) Serial.println("Captured entire buffer");
else Serial.println("Fail Capture (requested too much or buffer not large enough");
the FIFO is adjusted by the length and dumped the buffer contents for immediate callback!
 
Last edited:
You really are a glutton for punishment - this is what happens when you are away from the computer too long :). It should resolve the issues that I am having with between the 3.5 and 3.1 or other 3.5. By the way starting trying out your other library but I am having a hardware problem with my new toy I am playing with (https://www.tindie.com/products/cbu...with-wifibluetoothnrf24l01/?pt=ac_prod_search) - can't get the 8266 to respond for some reason. Will see the reset info but doesn't respond to AT commands. Oh well a project for another day :)
 
eww AT, that needs a reflash buddy :) (btw, after a couple days of no workbench, i only started playing with this stuff this morning ~ 4 hours ago) lol

yeah im totally beefing up this buffer with anything i can throw at it!
but, really, memmove a circular buffer to an array with a given length, im squeezing performance out of it no!? :D
 
Also, you could do a uint32_t buffer, memmove is setup with the Type you use (uint32_t for example) and it handles it accordingly:

Code:
memmove(buffer,_cbuf,_count*sizeof(T));

and if your feeling awesome, this works too

Code:
Circular_Buffer<uint64_t, 16> cb3;

16 slot circular array of U64's
 
according to the datasheet its using Teensy Serial1 port for the ESP RX/TX, however, pin2 is floating (not connected) so you would need to solder a jumper there to use that, route it to maybe an ALT pin RX on teensy and use that instead

also, the library is using 9600 default baudrate
https://github.com/cburgess5294/Arduino-Teensy

once u get that working, after you reflash, you should be able to run 2-3megabaud
 
test sketch:

Code:
#include "circular_buffer.h"

Circular_Buffer<uint16_t, 2048> cb;
Circular_Buffer<uint16_t, 16> cb2;
Circular_Buffer<uint32_t, 16> cb3;

void setup() {
  Serial.begin(1);
  delay(2000);
  Serial.println("----------------------");
  cb.write(0x1111);
  cb.write(0x1112);
  cb.write(0x1113);
  cb.write(0x1114);
  cb.write(0x1115);
  Serial.print("Available: ");  Serial.println(cb.available());
  while ( cb.available() > 0 ) {
    Serial.println(cb.read(), HEX);
  }


  Serial.println("----------------------");
  cb2.write(0x8807);
  cb2.write(6);
  cb2.write(0x2113);
  cb2.write(0x2114);
  cb2.write(0x2115);
  cb2.write(0x2116);
  cb2.write(0x2117);
  cb2.write(0x2118);
  cb2.write(0x2119);
  Serial.print("Available: ");  Serial.println(cb2.available());

  Serial.println("Peekbytes:");
  uint16_t buf[6];
  Serial.print("Count: "); Serial.println(cb2.readBytes(buf, 6));
  for ( uint16_t i = 0; i < 6; i++ ) {
    Serial.print(buf[i], HEX); Serial.print(" ");
  } Serial.println();

  Serial.print("Print FIFO: ");  Serial.println(cb2.available());
  while ( cb2.available() > 0 ) {
    Serial.println(cb2.peek(), HEX);
    Serial.println(cb2.read(), HEX);
  }




  cb3.write(0x10002111);
  cb3.write(0x10002112);
  cb3.write(0x10002113);
  cb3.write(0x10002114);
  cb3.write(0x10002115);
  cb3.write(0x10002116);
  cb3.write(0x10002117);
  cb3.write(0x10002118);
  cb3.write(0x10002119);
  cb3.write(0x10002110);



  Serial.print("Available: "); Serial.println(cb3.available());
  while ( cb3.available() > 0 ) {
    Serial.println(cb3.peek(), HEX);
    Serial.println(cb3.read(), HEX);
  }

}

void loop() {


}


Output:

Code:
----------------------
Available: 5
1111
1112
1113
1114
1115
----------------------
Available: 9
Peekbytes:
Count: 6
8807 6 2113 2114 2115 2116 
Print FIFO: 3
2117
2117
2118
2118
2119
2119
Available: 10
10002111
10002111
10002112
10002112
10002113
10002113
10002114
10002114
10002115
10002115
10002116
10002116
10002117
10002117
10002118
10002118
10002119
10002119
10002110
10002110
 
pin2 is floating (not connected) so you would need to solder a jumper there to use that,
Thanks man. Been playing with all day. If I press the reset button it responds and prints to the sermon or to the converter direct to the PC. I'll definitely check out the datasheet again and pin 2. Fun times.

Can't believe you got the circular buffer working already :) Scary.
 
Mike, again, I added unique circular FIFO bonus!

array -> circular buffer!

sketch code:
Code:
  cb4.write(0x2113);
  cb4.write(0x2114);
  uint16_t buff[4] = { 'T', 'o', 'n', 'y' };
  cb4.write(buff, 4);
  cb4.write(0x2115);
  cb4.write(0x2116);

  Serial.print("cb4 Available: ");  Serial.println(cb4.available());

  Serial.println("Printout:");
  while ( cb4.available() > 0 ) {
    Serial.println(cb4.read(), HEX);
  }


Output:

cb4 Available: 8
Printout:
2113
2114
54
6F
6E
79
2115
2116


my method of choice uses memmove, if the target array nears the end of buffer is too large needing to shift head back to 0, it uses normal for loop just that time, otherwise memmove every other time!

Code:
void Circular_Buffer<T,_size>::write(const T *buffer, uint16_t length) {
  if ( length < ( _size - tail ) ) {
    memmove(_cbuf+tail,buffer,length*sizeof(T));
    tail = (tail + length)&(2*_size-1);
  }
  else for ( uint16_t i = 0; i < length; i++ ) write(buffer[i]);
}

this means we can just dump the entire SPI_MST array directly into the circular queue without any for loops! (except at endpoint)
 
That means with a 2048 buffer, and 24 length payloads, 84 pushes will be memmoved, the 85th would be /for looped/, and memmove continues afterwards

1 for loop every 84 memmoves aint bad! :)

otherwise i'd have to probably split the count with remaining limit, and follow up with 2 memsets, which, i could prolly still do, if i spend a little time calculating those positions :)

then again, if your buffer is 3x or more smaller, your hitting a brick wall

i think for loop for the loop around is the best choice
 
Argh - you are giving me a headache... :) A big bonus - it also means you can use it for other stuff besides SPI_MSTransfer.

"1 for loop every 84 memmoves aint bad! " - not bad at all :)

"then again, if your buffer is 3x or more smaller," - definitely don't want to get into that situation. Are u planning on the user to be able to secifiy buffer size - if you do you might want to put a minimum size test in. Just thinking ahead.
 
yes! all buffers can be different sizes, and supports many many circular buffers!

for my tests i did this:

Code:
Circular_Buffer<uint16_t, 2048> cb;
Circular_Buffer<uint16_t, 16> cb2;
Circular_Buffer<uint32_t, 16> cb3;
Circular_Buffer<uint16_t, 16> cb4;

void setup() {
........etc

thats 4 circular buffers, different sizes, with all the features included

tests have been done successfully with 8, 16, and 32bit types

also, no malloc or new! very clean :)
 
...

also, no malloc or new! very clean :)

I kept saying you were just being lazy and sloppy and wasteful and flirting with disaster for no reason :) :) ... when you could do it better yourself :) :) ... though a bit more discretely :eek:

Is the template in a separate library file? If you post I can update the github repository. Do you have a github account to work with?
 
yeah it's all in a single H file (no CPP)

I have a feeling lots of people will use this for all kinds of projects

heres a demo for you to test/play with:

Code:
#include "circular_buffer.h"

Circular_Buffer<uint16_t, 2048> cb;
Circular_Buffer<uint16_t, 16> cb2;
Circular_Buffer<uint32_t, 16> cb3;
Circular_Buffer<uint16_t, 16> cb4;

void setup() {
  Serial.begin(1);
  delay(2000);
  Serial.println("----------------------");
  cb.write(0x1111);
  cb.write(0x1112);
  cb.write(0x1113);
  cb.write(0x1114);
  cb.write(0x1115);
  Serial.print("Available: ");  Serial.println(cb.available());
  while ( cb.available() > 0 ) {
    Serial.println(cb.read(), HEX);
  }


  Serial.println("----------------------");
  cb2.write(0x8807);
  cb2.write(6);
  cb2.write(0x2113);
  cb2.write(0x2114);
  cb2.write(0x2115);
  cb2.write(0x2116);
  cb2.write(0x2117);
  cb2.write(0x2118);
  cb2.write(0x2119);
  Serial.print("Available: ");  Serial.println(cb2.available());

  Serial.println("Peekbytes:");
  uint16_t buf[6];
  Serial.print("Count: "); Serial.println(cb2.readBytes(buf, 6));
  for ( uint16_t i = 0; i < 6; i++ ) {
    Serial.print(buf[i], HEX); Serial.print(" ");
  } Serial.println();

  Serial.print("Print FIFO: ");  Serial.println(cb2.available());
  while ( cb2.available() > 0 ) {
    Serial.println(cb2.peek(), HEX);
    Serial.println(cb2.read(), HEX);
  }




  cb3.write(0x10002111);
  cb3.write(0x10002112);
  cb3.write(0x10002113);
  cb3.write(0x10002114);
  cb3.write(0x10002115);
  cb3.write(0x10002116);
  cb3.write(0x10002117);
  cb3.write(0x10002118);
  cb3.write(0x10002119);
  cb3.write(0x10002110);



  Serial.print("Available: "); Serial.println(cb3.available());
  while ( cb3.available() > 0 ) {
    Serial.println(cb3.peek(), HEX);
    Serial.println(cb3.read(), HEX);
  }










  cb4.write(0x2113);
  cb4.write(0x2114);
  uint16_t buff[4] = { 'T', 'o', 'n', 'y' };
  cb4.write(buff, 4);
  cb4.write(0x2115);
  cb4.write(0x2116);

  Serial.print("cb4 Available: ");  Serial.println(cb4.available());

  Serial.println("Printout:");
  while ( cb4.available() > 0 ) {
    Serial.println(cb4.read(), HEX);
  }



}

void loop() {


}

and the library:

View attachment circular_buffer.zip


Public methods:

Code:
        void write(T value);                                          <-- write a single Type value
        void write(const T *buffer, uint16_t length);         <-- write an array of same Type values
        T peek(uint16_t pos = 0);                                  <-- peek a single Type value
        T peekBytes(T *buffer, uint16_t length);              <--  peek a specified number of entries into a local array
        T read();                                                        <-- read a single Type value
        T readBytes(T *buffer, uint16_t length);               <-- read a specified number of entries into a local array
        uint16_t available();                                          <-- how much data in queue
 
did another test:

Code:
Circular_Buffer<uint16_t, 4> cb4;

and..:

Code:
  cb4.write(0x2113);
  cb4.write(0x2114);
  uint16_t buff[4] = { 'T', 'o', 'n', 'y' };
  cb4.write(buff, 4);
  cb4.write(0x2115);
  cb4.write(0x2116);

  Serial.print("cb4 Available: ");  Serial.println(cb4.available());

  Serial.println("Printout:");
  while ( cb4.available() > 0 ) {
    Serial.println(cb4.read(), HEX);
  }

Result:

Code:
cb4 Available: 4
Printout:
6E
79
2115
2116

this shows the buffer used the for loop to wrap around since the buffer was too small, and still, the 4 last entries are intact! :)
 
Back
Top