#include <thread>
#include <mutex>
#include <iostream>
#include <iomanip>

class Temp {
private:
    double temp;
    bool switch_;
    std::mutex& display;
    void read();
    void write();
    void control();
public:
    Temp(std::mutex& m);
    void run();
};

class Pres {
    double pres, dac;
    std::mutex& display;
    void read();
    void write();
    void control();
public:
    Pres(std::mutex& m);
    void run();
};
    
Temp::Temp(std::mutex& m): temp(0), switch_(false), display(m) {
}

void Temp::read() {
//  dummy: should read temperature from ADC
    static double val = 0.0;
    val += 0.5;
    if (val > 20.0)
        val = 0.0;
    temp = val;
}

void Temp::write() {
//  dummy: should write switch_ to switch
}

void Temp::control() {
//  dummy: should use better algorithm
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    switch_ = temp > 10.0;
}

void Temp::run() {
    while (1) {
        read();
        control();
        {
            std::lock_guard<std::mutex> lock(display);
            std::cout << "temperature = " << std::fixed << std::setw(4) 
                      << std::setprecision(1) << temp << ", switch = " 
                      << switch_ << std::endl;
        }
        write();
        std::this_thread::sleep_for(std::chrono::seconds(3));
    }
}

Pres::Pres(std::mutex& m): pres(0), dac(0), display(m) {
}

void Pres::read() {
//  dummy: should read pressure from ADC
    static double val = 20.0;
    val -= 0.4;
    if (val < 0.0)
        val = 20.0;
    pres = val;
}

void Pres::write() {
//  dummy: should write dac to DAC
}

void Pres::control() {
//  dummy: should use better algorithm
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    dac = 10.0 - pres;
}

void Pres::run() {
    while (1) {
        read();
        control();
        {
            std::lock_guard<std::mutex> lock(display);
            std::cout << "presure = " << std::fixed << std::setw(4) 
                      << std::setprecision(1) << pres << ", DAC = " << std::fixed 
                      << std::setw(5) << std::setprecision(1) << dac << std::endl;
        }
        write();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

int main() {
    std::mutex m;
    Temp t(m);
    Pres p(m);
    std::thread t1(&Temp::run, &t); 
    std::thread t2(&Pres::run, &p); 
    t1.join();
    t2.join();
    return 0; 
}