I2c slave device to control NeoPixel strings

Dependencies:   NeoPixelString SimplyLog

Example program

#include "mbed.h"
#include "neopixel_string.h"
#include "i2c_device.h"
#include "neopixel_string_factory.h"
#include "neopixel_i2c_daemon.h"

// This must be an SPI MOSI pin.
#define DATA_PIN p5
#define STRING_SIZE 8

#define DEBUG_MODE 1
#include "log.h"

Serial pc(USBTX, USBRX); // tx, rx

int main() {
    pc.baud(115200);
    SimplyLog::Log::i("Neopixel driver loading\r\n");
    
    I2cSettings settings;
    settings.frequency = 100000;
    settings.address = 0x80;

    SimplyLog::Log::i("Slave is working @ %dHz\r\n", settings.frequency);
    SimplyLog::Log::i("Slave is working @ SLAVE_ADDRESS = 0x%x\r\n", settings.address);    
    
    SimplyLog::Log::i("Creating NeoPixel String\r\n");
    NeoPixelString * first_string = NeoPixelStringFactory::createNeoPixelString(DATA_PIN, STRING_SIZE);
    
    SimplyLog::Log::i("Creating I2cDevice\r\n");
    I2cDevice i2c(p28, p27, &settings);
    
    SimplyLog::Log::i("Creating NeoPixel I2c Daemon\r\n");
    NeoPixelI2cDaemon neo(&i2c, LED1);
    neo.attachPixelString(first_string);

    SimplyLog::Log::i("Listening in blocking mode\r\n");
    neo.listen(true);
    
    while(1) { }
}

neopixel_i2c_daemon.cpp

Committer:
dwini
Date:
2015-10-25
Revision:
2:e0269262d1f2
Parent:
0:3a31c84ed525

File content as of revision 2:e0269262d1f2:

#include "neopixel_i2c_daemon.h"

#define DEBUG_MODE 1
#include "log.h"

NeoPixelI2cDaemon::NeoPixelI2cDaemon(I2cDevice * i2c, PinName alive_pin) : alive(alive_pin) {
    this->i2c = i2c;
    cAlive = 0;
}

void NeoPixelI2cDaemon::attachPixelString(NeoPixelString * pixelstring) {
    pixelstrings.push_back(pixelstring);   
}

void NeoPixelI2cDaemon::allOff(void) {
    for (unsigned int i = 0; i < pixelstrings.size(); i++) {
        pixelstrings[i]->update(Colors::Black);
    }   
}

void NeoPixelI2cDaemon::allSingleColor(neopixel::Pixel singlecolor) {
    for (unsigned int i = 0; i < pixelstrings.size(); i++) {
        pixelstrings[i]->update(singlecolor);
    }   
}

void NeoPixelI2cDaemon::diagnoseAll(void) {
    for (unsigned int i = 0; i < pixelstrings.size(); i++) {
        pixelstrings[i]->diagnose();
    }   
}

void NeoPixelI2cDaemon::listen(bool blocking=false) {
    char buffer[10];

    while (blocking) {
        // Check for i2c message
        int i = i2c->receive();
            // NoData - the slave has not been addressed
            // ReadAddressed - the master has requested a read from this slave
            // WriteAddressed - the master is writing to this slave
            // WriteGeneral - the master is writing to all slave

        switch (i) {

            case I2cDevice::ReadAddressed:
                char sendbuffer[1];
                sendbuffer[0] = pixelstrings.size();
                int result = i2c->write(sendbuffer, sizeof(sendbuffer));
                i2c->stop();

                if (!result) {     // 0 on success, non-0 otherwise
                    SimplyLog::Log::i("Send info to master successfully\r\n");
                } else {
                    SimplyLog::Log::w("Send info to master failed\r\n");
                }
                break;

            case I2cDevice::WriteAddressed:
            {
                // First we read the command byte
                int command = i2c->read();
                
                // Check the command
                switch (command)
                {
                    case OFF:
                        i2c->stop();    // Necessary !! Otherwise write will fail on master end
                        SimplyLog::Log::i("Killing all neopixel leds\r\n");
                        allOff();
                        break;

                    case DIAGNOSTIC:
                        i2c->stop();    // Necessary !! Otherwise write will fail on master end
                        SimplyLog::Log::i("Executing diagnostic of neopixel strings\r\n");
                        diagnoseAll();
                        SimplyLog::Log::i("Diagnostic finished\r\n");
                        break;

                    case SINGLE_COLOR:
                        // Expect 3 more bytes [red green blue]
                        if(!i2c->read(buffer, 3)) {      //0 on success, non-0 otherwise
                            neopixel::Pixel color;
                            color.red = buffer[0];
                            color.green = buffer[1];
                            color.blue = buffer[2];
                            allSingleColor(color);

                            SimplyLog::Log::i("Setting single color [r,g,b] = [%d,%d,%d]\r\n", color.red, color.green, color.blue);
                        } else {
                            SimplyLog::Log::w("Single color set received with missing params\r\n");
                        }
                        break;
                    
                    default:
                        i2c->stop();    // Necessary !! Otherwise write will fail on master end
                        SimplyLog::Log::w("Unknown command byte\r\n");
                }
            }
        }

        for(int i = 0; i < 10; i++) {
            buffer[i] = 0;    // Clear buffer
        }
        
        // Alive LED
        cAlive = (cAlive + 1) % 100000;
        if (!cAlive) {
            alive = !alive;
        }
    }
}