summaryrefslogtreecommitdiffstats
path: root/Src/osmoconbb/src/target/firmware/layer1/sched_gsmtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/osmoconbb/src/target/firmware/layer1/sched_gsmtime.c')
-rw-r--r--Src/osmoconbb/src/target/firmware/layer1/sched_gsmtime.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/Src/osmoconbb/src/target/firmware/layer1/sched_gsmtime.c b/Src/osmoconbb/src/target/firmware/layer1/sched_gsmtime.c
new file mode 100644
index 0000000..01e22ca
--- /dev/null
+++ b/Src/osmoconbb/src/target/firmware/layer1/sched_gsmtime.c
@@ -0,0 +1,119 @@
+/* GSM-Time One-shot Event Scheduler Implementation (on top of TDMA sched) */
+
+/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <errno.h>
+
+#include <debug.h>
+#include <osmocom/core/linuxlist.h>
+
+#include <layer1/tdma_sched.h>
+#include <layer1/sched_gsmtime.h>
+
+static struct sched_gsmtime_event sched_gsmtime_events[16];
+static LLIST_HEAD(active_evts);
+static LLIST_HEAD(inactive_evts);
+
+/* Scheduling of a tdma_sched_item list one-shot at a given GSM time */
+int sched_gsmtime(const struct tdma_sched_item *si, uint32_t fn, uint16_t p3)
+{
+ struct llist_head *lh;
+ struct sched_gsmtime_event *evt, *cur;
+
+ printd("sched_gsmtime(si=%p, fn=%u)\n", si, fn);
+
+ /* obtain a free/inactive event structure */
+ if (llist_empty(&inactive_evts))
+ return -EBUSY;
+ lh = inactive_evts.next;
+ llist_del(lh);
+ evt = llist_entry(lh, struct sched_gsmtime_event, list);
+
+ evt->fn = fn;
+ evt->si = si;
+ evt->p3 = p3;
+
+ /* do a sorted insert into the list, i.e. insert the new
+ * event _before_ the first entry that has a higher fn */
+ llist_for_each_entry(cur, &active_evts, list) {
+ if (cur->fn > evt->fn) {
+ llist_add_tail(lh, &cur->list);
+ return 0;
+ }
+ }
+
+ /* if we reach here, active_evts is empty _OR_ new event
+ * is after all the other events: append at end of list */
+ llist_add_tail(lh, &active_evts);
+
+ return 0;
+}
+
+/* how many TDMA frame ticks should we schedule events ahead? */
+#define SCHEDULE_AHEAD 2
+
+/* how long do we need to tell the DSP in advance what we want to do? */
+#define SCHEDULE_LATENCY 1
+
+/* execute all GSMTIME one-shot events pending for 'fn' */
+int sched_gsmtime_execute(uint32_t fn)
+{
+ struct sched_gsmtime_event *evt, *evt2;
+ int num = 0;
+
+ llist_for_each_entry_safe(evt, evt2, &active_evts, list) {
+ if (evt->fn == fn + SCHEDULE_AHEAD) {
+ printd("sched_gsmtime_execute(time=%u): fn=%u si=%p\n", fn, evt->fn, evt->si);
+ tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY,
+ evt->si, evt->p3);
+ llist_del(&evt->list);
+ /* put event back in list of inactive (free) events */
+ llist_add(&evt->list, &inactive_evts);
+ num++;
+ } if (evt->fn > fn + SCHEDULE_AHEAD) {
+ /* break the loop as our list is ordered */
+ break;
+ }
+ }
+ return num;
+}
+
+void sched_gsmtime_init(void)
+{
+ unsigned int i;
+
+ printd("sched_gsmtime_init()\n");
+
+ for (i = 0; i < ARRAY_SIZE(sched_gsmtime_events); i++)
+ llist_add(&sched_gsmtime_events[i].list, &inactive_evts);
+}
+
+void sched_gsmtime_reset(void)
+{
+ struct sched_gsmtime_event *evt, *evt2;
+
+ llist_for_each_entry_safe(evt, evt2, &active_evts, list) {
+ llist_del(&evt->list);
+ /* put event back in list of inactive (free) events */
+ llist_add(&evt->list, &inactive_evts);
+ }
+}