diff --git a/scheduler/Makefile b/scheduler/Makefile
new file mode 100755
index 0000000000000000000000000000000000000000..1b1fc47ac978ad8ebbcb4cd4ce4c56a4ab5c2123
--- /dev/null
+++ b/scheduler/Makefile
@@ -0,0 +1,89 @@
+# setup
+# modified by zerom for WinARM 8/2010
+
+COMPILE_OPTS = -mlittle-endian -mthumb -mthumb-interwork
+COMPILE_OPTS += -Wall -O2 -fno-common
+#COMPILE_OPTS += -Wall -g -fno-common
+COMPILE_OPTS += -ffreestanding -nostdlib
+
+COMPILE_OPTS_M4_FPU = -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mcpu=cortex-m4
+COMPILE_OPTS_M0 = -mfloat-abi=softfp -mcpu=cortex-m0
+COMPILE_OPTS_M0plus = -mfloat-abi=softfp -mcpu=cortex-m0plus
+COMPILE_OPTS_M3 = -mfloat-abi=softfp -mcpu=cortex-m3
+
+INCLUDE_DIRS = -I./include/ -I../utils/include
+
+DOC_DIR = ./doc
+
+TCHAIN_PREFIX=arm-none-eabi-
+
+CC = $(TCHAIN_PREFIX)gcc
+CFLAGS = $(COMPILE_OPTS) $(INCLUDE_DIRS)
+
+AR = $(TCHAIN_PREFIX)ar
+ARFLAGS = cr
+
+SCHEDULER_OUT_M4_FPU = ./lib/scheduler_m4_fpu.a
+SCHEDULER_OUT_M0 = ./lib/scheduler_m0.a
+SCHEDULER_OUT_M0plus = ./lib/scheduler_m0plus.a
+SCHEDULER_OUT_M3 = ./lib/scheduler_m3.a
+
+SRC_DIR=./src/
+SRC=$(wildcard $(SRC_DIR)*.c)
+
+SCHEDULER_M4_FPU_OBJ_DIR=build/m4_fpu/
+SCHEDULER_M4_FPU_OBJS_TMP = $(notdir $(SRC:.c=.o))
+SCHEDULER_M4_FPU_OBJS = $(patsubst %,$(SCHEDULER_M4_FPU_OBJ_DIR)%,$(SCHEDULER_M4_FPU_OBJS_TMP))
+
+SCHEDULER_M0_OBJ_DIR=build/m0/
+SCHEDULER_M0_OBJS_TMP = $(notdir $(SRC:.c=.o))
+SCHEDULER_M0_OBJS = $(patsubst %,$(SCHEDULER_M0_OBJ_DIR)%,$(SCHEDULER_M0_OBJS_TMP))
+
+SCHEDULER_M0plus_OBJ_DIR=build/m0plus/
+SCHEDULER_M0plus_OBJS_TMP = $(notdir $(SRC:.c=.o))
+SCHEDULER_M0plus_OBJS = $(patsubst %,$(SCHEDULER_M0plus_OBJ_DIR)%,$(SCHEDULER_M0plus_OBJS_TMP))
+
+SCHEDULER_M3_OBJ_DIR=build/m3/
+SCHEDULER_M3_OBJS_TMP = $(notdir $(SRC:.c=.o))
+SCHEDULER_M3_OBJS = $(patsubst %,$(SCHEDULER_M3_OBJ_DIR)%,$(SCHEDULER_M3_OBJS_TMP))
+
+all: $(SCHEDULER_OUT_M4_FPU) $(SCHEDULER_OUT_M0) $(SCHEDULER_OUT_M0plus) $(SCHEDULER_OUT_M3)
+$(SCHEDULER_M4_FPU_OBJ_DIR)%.o: $(SRC_DIR)%.c
+	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M4_FPU) -o $@ $<
+$(SCHEDULER_M0_OBJ_DIR)%.o: $(SRC_DIR)%.c
+	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0) -o $@ $<
+$(SCHEDULER_M0plus_OBJ_DIR)%.o: $(SRC_DIR)%.c
+	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0plus) -o $@ $<
+$(SCHEDULER_M3_OBJ_DIR)%.o: $(SRC_DIR)%.c
+	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M3) -o $@ $<
+mkdir_build: 
+	mkdir -p build/m4_fpu
+	mkdir -p build/m0
+	mkdir -p build/m0plus
+	mkdir -p build/m3
+$(SCHEDULER_OUT_M4_FPU): mkdir_build $(SCHEDULER_M4_FPU_OBJS)
+	mkdir -p lib
+	$(AR) $(ARFLAGS) $@ $(SCHEDULER_M4_FPU_OBJS)
+$(SCHEDULER_OUT_M0): mkdir_build $(SCHEDULER_M0_OBJS)
+	mkdir -p lib
+	$(AR) $(ARFLAGS) $@ $(SCHEDULER_M0_OBJS)
+$(SCHEDULER_OUT_M0plus): mkdir_build $(SCHEDULER_M0plus_OBJS)
+	mkdir -p lib
+	$(AR) $(ARFLAGS) $@ $(SCHEDULER_M0plus_OBJS)
+$(SCHEDULER_OUT_M3): mkdir_build $(SCHEDULER_M3_OBJS)
+	mkdir -p lib
+	$(AR) $(ARFLAGS) $@ $(SCHEDULER_M3_OBJS)
+
+doc: 
+	doxygen $(DOC_DIR)/doxygen.conf 
+
+clean:
+	rm -f $(SCHEDULER_M4_FPU_OBJS)
+	rm -f $(SCHEDULER_M0_OBJS)
+	rm -f $(SCHEDULER_M0plus_OBJS)
+	rm -f $(SCHEDULER_M3_OBJS)
+	rm -rf lib
+	rm -rf build
+	rm -rf doc/html
+
+.PHONY: all clean doc
diff --git a/scheduler/include/scheduler.h b/scheduler/include/scheduler.h
new file mode 100644
index 0000000000000000000000000000000000000000..cdbdae51afea7b792d61cded39081c118bf8bcbe
--- /dev/null
+++ b/scheduler/include/scheduler.h
@@ -0,0 +1,51 @@
+#ifndef _SCHEDULER_H
+#define _SCHEDULER_H
+
+#ifndef SCHEDULER_MAX_CHANNELS
+  #define SCHEDULER_MAX_CHANNELS      4
+#endif
+
+#ifndef TIM_CHANNEL_1
+  #define TIM_CHANNEL_1                      0x00000000U
+#endif
+
+#ifndef TIM_CHANNEL_2
+  #define TIM_CHANNEL_2                      0x00000004U
+#endif
+
+#ifndef TIM_CHANNEL_3
+  #define TIM_CHANNEL_3                      0x00000008U
+#endif
+
+#ifndef TIM_CHANNEL_4
+  #define TIM_CHANNEL_4                      0x0000000CU
+#endif
+
+typedef enum {SCHED_CH1=0,SCHED_CH2=1,SCHED_CH3=2,SCHED_CH4=3} sched_channel_t;
+
+typedef struct{
+  void (*function)(void);
+  unsigned char period_ms;
+  unsigned int pulse;
+  unsigned char enabled;
+}TSchedulerChannel;
+
+typedef struct{
+  TSchedulerChannel channels[SCHEDULER_MAX_CHANNELS];
+  unsigned char num_channels;
+  unsigned short int prescaler;
+  void (* start)(sched_channel_t);
+  void (* stop)(sched_channel_t);
+  void (* set_pulse)(sched_channel_t,unsigned short,unsigned char);
+}TScheduler;
+
+void scheduler_init(TScheduler *scheduler,unsigned char num_channels, unsigned short int prescaler);
+void scheduler_interrupt(TScheduler *scheduler,sched_channel_t channel_id);
+unsigned short int scheduler_get_pulse(TScheduler *scheduler, sched_channel_t channel_id);
+void scheduler_set_channel(TScheduler *scheduler,sched_channel_t channel_id, void (*function)(void), unsigned char period_ms);
+void scheduler_enable_channel(TScheduler *scheduler,sched_channel_t channel_id);
+void scheduler_change_period(TScheduler *scheduler,sched_channel_t channel_id,unsigned char period_ms);
+void scheduler_disable_channel(TScheduler *scheduler,sched_channel_t channel_id);
+
+#endif
+
diff --git a/scheduler/src/scheduler.c b/scheduler/src/scheduler.c
new file mode 100644
index 0000000000000000000000000000000000000000..a9bfd0d96ffad632eaadb31c5a7c718492d46b80
--- /dev/null
+++ b/scheduler/src/scheduler.c
@@ -0,0 +1,100 @@
+#include "scheduler.h"
+
+extern unsigned int SystemCoreClock;
+
+/* private functions */
+unsigned short int scheduler_ms_to_pulse(TScheduler *scheduler,unsigned char period_ms)
+{
+  return (SystemCoreClock/(scheduler->prescaler*1000))*period_ms;
+}
+
+unsigned int scheduler_get_channel(sched_channel_t channel_id)
+{
+  switch(channel_id)
+  {
+    case SCHED_CH1: return TIM_CHANNEL_1;
+    case SCHED_CH2: return TIM_CHANNEL_2;
+    case SCHED_CH3: return TIM_CHANNEL_3;
+    case SCHED_CH4: return TIM_CHANNEL_4;
+    default: return TIM_CHANNEL_1;
+  }
+}
+
+void scheduler_init(TScheduler *scheduler,unsigned char num_channels, unsigned short int prescaler)
+{
+  unsigned char i=0;
+
+  for(i=0;i<SCHEDULER_MAX_CHANNELS;i++)
+  {
+    scheduler->channels[i].function=0x00000000;
+    scheduler->channels[i].period_ms=0;
+    scheduler->channels[i].enabled=0x00;
+  }
+  scheduler->num_channels=num_channels;
+  scheduler->prescaler=prescaler;
+  scheduler->stop=0x00000000;
+  scheduler->start=0x00000000;
+  scheduler->set_pulse=0x00000000;
+}
+
+void scheduler_interrupt(TScheduler *scheduler,sched_channel_t channel_id)
+{
+  if(channel_id<scheduler->num_channels)
+  {
+    if(scheduler->set_pulse!=0x00000000)
+      scheduler->set_pulse(channel_id,scheduler->channels[channel_id].pulse,0x01);
+    if(scheduler->channels[channel_id].function!=0x00000000)
+      scheduler->channels[channel_id].function();
+  }
+}
+
+void scheduler_set_channel(TScheduler *scheduler,sched_channel_t channel_id, void (*function)(void), unsigned char period_ms)
+{
+  if(channel_id<scheduler->num_channels)
+  {
+    if(scheduler->channels[channel_id].enabled==0x01)
+    {
+      if(scheduler->stop!=0x00000000)
+        scheduler->stop(channel_id);
+      scheduler->channels[channel_id].enabled=0x00;
+    }
+    scheduler->channels[channel_id].function=function;
+    scheduler->channels[channel_id].period_ms=period_ms;
+    scheduler->channels[channel_id].pulse=scheduler_ms_to_pulse(scheduler,period_ms);
+  }
+}
+
+void scheduler_enable_channel(TScheduler *scheduler,sched_channel_t channel_id)
+{
+  if(channel_id<scheduler->num_channels)
+  {
+    if(scheduler->channels[channel_id].enabled==0x00)
+    {
+      if(scheduler->set_pulse!=0x00000000)
+        scheduler->set_pulse(channel_id,scheduler->channels[channel_id].pulse,0x00);
+      if(scheduler->start!=0x00000000)
+        scheduler->start(channel_id);
+      scheduler->channels[channel_id].enabled=0x01;
+    }
+  }
+}
+
+void scheduler_change_period(TScheduler *scheduler,sched_channel_t channel_id,unsigned char period_ms)
+{
+  if(channel_id<scheduler->num_channels)
+    scheduler->channels[channel_id].period_ms=period_ms;
+}
+
+void scheduler_disable_channel(TScheduler *scheduler,sched_channel_t channel_id)
+{
+  if(channel_id<scheduler->num_channels)
+  {
+    if(scheduler->channels[channel_id].enabled==0x01)
+    {
+      if(scheduler->stop!=0x00000000)
+        scheduler->stop(channel_id);
+      scheduler->channels[channel_id].enabled=0x0;
+    }
+  }
+}
+