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

Many edge detection "interrupts" but level remains the same #149

Closed
andrewdavidmackenzie opened this issue Jun 20, 2024 · 46 comments
Closed

Comments

@andrewdavidmackenzie
Copy link

I was debugging some weirdness in my app ("piggui") and added some logging (println!()) to when it detects edges on inputs.

input.set_async_interrupt(Trigger::Both, move |level| {
                        callback(bcm_pin_number, level == Level::High)
                    })

I'm using it with a pretty crappy button, that I imagine it has quite a bit of HW bounce in it.
So I imagined a flurry of high/low/high/low level changes in short succession.

When testing however:

  • Sometimes it works "cleanly".
  • Other times I get a bunch of level changes that report the same level, something like:
  • low
  • low
  • high
  • 25 lows in succession
  • high
    etc.

So, while I expected "bounce" I didn't expect the interrupt to report multiple level changes in short succession with the same level being reported twice in a row.

  • Is that related to how the HW works (e.g. HW detects an edge, and by the time the level is read, it's back to where it was?)?
  • Is there anything that should be done in rppal about that?
  • Or should I just implement my own filter to detect edges in the reported level?

Thanks for clarifying what best to do.

@andrewdavidmackenzie
Copy link
Author

When trying to cache the previous level detected in my own code, then only report changes up the chain, I have ran into difficulties due to the 'static bound on the FnMut that is passed to set_async_interrupt... I will keep trying though.

@andrewdavidmackenzie
Copy link
Author

andrewdavidmackenzie commented Jun 20, 2024

I see this code in interrupt.rs:

else if fd == interrupt.fd() {
                            let level = interrupt.event()?.level();
                            callback(level);
                        }

Since that is sitting in a thread in a loop, per pin, would you accept a PR to filter out interrupts when the level has not actually changed?

I would read the initial level before entering the loop, then compare always to previous and only call callback if level changed, and update previous.

@golemparts
Copy link
Owner

It has been several years since I last looked into this issue, so it's nice to have some fresh eyes on it.

While it's certainly possible RPPAL is handling something incorrectly, my conclusion at the time was that this is a limitation of the underlying linux drivers, with triggered events getting lost when too many occur within a short period of time, likely because the interrupt handler is still running when the interrupt gets triggered again. A switch getting pressed would definitely cause a large amount of events, and would require some debouncing.

Since that is sitting in a thread in a loop, per pin, would you accept a PR to filter out interrupts when the level has not actually changed?

I would read the initial level before entering the loop, then compare always to previous and only call callback if level changed, and update previous.

The problem with that approach is that we're hiding interrupt events. The level has changed. It's just that the Low between the two Highs didn't get reported, or vice versa. I think a better approach would be to assume an event was lost, and add one in between, but I'm not sure if I'm comfortable manufacturing events instead of just reporting the data we get from the drivers. Perhaps we just need better documentation to make it clear this can happen under certain circumstances, and let the end-user (in this case piggui) decide how best to handle it.

@andrewdavidmackenzie
Copy link
Author

Understood.
Do you think it also happens if you use only Rising, or only Falling edges?

Maybe there are bugs in the linux drivers, but that's getting a bit beyond my "expertise"... is there somewhere upstream for the drivers I could ask?

@golemparts
Copy link
Owner

It's a little beyond my expertise as well, as for anything other than direct GPIO register reads/writes I'm relying on linux drivers. Unfortunately I currently don't have enough time to invest in some dedicated testing to figure out under what circumstances interrupts are lost. If the cause is indeed too many interrupts within a short period of time, it would also happen for only rising or only falling edges.

My guess would be these aren't bugs, but limitations of handling interrupts in linux. I would check the official Raspberry Pi forums first, as any Python library that works with interrupts in a similar way as RPPAL does would run into the same issue.

@andrewdavidmackenzie
Copy link
Author

I posted here on Raspberry Pi forum.

@andrewdavidmackenzie
Copy link
Author

It would be good to get to the bottom of this, and if at all possible NOT loose edges...

But, meantime, FWIW I would have rrpal respect the "contract" with its users, to inform (only?) ok of level changes on an input....hence if the event from the Linux driver reads the same level as before I would not call the callback.

@golemparts
Copy link
Owner

But, meantime, FWIW I would have rrpal respect the "contract" with its users, to inform (only?) ok of level changes on an input....hence if the event from the Linux driver reads the same level as before I would not call the callback.

I appreciate the feedback, but like I mentioned before, barring any bugs in RPPAL or the drivers, a level change did happen. Not calling the callback means that we'd be hiding events, which I don't think is the correct behavior here. We're getting the same level multiple times in a row because one or multiple interrupt triggers were not reported by the underlying drivers. If the cause is a timing issue, we would be exacerbating the problem by skipping even more events.

There is an argument to be made for inserting a callback for the missing level change, but in the end RPPAL is just an interface library that makes it easier to access the various peripherals, and not a way to correct the data as reported by the system. I do need to add this to the documentation.

For piggui the situation is different, as it's an application for end-users to interact with and report the status of the GPIO pins. I would probably insert the missing interrupt trigger for the most accurate reporting, but it's of course up to you if you think filtering out the events is the better choice.

@andrewdavidmackenzie
Copy link
Author

Fair enough.

I guess it comes down to the definition of "event" for the user of rrpal.

For me a level change event, should show a change in level.

Two level changes that in fact both report the same level, is kind of a non-event in my book. :-)

