PropWare  3.0.0.229
C++ objects and CMake build system for Parallax Propeller
Interval.cpp
Go to the documentation of this file.
1 
9 #include <Arduino.h>
10 #include <stdio.h>
11 #include <limits.h>
12 #include "Interval.h"
13 
14 // For LMM cog 160 bytes declared as int
15 // Add enough for stack & calcs (50 bytes declared as int
16 unsigned int stack[(160 + (90 * 4)) / 4];
17 
18 Interval::Slot Interval::_slots[MAX_SLOTS];
19 volatile unsigned int Interval::_intervalCog = 0;
20 volatile unsigned int Interval::_lockID = locknew();
21 
22 /* Binds a function to an interval
23  */
24 void Interval::attach(IntervalCallback callback, uint16_t interval, void * blob)
25 {
26  // Set lock before touching the shared properties array
27  while(lockset(Interval::_lockID));
28 
29  // If cog not started, start it.
30  if (Interval::_intervalCog == 0)
31  {
32  Interval::_intervalCog = cogstart(&intervalLoop, NULL, stack, sizeof(stack)) + 1;
33  }
34 
35  // find a free Interval slot.
36  for(uint8_t i = 0; i < MAX_SLOTS; i++)
37  {
38  if (!Interval::_slots[i].isAttached())
39  Interval::_slots[i].attach(callback, interval, blob);
40  }
41 
42  // Clear lock
43  lockclr(Interval::_lockID);
44 }
45 
46 /* Releases a pin from this Interval object and resets the slot state.
47  */
48 void Interval::detach(IntervalCallback callback)
49 {
50  // Set lock.
51  while(lockset(Interval::_lockID));
52 
53  int attachedCount = 0;
54 
55  // find the Interval slot.
56  for(uint8_t i = 0; i < MAX_SLOTS; i++)
57  {
58  if (Interval::_slots[i]._callback == callback)
59  Interval::_slots[i].detach();
60 
61  if (Interval::_slots[i].isAttached())
62  attachedCount++;
63  }
64 
65  // if no more attached Slot and the cog is running,
66  // then stop the cog and record that it's stopped.
67  if (attachedCount == 0 && Interval::_intervalCog != 0)
68  {
69  cogstop(Interval::_intervalCog-1);
70  Interval::_intervalCog = 0;
71  }
72 
73  // Clear lock
74  lockclr(Interval::_lockID);
75 }
76 
77 /* Interval tending cog method.
78  */
79 void Interval::intervalLoop(void *par)
80 {
81  // Interval control loop runs until stopped.
82  while(true)
83  {
84  // For each Interval.
85  for(uint8_t i = 0; i < MAX_SLOTS; i++)
86  {
87  // Set the lock
88  while(lockset(Interval::_lockID));
89 
90  // If this Interval slot is bound to a callback
91  if (Interval::_slots[i].isAttached() && Interval::_slots[i].isDue())
92  {
93  Interval::_slots[i].invokeCallback();
94  }
95 
96  // Clear the lock.
97  lockclr(Interval::_lockID);
98  }
99  }
100 }
101 
102 boolean Interval::Slot::isDue()
103 {
104  uint32_t now = CNT;
105 
106  // if the counter hasn't wrapped then the math is simple.
107  if (now > _lastTime)
108  {
109  if (now > (_lastTime + _interval))
110  return true;
111  }
112  else
113  {
114  if ((ULONG_MAX - _lastTime + now) > _interval)
115  return true;
116  }
117 
118  return true;
119 }
Arduino.h
Provides Arduino types and functions on the Propeller.
lockset
#define lockset(lockid)
Set a lock.
Definition: propeller.h:163
lockclr
#define lockclr(lockid)
Clear lock.
Definition: propeller.h:170
cogstop
#define cogstop(a)
Stop a COG.
Definition: propeller.h:100
CNT
#define CNT
The system clock count.
Definition: propeller1.h:151
locknew
#define locknew()
Get a new lock from the pool of Propeller hardware locks.
Definition: propeller.h:147
cogstart
int cogstart(void(*func)(void *), void *par, void *stack, size_t stacksize)
Start a new propeller LMM function/thread in another COG.