In January of this year I bought an old motorcycle, a 1946 Harley Davidson WL. This is a civilian model of a motorcycle that HD made several hundred thousand of during WW II. The engine has two cylinders displacing 45 cu. in., in what they call a "side-valve" configuration, what I've always called a flathead.
Being that this forum is concerned with electronics and such, I thought that some readers might be interested in how the ignition circuit works on this old beast.
On the right side of the engine is a component that looks something like a distributor, but unlike most car distributors, there are no spark plugs attached. The unit has a set of points and a capacitor inside, just like older car distributors, but unlike them, there are no spark plug wires attached to it. It's also referred to as a timer, or circuit breaker, rather than a distributor.
The ignition circuit is pretty simple. The primary circuit consists of the the battery, coil, and timer. The secondary circuit consists of the coil and the two spark plugs. When the engine is running (or when you're starting it), the timer rotor turns, and its two lobes cause the points to open and close at specified times related to crank and valve position. When the points close, current flows through the primary circuit, which induces a current in the secondary windings of the coil, and across the gaps of both spark plugs. When the points close, the electric field in the coil collapses.
By firing both spark plugs whenever the points close, they didn't need to distribute the spark to an individual plug, and this is why there aren't any plug wires coming out of the timer. The disadvantage of creating a wasted spark for a cylinder that isn't ready to fire is a weaker spark on the one that needs it, but hey, that's the way the engine was designed.
Dynamic methods, a feature of .NET Framework since v2.0, provide a way to create a method at program run time. When I learned about this feature, it looked like an opportunity for me to learn more about the intermediate language (IL) that is at the heart of .NET Framework programming.
By way of background, a program written in one of the languages supported by the .NET Framework is compiled into Microsoft Intermediate Language (MSIL). When the program is executed, the Common Language Runtime (CLR) has a just-in-time (or JIT) compiler that translates the IL codes into native machine instructions.
The program in the attached file has two dynamic methods. The first method has two int parameters, and returns the average of the two input values. The body of this method is six bytes! The second method converts a temperature from Celsius to Fahrenheit or vice versa. This method also has two parameters--one is the temperature, and the other is a Boolean flag that indicates whether the first parameter is a Celsius temperature or a Fahrenheit one. This body of this method is 36 bytes.
Both methods use integer division, so the results they produce aren't as precise as it would be using floating point division. Inasmuch as the goal for me was to use dynamic methods, precision was not a top priority.
Although the methods are tiny in size, there's a fair amount of overhead associated with using dynamic methods. You also need to include additional information about each method, namely maximum stack size during the method's execution, the method calling convention, the number of parameters, the type of each parameter, and the type of the return value.
The attached code file is extensively commented, to help you understand what's happening along the way. I have also included algorithms for each of the dynamic methods, as well as their IL opcodes.