Code Monkey home page Code Monkey logo

arduinocore-api's Introduction

ArduinoCore-API

Unit Tests codecov Spell Check status

This repository hosts the hardware independent layer of Arduino core. In other words it contains the abstract definition of the Arduino core API, consisting of hardware-independent header files that are then included and implemented by the various platform-specific cores.

Having a single place where the Arduino API is defined means that there is no longer a String implementation within every Arduino core (a String module within ArduinoCore-avr, a String module within ArduinoCore-samd, a String module within ArduinoCore-megaavr …) but rather one String implementation within ArduinoCore-API which all other cores utilise. This has the pleasant side effects that bugs fixed or features added within the ArduinoCore-API String implementation are automatically propagated to all cores utilizing ArduinoCore-API.

As of now, the following official cores are utilising ArduinoCore-API:

There's an ongoing effort to port the others, while maintainers of third-party cores are strongly invited to follow the same route in order to stay up-to-date with the new language features. For backwards compatibility, every revision of this repo will increase the ARDUINO_API_VERSION define.

Documentation

The Arduino API is documented in the official language reference, whose sources are located in this repository and are open to contributions from the community.

Support

This repository is not directly usable by final users. If you need assistance with Arduino, see the Help Center and browse the forum.

Development

Bugs & Issues

If you want to report an issue with this core, you can submit it to the issue tracker of this repository. Some rules apply:

  • If your issue is about a specific hardware platform, report it to its repository. This one is only about discussing the generic API.
  • Before posting, please check if the same problem has been already reported by someone else to avoid duplicates.
  • Remember to include as much detail as you can about your hardware set-up, code and steps for reproducing the issue. Make sure you're using an original Arduino board.

Contributions

Contributions are always welcome! You can submit them directly to this repository as Pull Requests. Please provide a detailed description of the problem you're trying to solve. We also appreciate any help in testing issues and patches contributed by other users.

Unit testing

This repository includes a test suite that covers most of the API and that is designed to run on generic hardware, thus not requiring a development board. We call this host-based unit-testing. In order to test the features that are only defined but not implemented in this repository, mock implementations are included.

Please help us improve the coverage of the test suite!

To build and run unit tests

The unit tests are automatically built by GitHub as part of pull request checks (in .github/workflows/unit-tests.yml).

To build and run locally:

Dependencies

On (Ubuntu) Linux run:

sudo apt-get install build-essential cmake

From the project root:

cd test && mkdir build && cd build
cmake ..
make && bin/test-ArduinoCore-API

Implementing ArduinoCore-API

In order to compile a core which is implementing ArduinoCore-API you'll need to copy/symlink the api directory to the target's cores/arduino directory as part of your development and release workflow. The most elegant and effective solution is to develop your core with api symlinked and produce the distributable archive by telling tar to follow symlinks. Example:

tar --exclude='*.git*' -cjhvf $yourcore-$version.tar.bz2 $yourcore/

The API is coded to the C++11 standard and the core's compiler must be able to support that version of the language.

Documentation for how to integrate with a Arduino core (which is necessary if you do not download the Arduino core via the Boards Manager) can be found here:

Donations

This open source code is maintained by Arduino with the help of the community. We invest a considerable amount of time in testing code, optimizing it and introducing new features. Please consider donating or sponsoring to support our work, as well as buying original Arduino boards which is the best way to make sure our effort can continue in the long term.

License and credits

This code is licensed under the terms of the GNU LGPL 2.1. If you have questions about licensing please contact us at [email protected].

arduinocore-api's People

Contributors

aentinger avatar alranel avatar camelcasename avatar cmaglie avatar cousteaulecommandant avatar earlephilhower avatar edgar-bonet avatar facchinm avatar giulcioffi avatar guberti avatar haydenroche5 avatar iabdalkader avatar jamadagni avatar jandrassy avatar jboynes avatar jrowberg avatar leg0 avatar matthijskooijman avatar mcspr avatar obra avatar pennam avatar per1234 avatar piotrekb416 avatar positron96 avatar robtillaart avatar rotzbua avatar sandeepmistry avatar sgryphon avatar tttapa avatar umbynos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

arduinocore-api's Issues

accept() function missing from the new Server base class. [imported]

This is Issue 616 moved from a Google Code project.
Added by 2011-08-31T19:11:09.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.

Original labels: Type-Defect, Priority-Medium, Component-Core

Original description

I'm guessing this is because we can't return a Client from it, and we're trying to avoid pointers or references. Maybe we can return a ClientProxy class or something, which also inherits from Client and basically wraps a pointer to a EthernetClient (or other subclass of Client)? Or even make the Client base class itself also able to act as a proxy?

What do you think, Adrian? Want to bring it up on the developers list?

round() macro in Arduino.h

The function round() in "math.h" is okay, it returns a floating point number as expected.
The macro round() in "Arduino.h" is a bug. It can not handle large floating point numbers and it returns a long integer.
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
It could be renamed to something else, for example ROUND_INT().

The sketch below shows the difference. With the normal round() function it returns four times "1.50", and with the round() macro in "Arduino.h" it returns: "1.00", "1.50", "1.50", "0.00".

// Arduino IDE 1.81 with Arduino Uno

// The "#undef round" removes the round() macro in Arduino.h
// Try with and without the #undef round
// #undef round

