Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 15:12 19 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Bitwise reversal of a hexidemal number?

     Page 1 of 2    
Author Message
Oldbitcollector

Senior Member

Joined: 16/05/2014
Location: United States
Posts: 172
Posted: 08:57am 23 Aug 2014
Copy link to clipboard 
Print this post

Can someone help me with an elegant method of doing a bitwise reversal of a hexadecimal number in MMBASIC?

Right now I'm looking at..

Convert hex number to binary equivalent. BIN$
Perform bitwise NOT. (FOR/NEXT LEN(VAl$) LOOP WITH MID$) (swap 1's and 0's)
Convert back to hex. A$="&B"+VAL$ / VAL(A$)

It's starting to get long and messy. Surely there is an easier way?

Thanks in advance.

Jeff


My Propeller/Micromite mini-computer project.
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1141
Posted: 10:23am 23 Aug 2014
Copy link to clipboard 
Print this post

Hi Jeff,

this could help if I understand U right?
a xor 255


Michael

 
Oldbitcollector

Senior Member

Joined: 16/05/2014
Location: United States
Posts: 172
Posted: 10:46am 23 Aug 2014
Copy link to clipboard 
Print this post

That helped!

Thanks!

My Propeller/Micromite mini-computer project.
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2794
Posted: 10:52am 23 Aug 2014
Copy link to clipboard 
Print this post

Hi Jeff,

Why not use a lookup table? It is quite easy to achieve but may seem difficult to understand. Here goes:

Each nibble has only one of 16 possibilities (0-F) - so store the 'reverse' of these 16 values in an array.
For example:
0 maps to 0 (i.e. 0000 becomes 0000)
1 maps to 8 (i.e. 0001 becomes 1000)
2 = 4
3 = C [12]
4 = 2
5 = A [10]
6 = 6
7 = E [14]
8 = 1
9 = 9
A = 5
B = D [13]
C = 3
D = B [11]
E = 7
F = F [15]

So store these 'reverse values in an array, the original nibble value as the array index, and the 'reverse' value as the data i.e. REV(0)=0, REV(1)=8, REV(2)=4 . . . . REV(10)=5, REV(11)=13 . . .

You could use DATA and a LOOP to READ these values but there are only 16 values so you may as well just 'hardcode' these values into the array.

Now to perform a 'reversal' it just becomes a simple matter of taking the first nibble in the original hex value, and use this as the index to get the 'reverse' value from the array, then take the second nibble in the original hex value, get the 'reverse' value from the array, and now recompile the reverse number.

There are many ways to do this, but I would do something like the following five lines of code:

REV(0)=0: REV(1)=8: REV(2)=4 . . . . REV(10)=5: REV(11)=13
x=234 'here x contains the value to reverse i.e. 234 decimal = 0xEA = 1110 1010
LNibb = (x AND 240)/16 ' i.e. 14 = 1110
RNibb = x AND 15 ' i.e. 10 = 1010
RevX = REV(RNibb)*16 + REV(LNibb) 'i.e. REV(10)*16 + REV(14) = 5*16 + 7 = 87 dec = 0x57 = 0101 0111

The above allows any length of number to be reversed with a bit more logic to loop through nibbles

Hope this helps . . . . .

WWEdited by WhiteWizzard 2014-08-24
For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1141
Posted: 10:56am 23 Aug 2014
Copy link to clipboard 
Print this post

@Oldbitcollector

You're welcome!
Edited by twofingers 2014-08-24
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2794
Posted: 10:58am 23 Aug 2014
Copy link to clipboard 
Print this post

Two different interpretations of 'reversal'!!
For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2794
Posted: 11:17am 23 Aug 2014
Copy link to clipboard 
Print this post

Did you need 'Inverting' or 'reversal'?

a XOR 255 is 'Inverting', my code is 'bit reversal'

If you need inverting, why not use NOT a ?

WW
For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
hitsware
Guru

Joined: 23/11/2012
Location: United States
Posts: 535
Posted: 11:44am 23 Aug 2014
Copy link to clipboard 
Print this post

For MSB to LSB type 'inversion' / Tassy Jim
[code]
main:
INPUT x
PRINT bitreverse(x, 16)
GOTO main

FUNCTION bitreverse(num, k)
' reverse bit order
' num = integer to reverse
' k = number of bits (8 or 16)
LOCAL n
FOR n = 1 TO k
IF (num AND 2^(n-1)) > 0 THEN
bitreverse =bitreverse+ 2^(k-n)
ENDIF
NEXT n
END FUNCTION
[/code]
 
