Skip to content

Instantly share code, notes, and snippets.

@felipemanga
Created August 14, 2022 17:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felipemanga/4a5abd64760dde6312964755a2bc387a to your computer and use it in GitHub Desktop.
Save felipemanga/4a5abd64760dde6312964755a2bc387a to your computer and use it in GitHub Desktop.
A06 Automatic Gearbox
// Compile like this: g++ fullauto.cpp --std=c++17 -o fullauto
// Run like this: sudo fullauto &
#include <thread>
#include <chrono>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
using namespace chrono;
using namespace chrono_literals;
ifstream stat{"/proc/stat"};
ifstream ac{"/sys/class/power_supply/axp22x-ac/present"};
ifstream cpuTemp{"/sys/class/thermal/thermal_zone0/temp"};
milliseconds batteryPollRate = 500ms, acPollRate = 175ms;
constexpr const int acBit = 2,
hotBit = 1,
busyBit = 0;
constexpr const int profiles[] = {
// 000 - battery, cool, idle
1,
// 001 - battery, cool, busy
3,
// 010 - battery, hot, idle
1,
// 011 - battery, hot, busy
2,
// 100 - mains, cool, idle
3,
// 101 - mains, cool, busy
6,
// 110 - mains, hot, idle
5,
// 111 - mains, hot, busy
5
};
const string& read(ifstream& stream) {
static stringstream buf;
static string out;
buf.str("");
stream.seekg(0);
buf << stream.rdbuf();
out = buf.str();
return out;
}
bool hasACPower() {
return read(ac)[0] == '1';
}
float getCPUTemp() {
return atof(read(cpuTemp).c_str()) * 0.001f;
}
int getCPUContention() {
static vector<int> prev;
static vector<int> columns;
auto& str = read(stat);
auto len = str.size();
columns.clear();
bool in = false;
for (auto i = str.find("cpu "); i < len && str[i] != '\n'; ++i) {
auto c = str[i];
bool isNum = c >= '0' && c <= '9';
if (isNum == in)
continue;
in = isNum;
if (isNum) {
columns.push_back(atoi(str.c_str() + i));
}
}
int cont = 0;
if (!prev.empty()) {
cont = columns[0] - prev[0];
}
prev = columns;
return cont;
}
void run() {
int currentProfile = -1;
bool busy = false;
bool hot = false;
while (1) {
auto isAC = hasACPower();
auto rate = isAC ? acPollRate : batteryPollRate;
auto cont = getCPUContention();
this_thread::sleep_for(rate);
cont = getCPUContention();
auto n = (cont * 100) / rate.count();
bool isHot = getCPUTemp() > (hot ? 70 : 80);
hot = isHot;
bool isBusy = n > (
isAC ? (busy ? 8 : 14) : (busy ? 4 : 8)
);
busy = isBusy;
int profile = profiles
[ (isAC << acBit)
| (isHot << hotBit)
| (isBusy << busyBit)
];
if (profile == currentProfile)
continue;
currentProfile = profile;
auto cmd = "devterm-a06-gearbox -s "
+ std::to_string(profile)
+ " > /dev/null";
system(cmd.c_str());
this_thread::sleep_for(rate);
}
}
int main() {
if (!stat || !ac || !cpuTemp) {
cout << "Could not read file" << endl;
return 1;
}
run();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment