View Single Post
Old 06-13-2015, 10:18 AM   #67 (permalink)
bobski
EcoModding Apprentice
 
Join Date: Jan 2010
Location: Newark, DE
Posts: 143

'91 CRX - '91 Honda CRX DX
90 day: 34.91 mpg (US)
Thanks: 0
Thanked 14 Times in 14 Posts
No, ledDisplayNumerical() is a subroutine. You use it as a command in your main program (loop) as you would digitalRead(), analogWrite() and so forth.
When you execute a subroutine, the program execution jumps down to the subroutine (the scripts you were referencing earlier), runs through the code once (or until it hits a return command) and then goes back and continues where it left off. Each time a subroutine is called, a new instance of the routine is created - nothing is carried over from the last run through unless it is passed in as an argument (explained below) and back out as a return, or the data is stored in a global variable (an int or byte or string or whatever declared at the top of your file, before setup() or loop(). If a variable is declared within a subroutine (or in its list of arguments), it is unique to that instance of the routine and is lost once the routine finishes.
Subroutines can call other subroutines (as is the case here), in which case they sort of stack up. When the sub-subroutine finishes, it goes back the the line that called it in the original subroutine. Once the original subroutine finishes, it goes back to the main program.
Subroutines can even call themselves (known as a recursive routine), though they need to be coded carefully to be sure the routine actually finishes doing what it's supposed to and not get stuck in an infinite loop of calling itself. Consideration also needs to be given to available memory. The variables used internally by a subroutine use RAM until the subroutine completes, so a recursive routine with many variables and sub-instances can quickly fill available RAM.
You pass arguments (relevant variables, strings, constants and such) to the subroutine in the parenthesis following the command. If the subroutine has more than one argument (inbound piece of data), they're separated by commas. In the case of ledDisplayNumerical(), the byte and ints in the first line are telling you what the subroutine is expecting as far as the kind of data you're handing it, and what names it gives those various pieces of data within the subroutine.

Example:
Code:
void LEDnumOdoDistance()
{
  ledDisplayNumerical(firstSaa1064Address, (10*vssPulseCount)/vssPulsesPerUnitDistance, 0x32);
}
LEDnumOdoDistance() is a subroutine that gets called by the main program (in a non-obvious way, i'll get to that). It only has one line of code that it executes:
Code:
ledDisplayNumerical(byte addr, int value, byte forceDig_dpSelect);
which has three arguments. "firstSaa1064Address" is a constant (stored in flash rather than RAM) byte (8 bits, written in hex as 0x##) which equals 0x70 as you seem to have figured out. "value" is an integer number that you want to display. If you want to display a float (something with a decimal point), you need to multiply it by 10 or 100 or whatever to get an integer you can display, then add the appropriate decimal point by flipping the appropriate bit of "forceDig_dpSelect".
Assuming the original subroutines (ledDisplayNumerical(), findSegs() and saa1064Update() ) are still intact and working, that should put your number on the display.

Going back to the non-obvious way that LEDnumOdoDistance() gets called, there's a constant declared at the top of the program:
Code:
const fptype LEDrenderPage [numLEDpages] = {&LEDnumBlankDisplay, &LEDnumOdoDistance, &LEDnumVehicleSpeed};
LEDrenderPage is an array - a variable name with multiple slots for information, though they all have to be the same type - int, byte, string or whatever. In this case, a custom data type is used: fptype. Don't ask me how that data type creation works - I begged the line of code out of a more knowledgable programmer. Anyway fptype lets you store a list of subroutines. To get the data back out of an array, you use it like a variable, but with [slot#] after the variable name: arrayName[4] would give you element 4 (5th slot, 0 is the 1st slot) in the array named "arrayName". You can also use a variable to select which array slot you want to access: arrayName[elementNumber].
In the actual program, you'll see:
Code:
LEDrenderPage[currentLEDPage]();
fptype isn't just a list of the names of subroutines, but their actual addresses. When you select an element from LEDrenderPage, it tells the processor where to go to execute that code. The parenthesis after the array name gets the processor to actually go there and run the subroutine.

All this lets you control what piece of data is being gathered, processed and displayed on the LED display by changing the value of currentLEDPage. The same thing is done with the main LCD display. Further, a 2-dimensional array (think a grid of slots - you feed it two numbers, the row and column of the grid, to get the piece of data you want) is used for the buttons' functions. The columns are the physical buttons 1 through 4 and a null (no buttons pressed) position. The rows are what page is being sent to the main display. That lets you change what the buttons do depending on the page that's being displayed... It would be silly to have a button dedicated to resetting the odometer when you're looking at a page with only MPG and fuel flow rate on it.
  Reply With Quote
The Following User Says Thank You to bobski For This Useful Post:
Theitguy (06-13-2015)