diff --git a/pid/zone.cpp b/pid/zone.cpp
new file mode 100644
index 0000000..04b3176
--- /dev/null
+++ b/pid/zone.cpp
@@ -0,0 +1,553 @@
+/**
+ * Copyright 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Configuration. */
+#include "conf.hpp"
+
+#include "zone.hpp"
+
+#include <algorithm>
+#include <chrono>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+#include <libconfig.h++>
+#include <memory>
+
+#include "pid/controller.hpp"
+#include "pid/fancontroller.hpp"
+#include "pid/thermalcontroller.hpp"
+#include "pid/ec/pid.hpp"
+
+
+using tstamp = std::chrono::high_resolution_clock::time_point;
+using namespace std::literals::chrono_literals;
+
+static constexpr bool deferSignals = true;
+static constexpr auto objectPath = "/xyz/openbmc_project/settings/fanctrl/zone";
+
+float PIDZone::getMaxRPMRequest(void) const
+{
+    return _maximumRPMSetPt;
+}
+
+bool PIDZone::getManualMode(void) const
+{
+    return _manualMode;
+}
+
+void PIDZone::setManualMode(bool mode)
+{
+    _manualMode = mode;
+}
+
+bool PIDZone::getFailSafeMode(void) const
+{
+    // If any keys are present at least one sensor is in fail safe mode.
+    return !_failSafeSensors.empty();
+}
+
+int64_t PIDZone::getZoneId(void) const
+{
+    return _zoneId;
+}
+
+void PIDZone::addRPMSetPoint(float setpoint)
+{
+    _RPMSetPoints.push_back(setpoint);
+}
+
+void PIDZone::clearRPMSetPoints(void)
+{
+    _RPMSetPoints.clear();
+}
+
+float PIDZone::getFailSafePercent(void) const
+{
+    return _failSafePercent;
+}
+
+float PIDZone::getMinThermalRpmSetPt(void) const
+{
+    return _minThermalRpmSetPt;
+}
+
+void PIDZone::addFanPID(std::unique_ptr<PIDController> pid)
+{
+    _fans.push_back(std::move(pid));
+}
+
+void PIDZone::addThermalPID(std::unique_ptr<PIDController> pid)
+{
+    _thermals.push_back(std::move(pid));
+}
+
+double PIDZone::getCachedValue(const std::string& name)
+{
+    return _cachedValuesByName.at(name);
+}
+
+void PIDZone::addFanInput(std::string fan)
+{
+    _fanInputs.push_back(fan);
+}
+
+void PIDZone::addThermalInput(std::string therm)
+{
+    _thermalInputs.push_back(therm);
+}
+
+void PIDZone::determineMaxRPMRequest(void)
+{
+    float max = 0;
+    std::vector<float>::iterator result;
+
+    if (_RPMSetPoints.size() > 0)
+    {
+        result = std::max_element(_RPMSetPoints.begin(), _RPMSetPoints.end());
+        max = *result;
+    }
+
+    /*
+     * If the maximum RPM set-point output is below the minimum RPM
+     * set-point, set it to the minimum.
+     */
+    max = std::max(getMinThermalRpmSetPt(), max);
+
+#ifdef __TUNING_LOGGING__
+    /*
+     * We received no set-points from thermal sensors.
+     * This is a case experienced during tuning where they only specify
+     * fan sensors and one large fan PID for all the fans.
+     */
+    static constexpr auto setpointpath = "/etc/thermal.d/set-point";
+    try
+    {
+        int value;
+        std::ifstream ifs;
+        ifs.open(setpointpath);
+        if (ifs.good()) {
+            ifs >> value;
+            max = value; // expecting RPM set-point, not pwm%
+        }
+    }
+    catch (const std::exception& e)
+    {
+        /* This exception is uninteresting. */
+        std::cerr << "Unable to read from '" << setpointpath << "'\n";
+    }
+#endif
+
+    _maximumRPMSetPt = max;
+    return;
+}
+
+#ifdef __TUNING_LOGGING__
+void PIDZone::initializeLog(void)
+{
+    /* Print header for log file. */
+
+    _log << "epoch_ms,setpt";
+
+    for (auto& f : _fanInputs)
+    {
+        _log << "," << f;
+    }
+    _log << std::endl;
+
+    return;
+}
+
+std::ofstream& PIDZone::getLogHandle(void)
+{
+    return _log;
+}
+#endif
+
+/*
+ * TODO(venture) This is effectively updating the cache and should check if the
+ * values they're using to update it are new or old, or whatnot.  For instance,
+ * if we haven't heard from the host in X time we need to detect this failure.
+ *
+ * I haven't decided if the Sensor should have a lastUpdated method or whether
+ * that should be for the ReadInterface or etc...
+ */
+
+/**
+ * We want the PID loop to run with values cached, so this will get all the
+ * fan tachs for the loop.
+ */
+void PIDZone::updateFanTelemetry(void)
+{
+    /* TODO(venture): Should I just make _log point to /dev/null when logging
+     * is disabled?  I think it's a waste to try and log things even if the
+     * data is just being dropped though.
+     */
+#ifdef __TUNING_LOGGING__
+    tstamp now = std::chrono::high_resolution_clock::now();
+    _log << std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
+    _log << "," << _maximumRPMSetPt;
+#endif
+
+    for (auto& f : _fanInputs)
+    {
+        auto& sensor = _mgr->getSensor(f);
+        ReadReturn r = sensor->read();
+        _cachedValuesByName[f] = r.value;
+
+        /*
+         * TODO(venture): We should check when these were last read.
+         * However, these are the fans, so if I'm not getting updated values
+         * for them... what should I do?
+         */
+#ifdef __TUNING_LOGGING__
+        _log << "," << r.value;
+#endif
+    }
+
+    return;
+}
+
+void PIDZone::updateSensors(void)
+{
+    using namespace std::chrono;
+    /* margin and temp are stored as temp */
+    tstamp now = high_resolution_clock::now();
+
+    for (auto& t : _thermalInputs)
+    {
+        auto& sensor = _mgr->getSensor(t);
+        ReadReturn r = sensor->read();
+        int64_t timeout = sensor->GetTimeout();
+
+        _cachedValuesByName[t] = r.value;
+        tstamp then = r.updated;
+
+        /* Only go into failsafe if the timeout is set for
+         * the sensor.
+         */
+        if (timeout > 0)
+        {
+            auto duration = duration_cast<std::chrono::seconds>
+                    (now - then).count();
+            auto period = std::chrono::seconds(timeout).count();
+            if (duration >= period)
+            {
+                //std::cerr << "Entering fail safe mode.\n";
+                _failSafeSensors.insert(t);
+            }
+            else
+            {
+                // Check if it's in there: remove it.
+                auto kt = _failSafeSensors.find(t);
+                if (kt != _failSafeSensors.end())
+                {
+                    _failSafeSensors.erase(kt);
+                }
+            }
+        }
+    }
+
+    return;
+}
+
+void PIDZone::initializeCache(void)
+{
+    for (auto& f : _fanInputs)
+    {
+        _cachedValuesByName[f] = 0;
+    }
+
+    for (auto& t : _thermalInputs)
+    {
+        _cachedValuesByName[t] = 0;
+
+        // Start all sensors in fail-safe mode.
+        _failSafeSensors.insert(t);
+    }
+}
+
+void PIDZone::dumpCache(void)
+{
+    std::cerr << "Cache values now: \n";
+    for (auto& k : _cachedValuesByName)
+    {
+        std::cerr << k.first << ": " << k.second << "\n";
+    }
+}
+
+void PIDZone::process_fans(void)
+{
+    for (auto& p : _fans)
+    {
+        p->pid_process();
+    }
+}
+
+void PIDZone::process_thermals(void)
+{
+    for (auto& p : _thermals)
+    {
+        p->pid_process();
+    }
+}
+
+std::unique_ptr<Sensor>& PIDZone::getSensor(std::string name)
+{
+    return _mgr->getSensor(name);
+}
+
+bool PIDZone::manual(bool value)
+{
+    std::cerr << "manual: " << value << std::endl;
+    setManualMode(value);
+    return ModeObject::manual(value);
+}
+
+bool PIDZone::failSafe() const
+{
+    return getFailSafeMode();
+}
+
+static std::string GetControlPath(int64_t zone)
+{
+    return std::string(objectPath) + std::to_string(zone);
+}
+
+std::map<int64_t, std::shared_ptr<PIDZone>> BuildZones(
+            std::map<int64_t, PIDConf>& ZonePids,
+            std::map<int64_t, struct zone>& ZoneConfigs,
+            std::shared_ptr<SensorManager> mgr,
+            sdbusplus::bus::bus& ModeControlBus)
+{
+    std::map<int64_t, std::shared_ptr<PIDZone>> zones;
+
+    for (auto& zi : ZonePids)
+    {
+        auto zoneId = static_cast<int64_t>(zi.first);
+        /* The above shouldn't be necessary but is, and I am having trouble
+         * locating my notes on why.  If I recall correctly it was casting it
+         * down to a byte in at least some cases causing weird behaviors.
+         */
+
+        auto zoneConf = ZoneConfigs.find(zoneId);
+        if (zoneConf == ZoneConfigs.end())
+        {
+            /* The Zone doesn't have a configuration, bail. */
+            static constexpr auto err =
+                "Bailing during load, missing Zone Configuration";
+            std::cerr << err << std::endl;
+            throw std::runtime_error(err);
+        }
+
+        PIDConf& PIDConfig = zi.second;
+
+        auto zone = std::make_shared<PIDZone>(
+                        zoneId,
+                        zoneConf->second.minthermalrpm,
+                        zoneConf->second.failsafepercent,
+                        mgr,
+                        ModeControlBus,
+                        GetControlPath(zi.first).c_str(),
+                        deferSignals);
+
+        zones[zoneId] = zone;
+
+        std::cerr << "Zone Id: " << zone->getZoneId() << "\n";
+
+        // For each PID create a Controller and a Sensor.
+        PIDConf::iterator pit = PIDConfig.begin();
+        while (pit != PIDConfig.end())
+        {
+            std::vector<std::string> inputs;
+            std::string name = pit->first;
+            struct controller_info* info = &pit->second;
+
+            std::cerr << "PID name: " << name << "\n";
+
+            /*
+             * TODO(venture): Need to check if input is known to the
+             * SensorManager.
+             */
+            if (info->type == "fan")
+            {
+                for (auto i : info->inputs)
+                {
+                    inputs.push_back(i);
+                    zone->addFanInput(i);
+                }
+
+                auto pid = FanController::CreateFanPid(
+                               zone,
+                               name,
+                               inputs,
+                               info->info);
+                zone->addFanPID(std::move(pid));
+            }
+            else if (info->type == "temp" || info->type == "margin")
+            {
+                for (auto i : info->inputs)
+                {
+                    inputs.push_back(i);
+                    zone->addThermalInput(i);
+                }
+
+                auto pid = ThermalController::CreateThermalPid(
+                               zone,
+                               name,
+                               inputs,
+                               info->setpoint,
+                               info->info);
+                zone->addThermalPID(std::move(pid));
+            }
+
+            std::cerr << "inputs: ";
+            for (auto& i : inputs)
+            {
+                std::cerr << i << ", ";
+            }
+            std::cerr << "\n";
+
+            ++pit;
+        }
+
+        zone->emit_object_added();
+    }
+
+    return zones;
+}
+
+std::map<int64_t, std::shared_ptr<PIDZone>> BuildZonesFromConfig(
+            std::string& path,
+            std::shared_ptr<SensorManager> mgr,
+            sdbusplus::bus::bus& ModeControlBus)
+{
+    using namespace libconfig;
+    // zone -> pids
+    std::map<int64_t, PIDConf> pidConfig;
+    // zone -> configs
+    std::map<int64_t, struct zone> zoneConfig;
+
+    std::cerr << "entered BuildZonesFromConfig\n";
+
+    Config cfg;
+
+    /* The load was modeled after the example source provided. */
+    try
+    {
+        cfg.readFile(path.c_str());
+    }
+    catch (const FileIOException& fioex)
+    {
+        std::cerr << "I/O error while reading file: " << fioex.what() << std::endl;
+        throw;
+    }
+    catch (const ParseException& pex)
+    {
+        std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
+                  << " - " << pex.getError() << std::endl;
+        throw;
+    }
+
+    try
+    {
+        const Setting& root = cfg.getRoot();
+        const Setting& zones = root["zones"];
+        int count = zones.getLength();
+
+        /* For each zone. */
+        for (int i = 0; i < count; ++i)
+        {
+            const Setting& zoneSettings = zones[i];
+
+            int id;
+            PIDConf thisZone;
+            struct zone thisZoneConfig;
+
+            zoneSettings.lookupValue("id", id);
+
+            thisZoneConfig.minthermalrpm =
+                    zoneSettings.lookup("minthermalrpm");
+            thisZoneConfig.failsafepercent =
+                    zoneSettings.lookup("failsafepercent");
+
+            const Setting& pids = zoneSettings["pids"];
+            int pidCount = pids.getLength();
+
+            for (int j = 0; j < pidCount; ++j)
+            {
+                const Setting& pid = pids[j];
+
+                std::string name;
+                controller_info info;
+
+                /*
+                 * Mysteriously if you use lookupValue on these, and the type
+                 * is float.  It won't work right.
+                 *
+                 * If the configuration file value doesn't look explicitly like
+                 * a float it won't let you assign it to one.
+                 */
+                name = pid.lookup("name").c_str();
+                info.type = pid.lookup("type").c_str();
+                /* set-point is only required to be set for thermal. */
+                /* TODO(venture): Verify this works optionally here. */
+                info.setpoint = pid.lookup("set-point");
+                info.info.ts = pid.lookup("pid.sampleperiod");
+                info.info.p_c = pid.lookup("pid.p_coefficient");
+                info.info.i_c = pid.lookup("pid.i_coefficient");
+                info.info.ff_off = pid.lookup("pid.ff_off_coefficient");
+                info.info.ff_gain = pid.lookup("pid.ff_gain_coefficient");
+                info.info.i_lim.min = pid.lookup("pid.i_limit.min");
+                info.info.i_lim.max = pid.lookup("pid.i_limit.max");
+                info.info.out_lim.min = pid.lookup("pid.out_limit.min");
+                info.info.out_lim.max = pid.lookup("pid.out_limit.max");
+                info.info.slew_neg = pid.lookup("pid.slew_neg");
+                info.info.slew_pos = pid.lookup("pid.slew_pos");
+
+                std::cerr << "out_lim.min: " << info.info.out_lim.min << "\n";
+                std::cerr << "out_lim.max: " << info.info.out_lim.max << "\n";
+
+                const Setting& inputs = pid["inputs"];
+                int icount = inputs.getLength();
+
+                for (int z = 0; z < icount; ++z)
+                {
+                    std::string v;
+                    v = pid["inputs"][z].c_str();
+                    info.inputs.push_back(v);
+                }
+
+                thisZone[name] = info;
+            }
+
+            pidConfig[static_cast<int64_t>(id)] = thisZone;
+            zoneConfig[static_cast<int64_t>(id)] = thisZoneConfig;
+        }
+    }
+    catch (const SettingTypeException &setex)
+    {
+        std::cerr << "Setting '" << setex.getPath() << "' type exception!" << std::endl;
+        throw;
+    }
+    catch (const SettingNotFoundException& snex)
+    {
+        std::cerr << "Setting '" << snex.getPath() << "' not found!" << std::endl;
+        throw;
+    }
+
+    return BuildZones(pidConfig, zoneConfig, mgr, ModeControlBus);
+}
