About "Moving" question

The new bin actually seems to make it easier to get the dpad into the state where the button is held but not registered.

Rather than just trying to explain, I’ll provide a video that hopefully makes it clear…

Seems I was ninja’d by @79859899, whose video demonstrates exactly what I’m talking about.

I’ll post mine anyway:

ButtonStick.zip (1.5 MB)

Sorry it’s not brilliant, but my camera is old and I had to balance it between my knees because I don’t have a tripod and it won’t stand up on its own.

(It’s a .webm in a .zip, let me know if that format isn’t suitable and I’ll convert to something else.)
(This is also the internet debut of my hands.)

Yep. I will take a look later today. It can be fixed, i just need to add a second layer of button state polling

1 Like

Please try this code…
https://os.mbed.com/users/spinal/code/HelloWorld_buttontest/

I had to check the buttons differently in sensitive because of this very reason, sometimes the button presses didn’t register. I couldn’t tell of it was old button presses not stopping in time, or new buttons not starting in time, either way this other method works 100% of the time.

3 Likes

Using this example I couldn’t get the bug to reoccur,
and it certainly wasn’t through lack of trying.

I think it would be worth having a bit-packed uint32_t states[3] instead of several bool states[3], (or maybe uint_fast8_t stats[3]), but I definately think the polling approach looks like it works better.

In fact, this makes me even more confident that the reason the bug happens in the original is because of the use of interrupts - be it due to interrupts getting dropped from the queue or interrupts being disabled temporarily by other code and thus not registered.

1 Like

the problem didn’t happen when running your code.
wishing update api:+1:

2 Likes

I’ve attempted to alter the Pokitto library to use DigitalIn instead of InterruptIn.

https://github.com/Pharap/PokittoLib/tree/digital-in-buttons

If enough people say this approach works better, I’ll make a PR.

Isn’t it so that if you are not using interrupts, the correctness of the button reading is more dependent on the framerate, e.g. how often you call Pokitto::Update()? On second thought, if the framerate is 15 or even 10 fps, is it likely that there could happen a button press and release under 100 ms, which you could then miss (?). But maybe it is a problem if there are fps hiccups, and sometimes it takes a long time before Update is called for a frame.

Possibly, but which games currently run at such low framerates?

I find that usually input only has to be considered once at the start of a game loop.
If it needs to be used several times throughout a game with a slow framerate then depending on the game it should be easy enough to poll occaisionally.

Even if the framerate is made artificially slow then the button update could be made to occur more often than drawing by manually calling the button polling function.

If it causes an issue for any already published games then we won’t use it, but the interrupt approach is currently causing issues for games running at more reasonable framerates.

Ideally we’ll fix the issue in PokittoLib V2 by giving the user a choice somehow.

1 Like

This is why I was using interrupts.

And I have a strong suspicion as to what is happening. @Pharap , @spinal, @79859899 this may be of interest to you also

Remember when I said I had been able to improve the sound output speed? The reason for that was that the ticker interrupt that was part of the mbed core library was made for extreme flexibility (infinite amount of concurrent timers) - not for speed. When I eliminated the mbed ticker interrupt, and replaced with my own, sound interrupt speed went up 2-3 x.

Now, I need to investigate this, but I am almost certain this is the case. The ARM Cortex M0+ should be able to handle the button interrupts no problem at all, and I am surprised that we have this issue (button edge changes not detected).

But then I got a thought. These interrupt handlers are also part of the mbed core. What is probably happening is that all pin interrupt handlers are routed to the same handler provided by mbed core. This means that instead of going to the nested interrupt handler, the interrupts are not nested. They are now all pointing to the same handler! Then, with many button presses, the handler gets overworked (still handling previous interrupt), and we get the end result here.

I have had a very busy few days. Now, in a few hours, I will finally get to investigate if this theory is correct. I will replace the button interrupt handlers with 100% custom code and see what happens.

3 Likes

But why use interrupts instead of just manually checking the pins?

I made a test while ago: use an Infrared receiver connected to Pokitto Header and plot my TV remote protocol. My choice went to use mbed interrupts… but without luck. Now I suspect it was not my fault.

Lets see that code.

The mbed interrupt handling is for the most part very good, but they are not optimized for speed. They are optimized for hardware abstraction.

