I looked fot a simple equivelent of
start-time
code
end-time
print time
time would be a long var.
I did try a 50Hz interrupt that increased a variable but it didn't work with iliglcd.
dim tim as long
TCCR1A = 0x80;
TCCR1B = 0x0A;
OCR1AH = 0x9c;
OCR1AL = 0x3f;
On Interrupt Timer1Match1 call ISR
tim=0
code
print tim
end
sub ISR
tim=tim+1
end sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Depending on your needs it may be easier to use the Millis() function.
It is timer based, Interrupt driven and device independent.
The drawback though in your case is that it has a minimum resolution of 1mS.
If the code you are timing takes several mS then the Millis function is fine, but if less than 1mS accuracy is needed then you would have to read the timer directly and compare.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks. I tried adding #include "millis.h" where millis.h is in gcb includes but got this error-
myline3.gcb (5): Warning: Cannot find C:\Users\stanley555\Documents\GCBasic stuff\arduino-new\millis.h
Should millis.h be in same folder as the program using it?
I want to test the speed of a line draw routine by drawing 1000 lines and timing it.
As an alternative I thought turn a port on, draw the line,turn port off then monitor the port on a scope and see the port frequency. The faster the line code the higher the port frequency...I might try that.
edit. I did using
for cntr=1 to 65535
set DIGITAL_6 on
; line (0,0,319,239,ILI9341_White) ;gcb line gave 17.19Hz
draw (1,1,320,240,ILI9341_White) ;new line gave 16.88Hz
set DIGITAL_6 off
next
not much difference but gcb faster.
Last edit: stan cartwright 2020-06-04
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
tim= millis()
for cntr=1 to 100
line (0,0,319,239,ILI9341_White)
; draw (1,1,320,240,ILI9341_White)
next
tim = millis() - tim
GLCDprint (1,200,tim,ILI9341_White)
gcb line (0,0,319,239,ILI9341_White) took 5024
my draw (1,1,320,240,ILI9341_White) took 5928
gcb clear winner.
I seem to remember an every command in one basic I used,maybe amstrad.
It set up an interrupt that every x ms jumped to a subroutine.
That would be handy in gcb as I find interrupts at the desired frequency complicated to set up.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I seem to remember an every command in one basic I used,maybe amstrad.
It set up an interrupt that every x ms jumped to a subroutine.
That would be handy in gcb as I find interrupts at the desired frequency complicated to set up.
Here is a crude Task scheduler using millis that may help, it is just a skeleton so you could flesh it out to suit your needs:
' Interrupt based Task Scheduling with millis() function
#Chip'mydevice'
#OptionExplicit
#Include<Millis.h>
#DefineSlice10' Time Slice in mS range 1 - 255
#DefineTasks5' Number of tasksDim Tick, Task as ByteDo Tick = millis() if Tick >= Slice then Select Case TaskCase1' Task 1 task1()' ...Case2' Task 2 task2()' ...Case3' Task 3 task3()' ...Case4' Task 4 Task(4)' ... Case Else end select Task = Task + 1 If Task = Tasks then Task = 0 Tick = 0 end ifLoopSub Task1()' ...end SubSub Task2()' ...end SubSub Task3()' ...end SubSub Task4()' ...end SubSub Task5()' ...end Sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Nice Chris but not what I was thinking of.
millis is a useful addition to gcb.
It was a thought that there must be a program pointer that is pushed when an interrupt happens then popped but I don't know avr/pic hardware.
If I wanted a 50Hz interrupt I could use millis in the program loop and check if 20ms had passed...as long as the program loop was less than 20ms.
I will look at the millis.h again as an insight to interrupts.
nice one,stan
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I wondered what happens when you include glcd.h
does it install all of it or just the bits you use?
like if you don't use circle or triangle are they installed or only installed if you use them?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is an example of how I would envisage it being used:
'' example of DoEvery'
#Chip'mychip'
#Include<millis.h>
#DefineMyLEDPortC.4DoDoEvery250,LEDTime,LEDTgl()‘FlashLEDloopsubLEDTgl()MYLED=~MYLEDendsub
It is not an interrupt so it would have to be polled in the main loop as shown but it should meet most needs.
I will test it in the morning and if it works I may expand on the idea and include it in the millis library.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I just had a thought of how it could be done as an actual timer interrupt.
I could build it into the existing millis interrupt so that no additional timer is needed and use #define to conditionally include code, that way no code is generated or memory used if no DoEvery events are set.
From the user perspective it would look something like this:
I looked up every command and it was in locomotive basic used on amstrad z80 machines.
I'm thinking if you #include <millis> it starts and runs even if you don't use millis() in the program.
A command like every 20 subname and the millis would every 20ms store the program counter, jump to the named sub then at the end sub restore the program counter... I will look up if there is a program counter or how interrupts work at hardware level.</millis>
Quote from locomotive basic command guide:-
BASIC branches to the subroutine at line ln EVERY (reccuring) i/50 seconds. (see also "AFTER i[,t] GOSUB line")
There are 4 delay timers from 0 to 3 which can be specified with ‹timer number›. If omitted ‹timer number› defaults to 0.
In the case of parallel task has 3 the highest and 0 the lowest priority.
With DI or EI you can disable or enable the timing interrupt. With REMAIN <timer number=""> you can also disable an AFTER or EVERY construct and stores the "remaining" time (> REMAIN)
Interrupts run as long as the main loop / program runs, even the main programm is paused > press ESC only once not twice for a break.
It is important to know or realise that low-priority-interrupts which occurs simultanously to higher-priority-interrupts are not lost. Their task remains or handled again after finishing the higher-prio interrupt.
10 REM > interrupts
20 EVERY 50,0 GOSUB 100: REM > lowest priority
30 EVERY 100,1 GOSUB 200
40 EVERY 200,2 GOSUB 300:
50 AFTER 1000,3 GOSUB 400: REM > highest priority
60 WHILE flag=0
70 a=a+1:print a
80 WEND
90 END
100 REM #0
110 PEN 2:PRINT "timer 0":PEN 1
120 RETURN
200 REM #1
210 PEN 2:PRINT "timer 1":PEN 1
220 RETURN
300 REM #2
310 PEN 2:PRINT "timer 2":PEN 1
320 RETURN
400 REM #3
410 flag=1:PEN 2:PRINT "no more interrupts..."
420 RETURN
Hint: Timing with interrupts is important, especially if more than one interrupts run. If the interval of a subroutine driven by an interrupt is too long than the processor can never get back to deal the main program again. Work out timing by measuring the subroutine or by trial and error.
There are system internal interrupts (highest level) which cannot be influenced by BASIC interrupts (e.g. keyboard scan > BREAK key.)
The next level of sytem internal interrupts CAN be influenced by BASIC interrupts. For example the sound queue which will be created by "ON SQ <chanel> GOSUB <line>". Those sound interrupts have an independent time tricker but their priority is parallel to the second priority times of BASICs interrupts. Therefore interrupts with timer 3 could "interrupt" them.</line></chanel></timer>
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
http://iamtechnical.com/program-counter-and-program-rom-space-pic
Thinking..the program counter would be in the millis.h not the main program which is what would be needed. Like a normal interrupt does.
I don't know how millis.h would know where in the main program the every occurred.
edit- if in the millis.h interrupt a gosub in main program could be called then it would return to the millis.h then that would what?? I have not a clue about this.
Interrupts need an update in gcb help. so many different chips. avr is different to pic.
reference to calculators that are for other basics or c.
interrupts are cool when you get them to work...like a robot I'm building and it uses stepper motors for wheels and the interrupt sends the rotating drive pattern to the motors with speed as every so many interrupts
so many uses...rc type servos need refreshing every 20ms
Last edit: stan cartwright 2020-06-06
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It looks like I was on the correct track then.
We don't have all of the resources of a Z80 unfortunately, and the code needs to execute on quite a few different devices including both PIC and AVR but still the syntax I chose is similar to what you posted above.
Here is a working test program using a tested first draft of a new “millis.h”:
#Chip 16f18855, 32#option Explicit#include"millis.h"Init_MsCtr_Int#define MyLED1 PortA.0#define MyLED2 PortA.1DirMyLED1OutDirMyLED2Out#define DoEvery1 (250, BitTgl(MyLED1)) ' Flash LED1 at a rate of 250 mS#define DoEvery2 (175, BitTgl(MyLED2)) ' Flash LED2 at a rate of 175 mSDo'MainloopisemptyLoopEndMacroBitTgl(BitAdr)BitAdr=!BitAdrendMacro
The above flashes two LED’s on the Xpress Board at different rates and independent of the main loop. In fact the main loop is empty and only exists to prevent the Device going to sleep.
I think it is close to your initial description and as a proof of concept I am happy with the result.
I will have a look now at the documentation you posted to see what needs adding or changing to suit.
Cheers
Chris
Last edit: Chris Roper 2020-06-06
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Brill,I'll check it out. What is asm ShowDebug Call_SetTimer_Millis_macro ???
ie asm showdebug.
It is in millis.h and don't know what it does. Is it documented in help?ie is it a script or macro thing?
‘asm ShowDebug’ is not Documented in Help as it is not user facing code.
It is part of the compiler and allows debug information to be displayed in the asm Listings.
There are a lot of cryptic things including Scripts, Macros, raw ASM code and obscure compiler derivatives, they are there to allow for portability and differing Clock speeds etc.
Even a simple change can cause a cascading error in that file so rather DO NOT ATTEMPT to edit it.
When I have something ready to test I will post working code and a replacement millis.h.
Cheers
Chris
edit:
thanks for theArduino example code I will try it here on a simulaton or, if I can find it, an ARDUINO Mega, to see if it works as part of my testing
Last edit: Chris Roper 2020-06-06
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If I mess up experimenting...it is not unusual :) not broken forever...couldn't spell permenantly.
I was just looking at adding your changes to a copy of millis but I guess I can wait...honest.
the mega328p test was to scope if it was 50 Hz
it would be
Macro servo
pulseout servopin,servopos
end Macro
where servopos would be 750 us to 2250 us which I know works as an interrupt..my first post but to find that...it's not in help or demos.
don't break a leg. I wish I could help.
ps there's a uno..and other pic, simulator posted on the forum called picsimlab which might not handle intterupts...or maybe does. Not used it much..I use breadboard
cheers stan
pps unos cheap as chips
Last edit: stan cartwright 2020-06-06
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
My proof of concept is working but I am still trying to find a timing method that works for all supported architectures and minimises RAM use. At the moment, whilst I can get independent control of two LED's, when connected to a Frequency counter the signal timing is way off the mark.
I have a lot more work to do before it is ready for you to test. If I give it to you as it is, it will probably let the smoke out of your Servo Motor.
It is after midnight again so I will pack in for now and work on it again tomorrow.
Sleeping on the problems often generates innovative solutions anyway. It certainly helped make the major breakthrough that I achieved this morning and greatly simplified syntax and User implementation.
Cheers
Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
there's no fun in programming if you're feeling under pressure but you aren't. it's just a thought for gcb. surprise us one day!
I got lots to do myself with like a h-bridge arrived today so to build a robot vehicle with v53l0x.
had one of these bridges and they got inhibit pin you can apply pwm to,nice.
thing is millis works so if an event is in code when compiled it would just set vars for the ifdef doevery time and sub. a check that it has reached the event time,goto sub,reset doevery time and count again until it reached the doevery time
but to do that is probably not in help
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Progress report - Timing is starting to look good and RAM footprint is reduced.
I have all 4 channels running simultaneously on the Target board.
Here is the Timing capture of DoEvery0, DoEvery1 and DoEvery2 .
Do Every3 is running a Countable LED pulse that is too slow for the analyzer to capture.
Here is the code, as you can see the syntax has changed slightly.
Not bad for a morning's work, especially as I have not had my second cup of coffee.
I still need to look at the Priority handling and code initialization but feel a lot more positive now.
Yes it can be a command, a subroutine call, a macro or a line of colon seperated code, the main thing though is that whatever is called is quick to execute as it is executing within the interrupt handler.
I have spent most of the day learning Locomotive BASIC and in particular the Amstrad CPC464 Computer.
The documentation is not very forthcoming on the internal workings but with a Simulator and z80 debugger/disassembler I am starting to see how they have implemented it and am quite far into reverse engineering their “Interrupt” implementation.
The main consideration is that the Amstrad BASIC language guide is misleading in that it talks of Timers, Interrupts, Priorities etc almost implying they are hardware functions, but in reality they use a single system clock to drive 4 software timers and use a Software interrupt.
Their tick rate is also strange, a period of 200 in the Always function is not, as I expected, 200 mS it is defined rather as 200 x 1/50th of one second. So it is 4 Seconds not 200 mS and would explain why they can use print statements in their examples.
Something that I would never recommend in a hardware interrupt routine.
More to come as I excavate this Rabbit hole - DoAlways will not be the only offshoot of this.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Errr....Wow!! I never thought you would bother with locomotive basic...good job I never said every is a unix command.
The cpc every was every 20ms minimum in basic use from what I quoted.
I had a 464 but never used every but did some asm and z80 was nice at the time.
No hardware graphics but z80 had ldir which shifted memory fast. What sinclair should have been.
Both used a ula and z80, cpc basic was better than sinclair. Nostalgia.
When I first mentioned this idea I was thinking of just one event although the basic quote shows 3.
As you said and it said in the quote, watch the sub time. Things like printing to a lcd could take too long. Other things like running servo motors that need a rotating pattern to rotate would be fast enough.
I was asked to convert jim bowens bullseye from bbc basic to amstrad but the company wanted it in machine code which was daft as they were given the bbc code,graphics,sound.
I did it and just looked it up and found this review which is honest...i took the money and ran. It has swearing in it sorry. https://www.youtube.com/watch?v=hMYI8kHtfmU
the 464 was a bbc micro contender. I liked the z80 more than 6502.
The bbc micro was for posh people...it had a rs232 port.
You'll find systems with a ula are different to a bbc micro. The ula is the system not the cpu.
Last edit: stan cartwright 2020-06-08
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I looked fot a simple equivelent of
start-time
code
end-time
print time
time would be a long var.
I did try a 50Hz interrupt that increased a variable but it didn't work with iliglcd.
dim tim as long
TCCR1A = 0x80;
TCCR1B = 0x0A;
OCR1AH = 0x9c;
OCR1AL = 0x3f;
On Interrupt Timer1Match1 call ISR
tim=0
code
print tim
end
sub ISR
tim=tim+1
end sub
Depending on your needs it may be easier to use the Millis() function.
It is timer based, Interrupt driven and device independent.
The drawback though in your case is that it has a minimum resolution of 1mS.
If the code you are timing takes several mS then the Millis function is fine, but if less than 1mS accuracy is needed then you would have to read the timer directly and compare.
An alternate approch is to use a single bit of i/o and a data analyzer (super cheap clone, £5 on ebay) set the bit hi to mark the start etc.
Thanks. I tried adding #include "millis.h" where millis.h is in gcb includes but got this error-
myline3.gcb (5): Warning: Cannot find C:\Users\stanley555\Documents\GCBasic stuff\arduino-new\millis.h
Should millis.h be in same folder as the program using it?
I want to test the speed of a line draw routine by drawing 1000 lines and timing it.
As an alternative I thought turn a port on, draw the line,turn port off then monitor the port on a scope and see the port frequency. The faster the line code the higher the port frequency...I might try that.
edit. I did using
not much difference but gcb faster.
Last edit: stan cartwright 2020-06-04
from the help:
So:
this error-
myline3.gcb (5): Warning: Cannot find C:\Users\stanley555\Documents\GCBasic stuff\arduino-new\millis.h
is a syntax error on your part just change :
to
Cheers
Chris
Last edit: Chris Roper 2020-06-05
Thanks Chris, it works well.
I used
gcb line (0,0,319,239,ILI9341_White) took 5024
my draw (1,1,320,240,ILI9341_White) took 5928
gcb clear winner.
I seem to remember an every command in one basic I used,maybe amstrad.
It set up an interrupt that every x ms jumped to a subroutine.
That would be handy in gcb as I find interrupts at the desired frequency complicated to set up.
Nice Chris but not what I was thinking of.
millis is a useful addition to gcb.
It was a thought that there must be a program pointer that is pushed when an interrupt happens then popped but I don't know avr/pic hardware.
If I wanted a 50Hz interrupt I could use millis in the program loop and check if 20ms had passed...as long as the program loop was less than 20ms.
I will look at the millis.h again as an insight to interrupts.
nice one,stan
I wondered what happens when you include glcd.h
does it install all of it or just the bits you use?
like if you don't use circle or triangle are they installed or only installed if you use them?
Just the bits you use.
Whilst I don't know much about the Amstrad or its BASIC implementation, it should be possible to create a DoEvery() type function with millis().
Here is my rough idea but as it is after midnight here and I am not in my Office It is not tested:
This is an example of how I would envisage it being used:
It is not an interrupt so it would have to be polled in the main loop as shown but it should meet most needs.
I will test it in the morning and if it works I may expand on the idea and include it in the millis library.
I just had a thought of how it could be done as an actual timer interrupt.
I could build it into the existing millis interrupt so that no additional timer is needed and use #define to conditionally include code, that way no code is generated or memory used if no DoEvery events are set.
From the user perspective it would look something like this:
There would be nothing in the main loop but the user program would obviously have to define the target functions, in this case:
An interesting concept Stan, and well worth a bit more research on my part.
Time to go and sleep on it.
Cheers
Chris
Last edit: Chris Roper 2020-06-05
I looked up every command and it was in locomotive basic used on amstrad z80 machines.
I'm thinking if you #include <millis> it starts and runs even if you don't use millis() in the program.
A command like every 20 subname and the millis would every 20ms store the program counter, jump to the named sub then at the end sub restore the program counter... I will look up if there is a program counter or how interrupts work at hardware level.</millis>
Quote from locomotive basic command guide:-
BASIC branches to the subroutine at line ln EVERY (reccuring) i/50 seconds. (see also "AFTER i[,t] GOSUB line")
There are 4 delay timers from 0 to 3 which can be specified with ‹timer number›. If omitted ‹timer number› defaults to 0.
In the case of parallel task has 3 the highest and 0 the lowest priority.
With DI or EI you can disable or enable the timing interrupt. With REMAIN <timer number=""> you can also disable an AFTER or EVERY construct and stores the "remaining" time (> REMAIN)
Interrupts run as long as the main loop / program runs, even the main programm is paused > press ESC only once not twice for a break.
It is important to know or realise that low-priority-interrupts which occurs simultanously to higher-priority-interrupts are not lost. Their task remains or handled again after finishing the higher-prio interrupt.
10 REM > interrupts
20 EVERY 50,0 GOSUB 100: REM > lowest priority
30 EVERY 100,1 GOSUB 200
40 EVERY 200,2 GOSUB 300:
50 AFTER 1000,3 GOSUB 400: REM > highest priority
60 WHILE flag=0
70 a=a+1:print a
80 WEND
90 END
100 REM #0
110 PEN 2:PRINT "timer 0":PEN 1
120 RETURN
200 REM #1
210 PEN 2:PRINT "timer 1":PEN 1
220 RETURN
300 REM #2
310 PEN 2:PRINT "timer 2":PEN 1
320 RETURN
400 REM #3
410 flag=1:PEN 2:PRINT "no more interrupts..."
420 RETURN
Hint: Timing with interrupts is important, especially if more than one interrupts run. If the interval of a subroutine driven by an interrupt is too long than the processor can never get back to deal the main program again. Work out timing by measuring the subroutine or by trial and error.
There are system internal interrupts (highest level) which cannot be influenced by BASIC interrupts (e.g. keyboard scan > BREAK key.)
The next level of sytem internal interrupts CAN be influenced by BASIC interrupts. For example the sound queue which will be created by "ON SQ <chanel> GOSUB <line>". Those sound interrupts have an independent time tricker but their priority is parallel to the second priority times of BASICs interrupts. Therefore interrupts with timer 3 could "interrupt" them.</line></chanel></timer>
http://iamtechnical.com/program-counter-and-program-rom-space-pic
Thinking..the program counter would be in the millis.h not the main program which is what would be needed. Like a normal interrupt does.
I don't know how millis.h would know where in the main program the every occurred.
edit- if in the millis.h interrupt a gosub in main program could be called then it would return to the millis.h then that would what?? I have not a clue about this.
Interrupts need an update in gcb help. so many different chips. avr is different to pic.
reference to calculators that are for other basics or c.
interrupts are cool when you get them to work...like a robot I'm building and it uses stepper motors for wheels and the interrupt sends the rotating drive pattern to the motors with speed as every so many interrupts
so many uses...rc type servos need refreshing every 20ms
Last edit: stan cartwright 2020-06-06
Thanks Stan,
It looks like I was on the correct track then.
We don't have all of the resources of a Z80 unfortunately, and the code needs to execute on quite a few different devices including both PIC and AVR but still the syntax I chose is similar to what you posted above.
Here is a working test program using a tested first draft of a new “millis.h”:
The above flashes two LED’s on the Xpress Board at different rates and independent of the main loop. In fact the main loop is empty and only exists to prevent the Device going to sleep.
I think it is close to your initial description and as a proof of concept I am happy with the result.
I will have a look now at the documentation you posted to see what needs adding or changing to suit.
Cheers
Chris
Last edit: Chris Roper 2020-06-06
Brill,I'll check it out. What is asm ShowDebug Call_SetTimer_Millis_macro ???
ie asm showdebug.
It is in millis.h and don't know what it does. Is it documented in help?ie is it a script or macro thing?
will this work ie syntax?
Last edit: stan cartwright 2020-06-06
Rather don't poke around with that stuff Stan.
‘asm ShowDebug’ is not Documented in Help as it is not user facing code.
It is part of the compiler and allows debug information to be displayed in the asm Listings.
There are a lot of cryptic things including Scripts, Macros, raw ASM code and obscure compiler derivatives, they are there to allow for portability and differing Clock speeds etc.
Even a simple change can cause a cascading error in that file so rather DO NOT ATTEMPT to edit it.
When I have something ready to test I will post working code and a replacement millis.h.
Cheers
Chris
edit:
thanks for theArduino example code I will try it here on a simulaton or, if I can find it, an ARDUINO Mega, to see if it works as part of my testing
Last edit: Chris Roper 2020-06-06
If I mess up experimenting...it is not unusual :) not broken forever...couldn't spell permenantly.
I was just looking at adding your changes to a copy of millis but I guess I can wait...honest.
the mega328p test was to scope if it was 50 Hz
it would be
Macro servo
pulseout servopin,servopos
end Macro
where servopos would be 750 us to 2250 us which I know works as an interrupt..my first post but to find that...it's not in help or demos.
don't break a leg. I wish I could help.
ps there's a uno..and other pic, simulator posted on the forum called picsimlab which might not handle intterupts...or maybe does. Not used it much..I use breadboard
cheers stan
pps unos cheap as chips
Last edit: stan cartwright 2020-06-06
It is just not ready Stan.
My proof of concept is working but I am still trying to find a timing method that works for all supported architectures and minimises RAM use. At the moment, whilst I can get independent control of two LED's, when connected to a Frequency counter the signal timing is way off the mark.
I have a lot more work to do before it is ready for you to test. If I give it to you as it is, it will probably let the smoke out of your Servo Motor.
It is after midnight again so I will pack in for now and work on it again tomorrow.
Sleeping on the problems often generates innovative solutions anyway. It certainly helped make the major breakthrough that I achieved this morning and greatly simplified syntax and User implementation.
Cheers
Chris
there's no fun in programming if you're feeling under pressure but you aren't. it's just a thought for gcb. surprise us one day!
I got lots to do myself with like a h-bridge arrived today so to build a robot vehicle with v53l0x.
had one of these bridges and they got inhibit pin you can apply pwm to,nice.
thing is millis works so if an event is in code when compiled it would just set vars for the ifdef doevery time and sub. a check that it has reached the event time,goto sub,reset doevery time and count again until it reached the doevery time
but to do that is probably not in help
Progress report - Timing is starting to look good and RAM footprint is reduced.
I have all 4 channels running simultaneously on the Target board.

