PDA

View Full Version : Teensyduino 1.54 Beta #2



Paul
10-24-2020, 03:12 AM
Here is a second beta test for Teensyduino 1.54.


Linux 32 bit:
https://www.pjrc.com/teensy/td_154-beta2/TeensyduinoInstall.linux32

Linux 64 bit:
https://www.pjrc.com/teensy/td_154-beta2/TeensyduinoInstall.linux64

Linux ARM:
https://www.pjrc.com/teensy/td_154-beta2/TeensyduinoInstall.linuxarm

Linux ARM64:
https://www.pjrc.com/teensy/td_154-beta2/TeensyduinoInstall.linuxaarch64

MacOS 10.10 to 10.15:
https://www.pjrc.com/teensy/td_154-beta2/Teensyduino_MacOS_Catalina.zip

MacOS 10.8 to 10.14:
https://www.pjrc.com/teensy/td_154-beta2/TeensyduinoInstall.dmg

Windows:
https://www.pjrc.com/teensy/td_154-beta2/TeensyduinoInstall.exe


Changes since Teensyduino 1.54-beta1 (https://forum.pjrc.com/threads/63997-Teensyduino-1-54-Beta-1):

Fix 1.54-beta1 startup problem on Teensy 4.1
EEPROM put/get handle String and warn for incompatible classes (luni64)
Add _extram_start & _extram_end for Teensy 4.1
Update Bounce2

defragster
10-24-2020, 03:13 AM
It installs :)

<edit>

T_4.1 10-15 uploads of 5 recent sketches noted in beta1 thread all good.

luni
10-24-2020, 07:00 AM
Update Bounce2
Great, the EncoderTool (https://github.com/luni64/EncoderTool) which depends on a current Bounce2 now compiles out of the box. Thanks

luni
10-24-2020, 07:35 AM
EEPROM put/get handle String and warn for incompatible classes

Tested with the code below. Works as expected.



#include "EEPROM.h"

struct GoodType // this is bytewise copyable
{
const char* text = "Good struct";
float version = 1.54f;
int relelase = 2;
};

struct BadType // this is NOT bytewise copyable
{
String text = "Bad struct";
float version = 1.54f;
int relelase = 2;
};


void setup()
{
while (!Serial) {}

int pos0 = 0;

// Save to EEProm -------------------------------

String s1 = "Hello Teensyduino 1.54 beta 2";
EEPROM.put(pos0, s1);
int pos1 = pos0 + s1.length() + 1; // need to take the delimiting /0 into account

GoodType goodType;
EEPROM.put(pos1, goodType);
int pos2 = pos1 + sizeof(goodType);

BadType badType;
//EEPROM.put(pos2, badType); // if uncommented this generates a compile time error since the type is not bytewise copyable
int pos3 = pos2 + sizeof(goodType);

// read from EEProm -----------------------------

String storedString1;
EEPROM.get(pos0, storedString1);

GoodType storedGoodType;
EEPROM.get(pos1, storedGoodType);

Serial.println(storedString1);

Serial.println(storedGoodType.text);
Serial.println(storedGoodType.version);
Serial.println(storedGoodType.relelase);
}

void loop(){
}


Prints out


Hello Teensyduino 1.54 beta 2
Good struct
1.54
2

mjs513
10-24-2020, 12:51 PM
It installs :)

<edit>

T_4.1 10-15 uploads of 5 recent sketches noted in beta1 thread all good.

Same here - all seems to be working. Ran with OpenGL, EigenTest, check42 psram test with no problem.

KurtE
10-24-2020, 01:34 PM
Morning all,

Installed Windows 10, and built T4.1 code ;)

Side notes: But with simple Camera test sketch I am now working through the new warnings for Serial.printf(...)

Fixed the first obvious one, of I passed a uint... to a %d instead of a %u...

But that still did not work, neither does %x...

Think will need to convert many many %u %x %d to %lu %lx %ld Will be sort of a pain!


Installed RPI4 8GB SSD Ubuntu Arm64 - Arduino 1.8.12, earlier 13 was not found on Arduino server.... It is today so downloading.

Same issue as mentioned in the thread: https://forum.pjrc.com/threads/61623-Teensyduino-1-53-Released?p=255856&viewfull=1#post255856
The build goes through but launching the Teensy tool has issues and errors out. The Teensy app shows up as a white window with nothing in it.
But if I go into and manually start Teensy app it shows up properly. But most of the time does not automatically program properly, but will if I press the program button.
Tested on T3.2

Edit same thing on 1.8.13
22190

jonr
10-24-2020, 03:08 PM
> Think will need to convert many many %u %x %d to %lu %lx %ld Will be sort of a pain!

> printf("uint32_t var : %"PRIu32"\n", u32x);

I see one here:
Audio/input_adc.cpp:341:45: warning: format '%X' expects argument of type 'unsigned int', but argument 3 has type 'uint32_t {aka long unsigned int}'

Where appropriate, I'd maintain portability with this idea (from bperrybap):

printf("uint32_t var : %"PRIu32"\n", u32x);

mjs513
10-24-2020, 03:39 PM
Installed RPI4 8GB SSD Ubuntu Arm64 issue Seeing exactly the same thing using Ubuntu 18.04, the screenshot matches exactly.


Think will need to convert many many %u %x %d to %lu %lx %ld Will be sort of a pain! Ran across an instance of that myself this morning. There are probably quite a few Lib's and examples that will need updating? Think there was a post where Paul mentioned this somewhere?

KurtE
10-24-2020, 03:48 PM
> Think will need to convert many many %u %x %d to %lu %lx %ld Will be sort of a pain!