@robsdedude
Copy link

I came across the same issue yesterday. Getting many events in short succession (even with the same state) wasn't a big deal as debouncing it is common practice. The bigger issue though was that the last event of the sequence was not always the expected level. E.g., when pulling the pin from high to low, after some bounces, the last event was sometimes reporting high.

Imo, this makes this API somewhat pointless. The only thing the interrupt could be used for then is to be notified that something change so that you can go and actively read the pin after some silence period but the level passed to the interrupt is not usable at all.

@golemparts
Copy link
Owner

golemparts commented Jun 25, 2024

Imo, this makes this API somewhat pointless. The only thing the interrupt could be used for then is to be notified that something change so that you can go and actively read the pin after some silence period but the level passed to the interrupt is not usable at all.

I haven't noticed issues when detecting changes for both rising and falling edges on the same GPIO pin at reasonable speeds. It seems to skip events when the interrupt is triggered in rapid succession, like when pressing a switch. The documentation needs to make this clear. The way I would interpret the event is "a rising or falling edge was detected, this is the current pin level", with the logical conclusion that the level had an opposite value before that.

If you want better performance, you would have to bypass the linux drivers or just go bare metal entirely. This isn't a limitation of RPPAL but of the underlying drivers, and while I could insert or hide events to make the output make more sense, I think it's more appropriate for the end-user to decide what to do in that situation.

@andrewdavidmackenzie
Copy link
Author

Piggy-backing on this issue thread, to mention that we've done a new release of the "piggui" GUI for controling and viewing GPIO hardware on a Raspberry Pi, using rppal.

You can find the release notes with videos and more gifs here

As a teaser, here is a YouTube video showing the LED and waveform display of an input, connected to a real hardware button.

If you have ideas for future functionality, please contribute issues or start a discussion

@golemparts
Copy link
Owner

golemparts commented Jun 25, 2024

As a side note, I started working on transitioning to the GPIO v2 API (here) back when it wasn't certain the Pi 5 would still give us direct GPIO register access, but never completed the transition when it was clear we could use /dev/gpiomem0 instead. The GPIO API, currently v1, is used for interrupt detection. The v2 documentation mentions this regarding missing events:

The size of the kernel event buffer is fixed at the time of line request creation, and can be influenced by the request.event_buffer_size. The default size is 16 times the number of lines requested.

The buffer may overflow if bursts of events occur quicker than they are read by userspace. If an overflow occurs then the oldest buffered event is discarded. Overflow can be detected from userspace by monitoring the event sequence numbers.

So while this doesn't solve the issue, once I get around to moving the interrupt handling to the v2 API, which adds those event sequence numbers, at least I can detect when an event has been skipped, and possibly add that info to the callback.

EDIT: Theoretically I could make the buffer as large as possible to limit how often it overflows if that's what's causing the missing events. It wouldn't solve the issue, just delay it, but it's something.

@andrewdavidmackenzie
Copy link
Author

Thanks for pursuing this.

When I observed this (using println in my code), I saw repeated levels in events, very quickly.... i.e. it was only one or two events (the initial "down" on a button and maybe a bounce) before I observed a stream of 23 events, all with the same level.... so it didn't appear at first blushes like a buffer overrun of events (unless a buffer size of 1 or 2). FYI.

@golemparts
Copy link
Owner

I'm not sure what the buffer size is for the v1 API, or if it even buffers events at all, as the request.event_buffer_size value is only part of the v2 API, so a buffer size of 1 or 2 could be possible. At least with v2 we should have a clearer picture of what's happening, even if there is no real solution.

