Event Driven API for PulsePosition

Status
Not open for further replies.

wsfish

Member
So I really like the PulsePosition library in TeensyDuino and have susesfuly used it a few times, may thanks Paul! But while the library is event driven rather than poll driven or blocking the interface/api with the main sketch is not.

I have fond that event driven things seem to be good and one of the guys I am working on a project with wants the hole thing to be almost completely event driven so i thought i would have a look under the hood of Pulse Position and I have a had a go at my own version.

I just took the version in my copy of TeensyDuino and had a bit of a hack at it.

https://github.com/fishrockz/PulseEvents

Not sure that it really follows any good practice or not but the little test/example seems to work as expected so i am going to have a go at using it in my main project soon but thought i would give it to you guys too.

Any feed back would be gratefully received. If it needs a bit more clean up before it is useful to others then let me know what would be good and i will have a stab at it.

Also dose the community have strong views on this sort of thing, are more event driven things a good idea or do they scare new people off? etc.

Will
 
Thanks Paul, I have had a look through and it seems like a good idea, I was about to start when I got detracted by the following and ended up down a 3hr rabbit hole..

So it occurred to me that the dosomething function might like to be running at a lower priority "higher numerical" than the original function, mainly for general good practice but also as (PulsePosition available()== true) / (PulseEvents triggers its event) straight after the end of the long pulse so it really needs to get back to lessening again ASAP. the next pulse could be only ~1ms away even tho the next complete pulse train will not be ready for ~13 to ~21ms.

There for i have been swatting up on Interrupts and I have found lots of references to software defined interrupts, https://www.pjrc.com/teensy/K20P64M72SF1RM.pdf mentions them on page 66 but then i cant find them again in the pdf.

https://gcc.gnu.org/onlinedocs/gcc/ARM-Function-Attributes.html mentions them but has not examples

https://github.com/FrankBoesing/Arduino-Teensy-Codec-lib has https://github.com/FrankBoesing/Arduino-Teensy-Codec-lib/search?utf8=✓&q=swi&type= but i dont understand how it sets them off.... is it: void initSwi(void) {PATCH_PRIO;NVIC_SET_PRIORITY(IRQ_AUDIOCODEC, IRQ_AUDIOCODEC_PRIO);NVIC_ENABLE_IRQ(IRQ_AUDIOCODEC);}

So I have three questions.

A) dose any one have any simple examples of SWI just for my knowledge?

B) do people/Paul think that, having the user bit of the function as a lower priority, is a good idea?

C) if B is true is swi a good way to do it or is there a alternative that would be better?
 
Not sure if this is useful to any one else but I think i would have found it useful a few days ago (or this morning).

Its a simple software defined interrupt, SWI, and timer triggered interrupt. the software interupt can be set to ether run in the space between a timer based interrupt or to block out the timer based interrupt.

Its based on this https://forum.pjrc.com/threads/2719...gered-interrupts?p=59360&viewfull=1#post59360

https://github.com/fishrockz/soft_timer_interrupts/tree/simpleExample

I had a go at trying to combine it with the structure of https://forum.pjrc.com/threads/44723-Arduino-Events but my first go was pretty poor so I will have another go some time.
 
Not sure if this is useful to any one else but I think i would have found it useful a few days ago (or this morning).

Its a simple software defined interrupt, SWI, and timer triggered interrupt. the software interupt can be set to ether run in the space between a timer based interrupt or to block out the timer based interrupt.

Its based on this https://forum.pjrc.com/threads/2719...gered-interrupts?p=59360&viewfull=1#post59360

https://github.com/fishrockz/soft_timer_interrupts/tree/simpleExample

There is a NVIC_TRIGGER_IRQ macro in kinetis.h (included by default). NVIC_STIR is also already defined there. You can use "attachInterruptVector(IRQ_NUMBER_t(isr_number), isr);" to access the interrupt table.
 
Thanks Guys

I have been having a play and making some progress but I am struggling with the ARM and other docs, but i am making slow progress on under standing it all.

One thing I have noticed is that the flexible timers have a FTM0_STATUS which could be used to work out why the ISR was triggered, as ISR's have not input variables? but i could call a software ISR for a number of resons but i cant find a way to work out who called it. is there a SWI_STATUS like register etc? As fare as I can see you only get one SWI?

Thanks
Will
 
