Arduino Events

@defragster. First, I apologize for being long winded but :) Conceptually I thought I understood what was going on with the eventresponder, at least for the repeating timer piece. However, with all the talk about chaining I started to dig into the inner workings to figure chaining out.

What I found was Tail-chaining as it refered to interrupts and the chaining of PIT timers, but I couldn't see where that was applicable to repeating timers.

So I then looked at what was going on with the code and that led me to Systick_isr which is runs the runFromTimer() function which is using the linked list (which I knew nothing about, oh well). From what I think I am seeing that systick_isr is running every millisecond so each timer created is decremeted until it hits zero and then the original value gets reloaded into the list and the process starts all over.

This is done via timer -> _ms decremented timer and timer -> reload which reloads the original timer value. The event gets triggered by the call to event.triggerEvent(0, timer). The process is shown below (i put a couple of prints where i thought things where happening):
Code:
=========
#define EVENT2_TIME 850
#define EVENT3_TIME 1050
#define EVENT4_TIME 250
#define EVENT0_TIME 750   (loop trigger at 750)
========
EventResponder test 
ms timer: 248
ms timer: 247
ms timer: 246
ms timer: 245
.......
.......
.......
ms timer: 4
ms timer: 3
ms timer: 2
ms timer: 1
ms timer: 0
Reload: 250
ms timer: 250
2213 - T4(0)           250 (T4)
ms timer: 249
ms timer: 248
ms timer: 247
.....
.....
.....
ms timer: 3
ms timer: 2
ms timer: 1
ms timer: 0
Reload: 250            500  (T4)
ms timer: 250
2463 - T4(0)
ms timer: 249
ms timer: 248
ms timer: 247
ms timer: 246
....
....
....
ms timer: 5
ms timer: 4
ms timer: 3
ms timer: 2
ms timer: 1
ms timer: 0
Reload: 250             
ms timer: 100           next timer is at 850-750=100
                        for T2
2713 - T4(0)            750  (T4) next trigger at 1000
ms timer: 99
ms timer: 98
ms timer: 97
.....
.....
.....
ms timer: 5
ms timer: 4
ms timer: 3
ms timer: 2
ms timer: 1
ms timer: 0
Reload: 850         850 actually funny  because its loading
                    850 for T2 timer plus 850 passed
ms timer: 150       150 left to go to T4 which is at 1000
2813 - T2(0)
ms timer: 149
ms timer: 148
ms timer: 147
......
........
......
ms timer: 4
ms timer: 3
ms timer: 2
ms timer: 1
ms timer: 0
Reload: 250
ms timer: 50            50 left to T3
2963 - T4(0)            bingo hit the T4 timer which is 
                        at 1000.  T3 should happen again
                        at 
loop trigger dosomething
dosomething event
ms timer: 49
ms timer: 48
ms timer: 47
......
......
......
ms timer: 3
ms timer: 2
ms timer: 1
ms timer: 0
Reload: 1050
ms timer: 200
3013 - T3(0)        Ok got through the cycle
Now what i don't understand is how the linkedlist actually gets created. It is, i think i know how, but its not what is shown when i do search for c++ linkedlist. Still have to figure out how the interrupt piece works because I did see anything where a IRQ number is assigned. I did see where pendSV is set - have to figure that one out next. Do you have an example of eventresponder using interrupt events?

Thanks for all your help.
Mike
 
The discussion I recall about tail chaining was only when the interrupt vector was already claimed but another purpose called for it to be added to but not replaced. That was resolved in TeensyThreads to allow EventResponder to continue to function with the updated code.

As far as the linked list - that is just an internal storage detail for the Events to be queued and accessed and tended to as time passes.
 
Hi all. Was playing around more with EventResponder and decider to give a go at triggering events from threads. After some headaches i managed to get it to create a blink example based on @Bill Greiman post. What can I say. Here is code but not sure if this is the best method or there is a better way, any suggestions would be helpful:
Code:
#include <EventResponder.h>
#include <Arduino.h>
#include "TeensyThreads.h"

const int LED = 13;
bool test;
int tOn, tOff;

volatile int blinkcode = 0;

EventResponder led_switch;

void ledOn() {
  while(1) {
    digitalWrite(LED, HIGH);
    delay(500);
    led_switch.triggerEvent(1);
    //threads.yield();
  }
}

void ledOff() {
  while(1) {
      //Serial.println(led_switch.getStatus());
      if(led_switch.getStatus() == 1){
        threads.suspend(tOn);
        digitalWrite(LED, LOW);
        led_switch.triggerEvent(0);
        led_switch.clearEvent();
      }
      delay(500);

      threads.restart(tOn);

  }
}


void setup() {
  while (!Serial && millis() < 4000) ;
  Serial.println("EventResponder test");
  pinMode(LED, OUTPUT);
  tOn = threads.addThread(ledOn);
  tOff = threads.addThread(ledOff);
}


void loop() {

}

v/R
Mike
 
Hi

What's the current status for the Interface? (EventResponder and MillisTimer)

Is it "safe" to use in new code?
 
It's still considered experimental. The API may change in the future.

Paul

thanks. Is it only a possible API change or is it still possible that the principal idea goes away for EventResponder and MillisTimer.
I would use it to let class instances do thing automatic. For example a encoder knob with pushbutton -encoder class for the encoder- and a bounce claas inside it, but without the need to call update regulary.
Changing API is small versus going away of the principle.
 
Does the EventResponder offer a way to be notified through callback when a character arrives on Serial? Is that parsed on yield() - or will it tie into the Serial# code in some fashion?

