Advertisement
Guest User

LDGoggles

a guest
Jan 14th, 2015
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.18 KB | None | 0 0
  1. const int prescaler = 1024; // How many clock cycles it takes before the underlying timer (Timer1) increments
  2. const int timerHertz = 16000000 / prescaler; // How many times per second the underlying timer (Timer1) increments. 16,000,000 is the Arduino's clock speed
  3.  
  4. int maxTasks;
  5. unsigned long tickIntervalMs;
  6. int compareMatchRegister;
  7.  
  8. struct Task
  9. {
  10.     void (*action)(void*);
  11.         void* argument;
  12.     unsigned long delayTicks;
  13. };
  14.  
  15. struct Task** tasks;
  16.  
  17. void setupTaskScheduler(int _maxTasks, unsigned long _tickIntervalMs)
  18. {
  19.         if (tasks != NULL)
  20.     {
  21.             for (int i = 0; i < maxTasks; i++)
  22.             {
  23.                Task* task = tasks[i];
  24.                free(task);
  25.             }
  26.            
  27.             free(tasks);
  28.     }
  29.  
  30.         tickIntervalMs = _tickIntervalMs;
  31.         double interruptHertz = 1000 / _tickIntervalMs; // interruptHertz = How many times per second the caller is asking to check for and execute due tasks
  32.     maxTasks = _maxTasks;
  33.     tasks = (Task**)calloc(maxTasks, sizeof(Task*));
  34.  
  35.         compareMatchRegister = timerHertz / interruptHertz; // compareMatchRegister = when the underlying timer (Timer1) hits this value, it interrupts and then resets to zero
  36. }
  37.  
  38. int scheduleTimer1Task(void (*action)(void*), void* argument, unsigned long delayMs)
  39. {
  40.   for (int i = 0; i < maxTasks; i++)
  41.   {
  42.     if (tasks[i] == NULL)
  43.     {
  44.       Task* ptr = (Task*)malloc(sizeof(struct Task));
  45.       ptr->action = action;
  46.       ptr->argument = argument;
  47.       ptr->delayTicks = delayMs / tickIntervalMs;
  48.       tasks[i] = ptr;
  49.       return true; // Found an empty spot in the task list for this task
  50.     }
  51.   }
  52.  
  53.   return false; // No spot for this task found, scheduling request rejected
  54. }
  55.  
  56. void startSchedulerTicking()
  57. {
  58.   noInterrupts();
  59.  
  60.   TCCR1A = 0;// set entire TCCR1A register to 0
  61.   TCCR1B = 0;// same for TCCR1B
  62.   TCNT1  = 0;//initialize counter value to 0
  63.   // set compare match register for 1hz increments
  64.   OCR1A = compareMatchRegister;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  65.   // turn on CTC mode
  66.   TCCR1B |= (1 << WGM12);
  67.   // Set CS10 and CS12 bits for 1024 prescaler
  68.   TCCR1B |= (1 << CS12) | (1 << CS10);  
  69.   // enable timer compare interrupt
  70.   TIMSK1 |= (1 << OCIE1A);
  71.  
  72.   interrupts();
  73. }
  74.  
  75. // This is the timer interrupt
  76. ISR( TIMER1_COMPA_vect )
  77. {
  78.   for (int i = 0; i < maxTasks; i++)
  79.   {
  80.     if (tasks[i] != NULL)
  81.     {
  82.       Task* task = tasks[i];
  83.       unsigned long ticks = task->delayTicks;
  84.      
  85.       if (ticks == 0)
  86.       {
  87.          void (*action)(void*) = task->action;
  88.          void* argument = task->argument;
  89.          free(task);
  90.          tasks[i] = NULL;
  91.          action(argument);
  92.        }
  93.       else
  94.       {
  95.         task->delayTicks--;
  96.       }
  97.     }
  98.   }
  99. }
  100.  
  101. const unsigned long DelayMs = 30;
  102. const int AnalogOutMaxForHypnaMode = 30;
  103. const int MaxFadeMs = 2000;
  104. const int MinFadeMs = 200;
  105. const unsigned long RampUpTimeMs = 1800000; // 30 minutes
  106. const unsigned long RampUpStepIntervalMs = 10000; // 10 seconds
  107. const unsigned int NumberOfLeds = 2;
  108. const unsigned int NumberOfColorsPerLed = 3;
  109.  
  110. const unsigned long LdModeInitialDelayMs = 1200000; // 60 minutes
  111. const unsigned long LdModeDelayBetweenPulsesMs = 600000; // 10 minutes
  112. const unsigned long LdModePulseDurationMs = 10000; // 10 seconds
  113.  
  114. const int LedPins[NumberOfLeds][NumberOfColorsPerLed] =
  115. {
  116.   { 2, 3, 4 },
  117.   { 5, 6, 7 },
  118. };
  119.  
  120. double ledIncrements[NumberOfLeds][NumberOfColorsPerLed] =
  121. {
  122.   { 0, 0, 0 },
  123.   { 0, 0, 0 },
  124. };
  125.  
  126. double ledTargets[NumberOfLeds][NumberOfColorsPerLed] =
  127. {
  128.   { 0, 0, 0 },
  129.   { 0, 0, 0 },
  130. };
  131.  
  132. double ledCurrentVoltages[NumberOfLeds][NumberOfColorsPerLed] =
  133. {
  134.   { 0, 0, 0 },
  135.   { 0, 0, 0 },
  136. };
  137.  
  138. int fadeMs = MaxFadeMs;
  139. int maxOffTimeMs = fadeMs * 5;
  140. unsigned long nextLedUpdateTime = 0;
  141.  
  142. void setup()
  143. {
  144.   randomSeed(analogRead(0));
  145.   setupTaskScheduler(NumberOfLeds + NumberOfColorsPerLed + 1, DelayMs);
  146.   startSchedulerTicking();
  147.   scheduleTimer1Task(&rampUp, NULL, RampUpStepIntervalMs);
  148.  
  149.   for (int led = 0; led < NumberOfLeds; led++)
  150.   {
  151.     for (int color = 0; color < NumberOfColorsPerLed; color++)
  152.     {
  153.       pinMode(LedPins[led][color], OUTPUT);
  154.     }
  155.    
  156.     scheduleLed(led);
  157.   }
  158. }
  159.  
  160. void loop()
  161. {
  162.     // 40 Hz
  163.     delay(900000); // Comment this line out unless you want to go into 40 Hz mode
  164.     ldMode40Hz(); // Comment this line out unless you want to go into 40 Hz mode
  165.    
  166.     unsigned long mill = millis();
  167.    
  168.     if (mill > LdModeInitialDelayMs)
  169.     {
  170.       ldMode();
  171.     }
  172.  
  173.     if (mill > nextLedUpdateTime)  
  174.     {
  175.       for (int led = 0; led < NumberOfLeds; led++)
  176.       {
  177.          if (ledDo(led))
  178.          {
  179.            scheduleLed(led);
  180.          }
  181.       }
  182.    
  183.       nextLedUpdateTime = millis() + DelayMs;
  184.     }
  185. }
  186.  
  187. void ldMode()
  188. {
  189.   for (int led = 0; led < NumberOfLeds; led++)
  190.   {
  191.     for (int color = 0; color < NumberOfColorsPerLed; color++)
  192.     {
  193.       analogWrite(LedPins[led][color], LOW);
  194.     }
  195.   }
  196.  
  197.   while (true)
  198.   {
  199.     unsigned long startMillis = millis();
  200.    
  201.     while (millis() < startMillis + LdModePulseDurationMs)
  202.     {
  203.       analogWrite(2, AnalogOutMaxForHypnaMode);
  204.       analogWrite(6, AnalogOutMaxForHypnaMode);
  205.       delay(500);
  206.       analogWrite(2, LOW);
  207.       analogWrite(6, LOW);
  208.       delay(500);
  209.     }
  210.    
  211.     delay(LdModeDelayBetweenPulsesMs);
  212.   }
  213. }
  214.  
  215. void ldMode40Hz()
  216. {
  217.   while (1)
  218.   {
  219.     for (int led = 0; led < NumberOfLeds; led++)
  220.     {
  221.       for (int color = 0; color < NumberOfColorsPerLed; color++)
  222.       {
  223.         digitalWrite(LedPins[led][color], HIGH);
  224.       }
  225.     }
  226.    
  227.     delay(12);
  228.    
  229.     for (int led = 0; led < NumberOfLeds; led++)
  230.     {
  231.       for (int color = 0; color < NumberOfColorsPerLed; color++)
  232.       {
  233.         digitalWrite(LedPins[led][color], LOW);
  234.       }
  235.     }
  236.    
  237.     delay(12);
  238.   }
  239. }
  240.  
  241. void rampUp(void*)
  242. {
  243.   unsigned long mill = millis();
  244.  
  245.   if (mill > RampUpTimeMs)
  246.   {
  247.     return;
  248.   }
  249.  
  250.   double multiplier = 1.0 - ((double)mill / (double)RampUpTimeMs);
  251.   fadeMs = (multiplier * (MaxFadeMs - MinFadeMs)) + MinFadeMs;
  252.   maxOffTimeMs = map(fadeMs, MinFadeMs, MaxFadeMs, 1000, maxOffTimeMs);
  253.   scheduleTimer1Task(&rampUp, NULL, RampUpStepIntervalMs);
  254. }
  255.  
  256. // Sets the LED's increments so that it begins moving toward its target
  257. void updateLed(void* _led)
  258. {
  259.     int led = *(int*)_led;
  260.     free(_led);
  261.    
  262.     double numberOfSteps = (double)fadeMs / (double)DelayMs;
  263.    
  264.     for (int color = 0; color < NumberOfColorsPerLed; color++)
  265.     {
  266.       ledIncrements[led][color] = ledTargets[led][color] / numberOfSteps;
  267.     }
  268. }
  269.  
  270. // Sets the LED's targets and schedules a call to updateLed to start its cycle
  271. void scheduleLed(int led)
  272. {
  273.     unsigned long offTimeMs = random(0, maxOffTimeMs);
  274.    
  275.     for (int color = 0; color < NumberOfColorsPerLed; color++)
  276.     {
  277.       ledTargets[led][color] = random(1, AnalogOutMaxForHypnaMode);
  278.     }
  279.    
  280.     void* ledVoid = malloc(sizeof(int));
  281.     memcpy(ledVoid, &led, sizeof(int));
  282.     scheduleTimer1Task(&updateLed, ledVoid, offTimeMs);
  283. }
  284.  
  285. // Puts the LED back in its initial off state
  286. void resetLed(int led)
  287. {
  288.   for (int color = 0; color < NumberOfColorsPerLed; color++)
  289.   {
  290.        analogWrite(LedPins[led][color], 0);
  291.        ledCurrentVoltages[led][color] = 0;
  292.        ledIncrements[led][color] = 0;
  293.   }
  294. }
  295.  
  296. // Moves the led a step toward its final state
  297. // Returns true if the led has reached its final state and returned to its initial state (the led has cycled completely from off to on to off again)
  298. boolean ledDo(int led)
  299. {
  300.   boolean returnVal = false;
  301.  
  302.   for (int color = 0; color < NumberOfColorsPerLed; color++)
  303.   {
  304.     double increment = ledIncrements[led][color];
  305.    
  306.     int pin = LedPins[led][color];
  307.     double output = ledCurrentVoltages[led][color] + increment;
  308.    
  309.     if (increment == 0)
  310.     {
  311.        continue;
  312.     }
  313.  
  314.     if (output < 0 || returnVal)
  315.     {
  316.        resetLed(led);
  317.        return true;
  318.     }
  319.     else if (output > ledTargets[led][color])
  320.     {
  321.        ledIncrements[led][color] = -1 * increment;
  322.     }
  323.     else
  324.     {
  325.        analogWrite(pin, output);
  326.        ledCurrentVoltages[led][color] = output;
  327.     }
  328.   }
  329.  
  330.   return false;
  331. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement