diff --git a/src/EcalBarrel_geo.cpp b/src/EcalBarrel_geo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4f3862df8775f9daf15ce49a8e7e245a9b524c8f
--- /dev/null
+++ b/src/EcalBarrel_geo.cpp
@@ -0,0 +1,164 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+//
+// Specialized generic detector constructor
+// 
+//==========================================================================
+#include "DD4hep/DetFactoryHelper.h"
+#include "XML/Layering.h"
+
+using namespace std;
+using namespace dd4hep;
+using namespace dd4hep::detail;
+
+static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens)  {
+  static double tolerance = 0e0;
+  Layering      layering (e);
+  xml_det_t     x_det     = e;
+  Material      air       = description.air();
+  int           det_id    = x_det.id();
+  string        det_name  = x_det.nameStr();
+  xml_comp_t    x_staves  = x_det.staves();
+  xml_comp_t    x_dim     = x_det.dimensions();
+  int           nsides    = x_dim.numsides();
+  double        inner_r   = x_dim.rmin();
+  double        dphi      = (2*M_PI/nsides);
+  double        hphi      = dphi/2;
+  double        mod_z     = layering.totalThickness();
+  double        outer_r   = inner_r + mod_z;
+  double        totThick  = mod_z;
+  double        offset    = x_det.attr<double>(_Unicode(offset));
+  DetElement    sdet      (det_name,det_id);
+  Volume        motherVol = description.pickMotherVolume(sdet);
+  PolyhedraRegular hedra  (nsides,inner_r,inner_r+totThick+tolerance*2e0,x_dim.z());
+  Volume        envelope  (det_name,hedra,air);
+  PlacedVolume  env_phv   = motherVol.placeVolume(envelope,Transform3D(Translation3D(0,0,offset)*RotationZ(M_PI/nsides)));
+
+  env_phv.addPhysVolID("system",det_id);
+  env_phv.addPhysVolID("barrel",0);
+  sdet.setPlacement(env_phv);
+
+  DetElement    stave_det("stave0",det_id);
+  double dx = 0.0; //mod_z / std::sin(dphi); // dx per layer
+    
+  // Compute the top and bottom face measurements.
+  double trd_x2 = (2 * std::tan(hphi) * outer_r - dx)/2 - tolerance;
+  double trd_x1 = (2 * std::tan(hphi) * inner_r + dx)/2 - tolerance;
+  double trd_y1 = x_dim.z()/2 - tolerance;
+  double trd_y2 = trd_y1;
+  double trd_z  = mod_z/2 - tolerance;
+		
+  // Create the trapezoid for the stave.
+  Trapezoid trd(trd_x1, // Outer side, i.e. the "short" X side.
+                trd_x2, // Inner side, i.e. the "long"  X side.
+                trd_y1, // Corresponds to subdetector (or module) Z.
+                trd_y2, //
+                trd_z); // Thickness, in Y for top stave, when rotated.
+
+  Volume mod_vol("stave",trd,air);
+
+  sens.setType("calorimeter");
+  { // =====  buildBarrelStave(description, sens, module_volume) =====
+    // Parameters for computing the layer X dimension:
+    double stave_z  = trd_y1;
+    double tan_hphi = std::tan(hphi);
+    double l_dim_x  = trd_x1; // Starting X dimension for the layer.
+    double l_pos_z  = -(layering.totalThickness() / 2);
+
+    // Loop over the sets of layer elements in the detector.
+    int l_num = 1;
+    for(xml_coll_t li(x_det,_U(layer)); li; ++li)  {
+      xml_comp_t x_layer = li;
+      int repeat = x_layer.repeat();
+      // Loop over number of repeats for this layer.
+      for (int j=0; j<repeat; j++)    {
+        string l_name = _toString(l_num,"layer%d");
+        double l_thickness = layering.layer(l_num-1)->thickness();  // Layer's thickness.
+
+        Position   l_pos(0,0,l_pos_z+l_thickness/2);      // Position of the layer.
+        Box        l_box(l_dim_x-tolerance,stave_z-tolerance,l_thickness / 2-tolerance);
+        Volume     l_vol(l_name,l_box,air);
+        DetElement layer(stave_det, l_name, det_id);
+
+        // Loop over the sublayers or slices for this layer.
+        int s_num = 1;
+        double s_pos_z = -(l_thickness / 2);
+        for(xml_coll_t si(x_layer,_U(slice)); si; ++si)  {
+          xml_comp_t x_slice = si;
+          string     s_name  = _toString(s_num,"slice%d");
+          double     s_thick = x_slice.thickness();
+          Box        s_box(l_dim_x-tolerance,stave_z-tolerance,s_thick / 2-tolerance);
+          Volume     s_vol(s_name,s_box,description.material(x_slice.materialStr()));
+          DetElement slice(layer,s_name,det_id);
+
+          if ( x_slice.isSensitive() ) {
+            s_vol.setSensitiveDetector(sens);
+          }
+          slice.setAttributes(description,s_vol,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
+
+          // Slice placement.
+          PlacedVolume slice_phv = l_vol.placeVolume(s_vol,Position(0,0,s_pos_z+s_thick/2));
+          slice_phv.addPhysVolID("slice", s_num);
+          slice.setPlacement(slice_phv);
+          // Increment Z position of slice.
+          s_pos_z += s_thick;
+                                        
+          // Increment slice number.
+          ++s_num;
+        }        
+
+        // Set region, limitset, and vis of layer.
+        layer.setAttributes(description,l_vol,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr());
+
+        PlacedVolume layer_phv = mod_vol.placeVolume(l_vol,l_pos);
+        layer_phv.addPhysVolID("layer", l_num);
+        layer.setPlacement(layer_phv);
+        // Increment to next layer Z position.
+        double xcut = l_thickness * tan_hphi;
+        l_dim_x += xcut;
+        l_pos_z += l_thickness;          
+        ++l_num;
+      }
+    }
+  }
+
+  // Set stave visualization.
+  if ( x_staves )   {
+    mod_vol.setVisAttributes(description.visAttributes(x_staves.visStr()));
+  }
+  // Phi start for a stave.
+  double phi = M_PI / nsides;
+  double mod_x_off = dx / 2;             // Stave X offset, derived from the dx.
+  double mod_y_off = inner_r + mod_z/2;  // Stave Y offset
+
+  // Create nsides staves.
+  for (int i = 0; i < nsides; i++, phi -= dphi)      { // i is module number
+    // Compute the stave position
+    double m_pos_x = mod_x_off * std::cos(phi) - mod_y_off * std::sin(phi);
+    double m_pos_y = mod_x_off * std::sin(phi) + mod_y_off * std::cos(phi);
+    Transform3D tr(RotationZYX(0,phi,M_PI*0.5),Translation3D(-m_pos_x,-m_pos_y,0));
+    PlacedVolume pv = envelope.placeVolume(mod_vol,tr);
+    pv.addPhysVolID("system",det_id);
+    pv.addPhysVolID("barrel",0);
+    pv.addPhysVolID("module",i+1);
+    DetElement sd = i==0 ? stave_det : stave_det.clone(_toString(i,"stave%d"));
+    sd.setPlacement(pv);
+    sdet.add(sd);
+  }
+
+  // Set envelope volume attributes.
+  envelope.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
+  return sdet;
+}
+
+DECLARE_DETELEMENT(refdet_EcalBarrel,create_detector)