#include "signal_processing.h"

#include "task.h"
#include "task_sine.h"
#include "task_cosinus.h"
#include "task_rand.h"
#include "task_add.h"
#include "task_sub.h"
#include "task_fft.h"
#include "task_crc.h"
#include "binding.h"
#include "data_channel.h"

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

const uint32_t TASK_CONNECTIONS[ TASK_COUNT ] = { 3, 3, 4, 4, 5, 6, 7 };

void * TASK_LIST [ TASK_COUNT ] = {
    & SINE_CONFIG,
    & COSINE_CONFIG,
    & RAND_CONFIG,
    & ADD_SINE_COSINE_CONFIG,
    & ADD_RAND_CONFIG,
    & FFT_CONFIG,
    & CRC_CONFIG
};

void signal_processing_init( SignalProcessing * system, const uint32_t * bindings ) {
    system->bindings = bindings;

    for ( uint32_t i = 0; i < TASK_COUNT; ++i ) {
        task_bind( TASK_LIST[ i ], system->bindings[ i ] );
    }

    for ( uint32_t i = 0; i < CHANNEL_COUNT; ++i ) {
        DataChannelBinding channel_binding;
        binding_get_channel_binding( TASK_CONNECTIONS, system->bindings, i,
            & channel_binding );

        data_channel_bind( DATA_CHANNEL_BASE_LIST[ i ], & channel_binding );
    }
}

void signal_processing_run( SignalProcessing * system ) {
    for ( uint32_t i = 0; i < TASK_COUNT; ++i ) {
        int ret = task_run( TASK_LIST[ i ] );
        if ( ret ) {
            printf( "ERROR while executing task %" PRIu32 "\n", i );
        }
    }
}

void signal_processing_print_results( SignalProcessing * system ) {
    printf( "                |  Software  |  Hardware\n" );
    printf( "----------------+------------+------------\n" );
    for ( uint32_t i = 0; i < TASK_COUNT; ++i ) {
        task_base_config * task = TASK_LIST[ i ];
        printf( "%15s |", task->name );
        if ( system->bindings[ i ] == BINDING_SW ) {
            printf( " %10" PRIu32 " |\n", task_get_cycle_count( TASK_LIST[ i ] ) );
        }
        else {
            printf( "            | %10" PRIu32 "\n", task_get_cycle_count( TASK_LIST[ i ] ) );
        }
    }
    printf( "\n" );
}

