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 StatesPosts: 172 |
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: GermanyPosts: 1141 |
Hi Jeff, this could help if I understand U right? a xor 255
Michael |
||||
Oldbitcollector Senior Member Joined: 16/05/2014 Location: United StatesPosts: 172 |
That helped! Thanks! My Propeller/Micromite mini-computer project. |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2794 |
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 . . . . . WW For everything Micromite visit micromite.org Direct Email: whitewizzard@micromite.o |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1141 |
@Oldbitcollector You're welcome! |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2794 |
Two different interpretations of 'reversal'!! For everything Micromite visit micromite.org Direct Email: whitewizzard@micromite.o |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2794 |
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 StatesPosts: 535 |
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 StatesPosts: 172 |
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: AustraliaPosts: 5923 |
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: GermanyPosts: 1141 |
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 KingdomPosts: 2794 |
@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: AustraliaPosts: 290 |
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: GermanyPosts: 1141 |
@WW I do not want to argue, but I understand this issue in a different way. Anyway, I thing any code will help our community. 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 KingdomPosts: 2794 |
@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: GermanyPosts: 1141 |
@WW good to share code & tips . . . YES! edit: that's why I like TBS and his creative visitors. regards Michael |
||||
ajkw Senior Member Joined: 29/06/2011 Location: AustraliaPosts: 290 |
@twofingers 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: AustraliaPosts: 5923 |
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: GermanyPosts: 1141 |
@Jim, that's of course correct! Michael |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1141 |
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! Michael |
||||
Page 1 of 2 |
Print this page |