Go to Post Keep in mind that words can be harsh and people do not forget what is said against them. Please, for your teammates sake, keep your egos in check and try to use some tact and consideration. - Andy Baker [more]
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
 
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 30-04-2010, 12:06
johncap100 johncap100 is offline
Registered User
FTC #0658
 
Join Date: Aug 2009
Location: Capital High School
Posts: 95
johncap100 is an unknown quantity at this point
Re: Older FRC autonomous code

mark i tried the following code from one of my students and it does not seem to work, i will try your code above.

any help is greatly appreciated.

by the way i am opening up the user-routine_fast.c to modify the autonomous code is that correct?
thanks


// Drive forward, turn, return, and stop

void Autonomous()
{
static int counter=0; //keep track of loops to use as a crude timer - static keeps it around from call to call
static int autostate=1; //keep track of what step we're supposed to be doing

switch (autostate)
{
case 1: // Drive forward
pwm01 = pwm02 = 200;
pwm03 = pwm04 = 54; //motor is reversed
if (counter>38) //1 second
{
autostate = 2; // move on to the next step
counter = 0; // reset our timer for the next step
}

case 2: // Turnaround
pwm01 = pwm02 = 200;
pwm03 = pwm04 = 200; //motor is reversed
if (counter>76) //2 seconds
{
autostate = 3;
counter = 0;
}

case 3: // Drive forward (returning now)
pwm01 = pwm02 = 200;
pwm03 = pwm04 = 54; //motor is reversed
if (counter>38) //1 second
{
autostate = 4;
counter = 0;
}

case 4: // Stop - What to do when everything else is done
default: // also what to do if an invalid autostate occurs

pwm01 = pwm02 = pwm03 = pwm04 = 127; // Make sure the last thing you do is always stop
}
counter++;
}
  #2   Spotlight this post!  
Unread 30-04-2010, 12:55
efoote868 efoote868 is offline
foote stepped in
AKA: E. Foote
FRC #0868
Team Role: Mentor
 
Join Date: Mar 2006
Rookie Year: 2005
Location: Noblesville, IN
Posts: 1,406
efoote868 has a reputation beyond reputeefoote868 has a reputation beyond reputeefoote868 has a reputation beyond reputeefoote868 has a reputation beyond reputeefoote868 has a reputation beyond reputeefoote868 has a reputation beyond reputeefoote868 has a reputation beyond reputeefoote868 has a reputation beyond reputeefoote868 has a reputation beyond reputeefoote868 has a reputation beyond reputeefoote868 has a reputation beyond repute
Re: Older FRC autonomous code

Did that compile OK?
When you loaded it and ran autonomous, I (hope) the robot just stayed still. Luckily your last state was no movement, because without break statements, it'll run through all the states.

Should be:

switch(variable)
{
case 0:
//do stuff
break;

case 1:
//do other stuff
break;

case 2:
//do some stuff, and case 3's stuff

case 3:
//do something else
break;

default:
//do nothing
break;
}

