User Tools

Site Tools


non-hardware_spi_example

The following code demonstrates how to efficiently control ShiftBrites without using the Arduino hardware SPI. The performance will be a little bit slower, but the ability to select any pins for communication will make it much easier to integrate ShiftBrites with applications that need to use hardware SPI, like the Arduino Ethernet Shield.

This example actually uses pins as wired on the ShiftBrite Shield, which happen to be SPI pins on the Arduino Diecimila and Duemilanove. In order to use other pins, you'll need to use some other method besides the ShiftBrite Shield to connect ShiftBrites. The exception would be the Arduino Mega, which uses other pins for the hardware SPI. Therefore, the second code listing below could be used to operate a ShiftBrite chain using a ShiftBrite shield on an Arduino Mega.

Arduino Code

/* Ports and Pins
 
 Direct port access is much faster than digitalWrite.
 You must match the correct port and pin as shown in the table below.
 
 Arduino Pin        Port        Pin
 13 (SCK)           PORTB       5
 12 (MISO)          PORTB       4
 11 (MOSI)          PORTB       3
 10 (SS)            PORTB       2
 9                  PORTB       1
 8                  PORTB       0
 7                  PORTD       7
 6                  PORTD       6
 5                  PORTD       5
 4                  PORTD       4
 3                  PORTD       3
 2                  PORTD       2
 1 (TX)             PORTD       1
 0 (RX)             PORTD       0
 A5 (Analog)        PORTC       5
 A4 (Analog)        PORTC       4
 A3 (Analog)        PORTC       3
 A2 (Analog)        PORTC       2
 A1 (Analog)        PORTC       1
 A0 (Analog)        PORTC       0
 
 */

// Defines for use with Arduino functions
#define clockpin   13 // CI
#define enablepin  10 // EI
#define latchpin    9 // LI
#define datapin    11 // DI

// Defines for direct port access
#define CLKPORT PORTB
#define ENAPORT PORTB
#define LATPORT PORTB
#define DATPORT PORTB
#define CLKPIN  5
#define ENAPIN  2
#define LATPIN  1
#define DATPIN  3

// Variables for communication
unsigned long SB_CommandPacket;
int SB_CommandMode;
int SB_BlueCommand;
int SB_RedCommand;
int SB_GreenCommand;

// Define number of ShiftBrite modules
#define NumLEDs 5

// Create LED value storage array
int LEDChannels[NumLEDs][3] = {0};

// Set pins to outputs and initial states
void setup() {
  pinMode(datapin, OUTPUT);
  pinMode(latchpin, OUTPUT);
  pinMode(enablepin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  digitalWrite(latchpin, LOW);
  digitalWrite(enablepin, LOW);
}

void SB_SendPacket() {

  if (SB_CommandMode == B01) {
    SB_RedCommand = 127;
    SB_GreenCommand = 110;
    SB_BlueCommand = 110;
  }

  SB_CommandPacket = SB_CommandMode & B11;
  SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_BlueCommand & 1023);
  SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_RedCommand & 1023);
  SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_GreenCommand & 1023);

  for (int j = 0; j < 32; j++) {
    if ((SB_CommandPacket >> (31 - j)) & 1) {
      DATPORT |= (1 << DATPIN);
    } 
    else {
      DATPORT &= ~(1 << DATPIN);
    }
    CLKPORT |= (1 << CLKPIN);
    CLKPORT &= ~(1 << CLKPIN); 
  } 
}

void SB_Latch() {

  delayMicroseconds(1);
  LATPORT |= (1 << LATPIN);
  ENAPORT |= (1 << ENAPIN);
  delayMicroseconds(1);
  ENAPORT &= ~(1 << ENAPIN);
  LATPORT &= ~(1 << LATPIN);

}

void WriteLEDArray() {

  SB_CommandMode = B00; // Write to PWM control registers

  for (int i = 0; i < NumLEDs; i++) {
    SB_RedCommand = LEDChannels[i][0];
    SB_GreenCommand = LEDChannels[i][1];
    SB_BlueCommand = LEDChannels[i][2];
    SB_SendPacket();
  }
  
  SB_Latch();
  
  SB_CommandMode = B01; // Write to current control registers

  for (int z = 0; z < NumLEDs; z++) SB_SendPacket();   

  SB_Latch();

}


// Example loop to cycle all LEDs through primary colors
void loop() {

  for (int i = 0; i < NumLEDs; i++) {
    LEDChannels[i][0] = 1023;
    LEDChannels[i][1] = 0;
    LEDChannels[i][2] = 0;
  }
  
  WriteLEDArray();
  
  delay(200);
  
  for (int i = 0; i < NumLEDs; i++) {
    LEDChannels[i][0] = 0;
    LEDChannels[i][1] = 1023;
    LEDChannels[i][2] = 0;
  }

  WriteLEDArray();

  delay(200);

  for (int i = 0; i < NumLEDs; i++) {
    LEDChannels[i][0] = 0;
    LEDChannels[i][1] = 0;
    LEDChannels[i][2] = 1023;
  }

  WriteLEDArray();
  
  delay(200);
  
}

