Comments (6)
Hi @wlwatkins,
I'm trying to port the firmata firmware in rust, more as an exercise to learn arduino coding than anything else.
The specific challenge that you chose proves to be have some unique difficulties with the current API of avr-hal
, as you have encountered :)
The problem lies in the fact that the API is mostly geared towards static use where pins are given predefined functions at compile-time and not dynamically, at runtime. You, however, need to do the latter here. So let's see what we can do. I'll begin by sketching the current situation:
In static world, a pin is represented as Pin<MODE, PIN>
where MODE
is the chosen pin function and PIN
is a specific pin. For example, a concrete pin type might be Pin<Output, PC1>
. Note that an object of this type can only represent this one specific pin in this specific mode. The next pin object would have a different type. For example, Pin<Output, PC2>
. This allows for crazy optimizations, but of course is not dynamic at all.
So to cater dynamic usecases, at least to some degree, you can call the .downgrade()
method. Calling that method on a pin object yields an object of a pin-generic type. In practice:
Pin<Output, PC1>::downgrade() -> Pin<Output, Dynamic>
Pin<Output, PC2>::downgrade() -> Pin<Output, Dynamic>
Pin<Output, PC3>::downgrade() -> Pin<Output, Dynamic>
// etc.
This means you can now dynamically handle any pin, as long as it is in the same mode. For example, you could put them all into an array:
let outputs = [
pins.d0.into_output().downgrade(),
pins.d1.into_output().downgrade(),
pins.d2.into_output().downgrade(),
pins.d3.into_output().downgrade(),
];
This gets us a step closer to your original question about pin numbers. But first, I have to tell you that we actually don't really know about the pin numbers at the moment. They only exist from the name of the fields in the Pins
struct. But using an array like the one shown above, you can now index into it using pin numbers:
let pin_number = 3;
outputs[pin_number].set_high();
The remaining problem is one of handling different modes. This is where things get a bit tricky. There is no dynamic downgrade for the mode, like there is for the concrete pin. An alternative might be to define an enum which can hold the different pin modes:
use arduino_hal::port::{self, mode};
enum IoPin {
Input(port::Pin<mode::Input<mode::AnyInput>>),
Output(port::Pin<mode::Output>),
}
let pins: [IoPin; 4] = [
IoPin::Input(pins.d0.downgrade().forget_imode()),
IoPin::Input(pins.d1.downgrade().forget_imode()),
IoPin::Input(pins.d2.downgrade().forget_imode()),
IoPin::Input(pins.d3.downgrade().forget_imode()),
];
This should allow you to dynamically handle pins in either input or output mode. Let me know if this helps or if you have any questions...
Writing all this out makes me thing what we could add to the pins abstraction to make this easier. Maybe the HAL should already provide a way to get a fully downgraded array of all pins for users who need it. But I am not sure what such an API should look like...
from avr-hal.
Regarding the modification of the Hal, my understanding is that is we want to shift the industry into using rust for embedded, wouldn't we need the same features to be available?
For the majority of usecases you don't need dynamic pin configuration which is why everyone is focusing on the static pin API. It just allows catching a large number of potential bugs at compiletime which dynamic config cannot.
I agree that it would be nice to also provide a fully dynamic API, but it's just not as important for most users.
from avr-hal.
from avr-hal.
from avr-hal.
For me here are X and Y
X = Learn how to do embedded programming in rust
Y = Port Firmata in rust
I'm trying to port the firmata firmware in rust, more as an exercise to learn arduino coding than anything else.
- User wants to do X.
- User doesn't know how to do X, but thinks they can fumble their way to a solution if they can just manage to do Y.
- User doesn't know how to do Y either.
- User asks for help with Y.
- Others try to help user with Y, but are confused because Y seems like a strange problem to want to solve.
- After much interaction and wasted time, it finally becomes clear that the user really wants help with X, and that Y wasn't even a suitable solution for X.
from avr-hal.
Hi, thanks for the comprehensive explanation. I was thinking about reimplementing some kid of struct to store each pin, which can later access the avr_hal API to work with it. But your approach is indeed interesting, and I appreciate the time you've put in the explanation.
Regarding the modification of the Hal, my understanding is that is we want to shift the industry into using rust for embedded, wouldn't we need the same features to be available?
Anyway, I'll try this out thanks
thanks
from avr-hal.
Related Issues (20)
- Panic while trying to write to serial using `ufmt::uwriteln` HOT 4
- Add configurable board options to ravedude HOT 3
- Program freezes if compiled in debug mode.
- ravedude should check rust target against selected MCU HOT 3
- Document clock type design in more detail HOT 1
- cargo build - error[E0658] - proc_macro::Literal::byte_character(byte) HOT 9
- can't find crate for `core` HOT 12
- cargo build - error[E0658] - proc_macro::Literal::byte_character(byte) HOT 4
- Very weird error when compiling a very basic program: __addsf3 multiple defenitions HOT 8
- Ravedude freezes on programmer uploading HOT 5
- Arduino Nano: avrdude error: programmer is not responding HOT 11
- Watchdog intterupt mode HOT 1
- [Solved] Cannot find `pwm` in `embedded_hal` HOT 2
- peripherals type alias HOT 2
- Enhance `avr_hal_generic::renamed_pins! {}` to also generate type aliases for each pin
- tier 3 target and broken
- Utilising the `atmega2560`'s "USART in SPI Mode" HOT 10
- Issue with math calculations with floats to serial port output HOT 4
- Incorrect ADC readings after toolchain bump HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from avr-hal.