aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.CodeGeneration/Templates/Property.cshtml
blob: f1dc61696718b053c50355e8a4e39967254ae042 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@if (Model.SetterContent == null && Model.GetterContent == null)
{
    <div>
        @(Model.GetAttributesString())
        @(Model.GetModifierString()) @(Model.Type) @(Model.Name) { get; set; }
    </div>
}
else if (Model.SetterContent != null && Model.GetterContent != null)
{
    <div>
        private @(Model.Type) @(Model.GetPrivateField());

        @(Model.GetAttributesString())
        @(Model.GetModifierString()) @(Model.Type) @(Model.Name)
        {
        get
        {
        @(Model.GetterContent)
        }
        @(Model.SetterModifier != CodeGenerator.CodeObjectModifier.None ? Model.SetterModifier.ToString().ToLower() : "") set
        {
        @(Model.SetterContent)
        }
        }
    </div>
}
else if (Model.GetterContent != null)
{
    <div>
        private @(Model.Type) @(Model.GetPrivateField());

        @(Model.GetAttributesString())
        @(Model.GetModifierString()) @(Model.Type) @(Model.Name)
        {
        get
        {
        @(Model.GetterContent)
        }
        }
    </div>
}
/************************************************************************************************************************
 * 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
 **************************************************************************************************************************/
#include "include.h"
#include "./printingSTM.h"

#include "Drivers/Heater/Heater.h"

#include "Modules/General/MachineStatus.h"
#include "modules/General/process.h"
#include "modules/thread/thread_ex.h"
#include "modules/Heaters/Heaters_ex.h"
#include "modules/Diagnostics/Diagnostics.h"
#include "modules/ids/ids_ex.h"

#include "PMR/Hardware/UploadHardWareConfigurationRequest.pb-c.h"
#include "PMR/Hardware/HardwareMotorType.pb-c.h"
#include "PMR/MachineStatus/MachineStatus.pb-c.h"
#include "PMR/Printing/JobDescriptionFileBrushStop.pb-c.h"
#include "PMR/Printing/JobDescriptionFileSegment.pb-c.h"

#include "Common/SWUpdate/FileSystem.h"

#include "drivers/Flash_Memory/fatfs/ff.h"

////////////////////////////////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
///////////////////////////////////////////////////////////////////////////////////////////

/********************************************************************************************
* functions describes motor operation flow and movement state during profile execution
* used to operate in runtime correct profileflow execution
*********************************************************************************************/
static uint32_t PreSegmentState(void *Segment, int,int);
static uint32_t SegmentState(void *Segment, int,int);
uint32_t EndState(void *JobDetails, char *Message);
//static uint32_t ExitState(void *JobDetails);
uint16_t n_segments = 0;
uint16_t n_units = 1;
uint16_t n_unit_segments = 0;

/**********************************************************************
* the array and enum of PrintingState_t below must be in sync order
***********************************************************************/
//static uint32_t (* state[])(void *JobDetails) = { EntryState, PrepareState, PreSegmentState,  SegmentState, EndState, ExitState};


typedef struct
{
    PrintingState_t m_sourceState;
    uint32_t          m_returnCode;
    PrintingState_t     m_destinationState;
} Transition_t;


////////////////////////Slow Motor State////////////////////////////////////
//static PrintingState_t gPrintingState;
////////////////////////////////////////////////////////////////////////////
ModuleStateEnum SegmentWaiting[MAX_SYSTEM_MODULES] =    {ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle};
ModuleStateEnum PreSegmentWaiting[MAX_SYSTEM_MODULES] = {ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle};
ModuleStateEnum DistanceToSpoolWaiting[MAX_SYSTEM_MODULES] = {ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle};
ModuleStateEnum PrintWaiting[MAX_SYSTEM_MODULES] =      {ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle};
ModuleStateEnum EndWaiting[MAX_SYSTEM_MODULES] =        {ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle,ModuleIdle};

bool Configured[MAX_SYSTEM_MODULES] = {false,false,false,false,false};

bool SuspendLargeMessages = false;
/*
Parsing the job description file.
The job description file simply contains an array of segments and their brush stops.
The job description file is meant to be read brush stop by brush stop while the job is in progress.
The following diagram represents a single job description file segment structure.
The process of reading the whole file is simply repeating that reading order.

Each JobDescriptionFileSegment contains a �BrushStopsCount� field that should be used to determine how many brush stops are associated
with the current segment and how many times the process of reading brush stops should be repeated.
1. 32bit integer containing the next JobFileDescriptionSegment message byte count
2. JobDescriptionFileSegment message
3. 32bit integer containing the next JobDescriptionFileBrushStop message byte count
4. JobDescriptionFileBrushStop message

1.  Read segment message length.
2.  Read segment message.
a.  Read brush stop message length.
b.  Read brush stop message.
c.  Go to step 2.a x Segment.BrushStopsCount.
3.  Go to step 1 until end of file.
*/

//job file reading functions
uint32_t bBytes = 0,readbBytes = 0,ImmediateRead = 0,SegmentSize = 0,BrushStopSize = 0;
FRESULT Fresult = FR_OK;
uint8_t *SegmentPtr = 0, *BrushStopPtr = 0;
FIL *JobRequestFileHandle = 0;  //the system supports a single active file
FRESULT OpenJobFile()
{
    if (CurrentJob->uploadstrategy == JOB_UPLOAD_STRATEGY__JobDescriptionFile)
    {
        JobRequestFileHandle = my_malloc(sizeof(FIL));

        Fresult = FileOpen(CurrentJob->jobdescriptionfile, &bBytes, JobRequestFileHandle);
        if (Fresult == FR_OK)
        {
            readbBytes = 0;
        }
        REPORT_MSG(bBytes,"OpenJobFile");
    }
    return Fresult;
}
FRESULT RewindJobFile()
{
    if (CurrentJob->uploadstrategy == JOB_UPLOAD_STRATEGY__JobDescriptionFile)
    {
        Fresult = f_lseek(JobRequestFileHandle, 0);

        if (Fresult == FR_OK)
        {
            readbBytes = 0;
        }
        REPORT_MSG(bBytes,"RewindJobFile");
    }
    return Fresult;
}
extern Semaphore_Handle FFS_Sem;
FRESULT CloseJobFile()
{
    Fresult = f_close(JobRequestFileHandle);
    //Semaphore_post(FFS_Sem);
#warning trying not to hold the semaphore and enable the PPC/MS to work on several files simultaneously

    readbBytes = 0;
    ImmediateRead = 0;
    SegmentSize = 0;
    BrushStopSize = 0;
    my_free (JobRequestFileHandle);
    JobRequestFileHandle = NULL;
    if (BrushStopPtr)
    {
        my_free(BrushStopPtr);
        BrushStopPtr = NULL;
    }
    if (SegmentPtr)
    {
        my_free(SegmentPtr);
        SegmentPtr = NULL;
    }
    REPORT_MSG(Fresult,"CloseJobFile");

    return Fresult;
}
JobDescriptionFileSegment *GetNextSegmentFromJobFile()
{
    //uint32_t status = OK;
    JobDescriptionFileSegment *Segment = NULL;
    if (JobRequestFileHandle == NULL)
    {
        LOG_ERROR(JobRequestFileHandle,"JobRequestFileHandle == NULL");
        return NULL;
    }
    if(readbBytes < bBytes)
    {
        Fresult = f_read(JobRequestFileHandle,&SegmentSize,4,&ImmediateRead );
        if (Fresult == FR_OK)
        {
            readbBytes += ImmediateRead;
            if (SegmentPtr)
            {
                my_free(SegmentPtr);
                SegmentPtr = NULL;
            }
            SegmentPtr = my_malloc (SegmentSize);
            if (SegmentPtr)
            {
                Fresult = f_read(JobRequestFileHandle,SegmentPtr,SegmentSize,&ImmediateRead );
                if (Fresult == FR_OK)
                {
                    readbBytes += ImmediateRead;
                    //n_segments++;
                    Segment = job_description_file_segment__unpack(NULL, SegmentSize, SegmentPtr);
                }
            }// read segment data
            my_free(SegmentPtr);
            SegmentPtr = NULL;
        }//segment malloc
        else
        {
            LOG_ERROR (SegmentPtr, "malloc error");
            //status = ERROR;
        }
    }//segment read size
    else
    {
        LOG_ERROR (Fresult, "f_read error");
        //status = ERROR;
    }
    //if (Segment)
    //    REPORT_MSG(Segment->brushstopscount,"GetNextSegmentFromJobFile file Read Index");
    return Segment;
}
void FreeSegmentFileData(JobDescriptionFileSegment *Segment)
{
    if (Segment)
    {
        //REPORT_MSG(Segment->brushstopscount,"FreeSegmentFileData file Read Index");
        job_description_file_segment__free_unpacked(Segment,NULL);
    }
    else
        LOG_ERROR (readbBytes, "Null segment free called");
    Segment = NULL;
    if (SegmentPtr)
        my_free(SegmentPtr);
    SegmentPtr = NULL;
}
JobDescriptionFileBrushStop *GetNextBrushStopFromJobFile()
{
    //uint32_t status = OK;
    JobDescriptionFileBrushStop *BrushStop = NULL;
    if (JobRequestFileHandle == NULL)
    {
        LOG_ERROR(JobRequestFileHandle,"JobRequestFileHandle == NULL");
        return NULL;
    }
    Fresult = f_read(JobRequestFileHandle,&BrushStopSize,4,&ImmediateRead );
    if (Fresult == FR_OK)
    {
        readbBytes += ImmediateRead;
        if (BrushStopPtr)
        {
            my_free(BrushStopPtr);
            BrushStopPtr = NULL;
        }

        BrushStopPtr = my_malloc (BrushStopSize);
        if (BrushStopPtr)
        {
            Fresult = f_read(JobRequestFileHandle,BrushStopPtr,BrushStopSize,&ImmediateRead );
            if (Fresult == FR_OK)
            {
                readbBytes += ImmediateRead;
                BrushStop = job_description_file_brush_stop__unpack(NULL, BrushStopSize, BrushStopPtr);
            }//brushstop malloc ok
            else
            {
                LOG_ERROR (Fresult, "f_read error");
                //status = ERROR;
            }
            my_free(BrushStopPtr);
            BrushStopPtr = NULL;
        }//brushstop size read ok
        else
        {
            LOG_ERROR (BrushStopPtr, "malloc error");
            //status = ERROR;
        }
    }// if brush stop count
    else
    {
        LOG_ERROR (0, "f_read error brush stop size error");
        //status = ERROR;
    }
    //REPORT_MSG(BrushStop->index,"BrushStop file Read Index");

    return BrushStop;
}
void FreeBrushStopFileData(JobDescriptionFileBrushStop *BrushStop)
{
    //REPORT_MSG(BrushStop->index,"Free BrushStop file Read Index");
    if (BrushStop)
        job_description_file_brush_stop__free_unpacked (BrushStop,NULL);
    BrushStop = NULL;
    if (BrushStopPtr)
        my_free(BrushStopPtr);
    BrushStopPtr = NULL;
}
/************************************************************************************************************************************/
/* this function is for development initial stages. it analyses the hardware configuration to determine which modules are operational
 * according to the configuration map
 */

uint32_t PrintingHWConfiguration(void *Configuration)
{
    /*
     *     Module_Thread,
    Module_Winder,
    Module_IDS,
    Module_Heaters,
    Module_Waste,
     *
     */
    uint32_t i;
    HardwareConfiguration *request = Configuration;
    if (request->n_winders == 1)
        Configured[Module_Winder] = true;

    if (request->n_motors < HARDWARE_MOTOR_TYPE__MOTO_SPARE1_1)
    {
        for (i = 0; i < request->n_motors ; i++)
        {
            if ((request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_LDRIVING)||
                (request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_RDRIVING)||
                (request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_DRYER_DRIVING))
            {
                Configured[Module_Thread] = true;
                //break;
            }
            if ((request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_1)||
                (request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_2)||
                (request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_3)||
                (request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_4)||
                (request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_5)||
                (request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_6)||
                (request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_7)||
                (request->motors[i]->hardwaremotortype == HARDWARE_MOTOR_TYPE__MOTO_DISPENSER_8))
            {
                Configured[Module_IDS] = true;
                //break;
            }
        }
    }
    if (request->n_pidcontrols <= HARDWARE_PID_CONTROL_TYPE__Dispenser8)
    {
        for (i = 0; i < request->n_pidcontrols ; i++)
        {
            if (isHeater(request->pidcontrols[i]->hardwarepidcontroltype))
            {
                Configured[Module_Heaters] = true;
                break;
            }
        }
    }
    /*if (request->n_dispensers <= MAX_SYSTEM_DISPENSERS)
    {
        for (i = 0; i < request->n_dispensers ; i++)
        {
            if(request->dispensers[i]->index)
            {
                Configured[Module_IDS] = true;
                break;
            }
        }
    }*/


    return OK;
}

