EmbeddedRelated.com
Forums

Need help with PIC Macros

Started by stephendbarnes April 16, 2003
Yes, it is actually calling the routine specified by the first case
it sees! I have just arrived at home and looked at your replies.
Thanks for the input. I'm going to compare my listing to yours and
correct the problem areas. In all honesty, I think I'm attempting to
use the macros as a crutch...I should be learning how to write this
code first and then use the macros as a convenience. My PIC projects
are not work related so I've got the time to learn. I will use the
info you have given me to test my project ideas on the PIC to see if
they work. Then I'm going to continue with the learning curve!
Thanks for the help and I'll post what I've done for all to see.

Regards,
Steve --- In , "rtstofer" <rstofer@p...> wrote:
>
> Just a thought - is the code actually calling your subroutines or
> just messing about with the xor beq stuff? There is a bunch of
code
> being executed in sequence - there is certainly no magic that makes
> the select statement jump to the proper case right off the bat.
>
> First the code evaluates whether W is 3, if not it evaluates
whether
> W is 2, if not it evaluates whether W is 1, if not it loops back
and
> gets a new value for W and does the process again.
>
> If any test is true, the appropriate subroutine is called and the
> code loops back for a new value of W.
>
> And yes, using a computed goto table is probably faster but the
table
> gets ugly if there are unused values of W: 1, 3, 19, 22, 29, 234
for
> example. You would need a table with 235 entries (0..234) most of
> which would branch to an error subroutine for invalid values.
>
> Where the values can be limited to something like [0..3] then a
> computed goto table can be faster. Just be sure to forcibly limit
> them with something like ANDLW B'00000011' after the value is
placed
> in W.
>
> Something to think about later. >
> --- In , "stephendbarnes"
> <stephendbarnes@h...> wrote:
> > The code wants to execute the first case argument it sees. I have
> > followed it in step mode but I don't yet understand what the
macro
> is
> > doing. I can comment out the first case (case 3) and it executes
> the
> > the first case it sees regardless of the W reg value! I'm stumped
> and
> > drowning!!
> >
> > Regards,
> > Steve






I never think of macros as a crutch - they are a readability aid and,
in some cases, an application specific instruction. If you use them,
you can learn from the emitted code and anytime you can see good code
and good coding it is worthwhile. That macro library is excellent
code.

I have two Mark III Minisumo Robots - one uses modified servo motors
where a bit is pulsed about 50 times per second. The width of the
pulse causes the servo to move at a speed either forward or reverse.
The other has an H bridge control and it uses the PWM output of the
16F877. So I have a macro that takes a motor, direction and speed
and does conditional assembly depending on the robot I am coding
for. The advantage is that the strategy of moving the robot is
independent of the hardware. Just call a macro:

Motor Left, Foward, Fast
Motor Right, Forward, Fast

Once I know the macros work correctly I can use them as application
specific instructions and not have to worry about the details. No
excess code is generated - the instructions are exactly what I would
have written in either case. But I only have to do it once.

If you write code once, fine. If you write it twice it should be a
macro or a subroutine in a library. In my opinion only.

Let me know how it works out - the listing I posted does work
correctly. None of the subroutines are actually called unless I
insert a statement like:

MOVLW 3 ; insert before 'select'

Good luck!

