Skip to content
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

Implement tri-state DIO #45

Open
auscompgeek opened this issue Apr 13, 2019 · 5 comments · May be fixed by #72
Open

Implement tri-state DIO #45

auscompgeek opened this issue Apr 13, 2019 · 5 comments · May be fixed by #72
Assignees
Labels
enhancement New feature or request

Comments

@auscompgeek
Copy link
Member

See wpilibsuite/allwpilib#606 and wpilibsuite/allwpilib@7eab437.

How might the Rust API look? The dio module will need a refactor, but https://docs.rust-embedded.org/book/static-guarantees/state-machines.html has some nice ideas.

@Lytigas
Copy link
Collaborator

Lytigas commented Apr 16, 2019

To clarify my understanding, this will enable more "dynamic" switching of a DIO from input to output, right? The states are then: Input (pulled high), Output (high), and Output (low).

My guess is that when this lands in WPILibC it will show up as a separate class, or perhaps deprecate the old DIO classes. We could take the same approach, which is usually what I'd be inclined to do.

However, if there's no reason not to, I would say something like this could work:

struct DioInternal {
//...
}

struct DigitalOutput(DioInternal);
impl DigitalOutput {
  pub fn set(val: HighOrLowEnumType) -> HalResult<()>;
}

struct DigitalInput(DioInternal);
impl DigitalInput {
  pub fn get() -> HalResult<bool>;
}

impl From<DigitalInput> for DigitalOutput {
//...
}
impl From<DigitalOutput> for DigitalInput {
//...
}

I'm not sure we need anything fancier than that; the state machine is fully connected. This also has the benefit that if your DigitalOutput is still within its lifetime, you can be sure your PWM output hasn't suddenly become an input. Of course, there are a ton of situations where that guarantee disappears, though.

@auscompgeek
Copy link
Member Author

My concern there would be that you would be duplicating a lot of the impls between the input and output types (e.g. get is implemented exactly the same way in DigitalInput and DigitalOutput, which would also be worth refactoring). The From impls would also cause the Drop impls to execute.

@Lytigas
Copy link
Collaborator

Lytigas commented Apr 25, 2019

I didn't think about Drop, that's true. We'd have to reallocate the resource with the HAL too, which adds overhead.

If we want to avoid Drop running, we need to make sure the two are the same type then. I see two options then:

  1. opaquely switch based on the Users last called function.
  2. have all methods on the same struct, but they error unless a transform_to_input or something was called.

@auscompgeek
Copy link
Member Author

Thinking a bit more, perhaps your suggested approach is the way to go with the internal struct.

Always exposing the input and output methods will probably be confusing for users.

@auscompgeek
Copy link
Member Author

I just realised we don't need an internal struct - std::men::forget is our friend here.

@auscompgeek auscompgeek linked a pull request Jul 17, 2019 that will close this issue
@auscompgeek auscompgeek self-assigned this Nov 11, 2019
@auscompgeek auscompgeek added the enhancement New feature or request label Nov 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants