Initial commit

This commit is contained in:
Johannes Kutning
2023-10-31 07:47:27 +01:00
commit 0d1b73e3e0
255 changed files with 16057 additions and 0 deletions
@@ -0,0 +1,83 @@
#include "Complex.h"
#include <math.h>
float complex_abs( const Complex * c ) {
return sqrt( pow( c->re, 2 ) + pow( c->im, 2 ) );
}
float complex_arg( const Complex * a )
{
return atan2( a->im, a->re );
}
Complex complex_comjunction( const Complex * a ) {
Complex c = { a->re, - a->im };
return c;
}
float complex_phi( const Complex * c ) {
float phi = 0.0;
// quadrant I
if ( c->re >= 0 && c->im >= 0 ) phi = atan( c->im / c->re );
// quadrant II, III
if ( c->re < 0 ) phi = atan( c->im / c->re ) + M_PI;
// quadrant IV
if ( c->re > 0 && c->im < 0 ) phi = atan( c->im / c->re ) + 2 * M_PI;
return phi * 180.0 / M_PI;
}
Complex complex_scalar_mul( const Complex * a, const float b ) {
Complex c = { 0.0, 0.0 };
float o_re = b;
float o_im = 0.0;
c.re = a->re * o_re - a->im * o_im;
c.im = a->re * o_im + o_re * a->im;
return c;
}
Complex complex_mul( const Complex * a, const Complex * b ) {
Complex c = { 0.0, 0.0 };
float o_re = b->re;
float o_im = b->im;
c.re = a->re * o_re - a->im * o_im;
c.im = a->re * o_im + o_re * a->im;
return c;
}
Complex complex_add( const Complex * a, const Complex * b ) {
Complex c = { 0.0, 0.0 };
c.re = a->re + b->re;
c.im = a->im + b->im;
return c;
}
Complex complex_sub( const Complex * a, const Complex * b ) {
Complex c = { 0.0, 0.0 };
c.re = a->re - b->re;
c.im = a->im - b->im;
return c;
}
Complex complex_polar( float roh, float theta )
{
Complex c = { roh * cos( theta ), roh * sin( theta ) };
return c;
}
Complex complex_pow( const Complex * a, int n )
{
float roh = pow( complex_abs( a ), n );
float theta = complex_arg( a );
return complex_polar( roh, ( float )( n ) * theta );
}
@@ -0,0 +1,27 @@
#pragma once
typedef struct {
float re;
float im;
} Complex;
float complex_abs( const Complex * c );
float complex_arg( const Complex * a );
Complex complex_comjunction( const Complex * a );
float complex_phi( const Complex * c );
Complex complex_scalar_mul( const Complex * a, const float b );
Complex complex_mul( const Complex * a, const Complex * b );
Complex complex_add( const Complex * a, const Complex * b );
Complex complex_sub( const Complex * a, const Complex * b );
Complex complex_polar( float roh, float theta );
Complex complex_pow( const Complex * a, int n );
@@ -0,0 +1,6 @@
#pragma once
#include "task_base_config.h"
typedef task_base_config add_config;
@@ -0,0 +1,42 @@
#include "binding.h"
#include "signal_processing.h"
#include <stdio.h>
static const char * BINDING_HW_STRING = "HW";
static const char * BINDING_SW_STRING = "SW";
static const char * UNKOWN_STRING = "UNKOWN_STRING";
void binding_from_value( uint32_t value, uint32_t * binding ) {
for ( uint32_t i = 0; i < TASK_COUNT; ++i ) {
binding[ i ] = value & 1;
value >>= 1;
}
}
int binding_get_channel_binding( const uint32_t * connections,
const uint32_t * binding,
uint32_t n,
DataChannelBinding * channel_binding ) {
if ( n >= CHANNEL_COUNT ) {
printf( "ERROR in %s: %" PRIu32 " not a valid channel number\n",
__func__, n );
return 1;
}
channel_binding->sink = binding[ n ];
channel_binding->source = binding[ connections[ n ] ];
return 0;
}
const char * binding_to_string( uint32_t binding ) {
switch ( binding ) {
case BINDING_SW: return BINDING_SW_STRING;
case BINDING_HW: return BINDING_HW_STRING;
}
return UNKOWN_STRING;
}
@@ -0,0 +1,32 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
enum {
BINDING_SW = 0,
BINDING_HW = 1
};
typedef struct {
uint32_t sink;
uint32_t source;
} DataChannelBinding;
void binding_from_value( uint32_t value, uint32_t * config );
int binding_get_channel_binding( const uint32_t * connections,
const uint32_t * binding,
uint32_t n,
DataChannelBinding * channel_binding );
const char * binding_to_string( uint32_t binding );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,8 @@
#pragma once
#include "task_base_config.h"
typedef struct {
task_base_config base;
uint32_t start;
} crc_config;
@@ -0,0 +1,99 @@
#include "data_channel.h"
#include <system.h>
#include <stdio.h>
#include <io.h>
const uint32_t DATA_CHANNEL_DEPTH = 1024;
const uint32_t DATA_CHANNEL_COUNT = 7;
const uint32_t DATA_CHANNEL_BASE_LIST[] = {
DATA_CHANNEL_0_BASE,
DATA_CHANNEL_1_BASE,
DATA_CHANNEL_2_BASE,
DATA_CHANNEL_3_BASE,
DATA_CHANNEL_4_BASE,
DATA_CHANNEL_5_BASE,
DATA_CHANNEL_6_BASE
};
#define REG_BINDING_OFFSET 0
#define BINDING_SINK_POS 0
#define BINDING_SOURCE_POS 1
#define REG_EMPTY_OFFSET 1
#define REG_FULL_OFFSET 2
#define REG_LEVEL_OFFSET 3
#define REG_SINK_OFFSET 4
#define REG_SOURCE_OFFSET 5
#define REG_CLEAR_OFFSET 6
void data_channel_bind( uint32_t base, const DataChannelBinding * binding ) {
uint32_t value = binding->sink << BINDING_SINK_POS |
binding->source << BINDING_SOURCE_POS;
IOWR( base, REG_BINDING_OFFSET, value );
}
uint32_t data_channel_get_binding( uint32_t base ) {
return IORD( base, REG_BINDING_OFFSET );
}
uint32_t data_channel_is_empty( uint32_t base ) {
return IORD( base, REG_EMPTY_OFFSET );
}
uint32_t data_channel_is_full( uint32_t base ) {
return IORD( base, REG_FULL_OFFSET );
}
uint32_t data_channel_level( uint32_t base ) {
return IORD( base, REG_LEVEL_OFFSET );
}
void data_channel_clear( uint32_t base ) {
IOWR( base, REG_CLEAR_OFFSET, 1 );
}
int data_channel_write( uint32_t base, uint32_t value ) {
if ( data_channel_is_full( base ) ) {
return 1;
}
IOWR( base, REG_SINK_OFFSET, value );
return 0;
}
int data_channel_write_all( uint32_t base, const uint32_t * data, uint32_t len ) {
for ( uint32_t i = 0; i < len; ++i ) {
int ret = data_channel_write( base, data[ i ] );
if ( ret ) return ret;
}
return 0;
}
int data_channel_read( uint32_t base, uint32_t * value ) {
if ( data_channel_is_empty( base ) ) {
return 1;
}
* value = IORD( base, REG_SOURCE_OFFSET );
return 0;
}
int data_channel_read_all( uint32_t base, void * buffer ) {
int i;
for ( i = 0; i < DATA_CHANNEL_DEPTH; ++i ) {
int ret = data_channel_read( base, buffer + i );
if ( ret ) {
break;
}
}
return i;
}
uint32_t data_channel_base_from_number( uint32_t channel ) {
return DATA_CHANNEL_BASE_LIST[ channel ];
}
@@ -0,0 +1,35 @@
#pragma once
#include "binding.h"
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const uint32_t DATA_CHANNEL_DEPTH;
extern const uint32_t DATA_CHANNEL_COUNT;
extern const uint32_t DATA_CHANNEL_BASE_LIST[];
void data_channel_bind( uint32_t base, const DataChannelBinding * binding );
uint32_t data_channel_get_binding( uint32_t base );
uint32_t data_channel_is_empty( uint32_t base );
uint32_t data_channel_is_full( uint32_t base );
uint32_t data_channel_level( uint32_t base );
void data_channel_clear( uint32_t base );
int data_channel_write( uint32_t base, uint32_t value );
int data_channel_write_all( uint32_t base, const uint32_t * data, uint32_t len );
int data_channel_read( uint32_t base, uint32_t * value );
int data_channel_read_all( uint32_t base, void * buffer );
uint32_t data_channel_base_from_number( uint32_t channel );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,9 @@
#pragma once
#include "task_base_config.h"
typedef struct {
task_base_config base;
float interval;
} fft_config;
@@ -0,0 +1,9 @@
#pragma once
#include <inttypes.h>
typedef union {
float value;
uint32_t word;
} float_word;
@@ -0,0 +1,32 @@
#include "hardware_task.h"
#include <io.h>
#include <stdio.h>
#define REG_START_OFFSET 0
#define START 1
#define REG_STATE_OFFSET 1
#define REG_CYCLE_COUNT_OFFSET 2
#define REG_CONFIG_OFFSET 3
void hardware_task_start( uint32_t base ) {
IOWR( base, REG_START_OFFSET, START );
}
uint32_t hardware_task_get_state( uint32_t base ) {
return IORD( base, REG_STATE_OFFSET );
}
uint32_t hardware_task_get_cycle_count( uint32_t base ) {
return IORD( base, REG_CYCLE_COUNT_OFFSET );
}
void hardware_task_set_config( uint32_t base, uint32_t offset, uint32_t value ) {
IOWR( base, REG_CONFIG_OFFSET + offset, value );
}
uint32_t hardware_task_get_config( uint32_t base, uint32_t offset ) {
return IORD( base, REG_CONFIG_OFFSET + offset );
}
@@ -0,0 +1,27 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
enum {
HARDWARE_TASK_IDLE = 0,
HARDWARE_TASK_RUNNING = 1,
HARDWARE_TASK_DONE = 2
};
void hardware_task_start( uint32_t base );
uint32_t hardware_task_get_state( uint32_t base );
uint32_t hardware_task_get_cycle_count( uint32_t base );
void hardware_task_set_config( uint32_t base, uint32_t offset, uint32_t value );
uint32_t hardware_task_get_config( uint32_t base, uint32_t offset );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,30 @@
#include "hardware_timestamp.h"
#include <io.h>
#define REG_STATE_OFFSET 0
#define STOPPED 0
#define RUNNING 1
#define REG_CYCLE_COUNT_OFFSET 1
uint32_t hardware_timestamp_is_running( uint32_t base ) {
return IORD( base, REG_STATE_OFFSET ) == RUNNING;
}
uint32_t hardware_timestamp_is_stopped( uint32_t base ) {
return IORD( base, REG_STATE_OFFSET ) == STOPPED;
}
uint32_t hardware_timestamp( uint32_t base ) {
return IORD( base, REG_CYCLE_COUNT_OFFSET );
}
void hardware_timestamp_start( uint32_t base ) {
IOWR( base, REG_STATE_OFFSET, RUNNING );
}
void hardware_timestamp_stop( uint32_t base ) {
IOWR( base, REG_STATE_OFFSET, STOPPED );
}
@@ -0,0 +1,10 @@
#pragma once
#include <inttypes.h>
uint32_t hardware_timestamp_is_running( uint32_t base );
uint32_t hardware_timestamp_is_stopped( uint32_t base );
uint32_t hardware_timestamp( uint32_t base );
void hardware_timestamp_start( uint32_t base );
void hardware_timestamp_stop( uint32_t base );
@@ -0,0 +1,13 @@
#pragma once
#include "task_base_config.h"
#include <inttypes.h>
typedef struct {
task_base_config base;
float seed;
float abs_min;
float abs_max;
} rand_config;
@@ -0,0 +1,69 @@
#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" );
}
@@ -0,0 +1,27 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
#define TASK_COUNT 7
#define CHANNEL_COUNT 7
extern const uint32_t TASK_CONNECTIONS[ TASK_COUNT ];
typedef struct {
const uint32_t * bindings;
uint32_t tasks[ TASK_COUNT ];
uint32_t channels[ CHANNEL_COUNT ];
} SignalProcessing;
void signal_processing_init( SignalProcessing * system, const uint32_t * bindings );
void signal_processing_run( SignalProcessing * system );
void signal_processing_print_results( SignalProcessing * system );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,11 @@
#pragma once
#include "task_base_config.h"
typedef struct {
task_base_config base;
uint32_t samples_per_periode;
float phase;
float amplitude;
} sine_config;
+68
View File
@@ -0,0 +1,68 @@
#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;
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
int task_bind( void * task, uint32_t binding );
int task_run( void * task );
uint32_t task_get_cycle_count( const void * task );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,26 @@
#include "task_add.h"
#include "data_channel.h"
#include <stdio.h>
#include <system.h>
add_config ADD_SINE_COSINE_CONFIG = {
.name = "add_sine_cosine",
.binding = BINDING_SW,
.software = task_add_run,
.configure = NULL,
.hardware = HARDWARE_TASK_3_BASE,
.sources = { DATA_CHANNEL_0_BASE, DATA_CHANNEL_1_BASE },
.sink = DATA_CHANNEL_3_BASE,
.cycle_count = 0 };
add_config ADD_RAND_CONFIG = {
.name = "add_rand",
.binding = BINDING_SW,
.software = task_add_run,
.configure = NULL,
.hardware = HARDWARE_TASK_4_BASE,
.sources = { DATA_CHANNEL_2_BASE, DATA_CHANNEL_3_BASE },
.sink = DATA_CHANNEL_4_BASE,
.cycle_count = 0 };
@@ -0,0 +1,17 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "add_config.h"
extern add_config ADD_SINE_COSINE_CONFIG;
extern add_config ADD_RAND_CONFIG;
int task_add_run( void * data );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,15 @@
#pragma once
#include "task_function.h"
#include <inttypes.h>
typedef struct {
const char * name;
uint32_t binding;
task_function software;
task_function configure;
uint32_t hardware;
uint32_t sources[ 2 ];
uint32_t sink;
uint32_t cycle_count;
} task_base_config;
@@ -0,0 +1,16 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "sine_config.h"
extern sine_config COSINE_CONFIG;
int task_cosinus( void * data );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,20 @@
#include "task_crc.h"
#include "data_channel.h"
#include "crc_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <system.h>
crc_config CRC_CONFIG = {
.base = { .name = "crc",
.binding = BINDING_SW,
.software = task_crc_run,
.configure = NULL,
.hardware = HARDWARE_TASK_6_BASE,
.sources = { DATA_CHANNEL_5_BASE },
.sink = DATA_CHANNEL_6_BASE,
.cycle_count = 0 },
.start = 0x00000000 };
@@ -0,0 +1,19 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "task.h"
#include "crc_config.h"
extern crc_config CRC_CONFIG;
#define CRC32POLY 0xEDB88320 /* CRC-32 Polynom (Invers)*/
int task_crc_run( void * task );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,20 @@
#include "task_fft.h"
#include "data_channel.h"
#include "fft_config.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <system.h>
fft_config FFT_CONFIG = {
.base = { .name = "fft",
.binding = BINDING_SW,
.software = task_fft_run,
.configure = NULL,
.hardware = HARDWARE_TASK_5_BASE,
.sources = { DATA_CHANNEL_4_BASE },
.sink = DATA_CHANNEL_5_BASE,
.cycle_count = 0 },
.interval = 1e-6 };
@@ -0,0 +1,16 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "fft_config.h"
extern fft_config FFT_CONFIG;
int task_fft_run( void * data );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,3 @@
#pragma once
typedef int ( * task_function )( void * );
@@ -0,0 +1,35 @@
#include "task_rand.h"
#include "hardware_task.h"
#include "data_channel.h"
#include "float_word.h"
#include <stdio.h>
#include <system.h>
#define REG_SEED_OFFSET 0
#define REG_EXP_MIN_OFFSET 1
#define REG_EXP_MAX_OFFSET 2
rand_config RAND_CONFIG = {
.base = { .name = "rand",
.binding = BINDING_SW,
.software = task_rand_run,
.configure = task_rand_configure,
.hardware = HARDWARE_TASK_2_BASE,
.sources = { 0, 0 },
.sink = DATA_CHANNEL_2_BASE,
.cycle_count = 0 },
.seed = 1.3,
.abs_min = 0.125,
.abs_max = 9.0 };
int task_rand_configure( void * data ) {
rand_config * task = ( rand_config * ) data;
uint32_t base = task->base.hardware;
float_word value = { .value = task->seed };
hardware_task_set_config( base, REG_SEED_OFFSET, value.word );
return 0;
}
@@ -0,0 +1,18 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "rand_config.h"
extern rand_config RAND_CONFIG;
int task_rand_configure( void * task );
int task_rand_run( void * task );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,66 @@
#include "task_sine.h"
#include "hardware_task.h"
#include "sine_config.h"
#include "data_channel.h"
#include "float_word.h"
#include <math.h>
#include <stdio.h>
#include <limits.h>
#include <system.h>
#define REG_STEP_SIZE_OFFSET 0
#define REG_PHASE_OFFSET 1
#define REG_AMPLITUDE_OFFSET 2
sine_config SINE_CONFIG = {
.base = {
.name = "sine",
.binding = BINDING_SW,
.software = task_sine_run,
.configure = task_sine_configure,
.hardware = HARDWARE_TASK_0_BASE,
.sources = { 0, 0 },
.sink = DATA_CHANNEL_0_BASE,
.cycle_count = 0 },
.samples_per_periode = 32,
.phase = 0.0,
.amplitude = 4.0 };
sine_config COSINE_CONFIG = {
.base = { .name = "cosine",
.binding = BINDING_SW,
.software = task_sine_run,
.configure = task_sine_configure,
.hardware = HARDWARE_TASK_1_BASE,
.sources = { 0, 0 },
.sink = DATA_CHANNEL_1_BASE,
.cycle_count = 0 },
.samples_per_periode = 200,
.phase = M_PI / 2.0,
.amplitude = 2.0 };
uint32_t to_hardware_step_size( uint32_t steps ) {
return UINT_MAX / steps + 1;
}
uint32_t to_hardware_phase( float phase ) {
return ( phase / ( 2.0 * M_PI ) ) * UINT_MAX;
}
int task_sine_configure( void * data ) {
sine_config * task = ( sine_config * ) data;
uint32_t base = task->base.hardware;
float_word amplitude;
amplitude.value = task->amplitude;
hardware_task_set_config( base, REG_STEP_SIZE_OFFSET,
to_hardware_step_size( task->samples_per_periode ) );
hardware_task_set_config( base, REG_PHASE_OFFSET,
to_hardware_phase( task->phase ) );
hardware_task_set_config( base, REG_AMPLITUDE_OFFSET, amplitude.word );
return 0;
}
@@ -0,0 +1,18 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "sine_config.h"
extern sine_config SINE_CONFIG;
extern sine_config COSINE_CONFIG;
int task_sine_configure( void * task );
int task_sine_run( void * task );
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,14 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "task.h"
int task_sub( void * data );
#ifdef __cplusplus
}
#endif