Skip to content

Virtual Pins #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
neu-rah opened this issue Oct 11, 2017 · 10 comments
Open

Virtual Pins #1

neu-rah opened this issue Oct 11, 2017 · 10 comments

Comments

@neu-rah
Copy link

neu-rah commented Oct 11, 2017

Virtualization of pins, allowing the environment to be extended with external pin over SPI or I²C and making them transparent to user and libraries.

This can be implemented on multiple ways:

1 - Add an extra burden to the pinMode/digitalRead/digital by installing an
if (pin>nr_of_digital_pins) «call virtual pins handler here»

2 - Extend the pin tables with a predefined set of allowed extra virtual pins, then the actual if (port == NOT_A_PIN) already present on the pin functions could be used to call the virtual pins handler with no extra burden to pin functions.

about the virtual pins handler, i sugest it to be just a function address (x3) pointing to a dumb function (just return).

this way virtual pins would have only the extra 3 function pointers and a simple return function allowing it to be implemented as a library

also all this can be conditionally compiled... if there's a way of introducing preprocessor defines to the compiler environment (-D parameter), last time i checked there was not an easy way of doing it on arduino IDE.

option 2 has the advantage of being compatible with code that checks the pin tables https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/Arduino.h#L177

I leave this to consideration and expect feedback of pros and cons before advancing.

I've done essays by extending the pin tables and they worked very well.

thanks

@mjbcopland
Copy link

mjbcopland commented Oct 12, 2017

Assuming I understand you correctly, this is pretty easy to do by overloading the pin manipulation functions. Here's a library I've put together which provides a wrapper around I/O member functions.

For example, SparkFun has a library for the SX1509 I/O expander used with something like io.digitalWrite(0, HIGH). My library provides a wrapper around the SparkFun class and allows for the syntax digitalWrite(io[0], HIGH) by overloading the global function with virtual pin objects. Is this the sort of thing you were thinking of?

Perhaps compare SparkFun's example with my virtual pin adaptation.

@neu-rah
Copy link
Author

neu-rah commented Oct 12, 2017

kind of, but doing this way does not help libraries and either virtual pins can not be passed to third party library object construction, thinking in the standard LiquidCrystal

with virtual pins embedded we can initialize the standard LCD with the virtual pins and therefor (with the appropriate virtual pins SPI drivers) use the same library over an SPI interface

that lib had no need to be changed to support SPI or I²C or whatever bus we want to support

@mjbcopland
Copy link

Ah, I see what you mean now. Something like this? It treats negative pin numbers as being virtual, and functions are 'attached' to pins in the same way that attachInterrupt() works.

There's currently no bounds checking (but the existing I/O functions don't do this either), no analogRead/Write (although that could be easily added in the same way), and is a bit tedious having to individually define multiple function pointers per pin, but I feel it otherwise comes pretty close to your original idea.

An example sketch could look something like this

VirtualPin pin = {
  [](uint8_t mode){ Serial.print("pinMode "); Serial.println(mode); },
  [](uint8_t val){ Serial.print("digitalWrite "); Serial.println(val); },
  [](){ Serial.println("digitalRead"); return -1; },
};

void setup() {
  Serial.begin(115200);
  attachVirtualPin(-1, &pin);
  pinMode(-1, OUTPUT);
}

void loop() {
  digitalWrite(-1, HIGH);
  delay(1000);
  digitalWrite(-1, LOW);
  delay(1000);
}

It could be cleaned up with polymorphism similar to my template approach from above, but that requires migrating the existing functions from C to C++ (not too difficult, but a larger change to the repository). Parts of STL's <functional> could also make things easier, but that's substantially more work to port to AVR.

My only concern is that I've seen -1 sometimes used to represent a null pin. Perhaps virtual pins should start at -2? This could get rather messy.

I'm not sure how useful this would be to the average user, but wrapping the changes in a preprocessor macro like you've suggested could be a simple solution.

As an aside, you can add extra command line arguments to platform.local.txt. It's a little tedious as the file is tucked away in the platform directory and any changes will affect every sketch, but afaik it's the easiest way to modify the build environment.

@neu-rah
Copy link
Author

neu-rah commented Oct 13, 2017

very interesting, I was thinking on the possibility of using negative pin numbers to express inverted logic, but that would require as you told some burden to the actual pin functions, and I understand its key and sensitive area.

The negative pins schema would involve an extra if there, and that can be shared to implement vpins. So there's a point in favor of an extra if added to the fact that no table extension had to be done, saving FLASH memory.

I would like pin 0 to mean "not used" and therefor ignored, but its unfortunate it is already taken.

@neu-rah
Copy link
Author

neu-rah commented Oct 13, 2017

I've also done a little survey over my local libraries to have an idea how many and what type of library does use pin tables (like digitalPinToPort), it happens to be on some very specialized graphics library like U8g2, and I guess that libraries like that wont be suitable for use over vpins.

So, not extending the pin tables will leave outside those kind of libraries, but be usable for simper ones like the LCD and for the user.

SPI shift registers were working very well doing both input and output and are transparent to the user, installing a button there or blinking a led are the exact same as for local pins. Apart the vpins initialization describing the geometry.

@per1234
Copy link
Contributor

per1234 commented Oct 13, 2017

Previously proposed at https://github.com/arduino/Arduino/issues/6175

@neu-rah
Copy link
Author

neu-rah commented Oct 13, 2017

thanks for linking it, the previous was on the bundle, now we have the avr-core separated and a much better discussion space.

@neu-rah
Copy link
Author

neu-rah commented Oct 16, 2017

also this on pin functions:

	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	volatile uint8_t *reg, *out;

	if (port == NOT_A_PIN) return;

can't it be replaced by:

	uint8_t port = digitalPinToPort(pin);
	if (port == NOT_A_PIN) return;
	uint8_t bit = digitalPinToBitMask(pin);
	volatile uint8_t *reg, *out;

avoiding one index to determine bit?

@neu-rah
Copy link
Author

neu-rah commented Oct 20, 2017

I can see that no checking against NUM_DIGITAL_PINS is currently done by the pin functions and therefor an arbitrary pin number can be successfully compiled and uploaded. Guess this was done to reduce the footprint of pin functions.
Therefor adding a check can be against the arduino team philosophy and interests, even if having the benefits of preventing erratic behavior.
It would be nice if we can have an official position on this (anyone?)

neu-rah added a commit to neu-rah/ArduinoCore-avr that referenced this issue Oct 20, 2017
arduino#1

defining alternative pin handling functions and respective triggers
installed into pin functions

all changes wraped by #defines

alternative handlers require compilation with VIRTUAL_PINS defined

digital pin functions triggers require both VIRTUAL_PINS and
VPINS_TRIGGER defined

eventually we can extend pin tables instead of installing the triggers
@neu-rah
Copy link
Author

neu-rah commented Oct 28, 2017

This schema would also allow all sort of software modified pins, in ex: providing a virtual pin that is a software debounced version of a physical pin, allowing software debounce to be composed a posterior and provided to libraries when needed.

facchinm pushed a commit that referenced this issue Oct 19, 2018
* fixed typos in UART
facchinm pushed a commit that referenced this issue Oct 19, 2018
Added ignore of directory "api" which is a link to another repo. View…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants