/************************************************************************************************************************ * Printing.c * High managment logical unit of slow motors in the system ( 6 dispensers and the screw motor) * profile run up begins from screw homing to begin position and only then from fast motors activation. * when every slow motor tuches the limit switch (no matter whether its screw or dispenser) * an interrupt occures in the system and as long as its pushing the limit switch all the system is prevented from operation. * because of that the work flow with interrupts must be : * design a function handle (what to do in the moment the interrupt arrives) * configure the wanted interrupt in the cfg file (according to the defined port and pin and its interrupt number and the handler) * enable interupt for predefined gpio in the application * when the interrupt arrives the handle will be automatically called * in case of the limit switches since the operation is continuess the interrupt must be disabled in order to continue the application running. * then the operation is not continues (like butten pushing) there is no need in disabling the interrupts * Printing module is responsible for : * operating diffrent winding algorithms with predefined parameters from the UI * operating the dispensers according to predefined dispensing rate from the UI **************************************************************************************************************************/ ////////////////////////////////State machine operation//////////////////////////////////// //the state machine operation is used to operate in runtime correct profile flow execution //by recieved esign flow of the user from the UI /////////////////////////////////////////////////////////////////////////////////////////// #include #include #include "include.h" #include #include #include #include "PMR/Printing/JobSegment.pb-c.h" #include "PMR/Printing/JobRequest.pb-c.h" #include "PMR/Hardware/Hardwaremotor.pb-c.h" #include "PMR/Hardware/HardwareWinder.pb-c.h" #include "PMR/common/MessageContainer.pb-c.h" #include "Modules/General/process.h" #include "./printingSTM.h" #include "modules/thread/thread_ex.h" #include "modules/ids/ids_ex.h" #define INVALID_MSG_ID 0xFFFF Mailbox_Handle JobmsgQ = NULL; static Clock_Handle JobClock; static Clock_Params jobclkParams; char JobDetails[MAX_MSG_LEN]; #define MAX_TICKET_SIZE 10000 SegmentGradientStruc SegmentGradient; char CurrentJobBuffer[MAX_TICKET_SIZE]; JobTicket *CurrentJob = (JobTicket *)CurrentJobBuffer; char PreviousJobBuffer[MAX_TICKET_SIZE]; JobTicket *PreviousJob = (JobTicket *)PreviousJobBuffer; ModuleStateEnum PrepareWaiting[MAX_SYSTEM_MODULES] = {ModuleIdle}; /******************************************************************************************** * functions describes motor operation flow and movement state during profile execution * used to operate in runtime correct profileflow execution *********************************************************************************************/ static ReturnCode IdleState(void *JobDetails); static ReturnCode ValidateState(void *JobDetails); static ReturnCode PrepareState(void *JobDetails); static ReturnCode PrintState(void *JobDetails); static ReturnCode CleanState(void *JobDetails); static ReturnCode ExitState(void *JobDetails); /********************************************************************** * the array and enum of JobState_t below must be in sync order ***********************************************************************/ //static ReturnCode (* state[])(void *JobDetails) = { IdleState, ValidateState, PrepareState, PrintState, CleanState}; typedef enum { Idle= 0, Validate, PrepareJob, Print, Clean, ExitJob } JobState_t; typedef struct { JobState_t m_sourceState; ReturnCode m_returnCode; JobState_t m_destinationState; } Transition_t; ////////////////////////Slow Motor State//////////////////////////////////// char JobToken[36]; //////////////////////////////////////////////////////////////////////////// void StartJob(void *JobDetails); //******************************************************************************************************************** /******************************************************************************************************************** *function describes entry point of motor in profile execution - accelerate from stop position *function described above used to operate motor operation flow and movement state during profile execution *********************************************************************************************************************/ static ReturnCode IdleState(void *JobDetails) { ReturnCode retcode; retcode = JobSuccess; return retcode; } //******************************************************************************************************************** static ReturnCode ValidateState(void *JobDetails) { ReturnCode retcode; retcode = JobSuccess; return retcode; } //******************************************************************************************************************** static ReturnCode PrepareState(void *JobDetails) { ReturnCode retcode; retcode = JobSuccess; //start (fast??) heating //wait for fast heating to end //start other peripheral systems: chiller, waist handling //check thread type //prepare winder PrepareWaiting[Module_Heaters] = ModuleWaiting; PrepareWaiting[Module_Winder] = ModuleWaiting; PrepareWaiting[Module_Thread] = ModuleWaiting; ThreadPrepareState(&CurrentJob); PrepareWaiting[Module_IDS] = ModuleWaiting; IDSPrepareState(JobDetails); /* * typedef enum { ModuleIdle = 0, ModuleWaiting, ModuleDone, ModuleFail } ModuleStateEnum; ModuleStateEnum PrepareWaiting[MAX_SYSTEM_MODULES] = {ModuleIdle}; * typedef enum { Module_Thread, Module_Winder, Module_IDS, Module_Heaters, Module_Waste, MAX_SYSTEM_MODULES }SYSTEM_MODULE_ID_ENUM; * */ return retcode; } //******************************************************************************************************************** uint32_t PrepareReady(int ModuleId, ModuleStateEnum result) { int i; bool ready = true; uint32_t retcode = 0,status = OK; JobMessageStruc Message; assert (ModuleIddata.len, requestContainer->data.data); strcpy (JobToken, requestContainer->token); JobTicket *Ticket = request->jobticket; int TicketSize = job_ticket__get_packed_size(Ticket); if (TicketSize >= MAX_TICKET_SIZE) { LOG_ERROR (TicketSize, "job ticket message too long"); status = FAILED; } else { memcpy(CurrentJob, Ticket,TicketSize); status = PASSED; status += HandleProcessParameters(Ticket->processparameters); PrepareWaiting[Module_Heaters] = ModuleWaiting; } if (status == PASSED) { StartJob(&CurrentJob); } JobResponse response = JOB_RESPONSE__INIT; if (status == PASSED) { responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, false, &response, &job_response__pack, &job_response__get_packed_size); container_buffer = malloc(message_container__get_packed_size(&responseContainer)); strcpy (response.status->message,"Job Accepted"); response.status->has_progress = true; response.status->progress = 0.0; response.status->has_currentsegmentindex = false; } else { responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, true, &response, &job_response__pack, &job_response__get_packed_size); container_buffer = malloc(message_container__get_packed_size(&responseContainer)); responseContainer.has_error = true; responseContainer.error = ERROR_CODE__BAD_CRC; strcpy (response.status->message,"Job message too large"); response.status->has_progress = true; response.status->progress = 0.0; response.status->has_currentsegmentindex = false; } size_t container_size = message_container__pack(&responseContainer, container_buffer); free(responseContainer.data.data); SendChars((char*)container_buffer, container_size); job_request__free_unpacked(request,NULL); //free(container_buffer); //free(requestContainer); } void StartJob(void *JobDetails) { JobMessageStruc Message; bool retcode = false; Message.messageId = JobRequestMsg; memcpy(Message.messageData,JobDetails,MAX_MSG_LEN); Message.msglen = MAX_MSG_LEN; if (JobmsgQ != NULL) retcode = Mailbox_post(JobmsgQ , &Message, BIOS_NO_WAIT); } /****************************************************************************** * ======== messageTsk ======== * Task for this function is created statically. See the project's .cfg file. * this message task is created statically in system initialization, ******************************************************************************/ Void jobTask(UArg arg0, UArg arg1) { JobMessageStruc Message; //char str[60]; //uint16_t length; //Clock_setTimeout(HostKAClock, 1000); //Clock_start(HostKAClock); while(1) { Mailbox_pend(JobmsgQ , &Message, BIOS_WAIT_FOREVER); switch (Message.messageId) { case JobRequestMsg: memcpy(JobDetails,Message.messageData, Message.msglen); /*ValidateState (&JobDetails); break; case ValidationResultsOk:*/ PrepareState (&JobDetails); break; case ValidationResultsFail: //send message data as a validation error message to host ExitState(Message.messageData); break; case PreparationResultsOk: PrintState(&JobDetails); break; case PreparationResultsFail: //send message data as a validation error message to host ExitState(Message.messageData); break; case PrintMessage: //send message data as a validation error message to host PrintSTMMsgHandler(&Message); break; case PrintingResultsOk: CleanState(&JobDetails); break; case PrintingResultsFail: //send message data as a validation error message to host ExitState(Message.messageData); break; case CleaningResultsOk: //send message data as a validation error message to host ExitState(Message.messageData); break; case CleaningResultsFail: //send message data as a validation error message to host ExitState(Message.messageData); break; case SystemFailure: //send message data as a validation error message to host ExitState(Message.messageData); break; default: break; } } }