Arduino Mega Code

/* Ports and Pins
 
 Direct port access is much faster than digitalWrite.
 You must match the correct port and pin as shown in the table below.
 
 Arduino Mega Pin   Port        Pin
 13.................PORTB.......7
 12.................PORTB.......6
 11.................PORTB.......5
 10.................PORTB.......4
 9..................PORTH.......6
 8..................PORTH.......5
 7..................PORTH.......4
 6..................PORTH.......3
 5..................PORTE.......3
 4..................PORTG.......5
 3..................PORTE.......5
 2..................PORTE.......4
 1 (TX).............PORTE.......1
 0 (RX).............PORTE.......0
 A7 (Analog)........PORTF.......7
 A6 (Analog)........PORTF.......6
 A5 (Analog)........PORTF.......5
 A4 (Analog)........PORTF.......4
 A3 (Analog)........PORTF.......3
 A2 (Analog)........PORTF.......2
 A1 (Analog)........PORTF.......1
 A0 (Analog)........PORTF.......0
 
*/

// Defines for use with Arduino functions
#define clockpin   13 // CI
#define enablepin  10 // EI
#define latchpin    9 // LI
#define datapin    11 // DI

// Defines for direct port access
#define CLKPORT PORTB
#define ENAPORT PORTB
#define LATPORT PORTH
#define DATPORT PORTB
#define CLKPIN  7
#define ENAPIN  4
#define LATPIN  6
#define DATPIN  5

// Variables for communication
unsigned long SB_CommandPacket;
int SB_CommandMode;
int SB_BlueCommand;
int SB_RedCommand;
int SB_GreenCommand;

// Define number of ShiftBrite modules
#define NumLEDs 5

// Create LED value storage array
int LEDChannels[NumLEDs][3] = {0};

// Set pins to outputs and initial states
void setup() {
  pinMode(datapin, OUTPUT);
  pinMode(latchpin, OUTPUT);
  pinMode(enablepin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  digitalWrite(latchpin, LOW);
  digitalWrite(enablepin, LOW);
}

void SB_SendPacket() {

  if (SB_CommandMode == B01) {
    SB_RedCommand = 127;
    SB_GreenCommand = 110;
    SB_BlueCommand = 110;
  }

  SB_CommandPacket = SB_CommandMode & B11;
  SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_BlueCommand & 1023);
  SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_RedCommand & 1023);
  SB_CommandPacket = (SB_CommandPacket << 10)  | (SB_GreenCommand & 1023);

  for (int j = 0; j < 32; j++) {
    if ((SB_CommandPacket >> (31 - j)) & 1) {
      DATPORT |= (1 << DATPIN);
    } 
    else {
      DATPORT &= ~(1 << DATPIN);
    }
    CLKPORT |= (1 << CLKPIN);
    CLKPORT &= ~(1 << CLKPIN); 
  } 
}

void SB_Latch() {

  delayMicroseconds(1);
  LATPORT |= (1 << LATPIN);
  ENAPORT |= (1 << ENAPIN);
  delayMicroseconds(1);
  ENAPORT &= ~(1 << ENAPIN);
  LATPORT &= ~(1 << LATPIN);

}

void WriteLEDArray() {

  SB_CommandMode = B00; // Write to PWM control registers

  for (int i = 0; i < NumLEDs; i++) {
    SB_RedCommand = LEDChannels[i][0];
    SB_GreenCommand = LEDChannels[i][1];
    SB_BlueCommand = LEDChannels[i][2];
    SB_SendPacket();
  }
  
  SB_Latch();
  
  SB_CommandMode = B01; // Write to current control registers

  for (int z = 0; z < NumLEDs; z++) SB_SendPacket();   

  SB_Latch();

}


// Example loop to cycle all LEDs through primary colors
void loop() {

  for (int i = 0; i < NumLEDs; i++) {
    LEDChannels[i][0] = 1023;
    LEDChannels[i][1] = 0;
    LEDChannels[i][2] = 0;
  }
  
  WriteLEDArray();
  
  delay(200);
  
  for (int i = 0; i < NumLEDs; i++) {
    LEDChannels[i][0] = 0;
    LEDChannels[i][1] = 1023;
    LEDChannels[i][2] = 0;
  }

  WriteLEDArray();

  delay(200);

  for (int i = 0; i < NumLEDs; i++) {
    LEDChannels[i][0] = 0;
    LEDChannels[i][1] = 0;
    LEDChannels[i][2] = 1023;
  }

  WriteLEDArray();
  
  delay(200);
  
}

/home/macetec/public_html/docs/data/pages/non-hardware_spi_example.txt · Last modified: 2014/08/20 14:59 by macegr