Advertisement
bipping

TaskManager

Jun 28th, 2024
563
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.56 KB | Source Code | 0 0
  1. #include "TaskManager.h"
  2. #include <Arduino.h>
  3.  
  4. // Copyright [2024] <Bipping>
  5.  
  6. #define MAX_TASKS 10
  7. const uint32_t DEFAULT_MARGIN = 288;
  8.  
  9. uint32_t margin = DEFAULT_MARGIN;
  10.  
  11. // Utilisation des types spécifiques pour optimiser la mémoire
  12. typedef struct {
  13.     TaskFunction callback;
  14.     uint32_t interval;
  15.     uint32_t lastRun;
  16. } Task;
  17.  
  18. Task tasks[MAX_TASKS];
  19. uint8_t taskCount = 0;
  20. volatile uint8_t isrCounter = 0;
  21. volatile uint8_t remainingMicros = 0;
  22.  
  23. void addTask(TaskFunction callback, uint32_t interval) {
  24.     if (taskCount < MAX_TASKS) {
  25.         tasks[taskCount] = {callback, interval, micros()};
  26.         taskCount++;
  27.     }
  28. }
  29.  
  30. void removeTask(TaskFunction callback) {
  31.     for (int i = 0; i < taskCount; i++) {
  32.         if (tasks[i].callback == callback) {
  33.             for (int j = i; j < taskCount - 1; j++) {
  34.                 tasks[j] = tasks[j + 1];
  35.             }
  36.             taskCount--;
  37.             break;
  38.         }
  39.     }
  40. }
  41.  
  42. void changeTaskInterval(TaskFunction callback, uint32_t newInterval) {
  43.     for (int i = 0; i < taskCount; i++) {
  44.         if (tasks[i].callback == callback) {
  45.             tasks[i].interval = newInterval;
  46.             break;
  47.         }
  48.     }
  49. }
  50.  
  51. void setSleepMode(SleepMode mode) {
  52.     switch (mode) {
  53.         case IDLE_MODE:
  54.             set_sleep_mode(SLEEP_MODE_IDLE);
  55.             break;
  56.         case POWER_SAVE_MODE:
  57.             set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  58.             break;
  59.         case EXTENDED_STANDBY_MODE:
  60.             set_sleep_mode(SLEEP_MODE_EXT_STANDBY);
  61.             break;
  62.         default:
  63.             set_sleep_mode(SLEEP_MODE_IDLE);
  64.             break;
  65.     }
  66. }
  67.  
  68. void updateTasks() {
  69.     uint32_t currentTime = micros();
  70.     uint32_t nextTime = UINT32_MAX;
  71.     Task *taskQueue[MAX_TASKS];
  72.     uint8_t taskQueueCount = 0;
  73.     Task *indexFonction = nullptr;
  74.     bool executeImmediately = false;
  75.  
  76.     for (int i = 0; i < taskCount; i++) {
  77.         uint32_t scheduledTime = tasks[i].lastRun + tasks[i].interval;
  78.         if (scheduledTime <= currentTime) {
  79.             taskQueue[taskQueueCount++] = &tasks[i];
  80.             executeImmediately = true;
  81.         } else if (scheduledTime < nextTime && !executeImmediately) {
  82.             nextTime = scheduledTime;
  83.             indexFonction = &tasks[i];
  84.         }
  85.     }
  86.  
  87.     if (executeImmediately) {
  88.         currentTime = micros();
  89.         for (int i = 0; i < taskQueueCount; i++) {
  90.             taskQueue[i]->callback();
  91.             taskQueue[i]->lastRun = currentTime;
  92.             // Fin de updateTask
  93.         }
  94.     } else {
  95.         currentTime = micros();
  96.         uint32_t timeToNextTask = nextTime > currentTime ? nextTime - currentTime : 0;
  97.  
  98.         if (timeToNextTask > margin) {
  99.             uint16_t prescalerBits;
  100.             uint32_t intervalMicros = timeToNextTask - margin;
  101.             int8_t shifts;
  102.  
  103.             if (intervalMicros > 237856) {
  104.                 prescalerBits = 0x07;  // Prescaler 1024
  105.                 shifts = -6;
  106.             } else if (intervalMicros > 113338) {
  107.                 prescalerBits = 0x06;  // Prescaler 256
  108.                 shifts = -4;
  109.             } else if (intervalMicros > 51078) {
  110.                 prescalerBits = 0x05;  // Prescaler 128
  111.                 shifts = -3;
  112.             } else if (intervalMicros > 19949) {
  113.                 prescalerBits = 0x04;  // Prescaler 64
  114.                 shifts = -2;
  115.             } else if (intervalMicros > 4384) {
  116.                 prescalerBits = 0x03;  // Prescaler 32
  117.                 shifts = -1;
  118.             } else if (intervalMicros > 288) {
  119.                 prescalerBits = 0x02;  // Prescaler 8
  120.                 shifts = 1;
  121.             } else {
  122.                 prescalerBits = 0x01;  // Prescaler 1
  123.                 shifts = 4;
  124.             }
  125.  
  126.             if (shifts < 0) {
  127.                 uint8_t mask = (1UL << -shifts) - 1;
  128.                 uint8_t lostBits = intervalMicros & mask;
  129.             }
  130.  
  131.             uint32_t clockCycles = (shifts > 0) ? (intervalMicros << shifts) : (intervalMicros >> -shifts);
  132.             isrCounter = clockCycles >> 8;
  133.             uint32_t remainingCycles = clockCycles & 0xFF;
  134.  
  135.             if (remainingCycles > 0) {
  136.                 remainingMicros = remainingCycles - 1
  137.                 isrCounter++;
  138.             } else {
  139.                 remainingMicros = 0;
  140.             }
  141.  
  142.             OCR2A = isrCounter > 1 ? 0xFF : remainingMicros;
  143.             TCCR2B = (TCCR2B & 0b11111000) | prescalerBits;
  144.  
  145.             TIMSK2 |= (1 << OCIE2A);  // Enable Timer2 Compare Match A interrupt
  146.             TCCR2B |= (1 << CS22);  // Start Timer
  147.             sleep_enable();
  148.             sleep_cpu();
  149.             // Au réveil
  150.  
  151.             TCCR2B &= ~(1 << CS22);  // Stop Timer
  152.             TIMSK2 &= ~(1 << OCIE2A);  // Disable Timer2 Compare Match A interrupt
  153.             sleep_disable();
  154.  
  155.             delayMicroseconds(lostBits);
  156.  
  157.         } else {
  158.             delayMicroseconds(timeToNextTask);
  159.         }
  160.  
  161.         if (indexFonction != nullptr) {
  162.             indexFonction->callback();
  163.             indexFonction->lastRun = micros();
  164.             // Fin de updateTask
  165.         }
  166.     }
  167. }
  168.  
  169. ISR(TIMER2_COMPA_vect) {
  170.     isrCounter--;
  171.     if (isrCounter == 1) {
  172.         TCCR2B &= ~(1 << CS22);  // Stop Timer
  173.         OCR2A = remainingMicros;
  174.         TCCR2B |= (1 << CS22);  // Start Timer
  175.         sleep_cpu();
  176.     } else if (isrCounter == 0) {
  177.         TCCR2B &= ~(1 << CS22);  // Stop Timer
  178.         TIMSK2 &= ~(1 << OCIE2A);  // Disable Timer2 Compare Match A interrupt
  179.         sleep_disable();
  180.     } else {
  181.         sleep_cpu();
  182.     }
  183. }
  184.  
Tags: C++
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement