[C.CC USERS] Button press counter

Christian Jacobsen cljacobsen at gmail.com
Sat Nov 17 10:41:12 GMT 2012


Hi Ian,

On 17 November 2012 01:55, Ian Armstrong <armstri at allegheny.edu> wrote:
> I am working on a project that involves switching LED pattern based on
> pressing a button.  I would like to have multiple "modes" that could be
> cycled through by pushing a button multiple times.  Im unsure of how to
> count the number of pushes that occur.  This is what I have so far.

Communication in occam is blocking, so when you process is waiting for
a push then it will not progress until it receives a SIGNAL from the
push channel. Thus, your code is almost correct, but there are both
some syntax and semantic errors which I'll iron out below...

> #INCLUDE "plumbing.module"
> PROC number.pushes (CHAN SIGNAL push?, CHAN INT num.pushes!)
>   CHAN INT pushes:
>   WHILE TRUE
>     IF push ? SIGNAL
>       SEQ
>         num.push := num.push +1
>         pushes ! num.push
>         IF num.push > 4
>           num.push := 0
> :

should become something like (I have also fixed the syntax of your IF,
but keep in mind that I have not run this through a compiler to check
that I actually remember occam syntax correctly!):

PROC number.pushes (CHAN SIGNAL push?, CHAN INT num.pushes!)
  CHAN INT pushes:
  WHILE TRUE
    SEQ
      push ? SIGNAL
      num.push := num.push +1
      pushes ! num.push
      IF
        num.push > 4
          num.push := 0
:

In this code the process will progress to the line 'push ? SIGNAL' and
then stop until a SIGNAL is received on the 'push' channel. Thus the
'only continue IF a communication happens' pattern which I am assuming
you were trying to express is in fact implicit in occampi. If you want
to poll in occam you have to be explicit about it.

There is however still one or two problems with this code. I'm not
sure what the "CHAN INT pushes" is doing, but I think what you are
trying to do here is define your num.push variable. You also have to
remember to set this to a an initial value, probably zero. The easiest
way to do this is to use an INITIAL declaration, but it does involve
learning a bit more occampi syntax :) You also have an issue with your
IF, in that it you must always take a branch in your IF or you will
get a runtime error at some point. The usual way this is handled is
having a branch at the end that will always be taken, using TRUE as
the conditional. If you have no code to run, you use TRUE with a SKIP
body. I have fixed the IF some more in the following code. I have also
rearranged it a bit:

PROC number.pushes (CHAN SIGNAL push?, CHAN INT pushes!)
  INITIAL INT num.push IS 0:
  WHILE TRUE
    SEQ
      push ? SIGNAL
      pushes ! num.push
      IF
        num.push > 4
          num.push := 0
        TRUE
          num.push := num.push + 1
:

You can get rid of the IF entirely by using modulo arithmetic, but
I'll leave that as an exercise for you :) This page will help:
https://www.cs.kent.ac.uk/research/groups/plas/wiki/OccamPiReference#built-in-operators
Also remember that you have to fully bracket your expressions, there
is no implicit operator precedence in occampi like you're used to in
C, Java or most other languages.

> PROC main()
>   CHAN SIGNAL s:
>   INT num.pushes:
>   CHAN INT pushes:
>   SEQ
>     serial.setup(TX0,9800)
>     PAR
>       button.press(2,s!)
>       number.pushes(s?, pushes!)
>       SEQ
>         pushes ? pushes
>         serial.write.int(TX0,pushes)
> :

You don't need the num.pushes variable in this process and another
thing to consider is how many times this process network will execute?
Consider the architecture of the parameterised process button.press
and number.pushes and how it differs from your SEQ process... run it
and see what happens and then the problem should hopefully become
quite apparent.

> I am unsure of how to implement what I have highlighted as red text.  Am I
> at least on the right track?

Yup

Hope that helps,
  Christian



More information about the users mailing list