Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 18:04 28 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Help me write a function...

Author Message
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 03:14pm 25 Dec 2013
Copy link to clipboard 
Print this post

Hi folks.


For those of you finished with Christmas day, and want to stretch your little grey cells, I am trying to work out how I can make the following loop into a function, that I can call from the main code.

Here is the code which is repeated several times in the main code:

[code]
do
timer=0
flag=0
print @(50,170) "_ "
do
k$=inkey$
loop until k$<>"" or timer>DEFAULT
if timer>9000 then
out$=""
goto start
endif
if asc(k$)>=0 and asc(k$)<=7 or asc(k$)>=9 and asc(k$)<=12 then
out$=""
goto start
endif
if asc(k$)>=14 and asc(k$)<=31 or asc(k$)>=128 and asc(k$)<=156 then
out$=""
goto start
endif
if asc(k$)=13 then
If out$="" Then GoTo start
lin$=out$
flag=1
endif
endif
if asc(k$)=8 and len(out$)>=1 then
out$=left$(out$,len(out$)-1)
else
out$=out$ + k$
endif
if len(out$)=1 then
if asc(out$)=8 then out$=""
endif
if flag=1 then
out$=""
exit
endif
loop
[/code]

This routine times out and goes back to the main menu, if no key is pressed within ten seconds, or whatever DEFAULT is set to.

It also deals with backspace etc, and builds a string with the results of your keypresses, for processing by the following code, when ENTER is pressed.

Most of you will easily see what is going on in the code - let me know if anyone does not follow it, and I will explain it some more.

What I would like to do, is make this routine a function which I can call from the main code, rather then repeating the code LOTS of times within the main program.

IT IS WORKING FINE LIKE THIS, but multipule copies of the code will be gobbling up lots of memory, so to try to streamline the process, the use of a function was suggested by other members.

This routine was built on by a couple of other members here aswell as myself - I will post a link to the thread about it, once I find it....

EDIT: Found links.
Building a string from keypresses
Show cursor during inputs

My problem is in trying to understand how I need to "Format" the function, and what I need to pass to it, and how to understand what comes back to the main code.

I have read about the FUNCTION command in the manual, but cannot understand it, so I am hoping that others here can prod me in the right direction.

Thanks for any help, and merry Christmas. Edited by Grogster 2013-12-27
Smoke makes things work. When the smoke gets out, it stops!
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 11:52pm 25 Dec 2013
Copy link to clipboard 
Print this post

First step you could make it into a sub routine. After that you could try for a function if still needed.

Put a label (GetMyInput:) on the front of it. Put an End Sub at the bottom of it. Convert each of the GoTo Start into Exit Sub, rinse and debug. At the point where your code used to be use a GoSub GetMyInput (or whatever label you choose).

Merry Christmas

edit: this post made me into a guru, lol.

edit again: Your code for the timeouts is a bit weird.
loop until k$<>"" or timer>DEFAULT
if timer>9000 then

if DEFAULT > 9000 then you will exit on timeout but if DEFAULT =< 9000 then you will process a timed out null entry. You may end up with some odd results.Edited by BobD 2013-12-27
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 12:05pm 26 Dec 2013
Copy link to clipboard 
Print this post

I will try your idea, and study the sub/end sub commands a bit more.

I will do more reading.

As to the timer>9000 - that is a small bug - thanks for pointing it out. It does not stop the code from running, but that line should be timer>=default - I will correct it.

I will upload my experiments here as I go.

Merry Christmas, Guru. Edited by Grogster 2013-12-27
Smoke makes things work. When the smoke gets out, it stops!
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 04:32pm 26 Dec 2013
Copy link to clipboard 
Print this post

OK, thanks primarily to BobD for the prod, I have come up with a defined subroutine which appears to work.

Before calling the sub, the following code is run:

[code]
GETIN (50,170,DEFAULT,0)
if GIFLAG<>0 then goto start
[/code]

GETIN is the routine(contraction of GET INPUT), values passed to the subroutine are cursor position X, cursor position Y, Timeout period, show keystrokes or not.

