BeBox style Blinkenlights

SOLVED

video here: 4 cpu blinkenlights arduino using teensy2.0++ - YouTube
going to integrate it into this computer case: http://www.instructables.com/id/Laser-Cut-Mini-ITX-Case-From-Scratch/

Back in the day Be, Inc made a Be Box with two rows of leds that would give a CPU utilization level. I've been playing with my arduino and have duplicated the functionality, except now I can control four banks of LEDs using Dual shift registers (595s), 40 LEDs, and Transistors. I've got the circuit working, and arduino running any light I want (or all for that matter).

Can I make the arduino take an input from the main computer and output it onto the LEDs? How would I accomplish this?

I have a function that controls the bank, and number of LEDs to be lit, then it shifts in the next bank of data to show the next CPU utilization. Technically I can still have 2 more banks, but I don't have a 6 CPU system...

My original guess is it should listen on some serial line, for a set of numbers (bank, number of LEDs to be lit) and then output this... I'm just not sure how this is accomplished using arduino. I got it working by taking in a character on the serial port, then switching it out to the proper configuration of LEDs, I'm sure there's enough keys on the keyboard to make this work.

I used the shift PWM RGB example to propel this to glory much faster than I would have been able to on my own (about 30-60 minutes of futzing, no swearing at all)

now that I got this working on my mac (haven't gotten everything working yet), I'm going to make it work with haiku (heck, BeOS might also work)...

Pretty straightforward to do. See: Arduino Playground - InterfacingWithSoftware for examples of how to talk serial to the Arduino.

See http://arduino.cc/en/Tutorial/ShiftOut for how to control a row of LEDs from the Arduino.

You would need an application on the PC which calculated the values for the Arduino to display and then sent them to the Arduino in a format the Arduino could understand. Since your total data set is too big to fit in a single byte you need to design a communication protocol that lets you transfer messages. By far the simplest and most robust scheme is to print out ascii text messages delimited by a newline, and parse those in the Arduino to extract the values for display. For example if you only need to transfer a fixed set of numbers, you could encode them as a sequence of comma separated values terminated by a newline.

Thanks for the quick replies.

Since I'm dealing with 42 bits, I can chop it down to 20 bits, and use a bit for even and odd and that leaves me with 21 bits... the rest is just shifting it out. Depends on the size of the byte? if it's a 32 bit byte, then yes :), 16 bit, then no :frowning:

actually, I would need 2 bits for assigning the led array (4 cpus, 0,1,2,3), and 4 bits for the 10 LEDs to light (0,1,2,3,4,5,6,7,8,9,10)

0000 CPU 1
0001 CPU 2
0010 CPU 3
0011 CPU 4

0000 No Lights
0001 1 LED
0010 2 LED
0011 3 LED
0100 4 LED
0101 5 LED
0110 6 LED
0111 7 LED
1000 8 LED
1001 9 LED
1010 10 LED

CPU 2, 8 LEDs would look something like this
00010010

so that's two octets... one 16 bit byte

Updated so they are not backwards to the uninitiated

your bits are backwards. 00000001 is 1, 00000010 is 2....

If you're bad at bit math you might want to use the ShiftPWM library (http://www.elcojacobs.com/shiftpwm/)

Depends on endian... big or little... My MSB is your LSB

or tomato, tomato

alright, so I've modified my code for the 1 byte "packet" as listed above.

The output on the shift register looks something like this:
CPU 2, 8 LEDs (previous example, now with bits not backwards to non geeks)
Input: 1000:0010 (08:02)
Output to the data pin (clocked in after each data pin is set high for a 1, or low for a 0, then after the whole register is clocked in, it latches the data to the outputs, displaying the LEDs)
LED 1 bit: 1
LED 2 bit: 1
LED 3 bit: 1
LED 4 bit: 1
LED 5 bit: 1
LED 6 bit: 1
LED 7 bit: 1
LED 8 bit: 1
LED 9 bit: 0
LED 10 bit: 0
LED (bus 1) 11 bit: 0
LED (bus 2) 12 bit: 1
LED (bus 3) 13 bit: 0
LED (bus 4) 14 bit: 0
Blank Pin 15 bit: 0
Blank Pin 16 bit: 0