--- In , "stephendbarnes"
<stephendbarnes@h...> wrote:
> Yes, it is actually calling the routine specified by the first case
> it sees! I have just arrived at home and looked at your replies.
> Thanks for the input. I'm going to compare my listing to yours and
> correct the problem areas. In all honesty, I think I'm attempting
to
> use the macros as a crutch...I should be learning how to write this
> code first and then use the macros as a convenience. My PIC
projects
> are not work related so I've got the time to learn. I will use the
> info you have given me to test my project ideas on the PIC to see
if
> they work. Then I'm going to continue with the learning curve!
> Thanks for the help and I'll post what I've done for all to see.
>
> Regards,
> Steve > --- In , "rtstofer" <rstofer@p...> wrote:
> >
> > Just a thought - is the code actually calling your subroutines or
> > just messing about with the xor beq stuff? There is a bunch of
> code
> > being executed in sequence - there is certainly no magic that
makes
> > the select statement jump to the proper case right off the bat.
> >
> > First the code evaluates whether W is 3, if not it evaluates
> whether
> > W is 2, if not it evaluates whether W is 1, if not it loops back
> and
> > gets a new value for W and does the process again.
> >
> > If any test is true, the appropriate subroutine is called and the
> > code loops back for a new value of W.
> >
> > And yes, using a computed goto table is probably faster but the
> table
> > gets ugly if there are unused values of W: 1, 3, 19, 22, 29, 234
> for
> > example. You would need a table with 235 entries (0..234) most
of
> > which would branch to an error subroutine for invalid values.
> >
> > Where the values can be limited to something like [0..3] then a
> > computed goto table can be faster. Just be sure to forcibly
limit
> > them with something like ANDLW B'00000011' after the value is
> placed
> > in W.
> >
> > Something to think about later.
> >
> >
> >
> > --- In , "stephendbarnes"
> > <stephendbarnes@h...> wrote:
> > > The code wants to execute the first case argument it sees. I
have
> > > followed it in step mode but I don't yet understand what the
> macro
> > is
> > > doing. I can comment out the first case (case 3) and it
executes
> > the
> > > the first case it sees regardless of the W reg value! I'm
stumped
> > and
> > > drowning!!
> > >
> > > Regards,
> > > Steve




I agree with you. My point was that as a raw beginner in assembly language, the easy way out has a way of making one loose sight of the objective (learning how to code). At times, one is so focused on the project at hand that looking at the results of the macro plays second fiddle to enjoying the end product! What is the saying...."Know thy self"? ;-)
Back to the subject...I have not tried the macro example listing you posted yet (but I will soon) because I solve this particular problem with inline code! I have always used high level languages when writing software for PC's, PLC's, etc., so assembly has really made me think about new ways (to me) to solve old problems. If you have the time, take a look at the attached file to see what I have done. It is well commented and is a work in progress so please excuse the time delay stuff which came from the MIT piclist examples page (any suggestions would be welcome).
 
Regards,
Steve
----- Original Message -----
From: rtstofer
To: p...@yahoogroups.com
Sent: Saturday, April 19, 2003 1:38 AM
Subject: [piclist] Re: Need help with PIC Macros


I never think of macros as a crutch - they are a readability aid and,
in some cases, an application specific instruction.  If you use them,
you can learn from the emitted code and anytime you can see good code
and good coding it is worthwhile.  That macro library is excellent
code.

I have two Mark III Minisumo Robots - one uses modified servo motors
where a bit is pulsed about 50 times per second.  The width of the
pulse causes the servo to move at a speed either forward or reverse. 
The other has an H bridge control and it uses the PWM output of the
16F877.  So I have a macro that takes a motor, direction and speed
and does conditional assembly depending on the robot I am coding
for.  The advantage is that the strategy of moving the robot is
independent of the hardware.  Just call a macro:

  Motor Left, Foward, Fast
  Motor Right, Forward, Fast

Once I know the macros work correctly I can use them as application
specific instructions and not have to worry about the details.  No
excess code is generated - the instructions are exactly what I would
have written in either case.  But I only have to do it once.

If you write code once, fine.  If you write it twice it should be a
macro or a subroutine in a library.  In my opinion only.

Let me know how it works out - the listing I posted does work
correctly.  None of the subroutines are actually called unless I
insert a statement like:

MOVLW 3 ; insert before 'select'

Good luck!

