Advertisement
Guest User

Untitled

a guest
Sep 8th, 2013
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.20 KB | None | 0 0
  1. #include "task.h"
  2.  
  3. #include <avr/io.h>
  4. #include <avr/interrupt.h>
  5. #include <stdlib.h>
  6.  
  7. typedef struct TaskNode_t {
  8.     void (*f)(void);
  9.     struct TaskNode_t *next;
  10.     uint16_t runTime;
  11.     uint8_t overflow;
  12. } TaskNode;
  13.  
  14. typedef struct {
  15.     TaskNode *head;
  16.     TaskNode *tail;
  17. } TaskList;
  18.  
  19. volatile bool flTask = false;
  20.  
  21. #define MAX_TASKS (20)
  22. static TaskNode nodes[MAX_TASKS];
  23.  
  24. static TaskList tasks;
  25. static TaskList freeSlots;
  26.  
  27. static volatile uint16_t ticks = 0;
  28.  
  29. void task_queue(TaskList *lst, TaskNode *task);
  30.  
  31. void task_init(TimerResolution res)
  32. {
  33.     /*
  34.      * Setup lists
  35.      */
  36.     tasks.head = NULL;
  37.     tasks.tail = NULL;
  38.    
  39.     TaskNode *last, *cur;
  40.    
  41.     last = &nodes[0];
  42.     freeSlots.head = last;
  43.    
  44.     for (int i = 1; i < MAX_TASKS; ++i) {
  45.         cur = &nodes[i];
  46.        
  47.         last->next = cur;
  48.         last = cur;
  49.     }
  50.    
  51.     last->next = NULL;
  52.     freeSlots.tail = last;
  53.    
  54.     /*
  55.      * Setup timer
  56.      *
  57.      * Clear interrupt flag
  58.      */
  59.     TIFR1 |= (1<<OCF1A);
  60.    
  61.     /*
  62.      * CTC Mode: WGM1n: 0100
  63.      * Output Disabled: COM1xn: 0
  64.      */
  65.     TCCR1A = (0<<WGM11) | (0<<WGM10);
  66.    
  67.     /*
  68.      * CTC Mode: WGM1n: 0100
  69.      *
  70.      * Clock speed:
  71.      *   20MHz system clock
  72.      *   TimerMilli:   CLK/1 (20MHz) with OCR1A = 20000 (1kHz frequency)
  73.      *   Timer100Nano: CLK/1 (20MHz) with OCR1A = 2000 (10kHz frequency)
  74.      */
  75.     TCCR1B = (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
  76.     switch (res) {
  77.         case TimerMilli:
  78.             OCR1A = 20000;
  79.             break;
  80.         case Timer100Nano:
  81.             OCR1A = 2000;
  82.             break;
  83.     }
  84.    
  85.     /*
  86.      * Enable interrupt
  87.      */
  88.     TIMSK1 = (1<<OCIE1A);
  89. }
  90.  
  91. bool task_add(void (*f)(void), uint16_t delay)
  92. {
  93.     if (!freeSlots.head) {
  94.         return false;
  95.     }
  96.  
  97.     PORTD |= (1<<PD2);
  98.    
  99.     TaskNode *task = freeSlots.head;
  100.     freeSlots.head = task->next;
  101.  
  102.     cli();
  103.  
  104.     task->runTime = ticks + delay;
  105.     task->overflow = task->runTime < ticks;
  106.  
  107.     sei();
  108.  
  109.     task->f = f;
  110.    
  111.     task_queue(&tasks, task);
  112.  
  113.     PORTD &= ~(1<<PD2);
  114.  
  115.     return true;
  116. }
  117.  
  118. void task_queue(TaskList *lst, TaskNode *task)
  119. {
  120.     if (!lst->head) {
  121.         lst->head = task;
  122.     } else {
  123.         lst->tail->next = task;
  124.     }
  125.     lst->tail = task;
  126.     task->next = NULL;
  127. }
  128.  
  129. bool task_process_next(void)
  130. {
  131.     static TaskNode *task = NULL;
  132.     static TaskNode *prev = NULL;
  133.  
  134.     if (!task) {
  135.         task = tasks.head;
  136.         prev = NULL;
  137.     }
  138.  
  139.     if (!task) {
  140.         return false;
  141.     }
  142.        
  143.     if (ticks == task->runTime || (ticks > task->runTime && !task->overflow)) {
  144.         PORTD |= (1<<PD4);
  145.  
  146.         task->f();
  147.  
  148.         PORTD &= ~(1<<PD4);
  149.  
  150.         if (prev) {
  151.             prev->next = task->next;
  152.         } else {
  153.             tasks.head = task->next;
  154.         }
  155.  
  156.         task_queue(&freeSlots, task);
  157.     } else if (ticks < task->runTime && task->overflow) {
  158.         task->overflow = 0;
  159.     }
  160.  
  161.     prev = task;
  162.     task = task->next;
  163.  
  164.     return !!task;
  165. }
  166.  
  167. /*!
  168.  * OCR1A == TCNT1 interrupt.
  169.  */
  170. ISR(TIMER1_COMPA_vect)
  171. {
  172.     ++ticks; // allow overflow
  173.     flTask = true;
  174. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement