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

Revision:
0:6da5625a6946
Child:
1:d1da77023e6a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UIMenu.cpp	Thu Dec 29 01:59:53 2011 +0000
@@ -0,0 +1,172 @@
+//
+// UIMenu - Click-knob menu implementation
+//
+
+#include "NokiaLCD.h"
+#include "UIMenu.h"
+#include "HoldInterrupts.h"
+
+static Timeout gScreenTimer;
+
+void PushKnobUI::ConnectDevices( RotaryEncoder * knob, PushButton * button )
+{
+    HoldInterrupts holdint();
+    
+    if (! knob && fKnob)    // Disconnect
+    {
+        fKnob->detach();
+        fKnob = NULL;
+    }
+    if (! button && fKnobButton)
+    {
+        fKnobButton->detach();
+        fKnobButton = NULL;
+    }
+    
+    if (knob && !fKnob)
+    {
+        fKnob = knob;
+        //fKnob->attach( this, &UIMenu::KnobMoved );
+        AttachKnob( fKnob );
+    }
+    if (button && !fKnobButton)
+    {
+        fKnobButton = button;
+        //fKnobButton->attach( this, &UIMenu::KnobPushed );
+        AttachButton( fKnobButton );
+    }
+}
+
+void PushKnobUI::SwitchTo( PushKnobUI * other )
+{
+    other->ConnectDevices( fKnob, fKnobButton );
+    fKnob = NULL;
+    fKnobButton = NULL;
+}    
+    
+int32_t PushKnobUI::KnobMoved( int32_t step )
+{
+    printf("Knob moved %d\r\n", step );
+    Wake();
+    return step;
+}
+
+void PushKnobUI::KnobPushed()
+{
+    Wake();
+    printf("Button pushed\r\n");
+}
+
+void PushKnobUI::Wake()
+{
+    fLCD->fade_backlight( true );
+    gScreenTimer.detach();
+    gScreenTimer.attach( this, &PushKnobUI::Sleep, 10 );
+}
+
+void PushKnobUI::Sleep()
+{
+    fLCD->fade_backlight( false );
+    gScreenTimer.detach();
+}
+    
+
+//----------------------------------------------------
+
+UIMenu::UIMenu( CheapLCD * lcd, const char * header, bool upMenuItem ) : PushKnobUI( lcd ),
+  fHeader( header ), 
+  fDisplayOn( false ), 
+  fUpMenuItem( upMenuItem ), 
+  fSelectedItem( kNoSelection ),
+  fLCD( lcd )
+{}
+
+void UIMenu::AddItem( const char * label )
+{
+    fLabels.push_back( string( label ));
+    if (fDisplayOn)
+        Display( true );    // Refresh
+}
+
+void UIMenu::ChangeItem( int item, const char * label )
+{
+    if ((item > 0) && (item < fLabels.size()))
+    {
+        fLabels[item] = string( label );
+        DrawItem( item );
+    }
+}
+
+int32_t UIMenu::KnobMoved( int32_t step )
+{
+    Wake();
+    
+    if (fSelectedItem == kNoSelection)
+    {
+        fSelectedItem = (step > 0) ? 0 : fLabels.size() - 1;
+        DrawItem( fSelectedItem );
+    }
+    else
+    {
+        int lastItem = fSelectedItem;
+        fSelectedItem += step;
+        // Handle wrap-around
+        if (fSelectedItem < 0)
+            fSelectedItem = fLabels.size() - 1; 
+        if (fSelectedItem == fLabels.size())
+            fSelectedItem = 0;
+            
+        DrawItem( lastItem );
+        DrawItem( fSelectedItem );
+    }
+
+    return 0;
+}
+
+void UIMenu::KnobPushed()
+{
+    Wake();
+    printf("Selected %s\n\r", fLabels[fSelectedItem].c_str() );
+}
+    
+// Parameters controlling the display layout
+const int kLineSpace = 20;
+const int kTopGap = 4;
+const int kIndent = 12;
+#define MEDGREEN 0x0A0      // "medium" green
+
+void UIMenu::DrawItem( int i )
+{
+    if (! fDisplayOn)
+        return;
+        
+    uint32_t foreColor = WHITE;
+    uint32_t backColor = (i == fSelectedItem) ? MEDGREEN : BLACK;
+    
+    fLCD->clear( backColor, 
+                 0, i * kLineSpace + kLineSpace + kTopGap, 
+                 131, (i+1) * kLineSpace + kLineSpace + kTopGap );
+    fLCD->draw_glyph_text( foreColor, backColor,
+                           kIndent, (i+2) * kLineSpace,
+                           fLabels[i].c_str() );
+}
+
+void UIMenu::Display( bool on )
+{   
+ 
+    if (on)
+    {
+        fDisplayOn = true;
+        fLCD->clear( GRAY, 0, kLineSpace + kTopGap-1, 131, kLineSpace + kTopGap );
+        if (! fHeader.empty())
+            fLCD->draw_glyph_text( WHITE, BLACK, 2, kLineSpace-2, fHeader.c_str() );
+        
+        int maxLines = std::min( (int)((131 - (kLineSpace + kTopGap)) / kLineSpace), (int)fLabels.size() );
+        
+        for (int i = 0; i < maxLines; ++i)
+            DrawItem( i );
+    }
+    else
+        fDisplayOn = false;
+}             
+