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

Committer:
isonno
Date:
Mon Feb 11 05:04:18 2013 +0000
Revision:
4:cfef06d8bb96
Parent:
3:0ac64c4ca40f
Minor changes to add backlight routines.  Not hooked up yet, shouldn't affect build operation.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
isonno 0:6da5625a6946 1 //
isonno 0:6da5625a6946 2 // UIMenu - Click-knob menu implementation
isonno 0:6da5625a6946 3 //
isonno 0:6da5625a6946 4
isonno 0:6da5625a6946 5 #include "NokiaLCD.h"
isonno 0:6da5625a6946 6 #include "UIMenu.h"
isonno 0:6da5625a6946 7 #include "HoldInterrupts.h"
isonno 0:6da5625a6946 8
isonno 0:6da5625a6946 9 static Timeout gScreenTimer;
isonno 0:6da5625a6946 10
isonno 0:6da5625a6946 11 void PushKnobUI::ConnectDevices( RotaryEncoder * knob, PushButton * button )
isonno 0:6da5625a6946 12 {
isonno 0:6da5625a6946 13 HoldInterrupts holdint();
isonno 0:6da5625a6946 14
isonno 0:6da5625a6946 15 if (! knob && fKnob) // Disconnect
isonno 0:6da5625a6946 16 {
isonno 0:6da5625a6946 17 fKnob->detach();
isonno 0:6da5625a6946 18 fKnob = NULL;
isonno 0:6da5625a6946 19 }
isonno 0:6da5625a6946 20 if (! button && fKnobButton)
isonno 0:6da5625a6946 21 {
isonno 0:6da5625a6946 22 fKnobButton->detach();
isonno 0:6da5625a6946 23 fKnobButton = NULL;
isonno 0:6da5625a6946 24 }
isonno 0:6da5625a6946 25
isonno 0:6da5625a6946 26 if (knob && !fKnob)
isonno 0:6da5625a6946 27 {
isonno 0:6da5625a6946 28 fKnob = knob;
isonno 0:6da5625a6946 29 //fKnob->attach( this, &UIMenu::KnobMoved );
isonno 0:6da5625a6946 30 AttachKnob( fKnob );
isonno 0:6da5625a6946 31 }
isonno 0:6da5625a6946 32 if (button && !fKnobButton)
isonno 0:6da5625a6946 33 {
isonno 0:6da5625a6946 34 fKnobButton = button;
isonno 0:6da5625a6946 35 //fKnobButton->attach( this, &UIMenu::KnobPushed );
isonno 0:6da5625a6946 36 AttachButton( fKnobButton );
isonno 0:6da5625a6946 37 }
isonno 0:6da5625a6946 38 }
isonno 0:6da5625a6946 39
isonno 1:d1da77023e6a 40 void PushKnobUI::SwitchControl( PushKnobUI * other )
isonno 0:6da5625a6946 41 {
isonno 0:6da5625a6946 42 other->ConnectDevices( fKnob, fKnobButton );
isonno 0:6da5625a6946 43 fKnob = NULL;
isonno 0:6da5625a6946 44 fKnobButton = NULL;
isonno 0:6da5625a6946 45 }
isonno 0:6da5625a6946 46
isonno 0:6da5625a6946 47 int32_t PushKnobUI::KnobMoved( int32_t step )
isonno 0:6da5625a6946 48 {
isonno 0:6da5625a6946 49 printf("Knob moved %d\r\n", step );
isonno 0:6da5625a6946 50 Wake();
isonno 0:6da5625a6946 51 return step;
isonno 0:6da5625a6946 52 }
isonno 0:6da5625a6946 53
isonno 0:6da5625a6946 54 void PushKnobUI::KnobPushed()
isonno 0:6da5625a6946 55 {
isonno 0:6da5625a6946 56 Wake();
isonno 0:6da5625a6946 57 printf("Button pushed\r\n");
isonno 0:6da5625a6946 58 }
isonno 0:6da5625a6946 59
isonno 0:6da5625a6946 60 void PushKnobUI::Wake()
isonno 0:6da5625a6946 61 {
isonno 0:6da5625a6946 62 fLCD->fade_backlight( true );
isonno 0:6da5625a6946 63 gScreenTimer.detach();
isonno 0:6da5625a6946 64 gScreenTimer.attach( this, &PushKnobUI::Sleep, 10 );
isonno 0:6da5625a6946 65 }
isonno 0:6da5625a6946 66
isonno 0:6da5625a6946 67 void PushKnobUI::Sleep()
isonno 0:6da5625a6946 68 {
isonno 0:6da5625a6946 69 fLCD->fade_backlight( false );
isonno 0:6da5625a6946 70 gScreenTimer.detach();
isonno 0:6da5625a6946 71 }
isonno 4:cfef06d8bb96 72
isonno 4:cfef06d8bb96 73 bool PushKnobUI::IsSleeping() const
isonno 4:cfef06d8bb96 74 {
isonno 4:cfef06d8bb96 75 return ! fLCD->is_backlight_on();
isonno 4:cfef06d8bb96 76 }
isonno 0:6da5625a6946 77
isonno 0:6da5625a6946 78 //----------------------------------------------------
isonno 0:6da5625a6946 79
isonno 0:6da5625a6946 80 UIMenu::UIMenu( CheapLCD * lcd, const char * header, bool upMenuItem ) : PushKnobUI( lcd ),
isonno 0:6da5625a6946 81 fHeader( header ),
isonno 0:6da5625a6946 82 fDisplayOn( false ),
isonno 3:0ac64c4ca40f 83 fSelectedItem( kNoSelection )
isonno 0:6da5625a6946 84 {}
isonno 0:6da5625a6946 85
isonno 0:6da5625a6946 86 void UIMenu::AddItem( const char * label )
isonno 0:6da5625a6946 87 {
isonno 0:6da5625a6946 88 fLabels.push_back( string( label ));
isonno 0:6da5625a6946 89 if (fDisplayOn)
isonno 0:6da5625a6946 90 Display( true ); // Refresh
isonno 0:6da5625a6946 91 }
isonno 0:6da5625a6946 92
isonno 0:6da5625a6946 93 void UIMenu::ChangeItem( int item, const char * label )
isonno 0:6da5625a6946 94 {
isonno 0:6da5625a6946 95 if ((item > 0) && (item < fLabels.size()))
isonno 0:6da5625a6946 96 {
isonno 0:6da5625a6946 97 fLabels[item] = string( label );
isonno 0:6da5625a6946 98 DrawItem( item );
isonno 0:6da5625a6946 99 }
isonno 0:6da5625a6946 100 }
isonno 0:6da5625a6946 101
isonno 3:0ac64c4ca40f 102 void UIMenu::ChangeHeader( const char * newHeader )
isonno 3:0ac64c4ca40f 103 {
isonno 3:0ac64c4ca40f 104 fHeader = string( newHeader );
isonno 3:0ac64c4ca40f 105 DrawHeader();
isonno 3:0ac64c4ca40f 106 }
isonno 3:0ac64c4ca40f 107
isonno 0:6da5625a6946 108 int32_t UIMenu::KnobMoved( int32_t step )
isonno 0:6da5625a6946 109 {
isonno 0:6da5625a6946 110 Wake();
isonno 0:6da5625a6946 111
isonno 0:6da5625a6946 112 if (fSelectedItem == kNoSelection)
isonno 0:6da5625a6946 113 {
isonno 0:6da5625a6946 114 fSelectedItem = (step > 0) ? 0 : fLabels.size() - 1;
isonno 0:6da5625a6946 115 DrawItem( fSelectedItem );
isonno 0:6da5625a6946 116 }
isonno 0:6da5625a6946 117 else
isonno 0:6da5625a6946 118 {
isonno 0:6da5625a6946 119 int lastItem = fSelectedItem;
isonno 0:6da5625a6946 120 fSelectedItem += step;
isonno 0:6da5625a6946 121 // Handle wrap-around
isonno 0:6da5625a6946 122 if (fSelectedItem < 0)
isonno 0:6da5625a6946 123 fSelectedItem = fLabels.size() - 1;
isonno 0:6da5625a6946 124 if (fSelectedItem == fLabels.size())
isonno 0:6da5625a6946 125 fSelectedItem = 0;
isonno 0:6da5625a6946 126
isonno 0:6da5625a6946 127 DrawItem( lastItem );
isonno 0:6da5625a6946 128 DrawItem( fSelectedItem );
isonno 0:6da5625a6946 129 }
isonno 0:6da5625a6946 130
isonno 0:6da5625a6946 131 return 0;
isonno 0:6da5625a6946 132 }
isonno 0:6da5625a6946 133
isonno 0:6da5625a6946 134 void UIMenu::KnobPushed()
isonno 0:6da5625a6946 135 {
isonno 0:6da5625a6946 136 Wake();
isonno 0:6da5625a6946 137 printf("Selected %s\n\r", fLabels[fSelectedItem].c_str() );
isonno 0:6da5625a6946 138 }
isonno 1:d1da77023e6a 139
isonno 1:d1da77023e6a 140 void UIMenu::SwitchTo( UIMenu * nextMenu )
isonno 1:d1da77023e6a 141 {
isonno 1:d1da77023e6a 142 Display( false );
isonno 1:d1da77023e6a 143 SwitchControl( nextMenu );
isonno 1:d1da77023e6a 144 nextMenu->Display( true );
isonno 1:d1da77023e6a 145 }
isonno 0:6da5625a6946 146
isonno 0:6da5625a6946 147 // Parameters controlling the display layout
isonno 0:6da5625a6946 148 const int kLineSpace = 20;
isonno 0:6da5625a6946 149 const int kTopGap = 4;
isonno 0:6da5625a6946 150 const int kIndent = 12;
isonno 0:6da5625a6946 151 #define MEDGREEN 0x0A0 // "medium" green
isonno 0:6da5625a6946 152
isonno 3:0ac64c4ca40f 153 void UIMenu::ClearItem( int i, uint32_t color )
isonno 3:0ac64c4ca40f 154 {
isonno 3:0ac64c4ca40f 155 if (! fDisplayOn)
isonno 3:0ac64c4ca40f 156 return;
isonno 3:0ac64c4ca40f 157
isonno 3:0ac64c4ca40f 158 fLCD->clear( color,
isonno 3:0ac64c4ca40f 159 0, i * kLineSpace + kLineSpace + kTopGap,
isonno 3:0ac64c4ca40f 160 131, (i+1) * kLineSpace + kLineSpace + kTopGap );
isonno 3:0ac64c4ca40f 161 }
isonno 3:0ac64c4ca40f 162
isonno 0:6da5625a6946 163 void UIMenu::DrawItem( int i )
isonno 0:6da5625a6946 164 {
isonno 0:6da5625a6946 165 if (! fDisplayOn)
isonno 0:6da5625a6946 166 return;
isonno 0:6da5625a6946 167
isonno 0:6da5625a6946 168 uint32_t foreColor = WHITE;
isonno 0:6da5625a6946 169 uint32_t backColor = (i == fSelectedItem) ? MEDGREEN : BLACK;
isonno 0:6da5625a6946 170
isonno 3:0ac64c4ca40f 171 ClearItem( i, backColor );
isonno 0:6da5625a6946 172 fLCD->draw_glyph_text( foreColor, backColor,
isonno 0:6da5625a6946 173 kIndent, (i+2) * kLineSpace,
isonno 0:6da5625a6946 174 fLabels[i].c_str() );
isonno 0:6da5625a6946 175 }
isonno 0:6da5625a6946 176
isonno 3:0ac64c4ca40f 177 void UIMenu::DrawHeader()
isonno 3:0ac64c4ca40f 178 {
isonno 3:0ac64c4ca40f 179 if (! fDisplayOn)
isonno 3:0ac64c4ca40f 180 return;
isonno 3:0ac64c4ca40f 181 fLCD->clear( BLACK, 0, 0, 131, kLineSpace + kTopGap );
isonno 3:0ac64c4ca40f 182 fLCD->clear( GRAY, 0, kLineSpace + kTopGap-1, 131, kLineSpace + kTopGap );
isonno 3:0ac64c4ca40f 183 if (! fHeader.empty())
isonno 3:0ac64c4ca40f 184 fLCD->draw_glyph_text( WHITE, BLACK, 2, kLineSpace-2, fHeader.c_str() );
isonno 3:0ac64c4ca40f 185 }
isonno 3:0ac64c4ca40f 186
isonno 0:6da5625a6946 187 void UIMenu::Display( bool on )
isonno 0:6da5625a6946 188 {
isonno 0:6da5625a6946 189
isonno 0:6da5625a6946 190 if (on)
isonno 0:6da5625a6946 191 {
isonno 0:6da5625a6946 192 fDisplayOn = true;
isonno 3:0ac64c4ca40f 193 DrawHeader();
isonno 3:0ac64c4ca40f 194
isonno 3:0ac64c4ca40f 195 int maxLines = (int)((131 - (kLineSpace + kTopGap)) / kLineSpace);
isonno 3:0ac64c4ca40f 196
isonno 3:0ac64c4ca40f 197 int numLines = std::min( maxLines, (int)fLabels.size() );
isonno 0:6da5625a6946 198
isonno 3:0ac64c4ca40f 199 for (int i = 0; i < numLines; ++i)
isonno 3:0ac64c4ca40f 200 DrawItem( i );
isonno 0:6da5625a6946 201
isonno 3:0ac64c4ca40f 202 for (int i = numLines; i < maxLines; ++i )
isonno 3:0ac64c4ca40f 203 ClearItem( i, BLACK );
isonno 0:6da5625a6946 204 }
isonno 0:6da5625a6946 205 else
isonno 0:6da5625a6946 206 fDisplayOn = false;
isonno 0:6da5625a6946 207 }
isonno 0:6da5625a6946 208