The last one is just a 1 or 0 switch - 1=show keystrokes on the screen, 0=hide them.

Now, the subroutine follows thus:

[code]
SUB GETIN (CX,CY,TP,SK)
do
timer=0
flag=0
giflag=0
if SK=1 then
print @(CX,CY) out$ + "_ "
else
print @(CX,CY) "_ "
endif
do
k$=inkey$
loop until k$<>"" or timer>TP
if timer>=TP then
out$=""
giflag=1
exit sub
endif
if asc(k$)>=0 and asc(k$)<=7 or asc(k$)>=9 and asc(k$)<=12 then
out$=""
giflag=1
exit sub
endif
if asc(k$)>=14 and asc(k$)<=31 or asc(k$)>=128 and asc(k$)<=156 then
out$=""
giflag=1
exit sub
endif
if asc(k$)=13 then
If out$="" Then exit sub
lin$=out$
flag=1
endif
endif
if asc(k$)=8 and len(out$)>=1 then
out$=left$(out$,len(out$)-1)
else
out$=out$ + k$
endif
if len(out$)=1 then
if asc(out$)=8 then out$=""
endif
if flag=1 then
out$=""
giflag=0
exit
endif
loop
end sub
[/code]

giflag keeps a track of if the subroutine has exited correctly, or if there has been a timeout or illegal keypress etc. this flag has to be zero when the code returns from the sub. If it is not, then the code jumps back to the main menu.

All this seems to be working well.

I have only ported this to one test area of the code, but will now port this to the rest of the code - I should save a bit of memory in the process, as this big routine was repeated quite a bit in the code, anywhere I needed keyboard input from the user, so I am hoping this will reduce the memory consumption - I will post back.

Current code size is 30976 bytes.


Edited by Grogster 2013-12-28
Smoke makes things work. When the smoke gets out, it stops!
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 07:23pm 26 Dec 2013
Copy link to clipboard 
Print this post

Graeme,
good to see it working. I see I didn't quite get the start of the sub correct. Sorry, I lack a bit of practice and I didn't have time to look it up yesterday. Err, actually I was also having a bit of difficulty reading. The screen kept getting blurred. I don't remember what caused that.
Bob
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 09:24pm 26 Dec 2013
Copy link to clipboard 
Print this post

  BobD said  I see I didn't quite get the start of the sub correct. Sorry, I lack a bit of practice and I didn't have time to look it up yesterday.


No worries - I knew what you were getting at.

  BobD said   Err, actually I was also having a bit of difficulty reading. The screen kept getting blurred. I don't remember what caused that.
Bob


Vodka?

Smoke makes things work. When the smoke gets out, it stops!
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 09:58pm 26 Dec 2013
Copy link to clipboard 
Print this post

Ported code is 19922 bytes - I have saved 11054 bytes - 11k of memory saved by making this a subroutine.

Well worth it.
Smoke makes things work. When the smoke gets out, it stops!
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 11:22pm 26 Dec 2013
Copy link to clipboard 
Print this post

  Grogster said  
Vodka?


I'm sticking to my story; I don't remember, lol.
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 12:10am 27 Dec 2013
Copy link to clipboard 
Print this post

Here is my interpretation (untested, just wrote it here in a post).
It doesn't use any global variables.
[code]
FUNCTION InputLine$ (ScreenX, ScreenY, AllowedCharacters$, Echo, ExitOnNotAllowedCharacters, MaxLength, Timeout)
LOCAL Line$

Line$ = ""
timer = 0
do
if Echo then
print @(ScreenX, ScreenY) Line$ + "_";
else
print @(ScreenX, ScreenY) "_";
endif

do
key$ = inkey$
loop until key$ <> "" or timer > Timeout

if timer > Timeout then
' Here you could give Line$ a special value
' that is not available from the keyboard.
' Like Line$ = chr(1) to signal that a timeout occured
Line$ = ""
exit
endif