/********************************************************************************************************************
*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
*********************************************************************************************************************/

uint32_t PreSegmentReady(int ModuleId, ModuleStateEnum result)
{
    int i;
    bool ready = true;
    uint32_t status = OK;

    JobMessageStruc Message;
    PrintMessageStruc *PrtMessage = (PrintMessageStruc *)Message.messageData;

    assert (ModuleId<MAX_SYSTEM_MODULES);
    assert (result<=ModuleFail);

    if (PreSegmentWaiting[ModuleId] != ModuleWaiting)
    {
        LOG_ERROR (ModuleId, "Message from unrelated module!!");
        return OK;
    }

    PreSegmentWaiting[ModuleId] = result;
    if (result == ModuleFail)
        {
            status = ERROR;
            Report("PreSegmentReady Fail!",__FILE__,__LINE__,(int)ModuleId,RpWarning,(int)result,0);
        }
    for (i=0;i<MAX_SYSTEM_MODULES ;i++)
    {
        if (PreSegmentWaiting[i] == ModuleWaiting)
            ready = false;
    }
    if ((ready == false)&&(status == OK)) return OK;
    else
    {
        Message.messageId = PrintMessage;
        if (status == OK)
            {
                SendJobProgress(0.0, 0, false, "PreSegment Ready");
                PrtMessage->messageId = PreSegmentResultsOk;
            }
        else
            {
                PrtMessage->messageId = PreSegmentResultsFail;
                SendJobProgress(0.0, 0, false, "PreSegment Failed");
	            Report("PreSegment Fail!",__FILE__,__LINE__,(int)ModuleId,RpWarning,(int)result,0);
            }
        //memcpy(Message.messageData,JobDetails,MAX_MSG_LEN);
        Message.msglen = 10;
        if (JobmsgQ != NULL)
            Mailbox_post(JobmsgQ , &Message, BIOS_NO_WAIT);
    }
    return 0;

}

//********************************************************************************************************************
static uint32_t PreSegmentState(void *SegmentDetails, int SegmentId,int SegmentIdPointer)
{
    SendJobProgress(0.0, SegmentId, false, "PreSegment Start");
    if (Configured[Module_Thread])
    {
        PreSegmentWaiting[Module_Thread] = ModuleWaiting;
    }
    if (Configured[Module_Winder])
    {
        PreSegmentWaiting[Module_Winder] = ModuleWaiting;
    }
    if (Configured[Module_IDS])
    {
        PreSegmentWaiting[Module_IDS] = ModuleWaiting;
    }
    if (Configured[Module_Thread])
    {
        ThreadPreSegmentState(SegmentDetails,SegmentId);
    }
    if (Configured[Module_Winder])
    {
        Winder_Presegment(SegmentDetails,SegmentId);  //must be after ThreadPreSegmentState
    }
    if (Configured[Module_IDS])
    {
        IDSPreSegmentState(SegmentDetails,SegmentId);
    }
    return OK;
}
//********************************************************************************************************************
uint32_t SegmentReady(int ModuleId, ModuleStateEnum result)
{
    int i;
    bool ready = true;
    uint32_t status = OK;

    JobMessageStruc Message;
    PrintMessageStruc *PrtMessage = (PrintMessageStruc *)Message.messageData;

    assert (ModuleId<MAX_SYSTEM_MODULES);
    assert (result<=ModuleFail);
    //REPORT_MSG (ModuleId, "SegmentReady");
    Report("SegmentReady",__FILE__,__LINE__,(int)ModuleId,RpWarning,(int)result,0);

    if (SegmentWaiting[ModuleId] != ModuleWaiting)
    {
        LOG_ERROR (ModuleId, "Message from unrelated module!!");
        return OK;
    }

    SegmentWaiting[ModuleId] = result;
    if (result == ModuleFail)
        status = ERROR;
    for (i=0;i<MAX_SYSTEM_MODULES ;i++)
    {
        if (SegmentWaiting[i] == ModuleWaiting)
            ready = false;
    }
    if ((ready == false)&&(status == OK)) return OK;
    else
    {
        Message.messageId = PrintMessage;
        if (status == OK)
            {
                PrtMessage->messageId = SegmentResultsOk;
                SendJobProgress(0.0, 0, false, "Segment Done");
            }
        else
            {
                PrtMessage->messageId = SegmentResultsFail;
                SendJobProgress(0.0, 0, false, "Segment Fail");
            }
        //memcpy(Message.messageData,JobDetails,MAX_MSG_LEN);
        Message.msglen = 10;
        if (JobmsgQ != NULL)
            Mailbox_post(JobmsgQ , &Message, BIOS_NO_WAIT);
    }
    return 0;

}

