Shop OBEX P1 Docs P2 Docs Learn Events
Menu options and ideas — Parallax Forums

Menu options and ideas

TCTC Posts: 1,019
edited 2014-05-29 19:26 in General Discussion
Hello all,

Still working on the reflow oven.

I am figuring out the menu for this oven, but I am having trouble deciding if what I have is OK, or is there something I missed. I feel like I am missing something. So I begging for your honest opinions and ideas.

Here is what I came up with for a menu. Nothing is set in stone, so please don't be afraid to say "That is a dumb idea"

Menu V1.jpg



Thanks
TC
1024 x 342 - 66K

Comments

  • kwinnkwinn Posts: 8,697
    edited 2014-05-25 15:25
    See if you can make adding a new profile part of editing a profile by creating a default or blank profile. Once that is created it is just a matter of editing it.
  • TCTC Posts: 1,019
    edited 2014-05-25 16:02
    kwinn wrote: »
    See if you can make adding a new profile part of editing a profile by creating a default or blank profile. Once that is created it is just a matter of editing it.

    I like that idea, should not be a problem.
  • FranklinFranklin Posts: 4,747
    edited 2014-05-25 17:28
    What device will this be running on? Is there ever a need to clear a PID config value rather than setting it to a different value?
  • TCTC Posts: 1,019
    edited 2014-05-25 17:40
    Franklin wrote: »
    What device will this be running on? Is there ever a need to clear a PID config value rather than setting it to a different value?

    It is for a DIY reflow oven.

    To set the values of the PID, each digit of the value can be selected and adjusted. With a max value being 99.999. I only had the clear option to make it easier to start over or to turn off a value. Do you think it would be a waist of time?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-25 18:07
    It's often useful to set a PID parameter to zero. Maybe it should be renamed?

    "Zero" or "Disable"? IMO, "Clear" is okay.

    I like the flow chart. I need to do that more often.
  • TCTC Posts: 1,019
    edited 2014-05-25 18:38
    Duane Degn wrote: »
    It's often useful to set a PID parameter to zero. Maybe it should be renamed?

    "Zero" or "Disable"? IMO, "Clear" is okay.

    I like the flow chart. I need to do that more often.

    I like the "Disable" name. I could set something up that if the value is zero, then display "Disabled" instead of the value.

    This is the first time doing a flow chart. I had to do something, I was doing this menu blind and out of my head. It is allowing me to be able to check off what I have done.
  • kwinnkwinn Posts: 8,697
    edited 2014-05-26 17:23
    It helps to list each of the functions you need, and then list the steps required to perform that function. Once that is done you can see what steps are common or similar to multiple functions so they can be shared. Planning to do that from the beginning makes for a smaller more modular and easier to write program.
  • TCTC Posts: 1,019
    edited 2014-05-27 04:53
    Thank you for the advice, I am going to give that a shot. Mostly what I am doing right now is, if I use a command more than once, I create a method for that command.
  • Mike GMike G Posts: 2,702
    edited 2014-05-27 06:36
    The menu system is relatively complex which can make maintenance a little tricky. I would, assign a unique ID number to each of the menu strings. When you're done you'll have a unique list of name and strings. Next assign a unique ID number to each menu functions. Create a parallel array that relates the string ID to the function ID. Create a CON block that relates the menu function ID to name that makes sense. Now you can refer to a menu functions by a CON name. The CON name is simply an ID. This ID can be used to index into the parallel array to find the display text.
  • TCTC Posts: 1,019
    edited 2014-05-27 07:31
    Mike G wrote: »
    The menu system is relatively complex which can make maintenance a little tricky. I would, assign a unique ID number to each of the menu strings. When you're done you'll have a unique list of name and strings. Next assign a unique ID number to each menu functions. Create a parallel array that relates the string ID to the function ID. Create a CON block that relates the menu function ID to name that makes sense. Now you can refer to a menu functions by a CON name. The CON name is simply an ID. This ID can be used to index into the parallel array to find the display text.

    I am sorry, but I am not quite understanding what you are explaining. Could you offer a simple example?
  • Mike GMike G Posts: 2,702
    edited 2014-05-27 10:32
    A data structure like this...
    CON
    	SystemConfig = 0
    	PIDConfig = 1
    	PGain = 2
    	IGain = 3
    	DGain = 4
    	Bias = 5
    	PGainEdit = 6
    	PGainClear = 7
    DAT
    	item0		byte "System Config",0
    	item1		byte "PID Config",0
    	item2   	byte "P Gain",0
    	item3   	byte "I Gain",0
    	item4   	byte "D Gain",0
    	item5   	byte "Bias",0
    	item6   	byte "Edit",0
    	item7   	byte "Clear",0
    	menu		long @item0,@item1,@item2,@item3,@item4,@item5,@item6,@item7 
    	function	byte 0,1,2,3,4,5,6,7 
    
    VAR
    	long	menuStack[4]
    

    Each menu item/function is enumerated and we have a stack to PUSH and POP the menu state.
  • TCTC Posts: 1,019
    edited 2014-05-27 13:09
    Mike G wrote: »
    A data structure like this...
    CON
    	SystemConfig = 0
    	PIDConfig = 1
    	PGain = 2
    	IGain = 3
    	DGain = 4
    	Bias = 5
    	PGainEdit = 6
    	PGainClear = 7
    DAT
    	item0		byte "System Config",0
    	item1		byte "PID Config",0
    	item2   	byte "P Gain",0
    	item3   	byte "I Gain",0
    	item4   	byte "D Gain",0
    	item5   	byte "Bias",0
    	item6   	byte "Edit",0
    	item7   	byte "Clear",0
    	menu		long @item0,@item1,@item2,@item3,@item4,@item5,@item6,@item7 
    	function	byte 0,1,2,3,4,5,6,7 
    
    VAR
    	long	menuStack[4]
    

    Each menu item/function is enumerated and we have a stack to PUSH and POP the menu state.

    I'm still not fully understanding, I think I am going to jump in to it head first. And see if I float or drown.
  • jazzedjazzed Posts: 11,803
    edited 2014-05-27 13:33
    It is a way of conveniently organizing display information. If you need to change a menu display, it's a one stop shop for editing what the menus say. This is better than scattering the display all over the code.

    Another code organization feature may be for each main menu item to have it's own .spin file.

    Many things can be done in code to make things easier in the long-run that may seem unnecessarily difficult to some in the short-run.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-27 13:40
    Mike G wrote: »
        menu        long @item0,@item1,@item2,@item3,@item4,@item5,@item6,@item7 
    
    

    Depending on how many items are in your list, you could do away with the list "menu" by using some code like this:
    PUB FindStringOrderPtr(firstStr, stringIndex)     
    '' Finds start address of one string in a list
    '' of string. "firstStr" is the address of 
    '' string #0 in the list. "stringIndex"
    '' indicates which of the strings in the list
    '' the method is to find.
    
    
      result := firstStr
      
      repeat while stringIndex    
        repeat while byte[result++]  
        stringIndex--
    
    
    

    To display item3 you'd use:
      term.str(FindStringOrderPtr(@item0, 3))
    
    
    I only use the above method on relative short lists that don't need to be accessed quickly.

    The above method is also limited to data structures not containing a zero (such as strings).
  • TCTC Posts: 1,019
    edited 2014-05-27 14:50
    jazzed wrote: »
    It is a way of conveniently organizing display information. If you need to change a menu display, it's a one stop shop for editing what the menus say. This is better than scattering the display all over the code.

    Another code organization feature may be for each main menu item to have it's own .spin file.

    I do like that idea. Right now, I have each part of the menu in its own method.

    Many things can be done in code to make things easier in the long-run that may seem unnecessarily difficult to some in the short-run.

    Yep, that's me. But I trust people on here, most of you have a lot more experience than me.

    Duane Degn wrote: »
    Depending on how many items are in your list, you could do away with the list "menu" by using some code like this:
    PUB FindStringOrderPtr(firstStr, stringIndex)     
    '' Finds start address of one string in a list
    '' of string. "firstStr" is the address of 
    '' string #0 in the list. "stringIndex"
    '' indicates which of the strings in the list
    '' the method is to find.
    
    
      result := firstStr
      
      repeat while stringIndex    
        repeat while byte[result++]  
        stringIndex--
    
    
    

    To display item3 you'd use:
      term.str(FindStringOrderPtr(@item0, 3))
    
    
    I only use the above method on relative short lists that don't need to be accessed quickly.

    The above method is also limited to data structures not containing a zero (such as strings).


    I am sooooo sorry, but I cant see why this is better.

    Would this not be the same?
    DAT
    
            RunProfile      BYTE    "Run Profile", 0
            LoadProfile     BYTE    "Load Profile", 0
            DeleteProfile   BYTE    "Delete Profile", 0
    
    
    
    PUB menu
    
      LoadString(RunProfile)
      LoadString(LoadProfile)
    
    
    PUB LoadString(StrPntr)
    
      Display.str(@StrPntr)
    
    

    I could be wrong on the "@" placement, but I think you get the idea.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-27 15:38
    TC wrote: »
    I am sooooo sorry, but I cant see why this is better.

    For one reason the address listed in the array "menu" need to be corrected because the compiler offset the RAM by 16 bytes in the top object.

    It's not necessarily better than the way Mike G illustrated (I use a similar technique with my robot remote code) but being able to access the strings with a index number is very useful when making menus.
    TC wrote: »
    Would this not be the same?

    DAT
    
            RunProfile      BYTE    "Run Profile", 0
            LoadProfile     BYTE    "Load Profile", 0
            DeleteProfile   BYTE    "Delete Profile", 0
    
    
    
    PUB menu
    
      LoadString(@RunProfile)
      LoadString(@LoadProfile)
    
    
    PUB LoadString(StrPntr)
    
      Display.str(StrPntr)
    
    

    TC wrote: »
    I could be wrong on the "@" placement, but I think you get the idea.

    Yes, I get the idea (and I fixed your "@" placements).

    No, it's not the same.

    In your code the method "menu" only displays those strings each time.

    However if you used Mike G's suggestion, your "menu" method would be more like this:
    DAT
    
            RunProfile      BYTE    "Run Profile", 0
            LoadProfile     BYTE    "Load Profile", 0
            DeleteProfile   BYTE    "Delete Profile", 0
            menuList        WORD @ RunProfile, @LoadProfile, @DeleteProfile
    
    
    
    PUB menu
      repeat
        LoadString(menuList[activeMenu])
        ' do stuff while in this particular menu
        ' wait for active menu to change
    
    
    PUB LoadString(StrPntr)
    
      Display.str(StrPntr + addressCorrection)
    

    The above code isn't anything close to the code you would really want to use but I was just trying to illustrate how having the active menu identifiable by some number can make constructing a menu easier to maintain in the long run.

    Or as jazzed said:
    jazzed wrote: »
    Many things can be done in code to make things easier in the long-run that may seem unnecessarily difficult to some in the short-run.

    Sorry, as I read back over this post, I feel like I've failed to express myself well. Hopefully another forum member can explain this concept better.
  • TCTC Posts: 1,019
    edited 2014-05-27 16:10
    Duane Degn wrote: »
    Yes, I get the idea (and I fixed your "@" placements).

    YAY :lol: I have to have the manual pulled up all the time when I program. It sucks having a very bad memory. But I refuse to let it hinder me.

    In your code the method "menu" only displays those strings each time.

    For my display, that is ok. The display will show the last thing it received, until it is changed.
    However if you used Mike G's suggestion, your "menu" method would be more like this:
    DAT
    
            RunProfile      BYTE    "Run Profile", 0
            LoadProfile     BYTE    "Load Profile", 0
            DeleteProfile   BYTE    "Delete Profile", 0
            menuList        WORD @ RunProfile, @LoadProfile, @DeleteProfile
    
    
    
    PUB menu
      repeat
        LoadString(menuList[activeMenu])
        ' do stuff while in this particular menu
        ' wait for active menu to change
    
    
    PUB LoadString(StrPntr)
    
      Display.str(StrPntr + addressCorrection)
    

    The above code isn't anything close to the code you would really want to use but I was just trying to illustrate how having the active menu identifiable by some number can make constructing a menu easier to maintain in the long run.

    It might not be close, but it helped. Now I understand it. Tell me if I am wrong. Lets say I want to add "EditProfile" between "RunProfile" And "LoadProfile", I would just have to do
    DAT
    
            EditProfile     BYTE    "Edit Profile", 0
            RunProfile      BYTE    "Run Profile", 0
            LoadProfile     BYTE    "Load Profile", 0
            DeleteProfile   BYTE    "Delete Profile", 0
            menuList        WORD @ RunProfile, @EditProfile, @LoadProfile, @DeleteProfile
    
    
    
    PUB menu
      repeat
        LoadString(menuList[activeMenu])
        ' do stuff while in this particular menu
        ' wait for active menu to change
    
    
    PUB LoadString(StrPntr)
    
      Display.str(StrPntr + addressCorrection)
    
    Sorry, as I read back over this post, I feel like I've failed to express myself well. Hopefully another forum member can explain this concept better.

    No you haven't, it is me that was having the problems. For things to click in my head, I have to see a benefit on doing it.
  • kwinnkwinn Posts: 8,697
    edited 2014-05-27 21:41
    TC wrote: »
    YAY :lol: I have to have the manual pulled up all the time when I program. It sucks having a very bad memory. But I refuse to let it hinder me.


    For my display, that is ok. The display will show the last thing it received, until it is changed.

    It might not be close, but it helped. Now I understand it. Tell me if I am wrong. Lets say I want to add "EditProfile" between "RunProfile" And "LoadProfile", I would just have to do
    DAT
    
            EditProfile     BYTE    "Edit Profile", 0
            RunProfile      BYTE    "Run Profile", 0
            LoadProfile     BYTE    "Load Profile", 0
            DeleteProfile   BYTE    "Delete Profile", 0
            menuList        WORD @ RunProfile, @EditProfile, @LoadProfile, @DeleteProfile
    
    
    
    PUB menu
      repeat
        LoadString(menuList[activeMenu])
        ' do stuff while in this particular menu
        ' wait for active menu to change
    
    
    PUB LoadString(StrPntr)
    
      Display.str(StrPntr + addressCorrection)
    



    No you haven't, it is me that was having the problems. For things to click in my head, I have to see a benefit on doing it.

    First you need to decide on the main and sub menus. Since you are using a small display you may have to step through the menu levels and choices, so keep each level to four or fewer choices if possible. What you have is a good start but I would change “Edit Profile” to “Add/Edit Profile”. Once a main menu item is selected it presents a sub menu similar to the suggestions below.

    - Add/Edit Profile > New Profile, Profile 1, Profile 2, Profile 3, ...Profile n

    Selecting New Profile would create a default profile and ask for a profile name before proceeding to the edit profile functions.

    Selecting one of the existing profiles would allow editing of the selected profile.

    - Run Profile > Profile 1, Profile 2, Profile 3, ...Profile n

    Starts executing the selected profile. May want to display “Press x to start run” before starting the profile.

    - Load Profile > Profile 1, Profile 2, Profile 3, ...Profile n

    Loads the profile into ram? What then?

    - Delete Profile > Profile 1, Profile 2, Profile 3, ...Profile n

    Deletes or marks the profile as deleted. Should have “ARE YOU SURE YOU WANT TO DELETE Profile x” Y/N


    Having Run and Load seems to be a bit redundant. Would you want to change some parameters for a single run without saving the changes?
  • TCTC Posts: 1,019
    edited 2014-05-28 04:56
    kwinn wrote: »
    First you need to decide on the main and sub menus. Since you are using a small display you may have to step through the menu levels and choices, so keep each level to four or fewer choices if possible. What you have is a good start but I would change “Edit Profile” to “Add/Edit Profile”. Once a main menu item is selected it presents a sub menu similar to the suggestions below.

    I like that idea. I dont see me editing profiles that much, but if I do I would just Add a new profile.

    - Add/Edit Profile > New Profile, Profile 1, Profile 2, Profile 3, ...Profile n

    Selecting New Profile would create a default profile and ask for a profile name before proceeding to the edit profile functions.

    I was thinking the same thing. That way it would confirm I wanted to add a new profile.

    Selecting one of the existing profiles would allow editing of the selected profile.

    - Run Profile > Profile 1, Profile 2, Profile 3, ...Profile n

    Starts executing the selected profile. May want to display “Press x to start run” before starting the profile.

    Instead of "Press x to start" I am going to use a stand alone button that has a duel color LED in it. The button would be for starting and stopping the oven. Green would be start, and red would be stop. The button is a SPDT type. I am using both the NO and the NC of the button. The NO is for starting the oven (makes sure the button is pressed), and the NC is for stopping the oven(Faster response)

    - Load Profile > Profile 1, Profile 2, Profile 3, ...Profile n

    Loads the profile into ram? What then?

    I have not figured out all the details yet, mostly because I have never done anything like this yet, and I have to take things step by step to figure them out.

    But what my plan is, When a profile is selected to be loaded and ran, A pointer to that profile would be saved in the upper side of the eeprom(so I don't have to keep selecting the same profile every time I turn on the oven), the first zone data would be loaded to RAM and ran. Once the first zone is done, the next zone is loaded and ran. That will continue until there are no more zones in the current profile. I figure by doing it that way, I would not have to worry about how many zones there are in the selected profile. And since all the zone data are the same, I would only have to have the same amount of RAM for each zone.

    - Delete Profile > Profile 1, Profile 2, Profile 3, ...Profile n

    Deletes or marks the profile as deleted. Should have “ARE YOU SURE YOU WANT TO DELETE Profile x” Y/N

    I agree with you there. But I was going to use the stand alone button for "YES" and the encoder select for "NO", just to make sure I do not select "YES" by mistake.

    Having Run and Load seems to be a bit redundant.

    The "Run" is to run the current/last profile, and the "Load" is to change the current profile to a different profile.

    Would you want to change some parameters for a single run without saving the changes?

    I dont really know, I never put any thought into that. I was just assuming that if I wanted to change something I would just edit and save the profile. Then if I use the changes, I would just create a new profile that has the changes.


    I am still learning, and figuring things out. A couple things have changed because members have given me better ideas.
  • Mike GMike G Posts: 2,702
    edited 2014-05-28 05:06
    I want to make sure you understand a profile and a menu are different things. In my opinion, profiles should be saved to an SD card where each profile has a unique and specific name. When reading profile data from the SD card, overlay the profile over a memory data structure or construct the data structure.

    First, get your menu system working then worry about the control logic.
  • TCTC Posts: 1,019
    edited 2014-05-28 05:31
    Mike G wrote: »
    I want to make sure you understand a profile and a menu are different things.

    I think I do.
    Profile = what the oven uses for temperature and time settings

    menu = what the user uses to select, edit, and change parameters of the oven

    In my opinion, profiles should be saved to an SD card where each profile has a unique and specific name. When reading profile data from the SD card, overlay the profile over a memory data structure or construct the data structure.

    That is what I wanted to do. The SD card has more space available, and that leaves me more room on the upper 32k for menu data.

    First, get your menu system working then worry about the control logic.

    Agreed, I figured the menu would take the most time, and effort to do.
  • kwinnkwinn Posts: 8,697
    edited 2014-05-28 18:37
    TC wrote: »
    I like that idea. I dont see me editing profiles that much, but if I do I would just Add a new profile.

    I was thinking the same thing. That way it would confirm I wanted to add a new profile.

    Since the only difference between adding a new profile and editing an existing one is providing a name for the new one it makes perfect sense to combine them, and it saves a bit of menu and memory space.
    Instead of "Press x to start" I am going to use a stand alone button that has a duel color LED in it. The button would be for starting and stopping the oven. Green would be start, and red would be stop. The button is a SPDT type. I am using both the NO and the NC of the button. The NO is for starting the oven (makes sure the button is pressed), and the NC is for stopping the oven(Faster response)

    Having separate buttons for those functions is a great time saver.
    I have not figured out all the details yet, mostly because I have never done anything like this yet, and I have to take things step by step to figure them out.

    But what my plan is, When a profile is selected to be loaded and ran, A pointer to that profile would be saved in the upper side of the eeprom(so I don't have to keep selecting the same profile every time I turn on the oven), the first zone data would be loaded to RAM and ran. Once the first zone is done, the next zone is loaded and ran. That will continue until there are no more zones in the current profile. I figure by doing it that way, I would not have to worry about how many zones there are in the selected profile. And since all the zone data are the same, I would only have to have the same amount of RAM for each zone.

    Both excellent ways to go at this. Divide it into small steps then solve them one at a time. Since many of the pieces will be similar you can use what you learn from one step to solve next one.
    I agree with you there. But I was going to use the stand alone button for "YES" and the encoder select for "NO", just to make sure I do not select "YES" by mistake.

    Another safety measure would be to mark the profile as deleted by changing the first character of the name to an asterisk (like msdos did) and leave the rest intact until the space was needed. That makes it possible to to recover an accidentally deleted profile.
    The "Run" is to run the current/last profile, and the "Load" is to change the current profile to a different profile.

    Ah, that makes sense.
    I dont really know, I never put any thought into that. I was just assuming that if I wanted to change something I would just edit and save the profile. Then if I use the changes, I would just create a new profile that has the changes.

    I am still learning, and figuring things out. A couple things have changed because members have given me better ideas.

    Being able to change values for a single run without actually changing the profile might be handy for troubleshooting or optimization. In heat treating metal parts being able to change the soak time was very useful. It may or may not be of any use for this application.
  • kwinnkwinn Posts: 8,697
    edited 2014-05-28 23:44
    After letting my previous suggestions settle to the back of my mind for a while I wonder if that might be the bass ackward way of doing things. Since you will always have to choose a new or existing protocol to work on perhaps that should be the main menu.

    Select “New” and you would always proceed to the edit function. After editing you would be presented with the “Save”, “Run” or “Cancel” functions. If you choose to run the function you would be presented with the “Save”, “Run” or “Cancel” functions again.

    Select an existing protocol and you would automatically load that protocol and be presented with the “Edit”, “Run” or “Delete” functions.

    This would be the ultimate in brevity and memory savings. The program would page through the “New” and existing protocols in the SD card to create the menu so no hub space would be needed to store the protocol names. The only hub memory required other than the program would be for four protocol names and the selected Protocol parameters.
  • TCTC Posts: 1,019
    edited 2014-05-29 03:48
    kwinn wrote: »
    Having separate buttons for those functions is a great time saver.

    Agreed, but I do want to keep it simple and try to keep it clean. That is why I changed the incandescent light bulb that was in the switch, to a dual color LED. I was able to turn 1 button into 2 buttons by adding the LED.

    Another safety measure would be to mark the profile as deleted by changing the first character of the name to an asterisk (like msdos did) and leave the rest intact until the space was needed. That makes it possible to to recover an accidentally deleted profile.

    Last time I used MS DOS, I was a kid. And even then I never paid to much attention to what happened when files were deleted. I will go that route later on.

    Being able to change values for a single run without actually changing the profile might be handy for troubleshooting or optimization. In heat treating metal parts being able to change the soak time was very useful. It may or may not be of any use for this application.

    I guess you are right. What I could do is, add a section to the "RUN" screen that allows me to change values on the fly.

    After letting my previous suggestions settle to the back of my mind for a while I wonder if that might be the bass ackward way of doing things.

    Hahaha.... Welcome to my world, I do that all the time. Mostly when I just lay down for bed.

    If you choose to run the function you would be presented with the “Save”, “Run” or “Cancel” functions again.

    I want to keep the "RUN" function simple (K.I.S.S). My goal is, when the oven is powered up, the "Run Profile" (with the last profiles name) function is loaded and on the screen. The Green LED button would be flashing to indicate to "push me to start". I push the button, and the oven starts. No menus to go through, nothing to change, just start. But if I wanted to change, edit, delete, or anything, I would turn the encoder knob at the "Run Profile" screen.

    I would be adding a flashing arrow indicator on the right side of the "Run Profile"( RunProfile "->" ) to show that there are more options. And with the Noritake 24x6 display, having individual characters flash just takes sending 2 bytes ($1B, $42) before I send the string data, then send 2 more bytes ($1B, $41) to turn off the flash for the rest of the screen.

    This would be the ultimate in brevity and memory savings. The program would page through the “New” and existing protocols in the SD card to create the menu so no hub space would be needed to store the protocol names. The only hub memory required other than the program would be for four protocol names and the selected Protocol parameters.

    That is exactly my plan. I could not see using up hub memory to load every part of the selected profile, when I could only use one zone worth of data at a time.

    For the SD naming I was thinking of just doing the first 8 characters of the profile name, with a .PRO extension. That way, I could also use the computer to edit, add, delete profiles. Again K.I.S.S.

    IE
    General Profile = GENERAL_.PRO
    Lead Free = LEAD_FRE.PRO
    Leaded = LEADED__.PRO
  • kwinnkwinn Posts: 8,697
    edited 2014-05-29 19:11
    Sounds like you have everything under control.
  • TCTC Posts: 1,019
    edited 2014-05-29 19:26
    kwinn wrote: »
    Sounds like you have everything under control.

    I really hope so. Thanks
Sign In or Register to comment.