--- In p...@yahoogroups.com, "stephendbarnes"
<stephendbarnes@h...> wrote:
> Yes, it is actually calling the routine specified by the first case
> it sees! I have just arrived at home and looked at your replies.
> Thanks for the input. I'm going to compare my listing to yours and
> correct the problem areas. In all honesty, I think I'm attempting
to
> use the macros as a crutch...I should be learning how to write this
> code first and then use the macros as a convenience. My PIC
projects
> are not work related so I've got the time to learn. I will use the
> info you have given me to test my project ideas on the PIC to see
if
> they work. Then I'm going to continue with the learning curve!
> Thanks for the help and I'll post what I've done for all to see.
>
> Regards,
> Steve> --- In p...@yahoogroups.com, "rtstofer" <rstofer@p...> wrote:
> >
> > Just a thought - is the code actually calling your subroutines or
> > just messing about with the xor beq stuff?  There is a bunch of
> code
> > being executed in sequence - there is certainly no magic that
makes
> > the select statement jump to the proper case right off the bat.
> >
> > First the code evaluates whether W is 3, if not it evaluates
> whether
> > W is 2, if not it evaluates whether W is 1, if not it loops back
> and
> > gets a new value for W and does the process again.
> >
> > If any test is true, the appropriate subroutine is called and the
> > code loops back for a new value of W.
> >
> > And yes, using a computed goto table is probably faster but the
> table
> > gets ugly if there are unused values of W: 1, 3, 19, 22, 29, 234
> for
> > example.  You would need a table with 235 entries (0..234) most
of
> > which would branch to an error subroutine for invalid values.
> >
> > Where the values can be limited to something like [0..3] then a
> > computed goto table can be faster.  Just be sure to forcibly
limit
> > them with something like ANDLW B'00000011' after the value is
> placed
> > in W.
> >
> > Something to think about later.
> >
> >
> >
> > --- In p...@yahoogroups.com, "stephendbarnes"
> > <stephendbarnes@h...> wrote:
> > > The code wants to execute the first case argument it sees. I
have
> > > followed it in step mode but I don't yet understand what the
> macro
> > is
> > > doing. I can comment out the first case (case 3) and it
executes
> > the
> > > the first case it sees regardless of the W reg value! I'm
stumped
> > and
> > > drowning!!
> > >
> > > Regards,
> > > Steve



to unsubscribe, go to http://www.yahoogroups.com and follow the instructions

">Yahoo! Terms of Service.


Attachment (not stored)
sallybot.asm
Type: application/octet-stream



Wonder why my email post never made it. Strange.

OK, the only thing I would reconsider is using self-relative jumps as
in 'goto $ - 3'. If you ever add a little debug code in the middle
of the loop that instruction will come back to bite you. In fact,
any change in the loop is a problem.

I would consider adding 3 labels (Reverse1, Left1, Right1) as the
targets for the 3 self-relative jumps.

I like the idea of assigning names to port bits with #define. I have
been trying to use that at every opportunity.

Looking good!

