aboutsummaryrefslogtreecommitdiff
path: root/AVR/queue.c
blob: f758ec93e4a4cd0a10976e5cfc984fec1209f303 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <stdint.h>
#include <string.h>
#include <stdio.h>

#include "queue.h"

static uint8_t queueStart = 0;
static uint8_t queueEnd = 0;
static uint8_t itemsInQueue = 0;

static queueItem scheduleQueue[QUEUE_DEPTH];

static int scheduleQueueGetTop(queueItem *returnItem);
static int internalScheduleFunction(queueItem pItem);

int scheduleFunction(queuedFunction pFunction, const char *pId, queue_time_t pInitialRun, queue_time_t pRecur)
{
    int rv = 0;

    queueItem newItem;
    newItem.fPtr = pFunction;
    memset(newItem.itemName, 0, NAME_LIMIT);
    memcpy(newItem.itemName, pId, strlen(pId));
    newItem.recur = pRecur;
    newItem.next = pInitialRun;

    rv = internalScheduleFunction(newItem);

    return rv;
}

int scheduleRemoveFunction(const char *pId)
{
    queueItem target;
    int rv = 0;
    for (int i = 0; i < itemsInQueue; ++i)
    {
        if(scheduleQueueGetTop(&target) == 0)
        {
            if(strcmp(target.itemName, pId) != 0)
            {
                internalScheduleFunction(target);
            }
        } else {
            rv = -1;
            break;
        }
    }

    return rv;
}

int scheduleChangeFunction(const char *pId, queue_time_t pNewNext, queue_time_t pNewRecur)
{
    queueItem target;
    int rv = 0;
    for (int i = 0; i < itemsInQueue; ++i)
    {
        if(scheduleQueueGetTop(&target) == 0)
        {
            if(strcmp(target.itemName, pId) == 0)
            {
                target.next = pNewNext;
                target.recur = pNewRecur;
            }
            internalScheduleFunction(target);
        } else {
            rv = -1;
            break;
        }
    }

    return rv;
}

int scheduleRun(queue_time_t pNow)
{
    queueItem target;
    int rv = 0;
    for (int i = 0; i < itemsInQueue; ++i)
    {
        if(scheduleQueueGetTop(&target)==0)
        {
            if(target.next <= pNow)
            {
                int tRv;
                tRv = (target.fPtr)(pNow);
                if(tRv == 0)
                {
                    rv++;
                }
                if(target.recur != 0)
                {
                    target.next = pNow + target.recur;
                    internalScheduleFunction(target);
                }
            } else {
                internalScheduleFunction(target);
            }
        } else {
            rv = -1;
            break;
        }
    }

    return rv;
}

static int scheduleQueueGetTop(queueItem *returnItem)
{
    int rv = 0;
    //Remove the top item, stuff it into returnItem
    if (queueEnd != queueStart) {
            queueItem tempQueueItem = scheduleQueue[queueStart];
            //This Algorithm also from Wikipedia.
            queueStart = (queueStart + 1) % QUEUE_DEPTH;
            *returnItem = tempQueueItem;
            itemsInQueue--;
    } else {
    //if the buffer is empty, return an error code
        rv = -1;
    }

    return rv;   
}

static int internalScheduleFunction(queueItem pItem)
{
    int rv = 0;
    if ((queueEnd + 1) % QUEUE_DEPTH != queueStart) {
        scheduleQueue[queueEnd] = pItem;
        queueEnd = (queueEnd + 1) % QUEUE_DEPTH;
        itemsInQueue++;
    } else {
        rv = -1;
    }
    return rv;
}