*
/*
SF port of C code adapted from int64.c
original code:
Copyright (c) Stuff, February 2013
Use of this program, for any purpose, is granted by the author,
Harry W (1and0), as long as this copyright notice is included in
the source code or any source code derived from this program.
The user assumes all responsibility for using this code.
*/
*)
Device = 18F14K22
Clock = 64
Include "SUART.bas"
Include "convert.bas"
include "system.bas"
public type
uint8_t = byte,
uint16_t = word,
uint32_t = longword,
int16_t = integer,
int32_t = longint
public structure uint64_t
b(8) as byte
L as b(0).asword // uint16_t
H as b(2).asword // uint16_t
U as b(4).asword // uint16_t
M as b(6).asword // uint16_t
LW as b(0).aslongword // uint32_t
HW as b(4).aslongword // uint32_t
MW as b(2).aslongword // uint32_t
end structure
(*
//--------------------------------------------------------------
Integer 64/32-bit Unsigned Division With Remainder
quotient = dividend / divisor
remainder = dividend % divisor
where
dividend = quotient * divisor + remainder
Arguments:
dividend = 64-bit unsigned integer to be divided
divisor = 32-bit unsigned integer being divided by
remainder = pointer to 32-bit unsigned integer holding the remainder
Return Values:
The function returns a 64-bit unsigned integer of the quotient and
a pointer to a 32-bit unsigned integer of the remainder.
Method:
* This division algorithm is known as long division, the same one we learned
in elementary school. It shifts gradually from the left to the right end
of the dividend, subtracting the largest possible multiple of the divisor
at each stage; the multiples become the digits of the quotient, and the
final difference is the remainder. The binary implementation is to
repeatedly double the quotient. When the divisor is less than or equal to
the dividend, subtract the divisor from the dividend and set the least
significant bit of the quotient to '1'. Then halve the divisor and repeat
the shift-and-subtract until 64 bits are computed. The remaining dividend
is the remainder.
//--------------------------------------------------------------
*)
public function div6432u(byval dividend as uint64_t, byval divisor as uint32_t, byref remainder as uint32_t) as uint64_t
dim
num_bits as uint8_t,
divisorL as uint32_t,
quotient as uint64_t
quotient.HW = 0
quotient.LW = 0
remainder = 0
if (divisor = 0) then
result = quotient
exit
endif
num_bits = sizeof(uint32_t)*8 + 1
while (divisor.bits(31) = 0) // divisor & (1UL<<31)
divisor = divisor << 1
num_bits = num_bits+1
end while
divisorL = 0
repeat
quotient.HW = quotient.HW << 1
if (quotient.LW.bits(31) = 1) then // quotient.LW & (1UL<<31)
quotient.HW.bits(0) = 1
endif
quotient.LW = quotient.LW << 1
if ((divisor < dividend.HW) or
((divisor = dividend.HW) and (divisorL <= dividend.LW))) then
dividend.HW = dividend.HW - divisor
if (dividend.LW < divisorL) then
dividend.HW = dividend.HW-1
endif
dividend.LW = dividend.LW - divisorL
quotient.LW.bits(0) = 1
endif
divisorL = divisorL >> 1
if (divisor.bits(0) = 1) then
divisorL.bits(31) = 1
endif
divisor = divisor >> 1
num_bits = num_bits - 1
until (num_bits = 0)
remainder = dividend.LW
result = quotient
end function
//
//
const
ArraySize = 16,
HexArray(ArraySize) as byte = ("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F")
dim B as uint32_t
dim N as uint64_t
dim istring as string
dim remainder as uint32_t
dim b64 as uint64_t
Dim hValue,lValue As byte // default is 23 chars SetAllDigital
//
// compute N = (B * 2^32)/125000000
//
main:
uart.SetTX(PORTA.0)
uart.SetRX(PORTA.5)
uart.SetBaudrate(sbr4800)
uart.SetMode(umiNVERTED)
UART.readterminator="N"
while true
uart.read(istring)
B = strtodec(istring)
b64.HW = B // b64 = (B * 2^32)
b64.LW = 0
N = div6432u(b64, 125000000, remainder)
if remainder>=62500000 then //round the result
N.LW=N.LW+1
endif
hvalue=N.b(3)/16
lValue=N.b(3) AND 15
write(HexArray(hValue),Hexarray(lvalue))
hvalue=N.b(2)/16
lValue=N.b(2) AND 15
write(HexArray(hValue),Hexarray(lvalue))
hvalue=N.b(1)/16
lValue=N.b(1) AND 15
write(HexArray(hValue),Hexarray(lvalue))
hvalue=N.b(0)/16
lValue=N.b(0) AND 15
write(HexArray(hValue),Hexarray(lvalue))
wend