A couple of noodle scratchers

:confused:
I have a couple of questions I have been able to figure out. I figure that you people here could give me accurate answers, in english. Here’s what they are:

  1. What is 2’s compliment? how does it work? what would I use it for?
  2. Is there any way to get more than 26 variables? What determines that, like is a memory constraint?
  3. What is the difference between GET and PUT?
  4. What are the EEPROM and Scratchpad RAM? What is the difference?
  5. How can I use the NOT command? Using the ~ does not seem to work for us, maybe we are using it wrong.
    Thanks in advance! :smiley:

I’ll se what I can do:

  1. Two’s complement: Two’s complement is a way of representing negative numbers in binary. It comes from the way processors work and generally makes life very easy as it allows you to just add two numbers and ignore their signs. For example:
    The two’s complement of -1 (in eight bits) is: 11111111. Adding 1 yields 100000000. However, because we are only dealing with eight-bit numbers, that leading 1 is chopped off and you get 0, as it should be. Likewise, adding -1 and -1 gives 111111110. Drop the leading one and you get 11111110, which is -2. To convert a positive number to its negative, invert all the bits and add 1. The only thing you really need this for is to realize that the Stamp processors will interpret -1 as 65000 something.

  2. Short answer: no, the processor only has 26 bytes worth of registers. Long answer: see answer to question 3.

  3. Put will place a value in scratchpad. The scratchpad is basically a 64-byte block of memory where you can store stuff you aren’t using at that particular moment. For example, if you want to store two bytes of data between loops, but you only have enough space for one variable, you could “put” these two values on scratchpad and retrieve them when you need them, one at a time. Note that you must do a “get” to fetch the value you put on scratchpad into a variable so you can use it in calculations.

4)EEPROM is where your program is stored, but you can also put data there. However, it is very slow to Read/write (the eeeprom equivalents of get/put) and writing to an individual location more than 1000000 times could cause that location to go bad. A lot of people use eeprom to store large tables of data as it is 2048 bytes. Also take a look at the “data” command if you are interested in doing this and the normal lookup/lookdown doesn’t meet your needs.

  1. ~ will compute the bitwise-not of a number, meaning each individual bit will be inverted. You shouldn’t use it unless this is what you want. Instead, do something like: “if not (p1_x = 127)…” ALWAYS use parenthesis with “not” as you could get some very unexpected results otherwise.

<shameless plug>
If you haven’t already, try download RoboEmu, either for Windows or Linux. It supports everything mentioned above and will let you play with all these commands without the need for an actual RC/OI at your house.
</shameless plug>

In an unsigned integer byte, the rightmost bit stands is the 1’s place, and each successive bit to the left stands for twice the previous bit’s place. There are 8 bits in a byte, so the leftmost bit in an unsigned integer byte is the 128’s place. In a signed integer byte, everything is the same except for the leftmost bit, which stands for the opposite of what it does in an unsigned integer (-128 instead of 128).