> printf("uint32_t var : %"PRIu32"\n", u32x);


Sorry I am old dog who has not learned the new trick yet ;)

What does that mean? Yes I can and will google it,
but does this print Hex or Decimal? Not terribly clear. Or maybe an example might help. Here is one I just fixed up:

Example how would you translate this one I just updated to remove the warnings:

void dumpDMA_TCD(DMABaseClass *dmabc)
{
Serial.printf("%lx %lx:", (uint32_t)dmabc, (uint32_t)dmabc->TCD);

Serial.printf("SA:%lx SO:%d AT:%x NB:%lx SL:%ld DA:%lx DO:%d CI:%x DL:%ld CS:%x BI:%x\n",
(uint32_t)dmabc->TCD->SADDR,
dmabc->TCD->SOFF, dmabc->TCD->ATTR, dmabc->TCD->NBYTES, dmabc->TCD->SLAST, (uint32_t)dmabc->TCD->DADDR,
dmabc->TCD->DOFF, dmabc->TCD->CITER, dmabc->TCD->DLASTSGA, dmabc->TCD->CSR, dmabc->TCD->BITER);
}



This dumps out a DMA structure I am using to help debug some code...
I wonder what would that translate to 8)

wwatson
10-24-2020, 04:00 PM
I just installed TD 1.54B2 and I was going through some sketches using USBHost_t36 and found that "#define USBHOST_PRINT_DEBUG" was uncommented.

So far all of everything is working well:)

luni
10-24-2020, 04:04 PM
Sorry I am old dog who has not learned the new trick yet
What does that mean? Yes I can and will google it,

PRIxN -> x is the usual u, d, x, X etc N is the width of the variable.

E.g.
PRIu16 will print a 16bit unsigned
PRId64 will print a 64bit signed
PRIX32 will print a 32bit hex number with uppercase letters
...

Advantage: doesn't rely on the platform dependent width of int, unsigned etc.
Disadvantage: a pain to type

I think I'll stick with lu, lx etc...

Edit: They and a lot more of them are defined in 'inttypes.h'

KurtE
10-24-2020, 04:21 PM
@luni - Thanks, Yep I think I will too stick with the easy way... With the more typing version wonder if one an do things like:
printf("Var: %08xl", my_var);

Would it be something like: printf("Var: %08"PRIu32"\n", u32x);

Again I could try but for now...

Thanks again!

luni
10-24-2020, 04:32 PM
Nearly :-). You also need to add spaces:


void setup()
{
while(!Serial){}

uint32_t test = 42;
Serial.printf("Var: %08" PRIu32 "\n", test);
}

void loop(){}

Prints:


Var: 00000042


Without the spaces I get a warning:



src/main.cpp:8:19: warning: invalid suffix on literal; C++11 requires a space between literal and string macro [-Wliteral-suffix]
Serial.printf("Var: %08"PRIu32"\n", test);


I'm sure this syntax was invented to scare users away from printf :-)

luni
10-24-2020, 05:01 PM
More tests with the PRIs



void setup()
{
while(!Serial){}

Serial.println("int64_t");
int64_t test0 = -2;
Serial.printf("PRIi64: %" PRIi64" \n", test0);
Serial.printf("PRIu64: %" PRIu64" \n", test0);
Serial.printf("PRIX64: %" PRIX64" \n", test0);

Serial.println("\nint32_t");
int32_t test1 = -2;
Serial.printf("PRIi32: %" PRIi32" \n", test1);
Serial.printf("PRIu32: %" PRIu32" \n", test1);
Serial.printf("PRIX32: %" PRIX32" \n", test1);

Serial.println("\nint16_t");
int16_t test2 = -2;
Serial.printf("PRIi16: %" PRIi16" \n", test2);
Serial.printf("PRIi16: %" PRIu16" \n", test2);
Serial.printf("PRIX16: %" PRIX16" \n", test2);

Serial.println("\nint8_t");
int8_t test3 = -2;
Serial.printf("PRIi8: %" PRIi8" \n", test3);
Serial.printf("PRIu8: %" PRIu8" \n", test3);
Serial.printf("PRIX8: %" PRIX8" \n", test3);
}

void loop(){}


Prints:


int64_t
PRIi64: -2
PRIu64: 18446744073709551614
PRIX64: FFFFFFFFFFFFFFFE

int32_t
PRIi32: -2
PRIu32: 4294967294
PRIX32: FFFFFFFE

int16_t
PRIi16: -2
PRIi16: 65534
PRIX16: FFFE

int8_t
PRIi8: -2
PRIu8: 65534
PRIX8: FFFE


Looks like the 8bit variants are not working as advertised?

mjs513
10-24-2020, 05:22 PM
@luni - thanks for the lesson. Learning something new now. Never realized those things were defined in inttypes.h. I have seen something similar in some .h files though.

EDIT: did a google search on the PRIX8 issue and came across this post first thing: https://stackoverflow.com/questions/30378633/c-printing-negative-int-values-as-hex-produces-too-many-characters


A int8_t will go through the usual integer promotions as a parameter to a variadic function like printf(). This typically means the int8_t is converted to int.

Yet "%X" is meant for unsigned arguments. So covert to some unsigned type first and use a matching format specifier:

For uint8_t, use PRIX8. With exact width types, include <inttypes.h> for the matching specifiers.

#include <inttypes.h>
printf(" int negative var is <%02" PRIX8 ">\n", iNegVar);`
With int8_t iNegVar = -1;, convert to some unsigned type before printing in hex

printf(" int negative var is <%02" PRIX8 ">\n", (uint8_t) iNegVar);` Using that format for 8 bit variants gets you:

int64_t