//********************************************************************************************************************
static uint32_t SegmentState(void *SegmentDetails, int SegmentId,int SegmentIdPointer)
{
    SendJobProgress(0.0, SegmentId, false, "Segment Start");
    if (Configured[Module_IDS])
    {
        //SegmentWaiting[Module_IDS] = ModuleWaiting;
        IDSSegmentState(SegmentDetails,SegmentId);
    }
    if (Configured[Module_Thread])
    {
        SegmentWaiting[Module_Thread] = ModuleWaiting;
        ThreadSegmentState(SegmentDetails,SegmentId);
    }
    if (Configured[Module_Winder])
    {
        //SegmentWaiting[Module_Winder] = ModuleWaiting;
        //Winder_Segment(JobDetails);
    }
    return OK;
}
//********************************************************************************************************************
uint32_t DistanceToSpoolReady(int ModuleId, ModuleStateEnum result)
{
    int i;
    bool ready = true;
    uint32_t status = OK;

    JobMessageStruc Message;
    PrintMessageStruc *PrtMessage = (PrintMessageStruc *)Message.messageData;

    assert (ModuleId<MAX_SYSTEM_MODULES);
    assert (result<=ModuleFail);

    if (DistanceToSpoolWaiting[ModuleId] != ModuleWaiting)
    {
        LOG_ERROR (ModuleId, "Message from unrelated module!!");
        return OK;
    }

    DistanceToSpoolWaiting[ModuleId] = result;
    if (result == ModuleFail) status = ERROR;
    for (i=0;i<MAX_SYSTEM_MODULES ;i++)
    {
        if (DistanceToSpoolWaiting[i] == ModuleWaiting)
            ready = false;
    }
    if ((ready == false)&&(status == OK)) return OK;
    else
    {
        Message.messageId = PrintMessage;
        if (status == OK)
            {
                PrtMessage->messageId = FinishResultsOk;
                SendJobProgress(0.0, 0, false, "DistanceToSpool Done");
            }
        else
            {
                //SuspendLargeMessages = true;
                //DiagnosticsStop();
                PrtMessage->messageId = FinishResultsFail;
                SendJobProgress(0.0, 0, false, "DistanceToSpool Fail");
                LOG_ERROR(1,"SuspendLargeMessages DistanceToSpoolReady");
            }
        //memcpy(Message.messageData,JobDetails,MAX_MSG_LEN);
        Message.msglen = 10;
        if (JobmsgQ != NULL)
            Mailbox_post(JobmsgQ , &Message, BIOS_NO_WAIT);
    }
    return 0;

}

//********************************************************************************************************************
static uint32_t DistanceToSpoolState(void *JobDetails)
{
    SendJobProgress(0.0, 0, false, "DistanceToSpool Start");
    if (Configured[Module_IDS])
    {
        DistanceToSpoolWaiting[Module_IDS] = ModuleWaiting;
        IDSDistanceToSpoolState();
    }
    if (Configured[Module_Thread])
    {
        DistanceToSpoolWaiting[Module_Thread] = ModuleWaiting;
        ThreadDistanceToSpoolState();
    }
    if (Configured[Module_Winder])
    {
        //DistanceToSpoolWaiting[Module_Winder] = ModuleWaiting;
        WinderDistanceToSpoolState();
        //Winder_DistanceToSpool(JobDetails);
    }
    return OK;
}