Here is the Timing capture of DoEvery0, DoEvery1 and DoEvery2 .
Do Every3 is running a Countable LED pulse that is too slow for the analyzer to capture.
Here is the code, as you can see the syntax has changed slightly.
Not bad for a morning's work, especially as I have not had my second cup of coffee.
I still need to look at the Priority handling and code initialization but feel a lot more positive now.
Cheers
Chris
Brill work @Chris !
In #define DoEvery0 40, MyLED0 = !MyLED0
can MyLED0 = !MyLED0 still be a sub call?
ie #define DoEvery0 40, sub mycode
Yes it can be a command, a subroutine call, a macro or a line of colon seperated code, the main thing though is that whatever is called is quick to execute as it is executing within the interrupt handler.
I have spent most of the day learning Locomotive BASIC and in particular the Amstrad CPC464 Computer.
The documentation is not very forthcoming on the internal workings but with a Simulator and z80 debugger/disassembler I am starting to see how they have implemented it and am quite far into reverse engineering their “Interrupt” implementation.
The main consideration is that the Amstrad BASIC language guide is misleading in that it talks of Timers, Interrupts, Priorities etc almost implying they are hardware functions, but in reality they use a single system clock to drive 4 software timers and use a Software interrupt.
Their tick rate is also strange, a period of 200 in the Always function is not, as I expected, 200 mS it is defined rather as 200 x 1/50th of one second. So it is 4 Seconds not 200 mS and would explain why they can use print statements in their examples.
Something that I would never recommend in a hardware interrupt routine.
More to come as I excavate this Rabbit hole - DoAlways will not be the only offshoot of this.
Errr....Wow!! I never thought you would bother with locomotive basic...good job I never said every is a unix command.
The cpc every was every 20ms minimum in basic use from what I quoted.
I had a 464 but never used every but did some asm and z80 was nice at the time.
No hardware graphics but z80 had ldir which shifted memory fast. What sinclair should have been.
Both used a ula and z80, cpc basic was better than sinclair. Nostalgia.
When I first mentioned this idea I was thinking of just one event although the basic quote shows 3.
As you said and it said in the quote, watch the sub time. Things like printing to a lcd could take too long. Other things like running servo motors that need a rotating pattern to rotate would be fast enough.
I was asked to convert jim bowens bullseye from bbc basic to amstrad but the company wanted it in machine code which was daft as they were given the bbc code,graphics,sound.
I did it and just looked it up and found this review which is honest...i took the money and ran. It has swearing in it sorry. https://www.youtube.com/watch?v=hMYI8kHtfmU
the 464 was a bbc micro contender. I liked the z80 more than 6502.
The bbc micro was for posh people...it had a rs232 port.
You'll find systems with a ula are different to a bbc micro. The ula is the system not the cpu.
Last edit: stan cartwright 2020-06-08
I needed to test the tape loader .......
Last edit: Chris Roper 2020-06-08