# How do we invert a complete byte variable?

#### OLDmarty

##### Senior Member
Hi All,
I thought there used to be an "invert" command for picaxe, but maybe not?

Anyhoo, i wish to invert the logic of a complete byte/variable before sending that value out to a port.
e.g. If i have a variable with "00" stored in it, then i want it to invert to "FF" before sending this data out of a port.

I can see there are toggle and togglebit commands, but it seems i would repeat the toggle 8 times to invert the entire byte.
I thought there would be an easier way to achieve this, almost like a "toggle BYTE" command of some sort.

Should i even consider doing something more mathematical like ANDing my variable with a fixed value like FF or 00 etc?

Any help will be greatly welcomed and thanks in advance.
Marty

#### inglewoodpete

##### Senior Member
I think it's (like) b0 = b0 XOR 255

#### OLDmarty

##### Senior Member
Thanks for that,

I have just discovered this in the manual, under the "Variables - Unary Mathematics" section:

NOT
The NOT function inverts a value.
e.g let b1 = NOT %01110000 (answer b1 = %10001111)

However, it seems i need to know the data value to be inverted and i simply want to invert "whatever" data is within the variable without knowing beforehand what it actually is.

Something like "let b1 = NOT b1" would suit me more, if there's such an option or similar option to apply?

#### Aries

##### New Member
NOT
The NOT function inverts a value.
e.g let b1 = NOT %01110000 (answer b1 = %10001111)
The example is simply that - an example. To demonstrate what is happening, it starts with a value and then inverts it.

Code:
``b0 = NOT b0``
inverts b0, whatever b0 happens to contain at the time.

#### Aries

##### New Member
Oh, and PS ... If you don't know if something will work - try it in the simulator. For example:
Code:
``````for b0 = 0 to 255
b1 = NOT b0
sertxd(cr,lf,#b0," ",#b1)
next b0``````

#### OLDmarty

##### Senior Member
Hi all,

Thanks for all the options.

Thanks Aries, i will use the simulator to help confirm my concepts & coding ;-)

#### OLDmarty

