//--------------------------- //The Help Quit Watch //--------------------------- //Nicholas Creely, nbc5 //Eric Chang, emc47 //ECE476 - Friday Lab //--------------------------- #include #include #include #include //Table to output the phrase: "Don't smoke. It's bad for you." #define TableSize0 5780 #include //Table to output the phrase: "Wake Up" #define TableSize1 1780 #include //include the LCD display #asm .equ __lcd_port = 0x15 #endasm #include char lcd_buffer[37]; //I like these definitions #define begin { #define end } //Variables for speech output flash char PCMvalue[4] = {-20, -4, 4, 20}; //Reconstruction differentials unsigned int outI, tableI; //indexes char cycle ; //decode phase counter char out, lastout; //output values char p1, p2, p3, p4 ; //hold 4 differentials char packed ; //byte containing 4 2-bit values unsigned char tsample; unsigned char mode; //0 for smoke alarm, 1 for time alarm #define t1 6250 //100ms timer (1/10 second) #define countdown 6000 //sleep timer countdown #define smoketime 6000 //smoke timer countdown #define sample 8 unsigned char slept; //if the MCU is coming out of sleep mode //variables for keeping time unsigned char hundredths, seconds, seconds10, minutes, minutes10, hours, hours10; unsigned char weekday, days, days10, months, months10, years, years10; //the time for the alarm to go off unsigned char alarm0minutes, alarm0minutes10, alarm0hours, alarm0hours10; //the status of the RTC alarm unsigned char RTCstatus, alarm0, alarm1; unsigned char onalarm; //if the arlarm is on or off //variables for SPI communication unsigned char junk, SPIin, SPIout; //Define variables for RTC read addresses #define Rseconds 0x00 #define Rminutes 0x01 #define Rhours 0x02 #define Rweekday 0x03 #define Rdays 0x04 #define Rmonths 0x05 #define Ryears 0x06 #define Ralarm0seconds 0x07 #define Ralarm0minutes 0x08 #define Ralarm0hours 0x09 #define Ralarm0weekday 0x0a #define Ralarm1seconds 0x0b #define Ralarm1minutes 0x0c #define Ralarm1hours 0x0d #define Ralarm1weekday 0x0e #define Rcontrol 0x0f #define Rstatus 0x10 //Define variables for RTC write addresses #define Wseconds 0x80 #define Wminutes 0x81 #define Whours 0x82 #define Wweekday 0x83 #define Wdays 0x84 #define Wmonths 0x85 #define Wyears 0x86 #define Walarm0seconds 0x87 #define Walarm0minutes 0x88 #define Walarm0hours 0x89 #define Walarm0weekday 0x8a #define Walarm1seconds 0x8b #define Walarm1minutes 0x8c #define Walarm1hours 0x8d #define Walarm1weekday 0x8e #define Wcontrol 0x8f #define Wstatus 0x90 //time since the last smoke unsigned char lastMinute, lastHour, lastYear; unsigned int lastDay; unsigned char fail; //number of times smoked this week unsigned char smokedweek; unsigned char smoking; //if the smoke detector is active unsigned char lastsmoke; //last smoke detector value //LCD control variables unsigned char lastpush0, lastpush1, lastpush2, lastpush3; //the last push value for the five buttons //variables for computation purposes unsigned char thishour, thisday, thismonth, thisyear; unsigned char minutescomp, hourscomp, yearscomp; unsigned int dayscomp; unsigned char i; //timers unsigned int time1, sleepin, stime; //days in every month flash unsigned char month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; flash unsigned char monthleap[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; void initialize(void); void task1(void); //task to keep time, respond to push void voice0(void); //task to handle the voice output for the smoke detector void voice1(void); //task to handle the voice output for the wake up alarm void lastSmokeCalc(void); //task to calculate the time since last smoked //timer 0 compare ISR interrupt [TIM0_OVF] void timer0_compare(void) begin //Play either of the voice samples tsample--; if(0 == tsample) begin tsample = sample; if(mode == 0) voice0(); else if(mode == 1) voice1(); end //maintain timer 1 and timer 2 if (time1>0) --time1; end //INT0 ISR (smoke detector) interrupt [EXT_INT0] void smoke_alarm(void) begin if(slept == 1) //wake up, synchronize the MCU with the RTC begin MCUCR = 0b00101010; slept = 0; //load seconds from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rseconds); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load seconds = SPIin & 0x0f; seconds10 = SPIin>>4; //load minutes from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rminutes); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load minutes = SPIin & 0x0f; minutes10 = SPIin>>4; //load hours from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rhours); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load hours = SPIin & 0x0f; hours10 = (SPIin>>4) & 0x03; //load weekday from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rweekday); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load weekday = SPIin & 0x0f; //load days from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rdays); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load days = SPIin & 0x0f; days10 = SPIin>>4; //load months from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rmonths); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load months = SPIin & 0x0f; months10 = SPIin>>4; //load years from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Ryears); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load years = SPIin & 0x0f; years10 = SPIin>>4; //Reinitialize the time since last smoke calculation thishour = 10*hours10 + hours; thisday = 10*days10 + days; thismonth = 10*months10 + months; thisyear = 10*years10 + years; lastSmokeCalc(); //A new smoke was detected, so restart the smoking timer stime = 0; end sleepin = countdown; //restart the sleep countdown smoking = 1; //raise the smoke detection flag end //INT1 ISR (push button) interrupt [EXT_INT1] void push_on(void) begin if(slept == 1) //wake up, synchronize the MCU with the RTC begin MCUCR = 0b00101010; slept = 0; //load seconds from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rseconds); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load seconds = SPIin & 0x0f; seconds10 = SPIin>>4; //load minutes from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rminutes); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load minutes = SPIin & 0x0f; minutes10 = SPIin>>4; //load hours from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rhours); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load hours = SPIin & 0x0f; hours10 = (SPIin>>4) & 0x03; //load weekday from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rweekday); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load weekday = SPIin & 0x0f; //load days from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rdays); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load days = SPIin & 0x0f; days10 = SPIin>>4; //load months from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rmonths); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load months = SPIin & 0x0f; months10 = SPIin>>4; //load years from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Ryears); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load years = SPIin & 0x0f; years10 = SPIin>>4; //Reinitialize the time since last smoke calculation thishour = 10*hours10 + hours; thisday = 10*days10 + days; thismonth = 10*months10 + months; thisyear = 10*years10 + years; lastSmokeCalc(); end sleepin = countdown; //restart the sleep countdown alarm0 = 0; //turn off the alarm if it is on end //INT2 ISR (RTC alarm) interrupt [EXT_INT2] void RTC_alarm(void) begin //load status from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rstatus); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load RTCstatus = SPIin; if(slept == 1) //wake up, synchronize the MCU with the RTC begin MCUCR = 0b00101010; slept = 0; //load seconds from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rseconds); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load seconds = SPIin & 0x0f; seconds10 = SPIin>>4; //load minutes from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rminutes); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load minutes = SPIin & 0x0f; minutes10 = SPIin>>4; //load hours from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rhours); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load hours = SPIin & 0x0f; hours10 = (SPIin>>4) & 0x03; //load weekday from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rweekday); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load weekday = SPIin & 0x0f; //load days from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rdays); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load days = SPIin & 0x0f; days10 = SPIin>>4; //load months from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Rmonths); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load months = SPIin & 0x0f; months10 = SPIin>>4; //load years from the RTC PORTB.4 = 1; //CS high begins load junk = spi(Ryears); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load years = SPIin & 0x0f; years10 = SPIin>>4; //Reinitialize the time since last smoke calculation thishour = 10*hours10 + hours; thisday = 10*days10 + days; thismonth = 10*months10 + months; thisyear = 10*years10 + years; lastSmokeCalc(); end //read from registers from alarm 0 and 1 to clear the RTC interrupt PORTB.4 = 1; //CS high begins load junk = spi(Ralarm0seconds); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load PORTB.4 = 1; //CS high begins load junk = spi(Ralarm1seconds); SPIin = spi(0x00); PORTB.4 = 0; //CS low ends load reportVdec(RTCstatus); //convert the RTC status into flags for alarm 0 (wake up alarm) and alarm 1 (end of week alarm) alarm0 = RTCstatus & 1 & onalarm; alarm1 = (RTCstatus>>1) & 1; //if it is the end of the week, reset the number of times smoked in a week if(alarm1 == 1) begin smokedweek = 0; alarm1 = 0; end //if there is a wake up alarm, play the "Wake Up" speech clip if(alarm0 == 1) begin //initialize the indexing into the speech table mode = 1; //set it to wake up mode tableI = 0; outI = 0; OCR0 = 128; tsample = sample; TCCR0 = 0b01101001; //PWM on end sleepin = countdown; //restart the MCU sleep countdown end void main(void) begin initialize(); // measure and display loop while (1) begin if(time1 == 0) task1(); end end //----------------------------TASK 1---------------------------------- //Task 1 is the main task of this program. It keeps time when the MCU //isn't in sleep mode, it initializes the speech clip telling the user //not to smoke if smoke is detected, it reads the STK pushbuttons and //carries out their functions, it handles the LCD output, and it puts //the MCU to sleep after a certain period of inactivity. //-------------------------------------------------------------------- void task1(void) begin time1 = t1; //reschedule task 1 sleepin--; //decrement the sleep timer if(stime > 0) stime--; //decrement the smoke timer //See if the user is smoking and play the speech clip to tell user to stop if(smoking == 1) begin //if there has been a minute since the last time smoke was detected, interpret it as a new cigarette if(stime == 0) begin smokedweek++; //increment the number of times smoked this week //store the time of this smoke for last smoke calculation lastMinute = minutes10*10 + minutes; lastHour = hours10*10 + hours; lastDay = (int)days10*10 + (int)days; lastYear = years10*10 + years; thismonth = (months10*10 + months); for(i = 0; i < thismonth - 1; i++) begin if(lastYear%4 == 0) lastDay = lastDay + monthleap[i]; else lastDay = lastDay + month[i]; end lastSmokeCalc(); //re-initialize the last smoke calculation end stime = smoketime; //start or restart the smoke timer //start the speech clip if it has not already started if(TCCR0 == 1) begin //initialize the speech table index mode = 0; //set it to "don't smoke" mode tableI = 0; outI = 0; OCR0 = 128; tsample = sample; TCCR0 = 0b01101001; //Turn the PWM on end end //---------Maintain time when the MCU is awake------// //Increment 1/10 seconds if(hundredths < 9) hundredths++; //Increment seconds digit else if(seconds < 9) begin hundredths = 0; seconds++; end //Increment 10 seconds digit else if(seconds10 < 5) begin hundredths = 0; seconds = 0; seconds10++; end //Increment minutes digit else if(minutes < 9) begin hundredths = 0; seconds = 0; seconds10 = 0; minutes++; end //Increment 10 minutes digit else if(minutes10 < 5) begin hundredths = 0; seconds = 0; seconds10 = 0; minutes = 0; minutes10++; end //Increment hours else if(thishour < 23) begin hundredths = 0; seconds = 0; seconds10 = 0; minutes = 0; minutes10 = 0; if(hours < 9) hours++; else //Increment the 10 hours digit begin hours = 0; hours10++; end //calculate the decimal value for hours thishour = 10*hours10 + hours; end //Increment the day of the month else if(((thisyear%4 == 0)&&(thisday < monthleap[thismonth - 1]))||((thisyear%4 > 0)&&(thisday < month[thismonth - 1]))) begin hundredths = 0; seconds = 0; seconds10 = 0; minutes = 0; minutes10 = 0; hours = 0; hours10 = 0; if(days < 9) days++; else begin days = 0; days10++; end //calculate the decimal value for hours and days thishour = 10*hours10 + hours; thisday = 10*days10 + days; end //Increment the month of the year else if(thismonth < 12) begin hundredths = 0; seconds = 0; seconds10 = 0; minutes = 0; minutes10 = 0; hours = 0; hours10 = 0; days = 1; days10 = 0; if(months < 9) months++; else begin months = 0; months10++; end //Calculate the decimal value for hours, days, and months thishour = 10*hours10 + hours; thisday = 10*days10 + days; thismonth = 10*months10 + months; end //Increment the singles digit of the year else if(years < 9) begin hundredths = 0; seconds = 0; seconds10 = 0; minutes = 0; minutes10 = 0; hours = 0; hours10 = 0; days = 1; days10 = 0; months = 1; months10 = 0; years++; //Calculate the decimal value for hours, days, months, and years thishour = 10*hours10 + hours; thisday = 10*days10 + days; thismonth = 10*months10 + months; thisyear = 10*years10 + years; end //Increment the decade else if(years10 < 9) begin hundredths = 0; seconds = 0; seconds10 = 0; minutes = 0; minutes10 = 0; hours = 0; hours10 = 0; days = 1; days10 = 0; months = 1; months10 = 0; years = 0; years10++; //Calculate the decimal value for hours, days, months, and years thishour = 10*hours10 + hours; thisday = 10*days10 + days; thismonth = 10*months10 + months; thisyear = 10*years10 + years; end //Roll over time to the earliest possible time else begin hundredths = 0; seconds = 0; seconds10 = 0; minutes = 0; minutes10 = 0; hours = 0; hours10 = 0; days = 1; days10 = 0; months = 1; months10 = 0; years = 0; years10++; thishour = 0; thisday = 1; thismonth = 1; thisyear = 0; //Calculate the decimal value for hours, days, months, and years thishour = 10*hours10 + hours; thisday = 10*days10 + days; thismonth = 10*months10 + months; thisyear = 10*years10 + years; end //----------Carry out push button functions---------------// //Button 0 is generally for changing the time if( PINA.0 == 0) begin //Button 1 + Button 2: Turn alarm on or off if(PINA.1 == 0) begin if((lastpush0 == 1) || (lastpush1 == 1)) //new push begin if(onalarm == 0) //alarm is being turned on begin onalarm = 1; //set the alarm PORTB.4 = 1; //CS high begins load junk = spi(Wcontrol); junk = spi(0b00000011); PORTB.4 = 0; //write to the LCD sprintf(lcd_buffer, "Alarm On"); lcd_clear(); lcd_puts(lcd_buffer); end else //alarm is being turned off begin onalarm = 0; //set the alarm PORTB.4 = 1; //CS high begins load junk = spi(Wcontrol); junk = spi(0b00000010); PORTB.4 = 0; //write to the LCD sprintf(lcd_buffer, "Alarm Off"); lcd_clear(); lcd_puts(lcd_buffer); end end //If the buttons are held, continue to else if(onalarm == 0) begin sprintf(lcd_buffer, "Alarm Off"); lcd_clear(); lcd_puts(lcd_buffer); end else begin sprintf(lcd_buffer, "Alarm On"); lcd_clear(); lcd_puts(lcd_buffer); end end else begin //Buttons 0&2: Change time +1 hour if((PINA.2 == 0) && (lastpush2 == 1)) //hr up is pressed begin if(thishour < 23) begin if(hours < 9) hours++; else begin hours = 0; hours10++; end end else begin hours = 0; hours10 = 0; end thishour = hours10*10 + hours; end //Buttons 0&3: Change time +1 minute else if((PINA.3 == 0) && (lastpush3 == 1)) begin if(minutes < 9) minutes++; else if(minutes10 < 5) begin minutes = 0; minutes10++; end else begin minutes = 0; minutes10 = 0; end end //Print to the LCD sprintf(lcd_buffer, "Time = %d%d:%d%d:%d%d", hours10, hours, minutes10, minutes, seconds10, seconds); lcd_clear(); lcd_puts(lcd_buffer); end sleepin = countdown; //restart the sleep timer end //Button 1 is for changing the alarm time else if (PINA.1 == 0) begin //Buttons 1&2: Change alarm time +1 hour if((PINA.2 == 0) && (lastpush2 == 1)) //hr up is pressed begin if((alarm0hours10*10 + alarm0hours) < 23) begin if(alarm0hours<9) alarm0hours++; else begin alarm0hours = 0; alarm0hours10++; end end else begin alarm0hours = 0; alarm0hours10 = 0; end end //Buttons 1&3: Change alarm time +1 minute else if((PINA.3 == 0) && (lastpush3 == 1)) //minute up is pressed begin if(alarm0minutes < 9) alarm0minutes++; else if(alarm0minutes10 < 5) begin alarm0minutes = 0; alarm0minutes10++; end else begin alarm0minutes = 0; alarm0minutes10 = 0; end end //Print to the LCD sprintf(lcd_buffer, "Alarm at %d%d:%d%d", alarm0hours10, alarm0hours, alarm0minutes10, alarm0minutes); lcd_clear(); lcd_puts(lcd_buffer); sleepin = countdown; //reset the sleep timer end //Button 2: Show time since the last smoke else if (PINA.2 == 0 ) begin //If the user has smoked this week, show how many they have smoked if(smokedweek > 0) begin sprintf(lcd_buffer, "%d this week. :( ", smokedweek); lcd_clear(); lcd_puts(lcd_buffer); end else //congratulate the user begin lcd_clear(); lcd_putsf("None this week :)"); end sleepin = countdown; //reset the sleep timer end //Button 3: Show the time since last smoked else if ( PINA.3 == 0 ) begin lastSmokeCalc(); //calculate the time since if(lastDay == 0) begin //Print to the LCD sprintf(lcd_buffer, "You haven't smoked"); lcd_clear(); lcd_puts(lcd_buffer); end else if(fail == 1) //the time since the last smoke cannot be computed because of a changed time begin //Print to the LCD sprintf(lcd_buffer, "Can't compute."); lcd_clear(); lcd_puts(lcd_buffer); end else if(yearscomp > 0) begin //Print to the LCD sprintf(lcd_buffer, "Over %d yr. YAY",yearscomp); lcd_clear(); lcd_puts(lcd_buffer); end else begin //Print to the LCD sprintf(lcd_buffer, "It has been %d d, %d hr, %d min", dayscomp, hourscomp, minutescomp); lcd_clear(); lcd_puts(lcd_buffer); end sleepin = countdown; //reset the sleep timer end //If nothing has been pressed, show the time else begin sprintf(lcd_buffer, "Time = %d%d:%d%d:%d%d", hours10, hours, minutes10, minutes, seconds10, seconds); lcd_clear(); lcd_puts(lcd_buffer); end if((PINA.0 == 1) && (lastpush0 == 0)) //time has been changed, update the RTC begin //Set up the RTC minutes value SPIout = (minutes10<<4) | (minutes & 0x0f); PORTB.4 = 1; //CS high begins load junk = spi(Wminutes); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC hours value (bit 6 set to 1 for 24-hour time keeping SPIout = (hours10<<4) | (hours & 0x0f) & 0b10111111; PORTB.4 = 1; //CS high begins load junk = spi(Whours); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load end if((PINA.1 == 1) && (lastpush1 == 0)) //alarm time has been changed, update the RTC begin //Set up the RTC Alarm 0 minutes value (bit 7 set to 0 for control) SPIout = (alarm0minutes10<<4) | (alarm0minutes & 0x0f) & 0x7f; PORTB.4 = 1; //CS high begins load junk = spi(Walarm0minutes); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC Alarm 0 hours value (bit 6 set to 0 for 24-hour time keeping, bit 7 is set to 0 for control) SPIout = (alarm0hours10<<4) | (alarm0hours & 0x0f) & 0b10111111 & 0x7f; PORTB.4 = 1; //CS high begins load junk = spi(Walarm0hours); junk = spi(SPIout); PORTB.4 = 0; end //Save the values of the push buttons for the next time going into the task lastpush0 = PINA.0; lastpush1 = PINA.1; lastpush2 = PINA.2; lastpush3 = PINA.3; //Save the value of smoking lastsmoke = smoking; smoking = 0; //If it has been over a minute since the last activity, put the MCU in sleep mode if(sleepin == 0) begin lcd_clear(); slept = 1; MCUCR = 0b10100000; //sleep enable #asm("sleep"); end end //This function calculates the time since the last smoke void lastSmokeCalc(void) begin //Initialize variables for computation minutescomp = minutes10*10 + minutes; hourscomp = hours10*10 + hours; yearscomp = 10*years10 + years; //Convert the month/day to a Julian date from 1 to 365 (366 for a leap year) dayscomp = 10*(int)days10 + (int)days; for(i = 0; i < thismonth - 1; i++) begin if(thisyear%4 == 0) dayscomp = dayscomp + monthleap[i]; else dayscomp = dayscomp + month[i]; end //Calculate minutes since the last smoke if(lastMinute <= minutescomp) minutescomp = minutescomp - lastMinute; else if(hourscomp > 0) //carry hours begin minutescomp = minutescomp + 60 - lastMinute; hourscomp = hourscomp - 1; end else if(dayscomp > 1) //carry days begin minutescomp = minutescomp + 60 - lastMinute; hourscomp = 23; dayscomp = dayscomp - 1; end else if(yearscomp > 0) //carry years begin minutescomp = minutescomp + 60 - lastMinute; hourscomp = 23; yearscomp = yearscomp - 1; if(yearscomp%4 == 0) dayscomp = 366; else dayscomp = 365; end else fail = 1; //cannot be calculated //Calculate the hours since last smoke if(lastHour <= hourscomp) hourscomp = hourscomp - lastHour; else if(dayscomp > 1) //carry days begin hourscomp = hourscomp + 24 - lastHour; dayscomp = dayscomp - 1; end else if(yearscomp > 0) //carry years begin hourscomp = hourscomp + 24 - lastHour; yearscomp = yearscomp - 1; if(yearscomp%4 == 0) dayscomp = 366; else dayscomp = 365; end else fail = 1; //cannot be calculated //Calculate days since last smoke if(lastDay <= dayscomp) dayscomp = dayscomp - lastDay; else if(yearscomp > 0) //carry years begin yearscomp = yearscomp - 1; if(yearscomp%4 == 0) dayscomp = 366 + dayscomp - lastDay; else dayscomp = 365 + dayscomp - lastDay; end else fail = 1; //cannot be calculated //Calculate years since last smoke if(lastYear <= yearscomp) yearscomp = yearscomp - lastYear; else fail = 1; //cannot be calculated end //Function to play the "Don't smoke. It's bad for you" sound clip void voice0(void) begin //compute next sample cycle = outI%4; if (cycle==0) //do we need to unpack more data? begin if (tableI>6; p2 = (packed & 48)>>4; p3 = (packed & 12)>>2; p4 = (packed & 3); tableI++ ; end //end unpack table entry //compute the output and send to PWM out = lastout + PCMvalue[p1] - lastout>>4 ; end else if (cycle==1) //don't need to unpack yet--just ouput out = lastout + PCMvalue[p2] - lastout>>4 ; else if (cycle==2) out = lastout + PCMvalue[p3] - lastout>>4 ; else if (cycle==3) out = lastout + PCMvalue[p4] - lastout>>4 ; //update outputs OCR0 = out; lastout = out; outI++; //at end, turn off TCCRO if (tableI==TableSize0) TCCR0 = 1; end //Function to play "Wake up" sound clip void voice1(void) begin //compute next sample cycle = outI%4; if (cycle==0) //do we need to unpack more data? begin if (tableI>6; p2 = (packed & 48)>>4; p3 = (packed & 12)>>2; p4 = (packed & 3); tableI++ ; end //end unpack table entry //compute the output and send to PWM out = lastout + PCMvalue[p1] - lastout>>4 ; end else if (cycle==1) //don't need to unpack yet--just ouput out = lastout + PCMvalue[p2] - lastout>>4 ; else if (cycle==2) out = lastout + PCMvalue[p3] - lastout>>4 ; else if (cycle==3) out = lastout + PCMvalue[p4] - lastout>>4 ; //update outputs OCR0 = out; lastout = out; outI++; //at end, turn off TCCRO if(alarm0 == 0) TCCR0 = 1; else if(tableI == TableSize1) begin tableI = 0; outI = 0; end end void initialize(void) begin //Set up MCUCR //Bit 7 - Sleep Enable (initialize it to 0) //Bit 6..4: 010 (power-down mode) //Bit 3..2: 10 (falling edge interrupt for the push button) INT1 //Bit 1..0: 10 (falling edge interrupt for the smoke detector) INT0 MCUCR = 0b00101010; //Set MCUCSR.6 = 0 for a falling edge interrupt from the RTC INT2 MCUCSR = 0b00000000; //Set GICR.7..5 high for INT1, INT0, INT2 GICR = 0b11100000; //Set SREG.7 (the I bit) to 1 to allow for the the interrupts to happen (I don't think we actually need this, the sei thing does this) //SREG.7 = 1; //Initialize PWM values TCCR0 = 1; TIMSK = 1; OCR0 = 128; outI = 0; tableI = 0; //Initialize smoking values smoking = 0; lastsmoke = 0; //Initialize Port C to an output for the LCD DDRC = 0xff; //Initialize Port B.3 to an output for the PWM DDRB.3 = 1; //Initialize Port A to an input for the STK push buttons DDRA = 0x00; //set up i/o data direction DDRB.4 = 1; //output chip select for ADC DDRB.5 = 1; //output MOSI DDRB.6 = 0; //input MISO is not used by the DAC DDRB.7 = 1; //output SCLK DDRB.2 = 0; //input for RTC interrupt //Initialize the SPI (CHECK THESE VALUES) SPCR = 0b01010100 ; SPSR = 1; PORTB.4 = 0; //Ititialize Port D.2 (INT0) to an in input for the smoke detector alarm DDRD.2 = 0; //Initialize Port D.3 (INT1) to an input for the on off button. DDRD.3 = 0; //Initialize the timers time1 = t1; sleepin = countdown; stime = 0; slept = 0; //start awake //Initialize alarm status RTCstatus = 0; alarm0 = 0; alarm1 = 0; lastpush0 = 1; //keep track if the button is held lastpush1 = 1; lastpush2 = 1; lastpush3 = 1; //time initialization hundredths = 0; seconds10 = 5; seconds = 5; minutes10 = 5; minutes = 9; hours10 = 2; hours = 3; weekday = 7; days10 = 0; days = 1; months10 = 0; months = 2; years10 = 0; years = 8; //Initialize decimal values for times thishour = 10*hours10 + hours; thisday = 10*days10 + days; thismonth = 10*months10 + months; thisyear = 10*years10 + years; //Initialize alarm time alarm0minutes10 = 0; alarm0minutes = 0; alarm0hours = 0; alarm0hours10 = 0; //Initialize alarm off onalarm = 0; //Initialize the number of times smoked this week smokedweek = 5; //the time of the last smoke (set day = 0 if never smoked) lastDay = 2; lastHour = 3; lastMinute = 5; lastYear = 8; //---Initialize the time since the last smoke---// if(lastDay > 0) begin fail = 0; lastSmokeCalc(); end //--------Set up the RTC------------------// //Set up the status register to disable write protect, enable the oscillator, and enable the weekly alarm PORTB.4 = 1; //CS high begins load junk = spi(Wcontrol); junk = spi(0b00000010); PORTB.4 = 0; //Set up the RTC seconds value SPIout = (seconds10<<4) | (seconds & 0x0f); //SPIout = 0x00; PORTB.4 = 1; //CS high begins load junk = spi(Wseconds); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC minutes value SPIout = (minutes10<<4) | (minutes & 0x0f); PORTB.4 = 1; //CS high begins load junk = spi(Wminutes); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC hours value (bit 6 set to 0 for 24-hour time keeping SPIout = (hours10<<4) | (hours & 0x0f) & 0b10111111; PORTB.4 = 1; //CS high begins load junk = spi(Whours); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC weekday value SPIout = weekday; PORTB.4 = 1; //CS high begins load junk = spi(Wweekday); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC date value SPIout = (days10<<4) | (days & 0x0f); PORTB.4 = 1; //CS high begins load junk = spi(Wdays); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC month value SPIout = (months10<<4) | (months & 0x0f); PORTB.4 = 1; //CS high begins load junk = spi(Wmonths); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC year value SPIout = (years10<<4) | (years & 0x0f); PORTB.4 = 1; //CS high begins load junk = spi(Wyears); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC Alarm 0 seconds value (bit 7 set to 0 for control) SPIout = 0x00; PORTB.4 = 1; //CS high begins load junk = spi(Walarm0seconds); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC Alarm 0 minutes value (bit 7 set to 0 for control) SPIout = (alarm0minutes10<<4) | (alarm0minutes & 0x0f) & 0x7f; PORTB.4 = 1; //CS high begins load junk = spi(Walarm0minutes); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load //Set up the RTC Alarm 0 hours value (bit 6 set to 0 for 24-hour time keeping, bit 7 is set to 0 for control) SPIout = (alarm0hours10<<4) | (alarm0hours & 0x0f) & 0b10111111 & 0x7f; PORTB.4 = 1; //CS high begins load junk = spi(Walarm0hours); junk = spi(SPIout); PORTB.4 = 0; //Set up the RTC Alarm 0 weekday value (bit 7 is set to 1 for control) SPIout = 0x81; PORTB.4 = 1; //CS high begins load junk = spi(Walarm0weekday); junk = spi(SPIout); PORTB.4 = 0; //Set up the RTC Alarm 1 to alarm at the beginning of every week SPIout = 0x00; PORTB.4 = 1; //CS high begins load junk = spi(Walarm1seconds); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load SPIout = 0x00; PORTB.4 = 1; //CS high begins load junk = spi(Walarm1minutes); junk = spi(SPIout); PORTB.4 = 0; //CS low ends load SPIout = 0x00; PORTB.4 = 1; //CS high begins load junk = spi(Walarm1hours); junk = spi(SPIout); PORTB.4 = 0; SPIout = 0x01; PORTB.4 = 1; //CS high begins load junk = spi(Walarm1weekday); junk = spi(SPIout); PORTB.4 = 0; //-------------------------------------------// //initialize the LCD lcd_init(16); lcd_clear(); //crank up the ISRs #asm sei #endasm end