The only mention I found of a bug was regarding a race condition with interrupts on multiple GPIO pins, but I assume you weren't testing this on multiple pins at the same time.

@golemparts
Copy link
Owner

Since I'm adding the event sequence number to the callback, I might as well add the timestamp at the same time (best estimate of time of event occurrence, in nanoseconds, provided by the GPIO v2 API), which can be helpful to detect how much time has passed between two trigger events.

@warthog618
Copy link

I'm not sure what the buffer size is for the v1 API, or if it even buffers events at all, as the request.event_buffer_size value is only part of the v2 API, so a buffer size of 1 or 2 could be possible. At least with v2 we should have a clearer picture of what's happening, even if there is no real solution.

v1 documentation. The buffer is fixed at 16. And if the buffer overflows the most recent event is discarded, which is really unfortunate for userspace debounce algorithms or anything interested in the final state. So for v1 you really don't want that buffer to overflow.

v2 has debounce support, and that is applied before the event buffer. That is probably what you want if you are dealing with noisy hardware.

Even v2 doesn't help with interrupts occurring faster then the kernel can handle them though. Those get lost with no indication, as they are too fast for the kernel to see.

Can't say I'm a fan of mixing direct register access with using a Linux driver. You have no protection against contention so you might get some entertaining interactions and those would be a serious pain to debug.

@andrewdavidmackenzie
Copy link
Author

" I assume you weren't testing this on multiple pins at the same time."