I've also added a bucket so if the 4 bits for the LED is 4 or over it just doesn't do anything.

Here's what I came up with
I used the ShiftPWM library (very nice) as it allows some better control over the light levels

// Alphaseinor's Blink program 
// Uses Teensyduino on a Teensy 2.0++ in it's current form
// Used to take a single character to control 40 LEDs
// These 40 LEDs are split into 4 sets of 10 LEDs
// They are controlled by 2 595 shift registers
// 4 sets of LEDs are controlled cathode to ground by NPN Transistors

// The warning from the ShiftPWM library:vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Clock and data pins are pins from the hardware SPI, you cannot choose them yourself if you use the hardware SPI.
// Data pin is MOSI (Uno and earlier: 11, Leonardo: ICSP 4, Mega: 51, Teensy 2.0: 2, Teensy 2.0++: 22) 
// Clock pin is SCK (Uno and earlier: 13, Leonardo: ICSP 3, Mega: 52, Teensy 2.0: 1, Teensy 2.0++: 21)

// You can choose the latch pin yourself.
const int ShiftPWM_latchPin=8;

// If your LED's turn on if the pin is low, set this to true, otherwise set it to false.
const bool ShiftPWM_invertOutputs = false; 

// You can enable the option below to shift the PWM phase of each shift register by 8 compared to the previous.
// This will slightly increase the interrupt load, but will prevent all PWM signals from becoming high at the same time.
// This will be a bit easier on your power supply, because the current peaks are distributed.
const bool ShiftPWM_balanceLoad = true;

#include <ShiftPWM.h>   // include ShiftPWM.h after setting the pins!

// Here you set the number of brightness levels, the update frequency and the number of shift registers.
// These values affect the load of ShiftPWM.
// Choose them wisely and use the PrintInterruptLoad() function to verify your load.
// There is a calculator on my website to estimate the load.

unsigned char maxBrightness = 50;
unsigned char pwmFrequency = 75;
int numRegisters = 2;
int numRGBleds = numRegisters*8/3;

void setup(){
  Serial.begin(9600);

  // Sets the number of 8-bit registers that are used.
  ShiftPWM.SetAmountOfRegisters(numRegisters);

  // SetPinGrouping allows flexibility in LED setup. 
  // If your LED's are connected like this: RRRRGGGGBBBBRRRRGGGGBBBB, use SetPinGrouping(4).
  ShiftPWM.SetPinGrouping(4); //This is the default, but I added here to demonstrate how to use the funtion
  
  ShiftPWM.Start(pwmFrequency,maxBrightness);
}

void blink(int numberOfLeds, int cpuNumber){ //this outputs to the 595 shift registers the appropriate amount of LEDs
  //first we set which bank of LEDs we want to use
  switch(cpuNumber){ //pins 10-13 on the registers use a NPN transistor to pull the LED bus low
    case 1:
      ShiftPWM.SetOne(10,maxBrightness);
      break;
    case 2:
      ShiftPWM.SetOne(11,maxBrightness);
      break;
    case 3:
      ShiftPWM.SetOne(12,maxBrightness);
      break;
    case 4:
      ShiftPWM.SetOne(13,maxBrightness);
      break;
    default:
      break;
    
  }
  //Then we light up the number of LEDs that need to be displayed in order to make a single line graph
  for(int i=0;i<numberOfLeds;i++){ //loops the number of LEDs starting at output 1
    ShiftPWM.SetOne(i,maxBrightness); //sets 1 LED at a time in the loop
  }
}