Oldbitcollector

Senior Member

Joined: 16/05/2014
Location: United States
Posts: 172
Posted: 11:46am 23 Aug 2014
Copy link to clipboard 
Print this post

As it turns out, I needed 'bit reversal' -- Seems like a command to do this might be a handy operator to have in future versions of the Micromite.

WW, while your code was exactly what I needed, I decided to handle the conversion on the other end of my project, since it made a lot more sense to do so.

Thanks guys. I've furthered my education today in two platforms. Cool stuff!

Jeff

My Propeller/Micromite mini-computer project.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5923
Posted: 12:06pm 23 Aug 2014
Copy link to clipboard 
Print this post

Safer to call it 'bit order reversal'.
Might save some confusion.

I get confused enough without any help...

Jim
VK7JH
MMedit   MMBasic Help
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1141
Posted: 01:43am 25 Aug 2014
Copy link to clipboard 
Print this post

I know the issue is already solved.
In some cases - bigger numbers - you will need the mask lenght for Xor.
This is a small code snippet to demonstrate.


' MMBasic 4.5 for Maximite/Duinomite
' twofingers at TBS 08-2014
' No warranty, provided at your own risk.
'
' Purpose:
' Calculating the mask lenght
' for bitwise inverting of a (positive) number
' Ex.: convert from "0110 0011" to "1001 1100"
' your_number Xor mask (255 = 1111 1111)
'
' This:
' Log(x)/Log(base)
' calculates the logarithm of a number (x) by base (=2 here)
' ************************************************************

x = 0 ' your_number to convert
L = 1 ' mask lenght wanted
mask = 255 ' binary mask wanted
base = 2 ' binary representation of numbers

Do
L=1:If x>0 Then L=Int(Log(x)/Log(base))+1 ' binary lenght of x
mask=2^L-1 ' Calculate the mask

' --- display 32x results (just demonstrate) ---|
S$=String$(L,"0") ' leading fill zeros
Print x,@(6*5,MM.VPos)L,@(6*12,MM.VPos)Bin$(x);
Print @(6*24,MM.VPos)Right$(S$+Bin$(x Xor mask),L),@(6*32,MM.VPos)mask
x=x+1
' ------------- end demonstration --------------|

Loop While x<=32


Michael
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2794
Posted: 01:51am 25 Aug 2014
Copy link to clipboard 
Print this post

@TwoFingers,

What you are performing is a simple NOT function i.e. bit invert. The actual requirement was for bit-order-reversal. So your example number of 0110 0011 would need to become 1100 0110

Just for reference there is a NOT command in MMBasic so there is no need to perform an XOR 255 (not that its wrong of course!)

WW
For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
ajkw
Senior Member

Joined: 29/06/2011
Location: Australia
Posts: 290
Posted: 03:07am 25 Aug 2014
Copy link to clipboard 
Print this post

This way works for me


byte = 19566 ' binary 0100110001101110

for i = 15 to 0 step -1
newbyte = newbyte + ((2^(15-i)) * ((byte AND (2 ^ i)) > 0))
next i

print newbyte ' Should return 30258 being 0111011000110010




Sample code only, make sure you do your own error testing and that it suits your own purpose!
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1141
Posted: 04:17am 25 Aug 2014
Copy link to clipboard 
Print this post

@WW

I do not want to argue, but I understand this issue in a different way.
  Quote  Perform bitwise NOT. (FOR/NEXT LEN(VAl$) LOOP WITH MID$) (swap 1's and 0's)

Anyway, I thing any code will help our community.

  Quote  Just for reference there is a NOT command in MMBasic so there is no need to perform an XOR 255

Have you tried this? I get always zero if I use a NOT on numbers <> 0 (Duinomite with MMBasic 4.5). Did I misunderstood something? And of course there is the way to use strings.


@ajkw

nice sample!
Will your code work with any (positive and legal) numbers?
(MMBasic limit for positive numbers is 3.40282347e+38)
I made my example to show a way working for an arbitrary (positive) number.

Your code shows a bit-order-reversal as WW wants. But - again -, I thing any code will help our community.

Anybody - me included! - seems confused?

regards
Michael

 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2794
Posted: 05:00am 25 Aug 2014
Copy link to clipboard 
Print this post

@twofingers. Jeff (oldbitcollector) has already confirmed he did indeed mean 'bit-order-reversal' in response to me saying that there were two different interpretations of what he posted initially.