void setup() 
{
  float x;
  Serial.begin( 9600);

  x = 15.0;
  x = round( x) / 10;   // a integer division with the macro
  Serial.println( x);   // wrong value with the macro

  x = 15.0;
  x = round( x) / 10.0; // always calculated with floats
  Serial.println( x);   // always okay

  x = 15.0;
  x = round( x);
  x /= 10;              // always calculated with floats
  Serial.println( x);   // always okay

  x = 1.5E+20;
  x = round( x);        // the macro fails
  x /= 1E+20;           // make it printable with Serial.println
  Serial.println( x);   // wrong value with macro 
}

void loop()
{
}

Add printf patch to print?

Arduino web site documents a patch to add to print ( class ) to implement "semistandard" printf.
Would it be possible to implement this patch permanently in next 1.5.x release?
With limited debugging tools any help to Serial and others ( LCD?) would be much appreciated.

Many thanks for speeding up the compiler, nice work!

String class buffer overflow prevention

Bug affects these functions

String::String(float value, unsigned char decimalPlaces)
{
    init();
    char buf[33];
    *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}

String::String(double value, unsigned char decimalPlaces)
{
    init();
    char buf[33];
    *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}

if decimalPlaces is greater than the size of buffer the buffer will overflow

Code should limit the decimalPlaces parameter in both functions like this.
Furthermore given the fact that an IEEE754 double has only ~17 significant digits and a float max 9 a buffer size of 20 (double) resp 12 (float) should be enough instead of 33.

String::String(double value, unsigned char decimalPlaces)
{
    init();
    char buf[33];
    if (decimalPlaces > 30) decimalPlaces = 30;     
    *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}

Suggest adding I2C_writeAnything to Wire library