void loop()
{    
  if (Serial.available()) { // if serial data is present
    char c = (char)Serial.read(); //note loop does not end here because it needs to switch 'c'
  
  ShiftPWM.SetAll(0); //this changes all of the sates back to off on every loop so we don't get cross talk on the different LED Banks
  
    switch (c){ // This is the switch for us to use the blink function 
                // A-K for CPU 1
                // L-V for CPU 2
                // a-k for CPU 3
                // l-v for CPU 4
                // 0 turns off LEDs
                // 1-9 Sets Brightness of LEDs
      case 'A': //LED Row 1, No LEDs Showing
        break;
      case 'B': //LED Row 1, 1 LEDs Showiing
        blink(1, 1);
        break;
      case 'C': //LED Row 1, 2 LEDs Showing
        blink(2, 1);
        break;
      case 'D': //LED Row 1, 3 LEDs Showing
        blink(3, 1);
        break;
      case 'E': //LED Row 1, 4 LEDs Showing
        blink(4, 1);
        break;
      case 'F': //LED Row 1, 5 LEDs Showing
        blink(5, 1);
        break;
      case 'G': //LED Row 1, 6 LEDs Showing
        blink(6, 1);
        break;
      case 'H': //LED Row 1, 7 LEDs Showing
        blink(7, 1);
        break;
      case 'I': //LED Row 1, 8 LEDs Showing
        blink(8, 1);
        break;
      case 'J': //LED Row 1, 9 LEDs Showing
        blink(9, 1);
        break;
      case 'K': //LED Row 1, 10 LEDs Showing
        blink(10, 1);
        break;
      case 'L': //LED Row 2, No LEDs Showing
        break;
      case 'M': //LED Row 2, 1 LEDs Showiing
        blink(1, 2);
        break;
      case 'N': //LED Row 2, 2 LEDs Showing
        blink(2, 2);
        break;
      case 'O': //LED Row 2, 3 LEDs Showing
        blink(3, 2);
        break;
      case 'P': //LED Row 2, 4 LEDs Showing
        blink(4, 2);
        break;
      case 'Q': //LED Row 2, 5 LEDs Showing
        blink(5, 2);
        break;
      case 'R': //LED Row 2, 6 LEDs Showing
        blink(6, 2);
        break;
      case 'S': //LED Row 2, 7 LEDs Showing
        blink(7, 2);
        break;
      case 'T': //LED Row 2, 8 LEDs Showing
        blink(8, 2);
        break;
      case 'U': //LED Row 2, 9 LEDs Showing
        blink(9, 2);
        break;
      case 'V': //LED Row 2, 10 LEDs Showing
        blink(10, 2);
        break;
      case 'a': //LED Row 3, No LEDs Showing
        break;
      case 'b': //LED Row 3, 1 LEDs Showiing
        blink(1, 3);
        break;
      case 'c': //LED Row 3, 2 LEDs Showing
        blink(2, 3);
        break;
      case 'd': //LED Row 3, 3 LEDs Showing
        blink(3, 3);
        break;
      case 'e': //LED Row 3, 4 LEDs Showing
        blink(4, 3);
        break;
      case 'f': //LED Row 3, 5 LEDs Showing
        blink(5, 3);
        break;
      case 'g': //LED Row 3, 6 LEDs Showing
        blink(6, 3);
        break;
      case 'h': //LED Row 3, 7 LEDs Showing
        blink(7, 3);
        break;
      case 'i': //LED Row 3, 8 LEDs Showing
        blink(8, 3);
        break;
      case 'j': //LED Row 3, 9 LEDs Showing
        blink(9, 3);
        break;
      case 'k': //LED Row 3, 10 LEDs Showing
        blink(10, 3);
        break;
      case 'l': //LED Row 4, No LEDs Showing
        break;
      case 'm': //LED Row 4, 1 LEDs Showiing
        blink(1, 4);
        break;
      case 'n': //LED Row 4, 2 LEDs Showing
        blink(2, 4);
        break;
      case 'o': //LED Row 4, 3 LEDs Showing
        blink(3, 4);
        break;
      case 'p': //LED Row 4, 4 LEDs Showing
        blink(4, 4);
        break;
      case 'q': //LED Row 4, 5 LEDs Showing
        blink(5, 4);
        break;
      case 'r': //LED Row 4, 6 LEDs Showing
        blink(6, 4);
        break;
      case 's': //LED Row 4, 7 LEDs Showing
        blink(7, 4);
        break;
      case 't': //LED Row 4, 8 LEDs Showing
        blink(8, 4);
        break;
      case 'u': //LED Row 4, 9 LEDs Showing
        blink(9, 4);
        break;
      case 'v': //LED Row 4, 10 LEDs Showing
        blink(10, 4);
        break;
      case '0':
        maxBrightness = 0;
        break;
      case '1':
        maxBrightness = 25;
        break;
      case '2':
        maxBrightness = 50;
        break;
      case '3':
        maxBrightness = 75;
        break;
      case '4':
        maxBrightness = 100;
        break;
      case '5':
        maxBrightness = 125;
        break;
      case '6':
        maxBrightness = 150;
        break;
      case '7':
        maxBrightness = 175;
        break;
      case '8':
        maxBrightness = 200;
        break;
      case '9':
        maxBrightness = 225;
        break;
      default:
        break;
    }  
  }
}