PRIi64: -2
PRIu64: 18446744073709551614
PRIX64: FFFFFFFFFFFFFFFE

int32_t

PRIi32: -2
PRIu32: 4294967294
PRIX32: FFFFFFFE

int16_t

PRIi16: -2
PRIi16: 65534
PRIX16: FFFE

int8_t

PRIi8: -2
PRIu8: 65534
PRIX8: FFFE
int negative var is <FE>

PaulStoffregen
10-24-2020, 05:48 PM
Never realized those things were defined in inttypes.h.

I've never heard of this syntax either.



Think will need to convert many many %u %x %d to %lu %lx %ld Will be sort of a pain!
....
There are probably quite a few Lib's and examples that will need updating? Think there was a post where Paul mentioned this somewhere?

This thread.
https://forum.pjrc.com/threads/62473-Adding-Print-class-printf()-format-string-vs-arguments-checking

luni
10-24-2020, 06:02 PM
I've never heard of this syntax either.

So far I've used it only for 64bit variables where this is the only way (I know of) to 'printf' them.

@mjs513: funny how complicated a simple thing like printing an 8bit variable can get :-).

IMHO, most of the code written here is tightly coupled to the used processor anyway. So, using all this complicated syntax just to get platform independent printfs for platform dependent code seems a bit, say, overengineered to me.
I like the new printf warnings but I personally think fixing it by lu, lx etc. should be good enough in most cases.

mjs513
10-24-2020, 06:06 PM
I've never heard of this syntax either.

This thread.
https://forum.pjrc.com/threads/62473-Adding-Print-class-printf()-format-string-vs-arguments-checking

Was just playing with the different types and added results to my previous posts. Looking at inttypes.h appears there are a few more variants for PRIxxxx usage as well:



Which i think is defined as:


Least-width integer types that are guaranteed to be the smallest type available in the implementation, that has at least specified number n of bits. Guaranteed to be specified for at least N=8,16,32,64.
Fastest integer types that are guaranteed to be the fastest integer type available in the implementation, that has at least specified number n of bits. Guaranteed to be specified for at least N=8,16,32,64.


---https://en.wikipedia.org/wiki/C_data_types#inttypes.h

mjs513
10-24-2020, 06:09 PM
So far I've used it only for 64bit variables where this is the only way (I know of) to 'printf' them.

@mjs513: funny how complicated a simple thing like printing an 8bit variable can get :-).

IMHO, most of the code written here is tightly coupled to the used processor anyway. So, using all this complicated syntax just to get platform independent printfs for platform dependent code seems a bit, say, overengineered to me.
I like the new printf warnings but I personally think fixing it by lu, lx etc. should be good enough in most cases.

I agree with you on how something simple can get overly complicated. Always subscribed to the KISS principal :)

vjmuzik
10-24-2020, 06:22 PM
I've made a pull request here (https://github.com/PaulStoffregen/SPI/pull/62) for some more SPI transfer functions for the Teensy 4.x. These can offer a significant speed improvement when you are sending large buffers such as pixel data for displays, is there any chance this can make it into a beta for testing?

PaulStoffregen
10-24-2020, 06:25 PM
Has anyone looked at the new map() function yet?

Several issues were reported on these 2 threads:

https://forum.pjrc.com/threads/63230-map()-returns-different-values-on-arduino-vs-teensy

https://forum.pjrc.com/threads/44503-map()-function-improvements?p=241232&viewfull=1#post241232

