aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/INotificationProvider.cs
blob: a2cf609b173b48b182c383ca57c8900b2693e950 (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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using Tango.SharedUI;

namespace Tango.MachineStudio.Common.Notifications
{
    /// <summary>
    /// Represents the Machine Studio user notification provider responsible for displaying information, alerts and dialogs to the user.
    /// </summary>
    public interface INotificationProvider
    {
        /// <summary>
        /// Gets the collection of active task items.
        /// </summary>
        ObservableCollection<TaskItem> TaskItems { get; }

        /// <summary>
        /// Gets the collection of active bar items.
        /// </summary>
        ObservableCollection<BarItem> BarItems { get; }

        /// <summary>
        /// Gets the current displayed task item.
        /// </summary>
        TaskItem CurrentTaskItem { get; }

        /// <summary>
        /// Gets a value indicating whether there are any queued task items.
        /// </summary>
        bool HasTaskItems { get; }

        /// <summary>
        /// Pushes the specified task item to the queue.
        /// </summary>
        /// <param name="taskItem">The task item.</param>
        void PushTaskItem(TaskItem taskItem);

        /// <summary>
        /// Create and push a new task item from the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <returns></returns>
        TaskItem PushTaskItem(String message);

        /// <summary>
        /// Creates and push a new bar item from the specified framework element.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns></returns>
        BarItem PushBarItem(FrameworkElement element);

        /// <summary>
        /// Pushes the specified bar item.
        /// </summary>
        /// <param name="barItem">The bar item.</param>
        /// <returns></returns>
        BarItem PushBarItem(BarItem barItem);

        /// <summary>
        /// Removed the specified task item from the queue.
        /// </summary>
        /// <param name="taskItem">The task item.</param>
        void PopTaskItem(TaskItem taskItem);

        /// <summary>
        /// Removed the specified bar item.
        /// </summary>
        /// <param name="barItem">The bar item.</param>
        void PopBarItem(BarItem barItem);

        /// <summary>
        /// Creates a new instance of the specified View type and displays it as a modal dialog.
        /// </summary>
        /// <typeparam name="View">The type of the view.</typeparam>
        /// <typeparam name="VM">The type of the view model.</typeparam>
        /// <param name="onAccept">Accept button callback.</param>
        /// <param name="onCancel">Cancel button callback.</param>
        void ShowModalDialog<View, VM>(Action<VM> onAccept, Action onCancel) where View : FrameworkElement where VM : DialogViewVM;

        /// <summary>
        /// Creates a new view by a naming convention of the specified view model type.
        /// </summary>
        /// <typeparam name="VM">The type of the view model.</typeparam>
        /// <param name="onAccept">Accept button callback.</param>
        /// <param name="onCancel">Cancel button callback.</param>
        void ShowModalDialog<VM>(Action<VM> onAccept, Action onCancel) where VM : DialogViewVM;

        /// <summary>
        ///  Shows the specified view with the specified view model as it's data context.
        /// </summary>
        /// <typeparam name="VM">The type of the mm.</typeparam>
        /// <typeparam name="View">The type of the view.</typeparam>
        /// <param name="vm">The view model.</param>
        /// <param name="onAccept">The accept action.</param>
        /// <param name="onCancel">The cancel action.</param>
        void ShowModalDialog<VM, View>(VM vm, Action<VM> onAccept, Action onCancel) where View : FrameworkElement where VM : DialogViewVM;

        /// <summary>
        ///  Shows the specified view with the specified view model as it's data context.
        /// </summary>
        /// <typeparam name="VM">The type of the mm.</typeparam>
        /// <typeparam name="View">The type of the view.</typeparam>
        /// <param name="vm">The view model.</param>
        /// <param name="view">The view.</param>
        /// <param name="onAccept">The accept action.</param>
        /// <param name="onCancel">The cancel action.</param>
        void ShowModalDialog<VM, View>(VM vm, View view, Action<VM> onAccept, Action onCancel) where View : FrameworkElement where VM : DialogViewVM;

        /// <summary>
        /// Creates a new view by a naming convention of the specified view model type.
        /// </summary>
        /// <typeparam name="VM">The type of the view model.</typeparam>
        /// <param name="onAccept">Accept button callback.</param>
        void ShowModalDialog<VM>(Action<VM> onAccept) where VM : DialogViewVM;

        /// <summary>
        /// Display a message box.
        /// </summary>
        /// <param name="icon">The icon.</param>
        /// <param name="iconColor">Color of the icon.</param>
        /// <param name="message">The message.</param>
        /// <param name="hasCancel">if set to <c>true</c> displays the cancel button.</param>
        /// <returns></returns>
        bool? ShowMessageBox(PackIconKind icon, Brush iconColor, String message, bool hasCancel);

        /// <summary>
        /// Shows an information message box.
        /// </summary>
        /// <param name="message">The message.</param>
        void ShowInfo(String message);

        /// <summary>
        /// Shows warning message box.
        /// </summary>
        /// <param name="message">The message.</param>
        void ShowWarning(String message);

        /// <summary>
        /// Shows an error message box.
        /// </summary>
        /// <param name="message">The message.</param>
        void ShowError(String message);

        /// <summary>
        /// Shows a question message box.
        /// </summary>
        /// <param name="message">The message.</param>
        bool ShowQuestion(String message);

        /// <summary>
        /// Shows a dialog with a text input field and returns the response.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="hint">Text field hint.</param>
        /// <param name="defaultResponse">Optional default response.</param>
        /// <returns></returns>
        String ShowTextInput(String message, String hint, String defaultResponse = null);
    }
}
/************************************************************************************************************************
 * Millisec.c
 * Millisec module
 *
 * The millisec task is called once every 1 millisecond to gather data from the FPGA crucial modules,
 * so it will be ready for the Millisec operations. it is called 300 (TBD, configurable)
 * microsecond before the Millisec task, so that the data will be ready for the Millisec handling.
 * the ,millisecond task holds the pointer to a double buffer of results, so that the Millisec will handle the
 * most updated data, without disturbing data gathering
 *
 **************************************************************************************************************************/

////////////////////////////////State machine operation////////////////////////////////////
//the state machine operation is used to operate in runtime correct profile flow execution
//by recieved design flow of the user from the UI
///////////////////////////////////////////////////////////////////////////////////////////
#include "include.h"
#include "Modules/General/GeneralHardware.h"

#include "Modules/AlarmHandling/AlarmHandling.h"
#include "Modules/General/MachineStatus.h"

#include "MillisecTask.h"
#include <driverlib/timer.h>
#include <Drivers/SSI_Comm/SSI_Comm.h>
#include <Drivers/SSI_Comm/Speed_Sensor/Speed_Sensor.h>
#include <Drivers/SSI_Comm/Dancer/Dancer.h>
#include "drivers/I2C_Communication/ADC_MUX/ADC_MUX.h"
#include <inc/hw_ints.h>

#include "drivers/adc_sampling/adc.h"
#include "control.h"

#include "drivers/Motors/Motor.h"
#include "drivers/Heater/TemperatureSensor.h"
#include "drivers/FPGA/FPGA_SPI_Comm.h"
#include "drivers/FPGA/FPGA.h"
#include <drivers/FPGA/FPGA_Comm.h>
#include "drivers/Valves/Valve.h"
#include "drivers/FPGA/FPGA_GPIO/FPGA_GPIO.h"
#include "Drivers/I2C_Communication/I2C.h"

#include "modules/thread/thread_ex.h"
#include "modules/ifs/ifs.h"
#include "modules/ids/ids_ex.h"
#include "modules/waste/waste_ex.h"
#include "modules/Diagnostics/Diagnostics.h"
#include "Modules/General/MachineStatus.h"

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

#include "Common/SWUpdate/FileSystem.h"

#include "Communication/Connection.h"
#include "Modules/General/buttons.h"
#include "Drivers/I2C_Communication/Head_Card/PT100/Head_PT100_ADC.h"

#include <Drivers/I2C_Communication/WHS_Card/D_ADS122_PT100/WHS_PT100_ADC.h>
#include <Drivers/I2C_Communication/I2C_Task.h>
#include <Drivers/I2C_Communication/WHS_Card/D_Max5805_ADC_Blower/WHS_Blower.h>
#include "Modules/Heaters/Heaters_ex.h"
#include <Drivers/I2C_Communication/WHS_Card/D_EMC2302_Fan/WHS_Fan.h>
#include <Drivers/I2C_Communication/WHS_Card/D_MAX11614_ADC/WHS_MAX11614_A2D.h>
#include <Drivers/I2C_Communication/I2C_Task.h>

Task_Handle Millisecond_Task_Handle;
/******************** Definitions  ********************************************/

/******************** STRUCTURES AND ENUMs  ********************************************/
typedef struct MillisecMotorData
{
    bool WaitForData;
    bool DataRequired;
    bool SyncRequired;
    MSecFptr Callback;
    unsigned long Data;
    int Length;
    bool Active;
}MillisecMotorDataStruc;
typedef enum
{
    OneMillisec,
}MillisecMessages;

typedef struct MillisecMessage{
    uint16_t messageId;
    uint16_t msglen;
    uint32_t tick;
    uint8_t messageData[20];
}MillisecMessageStruc;

//uint32_t  ADC_Data[MAX_ADC_DEVICES] = {0};
//uint32_t  TemperatureSensor_Data[MAX_MAIN_CARD_TEMPERATURE_SENSOR_ID] = {0};
//uint32_t  MotorSpeed_Data[NUM_OF_MOTORS] = {0};
//uint32_t  MotorStatus_Data[NUM_OF_MOTORS] = {0};
//uint32_t  MotorPosition_Data[NUM_OF_MOTORS] = {0};
//bool      MotorBusy_Data[NUM_OF_MOTORS] = {true};
uint32_t  Dancer_Data[NUM_OF_DANCERS] = {0};
float  Speed_Data = 0;
uint32_t DrawerFansStatus = 0;
uint32_t SystemFansStatus = 0;
bool watchdogCriticalAlarm = false;

uint32_t msec_millisecondCounter = 0;

extern bool Machine_Idle_Mode;

uint8_t Gas_PPM_Info;
MillisecMotorDataStruc ScrewSetMaxSpeedPending = {0};
MillisecMotorDataStruc ScrewMovePending = {0};
MillisecMotorDataStruc MotorData[NUM_OF_MOTORS] = {0};
MillisecMotorDataStruc SpeedSetPending[NUM_OF_MOTORS] = {0};
MillisecMotorDataStruc PT100Data[MAX_MAIN_CARD_TEMP_SENS_ID] = {0};
/******************** GLOBAL PARAMETERS  ********************************************/
Mailbox_Handle          MillisecMsgQ = NULL;
Mailbox_Handle          TenMillisecMsgQ = NULL;
Mailbox_Handle          MotorsMsgQ[NUM_OF_MOTORS] = {NULL};
bool                    MillisecRestart;
static GateMutex_Handle gateMillisecDB;

uint32_t        Millisec_timerBase = TIMER1_BASE;        //Timer handle
/******************** Functions  ********************************************/
//**********************************************************************
/******************** CODE  ********************************************/
//**********************************************************************
#define LOG_SIZE 200
uint32_t MSBacklog[LOG_SIZE+1]={0};
uint8_t Motor_Id[LOG_SIZE+1]={0};
uint32_t MSTick[LOG_SIZE+1]={0};
uint16_t MsecLogindex = 0;

void MillisecInit(void)
{
    Error_Block eb;
    int i;

    Error_init(&eb);

    MillisecMsgQ = Mailbox_create(sizeof(MillisecMessageStruc), 2, NULL,&eb);
    TenMillisecMsgQ = Mailbox_create(sizeof(MillisecMessageStruc), 2, NULL,&eb);
    for (i=0;i<NUM_OF_MOTORS;i++)
    {
        MotorsMsgQ[i] = Mailbox_create(sizeof(MillisecMotorDataStruc), 5, NULL,&eb);
    }

    MillisecRestart = false;


    gateMillisecDB = GateMutex_create(NULL, &eb);
    if (gateMillisecDB == NULL)
    {
        System_abort("Could not create USB Wait gate");
    }

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    ROM_TimerConfigure(Millisec_timerBase, TIMER_CFG_PERIODIC);   // 32 bits Timer
    //TimerIntRegister(Millisec_timerBase, TIMER_A, Timer0Isr);    // Registering  isr
    ROM_TimerEnable(Millisec_timerBase, TIMER_A);
    ROM_IntEnable(INT_TIMER1A);
    ROM_TimerIntEnable(Millisec_timerBase, TIMER_TIMA_TIMEOUT);

    ADCAcquireInit();

    return;
}
void MillisecStop(void)
{
    MillisecRestart = false;
    ADCAcquireStop();
}
#ifdef HUNDRED_MICROSECONDS_DANCER_READ
#define HIGH_TASK_FREQUENCY 12000
#else
#define HIGH_TASK_FREQUENCY 120000
#endif
void MillisecStart(void)
{
    MillisecRestart = true;

    ROM_TimerLoadSet(Millisec_timerBase, TIMER_A,HIGH_TASK_FREQUENCY);
    ROM_TimerEnable(Millisec_timerBase, TIMER_A);
    ROM_IntEnable(INT_TIMER1A);
    ROM_TimerIntEnable(Millisec_timerBase, TIMER_TIMA_TIMEOUT);
    ADCAcquireStart(0,1);

}

void OneMilliSecondMillisecInterrupt(UArg arg0)
{
    MillisecMessageStruc MillisecMessage;
    uint32_t Tenmsec_millisecondCounter = 0;
#ifndef HUNDRED_MICROSECONDS_DANCER_READ

    ROM_IntMasterDisable();
    ROM_TimerIntClear(Millisec_timerBase, TIMER_TIMA_TIMEOUT);  // Clear the timer interrupt
    if (MillisecRestart == true)
    {
        ROM_TimerLoadSet(Millisec_timerBase, TIMER_A,HIGH_TASK_FREQUENCY);
    }
    else
	{
        ROM_TimerDisable(Millisec_timerBase,TIMER_A);
	    ROM_IntMasterEnable();
		return;
	}
#endif
    if (msec_millisecondCounter%10 == 0)
    {
        Tenmsec_millisecondCounter = msec_millisecondCounter;
    }
    //send message to the Millisec task
    MillisecMessage.messageId = OneMillisec;
    MillisecMessage.tick = msec_millisecondCounter++;
    MillisecMessage.msglen = sizeof(MillisecMessageStruc);
    if (MillisecMsgQ != NULL)
        Mailbox_post(MillisecMsgQ , &MillisecMessage, BIOS_NO_WAIT);

    if (Tenmsec_millisecondCounter)
    {
        MillisecMessage.messageId = OneMillisec;
        MillisecMessage.tick = Tenmsec_millisecondCounter;
        MillisecMessage.msglen = sizeof(MillisecMessageStruc);
        if (TenMillisecMsgQ != NULL)
            Mailbox_post(TenMillisecMsgQ , &MillisecMessage, BIOS_NO_WAIT);
    }

    //
    // Enable all interrupts.
    //
    ROM_IntMasterEnable();
    return ;
}
uint32_t PT100Activity = 0;

int32_t MillisecReadFromTempSensor(uint32_t TempSensorId,  MSecFptr Callback)
{
    if (TempSensorId >= MAX_MAIN_CARD_TEMP_SENS_ID) return -1;
    PT100Activity++; //read request
    PT100Data[TempSensorId].Callback = Callback;
    PT100Data[TempSensorId].Active = true;
    return OK;
}
//typedef  uint32_t (* MSecFptr)(uint32_t deviceID, uint32_t ReadValue);
uint32_t MotorActivity = 0;

int32_t MillisecSetMotorSpeed(TimerMotors_t MotorId, unsigned long Data, int Length, MSecFptr Callback)
{
    if (MotorId >= NUM_OF_MOTORS) return -1;
    //==========================
    if ((MotorId == HARDWARE_MOTOR_TYPE__MOTO_WINDER)||
        (MotorId == HARDWARE_MOTOR_TYPE__MOTO_RDRIVING)||
        (MotorId == HARDWARE_MOTOR_TYPE__MOTO_LDRIVING)||
		(MotorId == HARDWARE_MOTOR_TYPE__MOTO_SCREW))
    {
    MSBacklog[MsecLogindex]=Data;
    MSTick[MsecLogindex]=msec_millisecondCounter;
    Motor_Id[MsecLogindex]=MotorId;
    MsecLogindex++;
    if (MsecLogindex>=LOG_SIZE)
        MsecLogindex = 0;
    }
    //==========================

    SpeedSetPending[MotorId].Callback = Callback;
    SpeedSetPending[MotorId].Data = Data;
    SpeedSetPending[MotorId].Length = Length;
    SpeedSetPending[MotorId].DataRequired = false;
    if (SpeedSetPending[MotorId].Active == false)
    {
        MotorActivity++;
        SpeedSetPending[MotorId].Active = true;
    }

    return OK;
}
int MillisecFlushMsgQ(TimerMotors_t MotorId)
{
    MillisecMotorDataStruc MotorInfo = {0};
    int pend = Mailbox_getNumPendingMsgs(MotorsMsgQ[MotorId]);
    int i;
    if (pend)
    {
        for (i=0;i<pend;i++)
            Mailbox_pend(MotorsMsgQ[MotorId] , &MotorInfo, BIOS_NO_WAIT);
    }
   return pend;
}
int32_t MillisecWriteToMotor(TimerMotors_t MotorId, unsigned long Data, int Length, MSecFptr Callback)
{
    MillisecMotorDataStruc MotorInfo = {0};
    //==========================
    if ((MotorId == HARDWARE_MOTOR_TYPE__MOTO_WINDER)||
        (MotorId == HARDWARE_MOTOR_TYPE__MOTO_RDRIVING)||
        (MotorId == HARDWARE_MOTOR_TYPE__MOTO_LDRIVING)||
		(MotorId == HARDWARE_MOTOR_TYPE__MOTO_SCREW))
    {
    MSBacklog[MsecLogindex]=Data;
    MSTick[MsecLogindex]=msec_millisecondCounter;
    Motor_Id[MsecLogindex]=MotorId;
    MsecLogindex++;
    if (MsecLogindex>=LOG_SIZE)
        MsecLogindex = 0;
    }
    //==========================
    if (MotorId >= NUM_OF_MOTORS) return -1;
    MotorActivity++;
    MotorInfo.Callback = Callback;
    MotorInfo.Data = Data;
    MotorInfo.Length = Length;
    MotorInfo.DataRequired = false;
    if (MotorsMsgQ[MotorId] != NULL)
        return Mailbox_post(MotorsMsgQ[MotorId] , &MotorInfo, BIOS_NO_WAIT);
    else return false;
}
int32_t MillisecReadFromMotor(TimerMotors_t MotorId, unsigned long Data, int Length, MSecFptr Callback)
{
    MillisecMotorDataStruc MotorInfo = {0};
    if (MotorId >= NUM_OF_MOTORS) return -1;
//==========================
    if ((MotorId == HARDWARE_MOTOR_TYPE__MOTO_WINDER)||
        (MotorId == HARDWARE_MOTOR_TYPE__MOTO_RDRIVING)||
        (MotorId == HARDWARE_MOTOR_TYPE__MOTO_LDRIVING)||
		(MotorId == HARDWARE_MOTOR_TYPE__MOTO_SCREW))
    {
    MSBacklog[MsecLogindex]=Data;
    Motor_Id[MsecLogindex]=MotorId;
    MSTick[MsecLogindex]=msec_millisecondCounter;
    MsecLogindex++;
    if (MsecLogindex>=LOG_SIZE)
        MsecLogindex = 0;
    }
    //==========================
    MotorActivity++;
    MotorActivity++;
    MotorInfo.Callback = Callback;
    MotorInfo.Data = Data;
    MotorInfo.Length = Length;
    MotorInfo.DataRequired = true;
    if (MotorsMsgQ[MotorId] != NULL)
        return Mailbox_post(MotorsMsgQ[MotorId] , &MotorInfo, BIOS_NO_WAIT);
    else return false;
}

uint32_t MillisecLoop(uint32_t tick)
{
    uint8_t Motor_i;
    TEMPERATURE_SENSOR_ID_ENUM Sensor_i;
    unsigned int MotorInfo = 0;
    static int temp=0;
    //call all modules Millisec functions
    //test dancers and speed encoders
    //check all callback units (state machine waiting for completion of a change)
/*    bool Ten_msTick, Hundred_msTick, Onesecond_Tick,O900Millisecond_Tick,Tick98,OneMinute_Tick;
    Ten_msTick      =   (tick%eTenMillisecond == 0)      ?true:false;
    Hundred_msTick  =   (tick%eHundredMillisecond == 0)  ?true:false;
    O900Millisecond_Tick  =   (tick%eOneSecond == 900)           ?true:false;
    Onesecond_Tick  =   (tick%eOneSecond == 0)           ?true:false;
    OneMinute_Tick  =   (tick%eOneMinute == 0)           ?true:false;
    Tick98          =   (tick%eHundredMillisecond == 99) ?true:false;
    //gather Motor data from FPGA
    //ROM_IntMasterDisable();
*/
#ifndef EVALUATION_BOARD
        FPGA_GetBusy();  //load the busy motor information to all motors
        FPGA_Read_LS_Safty_Ind_Reg();
        //Read_FPGA_GPI_Rgisters();//FPGA_Read_limit_Switches();
#endif

        temp += MotorActivity;
   if (MotorActivity)
   {
        for (Motor_i = 0;Motor_i < NUM_OF_MOTORS;Motor_i++)
        {
            if (MotorDriverResponse[Motor_i].Busy == true)
            {
                temp++;
                continue;
            }
            if (MotorData[Motor_i].WaitForData == true) //Read request sent, data is waiting
            {
                if (MotorGetFPGAResponse((HardwareMotorType)Motor_i,&MotorInfo) == OK) //got the data from the FPGA
                {
                    MotorData[Motor_i].WaitForData = false;
                    if (MotorData[Motor_i].Callback)
                        MotorData[Motor_i].Callback(Motor_i,MotorInfo);
                }
                MotorActivity--;
            }
            if (SpeedSetPending[Motor_i].Active == true)
            {
                MotorSendFPGARequest((HardwareMotorType)Motor_i,SpeedSetPending[Motor_i].Data,SpeedSetPending[Motor_i].Length);
                MotorActivity--;
                SpeedSetPending[Motor_i].Active = false;
                if (SpeedSetPending[Motor_i].Callback)
                    SpeedSetPending[Motor_i].Callback(Motor_i,0);
            }
            else if (Mailbox_pend(MotorsMsgQ[Motor_i] , &MotorData[Motor_i], BIOS_NO_WAIT)==true)
            {
                if (MotorSendFPGARequest((HardwareMotorType)Motor_i,MotorData[Motor_i].Data,MotorData[Motor_i].Length) == OK) //sent the data to the FPGA
                {
                    if (MotorData[Motor_i].DataRequired == true)
                    {
                        MotorData[Motor_i].WaitForData = true; // mark the motor for data request next round
                    }
                    else
                    {
                        if (MotorData[Motor_i].Callback)
                            MotorData[Motor_i].Callback(Motor_i,0); // call the callback to report execution
                    }
                }
                MotorActivity--;
            }
        }
   }
    //FPGA_GetTempSensorBusy();
   //int PT100Busy[MAX_MAIN_CARD_TEMPERATURE_SENSOR_ID] = {0,0,0,0,0,0,0,0,0,0};
   if (PT100Activity)
   {

       for (Sensor_i = 0;Sensor_i < MAX_MAIN_CARD_TEMP_SENS_ID;Sensor_i++)
       {
           /*if (TempSensorResponse[Sensor_i].Busy == true)
           {
               PT100Busy[Sensor_i]++;
               continue;
           }*/
           if (PT100Data[Sensor_i].Active == true)
           {
               if(Sensor_i < MAX_MAIN_CARD_TEMP_SENS_ID)
               {
                   TemperatureSendSensorDummyClk(Sensor_i);
               }
               PT100Data[Sensor_i].Active = false;
               PT100Data[Sensor_i].WaitForData = true; // mark the motor for data request next round
               break; //  one PT100 activitiy per MS 
           }
           else if (PT100Data[Sensor_i].WaitForData == true) //Read request sent, data is waiting
           {
               if(Sensor_i < MAX_MAIN_CARD_TEMP_SENS_ID)
               {
                   TemperatureSensorReadFromFPGA_Res(Sensor_i); //got the data from the FPGA
               }
               /*else if(Sensor_i < MAX_HEAD_CARD_TEMP_SENS_ID) - move to the function  control_HeadCard_PT100
               {
                   //HeadCard_Toggle_PT100(Sensor_i);
                   //delay??
                   //HeadADCPT100_SendReadDataCommand(Sensor_i);
               }
               else if(Sensor_i < MAX_WHS_CARD_TEMP_SENS_ID)
               {
                   //for WHS...
               }
               else
               {
                   //TBD
               }*/

               PT100Data[Sensor_i].WaitForData = false;
               PT100Data[Sensor_i].SyncRequired = true;
               if (PT100Data[Sensor_i].Callback)
                       PT100Data[Sensor_i].Callback(Sensor_i,MotorInfo);
               break; // one PT100 activitiy per MS 
           }
           else if (PT100Data[Sensor_i].SyncRequired == true)
           {
               if(Sensor_i < MAX_MAIN_CARD_TEMP_SENS_ID)
               {
                   TemperatureSensorSync(Sensor_i);
               }
               /*else if(Sensor_i < MAX_HEAD_CARD_TEMP_SENS_ID)  - NA move to the function  control_HeadCard_PT100
               {
                   //HeadADCPT100_StartSync(Sensor_i);
               }
               else if(Sensor_i < MAX_WHS_CARD_TEMP_SENS_ID)
               {
                   //StartSync WHS...
               }
               else
               {
                   //TBD...
               }*/


               PT100Data[Sensor_i].SyncRequired = false;
               PT100Activity--;
               break; // one PT100 activitiy per MS 
           }
       }
   }
#ifdef HUNDRED_MICROSECONDS_DANCER_READ
   SaveLogData();
#else

    #ifdef test_RTFU_dancer
       test_dancer_responce_RTFU();
    #else
        Dancer_Data[FEEDER_DANCER] = Read_Dancer_Position(FEEDER_DANCER);
        Dancer_Data[POOLER_DANCER] = Read_Dancer_Position(POOLER_DANCER);
        Dancer_Data[WINDER_DANCER] = Read_Dancer_Position(WINDER_DANCER);
    #endif

#endif
    return OK;
}
int TemperatureSum[MAX_HEAD_CARD_TEMP_SENS_ID];
int TemperatureMin[MAX_HEAD_CARD_TEMP_SENS_ID];
int TemperatureMax[MAX_HEAD_CARD_TEMP_SENS_ID];
int TemperatureCount[MAX_HEAD_CARD_TEMP_SENS_ID];
int TemperatureCalc[MAX_HEAD_CARD_TEMP_SENS_ID];
void MillisecUpdateTemperatures (TEMPERATURE_SENSOR_ID_ENUM SensorId,int temperature)
{
   //if(TemperatureCount[SensorId]++>=10)
   //    TemperatureCount[SensorId] = 0;
    TemperatureCount[SensorId]++;
    if (TemperatureMax[SensorId]<temperature) TemperatureMax[SensorId]=temperature;
    if (TemperatureMin[SensorId]>temperature) TemperatureMin[SensorId]=temperature;
    TemperatureSum[SensorId]+=temperature;
}
int MillisecCalculateTemperatures (TEMPERATURE_SENSOR_ID_ENUM SensorId)
{
    int calc = 0;
    TemperatureSum[SensorId]-=TemperatureMax[SensorId];
    TemperatureSum[SensorId]-=TemperatureMin[SensorId];
    calc = TemperatureSum[SensorId] / (TemperatureCount[SensorId]-2);

    TemperatureSum[SensorId] = 0;
    TemperatureCount[SensorId] = 0;
    TemperatureMin[SensorId] = 30000;
    TemperatureMax[SensorId] = -30000;
    return calc;
}
int MillisecGetTemperatures (TEMPERATURE_SENSOR_ID_ENUM SensorId)
{
    if (SensorId > WHS_PT100_4_0X82_1)
        return 0;
    return TemperatureCalc[SensorId];
}
bool RapidPressureRead = true;
float PressureSum[MAX_SYSTEM_DISPENSERS];
float PressureMin[MAX_SYSTEM_DISPENSERS];
float PressureMax[MAX_SYSTEM_DISPENSERS];
float PressureCount[MAX_SYSTEM_DISPENSERS];
float PressureCalc[MAX_SYSTEM_DISPENSERS];
void MillisecUpdatePressures (int SensorId,float Pressure)
{
   //if(PressureCount[SensorId]++>=10)
   //    PressureCount[SensorId] = 0;
    PressureCount[SensorId]++;
    if (PressureMax[SensorId]<Pressure) PressureMax[SensorId]=Pressure;
    if (PressureMin[SensorId]>Pressure) PressureMin[SensorId]=Pressure;
    PressureSum[SensorId]+=Pressure;
}
float MillisecCalculatePressures (int SensorId)
{
    float calc = 0;
    PressureSum[SensorId]-=PressureMax[SensorId];
    PressureSum[SensorId]-=PressureMin[SensorId];
    calc = PressureSum[SensorId] / (PressureCount[SensorId]-2);

    PressureSum[SensorId] = 0;
    PressureCount[SensorId] = 0;
    PressureMin[SensorId] = 30000;
    PressureMax[SensorId] = -30000;
    return calc;
}
float MillisecGetPressures (int SensorId)
{
    if (SensorId > MAX_SYSTEM_DISPENSERS)
        return 0;
    return PressureCalc[SensorId];
}

bool getRapidPressureRead(void)
{
    return RapidPressureRead;
}
void setRapidPressureRead(bool value)
{
    RapidPressureRead = value;
    if (GetDiagnosticMode() == Diagnostic_Extreme_Mode)
        RapidPressureRead = true;
}

uint16_t PumpCounter = 0;
uint16_t realtimetest[101];
uint32_t MillisecLowLoop(uint32_t tick)
{
    uint8_t Motor_i,Disp_i,temp;
    TEMPERATURE_SENSOR_ID_ENUM Sensor_i;

    //static int temp=0;
    //call all modules Millisec functions
    //test dancers and speed encoders
    //check all callback units (state machine waiting for completion of a change)
    bool Ten_msTick, Fifty_msTick, Hundred_msTick , m20msecTick,m70msecTick,m90msecTick, Onesecond_Tick,Tensecond_Tick,OneMinute_Tick,TenMinutes_Tick,OneHourTick,Gradient_Tick;
    bool O700Millisecond_Tick,O200Millisecond_Tick,O400Millisecond_Tick,O500Millisecond_Tick,O600Millisecond_Tick;
    //bool O100Millisecond_Tick,O200Millisecond_Tick,O400Millisecond_Tick,O500Millisecond_Tick,O600Millisecond_Tick,O800Millisecond_Tick,O900Millisecond_Tick;
    Ten_msTick      =   (tick%eTenMillisecond == 0)      ?true:false;
    Fifty_msTick      =   (tick%eHundredMillisecond == 40)      ?true:false; //eFiftyMillisecond
    Hundred_msTick  =   (tick%eHundredMillisecond == 0)  ?true:false;
    m20msecTick  =   (tick%eHundredMillisecond == 20)  ?true:false;
    m70msecTick  =   (tick%eHundredMillisecond == 70)  ?true:false;
    m90msecTick  =   (tick%eHundredMillisecond == 90)  ?true:false;
    O700Millisecond_Tick  =   (tick%eOneSecond == 700)           ?true:false;
    O200Millisecond_Tick  =   (tick%eOneSecond == 200)           ?true:false;
    O400Millisecond_Tick  =   (tick%eOneSecond == 400)           ?true:false;
    O500Millisecond_Tick  =   (tick%eOneSecond == 500)           ?true:false;
    O600Millisecond_Tick  =   (tick%eOneSecond == 600)           ?true:false;
    //O800Millisecond_Tick  =   (tick%eOneSecond == 800)           ?true:false;
    //O900Millisecond_Tick  =   (tick%eOneSecond == 900)           ?true:false;
    Gradient_Tick  =   (tick%400 == 0)           ?true:false;
    Onesecond_Tick  =   (tick%eOneSecond == 0)           ?true:false;
    Tensecond_Tick  =   (tick%10000 == 0)           ?true:false;
    OneMinute_Tick  =   (tick%eOneMinute == 0)           ?true:false;
    TenMinutes_Tick  =   (tick%eTenMinutes == 0)           ?true:false;
    OneHourTick  =   (tick%eOneHour == 0)           ?true:false;
    realtimetest[(tick%1000)/10]++;
    //gather Motor data from FPGA
    //ROM_IntMasterDisable();
    int StartPT100 = 0;
    //Screw_ENC_Velocity_to_DAC(); - for testing the screw enc
    if (Head_Type > HEAD_TYPE_SYLKO_WITHOUT_CARD)
        StartPT100 = TEMP_SENSE_ANALOG_DRYER_TEMP1;
    if (Ten_msTick)
    {
        Speed_Data = Read_Speed_Sensor_TypeII();
        //MillisecReadFromTempSensor(Sensor_Read, NULL);
        //if (Sensor_Read++ >= MAX_MAIN_CARD_TEMPERATURE_SENSOR_ID) Sensor_Read = 0;
        if(Machine_Idle_Mode == true)
            Machine_Idle_Breathing_Led();
        Trigger_HeaterWriting();

    }
    if (m20msecTick)
    {
        ADC0SS0Handler();
    }
    if(Fifty_msTick)
    {
        WHS_Read_GPI_Registers();
        Trigger_PT100_Read();//call every 50mSec (minimum delay 30mSec)
        //Set_HeadCard_PT100();//call every 50mSec (minimum delay 30mSec)
    }
    if(m70msecTick)
    {
        AlarmHandling_ControlTrigger(0,0);
    }
    if (m90msecTick)
    {
        for (Sensor_i = StartPT100;Sensor_i < MAX_HEAD_CARD_TEMP_SENS_ID;Sensor_i++)
        {
            MillisecReadFromTempSensor(Sensor_i, NULL);
        }
    }
    if (Hundred_msTick)
    {
        Speed_Data = Calculate_Speed_Sensor_Velocity();
#ifndef EVALUATION_BOARD
        Read_Buttons_Reg();
#endif
        ///////////////////////////////////////////////////////////////////


        for (Sensor_i = StartPT100;Sensor_i < MAX_HEAD_CARD_TEMP_SENS_ID;Sensor_i++)
        {
            MillisecUpdateTemperatures (Sensor_i,TemperatureSensorRead(Sensor_i));
        }
        if (GeneralHwReady == true)
        {
            if (watchdogCriticalAlarm == false)
            {
                Control_WD(ENABLE,10);  //activate heaters/dispenser watchdog, 0.5 seconds
                //LOG_ERROR (1111, "Control_WD");
            }
        }
        if (RapidPressureRead == true)
        {
            for (Disp_i = 0;Disp_i < MAX_SYSTEM_DISPENSERS;Disp_i++)
            {
                MillisecUpdatePressures(Disp_i, CalculateDispenserPressure(Disp_i));
            }
            ADC_TriggerCollection();
        }

        Trigger_InputsReading();
    }
    if (Gradient_Tick)
        DispensersCollectionCall();
    if (O700Millisecond_Tick)
    {
        Trigger_Heater_Current_Read();
    }
    if (O200Millisecond_Tick)
    {
        Trigger_WHS_MAX11614_Read_allADC();
        FPGA_GetAllDispensersValveBusyOCD();
        temp = Read_Fans_Tacho();
        DrawerFansStatus = temp & 0x1F;
        SystemFansStatus = temp & 0xE0;
    }
    if (O400Millisecond_Tick)
    {
        for (Motor_i = 0;Motor_i < NUM_OF_MOTORS;Motor_i++)
        {
            if (Motor_i == HARDWARE_MOTOR_TYPE__MOTO_SCREW)
                continue;  //
            if (isMotorConfigured(Motor_i))
                MotorGetStatusFromFPGA(Motor_i);
        }
    }
    if ((O500Millisecond_Tick)&&(RapidPressureRead == false))
    {
        ADC_TriggerCollection();
    }
    if (O600Millisecond_Tick)
    {
        Trigger_WHSReadAllFanTacho ();
        DrierHeaterVoltageSetup();
        if (RapidPressureRead == false)
        {
            for (Disp_i = 0;Disp_i < MAX_SYSTEM_DISPENSERS;Disp_i++)
            {
                CalculateDispenserPressure(Disp_i);
            }
        }
    }
    if (Onesecond_Tick)
    {
        //char Lenstr[160];
        //static int Counter = 0;
        MachineUpdateResponseFunc();
        //KeepAliveOneSecondCall();

        //TemperatureListString(Lenstr);
        //ReportWithPackageFilter(ThreadFilter,Lenstr,__FILE__,__LINE__,(int)Counter++,RpWarning,(int) msec_millisecondCounter,0);
        for (Sensor_i = StartPT100;Sensor_i < MAX_HEAD_CARD_TEMP_SENS_ID;Sensor_i++)
        {
            TemperatureCalc[Sensor_i] =  MillisecCalculateTemperatures ( Sensor_i);
        }
        if (RapidPressureRead == true)
        {
            for (Disp_i = 0;Disp_i < MAX_SYSTEM_DISPENSERS;Disp_i++)
            {
                PressureCalc[Disp_i] = MillisecCalculatePressures(Disp_i);
            }
        }
        if (WHS_Type == WHS_TYPE_NEW)
        {
            //Trigger_WHS_PT100_Read_All();
            WHS_Blower_Avarege(HEAD_FLOW_METER);
            WHS_Blower_Avarege(DRIER_FLOW_METER);
            WHS_Start_Blower_Control_Closed_Loop ();

           /* static uint8_t Whs_emptying_cycle = 0;

            // #warning TBD need to define the timing
            if(Whs_emptying_cycle >= 2)
            {
                waste_seq_step1();// include 1Sec delay
                Whs_emptying_cycle = 0;
            }
            else
            {
                Whs_emptying_cycle++;
            }
            */
        }

        //call waste state machine
        Waste_StateMachine_OneSecond_Call();

        //call IFS state machine
        midTankStateMachine();
    }
    if (Tensecond_Tick)
    {
        //Trigger_MidTank_Pressure_Read();
        for (Disp_i = 0;Disp_i < MAX_SYSTEM_DISPENSERS;Disp_i++)
        {
            Read_MidTank_Pressure_Sensor(Disp_i);
        }
    }
    if (OneMinute_Tick)
    {
//        MachineUpdateResponseFunc();
        /*        for (Motor_i = 0;Motor_i < NUM_OF_MOTORS;Motor_i++)
        {
            if (Motor_i == HARDWARE_MOTOR_TYPE__MOTO_SCREW)
                continue;  //
            if (isMotorConfigured(Motor_i))
                MotorGetStatusFromFPGA(Motor_i);
        }*/
        midtankDisplay = 1-midtankDisplay;
        /*if (WHS_Type == WHS_TYPE_UNKNOWN)
            Gas_PPM_Info = Calculate_Gas_Power_Consumption();*/
//            ReportWithPackageFilter(ThreadFilter,"waste tank calculate level",__FILE__,__LINE__,(int)(GetWHSWasteTankLevelMiliLiter()*1000),RpWarning,(int) msec_millisecondCounter,0);
        //Trigger_WHS_MAX11614_Read_allADC();
        Trigger_WHS_MAX11614_Read_Gas_Sensor();
#ifdef CONTROL_DEBUG
        ResetControlTime();
#endif
    }
    if (TenMinutes_Tick)
    {
        if (WHS_Type == WHS_TYPE_NEW)
        {
            waste_seq_step1();// include 1Sec delay           <- to open !!!!
        }
    }
    if (OneHourTick)
    {
#define PUMP_LIMIT 4
        PumpCounter++;
        if (PumpCounter>=PUMP_LIMIT)
        {
            PumpActivation(900);
            PumpCounter = 0;
        }
        MidTankReading();
        /*if (WHS_Type == WHS_TYPE_NEW)
        {
            waste_seq_step1();// include 1Sec delay           <- to open !!!!
        }*/
        //Trigger_WHS_MAX11614_Read_Gas_Sensor();
    }
    //ROM_IntMasterEnable();


    return OK;
}
/******************************************************************************
 *  ======== messageTsk ========
 *  Task for this function is created statically. See the project's .cfg file.
 *  this message task is created statically in system initialization,
 ******************************************************************************/
void MillisecTask(UArg arg0, UArg arg1)
{
    MillisecMessageStruc MillisecMessage;
    //char str[60];
    //uint16_t length;
    //Clock_setTimeout(HostKAClock, 1000);
    //Clock_start(HostKAClock);
    //MillisecInit();
    Millisecond_Task_Handle = Task_self();
    while(1)
    {
        Mailbox_pend(MillisecMsgQ , &MillisecMessage, BIOS_WAIT_FOREVER);
        switch (MillisecMessage.messageId)
        {
            case OneMillisec:
                MillisecLoop(MillisecMessage.tick);
                break;
            default:
                break;
        }
    }
}
/******************************************************************************
 *  ======== messageTsk ========
 *  Task for this function is created statically. See the project's .cfg file.
 *  this message task is created statically in system initialization,
 ******************************************************************************/
void MillisecLowTask(UArg arg0, UArg arg1)
{
    MillisecMessageStruc MillisecLowMessage;
    //char str[60];
    //uint16_t length;
    //Clock_setTimeout(HostKAClock, 1000);
    //Clock_start(HostKAClock);
    //MillisecInit();
    //Millisecond_Task_Handle = Task_self();
    while(1)
    {
        Mailbox_pend(TenMillisecMsgQ , &MillisecLowMessage, BIOS_WAIT_FOREVER);
        switch (MillisecLowMessage.messageId)
        {
            case OneMillisec:
                MillisecLowLoop(MillisecLowMessage.tick);
                break;
            default:
                break;
        }
    }
}


/*uint32_t getMotorStatusData(int MotorId)
{
    assert (MotorId < NUM_OF_MOTORS);
    return MotorStatus_Data[MotorId];
}*/
/*uint32_t getMotorSpeedData(int MotorId)
{
    assert (MotorId < NUM_OF_MOTORS);
    return MotorSpeed_Data[MotorId];
}
*/
/*uint32_t getTemperatureSensorData(int SensorId)
{
    assert (SensorId < MAX_MAIN_CARD_TEMPERATURE_SENSOR_ID);
    return TemperatureSensor_Data[SensorId];
}*/

/*uint32_t getADCData(int DeviceId)
{
    assert (DeviceId < MAX_ADC_DEVICES);
    return ADC_Data[DeviceId];
}*/
float getSensorSpeedData(void)
{
    return Speed_Data;
}

uint32_t getDrawerFansStatus(void)
{
    return DrawerFansStatus;
}
uint8_t getGasReading(void)
{
    return Gas_PPM_Info;
}

uint32_t getSystemFansStatus(void)
{
    return SystemFansStatus;
}
#ifdef HUNDRED_MICROSECONDS_DANCER_READ
uint32_t DancerData[NUM_OF_DANCERS];
uint32_t Control_Read_Dancer_Position(HardwareDancerType DancerId, uint32_t Parameter1, uint32_t Parameter2)
{
    return DancerData[DancerId];
}
uint32_t dancer1;
uint32_t dancer2;
uint32_t dancer3;
uint32_t dancer1sum;
uint32_t dancer2sum;
uint32_t dancer3sum;
uint32_t dancer_count;
/*-----------------------*/
uint32_t StoreBuffer[2][128];
//char * StoreBuffer[2][512];
/*-----------------------*/
int  StoreBufferId = 0;
int  StoreBufferCounter=0;
uint32_t  BufferCounter=0xEEEEEEEE;
bool storeData=false;
uint8_t len=0;
void HundredMicroTimerInterrupt(int ARG0)
{
    ROM_IntMasterDisable();
    ROM_TimerIntClear(Millisec_timerBase, TIMER_TIMA_TIMEOUT);  // Clear the timer interrupt
    if (MillisecRestart == true)
    {
        ROM_TimerLoadSet(Millisec_timerBase, TIMER_A,HIGH_TASK_FREQUENCY);
    }
    else
    {
        ROM_TimerDisable(Millisec_timerBase,TIMER_A);
        ROM_IntMasterEnable();
        return;
    }
    dancer1 = Read_Dancer_Position(WINDER_DANCER);
    dancer2 = Read_Dancer_Position(POOLER_DANCER);
    dancer3 = Read_Dancer_Position(FEEDER_DANCER);
//data store - logging
//double buffer switch
    /*-----------------------*/
    if (StoreBufferCounter>125)
    //if (StoreBufferCounter>490)
        /*-----------------------*/
    {
        StoreBufferId = 1-StoreBufferId;//switch buffer
        StoreBufferCounter=0;
        storeData = true;
    }
//double buffer initialize
    /*-----------------------*/
    if (StoreBufferCounter==0)
    {
        StoreBuffer[StoreBufferId][StoreBufferCounter] = BufferCounter++;
        StoreBufferCounter++;
    }
    /*-----------------------*/
//store data
    /*-----------------------*/
    StoreBuffer[StoreBufferId][StoreBufferCounter++] = dancer1;
    StoreBuffer[StoreBufferId][StoreBufferCounter++] = dancer2;
    StoreBuffer[StoreBufferId][StoreBufferCounter++] = dancer3;
    /*-----------------------*/
    //len = usprintf(&StoreBuffer[StoreBufferId][StoreBufferCounter], "%d %d %d", dancer1[dancer_count],dancer2[dancer_count],dancer3[dancer_count]);
    //StoreBufferCounter+=(len+1);
    /*-----------------------*/
    dancer1sum+=dancer1;
    dancer2sum+=dancer2;
    dancer3sum+=dancer3;
    dancer_count++;


    if (dancer_count == 10)
    {
        DancerData[WINDER_DANCER] = dancer1sum/dancer_count;
        DancerData[POOLER_DANCER] = dancer2sum/dancer_count;
        DancerData[FEEDER_DANCER] = dancer3sum/dancer_count;
        dancer_count = 0;
        dancer1sum = 0;
        dancer2sum = 0;
        dancer3sum = 0;
        OneMilliSecondMillisecInterrupt(ARG0);
    }
    ROM_IntMasterEnable();
    return ;

}
char MillisecPath[50] = "0://SysInfo//Millisec.txt";
FIL *FileHandle;
void SaveLogData(void)
{
    uint32_t WrittenBytes = 0;
    int BufferID = 1- StoreBufferId;

    if (storeData == true)
    {
        if (FileHandle)
        {
            f_write(FileHandle,StoreBuffer[BufferID],512,&WrittenBytes );
            storeData = false;
        }
    }
}
void MillisecLogInit(void)
{
    FRESULT Fresult = FR_OK;
    ROM_IntMasterDisable();
    BufferCounter = 0;
    FileHandle = my_malloc(sizeof(FIL));
    if (FileHandle == 0)
        Fresult = FR_DENIED;
    else
        Fresult = f_open(FileHandle,MillisecPath,FA_WRITE |  FA_OPEN_ALWAYS|FA_CREATE_ALWAYS);
    ROM_IntMasterEnable();
    return ;

}
void MillisecLogClose(void)
{
    FRESULT Fresult = FR_OK;
    if (FileHandle == 0)
        Fresult = FR_DENIED;
    else
    {
        storeData = false;
        ROM_IntMasterDisable();
        Fresult = f_close(FileHandle);
        my_free(FileHandle);
        FileHandle = 0;
        ROM_IntMasterEnable();
    }
    return ;

}
#endif
void MillisecInterrupt(UArg arg0)
{
#ifdef HUNDRED_MICROSECONDS_DANCER_READ
    HundredMicroTimerInterrupt(arg0);
#else
    OneMilliSecondMillisecInterrupt(arg0);
#endif
}