//********************************************************************************************************************
char ErMsg[50];
uint32_t EndState(void *JobDetails, char *Message)
{
    //ROM_IntMasterDisable();
    //SuspendLargeMessages = true;
    //LOG_ERROR(2,"SuspendLargeMessages EndState");
    //DiagnosticsStop();
    if (Configured[Module_Winder])
    {
        PrepareWaiting[Module_Winder] = ModuleIdle;
        SegmentWaiting[Module_Winder] = ModuleIdle;
        PreSegmentWaiting[Module_Winder] = ModuleIdle;
        DistanceToSpoolWaiting[Module_Winder] = ModuleIdle;
        //    EndWaiting[Module_Winder] = ModuleWaiting;
        Winder_End();
    }
    if (Configured[Module_IDS])
    {
        PrepareWaiting[Module_IDS] = ModuleIdle;
        SegmentWaiting[Module_IDS] = ModuleIdle;
        PreSegmentWaiting[Module_IDS] = ModuleIdle;
        DistanceToSpoolWaiting[Module_IDS] = ModuleIdle;
        //EndWaiting[Module_IDS] = ModuleWaiting;
        IDSEndState();
    }
    if (Configured[Module_Heaters])
    {
        PrepareWaiting[Module_Heaters] = ModuleIdle;
        //EndWaiting[Module_Heaters] = ModuleWaiting;
        //heaters preparation starts on process parameters handling
        // do not call HeatersEnd(); because the heaters should stay ready for coming jobs
    }
    if (Configured[Module_Thread])
    {
        PrepareWaiting[Module_Thread] = ModuleIdle;
        SegmentWaiting[Module_Thread] = ModuleIdle;
        PreSegmentWaiting[Module_Thread] = ModuleIdle;
        DistanceToSpoolWaiting[Module_Thread] = ModuleIdle;
        //EndWaiting[Module_Thread] = ModuleWaiting;
        ThreadEndState();
    }
    CloseJobFile();
    //ROM_IntMasterEnable();
    SendJobProgress(0.0,0,true,Message);
    if (JoggingJobActive == true)
    {
        JoggingJobActive = false;
        memcpy(&Configured,&CopyConfigured,sizeof(CopyConfigured));
        usnprintf(ErMsg, 80,"Copy Configured T %d W %d I %d H %d W %d",CopyConfigured[Module_Thread],CopyConfigured[Module_Winder],CopyConfigured[Module_IDS],CopyConfigured[Module_Heaters],CopyConfigured[Module_Waste]);
        Report(ErMsg, __FILE__, __LINE__, 0, RpWarning,   0, 0);
    }
    if (CleaningJobActive == true)
    {
        CleaningJobActive = false;
        memcpy(&Configured,&CopyConfigured,sizeof(CopyConfigured));
        usnprintf(ErMsg, 80,"Copy Configured T %d W %d I %d H %d W %d",CopyConfigured[Module_Thread],CopyConfigured[Module_Winder],CopyConfigured[Module_IDS],CopyConfigured[Module_Heaters],CopyConfigured[Module_Waste]);
        Report(ErMsg, __FILE__, __LINE__, 0, RpWarning,   0, 0);
    }

    return OK;
}
//********************************************************************************************************************
/*static uint32_t ExitState(void *JobDetails)
{
    return OK;
}*/

//********************************************************************************************************************

/*void PrintingsInit(void)
{
}
*/
//********************************************************************************************************************

void StartPrinting(void)
{
}

//********************************************************************************************************************
//********************************************************************************************************************

int SegmentId = 0,UnitId = 0, SegmentIdPointer = 0;
JobDescriptionFileSegment *Segment;
JobSegment SSegment;

