Simple 8x8 LED Matrix controller which interfaces with a Processing GUI over serial to display sketches

Dependencies:   Multi_WS2811 mbed

Fork of Multi_WS2811_test by Ned Konz

Files at this revision

API Documentation at this revision

Comitter:
bikeNomad
Date:
Thu Dec 05 15:25:16 2013 +0000
Parent:
16:5f75ea93f15d
Child:
18:d98353e8c61c
Commit message:
renamed ws2812.* to ws2811.*

Changed in this revision

LedStrip.cpp Show annotated file Show diff for this revision Revisions of this file
LedStrip.h Show annotated file Show diff for this revision Revisions of this file
WS2811.cpp Show annotated file Show diff for this revision Revisions of this file
WS2811.h Show annotated file Show diff for this revision Revisions of this file
bitband.h Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LedStrip.cpp	Thu Dec 05 15:25:16 2013 +0000
@@ -0,0 +1,80 @@
+#include "LedStrip.h"
+
+LedStrip::LedStrip(int n)
+{
+   // Allocate 3 bytes per pixel:
+    numLEDs = n;
+    pixels = (uint8_t *)malloc(numPixelBytes());
+    if (pixels) {
+        memset(pixels, 0x00, numPixelBytes()); // Init to RGB 'off' state
+    }
+}
+
+LedStrip::~LedStrip()
+{
+    free(pixels);
+}
+ 
+uint32_t LedStrip::total_luminance(void)
+{
+    uint32_t running_total;
+    running_total = 0;
+    for (int i=0; i< numPixelBytes(); i++)
+        running_total += pixels[i];
+    return running_total;
+}
+
+// Convert R,G,B to combined 32-bit color
+uint32_t LedStrip::Color(uint8_t r, uint8_t g, uint8_t b)
+{
+    // Take the lowest 7 bits of each value and append them end to end
+    // We have the top bit set high (its a 'parity-like' bit in the protocol
+    // and must be set!)
+    return ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b;
+}
+
+// store the rgb component in our array
+void LedStrip::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
+{
+    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
+
+    pixels[n*3  ] = g;
+    pixels[n*3+1] = r;
+    pixels[n*3+2] = b;
+}
+
+void LedStrip::setPixelR(uint16_t n, uint8_t r)
+{
+    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
+
+    pixels[n*3+1] = r;
+}
+
+void LedStrip::setPixelG(uint16_t n, uint8_t g)
+{
+    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
+
+    pixels[n*3] = g;
+}
+
+void LedStrip::setPixelB(uint16_t n, uint8_t b)
+{
+    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
+
+    pixels[n*3+2] = b;
+}
+
+void LedStrip::setPackedPixels(uint8_t * buffer, uint32_t n)
+{
+    if (n >= numLEDs) return;
+    memcpy(pixels, buffer, (size_t) (n*3));
+}
+
+void LedStrip::setPixelColor(uint16_t n, uint32_t c)
+{
+    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
+
+    pixels[n*3  ] = (c >> 16);
+    pixels[n*3+1] = (c >>  8);
+    pixels[n*3+2] =  c;
+}
--- a/LedStrip.h	Thu Oct 10 21:52:59 2013 +0000
+++ b/LedStrip.h	Thu Dec 05 15:25:16 2013 +0000
@@ -9,22 +9,33 @@
 // of strip may be used in a single array or container.
 
 #include "mbed.h"
+
 #ifndef LEDSTRIP_H
 #define LEDSTRIP_H
 
-class LedStrip {
- public:
-  virtual void begin(void)=0;
-  virtual void show(void)=0;
-  virtual void blank(void)=0;
-  virtual void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)=0;
-  virtual void setPackedPixels(uint8_t * buffer, uint32_t n)=0;
-  virtual void setPixelB(uint16_t n, uint8_t b)=0;
-  virtual void setPixelG(uint16_t n, uint8_t g)=0;
-  virtual void setPixelR(uint16_t n, uint8_t r)=0;
-  virtual void setPixelColor(uint16_t n, uint32_t c)=0;
-  virtual uint16_t numPixels(void)=0;
-  virtual uint32_t Color(uint8_t, uint8_t, uint8_t)=0;
-  virtual uint32_t total_luminance(void);
+class LedStrip
+{
+public:
+    LedStrip(int n);
+    ~LedStrip();
+
+    virtual void begin(void)=0;
+    virtual void show(void)=0;
+    virtual void blank(void)=0;
+
+    uint16_t numPixels(void) { return numLEDs; }
+    uint16_t numPixelBytes(void) { return numLEDs * 3; }
+    virtual uint32_t Color(uint8_t, uint8_t, uint8_t);
+    virtual uint32_t total_luminance(void);
+    virtual void setPixelB(uint16_t n, uint8_t b);
+    virtual void setPixelG(uint16_t n, uint8_t g);
+    virtual void setPixelR(uint16_t n, uint8_t r);
+    virtual void setPixelColor(uint16_t n, uint32_t c);
+    virtual void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
+    virtual void setPackedPixels(uint8_t * buffer, uint32_t n);
+
+protected:
+    uint8_t *pixels;     // Holds LED color values
+    uint16_t numLEDs;     // Number of RGB LEDs in strand
 };
 #endif