No, just one input connected to a button.
(you can see me using it in this video https://youtu.be/YZMhHqfmcx4 - but it doesn't show the trace of events....I could do that for you if needed)

" I might as well add the timestamp at the same time (best estimate of time of event occurrence, in nanoseconds, provided by the GPIO v2 API), which can be helpful to detect how much time has passed between two trigger events."

Yes, I add one later as soon as I receive the event, so one closer to the real time would be appreciated.
I end up converting to a DateTime in chrono for displaying them on the moving waveform shart.

"And if the buffer overflows the most recent event is discarded"

That is a strange choice....getting the last event and the last known level would seem a better choice to me.

"v2 has debounce support, and that is applied before the event buffer. That is probably what you want if you are dealing with noisy hardware."

That sounbds positive.

"Even v2 doesn't help with interrupts occurring faster then the kernel can handle them though. Those get lost with no indication, as they are too fast for the kernel to see."

Off course, there is a limit to what the kernel can handle, always possible to be too quick for it.

@warthog618
Copy link

"And if the buffer overflows the most recent event is discarded"

That is a strange choice....getting the last event and the last known level would seem a better choice to me.

Which is exactly why it was changed in v2. Not sure why v1 was that way - it was probably just easier and simpler and no one thought too hard about the implications. Discarding the oldest is more work given the way kernel FIFOs operate, but it is well worth the effort.

@andrewdavidmackenzie
Copy link
Author

A contributor passed this to me:

libgpiod is the standard library for driving GPIOs via the GPIO character device, /dev/gpiochipN, which is the standard GPIO userspace interface for Linux.
That interface is the only one that works on all Pi variants. Other libraries that use the obsolete sysfs interface or the /dev/gpiomem interface will not work on the Pi5.

Have you tried rppal on a Pi5?

@golemparts
Copy link
Owner

v1 documentation. The buffer is fixed at 16. And if the buffer overflows the most recent event is discarded, which is really unfortunate for userspace debounce algorithms or anything interested in the final state. So for v1 you really don't want that buffer to overflow.

Thanks for the insight. That explains a lot, and adds even more incentive to upgrade to v2.

Can't say I'm a fan of mixing direct register access with using a Linux driver. You have no protection against contention so you might get some entertaining interactions and those would be a serious pain to debug.

I would love to use the GPIO API for everything, but it has some limitations (in both v1 and v2) related to alternate function modes that makes it incompatible with part of RPPAL's feature set. It's something I'll be re-evaluating after the transition to v2, and limit direct register access only to functionality the API doesn't provide.

@golemparts
Copy link
Owner

A contributor passed this to me:

libgpiod is the standard library for driving GPIOs via the GPIO character device, /dev/gpiochipN, which is the standard GPIO userspace interface for Linux.
That interface is the only one that works on all Pi variants. Other libraries that use the obsolete sysfs interface or the /dev/gpiomem interface will not work on the Pi5.

Have you tried rppal on a Pi5?

RPPAL is compatible with the Pi 5. We moved away from using sysfs a long time ago, and the Pi 5 provides direct GPIO register access on the RP1 through /dev/gpiomem0. See #127 for development details of the initial Pi 5 support.

@warthog618
Copy link

I would love to use the GPIO API for everything, but it has some limitations (in both v1 and v2) related to alternate function modes that makes it incompatible with part of RPPAL's feature set. It's something I'll be re-evaluating after the transition to v2, and limit direct register access only to functionality the API doesn't provide.

Yeah, the GPIO character device is strictly a GPIO API. Call that a limitation if you like. There are other Linux subsystems and APIs for other pin functions. Switching pins between modes is very platform dependent and typically done with device-tree or some other API.

@golemparts
Copy link
Owner

Quick update on this issue. I've completed the transition to the v2 API for interrupts, and will merge the changes to master when I've had a chance for some hardware testing. The main change for RPPAL users is that all synchronous/asynchronous interrupt trigger functions/callbacks now return an Event struct:

pub struct Event {
    /// Best estimate of time of event occurrence.
    pub timestamp: SystemTime,
    /// Sequence number for this event in the sequence of interrupt trigger events for this pin.
    pub seqno: u32,
    /// Pin level that triggered the interrupt.
    pub level: Level,
}

I'll probably replace level with trigger to make it more obvious the level should be read separately, since it could have changed after the interrupt was triggered. event_buffer_size is set to 1024 for now, but I might change the value or make it configurable based on further testing.

@andrewdavidmackenzie
Copy link
Author

FYI. We have just released "pigg" 0.3.3 and now I will tackle updating to the new API for 0.4!

I was holding off on major API changes until I got this out the door.

====

"pigg" (GUI for Raspberry Pi GPIO interaction using Iced) v0.3 is out and ready for use

Release notes: https://github.com/andrewdavidmackenzie ... /tag/0.3.3

The main new feature is the addition of Remote GPIO interaction between "piggui" and a remote "piglet" over iroh-net.

Video with Dialog to connect: https://youtu.be/aToJ1aT7NeM

Video using CLI argument to connect: https://youtu.be/zcEa_Oke014

@andrewdavidmackenzie
Copy link
Author

I see last release was on May 18th, before these changes right?

I'm ready to migrate to try this new code for our app.

Are you planning to do a release with it?

Should I give it a try using HEAD of master in the meantime, or still subject to change?
(I would wait until a release is available to use in a release of ours)

Thanks

@golemparts
Copy link
Owner

I see last release was on May 18th, before these changes right?

I'm ready to migrate to try this new code for our app.

Are you planning to do a release with it?

Correct. The last release didn't have any of these changes yet. I've been a little swamped with other projects lately, which is why I haven't had a chance to get this completed. I'll try to make some time available this week to get the new API tested and merged in, after which I'll plan a release that includes them.

@golemparts
Copy link
Owner

golemparts commented Aug 8, 2024

@andrewdavidmackenzie the new changes are available on the master branch. I've also updated the dev documentation.

Both synchronous and asynchronous interrupts now use the v2 API internally. Interrupt handlers now get an Event struct instead of Level as mentioned above, but timestamp has been changed to a Duration as it specifies time elapsed since the system was booted, and level has been replaced by trigger.

The event buffer size has been set to 1024 by default, but some events are still skipped when the interrupt is triggered a lot. I didn't notice any gaps in the sequence numbers, so it seems they're not caught at all by the underlying drivers. However, I've added support for an optional debounce period, which eliminates the issue where it makes sense to use one, like with button presses.

I'll be cleaning up the code and documentation over the coming days, and will schedule a release for next week barring any serious issue.

@andrewdavidmackenzie
Copy link
Author

andrewdavidmackenzie commented Aug 8, 2024 via email

@golemparts
Copy link
Owner

I was passing on the timestamp to a remote node as a UTC time of when the event happened, so will see what changes that brings in with it.

Yeah, I originally intended to use SystemTime before I realized what the original value was based on. I considered converting it in RPPAL, but decided to leave that up to the user to avoid any unnecessary/double conversions if they're just using it to check elapsed time between events.

@andrewdavidmackenzie
Copy link
Author

andrewdavidmackenzie commented Aug 8, 2024 via email

@golemparts
Copy link
Owner

You get that from the driver you use, as opposed to using now() when you receive it?

Yep. Calculating the time based on when it's handled by RPPAL wouldn't be as accurate. You could use something like the sysinfo crate to get the Pi's boot time and calculate the timestamp in UTC.

@andrewdavidmackenzie
Copy link
Author

Is it safe to assume that only either Trigger::RisingEdge or Trigger::FallingEdge will ever be used in Event, as otherwise the level would be ambiguous (if Both were used)?

I'd prefer Trigger and Level being two separate types, but can work with it if that's a valid assumption.

Maybe add that to the doc comment for set_async_interrupt()?

@golemparts
Copy link
Owner

Is it safe to assume that only either Trigger::RisingEdge or Trigger::FallingEdge will ever be used in Event, as otherwise the level would be ambiguous (if Both were used)?

Correct, only one of those two values will ever be returned. I'll add a note to the documentation.

@andrewdavidmackenzie
Copy link
Author

OK, built using the new version from git.
Will be next week before I can test on Pi hw to see if any change and all OK.
I'll wait for you to produce a release from crates.io I can use, before merging my PR though.

Later I'll look into the debounce you added, not this first iteration.

Thanks!

@warthog618
Copy link

Yeah, I originally intended to use SystemTime before I realized what the original value was based on. I considered converting it in RPPAL, but decided to leave that up to the user to avoid any unnecessary/double conversions if they're just using it to check elapsed time between events.

There is the option in the v2 uAPI to select the source clock for edge events. It defaults to the MONOTONIC clock so differences between event times are always consistent. But you can select the REALTIME clock if that is what you would prefer. Just be aware that any corrections to system time will invalidate any calculations based on comparing timestamps. The event timestamp is captured by the kernel interrupt handler and so provides the closest possible time to the physical edge.

@golemparts
Copy link
Owner

There is the option in the v2 uAPI to select the source clock for edge events. It defaults to the MONOTONIC clock so differences between event times are always consistent.

Thanks for pointing that out. I forgot there was an option to set which clock to use. That said, I'll keep it on monotonic precisely for the reason you mentioned, allowing comparisons without having to worry about changes to the system time. Conversion can be done by the user if needed.

@golemparts
Copy link
Owner

Closing this as the original issue has been addressed as much as we can in the upcoming 0.19.0 release, scheduled for next week. Feel free to open a new issue for any new interrupt-related issues.

It's still possible to get the same event multiple times in a row, but based on the sequence numbers we're now adding to each event, these aren't caused by a buffer overflow as no events in the sequence are missing, which means these events are occurring faster than the kernel can handle them. To mitigate this, support for the v2 debounce feature has been added, filtering any input noise from buttons and similar components, which in my tests eliminated the double/missing events.

Thanks all for getting this figured out.

@andrewdavidmackenzie
Copy link
Author

Works perfectly for me and (subjectively) better than before I think.

I'll wait for you to do your 0.19.0 release before I merge my PR using it though, I prefer to not depend on the git version.

Thanks!

@andrewdavidmackenzie
Copy link
Author

andrewdavidmackenzie commented Sep 27, 2024

Commenting on this - as not sure the best way to reach out with a question:

I have updated to rppal v2 API.

I am displaying the values read/sent from an input pin in a moving time window graph, using the Event timestamp (a Duration).

Screenshot 2024-09-27 at 3 29 10 PM

At startup of my app, I want to start-up the graph with the current level, using InputPin::read().
To get the timing right (relative to future events yet to be sent via set_async_interrupt callback) I need to fabricate a timestamp for this that will match the time of the future events to be sent.

My first attempt was:

                let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();

But that didn't work, as timestamps are very different hence time (X) axis is out of whack.

Converting Duration to DateTime to display:
This is the one created with the code above:

set_level: DateTime = 2024-09-27 13:44:39.084842132 UTC

These are subsequent ones received via Event:

set_level: DateTime = 1970-01-06 18:35:19.894893768 UTC
set_level: DateTime = 1970-01-06 18:35:20.198849336 UTC

(I did a Pi reboot 6 days ago??)

I see your event is created thus:

pub(crate) fn into_event(self) -> Event {
        Event {
            timestamp: Duration::from_nanos(self.timestamp_ns),
            seqno: self.line_seqno,
            trigger: match self.id {
                LINE_EVENT_RISING_EDGE => Trigger::RisingEdge,
                _ => Trigger::FallingEdge,
            },
        }
    }

I believe you get that timestamp from the BCM hardware?

Do you know how (for the first "sample" I create manually) I can create a timestamp that will match the time period and scale of the future events sent, so it all works on a time graph?

@golemparts
Copy link
Owner

Do you know how (for the first "sample" I create manually) I can create a timestamp that will match the time period and scale of the future events sent, so it all works on a time graph?

The timestamp in the Event data uses a monotonic clock, so any time changes (like DST) won't affect it. I'm not sure if there's anything available in the standard library that will help you out. Instant uses a monotonic clock as well, but its inner structure is opaque and it serves a different purpose than Duration. Your best bet probably is to either grab a third-party crate, or call libc::clock_gettime directly to get the raw data yourself and convert that into a Duration.

let mut time = libc::timespec {
    tv_sec: 0,
    tv_nsec: 0,
};
let ret = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut time) };
let start = std::time::Duration::new(time.tv_sec as u64, time.tv_nsec as u32);

