RCU Forums - View Single Post - CDI gr8flyer55
View Single Post
Old 09-11-2012 | 11:12 PM
  #249  
jakestew
Senior Member
 
Joined: Aug 2011
Posts: 144
Likes: 0
Received 0 Likes on 0 Posts
From: Moscow, ID
Default RE: CDI gr8flyer55

I tried to comment every line of code so that it could be easily worked on, but a general explanation will probably help understanding better.

The program is interrupt driven. The main function only initalizes the processor and turns on the interrupts. The actual main loop does nothing at all, it's just a while(1) loop with no instructions.

There are three interrupts. GP2 falling edge, Timer1 compare match, and Timer1 overflow.

-[Timer1 Overflow] Timer1 is a 16-bit timer that runs at 1 uS per tick. It overflows every 65ms if not reset by the GP2 interrupt. If it overflows we know that the sensor on GP2 has not triggered in 65ms. Each overflow we add 1 to the TMR1_Overflow counter. If the counter goes over 7 we know that the engine is turning at less than 120 RPM (2 RPS), and we declare the engine not running.

-[GP2 Interrupt] happens once every revolution when the sensor activates. We then store the value from Timer1. Then we take the value from Timer1 and use it to look up a delay value from the ignition advance table. Then we reset Timer1 and load the advance table value into the Timer1 compare register.

-[Timer1 Compare] this is called when the Timer1 value increases to the Timer1 compare value. We then know it is time for the spark, so we turn on GP1 (SCR trigger/output), wait for the specified dwell time, and turn GP1 off.


And that's it! Pretty simple huh? It took me many hours, and several false starts that turned out to be overly complicated dead ends, to distill that pure simplicity.
If you add the other features to that basic outline you'll understand all of the program. I didn't explain the MSD code, starting code, or calculation of the speed at RPMs below the table values, but that's all just extra trimmings.

The main thing to understand is that Timer1 ticks at 1uS and gives us the uS per revolution. The Timer1 value can be accessed as a 16-bit value or two 8-bit values. Because of this we can avoid all sorts of slow math that would bog down the processor.

Using the high value (top 8-bits) we automatically already have the uS per revolution / 256. So instead of using 360 degrees per revolution we just figure on 256 digi-degrees per revolution (1dd = 1.4 deg.). This also automatically gives us the uS per digi-degree! All of this is done by simply taking advantage of the way the timer is set up, no math at this point at all!

So now all we have to do is multiply the timer value by the number of degrees we want to wait before sparking and load it into the compare module. Multiplying is slow, so we use a table for the faster values, and only calculate the delay at lower RPMs where we have the time to do so.


Hopefully this all is clear enough. Feel free to ask questions. I wanted to explain the digi-degree thing before it caused too many problems. There's probably a proper term for them, but I don't know it.

1 revolution = 360 degrees = 256 digi-degrees
degrees * 360/256 = digi-degrees
digi-degrees * 256/360 = degrees
1 digi-degree ~= 1.4 degrees
1 degree ~= 0.7 digi-degrees<br type="_moz" />