\ No newline at end of file
--- a/WS2811.cpp	Thu Oct 10 21:52:59 2013 +0000
+++ b/WS2811.cpp	Thu Dec 05 15:25:16 2013 +0000
@@ -2,97 +2,73 @@
 //
 // Parameterized and modified to use soft SPI.
 // Jas Strong <jasmine@electronpusher.org>
+// Modified to use hard SPI by Ned Konz <ned@bike-nomad.com>
 /*****************************************************************************/
 
 #include "LedStrip.h"
 #include "WS2811.h"
-#include "bitband.h"
 
-extern int onewire_speed_multiplier;   // speed setting for ws2811 et al.
-
-
-WS2811::WS2811(PinName dataPin, PinName clockPin, int n) :
-    dat(dataPin),
-    clk(clockPin) {
-    // Allocate 3 bytes per pixel:
-    numLEDs = n;
-    pixels = (uint8_t *)malloc(numLEDs * 3);
-    if (pixels) {
-        memset(pixels, 0x00, numLEDs * 3); // Init to RGB 'off' state
-    }
-    // calibrate delay loops for NRZ 
-    int i;
-    guardtime.start();
-    for (i=0; i<1000; i++)
-        /* do nothing */;
-    i=guardtime.read_us();
-    printf("ws2811:  1000 iters took %d usec.\n", i);
-    bogocal = (1000 / (onewire_speed_multiplier * i * 4.2)); // iterations per bitcell (417 nsec)
-    printf("ws2811:  calibrating to %d bogojiffies.\n", bogocal);
-    
-    data_mask = dat.get_mask();
-    clock_mask = clk.get_mask();
-    data_set = dat.get_set();
-    data_clr = dat.get_clr();
-    clock_set = clk.get_set();
-    clock_clr = clk.get_clr();
-    
-    printf("ws2811:          data mask 0x%x, data set reg 0x%x, data clear reg 0x%x\r\n", data_mask, data_set, data_clr);
-    printf("ws2811: (unused) clock mask 0x%x, clock set reg 0x%x, clock clear reg 0x%x\r\n", clock_mask, clock_set, clock_clr);
-    
+WS2811::WS2811(int n, PinName mosi, PinName sclk) :
+    LedStrip(n),
+    spi(mosi, NC, sclk)
+{
+#ifdef TARGET_KL25Z
+    spi.format(8, 3);
+#else
+    spi.format(16, 3);
+#endif
+    spi.frequency(800e3 * 16);  // 12.8 MHz => 800KHz bit rate
 }
 
 /*
  *  These chips use a one-wire protocol based on a sort of NRZ signalling- jas.
  */
- 
-void WS2811::write(uint8_t byte) {
-    
-    for (int i=0; i<8; i++) {
-        if (byte & 0x80)
-            writebit(1);
-        else
-            writebit(0);
-        byte <<= 1;
+
+inline void WS2811::writebit(bool bit)
+{
+    if (bit) {
+#ifdef TARGET_KL25Z
+        spi.write(0xff);    // 8 high
+        spi.write(0x00);    // 8 low
+#else
+        spi.write(0xff00);
+#endif
+    } else {
+#ifdef TARGET_KL25Z
+        spi.write(0xe0);    // 3 high, 5 low
+        spi.write(0x00);    // +8 low
+#else
+        spi.write(0xe000);
+#endif
     }
 }
 
-inline void WS2811::celldelay(void) {
-    for (volatile int i = 0; i<bogocal; i++)
-        /* do nothing */ ;
+void WS2811::write(uint8_t byte)
+{
+    writebit(byte & 0x80);
+    writebit(byte & 0x40);
+    writebit(byte & 0x20);
+    writebit(byte & 0x10);
+    writebit(byte & 0x08);
+    writebit(byte & 0x04);
+    writebit(byte & 0x02);
+    writebit(byte & 0x01);
 }
 
-inline void WS2811::writebit(bool bit) {
-    // first cell is always 1
-    (*data_set) = data_mask;
-    celldelay();
-    if (bit) {
-        (*clock_set) = data_mask; // dummy, we don't care but must take constant time
-        celldelay();
-    } else {
-        (*data_clr) = data_mask;
-        celldelay();
-    }
-    // last cell is always 0
-    (*data_clr) = data_mask;
-    celldelay();
-}
-
-void WS2811::begin(void) {
+void WS2811::begin(void)
+{
     blank();
     show();
 }
 
-uint16_t WS2811::numPixels(void) {
-    return numLEDs;
+void WS2811::blank(void)
+{
+    memset(pixels, 0x00, numPixelBytes());
 }
 
-void WS2811::blank(void) {
-    memset(pixels, 0x00, numLEDs * 3);
-}
-
-void WS2811::show(void) {
-    uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED
+void WS2811::show(void)
+{
+    uint16_t i, nl3 = numPixelBytes(); // 3 bytes per LED
     while (guardtime.read_us() < 50)
         /* spin */;
     __disable_irq();
@@ -104,58 +80,3 @@
 }
 
 
-uint32_t WS2811::total_luminance(void) {
-    uint32_t running_total;
-    running_total = 0;
-    for (int i=0; i<numLEDs*3; i++)
-        running_total += pixels[i];
-    return running_total;
-}
-
-// Convert R,G,B to combined 32-bit color
-uint32_t WS2811::Color(uint8_t r, uint8_t g, uint8_t b) {
-    // Take the lowest 7 bits of each value and append them end to end
-    // We have the top bit set high (its a 'parity-like' bit in the protocol
-    // and must be set!)
-    return ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b;
-}
-
-// store the rgb component in our array
-void WS2811::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
-    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
-
-    pixels[n*3  ] = g;
-    pixels[n*3+1] = r;
-    pixels[n*3+2] = b;
-}
-
-void WS2811::setPixelR(uint16_t n, uint8_t r) {
-    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
-
-    pixels[n*3+1] = r;
-}
-
-void WS2811::setPixelG(uint16_t n, uint8_t g) {
-    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
-
-    pixels[n*3] = g;
-}
-
-void WS2811::setPixelB(uint16_t n, uint8_t b) {
-    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
-
-    pixels[n*3+2] = b;
-}
-
-void WS2811::setPackedPixels(uint8_t * buffer, uint32_t n) {
-    if (n >= numLEDs) return;
-    memcpy(pixels, buffer, (size_t) (n*3));
-}
-
-void WS2811::setPixelColor(uint16_t n, uint32_t c) {
-    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed
-
-    pixels[n*3  ] = (c >> 16);
-    pixels[n*3+1] = (c >>  8);
-    pixels[n*3+2] =  c;
-}
--- a/WS2811.h	Thu Oct 10 21:52:59 2013 +0000
+++ b/WS2811.h	Thu Dec 05 15:25:16 2013 +0000
@@ -15,41 +15,28 @@
 #ifndef MBED_WS2811_H
 #define MBED_WS2811_H
 
-
-class WS2811 : public LedStrip {
-
- public:
+#ifdef TARGET_KL25Z
+#define MOSI_DEFAULT PTD2
+#define SCLK_DEFAULT PTC5
+#else
+#endif
 
-  WS2811(PinName dataPin, PinName clockPin, int n);
-  virtual void begin(void);
-  virtual void show(void);
-  virtual void blank(void);
-  virtual void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
-  virtual void setPackedPixels(uint8_t * buffer, uint32_t n);
-  virtual void setPixelB(uint16_t n, uint8_t b);
-  virtual void setPixelG(uint16_t n, uint8_t g);
-  virtual void setPixelR(uint16_t n, uint8_t r);
-  virtual void setPixelColor(uint16_t n, uint32_t c);
-  virtual uint16_t numPixels(void);
-  virtual uint32_t Color(uint8_t, uint8_t, uint8_t);
-  virtual uint32_t total_luminance(void);
+class WS2811 : public LedStrip
+{
+public:
+    WS2811(int n, PinName mosi = MOSI_DEFAULT, PinName sclk = SCLK_DEFAULT);
+    virtual void begin(void);
+    virtual void show(void);
+    virtual void blank(void);
 
- private:
-  DigitalOut dat;
-  DigitalOut clk;
-  __IO uint32_t *data_set;
-  __IO uint32_t *clock_set;
-  __IO uint32_t *data_clr;
-  __IO uint32_t *clock_clr;
-  uint32_t clock_mask;
-  uint32_t data_mask;
-  void write(uint8_t byte);
-  void writebit(bool bit);
-  void celldelay(void);
-  uint8_t *pixels;     // Holds LED color values
-  uint16_t numLEDs;     // Number of RGB LEDs in strand
-  Timer guardtime;
-  uint32_t bogocal;
-    
+private:
+    SPI spi;            // to do actual communication
+
+    Timer guardtime;
+    uint32_t bogocal;
+
+    void write(uint8_t byte);
+    void writebit(bool bit);
+    void celldelay(void);
 };
 #endif
\ No newline at end of file
--- a/bitband.h	Thu Oct 10 21:52:59 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-//*****************************************************************************
-//   +--+
-//   | ++----+
-//   +-++    |
-//     |     |
-//   +-+--+  |
-//   | +--+--+
-//   +----+    Copyright (c) 2011 Code Red Technologies Ltd.
-//
-// Header file containing C macros to provide bitbanding on Cortex-M3 MCU's
-//
-// Software License Agreement
-//
-// The software is owned by Code Red Technologies and/or its suppliers, and is
-// protected under applicable copyright laws.  All rights are reserved.  Any
-// use in violation of the foregoing restrictions may subject the user to criminal
-// sanctions under applicable laws, as well as to civil liability for the breach
-// of the terms and conditions of this license.
-//
-// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
-// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
-// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT
-// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH
-// CODE RED TECHNOLOGIES LTD.
-//
-//*****************************************************************************
-
-#ifndef BITBAND_H_
-#define BITBAND_H_
-
-/* The Cortex-M3 memory map includes two bit-band regions. These occupy the lowest
- * 1MB of the SRAM and peripheral memory regions respectively.
- * + SRAM:  Bit-band region:    0x20000000 - 0x20100000
- *          Bit-band alias:     0x22000000 - 0x23FFFFFF
- * + PERI:  Bit-band region:    0x40000000 - 0x40100000
- *          Bit-band alias:     0x42000000 - 0x43FFFFFF
- * The mapping formula:
- *      bit_word_offset = (byte_offset * 32) + (bit_number * 4)
- *      bit_word_address = bit_band_base + bit_word_offset
- * where:
- *  + bit_word_offset: the position of the target bit in the bit-band memory region
- *  + bit_word_addr: the address of the word in the alias memory region that maps to the target bit
- *  + bit_band_base: the starting address of the alias region
- *  + byte_offset: the number of byte in the bit-band region that contains the targeted bit
- *  + bit_number: is the bit position (0-7) of the targeted bit
- */
-
-/* Bit band SRAM definitions */
-#define BITBAND_SRAM_REF   0x20000000
-#define BITBAND_SRAM_BASE  0x22000000
-
-#define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + ((a-BITBAND_SRAM_REF)<<5) + (b<<2)))  // Convert SRAM address
-
-/* Bit band PERIPHERAL definitions */
-#define BITBAND_PERI_REF   0x40000000
-#define BITBAND_PERI_BASE  0x42000000
-
-#define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + ((a-BITBAND_PERI_REF)<<5) + (b<<2)))  // Convert PERI address
-
-/* Basic bit band function definitions */
-#define BITBAND_SRAM_ClearBit(a,b)  (*(volatile uint32_t *) (BITBAND_SRAM(a,b)) = 0)
-#define BITBAND_SRAM_SetBit(a,b)    (*(volatile uint32_t *) (BITBAND_SRAM(a,b)) = 1)
-#define BITBAND_SRAM_GetBit(a,b)    (*(volatile uint32_t *) (BITBAND_SRAM(a,b)))
-
-#define BITBAND_PERI_ClearBit(a,b)  (*(volatile uint32_t *) (BITBAND_PERI(a,b)) = 0)
-#define BITBAND_PERI_SetBit(a,b)    (*(volatile uint32_t *) (BITBAND_PERI(a,b)) = 1)
-#define BITBAND_PERI_GetBit(a,b)    (*(volatile uint32_t *) (BITBAND_PERI(a,b)))
-
-
-#endif /* BITBAND_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Dec 05 15:25:16 2013 +0000
@@ -0,0 +1,7 @@
+#include "mbed.h"
+#include "WS2812.h"
+
+int main(void)
+{
+    WS2812 lightStrip(60*4, PTD2, PTD3);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Dec 05 15:25:16 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9c8f0e3462fb
\ No newline at end of file