/*
 * Andrue Peters
 * 11/13/18
 *
 */
/*
 *  ======== empty.c ========
 */

#include "project5.h"

/* Graphic library context */
Graphics_Context g_sContext;






/*
 *  ======== main ========
 */
int main(void)
{

    /* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();
    Board_initADC();
    Board_initPWM();
    // Board_initI2C();

    LCD_init();

    Error_Block eb;
    Error_init(&eb);

    /* Constructs a one-shot clock instance to show splash screen */
    Clock_Params clk_params;
    Clock_Params_init(&clk_params);
    clk_params.period = 0;
    clk_params.startFlag = TRUE;
    Clock_construct(&clock_splash_scrn_struct, (Clock_FuncPtr)CLK_TSK_LCD_draw_splash_screen,
                    1, &clk_params);

    /* Constructs a one-shot clock instance for enabling buzzer */
    clk_params.startFlag = FALSE; // only this needed to change from previous
    CLK_HDL_enable_buzzer = Clock_create((Clock_FuncPtr)CLK_TSK_en_buzzer,
                                         1, &clk_params, &eb);

    /* Constructs a one-shot clock instance for disabling buzzer */
    CLK_HDL_disable_buzzer = Clock_create((Clock_FuncPtr)CLK_TSK_disable_buzzer,
                                         Clock_tickPeriod, &clk_params, &eb);


    /* Periodic clock to check accelerometer values */
    clk_params.period = 400000 / Clock_tickPeriod;
    clk_params.startFlag = TRUE;
    Clock_construct(&clock_accel_struct, (Clock_FuncPtr)CLK_TSK_read_accelerometer, Clock_tickPeriod*10, &clk_params);

    /* Create PWM */
    PWM_Params params;
    uint16_t pwm_pd = 3000;
    uint16_t pwm_dc = pwm_pd / 2;

    PWM_Params_init(&params);
    params.dutyUnits = PWM_DUTY_US;
    params.dutyValue = pwm_dc;
    params.periodValue = pwm_pd;
    PWM_HDL_buzzer = PWM_open(Booster_BUZZER_PWM, &params);

    /* Configure Semaphores */
    Semaphore_Params sem_params;
    sem_params.mode = ti_sysbios_knl_Semaphore_Mode_BINARY;
    Semaphore_Params_init(&sem_params);

    Semaphore_construct(&SEMSTRUCT_update_LCD, 1, &sem_params);
    SEMHDL_update_LCD = Semaphore_handle(&SEMSTRUCT_update_LCD);

    Semaphore_construct(&SEMSTRUCT_update_accel, 1, &sem_params);
    SEMHDL_update_accel = Semaphore_handle(&SEMSTRUCT_update_accel);

    Semaphore_construct(&SEMSTRUCT_update_temp, 1, &sem_params);
    SEMHDL_update_temp = Semaphore_handle(&SEMSTRUCT_update_temp);


    /*Task_Struct adc_task_struct, update_lcd_task_struct, update_temp_task_struct;
    Char adc_task_stack[TASKSTACKSIZE], update_lcd_task_stack[TASKSTACKSIZE], update_temp_stack[TASKSTACKSIZE];
*/
    /* Initialize Tasks */
    Task_Params task_params;
    Task_Params_init(&task_params);
    task_params.stackSize = TASKSTACKSIZE;
    task_params.priority = 1;

    // init adc task
    task_params.stack = &adc_task_stack;
    TSK_HDL_adc = Task_create(TSK_read_accelerometer, &task_params, &eb);
   // Task_construct(&adc_task_struct, (Task_FuncPtr)TSK_read_accelerometer, &task_params, NULL);

    // init




    System_printf("Starting the example\nSystem provider is set to SysMin. "
                  "Halt the target to view any SysMin contents in ROV.\n");
    /* SysMin will only print to the console when you call flush or exit */
    System_flush();


    /* Start BIOS */
    BIOS_start();

    return (0);
}

/*************************************************************/
/*              Hardware Config                              */
/*************************************************************/
Void LCD_init()
{
    MAP_FlashCtl_setWaitState(FLASH_BANK0, 2);
    MAP_FlashCtl_setWaitState(FLASH_BANK1, 2);

    /* Initializes display */
    Crystalfontz128x128_Init();

    /* Set default screen orientation */
    Crystalfontz128x128_SetOrientation(0);

    /* Initializes graphics context */
    Graphics_initContext(&g_sContext, &g_sCrystalfontz128x128, &g_sCrystalfontz128x128_funcs);
    Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_RED);
    Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_WHITE);
    GrContextFontSet(&g_sContext, &g_sFontFixed6x8);
    Graphics_clearDisplay(&g_sContext);



    /* Turn on user LED */
    GPIO_write(Board_LED0, Board_LED_OFF);
}

/*************************************************************/
/*              Clock Tasks                                  */
/*************************************************************/