@andrewdavidmackenzie
Copy link
Author

I'll look into using that.

Thoughts on providing a mechanism in rrpal, to get a clock/Duration that corresponds to that uses in Events sent?

(I had thought on asking a timestamp alongside the value provided by read(), but that would be a breaking change and doubt a read_with_timestamp() would be a great addition....?)

@golemparts
Copy link
Owner

Thoughts on providing a mechanism in rrpal, to get a clock/Duration that corresponds to that uses in Events sent?

I'll have to give it some thought. Providing a monotonic clock version of Duration doesn't really fall within RPPAL's scope, but considering the standard library doesn't seem to provide anything helpful, it's something to consider at least. If I go that route I'd probably just add a Timestamp type that can be converted to Duration. For now, the above-mentioned solution should work for your situation.

@andrewdavidmackenzie
Copy link
Author

I'm told

"note that CLOCK_MONOTONIC does not count suspended time, while CLOCK_BOOTTIME does"

Probably not very important though

@golemparts
Copy link
Owner

Probably not very important though

You'll want to use the same clock as is used to calculate the timestamps. From a quick search it looks like it calls ktime_get_ns(), which is the same as ktime_get() and uses CLOCK_MONOTONIC.

@andrewdavidmackenzie
Copy link
Author

FYI - just to let you know I finally released 0.4.0 that updated to v2 API and uses hardware timestamps.