There is also quite a bit about map() problems on Arduino's issue trackers. Here's a message where Cristian Maglie (then Arduino's lead developer) compared 3 implementations and concluded "there isn't still a good solution".

https://github.com/arduino/ArduinoCore-API/issues/51#issuecomment-69585614

My hope is we'll finally have that "good solution" in Teensy, where the results are correct at the extremes of the mapped range and the numbers are fairly distributed throughout the range, and no weird non-linearity exists if you extrapolate beyond the mapped range (within numerical range of 32 bit long, of course).

I will admit, the new implementation is probably slower. How much I don't know. Also unknown is whether just using 32 bit float on Teensy 3.5 & 3.5 and maybe 64 bit double on Teensy 4.x would be faster than such a complicated integer-only approach?

PaulStoffregen
10-24-2020, 06:29 PM
is there any chance this can make it into a beta for testing?

I'm not eager to extend the SPI library public API this way, so as written, no, probably not.

But I would be happy to merge this if it didn't change the public API. Maybe some trickery with inline methods and possibly __builtin_const_p could let these be private functions that get automatically used when the inputs are conducive?

WMXZ
10-24-2020, 06:35 PM
I have a PR pending on adding a function to DMAChannel.h to allow ISR to be executed at specific interrupt level.

mjs513
10-24-2020, 06:40 PM
Has anyone looked at the new map() function yet?

Several issues were reported on these 2 threads:

https://forum.pjrc.com/threads/63230-map()-returns-different-values-on-arduino-vs-teensy

https://forum.pjrc.com/threads/44503-map()-function-improvements?p=241232&viewfull=1#post241232

There is also quite a bit about map() problems on Arduino's issue trackers. Here's a message where Cristian Maglie (then Arduino's lead developer) compared 3 implementations and concluded "there isn't still a good solution".

https://github.com/arduino/ArduinoCore-API/issues/51#issuecomment-69585614

My hope is we'll finally have that "good solution" in Teensy, where the results are correct at the extremes of the mapped range and the numbers are fairly distributed throughout the range, and no weird non-linearity exists if you extrapolate beyond the mapped range (within numerical range of 32 bit long, of course).

I will admit, the new implementation is probably slower. How much I don't know. Also unknown is whether just using 32 bit float on Teensy 3.5 & 3.5 and maybe 64 bit double on Teensy 4.x would be faster than such a complicated integer-only approach?

Was looking that over this morning and planned on testing. That cmaglie sketch helps. I changed it to read:


// This is the original map() function in Arduino Core
long map1(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

// This is the same but with the +1 "range extrension" as suggested by st42
long mapPlus1(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
}

// This is another version of map with rounding done only with integer calculations
// as suggested by M.Kooijman
long mapRound(long x, long in_min, long in_max, long out_min, long out_max)
{
return ((x - in_min) * (out_max - out_min) + (in_max - in_min)/2) / (in_max - in_min) + out_min;
}

void setup(void) {

Serial.begin(115200);
delay(2000);
long x;
Serial.printf("Range 0-20 to 0-4\n");
Serial.printf(" x map map1 map(+1) map(round)\n");
for (x=-10; x<=30; x++) {
Serial.printf("%6ld %6ld %6ld %6ld %6ld\n", x,
map(x, 0, 20, 0, 4),
map1(x, 0, 20, 0, 4),
mapPlus1(x, 0, 20, 0, 4),
mapRound(x, 0, 20, 0, 4));
}

Serial.printf("\n\n");
Serial.printf("Range 0-5 to 0-1023\n");
Serial.printf(" x map map1 map(+1) map(round)\n");
for (x=-5; x<=10; x++) {
Serial.printf("%6ld %6ld %6ld %6ld %6ld\n", x,
map(x, 0, 5, 0, 1023),
map1(x, 0, 5, 0, 1023),
mapPlus1(x, 0, 5, 0, 1023),
mapRound(x, 0, 5, 0, 1023));
}
}

void loop() {} with the results:

Range 0-20 to 0-4
x map map1 map(+1) map(round)
-10 -2 -2 -2 -1
-9 -2 -1 -2 -1
-8 -2 -1 -1 -1
-7 -1 -1 -1 0
-6 -1 -1 -1 0
-5 -1 -1 -1 0
-4 -1 0 0 0
-3 -1 0 0 0
-2 0 0 0 0
-1 0 0 0 0
0 0 0 0 0
1 0 0 0 0
2 0 0 0 0
3 1 0 0 1
4 1 0 0 1
5 1 1 1 1
6 1 1 1 1
7 1 1 1 1
8 2 1 1 2
9 2 1 2 2
10 2 2 2 2
11 2 2 2 2
12 2 2 2 2
13 3 2 3 3
14 3 2 3 3
15 3 3 3 3
16 3 3 3 3
17 3 3 4 3
18 4 3 4 4
19 4 3 4 4
20 4 4 4 4
21 4 4 5 4
22 4 4 5 4
23 5 4 5 5
24 5 4 5 5
25 5 5 5 5
26 5 5 6 5
27 5 5 6 5
28 6 5 6 6
29 6 5 6 6
30 6 6 7 6


Range 0-5 to 0-1023
x map map1 map(+1) map(round)
-5 -1023 -1023 -853 -1022
-4 -819 -818 -682 -818
-3 -614 -613 -512 -613
-2 -409 -409 -341 -408
-1 -205 -204 -170 -204
0 0 0 0 0
1 205 204 170 205
2 409 409 341 409
3 614 613 512 614
4 818 818 682 818
5 1023 1023 853 1023
6 1228 1227 1024 1228
7 1432 1432 1194 1432
8 1637 1636 1365 1637
9 1841 1841 1536 1841
10 2046 2046 1706 2046


Now have to figure the output out and reread the rest of the issue.

PaulStoffregen
10-24-2020, 07:07 PM
I should have mentioned, another property some people are expecting is identical result for "reverse" mapping.

In other words, ideally these should give the same result for all inputs:

map(x, 0, 5, 0, 1023);
map(x, 5, 0, 1023, 0);

And these 2 should give the same result as the 2 above, but "reversed"

map(x, 0, 5, 1023, 0);
map(x, 5, 0, 0, 1023);

Of course Arduino's map() doesn't do any of this, and I do not believe any of the proposed map() functions on their issue trackers do either, especially when considering extrapolating beyond the mapped range.

mjs513
10-24-2020, 07:34 PM
I should have mentioned, another property some people are expecting is identical result for "reverse" mapping.

In other words, ideally these should give the same result for all inputs:

map(x, 0, 5, 0, 1023);
map(x, 5, 0, 1023, 0);

And these 2 should give the same result as the 2 above, but "reversed"

map(x, 0, 5, 1023, 0);
map(x, 5, 0, 0, 1023);

Of course Arduino's map() doesn't do any of this, and I do not believe any of the proposed map() functions on their issue trackers do either, especially when considering extrapolating beyond the mapped range.

Thanks Paul - will check that next. Out of curiosity I was looking for a mathematical approach to map and found something on rosetta code for a map function: https://rosettacode.org/wiki/Map_range. I added this to the code just to see what it would give me:

#include <vector>
template<typename tVal>
tVal map_value(std::pair<tVal,tVal> a, std::pair<tVal, tVal> b, tVal inVal)
{
tVal inValNorm = inVal - a.first;
tVal aUpperNorm = a.second - a.first;
tVal normPosition = inValNorm / aUpperNorm;

tVal bUpperNorm = b.second - b.first;
tVal bValNorm = normPosition * bUpperNorm;
tVal outVal = b.first + bValNorm;

return outVal;
}

// This is the original map() function in Arduino Core
long map1(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

// This is the same but with the +1 "range extrension" as suggested by st42
long mapPlus1(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
}

// This is another version of map with rounding done only with integer calculations
// as suggested by M.Kooijman
long mapRound(long x, long in_min, long in_max, long out_min, long out_max)
{
return ((x - in_min) * (out_max - out_min) + (in_max - in_min)/2) / (in_max - in_min) + out_min;
}

void setup(void) {

Serial.begin(115200);
delay(2000);
long x;
Serial.printf("Range 0-20 to 0-4\n");
//rosetta version
//https://rosettacode.org/wiki/Map_range#C.2B.2B
Serial.printf(" x map map1 map(+1) map(round) Rosetta\n");
std::pair<float,float> a(0,20), b(0,4);
for (x=-10; x<=30; x++) {
Serial.printf("%6ld %6ld %6ld %6ld %6ld %f\n", x,
map(x, 0, 20, 0, 4),
map1(x, 0, 20, 0, 4),
mapPlus1(x, 0, 20, 0, 4),
mapRound(x, 0, 20, 0, 4),
map_value(a, b, (float)x));
}

Serial.printf("\n\n");
Serial.printf("Range 0-5 to 0-1023\n");
std::pair<float,float> c(0,5), d(0,1023);

Serial.printf(" x map map1 map(+1) map(round) Rosetta\n");
for (x=-5; x<=10; x++) {
Serial.printf("%6ld %6ld %6ld %6ld %6ld %f\n", x,
map(x, 0, 5, 0, 1023),
map1(x, 0, 5, 0, 1023),
mapPlus1(x, 0, 5, 0, 1023),
mapRound(x, 0, 5, 0, 1023),
map_value(c, d, (float)x));
}
}

void loop() {}

Output:

Range 0-20 to 0-4
x map map1 map(+1) map(round) Rosetta
-10 -2 -2 -2 -1 -2.000000
-9 -2 -1 -2 -1 -1.800000
-8 -2 -1 -1 -1 -1.600000
-7 -1 -1 -1 0 -1.400000
-6 -1 -1 -1 0 -1.200000
-5 -1 -1 -1 0 -1.000000
-4 -1 0 0 0 -0.800000
-3 -1 0 0 0 -0.600000
-2 0 0 0 0 -0.400000
-1 0 0 0 0 -0.200000
0 0 0 0 0 0.000000
1 0 0 0 0 0.200000
2 0 0 0 0 0.400000
3 1 0 0 1 0.600000
4 1 0 0 1 0.800000
5 1 1 1 1 1.000000
6 1 1 1 1 1.200000
7 1 1 1 1 1.400000
8 2 1 1 2 1.600000
9 2 1 2 2 1.800000
10 2 2 2 2 2.000000
11 2 2 2 2 2.200000
12 2 2 2 2 2.400000
13 3 2 3 3 2.600000
14 3 2 3 3 2.800000
15 3 3 3 3 3.000000
16 3 3 3 3 3.200000
17 3 3 4 3 3.400000
18 4 3 4 4 3.600000
19 4 3 4 4 3.800000
20 4 4 4 4 4.000000
21 4 4 5 4 4.200000
22 4 4 5 4 4.400000
23 5 4 5 5 4.600000
24 5 4 5 5 4.800000
25 5 5 5 5 5.000000
26 5 5 6 5 5.200000
27 5 5 6 5 5.400000
28 6 5 6 6 5.600000
29 6 5 6 6 5.800000
30 6 6 7 6 6.000000


Range 0-5 to 0-1023
x map map1 map(+1) map(round) Rosetta
-5 -1023 -1023 -853 -1022 -1023.000000
-4 -819 -818 -682 -818 -818.400024
-3 -614 -613 -512 -613 -613.800049
-2 -409 -409 -341 -408 -409.200012
-1 -205 -204 -170 -204 -204.600006
0 0 0 0 0 0.000000
1 205 204 170 205 204.600006
2 409 409 341 409 409.200012
3 614 613 512 614 613.800049
4 818 818 682 818 818.400024
5 1023 1023 853 1023 1023.000000
6 1228 1227 1024 1228 1227.600098
7 1432 1432 1194 1432 1432.199951
8 1637 1636 1365 1637 1636.800049
9 1841 1841 1536 1841 1841.399902
10 2046 2046 1706 2046 2046.000000
and it looks like it is working - unless you used the same method so would get identical results :)

Next up - reverse range.

mjs513
10-24-2020, 07:53 PM
Ok - here is a side by side comparison. looks like its working both in forward and reversed ! ....



Range 0-20 to 4-0 Range 0-20 to 0-4
x map map1 map(+1) map(round) Rosetta x map map1 map(+1) map(round) Rosetta
-10 6 6 5 6 6 -10 -2 -2 -2 -1 -2
-9 6 5 5 6 5.8 -9 -2 -1 -2 -1 -1.8
-8 6 5 5 6 5.6 -8 -2 -1 -1 -1 -1.6
-7 5 5 5 5 5.4 -7 -1 -1 -1 0 -1.4
-6 5 5 4 5 5.2 -6 -1 -1 -1 0 -1.2
-5 5 5 4 5 5 -5 -1 -1 -1 0 -1
-4 5 4 4 5 4.8 -4 -1 0 0 0 -0.8
-3 5 4 4 5 4.6 -3 -1 0 0 0 -0.6
-2 4 4 4 4 4.4 -2 0 0 0 0 -0.4
-1 4 4 4 4 4.2 -1 0 0 0 0 -0.2
0 4 4 4 4 4 0 0 0 0 0 0
1 4 4 4 4 3.8 1 0 0 0 0 0.2
2 4 4 4 4 3.6 2 0 0 0 0 0.4
3 3 4 4 4 3.4 3 1 0 0 1 0.6
4 3 4 4 4 3.2 4 1 0 0 1 0.8
5 3 3 4 4 3 5 1 1 1 1 1
6 3 3 4 4 2.8 6 1 1 1 1 1.2
7 3 3 3 4 2.6 7 1 1 1 1 1.4
8 2 3 3 3 2.4 8 2 1 1 2 1.6
9 2 3 3 3 2.2 9 2 1 2 2 1.8
10 2 2 3 3 2 10 2 2 2 2 2
11 2 2 3 3 1.8 11 2 2 2 2 2.2
12 2 2 3 3 1.6 12 2 2 2 2 2.4
13 1 2 3 2 1.4 13 3 2 3 3 2.6
14 1 2 2 2 1.2 14 3 2 3 3 2.8
15 1 1 2 2 1 15 3 3 3 3 3
16 1 1 2 2 0.8 16 3 3 3 3 3.2
17 1 1 2 2 0.6 17 3 3 4 3 3.4
18 0 1 2 1 0.4 18 4 3 4 4 3.6
19 0 1 2 1 0.2 19 4 3 4 4 3.8
20 0 0 2 1 0 20 4 4 4 4 4
21 0 0 1 1 -0.2 21 4 4 5 4 4.2
22 0 0 1 1 -0.4 22 4 4 5 4 4.4
23 -1 0 1 0 -0.6 23 5 4 5 5 4.6
24 -1 0 1 0 -0.8 24 5 4 5 5 4.8
25 -1 -1 1 0 -1 25 5 5 5 5 5
26 -1 -1 1 0 -1.2 26 5 5 6 5 5.2
27 -1 -1 1 0 -1.4 27 5 5 6 5 5.4
28 -2 -1 0 -1 -1.6 28 6 5 6 6 5.6
29 -2 -1 0 -1 -1.8 29 6 5 6 6 5.8
30 -2 -2 0 -1 -2 30 6 6 7 6 6





Range 0-5 to 1023-0 Range 0-5 to 0 -1023
x map map1 map(+1) map(round) Rosetta x map map1 map(+1) map(round) Rosetta
-5 2046 2046 1874 2046 2046 -5 -1023 -1023 -853 -1022 -1023
-4 1842 1841 1704 1841 1841.400024 -4 -819 -818 -682 -818 -818.400024
-3 1637 1636 1534 1637 1636.800049 -3 -614 -613 -512 -613 -613.800049
-2 1432 1432 1363 1432 1432.199951 -2 -409 -409 -341 -408 -409.200012
-1 1228 1227 1193 1228 1227.599976 -1 -205 -204 -170 -204 -204.600006
0 1023 1023 1023 1023 1023 0 0 0 0 0 0
1 818 819 853 819 818.400024 1 205 204 170 205 204.600006
2 614 614 683 615 613.799988 2 409 409 341 409 409.200012
3 409 410 512 410 409.199982 3 614 613 512 614 613.800049
4 205 205 342 205 204.599991 4 818 818 682 818 818.400024
5 0 0 172 1 0 5 1023 1023 853 1023 1023
6 -205 -204 1 -204 -204.600052 6 1228 1227 1024 1228 1227.600098
7 -409 -409 -169 -408 -409.199982 7 1432 1432 1194 1432 1432.199951
8 -614 -613 -339 -613 -613.800049 8 1637 1636 1365 1637 1636.800049
9 -818 -818 -510 -818 -818.399963 9 1841 1841 1536 1841 1841.399902
10 -1023 -1023 -680 -1022 -1023 10 2046 2046 1706 2046 2046

KurtE
10-24-2020, 08:05 PM
I'm not eager to extend the SPI library public API this way, so as written, no, probably not.

But I would be happy to merge this if it didn't change the public API. Maybe some trickery with inline methods and possibly __builtin_const_p could let these be private functions that get automatically used when the inputs are conducive?

Paul I commented in the PR, that I also wanted to add these (16 bit versions) earlier and we removed it from the PR, back then. And as I commented on this PR, if we do add the 16 bit extensions we should add them to 3.x and LC as well.

MichaelMeissner
10-24-2020, 08:48 PM
I've never heard of this syntax either.




This thread.
https://forum.pjrc.com/threads/62473-Adding-Print-class-printf()-format-string-vs-arguments-checking

I believe inttypes.h were added in C99, and I think C++11. I left the C standards committee between the C90 and C99 standards, so I don't recall exactly when it got added. It relies on string concatenation that was in the original C standard (and in fact was one of the changes added by the committee that weren't in the original K&R C and later pcc, GNU compilers).

String concatenation is when the lexer sees two or more adjacent string literals together, and pastes them into one string. I tend to use it for printf formats to break long lines, but it is also useful for substitution of the formats:


printf ("This is the first line\n"
"This is the second line\n"
"This is the third line\n");



IMHO, most of the code written here is tightly coupled to the used processor anyway. So, using all this complicated syntax just to get platform independent printfs for platform dependent code seems a bit, say, overengineered to me.
I appreciate having the ability in the times when the size of the item needs to be a given size (since I have used many different platforms over the years). While I haven't programmed an AVR 32u4 (such as the Leonardo) or AVR 328p (such as the Uno) in a few years, I have moved some of my code between the platforms. There int was 16-bits, instead of 32-bits And who knows, maybe the Teensy 5 systems will have different defaults.


https://pubs.opengroup.org/onlinepubs/009696799/basedefs/inttypes.h.html

mjs513
10-24-2020, 10:07 PM
I believe inttypes.h were added in C99, and I think C++11. I left the C standards committee between the C90 and C99 standards, so I don't recall exactly when it got added. It relies on string concatenation that was in the original C standard (and in fact was one of the changes added by the committee that weren't in the original K&R C and later pcc, GNU compilers). You are correct Michael. When I was looking at the c++ man pages it showed C99 and a tab for C++11.

PaulStoffregen
10-25-2020, 01:50 PM
Ok - here is a side by side comparison. looks like its working both in forward and reversed ! ....

Thanks for testing!

Hopefully we will finally have a map() function that meets all expectations.

mjs513
10-25-2020, 02:05 PM
Thanks for testing!

Hopefully we will finally have a map() function that meets all expectations.

Not problem glad to help. This is deja vu. Seem to remember you working on the map() function a couple of years ago as well.

If there is anything else you need checked let me know.

PaulStoffregen
10-25-2020, 02:15 PM
I tried making use of the SPI 16 and 32 bit block transfer functions. The Ethernet library fails to run if they're used.

Can anyone see a mistake?

https://github.com/PaulStoffregen/SPI/commit/aedb543cb374217c1ee4c731ffcb8f06f7533afa

I'm about to turn on my oscilloscope and start checking if these functions actually work...

KurtE
10-25-2020, 02:39 PM
I tried making use of the SPI 16 and 32 bit block transfer functions. The Ethernet library fails to run if they're used.

Can anyone see a mistake?

https://github.com/PaulStoffregen/SPI/commit/aedb543cb374217c1ee4c731ffcb8f06f7533afa

I'm about to turn on my oscilloscope and start checking if these functions actually work...

I am guessing byte ordering.

For example earlier when I had transfer16 with buffers, I could use it do an easy faster display driver for 16 bit colors, which worked great and did not work correctly to use the transfer(.,..) buffer version as the LSB and MSB bytes were swapped....

KurtE
10-25-2020, 02:41 PM
Note: On T3.x code we have stuff that when you call transfer with buffers, we try packing the data into words and unpack as we push the stuff onto the FIFO and pull it off ... Don't think we ever did that on T4 code yet.

mjs513
10-25-2020, 02:54 PM
Looking at the SPI.h looks like you still have some 1052 defines (line 1139 or so not sure still needed unless for posterity :) );