Now on to programming that arduino driver for www.Haiku-OS.org haven't even seen if someone else has done it for me.

Added a demo code to when the device starts up, just a random number generator... it's in the bottom else in main

video here: 4 cpu blinkenlights arduino using teensy2.0++ - YouTube
going to integrate it into this computer case: http://www.instructables.com/id/Laser-Cut-Mini-ITX-Case-From-Scratch/

// Alphaseinor's Blink program
// Uses Teensyduino on a Teensy 2.0++ in it's current form
// Used to take a single character to control 40 LEDs
// These 40 LEDs are split into 4 sets of 10 LEDs
// They are controlled by 2 595 shift registers
// 4 sets of LEDs are controlled cathode to ground by NPN Transistors

// The warning from the ShiftPWM library:vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Clock and data pins are pins from the hardware SPI, you cannot choose them yourself if you use the hardware SPI.
// Data pin is MOSI (Uno and earlier: 11, Leonardo: ICSP 4, Mega: 51, Teensy 2.0: 2, Teensy 2.0++: 22) 
// Clock pin is SCK (Uno and earlier: 13, Leonardo: ICSP 3, Mega: 52, Teensy 2.0: 1, Teensy 2.0++: 21)

// You can choose the latch pin yourself.
const int ShiftPWM_latchPin=8;

// If your LED's turn on if the pin is low, set this to true, otherwise set it to false.
const bool ShiftPWM_invertOutputs = false; 

// You can enable the option below to shift the PWM phase of each shift register by 8 compared to the previous.
// This will slightly increase the interrupt load, but will prevent all PWM signals from becoming high at the same time.
// This will be a bit easier on your power supply, because the current peaks are distributed.
const bool ShiftPWM_balanceLoad = true;

#include <ShiftPWM.h>   // include ShiftPWM.h after setting the pins!

// Here you set the number of brightness levels, the update frequency and the number of shift registers.
// These values affect the load of ShiftPWM.
// Choose them wisely and use the PrintInterruptLoad() function to verify your load.
// There is a calculator on my website to estimate the load.

unsigned char maxBrightness = 50;
unsigned char pwmFrequency = 75;
int numRegisters = 2;
int numCPUs = 4;
int numLeds = 10;

void setup(){
  Serial.begin(9600);

  // Sets the number of 8-bit registers that are used.
  ShiftPWM.SetAmountOfRegisters(numRegisters);

  // SetPinGrouping allows flexibility in LED setup. 
  // If your LED's are connected like this: RRRRGGGGBBBBRRRRGGGGBBBB, use SetPinGrouping(4).
  ShiftPWM.SetPinGrouping(4); //This is the default, but I added here to demonstrate how to use the funtion
  
  ShiftPWM.Start(pwmFrequency,maxBrightness);
}