##### Senior Member
Oh, and PS ... If you don't know if something will work - try it in the simulator. For example:
Code:
``````for b0 = 0 to 255
b1 = NOT b0
sertxd(cr,lf,#b0," ",#b1)
next b0``````

Hi again,
I tinkered a little to use HEX numbers and found that the listing bugs out when the hex value reaches 9,A or D.
if i change "for b0 = \$0 to \$F" to "\$FF", then the counting bug comes and goes through various banks of numbers.

Here's the code i used, if anyone wants to try it in their simulator...

Code:
``````for b0 = \$0 to \$F
b1 = NOT b0
sertxd(cr,lf,b0," ",b1)
next b0``````

#### inglewoodpete

##### Senior Member
You syntax is wrong if you're expecting numeric logging. You need to use the following:
Rich (BB code):
``````For b0 = \$0 to \$F
b1 = NOT b0
SerTxd(CR, LF, #b0, " ", #b1)
Next b0``````
I bet you're saying "doh..." now

@IWP:

#### OLDmarty

##### Senior Member
You syntax is wrong if you're expecting numeric logging. You need to use the following:
Rich (BB code):
``````For b0 = \$0 to \$F
b1 = NOT b0
SerTxd(CR, LF, #b0, " ", #b1)
Next b0``````
I bet you're saying "doh..." now
Nope, No DOH's at all lol

I didn't use the "#" symbols because i wanted to see the HEX values instead of the decimal values.

I believe it's a legit bug in the simulator. ;-(

Feel free to try my code-snippet and see if you also have some missing numbers in the listing, like \$9, \$A & \$D like i do.

#### inglewoodpete

##### Senior Member
That's easy! No bugs are present.

Those three codes (characters) are formatting instructions: \$9 is horizontal tab; \$A is line feed and \$D is carriage return. The terminal does the best it can for those three characters.

You need to select "Settings" in the Serial Terminal Simulation window, once it opens. Several options are available: I chose "Display all RX as hex".

#### AllyCat

##### Senior Member
Hi,

Indeed, there is no bug. Variables like b0, etc. can have any byte value between 0 and 255, so if you SEROUT or SERTXT b0, it will be treated as an ASCII character with that value. Of those 256 numbers, about 95 are "Printable", i.e. Alphanumerics (upper and lower case) and symbols, etc., or maybe control/formatting codes (as described by Inglewoodpete), or some are just ignored. To overcome this, PICaxe Basic uses the # prefix to instead send the byte as a decimal number, i.e. 0 to 255 in 1 to 3 printing ASCII digits (plus a space).

If neither of those formats are acceptable, then you can change the setup of the "Terminal Emulator" so that the "unprintable" (or all) characters are displayed in a more readable format, as again described by pete. Alternatively, you must write your own subroutine to break each byte into "printable" characters, such as "Hexadecimal Pairs" (e.g. "7F" or "A5", etc.). That requires three stages; first split the byte into two nibbles (i.e. 4 bits each), for example by dividing by 16 (for the first nibble) and ANDing with 15 (i.e. %00001111) for the second nibble. Then the nibble values 0 .... 15 need to be converted to printable ASCII characters, the most convenient method being a LOOKUP bN , "0123456789ABCDEF" , bO , and finally SEROUT or SERTXD each value (and probably a space) to the ASCII terminal.

Cheers, Alan.

#### Aries

##### New Member
As it happens, I have been working with something that prints hex values today ...
Code:
``````' write S_W0 as 2 hex characters
_WriteHex2:
S_W1 = S_W0>>4 : gosub _WriteHex1
S_W1 = S_W0&\$0F : gosub _WriteHex1
return

' write S_W1 as 1 hex character
_WriteHex1:
S_W1 = S_W1 / 10 MAX 1 * 7 + S_W1 + "0"
sertxd(S_W1)
return``````
It uses S_W0 and S_W1 to avoid corruption of any registers being used. To call it ...
Code:
``S_W0 = b0 : gosub _WriteHex2``
or, more elegantly, using macros:
Code:
``````#macro WriteHex1(value)
S_W1 = value
gosub _WriteHex1
#endmacro

#macro WriteHex2(value)
S_W0 = value
gosub _WriteHex2
#endmacro

WriteHex2(b0)``````

#### Aries

##### New Member
i wanted to see the HEX values instead of the decimal values.
In PE6 you would see hex values (enclosed in square brackets) for non-printing characters. If they are printable then, reasonably enough, it prints them.

#### inglewoodpete

##### Senior Member
In PE6 you would see hex values (enclosed in square brackets) for non-printing characters. If they are printable then, reasonably enough, it prints them.
Apart from the fact that <HT>,<CR> and <LF> are considered to be "Printable" but not clearly visible chararacters. They showed up in the log from Gramps' little code snip but you have to know what you're looking for.

#### hippy

##### Technical Support
Staff member
One handy trick to see what bits are doing is to use the bit variables, for example ...
Code:
``````For b1 = \$0 To \$F
b0 = b1 : Gosub ShowBits
b2 = Not b1
b0 = b2 : Gosub ShowBits
SerTxd(CR, LF)
Next
End

ShowBits:
SerTxd( #bit7, #bit6, #bit5, #bit4, #bit3, #bit2, #bit1, #bit0, CR, LF)
Return``````
And using a macro which makes it a little clearer, and also allows the variable name to be added ...
Code:
``````#Macro ShowBits(varName, bVar)
b0 = bVar
SerTxd(varName, " = ")
SerTxd(#bit7, #bit6, #bit5, #bit4, #bit3, #bit2, #bit1, #bit0, CR, LF)
#EndMacro

For b1 = \$0 To \$F
ShowBits("b1", b1)
b2 = Not b1
ShowBits("b2", b2)
SerTxd(CR, LF)
Next
End``````

#### Aries

##### New Member
also allows the variable name to be added ...
and if you want to be able to print any variable (apart from the system ones), then you can save and restore b0 in the macro ...
Code:
``````#Macro ShowBits(varName, bVar)
S_W0 = b0
b0 = bVar
SerTxd(varName, " = ")
SerTxd(#bit7, #bit6, #bit5, #bit4, #bit3, #bit2, #bit1, #bit0, CR, LF)
b0 = S_W0
#EndMacro``````