FEZ Hydra - OSHW Signal Generator

@ taylorza - top stuff fella

Awesome!

I see full set of Premium features on hydra soon! :wink:

Nicely done. I’m still working with Ian to get him up and running, but I’m sure we’ll get him sorted.

Great contribution!

@ taylorza - You rock!

@ Gus - Are we going to be able to get this rolled into the official firmware in the next release?

Sorry, I’ve been distracted with another project. I’ll hopefully get back to testing your module today.

@ ianlee74 - Dude, no worries. I’m not sitting here waiting for your next email or anything. :wink:

I’ll just be very happy when you can actually USE the module!

Me too!!! [Un]fortunately, I have a mouse in the attic that needs a high-tech end to his life :wink:

Glue traps are very effective, as long as you’re not soft-hearted like I am and want to take the mouse off and release him (far from your home, of course). Pulling them off is pretty hard on the little critters, it turns out. The old fashioned snap trap is probably the most humane, in the end.

Yea…not soft-hearted at all when it comes to critters who want to eat my house. Plus, how to do you get a twitter notification from a glue trap? Snap traps are a little easier and give the least amount of suffering for the critters than any other solution.

@ ianlee74 -

Snap-trap + accelerometer = twitter notification of successful mouse obliteration.

Wonder if that rig would make H.A.D.? :wink:

@ devhammer - you’re over thinking it… I don’t want my good modules anywhere near a nasty, dirty, ole mouse :wink: Look for a post soon once I can get these darn networking problems stabilized :frowning:

That is some serious OT guys :slight_smile:

LOL

@ taylorza - Any chance there is a SignalCapture in the works?

I can definitely do one. I do not know if you saw, but I also created a RLPLite version of the SignalGenerator for the Hydra, I figured people would rather load that than load a custom firmware. I mention this, because I guess the question would be if there is a preference for a version that is implemented in RLPLite or as another extension to the firmware?

Btw. :@ jernejk and I were just discussing implementing SignalCompare and PinCapture in the DL40IO firmware. Would you be interested in that?

1 Like

RLPLite will work to start with. That way I can use it on Cerberus (that is actually where I needed the most at the moment)
Ideally it would be great if GHI will merge your work into OSHW library. So we can have this nice feature for all OSHW devices.

The Hydra and Cerb MCU are very different, so the RLPLite will need to be done specifically for the Cerb as well. I will give it a shot and see what I can do, I am just finishing the testing of the PWM implementation for DL40IO.

Sounds great!

I have been working on a signal capture RLPLite function and ran across your posted signal generator codeshare. I have 2 questions about the code and a problem I’m hoping you can help me with. Question 1: How did you know the timer2 time per tick? Question 2: Why did you use timer2 and not the Periodic timer (PITC_PIIR)?
My current problem is I created a function to compute the ticks per second of the Periodic Timer. I use this function in along with the PIT register to compute elapsed time. Here is the Native code:

unsigned int Get_ticks_per_second(void)
{
    unsigned int ticks_per_sec = 0;
    unsigned int MCKR = 0; //  Master Clock Register value
     unsigned int MDIV = 0;  // Master Clock Divisor
    unsigned int MCFR = 0; //  Main Clock Frequency Register value
    unsigned int MAINCLK = 0, MCK = 0;    // variables for main clock and Master clock values
    unsigned int PLL = 0; // PPLA  Register value
    unsigned int PLL_MUL = 0, PLL_DIV = 0;   // PLL Multiplier and Divisor
    MCKR = *AT91C_PMC_MCKR;
    MDIV = (MCKR & 0x300) >> 8;
    MCFR = *AT91C_CKGR_MCFR;
    MAINCLK = (MCFR & 0xFFFF) * 2048;   // 2048 from slow_clock/4 where slow clock is 32768. PRES is 0 so not needed 
     // note - did not add code her to check  CSS - testing showed it was 2, so Master clock is based on the PLL clock
     // a more robust version of this code should check CSS and PRES values for safety.
    PLL = *AT91C_CKGR_PLLAR;                // read the PLL register
    PLL_DIV = (PLL & 0xFF);
    PLL_MUL = (PLL & 0xFF0000) >> 16;
    if (PLL_DIV < 1) PLL_DIV = 1;
    MCK = (MAINCLK / PLL_DIV) * (PLL_MUL + 1);    // PLL Clock is multiple of main clock
    if (MDIV == 1) MCK /= 2;
    else if (MDIV == 2) MCK /= 4;       
    ticks_per_sec = MCK / 16;           // Periodic timer is Master Clock / 16
    return ticks_per_sec;
}