void blink(int numberOfLeds, int cpuNumber){ //this outputs to the 595 shift registers the appropriate amount of LEDs
  //first we set which bank of LEDs we want to use
  switch(cpuNumber){ //pins 10-13 on the registers use a NPN transistor to pull the LED bus low
    case 1:
      ShiftPWM.SetOne(10,maxBrightness);
      break;
    case 2:
      ShiftPWM.SetOne(11,maxBrightness);
      break;
    case 3:
      ShiftPWM.SetOne(12,maxBrightness);
      break;
    case 4:
      ShiftPWM.SetOne(13,maxBrightness);
      break;
    default:
      break;
    
  }
  
  //Then we light up the number of LEDs that need to be displayed in order to make a single line graph
  for(int i=0;i<numberOfLeds;i++){ //loops the number of LEDs starting at output 1
    ShiftPWM.SetOne(i,maxBrightness); //sets 1 LED at a time in the loop
  }
}

void loop()
{    
  if (Serial.available()) { // if serial data is present
    char c = (char)Serial.read(); //note loop does not end here because it needs to switch 'c'
  
  ShiftPWM.SetAll(0); //this changes all of the sates back to off on every loop so we don't get cross talk on the different LED Banks
  
    switch (c){ // This is the switch for us to use the blink function 
                // A-K for CPU 1
                // L-V for CPU 2
                // a-k for CPU 3
                // l-v for CPU 4
                // 0 turns off LEDs
                // 1-9 Sets Brightness of LEDs
      case 'A': //LED Row 1, No LEDs Showing
        break;
      case 'B': //LED Row 1, 1 LEDs Showiing
        blink(1, 1);
        break;
      case 'C': //LED Row 1, 2 LEDs Showing
        blink(2, 1);
        break;
      case 'D': //LED Row 1, 3 LEDs Showing
        blink(3, 1);
        break;
      case 'E': //LED Row 1, 4 LEDs Showing
        blink(4, 1);
        break;
      case 'F': //LED Row 1, 5 LEDs Showing
        blink(5, 1);
        break;
      case 'G': //LED Row 1, 6 LEDs Showing
        blink(6, 1);
        break;
      case 'H': //LED Row 1, 7 LEDs Showing
        blink(7, 1);
        break;
      case 'I': //LED Row 1, 8 LEDs Showing
        blink(8, 1);
        break;
      case 'J': //LED Row 1, 9 LEDs Showing
        blink(9, 1);
        break;
      case 'K': //LED Row 1, 10 LEDs Showing
        blink(10, 1);
        break;
      case 'L': //LED Row 2, No LEDs Showing
        break;
      case 'M': //LED Row 2, 1 LEDs Showiing
        blink(1, 2);
        break;
      case 'N': //LED Row 2, 2 LEDs Showing
        blink(2, 2);
        break;
      case 'O': //LED Row 2, 3 LEDs Showing
        blink(3, 2);
        break;
      case 'P': //LED Row 2, 4 LEDs Showing
        blink(4, 2);
        break;
      case 'Q': //LED Row 2, 5 LEDs Showing
        blink(5, 2);
        break;
      case 'R': //LED Row 2, 6 LEDs Showing
        blink(6, 2);
        break;
      case 'S': //LED Row 2, 7 LEDs Showing
        blink(7, 2);
        break;
      case 'T': //LED Row 2, 8 LEDs Showing
        blink(8, 2);
        break;
      case 'U': //LED Row 2, 9 LEDs Showing
        blink(9, 2);
        break;
      case 'V': //LED Row 2, 10 LEDs Showing
        blink(10, 2);
        break;
      case 'a': //LED Row 3, No LEDs Showing
        break;
      case 'b': //LED Row 3, 1 LEDs Showiing
        blink(1, 3);
        break;
      case 'c': //LED Row 3, 2 LEDs Showing
        blink(2, 3);
        break;
      case 'd': //LED Row 3, 3 LEDs Showing
        blink(3, 3);
        break;
      case 'e': //LED Row 3, 4 LEDs Showing
        blink(4, 3);
        break;
      case 'f': //LED Row 3, 5 LEDs Showing
        blink(5, 3);
        break;
      case 'g': //LED Row 3, 6 LEDs Showing
        blink(6, 3);
        break;
      case 'h': //LED Row 3, 7 LEDs Showing
        blink(7, 3);
        break;
      case 'i': //LED Row 3, 8 LEDs Showing
        blink(8, 3);
        break;
      case 'j': //LED Row 3, 9 LEDs Showing
        blink(9, 3);
        break;
      case 'k': //LED Row 3, 10 LEDs Showing
        blink(10, 3);
        break;
      case 'l': //LED Row 4, No LEDs Showing
        break;
      case 'm': //LED Row 4, 1 LEDs Showiing
        blink(1, 4);
        break;
      case 'n': //LED Row 4, 2 LEDs Showing
        blink(2, 4);
        break;
      case 'o': //LED Row 4, 3 LEDs Showing
        blink(3, 4);
        break;
      case 'p': //LED Row 4, 4 LEDs Showing
        blink(4, 4);
        break;
      case 'q': //LED Row 4, 5 LEDs Showing
        blink(5, 4);
        break;
      case 'r': //LED Row 4, 6 LEDs Showing
        blink(6, 4);
        break;
      case 's': //LED Row 4, 7 LEDs Showing
        blink(7, 4);
        break;
      case 't': //LED Row 4, 8 LEDs Showing
        blink(8, 4);
        break;
      case 'u': //LED Row 4, 9 LEDs Showing
        blink(9, 4);
        break;
      case 'v': //LED Row 4, 10 LEDs Showing
        blink(10, 4);
        break;
      case '0':
        maxBrightness = 0;
        break;
      case '1':
        maxBrightness = 25;
        break;
      case '2':
        maxBrightness = 50;
        break;
      case '3':
        maxBrightness = 75;
        break;
      case '4':
        maxBrightness = 100;
        break;
      case '5':
        maxBrightness = 125;
        break;
      case '6':
        maxBrightness = 150;
        break;
      case '7':
        maxBrightness = 175;
        break;
      case '8':
        maxBrightness = 200;
        break;
      case '9':
        maxBrightness = 225;
        break;
      default:
        break;
    }  
  }
  else
  {
    //startup routine
    for(int cpu=1;cpu<numCPUs+1;cpu++){
      for(int led=0;led<numLeds+1;led++){
        if (Serial.available()){break;}
        blink(random(led),cpu);
        delay(10);
        ShiftPWM.SetAll(0);
      }
    }
  }
}