//********************************************************************************************************************
//********************************************************************************************************************
void PrintSTMMsgHandler(void * msg)
{
    JobMessageStruc *Message = msg;
    PrintMessageStruc *PrtMessage = (PrintMessageStruc *)Message->messageData;

    Report("PrintSTMMsgHandler",__FILE__,__LINE__, Message->messageId,RpMessage,PrtMessage->messageId,0);

    if ((Message->messageId != PrintMessage)&&(Message->messageId != Abort))
    {
        //REPORT_ERR ...
        return;
    }
    switch(PrtMessage->messageId)
    {
        case PrintRequest:
            SetMachineStatus(MACHINE_STATE__RunningJob);
            SegmentId = 0;
            SegmentIdPointer = 0;
            UnitId = 0;
            if (CurrentJob->uploadstrategy == JOB_UPLOAD_STRATEGY__JobDescriptionFile)
            {
                Segment = GetNextSegmentFromJobFile();
                SSegment.length = Segment->length;
                SSegment.has_length = Segment->has_length;
                SSegment.n_brushstops = Segment->brushstopscount;
                PreSegmentState(&SSegment,SegmentId,SegmentIdPointer);
            }
            else
            {
                PreSegmentState(CurrentJob->segments[SegmentIdPointer],SegmentId,SegmentIdPointer);
            }
            break;
        case PreSegmentResultsOk:
            if (CurrentJob->uploadstrategy == JOB_UPLOAD_STRATEGY__JobDescriptionFile)
            {
                SegmentState(&SSegment,SegmentId,SegmentIdPointer);
            }
            else
            {
                SegmentState(CurrentJob->segments[SegmentIdPointer],SegmentId,SegmentIdPointer);
            }
            break;
        case PreSegmentResultsFail:
            EndState(CurrentJob, "PreSegment Failed");
            //ExitState(Message->messageData);
            break;
        case SegmentResultsOk:
            SegmentId++;
            SegmentIdPointer++;
            //REPORT_MSG(SegmentId, "SegmentResultsOk segmentId");
            if ((SegmentId % n_unit_segments)==0) //finished a unit
            {
                Report("unit finished",__FILE__,__LINE__, SegmentId,RpMessage,n_unit_segments,0);
                UnitId++;
                if (UnitId < n_units)
                {
                    if (CurrentJob->uploadstrategy == JOB_UPLOAD_STRATEGY__JobDescriptionFile)
                    {
                        //rewind file
                        if (RewindJobFile() != FR_OK)
                        {
                          JobEndReason = JOB_OTHER_ALARM;
                          if (dryerbufferlength <= 0.1)
                              EndState(CurrentJob, "Job Ended");
                          else
                              DistanceToSpoolState(CurrentJob);
                        }
                        Report("start unit ",__FILE__,__LINE__, UnitId,RpMessage,n_units,0);
                    }
                    SegmentIdPointer = 0;
                }
            }



            Report("SegmentResultsOk segmentId",__FILE__,__LINE__, SegmentId,RpMessage,n_segments,0);
            if (SegmentId >= n_segments)
                {
                if (dryerbufferlength <= 0.1)
                      EndState(CurrentJob, "Job Ended");
                  else
                      Report("DistanceToSpoolState segmentId",__FILE__,__LINE__, SegmentId,RpMessage,n_segments,0);
                      DistanceToSpoolState(CurrentJob);
                }
            else
            {
                if (CurrentJob->uploadstrategy == JOB_UPLOAD_STRATEGY__JobDescriptionFile)
                {
                    if ((Segment) && (Segment->base.descriptor->sizeof_message != 40))
                        LOG_ERROR(SegmentId, "Error releasing Segment");
                    else if (Segment)
                    {
                        if (SegmentIdPointer) //do not perform after a rewind
                        {
                            if (IDSCheckSegmentData(Segment, SegmentId) == OK)
                            {
                                FreeSegmentFileData(Segment);
                            }
                            else
                            {
                              JobEndReason = JOB_OTHER_ALARM;
                              if (dryerbufferlength <= 0.1)
                                  EndState(CurrentJob, "Job Ended");
                              else
                                  DistanceToSpoolState(CurrentJob);
                            }
                        }
                        else
                            Report("not checking after a rewind ",__FILE__,__LINE__, SegmentId,RpMessage,SegmentIdPointer,0);
                    }
                    else
                    {
                        LOG_ERROR(SegmentId, "Error Segment is null");
                    }

                    Segment = GetNextSegmentFromJobFile();
					if ((Segment == NULL)||(Segment->length <0.1))
					{
			            Report("SegmentLoading failed",__FILE__,__LINE__, Segment,RpMessage,(int)(Segment->length*100),0);
					  JobEndReason = JOB_OTHER_ALARM;
                      if (dryerbufferlength <= 0.1)
	                      EndState(CurrentJob, "Job Ended");
	                  else
	                      DistanceToSpoolState(CurrentJob);
					}
					else
					{
                        SSegment.length = Segment->length;
                        SSegment.has_length = Segment->has_length;
                        SSegment.n_brushstops = Segment->brushstopscount;

                        PreSegmentState(&SSegment,SegmentId,SegmentIdPointer);
					}
                }
                else
                {
                    PreSegmentState(CurrentJob->segments[SegmentIdPointer],SegmentId,SegmentIdPointer);
                }
            }
            break;
        case SegmentResultsFail:
            EndState(CurrentJob, "Segment Failed");
            break;
        case FinishResultsOk:
            EndState(CurrentJob, "Job Ended");
            break;
        case FinishResultsFail:
            EndState(CurrentJob, "Job Distance t Spool Failed");
            break;
        case PrintSystemFailure:
            Report("PrintSystemFailure - Job aborted",__FILE__,__LINE__, SegmentId,RpMessage,n_segments,0);
            EndState(CurrentJob, Message->messageData);
            break;
        default:
            break;
    }



}