int arrayMin(int *a, int size, int min, int index) { if (index == size - 1) { return min; } else { min = min < a[index] ? min : a[index]; index++; } return arrayMin(a, size, min, index); }
/*Fills taskList until it's full. With current implementation it makes sure that the list is really full when it stops the refilling, even if some recently calculated values have been used already. This allows for slightly longer independent execution of tasks in the interrupts, but may cause an infinite loop, if the tasks are executed faster than new tasks can be added. So make sure you have few enough motors that move slowly enough.*/ void StepperControl::fillTaskList(uint16_t mask){ uint16_t nextTimeAction = 0; //Each bit indicates a motor that will be moved after nextTaskTime. unsigned long nextTaskTime = 0; //Gives the amount of time before the next time something happens. int nextTaskTimeIndex = 0; //Index of the lowest value in nextStep that isn't 0. //Adds entries to the buffer as long as there is any space available. //If calculationIndex == executionIndex, means that the execution has caught up with the calculation. //If that is the case, bufferCheck() will return 0, but the calculation has to continue. while(bufferCheck() || calculationIndex == executionIndex){ //Calculate the time until next step for each motor that is moved now. for(int i = 0; i < motorsCount; i++){ if(nextStep[i] <= minimumTimerInterval && !(mask & (1 << i))) calculateNextStepTime(i, nextStep); } nextTaskTimeIndex = arrayMin(nextStep, motorsCount, minimumTimerInterval); if(nextTaskTimeIndex == -1) mask = 0xFFFF; //If there is no movement to be done, set mask to disable all motors. else nextTaskTime = nextStep[nextTaskTimeIndex]; //Adding the time values to the buffer. if(mask != 0xFFFF){ taskList[0][calculationIndex%bufferSize] = nextTaskTime%0x10000; //Remaining time after all overflows are done. taskList[1][calculationIndex%bufferSize] = (nextTaskTime/0x10000)+1; //Timer overflow count +1. } //Subtracts the previously determined lowest time before next step from the waiting time of each motor. //For each motor that reached minimumTimerInterval (has to be moved at this time), the nextTimeAction flag is set to 1. nextTimeAction = 0; //Resetting the action. for(int i = 0; i < motorsCount; i++){ if(nextStep[i] > minimumTimerInterval) nextStep[i] -= nextTaskTime; if(nextStep[i] <= minimumTimerInterval && !(mask & (1 << i))){ stepsCounterCalc++; nextTimeAction |= (1 << i); } } //Copying action flags to the buffer. taskList[2][calculationIndex%bufferSize] = nextTimeAction; //Debug output. /*Serial.print(calculationIndex); Serial.print(" "); Serial.print(executionIndex); Serial.print(" "); Serial.print(taskList[0][calculationIndex%bufferSize]); Serial.print(" "); Serial.print(taskList[1][calculationIndex%bufferSize]); Serial.print(" "); Serial.println(taskList[2][calculationIndex%bufferSize]);*/ calculationIndex++; } }
/*Moves the motors simultaneously the number of steps given in the array. The motors will start and stop at the same time, no matter the selected speed and number of steps (the motor that would take the longest is taken as reference, and the speed of other motors adjusted accordingly).*/ int StepperControl::moveAll(long *stepsE){ movementCompleted = 0; //Resetting status. int exitStatus = 0; //Return value of the external function that can be added to the loop. uint16_t mask = 0; //Each bit contains info about what motor will be disabled (1 disabled, 0 enabled). long steps[motorsCount]; //Local array containing the number of steps to be executed by each motor. if(steps != NULL) memcpy(steps, stepsE, motorsCount*sizeof(long)); else return 2; //End function if the given array is not valid. long minMovementDuration; //The lowest amount of time the slowest motor (or the one with the most steps to do) will need to complete it's movement. long durations[motorsCount]; //Used for calculation of time-dependent values. Has different contents. int slowestMotor = 0; //Index of the motor of which the movement will take the longest. int dir[motorsCount]; //Contains movement direction of the motors. totalSteps = 0; //Resetting the number of steps to be done. int slMin; //Index of the motor with the lowest signalLength value among the active ones. unsigned long *slp; //Points to a copy of signalLength. slp = (unsigned long*)calloc(motorsCount, sizeof(unsigned long)); memcpy(slp, signalLength, motorsCount*sizeof(unsigned long)); //Sloppy (signalLength has type long*), but if signalLength contains negative values, there is a bigger problem. //The direction pins of all motors are set here depending on whether or not the number of steps is negative. //The total number of state changes to be done is also calculated here. for(int i = 0; i < motorsCount; i++){ if(steps[i] < 0){ dir[i] = 1; steps[i] = -steps[i]; }else{ dir[i] = 0; } totalSteps += steps[i]; setDir(i, dir[i]); //Setting the correct values to the direction pins. durations[i] = movementTime[i] * steps[i]; if(!steps[i]){ mask |= (1 << i); slp[i] = 0; //Causes arrayMin in the next step to ignore the motors that will be inactive. } } totalSteps = totalSteps*2; //Set starting conditions (without this part the signal polarity can be wrong). slMin = arrayMin(slp, motorsCount, 0); for(int i = 0; i < motorsCount; i++){ if(signalLength[i] > signalLength[slMin] && !(mask & (1 << i))){ stepStatus[i] = 1; currentState[i] = 1; }else{ stepStatus[i] = 0; currentState[i] = 0; } } free(slp);//We won't need slp any more. //Here, the form and duration of the impulses is determined. slowestMotor = arrayMax(durations, motorsCount); minMovementDuration = durations[slowestMotor]; for(int i = 0; i < motorsCount; i++){ durations[i] = minMovementDuration / steps[i]; if(durations[i] > signalLength[i]) durations[i] -= signalLength[i]; else durations[i] = 0; if(durations[i] > 0){ lowTime[i] = (long)((clockFrequency/(64*(1000000.0/durations[i])))); highTime[i] = (long)((clockFrequency/(64*(1000000.0/signalLength[i])))); }else{ lowTime[i] = 0; highTime[i] = 0; } } //Actual movement starts to happen here. //Setting all motors to HIGH at start. taskList[3][0] = 0xFFFF; fillTaskList(mask);//Preparing the buffer. enableInterrupt();//Starting movement. while(!movementCompleted){ //if(idleCounter) Serial.println(idleCounter); //debug exitStatus = repeatInLoop(); //External function to be executed during the movement. if(exitStatus == 1) break; //If the external function returns 1, the movemen stops. fillTaskList(mask); } disableInterrupt();//Stopping interrupts, so that they won't interfere with the program. //Movement ended, resetting values. stepsCounter = 0; stepsCounterCalc = 0; movementCompleted = 0; executionIndex = 0; calculationIndex = 1; clearTaskList(); for(int i = 0; i < motorsCount; i++){ //individualStepsCounter[i] = 0; //Use resetIndividualStepsCounter() instead. currentState[i] = 0; stepStatus[i] = 0; nextStep[i] = 0; } return exitStatus; }
void pageit(Pentry q[MAXPROCESSES]) { /* This file contains the stub for an LRU pager */ /* You may need to add/remove/modify any part of this file */ //printf("%ld",processes[0]->pid); /* Static vars */ static int initialized = 0; //static int tick = 1; // artificial time //printf("here\n"); /* Local vars */ int proctmp; int minPageTwo; int secondMinPageOne; int secondMinPageTwo; int pagetmp; int secondMaxPage; int secondsecondMaxPage; int pc; int page; static int procount=0; int min; int pageOne; int predOne; int predTwo; int predThree; int swapRow=0; int swapCol=0; int tmppage; int proc; int pageTwo; int minPage; int i; int minPageOne; /* initialize static vars on first run */ if(!initialized){ for(proctmp=0; proctmp < MAXPROCESSES; proctmp++){ for(pagetmp=0; pagetmp < MAXPROCPAGES; pagetmp++){ timestamps[proctmp][pagetmp] = 0; pageLastRemovedAt[proctmp][pagetmp]=0; numberofpagesout=0; for(i=0; i<2;i++){ betRevlentPage[proctmp][pagetmp][i]=0; } for(i=0;i<MAXPROCPAGES;i++){ revelentPageFreq[proctmp][pagetmp][i]=0; } } lastPageCalled[proctmp]=0; } tick=1; prevtick=0; initialized = 1; } //pager(); for(proc=0; proc <MAXPROCESSES; proc++){ //printf("1\n"); if(q[proc].active){ //printf("2\n"); pc = q[proc].pc; page=pc/PAGESIZE; /*if(procount>=4){ pager(q); }*/ timestamps[proc][page] = tick; tmppage=lastPageCalled[page]; betRevlentPage[proc][tmppage][1]=betRevlentPage[proc][tmppage][0]; betRevlentPage[proc][tmppage][0]=page; predOne=betRevlentPage[proc][page][0]; predTwo=betRevlentPage[proc][predOne][0]; predThree=betRevlentPage[proc][predTwo][0]; revelentPageFreq[proc][tmppage][page]++; lastPageCalled[proc]=page; pageOne=arrayMax(proc,page,&secondMaxPage); pageTwo=arrayMax(proc,pageOne,&secondsecondMaxPage); minPageOne=arrayMin(q,proc,page,&secondMinPageOne); minPageTwo=arrayMin(q,proc,pageOne,&secondMinPageTwo); minPage=lru(q,proc,page); pagein(proc,page); pagein(proc,pageTwo); pagein(proc,pageOne); /*if(secondMaxPage!=-100 && secondMaxPage!=secondMinPageOne){ pagein(proc,secondMaxPage); if(secondMinPageOne!=-100){ pageout(proc, secondMinPageOne); } } if(secondMaxPage!=-100 && secondMaxPage!=secondMinPageTwo){ pagein(proc,secondsecondMaxPage);* if(secondMinPageTwo!=-100){ pageout(proc,secondMinPageTwo); } }*/ //pagein(proc,predThree); //pagein(proc,predTwo); //pagein(proc,predOne); if(!q[proc].pages[page]){ effChecker(proc,page); if(!pagein(proc,page)){ pageout(proc,minPage); pageout(proc,minPageOne); pageout(proc,minPageTwo); if(secondMinPageTwo!=-100){ pageout(proc,secondMinPageTwo); } if(secondMinPageOne!=-100){ pageout(proc, secondMinPageOne); } }else if(!pagein(proc,pageTwo)){ pageout(proc,minPage); pageout(proc,minPageOne); if(secondMinPageTwo!=-100){ pageout(proc,secondMinPageTwo); } if(secondMinPageOne!=-100){ pageout(proc, secondMinPageOne); } }else if(!pagein(proc,pageOne)){ //pageout(proc,minPage); pageout(proc,minPage); pageout(proc,minPageOne); pageout(proc,minPageTwo); //pageout(proc,minPageOne); if(secondMinPageTwo!=-100){ pageout(proc,secondMinPageTwo); } if(secondMinPageOne!=-100){ pageout(proc, secondMinPageOne); } } } }else{//remove all things related to the process if not active for(i=0;i<MAXPROCPAGES;i++){ pageout(proc,i); procount++; } } } /* TODO: Implement LRU Paging */ //pager(q); /* advance time for next pageit iteration */ pager(q); tick++; }