Source code for the Curilights Controller. See http://www.saccade.com/writing/projects/CuriController/ for details.

Dependencies:   FatFileSystem mbed

This is the source code for the Curilights controller. This lets you interactively control a string of Curilights. It provides a simple click-wheel user interface for changing colors, brightness and behavior. It responds to movement and lighting.

Finished Controller

/media/uploads/isonno/nxp3872_controllerclose.jpg

System Block Diagram

/media/uploads/isonno/blockdiagram.png

main.cpp

Committer:
isonno
Date:
2013-02-11
Revision:
4:cfef06d8bb96
Parent:
3:0ac64c4ca40f

File content as of revision 4:cfef06d8bb96:

//
// CuriLights Controller firmware
//

#include "mbed.h"  // Lives in http://mbed.org/projects/libraries/svn/mbed/trunk

#include "SerialConnect.h"
#include "ZMotionDetector.h"
#include "SDFileSystem.h"
#include "NokiaLCD.h"
#include "RotaryEncoder.h"
#include "HoldInterrupts.h"
#include "PinDetect.h"
#include "LightString.h"
#include "PushButton.h"
#include "SystemState.h"
#include "UserInterface.h"
#include "SettingsMenu.h"

#include "RGBLED.h"
#include "DebugLED.h"

#include <string>

// Light sensor wrapper
class LightSensor
{
public:
    LightSensor() : fLightPin( p19 ) {};
    
//    int light() { return (int)(fLightPin.read() * 1000); }
    int32_t light() {volatile float a = fLightPin.read(); return (int)(a * 1000); }

private:
    AnalogIn fLightPin;
};

// This is a version of Timeout that you simply 
// poll to see if the timeout is still in effect
class MotionDelay : public Timeout
{
public:
    MotionDelay() : Timeout()
    { fWaiting = false; }
    
    bool IsWaiting() { return fWaiting; }
    
    void Start( int seconds )
    {
        detach();   // Reset the time
        attach( this, &MotionDelay::Completed, seconds );
        fWaiting = true;
    }

private:  
    void Completed() { fWaiting = false; }

    bool fWaiting;
};

// We want to be able to download files over USB, but only
// look for them on the SD Card.  So at startup, we move
// any .CRI files found on the local drive to the SD card.
void CopyPatternFilesToSD()
{
    SDFileSystem sdcard( p5, p6, p7, p8, "sdcard" );
    LocalFileSystem local("local");

    DIR * localDir = opendir("/local");
    
    struct dirent *p;
    
    while ((p = readdir( localDir )) != NULL)
    {
        string srcName = string("/local/") + string(p->d_name);
        printf("Examining %s\r\n", srcName.c_str() );
        if (srcName.rfind( ".CRI") != string::npos)
        {
            printf("Copying %s to SD Card\r\n", srcName.c_str());
        
            string dstName = string("/sdcard/") + string(p->d_name);

            FILE * src = fopen( srcName.c_str(), "rb" );
            FILE * dst = fopen( dstName.c_str(), "wb" );
            
            if (!src)
            {
                printf("Can't open: %s\r\n", srcName.c_str() );
                continue;
            }
            if (!dst)
            {
                printf("Can't open %s\r\n", dstName.c_str() );
                fclose( src );
                continue;
            }
            
            // Copy the data
            while (! feof(src))
            {
                char buffer[1024];
                uint32_t numRead = fread( buffer, 1, sizeof( buffer ), src );
                fwrite( buffer, 1, numRead, dst );
            }
            fclose(src);
            fclose(dst);
            remove(srcName.c_str());    // Wham! We only look for these on the sdcard
        }
    }
}

RGBLED gDebugLED( p22, p23, p24 );

void CheckDownloadedPattern( LightString& lightString )
{
    static time_t activeTime;
    static bool active = false;
    bool nowActive = lightString.Snoop()->IsActive();
    static bool saved = false;
    
    
    int lightValue = 0;
    
    if (active)
        lightValue = 700;
        
    if (saved)
        lightValue += 70;
        
    if (nowActive)
        lightValue += 7;
        
    gDebugLED.Set( lightValue );
    
    if (!active && nowActive)
    {
        activeTime = time( NULL );
        active = true;
    }
    else
    if (active && nowActive)
    {
        activeTime = time( NULL );
    }
    else
    if (active && !nowActive 
        && (time( NULL ) - activeTime > 2))
    {
        active = false;
        lightString.Snoop()->SaveSnoop();
        saved = true;
    }
}

int main() {
    printf("Welcome\r\n");
    CopyPatternFilesToSD();
    
    gSystemState.LoadState();

    // Create hardware objects
    
    CheapLCD lcd( p11, p13, p14, p12 );  //   mosi, sclk, cs, rst

    lcd.erase();
    lcd.switch_backlight( true );
    
    ZMotionDetector mdetect( p28, p27 );    
    mdetect.SetExtendedRange( true );

    LightString curiLights( p9, 58 );
    curiLights.InitLights();
    
    RotaryEncoder knob( p17, p18 );
    PushButton knobButton( p30, "Knob" );

    LightSensor lightSensor;
    MotionDelay motionDelay;

    // Set up the User Interface    
    HomeMenu homeMenu( &lcd, &curiLights );
    homeMenu.ConnectDevices( &knob, &knobButton );
    homeMenu.Display( true );

    // Infinite loop watches the light sensor and
    // the motion detector.  All other input is
    // handled via interrupts.
    
    gLeds[0] = gLeds[1] = gLeds[2] = gLeds[3] = 0;
    gDebugLED.Set(0);

    while(1) {
        cycleLEDs();
        wait(lightSensor.light() * 0.0004 );
//        printf( "LightSensor: %d\r\n", lightSensor.light() );
        
//        CheckDownloadedPattern( curiLights );
        // If the lightSensor shows enough light, OR the light sensor is disabled.
        bool lightSensorState = (lightSensor.light() < 800)  || (gSystemState.GetLightSensor() == 0);
        
        homeMenu.SetLightsOn( lightSensorState || motionDelay.IsWaiting() );
            
        if (mdetect.IsMotionDetected())
        {
            motionDelay.Start( 10 );
            gLeds[0] = 1; gLeds[1] = 1; gLeds[2] = 1; gLeds[3] = 1;
            wait(0.6);
        }
        
        curiLights.FlushOutput();
    }
}