However, you are correct, the NOT command will return 0 as it is NOT a logical operator to 'invert' the binary bits of a number.
It is however used with the IF command i.e. IF NOT condition THEN . . .

I therefore stand corrected about using NOT to invert a binary number and confirm that twofingers is 100% correct for bit 'inverting' a number by using a XOR 255 with each byte (or indeed ajkw's code above).

As twofingers says - good to share code & tips . . .

WW


For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1141
Posted: 05:45am 25 Aug 2014
Copy link to clipboard 
Print this post

@WW

good to share code & tips . . . YES!

edit: that's why I like TBS and his creative visitors.

regards
MichaelEdited by twofingers 2014-08-26
 
ajkw
Senior Member

Joined: 29/06/2011
Location: Australia
Posts: 290
Posted: 01:00pm 25 Aug 2014
Copy link to clipboard 
Print this post

@twofingers

  Quote  Will your code work with any (positive and legal) numbers?


I have only tried it to 16 bits 65535 in decimal.

The 'magic' part I see is also in Hitwares' example above which may well be a quicker routine as it only does part of the maths if the test is true. Also, it is in the MMbasic library in the BIN8 routine (crackerjack).

Time to experiment later on.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5923
Posted: 01:30pm 25 Aug 2014
Copy link to clipboard 
Print this post

  twofingers said  
Will your code work with any (positive and legal) numbers?
(MMBasic limit for positive numbers is 3.40282347e+38)
I made my example to show a way working for an arbitrary (positive) number.


MMBasic uses floating point for numbers.

"The range of integers (whole numbers) that can be manipulated without loss of accuracy is ±16777100."

Any numbers outside that range will have problems.

Jim
VK7JH
MMedit   MMBasic Help
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1141
Posted: 01:49pm 25 Aug 2014
Copy link to clipboard 
Print this post

@Jim,

  Quote  Any numbers outside that range will have problems.


that's of course correct!

Michael
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1141
Posted: 09:19am 16 Feb 2016
Copy link to clipboard 
Print this post

This is a small code example for a bit order reversal using a CFunction.
(Just for training purposes and provided AS IS without any warranty)
(Credit: PeterM, PeterC, Geoff and Jim)


Option default integer
Option explicit

Dim integer l=64, rnum=0, i, tm
Dim integer num=19566 ' just a example number

Print "num (dec):";num, "lenght:"l; "bit"
Print Bin$(num,l)
Print Bin$(borev(num,l),l)

Timer=0
For i = 1 To 1000
rnum=borev(num,l)
Next i
tm= Timer-23

Print "rnum (dec):";rnum
Print tm " us for one borev() function call"

End

' borev(integer_num, bit_lenght)
' "integer_num" can be any MMBasic integer.
' "bit_lenght" can be any integer in the range from 1 to 64.
' returns a unsigned integer of "integer_num" with reversed bit order
CFunction borev
00000000
8CA90004 1D200005 8CAC0000 5520002C 00002021 5180002A 00002021 8C8B0000
8C8D0004 2587FFFF 00002021 00002821 24020001 240A0001 2443FFFF 30680020
006A1804 00603021 0008300A 0008180B 006B1824 00CD3024 00664025 1100000D
24420001 30E80020 00EA1804 00603021 0008300A 0008180B 00831821 00A63021
0064202B 00862021 00803021 00602021 00C02821 00021FC3 0123302A 14C00009
24E7FFFF 1469FFE5 2443FFFF 0182402B 1100FFE3 30680020 10000003 00801021
00002821 00801021 03E00008 00A01821
End CFunction


C source

long long borev(long long *orig, long long *nbits)
{
int i = 1;
unsigned long long reversed = 0;
unsigned long long one_bit = 1;

for(;i<=*nbits;i++)
{
if ((*orig & (one_bit<<(i-1))) > 0)
reversed += one_bit<<(*nbits-i);
}
return reversed;
}


Output (Example on a MM2/MX170/48MHz, MMBasic v5.1)
num (dec): 19566 lenght: 64bit
0000000000000000000000000000000000000000000000000100110001101110
0111011000110010000000000000000000000000000000000000000000000000
rnum (dec): 8516869845311029248
116 µs for one borev function call


Comments & suggestions are welcome!
MichaelEdited by twofingers 2016-02-17
 
     Page 1 of 2    
Print this page
© JAQ Software 2024