/********************************** Nick Sitarski Vladi Gergov Project ECE 473 W 2003 Professor Shaout **********************************/ /********************************* INCLUDES **********************************/ #include #include #include #include /********************************* GLOBAL VARIABLES **********************************/ unsigned int sensor; unsigned int ontime; unsigned int offtime; unsigned int dummy; unsigned char motorstatus; unsigned char temperature; unsigned int lookuptbl[255]; /********************************* BIT MASK **********************************/ #define bit0 0x01 #define bit1 0x02 #define bit2 0x04 #define bit3 0x08 #define bit4 0x10 #define bit5 0x20 #define bit6 0x40 #define bit7 0x80 /********************************* PRAGMA STATEMENTS **********************************/ #pragma interrupt_handler ThreadSwitch() /************************************************************* Function: initialize Purpose: This function initializes the hc11 board. Powers up the A/D converter, waits untill its powered up via the 100 us delay, sets up initial fan speed to 50% duty cycle, sets motor on or off status flag to 0 meaning motor is off, and initializes the sensor variable to 256. Inputs: None Outputs: None **************************************************************/ void initialize( void ) { int i; OPTION = (OPTION | 0xC0); // Power up A/D, set csel for (i=0; i<200; i++) // Delay 100 us dummy = i; ADCTL = 0X31; // Set SCAN & MULT for the A/D ontime = 10000; // Initialize ontime to 50% duty offtime = 10000; // Initialize offtime to 50% duty motorstatus = 0; // Initialize global motor flag PORTA = 0; // Stop the motor sensor = 256; // Initialize sensor to 256 for (i=0; i<256; i++) // Fill in the lookup table for the temature using this formula lookuptbl[i] = (81.994-(40.8917*(log(i * .019531)))); // formula used to translate a/d value to tempature } /************************************************************* Function: atod Purpose: This function takes the a/d value and converts it into ontime and offtime for the thread switcher. Since our tempature sensor decreases in resistance as it gets hotter we have to account for that fact by using a simple formula. This formula takes the A/D value and subtracts 255 that way when the A/D reaches its max 255 that means that the sensor is at 0 degrees. Then we take that value and multiply it by 30 to give the threads a bigger spread in time. Inputs: None Outputs: None **************************************************************/ void atod( void ) { int i; while(1) { sensor = ADR2; // Get data from A/D converter ontime = (((256 - sensor) * 30) + 10000); // Calculate A/D value to proper ontime offtime = 20000 - ontime; // Calculate offtime from ontime temperature = lookuptbl[sensor]; // Do the table lookup for the correct tempature - // coresponding to our A/D value } } /************************************************************* Function: temp Purpose: This function goes in an delay which is used to print the tempature only at a certain interval. Inputs: None Outputs: None **************************************************************/ void temp( void ) { int i; while(1) { for(i=0; i<2000; i++); // Delay printf("\n%d",temperature); // Take a sample of the temp and print } } /************************************************************* Function: tempcheck Purpose: This function checks to see if the sensor has gotten in the critical tempeture range. If the tempature is above 50 Degrees celcius then print Too Hot on the screen. Inputs: None Outputs: None **************************************************************/ void tempcheck( void ) { while(1) { if (temperature > 50) { asm("sei"); printf("\nToo Hot"); asm("cli"); } } } /************************************************************* Structure: TCB Purpose: This structure is the thread control block which has all the info required for the Thread switch interrupt to control the stack pointer, registers, and the id of eatch thread. **************************************************************/ struct TCB { struct TCB *Next; unsigned char *SP; unsigned int ID; unsigned char MoreStack[150]; unsigned char CCR; unsigned char RegB; unsigned char RegA; unsigned int RegX; unsigned int RegY; void (*PC)(void); }; typedef struct TCB TCBType; typedef TCBType * TCBPtr; TCBType sys[3]={ { &sys[1], &sys[0].MoreStack[149], 1, { 0}, 0x40,0,0,0,0, atod, }, { &sys[2], &sys[1].MoreStack[149], 2, { 0}, 0x40,0,0,0,0, temp, }, { &sys[0], &sys[2].MoreStack[149], 4, { 0}, 0x40,0,0,0,0, tempcheck, } }; TCBPtr RunPt; /************************************************************* Function: ThreadSwitch Purpose: This function is used to switch between the three threads that we have. It also uses the motorstatus flagg to decide if our fan is off or on and schedule the interrupt accordingly. If the fan is off then it will be turned on and TOC3 will be rescheduled with ontime. If the fan is on then it will be turned off and TOC3 will be rescheduled with offtime. Inputs: None Outputs: None **************************************************************/ void ThreadSwitch( void ) { asm("ldx _RunPt\n" // Save the Stack pointer for current thread "sts 2,x"); RunPt=RunPt->Next; // Set the RunPt to point the the next thread PORTD=RunPt->ID; // Display the current Thread on PORTD asm("ldx _RunPt\n" // Load the Stack pointer for the current thread "lds 2,x"); if (motorstatus == 0) { motorstatus = 1; // Set the global fan status flag PORTA = bit6; // Turn the motor on TOC3 += ontime; // Reschedule the OC3 with ontime } else { motorstatus = 0; // Clear the global fan status flag PORTA = 0x00; // Turn the motor off TOC3 += offtime; // Reschedule the OC3 with offtime } TFLG1=0x20; // Clear the OC3 Interrupt flag } /************************************************************* Function: main Purpose: The main function calls the initialize function to set up the hc11 board, then sets up the the run pointer to go to the first thread, enables interrupts, and it also uses the motorstatus flagg to decide if our fan is off or on and schedule the interrupt accordingly. If the fan is off then it will be turned on and TOC3 will be rescheduled with ontime. If the fan is on then it will be turned off and TOC3 will be rescheduled with offtime. Also sets portd to the current interrupt. Inputs: None Outputs: None **************************************************************/ void main( void ) { initialize(); // Initialize the hc11 RunPt=&sys[0]; // Setup the pointer to point to first thread asm("sei"); // Enable interrupts TOC3vector=&ThreadSwitch; // Setup the vector jump table TFLG1 = 0x20; // Clear the OC3 Interrupt Flag TMSK1 = 0x20; // Enable the OC3 Interrupt if (motorstatus == 0) { motorstatus = 1; // Set the global fan status flag PORTA = bit6; // Turn the motor on TCNT += ontime; // Reschedule the OC3 interrupt with ontime } else { motorstatus = 0; // Clear the global fan status flag PORTA = 0x00; // Clear PortA which clears the motor TCNT += offtime; // Reschedule the OC3 interrupt with offtime } PORTD=RunPt->ID // Display the current thread on PORTD asm("ldx _RunPt\n" "lds 2,x\n" "cli\n" "rti"); }