Don't really use ethernet much but looking at the lib looks like the only place that uses SPI is in W5100.cpp especially in the read write function (line 298) (not sure I even have a wiznet board around but might). The 32 bit write looks like this (not sure what chip == 52 or 51 or 55 means though):

} else if (chip == 52) {
setSS();
cmd[0] = addr >> 8;
cmd[1] = addr & 0xFF;
cmd[2] = ((len >> 8) & 0x7F) | 0x80;
cmd[3] = len & 0xFF;
SPI.transfer(cmd, 4);
#ifdef SPI_HAS_TRANSFER_BUF
SPI.transfer(buf, NULL, len);
#else
// TODO: copy 8 bytes at a time to cmd[] and block transfer
for (uint16_t i=0; i < len; i++) {
SPI.transfer(buf[i]);
}
#endif Don't remember what we did on the transfer16 in the display libs so will defer to Kurt

PaulStoffregen
10-25-2020, 02:56 PM
Yes, byte order is an issue.

But I also made a silly mistake of not converting byte count to word count. Doh!

https://github.com/PaulStoffregen/SPI/commit/574ab8c7a8a45ea21cc56dcc6b7361da90868e86

mjs513
10-25-2020, 02:57 PM
Yes, byte order is an issue.

But I also made a silly mistake of not converting byte count to word count. Doh!

https://github.com/PaulStoffregen/SPI/commit/574ab8c7a8a45ea21cc56dcc6b7361da90868e86

Smile - glad its not just me that makes "silly mistakes" - feel better now.

PaulStoffregen
10-25-2020, 03:03 PM
Turns out this optimization makes only a small improvement.

Here's a little test program which transmits 12 bytes at 33 Mbit/sec.



#include <SPI.h>

void setup() {
SPI.begin();
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
}

void loop() {
uint32_t data[] = {0x12345678, 0xDEADC0DE, 0x55AA964C};
SPI.beginTransaction(SPISettings(33000000, MSBFIRST, SPI_MODE0));
digitalWriteFast(10, LOW);
SPI.transfer(data, sizeof(data));
digitalWriteFast(10, HIGH);
SPI.endTransaction();
delay(10);
}


With the original byte-oriented block transfer, total time taken is 3.67 us.

22195

Using the 32 bit word-oriented block transfer, total time taken is 3.54 us.

22196

You can see the bytes are in the wrong order, but otherwise it seems to be working. Not sure if this modest speedup is worth the complexity? Any thoughts?

KurtE
10-25-2020, 03:10 PM
I will try to take a look through some of the code for the fun of it.

Some of the more recent changes were sort of a hack to get around some interesting features of the TCR register.

That is if you do something like:
spi_registers->TCR = <Set to 16 bit mode >

spi_registers->TDR = my_word;
spi_registers->TCR = <Set to 8 bit mode>
....

Serial.print(spi_registers->TCR, HEX);


The print will show you are in 16 bit mode. This was the issue we had awhile ago if someone did: transfer(x);transfer16(y); transfer16(z); transfer(a);
The a would output 16 bits... Why, because the transfer 16, Read in the current TCR, set it to 16 bit mode, output its data, set it back to the saved TCR... Well when you call the transfer16 the
second time it reads that it is in 16 bit mode and restores it to 16 bit mode....

And yes, the KinetisK code originally always reversed the bytes when it packed them to the PUSHR register, but that screwed things up when code was LSBFIRST

mjs513
10-25-2020, 03:11 PM
@KurtE is the expert here but I think why the speed up for 1 32-bit word transfer or 16-bit (my guess) is small if you are doing alot of transfers like for a display it may add up to a greater savings - not sure I said that correctly.

KurtE
10-25-2020, 03:26 PM
Turns out this optimization makes only a small improvement.

You can see the bytes are in the wrong order, but otherwise it seems to be working. Not sure if this modest speedup is worth the complexity? Any thoughts?

Yep that was sort of what I saw earlier on, which is why at the time I punted on it at the time...

But I did like the transfer16(buf, retbuf, cnt) like functions.

as one could write pretty quickly functions like we use in display libraries pretty quickly...
Like:

void ILI9341_t3::writeRect(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t *pcolors)
{
beginSPITransaction(_clock);
setAddr(x, y, x+w-1, y+h-1);
writecommand_cont(ILI9341_RAMWR);
for(y=h; y>0; y--) {
for(x=w; x>1; x--) {
writedata16_cont(*pcolors++);
}
writedata16_last(*pcolors++);
}
endSPITransaction();
}



void ILI9341_t3::writeRect(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t *pcolors)
{
beginSPITransaction(_clock);
setAddr(x, y, x+w-1, y+h-1);
writecommand_cont(ILI9341_RAMWR);
_pspi->transfer16(pcolors, nullptr, w*h);
endSPITransaction();
}


Note: I did not do the full conversion here showing what the other functions would be without touching hardware registers. Again on T3.x it would still be reasonably slower than the current code in that with T3.x the PUSHR can handle the automatic switching of DC pin, where here the transfers have to complete and then change. But still would not be bad...

Side note: the above is why the ESP32's SPI has the methods:

void writePixels(const void * data, uint32_t size);//ili9341 compatible
void writePattern(uint8_t * data, uint8_t size, uint32_t repeat);

vjmuzik
10-25-2020, 07:32 PM
For my use case I was using transfer32 to write 2 pixels at a time to 6 displays which offered a significant increase in performance. Of course for the pixel data the byte order didn’t have to be changed so I could just write all the buffers as is and the displays showed up correctly. I know Paul doesn’t like making changes to public API, but it would be nice to access these functions in some type of way for the special cases that can make use of them.

defragster
10-31-2020, 09:04 AM
From : File-abstraction-and-SdFat-integration (https://forum.pjrc.com/threads/64136-File-abstraction-and-SdFat-integration?p=257767&viewfull=1#post257767)

@KurtE / @mjs513:: ... @Paul
the Println() is ugly - it prints like:

size_t Print::println(void)
{
uint8_t buf[2]={'\r', '\n'};
return write(buf, 2);
}


I suppose the fix is to have the Windows IDE SerMon act like it does under Mac/Linux and turn "\r\n" into a single "\n" for GUI display?

Or maybe the '\r' and '\n' are not needed for Mac/Linux either and they just happen to eat the Return [ like a good line printer ] then do the New Line without showing a double line feed like on Windows.

PaulStoffregen
10-31-2020, 10:38 AM
the Println() is ugly

You need to be much more specific about how to reproduce this problem!

I tried just now with Arduino 1.8.13 and 1.54-beta2 on Windows 10. I believe you can see in this screenshot it looks perfectly fine.

22258

I'm sure you're doing something else that does bring out some sort of problem. But how am I supposed to guess what you're actually doing that's giving ugly printing?

mjs513
10-31-2020, 12:03 PM
You need to be much more specific about how to reproduce this problem!

I tried just now with Arduino 1.8.13 and 1.54-beta2 on Windows 10. I believe you can see in this screenshot it looks perfectly fine.


I'm sure you're doing something else that does bring out some sort of problem. But how am I supposed to guess what you're actually doing that's giving ugly printing? Oops - guess I forgot the other piece of the puzzle.

When you dump to the SerMon everything looks fine, as you have shown, but now try and copy the contents of the window and paste it into your editor of choice including the forum. You will see extra blank lines. Using your example:

Hello World 1

Hello World 2

Hello World 3

Hello World 4

Hello World 5

Hello World 6

KurtE
10-31-2020, 12:44 PM
@Paul and all - yep that is the issue I mentioned earlier.

As for stuff for the next beta - Wonder about the Hardware Serial Half duplex support I did earlier in the Pull Request: https://github.com/PaulStoffregen/cores/pull/489
It was sort of fun to do an T3.x as no real additional overhead to the Serial Writes and the ISR as in this case simply changed the bitband register value we were saving to instead of setting or clearing the IO pins it instead changed the bit in the IO register that set the TX pin to transmit or receive.

PaulStoffregen
10-31-2020, 04:21 PM
Ah, yes, I see it now. Double space with copy & paste. This problem is on the Arduino side. To see this, select the non-Teensy COM port from the Tools > Ports menu. That will use Arduino's normal (slow) serial monitor. If you copy & paste from that one, you'l get single space lines.

I've put this on my bug list. But I'm going to wait until at least beta4. I want to get beta3 wrapped up for testing just as soon as the new File and SD / SdFat stuff is stable enough for widespread testing.

jonr
10-31-2020, 06:06 PM
I confirmed this USB audio issue:

https://forum.pjrc.com/threads/61142-USB-Audio-Frame-Sync-on-Teensy-4-0

bicycleguy
11-01-2020, 09:45 PM
Installed on macOS Catalina 10.15.7

No new issues so far. Haven't looked at any of the new features but all old stuff seems to work.

defragster
11-02-2020, 06:40 AM
Beta 3 released >>> Teensyduino-1-54-Beta-3 (https://forum.pjrc.com/threads/64235-Teensyduino-1-54-Beta-3)