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
System Block Diagram
Diff: UIMenu.cpp
- 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; +} +