It is the same thing in Arduino. If you need to make time-critical code, you need to go to port manipulation.

1 Like

Because:

It would only happen with really slow games, but it is possible to miss button presses.


If it can be fixed so interrupts still work then that’s a good thing, but if it can’t then I’m on the side of polling since I’m fairly confident that most games here manage better than 15fps.

It would be interesting to know what is the theoretical minimum time for a Pokitto button to mechanically push-and-release.

Lucky for you I have a kickass digital scope now. I will find out.

3 Likes

And here is the culprit, in gpio_irc_api.c :

void gpio_irq0(void) {handle_interrupt_in(0);}
void gpio_irq1(void) {handle_interrupt_in(1);}
void gpio_irq2(void) {handle_interrupt_in(2);}
void gpio_irq3(void) {handle_interrupt_in(3);}
void gpio_irq4(void) {handle_interrupt_in(4);}
void gpio_irq5(void) {handle_interrupt_in(5);}
void gpio_irq6(void) {handle_interrupt_in(6);}
void gpio_irq7(void) {handle_interrupt_in(7);}

In other words, all pin interrupts are handled by one handler

1 Like

@79859899 please try this binary. If you find it works, update your PokittoLib

Pokitto_Game_Lost_LPC11U68.bin (53.0 KB)

@spinal , @Pharap , @Hanski : mbed interruptin handler replaced with a heavy-duty direct interrupt handlers

I am still of the opinion that interrupts are better than polling, although @spinal’s implementation does work very nicely indeed.

Initialization (I use the mbed funcs still to set the registers & enables, will clean later)

void Pokitto::initButtons() {
ABtn.fall(&AReleased);
ABtn.rise(&APressed);
BBtn.fall(&BReleased);
BBtn.rise(&BPressed);
CBtn.fall(&CReleased);
CBtn.rise(&CPressed);
UBtn.fall(&UReleased);
UBtn.rise(&UPressed);
DBtn.fall(&DReleased);
DBtn.rise(&DPressed);
LBtn.fall(&LReleased);
LBtn.rise(&LPressed);
RBtn.fall(&RReleased);
RBtn.rise(&RPressed);
NVIC_SetVector((IRQn_Type)(PIN_INT0_IRQn), (uint32_t)&PIN_INT0_IRQHandler);
NVIC_SetVector((IRQn_Type)(PIN_INT1_IRQn), (uint32_t)&PIN_INT1_IRQHandler);
NVIC_SetVector((IRQn_Type)(PIN_INT2_IRQn), (uint32_t)&PIN_INT2_IRQHandler);
NVIC_SetVector((IRQn_Type)(PIN_INT3_IRQn), (uint32_t)&PIN_INT3_IRQHandler);
NVIC_SetVector((IRQn_Type)(PIN_INT4_IRQn), (uint32_t)&PIN_INT4_IRQHandler);
NVIC_SetVector((IRQn_Type)(PIN_INT5_IRQn), (uint32_t)&PIN_INT5_IRQHandler);
NVIC_SetVector((IRQn_Type)(PIN_INT6_IRQn), (uint32_t)&PIN_INT6_IRQHandler);
}

Example interrupt handler:

static inline void ClearPinInt(LPC_PIN_INT_T *pPININT, uint32_t pins)
{
pPININT->IST = pins;
}

void PIN_INT0_IRQHandler(void)
{
if ((((LPC_PIN_INT_T*)LPC_PININT)->RISE)&(1<<0)) Pokitto::heldStates[BTN_A] = 1;
else Pokitto::heldStates[BTN_A] = 0;
ClearPinInt((LPC_PIN_INT_T *)LPC_PININT, PININTCH(0));
}

#notice

This change is already in the git repo & mbed PokittoLib

1 Like

Thanks jonne
Ive tied it.
but I found a new problem
the aircraft will go forward a different direction when I quickly and casually pressing direction button.
and sometime the aircraft will auto go out of screen even I release the button

VID_20180423_232212.zip (2.3 MB)

1 Like

I second @79859899, I also experienced the plane flying offscreen under certain conditions.

All I have to do is mash the dpad quickly and let go and the plane flies off, implying that the button release isn’t registering properly underr some circumstances.

In that case we need polling. Or level interrupt triggering (i am using edge trigger)