diff --git a/algos/cfs-template/algo_cfgtemplate1_harness_run.m b/algos/cfs-template/algo_cfgtemplate1_harness_run.m
new file mode 100644
index 0000000000000000000000000000000000000000..c24b0265dc6fa107b140a272c047911afb492573
--- /dev/null
+++ b/algos/cfs-template/algo_cfgtemplate1_harness_run.m
@@ -0,0 +1,69 @@
+function algo_template_harness_run(obj)
+% run harness and check the result
+
+% load tunable control parameters from mds
+shot = 100; % shot reference
+obj.actualize(shot);
+
+% Input Data - must be structure of timeseries matching input bus structure
+% time = 0:obj.gettiming.dt:1;
+% data = single(sin(2*pi*time*10)');
+% % NB: these struct name and types must match the corresponding data bus
+% tsStructData = struct('simple_signal',timeseries(data,time,'Name','Test Input Data'));
+
+% SimIn object to customize configuration of Simulation run for test
+SimIn = Simulink.SimulationInput([obj.getname '_harness']);
+
+% Create template Input dataset for this model
+% Dataset = createInputDataset(obj.getname);
+
+% assign input data signal to Simulink.Signal object
+% DataIn = Simulink.SimulationData.Signal;
+% DataIn.Values = tsStructData;
+
+% assign as first element in input data set
+% isig = find(contains(Dataset.getElementNames,'signal_in')); % find input signal index
+% Dataset = Dataset.setElement(isig,DataIn); %#ok<FNDSB>
+% SimIn.ExternalInput = Dataset; % assign this as external input for simulation
+
+% Custom parameters for this run to save outport data
+SimIn = SimIn.setModelParameter('SaveOutput','on'); % set to save outport signals
+SimIn = SimIn.setModelParameter('SignalLogging','on'); % set to save log signals
+SimIn = SimIn.setModelParameter('OutputSaveName','SimOut');
+SimIn = SimIn.setModelParameter('SaveFormat','Dataset');
+SimIn = SimIn.setModelParameter('StartTime',num2str(obj.gettiming().t_start));
+SimIn = SimIn.setModelParameter('StopTime',num2str(obj.gettiming().t_stop));
+SimIn = SimIn.setModelParameter('FixedStep',num2str(obj.gettiming().dt));
+
+% simulate - simulate only single types to save time
+result = sim(SimIn);
+
+% check output port data
+tp = Simulink.data.evalinGlobal(obj.getname,'algo_template_tp.Value');
+fp = Simulink.data.evalinGlobal(obj.getname,'algo_template_fp');
+
+input = evalin('base','algo_template_inbus1');
+input1  = input.signal1.Data;
+input2  = input.signal2.Data;
+
+output1 = result.simout.signal1.Data;
+output2 = result.simout.signal2.Data;
+
+size(input1)
+size(output1)
+
+maxerror1 = 0.1;
+maxerror2 = 0.1; 
+assert(max(abs(output1 - input1.*tp.gain))<maxerror1,'Wrong output 1!');
+assert(max(abs(output2 - (input2.*tp.refmodel.gain+fp.refmodel.offset)))<maxerror2,'Wrong output 2!');
+
+% check logs which contain a SCDsignal type data
+% logsout = result.logsout;
+% 
+% signal    = logsout.getElement('SCDsignal type bus').Values.Value;
+% Quality   = logsout.getElement('SCDsignal type bus').Values.QualityTag;
+% State     = logsout.getElement('SCDsignal type bus').Values.ProductionState;
+% 
+% assert(all(State  .Data == ProductionState.RUNNING),'ProductionState must be RUNNING');
+% assert(all(Quality.Data == QualityTag.GOOD        ),'QualityTag must be RUNNING'     );
+end
diff --git a/algos/cfs-template/algo_cfstemplate1.slx b/algos/cfs-template/algo_cfstemplate1.slx
new file mode 100644
index 0000000000000000000000000000000000000000..2759c85d3e689413b87a5c682b8a256cc4371ef1
Binary files /dev/null and b/algos/cfs-template/algo_cfstemplate1.slx differ
diff --git a/algos/cfs-template/algo_cfstemplate1_harness.slx b/algos/cfs-template/algo_cfstemplate1_harness.slx
new file mode 100644
index 0000000000000000000000000000000000000000..6beba1d4535228191471cd1460a5ca438f669736
Binary files /dev/null and b/algos/cfs-template/algo_cfstemplate1_harness.slx differ
diff --git a/algos/cfs-template/algo_cfstemplate1_inBus_def.m b/algos/cfs-template/algo_cfstemplate1_inBus_def.m
new file mode 100644
index 0000000000000000000000000000000000000000..9cf6ec1c29c05725798261f335cdc3aa5f60574f
--- /dev/null
+++ b/algos/cfs-template/algo_cfstemplate1_inBus_def.m
@@ -0,0 +1,33 @@
+% Bus object: SCDalgo_template_inBus 
+clear elems;
+elems(1) = Simulink.BusElement;
+elems(1).Name = 'signal1';
+elems(1).Dimensions = 1;
+elems(1).DimensionsMode = 'Fixed';
+elems(1).DataType = 'single';
+elems(1).SampleTime = -1;
+elems(1).Complexity = 'real';
+elems(1).Min = [];
+elems(1).Max = [];
+elems(1).DocUnits = '';
+elems(1).Description = '';
+
+elems(2) = Simulink.BusElement;
+elems(2).Name = 'signal2';
+elems(2).Dimensions = 1;
+elems(2).DimensionsMode = 'Fixed';
+elems(2).DataType = 'single';
+elems(2).SampleTime = -1;
+elems(2).Complexity = 'real';
+elems(2).Min = [];
+elems(2).Max = [];
+elems(2).DocUnits = '';
+elems(2).Description = '';
+
+algo_template_inBus = Simulink.Bus;
+algo_template_inBus.HeaderFile = '';
+algo_template_inBus.Description = '';
+algo_template_inBus.DataScope = 'Auto';
+algo_template_inBus.Alignment = -1;
+algo_template_inBus.Elements = elems;
+clear elems;
diff --git a/algos/cfs-template/algo_cfstemplate1_loadfp.m b/algos/cfs-template/algo_cfstemplate1_loadfp.m
new file mode 100644
index 0000000000000000000000000000000000000000..2fd64eb55fe35ec632a907cc6088d207c78baafb
--- /dev/null
+++ b/algos/cfs-template/algo_cfstemplate1_loadfp.m
@@ -0,0 +1,6 @@
+function fp = algo_template_loadfp(obj)
+
+%% Load other fixed parameters
+fp.timing = obj.gettiming;
+fp.refmodel.offset = 1; % a fixed parameter
+end
\ No newline at end of file
diff --git a/algos/cfs-template/algo_cfstemplate1_loadtp.m b/algos/cfs-template/algo_cfstemplate1_loadtp.m
new file mode 100644
index 0000000000000000000000000000000000000000..1c08d9286f2f173a425caf3672d100c7adcde017
--- /dev/null
+++ b/algos/cfs-template/algo_cfstemplate1_loadtp.m
@@ -0,0 +1,11 @@
+function TP = algo_template_loadtp()
+% Setup tunable control params
+
+TP.enable           = true;
+TP.gain             = single(2);
+TP.refmodel.gain    = single(4); % another gain used in referenced model
+TP.rowvect          = int32([1 2 3]);
+TP.colvect          = int16([1 2 3]');
+TP.matrix           = int8([1 2; 3 4]);
+
+end
diff --git a/algos/cfs-template/algo_cfstemplate1_outBus_def.m b/algos/cfs-template/algo_cfstemplate1_outBus_def.m
new file mode 100644
index 0000000000000000000000000000000000000000..3acb8cd5d98cbcc0aa9c2deebd1c1f91dc8df786
--- /dev/null
+++ b/algos/cfs-template/algo_cfstemplate1_outBus_def.m
@@ -0,0 +1,35 @@
+% Bus object: SCDalgo_template_outBus 
+clear elems;
+elems(1) = Simulink.BusElement;
+elems(1).Name = 'signal1';
+elems(1).Dimensions = 1;
+elems(1).DimensionsMode = 'Fixed';
+%elems(1).DataType = 'Bus:SCDBus_single_11_Vector';
+elems(1).DataType = 'single';
+elems(1).SampleTime = -1;
+elems(1).Complexity = 'real';
+elems(1).Min = [];
+elems(1).Max = [];
+elems(1).DocUnits = '';
+elems(1).Description = '';
+
+elems(2) = Simulink.BusElement;
+elems(2).Name = 'signal2';
+elems(2).Dimensions = 1;
+elems(2).DimensionsMode = 'Fixed';
+%elems(2).DataType = 'Bus:SCDBus_int32_Scalar';
+elems(2).DataType = 'single';
+elems(2).SampleTime = -1;
+elems(2).Complexity = 'real';
+elems(2).Min = [];
+elems(2).Max = [];
+elems(2).DocUnits = '';
+elems(2).Description = '';
+
+algo_template_outBus = Simulink.Bus;
+algo_template_outBus.HeaderFile = '';
+algo_template_outBus.Description = '';
+algo_template_outBus.DataScope = 'Auto';
+algo_template_outBus.Alignment = -1;
+algo_template_outBus.Elements = elems;
+clear elems;
diff --git a/algos/cfs-template/algo_cfstemplate1_signal_buses.m b/algos/cfs-template/algo_cfstemplate1_signal_buses.m
new file mode 100644
index 0000000000000000000000000000000000000000..82c52b2d9e153d06db5d81c609e7203fd7c81de3
--- /dev/null
+++ b/algos/cfs-template/algo_cfstemplate1_signal_buses.m
@@ -0,0 +1,47 @@
+function [busNames,Buses] = algo_template_signal_buses()
+% [busNames,Buses] = SCDalgo_template_signal_buses()
+% Define some buses needed for the template
+
+%% Define signal buses for various SCDsignal types
+% Data examples for which to create buses
+D = {...
+  ones(11,1,'single'),...
+  ones(3,3,'single'),...
+  int32(1)};
+
+% Create buses for these signals and add them to the list
+[Buses,busNames] = deal(cell(numel(D),1)); % init
+for ii = 1:numel(D)
+  mydata = D{ii};
+  mysig = SCDsignal(mydata); % create SCDsignal object for this data example
+  mybus = mysig.createBus; % create Bus for this signal using object method
+  % Store
+  Buses{ii} = mybus;
+  busNames{ii} = mybus.Description;
+end
+
+%% Add output structure: a bus that includes only SCDsignal data types
+
+% First add 3 busElements for the three signals defined above
+for ii=1:3
+elems(ii) = Simulink.BusElement;
+elems(ii).Name = sprintf('signal%d',ii);
+elems(ii).Dimensions = 1;
+elems(ii).DimensionsMode = 'Fixed';
+elems(ii).DataType = sprintf('Bus: %s',busNames{ii});
+end
+
+% Define output bus with these elements
+outBus = Simulink.Bus;
+outBus.HeaderFile = '';
+outBus.Description = '';
+outBus.DataScope = 'Auto';
+outBus.Alignment = -1;
+outBus.Elements = elems;
+clear elems;
+
+% append to list
+busNames{end+1} = 'algo_template_bus1';
+Buses{end+1}    = outBus; 
+
+end
diff --git a/algos/cfs-template/algo_cfstemplate1_test.m b/algos/cfs-template/algo_cfstemplate1_test.m
new file mode 100644
index 0000000000000000000000000000000000000000..d37df45c34dd9e4235cc6bddf911856aed141cea
--- /dev/null
+++ b/algos/cfs-template/algo_cfstemplate1_test.m
@@ -0,0 +1,7 @@
+classdef algo_template_test < SCDalgo_test
+  
+  properties
+    algoobj = algoobj_template();
+  end
+  
+end
\ No newline at end of file
diff --git a/algos/cfs-template/algoobj_cfstemplate1.m b/algos/cfs-template/algoobj_cfstemplate1.m
new file mode 100644
index 0000000000000000000000000000000000000000..80ce3b87bc1ef0030c59c55e37b42eeb978000ab
--- /dev/null
+++ b/algos/cfs-template/algoobj_cfstemplate1.m
@@ -0,0 +1,42 @@
+function obj = algoobj_cfstemplate1()
+
+%% Doublets SPC controller algorithm
+obj = SCDclass_algo('algo_cfstemplate1');
+
+%% Timing of the algorithm
+obj=obj.settiming(-1,1e-3,1.0);
+
+%% Fixed parameters init functions 
+obj=obj.addfpinitfcn('algo_cfstemplate1_loadfp','algo_cfstemplate1_fp');
+
+%% Tunable parameters structure name
+obj=obj.addtunparamstruct('algo_cfstemplate1_tp', @()algo_cfstemplate1_loadtp(), false);
+
+%% Tunable parameters
+parshot=10;
+obj=obj.addparameter(SCDclass_mdsparnumeric('kb1','enable'          ,'srcsrv','spcpc171.epfl.ch','srctree','martetest','shot',parshot)); 
+obj=obj.addparameter(SCDclass_mdsparnumeric('ks1','gain'            ,'srcsrv','spcpc171.epfl.ch','srctree','martetest','shot',parshot)); 
+obj=obj.addparameter(SCDclass_mdsparnumeric('kv1','rowvect'         ,'srcsrv','spcpc171.epfl.ch','srctree','martetest','shot',parshot));
+obj=obj.addparameter(SCDclass_mdsparnumeric('kv2','colvect'         ,'srcsrv','spcpc171.epfl.ch','srctree','martetest','shot',parshot));
+obj=obj.addparameter(SCDclass_mdsparnumeric('km1','matrix'          ,'srcsrv','spcpc171.epfl.ch','srctree','martetest','shot',parshot));
+
+%% Wavegens
+obj=obj.addwavegenbasetruct('algo_cfstemplate1_inbus');
+obj=obj.addwavegen(SCDclass_mdswgsigsingle( 'ai.ch001','signal1'        ,'srcsrv','spcpc171.epfl.ch','srctree','martetest','shot',parshot));
+obj=obj.addwavegen(SCDclass_mdswgsigsingle( 'ai.ch002','signal2'        ,'srcsrv','spcpc171.epfl.ch','srctree','martetest','shot',parshot));
+
+
+%% Buses
+obj = obj.addbus('algo_template_inBus', 'algo_template_inBus_def' );
+obj = obj.addbus('algo_template_outBus', 'algo_template_outBus_def' );
+ % function handle that returns cell arays of buses and busnames to be
+ % registered
+obj = obj.addbus('',@() algo_template_signal_buses());
+
+%% Tasks
+
+%% Print (optional)
+obj.printinfo;
+
+end
+