lancaster-university / microbit-dal

http://lancaster-university.github.io/microbit-docs
Other
254 stars 130 forks source link

Serial Events Not Firing #181

Open Drmikej opened 8 years ago

Drmikej commented 8 years ago

This one is almost certainly my error but it must be down to me not understanding something everyone else is taking for granted. I'm trying to use serial interrupts. I've finally reduced back to the simplest program:

include "MicroBit.h"

MicroBit uBit; void onChar(MicroBitEvent e){ uBit.display.print("A"); };

int main() { uBit.init(); uBit.serial.baud(115200); uBit.serial.eventAfter(1); uBit.messageBus.listen(MICROBIT_ID_SERIAL, MICROBIT_EVT_ANY, onChar); while(1)uBit.sleep(1000); release_fiber(); }

I have tried the more specific event ids, eventAfter and eventOn. I checked the serial USB was working and and that I can respond to an event from somewhere else - button A. All put into the code as above and then taken back out for simplicity. I am using the same release as previous question rc4. What am I missing?

remay commented 8 years ago

You haven't explained how you're sending bytes down the USB Serial cable, but from what I can see what you've done should work. I see one possible race condition ... I'd swap the lines registering the listener and requesting the event to ensure that the listener is place before the event is triggered, otherwise it could get lost.

Have you tried using eventAfter(x) with x greater than 1 to ensure there's not an off-by-one error somewhere?

Drmikej commented 8 years ago

Its PuTTY via a standard PC. Swapped lines over - no change. Have tried 2 to 5 - no change. Your comment made me wonder if the serial connection really was working - it always has done. And it works with other programs reading data in and I can see the LED on the micro:bit flash when I type in PuTTY. However the event not firing really does make me think that something isn't getting to the serial device So I added: uBit.serial.baud(115200);

uBit.messageBus.listen(MICROBIT_ID_SERIAL, MICROBIT_EVT_ANY, onChar); uBit.serial.eventAfter(1); ManagedString s=uBit.serial.read(6,ASYNC); uBit.display.scroll(s,400);

i.e. I read the serial port for characters. Now when I run the program I see a single character (I'm typing it repeatedly) scroll pass and then the A from the event handler. So reading from the serial port triggers the event handler - I'm I misunderstanding what should happen? I supposed the event would occur if the hardware received any data no matter what the main program was doing.

jamesadevine commented 8 years ago

@Drmikej sounds like a bug! :smile: Considering you've already done the yotta-version song and dance, I think we can safely assume it's not your environment :wink:

I will take a look when I get some airtime!

jamesadevine commented 8 years ago

@Drmikej can you try setting the rxBuffer before the event configuration?

uBit.serial.setRxBufferSize(20);

I feel this does not work as a result of some missed initialisation of buffers, as we adopt a lazy initialisation approach.

Drmikej commented 8 years ago

Yes. That fixed it. I am surprised that it did because I did try querying the size of the RX buffer and it returned 21. Surely you can't be that lazy! :-) While this isn't a bug its a feature that is going to catch other programmers out in the future. It either needs to be added to the docs or the init should be not quite as lazy. Personally I would be happy with it being added to the docs. Many Thanks

jamesadevine commented 8 years ago

@Drmikej Of course! Was just diagnosing :smile: I will make a patch soon, it was not intentional! Sorry for the head scratching!

Drmikej commented 8 years ago

Additional problem it seems to only fire the interrupt once. Still investigating.

jamesadevine commented 8 years ago

@Drmikej it will fire only once, perhaps there should be a repeat = true/false parameter...?

jamesadevine commented 8 years ago

I thought it would be a cool thing to add to the serial interface, and might have some interesting use cases. Of course, through use we can begin to shape the API a bit better... What's your particular use case @Drmikej ?

remay commented 8 years ago

@jamesadevine - FYI I have some time carved out next week to write some real code using the new API - I haven't actually used it since we did the code review a few months back. I'll provide feedback then.

Drmikej commented 8 years ago

Well the standard use case for events and serial devices is to read in a character when ever one is ready to be read. So the event handler is something like void onChar(MicroBitEvent e) { ManagedString s= uBit.serial.read(1); uBit.serial.clearRxBuffer(); uBit.display.scroll(s); };

Only it would process the character in some way.

Drmikej commented 8 years ago

I can't find any way to re-enable the event. I've tired ignore and then listen in the event handler but I still get only one event responded to.

remay commented 8 years ago

@Drmikej I think you need to call uBit.serial.eventAfter(1); again.

jamesadevine commented 8 years ago

@remay That would be great! :smile:

@Drmikej a call to uBit.serial.eventAfter(1); in your event handler does not work?

Drmikej commented 8 years ago

Yes that works - so the fixup is: void onChar(MicroBitEvent e) { ManagedString s = uBit.serial.read(1); uBit.serial.clearRxBuffer(); uBit.display.scroll(s); uBit.serial.eventAfter(1); };

and remember to do something with the Rx buffer before waiting for the event.