--- In , "Stephen D. Barnes"
<stephendbarnes@h...> wrote:
> I agree with you. My point was that as a raw beginner in assembly
language, the easy way out has a way of making one loose sight of the
objective (learning how to code). At times, one is so focused on the
project at hand that looking at the results of the macro plays second
fiddle to enjoying the end product! What is the saying...."Know thy
self"? ;-)
> Back to the subject...I have not tried the macro example listing
you posted yet (but I will soon) because I solve this particular
problem with inline code! I have always used high level languages
when writing software for PC's, PLC's, etc., so assembly has really
made me think about new ways (to me) to solve old problems. If you
have the time, take a look at the attached file to see what I have
done. It is well commented and is a work in progress so please excuse
the time delay stuff which came from the MIT piclist examples page
(any suggestions would be welcome).
>
> Regards,
> Steve
> ----- Original Message -----
> From: rtstofer
> To:
> Sent: Saturday, April 19, 2003 1:38 AM
> Subject: [piclist] Re: Need help with PIC Macros >
> I never think of macros as a crutch - they are a readability aid
and,
> in some cases, an application specific instruction. If you use
them,
> you can learn from the emitted code and anytime you can see good
code
> and good coding it is worthwhile. That macro library is
excellent
> code.
>
> I have two Mark III Minisumo Robots - one uses modified servo
motors
> where a bit is pulsed about 50 times per second. The width of
the
> pulse causes the servo to move at a speed either forward or
reverse.
> The other has an H bridge control and it uses the PWM output of
the
> 16F877. So I have a macro that takes a motor, direction and
speed
> and does conditional assembly depending on the robot I am coding
> for. The advantage is that the strategy of moving the robot is
> independent of the hardware. Just call a macro:
>
> Motor Left, Foward, Fast
> Motor Right, Forward, Fast
>
> Once I know the macros work correctly I can use them as
application
> specific instructions and not have to worry about the details.
No
> excess code is generated - the instructions are exactly what I
would
> have written in either case. But I only have to do it once.
>
> If you write code once, fine. If you write it twice it should be
a
> macro or a subroutine in a library. In my opinion only.
>
> Let me know how it works out - the listing I posted does work
> correctly. None of the subroutines are actually called unless I
> insert a statement like:
>
> MOVLW 3 ; insert before 'select'
>
> Good luck!
>
> --- In , "stephendbarnes"
> <stephendbarnes@h...> wrote:
> > Yes, it is actually calling the routine specified by the first
case
> > it sees! I have just arrived at home and looked at your
replies.
> > Thanks for the input. I'm going to compare my listing to yours
and
> > correct the problem areas. In all honesty, I think I'm
attempting
> to
> > use the macros as a crutch...I should be learning how to write
this
> > code first and then use the macros as a convenience. My PIC
> projects
> > are not work related so I've got the time to learn. I will use
the
> > info you have given me to test my project ideas on the PIC to
see
> if
> > they work. Then I'm going to continue with the learning curve!
> > Thanks for the help and I'll post what I've done for all to see.
> >
> > Regards,
> > Steve
> >
> >
> > --- In , "rtstofer" <rstofer@p...> wrote:
> > >
> > > Just a thought - is the code actually calling your
subroutines or
> > > just messing about with the xor beq stuff? There is a bunch
of
> > code
> > > being executed in sequence - there is certainly no magic that
> makes
> > > the select statement jump to the proper case right off the
bat.
> > >
> > > First the code evaluates whether W is 3, if not it evaluates
> > whether
> > > W is 2, if not it evaluates whether W is 1, if not it loops
back
> > and
> > > gets a new value for W and does the process again.
> > >
> > > If any test is true, the appropriate subroutine is called and
the
> > > code loops back for a new value of W.
> > >
> > > And yes, using a computed goto table is probably faster but
the
> > table
> > > gets ugly if there are unused values of W: 1, 3, 19, 22, 29,
234
> > for
> > > example. You would need a table with 235 entries (0..234)
most
> of
> > > which would branch to an error subroutine for invalid values.
> > >
> > > Where the values can be limited to something like [0..3] then
a
> > > computed goto table can be faster. Just be sure to forcibly
> limit
> > > them with something like ANDLW B'00000011' after the value is
> > placed
> > > in W.
> > >
> > > Something to think about later.
> > >
> > >
> > >
> > > --- In , "stephendbarnes"
> > > <stephendbarnes@h...> wrote:
> > > > The code wants to execute the first case argument it sees.
I
> have
> > > > followed it in step mode but I don't yet understand what
the
> > macro
> > > is
> > > > doing. I can comment out the first case (case 3) and it
> executes
> > > the
> > > > the first case it sees regardless of the W reg value! I'm
> stumped
> > > and
> > > > drowning!!
> > > >
> > > > Regards,
> > > > Steve > Yahoo! Groups Sponsor >
> to unsubscribe, go to http://www.yahoogroups.com and follow the
instructions
>
> Your use of Yahoo! Groups is subject to the Yahoo! Terms of
Service.


I'm not sure why the group doesn't accept your email posts. It took about eight tries before it finally posted from my email client!
 
Good suggestion concerning the self relative jumps...I've implemented that. What are your thoughts about the timing loops?
 
Regards,
Steve
----- Original Message -----
From: rtstofer
To: p...@yahoogroups.com
Sent: Saturday, April 19, 2003 10:03 PM
Subject: [piclist] Re: Need help with PIC Macros


Wonder why my email post never made it.  Strange.

OK, the only thing I would reconsider is using self-relative jumps as
in 'goto $ - 3'.  If you ever add a little debug code in the middle
of the loop that instruction will come back to bite you.  In fact,
any change in the loop is a problem.

