#include "task.h"
#include "task_base_config.h"

#include "binding.h"
#include "hardware_task.h"
#include "hardware_timestamp.h"

#include <stdio.h>
#include <system.h>

int task_configure_and_run_hardware( void * task );
int task_run_software( void * task );

int task_bind( void * task, uint32_t binding ) {
    task_base_config * base = ( task_base_config * ) task;
    base->binding = binding;
    return 0;
}

int task_run( void * task ) {
    task_base_config * base = ( task_base_config * ) task;

    base->cycle_count = 0;

    int ret = 0;
    if ( base->binding == BINDING_HW ) {
        ret = task_configure_and_run_hardware( task );
    }
    else {
        ret = task_run_software( task );
    }

    return ret;
}

uint32_t task_get_cycle_count( const void * task ) {
    task_base_config * base = ( task_base_config * ) task;

    if ( base->binding == BINDING_HW ) {
        return hardware_task_get_cycle_count( base->hardware );
    }

    return base->cycle_count;
}

int task_configure_and_run_hardware( void * task ) {
    task_base_config * base = ( task_base_config * ) task;
    if ( base->configure != NULL ) {
        base->configure( task );
    }

    hardware_task_start( base->hardware );
    while ( hardware_task_get_state( base->hardware ) != HARDWARE_TASK_DONE );
    return 0;
}

int task_run_software( void * task ) {
    task_base_config * base = ( task_base_config * ) task;

    hardware_timestamp_start( HARDWARE_TIMESTAMP_BASE );

    int ret = base->software( task );

    base->cycle_count = hardware_timestamp( HARDWARE_TIMESTAMP_BASE );

    return ret;
}

