summaryrefslogtreecommitdiffstats
path: root/mig_test/software/schedule.c
blob: 41357eb77a654609b4ce7342fd8d84c63baa11f2 (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
139
140
141
142
143
144
/*
 * $HeadURL: https://svn.fzd.de/repo/concast/FWF_Projects/FWKE/hw_sp605/bsp_zpuahb/software/schedule.c $
 * $Date$
 * $Author$
 * $Revision$
 */

#include <types.h>
#include "schedule.h"

#define MAXTIMERS    10
#define T_FREE      254                     // > MAXTIMERS
#define T_LAST      255

typedef struct{
    uint8_t next;                           // next in list or end mark
    t_res   delta;                          // delta to previous entry
    funcp   func;
} t_ctrl_struct;


t_ctrl_struct t_ctrl_lst[MAXTIMERS];
t_res   t_delay;                            // count down until next service
uint8_t t_first;                            // point to first entry


void scheduler_task_check(void)
{
    t_ctrl_struct  *p;                      // for faster access

    --t_delay;
    while( t_delay == 0 ){                  // serve if delay = 0
        if( t_first == T_LAST )             // no function to serve
            break;
        p = &t_ctrl_lst[t_first];
        t_first = p->next;                  // point to next
        p->next = T_FREE;                   // mark free
        t_delay = t_ctrl_lst[t_first].delta; // next delay delta
        p->func();                          // execute function
    }
}


uint8_t scheduler_task_add( funcp func, t_res delay )
{
    uint8_t n;
    uint8_t i;                              // index
    uint8_t ipre;                           // previous index
    t_res d1;                               // last delta delay
    t_ctrl_struct  *p;                      // for faster access

    for( n = 0;; ){
        p = &t_ctrl_lst[n];
        if( p->next == T_FREE )
            break;
        n++;
        if( n == MAXTIMERS )
            return 1;                       // error, list full
    }

    i = t_first;
    d1 = t_delay;
    while( i != T_LAST ){                   // check until end
        if( d1 >= delay ){                  // last >= new
            t_ctrl_lst[i].delta = d1 - delay; // correct following entry
            break;
        }else{
            delay -= d1;                    // remaining delay
            ipre   = i;                     // previous entry
            i      = t_ctrl_lst[i].next;    // index of next entry
            d1     = t_ctrl_lst[i].delta;   // next delay delta
        }
    }                                       // insert new entry

    p->next  = i;                           // following entry
    p->delta = delay;                       // store remaining delay
    p->func  = func;

    if( i == t_first ){                     // insert at first
        t_first = n;
        t_delay = delay;
    }else{
        t_ctrl_lst[ipre].next = n;          // previous entry
    }
    return 0;                               // successful
}


uint8_t scheduler_task_remove( funcp func )
{
    uint8_t ipre;                           // previous index
    uint8_t irem;                           // index to be removed
    uint8_t ifol = t_first;                 // following index
    t_ctrl_struct  *p;                      // for faster access

    do{
        if( ifol == T_LAST )
            return 1;                       // not found
        ipre = irem;
        irem = ifol;
        p = &t_ctrl_lst[irem];
        ifol = p->next;                     // get next
    }while( p->func != func );              // found it

    p->next = T_FREE;                       // mark it as free
    if( irem == t_first ){
        t_first = ifol;                     // serve next entry
        t_delay += t_ctrl_lst[ifol].delta;  // correct current delta
    }else{
        t_ctrl_lst[ipre].next = ifol;       // skip index
        if( ifol != T_LAST )                // correct following delta
            t_ctrl_lst[ifol].delta += p->delta;
    }
    return 0;                               // successful
}


void scheduler_init(void)
{
    uint8_t i;

    for( i = MAXTIMERS; i; i-- )
        t_ctrl_lst[i-1].next = T_FREE;      // mark all free
    t_first = T_LAST;                       // set no timer served
}


uint32_t scheduler_tasklist( void)
{
    uint8_t i;

    for( i = MAXTIMERS; i; i-- )
    {
        if ( t_ctrl_lst[i-1].next != T_FREE)
        {
            putint( i);
            putstr(":  func: ");
            puthex( 32, t_ctrl_lst[i-1].func);
            putchar('\n');
        }
    }

    return 0;
}
OpenPOWER on IntegriCloud