I'm looking to closely associate {processor cycle counter resolution} IMU and GPS data. The IMU data comes with an interrupt, but the GPS data just streams in on some period over Serial, and knowing when that starts would allow time stamping the start of the data that will take some 6 ms to see completed - I can poll for and read the rest of the data - but time tracking the first byte arrival would allow it to be properly placed within the IMU data set.

My GPS with PPS signal hasn't arrived yet - but reading cpu cycle counter seems very efficient and accurate tested against the RTC interrupt - thanks Manitou. 4 hours of monitoring it shows all RTC seconds arrived within 53 cycles (-24 to +28) of my floating average at 240 MHz - and the floating average has moved some 75 cycles it seems in that time - so polling or millis() would be a world away from that.
 
Sorry, I did not see this question...

I don't believe EventResponder is hooked up to any Serial code yet. So yes you would probably have to modify the core to get it this way.

Another hack you might try, is to set attach an interrupt to the RX pin of the USART, on the first fall or rise and grab the time at that point.

I was playing around with this earlier with SPI client code, on trying to see when the CS pin was asserted.
 
Indeed it works to catch first char of each new message, without messing with Serial. Wired Pin 8 and 9 together for test.
S:\DK_XFER\Rx2Int\Rx2Int.ino
<<|/`~abcdefghij [Rx+1401 uS=2] klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:
<<|/`~abcdefghij [Rx+2401 uS=2] klmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:

Forgot qBlink.

Code:
#define qBlink() {GPIOC_PTOR=32;} // BLINK LED_BUILTIN Pin 13
#define SP2( A, B ) { Serial.print(A);  Serial.print(B); }

// WIRE PIN 8 (TX3) to PIN 9 (RX2)

elapsedMillis foo;
volatile uint32_t GPS_RX_time = 0;
FASTRUN void GPS_serialrx_isr() {
  uint32_t tt = millis();
  if ( tt - GPS_RX_time > 6 ) {
    GPS_RX_time = tt;  
    qBlink();
  }
}

#define GPS_SRX 9

void setup() {
  Serial.begin(9600);
  Serial2.begin(115200);
  Serial3.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  // pinMode(GPS_SRX, INPUT); // set input by Serial3.begin()
  attachInterrupt(digitalPinToInterrupt(GPS_SRX), GPS_serialrx_isr, RISING);
  NVIC_SET_PRIORITY(IRQ_PORTC, 180);
  while (!Serial && millis() < 4000 );
  Serial.println("\n"__FILE__);
}

uint32_t last_GPS_RX_time = 0;
void loop() {
	if ( foo > 1000 ) {
	  Serial3.print( "<<|/`~abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:\n" );
	  foo-=1000;
	}

	while ( Serial2.available() ) {
	    Serial.print( (char)Serial2.read() );
  }

  if ( last_GPS_RX_time != GPS_RX_time ) {
    last_GPS_RX_time = GPS_RX_time;
    SP2( " [Rx+", GPS_RX_time );
    SP2( "  uS=", foo );
    SP2( "]  ", "");
  }
  	
}

** removed print from isr() - the first character time stamp is marked - but printed after returning to capture the buffered data as shown in output

<edit> Seems FALLING would catch the start bit? Stop is held HIGH and falls for START - then the character starts - and who knows how many zeros will follow.
 
Last edited:
Was wondering if and when Hardware serial would be updated to make use of eventresponder, or if there is a moded version to give a try for. It is relation to defragster's last post and whats going on in the uNavAHRS thread.
 
EventResponder is still stuck in a limbo of indecision, and that's all my fault.

I recently had a conversation with Massimo Banzi. Arduino may be really interested, but that's very tentative. We're planning to talk further in mid-March.

Something that did come out of that conversation is a better understanding of what sort of example application will really motive Arduino to adopt this API. It also has me re-thinking whether the "operation complete" model we're currently using in the SPI library (thanks to KurtE) and planning to do in the Wire library is the best way for stream-based protocols. I'm considering a base class like StreamEvent, but to be honest, I really have quite a lot of work to do for non-trivial applications.

Also on my mind is whether we want to encourage APIs where EventResponder objects are instantiated within Arduino sketches, versus a recommended style (supported by examples & documentation) where ordinary users don't have to create/use 2 objects just to accomplish one thing.

Sorry I can't give more detail at this time. While PJRC doesn't have any NDA with Arduino, the last thing I want to do is cause trouble for them by disclosing any private info. But I will confirm we're talking directly, and plan to do more soon. I also have a lot of "homework" to do on EventResponder....
 
Paul. Thanks for the data dump. Really interesting your discussions with Massimo Banzi. You really do need to be cloned with everything on your plate.

Anyway, StreamEvent sounds interesting but not really a priority in the scheme of things.

You are right, if you formally publish the API you do really want it to be supported by documentation and examples especially for ordinary users - and I do put myself in that category - maybe a little above :)

Again thanks for the info you provided. Its more than I was expecting. Been doing a lot of homework myself lately - so I understand.

Thanks
Mike
 
Note with the EventResponder objects, There is a method called setContext, which allows you to save away a 32 bit value...

So when I use it as part of some object (like my current hacking around with SSD1306_FlexIO code), when I initialize the Event Responders, I do something like:
Code:
_event_responder.setContext(this);  // Set the contxt to us
  _event_responder.attachImmediate(&SSD1306_FlexIO::asyncEventResponder);

And then in the call back function I do:
Code:
oid SSD1306_FlexIO::asyncEventResponder(EventResponderRef event_responder) {
  SSD1306_FlexIO *pdisp = (SSD1306_FlexIO*)event_responder.getContext();
  pdisp->displayAsyncCallBack();
}
So we have one static method that gets called who extracts the this pointer for the associated object out of the context variable and then calls off to the classes code to respond to the event...
 
Back
Top