/******************************************************************************
* File name:   main.c
* Version:     1.0.0
* Discription:
*   This is the trial of anomaly detection for ECG by means of autoencoder.
** History:
*   1.0.0  2018.03.28  Initial coding
*
* Copyright 2018 METOOL Inc. All Rights Reserved
******************************************************************************/

/******************************************************************************
* Included headers
******************************************************************************/
#include "main.h"

/******************************************************************************
* Static variables 
******************************************************************************/
int data_ptr;                           // Indicate to input data
int32 in_node[INPUT_UNIT_SIZE];         // Input node values
int32 hid_node[HIDDEN_UNIT_SIZE];       // Hidden node values
int64 score_val;                        // Anomaly score value
int volatile score_flag;                // Score ready flag

/******************************************************************************
* Function Name: timer_isr
*******************************************************************************
* Summary:
* Timer interrupt service routine. Loading ECG data and calculating anomaly score.
*
* Parameters:
*  void
*
******************************************************************************/
CY_ISR(timer_isr)
{
    int i, j;

    int32 temp;

    Pin_GPIO_2_Write(IO_HIGH);
    
    // Load ECG data
    for(i=0; i<INPUT_UNIT_SIZE; i++) {
        in_node[i] = ECG_DAT[i + data_ptr];
    }
    data_ptr = (data_ptr + 1) % (TEST_DATA_SIZE - INPUT_UNIT_SIZE + 1);

    // Start calculating 2 layer neural network and anomaly score
    Pin_GPIO_1_Write(IO_HIGH);
    
    // Hidden layer
    for(i=0; i<HIDDEN_UNIT_SIZE; i++) {
        temp = 0;
        for(j=0; j<INPUT_UNIT_SIZE; j++) {
            temp += ( (in_node[j] * W1[i*INPUT_UNIT_SIZE + j]) >> DAT_Q_FMT );      // Never exceeding int32
        }
        temp += B1[i];
        hid_node[i] = RELU(temp);
    }

    // Output layer
    score_val = 0;
    for(i=0; i<OUTPUT_UNIT_SIZE; i++) {
        temp = 0;
        for(j=0; j<HIDDEN_UNIT_SIZE; j++) {
            temp += ( (hid_node[j] * W2[i*HIDDEN_UNIT_SIZE + j]) >> DAT_Q_FMT );    // Never exceeding int32
        }
        temp += B2[i];
        temp = in_node[i] - RELU(temp);
        score_val += ((int64)temp * (int64)temp);
    }
    score_val = (int64)(sqrt(score_val));
    
    Pin_GPIO_1_Write(IO_LOW);

    // Output the score value to DAC
    VDAC8_1_SetValue((uint8)MIN( (score_val >> 4), 255 ));
    
    // Detecting anomaly data
    if( score_val > THRESHOLD_VALUE ) {
        Pin_LED_Write(LED_ON);
    } else {
        Pin_LED_Write(LED_OFF);
    }
    
    // Set score ready flag
    score_flag = TRUE;
    
    Pin_GPIO_2_Write(IO_LOW);
}

/******************************************************************************
* Function Name: main
*******************************************************************************
* Summary:
* System entrance point.
* This processes initializing and sending result via USB serial.
*
* Parameters:
*  void
*
* Return:
*  int
*
******************************************************************************/
int main(void)
{
    char str[16];
    
    // Initiaize
    data_ptr = 0;
    score_val = 0;
    score_flag = FALSE;

    Pin_GPIO_1_Write(IO_LOW);
    Pin_GPIO_2_Write(IO_LOW);
    Pin_LED_Write(LED_OFF);
    VDAC8_1_Start();
    isr_1_StartEx(timer_isr);
    Timer_1_Start();
    
    CyGlobalIntEnable;

    USBUART_1_Start(0, USBUART_1_5V_OPERATION);
    while(!USBUART_1_GetConfiguration()){};
    USBUART_1_CDC_Init();
    
    for(;;) {
        if(score_flag) {
            sprintf(str, "%ld", (int32)score_val);
            while(USBUART_1_CDCIsReady() == 0u) {};
            USBUART_1_PutString(str);
            while(USBUART_1_CDCIsReady() == 0u) {};
            USBUART_1_PutCRLF();
            score_flag = FALSE;
        }
    }
}

/* [] END OF FILE */