One thing I have noticed is that the flexible timers have a FTM0_STATUS which could be used to work out why the ISR was triggered, as ISR's have not input variables? but i could call a software ISR for a number of resons but i cant find a way to work out who called it. is there a SWI_STATUS like register etc? As fare as I can see you only get one SWI?

The software_isr is a NVIC hardware interrupt, an unused entry in the NVIC interrupt table. Depending on the Teensy version, there can be a few of those unused entries, look at the manuals, "Interrupt channel assignments". If some peripheral isn't used, you can hijack that entry as well.

These interrupts don't get parameters directly. You could use something like an event queue (ring buffer).
 
So I think I am moving in the direction of https://forum.pjrc.com/threads/44723-Arduino-Events?p=145876&viewfull=1#post145876

They need a lot more work but If any one is interested.. I currently have:
https://github.com/fishrockz/EventObjects/commit/73e7b5a7fc7bad4ad6c128db75757cbf5b5c4264
https://github.com/fishrockz/PulseEvents/commit/892bff9bf7ac2110407fb8f99307d8619dd3eb74


The TODO's / things I feel I am missing most are:
* Something to disable interrupts at key points so that things doesn't clash
* A good way of interacting with the objects passed in to the handler functions, maybe get some inheritance going...
* Test it with two different interrupt sources to see how they play ball with each other, I am thinking of the second flexi timer on the T3.5 as I have something in mind for that one any way.

