Suppose I want an Applesoft (Microsoft) BASIC program to do something for a certain amount of time as measured in seconds or minutes. FOR-NEXT loops don't align to any real increment -- they just count based on how fast the processor can go, right? If so, then how do you make something happen for a time amount? ------------------------- Evan Koblentz, director Vintage Computer Federation A 501(c)3 educational non-profit Evan@vcfed.org (646) 546-9999 www.vcfed.org facebook.com/vcfederation twitter.com/vcfederation
Reading the documentation for Applesoft BASIC, there is no timer, no sleep and no internal clock.
From a fairly reasonable sounding source:
The Apple ][ and ][+ don't have any built-in hardware timers, so you generally have to do them in software. This typically means doing carefully timed delay loops which will execute in a known amount of time. This is tricky if the computer might have an accelerator, unless you use a well defined timing routine which behaves predictably in the presence of an accelerator. The Apple IIe and later models have a hardware input which can be used to detect screen refresh, but you have to poll it fast enough to ensure you don't miss the signal. It isn't useful for long term timing if you want to do any disk I/O. You also need to know the screen refresh rate (50 or 60 Hz, depending on the model and settings) if you want to use it for general purpose timing. If you have a real time clock installed, it may provide some useful timing features. From: vcf-midatlantic <vcf-midatlantic-bounces@lists.vintagecomputerfederation.org> on behalf of Evan Koblentz via vcf-midatlantic <vcf-midatlantic@lists.vintagecomputerfederation.org> Sent: Wednesday, May 24, 2017 1:02 AM To: Vcf Cc: Evan Koblentz Subject: [vcf-midatlantic] Computing time in BASIC Suppose I want an Applesoft (Microsoft) BASIC program to do something for a certain amount of time as measured in seconds or minutes. FOR-NEXT loops don't align to any real increment -- they just count based on how fast the processor can go, right? If so, then how do you make something happen for a time amount? ------------------------- Evan Koblentz, director Vintage Computer Federation A 501(c)3 educational non-profit Evan@vcfed.org (646) 546-9999 www.vcfed.org facebook.com/vcfederation twitter.com/vcfederation
Thanks everyone. Interesting stuff. Here's something I do not understand. Lego's modified version of Logo has a command, COUNTER, which they say increments in tenths of a second. One of their sample programs runs the counter to 600 to give you a minute of something happening (a motor spinning). I didn't time it against a real clock, but, how could this work? The same Logo environment disk runs identically in anything from a ][+ through a GS. (My demo uses a Laser 128 as you'll recall.)
It's a good question. With only Google as my guide (I'm admittedly no Apple expert!) it appears that Apple introduced a display refresh signal with the IIc model (50 or 60 Hz, depending on settings) and a true real time clock beginning with the IIgs. Since the Laser is apparently a IIc clone, perhaps it's using the display clock? -Glenn Sent from my iPhone
On May 24, 2017, at 10:10 AM, Evan Koblentz via vcf-midatlantic <vcf-midatlantic@lists.vintagecomputerfederation.org> wrote:
Thanks everyone. Interesting stuff.
Here's something I do not understand. Lego's modified version of Logo has a command, COUNTER, which they say increments in tenths of a second. One of their sample programs runs the counter to 600 to give you a minute of something happening (a motor spinning). I didn't time it against a real clock, but, how could this work? The same Logo environment disk runs identically in anything from a ][+ through a GS. (My demo uses a Laser 128 as you'll recall.)
It might be worth looking at call -856, which appears to allow for arbitrary time delay on the Apple II:
From https://mirrors.apple2.org.za/ground.icaen.uiowa.edu/Collections/1WSW/MEGA.P...
$FCA8....64680....CALL -856......WAITs; executes time delay; set delay value (dly) to the accumulator (address 69 or $45) before CALLing; the delay time (in seconds) can be found using this equation: delay=(0.5*(5*(dly*dly)+27*dly+26))/10000 Devin On Wed, May 24, 2017 at 11:28 AM, Glenn Roberts via vcf-midatlantic <vcf-midatlantic@lists.vintagecomputerfederation.org> wrote:
It's a good question. With only Google as my guide (I'm admittedly no Apple expert!) it appears that Apple introduced a display refresh signal with the IIc model (50 or 60 Hz, depending on settings) and a true real time clock beginning with the IIgs. Since the Laser is apparently a IIc clone, perhaps it's using the display clock?
-Glenn
Sent from my iPhone
On May 24, 2017, at 10:10 AM, Evan Koblentz via vcf-midatlantic <vcf-midatlantic@lists.vintagecomputerfederation.org> wrote:
Thanks everyone. Interesting stuff.
Here's something I do not understand. Lego's modified version of Logo has a command, COUNTER, which they say increments in tenths of a second. One of their sample programs runs the counter to 600 to give you a minute of something happening (a motor spinning). I didn't time it against a real clock, but, how could this work? The same Logo environment disk runs identically in anything from a ][+ through a GS. (My demo uses a Laser 128 as you'll recall.)
-- Devin J. Heitmueller http://www.devinheitmueller.com
On Wed, May 24, 2017 at 1:02 AM, Evan Koblentz via vcf-midatlantic < vcf-midatlantic@lists.vintagecomputerfederation.org> wrote:
Suppose I want an Applesoft (Microsoft) BASIC program to do something for a certain amount of time as measured in seconds or minutes. FOR-NEXT loops don't align to any real increment -- they just count based on how fast the processor can go, right? If so, then how do you make something happen for a time amount?
On Wed, May 24, 2017 at 10:10 AM, Evan Koblentz via vcf-midatlantic < vcf-midatlantic@lists.vintagecomputerfederation.org> wrote:
Thanks everyone. Interesting stuff. Here's something I do not understand. Lego's modified version of Logo has a command, COUNTER, which they say increments in tenths of a second. One of their sample programs runs the counter to 600 to give you a minute of something happening (a motor spinning). I didn't time it against a real clock, but, how could this work? The same Logo environment disk runs identically in anything from a ][+ through a GS. (My demo uses a Laser 128 as you'll recall.)
The Apple ][ and Applesoft Basic doesn't have an exact counter/timing mechanism built-in. There's only a couple of software methods available in a stock Apple ][ eg #1. For/Next loop -- you know already how to do this #2. Timer [software/Kernal Rom] I mentioned this to you before [see my old email with the sample code in Basic from 4/14/17] Even though this is still software controlled, this is incremented using the Applesoft Kernel machine code, So this is more accurate than the For/Next loop in BASIC In Zero page memory, you have 16bit binary counter, decimal 0 to 65535 at locations $4E, $4F, in basic you would use PEEK(78), PEEK(79) Then, there's the Hardware methods which include such cards as the popular Mountain Clock/Calendar card. This is just a glorified Timer with the values formatted into seconds,minutes, day,date,years, etc and with battery backup. But even if you did use that card, you still have to rely on software to keep track of the time, to keep checking the time in a software loop to find the elapsed time, either 1 sec or 10 sec. So even thought that Clock card is accurate, your added Basic code makes it less accurate. So, The Lego version of Logo is a much different beast than Applesoft Basic. The primary difference is that Lego supports Interrupts and Applesoft Basic doesn't [not without a kludge of assembly code]. Since you keep mentioning these Logo commands, I suppose you are trying this in combination with your Lego robot project using the Lego 9767 Apple card with the Lego 9750 controller box. This is also related to the SETPOWER command you mentioned a while back and there's several other Logo Timer commands. I haven't tried any programming with the Lego version of Logo on my Apple ][ yet. But I suspect this is making use of the Timer built into the 6522 chip on your Lego 9767 card. It's th eonly source of Interrupts in that Hardware. Since they have to assume you don't have a Clock/Calendar card or any other 3rd party card. And it's the only way to get accurate timing measurements using those Commands and with that card. There's the Interrupt signal pin.21 on the 6522 wired to the slot on your Apple ][. And I bet this is how they get the accurate timing measurements with the COUNTER command and the PWM Motor Speed control with the SETPOWER command. This is besides the generic Timer commands in there. I would have to install that Lego version of Logo to verify this and check it with my o'scope. But, the problem with Applesoft Basic as I mentioned above is that it does not support Interrupts. Not without a convoluted mix of assembly code to switch back and forth between your BASIC code and assembly whenever the 6502 receives an interrupt from the 6522. Because the assembly code has to keep track of your Basic code to know which line it's supposed to return and execute next. The only proper way to acknowledge and service the interrupt signal is in assembly code. I would suggest sticking with that Counter I mentioned in zero page memory at $4E,$4F -- PEEK(78), PEEK(79) Dan
On Wed, May 24, 2017 at 12:10 PM, Dan Roganti <ragooman@gmail.com> wrote:
On Wed, May 24, 2017 at 1:02 AM, Evan Koblentz via vcf-midatlantic < vcf-midatlantic@lists.vintagecomputerfederation.org> wrote:
Suppose I want an Applesoft (Microsoft) BASIC program to do something for a certain amount of time as measured in seconds or minutes. FOR-NEXT loops don't align to any real increment -- they just count based on how fast the processor can go, right? If so, then how do you make something happen for a time amount?
On Wed, May 24, 2017 at 10:10 AM, Evan Koblentz via vcf-midatlantic < vcf-midatlantic@lists.vintagecomputerfederation.org> wrote:
Thanks everyone. Interesting stuff. Here's something I do not understand. Lego's modified version of Logo has a command, COUNTER, which they say increments in tenths of a second. One of their sample programs runs the counter to 600 to give you a minute of something happening (a motor spinning). I didn't time it against a real clock, but, how could this work? The same Logo environment disk runs identically in anything from a ][+ through a GS. (My demo uses a Laser 128 as you'll recall.)
The Apple ][ and Applesoft Basic doesn't have an exact counter/timing mechanism built-in. There's only a couple of software methods available in a stock Apple ][ eg #1. For/Next loop -- you know already how to do this #2. Timer [software/Kernal Rom] I mentioned this to you before [see my old email with the sample code in Basic from 4/14/17] Even though this is still software controlled, this is incremented using the Applesoft Kernel machine code, So this is more accurate than the For/Next loop in BASIC In Zero page memory, you have 16bit binary counter, decimal 0 to 65535 at locations $4E, $4F, in basic you would use PEEK(78), PEEK(79)
[SNIP]
I would suggest sticking with that Counter I mentioned in zero page memory at $4E,$4F -- PEEK(78), PEEK(79) Dan
might as well post the sample code in here too so you just need the decimal value, this is a 16bit binary counter, so in decimal it's 0 to 65535 T1 = PEEK(78) + 256 * PEEK(79) You'll have to use this calibration test code and a stopwatch to find how many ticks of that Counter will get 1sec of time eg 10 T1 = PEEK(78) + 256 * PEEK(79) 20 FOR J=1 TO 1000:NEXT J 30 T2 = PEEK(78) + 256 * PEEK(79) 40 PRINT T2-T1 50 END Then adjust J for 1sec before the PRINT displays the answer But it will wrap around, cause this Counter is non-stop so sometimes T2-T1 will be negative just convert it back to positive if T2 <0 by multiplying this with -1 When you add this to your robot code, you'll have to adjust J again, Because the extra lines from your robot code will create more delay But at least you'll be in the ballpark, just calibrate this again using your robot code and a stopwatch to tweak the measurement closely. That difference will now be your constant for 1sec of time Now you can use this measurement for things such as travel time in the robot But there's one slight glitch to work around, [on live hardware - some emulators don't replicate this entirely] I know you like to use RUN "filename" most of the times But for some reason that Counter is frozen at a fixed value, basically from the time you Power On the computer. So just do this first, LOAD "filename", then RUN And so the counter will be free running for as long as the computer is On Dan -- _ ____ / \__/ Scotty, We Need More Power !! \_/ _\__ Aye, Cap'n, but we've only got 80 col's !!
While Dan's point about still needing software to monitor a hardware clock and the inherent limitations of that would still hold true, there have been solutions for the iic and laser form factor machines. Bill D. mentioned it earlier. A no slot clock (clock and battery on a chip) I know in the past Henry Courbis sold one through his reactive micro site. I don't k ow if that's still the case but it's something to consider. His specifically worked on the iic (without memory expansion card installed) and on the laser 128.....since obviously the card options like the mountain or Timemaster cards cannot work with a laser 128. Tony
On Wed, May 24, 2017 at 1:23 PM, Tony Bogan <thebogans@mac.com> wrote:
While Dan's point about still needing software to monitor a hardware clock and the inherent limitations of that would still hold true, there have been solutions for the iic and laser form factor machines.
Bill D. mentioned it earlier. A no slot clock (clock and battery on a chip)
I know in the past Henry Courbis sold one through his reactive micro site. I don't k ow if that's still the case but it's something to consider. His specifically worked on the iic (without memory expansion card installed) and on the laser 128.....since obviously the card options like the mountain or Timemaster cards cannot work with a laser 128.
Tony
About the Clock card, I really don't think it matters which form you install, either a card or no-slot version. You would still need to access the Clock/Calendar with your basic code twice each time to measure the elapsed time. And since Applesoft Basic is an Interpeter, the Timing errors can aggregate all together after running after a few min So sometimes you might get 0.8sec or other times you might get 1.2sec depending how many lines of Basic code or which branch was taken in the code. Dan
My point was the laser 128 does not have any internal slots and a card made for the Apple II cannot be installed in the machine. There is the expansion port but that is already being used by the Lego card. Tony Sent from my iPhone
On May 24, 2017, at 2:04 PM, Dan Roganti <ragooman@gmail.com> wrote:
On Wed, May 24, 2017 at 1:23 PM, Tony Bogan <thebogans@mac.com> wrote: While Dan's point about still needing software to monitor a hardware clock and the inherent limitations of that would still hold true, there have been solutions for the iic and laser form factor machines.
Bill D. mentioned it earlier. A no slot clock (clock and battery on a chip)
I know in the past Henry Courbis sold one through his reactive micro site. I don't k ow if that's still the case but it's something to consider. His specifically worked on the iic (without memory expansion card installed) and on the laser 128.....since obviously the card options like the mountain or Timemaster cards cannot work with a laser 128.
Tony
About the Clock card, I really don't think it matters which form you install, either a card or no-slot version. You would still need to access the Clock/Calendar with your basic code twice each time to measure the elapsed time. And since Applesoft Basic is an Interpeter, the Timing errors can aggregate all together after running after a few min So sometimes you might get 0.8sec or other times you might get 1.2sec depending how many lines of Basic code or which branch was taken in the code. Dan
There is the expansion port but that is already being used by the Lego card.
The expansion enclosure supports two cards. We don't have that part, so I attached the Lego card directly where the enclosure attaches. Presumably there are people on this list who can make us a doubler thingamajig.
On May 24, 2017, at 2:31 PM, Evan Koblentz <evan@vcfed.org> wrote:
There is the expansion port but that is already being used by the Lego card.
The expansion enclosure supports two cards.
We don't have that part, so I attached the Lego card directly where the enclosure attaches.
Presumably there are people on this list who can make us a doubler thingamajig.
Eggcellent!! Tony
On Wed, May 24, 2017 at 2:31 PM, Evan Koblentz <evan@vcfed.org> wrote:
There is the expansion port but that is already being used by the Lego card.
The expansion enclosure supports two cards.
We don't have that part, so I attached the Lego card directly where the enclosure attaches.
Presumably there are people on this list who can make us a doubler thingamajig.
save your money, just try using the Peek(78) and Peek(79)
On Wed, May 24, 2017 at 01:14:10PM -0400, Dan Roganti via vcf-midatlantic wrote:
so you just need the decimal value, this is a 16bit binary counter, so in decimal it's 0 to 65535 ???T1 = PEEK(78) + 256 * PEEK(79)
This code can give errors in the count since say the counter was 78 = 255 and 79 = 1 when you execute the peek(78) and then it increments to 0, 2 before the peek(79) You will then get 255, 2. Don't know if its important to our usage. There are techniques to handle this such as reading high, then low, then high again to see if you read over a rollover. I can provide more if interested.
You'll have to use this calibration test code and a stopwatch to find how many ticks of that Counter will get 1sec of time eg 10 T1 = PEEK(78) + 256 * PEEK(79) 20 FOR J=1 TO 1000:NEXT J 30 T2 = PEEK(78) + 256 * PEEK(79) 40 PRINT T2-T1 50 END
Then adjust J for 1sec before the PRINT displays the answer
But it will wrap around, cause this Counter is non-stop so sometimes T2-T1 will be negative just convert it back to positive if T2 <0 by multiplying this with -1
That's not really correct. Say T1 was 255,255 = 65535 and T2 is 0,0. Subtract is -65535. Just flipping the sign gives 65535. The correct difference is 1. Correct correction if negative time is 65536 + difference I think. This type of stuff is a lot harder than it looks.
On Wed, May 24, 2017 at 10:35 PM, David Gesswein via vcf-midatlantic < vcf-midatlantic@lists.vintagecomputerfederation.org> wrote:
On Wed, May 24, 2017 at 01:14:10PM -0400, Dan Roganti via vcf-midatlantic wrote:
so you just need the decimal value, this is a 16bit binary counter, so in decimal it's 0 to 65535 ???T1 = PEEK(78) + 256 * PEEK(79)
This code can give errors in the count since say the counter was 78 = 255 and 79 = 1 when you execute the peek(78) and then it increments to 0, 2 before the peek(79) You will then get 255, 2. Don't know if its important to our usage.
There are techniques to handle this such as reading high, then low, then high again to see if you read over a rollover. I can provide more if interested.
yes, Basic code will always have some pitfalls This is by far not a highly accurate Timer, it's a software Timer I found this method in an old 80s article as an alternate solution Atomic Reads in Basic code is the least of all options that's possible I'm not entirely aware of the Applesoft Kernel Rom internals, If you run this in a loop, and print the values continuously on the screen, I almost never see this scenario happen, but I confess my eyes are tired maybe I should save it in a file to look it over Probably since the Basic Kernel Rom isn't running that much faster. And since the Basic code is interpreted, this scenario can be considered negligible Of course, Assembly code with a Hardware Timer is still by far the optimum solution.
You'll have to use this calibration test code and a stopwatch to find how many ticks of that Counter will get 1sec of time eg 10 T1 = PEEK(78) + 256 * PEEK(79) 20 FOR J=1 TO 1000:NEXT J 30 T2 = PEEK(78) + 256 * PEEK(79) 40 PRINT T2-T1 50 END
Then adjust J for 1sec before the PRINT displays the answer
But it will wrap around, cause this Counter is non-stop so sometimes T2-T1 will be negative just convert it back to positive if T2 <0 by multiplying this with -1
That's not really correct. Say T1 was 255,255 = 65535 and T2 is 0,0. Subtract is -65535. Just flipping the sign gives 65535. The correct difference is 1. Correct correction if negative time is 65536 + difference I think. This type of stuff is a lot harder than it looks.
I see what you mean, your scenario shows when the counter wraps around. Since that's only a Calibration Test code, in order to determine the constant for 1sec elapsed time, I only accounted for normal situations with small amounts of elapsed Time, eg T2=1000, T1=2000, then the difference is -1000, multiply -1, then diff = 1000 That scenario would be significant within the actual robot code. Then you would need to add a check in the code for whenever the Counter wraps around. But then Basic code wouldn't be fast enough to check the Carry Bit of the Add Acc operation for when the Counter wraps around. Here again, Assembly code would come in to "Save the Day", just like UnderDog :) In Basic code, you can use this to check for that wrap around. If ABS(T2-T1) > 65535-T1 is True Then you know the Counter wrapped around like in your scenario eg. T1=65000, T2=0 IF ABS(T2-T1) > 65535-T1 IF ABS(0-65000) > 65535-65000 65000 > 535 [True] Then this means the Counter has wrapped around, so skip this T2-T1 value and try again versus the normal scenario T1=1000, T2=2000 IF ABS(T2-T1) > 65535-T1 IF ABS(2000-1000) > 65535-1000 1000 > 64535 [False] Then this means the Counter has not wrapped around, so this T2-T1 value is valid Dan -- _ ____ / \__/ Scotty, We Need More Power !! \_/ _\__ Aye, Cap'n, but we've only got 80 col's !!
participants (7)
-
Dan Roganti -
David Gesswein -
Devin Heitmueller -
Evan Koblentz -
Glenn Roberts -
Kelly Leavitt -
Tony Bogan