I would consider adding 3 labels (Reverse1, Left1, Right1) as the
targets for the 3 self-relative jumps.

I like the idea of assigning names to port bits with #define.  I have
been trying to use that at every opportunity.

Looking good!

--- In p...@yahoogroups.com, "Stephen D. Barnes"
<stephendbarnes@h...> wrote:
> I agree with you. My point was that as a raw beginner in assembly
language, the easy way out has a way of making one loose sight of the
objective (learning how to code). At times, one is so focused on the
project at hand that looking at the results of the macro plays second
fiddle to enjoying the end product! What is the saying...."Know thy
self"? ;-)
> Back to the subject...I have not tried the macro example listing
you posted yet (but I will soon) because I solve this particular
problem with inline code! I have always used high level languages
when writing software for PC's, PLC's, etc., so assembly has really
made me think about new ways (to me) to solve old problems. If you
have the time, take a look at the attached file to see what I have
done. It is well commented and is a work in progress so please excuse
the time delay stuff which came from the MIT piclist examples page
(any suggestions would be welcome).
>
> Regards,
> Steve
>   ----- Original Message -----
>   From: rtstofer
>   To: p...@yahoogroups.com
>   Sent: Saturday, April 19, 2003 1:38 AM
>   Subject: [piclist] Re: Need help with PIC Macros>
>   I never think of macros as a crutch - they are a readability aid
and,
>   in some cases, an application specific instruction.  If you use
them,
>   you can learn from the emitted code and anytime you can see good
code
>   and good coding it is worthwhile.  That macro library is
excellent
>   code.
>
>   I have two Mark III Minisumo Robots - one uses modified servo
motors
>   where a bit is pulsed about 50 times per second.  The width of
the
>   pulse causes the servo to move at a speed either forward or
reverse. 
>   The other has an H bridge control and it uses the PWM output of
the
>   16F877.  So I have a macro that takes a motor, direction and
speed
>   and does conditional assembly depending on the robot I am coding
>   for.  The advantage is that the strategy of moving the robot is
>   independent of the hardware.  Just call a macro:
>
>     Motor Left, Foward, Fast
>     Motor Right, Forward, Fast
>
>   Once I know the macros work correctly I can use them as
application
>   specific instructions and not have to worry about the details. 
No
>   excess code is generated - the instructions are exactly what I
would
>   have written in either case.  But I only have to do it once.
>
>   If you write code once, fine.  If you write it twice it should be
a
>   macro or a subroutine in a library.  In my opinion only.
>
>   Let me know how it works out - the listing I posted does work
>   correctly.  None of the subroutines are actually called unless I
>   insert a statement like:
>
>   MOVLW 3 ; insert before 'select'
>
>   Good luck!
>
>   --- In p...@yahoogroups.com, "stephendbarnes"
>   <stephendbarnes@h...> wrote:
>   > Yes, it is actually calling the routine specified by the first
case
>   > it sees! I have just arrived at home and looked at your
replies.
>   > Thanks for the input. I'm going to compare my listing to yours
and
>   > correct the problem areas. In all honesty, I think I'm
attempting
>   to
>   > use the macros as a crutch...I should be learning how to write
this
>   > code first and then use the macros as a convenience. My PIC
>   projects
>   > are not work related so I've got the time to learn. I will use
the
>   > info you have given me to test my project ideas on the PIC to
see
>   if
>   > they work. Then I'm going to continue with the learning curve!
>   > Thanks for the help and I'll post what I've done for all to see.
>   >
>   > Regards,
>   > Steve
>   >
>   >
>   > --- In p...@yahoogroups.com, "rtstofer" <rstofer@p...> wrote:
>   > >
>   > > Just a thought - is the code actually calling your
subroutines or
>   > > just messing about with the xor beq stuff?  There is a bunch
of
>   > code
>   > > being executed in sequence - there is certainly no magic that
>   makes
>   > > the select statement jump to the proper case right off the
bat.
>   > >
>   > > First the code evaluates whether W is 3, if not it evaluates
>   > whether
>   > > W is 2, if not it evaluates whether W is 1, if not it loops
back
>   > and
>   > > gets a new value for W and does the process again.
>   > >
>   > > If any test is true, the appropriate subroutine is called and
the
>   > > code loops back for a new value of W.
>   > >
>   > > And yes, using a computed goto table is probably faster but
the
>   > table
>   > > gets ugly if there are unused values of W: 1, 3, 19, 22, 29,
234
>   > for
>   > > example.  You would need a table with 235 entries (0..234)
most
>   of
>   > > which would branch to an error subroutine for invalid values.
>   > >
>   > > Where the values can be limited to something like [0..3] then
a
>   > > computed goto table can be faster.  Just be sure to forcibly
>   limit
>   > > them with something like ANDLW B'00000011' after the value is
>   > placed
>   > > in W.
>   > >
>   > > Something to think about later.
>   > >
>   > >
>   > >
>   > > --- In p...@yahoogroups.com, "stephendbarnes"
>   > > <stephendbarnes@h...> wrote:
>   > > > The code wants to execute the first case argument it sees.
I
>   have
>   > > > followed it in step mode but I don't yet understand what
the
>   > macro
>   > > is
>   > > > doing. I can comment out the first case (case 3) and it
>   executes
>   > > the
>   > > > the first case it sees regardless of the W reg value! I'm
>   stumped
>   > > and
>   > > > drowning!!
>   > > >
>   > > > Regards,
>   > > > Steve>         Yahoo! Groups Sponsor
>       
>       
>
>   to unsubscribe, go to http://www.yahoogroups.com and follow the
instructions
>
>   ">Yahoo! Terms of Service.





