|
|
Proposed Plan for adding Nano Meters into PCBNEW as the Board Internal Unit===========================================================================
Author: Dick Hollenbeck November 25, 2011
Introduction:============
This document sketches out a plan to move KiCad's PCBNEW program from deci-milinternal units to nanometer internal units. The changes to the code aresignificant enough to describe the basic process before the work is started.
Definitions:===========
*) Board Internal Units (BIU). This is a pseudonym for the engineering unitsused by a BOARD when it is in RAM, and only when it is in RAM. BIU isessentially equal to nanometers in the future, and equal to deci-mils currently.A BIU refers typically to a measurement or a position on an XY grid, and this isbecause this grid is dimensioned in BIUs along both its X and Y axes. Both X andY can be either positive or negative on this grid. In the case of measurementsor scalars, there can be a radius, a diameter, a distance (length), and all ofthese can and should be expressed in BIUs, so long we are in RAM and so long aswe are talking about the objects within the class BOARD instance. One specialfeature of XY points within the BIU coordinate system is that they will alwaysbe integers. In contrast, distances and other forms of measurements are notsubject to the same limitation by the very nature of physics. Coordinates arealways integers because we used signed whole numbers to represent these BIUcoordinates.
*) Snap grid. A snap grid is a subset of the full set of possible XY coordinatesin the BIU coordinate system. Points falling on the snap grid are evenly spacedin X and Y directions and are some integer multiple apart in this 2D space,greater than one BIU.
Assumptions:===========
a) It is ok to modify the board file format in order to handle the BIU change.
b) Boards saved on disk in the new format will not be readable using old software.
c) Since we have no backwards compatibility obligation (see b) above), we canmake significant changes to the file format while we have this disruptionopportunity.
General:=======
With nano meters as the Board Internal Unit (BIU), a 32 bit signed integer canonly hold about 2 meters of positive length and 2 meters of negative length.Moreover, because most of the bits within a 32 bit integer can be "used up" tohold a typical length within a board, it is very likely that if pure 32 bitinteger math is done, such as the multiplication of two integers in order tocalculate a hypotenuse, then there will be an overflow within the 32 bitinteger. (Another way to think of the BIU acronym is "Board Integer Unit" insteadof as Board Internal Unit, to pave the way for the BFU, discussed below.)
Therefore all intermediate products, quotients, trig, and exponentialcalculations should be done using some larger floating point type. By larger,bitness or number of bits is meant. Distances that do not have to be roundedback to integer immediately can and should stay in the larger floating point"value container" for as long as possible. The typedef name of this floatingpoint type is BFU (Board Float Unit). The engineering units on a BFU are thesame as on a BIU. A typedef is nice so that we can toggle between double and"long double" for various compilations, and so that when performing casts, theseare brief textual expressions.
Format Strings:==============
Because all our save to disk functions use printf() style format strings, wediscuss how to construct a format string in the most usable way. There should bea printf() style format string like "%.6g" for the BFU (cast to a hard codeddouble) enclosed within a #define and its name should be FMT_ENG. This formatstring will be used at least for saving BOARD and MODULE files, and perhapsmore.
FMT_ENG stands for "format string for ENGineering units used out in the file". Adefine is needed simply to provide consistency across many sites of usage. BIUswill be scaled before being written to disk in most every case, and sincescaling is a multiplication, it means casting one of the factors to BFU, andthen this product is output with a printf() style function using the FMT_ENGstring segment.
That is, the FMT_ENG will be suitable for use with a BFU type. When BFU is setto double, then FMT_ENG will be set to "%.6g". When BFU is set to long doublethen FMT_ENG will be set to "%.6Lg". For example:
#if USE_DOUBLE_BFUtypedef double BFU;#define FMT_ENG ".%10g"#elsetypedef long double BFU;#define FMT_ENG ".%10Lg"#endif
A format string can then be built up using compile time concatenation ofstrings, like this:
fprintf( fp, "Value: " FMT_ENG " " FMT_ENG "\n", BFU( biu1 * scale), BFU( biu2 * scale ) );
The 3rd and 4th arguments are BFUs, and the casting is done after the multiplysince the scaling factor is already a double or perhaps even a long double. Thefinal argument needs to match the format string, so the final product is wrappedin a BFU, which could actually be a truncation down to 64 bit float from 80 bitfloat. The key points are: the calculation must be done in a float type at leastas bit-wide as BFU, and that the value actually passed to fprintf() must matchthe format string.
Choosing BIU Units:==================
BIUs are only used when a BOARD or MODULE is in RAM. A BIU is equivalent toeither a 1) deci-mil or 2) nanometer, depending on how the source code iscompiled. It is not a runtime decision. Form 1) is needed only during thepreparation phase of the source code transition to nanometers. After thetransition, only nanometers will be used in the compilation. No runtimeswitching is needed or wanted. Again, BIUs can only be one or the other for agiven compilation, and this will swing based on a single #define.
Eventually we may want to actually use "BIU" as our integer type in source codefor those lengths which pertain to the board coordinate space. This would giveus the ability to easily modify it, go to a larger bitness, make the source codemore readable, and keep the type information out of the variable name. Thiswould mean having a point and/or size class based on BIU as the containedinteger types. This is a nice to have, but not immediately mandatory.
There will be a number of places within the source code which will have to bedoctored up to use the BFU casting. It will take some time to find all thesesites. During this time it should be possible to continue using deci-mils as theBIU for source compilation.
There are a quite a number of path ways in and out of BOARDs and MODULEs. Mosteveryone of these pathways involve conversion or scaling of BIUs. An example ofa pathway in is a BOARD disk file loading function. An example of a pathway outof a BOARD is a disk file saving function. Likewise for MODULEs. We cancharacterize the load and save functions by their source and destinationrepresentations of lengths.
BOARDs and MODULEs will soon have a new format, which is basically the existingformat expressed in um or nm (TBD) rather than in deci-mils. For discussion, wewill say this new format is in mm, even though it may end up being in um. Inanother year or two we will switch to s-expressions, or sooner if there is avolunteer.
Here are the required immediate need BOARD load functions:
1) Legacy to deci-mil loader. This loader uses a floating point scaling factorof unity, since destination is a RAM BOARD using deci-mils as its BIU.
2) Legacy to nanometer loader. This loader uses a floating point scaling factorof 2540, since destination is a RAM BOARD using nanometers as its BIU, andthe source format is using deci-mils.
3) mm to nanometer loader. This loader uses a floating point scaling factorof 1000000, since the destination is a RAM BOARD using nanometers as its BIU.
There is no need for a nm to deci-mil loader. (Once somebody saves a file in thenew format, that format is used going forward, or its backup in the old format.)
Now duplicate the above 3 loader types for MODULEs.
Here are the required immediate need BOARD save functions:
1) deci-mil to deci-mil, using a floating point scaling factor of unity. Itshould be possible to use trailing zero suppression on the deci-mils to get aBOARD that is identical to an old BOARD, and this can be used to test the newsave function, using "diff" with whitespace ignore. This saver is only in playwhen the BIU is compiled to be deci-mils.
2) nanometer to mm, using a floating point scaling factor of 1/1000000. Thissaver is only in play when the BIU is compiled to be nanometers.
Now duplicate the above 3 saver types for MODULEs.
New BOARD and MODULE files will have a new field in them identifying theengineering units used, say mm.
In actuality, the source code to all 3 loaders, and to all 3 savers can be thesame source code with a single variable in each case for scaling.
All 6 loaders and all 6 savers should be written in parallel with existingloaders and savers, so that we can toggle usage back and forth between the twofor awhile. This means we do not gut existing savers and loaders until the newones are debugged and stable.
The new savers and loaders are to be done in the context of a plug-inarchitecture, described elsewhere.
Angles and Rotations:====================
Internally we are switching from using an int to hold 1/10 of degrees angle to atypedef called DEGREES. The allowed values that DEGREES can hold will beenforced by the user interface policy, decided elsewhere. The engineering unitsin the DEGREES type is degrees, no longer tenths of degrees.
/// a value used to hold rotations or angles.typedef double DEGREES;
User Interface Changes:======================
All these changes have to be done in a way where they hinge on one #ifdef.
*) The grid dimension choices will have to be changed.
*) The drawing routines will have to be changed to handle the case that BIU iscompiled to be nm. Work towards getting legacy drawing code capable of handlinga compile time #define to control a single scaling factor. Only the scalingfactor should need be changed in the final state. Up until then, the workrequired is to inject the BFU casting where needed along with the scalingfactor(s).
*) Remove any funky imperial to metric conversion functions which tried to hide/maskproblems with lack of BIU precision.
*) There may be some fix ups pertaining to "near enough" type testing involvingthe user's mouse position, other than bounding box hit testing which should takecare of itself (in BIUs). This has more to do with near-ness to a line typetests, and these are thought to best be done in screen coordinates anyway, notBIUs.
Work Tasks:==========
*) Within PCBNEW, find math expressions involving BIUs and cast them to BFUsearly enough so that the compiler generates code in the BFU realm.
*) Find a way to consistently round values from BFUs back to BIUs, and put thatcode in place. This could be done using a set accessor on a BIU, or other way.
*) Fix the User Interface issues mentioned above, and more found later.
*) Write the 4 new load and save functions. Vladimir recently committed codewhich can be a starting point for some of these functions, except that the newones should reside within a PLUGIN object where we can save the scaling factorvariable as a member field of the plugin. In order to meet the requirementsof all 3 board loaders, we may have to dynamically change the scaling factordepending on what we find in the *.brd file and how the plugin is compiled.
|