/*
 * Draws image on screen. Configured as a one-shot clk task
 */
Void CLK_TSK_LCD_draw_splash_screen()
{
    Graphics_drawImage(&g_sContext, &lotr_tree_splash_screen_img, 0, 0);
}

/*
 * Posts a semaphore, allowing the ADC tasks to process the accelerometer
 * Configured to be periodic
 */
Void CLK_TSK_read_accelerometer()
{
    Semaphore_post(SEMHDL_update_accel);
}

/*
 * Enables the buzzer. Automatically disables on leave.
 * Configured as a one-shot that is called as needed in the accelerometer tasks
 */
Void CLK_TSK_en_buzzer()
{
    PWM_start(PWM_HDL_buzzer);
    Clock_start(CLK_HDL_disable_buzzer);
}

/*
 * Disables the buzzer. Automatically disables on leave.
 * Configured as a one-shot that is called as needed in the accelerometer tasks
 */
Void CLK_TSK_disable_buzzer()
{
    PWM_stop(PWM_HDL_buzzer);
}
/*************************************************************/
/*              ADC Funcs                                    */
/*************************************************************/

/*
 * Reads, udpates, and process information relating to accelerometer
 * Waits on SEMHDL_update_accel
 * Also disables Hwi's, Swi's, and tasks until critical section is completed
 */
Void TSK_read_accelerometer()
{
    while(1) {
        // wait for resource to be available
        Semaphore_pend(SEMHDL_update_accel, BIOS_WAIT_FOREVER);

        // disable all other interrupt sources; Hwi_disable() also disables tasks and Swis
       // UInt key = Hwi_disable();

        // update accel prev
        accel_prev = accel_current;

        // update accel_current
        accel_current.z = ADC_read_z_axis();
        accel_current.y =  ADC_read_y_axis();
        accel_current.x = ADC_read_x_axis();

        // update accel max values
        if (accel_current.z > accel_max.z)
            accel_max.z = accel_current.z;

        if (accel_current.y > accel_max.y)
            accel_max.y = accel_current.y;

        if (accel_current.x > accel_max.x)
            accel_max.x = accel_current.x;

        // Check for fall detection
        if ( (accel_current.z > accel_prev.z - 3000) ||
             (accel_current.z < accel_prev.x + 3000) ||
             (accel_current.z > 15000))               {
            Clock_start(CLK_HDL_enable_buzzer);
        }

        System_printf("X: %d\t", accel_current.x);
        System_printf("Y: %d\t", accel_current.y);
        System_printf("Z: %d\n", accel_current.z);
        System_flush();
    }
    // re-enable Hwi's, Swi's, and tasks
  //  Hwi_restore(key);
}

/*
 * Blocking function to read z axis of accelerometer
 */
uint16_t ADC_read_z_axis()
{
    ADC_Handle   adc;
    ADC_Params   params;
    uint16_t adc_val;
    int_fast16_t res;

    ADC_Params_init(&params);
   adc = ADC_open(Board_ADC11, &params);
/*
   if (adc == NULL) {
       System_abort("Error initializing ADC channel z\n");
   }
   else {
       System_printf("ADC channel z initialized\n");
   }
*/
   res = ADC_convert(adc, &adc_val);
   if (res == ADC_STATUS_ERROR) {
       adc_val = 0;
   }

   ADC_close(adc);
   return adc_val;
}

/*
 * Blocking function to read y axis of accelerometer
 */
uint16_t ADC_read_y_axis()
{
    ADC_Handle   adc;
    ADC_Params   params;
    uint16_t adc_val;
    int_fast16_t res;

   ADC_Params_init(&params);
   adc = ADC_open(Board_ADC13, &params);
/*
   if (adc == NULL) {
       System_abort("Error initializing ADC channel y\n");
   }
   else {
       System_printf("ADC channel y initialized\n");
   }
*/
   res = ADC_convert(adc, &adc_val);
   if (res == ADC_STATUS_ERROR) {
       adc_val = 0;
   }

   ADC_close(adc);
   return adc_val;
}

/*
 * Blocking function to read x axis of accelerometer
 */
uint16_t ADC_read_x_axis()
{
    ADC_Handle   adc;
    ADC_Params   params;
    uint16_t adc_val;
    int_fast16_t res;

   ADC_Params_init(&params);
   adc = ADC_open(Board_ADC14, &params);

   /*if (adc == NULL) {
       System_abort("Error initializing ADC channel x\n");
   }
   else {
       System_printf("ADC channel x initialized\n");
   }*/

   res = ADC_convert(adc, &adc_val);
   if (res == ADC_STATUS_ERROR) {
       adc_val = 0;
   }

   ADC_close(adc);
   return adc_val;
}
/*************************************************************/
/*              Button Callbacks                             */
/*************************************************************/