I’m just going to tackle a couple of these questions right now:

  1. Two’s complement is one of the ways represent negative numbers. Basically, the easy way to calculate the 2’s complement of a number is to flip all the bits and add 1. the number (00110101) = 53 has a 2’s complement of -53 = (11001011). However, in our world of P-BASIC, (11001011) = 203 because P-BASIC will display numbers as positive intergers only.
    This form of a number is useful when you want to subtract numbers. If you want to do A-B = A + (2’s complement of B) This is what most people use when they create digital circuitry, and what most (not all) computer processors use. My advise is to stay away from this unless you must because it can get very confusing very quickly.

  2. I think i understand what you are asking because i’ve run into the same problem a numebr of times. Understand that a variable (in our case mostly bytes (8 bits) are loaded into the Arithmetic unit which uses 16 bits to perform calculations. So if we were to take a byte, in binary, (10011100) and perform ~(10011100) and then save it back ot the same place the basic process would look something like this:

varName = (10011100)
varName = ~varName

Description of the 2nd line of code:

  1. 10011100 is loaded into the Arithmetic Unit and becomes (00000000 10011100)

  2. this word (16 bits) is then inverted and becomes (11111111 01100011)

  3. the word value (11111111 01100011) is truncated to a byte and the new value of varName = (01100011)

if you were using the ~ operator in the middle of a calculation then you were adding a whole lot of 1’s to the front thus making your calculations not work, unless you saved back to a varriable.

There is a simple way to fix this. if you were to subtract off the leading 1’s then you would get the answer you are loking for. So in the case of a byte, using the expression: (~varName - 65280) This means you can bitwise invert the number without having to save.

65280 = (11111111 00000000)

I hope this helps.

Steve

Thanks to everyone whose responded
We’d use the ~ like if ~(p1_y > 127 & p2_y > 127) then next2
Is there anything wrong with that?

Technically you should use NOT instead of ~ for things like this. Also, you should use AND instead of &. & will calculate the bitwise “and” of your two expressions, meaning it will apply the “and” to each individual set of bits. If it so happens that both p1_y > 127 as well as p2_y > 127 evaluate to exactly 1, it will work. Otherwise it may not. ~ Will compute the bitwise NOT of your expression. Assuming the inner part evaluates to 1, ~ will make it 1111111111111110 (65534).

If you ever wonder what an expression will evaluate to, try popping it in RoboEmu and doing a debug. For example, using:

myVar= ~1
debug? myVar

will give you:
myVar=254

-and-

myVar=0-1
debug? myVar

will give you:
myVar=255

*Originally posted by Cheese Head *
** if ~(p1_y > 127 & p2_y > 127) then next2
Is there anything wrong with that? **

Yes, there are a few mistakes in this expression form what i assume you are trying to accomplish. You are forgetting the order of opperations in P-BASIC. That is expressions are evaluated Left to right inside of each level of parentheses. So in your expression, this is what is really evaluated: ~(((p1_y>127) & p2_y) > 127) which is not what you are looking for. Also, you will never get a 0 value, you will always have a value > 0 because of the leading 1’s (see my post above for the explanation). So the if statement will always evaluate true.
The easiest way to fix that is to sue NOT instead of ~ in the middle of the if statement. This will not work for stand alone calculations. Another option is to subtract out the 65534 after the ~ operation.

Steve

*Originally posted by Steve Shade *
**
So in your expression, this is what is really evaluated: ~(((p1_y>127) & p2_y) > 127) **

Not quite. The PBASIC compiler is smart enough to do comparisons (>, =, etc) after regular stuff. Here’s an example straight from the BASIC Stamp Manual:


number1 con 99
number2 con 30

if number1=number2 * 4 - 21 then equal
debug "not equal"
stop

equal:
debug "equal"
stop

This will evaluate each side of the expression before comparing them with =, so it will print “equal” because (30*4-21) is 99.

Also, true is not necessarily 1. Like most processors, the basic stamp interprets 0 to mean false, and ANYTHING else to be true. Therefore, always make sure to use the logic operators (AND, NOT, OR, XOR) instead of the bitwise equivalents (&, ~, |, ^).

I have taken a college course on programming x86 Assembly last year… I will try to explain it.

Two’s complement is a way of representing negative numbers in the binary world. If you understand binary numbers (such as 00001000), and what they mean, then you will understand it.

The binary system works off powers of 2, versus the power of 10 in our standard counting system. In our system, the number 34 is actually represented mathematicaly as (4 x 10^0 + 3 x 10^1). The previous numbers are 4 and 30, added become 34. Binary is similar, but replace the 10’s with 2, and the 3 and 4 are 0 and 1’s. The number 34 would be represented as: 00100010. This is (0 x 2^0 + 1 x 2^1 + 0 x 2^2 + … + 1 x 10^5 + 0 x 10^6 + …). The numbers mulitplied by 0 are not counted. The numbers added are 2 and 32, which become 34. In the binary system, each 0 or 1 (digit) is called a “bit”.

Negative numbers can be represented by one of two ways. The most obvious way would be to represent the numbers normally, and use a bit to represent whether the number is negative or not. For example, using this method, 34 would be (00100010) and -34 would be (10100010). Note that only values of up to 127 can be represented using 8 digits (bits) since the last value is a sign marker. This is true for two’s complement as well.

The problem with the method above is that it is cumbersome when you needed to add the numbers. First, one would have to check the “marker” (sign) bit to see if it is negative. Then, you would have to devise a method that would add the numbers appropriately based on the sign bit. If you think about ways to do it, such as for the numbers 52 and -7, which makes 45 (00110100 and 10000111 makes 00101101). Any way you can think of would be cumbersome.

With Two’s Complement, you can just add the binary numbers together, and you will get the answer. To get a number’s two’s compliment:

  1. Take the binary number and switch the 0’s to 1’s and the 1’s to 0’s.
  2. Add 1 (binary numbers “carry” like normal, so 0111 becomes 1000).

For example, 52 and -7:
52, as before, is 00110100.
7 is 00000111. Two’s complement of this is 11111001.

When adding with two’s complement, all one has to do is add the numbers. Remember to “carry” to the next digit when you add, like adding normally (just like when you calculate the Two’s Complement).

00110100 (52)
11111001 (-7)

00101101 (45)

*Originally posted by Cheese Head *
**:confused:
I have a couple of questions I have been able to figure out. I figure that you people here could give me accurate answers, in english. Here’s what they are:

  1. What is 2’s compliment? how does it work? what would I use it for?
  2. Is there any way to get more than 26 variables? What determines that, like is a memory constraint?
  3. What is the difference between GET and PUT?
  4. What are the EEPROM and Scratchpad RAM? What is the difference?
  5. How can I use the NOT command? Using the ~ does not seem to work for us, maybe we are using it wrong.
    Thanks in advance! :smiley: **

Basic Stamp User’s Manual - A FIRST Programmer’s Holy Bible

Many of the answers to your questions can be answered here.

  1. Answered above.

  2. 26 variables is not the constraint. The constraint is actually 26 bytes. You can meet this using any combination of words (2 bytes, numbers 0-65535), bytes (0-255), nibs (1/2 byte, numbers 0-15 (useful for speed settings)), and bits (1/8 byte, only 0 or 1 (useful for on/off)).
    Technically there are 32 bytes, but 6 are used by the chip for I/O Pins and such.

One way to get around the limitation is by loading the program into “slots”. Read the manual for more details. Basically, when a slot is loaded the same RAM is used, erasing all the previous contents. Scratchpad RAM, however, is carried over between slots. There are 64 bytes present (and bytes only). Only 0-62 are available. Read the manual to learn how to use it (GET and PUT commands).

  1. Check the manual. GET retrieves a value from Scratchpad RAM. PUT places a value into a Scratchpad RAM location.

    1. EEPROM is where your program is stored. It can be written to, but only all-or-nothing. The entire EEPROM needs to be erased and then data sent to it.
  1. RAM on the chip is available for your program to use. 26 bytes are available for variable use. These can be used to add/subtract/divide/multiply numbers.
  2. Scratchpad RAM is available for storing numbers only. You can’t perform math operations with it.
  1. ~ will inverse the bits. For example, 128 becomes 126. 0 becomes 255. 1 becomes 254, etc. 127 is still 127.

*Originally posted by Jnadke *
**

One way to get around this is by loading the program into “slots”. Read the manual for more details, but basically each slot has its own 26 bytes available to it. However, the data is not carried over from each slot.

Scratchpad RAM, however, is carried over. **

Actually, the data is carried over between slots and all eight share a common 26 bytes of memory. The key is just making sure your variables “line-up” the same between slots. For example, if you have a byte variable named “myByte,” you need to make sure it is in the same location in all slots if you want to access it in multiple programs.

The easiest way to do this is explicitly tell the PBASIC compiler where to put each variable. This can be done by making all variables “aliases” to the built-in, primitive ones (named b0-b25 and w0-w13). Note that these names do overlap. B0 and B1 are the two bytes of w0, b2 and b3 are the parts of w1, etc.

So far, I haven’t seen a single program that was broken into multiple slots that couldn’t have been done in a single slot. In fact, the only real advantage I see is that it could let you store different programs for different configurations (if your bot was modular), but even that can be done with a few well-placed “if” statements.

I see many operational definitions of “complementing”, which means “filling up”.

The two’s complement of a number is the number which, added to the number, gives 2 (that is, it “fills up” to the two. In binary, two is 10, the twos complement of ‘1’ is ‘1’, which adds to 0, with a carry.

In binary, if the number must be represented in n bits, then you probably mean to find the n-bit “two’s complement”, which means the number added to your number which gives a rollover to ‘n’ zeros and a carry (for the n+1st bit (or all zeros and a carry).

** Without resorting to bits …

For a nibble (4 bits), which allows a 15(decimal) max before rollver (that is, the one bit in the fifth place means 16), the “two’s complement” is the number which added to your number gives 16. If your number is 5, then 11 is the “twos complement” giving zeros in the four bits and a carry to a fifth.

** It works in decimal, too …

The ten’s complement of seven is three: add three to seven, you get zero, and a carry, which is 10. in two digits.

** Operationally, with bits, recpping earlier posts …

If you want two’s complements, add one to all n bits, and add one to the result.