Well, as you have no doubt discovered, timing loops consume 100% of
the CPU cycles. Maybe that is ok, maybe not. I have been using a
cooperative multi-task scheduler which doesn't take a lot of code.
Not coincidentally it uses a few macros to generate the code and
tables.

Basically, tasks are statically created at assembly time and an
interrupt routine schedules them for execution on a periodic basis.
One of the neat things is that not only do the tasks repeat every so
many clock ticks but they can be delayed an initial amount of time
and this achieves an interleave effect.

Take something as simple as flashing an LED. What happens is that
every 250 mS the flash task is scheduled by the interrupt routine and
subsequently executed by the dispatch loop. The routine itself just
alternates the state of the LED. Very fast task, just invert the
output bit and return.

A couple of other thoughts: infrared proximity sensors (Sharp GP2D12,
etc) only update every 28.7 to 37.9 mS. Then a handfull of
microseconds for the A/D conversion and the data is ready. At most
these devices need to be sampled every 14 mS. So, if there are 8 A/D
channels why not schedule it such that at every 1 mS tick a channel
is read and the value placed in an A/D array. This implies that the
latest A/D conversion of any sensor is immediately available for the
code - no time lost selecting a channel, starting a conversion and
fetching the result. Just get the value from the array! Overlap and
pipeline - these are the keys to getting a lot of processing out of a
small processor.

My interrupt routine does two things: it grabs an A/D conversion,
sticks it in an array, updates the channel selection and ultimately
starts the conversion. Second, it looks through an array of task
schedule information for a task to initiate and sets a flag for those
that are ready. One assumption is that any given task will be
complete before the next mS tick. This is pretty easy to do since
the processor can execute about 5000 instructions in a mS (generally
I am using a 20 MHz 16F87x). Now, there is the fixed overhead of the
interrupt handler and the dispatch loop that takes a certain amount
of time out of every mS tick but there is still a lot of time for
each task. This is where staggering the tasks really pays off -
assuming that every task doesn't have to be scheduled every mS.

Outside the interrupt routine is a round robin task dispatcher as the
main code for the program. It simply looks through the ready flags
and calls the various routines. No real processing being done in the
main loop - just test and call.

By creating tasks the larger problem has been partitioned into
smaller pieces that can be developed separately. Intellectually the
progam is easier to comprehend because a certain structure has been
forced on a complex problem.

So, my thoughts on delay loops are that they waste resources that
could better be used for other things like strategy and tactics and
that, in most cases, they are unnecessary. Further, eliminating them
actually simplifies the program while adding structure and clarity.

