Converting mm to thou and back

Discuss all aspects of programming here. From 8-bit through to modern architectures.
Post Reply
julie_m
Posts: 17
Joined: Wed Jul 24, 2019 8:53 pm
Location: Derby, UK
Contact:

Converting mm to thou and back

Post by julie_m » Wed Aug 14, 2019 10:58 pm

BCP uses a grid based on thousandths of an inch (thou) to fit neatly with DIL packages, but sometimes we need to convert to or from millimetres. To keep things "integer-y" I decided to use hundredths of a millimetre as the base unit (this gives a slightly better resolution). I already have a 16-bit multiply subroutine that actually calculates a 32-bit product. So all we need do is work with values that are 65536 times bigger than we need, and then our answer will be in the upper two bytes. Knowing that 1 inch = 25.4mm:
  • Multiply hundredths of a millimetre by &64CA and take the top 2 bytes of the 32-bit product to get thousandths of an inch.
  • Multiply thousandth of an inch by &A290, shift the 32-bit product left another 2 places and take the top 2 bytes to get hundredths of a millimetre.
The integer results are within tolerance over the full +/-327.67mm. / 12.9in. usable range.

We can test this with a program to step through all possible inputs and work out the error in each conversion as compared to BASIC's floating point calculations as follows:

Code: Select all

*| THOUSANDTHS OF AN INCH TO HUNDREDTHS OF A MILLIMETRE
*| BEST RUN IN AN EMULATOR AT HIGH SPEED!
   10REM S% => scroll control
   20REM Q% => quit after printing figures
   30REM V% => print comparison results
   35REM O% => print every value
   40*KEY0MODE7|ML.|N|M
   50MODE7
   60IFS%VDU14
   70thou_to_mmx100=2.54
   80thou_to_mmx100A=16384*thou_to_mmx100
   90PRINT"1th = ";thou_to_mmx100;" * 0.01mm."
  100PRINT"1th = ";thou_to_mmx100A;" * 163.84mm."
  110T%=INTthou_to_mmx100A+1
  120PRINT"1th = ";T%;" * 163.84mm. approx."
  130PRINT"]";STRING$(37,"_");"["
  140IFQ%END
  150N%=0:B%=0:Z%=0
*| C%(E%+5) IS THE NUMBER OF VALUES WITH A CONVERSION ERROR OF E%
  160DIMC%(10)
  170FORE%=-5TO5
  180C%(E%+5)=0
  190NEXTE%
*| -8.96 INCHES TO +10.235 INCHES IN 0.005IN STEPS IS BCP WORKING RANGE
  200FORI%=-8960TO10235STEP5
  210M%=INT(thou_to_mmx100*I%)
  220A%=I%*T%DIV16384
  230IFV%PRINT;M%;"=";A%;"? ";M%=A%;"  ";N%;"=";B%;"? ";N%=B%
  240E%=A%-M%
  250IFE%>5 E%=5
  260IFE%<-5 E%=-5
  270C%(E%+5)=C%(E%+5)+1
  280Z%=Z%+1
  290IFO%AND(M%=A%ANDN%=B%ORM%<>A%ANDN%<>B%)GOTO320
  300PRINTI%,M%,A%;
  310IFM%=A%PRINT"  ="ELSEPRINT
  320N%=M%:B%=A%
  330NEXTI%
  340PRINT
  350PRINT"Conversion factor=";T%;" &";~T%
  360FORE%=-5TO5
  370PRINT"Error=";E%;" : Count=";C%(E%+5);" (";100*C%(E%+5)/Z%;"%)"
  380NEXTE%
  390PRINT"Total count=";Z%
Which produces the following measurement of accuracy:
thou_to_mm.png
conversion thou->mm test
thou_to_mm.png (5.74 KiB) Viewed 60 times
and we can also test conversion the other way:

Code: Select all

*| HUNDREDTHS OF A MILLIMETRE TO THOUSANDTHS OF AN INCH
*| DEFINITELY BEST RUN IN AN EMULATOR AT HIGH SPEED
   10REM S% => scroll control
   20REM Q% => quit after printing figures
   30REM V% => print comparison results
   35REM O% => print every value
   40*KEY0MODE7|ML.|N|M
   50MODE7
   60IFS%VDU14
   70mmX100_to_thou=.3937
   80mmX100_to_thouA=mmX100_to_thou*65536
   90PRINT"0.01mm = ";mmX100_to_thou;"thou."
  100PRINT"0.01mm = ";mmX100_to_thouA;" * 65536 thou."
  110T%=INTmmX100_to_thouA+1
  120PRINT"0.01mm = ";T%;" * 63336 th. approx."
  130PRINT"]";STRING$(37,"_");"["
  140IFQ%END
  150J%=0:B%=0:Z%=0
  160DIMC%(10)
  170FORE%=-5TO5
  180C%(E%+5)=0
  190NEXTE%
*| MAKE THE STEP BIGGER TO FINISH RUNNING ON REAL HARDWARE!
  200FORM%=-32768TO32767STEP1
  210I%=INT(mmX100_to_thou*M%)
  220A%=M%*T%DIV65536
  230IFV%PRINT;I%;"=";A%;"? ";I%=A%;"  ";J%;"=";B%;"? ";J%=B%
  240E%=A%-I%
  250IFE%>5 E%=5
  260IFE%<-5 E%=-5
  270C%(E%+5)=C%(E%+5)+1
  280Z%=Z%+1
  290IFO%AND(I%=A%ANDJ%=B%ORI%<>A%ANDJ%<>B%)GOTO320
  300PRINTM%,I%,A%;
  310IFI%=A%PRINT"  ="ELSEPRINT
  320J%=I%:B%=A%
  330NEXTM%
  340PRINT
  350PRINT"Conversion factor=";T%;" &";~T%
  360FORE%=-5TO5
  370PRINT"Error=";E%;" : Count=";C%(E%+5);" (";100*C%(E%+5)/Z%;"%)"
  380NEXTE%
  390PRINT"Total count=";Z%
This time, it is having to do many more calculations, and the result is an n→1 mapping since 1 thou < 0.01 mm.:
mm_to_thou.png
conversion mm->thou test
mm_to_thou.png (5.78 KiB) Viewed 60 times
Finally, one last screenshot in which I bodged the program to convert thous to millimetres, and then straight back again:
thou_mm_back.png
conversion thou->mm->thou test
thou_mm_back.png (5.87 KiB) Viewed 59 times
Last edited by julie_m on Sat Aug 17, 2019 1:01 am, edited 4 times in total.

Post Reply