changed the code to have the 10 anodes loop last, and the 4 cathodes loop first... this reduces the CPU flicker on the leds.
drop the delay to 4 and the flicker goes away completely.

still working on the haiku driver... i'll post it here when I'm done.

// Alphaseinor's Blink program
// Uses Teensyduino on a Teensy 2.0++ in it's current form
// Used to take a single character to control 40 LEDs
// These 40 LEDs are split into 4 sets of 10 LEDs
// They are controlled by 2 595 shift registers
// 4 sets of LEDs are controlled cathode to ground by NPN Transistors

// The warning from the ShiftPWM library:vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Clock and data pins are pins from the hardware SPI, you cannot choose them yourself if you use the hardware SPI.
// Data pin is MOSI (Uno and earlier: 11, Leonardo: ICSP 4, Mega: 51, Teensy 2.0: 2, Teensy 2.0++: 22) 
// Clock pin is SCK (Uno and earlier: 13, Leonardo: ICSP 3, Mega: 52, Teensy 2.0: 1, Teensy 2.0++: 21)

// You can choose the latch pin yourself.
const int ShiftPWM_latchPin=8;

// If your LED's turn on if the pin is low, set this to true, otherwise set it to false.
const bool ShiftPWM_invertOutputs = false; 

// You can enable the option below to shift the PWM phase of each shift register by 8 compared to the previous.
// This will slightly increase the interrupt load, but will prevent all PWM signals from becoming high at the same time.
// This will be a bit easier on your power supply, because the current peaks are distributed.
const bool ShiftPWM_balanceLoad = true;