When I get home I will try to polish up what I have and see if I can
post it using MS Outlook instead of Linux sendmail.
--- In , "Stephen D. Barnes"
<stephendbarnes@h...> wrote:
> I'm not sure why the group doesn't accept your email posts. It took
about eight tries before it finally posted from my email client!
>
> Good suggestion concerning the self relative jumps...I've
implemented that. What are your thoughts about the timing loops?
>
> Regards,
> Steve
> ----- Original Message -----
> From: rtstofer
> To:
> Sent: Saturday, April 19, 2003 10:03 PM
> Subject: [piclist] Re: Need help with PIC Macros >
> Wonder why my email post never made it. Strange.
>
> OK, the only thing I would reconsider is using self-relative
jumps as
> in 'goto $ - 3'. If you ever add a little debug code in the
middle
> of the loop that instruction will come back to bite you. In
fact,
> any change in the loop is a problem.
>
> I would consider adding 3 labels (Reverse1, Left1, Right1) as the
> targets for the 3 self-relative jumps.
>
> I like the idea of assigning names to port bits with #define. I
have
> been trying to use that at every opportunity.
>
> Looking good!


Thank you. I would really like to see what you have created!
 
Regards,
Steve
----- Original Message -----
From: rtstofer
To: p...@yahoogroups.com
Sent: Sunday, April 20, 2003 1:56 PM
Subject: [piclist] Re: Need help with PIC Macros


Well, as you have no doubt discovered, timing loops consume 100% of
the CPU cycles.  Maybe that is ok, maybe not.  I have been using a
cooperative multi-task scheduler which doesn't take a lot of code. 
Not coincidentally it uses a few macros to generate the code and
tables.

Basically, tasks are statically created at assembly time and an
interrupt routine schedules them for execution on a periodic basis. 
One of the neat things is that not only do the tasks repeat every so
many clock ticks but they can be delayed an initial amount of time
and this achieves an interleave effect.

Take something as simple as flashing an LED.  What happens is that
every 250 mS the flash task is scheduled by the interrupt routine and
subsequently executed by the dispatch loop.  The routine itself just
alternates the state of the LED.  Very fast task, just invert the
output bit and return.

A couple of other thoughts: infrared proximity sensors (Sharp GP2D12,
etc) only update every 28.7 to 37.9 mS.  Then a handfull of
microseconds for the A/D conversion and the data is ready.  At most
these devices need to be sampled every 14 mS.  So, if there are 8 A/D
channels why not schedule it such that at every 1 mS tick a channel
is read and the value placed in an A/D array.  This implies that the
latest A/D conversion of any sensor is immediately available for the
code - no time lost selecting a channel, starting a conversion and
fetching the result.  Just get the value from the array!  Overlap and
pipeline - these are the keys to getting a lot of processing out of a
small processor.

My interrupt routine does two things: it grabs an A/D conversion,
sticks it in an array, updates the channel selection and ultimately
starts the conversion.  Second, it looks through an array of task
schedule information for a task to initiate and sets a flag for those
that are ready.  One assumption is that any given task will be
complete before the next mS tick.  This is pretty easy to do since
the processor can execute about 5000 instructions in a mS (generally
I am using a 20 MHz 16F87x).  Now, there is the fixed overhead of the
interrupt handler and the dispatch loop that takes a certain amount
of time out of every mS tick but there is still a lot of time for
each task.  This is where staggering the tasks really pays off -
assuming that every task doesn't have to be scheduled every mS.

Outside the interrupt routine is a round robin task dispatcher as the
main code for the program.  It simply looks through the ready flags
and calls the various routines.  No real processing being done in the
main loop - just test and call.

By creating tasks the larger problem has been partitioned into
smaller pieces that can be developed separately.  Intellectually the
progam is easier to comprehend because a certain structure has been
forced on a complex problem.

So, my thoughts on delay loops are that they waste resources that
could better be used for other things like strategy and tactics and
that, in most cases, they are unnecessary.  Further, eliminating them
actually simplifies the program while adding structure and clarity.