Thanks again


We have just published release 0.4.0
of pigg, your "No-Code" way to control Raspberry Pi GPIO hardware via
GUI locally (on a Pi) or remotely (on macos, linux or windows).

Install it (on your macos/linux/windows "host" and/or your Raspberry Pi) with:

  • cargo install pigg if you have a working rust toolchain
  • cargo binstall pigg to install pre-build binaries for your platform (you need cargo and cargo-binstall installed)
  • To install pre-build binaries via shell script: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/andrewdavidmackenzie/pigg/releases/download/0.4.0/pigg-installer.sh | sh
  • To install pre-build binaries via brew brew install andrewdavidmackenzie/pigg-tap/pigg

This release has been a long time coming due to Summer vacations, being busy in general, struggling to get GH Action for our release
to build for armv7 and aarch64 working correctly and quite a lot of work on a Raspberry Pi Pico port.

Notable features and changes in this release include:

  • Pre-built binaries for armv7 and aarch64 for different Raspberry Pi devices, easing the installation process for Pi users.
  • Updated to rppal (crate for interacting with GPIO on Raspberry Pi) v2, that among other things used a hardware timestamp
    on Input pin edge transitions detected, for more timing accuracy.
  • Added the ability for piggui (host GUI) to connect piglet (CLI, on Pi) via a TCP connection.
    Piglet will listen for connections via TCP or Iroh and accept the first to arrive, and when done, go back to listen for both again.
    Just supply the ip:port that piglet outputs to piggui, via the command line option or via the connect dialog.
  • A lot of code changes in preparation for Raspberry Pi Pico version ("porky"), including changes in serialization crate used for network connections
  • Prototype of the Raspberry Pi Pico implementation ("porky"). With this release done I will go back and finish that as part of
    the plan for 0.5.0

There are quite a few issues in that 0.5.0 Milestone that are related to small UI improvements, code improvements or the Pico port and allow me to continue to learn new aspects of rust.
But the plan can change if we get user adoption and input, so please drop a message here if you are using pigg, or would like any particular enhancement, new feature or bug fixed.

See the Release 0.4.0 Discussion topic on pigg's GitHub Discussions, where there are more details on the changes made

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants