![]() |
Forum Index : Microcontroller and PC projects : PIO UINT32 counter to INT64 courtesy of Gemini
Author | Message | ||||
PhenixRising Guru ![]() Joined: 07/11/2023 Location: United KingdomPosts: 1360 |
' --- GLOBAL VARIABLES (Must retain their values between counter readings) --- ' Declare these at the top of your program or in a GLOBAL block. DIM LastRaw32BitReading AS INTEGER ' Stores the previous 32-bit counter reading (0 to 4,294,967,295) DIM TotalSigned64BitCount AS INTEGER ' The accumulated 64-bit signed counter value DIM CurrentRaw32BitReading AS INTEGER DIM SignedDelta AS INTEGER ' --- INITIALIZATION (Run ONCE at program startup) --- ' Read the very first value of the counter to set the baseline. ' This assumes the counter starts at 0 or a known, consistent value. ' If the counter's initial state is truly arbitrary, you might need a reset mechanism. TotalSigned64BitCount = 0 ' Start the total count at zero LastRaw32BitReading = EXT_READ_32BIT_COUNTER_FUNCTION() ' REPLACE with your actual function to read the 32-bit counter ' --- COUNTER READING AND UPDATE LOGIC (Place this inside your main loop or timer interrupt) --- ' This block should be executed every time you want to update the counter. ' 1. Read the current 32-bit unsigned value from your external counter. CurrentRaw32BitReading = EXT_READ_32BIT_COUNTER_FUNCTION() ' REPLACE with your actual function ' 2. Calculate the raw difference. ' MicroMite BASIC performs this subtraction using 64-bit signed arithmetic. ' If the 32-bit counter has rolled over or under, this 'SignedDelta' will ' be a large positive or negative 64-bit number. SignedDelta = CurrentRaw32BitReading - LastRaw32BitReading ' 3. Correct for 32-bit unsigned rollovers/roll-unders. ' This is the core "magic" that converts the raw 64-bit difference ' into the correct signed 32-bit delta, accounting for the 32-bit wrap. ' Constants: ' &H100000000 = 2^32 = 4,294,967,296 (the full range of a 32-bit unsigned int) ' &H80000000 = 2^31 = 2,147,483,648 (the value of the 32-bit sign bit) ' If SignedDelta is a large positive number (e.g., Last=10, Current=4294967290, delta=4294967280) ' This indicates a roll-under from a small value to a large value (e.g., 10 -> -6) IF SignedDelta > 2147483647 THEN ' If delta > (2^31 - 1) SignedDelta = SignedDelta - 4294967296 ' Subtract 2^32 to make it correctly negative ' If SignedDelta is a large negative number (e.g., Last=4294967290, Current=10, delta=-4294967280) ' This indicates a roll-over from a large value to a small value (e.g., -6 -> 10) ELSEIF SignedDelta < -2147483648 THEN ' If delta < -2^31 SignedDelta = SignedDelta + 4294967296 ' Add 2^32 to make it correctly positive END IF ' 4. Add the corrected signed delta to the total 64-bit counter. TotalSigned64BitCount = TotalSigned64BitCount + SignedDelta ' 5. Update LastRaw32BitReading for the next iteration. LastRaw32BitReading = CurrentRaw32BitReading ' --- TotalSigned64BitCount now holds the accurately extended signed 64-bit counter value --- ' PRINT "Extended 64-bit Counter: "; TotalSigned64BitCount Stripped down and with short VAR names, ~60µS on RP2350 @378MHz |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5058 |
On RP2040 @ 252MHz x%=(x%<<32)/2^32 46us If you define 2^32 up front as constant const z%=2^32 x%=(x%<<32)/z% 38us Volhout Edited 2025-07-10 19:28 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
PhenixRising Guru ![]() Joined: 07/11/2023 Location: United KingdomPosts: 1360 |
Harm, Yeah that's really quick ![]() However, I should've explained better; the one that I posted extends the counting range from: INT32 (32-bit signed integer): Minimum value: −2,147,483,648 Maximum value: 2,147,483,647 To: INT64 (64-bit signed integer): Minimum value: −9,223,372,036,854,775,808 Maximum value: 9,223,372,036,854,775,807 This could be very useful for a high-speed spindle that needs to run for thousands of years and not lose position due to rollover ![]() |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |