diff --git a/src/Makefile b/src/Makefile
index acc05d030e5834bc28c54f4a167452f186418ef3..5b21051a23559c531f2e5d1e1a2b2f22068f8b0c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -12,7 +12,7 @@
 TARGET = scdaq
 
 # source files
-SOURCES = config.cc dma_input.cc elastico.cc  file_input.cc  input.cc  output.cc  processor.cc  scdaq.cc  session.cc  slice.cc wzdma_input.cc
+SOURCES = config.cc dma_input.cc elastico.cc file_dma_input.cc file_input.cc  input.cc  output.cc  processor.cc  scdaq.cc  session.cc  slice.cc wzdma_input.cc
 C_SOURCES = wz_dma.c
 
 # work out names of object files from sources
@@ -61,6 +61,7 @@ scdaq.o:	file_input.h processor.h elastico.h output.h format.h server.h controls
 config.o:	config.h
 dma_input.o:	dma_input.h slice.h
 elastico.o:	elastico.h format.h slice.h controls.h
+file_dma_input.o:	file_dma_input.h
 file_input.o:	file_input.h slice.h utility.h
 input.o:	input.h slice.h
 output.o:	output.h slice.h
diff --git a/src/config.h b/src/config.h
index 66c50048ba0812d89623bffe88e42f3ee45ac935..ad4f53d35c9ff0c070c06c2335001e7e609acccf 100644
--- a/src/config.h
+++ b/src/config.h
@@ -10,7 +10,7 @@
 class config{
 public:
   
-  enum class InputType { WZDMA, DMA, FILE };
+  enum class InputType { WZDMA, DMA, FILEDMA, FILE };
 
   config(std::string filename);
 
@@ -24,6 +24,9 @@ public:
     if (input == "dma") {
       return InputType::DMA;
     }
+    if (input == "filedma") {
+      return InputType::FILEDMA;
+    }    
     if (input == "file") {
       return InputType::FILE;
     }
diff --git a/src/file_dma_input.cc b/src/file_dma_input.cc
new file mode 100644
index 0000000000000000000000000000000000000000..107246eabccf3d810e8923c7fcf3a0b88ab7c7a0
--- /dev/null
+++ b/src/file_dma_input.cc
@@ -0,0 +1,164 @@
+#include <cassert>
+#include <cstdio>
+#include <cerrno>
+#include <system_error>
+#include <iostream>
+#include <sstream>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "file_dma_input.h"
+#include "slice.h"
+
+
+FileDmaInputFilter::FileDmaInputFilter( const std::string& file_name_, size_t packet_buffer_size_, 
+			  size_t number_of_packet_buffers_) : 
+
+  filter(serial_in_order),
+  next_slice(Slice::preAllocate( packet_buffer_size_, number_of_packet_buffers_) ),
+  counts(0),
+  ncalls(0),
+  lastStartTime(tbb::tick_count::now()),
+  last_count(0)
+{ 
+  input_file = fopen( file_name_.c_str(), "r" );
+  if ( !input_file ) {
+    throw std::invalid_argument( "Invalid input file name: " + file_name_ );
+  }
+  fprintf(stderr,"Created input dma filter and allocated at 0x%llx \n",(unsigned long long)next_slice);
+}
+
+FileDmaInputFilter::~FileDmaInputFilter() {
+  fprintf(stderr,"Destroy input dma filter and delete at 0x%llx \n",(unsigned long long)next_slice);
+  Slice::giveAllocated(next_slice);
+  fprintf(stderr,"input operator total %lu  read \n",counts);
+  //  fclose( output_file );
+  fclose( input_file );
+}
+
+/*
+ * This function reads packet by packet from a file
+ * in order to simulate DMA reads.
+ * 
+ * TODO: Better would be mmap directly the file
+ */ 
+static inline ssize_t read_dma_packet_from_file(FILE *input_file, char *buffer, uint64_t size, uint64_t pkt_count)
+{
+  static constexpr uint64_t deadbeaf = 0xdeadbeefdeadbeefL;
+  size_t bytes_read = 0;
+  size_t rc;
+
+  while ( !feof(input_file) && bytes_read < size) {
+    // Expecting 32 byte alignment 
+    rc = fread( buffer, 1, 32, input_file );
+
+    if (ferror(input_file)) {
+        throw std::system_error(errno, std::system_category(), "File error");
+    }
+
+    if (rc != 32) {
+      if ( feof(input_file) && rc == 0 && bytes_read == 0) {
+        // We have reached the perfect end of the file, let's start again
+        fseek(input_file, 0, SEEK_SET);
+        continue;
+      }
+
+      // Misaligned data
+      throw std::runtime_error("#" + std::to_string(pkt_count) + ": File read ends prematurely, missing " + std::to_string(32-rc) + " bytes. Something is probably misaligned.");
+    }
+
+    bytes_read += 32;
+
+    if ( *(uint64_t*)(buffer) == deadbeaf ) {
+      // End of the packet was found
+      return bytes_read;
+    }
+
+    buffer += 32;
+  }
+
+  // We are here either
+  //   because we found EOF earlier than the end of the packet 
+  //   or the packet cannot fit into the buffer
+  // We can deal with both conditions but for the moment we throw an error 
+
+  if (feof(input_file)) {
+    throw std::runtime_error("EOF reached but no end of the packet found.");
+  }
+
+  throw std::runtime_error("Packet is too big and cannot fit into preallocated memory");
+  // TODO: Read and discard data until deadbeef is found
+
+  return -1;
+}
+
+
+void* FileDmaInputFilter::operator()(void*) {
+  size_t buffer_size = next_slice->avail();
+  ssize_t bytes_read = 0;
+
+  // We need at least 1MB buffer
+  assert( buffer_size >= 1024*1024 );
+
+  while (true) {
+    // Count reads
+     ncalls++;
+
+    // Read from DMA
+    bytes_read = read_dma_packet_from_file(input_file, next_slice->begin(), buffer_size, ncalls);
+
+    if (bytes_read < 0) {
+      // Check for errors we can skip
+      if (errno == EIO || errno == EMSGSIZE) {
+        std::cerr << "Iteration: " << ncalls; 
+        if (errno == EIO) {
+          std::cerr << " DMA ERROR: I/O ERROR, skipping packet...\n"; 
+        } else {
+          std::cerr << " DMA ERROR: Packet too long, skipping packet...\n"; 
+        }
+        continue;
+      }
+
+      // Some fatal error occured
+      std::ostringstream os;
+      os  << "Iteration: " << ncalls 
+          << "  ERROR: DMA read failed.";
+      throw std::system_error(errno, std::system_category(), os.str() );
+    }
+
+    // We have some data
+    break;
+  }
+
+  // This should not happen
+  if (bytes_read > (ssize_t)buffer_size ){
+    std::ostringstream os;
+    os  << "Iteration: " << ncalls 
+        << "  ERROR: DMA read returned " << bytes_read 
+        << " > buffer size " << buffer_size;
+    throw std::runtime_error( os.str() );
+  }
+
+  // This should really not happen
+  assert( bytes_read != 0);
+
+  // Calculate DMA bandwidth
+  tbb::tick_count now = tbb::tick_count::now();
+  double time_diff =  (double)((now - lastStartTime).seconds());
+  lastStartTime = now;
+  double bwd = bytes_read / ( time_diff * 1024.0 * 1024.0 );
+
+  std::cout << "#" << ncalls << ": Read returned: " << bytes_read << ", DMA bandwidth " << bwd << "MBytes/sec\n";
+
+  // Have more data to process.
+  Slice* this_slice = next_slice;
+  next_slice = Slice::getAllocated();
+  
+  // Adjust the end of this buffer
+  this_slice->set_end( this_slice->end() + bytes_read );
+  
+  return this_slice;
+
+}
diff --git a/src/file_dma_input.h b/src/file_dma_input.h
new file mode 100644
index 0000000000000000000000000000000000000000..1094796baab5f90bd75314dc78ff338ee3317181
--- /dev/null
+++ b/src/file_dma_input.h
@@ -0,0 +1,27 @@
+#ifndef FILE_DMA_INPUT_H
+#define FILE_DMA_INPUT_H
+
+#include <memory>
+#include <string>
+#include "tbb/pipeline.h"
+#include "tbb/tick_count.h"
+
+class Slice;
+
+class FileDmaInputFilter: public tbb::filter {
+ public:
+  FileDmaInputFilter( const std::string&, size_t, size_t);
+  ~FileDmaInputFilter();
+ private:
+  FILE* input_file;
+  Slice* next_slice;
+  void* operator()(void*) /*override*/;
+  uint64_t counts;
+  uint64_t ncalls;
+  tbb::tick_count lastStartTime;
+  uint64_t last_count;
+};
+
+typedef std::shared_ptr<FileDmaInputFilter> FileDmaInputFilterPtr;
+
+#endif
diff --git a/src/scdaq.cc b/src/scdaq.cc
index 197bc077d2d6dbe258a47494d2f722cae6d45db1..693e1681c07b6b3c9ec71999d66ce62b3e1b29b9 100644
--- a/src/scdaq.cc
+++ b/src/scdaq.cc
@@ -17,6 +17,7 @@
 
 #include "wzdma_input.h"
 #include "dma_input.h"
+#include "file_dma_input.h"
 #include "file_input.h"
 #include "processor.h"
 #include "elastico.h"
@@ -65,6 +66,14 @@ int run_pipeline( int nthreads, ctrl *control, config *conf)
       // Create DMA reader
       input_filter = std::make_shared<DmaInputFilter>( conf->getDmaDevice(), MAX_BYTES_PER_INPUT_SLICE, TOTAL_SLICES );
 
+  } else if (input == config::InputType::FILEDMA) {
+      // Prepare reading from FILE and simulating DMA
+      MAX_BYTES_PER_INPUT_SLICE = conf->getDmaPacketBufferSize();
+      TOTAL_SLICES = conf->getNumberOfDmaPacketBuffers();
+
+      // Create DMA reader
+      input_filter = std::make_shared<FileDmaInputFilter>( conf->getInputFile(), MAX_BYTES_PER_INPUT_SLICE, TOTAL_SLICES );
+
   } else if (input == config::InputType::WZDMA ) {
       // Prepare reading from WZ DMA
       MAX_BYTES_PER_INPUT_SLICE = conf->getDmaPacketBufferSize();
diff --git a/src/scdaq.conf b/src/scdaq.conf
index b77f59965c982d9f7d18db40a42b986735c2ea83..805e7eb7d86a326a9d5ebda706ae6343cbb9652a 100644
--- a/src/scdaq.conf
+++ b/src/scdaq.conf
@@ -1,8 +1,10 @@
 # Input settings, allowed values are:
-#   "wzdma" for DMA driver from Wojciech M. Zabolotny
-#   "dma"   for XILINX DMA driver
-#   "file"  for reading from file
-input:wzdma
+#   "wzdma"     for DMA driver from Wojciech M. Zabolotny
+#   "dma"       for XILINX DMA driver
+#   "filedma"   for reading from file and simulating DMA
+#   "file"      for reading from file
+#input:wzdma
+input:filedma
 
 
 ## Settings for DMA input
@@ -18,7 +20,8 @@ dma_number_of_packet_buffers:100
 
 
 ## Settings for file input
-input_file:/dev/shm/testdata.bin
+#input_file:/dev/shm/testdata.bin
+input_file:testdata.bin
 input_buffers:10
 blocks_buffer:1000