When I get home I will try to polish up what I have and see if I can
post it using MS Outlook instead of Linux sendmail.
--- In p...@yahoogroups.com, "Stephen D. Barnes"
<stephendbarnes@h...> wrote:
> I'm not sure why the group doesn't accept your email posts. It took
about eight tries before it finally posted from my email client!
>
> Good suggestion concerning the self relative jumps...I've
implemented that. What are your thoughts about the timing loops?
>
> Regards,
> Steve
>   ----- Original Message -----
>   From: rtstofer
>   To: p...@yahoogroups.com
>   Sent: Saturday, April 19, 2003 10:03 PM
>   Subject: [piclist] Re: Need help with PIC Macros>
>   Wonder why my email post never made it.  Strange.
>
>   OK, the only thing I would reconsider is using self-relative
jumps as
>   in 'goto $ - 3'.  If you ever add a little debug code in the
middle
>   of the loop that instruction will come back to bite you.  In
fact,
>   any change in the loop is a problem.
>
>   I would consider adding 3 labels (Reverse1, Left1, Right1) as the
>   targets for the 3 self-relative jumps.
>
>   I like the idea of assigning names to port bits with #define.  I
have
>   been trying to use that at every opportunity.
>
>   Looking good!


to unsubscribe, go to http://www.yahoogroups.com and follow the instructions

">Yahoo! Terms of Service.



Attached is the code we discussed. Thinking about it today I have decided
that since the A/D values are only used every 20 mS (by throttle and
steering code) it would be better to pull that code out of the interrupt
routine and use two tasks separated in time by a couple of mS.

The first task would grab the previous conversion, update the channel
selection and exit. A couple of mS later the second task would start the
conversion. This gives plenty of time for settling after channel selection
and the actual conversion. It also reduces the amount of overhead in the
interrupt routine.

Work in progress but maybe there are some tidbits.


Attachment (not stored)
ElectricBoat.zip
Type: application/x-zip-compressed

Thanks for the attachment. I'll be looking at it tonight.
 
Regards,
Steve
----- Original Message -----
From: rstofer
To: p...@yahoogroups.com
Sent: Monday, April 21, 2003 9:07 PM
Subject: [piclist] Re: Need help with PIC Macros


Attached is the code we discussed.  Thinking about it today I have decided
that since the A/D values are only used every 20 mS (by throttle and
steering code) it would be better to pull that code out of the interrupt
routine and use two tasks separated in time by a couple of mS.

The first task would grab the previous conversion, update the channel
selection and exit.  A couple of mS later the second task would start the
conversion.  This gives plenty of time for settling after channel selection
and the actual conversion.  It also reduces the amount of overhead in the
interrupt routine.

Work in progress but maybe there are some tidbits.


to unsubscribe, go to http://www.yahoogroups.com and follow the instructions

">Yahoo! Terms of Service.




During the 'clean-up' process at least one problem crept in. The
definition of Delay in CBLOCK has a semicolon where a colon is
required.

I started playing with the cleaned up version plus the task changes
and noted the problem.

--- In , "Stephen D. Barnes"
<stephendbarnes@h...> wrote:
> Thanks for the attachment. I'll be looking at it tonight.
>
> Regards,
> Steve
> ----- Original Message -----
> From: rstofer
> To:
> Sent: Monday, April 21, 2003 9:07 PM
> Subject: [piclist] Re: Need help with PIC Macros >
> Attached is the code we discussed. Thinking about it today I
have decided
> that since the A/D values are only used every 20 mS (by throttle
and
> steering code) it would be better to pull that code out of the
interrupt
> routine and use two tasks separated in time by a couple of mS.
>
> The first task would grab the previous conversion, update the
channel
> selection and exit. A couple of mS later the second task would
start the
> conversion. This gives plenty of time for settling after channel
selection
> and the actual conversion. It also reduces the amount of
overhead in the
> interrupt routine.
>
> Work in progress but maybe there are some tidbits.
>
> Yahoo! Groups Sponsor > to unsubscribe, go to http://www.yahoogroups.com and follow the
instructions
>
> Your use of Yahoo! Groups is subject to the Yahoo! Terms of
Service.