Object Model code with hardware support

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
bgrissom
Date:
Fri Sep 05 00:07:44 2014 +0000
Commit message:
Object Model code with Toshiba S0 and S1 routines compiles with ST F401RE board support. If you try to compile this for the F030 or F072, it will run out of SRAM space.

Changed in this revision

ToshibaTC62D723.cpp Show annotated file Show diff for this revision Revisions of this file
ToshibaTC62D723.hpp Show annotated file Show diff for this revision Revisions of this file
anthem.cpp Show annotated file Show diff for this revision Revisions of this file
anthem.hpp Show annotated file Show diff for this revision Revisions of this file
configs.hpp Show annotated file Show diff for this revision Revisions of this file
defines.hpp Show annotated file Show diff for this revision Revisions of this file
hardware_F072.cpp Show annotated file Show diff for this revision Revisions of this file
hardware_F072.hpp Show annotated file 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/ToshibaTC62D723.cpp	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,104 @@
+#include <cstddef>
+#include <string.h>
+#include "ToshibaTC62D723.hpp"
+
+bool gSpiMode;
+SPI* gSpiPtr = NULL;
+DigitalOut gbbTRANS(PA_4); // Global bit bang TRANS (data) line
+
+ToshibaTC62D723::ToshibaTC62D723(void)
+ : _dataIn(NULL),
+   _dataOut(NULL)
+{
+    memset(_channelBrightness, 0, sizeof(uint16_t) * NUM_CHANNELS);
+}
+
+ToshibaTC62D723::~ToshibaTC62D723(void)
+{
+    // Its good practice to clear memory in the destructor
+    memset(_channelBrightness, 0, sizeof(uint16_t) * NUM_CHANNELS);
+}
+
+void ToshibaTC62D723::shiftBrightnessDataIn(const uint16_t p_brightness)
+{
+    // TODO check return code?
+    s0(p_brightness);
+}
+
+void ToshibaTC62D723::outputBrightnessDataToLEDs(void)
+{
+    s1();
+}
+
+// S0 Command:
+//      Needs only SCK and SIN (which are SPI_SCK and SPI_MOSI respectively).
+//      This is because TRANS can be 0 for this command according to the datasheet.
+int ToshibaTC62D723::s0(const uint16_t p_value)
+{
+    if (p_value > 0 ) {
+        BAGINFO3("%x", p_value);
+    } else {
+        BAGINFO3(".");
+    }
+
+    // Command S0 and S1 share the same clock line, so we need to be
+    // careful which mode we are in.  This avoids re-initializing these
+    // pins if we are already in SPI mode.
+    // WARNING: Re-initializing every time makes the MOSI line dirty and
+    //          is wasteful for the CPU.
+    if ( gSpiMode == false &&
+         gSpiPtr  == NULL)
+    {
+        // We are not using MISO, this is a one-way bus
+        gSpiPtr = new SPI(SPI_MOSI, NC, SPI_SCK);
+
+        if (gSpiPtr == NULL) {
+            printf("ERROR: Could not allocate SPI\n");
+            return AERROR;
+        }
+
+        // Note: Polarity and phase are both 0 for the TC62D723FNG
+        // For a graphical reminder on polarity and phase, visit:
+        //     http://www.eetimes.com/document.asp?doc_id=1272534
+        gSpiPtr->format(16, 0);
+        // gSpiPtr->frequency(1000000);  // 1.5 MHz on the scope
+        gSpiPtr->frequency(24000000); // 24 MHz
+        gSpiMode = true;
+    }
+    gbbTRANS = 0; // Like an SPI slave select
+    gSpiPtr->write(p_value);
+    gbbTRANS = 1; // Like an SPI slave select
+
+    return AOK;
+}
+
+void ToshibaTC62D723::s1(void)
+{
+    BAGINFO3("\nLATCH\n");
+
+    int i = 0;
+    int j = 0;
+
+    gbbTRANS = 0;
+
+    if ( gSpiMode == true &&
+         gSpiPtr  != NULL)
+    {
+        delete gSpiPtr;
+        gSpiPtr  = NULL;
+        gSpiMode = false;
+    }
+
+    DigitalOut bbSCK (D13); // bit bang clock
+
+    bbSCK    = 0; // Start off/low
+    gbbTRANS = 1; // Set high
+
+    // Loop 6 times = 3 clock cycles
+    for (j=0; j<6; j++) { // Always use an even number here!
+        // The order of these two lines matter!
+        i == 0 ? i = 1 : i = 0;          // Toggle i
+        i == 0 ? bbSCK = 0 : bbSCK = 1;  // Set SCK to the same value as i
+    }
+    gbbTRANS = 0; // Set low
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ToshibaTC62D723.hpp	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,38 @@
+#ifndef __TOSHIBATC62D723_H__
+#define __TOSHIBATC62D723_H__
+
+#include "mbed.h"
+#include <stdint.h>
+#include "defines.hpp"
+
+// TODO  Make this the parent class and have ToshibaTC62D723 inherit from it.
+// class LEDDriver { };
+
+class ToshibaTC62D723 {
+    public:
+        // Constructor
+        ToshibaTC62D723(void);
+
+        // Default Destructor
+        virtual ~ToshibaTC62D723();
+
+        // Members
+        static const int NUM_CHANNELS = 16;
+        uint16_t _channelBrightness[NUM_CHANNELS];
+        ToshibaTC62D723 *_dataIn;
+        ToshibaTC62D723 *_dataOut;
+
+        // Member Functions
+        static void shiftBrightnessDataIn(const uint16_t p_brightness);
+        static void outputBrightnessDataToLEDs(void);
+
+
+    private:
+        // Private Member Variables
+
+        // Private Member Functions
+        static int  s0(const uint16_t p_value);
+        static void s1(void);
+};
+
+#endif // __TOSHIBATC62D723_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/anthem.cpp	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,330 @@
+#include <cstddef>
+#include <string.h>
+#include "defines.hpp"
+#include "configs.hpp"
+#include "anthem.hpp"
+
+#include <stdio.h>
+
+LEDModule::LEDModule(void)
+ : _rowNum(MODULE_HEIGHT),
+   _colNum(MODULE_WIDTH)
+{
+    int i = 0;
+
+    // Read in 3 things from the EEPROM:
+    //      - LED driver to pixel mapping
+    //      - Scan group to pixel mapping
+    //      - LED driver channel to pixel mapping
+
+    // Also read in other auxillary data from EEPROM:
+    //      - Module brightness
+
+    _moduleBrightness  = 1.0f; // FIXME get from EEPROM
+
+    // FIXME where does this come from?  It will change depending on day/night correct?
+    _displayBrightness = 1.0f;
+
+    //--------------------------------------------
+    //               SCAN GROUPS
+    //--------------------------------------------
+    ScanGroup *lastScanGroup = NULL;
+    for (i = 0; i < NUM_SCANGROUPS; i++) {
+        if (i == 0) {
+            _currentScanGroup = &_scanGroupArray[i];
+        }
+
+        // Tie the last to this one
+        if (lastScanGroup != NULL) {
+            lastScanGroup->_nextScanGroup = &_scanGroupArray[i];
+        }
+
+        // If we are the last, tie it to the first
+        if (i == (NUM_SCANGROUPS-1)) {
+            _scanGroupArray[i]._nextScanGroup = &_scanGroupArray[0];
+        }
+
+        lastScanGroup = &_scanGroupArray[i];
+    }
+    //--------------------------------------------
+    //--------------------------------------------
+
+
+    //--------------------------------------------
+    //               LED DRIVERS
+    //--------------------------------------------
+    ToshibaTC62D723 *lastDriver = NULL;
+    for (i = 0; i < NUM_LED_DRIVERS; i++) {
+        if (i == 0) {
+            _dataOutDriver = &_ledDriverArray[i];
+        }
+
+        // Tie the last to this one
+        if (lastDriver != NULL) {
+            lastDriver->_dataOut = &_ledDriverArray[i];
+            _ledDriverArray[i]._dataIn = lastDriver;
+        }
+
+        if (i == (NUM_LED_DRIVERS-1)) {
+            _dataInDriver = &_ledDriverArray[i];
+        }
+
+        lastDriver = &_ledDriverArray[i];
+    }
+    //--------------------------------------------
+    //--------------------------------------------
+
+
+    //--------------------------------------------
+    //               LED PIXELS
+    //--------------------------------------------
+    int x = 0;
+    int y = 0;
+    for (y = 0; y < MODULE_WIDTH; y++) {
+        for (x = 0; x < MODULE_HEIGHT; x++) {
+            // FIXME Get the calibration factor from EEPROM
+            _pixel[x][y].setCalibrationFactor(1.0f);
+            // FIXME Get the calibration factor from EEPROM
+            _pixel[x][y].  _redLED.setCalibrationFactor(1.0f);
+            _pixel[x][y]._greenLED.setCalibrationFactor(1.0f);
+            _pixel[x][y]. _blueLED.setCalibrationFactor(1.0f);
+            _pixel[x][y].  _redLED._ledDriver = &_ledDriverArray[ g_driverChain[g_pix2Drv[x][y].  redDrv] ];
+            _pixel[x][y]._greenLED._ledDriver = &_ledDriverArray[ g_driverChain[g_pix2Drv[x][y].greenDrv] ];
+            _pixel[x][y]. _blueLED._ledDriver = &_ledDriverArray[ g_driverChain[g_pix2Drv[x][y]. blueDrv] ];
+            _pixel[x][y].  _redLED.setDriverChannelNum(g_pix2DrvChan[x][y]);
+            _pixel[x][y]._greenLED.setDriverChannelNum(g_pix2DrvChan[x][y]);
+            _pixel[x][y]. _blueLED.setDriverChannelNum(g_pix2DrvChan[x][y]);
+
+            // Nothing needs to change for column-based vs row-based scangroups
+            _scanGroupArray[ g_pix2ScanGroup[x][y] ].addLED( &(_pixel[x][y].  _redLED) );
+            _scanGroupArray[ g_pix2ScanGroup[x][y] ].addLED( &(_pixel[x][y]._greenLED) );
+            _scanGroupArray[ g_pix2ScanGroup[x][y] ].addLED( &(_pixel[x][y]. _blueLED) );
+        }
+    }
+    //--------------------------------------------
+    //--------------------------------------------
+}
+
+
+LEDModule::~LEDModule(void)
+{
+}
+
+void LEDModule::displayImage(void)
+{
+    int i = 0;
+
+    adjustImage();
+
+    for (i = 0; i < NUM_SCANGROUPS; i++) {
+        BAGINFO3("\nScanGroup[%d]", i);
+        _scanGroupArray[i].mapLEDsToDrivers();
+        shiftBrightnessDataIn();
+        enableNextScanGroup();
+        ToshibaTC62D723::outputBrightnessDataToLEDs();
+    }
+}
+
+
+void LEDModule::adjustImage(void)
+{
+    int x = 0;
+    int y = 0;
+    PixelColor oldColor;
+    for (y = 0; y < MODULE_WIDTH; y++) {
+        for (x = 0; x < MODULE_HEIGHT; x++) {
+            oldColor = _sourceImage.getPixel(x, y);
+            _pixel[x][y]._redLED.setBrightness
+                                (
+                                    oldColor._r * 256
+                                    * _displayBrightness
+                                    * _moduleBrightness
+                                    * _pixel[x][y].getCalibrationFactor()
+                                    * _pixel[x][y]._redLED.getCalibrationFactor()
+                                );
+            _pixel[x][y]._greenLED.setBrightness
+                                (
+                                    oldColor._g * 256
+                                    * _displayBrightness
+                                    * _moduleBrightness
+                                    * _pixel[x][y].getCalibrationFactor()
+                                    * _pixel[x][y]._greenLED.getCalibrationFactor()
+                                );
+            _pixel[x][y]._blueLED.setBrightness
+                                (
+                                    oldColor._b * 256
+                                    * _displayBrightness
+                                    * _moduleBrightness
+                                    * _pixel[x][y].getCalibrationFactor()
+                                    * _pixel[x][y]._blueLED.getCalibrationFactor()
+                                );
+        }
+    }
+}
+
+
+void LEDModule::shiftBrightnessDataIn(void)
+{
+    int i = 0; // Driver index
+    int chan = 0; // Channel
+    for (i = NUM_LED_DRIVERS-1; i >= 0; i--) {
+        BAGINFO3("\nDRV[%02d]", g_dbgDrvChain[i]);
+        for (chan = (ToshibaTC62D723::NUM_CHANNELS)-1; chan >= 0; chan--) {
+            ToshibaTC62D723::shiftBrightnessDataIn(_ledDriverArray[i]._channelBrightness[chan]);
+        }
+    }
+}
+
+
+void LEDModule::enableNextScanGroup(void)
+{
+    ScanGroup *lastScanGroup = NULL;
+    if (_currentScanGroup != NULL) {
+        lastScanGroup = _currentScanGroup;
+        if (_currentScanGroup->_nextScanGroup != NULL) {
+            _currentScanGroup = _currentScanGroup->_nextScanGroup;
+            setPinToValue(lastScanGroup->getTransistorMCUPinNum(), LOW);
+            setPinToValue(_currentScanGroup->getTransistorMCUPinNum(), HIGH);
+        }
+    }
+}
+
+
+void LEDModule::setPinToValue(int p_pin, int p_val)
+{
+    // TODO
+    // Set a GPIO value here
+}
+
+
+ScanGroup::ScanGroup(void)
+ : _nextScanGroup(NULL),
+   _transistorMCUPinNum(0),
+   _index(0)
+{
+    memset(_LEDs, 0, sizeof(LED*) * LEDS_PER_SCANGROUP);
+}
+
+
+ScanGroup::~ScanGroup(void)
+{
+    // Its good practice to clear memory in the destructor
+    memset(_LEDs, 0, sizeof(LED*) * LEDS_PER_SCANGROUP);
+}
+
+
+// For all individual LEDs in this scangroup, set its driver's
+// brightness for the appropriate channel.
+void ScanGroup::mapLEDsToDrivers(void)
+{
+    int i = 0;
+    for (i = 0; i < LEDS_PER_SCANGROUP; i++) {
+        _LEDs[i]->_ledDriver->_channelBrightness[_LEDs[i]->getDriverChannelNum()] = _LEDs[i]->getBrightness();
+    }
+}
+
+
+void ScanGroup::addLED(LED *p_led)
+{
+    if ( (_index < LEDS_PER_SCANGROUP) &&
+         (p_led != NULL)
+       )
+    {
+        _LEDs[_index] = p_led;
+        _index++;
+    }
+}
+
+int ScanGroup::getTransistorMCUPinNum(void)
+{
+    // TODO
+    return 0;
+}
+
+
+LEDPixel::LEDPixel(void)
+ : _calibrationFactor(0.0f)
+{
+}
+
+LEDPixel::~LEDPixel(void)
+{
+}
+
+float LEDPixel::getCalibrationFactor(void)
+{
+    return _calibrationFactor;
+}
+
+void LEDPixel::setCalibrationFactor(float p_cal)
+{
+    _calibrationFactor = p_cal;
+}
+
+
+LED::LED(void)
+ : _ledDriver(NULL),
+   _calibrationFactor(0.0f),
+   _driverChannelNum(0),
+   _brightness(0)
+{
+}
+
+LED::~LED(void)
+{
+}
+
+float LED::getCalibrationFactor(void)
+{
+    return _calibrationFactor;
+}
+
+void LED::setCalibrationFactor(float p_val)
+{
+    _calibrationFactor = p_val;
+}
+
+uint8_t LED::getDriverChannelNum(void)
+{
+    return _driverChannelNum;
+}
+
+void LED::setDriverChannelNum(uint8_t p_val)
+{
+    _driverChannelNum = p_val;
+}
+
+uint16_t LED::getBrightness(void)
+{
+    return _brightness;
+}
+
+void LED::setBrightness(uint16_t p_val)
+{
+    _brightness = p_val;
+}
+
+
+Image::Image(void)
+{
+}
+Image::~Image(void)
+{
+}
+PixelColor Image::getPixel(uint16_t x, uint16_t y)
+{
+    return _imgPixel[x][y];
+}
+void Image::setPixel(uint16_t x, uint16_t y, PixelColor p_pix)
+{
+    _imgPixel[x][y] = p_pix;
+}
+
+
+PixelColor::PixelColor(void)
+ : _r(0), _g(0), _b(0)
+{
+}
+PixelColor::~PixelColor(void)
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/anthem.hpp	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,181 @@
+#ifndef __ANTHEM_H__
+#define __ANTHEM_H__
+
+#include <stdint.h>
+#include "defines.hpp"
+#include "ToshibaTC62D723.hpp"
+
+// CODING STANDARDS:
+//      Local     variable: var
+//      Global    variable: g_var
+//      Paramater variable: p_var
+//      Member    variable: _var
+
+class LED {
+    public:
+        // Constructor
+        LED(void);
+
+        // Default Destructor
+        virtual ~LED();
+
+        // Members
+        ToshibaTC62D723 *_ledDriver;
+
+        // Member Functions
+        float    getCalibrationFactor (void);
+        void     setCalibrationFactor (float p_val);
+        uint8_t  getDriverChannelNum  (void);
+        void     setDriverChannelNum  (uint8_t p_val);
+        uint16_t getBrightness        (void);
+        void     setBrightness        (uint16_t p_val);
+
+
+    private:
+        // Private Member Variables
+        float    _calibrationFactor;
+        uint8_t  _driverChannelNum;
+        uint16_t _brightness;
+
+        // Private Member Functions
+};
+
+
+class LEDPixel {
+    public:
+        // Constructor
+        LEDPixel(void);
+
+        // Default Destructor
+        virtual ~LEDPixel();
+
+        // Members
+        LED _redLED;
+        LED _greenLED;
+        LED _blueLED;
+
+        // Member Functions
+        float getCalibrationFactor(void);
+        void  setCalibrationFactor(float p_cal);
+
+
+    private:
+        // Private Member Variables
+        float _calibrationFactor;
+
+        // Private Member Functions
+};
+
+
+class ScanGroup {
+    public:
+        // Constructor
+        ScanGroup(void);
+
+        // Default Destructor
+        virtual ~ScanGroup();
+
+        // Members
+        ScanGroup *_nextScanGroup;
+
+        // Member Functions
+        void mapLEDsToDrivers(void);
+        void addLED(LED *p_led);
+        int getTransistorMCUPinNum(void);
+
+
+    private:
+        // Private Member Variables
+        uint16_t _transistorMCUPinNum;
+        LED *_LEDs[LEDS_PER_SCANGROUP];
+        uint16_t _index; // Index into the _LEDs array
+
+        // Private Member Functions
+};
+
+
+class PixelColor {
+    public:
+        // Constructor
+        PixelColor(void);
+
+        // Default Destructor
+        virtual ~PixelColor();
+
+        // Members
+        uint8_t _r;
+        uint8_t _g;
+        uint8_t _b;
+
+        // Member Functions
+
+
+    private:
+        // Private Member Variables
+
+        // Private Member Functions
+};
+
+
+class Image {
+    public:
+        // Constructor
+        Image(void);
+
+        // Default Destructor
+        virtual ~Image();
+
+        // Members
+
+        // Member Functions
+        PixelColor getPixel(uint16_t x, uint16_t y);
+        void setPixel(uint16_t x, uint16_t y, PixelColor p_pix);
+
+
+    private:
+        // Private Member Variables
+        PixelColor _imgPixel[MODULE_WIDTH][MODULE_HEIGHT];
+
+        // Private Member Functions
+};
+
+
+class LEDModule {
+    public:
+        // Constructor
+        LEDModule(void);
+
+        // Default Destructor
+        virtual ~LEDModule();
+
+        // Members
+        Image   _sourceImage;
+
+        // Member Functions
+        void displayImage(void);
+
+
+    private:
+        // Private Member Variables
+        uint8_t _rowNum;
+        uint8_t _colNum;
+        float   _moduleBrightness;
+        float   _displayBrightness;
+        ScanGroup _scanGroupArray[NUM_SCANGROUPS];
+        ScanGroup *_currentScanGroup;
+        ToshibaTC62D723 _ledDriverArray[NUM_LED_DRIVERS];
+        ToshibaTC62D723 *_dataOutDriver; // This is at the begginging of the chain.
+                                         // Data is shifted into this driver.
+        ToshibaTC62D723 *_dataInDriver;  // This is at the end of the chain.
+                                         // Error messages are received from this driver.
+        LEDPixel _pixel        [MODULE_WIDTH][MODULE_HEIGHT];
+
+        // Private Member Functions
+        void adjustImage(void);
+        void shiftBrightnessDataIn(void);
+        void enableNextScanGroup(void);
+        void setPinToValue(int p_pin, int p_val);
+};
+
+
+#endif // __ANTHEM_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs.hpp	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,194 @@
+#ifndef __CONFIGS_H__
+#define __CONFIGS_H__
+
+#include <stdint.h>
+#include "defines.hpp"
+
+// FIXME populate this from the EEPROM
+
+// NOTE:
+//     Each "pixel" is three LEDs: Red, Green, Blue.  Each LED in a pixel can be
+//     (and usually is!) driven by a different driver.  It is not as simple as a
+//     pixel-to-driver mapping, it actually consists of 3 led-to-driver mappings.
+typedef struct ColorDrv_t {
+    uint8_t redDrv;
+    uint8_t greenDrv;
+    uint8_t blueDrv;
+} ColorDrv;
+
+// Pixel to LED driver mapping
+static const ColorDrv g_pix2Drv[MODULE_WIDTH][MODULE_HEIGHT] =
+{
+    { { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7} },
+    { { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7} },
+    { { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7} },
+    { { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7} },
+    { { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7} },
+    { { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7} },
+    { { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7} },
+    { { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 2, 3, 1}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 5, 6, 4}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7}, { 8, 9, 7} },
+    { {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29} },
+    { {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29} },
+    { {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29} },
+    { {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29} },
+    { {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29} },
+    { {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29} },
+    { {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29} },
+    { {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {24,25,23}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {27,28,26}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29}, {30,31,29} },
+    { {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34} },
+    { {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34}, {33,32,34} }
+};
+
+
+// Pixel to LED driver channel mapping
+static const uint8_t g_pix2DrvChan[MODULE_WIDTH][MODULE_HEIGHT] =
+{
+    { 0, 0, 0,15,15,15, 0, 0, 0,15,15,15, 0, 0, 0,15,15,15},
+    { 1, 1, 1,14,14,14, 1, 1, 1,14,14,14, 1, 1, 1,14,14,14},
+    { 2, 2, 2,13,13,13, 2, 2, 2,13,13,13, 2, 2, 2,13,13,13},
+    { 3, 3, 3,12,12,12, 3, 3, 3,12,12,12, 3, 3, 3,12,12,12},
+    { 4, 4, 4,11,11,11, 4, 4, 4,11,11,11, 4, 4, 4,11,11,11},
+    { 5, 5, 5,10,10,10, 5, 5, 5,10,10,10, 5, 5, 5,10,10,10},
+    { 6, 6, 6, 9, 9, 9, 6, 6, 6, 9, 9, 9, 6, 6, 6, 9, 9, 9},
+    { 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 8, 8},
+    { 0, 0, 0,15,15,15, 0, 0, 0,15,15,15, 0, 0, 0,15,15,15},
+    { 1, 1, 1,14,14,14, 1, 1, 1,14,14,14, 1, 1, 1,14,14,14},
+    { 2, 2, 2,13,13,13, 2, 2, 2,13,13,13, 2, 2, 2,13,13,13},
+    { 3, 3, 3,12,12,12, 3, 3, 3,12,12,12, 3, 3, 3,12,12,12},
+    { 4, 4, 4,11,11,11, 4, 4, 4,11,11,11, 4, 4, 4,11,11,11},
+    { 5, 5, 5,10,10,10, 5, 5, 5,10,10,10, 5, 5, 5,10,10,10},
+    { 6, 6, 6, 9, 9, 9, 6, 6, 6, 9, 9, 9, 6, 6, 6, 9, 9, 9},
+    { 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 8, 8},
+    { 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0},
+    { 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9,10,10,10,11,11,11}
+};
+
+
+// Pixel to scan group mapping
+static const uint8_t g_pix2ScanGroup[MODULE_WIDTH][MODULE_HEIGHT] =
+{
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2},
+    { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2}
+};
+
+
+// The driver numbers are based on the PCB schematic and they are connected to
+// each other as shown below (i.e. #2 connected to #5 connected to #8...)
+//
+// Index, Driver Number
+//
+//    0,  2
+//    1,  5
+//    2,  8
+//    3, 24
+//    4, 27
+//    5, 30
+//    6, 33
+//    7,  1
+//    8,  4
+//    9,  7
+//   10, 23
+//   11, 26
+//   12, 29
+//   13, 34
+//   14,  3
+//   15,  6
+//   16,  9
+//   17, 25
+//   18, 28
+//   19, 31
+//   20, 32
+
+// Debug driver chain
+static const uint8_t g_dbgDrvChain[21] =
+{
+// Driver Number,  // Index
+     2, //  0
+     5, //  1
+     8, //  2
+    24, //  3
+    27, //  4
+    30, //  5
+    33, //  6
+     1, //  7
+     4, //  8
+     7, //  9
+    23, // 10
+    26, // 11
+    29, // 12
+    34, // 13
+     3, // 14
+     6, // 15
+     9, // 16
+    25, // 17
+    28, // 18
+    31, // 19
+    32  // 20
+};
+
+// The problem is that in software we'll have the driver number from the
+// pixel2Driver mapping and we'll need the index of the driver.  We could
+// take the above mapping and create a translation routine (search for
+// the driver number and return the index) OR we could instead make a
+// little array where you lookup by using the driver number as the index
+// and the value is the true index as shown above.
+//
+// This is like the reverse mapping of the above mapping.
+
+static const uint8_t g_driverChain[35] =
+{
+        // Index = driver number
+  0xFF, //     0 = No such driver
+     7, //     1 =  7
+     0, //     2 =  0
+    14, //     3 = 14
+     8, //     4 =  8
+     1, //     5 =  1
+    15, //     6 = 15
+     9, //     7 =  9
+     2, //     8 =  2
+    16, //     9 = 16
+  0xFF, //    10 = No such driver
+  0xFF, //    11 = No such driver
+  0xFF, //    12 = No such driver
+  0xFF, //    13 = No such driver
+  0xFF, //    14 = No such driver
+  0xFF, //    15 = No such driver
+  0xFF, //    16 = No such driver
+  0xFF, //    17 = No such driver
+  0xFF, //    18 = No such driver
+  0xFF, //    19 = No such driver
+  0xFF, //    20 = No such driver
+  0xFF, //    21 = No such driver
+  0xFF, //    22 = No such driver
+    10, //    23 = 10
+     3, //    24 = 3
+    17, //    25 = 17
+    11, //    26 = 11
+     4, //    27 = 4
+    18, //    28 = 18
+    12, //    29 = 12
+     5, //    30 = 5
+    19, //    31 = 19
+    20, //    32 = 20
+     6, //    33 = 6
+    13  //    34 = 13
+};
+
+#endif // __CONFIGS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/defines.hpp	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,31 @@
+#ifndef __ANTHEM_DEFINES_H__
+#define __ANTHEM_DEFINES_H__
+
+// Global Definitions
+#define AOK    (0)   // Anthem OK    (can't clobber global definiton)
+#define AERROR (-1)  // Anthem ERROR (can't clobber global definiton)
+
+#define  MODULE_WIDTH     (18)  // Module width  (i.e. this PCB is 20 X 20 pixels)
+#define  MODULE_HEIGHT    (18)  // Module height (i.e. this PCB is 20 X 20 pixels)
+
+#define  NUM_SCANGROUPS   (3)  // In the future maybe store this on the EEPROM?
+// 18 X 18 Board
+#define  NUM_LED_DRIVERS (21)  // 7 sections with 3 LED driver chips each on a 18 X 18 board
+// 20 X 20 Board
+// #define  NUM_LED_DRIVERS (27)  // 9 sections with 3 LED driver chips each on a 20 X 20 board
+
+#define  PIXELS_PER_SCANGROUP (MODULE_WIDTH*MODULE_HEIGHT/NUM_SCANGROUPS)
+// There are 3 LEDs per pixel
+#define  LEDS_PER_SCANGROUP   (PIXELS_PER_SCANGROUP*3)
+#define  LOW  (0)
+#define  HIGH (1)
+
+// Enable these for debugging
+#define BAGINFO1(fmt, args...)  do { } while(0)
+// #define BAGINFO1(fmt, args...) printf("BAGINFO1 (%s|%s()|%d): " fmt, __FILE__, __func__, __LINE__, ## args)
+#define BAGINFO2(fmt, args...)  do { } while(0)
+// #define BAGINFO2(fmt, args...) printf("BAGINFO2 (%s|%s()|%d): " fmt, __FILE__, __func__, __LINE__, ## args)
+#define BAGINFO3(fmt, args...)  do { } while(0)
+// #define BAGINFO3(fmt, args...) printf(fmt, ## args)
+
+#endif // __ANTHEM_DEFINES_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hardware_F072.cpp	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,139 @@
+#include "hardware_F072.hpp"
+
+static TIM_HandleTypeDef TimHandleBAG;
+
+static void pwmout_write_BAG(pwmout_t* obj, float value) {
+    TIM_OC_InitTypeDef sConfig;
+    int channel = 0;
+    int complementary_channel = 0;
+
+    TimHandleBAG.Instance = (TIM_TypeDef *)(obj->pwm);
+
+    if (value < (float)0.0) {
+        value = 0.0;
+    } else if (value > (float)1.0) {
+        value = 1.0;
+    }
+
+    obj->pulse = (uint32_t)((float)obj->period * value);
+
+    // Configure channels
+    sConfig.OCMode       = TIM_OCMODE_PWM1;
+    sConfig.Pulse        = obj->pulse;
+    sConfig.OCPolarity   = TIM_OCPOLARITY_HIGH;
+    sConfig.OCNPolarity  = TIM_OCNPOLARITY_HIGH;
+    sConfig.OCFastMode   = TIM_OCFAST_DISABLE;
+    sConfig.OCIdleState  = TIM_OCIDLESTATE_RESET;
+    sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
+
+    switch (obj->pin) {
+        // Channels 1
+        case PA_2:
+        case PA_4:
+        case PA_6:
+        case PA_7:
+        case PA_8:
+        case PB_1:
+        case PB_4:
+        case PB_8:
+        case PB_9:
+        case PB_14:
+        case PC_6:
+            channel = TIM_CHANNEL_1;
+            break;
+        // Channels 1N
+        case PA_1:
+        case PB_6:
+        case PB_7:
+        case PB_13:
+            channel = TIM_CHANNEL_1;
+            complementary_channel = 1;
+            break;
+        // Channels 2
+        case PA_3:
+        case PA_9:
+        case PB_5:
+        case PB_15:
+        case PC_7:
+            channel = TIM_CHANNEL_2;
+            break;
+        // Channels 3
+        case PA_10:
+        case PB_0:
+        case PC_8:
+            channel = TIM_CHANNEL_3;
+            break;
+        // Channels 4
+        case PA_11:
+        case PC_9:
+            channel = TIM_CHANNEL_4;
+            break;
+        default:
+            return;
+    }
+
+    HAL_TIM_PWM_ConfigChannel(&TimHandleBAG, &sConfig, channel);
+
+    if (complementary_channel) {
+        HAL_TIMEx_PWMN_Start(&TimHandleBAG, channel);
+    } else {
+        HAL_TIM_PWM_Start(&TimHandleBAG, channel);
+    }
+}
+
+
+void pwmout_period_ns(pwmout_t* obj, int us) {
+    TimHandleBAG.Instance = (TIM_TypeDef *)(obj->pwm);
+
+    float dc = pwmout_read(obj);
+
+    __HAL_TIM_DISABLE(&TimHandleBAG);
+
+    // Update the SystemCoreClock variable
+    SystemCoreClockUpdate();
+
+    TimHandleBAG.Init.Period        = us - 1;
+    // BAG Orig:  TimHandle.Init.Prescaler     = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
+    TimHandleBAG.Init.Prescaler     = 0; // BAG 1 ns tick (?)
+    TimHandleBAG.Init.ClockDivision = 0;
+    TimHandleBAG.Init.CounterMode   = TIM_COUNTERMODE_UP;
+    HAL_TIM_PWM_Init(&TimHandleBAG);
+
+    // Set duty cycle again
+    pwmout_write_BAG(obj, dc);
+
+    // Save for future use
+    obj->period = us;
+
+    __HAL_TIM_ENABLE(&TimHandleBAG);
+}
+
+
+/* USED FOR THE F030 BOARD
+// This code is based off:
+// mbed/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8/pwmout_api.c  pwmout_period_us()
+void pwmout_period_ns_NOT_USED(pwmout_t* obj, int us) {
+    TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm);
+    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+    float dc = pwmout_read(obj);
+
+    TIM_Cmd(tim, DISABLE);
+
+    obj->period = us;
+
+    TIM_TimeBaseStructure.TIM_Period = obj->period - 1;
+    // Orig code:  TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
+    TIM_TimeBaseStructure.TIM_Prescaler = 0;  // BAG 1 ns tick (?)
+    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
+    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
+    TIM_TimeBaseInit(tim, &TIM_TimeBaseStructure);
+
+    // Set duty cycle again
+    pwmout_write(obj, dc);
+
+    TIM_ARRPreloadConfig(tim, ENABLE);
+
+    TIM_Cmd(tim, ENABLE);
+}
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hardware_F072.hpp	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,8 @@
+#ifndef __HARDWARE_F072_H__
+#define __HARDWARE_F072_H__
+
+#include "mbed.h"
+
+void pwmout_period_ns(pwmout_t* obj, int us);
+
+#endif // __HARDWARE_F072_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,121 @@
+#include "mbed.h"
+#include <stdio.h>
+#include "anthem.hpp"
+#include "hardware_F072.hpp"
+
+// Definitions
+#define PIN_41 PB_5
+#define PIN_46 PB_9
+#define PIN_32 PA_11
+#define PIN_20 PB_2
+#define HEX_ONE_THOUSAND (0x03E8)
+const int SCLK_ENABLED = 0;
+
+// Forward Declarations
+void display_RthenGthenB_for_1_pixel(uint16_t xON, uint16_t yON);
+void debug_printf(uint16_t xON, uint16_t yON, int colorRotate);
+
+// Globals
+LEDModule g_mod;
+DigitalOut ENA(PIN_41);
+DigitalOut ENB(PIN_46);
+DigitalOut ENC(PIN_32);
+DigitalOut EnSclk(PIN_20);
+
+
+int main (int argc, char *argv[])
+{
+    uint16_t x = 0;
+    uint16_t y = 0;
+
+    ENA = 1;
+    ENB = 1;
+    ENC = 1;
+    EnSclk = SCLK_ENABLED;
+
+    // NOTE: 24MHz is half the 48MHz clock rate.  The PWM registers
+    //       seem to only allow 24MHz at this point, so I'm matching
+    //       the SPI bus speed to be the same.
+    //
+    //       1/24MHz  =>  1/(24*10^6)  =>  41.6*10^-9 second period,
+    //       which means 41.6ns period and 20.8ns pulse width at
+    //       50% duty cycle (which seems to be right for the SPI clock
+    //       line as well as a reasonable choice for the PWM line).
+
+    // PWMCLK
+    pwmout_t outs;
+    pwmout_init(&outs, PB_4);
+    pwmout_period_ns(&outs, 2); // 24 MHz (not very clean on the scope)
+    // pwmout_period_ns(&outs, 40); // 1.2 MHz on the scope
+    // Very slow!  pwmout_period_us(&outs, 2);
+    pwmout_write(&outs, 0.5f); // Duty cycle 50%
+
+
+    for (y = 0; y < MODULE_WIDTH; y++) {
+        for (x = 0; x < MODULE_HEIGHT; x++) {
+            display_RthenGthenB_for_1_pixel(x, y);
+        }
+    }
+
+    return 0;
+}
+
+
+// This will display 3 "images":
+//
+// For one pixel location only, it will:
+//     - Red   LED of that pixel ON (all the rest off)
+//     - Green LED of that pixel ON (all the rest off)
+//     - Blue  LED of that pixel ON (all the rest off)
+//
+void display_RthenGthenB_for_1_pixel(uint16_t xON, uint16_t yON)
+{
+    PixelColor srcPix;
+    const uint8_t brightness = 0x07;
+    int colorRotate = 0; // 0=Red, 1=Green, 2=Blue
+    uint16_t x = 0;
+    uint16_t y = 0;
+
+    for (colorRotate = 0; colorRotate < 3; colorRotate++) {
+        debug_printf(xON, yON, colorRotate);
+        for (y = 0; y < MODULE_WIDTH; y++) {
+            for (x = 0; x < MODULE_HEIGHT; x++) {
+                if ( (xON == x) &&  // Should this pixel be turned on?
+                     (yON == y) )
+                {
+                    if (colorRotate == 0) {
+                        srcPix._r = brightness;
+                        srcPix._g = 0;
+                        srcPix._b = 0;
+                    } else if (colorRotate == 1) {
+                        srcPix._r = 0;
+                        srcPix._g = brightness;
+                        srcPix._b = 0;
+                    } else if (colorRotate == 2) {
+                        srcPix._r = 0;
+                        srcPix._g = 0;
+                        srcPix._b = brightness;
+                    }
+                } else {
+                    // This pixel should be turned off
+                    srcPix._r = 0;
+                    srcPix._g = 0;
+                    srcPix._b = 0;
+                }
+                g_mod._sourceImage.setPixel(x, y, srcPix);
+            }
+        }
+        g_mod.displayImage();
+    }
+}
+
+void debug_printf(uint16_t x, uint16_t y, int color)
+{
+    if (color == 0) {
+        BAGINFO3("\nPICTURE RED   x[%d] y[%d]", x, y);
+    } else if (color == 1) {
+        BAGINFO3("\nPICTURE GREEN x[%d] y[%d]", x, y);
+    } else if (color == 2) {
+        BAGINFO3("\nPICTURE BLUE  x[%d] y[%d]", x, y);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Sep 05 00:07:44 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9327015d4013
\ No newline at end of file