I had a really quick play and by changing the priority of the software interrupt you can show that the code that deals with the pulse train or packet of info can last for a while, in the example code its 5ms which would upset reading the next packet but by pushing it in to a software ISR and thus down the priority stack it dose not upset reading the next packet. BUT if you change ISR priority to, say 10, on line 44 of EventObjects.cpp (https://github.com/fishrockz/EventObjects/commit/73e7b5a7fc7bad4ad6c128db75757cbf5b5c4264) then the loop back values in the terminal will be changed.
 
So I finally have a working example, I was hoping to have a example that used two different event sources but this is as far as I have got tonight.

https://github.com/fishrockz/PulseEvents/commit/414f8583a49371fe6011d43b833bf83d4a141f59
https://github.com/fishrockz/EventObjects/commit/4470e5eb62ece763c86d650b3b99abddf1d2ff14

The example in PulseEvents now looks like:

Code:
#include <PulseEvent.h>
//#include "EventObjects.h"
// Simple loopback test: create 1 output to transmit
// test pulses, and 1 input to receive the pulses
PulseEventOutput myOut;
PulseEventInput myIn;

int count=0;
void EventFunction(EventBaseObject * ThisFunctionsInfoPointer){
	PulseEventObject* ThisFunctionsInfo = static_cast<PulseEventObject*>(ThisFunctionsInfoPointer);


	Serial.print("EventFunction, num: ");
	int num = ThisFunctionsInfo->available();
	Serial.println(num);

	if (num > 0) {
		count = count + 1;
		Serial.print("EventFunction called: ");
		Serial.print(count);
		Serial.print(" :  ");
		for (int i=1; i <= num; i++) {
			float val = ThisFunctionsInfo->read(i);
			Serial.print(val);
			Serial.print("  ");
		}
		Serial.println();
	}else{
		Serial.println("num==0");
	}
	//delay(500);
}


void setup() {while(!Serial){};delay(200);Serial.println("setting off A");
	myOut.begin(9);  // connect pins 9 and 10 together...
	myIn.begin(10, EventFunction);
	myOut.write(1, 600.03);
	myOut.write(2, 1500);
	myOut.write(3, 759.24);
	// slots 4 and 5 will default to 1500 us
	myOut.write(6, 1234.56);

	Serial.println("setting off B");
}



void loop() {
//Serial.println("going");
}
 
So I haven't been keeping up with all the updates in https://forum.pjrc.com/threads/44723-Arduino-Events/ but I have now subscribed to that thread so I should keep my self in the loop.

That said I have been working way in bliss full ignorance of the other thread.. and have come up with what seem like a fair proof of concept that a quick scan doesn't seem to be a million miles different we have both come up with passing pointers to our interrupt handling functions etc mine is a bit messy requiring recasting etc.

I now have two different FTM based libraries, one is just a version of Paul's PulsePosition for my events library. and the other is a bit like the standard timer function except that they are meant for triggering a cascade of events with varying wait times. the second also copys much from PulsePosition but is much less polished.

I have
https://github.com/fishrockz/UnevenTime/commit/c613ed7e4d0f7fbd9df5c7ba13e9841fdf0f2f9d
https://github.com/fishrockz/PulseEvents/commit/9e1a5994bebd6033e779067989ea075db9114601

they both use
https://github.com/fishrockz/EventObjects/commit/a060833820a08f730f9087304b51c005a0712f5b

and an example of them working together can be found
https://github.com/fishrockz/combinedTimersExample/commit/3627009b0e1d2fa0ffcc984ad5f31d460c8073af

Code:
#include <PulseEvent.h>
#include <UnevenTime.h>

#include <math.h> 

//#include "EventObjects.h"
// Simple loopback test: create 1 output to transmit
// test pulses, and 1 input to receive the pulses
PulseEventOutput myOut;
PulseEventInput myIn;
UnevenTimeTriger UnevenTimerBlock;


uint32_t reversvalueA [] = { 
10,
40,
500,
4,
300,
20,
50,
20,
5,
20,

};

int LEDSTATE;
int trigerPin=12;

void blockFunction(EventBaseObject * ThisFunctionsInfoPointer){
	
	Serial.println ("this is the fast function");
	
	if (LEDSTATE==1){LEDSTATE=0;}else{LEDSTATE=1;}
	digitalWrite(ledPin, LEDSTATE);
	

}

void generalFunction(EventBaseObject * ThisFunctionsInfoPointer){
	digitalWrite(trigerPin, 0);
	Serial.println ("this is the slow function");

	if (LEDSTATE==1){LEDSTATE=0;}else{LEDSTATE=1;}
	digitalWrite(ledPin, LEDSTATE);
	

}



int count=0;
int state=0;
void PulseEventFunction(EventBaseObject * ThisFunctionsInfoPointer){
PulseEventObject* ThisFunctionsInfo = static_cast<PulseEventObject*>(ThisFunctionsInfoPointer);



	int  num;

	num = ThisFunctionsInfo->available();

	//Serial.println(num);

	if (num > 0) {
		count = count + 1;

		for (int i=1; i <= num; i++) {
			float val = ThisFunctionsInfo->read(i);

			if (i==3){
				int curstate = round(val/100);
				if (state!=curstate){
					Serial.print("EventFunction called: State changed: ");
					Serial.println(curstate);
					state=curstate;
					reversvalueA[4]=state*10;
					LEDSTATE=1;digitalWrite(ledPin, LEDSTATE);
					digitalWrite(trigerPin, 1);
					UnevenTimerBlock.StartTimer(reversvalueA,(uint32_t)10,generalFunction,blockFunction);
				}
			}
		}
		//Serial.println();
	}else{
		Serial.println("num==0");
	}
	//delay(500);
}


void setup() {

	pinMode(ledPin, OUTPUT);
	pinMode(trigerPin, OUTPUT);
	
	while(!Serial){};delay(200);Serial.println("setting off A");

	myOut.begin(9);  // connect pins 9 and 10 together...
	myIn.begin(10, PulseEventFunction);
	myOut.write(1, 600.03);
	myOut.write(2, 1500);
	myOut.write(3, 759.24);
	// slots 4 and 5 will default to 1500 us
	myOut.write(6, 1234.56);

	Serial.println("setting off B");
}


int output=0;
void loop() {
//Serial.println("going");

	delay(1000);
	myOut.write(3, 1000 + 60.*output);// as PulseEventFunction rounds to the nearst 100ms and 60 isnt a multipule of 100 you get a paten on the scope of between 1 to 3 repeted pulses then a gap of a second or so. also some of the pulse train changes according to this value
	output++;
	if (output>20) output=0;

}


and it produces pulses like this
https://github.com/fishrockz/combinedTimersExample/blob/master/triggerLED.png

I want to do some proper testing and cleaning up of my code but i also want to update the project that this is inspired by...

I am particularly interested in how my mini queue deals with slow functions etc..

I should really migrate over to what ever https://forum.pjrc.com/threads/44723-Arduino-Events/ comes up with but as the other thread is still not finished I am torn as to getting on with finishing mine and not putting too much effort into something that will get super seeded..
 
Last edited:
Status
Not open for further replies.
Back
Top