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:
Tue Jan 17 13:45:17 2012 +0000
Revision:
3:0ac64c4ca40f
Parent:
1:d1da77023e6a
Child:
4:cfef06d8bb96
LightSensor settings menu; more work (unsuccessful) on serial input from USB.

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 0:6da5625a6946 72
isonno 0:6da5625a6946 73
isonno 0:6da5625a6946 74 //----------------------------------------------------
isonno 0:6da5625a6946 75
isonno 0:6da5625a6946 76 UIMenu::UIMenu( CheapLCD * lcd, const char * header, bool upMenuItem ) : PushKnobUI( lcd ),
isonno 0:6da5625a6946 77 fHeader( header ),
isonno 0:6da5625a6946 78 fDisplayOn( false ),
isonno 3:0ac64c4ca40f 79 fSelectedItem( kNoSelection )
isonno 0:6da5625a6946 80 {}
isonno 0:6da5625a6946 81
isonno 0:6da5625a6946 82 void UIMenu::AddItem( const char * label )
isonno 0:6da5625a6946 83 {
isonno 0:6da5625a6946 84 fLabels.push_back( string( label ));
isonno 0:6da5625a6946 85 if (fDisplayOn)
isonno 0:6da5625a6946 86 Display( true ); // Refresh
isonno 0:6da5625a6946 87 }
isonno 0:6da5625a6946 88
isonno 0:6da5625a6946 89 void UIMenu::ChangeItem( int item, const char * label )
isonno 0:6da5625a6946 90 {
isonno 0:6da5625a6946 91 if ((item > 0) && (item < fLabels.size()))
isonno 0:6da5625a6946 92 {
isonno 0:6da5625a6946 93 fLabels[item] = string( label );
isonno 0:6da5625a6946 94 DrawItem( item );
isonno 0:6da5625a6946 95 }
isonno 0:6da5625a6946 96 }
isonno 0:6da5625a6946 97
isonno 3:0ac64c4ca40f 98 void UIMenu::ChangeHeader( const char * newHeader )
isonno 3:0ac64c4ca40f 99 {
isonno 3:0ac64c4ca40f 100 fHeader = string( newHeader );
isonno 3:0ac64c4ca40f 101 DrawHeader();
isonno 3:0ac64c4ca40f 102 }
isonno 3:0ac64c4ca40f 103
isonno 0:6da5625a6946 104 int32_t UIMenu::KnobMoved( int32_t step )
isonno 0:6da5625a6946 105 {
isonno 0:6da5625a6946 106 Wake();
isonno 0:6da5625a6946 107
isonno 0:6da5625a6946 108 if (fSelectedItem == kNoSelection)
isonno 0:6da5625a6946 109 {
isonno 0:6da5625a6946 110 fSelectedItem = (step > 0) ? 0 : fLabels.size() - 1;
isonno 0:6da5625a6946 111 DrawItem( fSelectedItem );
isonno 0:6da5625a6946 112 }
isonno 0:6da5625a6946 113 else
isonno 0:6da5625a6946 114 {
isonno 0:6da5625a6946 115 int lastItem = fSelectedItem;
isonno 0:6da5625a6946 116 fSelectedItem += step;
isonno 0:6da5625a6946 117 // Handle wrap-around
isonno 0:6da5625a6946 118 if (fSelectedItem < 0)
isonno 0:6da5625a6946 119 fSelectedItem = fLabels.size() - 1;
isonno 0:6da5625a6946 120 if (fSelectedItem == fLabels.size())
isonno 0:6da5625a6946 121 fSelectedItem = 0;
isonno 0:6da5625a6946 122
isonno 0:6da5625a6946 123 DrawItem( lastItem );
isonno 0:6da5625a6946 124 DrawItem( fSelectedItem );
isonno 0:6da5625a6946 125 }
isonno 0:6da5625a6946 126
isonno 0:6da5625a6946 127 return 0;
isonno 0:6da5625a6946 128 }
isonno 0:6da5625a6946 129
isonno 0:6da5625a6946 130 void UIMenu::KnobPushed()
isonno 0:6da5625a6946 131 {
isonno 0:6da5625a6946 132 Wake();
isonno 0:6da5625a6946 133 printf("Selected %s\n\r", fLabels[fSelectedItem].c_str() );
isonno 0:6da5625a6946 134 }
isonno 1:d1da77023e6a 135
isonno 1:d1da77023e6a 136 void UIMenu::SwitchTo( UIMenu * nextMenu )
isonno 1:d1da77023e6a 137 {
isonno 1:d1da77023e6a 138 Display( false );
isonno 1:d1da77023e6a 139 SwitchControl( nextMenu );
isonno 1:d1da77023e6a 140 nextMenu->Display( true );
isonno 1:d1da77023e6a 141 }
isonno 0:6da5625a6946 142
isonno 0:6da5625a6946 143 // Parameters controlling the display layout
isonno 0:6da5625a6946 144 const int kLineSpace = 20;
isonno 0:6da5625a6946 145 const int kTopGap = 4;
isonno 0:6da5625a6946 146 const int kIndent = 12;
isonno 0:6da5625a6946 147 #define MEDGREEN 0x0A0 // "medium" green
isonno 0:6da5625a6946 148
isonno 3:0ac64c4ca40f 149 void UIMenu::ClearItem( int i, uint32_t color )
isonno 3:0ac64c4ca40f 150 {
isonno 3:0ac64c4ca40f 151 if (! fDisplayOn)
isonno 3:0ac64c4ca40f 152 return;
isonno 3:0ac64c4ca40f 153
isonno 3:0ac64c4ca40f 154 fLCD->clear( color,
isonno 3:0ac64c4ca40f 155 0, i * kLineSpace + kLineSpace + kTopGap,
isonno 3:0ac64c4ca40f 156 131, (i+1) * kLineSpace + kLineSpace + kTopGap );
isonno 3:0ac64c4ca40f 157 }
isonno 3:0ac64c4ca40f 158
isonno 0:6da5625a6946 159 void UIMenu::DrawItem( int i )
isonno 0:6da5625a6946 160 {
isonno 0:6da5625a6946 161 if (! fDisplayOn)
isonno 0:6da5625a6946 162 return;
isonno 0:6da5625a6946 163
isonno 0:6da5625a6946 164 uint32_t foreColor = WHITE;
isonno 0:6da5625a6946 165 uint32_t backColor = (i == fSelectedItem) ? MEDGREEN : BLACK;
isonno 0:6da5625a6946 166
isonno 3:0ac64c4ca40f 167 ClearItem( i, backColor );
isonno 0:6da5625a6946 168 fLCD->draw_glyph_text( foreColor, backColor,
isonno 0:6da5625a6946 169 kIndent, (i+2) * kLineSpace,
isonno 0:6da5625a6946 170 fLabels[i].c_str() );
isonno 0:6da5625a6946 171 }
isonno 0:6da5625a6946 172
isonno 3:0ac64c4ca40f 173 void UIMenu::DrawHeader()
isonno 3:0ac64c4ca40f 174 {
isonno 3:0ac64c4ca40f 175 if (! fDisplayOn)
isonno 3:0ac64c4ca40f 176 return;
isonno 3:0ac64c4ca40f 177 fLCD->clear( BLACK, 0, 0, 131, kLineSpace + kTopGap );
isonno 3:0ac64c4ca40f 178 fLCD->clear( GRAY, 0, kLineSpace + kTopGap-1, 131, kLineSpace + kTopGap );
isonno 3:0ac64c4ca40f 179 if (! fHeader.empty())
isonno 3:0ac64c4ca40f 180 fLCD->draw_glyph_text( WHITE, BLACK, 2, kLineSpace-2, fHeader.c_str() );
isonno 3:0ac64c4ca40f 181 }
isonno 3:0ac64c4ca40f 182
isonno 0:6da5625a6946 183 void UIMenu::Display( bool on )
isonno 0:6da5625a6946 184 {
isonno 0:6da5625a6946 185
isonno 0:6da5625a6946 186 if (on)
isonno 0:6da5625a6946 187 {
isonno 0:6da5625a6946 188 fDisplayOn = true;
isonno 3:0ac64c4ca40f 189 DrawHeader();
isonno 3:0ac64c4ca40f 190
isonno 3:0ac64c4ca40f 191 int maxLines = (int)((131 - (kLineSpace + kTopGap)) / kLineSpace);
isonno 3:0ac64c4ca40f 192
isonno 3:0ac64c4ca40f 193 int numLines = std::min( maxLines, (int)fLabels.size() );
isonno 0:6da5625a6946 194
isonno 3:0ac64c4ca40f 195 for (int i = 0; i < numLines; ++i)
isonno 3:0ac64c4ca40f 196 DrawItem( i );
isonno 0:6da5625a6946 197
isonno 3:0ac64c4ca40f 198 for (int i = numLines; i < maxLines; ++i )
isonno 3:0ac64c4ca40f 199 ClearItem( i, BLACK );
isonno 0:6da5625a6946 200 }
isonno 0:6da5625a6946 201 else
isonno 0:6da5625a6946 202 fDisplayOn = false;
isonno 0:6da5625a6946 203 }
isonno 0:6da5625a6946 204