aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/HAL/LINUX/hardware
diff options
context:
space:
mode:
Diffstat (limited to 'Marlin/src/HAL/LINUX/hardware')
-rw-r--r--Marlin/src/HAL/LINUX/hardware/Clock.cpp31
-rw-r--r--Marlin/src/HAL/LINUX/hardware/Clock.h89
-rw-r--r--Marlin/src/HAL/LINUX/hardware/Gpio.cpp29
-rw-r--r--Marlin/src/HAL/LINUX/hardware/Gpio.h141
-rw-r--r--Marlin/src/HAL/LINUX/hardware/Heater.cpp60
-rw-r--r--Marlin/src/HAL/LINUX/hardware/Heater.h47
-rw-r--r--Marlin/src/HAL/LINUX/hardware/IOLoggerCSV.cpp49
-rw-r--r--Marlin/src/HAL/LINUX/hardware/IOLoggerCSV.h40
-rw-r--r--Marlin/src/HAL/LINUX/hardware/LinearAxis.cpp65
-rw-r--r--Marlin/src/HAL/LINUX/hardware/LinearAxis.h45
-rw-r--r--Marlin/src/HAL/LINUX/hardware/Timer.cpp117
-rw-r--r--Marlin/src/HAL/LINUX/hardware/Timer.h76
12 files changed, 789 insertions, 0 deletions
diff --git a/Marlin/src/HAL/LINUX/hardware/Clock.cpp b/Marlin/src/HAL/LINUX/hardware/Clock.cpp
new file mode 100644
index 0000000..1984a4a
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/Clock.cpp
@@ -0,0 +1,31 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#ifdef __PLAT_LINUX__
+
+#include "../../../inc/MarlinConfig.h"
+#include "Clock.h"
+
+std::chrono::nanoseconds Clock::startup = std::chrono::high_resolution_clock::now().time_since_epoch();
+uint32_t Clock::frequency = F_CPU;
+double Clock::time_multiplier = 1.0;
+
+#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/hardware/Clock.h b/Marlin/src/HAL/LINUX/hardware/Clock.h
new file mode 100644
index 0000000..072eacf
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/Clock.h
@@ -0,0 +1,89 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include <chrono>
+#include <thread>
+
+class Clock {
+public:
+ static uint64_t ticks(uint32_t frequency = Clock::frequency) {
+ return (Clock::nanos() - Clock::startup.count()) / (1000000000ULL / frequency);
+ }
+
+ static uint64_t nanosToTicks(uint64_t ns, uint32_t frequency = Clock::frequency) {
+ return ns / (1000000000ULL / frequency);
+ }
+
+ // Time acceleration compensated
+ static uint64_t ticksToNanos(uint64_t tick, uint32_t frequency = Clock::frequency) {
+ return (tick * (1000000000ULL / frequency)) / Clock::time_multiplier;
+ }
+
+ static void setFrequency(uint32_t freq) {
+ Clock::frequency = freq;
+ }
+
+ // Time Acceleration compensated
+ static uint64_t nanos() {
+ auto now = std::chrono::high_resolution_clock::now().time_since_epoch();
+ return (now.count() - Clock::startup.count()) * Clock::time_multiplier;
+ }
+
+ static uint64_t micros() {
+ return Clock::nanos() / 1000;
+ }
+
+ static uint64_t millis() {
+ return Clock::micros() / 1000;
+ }
+
+ static double seconds() {
+ return Clock::nanos() / 1000000000.0;
+ }
+
+ static void delayCycles(uint64_t cycles) {
+ std::this_thread::sleep_for(std::chrono::nanoseconds( (1000000000L / frequency) * cycles) / Clock::time_multiplier );
+ }
+
+ static void delayMicros(uint64_t micros) {
+ std::this_thread::sleep_for(std::chrono::microseconds( micros ) / Clock::time_multiplier);
+ }
+
+ static void delayMillis(uint64_t millis) {
+ std::this_thread::sleep_for(std::chrono::milliseconds( millis ) / Clock::time_multiplier);
+ }
+
+ static void delaySeconds(double secs) {
+ std::this_thread::sleep_for(std::chrono::duration<double, std::milli>(secs * 1000) / Clock::time_multiplier);
+ }
+
+ // Will reduce timer resolution increasing likelihood of overflows
+ static void setTimeMultiplier(double tm) {
+ Clock::time_multiplier = tm;
+ }
+
+private:
+ static std::chrono::nanoseconds startup;
+ static uint32_t frequency;
+ static double time_multiplier;
+};
diff --git a/Marlin/src/HAL/LINUX/hardware/Gpio.cpp b/Marlin/src/HAL/LINUX/hardware/Gpio.cpp
new file mode 100644
index 0000000..61a7be7
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/Gpio.cpp
@@ -0,0 +1,29 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#ifdef __PLAT_LINUX__
+
+#include "Gpio.h"
+
+pin_data Gpio::pin_map[Gpio::pin_count+1] = {};
+IOLogger* Gpio::logger = nullptr;
+
+#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/hardware/Gpio.h b/Marlin/src/HAL/LINUX/hardware/Gpio.h
new file mode 100644
index 0000000..2d9b1f2
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/Gpio.h
@@ -0,0 +1,141 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include "Clock.h"
+#include "../../../inc/MarlinConfigPre.h"
+#include <stdint.h>
+
+typedef int16_t pin_type;
+
+struct GpioEvent {
+ enum Type {
+ NOP,
+ FALL,
+ RISE,
+ SET_VALUE,
+ SETM,
+ SETD
+ };
+ uint64_t timestamp;
+ pin_type pin_id;
+ GpioEvent::Type event;
+
+ GpioEvent(uint64_t timestamp, pin_type pin_id, GpioEvent::Type event){
+ this->timestamp = timestamp;
+ this->pin_id = pin_id;
+ this->event = event;
+ }
+};
+
+class IOLogger {
+public:
+ virtual ~IOLogger(){};
+ virtual void log(GpioEvent ev) = 0;
+};
+
+class Peripheral {
+public:
+ virtual ~Peripheral(){};
+ virtual void interrupt(GpioEvent ev) = 0;
+ virtual void update() = 0;
+};
+
+struct pin_data {
+ uint8_t dir;
+ uint8_t mode;
+ uint16_t value;
+ Peripheral* cb;
+};
+
+class Gpio {
+public:
+
+ static const pin_type pin_count = 255;
+ static pin_data pin_map[pin_count+1];
+
+ static bool valid_pin(pin_type pin) {
+ return pin >= 0 && pin <= pin_count;
+ }
+
+ static void set(pin_type pin) {
+ set(pin, 1);
+ }
+
+ static void set(pin_type pin, uint16_t value) {
+ if (!valid_pin(pin)) return;
+ GpioEvent::Type evt_type = value > 1 ? GpioEvent::SET_VALUE : value > pin_map[pin].value ? GpioEvent::RISE : value < pin_map[pin].value ? GpioEvent::FALL : GpioEvent::NOP;
+ pin_map[pin].value = value;
+ GpioEvent evt(Clock::nanos(), pin, evt_type);
+ if (pin_map[pin].cb) {
+ pin_map[pin].cb->interrupt(evt);
+ }
+ if (Gpio::logger) Gpio::logger->log(evt);
+ }
+
+ static uint16_t get(pin_type pin) {
+ if (!valid_pin(pin)) return 0;
+ return pin_map[pin].value;
+ }
+
+ static void clear(pin_type pin) {
+ set(pin, 0);
+ }
+
+ static void setMode(pin_type pin, uint8_t value) {
+ if (!valid_pin(pin)) return;
+ pin_map[pin].mode = value;
+ GpioEvent evt(Clock::nanos(), pin, GpioEvent::Type::SETM);
+ if (pin_map[pin].cb) pin_map[pin].cb->interrupt(evt);
+ if (Gpio::logger) Gpio::logger->log(evt);
+ }
+
+ static uint8_t getMode(pin_type pin) {
+ if (!valid_pin(pin)) return 0;
+ return pin_map[pin].mode;
+ }
+
+ static void setDir(pin_type pin, uint8_t value) {
+ if (!valid_pin(pin)) return;
+ pin_map[pin].dir = value;
+ GpioEvent evt(Clock::nanos(), pin, GpioEvent::Type::SETD);
+ if (pin_map[pin].cb) pin_map[pin].cb->interrupt(evt);
+ if (Gpio::logger) Gpio::logger->log(evt);
+ }
+
+ static uint8_t getDir(pin_type pin) {
+ if (!valid_pin(pin)) return 0;
+ return pin_map[pin].dir;
+ }
+
+ static void attachPeripheral(pin_type pin, Peripheral* per) {
+ if (!valid_pin(pin)) return;
+ pin_map[pin].cb = per;
+ }
+
+ static void attachLogger(IOLogger* logger) {
+ Gpio::logger = logger;
+ }
+
+private:
+ static IOLogger* logger;
+};
diff --git a/Marlin/src/HAL/LINUX/hardware/Heater.cpp b/Marlin/src/HAL/LINUX/hardware/Heater.cpp
new file mode 100644
index 0000000..70df816
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/Heater.cpp
@@ -0,0 +1,60 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#ifdef __PLAT_LINUX__
+
+#include "Clock.h"
+#include <stdio.h>
+#include "../../../inc/MarlinConfig.h"
+
+#include "Heater.h"
+
+Heater::Heater(pin_t heater, pin_t adc) {
+ heater_state = 0;
+ room_temp_raw = 150;
+ last = Clock::micros();
+ heater_pin = heater;
+ adc_pin = adc;
+ heat = 0.0;
+}
+
+Heater::~Heater() {
+}
+
+void Heater::update() {
+ // crude pwm read and cruder heat simulation
+ auto now = Clock::micros();
+ double delta = (now - last);
+ if (delta > 1000 ) {
+ heater_state = pwmcap.update(0xFFFF * Gpio::pin_map[heater_pin].value);
+ last = now;
+ heat += (heater_state - heat) * (delta / 1000000000.0);
+
+ NOLESS(heat, room_temp_raw);
+ Gpio::pin_map[analogInputToDigitalPin(adc_pin)].value = 0xFFFF - (uint16_t)heat;
+ }
+}
+
+void Heater::interrupt(GpioEvent ev) {
+ // ununsed
+}
+
+#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/hardware/Heater.h b/Marlin/src/HAL/LINUX/hardware/Heater.h
new file mode 100644
index 0000000..b17078d
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/Heater.h
@@ -0,0 +1,47 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include "Gpio.h"
+
+struct LowpassFilter {
+ uint64_t data_delay = 0;
+ uint16_t update(uint16_t value) {
+ data_delay = data_delay - (data_delay >> 6) + value;
+ return (uint16_t)(data_delay >> 6);
+ }
+};
+
+class Heater: public Peripheral {
+public:
+ Heater(pin_t heater, pin_t adc);
+ virtual ~Heater();
+ void interrupt(GpioEvent ev);
+ void update();
+
+ pin_t heater_pin, adc_pin;
+ uint16_t room_temp_raw;
+ uint16_t heater_state;
+ LowpassFilter pwmcap;
+ double heat;
+ uint64_t last;
+};
diff --git a/Marlin/src/HAL/LINUX/hardware/IOLoggerCSV.cpp b/Marlin/src/HAL/LINUX/hardware/IOLoggerCSV.cpp
new file mode 100644
index 0000000..c11fd1f
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/IOLoggerCSV.cpp
@@ -0,0 +1,49 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#ifdef __PLAT_LINUX__
+
+#include "IOLoggerCSV.h"
+
+IOLoggerCSV::IOLoggerCSV(std::string filename) {
+ file.open(filename);
+}
+
+IOLoggerCSV::~IOLoggerCSV() {
+ file.close();
+}
+
+void IOLoggerCSV::log(GpioEvent ev) {
+ std::lock_guard<std::mutex> lock(vector_lock);
+ events.push_back(ev); //minimal impact to signal handler
+}
+
+void IOLoggerCSV::flush() {
+ { std::lock_guard<std::mutex> lock(vector_lock);
+ while (!events.empty()) {
+ file << events.front().timestamp << ", "<< events.front().pin_id << ", " << events.front().event << std::endl;
+ events.pop_front();
+ }
+ }
+ file.flush();
+}
+
+#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/hardware/IOLoggerCSV.h b/Marlin/src/HAL/LINUX/hardware/IOLoggerCSV.h
new file mode 100644
index 0000000..d8fe738
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/IOLoggerCSV.h
@@ -0,0 +1,40 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include <mutex>
+#include <list>
+#include <fstream>
+#include "Gpio.h"
+
+class IOLoggerCSV: public IOLogger {
+public:
+ IOLoggerCSV(std::string filename);
+ virtual ~IOLoggerCSV();
+ void flush();
+ void log(GpioEvent ev);
+
+private:
+ std::ofstream file;
+ std::list<GpioEvent> events;
+ std::mutex vector_lock;
+};
diff --git a/Marlin/src/HAL/LINUX/hardware/LinearAxis.cpp b/Marlin/src/HAL/LINUX/hardware/LinearAxis.cpp
new file mode 100644
index 0000000..c5b3ccc
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/LinearAxis.cpp
@@ -0,0 +1,65 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#ifdef __PLAT_LINUX__
+
+#include <random>
+#include <stdio.h>
+#include "Clock.h"
+#include "LinearAxis.h"
+
+LinearAxis::LinearAxis(pin_type enable, pin_type dir, pin_type step, pin_type end_min, pin_type end_max) {
+ enable_pin = enable;
+ dir_pin = dir;
+ step_pin = step;
+ min_pin = end_min;
+ max_pin = end_max;
+
+ min_position = 50;
+ max_position = (200*80) + min_position;
+ position = rand() % ((max_position - 40) - min_position) + (min_position + 20);
+ last_update = Clock::nanos();
+
+ Gpio::attachPeripheral(step_pin, this);
+
+}
+
+LinearAxis::~LinearAxis() {
+
+}
+
+void LinearAxis::update() {
+
+}
+
+void LinearAxis::interrupt(GpioEvent ev) {
+ if (ev.pin_id == step_pin && !Gpio::pin_map[enable_pin].value){
+ if (ev.event == GpioEvent::RISE) {
+ last_update = ev.timestamp;
+ position += -1 + 2 * Gpio::pin_map[dir_pin].value;
+ Gpio::pin_map[min_pin].value = (position < min_position);
+ //Gpio::pin_map[max_pin].value = (position > max_position);
+ //if (position < min_position) printf("axis(%d) endstop : pos: %d, mm: %f, min: %d\n", step_pin, position, position / 80.0, Gpio::pin_map[min_pin].value);
+ }
+ }
+}
+
+#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/hardware/LinearAxis.h b/Marlin/src/HAL/LINUX/hardware/LinearAxis.h
new file mode 100644
index 0000000..34541e7
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/LinearAxis.h
@@ -0,0 +1,45 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include <chrono>
+#include "Gpio.h"
+
+class LinearAxis: public Peripheral {
+public:
+ LinearAxis(pin_type enable, pin_type dir, pin_type step, pin_type end_min, pin_type end_max);
+ virtual ~LinearAxis();
+ void update();
+ void interrupt(GpioEvent ev);
+
+ pin_type enable_pin;
+ pin_type dir_pin;
+ pin_type step_pin;
+ pin_type min_pin;
+ pin_type max_pin;
+
+ int32_t position;
+ int32_t min_position;
+ int32_t max_position;
+ uint64_t last_update;
+
+};
diff --git a/Marlin/src/HAL/LINUX/hardware/Timer.cpp b/Marlin/src/HAL/LINUX/hardware/Timer.cpp
new file mode 100644
index 0000000..9f0d6a8
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/Timer.cpp
@@ -0,0 +1,117 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#ifdef __PLAT_LINUX__
+
+#include "Timer.h"
+#include <stdio.h>
+
+Timer::Timer() {
+ active = false;
+ compare = 0;
+ frequency = 0;
+ overruns = 0;
+ timerid = 0;
+ cbfn = nullptr;
+ period = 0;
+ start_time = 0;
+ avg_error = 0;
+}
+
+Timer::~Timer() {
+ timer_delete(timerid);
+}
+
+void Timer::init(uint32_t sig_id, uint32_t sim_freq, callback_fn* fn) {
+ struct sigaction sa;
+ struct sigevent sev;
+
+ frequency = sim_freq;
+ cbfn = fn;
+
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = Timer::handler;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGRTMIN, &sa, nullptr) == -1) {
+ return; // todo: handle error
+ }
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGRTMIN);
+
+ disable();
+
+ sev.sigev_notify = SIGEV_SIGNAL;
+ sev.sigev_signo = SIGRTMIN;
+ sev.sigev_value.sival_ptr = (void*)this;
+ if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
+ return; // todo: handle error
+ }
+}
+
+void Timer::start(uint32_t frequency) {
+ setCompare(this->frequency / frequency);
+ //printf("timer(%ld) started\n", getID());
+}
+
+void Timer::enable() {
+ if (sigprocmask(SIG_UNBLOCK, &mask, nullptr) == -1) {
+ return; // todo: handle error
+ }
+ active = true;
+ //printf("timer(%ld) enabled\n", getID());
+}
+
+void Timer::disable() {
+ if (sigprocmask(SIG_SETMASK, &mask, nullptr) == -1) {
+ return; // todo: handle error
+ }
+ active = false;
+}
+
+void Timer::setCompare(uint32_t compare) {
+ uint32_t nsec_offset = 0;
+ if (active) {
+ nsec_offset = Clock::nanos() - this->start_time; // calculate how long the timer would have been running for
+ nsec_offset = nsec_offset < 1000 ? nsec_offset : 0; // constrain, this shouldn't be needed but apparently Marlin enables interrupts on the stepper timer before initialising it, todo: investigate ?bug?
+ }
+ this->compare = compare;
+ uint64_t ns = Clock::ticksToNanos(compare, frequency) - nsec_offset;
+ struct itimerspec its;
+ its.it_value.tv_sec = ns / 1000000000;
+ its.it_value.tv_nsec = ns % 1000000000;
+ its.it_interval.tv_sec = its.it_value.tv_sec;
+ its.it_interval.tv_nsec = its.it_value.tv_nsec;
+
+ if (timer_settime(timerid, 0, &its, nullptr) == -1) {
+ printf("timer(%ld) failed, compare: %d(%ld)\n", getID(), compare, its.it_value.tv_nsec);
+ return; // todo: handle error
+ }
+ //printf("timer(%ld) started, compare: %d(%d)\n", getID(), compare, its.it_value.tv_nsec);
+ this->period = its.it_value.tv_nsec;
+ this->start_time = Clock::nanos();
+}
+
+uint32_t Timer::getCount() {
+ return Clock::nanosToTicks(Clock::nanos() - this->start_time, frequency);
+}
+
+#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/hardware/Timer.h b/Marlin/src/HAL/LINUX/hardware/Timer.h
new file mode 100644
index 0000000..757efdc
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/hardware/Timer.h
@@ -0,0 +1,76 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <stdio.h>
+
+#include "Clock.h"
+
+class Timer {
+public:
+ Timer();
+ virtual ~Timer();
+
+ typedef void (callback_fn)();
+
+ void init(uint32_t sig_id, uint32_t sim_freq, callback_fn* fn);
+ void start(uint32_t frequency);
+ void enable();
+ bool enabled() {return active;}
+ void disable();
+ void setCompare(uint32_t compare);
+ uint32_t getCount();
+ uint32_t getCompare() {return compare;}
+ uint32_t getOverruns() {return overruns;}
+ uint32_t getAvgError() {return avg_error;}
+
+ intptr_t getID() {
+ return (*(intptr_t*)timerid);
+ }
+
+ static void handler(int sig, siginfo_t *si, void *uc){
+ Timer* _this = (Timer*)si->si_value.sival_ptr;
+ _this->avg_error += (Clock::nanos() - _this->start_time) - _this->period; //high_resolution_clock is also limited in precision, but best we have
+ _this->avg_error /= 2; //very crude precision analysis (actually within +-500ns usually)
+ _this->start_time = Clock::nanos(); // wrap
+ _this->cbfn();
+ _this->overruns += timer_getoverrun(_this->timerid); // even at 50Khz this doesn't stay zero, again demonstrating the limitations
+ // using a realtime linux kernel would help somewhat
+ }
+
+private:
+ bool active;
+ uint32_t compare;
+ uint32_t frequency;
+ uint32_t overruns;
+ timer_t timerid;
+ sigset_t mask;
+ callback_fn* cbfn;
+ uint64_t period;
+ uint64_t avg_error;
+ uint64_t start_time;
+};