#include <ShiftPWM.h>   // include ShiftPWM.h after setting the pins!

// Here you set the number of brightness levels, the update frequency and the number of shift registers.
// These values affect the load of ShiftPWM.
// Choose them wisely and use the PrintInterruptLoad() function to verify your load.
// There is a calculator on my website to estimate the load.

unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 75;
int numRegisters = 2;
int numCPUs = 4;
int numLeds = 10;

void setup(){
  Serial.begin(9600);

  // Sets the number of 8-bit registers that are used.
  ShiftPWM.SetAmountOfRegisters(numRegisters);

  // SetPinGrouping allows flexibility in LED setup. 
  // If your LED's are connected like this: RRRRGGGGBBBBRRRRGGGGBBBB, use SetPinGrouping(4).
  ShiftPWM.SetPinGrouping(4); //This is the default, but I added here to demonstrate how to use the funtion
  
  ShiftPWM.Start(pwmFrequency,maxBrightness);
}

void blink(int numberOfLeds, int cpuNumber){ //this outputs to the 595 shift registers the appropriate amount of LEDs
  //first we set which bank of LEDs we want to use
  switch(cpuNumber){ //pins 10-13 on the registers use a NPN transistor to pull the LED bus low
    case 1:
      ShiftPWM.SetOne(10,maxBrightness);
      break;
    case 2:
      ShiftPWM.SetOne(11,maxBrightness);
      break;
    case 3:
      ShiftPWM.SetOne(12,maxBrightness);
      break;
    case 4:
      ShiftPWM.SetOne(13,maxBrightness);
      break;
    default:
      break;
    
  }
  
  //Then we light up the number of LEDs that need to be displayed in order to make a single line graph
  for(int i=0;i<numberOfLeds;i++){ //loops the number of LEDs starting at output 1
    ShiftPWM.SetOne(i,maxBrightness); //sets 1 LED at a time in the loop
  }
}

