Teensyduino 1.54 Beta #2

Status
Not open for further replies.
It installs :)

<edit>

T_4.1 10-15 uploads of 5 recent sketches noted in beta1 thread all good.
 
Last edited:
EEPROM put/get handle String and warn for incompatible classes

Tested with the code below. Works as expected.

Code:
#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
Code:
Hello Teensyduino 1.54 beta 2
Good struct
1.54
2
 
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
ScreenShot.jpg
 
Last edited:
> 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);
 
KurtE said:
Installed RPI4 8GB SSD Ubuntu Arm64 issue
Seeing exactly the same thing using Ubuntu 18.04, the screenshot matches exactly.

Code:
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?
 
> 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:
Code:
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)
 
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:)
 
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'
 
@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!
 
Nearly :). You also need to add spaces:

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

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

void loop(){}

Prints:
Code:
Var: 00000042

Without the spaces I get a warning:

Code:
[COLOR="#B22222"]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)[/COLOR];

I'm sure this syntax was invented to scare users away from printf :)
 
More tests with the PRIs

Code:
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:
Code:
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?
 
@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...nt-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:
Code:
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

[COLOR="#FF0000"]PRIi8: -2 
PRIu8: 65534 
PRIX8: FFFE 
 int negative var is <FE>[/COLOR]
 
Last edited:
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
 
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.
 

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:
Code:

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
 
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 :)
 
I've made a pull request here 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?
 
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?
 
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?
 
I have a PR pending on adding a function to DMAChannel.h to allow ISR to be executed at specific interrupt level.
 
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:
Code:
// 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:
Code:
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.
 
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.
 
Status
Not open for further replies.
Back
Top