One of the greatest challenges of this project so far has been representing the values for Potassium Conductance (GK), Threshold, and Membrane Voltage as 8-bit binary values. The use of numerical integreation introduces constants which are non-integers. The computation required to produce a value for the membrane voltage requires an expontential, which also produces a non-integer number. To represent these values, I chose a two word, fixed point representation, forcing 8 bits to represent the signed integer part of the value, and a second register to represent the fractional part of the number. There is a small, but not terrible, error introduced from the finite-precision. That is the the value to the left of the binary point is limited to some multiple of 1/255.
Two multiply routines are used in the program: signed and unsigned 16-bit x 16-bit multiply routines. These were taken directly from avr200.asm from Atmel's website. I modified these routines to save the values of the registers that it overwrites and to take inputs from the operand registers and put the output in the return registers. The code was also modified to check for overflow and return the maximum value if an overflow occured. The modified multiplication routines can be found in the code.
Creating the divide routine needed for the membrane voltage calculation was a complicated affair. The signed 16x16 divide routine given in avr200.asm returned a 16-bit modulo value and a 16-bit remainder—an arrangement that was is very useful, because I needed to get an "exact" value for the division. To accomplish this feat, I used the well-known principle of left-shifting the divisor, then following the standard divide routine to get a more accurate divide result. Because the divisor, which is 1+GK, is always greater than 1, I did not have to account for overflow and was able to optimise the divide routine to a 24-bitx16-bit scheme. Also because divisor is always positive, the sign bit is only checked in the dividend, which allowed me to optomize the code. The version of the 24x16 divide can be found in the source code for the neuron program. A general signed 16x16 divide which returns a 16-bit fractional result is given here.
Suprisingly, creating an exponential function in binary had less head-aches than the divide routine. The idea for this algorithm is to convert the exponential from base-e to base-2. This is done by dividing the exponent by the natural logarithm of 2. The resulting value is the 2^x needed to get the same value as the original exponential. The integer part represents a simple right shift (it is a right shift since, in this case, it is always a negative exponential—if it were a positive, it would be a left shift). The fractional part of the new exponent is used compared to a linear interpolation (of 5 points) of the 2^x function for 0 < x < 1 and then multiplied by the right-shifted value from before. This code is also located in the source. A general expoential can be found here.