#include "config.h" #include "tft_master.h" #include "tft_gfx.h" // threading library #include "pt_cornell_1_2_1.h" #include #include #include #include typedef int bool; #define true 1 #define false 0 //set pulldown for PORTA RA2 and RA3 and RA4 #define EnablePullDownA(bits) CNPDACLR=bits; CNPDASET=bits; #define DisablePullDownA(bits) CNPDACLR=bits; #define NoPush 0 #define MaybePush 2 #define Pushed 1 #define MaybeNoPush 3 //color for display #define ILI9340_BLACK 0x0000 #define ILI9340_BLUE 0x001F #define ILI9340_RED 0xF800 #define ILI9340_GREEN 0x07E0 #define ILI9340_CYAN 0x07FF #define ILI9340_MAGENTA 0xF81F #define ILI9340_YELLOW 0xFFE0 #define ILI9340_WHITE 0xFFFF char buffer[60]; char buffer0[60]; char buffer1[60]; char buffer2[60]; char buffer3[60]; char bufferm[60]; void printLine(int line_number, char* print_buffer, short text_color, short back_color){ int v_pos; v_pos = line_number * 10 ; // erase the pixels tft_fillRoundRect(0, v_pos, 320, 10, 1, back_color);// x,y,w,h,radius,color tft_setTextColor(text_color); tft_setCursor(0, v_pos); tft_setTextSize(1); tft_writeString(print_buffer); } // === thread structures ============================================ // thread control structs static struct pt pt_time, pt_display, pt_linear; //static struct pt_PWM; // system 1 second interval tick int sys_time_seconds ; //The actual period of the wave int generate_period = 40000 ; int pwm_on_time = 40000; int testButton1, testButton2, testButton3; int buttonCount=1, buttonCount2=0; int temp=1; int i=0, j=0, k=0; int manualMode=0, ToppingMode=0; int x=0, linear =0; // == Timer 2 ISR ===================================================== void __ISR(_TIMER_2_VECTOR, ipl2) Timer2Handler(void) { mT2ClearIntFlag(); } static PT_THREAD (protothread_display(struct pt *pt)) { PT_BEGIN(pt); static int line_count=0; static unsigned short text_color, back_color ; text_color = ILI9340_WHITE; back_color = ILI9340_BLUE; tft_setTextColor(text_color); static int PushState; while (1){ testButton2 = mPORTAReadBits(BIT_3); //when press button 2, testButton2 = 1 if (testButton2>0){ manualMode=1; //change to manual mode } if (manualMode==1){ testButton1 = mPORTAReadBits(BIT_2); i=testButton1; //move to next value tft_setCursor(0, 0); //Debounce state machine switch(PushState) { case NoPush: if (i > 0) { PushState = MaybePush; k = i; } else PushState = NoPush; break; case MaybePush: if (i == k){ PushState = Pushed; buttonCount++; } else PushState = NoPush; break; case Pushed: if (i == k){ PushState = Pushed; } else PushState = MaybeNoPush; break; case MaybeNoPush: if (i == k) PushState = Pushed; else PushState = NoPush; break; } if (buttonCount==1) { //move highlight to Kristen if (temp ==1){ tft_setCursor(10, 10); sprintf(buffer0,"Please select your topping mode"); //print time on LCD printLine(1, buffer0, ILI9340_WHITE, ILI9340_BLACK); //each line 10pixel seperate tft_setCursor(30, 10); sprintf(buffer1,"Kristen's Mode "); printLine(3, buffer1, text_color, back_color); tft_setCursor(50, 10); sprintf(buffer2,"May's Mode "); printLine(5, buffer2, ILI9340_WHITE, ILI9340_BLACK); //each line 10pixel seperate tft_setCursor(70, 10); sprintf(buffer3,"Ezra's Mode"); printLine(7, buffer3, ILI9340_WHITE, ILI9340_BLACK); //each line 10pixel seperate temp++; } testButton3 = mPORTAReadBits(BIT_4); //when press button 2, testButton2 = 1 if (testButton3>0){ ToppingMode=1; //Start Kristen's mode tft_fillRoundRect(0,150, 320, 30, 1, ILI9340_BLACK);// x,y,w,h,radius,color tft_setCursor(0, 150); sprintf(bufferm,"Kristen's Mode START!!!"); tft_setTextSize(2); tft_writeString(bufferm); //Add values of Kristen's mode ///////////Step 0: Check the motor for one round spin // mPORTBSetBits(BIT_3); //dc motor start spinning // PT_YIELD_TIME_msec(2500); // 1 round of the motor // mPORTBClearBits(BIT_3); // PT_YIELD_TIME_msec(3000); /////////////////////////Step1: The bowl start spinning mPORTBSetBits(BIT_3); //dc motor start spinning PT_YIELD_TIME_msec(3000); /////////////////////////Step2: Stepper motor works moving the whip cream container //stepper motor makes the whip cream moving in mPORTBClearBits(BIT_15); //dir pin x=0; for(x = 0; x < 500; x++ ){ mPORTBSetBits(BIT_10); //step pin PT_YIELD_TIME_msec(1); mPORTBClearBits(BIT_10); PT_YIELD_TIME_msec(1); } /////////////////////////Step3: While the stepper is working, the whip cream servo works SetPulseOC2(0, 2900); //servo1 for whip cream start pressing PT_YIELD_TIME_msec(500); /////////////////////////Step4: Keep moving in and pressing the whip cream until it reach the center of a bowl. x=0; for(x = 0; x < 1500; x++ ){ mPORTBSetBits(BIT_10); //step pin PT_YIELD_TIME_msec(1); mPORTBClearBits(BIT_10); PT_YIELD_TIME_msec(1); } //PT_YIELD_TIME_msec(1000); //The stepper motor is at the center and the whip cream servo still pressing /////////////////////////Step5: A whip cream servo stops. SetPulseOC2(0, 1200); // A whip cream servo stops /////////////////////////Step6: The stepper motor moving back x=0; mPORTBSetBits(BIT_15); //changes rotation direction for(x = 0; x < 2000; x++ ){ mPORTBSetBits(BIT_10); //step pin PT_YIELD_TIME_msec(1); mPORTBClearBits(BIT_10); PT_YIELD_TIME_msec(1); } mPORTBClearBits(BIT_10); /////////////////////////Step7: The fluid topping pump starts and stops mPORTBSetBits(BIT_8); //pump starts PT_YIELD_TIME_msec(5000); mPORTBClearBits(BIT_8); // pump stops PT_YIELD_TIME_msec(3000); /////////////////////////Step8: The dry topping servo works. //servo 2 for dry topping SetPulseOC3(0, 1200); //topping flow PT_YIELD_TIME_msec(2500); SetPulseOC3(0, 2100); /////////////////////////Step9: The bowl stop spinning mPORTBClearBits(BIT_3); //dc motor stop spinning tft_fillRoundRect(0,150, 320, 30, 1, ILI9340_BLACK);// x,y,w,h,radius,color tft_setCursor(0, 150); sprintf(bufferm,"Kristen's Mode FINISH!!!"); tft_setTextSize(2); tft_writeString(bufferm); } } linear=0; if (buttonCount==2) { if (temp ==2){ tft_setCursor(10, 10); sprintf(buffer0,"Please select your topping mode"); //print time on LCD printLine(1, buffer0, ILI9340_WHITE, ILI9340_BLACK); //each line 10pixel seperate tft_setCursor(30, 10); sprintf(buffer1,"Kristen's Mode "); printLine(3, buffer1, ILI9340_WHITE, ILI9340_BLACK); //each line 10pixel seperate tft_setCursor(50, 10); sprintf(buffer2,"May's Mode "); printLine(5, buffer2, text_color, back_color); tft_setCursor(70, 10); sprintf(buffer3,"Ezra's Mode"); printLine(7, buffer3, ILI9340_WHITE, ILI9340_BLACK); //each line 10pixel seperate temp++; } testButton3 = mPORTAReadBits(BIT_4); //when press button 2, testButton2 = 1 if (testButton3>0){ ToppingMode=2; //Start May's mode tft_fillRoundRect(0,150, 320, 30, 1, ILI9340_BLACK);// x,y,w,h,radius,color tft_setCursor(0, 150); sprintf(bufferm,"May's Mode START!!!"); tft_setTextSize(2); tft_writeString(bufferm); //Add values of May's mode ///////////Step 0: Check the motor for one round spin // mPORTBSetBits(BIT_3); //dc motor start spinning // PT_YIELD_TIME_msec(3000); // 1 round of the motor // mPORTBClearBits(BIT_3); // PT_YIELD_TIME_msec(3000); /////////////////////////Step1: The bowl start spinning mPORTBSetBits(BIT_3); //dc motor start spinning PT_YIELD_TIME_msec(3000); /////////////////////////Step2: Stepper motor works moving the whip cream container //stepper motor makes the whip cream moving in mPORTBClearBits(BIT_15); //dir pin x=0; for(x = 0; x < 250; x++ ){ mPORTBSetBits(BIT_10); //step pin PT_YIELD_TIME_msec(1); mPORTBClearBits(BIT_10); PT_YIELD_TIME_msec(1); } /////////////////////////Step3: While the stepper is working, the whip cream servo works SetPulseOC2(0, 2900); //servo1 for whip cream start pressing PT_YIELD_TIME_msec(500); /////////////////////////Step4: Keep moving in and pressing the whip cream until it reach the center of a bowl. x=0; for(x = 0; x < 500; x++ ){ mPORTBSetBits(BIT_10); //step pin PT_YIELD_TIME_msec(1); mPORTBClearBits(BIT_10); PT_YIELD_TIME_msec(1); } //PT_YIELD_TIME_msec(1000); //The stepper motor is at the center and the whip cream servo still pressing /////////////////////////Step5: A whip cream servo stops. SetPulseOC2(0, 1200); // A whip cream servo stops /////////////////////////Step6: The stepper motor moving back x=0; mPORTBSetBits(BIT_15); //changes rotation direction for(x = 0; x < 750; x++ ){ mPORTBSetBits(BIT_10); //step pin PT_YIELD_TIME_msec(1); mPORTBClearBits(BIT_10); PT_YIELD_TIME_msec(1); } mPORTBClearBits(BIT_10); /////////////////////////Step7: The fluid topping pump starts and stops // mPORTBSetBits(BIT_8); //pump starts // PT_YIELD_TIME_msec(5000); // mPORTBClearBits(BIT_8); // pump stops // PT_YIELD_TIME_msec(3000); /////////////////////////Step8: The dry topping servo works. //servo 2 for dry topping SetPulseOC3(0, 1200); //topping flow PT_YIELD_TIME_msec(1000); SetPulseOC3(0, 2100); PT_YIELD_TIME_msec(500); SetPulseOC3(0, 1200); //topping flow PT_YIELD_TIME_msec(1000); SetPulseOC3(0, 2100); PT_YIELD_TIME_msec(500); SetPulseOC3(0, 1200); //topping flow PT_YIELD_TIME_msec(1000); SetPulseOC3(0, 2100); PT_YIELD_TIME_msec(500); /////////////////////////Step9: The bowl stop spinning mPORTBClearBits(BIT_3); //dc motor stop spinning tft_fillRoundRect(0,150, 320, 30, 1, ILI9340_BLACK);// x,y,w,h,radius,color tft_setCursor(0, 150); sprintf(bufferm,"May's Mode FINISH!!!"); tft_setTextSize(2); tft_writeString(bufferm); } } if (buttonCount==3) { if (temp ==3){ tft_setCursor(10, 10); sprintf(buffer0,"Please select your topping mode"); //print time on LCD printLine(1, buffer0, ILI9340_WHITE, ILI9340_BLACK); //each line 10pixel seperate tft_setCursor(30, 10); sprintf(buffer1,"Kristen's Mode "); printLine(3, buffer1, ILI9340_WHITE, ILI9340_BLACK); //each line 10pixel seperate tft_setCursor(50, 10); sprintf(buffer2,"May's Mode "); printLine(5, buffer2, ILI9340_WHITE, ILI9340_BLACK); //each line 10pixel seperate tft_setCursor(70, 10); sprintf(buffer3,"Ezra's Mode"); printLine(7, buffer3, text_color, back_color); temp++; } testButton3 = mPORTAReadBits(BIT_4); //when press button 2, testButton2 = 1 if (testButton3>0){ ToppingMode=3; //Start Erza's mode tft_fillRoundRect(0,150, 320, 30, 1, ILI9340_BLACK);// x,y,w,h,radius,color tft_setCursor(0, 150); sprintf(bufferm,"Ezra's Mode START!!!"); tft_setTextSize(2); tft_writeString(bufferm); //Add values of Ezra's mode ///////////Step 0: Check the motor for one round spin mPORTBSetBits(BIT_3); //dc motor start spinning PT_YIELD_TIME_msec(2500); // 1 round of the motor mPORTBClearBits(BIT_3); PT_YIELD_TIME_msec(3000); /////////////////////////Step1: The bowl start spinning mPORTBSetBits(BIT_3); //dc motor start spinning PT_YIELD_TIME_msec(3000); /////////////////////////Step2: Stepper motor works moving the whip cream container //stepper motor makes the whip cream moving in mPORTBClearBits(BIT_15); //dir pin x=0; for(x = 0; x < 250; x++ ){ mPORTBSetBits(BIT_10); //step pin PT_YIELD_TIME_msec(1); mPORTBClearBits(BIT_10); PT_YIELD_TIME_msec(1); } /////////////////////////Step3: While the stepper is working, the whip cream servo works SetPulseOC2(0, 2900); //servo1 for whip cream start pressing PT_YIELD_TIME_msec(500); /////////////////////////Step4: Keep moving in and pressing the whip cream until it reach the center of a bowl. x=0; for(x = 0; x < 1000; x++ ){ mPORTBSetBits(BIT_10); //step pin PT_YIELD_TIME_msec(1); mPORTBClearBits(BIT_10); PT_YIELD_TIME_msec(1); } //PT_YIELD_TIME_msec(1000); //The stepper motor is at the center and the whip cream servo still pressing /////////////////////////Step5: A whip cream servo stops. SetPulseOC2(0, 1200); // A whip cream servo stops /////////////////////////Step6: The stepper motor moving back x=0; mPORTBSetBits(BIT_15); //changes rotation direction for(x = 0; x < 1250; x++ ){ mPORTBSetBits(BIT_10); //step pin PT_YIELD_TIME_msec(1); mPORTBClearBits(BIT_10); PT_YIELD_TIME_msec(1); } mPORTBClearBits(BIT_10); tft_fillRoundRect(0,150, 320, 30, 1, ILI9340_BLACK);// x,y,w,h,radius,color tft_setCursor(0, 150); sprintf(bufferm,"Ezra's Mode FINISH!!!"); tft_setTextSize(2); tft_writeString(bufferm); } } if (buttonCount>3) { buttonCount=1; if (temp ==4){ i=0; temp=1; } } } PT_YIELD_TIME_msec(32); } // END WHILE(1) PT_END(pt); } // thread 4 static PT_THREAD (protothread_linear(struct pt *pt)) { PT_BEGIN(pt); while(1) { PT_YIELD_TIME_msec(1) ; }// END WHILE(1)s PT_END(pt); } // === One second Thread ====================================================== // update a 1 second tick counter static PT_THREAD (protothread_time(struct pt *pt)) { PT_BEGIN(pt); // string buffer char buffer[128]; tft_setCursor(0, 0); tft_setTextColor(ILI9340_WHITE); tft_setTextSize(1); while(1) { PT_YIELD_TIME_msec(1000) ; sys_time_seconds++; } // END WHILE(1)s PT_END(pt); } // thread 4 // === Main ====================================================== int main(void) { ANSELA = 0; ANSELB = 0; // === config the uart, DMA, vref, timer5 ISR =========== PT_setup(); ////////////////PWM setting//////////////// // === Config timer and output compares to make pulses ======== // set up timer2 to generate the wave period OpenTimer2(T2_ON | T2_SOURCE_INT | T2_PS_1_32, 0x61A8); //20ms period //timer sets period OpenOC2(OC_ON | OC_TIMER2_SRC | OC_CONTINUE_PULSE ,1200, 0); // //set duty cycle //percentage of period that square wave is high //pulse stop, pulse start // differnce is duty cycle OpenOC3(OC_ON | OC_TIMER2_SRC | OC_CONTINUE_PULSE ,2100, 0); // ConfigIntTimer2(T2_INT_ON | T2_INT_PRIOR_2); mT2ClearIntFlag(); // and clear the interrupt flag // OC3 is PPS group 4, map to RPB9 (pin 18) PPSOutput(2, RPB5, OC2); PPSOutput(4, RPB9, OC3); // init the display // NOTE that this init assumes SPI channel 1 connections tft_init_hw(); tft_begin(); tft_fillScreen(ILI9340_BLACK); //240x320 vertical display tft_setRotation(1); // Use tft_setRotation(1) for 320x240 // === setup system wide interrupts ==================== INTEnableSystemMultiVectoredInt(); //For buttons mPORTASetPinsDigitalIn(BIT_2|BIT_3|BIT_4); EnablePullDownA(BIT_2|BIT_3|BIT_4); mPORTBSetPinsDigitalOut(BIT_15|BIT_10|BIT_8|BIT_3); mPORTBClearBits(BIT_8); mPORTBClearBits(BIT_3); mPORTBSetBits(BIT_15); mPORTBClearBits(BIT_10); // === now the threads =================================== // init the threads PT_INIT(&pt_time); PT_INIT(&pt_display); PT_INIT(&pt_linear); // schedule the threads while(1) { PT_SCHEDULE(protothread_time(&pt_time)); PT_SCHEDULE(protothread_display(&pt_display)); PT_SCHEDULE(protothread_linear(&pt_linear)); } } // main