I have the following small template library on my page about I2C ( http://www.gammon.com.au/i2c ):

template <typename T> unsigned int I2C_writeAnything (const T& value)
  {
  Wire.write((byte *) &value, sizeof (value));
  return sizeof (value);
  }  // end of I2C_writeAnything

template <typename T> unsigned int I2C_readAnything(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          *p++ = Wire.read();
    return i;
  }  // end of I2C_readAnything

It has been suggested to me that I request that you include this in the standard Wire library (Wire.h). This lets you more easily send things like floats or structs via I2C. For example:

    float fnum = 42.666;
    Wire.beginTransmission (SLAVE_ADDRESS);
    I2C_writeAnything (fnum);
    Wire.endTransmission ();

Being a template function it won't add any bloat unless you actually use it.

Related request: https://github.com/arduino/Arduino/issues/3692

Rename RealtimeClock to ArduinoTime

The RealtimeClock class is actually managing time so it should be called ArduinoTime

we could also provide a software only implementation which can be useful even if only based on millis() (there are a number of use cases where one needs to manage time, maybe syncronising via NTP every etc)

Add support for printf, stdio, etc. [imported]

This is Issue 903 moved from a Google Code project.
Added by 2012-04-28T07:11:30.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.

Original labels: Type-Enhancement, Priority-Low

Original description

It might be nice to put an arduino-style wrapper around the standard printf() and related functions.

Serial.setAsSTDOUT();

or something like that. For anything based on stream ?

Multi-target versions of Stream::find() and Stream::findUntil().

Sometimes, you want to read / parse incoming stream data until you find one of two (or a few) different strings. This is particularly useful when dealing with Serial-based (or other Stream based) APIs, like the Quectel M10 GSM module or the ESP8266 wifi module.

It's not entirely clear to me what the best API / implementation would be, since there are a variety of use cases / needs. For example, with those modules, you may want to look for either an okay message, an error message, or an unsolicited event that's not in reply to your previous command.

Templated map() function

Hello !

Apologies if this is a duplicate, but I couldn't find any previous discussions on github about it.

Is there a reason why map() isn't templated to provide maximum awesomeness??

Something as simple as this, would get rid of surprises when trying to use map() to scale to [0,1]:

template<class T>
T map(T x, T in_min, T in_max, T out_min, T out_max)
{
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Low Power Shared API

As per ongoing discussion with .org about libraries, here is a proposal for MCU (and companion MCU) standby API

https://github.com/rocketscream/Low-Power is a good starting point, AVR API is too granular so we should avoid it. But the SAMD API is quite good.

Function calls would simply be

  • idle()
  • sleep()
  • deepSleep() -> might call sleep() if there is only one sleep mode

which in modern MCU is like WFI with peripherals enabled and WFI with peripherals disabled.
STM32 processors also have a mode called WFE which I would avoid exposing. Other MCU (nRF chips for example) might have multiple sleep levels; I'd select two/three of them to be exposed.

To register a wakeup source I propose overloading attachInterrupt API with a couple of versions:

  • attachInterrupt(pin, function, MODE, wakeup) would become the main function;
  • attachInterrupt(pin, function, MODE, false) will be called for classic API
  • attachInterruptWakeup(pin, function, MODE) will call attachInterrupt(pin, function, MODE, true)

If function is NULL, wakeup-enable bit should be set and no function called

if pin in NOT_A_PIN, extra code can handle the additional wakeup sources.
I suggest using macros like RTC_WAKEUP or ADC_WAKEUP with high values (0xFF, 0FE etc)

@cmaglie @sandeepmistry @tigoe any thoughts about that?

Alternate SPI configuration with SPI transaction function

This issue relates to use of the spi transaction function with respect to device libraries that handle SPI configuration internally.
While one could dig into the library code for each device to determine how it configures the SPI device, it would seem better, (to me anyway) to have a configuration read-back function.
One would instantiate each device and let it configure SPI, Then use a SPI library function to read-back and save the current configuration. Even better, integrate this into the transaction function giving it the ability to read/save/use the current configuration. So the final process would be instantiate each device , use the transaction function to read/save the SPI configuration for each device.
The result is the same as the current transaction process but seems to better encapsulate/manage library based SPI configuration.

Thanks for the opportunity to discuss this.

Regards,
Jim Brooks

Retrieve current pin mode

There is currently no function to get the current pin mode. A possible implementation is:

int pinMode(uint8_t pin)
{
  if (pin >= NUM_DIGITAL_PINS) return (-1);

  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *reg = portModeRegister(port);
  if (*reg & bit) return (OUTPUT);

  volatile uint8_t *out = portOutputRegister(port);
  return ((*out & bit) ? INPUT_PULLUP : INPUT);
}

The return value is the pin mode or error code (-1) for illegal pin number.

Cheers!

sensors without FIFO

availableGyroscope() should be required.

Sensors without a FIFO should have their available functions return 1 when the sensor has produced a new measurement since the most recent read, or 0 if no new measurement has been completed where reading again would give duplicate data.

Filter algorithms which accumulate need to be able to know whether the read is the same data they previously used, so they don't double count anything. This is always done with gyroscope data, so it's really important for the API to not allow a default 1 return for availableGyroscope(). Some advanced algorithms may also accumulate accelerometer data, but Madgwick does not. As far as I know, this isn't important for magnetometer data.

The sampleRateGyroscope() function should probably also be required, without a default. The data just isn't usable if this info is missing.

Add a way for Stream objects to indicate that the end of the stream has been reached

Certain stream types can end - obviously not Serial, but those derived from Client, plus the File objects in SD. File gets round the problem by returning an available of 0, but that doesn't work for the Client-derives classes as they might be waiting for more data to arrive over the network.

There was some discussion about this when I submitted the pull request to add the HttpClient library, which includes endOfStream() and completed() methods which are synonyms for checking that. So the easiest option would be for one (or both) of those method names to migrate up the class hierarchy to Stream.

The lack of this method is most visible when using the Stream::findX methods with the Ethernet or WiFi classes. Because you want a reasonable timeout on the Stream to allow for the network delays, and because when it reaches the end of the stream the only way for the timedRead in Stream to exit is to wait until it times out, you get a long delay at the end of reading your web page (or whatever you've downloaded). With an endOfStream or completed method on Stream, the timedRead and timedPeek methods could use that to check whether they should continue waiting or fail immediately.

SPI transaction API insufficient?

Originally posted in arduino/Arduino#2449 by @PaulStoffregen:

Please do not mistake the issue I'm about to describe with the transaction scope discussion.

Also, please let me preface this with the caveat that it's still very preliminary. I'm actively working on the nRF8001 library, and it's still very much a work-in-progress.

Nordic's nRF8001 seems to be exposing a weakness in the API, which I didn't consider until now. I had considered the RFM69 radio modules, Wiznet ethernet chips, and CC3000 Wifi module in the design of this API. In all those cases, the chip requests service by asserting an interrupt signal. CC3000 is a bit strange, but I'm not going to discuss is right now.

The problem with nRF8001 is the request to initiate communication is done by asserting chip select, which then causes the chip to request an interrupt. SPI transfers must be blocked during that request-to-interrupt time. The trouble is SPI.beginTransaction() disables all registered interrupts, including the one for nRF8001, which prevents the ISR from responding.

At the moment, I'm working with a kludge where I just turn that specific interrupt back on. That may be the final answer. It may be perfectly acceptable to just leave the SPI API as it is, and accept that nRF8001 (and any future chips from Nordic or others) require this workaround.

Or perhaps the SPI API should be able to accommodate this sort of case? Ideally, what's needed is for beginTransaction() to disable the interrupts being used by all other SPI libraries. That's probably much easier to achieve on Cosa, since each library creates an instance of SPI. On Arduino, we're trying to work within the legacy of the SPI library being a thin, static-only C++ wrapper. Requiring sketches and libraries to create instances of the SPI library is probably far too large of an API change to even consider.

Perhaps beginTransaction() could have an alternate/overloaded version that disables all but a specific interrupt. Or perhaps just a function to re-enable the interrupt would work? Or just pushing the responsibility to do that onto the nRF8001 library may be the answer... but that does mean the nRF8001 lib couldn't rely on the SPI lib and core library to fully abstract the hardware.

Well, unless we end up implementing enableInterrupt() and disableInterrupt() or similar core lib functions, as Matthijs has already worked on.

In hingsight, I really should have worked on nRF8001 much earlier. Sorry about that, and really, the last thing I wanted to do was make this SPI stuff even more complicated. Sadly, it seems Nordic has used a design which requires us to acquire exclusive access to the SPI bus, then assert a chip select, and then respond to the falling edge or low level of an interrupt signal, which doesn't assert until the chip select is asserted.

Feature request: String::isInt() and String::isFloat() for more robust String parsing/conversion

The current implementations of String::toInt() and String::toFloat() rely on atol() and atof(), respectively (See WString.cpp). As both atol() and atof() have no means of signaling a failed conversion due to improper input Strings (both return 0 upon error) I propose adding two new member functions to the String Class:

int String::isInt()
Returns a value different from zero if String is a valid representation of an integer.
Returns zero otherwise.

int String::isFloat()
Returns a value different from zero if String is a valid representation of a floating point number.
Returns zero otherwise.

Official freeRam() command

All mcu project may pay attention on Ram use, and have an official command for print freeRam at runtime it is very important.
For avr there is a well know freeram function, but it do not work on other architecture, like Zero, Due, etc.

So i think that an official freeRam() function is actually very needed inside the Arduino core, and this also would push third-party core authors to work on their implementation of freeRam().

Serial.print as HEX should ALWAYS print 2 chars per byte; it omits leading zeroes [imported]

This is Issue 1097 moved from a Google Code project.
Added by 2012-11-05T10:22:49.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.

Original labels: Type-Defect, Priority-Medium

Original description

What steps will reproduce the problem?
1.If byte or integer variables are printed with serial.print or serial.println with the HEX output format option leading zeroes are not printed:
byte reading5 = 0x0F;
byte reading6 = 0x00;
byte reading7 = 0xF0;
.............
Serial.print("reading5 = ");
Serial.println(reading5, HEX);
Serial.print("reading6 = ");
Serial.println(reading6, HEX);
Serial.print("reading7 = ");
Serial.println(reading7, HEX);


and the result is:
reading5 = F
reading6 = 0
reading7 = F0

What is the expected output? What do you see instead?

The output for HEX should always be one char per nibble; leading zeroes matter. With the data above, calling:
Serial.print("0x");
Serial.print(reading5, HEX);
Serial.print(reading6, HEX);
Serial.println(reading7, HEX);

yields 0xF0FO where it should display 0x0F00FO; the value is totally changed by omission of the leading zero.

What version of the Arduino software are you using? On what operating
system? Which Arduino board are you using?
Arduino 1.0.1, WinXP (current, fully updated), Duemilinove

Please provide any additional information below.

Same behaviour with Arduino 1.0 and using the Arduino serial monitor or SecureCRT interface.

I can't think of any reason to omit leading zeroes when using the HEX format. In cases like this, where a sequence of bytes is read from a device that represents a multi-byte return value, and you want to see the real value returned it gives incorrect results. One could assemble the bytes into a LONG and then call the function, but I think that most who use the HEX format would like to see all their nibble values with any size data. The examples in the Arduino reference sidestep the issue by not showing any example with a leading zero ;-)
http://arduino.cc/en/Serial/Print

Add 9bit support to HardwareSerial

I stumbled over a few different implementations / tweaks how Arduino could read 9bit data using Serial objects; the core library does not support 9bit, while the standard UART HW does ...

I am aware of issues arduino/Arduino#2292 and arduino/Arduino#2291 - however I'd like to take a differen timplementation path: use guard macro to conditionally enable the extra code (and twice as long buffer). This way, normal user will not see any performance/size penalty, but developer who needs 9bit support could enable it at the documented cost.

Diffs will be attached shortly as PR...

add peek(size_t pos) Stream/HardwareSerial

It would be nice, if the Stream-Interface could be changed/extended with a peek method that takes a position/offset. I often have the need to search/wait, until a certain charakter is received - before i process the message. If course, storing in a temporary buffer works as well, but uses more memory and often complicates things...

Most simple way would be to add a default argument to peek
int peek(size_t = 0);

int HardwareSerial::peek(size_t pos)
{
   if (_rx_buffer->head == _rx_buffer->tail) {
     return -1;
   } else {
     return _rx_buffer->buffer[(_rx_buffer->tail+pos)%SERIAL_BUFFER_SIZE];
   }
}

Suggestion to add constants RAND_MAX, AD_MAX, DA_MAX

To enamble to write portable code please add following costants to a header file:

RAND_MAX -> maximal random number

AD_MAX -> maximal value provided by analogRead() 1023 or 4095 depending on the microcontroller.

Best regards, Bela

Add more readable name for isnan() from math.h [imported]

This is Issue 812 moved from a Google Code project.
Added by 2012-02-10T18:03:34.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.

Original labels: Type-Enhancement, Priority-Medium, Component-Core

Original description

There are some useful functions in math.h, especially isnan(). We should add a few defines to give them more beginner-readable names.

IPAddress conversion to uint32_t has wrong endianness

Running the following code

// 0x0A000102 is the hex representation of 10.0.1.2
Serial.println(0x0A000102);
Serial.println(IPAddress(0x0A000102UL));
Serial.println((uint32_t)IPAddress(2,1,0,10));
Serial.println((uint32_t)IPAddress(10,0,1,2));  

will output this:

167772418
2.1.0.10
167772418
33619978

This is because the constructor stores the first octet (most significant byte) at the lowest address of the _address union:

IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
{
    _address.bytes[0] = first_octet;
    _address.bytes[1] = second_octet;
    _address.bytes[2] = third_octet;
    _address.bytes[3] = fourth_octet;
}

This is big-endian behavior. The Atmega is little-endian, so the conversion to uint32_t, which is simply done like this:

operator uint32_t() const { return _address.dword; };

yields the octets in the reverse order, breaking code that interfaces with libraries such as low-level sockets or Adafruit's CC3000 library expecting IP addresses in uint32_t.

The easy fix would be to simply reverse the assignment order in the IPAddress constructor, but that may break existing code as the internal data structure is barely hidden. Another fix would be to perform the order reversal in the operator uint32_t().

SD library API for use with SDIO port

All SD cards support 2 access methods, native SDIO mode and a simpler/slower SPI mode meant for microcontrollers. Some newer 32 bit microcontrollers are featuring native SDIO ports. I'm working with one right now....

Would like any input on how the SD library API should be extended to support these? So far, my main thought is to define a symbol like SDIO_PORT

  SD.begin(4);          // use SPI mode with pin 4 as chip select

  SD.begin(SDIO_PORT);  // use native SDIO port, which does not have a chip select line

Does this look reasonable? Or has anyone already made other plans or ideas for supporting chips with native SDIO?

AudioStream API

Hi @PaulStoffregen,

We're exploring adding an AudioStream API to Arduino that extends the current Stream type. The draft interface can be found here: api/Audio/AudioStream.h. We would appreciate any feedback you have on it.

We've taken a look at the Teensy Core's AudioStream type and noticed it doesn't have any public interfaces to access the raw sample data. Was this done for performance reasons?

Uses cases we are thinking about include:

serial.write(byte)0)

the programmcode 👍
serial.write(0);
will work with arduino uno / mega

but with :
arduino 101
arduino MO
chipKIT uC32

I get an compiler error 👍

test_serial:31: error: call of overloaded 'write(int)' is ambiguous

     Serial.write(0);

use :Arduino 1.8.1
win 7

toggle();

many core have a toogle() function.
Also some third part arduino core have it.
a toogle() function is useful on many or all project,
please add it to the official arduino core.

Issues with Print::print() and partial writes

quoting @bperrybap here
http://forum.arduino.cc/index.php?topic=357312.msg2481770#msg2481770

While there was an issue in the i2c library that was triggered by this new Print
class code, there is a still a fundamental issue with new new Print class code.
The issue is that the Print class code is actually composed of two parts.
The low level functions like read()/write() and the higher level output formatting
functions like print(). And both layers support partial/incomplete i/o.
(outputting less than the maximum asked to output)
I believe that if print() is allowed to support partial/incomplete i/o, that we will be
fighting related issues for years.

What seems to have happened is that in 1.6.6. write() was updated to properly
support incomplete i/o and print() is now seeing issues because it doesn't
support incomplete i/o.
(An error is essentially a single type of incomplete i/o)

Yes it was a coding error in a library in this case, but it brings up a larger issue
related to partial/incomplete i/o and the print() functions.

Currently, I don't believe that the write() API is mandated to always swallow all
the data provided unless there is an error.

So the issues becomes, how to deal with print() when write() does
incomplete/partial i/o?

Looking forward, unless the write() API mandates blocking when low level 
buffers are full or updating the Print class print() functions to ensure blocking, 
when write() returns after incomplete i/o, I think we will see more issues in 
the future.

While it is ok for functions like write() to support and potentially even require 
supporting incomplete i/o, it is not appropriate for functions like print() to force
this same requirement back up to its callers.
This is because callers of write() know the full contents of what is being output.
The callers of print() do not know the full contents of what is being output since
print() is performing output formatting.
In other words suppose I do something like:

foo.print(bar);

and the variable bar is an big integer number and is is 1234567

Now suppose that the low level i/o library buffer is full and rather than block
(spin) waiting for enough room to take all the requested output,  decides to 
take only what it can.
Suppose that was only 4 bytes.
So the low level i/o library write() will return 4 and then foo.print() will now 
return 4. What the heck is a sketch or any other potentially caller of print() 
code, supposed to do with that?
It has no way of resuming the output nor does it even know how many total 
output characters there were.

The point is that if the API is going to support incomplete i/o, it MUST have 
a option to enable/disable this mechanism for functions like print() to not 
return until all output characters have been handed off.
(The only exception is a fatal error where the i/o would never complete)
I argued this point (enable/disable incomplete/async i/o) a year or so ago 
when we were looking at and arguing over the buffer available function calls.

There must be a way to allow users of the Print class, specifically the print()
functions to have a mechanism to be assured that when the print() function 
returns that all the characters have been handed off.
This is an absolute requirement since only print() knows what characters 
are to be output when formatting is done. The caller has no idea.

It is unacceptable to require all users of the print() calls to have to support 
incomplete i/o. And even if they do support incomplete i/o, there is no way 
to complete the i/o for output that was formatted by print() like number output.

Suppose somebody writes an i/o library that decides to do very limited 
output buffering and simply returns 0 when the output buffer is full vs 
blocking? This is allowed by the API but a sketch would never be able to 
print numbers using print() calls when the numbers were more digits than 
output buffer could hold, even if the sketch code add in all the complexities 
to support incomplete i/o for print() functions.

I'm strongly suggesting that print() use blocking i/o.
If non blocking print() i/o behavior is supported by print() (which I don't even 
think is possible since print() does output formatting), then there needs to be 
an API to enable incomplete i/o for an object (disabled by default) so that 
sketches can get the existing blocking behavior by default which preserves
backward compatibility and keeps user sketches simple.
But I'd still recommend that print() be kept simple and always be blocking 
since there is no real technical way to support incomplete i/o with print() 
functions. Return on errors, yes, but not incomplete i/o.

With regard to errors vs partial i/o. That brings up another API issue.
The write() API should be able to distinguish between errors and incomplete 
i/o. for example, if the hardware is broken and it can't transmit, how can that
be indicated?
Currently, if you return zero, then that could mean the low level buffers are 
full (incomplete i/o) or it could mean an actual error.
A negative value would be better to indicate an error.

Add variadic print(String...) function

Just found this:
http://stackoverflow.com/questions/10044449/a-function-with-variable-number-of-arguments-with-known-types-the-c11-way

Add this to Print.h:

    template <typename ...TailType>
    size_t println(const String &head, TailType&&... tail)
    {
        size_t r = 0;
        r+=println(head);
        r+=println((tail)...);
        return r;
    }

Now you can do stuff like this:
Serial.println("Hey", "this", "is", "a", "Test");

Every word is printed in a new line. You can also add this for Serial.print (without newline).
Maybe this can be optimized to only print the last input with a new line. An overload with two arguments is needed here I guess.

Not sure if its perfect c++, but this would give us the option to print infinite strings at once.
Maybe one can generalize this even more to also print numbers (without formating of course, just DEC).

It takes a lot of flash though. But maybe someone can optimize this further? (Now that we also have c++11 with the merged PR)

Any comments on that?

Edit: Maybe this is also relevant. This uses the same size as if there was no template.
It can also handle numbers (without format).
https://msdn.microsoft.com/en-us/library/dn439779.aspx

    template <typename First, typename... Rest> 
    inline size_t println(const First& first, const Rest&... rest) {
        size_t r = 0;
        r+=println(first);
        r+=println(rest...); // recursive call using pack expansion syntax
        return r;
    }

Another example (ln now only adds a new line at the end):

    template <typename First> 
    inline size_t println2(const First& first) {
        return println(first);
    }

    template <typename First, typename... Rest> 
    inline size_t println2(const First& first, const Rest&... rest) {
        size_t r = 0;
        r+=print(first);
        r+=println2(rest...); // recursive call using pack expansion syntax
        return r;
    }

map() for float data type

This is related to issue 288. The Arduino.app C++ compiler accepts float arguments (no warning) to the map() function and then truncates them to integer values. This provides erroneous output that may not be immediately noticed. I think that map() should be defined as all float -- args and return (below). Particle.io's development platform has the same problem. All C++ compilers?

My float version:
float mapf(float value, float istart, float istop, float ostart, float ostop) {
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}

See http://dicks-photon-arduino.blogspot.com/

Should we provide a Math.h?

I think that EulerAngles, Quaternion and any other math structure should be moved into a specific Math.h file.

I imagine that maintaining a Math.h file may quickly become a project on his own if we try to support all the possible mathematical constructs... maybe we should consider adopting an already existing library? Or extract a subset of an existing library?

String class plus plus

String str0, str1, str2, str3;

str0 = str1 + str2 + str3; //// will cause problem
str0 += str1 + str2; //// will cause problem

str0 = str1; str0 += str2; str0 += str3; // good.

return value from micros() is inconistent on AVR vs SAM

The documentation here:
https://www.arduino.cc/en/Reference/Micros
states that the return value from micros() is an unsigned long.
From looking at wiring.h and wiring.c in both the AVR and SAM cores:

  • return value is (unsigned long) on AVR
  • return return value is a uint32_t on SAM

For additional reference:
The return value on Teensy3 uses uint32_t
The return value on ChipKit (pic32) uses unsigned long (which is 64 bits)

unsigned long and uint32_t are often not the same in 32 bit environments.
I'm not sure how to fix this as the code in the SAM and Teensy3 cores do not reflect what the API documentation says and I'm not sure what the implication of changing those cores to return an unsigned long instead of a uint32_t would be.

Was the intent for it to be a 32bit value or was it to be a "unsigned long" which means it will be at least 32 bits?
It might be better/clearer not to use unsigned long in the API documentation unless the code really does use that type .
There are other standard types that could be used to better reflect what was intended.
i.e. uint32_t, uint_least32_t

Or if unsigned long was really meant, then it seems like the code should be returning that type.

This can be a potential issue when writing library or sketch code that needs to work on many different cores.

i.e. I have code that needs to save the return value and use it later.

Also, there might be some rollover calculation issues when doing compares & math if the sketch/library moves the uint32_t into an unsigned long when the actual value is only 32 bits but unsigned long is 64.

I think in my code for the time being I'm going to cast the return value of micros() to be a uint32_t to work around any of these potential issues.

Trouble with static buffer sizes within the RingBuffer libray

(Arduino 1.6.18.1)

  • Serial communication:

If serial data are read and the attached device does not support any flow control (like most devices that you can buy) the CPU must be in receive mode all over the time. The data received are buffered in a static preallocated 128 byte buffer SAM) within the Arduino library.

The user application must periodical check if there are data and read them and must do it fast enough, before buffer overflow.

If you do for example SD-card-i/o, the SD-card may awake from sleep mode and that cost a few 100ms, you can quickly get an overflow of the serial buffer.

The only chance to overcome this situation is to align the serial buffer size to your application. If there is no flow control on receive, one cannot use a fixed size for all projects.

Please implement a simple method, that the user can set the size of the buffer from within the project (AVR, SAM, and SAMD(?)).

Currently one must modify (SAM): "Ringbuffer.h" => "#define SERIAL_BUFFER_SIZE xxxxx".

(This topic is currently in discussion within the Arduino group.)

VirtualPins

Hi!

I have and enhancement proposal to do small changes in the wiring_digital file and pins_arduino pin mapping, fully preserving compatibility, virtualizing the pins concept and do media (SPI,I2C, etc..) abstraction.
With minimal impact on existing function performance. The existing checks can work on an extended pin map and only adding an if, comparing pin number with a constant to existing functions (digital read/write).

In case of mapping to a virtual pin then the "content" is sent over an SPI or I2C (according to the map).

with this changes, libraries like LiquidCristal wouldn't have to be rewritten to control the same LCD's wired over SPI or I2C.

There are a LOT of advantages beside the mentioned one, but just for that I thinks it worth the effort considering the minimal impact it has.

I've done the implementation and some tests, available here for testing/appreciation:

https://github.com/neu-rah/VirtualPins

but I wish to put it here for discussion first and to get some advice on how should I proceed.

  1. do a pull request with the changes to the arduino environment.
  2. implement an alternative core and board that use virtual pins by duplicating some of the existing boards and pointing them to the alternative core.

waiting for feedback.

thanks.

P.S. this was once done (in bad timing, to and older IDE) but now I'm available again and ported it to 1.8.3

ANSI-C-like fprintf(), fscanf()

Urgently needed: ANSI-C-like fprintf(), fscanf()

Actually homebrewed fprintf_ works fine (SD file checked on PC), just fscanf_ muddles all up.

Up to now I've used a homebrewed function fscanf_ but it doesn't work for floats in larger files (>400 elements), neither by 1.6.1 nor by 1.6.3 nor by 1.6.5.

These are the homebrewed functions:

Code:

//*******************************************************************************_​**_********
int32_t  fscanf_ ( File \* stream, const char fmtstr[], ... ) {
   const  int32_t   MAXSTRSIZE = 1024;
   char   str[MAXSTRSIZE];
   va_list   args;
   int32_t   i=0, cnt=0;
   int16_t   chr;

   va_start(args, fmtstr);

   strcpy(str, "");
   while ( (stream->available()) && (i < MAXSTRSIZE-1) ) {  
      chr = stream->read() ;
      if (chr>=0 && chr!='\n') {
           str[i]=(char)chr;  
           ++i;
      }
      else break;  
   }

   str[++i] = '\0';

   cnt = vsscanf( str, fmtstr, args );
   va_end(args);

   return cnt;
}

//*******************************************************************************_​**_********

int32_t fprintf_ ( File \* stream, const char fmtstr[], ... ) {
   char      str[1024];
   va_list   args;
   int32_t   num;

   va_start( args, fmtstr );
   num = vsnprintf(str, sizeof(str), fmtstr, args);
   stream->print(str);
   va_end( args );

   return num;
}

//*******************************************************************************_​**_********

Unexpected behaviour of print(char, HEX) and print(int, HEX)

char c = 255;
Serial.print(c, HEX);

produces

FFFFFFFF

This is due to the fact that print(char c, int base) convert char c (1 byte) into an unsigned long (4 bytes). As char is signed 255 is in fact -1(Two's complement), once written in 4 bytes it becomes FFFFFFFF. But as a user I would rather have FF than FFFFFFFF.

The problem exist with int (2 bytes) too

Here is a more complete example:

void setup() {
  Serial.begin(9600);
  int i = 1;
  Serial.print("i: ");
  Serial.print(i, 10);
  Serial.print(" | ");
  Serial.println(i, HEX);
  i = -1;
  Serial.print("i: ");
  Serial.print(i, 10);
  Serial.print(" | ");
  Serial.println(i, HEX);

  char c = 127;
  Serial.print("c: ");
  Serial.print(c, 10);
  Serial.print(" | ");
  Serial.println(c, HEX);
  c = 255;
  Serial.print("c: ");
  Serial.print(c, 10);
  Serial.print(" | ");
  Serial.println(c, HEX);
}

void loop() {}

output

i: 1 | 1
i: -1 | FFFFFFFF
c: 127 | 7F
c: -1 | FFFFFFFF

where I owuld rather have

i: 1 | 1
i: -1 | FFFF
c: 127 | 7F
c: -1 | FF

Suggest adding SPI_writeAnything to SPI library

I have the following small template library on my page about SPI ( http://www.gammon.com.au/spi ):

template <typename T> unsigned int SPI_writeAnything (const T& value)
  {
    const byte * p = (const byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          SPI.transfer(*p++);
    return i;
  }  // end of SPI_writeAnything

template <typename T> unsigned int SPI_readAnything(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          *p++ = SPI.transfer (0);
    return i;
  }  // end of SPI_readAnything


template <typename T> unsigned int SPI_readAnything_ISR(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    *p++ = SPDR;  // get first byte
    for (i = 1; i < sizeof value; i++)
          *p++ = SPI.transfer (0);
    return i;
  }  // end of SPI_readAnything_ISR  

The function SPI_readAnything_ISR is for using inside an ISR, as it directly accesses SPDR.

It has been suggested to me that I request that you include this in the standard SPI library (SPI.h). This lets you more easily send things like floats or structs via SPI. For example:

  float fnum = 42.666;
  digitalWrite(SS, LOW);  
  SPI_writeAnything (fnum);
  digitalWrite(SS, HIGH);

Being a template function it won't add any bloat unless you actually use it.

Related request: https://github.com/arduino/Arduino/issues/3691

HardwareSerial::write(long/int) is incorrect/dangerous!

any value above 255 will just be cut off -

inline size_t write(unsigned long n) { return write((uint8_t)n); }
inline size_t write(long n) { return write((uint8_t)n); }
inline size_t write(unsigned int n) { return write((uint8_t)n); }
inline size_t write(int n) { return write((uint8_t)n); }

please remove or fix the incorrect implementations!

Add (nonblocking) read(buf, len) to Stream class

Currently, the Stream class only has a (virtual) read() method to read one character at a time. It does have a readBytes() method to read multiple bytes at a time, but hat one blocks (with a timeout) and is not virtual, so it resorts to single-character reads.

It would be good to have a virtual multiple-byte reading method, which allows:

  • Callers to easily read multiple bytes into a buffer
  • Stream implementations to do efficient multiple-byte reads (e.g. prevent one SPI transfer per byte)

The Client class already has exactly this method, probably for the above reasons. Adding a virtual version of it to Stream means that Client implementations will support it out of the box.

We can also add a default implementation to the Stream class (using the existing read() method), that should keep all existing Stream implementations working. The default implementation would be something like:

Something like this (untested):

int read(uint8_t *buf, size_t size) {
    if (!available())
        return -1;
    int res = 0;
    while((int c = read()) >= 0 && size--)
        buf[res] = c;
    return res;
}

Note that this has a slightly peculiar return value: it returns -1 when
there is no data, to match the (Ethernet)Client implementation (which
returns 0 when the connection is closed). I guess it would make sense
swapping these, but that would break backward compatibility for the
Ethernet and (to a lesser degree, see arduino/Arduino#2251) the Wifi library.

How does all this sound?

BLE central API

Based on the outcome of the API meeting, I've added a first draft of a BLE central API in the api/BLE/central folder.

It's probably best to review the examples in the following order:

Other item's to discuss:

  1. Are there too many API's to access attributes of a peripheral? I've added a few to cater for various use cases, however I understand this might make documentation more difficult.
  2. Is there a nicer way to handle reading and writing attributes with values (characteristics and descriptors). See BLERemotePeripheralAttributeWithValue.h. Maybe we can re-use the UDP style, with beginWrite, Print API's, and endWrite.
  3. Class names, they are long now, mostly to avoid clashes with the BLEPeripheral API. In case there are use cases for using both peripheral and central mode at the same time in the future.

cc/ @tigoe @damellis @cmaglie @agdl

Add API to advance millis() and micros()

When an AVR MCU sleeps in power-down mode, it's clock stops running. Typically time is being kept using the watchdog timer, or an asynchronous timer2, to allow waking up after a specified time. However, the millis() and micros() counters are not updated during sleep, meaning that the sketch needs to jump through hoops (manually offsetting these counters, or modifying Arduino's global variables) to make various timing work. The former only works with sketch code, not libraries that rely on both counters, and the latter is obviously very ugly and non-portable.

Ideally, there would be an API that allows modifying the millis() and micros() timers by adding (or perhaps also subtracting?) a specified time from both. Most obvious would be an int32_t specifying the number of microseconds. This allows offsetting the time by about 35 minutes in one call. Alternatively, specifying both millis and micros separately would increase the range, but also complicate the code a bit (needing actual division instead of just bitshifting, I think). In either case, I'd say that both counters are always updated at the same time and stay in sync, not being updated individually.

map() function equation wrong

EDIT NOTE: I added a comment to the end of this from a later comment because I thought it should have been included in the first place.

The equation in the function stated at http://arduino.cc/en/Reference/Map

long map(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;
}

is wrong. The example given:

val = map(val, 0, 1023, 0, 255);

In this example 0-1023 is mapped to 0-255. The equation gets it wrong by mapping 1023 numbers to 255 numbers, when it should be mapping 1024 numbers to 256 numbers.

0 through 1023 is 1024 numbers not 1023 : in_max - in_min : 1023-0=1023
0 through 255 is 256 numbers not 255 : out_max - out_min : 255-0=255

The corrected equation in the function should be:

long map(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;
}

In the following simpler example it will be easier to see:

val = map(val, 0, 3, 0, 1);

In this example 0,1,2 and 3 is mapped to 0 and 1. Mapped correctly it should be:

0 maps to 0
1 maps to 0
2 maps to 1
3 maps to 1

Using the equation in the the function as it is now, it is mapped as such:

0 maps to 0
1 maps to 0
2 maps to 0
3 maps to 1

This is a common problem programmers have dealt with before. When dealing with arrays you can not determine array size by simply subtracting first position from last position you will always be off by 1. That is why you add 1 to get proper size. I know this is for the most part a minor problem, but if your project requires accurate results this could be a serious issue.

--- Added from later comment---

To give a real world scenario as to why this needs changed consider this. You are using the arduino with a sensor to sample data and based on this data set a servo into 1 of 4 positions. The arduino uses a 10 bit adc and outputs integers from 0 to 1023. You would use map(x, 0, 1023, 1, 4). With the map function as it is currently the only time position 4 would be active is when the arduino outputs the integer 1023. With my proposed change each position would get an equal share of the possible range. When they converted this function from a float function to an integer function they didn't consider that the output is no longer a value but a position. Value mapping maps one value to another and the function works perfectly for floats. Positional mapping distributes the input as evenly as possible to the output and the function as is doesn't do that.

This function needs to be split into two functions. One for floats as it is now and one for integers as I proposed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.