Pakistan
Offline
Sr. Member
Karma: 5
Posts: 318
Arduino rocks
|
 |
« Reply #255 on: December 22, 2012, 02:49:56 am » |
Next version  As behaviour of the MW_ROOT _menu I will be the one who shall wait forever  Thanks
|
|
|
|
|
Logged
|
|
|
|
|
Norway
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #256 on: December 22, 2012, 04:58:02 am » |
Hi, I plan to use Menwiz for menu input in a temperature control system with two pid processes and 8-10 one-wire sensors. I will use input via ISR. Here is my test code based on the quick_tour.ino example. I hope this is useful and helps someone. /* Sketch for Arduino/IDE 1.x (quick_tour_rotEnc.ino). Based on MENWIZ quick_tour.ino Detent rotary encoder with two buttons and 16x2 LCD example. Input signal using interrupts on pin A0/1 for encoder and A2/3 for buttons. Based on BenF forum sketch 25may2011 and debounce from delphino-999 forum sketch 19oct2012. HW: Roboduino (http://arduino-direct.com/sunshop) and rotary encoder with pushbutton (Panasonic 30 PPR, audiosector, www.ebay.com) Desember 2012, Hans Fredrik Sandberg Pin allocation on Uno D4 LCD DB4 D5 LCD DB5 D6 LCD DB6 D7 LCD DB7 D8 LCD RS D9 LCD Enable D10 LCD backlit control A0 D14 Rotary A left 1 A1 D15 Rotary B right 2 A2 D16 Button 1 confirm 6 A3 D17 Button 2 escape 5 */ #include <Wire.h> #include <LiquidCrystal.h> #include <buttons.h> #include <MENWIZ.h> #include <EEPROM.h>
volatile byte virtualButton = 0; // which button was pressed volatile int push[2] = {0,0}; // Variable to pass button press back to main loop long debouncing_time = 40; // Debouncing Time in Milliseconds volatile unsigned long last_micros; // Variable to keep time while debounce
menwiz menu; LiquidCrystal lcd( 8, 9, 4, 5, 6, 7, 10, POSITIVE ); //LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlightpin, polarity 4 x 20 LCD extern byte MW_navbtn; // needed to run the software key navigation in Menwiz int list,setp=110;
void setup() { Serial.begin(9600); Serial.println("Start"); PORTC |= _BV(PORTC0) | _BV(PORTC1) | _BV(PORTC2) | _BV(PORTC3); // enable pullup for pins PCMSK1 = _BV(PCINT8) | _BV(PCINT9) | _BV(PCINT10) | _BV(PCINT11); // enable button pin change interrupt A0 A1 A2 A3 PCICR = _BV(PCIE1); // C-port interrupt enable
_menu *r,*s1,*s2; menu.begin(&lcd,16,2); menu.addUsrNav(navMenu); MW_navbtn=4; // force 4 or 6 buttons mode for menu navigation -> MW_navbtn=4; or MW_navbtn=6;
r=menu.addMenu(MW_ROOT,NULL,F("Root")); s1=menu.addMenu(MW_SUBMENU,r, F("Node1-submenu")); s2=menu.addMenu(MW_VAR,s1, F("Node3-list")); s2->addVar(MW_LIST,&list); s2->addItem(MW_LIST, F("Option1")); s2->addItem(MW_LIST, F("Option2")); s2->addItem(MW_LIST, F("Option3")); s2=menu.addMenu(MW_VAR,s1, F("Node4-int")); s2->addVar(MW_AUTO_INT,&setp,0,120,1); s2=menu.addMenu(MW_VAR,s1,F("back")); s2->addVar(MW_ACTION,escapeFunct); s2->setBehaviour(MW_ACTION_CONFIRM,false); // MW_ACTION_IMMEDIATE described in MENWIZ_0-6-0_QUICK TOUR.pdf s1=menu.addMenu(MW_VAR,r, F("Node2-action")); s1->addVar(MW_ACTION,myfunc);
sprintf(menu.sbuf,"Test MENWIZ\nRotEnc SwBtn",1); // Splash screen shown at startup time menu.addSplash((char *) menu.sbuf,4000); // Shown for msecs menu.addUsrScreen(msc,3000); // Default screen function shown after msecs since last button push digitalWrite(10, HIGH); // LCD backlit on }
void loop() { menu.draw(); // NAVIGATION MANAGEMENT & DRAWING ON LCD. NOT BLOCKING has to be the first in the void loop /* put your regular code here */ if ( push [0] > 0 ) { // confirm virtualButton = 6; push[0] = 0; } if ( push [1] > 0 ) { // escape virtualButton = 5; push[1] = 0; } }
ISR(PCINT1_vect) // handle pin change interrupt for A0 to A5 here { static uint8_t AB = 0x03; //lookup table index static long encval = 0; //encoder value static const int8_t enc_states[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0}; static uint8_t btn = _BV(PINC2) | _BV(PINC3); uint8_t t = PINC; // read port status
// check for rotary2 state change on pin A0 A1 AB <<= 2; // save previous state AB |= ( t & 0x03 ); // add current state, from lower port pin pair encval += enc_states[AB & 0x0f]; if( encval > 1 ) { // step forward virtualButton = 2; encval = 0; } else if( encval < -1 ) { // step backwards virtualButton = 1; encval = 0; }
// check if buttons are pushed t &= _BV(PINC2) | _BV(PINC3); // A2 A3 if (t != btn) { // activity on pins, we're only interested in high to low transitions if((long)(micros() - last_micros) >= debouncing_time * 1000) { push[0] |= !(t & _BV(PINC2)); push[1] |= !(t & _BV(PINC3)); btn = t; last_micros = micros(); // start/restart bounce guard timer (covers make and break) } } }
void myfunc(){Serial.println("ACTION FIRED");}
int navMenu() // called from menu.draw { switch (virtualButton) { case 5: // Escape virtualButton = 0; return MW_BTE; break; case 6: // Confirm virtualButton = 0; return MW_BTC; break; case 1: // Up virtualButton = 0; return MW_BTU; break; case 2: // Down virtualButton = 0; return MW_BTD; break; case 0: // no button return MW_BTNULL; break; } }
void escapeFunct() { Serial.println("Back Called"); virtualButton = 5; //simulate escape button press, for use in some menus }
// user defined default screen. void msc() { sprintf(menu.sbuf,"Proc.time:%ld\nFr.mem:%d\n",millis()/1000,(int)menu.freeRam()); menu.drawUsrScreen(menu.sbuf); } I will gladly do testing of new library version 1.1.0 beta! I have downloaded the zip from 18des. Will these steps do as verifiation of the new library? (I have never done this before, that is why so detailed...) - Stop the IDE
- Move directory C:\arduino-1.0.2\libraries\MENWIZ to another place
- Create a new directory C:\arduino-1.0.2\libraries\MENWIZ.
- Copy the two new files MENWIZ.cpp and MENWIZ.h
- Start the IDE, open sketch and upload to board
- Test all the menu posibilities with the four button actions
Another question: Is the version noted somewere inside the files?
|
|
|
|
|
Logged
|
|
|
|
|
Pakistan
Offline
Sr. Member
Karma: 5
Posts: 318
Arduino rocks
|
 |
« Reply #257 on: December 23, 2012, 01:55:01 am » |
Hi brunitali, How can we load the variable from EEPROM automatically after powering up of Arduino..i tried loadvar(); at the end of Setup(); This trick load the variable parameters but when i enter into Basic Parameters, the last parameters description always double.. e.g: Basic Parameters: -Khalid -Khattak -Farooq -Farooq
You see the -Farooq double.. why? Anyway, to load the parameters from EEPROM at startup so that programm can run automatically based on those values and user not to Load the parameters manually.
|
|
|
|
|
Logged
|
|
|
|
|
rome
Offline
Sr. Member
Karma: 13
Posts: 342
|
 |
« Reply #258 on: December 23, 2012, 04:21:54 am » |
@HansF The steps are: - create a library directory anywhere (e.g. c:/mysketches) - enter the ide menu File/Preferences and enter the c:/mysketches as default sketches directory - create the libraries MENWIZ subdirectory directory inside c:/mysketches - move into MENWIZ the MENWIZ.h, MENWIZ.cpp, keywords.txt files and the examples directory - start IDE again
WARNING: addUsrNav requires now two parameters, and it is not any more necessary to manually force MW_navbtn parameter.
The 1.1.0 is available on github. I suggest to subscribe for notificazion on github, so you'll b enotified as new versione will be available (1.2.0 quite soon).
EDIT: in the 1.1.0 MENWIZ the version is available calling menu.getVer(). In version 1.2.0 the getVer will be stripped off the menwiz class and will became a pseudofunction (a function declared via a #define).
@khalid The setup invocation should be correct. I cannot undestand exactly what do you mean with doubling parameter description... do you mean you find a two lines in the menus instead of one? let me see the setup code
|
|
|
|
« Last Edit: December 23, 2012, 05:26:28 am by brunialti »
|
Logged
|
|
|
|
|
rome
Offline
Sr. Member
Karma: 13
Posts: 342
|
 |
« Reply #259 on: December 23, 2012, 06:03:16 am » |
@Khalid May be i found a bug. Do the line duplication occours when you set root menu as collapsed menu? If it is true that is a bug I detected and solved. Probably I need to anticipate the release of 1.2.0. version to fix the problem
|
|
|
|
|
Logged
|
|
|
|
|
Pakistan
Offline
Sr. Member
Karma: 5
Posts: 318
Arduino rocks
|
 |
« Reply #260 on: December 23, 2012, 06:05:25 am » |
brunialti, I shall soon make the video and post..Youtube service is unavailable in my country.. However, my question is: How can we load the variable from EEPROM at the start of program?
|
|
|
|
|
Logged
|
|
|
|
|
Pakistan
Offline
Sr. Member
Karma: 5
Posts: 318
Arduino rocks
|
 |
« Reply #261 on: December 23, 2012, 06:08:57 am » |
@Khalid May be i found a bug. Do the line duplication occours when you set root menu as collapsed menu? If it is true that is a bug I detected and solved. Probably I need to anticipate the release of 1.2.0. version to fix the problem
Just see i called the loadvar(); in the end of setup after creations of all menuobjects. Which causes duplication in collapsed menu. //MENWIZ ESAMPLE #include <Wire.h> //INSERT ALL THE FOLLOWING 5 INCLUDES AFTER INCLUDING WIRE LIB #include <LCD.h> #include <LiquidCrystal_I2C.h> #include <buttons.h> #include <MENWIZ.h> #include <EEPROM.h> // to be included only if defined EEPROM_SUPPORT
// DEFINE ARDUINO PINS FOR THE NAVIGATION BUTTONS #define UP_BUTTON_PIN 9 #define DOWN_BUTTON_PIN 10 #define LEFT_BUTTON_PIN 7 #define RIGHT_BUTTON_PIN 8 #define CONFIRM_BUTTON_PIN 12 #define ESCAPE_BUTTON_PIN 11
//Create global object menu and lcd menwiz menu; LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlighpin, polarity
//instantiate global variables to bind to menu int tp=0; float f=26.0; boolean bb=0; byte b=50;
void setup(){ _menu *r,*s1,*s2; _var *v; int mem;
Serial.begin(19200); // have a look on memory before menu creation Serial.println(sizeof(menwiz)); mem=menu.freeRam(); // inizialize the menu object (20 colums x 4 rows) menu.begin(&lcd,20,4);
//create the menu tree r=menu.addMenu(MW_ROOT,NULL,F("MAIN MENU")); //create a root menu at first (required) s1=menu.addMenu(MW_SUBMENU,r,F("MEASURE SUBMENU")); //add a child (submenu) node to the root menu s1->setBehaviour(MW_MENU_COLLAPSED,true); s2=menu.addMenu(MW_VAR,s1,F("list")); //add a terminal node (that is "variable"); s2->addVar(MW_LIST,&tp); //create a variable of type "option list".. s2->addItem(MW_LIST,F("option 1")); //add option to the OPTION LIST s2->addItem(MW_LIST,F("option 2")); //add option to the OPTION LIST s2->addItem(MW_LIST,F("option 3")); //add option to the OPTION LIST s2->addItem(MW_LIST,F("option 4")); //add option to the OPTION LIST s2->addItem(MW_LIST,F("option 5")); //add option to the OPTION LIST // s2->setBehaviour(MW_SCROLL_HORIZONTAL,true); // s2->setBehaviour(MW_LIST_2COLUMNS,true); // s2->setBehaviour(MW_LIST_3COLUMNS,true);
s2=menu.addMenu(MW_VAR,s1,F("float var")); //add a terminal node (that is "variable"); s2->addVar(MW_AUTO_FLOAT,&f,11.00,100.00,0.5); //create a variable of type "float number"... //...associated to the terminal node and bind it to the app variable "f" of type float s2=menu.addMenu(MW_VAR,s1,F("byte var")); //add a terminal node (that is "variable"); s2->addVar(MW_AUTO_BYTE,&b,25,254,10); //create a variable of type "byte"... //...associated to the terminal node and bind it to the app variable "b" of typr byte s2=menu.addMenu(MW_VAR,s1,F("boolean var")); //add a terminal node (that is "variable"); s2->addVar(MW_BOOLEAN,&bb); //create a variable of type "boolean" //...associated to the terminal node and bind it to the app variable "bb" of type boolean s1=menu.addMenu(MW_VAR,r,F("WRITE TO SERIAL")); //add a terminal node (that is "variable") create an "action" associated to the terminal node... s1->addVar(MW_ACTION,act); //the act function as default will be called when enter button is pushed // s1->setBehaviour(MW_ACTION_CONFIRM,false); //...if you don't need action confirmation
s1=menu.addMenu(MW_VAR,r,F("SAVE TO EPROM")); //add a terminal node (that is "variable") create an "action" associated to the terminal node... s1->addVar(MW_ACTION,savevar); //the act function as default will be called when enter button is pushed
s1=menu.addMenu(MW_VAR,r,F("LOAD FROM EEPROM")); //add a terminal node (that is "variable") create an "action" associated to the terminal node... s1->addVar(MW_ACTION,loadvar); //the act function as default will be called when enter button is pushed
//declare navigation buttons (required) menu.navButtons(UP_BUTTON_PIN,DOWN_BUTTON_PIN,ESCAPE_BUTTON_PIN,CONFIRM_BUTTON_PIN);
loadvar(); //(optional)create a user define screen callback to activate after 10 secs (10.000 millis) since last button push menu.addUsrScreen(msc,10000);
//(optional) create a splash screen (duration 5.000 millis)with some usefull infos the character \n marks end of LCD line //(tip): use preallocated internal menu.sbuf buffer to save memory space! // sprintf(menu.sbuf,"MENWIZ TEST V %s\n.Free mem. :%d\n.Used mem :%d\n.Lap secs :%d",menu.getVer(),menu.freeRam(),mem-menu.freeRam(),5); // menu.addSplash((char *) menu.sbuf, 5000); }
void loop(){ menu.draw(); //PUT APPLICATION CODE HERE (if any) }
// user defined callbacks // WARNING avoid sprintf usage: it requires > 1.5 kbytes of memory! void msc(){ static char buf[7]; strcpy(menu.sbuf,"User screen"); //1st lcd line strcat(menu.sbuf,"\nUptime (s): ");strcat(menu.sbuf,itoa((int)(millis()/1000),buf,10));//2nd lcd line strcat(menu.sbuf,"\nFree mem : ");strcat(menu.sbuf,itoa((int)menu.freeRam(),buf,10));//3rd lcd line strcat(menu.sbuf,"\n"); //4th lcd line (empty) menu.drawUsrScreen(menu.sbuf); } void act(){ Serial.println("FIRED ACTION!"); } void savevar(){ menu.writeEeprom(); } void loadvar(){ menu.readEeprom(); }
if i comment the loadvar(); function duplication not happen... for close lookup, just see the following sketch where i loaded the EEPROM in void Setup(); s1=menu.addMenu(MW_VAR,r,F("LOAD FROM EEPROM")); //add a terminal node (that is "variable") create an "action" associated to the terminal node... s1->addVar(MW_ACTION,loadvar); //the act function as default will be called when enter button is pushed
//declare navigation buttons (required) menu.navButtons(UP_BUTTON_PIN,DOWN_BUTTON_PIN,ESCAPE_BUTTON_PIN,CONFIRM_BUTTON_PIN); //Loading variable from EEPROM loadvar();
|
|
|
|
« Last Edit: December 23, 2012, 06:16:30 am by Khalid »
|
Logged
|
|
|
|
|
Pakistan
Offline
Sr. Member
Karma: 5
Posts: 318
Arduino rocks
|
 |
« Reply #262 on: December 24, 2012, 08:24:24 am » |
Hi again, I want to display the byte variable on LCD in void msc(); How can i convert byte to string?
You posted itoa for integer conversion to string , do you help me in byte to string?
Regards
|
|
|
|
|
Logged
|
|
|
|
|
rome
Offline
Sr. Member
Karma: 13
Posts: 342
|
 |
« Reply #263 on: December 24, 2012, 01:22:12 pm » |
Khalid, this is not the place where to post general questions about c language and programming. There are other threads and places where you can get help about that. By the way the itoa works fine also with byte, without casting.
byte a=78; char buf[4]; Serial.print(itoa(a, buf,10));
|
|
|
|
|
Logged
|
|
|
|
|
rome
Offline
Sr. Member
Karma: 13
Posts: 342
|
 |
« Reply #264 on: December 24, 2012, 01:38:57 pm » |
@Khalid, some bugs found in the 1.1.0 in boundary conditions (e.g. using some behaviours with root menus). Neverthless I could'nt replicate the loadvar error. As I worked to the 1.2.0 please use it (here attached in beta). Any test is wellcome. This is the last version (this year  ) Solved bugsSolved few bug occourring when a root menu is declared as collapsed menu in ver 1.1.0 . Internal changesIt is possible to disable button.h support in order to save space. New and modified functionsNew behaviours added: MW_MENU_INDEX (applies to objects of class menwiz). The getVer() function is now declared as #define pseudofunction, outside menwiz class.
|
|
|
|
« Last Edit: December 24, 2012, 01:50:46 pm by brunialti »
|
Logged
|
|
|
|
|
Pakistan
Offline
Sr. Member
Karma: 5
Posts: 318
Arduino rocks
|
 |
« Reply #265 on: December 24, 2012, 02:19:49 pm » |
Thanks brunialti Roberto, I shall check and tell you tommorrow.. I am stuck here , i have defined M_PWM as a byte variable. This store motor PWM value in the range 0~100 in the EEPROM. I was unable to make user screen in MENWIZ.. you can see following code, especially below the //2nd LCD Line: void msc(){ static char buf[7]; int Diff=0; //1st lcd line strcpy(menu.sbuf,"E:"); strcat(menu.sbuf,itoa((int)(READ_RIGHT_LDR),buf,10)); strcat(menu.sbuf,"W:"); strcat(menu.sbuf,itoa((int)(READ_LEFT_LDR),buf,10)); //integer variable READ_RIGHT_LDR and READ_LEFT_LDR getting values from Analog pins (1~1023) if (READ_RIGHT_LDR>READ_LEFT_LDR) { Diff=READ_RIGHT_LDR-READ_LEFT_LDR; } else { Diff=READ_LEFT_LDR-READ_RIGHT_LDR; } strcat(menu.sbuf,"Diff:"); strcat(menu.sbuf,itoa((int)(Diff),buf,10)); //2nd LCD Line strcat(menu.sbuf,"\nMpwm:");strcat(menu.sbuf,itoa(M_PWM,buf,10)); //M_PWM is a byte range any value from 0 to 100. Here i am stuck....how can i use strcat?? // CALCULATING MINUTES AND SECOND int seconds = (int) ( CountdownTime/ 1000) % 60 ; //CountdownTime is unsigned long and a global variable suppose its getting values from Millis() int minutes = (int) ((CountdownTime / (1000*60)) % 60); strcat(menu.sbuf," CNTD:");strcat(menu.sbuf,itoa((int)(minutes),buf,10)); strcat(menu.sbuf,":");strcat(menu.sbuf,itoa((int)(seconds),buf,10)); //3rd LCD Line strcat(menu.sbuf,"\nSamplingTime: ");strcat(menu.sbuf,itoa((int)(SampleTime),buf,10));//SampleTime is integer variable //4th LCDLine strcat(menu.sbuf,"\nSensitivity: ");strcat(menu.sbuf,itoa((int)(Sensitivity),buf,10));//Sensitivity is also integer menu.drawUsrScreen(menu.sbuf); }
|
|
|
|
« Last Edit: December 24, 2012, 02:29:26 pm by Khalid »
|
Logged
|
|
|
|
|
rome
Offline
Sr. Member
Karma: 13
Posts: 342
|
 |
« Reply #266 on: December 24, 2012, 03:30:44 pm » |
I have not enough information, Anyway the following code (extracted by your example) works correctly. Check actual values of your variable in msc.... byte M_PWM=78; //is it correc?t
void setup(){ static char buf[7],sbuf[25]; int Diff=0; Serial.begin(19200); //2nd LCD Line strcat(sbuf,"Mpwm:"); strcat(sbuf,itoa(M_PWM,buf,10)); Serial.println(sbuf); } void loop() {}
|
|
|
|
|
Logged
|
|
|
|
|
Pakistan
Offline
Sr. Member
Karma: 5
Posts: 318
Arduino rocks
|
 |
« Reply #267 on: December 25, 2012, 12:18:04 am » |
Okay Brunalti, I tested the new functionalities and here is my review: GOOD THING: 1- Menu index (MW_MENU_INDEX) appears on the LCD screen and looks good 2- The new library function good when serial.println function is not in use in the USER DISPLAY SCREEN. BAD THING: 1- The new library is unstable, if the serial monitor is ON and Serial.Println function working in the USER DISPLAY SCREEN:
a)I have 04 nodes in the MAIN MENU, If the Serial.Println(); i.e. serial communication is on then when i reach to 4/4, the arduino reset itself and shows weired characters on LCD. It always reset.. Just see the MenuStructure: MAIN MENU Basic Parameters Move East Save Load
Basic Parameters have terminal nodes like following Basic Parameters Manual (This is List of 5) Motor PWM Sensitivity NightRetHr RTimeSec LightPoint SampleTimein
b) if the serial communication is on, When i go to Node 3 of the Menu (Save), and press the confirm button, the next screen appears but all things are mixed up and nothing happen. c)if the serial communication is on, I can't go to Node-4 (Load) of the menu, the LCD shows weired character and hang..
Previously all working fine for me....
Regards
|
|
|
|
« Last Edit: December 25, 2012, 01:53:18 am by Khalid »
|
Logged
|
|
|
|
|
Pakistan
Offline
Sr. Member
Karma: 5
Posts: 318
Arduino rocks
|
 |
« Reply #268 on: December 25, 2012, 02:31:49 am » |
I disabled the Serial function in USER DISPLAY SCREEN and all things are working fine to me. Have few questions: 1- How can i display the following two cutom characters on my USER DISPLAY SCREEN: //MOON byte Moon[8] = { B00100, B01000, B11000, B11001, B11001, B11111, B01110, B00000 };
byte Sun[8] = { B00000, B00100, B10101, B01010, B11111, B11111, B11111, B11111 }; 2- How can i increase the delay time in USER DISPLAY SCREEN. actually my analog sensors readings are too fast on USER SCREEN unable to read.
|
|
|
|
|
Logged
|
|
|
|
|
rome
Offline
Sr. Member
Karma: 13
Posts: 342
|
 |
« Reply #269 on: December 25, 2012, 04:43:07 am » |
About Serial problems in user screen It is obscure for me. I'll try to replicate. Maybe serial connection introduces a delay time and/or has conflicts with your current arduino attached sensors/devices.
About characters, you can use createChar (this is not a MENWIZ char, it is a LiquidCrystal method instead, look at menwiz.cpp). Be carefull: it may conflict with MEWNWIZ, as it also create characters. Use char indexes higher than 3.
The user display elapsed time (the idle time before user screen appears) is the last parameter of addusrscreen. But perhaps I did not uderstand your problem. If you refer to rapidly changes to values in user screen ... there are no ways other than to introduce a delay ... but it will slow down the interface responsivity. Try values around max 100 millis ... It sound quite strange as in my experience sensors values never changed at such a dramatic pace to let them unreadable on a LCD ... You can also and preferably set a user software implemented delay time before refresh values: store the latest read time and let the value be refreshed after that value (I suggest 500 millis).
|
|
|
|
« Last Edit: December 25, 2012, 04:54:26 am by brunialti »
|
Logged
|
|
|
|
|
|