Tangible Computing
4. Signed, Unsigned, Byte, Normal, and Long, LED Bit Arithmetic




4.1 Part 1: Counting Bits

Consider the following variable declarations.
int i;
long l;
unsigned int ui;
unsigned long ul;
Each one declares an variable that takes on integer values. The unsigned modifier means the variable takes on only non-negative (0 or positive) values. While the unmodified declarations hold both positive, 0, and negative numbers using the Two's Complement (i.e. modular) representation described in the previous section.

How can we determine how many bits are used? We can always guess and check by trying to assign values to see if they work as they should, or we can look it up.

We can, and should, also use these declarations instead. They emphasize exactly how many bits are present, and the way they are interpreted:

type Num Bytes Num Bits Integer Range
int8_t 1 8 -128 to 127
uint8_t 1 8 0 to 255
int16_t 2 16 -32768 to 32767
uint16_t 2 16 0 to 65535
int32_t 4 32 -2147483648 to 2147483647
uint32_t 4 32 0 to 4294967295


This explicitly tells us how many bits we're using (the number after the int), and whether it's unsigned or signed (whether it starts with a 'u' or not). This means that an int8_t variable will use 8 bits, its values from (-2**7) to (2**7 - 1), or -128 to 127. An uint8_t is unsigned and it uses 8 bits, so its range is from 0 to (2**8 - 1), or 0 to 255.

For our programs we're going to use this form of declaring variables to be conscious of what range of values our variables will be using, so we know how much memory we need to use. We don't have to worry about the limitations on memory now, but it would be a good habit to get into to be conscious of it. We'll talk more about memory later.

What happens when we try to use values outside of a variable's range? What happens a value that we want to store is greater than the number of bits that can be used by the variable? Think about this in terms of modular arithmetic. What is the largest and smallest number that each variable can hold? See below for an Arduino program that can display binary values using only 8 bits.

4.2 Part 2: LED Bit Display

The circuit and the code below display binary numbers, from the serial input. It uses only 8 bits, represented by 8 LEDs. Note that the program needs to be resetted if you wish enter in a new value in.



See wiring on LEDs and resistors if you need a reminder!

Download the code: code/labBits/labBits.ino

    /* LAB 2: LED Bit Arithmetic  
     */
     
    /* LED Pins
     *
     * We use output pins { start_led,  ... , (start_led+num_bits-1) } to drive
     * the display LEDs.  The pins are ordered from low bit 0 (on the right)
     * to the high bit 7 (on the left).
     */
    uint8_t start_led = 6;
    uint8_t num_bits = 8;
     
    void setup() {
      
      /* Set each pin connected to an LED to output mode */
      for(uint8_t i = 0; i < num_bits; i++){         
          pinMode(start_led + i,OUTPUT); 
      }                                   
     
      Serial.begin(9600);
    }
     
     
    void loop() {
        /* Read a number from the serial port and display the number with
           the 8 LEDs */ 
        int32_t recv = readint();
        Serial.println(recv);
     
        display_1(recv);
        // display_2(recv);
        // display_3(recv);
    }
     
     
    /* QUESTION #1: This is not very good code.  Why? */
    void display_1 (int input) {
        if (0x0001 & input) { digitalWrite(start_led + 0, HIGH);}
        if (0x0002 & input) { digitalWrite(start_led + 1, HIGH);}
        if (0x0004 & input) { digitalWrite(start_led + 2, HIGH);}
        if (0x0008 & input) { digitalWrite(start_led + 3, HIGH);}
        if (0x0010 & input) { digitalWrite(start_led + 4, HIGH);}
        if (0x0020 & input) { digitalWrite(start_led + 5, HIGH);}
        if (0x0040 & input) { digitalWrite(start_led + 6, HIGH);}
        if (0x0080 & input) { digitalWrite(start_led + 7, HIGH);}
                    
    }
     
    /* QUESTION #2: This is an alternative version of the display_1 code
       that is more general.  Why? */
    void display_2 (int32_t input) {
        int16_t mask = 0x0001;
     
        for (int8_t i=0; i < num_bits; i++) {
            if ( (mask << i) & input) {
                digitalWrite(start_led + i, HIGH);
            }
        }
    }
     
    /* Another alternative version of display_1. */
    void display_3 (int32_t input) {
        int16_t mask = 0x0001;
     
        for (int8_t i=0; i < num_bits; i++) {
            if (mask & input) {
                digitalWrite(start_led + i, HIGH);
            }
     
            /* QUESTION #3: You can use either of these two.  Why? 
             *    mask = mask << 1;
             * or
             *    input = input >> 1;
             *
             * QUESTION #4: What happens if the sign bit of the input is
             * set?
             */
     
            input = input >> 1;             
        }
    }
     
    /* Read an integer off of the serial port and return. */
    int32_t readint() {
      char s[128]; /* 128 characters should be more than enough. */
      readline(s, 127);
      s[127] = '\0';
      return atoi(s);
    }
     
    /* Read a line (up to maxlen characters) off of the serial port. */
    void readline(char *s, uint8_t maxlen) {
      uint8_t i = 0;
      
      while(1) {
        while (Serial.available() == 0) { } /* Do nothing */
        s[i] = Serial.read();
        if (s[i] == '\0' || s[i] == '\n' || i == maxlen-1) break;
        i += 1;
      }
    }


After uploading the code to the Arduino, open the "Serial Monitor". Enter a number and hit enter. It should light up that number in binary on the LEDs.

LEDs not lighting up?: Make sure in serial monitor you have Newline selected and make sure you're using the correct baud rate.

4.3 Tasks

  1. Look at the function display_1(). Can you describe what it is doing?
  2. Look at the functions display_1(), display_2(), display_3(). Answer the four questions.
  3. What happens when you input 312 into the program? Is the correct number displayed in the LED's?
  4. Implement a binary counter that counts from the lowest negative integer to the highest positive integer and back down to the lowest negative integer.

4. Signed, Unsigned, Byte, Normal, and Long, LED Bit Arithmetic
Tangible Computing / Version 3.20 2013-03-25