If you take the default case out in your current setup, you should drive forward forever (which is dangerous, so I suggest you don't).
I also suggest that you disconnect the motors and just watch lights to see if its doing what you want.
__________________
Be Healthy. Never Stop Learning. Say It Like It Is. Own It.

Like our values? Flexware Innovation is looking for Automation Engineers. Check us out!

Last edited by efoote868 : 30-04-2010 at 12:57. Reason: a little clarification
  #3   Spotlight this post!  
Unread 30-04-2010, 15:01
Mark McLeod's Avatar
Mark McLeod Mark McLeod is offline
Just Itinerant
AKA: Hey dad...Father...MARK
FRC #0358 (Robotic Eagles)
Team Role: Engineer
 
Join Date: Mar 2003
Rookie Year: 2002
Location: Hauppauge, Long Island, NY
Posts: 8,801
Mark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond repute
Re: Older FRC autonomous code

Those are the break;'s
The break statement concludes individual cases. Without it one case statement blends right into the next without a "break".
That is one of the reasons for stopping all motors at the end.

I unfortunately duplicated one block and missed copying the original break statement as part of the block of code.
Sorry about that...

Corrected version:
Code:
// Drive forward, turn, return, and stop
 
void Autonomous()
{
 static int counter=0; //keep track of loops to use as a crude timer - static keeps it around from call to call
 static int autostate=1;   //keep track of what step we're supposed to be doing
 
  switch (autostate)
  {
    case 1:   // Drive forward
        pwm01 = pwm02 = 200;
        pwm03 = pwm04 = 54;  //motor is reversed
        if (counter>38)  //1 second
        {  
           autostate = 2;  // move on to the next step
           counter = 0;    // reset our timer for the next step
        }
        break;
 
    case 2:   // Turnaround
        pwm01 = pwm02 = 200;
        pwm03 = pwm04 = 200;  //motor is reversed
        if (counter>76)  //2 seconds
        {  
           autostate = 3;
           counter = 0;
        }
        break;

 
    case 3:   // Drive forward (returning now)
        pwm01 = pwm02 = 200;
        pwm03 = pwm04 = 54;  //motor is reversed
        if (counter>38)  //1 second
        {  
           autostate = 4;
           counter = 0;
        }
        break;

 
     case 4:   // Stop - What to do when everything else is done
     default:  // also what to do if an invalid autostate occurs
 
       pwm01 = pwm02 = pwm03 = pwm04 = 127;   // Make sure the last thing you do is always stop
  }
  counter++;
}
__________________
"Rationality is our distinguishing characteristic - it's what sets us apart from the beasts." - Aristotle

Last edited by Mark McLeod : 30-04-2010 at 15:13.
  #4   Spotlight this post!  
Unread 30-04-2010, 15:28
Mark McLeod's Avatar
Mark McLeod Mark McLeod is offline
Just Itinerant
AKA: Hey dad...Father...MARK
FRC #0358 (Robotic Eagles)
Team Role: Engineer
 
Join Date: Mar 2003
Rookie Year: 2002
Location: Hauppauge, Long Island, NY
Posts: 8,801
Mark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond repute
Re: Older FRC autonomous code

Quote:
Originally Posted by johncap100 View Post
by the way i am opening up the user-routine_fast.c to modify the autonomous code is that correct?
That means you're using the IFI default code rather than the Watson default code.

You'll need slightly different handling for that just because the framework structure is different. In user_routines_fast.c in the Autonomous() routine already there you'll want to keep some of the default code it uses. Below the lines in black are what you should already see in that default routine, and the lines in red are what need to be added. Really the critical part that's missing is the Getdata that tells the robot when autonomous mode is over and Putdata that sends your motor settings out to be used. Without that nothing would ever happen.

Code:
void User_Autonomous_Code(void)
{
 static int counter=0; //keep track of loops to use as a crude timer - static keeps it around from call to call
 static int autostate=1;   //keep track of what step we're supposed to be doing

  /* Initialize all PWMs and Relays when entering Autonomous mode, or else it
     will be stuck with the last values mapped from the joysticks.  Remember, 
     even when Disabled it is reading inputs from the Operator Interface. 
  */
  pwm01 = pwm02 = pwm03 = pwm04 = pwm05 = pwm06 = pwm07 = pwm08 = 127;
  pwm09 = pwm10 = pwm11 = pwm12 = pwm13 = pwm14 = pwm15 = pwm16 = 127;
  relay1_fwd = relay1_rev = relay2_fwd = relay2_rev = 0;
  relay3_fwd = relay3_rev = relay4_fwd = relay4_rev = 0;
  relay5_fwd = relay5_rev = relay6_fwd = relay6_rev = 0;
  relay7_fwd = relay7_rev = relay8_fwd = relay8_rev = 0;

  while (autonomous_mode)   /* DO NOT CHANGE! */
  {
    if (statusflag.NEW_SPI_DATA)      /* 26.2ms loop area */
    {
        Getdata(&rxdata);   /* DO NOT DELETE, or you will be stuck here forever! */
 
        // Drive forward, turn, return, and stop

        switch (autostate)
        {
    case 1:   // Drive forward
       pwm01 = pwm02 = 200;
        pwm03 = pwm04 = 54;  //motor is reversed
       if (counter>38)  //1 second
        {  
           autostate = 2;  // move on to the next step
           counter = 0;    // reset our timer for the next step
        }
        break;
 
    case 2:   // Turnaround
        pwm01 = pwm02 = 200;
        pwm03 = pwm04 = 200;  //motor is reversed
        if (counter>76)  //2 seconds
        {  
           autostate = 3;
           counter = 0;
        }
        break;

 
    case 3:   // Drive forward (returning now)
        pwm01 = pwm02 = 200;
        pwm03 = pwm04 = 54;  //motor is reversed
        if (counter>38)  //1 second
        {  
           autostate = 4;
           counter = 0;
       }
       break;

 
     case 4:   // Stop - What to do when everything else is done
     default:  // also what to do if an invalid autostate occurs
 
       pwm01 = pwm02 = pwm03 = pwm04 = 127;   // Make sure the last thing you do is always stop
  }
  counter++;

        Generate_Pwms(pwm13,pwm14,pwm15,pwm16);

        Putdata(&txdata);   /* DO NOT DELETE, or you will get no PWM outputs! */
    }
  }
}

__________________
"Rationality is our distinguishing characteristic - it's what sets us apart from the beasts." - Aristotle

Last edited by Mark McLeod : 30-04-2010 at 15:36.
  #5   Spotlight this post!  
Unread 30-04-2010, 21:38
johncap100 johncap100 is offline
Registered User
FTC #0658
 
Join Date: Aug 2009
Location: Capital High School
Posts: 95
johncap100 is an unknown quantity at this point
Re: Older FRC autonomous code

Well Mark i typed in the code above in red, and yes the black code is there.
It built fine, and i downloaded it , but the autonomous did not work, all that is working is the teleop, one joystick operates one motor and the other joystick the other one.
i have the motor controllers plugged into pwm ports 1 and 2. There seems that there should be someway to let the program that this is autonomous and not teleop. is it set up to go to autononmous if there is code there?
how many times will it go through the autononmous code?
thanks
  #6   Spotlight this post!  
Unread 30-04-2010, 22:11
Mark McLeod's Avatar
Mark McLeod Mark McLeod is offline
Just Itinerant
AKA: Hey dad...Father...MARK
FRC #0358 (Robotic Eagles)
Team Role: Engineer
 
Join Date: Mar 2003
Rookie Year: 2002
Location: Hauppauge, Long Island, NY
Posts: 8,801
Mark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond repute
Re: Older FRC autonomous code

You do have to put the robot into Autonomous mode before it'll take effect.

Normally, we use a special switch constructed for the purpose. (You can ignore switch 3 on that schematic. It's for earlier versions of the IFI control system.)
The disable button is handy to have in any case for emergency stops.

You can also setup an auto routine to run while you push a joystick button.

If you only want to run autonomous and don't care about Teleop, there is a way to set the team number most-significant-bit so the robot runs Auto mode all the time.


P.S.
Since you're using PWM 1 and 2 only, the auto code needs to be adjusted to reflect this, rather than pwm01/pwm02 and pwm03/pwm04
E.g.,
pwm01 = 200;
pwm02 = 54;
__________________
"Rationality is our distinguishing characteristic - it's what sets us apart from the beasts." - Aristotle

Last edited by Mark McLeod : 30-04-2010 at 22:40.
  #7   Spotlight this post!  
Unread 01-05-2010, 08:09
johncap100 johncap100 is offline
Registered User
FTC #0658
 
Join Date: Aug 2009
Location: Capital High School
Posts: 95
johncap100 is an unknown quantity at this point
Re: Older FRC autonomous code

Where does the switch plug in? on the robot controller?

How would one go about adding the routine into the code?

if you would be so kind as to helpme on these two things

thanks
  #8   Spotlight this post!  
Unread 01-05-2010, 09:14
apalrd's Avatar
apalrd apalrd is offline
More Torque!
AKA: Andrew Palardy (Most people call me Palardy)
VRC #3333
Team Role: College Student
 
Join Date: Mar 2009
Rookie Year: 2009
Location: Auburn Hills, MI
Posts: 1,347
apalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond repute
Re: Older FRC autonomous code

The switch plugs into the "competition" port on the Operator Interface. You only need sw1 and sw2, Disabled and Autonomous. If you would rather use a joystick button to indicate autonomous mode, you could say something like "autonomous_mode = pw_trig;" right after Getdata, for both Process_Data_From_Master_uP and User_Autonomous_Code.
__________________
Kettering University - Computer Engineering
Kettering Motorsports
Williams International - Commercial Engines - Controls and Accessories
FRC 33 - The Killer Bees - 2009-2012 Student, 2013-2014 Advisor
VEX IQ 3333 - The Bumble Bees - 2014+ Mentor

"Sometimes, the elegant implementation is a function. Not a method. Not a class. Not a framework. Just a function." ~ John Carmack
  #9   Spotlight this post!  
Unread 01-05-2010, 16:03
Mark McLeod's Avatar
Mark McLeod Mark McLeod is offline
Just Itinerant
AKA: Hey dad...Father...MARK
FRC #0358 (Robotic Eagles)
Team Role: Engineer
 
Join Date: Mar 2003
Rookie Year: 2002
Location: Hauppauge, Long Island, NY
Posts: 8,801
Mark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond repute
Re: Older FRC autonomous code

Yes, it connects to the Operator Interface at the driver controls.
I've attached a photo of a Disable/Auto switch on our '08 robot controls.
It happens to be out in my van for an appearance at the Special Olympics tomorrow.

If you want to use one of the joystick buttons to trigger it as well, the Autonomous routine can be rewritten slightly to accommodate being called two different ways. I'd prefer not to flat-out clobber the autonomous mode flag, but to structure the code such that either way will trigger the auto routine.
Had one team fail year after year on the playing field whenever a particular mentor would return every-other year to help them. Always turned out he would overwrite the autonomous mode flag with a joystick switch so the real flag would never work. It's a bad habit to start.

Maybe something along the lines of (in User_Autonomous_Code and main.c):
Code:
while (autonomous_mode || (p1_sw_trig == 1) )   /* DO NOT CHANGE! */
You'd also need to modify main.c with the same statement modification to get it to start and the joystick button would act as a dead-man switch. You'd have to hold it to keep autonomous running. Letting go would stop it.

What might be simpler for you right now is to just call an auto routine like that in post #14 directly from user_routines.c whenever the button is held down. a la,
Code:
void Process_Data_From_Master_uP(void)
{
  static unsigned char i;

  Getdata(&rxdata);   /* Get fresh data from the master microprocessor. */

    if (p1_sw_trig == 1)
    {
       Autonomous();
    }
    else 
        Default_Routine();  /* Optional.  See below. */
You don't have to be in Autonomous Mode to run some autonomous routine in teleop.

P.S. If you add a new routine like Autonomous(), depending on where you add it you may need to declare it in one of the header files (.h) so the compiler knows where to find it.
Attached Thumbnails
Click image for larger version

Name:	Kill-08-2.jpg
Views:	24
Size:	139.0 KB
ID:	9076  
__________________
"Rationality is our distinguishing characteristic - it's what sets us apart from the beasts." - Aristotle

Last edited by Mark McLeod : 02-05-2010 at 08:09.
  #10   Spotlight this post!  
Unread 01-05-2010, 17:32
johncap100 johncap100 is offline
Registered User
FTC #0658
 
Join Date: Aug 2009
Location: Capital High School
Posts: 95
johncap100 is an unknown quantity at this point
Re: Older FRC autonomous code

Ok great with all the info, sounds like it is best to have a dongle mostly as a kill switch, and then do the simple code in autonomous_user.c using a button trigger. i will try it this afternoon
thanks a bunch and will post how it goes
  #11   Spotlight this post!  
Unread 02-05-2010, 13:08
johncap100 johncap100 is offline
Registered User
FTC #0658
 
Join Date: Aug 2009
Location: Capital High School
Posts: 95
johncap100 is an unknown quantity at this point
Re: Older FRC autonomous code

well i went to the users_routines.c and right after the"Getdata (&rxdata);" i typed in the code from post 20 (the second code). When i ran the build all i get back the following 2 errors:
pl_sw_trig has not been defined
and
"call of function without prototype" referring to the Autonomous (); line.

any help is appreciated.

also just a quick check, i am doing this i the users_routines.c and not in the users_routines_fast.c. I understand that the latter one is for autonomous code editing only.
  #12   Spotlight this post!  
Unread 02-05-2010, 13:24
apalrd's Avatar
apalrd apalrd is offline
More Torque!
AKA: Andrew Palardy (Most people call me Palardy)
VRC #3333
Team Role: College Student
 
Join Date: Mar 2009
Rookie Year: 2009
Location: Auburn Hills, MI
Posts: 1,347
apalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond repute
Re: Older FRC autonomous code

Where is your Autonomous() function? It (or a prototype to it) should be before the routine that gets the error, Process_Data_From_Master_uP(). If the routine is in a separate file, then the prototype needs to go in a header. If Autonomous() is in the same file, then put it before Process_Data_From_Master_uP().

If you build the box, then you don't need the joystick trigger. One or the other. If you don't build the box, then it is easier to just use a joystick trigger.

p1_sw_trig should be valid..... it is.

http://ifirobotics.com/docs/legacy/2...2-apr-2004.pdf has a list of the IO definitions, you can find everything there. If you look at ifi_aliases.h it will tell you what the definition for everything is. If you created a C file for your code, you have to include ifi_aliases.h to use... anything (OI data, PWM outs, Analog, Digital inputs).
__________________
Kettering University - Computer Engineering
Kettering Motorsports
Williams International - Commercial Engines - Controls and Accessories
FRC 33 - The Killer Bees - 2009-2012 Student, 2013-2014 Advisor
VEX IQ 3333 - The Bumble Bees - 2014+ Mentor

"Sometimes, the elegant implementation is a function. Not a method. Not a class. Not a framework. Just a function." ~ John Carmack
  #13   Spotlight this post!  
Unread 02-05-2010, 13:58
Kevin Watson's Avatar
Kevin Watson Kevin Watson is offline
La Caņada High School
FRC #2429
Team Role: Mentor
 
Join Date: Jan 2002
Rookie Year: 2001
Location: La Caņada, California
Posts: 1,335
Kevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond reputeKevin Watson has a reputation beyond repute
Re: Older FRC autonomous code

Quote:
Originally Posted by johncap100 View Post
...any help is appreciated.
If you get stuck, feel free to send me your code and I'll have a look. Use kevin at kevin period org if you send me anything.

-Kevin
__________________
Kevin Watson
Engineer at stealth-mode startup
http://kevin.org
  #14   Spotlight this post!  
Unread 02-05-2010, 15:21
Mark McLeod's Avatar
Mark McLeod Mark McLeod is offline
Just Itinerant
AKA: Hey dad...Father...MARK
FRC #0358 (Robotic Eagles)
Team Role: Engineer
 
Join Date: Mar 2003
Rookie Year: 2002
Location: Hauppauge, Long Island, NY
Posts: 8,801
Mark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond repute
Re: Older FRC autonomous code

Quote:
Originally Posted by johncap100 View Post
pl_sw_trig has not been defined
"p1_" not "pl_"
I think you might not have used the numeral one.

It stands for port 1 on the Operator Interface. You can also use a joystick connected to any of the four ports available and refer to the buttons by the prefixes "p1_" "p2_" "p3_" or "p4_"

Quote:
Originally Posted by johncap100 View Post
"call of function without prototype" referring to the Autonomous (); line.
The compiler needs to be told a little bit about how the Autonomous() function is supposed to be called.
Up at the top of user_routines.c after the "#include" lines add the statement:
Code:
void Autonomous(void);
This'll tell the compiler that the routine doesn't have any calling arguments.

Doing this in users_routines.c is fine.
__________________
"Rationality is our distinguishing characteristic - it's what sets us apart from the beasts." - Aristotle

Last edited by Mark McLeod : 03-05-2010 at 14:01.
  #15   Spotlight this post!  
Unread 02-05-2010, 21:05
johncap100 johncap100 is offline
Registered User
FTC #0658
 
Join Date: Aug 2009
Location: Capital High School
Posts: 95
johncap100 is an unknown quantity at this point
Re: Older FRC autonomous code

Hey mark well i did cure the p1 issue, thanks

But when i try to build all i get an error as follows:
'could not find definition of symbol "Autonomous" in file 'C:\FRC Miller-2006 Codeopt b\user_routines.o' the file is where i have the workspace.

I suspect i need to add a line in an .h extension according to the bottom of your post #20, not sure what or where to put it.
thanks
Closed Thread


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Autonomous 2010 FRC Drucifur Java 10 14-02-2010 08:06
FRC...autonomous or driver-controlled competition? tribotec_ca88 General Forum 28 10-03-2005 14:47
Autonomous code PBoss Programming 7 14-01-2003 15:29
Autonomous Code Adrian Wong Robotics Education and Curriculum 1 18-11-2002 22:34


All times are GMT -5. The time now is 03:36.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi