The out-of-the-box demo application flashed on all display modules before they are shipped.
Dependencies: DMBasicGUI DMSupport
AppRTCSettings.cpp
00001 /* 00002 * Copyright 2014 Embedded Artists AB 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 00018 #include "mbed.h" 00019 #include "AppRTCSettings.h" 00020 #include "lpc_swim_font.h" 00021 00022 /****************************************************************************** 00023 * Defines and typedefs 00024 *****************************************************************************/ 00025 00026 #define BTN_OFF 20 00027 00028 /****************************************************************************** 00029 * Private variables 00030 *****************************************************************************/ 00031 00032 // Ugly but needed for callbacks 00033 static AppRTCSettings* theApp = NULL; 00034 00035 /****************************************************************************** 00036 * Private functions 00037 *****************************************************************************/ 00038 00039 static void buttonClicked(uint32_t x) 00040 { 00041 bool* done = (bool*)x; 00042 *done = true; 00043 } 00044 00045 static void fieldClicked(uint32_t x) 00046 { 00047 if (theApp != NULL) { 00048 theApp->setActiveField(x); 00049 } 00050 } 00051 00052 static void increaseValue(uint32_t x) 00053 { 00054 AppRTCSettings* app = (AppRTCSettings*)x; 00055 app->modifyValue(1); 00056 } 00057 00058 static void decreaseValue(uint32_t x) 00059 { 00060 AppRTCSettings* app = (AppRTCSettings*)x; 00061 app->modifyValue(-1); 00062 } 00063 00064 static void nextField(uint32_t x) 00065 { 00066 AppRTCSettings* app = (AppRTCSettings*)x; 00067 app->changeActiveField(true); 00068 } 00069 00070 static void prevField(uint32_t x) 00071 { 00072 AppRTCSettings* app = (AppRTCSettings*)x; 00073 app->changeActiveField(false); 00074 } 00075 00076 void AppRTCSettings::draw() 00077 { 00078 // Prepare fullscreen 00079 swim_window_open(_win, 00080 _disp->width(), _disp->height(), // full size 00081 (COLOR_T*)_fb, 00082 0,0,_disp->width()-1, _disp->height()-1, // window position and size 00083 1, // border 00084 GREEN,WHITE,BLACK);/*WHITE, RED, BLACK);*/ // colors: pen, backgr, forgr 00085 swim_set_pen_color(_win, BLACK); 00086 swim_set_title(_win, "Real Time Clock Settings", GREEN); 00087 swim_set_pen_color(_win, BLACK); 00088 00089 ImageButton* ib; 00090 00091 Resource* rOk = _res[Resource_Ok_button]; 00092 Resource* rCancel = _res[Resource_Cancel_button]; 00093 ib = new ImageButton(_win->fb, _win->xpmax - 2*BTN_OFF - rCancel->width() -rOk->width(), _win->ypmax - BTN_OFF - rOk->height(), rOk->width(), rOk->height()); 00094 ib->loadImages(rOk); 00095 ib->draw(); 00096 _buttons[ButtonOk] = ib; 00097 ib = new ImageButton(_win->fb, _win->xpmax - BTN_OFF - rCancel->width(), _win->ypmax - BTN_OFF - rCancel->height(), rCancel->width(), rCancel->height()); 00098 ib->loadImages(rCancel); 00099 ib->draw(); 00100 _buttons[ButtonCancel] = ib; 00101 00102 int arrowW = _res[Resource_ArrowUp_button]->width(); 00103 int arrowH = _res[Resource_ArrowUp_button]->height(); 00104 ib = new ImageButton(_win->fb, 300, 40, arrowW, arrowH); 00105 ib->loadImages( _res[Resource_ArrowUp_button]); 00106 ib->setAction(increaseValue, (uint32_t)this); 00107 ib->draw(); 00108 _buttons[ButtonUp] = ib; 00109 ib = new ImageButton(_win->fb, 300, 40+arrowH+arrowH, arrowW, arrowH); 00110 ib->loadImages( _res[Resource_ArrowDown_button]); 00111 ib->setAction(decreaseValue, (uint32_t)this); 00112 ib->draw(); 00113 _buttons[ButtonDown] = ib; 00114 ib = new ImageButton(_win->fb, 300-arrowW/2-10, 40+arrowH, arrowW, arrowH); 00115 ib->loadImages(_res[Resource_ArrowLeft_button]); 00116 ib->setAction(prevField, (uint32_t)this); 00117 ib->draw(); 00118 _buttons[ButtonLeft] = ib; 00119 ib = new ImageButton(_win->fb, 300+arrowW/2+10, 40+arrowH, arrowW, arrowH); 00120 ib->loadImages(_res[Resource_ArrowRight_button]); 00121 ib->setAction(nextField, (uint32_t)this); 00122 ib->draw(); 00123 _buttons[ButtonRight] = ib; 00124 00125 // To avoid having each DigitButton deallocate the shared image 00126 void* pointerToFree = _digitImage.pointerToFree; 00127 _digitImage.pointerToFree = NULL; 00128 00129 addDateFields(0, 20); 00130 addTimeFields(0, 20+65); 00131 00132 // Restore shared image so that it will be deallocated during teardown 00133 _digitImage.pointerToFree = pointerToFree; 00134 00135 for (int i = 0; i < NumButtons; i++) { 00136 _buttons[i]->draw(); 00137 } 00138 00139 markField(_activeField, true); 00140 } 00141 00142 void AppRTCSettings::addDateFields(int xoff, int yoff) 00143 { 00144 DigitButton* db; 00145 00146 int fontY = yoff; 00147 int y = fontY + swim_get_font_height(_win) + 2; 00148 int btny = y-7; 00149 y += _win->ypvmin; // compensate for title bar 00150 int x = xoff+20; 00151 int idx = ButtonYear; 00152 int btnw; 00153 00154 swim_put_text_xy(_win, "Year", x, fontY); 00155 btnw = 65; 00156 db = new DigitButton(_win->fb, x, y, btnw, 34); 00157 db->loadImages(&_digitImage); 00158 db->setNumDigits(4); 00159 db->setValue(_values[idx]); 00160 db->setAction(fieldClicked, idx); 00161 _buttons[idx++] = db; 00162 00163 x += btnw + 20; 00164 btnw = 45; 00165 swim_put_text_xy(_win, "Month", x, fontY); 00166 db = new DigitButton(_win->fb, x, y, btnw, 34); 00167 db->loadImages(&_digitImage); 00168 db->setNumDigits(2); 00169 db->setValue(_values[idx]); 00170 db->setAction(fieldClicked, idx); 00171 _buttons[idx++] = db; 00172 swim_put_box(_win, x-13, btny+20, x-2, btny+23); 00173 00174 x += btnw + 10; 00175 swim_put_text_xy(_win, "Day", x, fontY); 00176 db = new DigitButton(_win->fb, x, y, btnw, 34); 00177 db->loadImages(&_digitImage); 00178 db->setNumDigits(2); 00179 db->setValue(_values[idx]); 00180 db->setAction(fieldClicked, idx); 00181 _buttons[idx++] = db; 00182 swim_put_box(_win, x-13, btny+20, x-2, btny+23); 00183 } 00184 00185 void AppRTCSettings::addTimeFields(int xoff, int yoff) 00186 { 00187 DigitButton* db; 00188 00189 int fontY = yoff; 00190 int y = fontY + swim_get_font_height(_win) + 2; 00191 int btny = y-7; 00192 y += _win->ypvmin; // compensate for title bar 00193 int x = xoff+20; 00194 int idx = ButtonHour; 00195 int btnw = 45; 00196 00197 swim_put_text_xy(_win, "Hour", x, fontY); 00198 db = new DigitButton(_win->fb, x, y, btnw, 34); 00199 db->loadImages(&_digitImage); 00200 db->setNumDigits(2); 00201 db->setValue(_values[idx]); 00202 db->setAction(fieldClicked, idx); 00203 _buttons[idx++] = db; 00204 00205 x += btnw + 10; 00206 swim_put_text_xy(_win, "Minutes", x, fontY); 00207 db = new DigitButton(_win->fb, x, y, btnw, 34); 00208 db->loadImages(&_digitImage); 00209 db->setNumDigits(2); 00210 db->setValue(_values[idx]); 00211 db->setAction(fieldClicked, idx); 00212 _buttons[idx++] = db; 00213 swim_put_box(_win, x-13, btny+22, x-2, btny+25); 00214 00215 x += btnw + 10; 00216 swim_put_text_xy(_win, "Seconds", x, fontY); 00217 db = new DigitButton(_win->fb, x, y, btnw, 34); 00218 db->loadImages(&_digitImage); 00219 db->setNumDigits(2); 00220 db->setValue(_values[idx]); 00221 db->setAction(fieldClicked, idx); 00222 _buttons[idx++] = db; 00223 swim_put_box(_win, x-13, btny+22, x-2, btny+25); 00224 } 00225 00226 void AppRTCSettings::markField(int field, bool active) 00227 { 00228 COLOR_T oldPen = _win->pen; 00229 COLOR_T oldFill = _win->fill; 00230 _win->fill = active ? BLACK : _win->bkg; 00231 _win->pen = active ? BLACK : _win->bkg; 00232 if (field >= 0 && field < NumFields) { 00233 int x0, y0, x1, y1; 00234 _buttons[field]->bounds(x0,y0,x1,y1); 00235 y1 -= _win->ypvmin+1; 00236 x0--; 00237 swim_put_box(_win, x0, y1, x1, y1+3); 00238 } 00239 _win->fill = oldFill; 00240 _win->pen = oldPen; 00241 } 00242 00243 /****************************************************************************** 00244 * Public functions 00245 *****************************************************************************/ 00246 00247 AppRTCSettings::AppRTCSettings() : _disp(NULL), _win(NULL), _fb(NULL), _activeField(0) 00248 { 00249 for (int i = 0; i < NumButtons; i++) { 00250 _buttons[i] = NULL; 00251 } 00252 for (int i = 0; i < NumResources; i++) { 00253 _res[i] = NULL; 00254 } 00255 time_t rawtime; 00256 struct tm * timeinfo; 00257 00258 time (&rawtime); 00259 timeinfo = localtime (&rawtime); 00260 00261 _values[ButtonYear] = timeinfo->tm_year + 1900; 00262 _values[ButtonMonth] = timeinfo->tm_mon + 1; 00263 _values[ButtonDay] = timeinfo->tm_mday; 00264 _values[ButtonHour] = timeinfo->tm_hour; 00265 _values[ButtonMinute] = timeinfo->tm_min; 00266 _values[ButtonSecond] = timeinfo->tm_sec; 00267 00268 _digitImage.pointerToFree = NULL; 00269 00270 theApp = this; 00271 } 00272 00273 AppRTCSettings::~AppRTCSettings() 00274 { 00275 theApp = NULL; 00276 teardown(); 00277 } 00278 00279 bool AppRTCSettings::setup() 00280 { 00281 _disp = DMBoard::instance().display(); 00282 _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T)); 00283 _fb = _disp->allocateFramebuffer(); 00284 int res = Image::decode(_res[Resource_Digits], Image::RES_16BIT, &_digitImage); 00285 00286 return (_win != NULL && _fb != NULL && res == 0); 00287 } 00288 00289 void AppRTCSettings::runToCompletion() 00290 { 00291 // Alternative 1: use the calling thread's context to run in 00292 bool done = false; 00293 bool abort = false; 00294 draw(); 00295 _buttons[ButtonOk]->setAction(buttonClicked, (uint32_t)&done); 00296 _buttons[ButtonCancel]->setAction(buttonClicked, (uint32_t)&abort); 00297 void* oldFB = _disp->swapFramebuffer(_fb); 00298 00299 // Wait for touches 00300 TouchPanel* touch = DMBoard::instance().touchPanel(); 00301 touch_coordinate_t coord; 00302 00303 int lastPressed = NumButtons; 00304 Timer t; 00305 t.start(); 00306 int repeatAt = 0; 00307 00308 uint32_t maxDelay = osWaitForever; 00309 while(!done && !abort) { 00310 ThisThread::flags_wait_all_for(0x1, maxDelay); 00311 if (touch->read(coord) == TouchPanel::TouchError_Ok) { 00312 for (int i = 0; i < NumButtons; i++) { 00313 if (_buttons[i]->handle(coord.x, coord.y, coord.z > 0)) { 00314 _buttons[i]->draw(); 00315 if (_buttons[i]->pressed()) { 00316 lastPressed = i; // new button pressed 00317 t.reset(); 00318 repeatAt = 1000; 00319 } 00320 } 00321 } 00322 if (lastPressed == ButtonUp || lastPressed == ButtonDown) { 00323 maxDelay = 10; 00324 if (_buttons[lastPressed]->pressed() && t.read_ms() > repeatAt) { 00325 modifyValue((lastPressed == ButtonUp) ? 1 : -1); 00326 repeatAt = t.read_ms()+(200/(t.read_ms()/1000)); 00327 } 00328 } else { 00329 maxDelay = osWaitForever; 00330 } 00331 } 00332 } 00333 00334 if (!abort) { 00335 RtosLog* log = DMBoard::instance().logger(); 00336 log->printf("New time: %04d-%02d-%02d %02d:%02d:%02d\n", _values[0], _values[1], 00337 _values[2], _values[3], _values[4], _values[5]); 00338 tm t; 00339 t.tm_year = _values[ButtonYear] - 1900; // years since 1900 00340 t.tm_mon = _values[ButtonMonth] - 1; // month is 0..11 00341 t.tm_mday = _values[ButtonDay]; 00342 t.tm_hour = _values[ButtonHour]; 00343 t.tm_min = _values[ButtonMinute]; 00344 t.tm_sec = _values[ButtonSecond]; 00345 set_time(mktime(&t)); 00346 } 00347 00348 // User has clicked the button, restore the original FB 00349 _disp->swapFramebuffer(oldFB); 00350 swim_window_close(_win); 00351 } 00352 00353 bool AppRTCSettings::teardown() 00354 { 00355 if (_win != NULL) { 00356 free(_win); 00357 _win = NULL; 00358 } 00359 if (_fb != NULL) { 00360 free(_fb); 00361 _fb = NULL; 00362 } 00363 for (int i = 0; i < NumButtons; i++) { 00364 if (_buttons[i] != NULL) { 00365 delete _buttons[i]; 00366 _buttons[i] = NULL; 00367 } 00368 } 00369 if (_digitImage.pointerToFree != NULL) { 00370 free(_digitImage.pointerToFree); 00371 _digitImage.pointerToFree = NULL; 00372 } 00373 return true; 00374 } 00375 00376 void AppRTCSettings::modifyValue(int mod) 00377 { 00378 uint32_t v = _values[_activeField]; 00379 switch (_activeField) { 00380 case ButtonYear: 00381 // 1970..2100 00382 _values[_activeField] = (((v - 1970 + (2100-1970)) + mod) % (2100-1970)) + 1970; 00383 break; 00384 case ButtonMonth: 00385 // 1..12 00386 _values[_activeField] = (((v - 1 + 12) + mod) % 12) + 1; 00387 break; 00388 case ButtonDay: 00389 // 1..31 00390 _values[_activeField] = (((v - 1 + 31) + mod) % 31) + 1; 00391 break; 00392 case ButtonHour: 00393 // 0..23 00394 _values[_activeField] = (v + 24 + mod) % 24; 00395 break; 00396 case ButtonMinute: 00397 case ButtonSecond: 00398 // 0..59 00399 _values[_activeField] = (v + 60 + mod) % 60; 00400 break; 00401 } 00402 ((DigitButton*)_buttons[_activeField])->setValue(_values[_activeField]); 00403 } 00404 00405 void AppRTCSettings::changeActiveField(bool next) 00406 { 00407 markField(_activeField, false); 00408 if (next) { 00409 _activeField = (_activeField+1) % NumFields; 00410 } else { 00411 _activeField = (_activeField+NumFields-1) % NumFields; 00412 } 00413 markField(_activeField, true); 00414 } 00415 00416 void AppRTCSettings::setActiveField(uint32_t newField) 00417 { 00418 if (_activeField != newField && newField < NumFields) { 00419 markField(_activeField, false); 00420 _activeField = newField; 00421 markField(_activeField, true); 00422 } 00423 } 00424 00425 void AppRTCSettings::addResource(Resources id, Resource* res) 00426 { 00427 _res[id] = res; 00428 } 00429 00430
Generated on Wed Jul 13 2022 05:17:56 by 1.7.2