The value I get back is 7116800 ticks per second.
However, when I use this time in a simple delay function, it takes about 13% longer than it should (i.e. 1.13 second delay when requesting 1.0).
The 13% is linear - not just the overhead of calling the function (i.e. 30 second delay takes 34.1 seconds).
I know I can hard code a scale factor, but I want to know what is wrong.
Thanks for any ideas.

Given the 200MHz clock speed and the divisor I selected for the timer I calculated the ticks and the uS per tick in Excel.

The original code is not RLP code, but core that I wrote into a custom firmware (available in this thread) the firmware implements the non-blocking signal generation for which I hook the timer interruptes etc. Since I needed finer control of the timer and did not want to interfere with anything that might/might already be using the periodic timer for scheduling of threads etc. I choose to use the last timer since it was least likely to be used by anything else. I basically pulled the code from my firmware implementation and repackaged it as an RLP implementation for easier consumption by a broader audience.

As you have seen with you code, getting the timing right is a challenge and therefore I did not change anything I did not need to change when I moved the code to RLP. Especially since it took the efforts of community members like @ Architect and @ devhammer to test the code for accuracy since I do not have the tools required.

Off the top of my head I do not have anything concrete, it might help to see your code. Are you just looping and incrementing a variable until you read the 7116800 or some multiple of that, or are you actually checking the timer tick value. I found that checking the timer value is much more accurate, you would need to drop down to assembly or perform an analysis of the generated assembly instruction timings so that you can compensate for the time spent loading registers, comparing values taking jumps etc.

What I eventually settled on is that I maintain an accumulator that is incremented by the timer tick value and when ever I exceed the counter threshold I react and compensate for the excess in the next iteration. So if the target is 10 but the accumulator overshoots and hits 12 then the next target which might be 30 for example will be reached within 18 ticks rather than the expected 20 and if that overshoots then the next target is compensated etc.

Of course the above might not be suitable for your needs, if you simply need accurate delays then you will need to count the clock cycles for each instruction. For this I prefer to drop to assembly, that way I do not need to worry about the compiler changes as I upgrade the version or change compiler switches etc.

I hope this helps at least a little.

NB:
Using code tags will make your post more readable. This can be done in two ways:

Click the "101010" icon and paste your code between the 
 tags or...
    Select the code within your post and click the "101010" icon.

(Generated by QuickReply)

Thanks for the quick reply.
I am checking the timer tick value .
Here is the main part of the delay function:

while (still_waiting)
		{
			max_safety_counter--;
			if (max_safety_counter < 1) still_waiting = false;	
			temp = *AT91C_PITC_PIIR;  // read the periodic timer clock register
			// Periodic_time counts to 1048575 then rolls to 0 and incs the intervals
			Periodic_time = temp & 0XFFFFF;   // how many ticks
			Periodic_intervals = (temp & 0XFFF00000) >> 20;   // each interval is 1048576 ticks
			ticks_so_far = (Periodic_intervals * 1048576) + Periodic_time;  // total ticks
			// now compute us passed so far and if more than us - we are done
			if (ticks_so_far >= ticks_to_wait)
			{
                                still_waiting = false;	
 		       };				
		};[/code
Thanks for your help!!