if key$ = chr$(8) then
if len(Line$) = 1 then Line$=""
if len(Line$) > 1 then Line$ = left(Line$,len(Line$)-1)
endif

if key$ = chr(13) then
exit
endif


if instr(AllowedCharacters$, key$) = 0 then
if ExitOnNotAllowedCharacters then
' Comment the next line if you want to keep
' what was entered until a NotAllowedCharacter occured.
' Or you could use Line$ = chr$(2) to signal that a
' not allowed character occured.
Line$ = ""
exit
end if
else
if len(Line$) < MaxLength then
Line$ = Line$ + key$
endif
endif
loop

InputLine$ = Line$
END FUNCTION
[/code]

if you use it many times it is better to have the AllowedCharacters$ defined at the start of your program to save on memory requirement.
[code]
Numbers$ = "0123456789"
Text$ = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Special$ = "!@#$%^&*()_+"
SuperSpecial$ = "{}[]|\/?.>,<;:'" + chr$(34)
AllowAll$ = Number$ + Text$ + Special$ + SuperSpecial$
[/code]

You can then use it wherever in your program like this:
[code]
Answer$ = InputLine$(10, 8, Numbers$, true, true, 1, 5000)
[/code]

And if you really want to save memory:
[code]
FUNCTION InputLine$ (X, Y, A$, E, N, M, T)
LOCAL L$
L$ = "" : timer = 0
do
if E then
print @(X, Y) L$ + "_";
else
print @(X, Y) "_";
endif
do
k$ = inkey$
loop until k$ <> "" or timer > T
if timer > T then
L$ = "": exit
endif

if k$ = chr$(8) then
if len(L$) = 1 then L$=""
if len(L$) > 1 then L$ = left(L$,len(L$)-1)
endif

if k$ = chr(13) then exit
if instr(A$, k$) = 0 then
if N then
L$ = ""
exit
end if
else
if len(L$) < M then
L$ = L$ + k$
endif
endif
loop
InputLine$ = L$
END FUNCTION
[/code]

If you need to test in your program that a timeout occured change the line L$ = "" to L$ = chr$(1). You can then test for it.

[code]
answer$=InputLine$(10, 8, Numbers$, true, true, 1, 5000)
if answer$ = chr$(1) then
' Timeout occured
' do your stuff
endif
[/code]

Edited by TZAdvantage 2013-12-28
Microblocks. Build with logic.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 12:29am 27 Dec 2013
Copy link to clipboard 
Print this post

WOW, TZ - you really know how to code.

I will have to read that a few times to understand it.

Nice work. I will read this a few times to comprehend it.
Smoke makes things work. When the smoke gets out, it stops!
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 12:37am 27 Dec 2013
Copy link to clipboard 
Print this post

You might want to add
[code]
timer = 0
[/code]
right after the timeout test.
This will allow the user time after each keystroke, not a total time to be in the menu.
Depends on what you need.
Microblocks. Build with logic.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 01:44pm 27 Dec 2013
Copy link to clipboard 
Print this post

Thanks, TZ, but it does that already - great minds think alike.

Sample from my code above:

[code]
SUB GETIN (CX,CY,TP,SK)
do
timer=0
flag=0
giflag=0
if SK=1 then
print @(CX,CY) out$ + "_ "
else
print @(CX,CY) "_ "
endif
[/code]

After every keypress(controlled by the master DO/LOOP), the timer is reset, so as long as the user types SOMETHING, the timer is always being reset. This gives the user practically unlimited time to type, provided that they type something within the default time-out period.

EDIT: OH - I think you mean in YOUR version of the code... (add timer=0)Edited by Grogster 2013-12-29
Smoke makes things work. When the smoke gets out, it stops!
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 08:00pm 27 Dec 2013
Copy link to clipboard 
Print this post

One more suggestion.

There are a fair number of parameters being passed to TZ's function. If I recall correctly it's possible to test for an empty parameter so you could add code at the start of the function (before the Do command) to test for empty parameters and replace them with default values. That would make the calling of the function simpler and neater.

BTW. I agree with Grogster. Nice code.

James
My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024