void loop()
{    
  if (Serial.available()) { // if serial data is present
    char c = (char)Serial.read(); //note loop does not end here because it needs to switch 'c'
  
  ShiftPWM.SetAll(0); //this changes all of the sates back to off on every loop so we don't get cross talk on the different LED Banks
  
    switch (c){ // This is the switch for us to use the blink function 
                // A-K for CPU 1
                // L-V for CPU 2
                // a-k for CPU 3
                // l-v for CPU 4
                // 0 turns off LEDs
                // 1-9 Sets Brightness of LEDs
      case 'A': //LED Row 1, No LEDs Showing
        break;
      case 'B': //LED Row 1, 1 LEDs Showiing
        blink(1, 1);
        break;
      case 'C': //LED Row 1, 2 LEDs Showing
        blink(2, 1);
        break;
      case 'D': //LED Row 1, 3 LEDs Showing
        blink(3, 1);
        break;
      case 'E': //LED Row 1, 4 LEDs Showing
        blink(4, 1);
        break;
      case 'F': //LED Row 1, 5 LEDs Showing
        blink(5, 1);
        break;
      case 'G': //LED Row 1, 6 LEDs Showing
        blink(6, 1);
        break;
      case 'H': //LED Row 1, 7 LEDs Showing
        blink(7, 1);
        break;
      case 'I': //LED Row 1, 8 LEDs Showing
        blink(8, 1);
        break;
      case 'J': //LED Row 1, 9 LEDs Showing
        blink(9, 1);
        break;
      case 'K': //LED Row 1, 10 LEDs Showing
        blink(10, 1);
        break;
      case 'L': //LED Row 2, No LEDs Showing
        break;
      case 'M': //LED Row 2, 1 LEDs Showiing
        blink(1, 2);
        break;
      case 'N': //LED Row 2, 2 LEDs Showing
        blink(2, 2);
        break;
      case 'O': //LED Row 2, 3 LEDs Showing
        blink(3, 2);
        break;
      case 'P': //LED Row 2, 4 LEDs Showing
        blink(4, 2);
        break;
      case 'Q': //LED Row 2, 5 LEDs Showing
        blink(5, 2);
        break;
      case 'R': //LED Row 2, 6 LEDs Showing
        blink(6, 2);
        break;
      case 'S': //LED Row 2, 7 LEDs Showing
        blink(7, 2);
        break;
      case 'T': //LED Row 2, 8 LEDs Showing
        blink(8, 2);
        break;
      case 'U': //LED Row 2, 9 LEDs Showing
        blink(9, 2);
        break;
      case 'V': //LED Row 2, 10 LEDs Showing
        blink(10, 2);
        break;
      case 'a': //LED Row 3, No LEDs Showing
        break;
      case 'b': //LED Row 3, 1 LEDs Showiing
        blink(1, 3);
        break;
      case 'c': //LED Row 3, 2 LEDs Showing
        blink(2, 3);
        break;
      case 'd': //LED Row 3, 3 LEDs Showing
        blink(3, 3);
        break;
      case 'e': //LED Row 3, 4 LEDs Showing
        blink(4, 3);
        break;
      case 'f': //LED Row 3, 5 LEDs Showing
        blink(5, 3);
        break;
      case 'g': //LED Row 3, 6 LEDs Showing
        blink(6, 3);
        break;
      case 'h': //LED Row 3, 7 LEDs Showing
        blink(7, 3);
        break;
      case 'i': //LED Row 3, 8 LEDs Showing
        blink(8, 3);
        break;
      case 'j': //LED Row 3, 9 LEDs Showing
        blink(9, 3);
        break;
      case 'k': //LED Row 3, 10 LEDs Showing
        blink(10, 3);
        break;
      case 'l': //LED Row 4, No LEDs Showing
        break;
      case 'm': //LED Row 4, 1 LEDs Showiing
        blink(1, 4);
        break;
      case 'n': //LED Row 4, 2 LEDs Showing
        blink(2, 4);
        break;
      case 'o': //LED Row 4, 3 LEDs Showing
        blink(3, 4);
        break;
      case 'p': //LED Row 4, 4 LEDs Showing
        blink(4, 4);
        break;
      case 'q': //LED Row 4, 5 LEDs Showing
        blink(5, 4);
        break;
      case 'r': //LED Row 4, 6 LEDs Showing
        blink(6, 4);
        break;
      case 's': //LED Row 4, 7 LEDs Showing
        blink(7, 4);
        break;
      case 't': //LED Row 4, 8 LEDs Showing
        blink(8, 4);
        break;
      case 'u': //LED Row 4, 9 LEDs Showing
        blink(9, 4);
        break;
      case 'v': //LED Row 4, 10 LEDs Showing
        blink(10, 4);
        break;
      case '0':
        maxBrightness = 0;
        break;
      case '1':
        maxBrightness = 25;
        break;
      case '2':
        maxBrightness = 50;
        break;
      case '3':
        maxBrightness = 75;
        break;
      case '4':
        maxBrightness = 100;
        break;
      case '5':
        maxBrightness = 125;
        break;
      case '6':
        maxBrightness = 150;
        break;
      case '7':
        maxBrightness = 175;
        break;
      case '8':
        maxBrightness = 200;
        break;
      case '9':
        maxBrightness = 225;
        break;
      default:
        break;
    }  
  }
  else
  {
    //startup routine
    for(int led=1;led<numLeds+1;led++){
      for(int cpu=0;cpu<numCPUs+1;cpu++){
        if (Serial.available()){break;}
        blink(random(led),cpu);
        delay(5);
        ShiftPWM.SetAll(0);
      }
    }
  }
}