diff --git a/src/config_reader.cpp b/src/config_reader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5baadcebe6c9cfaaed8c3cdc4ed1de0bda644790
--- /dev/null
+++ b/src/config_reader.cpp
@@ -0,0 +1,217 @@
+// config.cpp
+//
+// original from https://cppsecrets.com/users/41129711010797106994610011511264103109971051084699111109/C00-Config-Reader.php
+//
+// Code Specific Header File(s)
+#include "config_reader.h"
+
+// C++ Header File(s)
+#include <fstream>
+#include <algorithm>
+
+using namespace std;
+
+#define NULL_PTR 0
+
+ConfigReader* ConfigReader::m_pInstance = NULL_PTR;
+
+ConfigReader::ConfigReader()
+{
+    m_ConfigSettingMap.clear();
+}
+
+ConfigReader::~ConfigReader()
+{
+    m_ConfigSettingMap.clear();
+}
+
+ConfigReader* ConfigReader::getInstance()
+{
+    // No need to use double re-check lock mechanism here
+    // because this getInstance() will call at the time of
+    // initialization only and mostly, at the time of
+    // initialization, there will be only one thread.
+
+    if(NULL_PTR == m_pInstance)
+    {
+        m_pInstance = new ConfigReader;
+    }
+    return m_pInstance;
+}
+
+bool ConfigReader::getValue(std::string group, std::string tag, int& value)
+{
+    string _tag = group + "/" + tag;
+    map<string, string>::iterator it ;
+    it = m_ConfigSettingMap.find(_tag);
+    if(it != m_ConfigSettingMap.end())
+    {
+        value = atoi((it->second).c_str());
+        return true;
+    }
+    return false;
+}
+
+bool ConfigReader::getValue(std::string group, std::string tag, std::string& value)
+{
+    string _tag = group + "/" + tag;
+    map<string, string>::iterator it ;
+    it = m_ConfigSettingMap.find(_tag);
+    if(it != m_ConfigSettingMap.end())
+    {
+        value = it->second;
+        return true;
+    }
+    return false;
+}
+
+bool ConfigReader::parseFile(string fileName)
+{
+    ifstream inputFile;
+    inputFile.open(fileName.c_str());
+    string delimeter = "=";
+    string group_label = "";
+    int initPos = 0;
+
+    if (inputFile.fail())
+    {
+        cout << "Unable to find defaultConfig file" << endl;
+        return false;
+    }
+
+    string line;
+    while(getline(inputFile, line))
+    {
+        // Remove comment Lines
+        size_t found = line.find_first_of('#');
+        string configData = line.substr(0, found);
+
+        // Remove ^M from configData
+        configData.erase(std::remove(configData.begin(), configData.end(), '\r'), configData.end());
+
+        if(configData.empty())
+            continue;
+
+        size_t gr_start = configData.find("[");
+        size_t gr_stop = configData.find("]");
+        if ((gr_start != string::npos) && (gr_stop != string::npos)) {
+            group_label = configData.substr(gr_start+1, gr_stop-1);
+            // cout << "group_label=" << group_label << endl;
+            continue;
+        }
+        size_t length = configData.find(delimeter);
+
+        string tag, value;
+
+        if (length != string::npos) {
+            tag   = configData.substr(initPos, length);
+            value = configData.substr(length+1);
+        }
+
+        // Trim white spaces
+        tag   = reduce(tag);
+        value = reduce(value);
+        // cout << tag << "=" << value << endl;
+
+        if(tag.empty() || value.empty())
+            continue;
+
+        // add group_name to tag
+        tag = group_label + "/" + tag;
+        
+        // Check if any of the tags is repeated more than one times
+        // it needs to pick the latest one instead of the old one.
+
+        // Search, if the tag is already present or not
+        // If it is already present, then delete an existing one
+
+        std::map<std::string, std::string>::iterator itr = m_ConfigSettingMap.find(tag);
+        if(itr != m_ConfigSettingMap.end())
+        {
+            m_ConfigSettingMap.erase(tag);
+        }
+
+        m_ConfigSettingMap.insert(std::pair<string, string>(tag, value));
+    }
+    return true;
+}
+
+std::string ConfigReader::trim(const std::string& str, const std::string& whitespace)
+{
+    size_t strBegin = str.find_first_not_of(whitespace);
+    if (strBegin == std::string::npos)
+        return "";
+
+    size_t strEnd = str.find_last_not_of(whitespace);
+    size_t strRange = strEnd - strBegin + 1;
+
+    return str.substr(strBegin, strRange);
+}
+
+std::string ConfigReader::reduce(const std::string& str,
+        const std::string& fill,
+        const std::string& whitespace)
+{
+    // trim first
+    string result = trim(str, whitespace);
+
+    // replace sub ranges
+    size_t beginSpace = result.find_first_of(whitespace);
+    while (beginSpace != std::string::npos)
+    {
+        size_t endSpace = result.find_first_not_of(whitespace, beginSpace);
+        size_t range = endSpace - beginSpace;
+
+        result.replace(beginSpace, range, fill);
+
+        size_t newStart = beginSpace + fill.length();
+        beginSpace = result.find_first_of(whitespace, newStart);
+    }
+
+    return result;
+}
+
+void ConfigReader::dumpFileValues()
+{
+    map<string, string>::iterator it;
+    for(it=m_ConfigSettingMap.begin(); it!=m_ConfigSettingMap.end(); ++it)
+    {
+        cout << it->first << " = " << it->second << endl;
+    }
+}
+
+// int main()
+// {
+//     // Create object of the class ConfigReader
+//     ConfigReader* p = ConfigReader::getInstance();
+
+//     // parse the configuration file
+//     p->parseFile();
+
+//     // Dump map on the console after parsing it
+//     p->dumpFileValues();
+
+//     // Print divider on the console to understand the output properly
+//     cout << endl << "=================================================" << endl << endl;
+
+//     // Define variables to store the value
+//     string name("");
+//     string skill("");
+//     string website("");
+//     int age = 0;
+
+//     // Update the variable by the value present in the configuration file.
+//     p->getValue("Name", name);
+//     p->getValue("Skill", skill);
+//     p->getValue("Website", website);
+//     p->getValue("Age", age);
+
+//     // Variables has been updated. Now print it on the console.
+//     cout << "Name = " << name << endl;
+//     cout << "Skill = " << skill << endl;
+//     cout << "Website = " << website << endl;
+//     cout << "Age = " << age << endl;
+
+//     // Return sucees to the caller
+//     return 0;
+// }
\ No newline at end of file
diff --git a/src/config_reader.h b/src/config_reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..df7413d7db3af281fa4fdf258660cf16718591a3
--- /dev/null
+++ b/src/config_reader.h
@@ -0,0 +1,97 @@
+// config.h
+#ifndef _CONFIG_READER_H_
+#define _CONFIG_READER_H_
+
+// C++ Header File(s)
+#include <iostream>
+#include <map>
+
+// Define namespace for this class. so that anyonelo
+// can easily integrate it. The class name is vary generic
+// so the chance to collapse the class name is high.
+// So need to define the class inside the namespace.
+
+// Defining ConfigReader as singleton class
+// Easy to access across the multiple classes
+//
+// The responsibility of this class is to parse the
+// Config file and store it in the std::map
+// Defined getter function getValue() to get the
+// data from the std::map.
+//
+// To use this class, pass the config file path to
+// the function getInstance()
+//
+// This is one of the advance config reader, because this
+// class is handling the comment line as well. Comment line 
+// will start from hash(#). So all the string after
+// semicolon will be discarded.
+//
+// NOTE: NO NEED TO MAKE THIS CLASS THREAD-SAFE. IT IS EXTRA OVEHEAD.
+// BECAUSE MOSTLY WE ARE DOING ONLY READ OPERATION. WRITE OPERATION IS
+// HAPPENING ONLY ONE TIME, WHICH IS IN THE FUNCTION parse(). SO CALL
+// parse() FUNCTION AT THE TIME OF INITIALIZATION ONLY.
+//
+// IF YOUR CONFIGURATION FILE IS UPDATING AT THE RUN TIME AND YOU NEED
+// UPDATED DATA FROM THE CONFIGURATION FILE AT RUN TIME, THEN YOU NEED 
+// TO MAKE THIS CLASS THREAD-SAFE.
+
+class ConfigReader
+{
+  private:
+     
+    // Define the map to store data from the config file
+    std::map<std::string, std::string> m_ConfigSettingMap;
+
+    // Static pointer instance to make this class singleton.
+    static ConfigReader* m_pInstance;
+
+  public:
+     
+    // Public static method getInstance(). This function is
+    // responsible for object creation.
+    static ConfigReader* getInstance();
+
+    // Parse the config file.
+    bool parseFile(std::string fileName = "/tmp/default_config");
+    // bool parseFile(std::string fileName = "/tmp/sdptr.conf");
+
+    // Overloaded getValue() function.
+    // Value of the tag in cofiguration file could be
+    // string or integer. So the caller need to take care this.
+    // Caller need to call appropiate function based on the
+    // data type of the value of the tag.
+
+    bool getValue(std::string group, std::string tag, int& value);
+    bool getValue(std::string group, std::string tag, std::string& value);
+
+    // Function dumpFileValues is for only debug purpose
+    void dumpFileValues();
+
+  private:
+
+    // Define constructor in the private section to make this
+    // class as singleton.
+    ConfigReader();
+
+    // Define destructor in private section, so no one can delete 
+    // the instance of this class.
+    ~ConfigReader();
+
+    // Define copy constructor in the private section, so that no one can 
+    // voilate the singleton policy of this class
+    ConfigReader(const ConfigReader& obj){}
+     
+    // Define assignment operator in the private section, so that no one can 
+    // voilate the singleton policy of this class
+    void operator=(const ConfigReader& obj){}
+
+    // Helper function to trim the tag and value. These helper function is
+    // calling to trim the un-necessary spaces.
+    std::string trim(const std::string& str, const std::string& whitespace = " \t");
+    std::string reduce(const std::string& str,
+                       const std::string& fill = " ",
+                       const std::string& whitespace = " \t");
+};
+
+#endif // End of _CONFIG_READER_H_
\ No newline at end of file
diff --git a/src/sdptr.conf b/src/sdptr.conf
new file mode 100644
index 0000000000000000000000000000000000000000..21a9b60b34f2d45c557d6dce5ee676dd23682bd9
--- /dev/null
+++ b/src/sdptr.conf
@@ -0,0 +1,59 @@
+# sdptr_lts.conf
+# configuration file for the SDP Translator.
+#
+# this config file holds settings for all [type].
+#
+# # settings per type
+# [LB_Core]						  # [band_stationtype]
+# n_fpgas = 4                     # normal 8 or 16, lts=4, dts=?
+# first_pfga_nr = 0               # normal 0, lts=8, dts=?
+# ip_prefix = "10.99."            # first part of ip (last part is hardware dependent)
+# n_beamsets = 1                  # 1 for 'LB', 'HB Remote' and 'HB International' and 2 for 'HB Core'
+
+
+[]
+fw_name = "lofar2_unb2b_sdp_station_xsub_one"  # expected firmware name
+fw_version = 2                                 # expected firmware version
+
+
+[LB_Core]
+n_fpgas = 16
+first_fpga_nr = 0
+ip_prefix = "10.99."
+n_beamsets = 1
+
+[LB_Remote]
+n_fpgas = 16
+first_fpga_nr = 0
+ip_prefix = "10.99."
+n_beamsets = 1
+
+[LB_International]
+n_fpgas = 16
+first_fpga_nr = 0
+ip_prefix = "10.99."
+n_beamsets = 1
+
+[HB_Core]
+n_fpgas = 8
+first_fpga_nr = 0
+ip_prefix = "10.99."
+n_beamsets = 2
+
+[HB_Remote]
+n_fpgas = 8
+first_fpga_nr = 0
+ip_prefix = "10.99."
+n_beamsets = 1
+
+[HB_International]
+n_fpgas = 16
+first_fpga_nr = 0
+ip_prefix = "10.99."
+n_beamsets = 1
+
+[LTS]
+n_fpgas = 4
+first_fpga_nr = 8
+ip_prefix = "10.99."
+n_beamsets = 1