Move 'libs' files
This commit is contained in:
145
Marlin/src/libs/buzzer.h
Normal file
145
Marlin/src/libs/buzzer.h
Normal file
@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BUZZER_H__
|
||||
#define __BUZZER_H__
|
||||
|
||||
#include "types.h"
|
||||
#include "circularqueue.h"
|
||||
#include "temperature.h"
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
#define TONE_QUEUE_LENGTH 4
|
||||
|
||||
/**
|
||||
* @brief Tone structure
|
||||
* @details Simple abstraction of a tone based on a duration and a frequency.
|
||||
*/
|
||||
struct tone_t {
|
||||
uint16_t duration;
|
||||
uint16_t frequency;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Buzzer class
|
||||
*/
|
||||
class Buzzer {
|
||||
private:
|
||||
struct state_t {
|
||||
tone_t tone;
|
||||
uint32_t endtime;
|
||||
} state;
|
||||
|
||||
protected:
|
||||
CircularQueue<tone_t, TONE_QUEUE_LENGTH> buffer;
|
||||
|
||||
/**
|
||||
* @brief Inverts the sate of a digital PIN
|
||||
* @details This will invert the current state of an digital IO pin.
|
||||
*/
|
||||
void invert() {
|
||||
TOGGLE(BEEPER_PIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn off a digital PIN
|
||||
* @details Alias of digitalWrite(PIN, LOW) using FastIO
|
||||
*/
|
||||
void off() {
|
||||
WRITE(BEEPER_PIN, LOW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn on a digital PIN
|
||||
* @details Alias of digitalWrite(PIN, HIGH) using FastIO
|
||||
*/
|
||||
void on() {
|
||||
WRITE(BEEPER_PIN, HIGH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the state of the class
|
||||
* @details Brings the class state to a known one.
|
||||
*/
|
||||
void reset() {
|
||||
this->off();
|
||||
this->state.endtime = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Class constructor
|
||||
*/
|
||||
Buzzer() {
|
||||
SET_OUTPUT(BEEPER_PIN);
|
||||
this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a tone to the queue
|
||||
* @details Adds a tone_t structure to the ring buffer, will block IO if the
|
||||
* queue is full waiting for one slot to get available.
|
||||
*
|
||||
* @param duration Duration of the tone in milliseconds
|
||||
* @param frequency Frequency of the tone in hertz
|
||||
*/
|
||||
void tone(const uint16_t &duration, const uint16_t &frequency = 0) {
|
||||
while (buffer.isFull()) {
|
||||
this->tick();
|
||||
thermalManager.manage_heater();
|
||||
}
|
||||
tone_t tone = { duration, frequency };
|
||||
this->buffer.enqueue(tone);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Loop function
|
||||
* @details This function should be called at loop, it will take care of
|
||||
* playing the tones in the queue.
|
||||
*/
|
||||
virtual void tick() {
|
||||
const millis_t now = millis();
|
||||
|
||||
if (!this->state.endtime) {
|
||||
if (this->buffer.isEmpty()) return;
|
||||
|
||||
this->state.tone = this->buffer.dequeue();
|
||||
this->state.endtime = now + this->state.tone.duration;
|
||||
|
||||
if (this->state.tone.frequency > 0) {
|
||||
#if ENABLED(SPEAKER)
|
||||
CRITICAL_SECTION_START;
|
||||
::tone(BEEPER_PIN, this->state.tone.frequency, this->state.tone.duration);
|
||||
CRITICAL_SECTION_END;
|
||||
#else
|
||||
this->on();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (ELAPSED(now, this->state.endtime)) this->reset();
|
||||
}
|
||||
};
|
||||
|
||||
extern Buzzer buzzer;
|
||||
|
||||
#endif
|
145
Marlin/src/libs/circularqueue.h
Normal file
145
Marlin/src/libs/circularqueue.h
Normal file
@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CIRCULARQUEUE_H__
|
||||
#define __CIRCULARQUEUE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Circular Queue class
|
||||
* @details Implementation of the classic ring buffer data structure
|
||||
*/
|
||||
template<typename T, uint8_t N>
|
||||
class CircularQueue {
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Buffer structure
|
||||
* @details This structure consolidates all the overhead required to handle
|
||||
* a circular queue such as the pointers and the buffer vector.
|
||||
*/
|
||||
struct buffer_t {
|
||||
uint8_t head;
|
||||
uint8_t tail;
|
||||
uint8_t count;
|
||||
uint8_t size;
|
||||
T queue[N];
|
||||
} buffer;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Class constructor
|
||||
* @details This class requires two template parameters, T defines the type
|
||||
* of item this queue will handle and N defines the maximum number of
|
||||
* items that can be stored on the queue.
|
||||
*/
|
||||
CircularQueue<T, N>() {
|
||||
this->buffer.size = N;
|
||||
this->buffer.count = this->buffer.head = this->buffer.tail = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes and returns a item from the queue
|
||||
* @details Removes the oldest item on the queue, pointed to by the
|
||||
* buffer_t head field. The item is returned to the caller.
|
||||
* @return type T item
|
||||
*/
|
||||
T dequeue() {
|
||||
if (this->isEmpty()) return T();
|
||||
|
||||
uint8_t index = this->buffer.head;
|
||||
|
||||
--this->buffer.count;
|
||||
if (++this->buffer.head == this->buffer.size)
|
||||
this->buffer.head = 0;
|
||||
|
||||
return this->buffer.queue[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds an item to the queue
|
||||
* @details Adds an item to the queue on the location pointed by the buffer_t
|
||||
* tail variable. Returns false if no queue space is available.
|
||||
* @param item Item to be added to the queue
|
||||
* @return true if the operation was successful
|
||||
*/
|
||||
bool enqueue(T const &item) {
|
||||
if (this->isFull()) return false;
|
||||
|
||||
this->buffer.queue[this->buffer.tail] = item;
|
||||
|
||||
++this->buffer.count;
|
||||
if (++this->buffer.tail == this->buffer.size)
|
||||
this->buffer.tail = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the queue has no items
|
||||
* @details Returns true if there are no items on the queue, false otherwise.
|
||||
* @return true if queue is empty
|
||||
*/
|
||||
bool isEmpty() {
|
||||
return this->buffer.count == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the queue is full
|
||||
* @details Returns true if the queue is full, false otherwise.
|
||||
* @return true if queue is full
|
||||
*/
|
||||
bool isFull() {
|
||||
return this->buffer.count == this->buffer.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the queue size
|
||||
* @details Returns the maximum number of items a queue can have.
|
||||
* @return the queue size
|
||||
*/
|
||||
uint8_t size() {
|
||||
return this->buffer.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the next item from the queue without removing it
|
||||
* @details Returns the next item in the queue without removing it
|
||||
* or updating the pointers.
|
||||
* @return first item in the queue
|
||||
*/
|
||||
T peek() {
|
||||
return this->buffer.queue[this->buffer.head];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the number of items on the queue
|
||||
* @details Returns the current number of items stored on the queue.
|
||||
* @return number of items in the queue
|
||||
*/
|
||||
uint8_t count() {
|
||||
return this->buffer.count;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
167
Marlin/src/libs/duration_t.h
Normal file
167
Marlin/src/libs/duration_t.h
Normal file
@ -0,0 +1,167 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DURATION_T__
|
||||
#define __DURATION_T__
|
||||
|
||||
struct duration_t {
|
||||
/**
|
||||
* @brief Duration is stored in seconds
|
||||
*/
|
||||
uint32_t value;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
duration_t()
|
||||
: duration_t(0) {};
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param seconds The number of seconds
|
||||
*/
|
||||
duration_t(uint32_t const &seconds) {
|
||||
this->value = seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equality comparison
|
||||
* @details Overloads the equality comparison operator
|
||||
*
|
||||
* @param value The number of seconds to compare to
|
||||
* @return True if both durations are equal
|
||||
*/
|
||||
bool operator==(const uint32_t &value) const {
|
||||
return (this->value == value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inequality comparison
|
||||
* @details Overloads the inequality comparison operator
|
||||
*
|
||||
* @param value The number of seconds to compare to
|
||||
* @return False if both durations are equal
|
||||
*/
|
||||
bool operator!=(const uint32_t &value) const {
|
||||
return ! this->operator==(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Formats the duration as years
|
||||
* @return The number of years
|
||||
*/
|
||||
inline uint8_t year() const {
|
||||
return this->day() / 365;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Formats the duration as days
|
||||
* @return The number of days
|
||||
*/
|
||||
inline uint16_t day() const {
|
||||
return this->hour() / 24;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Formats the duration as hours
|
||||
* @return The number of hours
|
||||
*/
|
||||
inline uint32_t hour() const {
|
||||
return this->minute() / 60;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Formats the duration as minutes
|
||||
* @return The number of minutes
|
||||
*/
|
||||
inline uint32_t minute() const {
|
||||
return this->second() / 60;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Formats the duration as seconds
|
||||
* @return The number of seconds
|
||||
*/
|
||||
inline uint32_t second() const {
|
||||
return this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Formats the duration as a string
|
||||
* @details String will be formated using a "full" representation of duration
|
||||
*
|
||||
* @param buffer The array pointed to must be able to accommodate 21 bytes
|
||||
*
|
||||
* Output examples:
|
||||
* 123456789012345678901 (strlen)
|
||||
* 135y 364d 23h 59m 59s
|
||||
* 364d 23h 59m 59s
|
||||
* 23h 59m 59s
|
||||
* 59m 59s
|
||||
* 59s
|
||||
*/
|
||||
void toString(char *buffer) const {
|
||||
int y = this->year(),
|
||||
d = this->day() % 365,
|
||||
h = this->hour() % 24,
|
||||
m = this->minute() % 60,
|
||||
s = this->second() % 60;
|
||||
|
||||
if (y) sprintf_P(buffer, PSTR("%iy %id %ih %im %is"), y, d, h, m, s);
|
||||
else if (d) sprintf_P(buffer, PSTR("%id %ih %im %is"), d, h, m, s);
|
||||
else if (h) sprintf_P(buffer, PSTR("%ih %im %is"), h, m, s);
|
||||
else if (m) sprintf_P(buffer, PSTR("%im %is"), m, s);
|
||||
else sprintf_P(buffer, PSTR("%is"), s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Formats the duration as a string
|
||||
* @details String will be formated using a "digital" representation of duration
|
||||
*
|
||||
* @param buffer The array pointed to must be able to accommodate 10 bytes
|
||||
*
|
||||
* Output examples:
|
||||
* 123456789 (strlen)
|
||||
* 99:59
|
||||
* 11d 12:33
|
||||
*/
|
||||
uint8_t toDigital(char *buffer, bool with_days=false) const {
|
||||
uint16_t h = uint16_t(this->hour()),
|
||||
m = uint16_t(this->minute() % 60UL);
|
||||
if (with_days) {
|
||||
uint16_t d = this->day();
|
||||
sprintf_P(buffer, PSTR("%ud %02u:%02u"), d, h % 24, m);
|
||||
return d >= 10 ? 8 : 7;
|
||||
}
|
||||
else if (h < 100) {
|
||||
sprintf_P(buffer, PSTR("%02u:%02u"), h % 24, m);
|
||||
return 5;
|
||||
}
|
||||
else {
|
||||
sprintf_P(buffer, PSTR("%u:%02u"), h, m);
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __DURATION_T__
|
55
Marlin/src/libs/hex_print_routines.cpp
Normal file
55
Marlin/src/libs/hex_print_routines.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "Marlin.h"
|
||||
#include "gcode.h"
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(M100_FREE_MEMORY_WATCHER) || ENABLED(DEBUG_GCODE_PARSER)
|
||||
|
||||
#include "hex_print_routines.h"
|
||||
|
||||
static char _hex[7] = "0x0000";
|
||||
|
||||
char* hex_byte(const uint8_t b) {
|
||||
_hex[4] = hex_nybble(b >> 4);
|
||||
_hex[5] = hex_nybble(b);
|
||||
return &_hex[4];
|
||||
}
|
||||
|
||||
char* hex_word(const uint16_t w) {
|
||||
_hex[2] = hex_nybble(w >> 12);
|
||||
_hex[3] = hex_nybble(w >> 8);
|
||||
_hex[4] = hex_nybble(w >> 4);
|
||||
_hex[5] = hex_nybble(w);
|
||||
return &_hex[2];
|
||||
}
|
||||
|
||||
char* hex_address(const void * const w) {
|
||||
(void)hex_word((int)w);
|
||||
return _hex;
|
||||
}
|
||||
|
||||
void print_hex_nybble(const uint8_t n) { SERIAL_CHAR(hex_nybble(n)); }
|
||||
void print_hex_byte(const uint8_t b) { SERIAL_ECHO(hex_byte(b)); }
|
||||
void print_hex_word(const uint16_t w) { SERIAL_ECHO(hex_word(w)); }
|
||||
void print_hex_address(const void * const w) { SERIAL_ECHO(hex_address(w)); }
|
||||
|
||||
#endif // AUTO_BED_LEVELING_UBL || M100_FREE_MEMORY_WATCHER || DEBUG_GCODE_PARSER
|
48
Marlin/src/libs/hex_print_routines.h
Normal file
48
Marlin/src/libs/hex_print_routines.h
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HEX_PRINT_ROUTINES_H
|
||||
#define HEX_PRINT_ROUTINES_H
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
#include "gcode.h"
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(M100_FREE_MEMORY_WATCHER) || ENABLED(DEBUG_GCODE_PARSER)
|
||||
|
||||
//
|
||||
// Utility functions to create and print hex strings as nybble, byte, and word.
|
||||
//
|
||||
|
||||
inline char hex_nybble(const uint8_t n) {
|
||||
return (n & 0xF) + ((n & 0xF) < 10 ? '0' : 'A' - 10);
|
||||
}
|
||||
char* hex_byte(const uint8_t b);
|
||||
char* hex_word(const uint16_t w);
|
||||
char* hex_address(const void * const w);
|
||||
|
||||
void print_hex_nybble(const uint8_t n);
|
||||
void print_hex_byte(const uint8_t b);
|
||||
void print_hex_word(const uint16_t w);
|
||||
void print_hex_address(const void * const w);
|
||||
|
||||
#endif // AUTO_BED_LEVELING_UBL || M100_FREE_MEMORY_WATCHER || DEBUG_GCODE_PARSER
|
||||
#endif // HEX_PRINT_ROUTINES_H
|
71
Marlin/src/libs/least_squares_fit.cpp
Normal file
71
Marlin/src/libs/least_squares_fit.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Least Squares Best Fit by Roxy and Ed Williams
|
||||
*
|
||||
* This algorithm is high speed and has a very small code footprint.
|
||||
* Its results are identical to both the Iterative Least-Squares published
|
||||
* earlier by Roxy and the QR_SOLVE solution. If used in place of QR_SOLVE
|
||||
* it saves roughly 10K of program memory. It also does not require all of
|
||||
* coordinates to be present during the calculations. Each point can be
|
||||
* probed and then discarded.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(AUTO_BED_LEVELING_LINEAR)
|
||||
|
||||
#include "macros.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "least_squares_fit.h"
|
||||
|
||||
int finish_incremental_LSF(struct linear_fit_data *lsf) {
|
||||
|
||||
const float N = lsf->N;
|
||||
|
||||
if (N == 0.0)
|
||||
return 1;
|
||||
|
||||
lsf->xbar /= N;
|
||||
lsf->ybar /= N;
|
||||
lsf->zbar /= N;
|
||||
lsf->x2bar = lsf->x2bar / N - sq(lsf->xbar);
|
||||
lsf->y2bar = lsf->y2bar / N - sq(lsf->ybar);
|
||||
lsf->z2bar = lsf->z2bar / N - sq(lsf->zbar);
|
||||
lsf->xybar = lsf->xybar / N - lsf->xbar * lsf->ybar;
|
||||
lsf->yzbar = lsf->yzbar / N - lsf->ybar * lsf->zbar;
|
||||
lsf->xzbar = lsf->xzbar / N - lsf->xbar * lsf->zbar;
|
||||
const float DD = lsf->x2bar * lsf->y2bar - sq(lsf->xybar);
|
||||
|
||||
if (FABS(DD) <= 1e-10 * (lsf->max_absx + lsf->max_absy))
|
||||
return 1;
|
||||
|
||||
lsf->A = (lsf->yzbar * lsf->xybar - lsf->xzbar * lsf->y2bar) / DD;
|
||||
lsf->B = (lsf->xzbar * lsf->xybar - lsf->yzbar * lsf->x2bar) / DD;
|
||||
lsf->D = -(lsf->zbar + lsf->A * lsf->xbar + lsf->B * lsf->ybar);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // AUTO_BED_LEVELING_UBL || ENABLED(AUTO_BED_LEVELING_LINEAR)
|
90
Marlin/src/libs/least_squares_fit.h
Normal file
90
Marlin/src/libs/least_squares_fit.h
Normal file
@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Incremental Least Squares Best Fit By Roxy and Ed Williams
|
||||
*
|
||||
* This algorithm is high speed and has a very small code footprint.
|
||||
* Its results are identical to both the Iterative Least-Squares published
|
||||
* earlier by Roxy and the QR_SOLVE solution. If used in place of QR_SOLVE
|
||||
* it saves roughly 10K of program memory. And even better... the data
|
||||
* fed into the algorithm does not need to all be present at the same time.
|
||||
* A point can be probed and its values fed into the algorithm and then discarded.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(AUTO_BED_LEVELING_LINEAR)
|
||||
|
||||
#include "Marlin.h"
|
||||
#include "macros.h"
|
||||
#include <math.h>
|
||||
|
||||
struct linear_fit_data {
|
||||
float xbar, ybar, zbar,
|
||||
x2bar, y2bar, z2bar,
|
||||
xybar, xzbar, yzbar,
|
||||
max_absx, max_absy,
|
||||
A, B, D, N;
|
||||
};
|
||||
|
||||
void inline incremental_LSF_reset(struct linear_fit_data *lsf) {
|
||||
memset(lsf, 0, sizeof(linear_fit_data));
|
||||
}
|
||||
|
||||
void inline incremental_WLSF(struct linear_fit_data *lsf, const float &x, const float &y, const float &z, const float &w) {
|
||||
// weight each accumulator by factor w, including the "number" of samples
|
||||
// (analagous to calling inc_LSF twice with same values to weight it by 2X)
|
||||
lsf->xbar += w * x;
|
||||
lsf->ybar += w * y;
|
||||
lsf->zbar += w * z;
|
||||
lsf->x2bar += w * x * x; // don't use sq(x) -- let compiler re-use w*x four times
|
||||
lsf->y2bar += w * y * y;
|
||||
lsf->z2bar += w * z * z;
|
||||
lsf->xybar += w * x * y;
|
||||
lsf->xzbar += w * x * z;
|
||||
lsf->yzbar += w * y * z;
|
||||
lsf->N += w;
|
||||
lsf->max_absx = max(FABS(w * x), lsf->max_absx);
|
||||
lsf->max_absy = max(FABS(w * y), lsf->max_absy);
|
||||
}
|
||||
|
||||
void inline incremental_LSF(struct linear_fit_data *lsf, const float &x, const float &y, const float &z) {
|
||||
lsf->xbar += x;
|
||||
lsf->ybar += y;
|
||||
lsf->zbar += z;
|
||||
lsf->x2bar += sq(x);
|
||||
lsf->y2bar += sq(y);
|
||||
lsf->z2bar += sq(z);
|
||||
lsf->xybar += x * y;
|
||||
lsf->xzbar += x * z;
|
||||
lsf->yzbar += y * z;
|
||||
lsf->max_absx = max(FABS(x), lsf->max_absx);
|
||||
lsf->max_absy = max(FABS(y), lsf->max_absy);
|
||||
lsf->N += 1.0;
|
||||
}
|
||||
|
||||
int finish_incremental_LSF(struct linear_fit_data *);
|
||||
|
||||
#endif
|
||||
|
238
Marlin/src/libs/nozzle.cpp
Normal file
238
Marlin/src/libs/nozzle.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
#include "nozzle.h"
|
||||
|
||||
#include "Marlin.h"
|
||||
#include "point_t.h"
|
||||
|
||||
/**
|
||||
* @brief Stroke clean pattern
|
||||
* @details Wipes the nozzle back and forth in a linear movement
|
||||
*
|
||||
* @param start point_t defining the starting point
|
||||
* @param end point_t defining the ending point
|
||||
* @param strokes number of strokes to execute
|
||||
*/
|
||||
void Nozzle::stroke(
|
||||
_UNUSED point_t const &start,
|
||||
_UNUSED point_t const &end,
|
||||
_UNUSED uint8_t const &strokes
|
||||
) {
|
||||
#if ENABLED(NOZZLE_CLEAN_FEATURE)
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
// Store the current coords
|
||||
point_t const initial = {
|
||||
current_position[X_AXIS],
|
||||
current_position[Y_AXIS],
|
||||
current_position[Z_AXIS],
|
||||
current_position[E_AXIS]
|
||||
};
|
||||
#endif // NOZZLE_CLEAN_GOBACK
|
||||
|
||||
// Move to the starting point
|
||||
do_blocking_move_to_xy(start.x, start.y);
|
||||
do_blocking_move_to_z(start.z);
|
||||
|
||||
// Start the stroke pattern
|
||||
for (uint8_t i = 0; i < (strokes >>1); i++) {
|
||||
do_blocking_move_to_xy(end.x, end.y);
|
||||
do_blocking_move_to_xy(start.x, start.y);
|
||||
}
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
// Move the nozzle to the initial point
|
||||
do_blocking_move_to(initial.x, initial.y, initial.z);
|
||||
#endif // NOZZLE_CLEAN_GOBACK
|
||||
|
||||
#endif // NOZZLE_CLEAN_FEATURE
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Zig-zag clean pattern
|
||||
* @details Apply a zig-zag cleanning pattern
|
||||
*
|
||||
* @param start point_t defining the starting point
|
||||
* @param end point_t defining the ending point
|
||||
* @param strokes number of strokes to execute
|
||||
* @param objects number of objects to create
|
||||
*/
|
||||
void Nozzle::zigzag(
|
||||
_UNUSED point_t const &start,
|
||||
_UNUSED point_t const &end,
|
||||
_UNUSED uint8_t const &strokes,
|
||||
_UNUSED uint8_t const &objects
|
||||
) {
|
||||
#if ENABLED(NOZZLE_CLEAN_FEATURE)
|
||||
const float A = nozzle_clean_horizontal ? nozzle_clean_height : nozzle_clean_length, // [twice the] Amplitude
|
||||
P = (nozzle_clean_horizontal ? nozzle_clean_length : nozzle_clean_height) / (objects << 1); // Period
|
||||
|
||||
// Don't allow impossible triangles
|
||||
if (A <= 0.0f || P <= 0.0f ) return;
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
// Store the current coords
|
||||
point_t const initial = {
|
||||
current_position[X_AXIS],
|
||||
current_position[Y_AXIS],
|
||||
current_position[Z_AXIS],
|
||||
current_position[E_AXIS]
|
||||
};
|
||||
#endif // NOZZLE_CLEAN_GOBACK
|
||||
|
||||
for (uint8_t j = 0; j < strokes; j++) {
|
||||
for (uint8_t i = 0; i < (objects << 1); i++) {
|
||||
float const x = start.x + ( nozzle_clean_horizontal ? i * P : (A/P) * (P - FABS(FMOD((i*P), (2*P)) - P)) );
|
||||
float const y = start.y + (!nozzle_clean_horizontal ? i * P : (A/P) * (P - FABS(FMOD((i*P), (2*P)) - P)) );
|
||||
|
||||
do_blocking_move_to_xy(x, y);
|
||||
if (i == 0) do_blocking_move_to_z(start.z);
|
||||
}
|
||||
|
||||
for (int i = (objects << 1); i > -1; i--) {
|
||||
float const x = start.x + ( nozzle_clean_horizontal ? i * P : (A/P) * (P - FABS(FMOD((i*P), (2*P)) - P)) );
|
||||
float const y = start.y + (!nozzle_clean_horizontal ? i * P : (A/P) * (P - FABS(FMOD((i*P), (2*P)) - P)) );
|
||||
|
||||
do_blocking_move_to_xy(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
// Move the nozzle to the initial point
|
||||
do_blocking_move_to_z(initial.z);
|
||||
do_blocking_move_to_xy(initial.x, initial.y);
|
||||
#endif // NOZZLE_CLEAN_GOBACK
|
||||
|
||||
#endif // NOZZLE_CLEAN_FEATURE
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Circular clean pattern
|
||||
* @details Apply a circular cleaning pattern
|
||||
*
|
||||
* @param start point_t defining the middle of circle
|
||||
* @param strokes number of strokes to execute
|
||||
* @param radius radius of circle
|
||||
*/
|
||||
void Nozzle::circle(
|
||||
_UNUSED point_t const &start,
|
||||
_UNUSED point_t const &middle,
|
||||
_UNUSED uint8_t const &strokes,
|
||||
_UNUSED float const &radius
|
||||
) {
|
||||
#if ENABLED(NOZZLE_CLEAN_FEATURE)
|
||||
if (strokes == 0) return;
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
// Store the current coords
|
||||
point_t const initial = {
|
||||
current_position[X_AXIS],
|
||||
current_position[Y_AXIS],
|
||||
current_position[Z_AXIS],
|
||||
current_position[E_AXIS]
|
||||
};
|
||||
#endif // NOZZLE_CLEAN_GOBACK
|
||||
|
||||
if (start.z <= current_position[Z_AXIS]) {
|
||||
// Order of movement is pretty darn important here
|
||||
do_blocking_move_to_xy(start.x, start.y);
|
||||
do_blocking_move_to_z(start.z);
|
||||
}
|
||||
else {
|
||||
do_blocking_move_to_z(start.z);
|
||||
do_blocking_move_to_xy(start.x, start.y);
|
||||
}
|
||||
|
||||
float x, y;
|
||||
for (uint8_t s = 0; s < strokes; s++) {
|
||||
for (uint8_t i = 0; i < NOZZLE_CLEAN_CIRCLE_FN; i++) {
|
||||
x = middle.x + sin((M_2_PI / NOZZLE_CLEAN_CIRCLE_FN) * i) * radius;
|
||||
y = middle.y + cos((M_2_PI / NOZZLE_CLEAN_CIRCLE_FN) * i) * radius;
|
||||
|
||||
do_blocking_move_to_xy(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// Let's be safe
|
||||
do_blocking_move_to_xy(start.x, start.y);
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
// Move the nozzle to the initial point
|
||||
if (start.z <= initial.z) {
|
||||
// As above order is important
|
||||
do_blocking_move_to_z(initial.z);
|
||||
do_blocking_move_to_xy(initial.x, initial.y);
|
||||
}
|
||||
else {
|
||||
do_blocking_move_to_xy(initial.x, initial.y);
|
||||
do_blocking_move_to_z(initial.z);
|
||||
}
|
||||
#endif // NOZZLE_CLEAN_GOBACK
|
||||
|
||||
#endif // NOZZLE_CLEAN_FEATURE
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clean the nozzle
|
||||
* @details Starts the selected clean procedure pattern
|
||||
*
|
||||
* @param pattern one of the available patterns
|
||||
* @param argument depends on the cleaning pattern
|
||||
*/
|
||||
void Nozzle::clean(
|
||||
_UNUSED uint8_t const &pattern,
|
||||
_UNUSED uint8_t const &strokes,
|
||||
_UNUSED float const &radius,
|
||||
_UNUSED uint8_t const &objects
|
||||
) {
|
||||
#if ENABLED(NOZZLE_CLEAN_FEATURE)
|
||||
#if ENABLED(DELTA)
|
||||
if (current_position[Z_AXIS] > delta_clip_start_height)
|
||||
do_blocking_move_to_z(delta_clip_start_height);
|
||||
#endif
|
||||
switch (pattern) {
|
||||
case 1:
|
||||
Nozzle::zigzag(
|
||||
NOZZLE_CLEAN_START_POINT,
|
||||
NOZZLE_CLEAN_END_POINT, strokes, objects);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Nozzle::circle(
|
||||
NOZZLE_CLEAN_START_POINT,
|
||||
NOZZLE_CLEAN_CIRCLE_MIDDLE, strokes, radius);
|
||||
break;
|
||||
|
||||
default:
|
||||
Nozzle::stroke(
|
||||
NOZZLE_CLEAN_START_POINT,
|
||||
NOZZLE_CLEAN_END_POINT, strokes);
|
||||
}
|
||||
#endif // NOZZLE_CLEAN_FEATURE
|
||||
}
|
||||
|
||||
void Nozzle::park(
|
||||
_UNUSED uint8_t const &z_action
|
||||
) {
|
||||
#if ENABLED(NOZZLE_PARK_FEATURE)
|
||||
float const z = current_position[Z_AXIS];
|
||||
point_t const park = NOZZLE_PARK_POINT;
|
||||
|
||||
switch(z_action) {
|
||||
case 1: // force Z-park height
|
||||
do_blocking_move_to_z(park.z);
|
||||
break;
|
||||
|
||||
case 2: // Raise by Z-park height
|
||||
do_blocking_move_to_z(
|
||||
(z + park.z > Z_MAX_POS) ? Z_MAX_POS : z + park.z);
|
||||
break;
|
||||
|
||||
default: // Raise to Z-park height if lower
|
||||
if (current_position[Z_AXIS] < park.z)
|
||||
do_blocking_move_to_z(park.z);
|
||||
}
|
||||
|
||||
do_blocking_move_to_xy(park.x, park.y);
|
||||
|
||||
#endif // NOZZLE_PARK_FEATURE
|
||||
}
|
109
Marlin/src/libs/nozzle.h
Normal file
109
Marlin/src/libs/nozzle.h
Normal file
@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NOZZLE_H__
|
||||
#define __NOZZLE_H__
|
||||
|
||||
#include "Marlin.h"
|
||||
#include "point_t.h"
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_FEATURE)
|
||||
constexpr float nozzle_clean_start_point[4] = NOZZLE_CLEAN_START_POINT,
|
||||
nozzle_clean_end_point[4] = NOZZLE_CLEAN_END_POINT,
|
||||
nozzle_clean_length = FABS(nozzle_clean_start_point[X_AXIS] - nozzle_clean_end_point[X_AXIS]), //abs x size of wipe pad
|
||||
nozzle_clean_height = FABS(nozzle_clean_start_point[Y_AXIS] - nozzle_clean_end_point[Y_AXIS]); //abs y size of wipe pad
|
||||
constexpr bool nozzle_clean_horizontal = nozzle_clean_length >= nozzle_clean_height; //whether to zig-zag horizontally or vertically
|
||||
#endif // NOZZLE_CLEAN_FEATURE
|
||||
|
||||
/**
|
||||
* @brief Nozzle class
|
||||
*
|
||||
* @todo: Do not ignore the end.z value and allow XYZ movements
|
||||
*/
|
||||
class Nozzle {
|
||||
private:
|
||||
/**
|
||||
* @brief Stroke clean pattern
|
||||
* @details Wipes the nozzle back and forth in a linear movement
|
||||
*
|
||||
* @param start point_t defining the starting point
|
||||
* @param end point_t defining the ending point
|
||||
* @param strokes number of strokes to execute
|
||||
*/
|
||||
static void stroke(
|
||||
_UNUSED point_t const &start,
|
||||
_UNUSED point_t const &end,
|
||||
_UNUSED uint8_t const &strokes
|
||||
) _Os;
|
||||
|
||||
/**
|
||||
* @brief Zig-zag clean pattern
|
||||
* @details Apply a zig-zag cleaning pattern
|
||||
*
|
||||
* @param start point_t defining the starting point
|
||||
* @param end point_t defining the ending point
|
||||
* @param strokes number of strokes to execute
|
||||
* @param objects number of objects to create
|
||||
*/
|
||||
static void zigzag(
|
||||
_UNUSED point_t const &start,
|
||||
_UNUSED point_t const &end,
|
||||
_UNUSED uint8_t const &strokes,
|
||||
_UNUSED uint8_t const &objects
|
||||
) _Os;
|
||||
|
||||
/**
|
||||
* @brief Circular clean pattern
|
||||
* @details Apply a circular cleaning pattern
|
||||
*
|
||||
* @param start point_t defining the middle of circle
|
||||
* @param strokes number of strokes to execute
|
||||
* @param radius radius of circle
|
||||
*/
|
||||
static void circle(
|
||||
_UNUSED point_t const &start,
|
||||
_UNUSED point_t const &middle,
|
||||
_UNUSED uint8_t const &strokes,
|
||||
_UNUSED float const &radius
|
||||
) _Os;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Clean the nozzle
|
||||
* @details Starts the selected clean procedure pattern
|
||||
*
|
||||
* @param pattern one of the available patterns
|
||||
* @param argument depends on the cleaning pattern
|
||||
*/
|
||||
static void clean(
|
||||
_UNUSED uint8_t const &pattern,
|
||||
_UNUSED uint8_t const &strokes,
|
||||
_UNUSED float const &radius,
|
||||
_UNUSED uint8_t const &objects = 0
|
||||
) _Os;
|
||||
|
||||
static void park(
|
||||
_UNUSED uint8_t const &z_action
|
||||
) _Os;
|
||||
};
|
||||
|
||||
#endif
|
77
Marlin/src/libs/point_t.h
Normal file
77
Marlin/src/libs/point_t.h
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __POINT_T__
|
||||
#define __POINT_T__
|
||||
|
||||
/**
|
||||
* @brief Cartesian Point
|
||||
* @details Represents a three dimensional point on Cartesian coordinate system,
|
||||
* using an additional fourth dimension for the extrusion length.
|
||||
*
|
||||
* @param x The x-coordinate of the point.
|
||||
* @param y The y-coordinate of the point.
|
||||
* @param z The z-coordinate of the point.
|
||||
* @param e The e-coordinate of the point.
|
||||
*/
|
||||
struct point_t {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float e;
|
||||
|
||||
/**
|
||||
* @brief Two dimensional point constructor
|
||||
*
|
||||
* @param x The x-coordinate of the point.
|
||||
* @param y The y-coordinate of the point.
|
||||
*/
|
||||
point_t(float const x, float const y)
|
||||
: point_t(x, y, NAN, NAN) {}
|
||||
|
||||
/**
|
||||
* @brief Three dimensional point constructor
|
||||
*
|
||||
* @param x The x-coordinate of the point.
|
||||
* @param y The y-coordinate of the point.
|
||||
* @param z The z-coordinate of the point.
|
||||
*/
|
||||
point_t(float const x, float const y, float const z)
|
||||
: point_t(x, y, z, NAN) {}
|
||||
|
||||
/**
|
||||
* @brief Tree dimensional point constructor with extrusion length
|
||||
*
|
||||
* @param x The x-coordinate of the point.
|
||||
* @param y The y-coordinate of the point.
|
||||
* @param z The z-coordinate of the point.
|
||||
* @param e The e-coordinate of the point.
|
||||
*/
|
||||
point_t(float const x, float const y, float const z, float const e) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->e = e;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __POINT_T__
|
57
Marlin/src/libs/private_spi.h
Normal file
57
Marlin/src/libs/private_spi.h
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PRIVATE_SPI_H__
|
||||
#define __PRIVATE_SPI_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "softspi.h"
|
||||
|
||||
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
|
||||
class SPI {
|
||||
static SoftSPI<MisoPin, MosiPin, SckPin> softSPI;
|
||||
public:
|
||||
FORCE_INLINE static void init() { softSPI.begin(); }
|
||||
FORCE_INLINE static void send(uint8_t data) { softSPI.send(data); }
|
||||
FORCE_INLINE static uint8_t receive() { return softSPI.receive(); }
|
||||
};
|
||||
|
||||
|
||||
// Hardware SPI
|
||||
template<>
|
||||
class SPI<MISO_PIN, MOSI_PIN, SCK_PIN> {
|
||||
public:
|
||||
FORCE_INLINE static void init() {
|
||||
OUT_WRITE(SCK_PIN, LOW);
|
||||
OUT_WRITE(MOSI_PIN, HIGH);
|
||||
SET_INPUT(MISO_PIN);
|
||||
WRITE(MISO_PIN, HIGH);
|
||||
}
|
||||
FORCE_INLINE static uint8_t receive() {
|
||||
SPDR = 0;
|
||||
for (;!TEST(SPSR, SPIF););
|
||||
return SPDR;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // __PRIVATE_SPI_H__
|
770
Marlin/src/libs/softspi.h
Normal file
770
Marlin/src/libs/softspi.h
Normal file
@ -0,0 +1,770 @@
|
||||
//https://github.com/niteris/ArduinoSoftSpi
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef __arm__
|
||||
#ifdef CORE_TEENSY
|
||||
//------------------------------------------------------------------------------
|
||||
/** read pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return value read
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
bool fastDigitalRead(uint8_t pin) {
|
||||
return *portInputRegister(pin);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] level value to write
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalWrite(uint8_t pin, bool value) {
|
||||
if (value) {
|
||||
*portSetRegister(pin) = 1;
|
||||
} else {
|
||||
*portClearRegister(pin) = 1;
|
||||
}
|
||||
}
|
||||
#else // CORE_TEENSY
|
||||
//------------------------------------------------------------------------------
|
||||
/** read pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return value read
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
bool fastDigitalRead(uint8_t pin){
|
||||
return g_APinDescription[pin].pPort->PIO_PDSR & g_APinDescription[pin].ulPin;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] level value to write
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalWrite(uint8_t pin, bool value){
|
||||
if(value) {
|
||||
g_APinDescription[pin].pPort->PIO_SODR = g_APinDescription[pin].ulPin;
|
||||
} else {
|
||||
g_APinDescription[pin].pPort->PIO_CODR = g_APinDescription[pin].ulPin;
|
||||
}
|
||||
}
|
||||
#endif // CORE_TEENSY
|
||||
//------------------------------------------------------------------------------
|
||||
inline void fastDigitalToggle(uint8_t pin) {
|
||||
fastDigitalWrite(pin, !fastDigitalRead(pin));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void fastPinMode(uint8_t pin, bool mode) {pinMode(pin, mode);}
|
||||
#else // __arm__
|
||||
#include <avr/io.h>
|
||||
#include <util/atomic.h>
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class pin_map_t
|
||||
* @brief struct for mapping digital pins
|
||||
*/
|
||||
struct pin_map_t {
|
||||
volatile uint8_t* ddr; /**< address of DDR for this pin */
|
||||
volatile uint8_t* pin; /**< address of PIN for this pin */
|
||||
volatile uint8_t* port; /**< address of PORT for this pin */
|
||||
uint8_t bit; /**< bit number for this pin */
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(__AVR_ATmega168__)\
|
||||
||defined(__AVR_ATmega168P__)\
|
||||
||defined(__AVR_ATmega328P__)
|
||||
// 168 and 328 Arduinos
|
||||
const static pin_map_t pinMap[] = {
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 8
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 9
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 10
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 11
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 12
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 13
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 14
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 15
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 16
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 17
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 18
|
||||
{&DDRC, &PINC, &PORTC, 5} // C5 19
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#elif defined(__AVR_ATmega1280__)\
|
||||
|| defined(__AVR_ATmega2560__)
|
||||
// Mega
|
||||
static const pin_map_t pinMap[] = {
|
||||
{&DDRE, &PINE, &PORTE, 0}, // E0 0
|
||||
{&DDRE, &PINE, &PORTE, 1}, // E1 1
|
||||
{&DDRE, &PINE, &PORTE, 4}, // E4 2
|
||||
{&DDRE, &PINE, &PORTE, 5}, // E5 3
|
||||
{&DDRG, &PING, &PORTG, 5}, // G5 4
|
||||
{&DDRE, &PINE, &PORTE, 3}, // E3 5
|
||||
{&DDRH, &PINH, &PORTH, 3}, // H3 6
|
||||
{&DDRH, &PINH, &PORTH, 4}, // H4 7
|
||||
{&DDRH, &PINH, &PORTH, 5}, // H5 8
|
||||
{&DDRH, &PINH, &PORTH, 6}, // H6 9
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 10
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 11
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 12
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 13
|
||||
{&DDRJ, &PINJ, &PORTJ, 1}, // J1 14
|
||||
{&DDRJ, &PINJ, &PORTJ, 0}, // J0 15
|
||||
{&DDRH, &PINH, &PORTH, 1}, // H1 16
|
||||
{&DDRH, &PINH, &PORTH, 0}, // H0 17
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 18
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 19
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 20
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 21
|
||||
{&DDRA, &PINA, &PORTA, 0}, // A0 22
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 23
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 24
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 25
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 26
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 27
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 28
|
||||
{&DDRA, &PINA, &PORTA, 7}, // A7 29
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 30
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 31
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 32
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 33
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 34
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 35
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 36
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 37
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 38
|
||||
{&DDRG, &PING, &PORTG, 2}, // G2 39
|
||||
{&DDRG, &PING, &PORTG, 1}, // G1 40
|
||||
{&DDRG, &PING, &PORTG, 0}, // G0 41
|
||||
{&DDRL, &PINL, &PORTL, 7}, // L7 42
|
||||
{&DDRL, &PINL, &PORTL, 6}, // L6 43
|
||||
{&DDRL, &PINL, &PORTL, 5}, // L5 44
|
||||
{&DDRL, &PINL, &PORTL, 4}, // L4 45
|
||||
{&DDRL, &PINL, &PORTL, 3}, // L3 46
|
||||
{&DDRL, &PINL, &PORTL, 2}, // L2 47
|
||||
{&DDRL, &PINL, &PORTL, 1}, // L1 48
|
||||
{&DDRL, &PINL, &PORTL, 0}, // L0 49
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 50
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 51
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 52
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 53
|
||||
{&DDRF, &PINF, &PORTF, 0}, // F0 54
|
||||
{&DDRF, &PINF, &PORTF, 1}, // F1 55
|
||||
{&DDRF, &PINF, &PORTF, 2}, // F2 56
|
||||
{&DDRF, &PINF, &PORTF, 3}, // F3 57
|
||||
{&DDRF, &PINF, &PORTF, 4}, // F4 58
|
||||
{&DDRF, &PINF, &PORTF, 5}, // F5 59
|
||||
{&DDRF, &PINF, &PORTF, 6}, // F6 60
|
||||
{&DDRF, &PINF, &PORTF, 7}, // F7 61
|
||||
{&DDRK, &PINK, &PORTK, 0}, // K0 62
|
||||
{&DDRK, &PINK, &PORTK, 1}, // K1 63
|
||||
{&DDRK, &PINK, &PORTK, 2}, // K2 64
|
||||
{&DDRK, &PINK, &PORTK, 3}, // K3 65
|
||||
{&DDRK, &PINK, &PORTK, 4}, // K4 66
|
||||
{&DDRK, &PINK, &PORTK, 5}, // K5 67
|
||||
{&DDRK, &PINK, &PORTK, 6}, // K6 68
|
||||
{&DDRK, &PINK, &PORTK, 7}, // K7 69
|
||||
|
||||
//pins_MIGHTYBOARD_REVE.h
|
||||
{&DDRG, &PING, &PORTG, 4}, // G4 70
|
||||
{&DDRG, &PING, &PORTG, 3}, // G3 71
|
||||
{&DDRJ, &PINJ, &PORTJ, 2}, // J2 72
|
||||
{&DDRJ, &PINJ, &PORTJ, 3}, // J3 73
|
||||
{&DDRJ, &PINJ, &PORTJ, 7}, // J7 74
|
||||
{&DDRJ, &PINJ, &PORTJ, 4}, // J4 75
|
||||
{&DDRJ, &PINJ, &PORTJ, 5}, // J5 76
|
||||
{&DDRJ, &PINJ, &PORTJ, 6}, // J6 77
|
||||
{&DDRE, &PINE, &PORTE, 2}, // E2 78
|
||||
{&DDRE, &PINE, &PORTE, 6} // E6 79
|
||||
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#elif defined(__AVR_ATmega1284P__)\
|
||||
|| defined(__AVR_ATmega1284__)\
|
||||
|| defined(__AVR_ATmega644P__)\
|
||||
|| defined(__AVR_ATmega644__)\
|
||||
|| defined(__AVR_ATmega64__)\
|
||||
|| defined(__AVR_ATmega32__)\
|
||||
|| defined(__AVR_ATmega324__)\
|
||||
|| defined(__AVR_ATmega16__)
|
||||
|
||||
#if defined(VARIANT_MIGHTY)
|
||||
// Mighty Layout
|
||||
static const pin_map_t pinMap[] = {
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 4
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 5
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 6
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 7
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 8
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 9
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 10
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 11
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 12
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 13
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 14
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 15
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 16
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 17
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 18
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 19
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 20
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 21
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 22
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 23
|
||||
{&DDRA, &PINA, &PORTA, 0}, // A0 24
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 25
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 26
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 27
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 28
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 29
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 30
|
||||
{&DDRA, &PINA, &PORTA, 7} // A7 31
|
||||
};
|
||||
#elif defined(VARIANT_BOBUINO)
|
||||
// Bobuino Layout
|
||||
static const pin_map_t pinMap[] = {
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 4
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 5
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 6
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 7
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 8
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 9
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 10
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 11
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 12
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 13
|
||||
{&DDRA, &PINA, &PORTA, 7}, // A7 14
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 15
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 16
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 17
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 18
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 19
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 20
|
||||
{&DDRA, &PINA, &PORTA, 0}, // A0 21
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 22
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 23
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 24
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 25
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 26
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 27
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 28
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 29
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 30
|
||||
{&DDRD, &PIND, &PORTD, 7} // D7 31
|
||||
};
|
||||
#elif defined(VARIANT_STANDARD)
|
||||
// Standard Layout
|
||||
static const pin_map_t pinMap[] = {
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 4
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 5
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 6
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 7
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 8
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 9
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 10
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 11
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 12
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 13
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 14
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 15
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 16
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 17
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 18
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 19
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 20
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 21
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 22
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 23
|
||||
{&DDRA, &PINA, &PORTA, 7}, // A7 24
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 25
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 26
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 27
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 28
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 29
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 30
|
||||
{&DDRA, &PINA, &PORTA, 0} // A0 31
|
||||
};
|
||||
#else // VARIANT_MIGHTY
|
||||
#error Undefined variant 1284, 644, 324, 64, 32
|
||||
#endif // VARIANT_MIGHTY
|
||||
//------------------------------------------------------------------------------
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
#ifdef CORE_TEENSY
|
||||
// Teensy 2.0
|
||||
static const pin_map_t pinMap[] = {
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 4
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 5
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 6
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 7
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 8
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 9
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 10
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 11
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 12
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 13
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 14
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 15
|
||||
{&DDRF, &PINF, &PORTF, 7}, // F7 16
|
||||
{&DDRF, &PINF, &PORTF, 6}, // F6 17
|
||||
{&DDRF, &PINF, &PORTF, 5}, // F5 18
|
||||
{&DDRF, &PINF, &PORTF, 4}, // F4 19
|
||||
{&DDRF, &PINF, &PORTF, 1}, // F1 20
|
||||
{&DDRF, &PINF, &PORTF, 0}, // F0 21
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 22
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 23
|
||||
{&DDRE, &PINE, &PORTE, 6} // E6 24
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#else // CORE_TEENSY
|
||||
// Leonardo
|
||||
static const pin_map_t pinMap[] = {
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 0
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 1
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 2
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 3
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 5
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 6
|
||||
{&DDRE, &PINE, &PORTE, 6}, // E6 7
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 8
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 9
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 10
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 11
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 12
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 13
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 14
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 15
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 16
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 17
|
||||
{&DDRF, &PINF, &PORTF, 7}, // F7 18
|
||||
{&DDRF, &PINF, &PORTF, 6}, // F6 19
|
||||
{&DDRF, &PINF, &PORTF, 5}, // F5 20
|
||||
{&DDRF, &PINF, &PORTF, 4}, // F4 21
|
||||
{&DDRF, &PINF, &PORTF, 1}, // F1 22
|
||||
{&DDRF, &PINF, &PORTF, 0}, // F0 23
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 24
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 25
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 26
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 27
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 28
|
||||
{&DDRD, &PIND, &PORTD, 6} // D6 29
|
||||
};
|
||||
#endif // CORE_TEENSY
|
||||
//------------------------------------------------------------------------------
|
||||
#elif defined(__AVR_AT90USB646__)\
|
||||
|| defined(__AVR_AT90USB1286__)
|
||||
// Teensy++ 1.0 & 2.0
|
||||
static const pin_map_t pinMap[] = {
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
||||
{&DDRE, &PINE, &PORTE, 0}, // E0 8
|
||||
{&DDRE, &PINE, &PORTE, 1}, // E1 9
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 10
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 11
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 12
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 13
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 14
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 15
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 16
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 17
|
||||
{&DDRE, &PINE, &PORTE, 6}, // E6 18
|
||||
{&DDRE, &PINE, &PORTE, 7}, // E7 19
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 20
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 21
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 22
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 23
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 24
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 25
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 26
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 27
|
||||
{&DDRA, &PINA, &PORTA, 0}, // A0 28
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 29
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 30
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 31
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 32
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 33
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 34
|
||||
{&DDRA, &PINA, &PORTA, 7}, // A7 35
|
||||
{&DDRE, &PINE, &PORTE, 4}, // E4 36
|
||||
{&DDRE, &PINE, &PORTE, 5}, // E5 37
|
||||
{&DDRF, &PINF, &PORTF, 0}, // F0 38
|
||||
{&DDRF, &PINF, &PORTF, 1}, // F1 39
|
||||
{&DDRF, &PINF, &PORTF, 2}, // F2 40
|
||||
{&DDRF, &PINF, &PORTF, 3}, // F3 41
|
||||
{&DDRF, &PINF, &PORTF, 4}, // F4 42
|
||||
{&DDRF, &PINF, &PORTF, 5}, // F5 43
|
||||
{&DDRF, &PINF, &PORTF, 6}, // F6 44
|
||||
{&DDRF, &PINF, &PORTF, 7} // F7 45
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#else // CPU type
|
||||
#error unknown CPU type
|
||||
#endif // CPU type
|
||||
//------------------------------------------------------------------------------
|
||||
/** count of pins */
|
||||
static const uint8_t digitalPinCount = sizeof(pinMap)/sizeof(pin_map_t);
|
||||
//==============================================================================
|
||||
/** generate bad pin number error */
|
||||
void badPinNumber(void)
|
||||
__attribute__((error("Pin number is too large or not a constant")));
|
||||
//------------------------------------------------------------------------------
|
||||
/** Check for valid pin number
|
||||
* @param[in] pin Number of pin to be checked.
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void badPinCheck(uint8_t pin) {
|
||||
if (!__builtin_constant_p(pin) || pin >= digitalPinCount) {
|
||||
badPinNumber();
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** fast write helper
|
||||
* @param[in] address I/O register address
|
||||
* @param[in] bit bit number to write
|
||||
* @param[in] level value for bit
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) {
|
||||
uint8_t oldSREG;
|
||||
if (address > (uint8_t*)0x5F) {
|
||||
oldSREG = SREG;
|
||||
cli();
|
||||
}
|
||||
if (level) {
|
||||
*address |= 1 << bit;
|
||||
} else {
|
||||
*address &= ~(1 << bit);
|
||||
}
|
||||
if (address > (uint8_t*)0x5F) {
|
||||
SREG = oldSREG;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** read pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return value read
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
bool fastDigitalRead(uint8_t pin) {
|
||||
badPinCheck(pin);
|
||||
return (*pinMap[pin].pin >> pinMap[pin].bit) & 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** toggle a pin
|
||||
* @param[in] pin Arduino pin number
|
||||
*
|
||||
* If the pin is in output mode toggle the pin level.
|
||||
* If the pin is in input mode toggle the state of the 20K pullup.
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalToggle(uint8_t pin) {
|
||||
badPinCheck(pin);
|
||||
if (pinMap[pin].pin > (uint8_t*)0x5F) {
|
||||
// must write bit to high address port
|
||||
*pinMap[pin].pin = 1 << pinMap[pin].bit;
|
||||
} else {
|
||||
// will compile to sbi and PIN register will not be read.
|
||||
*pinMap[pin].pin |= 1 << pinMap[pin].bit;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] level value to write
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalWrite(uint8_t pin, bool level) {
|
||||
badPinCheck(pin);
|
||||
fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** set pin mode
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] mode if true set output mode else input mode
|
||||
*
|
||||
* fastPinMode does not enable or disable the 20K pullup for input mode.
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastPinMode(uint8_t pin, bool mode) {
|
||||
badPinCheck(pin);
|
||||
fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode);
|
||||
}
|
||||
|
||||
#endif // __arm__
|
||||
//------------------------------------------------------------------------------
|
||||
/** set pin configuration
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] mode If true set output mode else input mode
|
||||
* @param[in] level If mode is output, set level high/low.
|
||||
* If mode is input, enable or disable the pin's 20K pullup.
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastPinConfig(uint8_t pin, bool mode, bool level) {
|
||||
fastPinMode(pin, mode);
|
||||
fastDigitalWrite(pin, level);
|
||||
}
|
||||
//==============================================================================
|
||||
/**
|
||||
* @class DigitalPin
|
||||
* @brief Fast digital port I/O
|
||||
*/
|
||||
template<uint8_t PinNumber>
|
||||
class DigitalPin {
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Constructor */
|
||||
DigitalPin() {}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Constructor
|
||||
* @param[in] pinMode if true set output mode else input mode.
|
||||
*/
|
||||
explicit DigitalPin(bool pinMode) {
|
||||
mode(pinMode);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Constructor
|
||||
* @param[in] mode If true set output mode else input mode
|
||||
* @param[in] level If mode is output, set level high/low.
|
||||
* If mode is input, enable or disable the pin's 20K pullup.
|
||||
*/
|
||||
DigitalPin(bool mode, bool level) {
|
||||
config(mode, level);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Asignment operator
|
||||
* @param[in] value If true set the pin's level high else set the
|
||||
* pin's level low.
|
||||
*
|
||||
* @return This DigitalPin instance.
|
||||
*/
|
||||
inline DigitalPin & operator = (bool value) __attribute__((always_inline)) {
|
||||
write(value);
|
||||
return *this;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Parenthesis operator
|
||||
* @return Pin's level
|
||||
*/
|
||||
inline operator bool () const __attribute__((always_inline)) {
|
||||
return read();
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** set pin configuration
|
||||
* @param[in] mode If true set output mode else input mode
|
||||
* @param[in] level If mode is output, set level high/low.
|
||||
* If mode is input, enable or disable the pin's 20K pullup.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void config(bool mode, bool level) {
|
||||
fastPinConfig(PinNumber, mode, level);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set pin level high if output mode or enable 20K pullup if input mode.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void high() {write(true);}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set pin level low if output mode or disable 20K pullup if input mode.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void low() {write(false);}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set pin mode
|
||||
* @param[in] pinMode if true set output mode else input mode.
|
||||
*
|
||||
* mode() does not enable or disable the 20K pullup for input mode.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void mode(bool pinMode) {
|
||||
fastPinMode(PinNumber, pinMode);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** @return Pin's level */
|
||||
inline __attribute__((always_inline))
|
||||
bool read() const {
|
||||
return fastDigitalRead(PinNumber);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** toggle a pin
|
||||
*
|
||||
* If the pin is in output mode toggle the pin's level.
|
||||
* If the pin is in input mode toggle the state of the 20K pullup.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void toggle() {
|
||||
fastDigitalToggle(PinNumber);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write the pin's level.
|
||||
* @param[in] value If true set the pin's level high else set the
|
||||
* pin's level low.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void write(bool value) {
|
||||
fastDigitalWrite(PinNumber, value);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** Nop for timing. */
|
||||
#define nop asm volatile ("nop\n\t")
|
||||
//------------------------------------------------------------------------------
|
||||
/** Pin Mode for MISO is input.*/
|
||||
const bool MISO_MODE = false;
|
||||
/** Pullups disabled for MISO are disabled. */
|
||||
const bool MISO_LEVEL = false;
|
||||
/** Pin Mode for MOSI is output.*/
|
||||
const bool MOSI_MODE = true;
|
||||
/** Pin Mode for SCK is output. */
|
||||
const bool SCK_MODE = true;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SoftSPI
|
||||
* @brief Fast software SPI.
|
||||
*/
|
||||
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
|
||||
class SoftSPI {
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Initialize SoftSPI pins. */
|
||||
void begin() {
|
||||
fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
|
||||
fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
|
||||
fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Soft SPI receive byte.
|
||||
* @return Data byte received.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
uint8_t receive() {
|
||||
uint8_t data = 0;
|
||||
receiveBit(7, &data);
|
||||
receiveBit(6, &data);
|
||||
receiveBit(5, &data);
|
||||
receiveBit(4, &data);
|
||||
receiveBit(3, &data);
|
||||
receiveBit(2, &data);
|
||||
receiveBit(1, &data);
|
||||
receiveBit(0, &data);
|
||||
return data;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Soft SPI send byte.
|
||||
* @param[in] data Data byte to send.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void send(uint8_t data) {
|
||||
sendBit(7, data);
|
||||
sendBit(6, data);
|
||||
sendBit(5, data);
|
||||
sendBit(4, data);
|
||||
sendBit(3, data);
|
||||
sendBit(2, data);
|
||||
sendBit(1, data);
|
||||
sendBit(0, data);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Soft SPI transfer byte.
|
||||
* @param[in] txData Data byte to send.
|
||||
* @return Data byte received.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
uint8_t transfer(uint8_t txData) {
|
||||
uint8_t rxData = 0;
|
||||
transferBit(7, &rxData, txData);
|
||||
transferBit(6, &rxData, txData);
|
||||
transferBit(5, &rxData, txData);
|
||||
transferBit(4, &rxData, txData);
|
||||
transferBit(3, &rxData, txData);
|
||||
transferBit(2, &rxData, txData);
|
||||
transferBit(1, &rxData, txData);
|
||||
transferBit(0, &rxData, txData);
|
||||
return rxData;
|
||||
}
|
||||
|
||||
private:
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;}
|
||||
inline __attribute__((always_inline))
|
||||
bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
|
||||
inline __attribute__((always_inline))
|
||||
void receiveBit(uint8_t bit, uint8_t* data) {
|
||||
if (MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
}
|
||||
nop;
|
||||
nop;
|
||||
fastDigitalWrite(SckPin,
|
||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||
if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
|
||||
if (!MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void sendBit(uint8_t bit, uint8_t data) {
|
||||
if (MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
}
|
||||
fastDigitalWrite(MosiPin, data & (1 << bit));
|
||||
fastDigitalWrite(SckPin,
|
||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||
nop;
|
||||
nop;
|
||||
if (!MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
|
||||
if (MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
}
|
||||
fastDigitalWrite(MosiPin, txData & (1 << bit));
|
||||
fastDigitalWrite(SckPin,
|
||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||
if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
|
||||
if (!MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
|
106
Marlin/src/libs/stopwatch.cpp
Normal file
106
Marlin/src/libs/stopwatch.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Marlin.h"
|
||||
#include "stopwatch.h"
|
||||
|
||||
Stopwatch::Stopwatch() {
|
||||
this->reset();
|
||||
}
|
||||
|
||||
bool Stopwatch::stop() {
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
Stopwatch::debug(PSTR("stop"));
|
||||
#endif
|
||||
|
||||
if (this->isRunning() || this->isPaused()) {
|
||||
this->state = STOPPED;
|
||||
this->stopTimestamp = millis();
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool Stopwatch::pause() {
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
Stopwatch::debug(PSTR("pause"));
|
||||
#endif
|
||||
|
||||
if (this->isRunning()) {
|
||||
this->state = PAUSED;
|
||||
this->stopTimestamp = millis();
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool Stopwatch::start() {
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
Stopwatch::debug(PSTR("start"));
|
||||
#endif
|
||||
|
||||
if (!this->isRunning()) {
|
||||
if (this->isPaused()) this->accumulator = this->duration();
|
||||
else this->reset();
|
||||
|
||||
this->state = RUNNING;
|
||||
this->startTimestamp = millis();
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
void Stopwatch::reset() {
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
Stopwatch::debug(PSTR("reset"));
|
||||
#endif
|
||||
|
||||
this->state = STOPPED;
|
||||
this->startTimestamp = 0;
|
||||
this->stopTimestamp = 0;
|
||||
this->accumulator = 0;
|
||||
}
|
||||
|
||||
bool Stopwatch::isRunning() {
|
||||
return (this->state == RUNNING) ? true : false;
|
||||
}
|
||||
|
||||
bool Stopwatch::isPaused() {
|
||||
return (this->state == PAUSED) ? true : false;
|
||||
}
|
||||
|
||||
millis_t Stopwatch::duration() {
|
||||
return (((this->isRunning()) ? millis() : this->stopTimestamp)
|
||||
- this->startTimestamp) / 1000UL + this->accumulator;
|
||||
}
|
||||
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
|
||||
void Stopwatch::debug(const char func[]) {
|
||||
if (DEBUGGING(INFO)) {
|
||||
SERIAL_ECHOPGM("Stopwatch::");
|
||||
serialprintPGM(func);
|
||||
SERIAL_ECHOLNPGM("()");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
117
Marlin/src/libs/stopwatch.h
Normal file
117
Marlin/src/libs/stopwatch.h
Normal file
@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STOPWATCH_H
|
||||
#define STOPWATCH_H
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
// Print debug messages with M111 S2 (Uses 156 bytes of PROGMEM)
|
||||
//#define DEBUG_STOPWATCH
|
||||
|
||||
/**
|
||||
* @brief Stopwatch class
|
||||
* @details This class acts as a timer proving stopwatch functionality including
|
||||
* the ability to pause the running time counter.
|
||||
*/
|
||||
class Stopwatch {
|
||||
private:
|
||||
enum State {
|
||||
STOPPED,
|
||||
RUNNING,
|
||||
PAUSED
|
||||
};
|
||||
|
||||
Stopwatch::State state;
|
||||
millis_t accumulator;
|
||||
millis_t startTimestamp;
|
||||
millis_t stopTimestamp;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Class constructor
|
||||
*/
|
||||
Stopwatch();
|
||||
|
||||
/**
|
||||
* @brief Stops the stopwatch
|
||||
* @details Stops the running timer, it will silently ignore the request if
|
||||
* no timer is currently running.
|
||||
* @return true is method was successful
|
||||
*/
|
||||
bool stop();
|
||||
|
||||
/**
|
||||
* @brief Pause the stopwatch
|
||||
* @details Pauses the running timer, it will silently ignore the request if
|
||||
* no timer is currently running.
|
||||
* @return true is method was successful
|
||||
*/
|
||||
bool pause();
|
||||
|
||||
/**
|
||||
* @brief Starts the stopwatch
|
||||
* @details Starts the timer, it will silently ignore the request if the
|
||||
* timer is already running.
|
||||
* @return true is method was successful
|
||||
*/
|
||||
bool start();
|
||||
|
||||
/**
|
||||
* @brief Resets the stopwatch
|
||||
* @details Resets all settings to their default values.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* @brief Checks if the timer is running
|
||||
* @details Returns true if the timer is currently running, false otherwise.
|
||||
* @return true if stopwatch is running
|
||||
*/
|
||||
bool isRunning();
|
||||
|
||||
/**
|
||||
* @brief Checks if the timer is paused
|
||||
* @details Returns true if the timer is currently paused, false otherwise.
|
||||
* @return true if stopwatch is paused
|
||||
*/
|
||||
bool isPaused();
|
||||
|
||||
/**
|
||||
* @brief Gets the running time
|
||||
* @details Returns the total number of seconds the timer has been running.
|
||||
* @return the delta since starting the stopwatch
|
||||
*/
|
||||
millis_t duration();
|
||||
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
|
||||
/**
|
||||
* @brief Prints a debug message
|
||||
* @details Prints a simple debug message "Stopwatch::function"
|
||||
*/
|
||||
static void debug(const char func[]);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // STOPWATCH_H
|
160
Marlin/src/libs/vector_3.cpp
Normal file
160
Marlin/src/libs/vector_3.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
vector_3.cpp - Vector library for bed leveling
|
||||
Copyright (c) 2012 Lars Brubaker. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <math.h>
|
||||
#include "Marlin.h"
|
||||
|
||||
#if HAS_ABL
|
||||
#include "vector_3.h"
|
||||
|
||||
vector_3::vector_3() : x(0), y(0), z(0) { }
|
||||
|
||||
vector_3::vector_3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) { }
|
||||
|
||||
vector_3 vector_3::cross(vector_3 left, vector_3 right) {
|
||||
return vector_3(left.y * right.z - left.z * right.y,
|
||||
left.z * right.x - left.x * right.z,
|
||||
left.x * right.y - left.y * right.x);
|
||||
}
|
||||
|
||||
vector_3 vector_3::operator+(vector_3 v) { return vector_3((x + v.x), (y + v.y), (z + v.z)); }
|
||||
vector_3 vector_3::operator-(vector_3 v) { return vector_3((x - v.x), (y - v.y), (z - v.z)); }
|
||||
|
||||
vector_3 vector_3::get_normal() {
|
||||
vector_3 normalized = vector_3(x, y, z);
|
||||
normalized.normalize();
|
||||
return normalized;
|
||||
}
|
||||
|
||||
float vector_3::get_length() { return SQRT(sq(x) + sq(y) + sq(z)); }
|
||||
|
||||
void vector_3::normalize() {
|
||||
const float inv_length = 1.0 / get_length();
|
||||
x *= inv_length;
|
||||
y *= inv_length;
|
||||
z *= inv_length;
|
||||
}
|
||||
|
||||
void vector_3::apply_rotation(matrix_3x3 matrix) {
|
||||
const float resultX = x * matrix.matrix[3 * 0 + 0] + y * matrix.matrix[3 * 1 + 0] + z * matrix.matrix[3 * 2 + 0],
|
||||
resultY = x * matrix.matrix[3 * 0 + 1] + y * matrix.matrix[3 * 1 + 1] + z * matrix.matrix[3 * 2 + 1],
|
||||
resultZ = x * matrix.matrix[3 * 0 + 2] + y * matrix.matrix[3 * 1 + 2] + z * matrix.matrix[3 * 2 + 2];
|
||||
x = resultX;
|
||||
y = resultY;
|
||||
z = resultZ;
|
||||
}
|
||||
|
||||
void vector_3::debug(const char * const title) {
|
||||
serialprintPGM(title);
|
||||
SERIAL_PROTOCOLPGM(" x: ");
|
||||
SERIAL_PROTOCOL_F(x, 6);
|
||||
SERIAL_PROTOCOLPGM(" y: ");
|
||||
SERIAL_PROTOCOL_F(y, 6);
|
||||
SERIAL_PROTOCOLPGM(" z: ");
|
||||
SERIAL_PROTOCOL_F(z, 6);
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
void apply_rotation_xyz(matrix_3x3 matrix, float &x, float &y, float &z) {
|
||||
vector_3 vector = vector_3(x, y, z);
|
||||
vector.apply_rotation(matrix);
|
||||
x = vector.x;
|
||||
y = vector.y;
|
||||
z = vector.z;
|
||||
}
|
||||
|
||||
matrix_3x3 matrix_3x3::create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2) {
|
||||
//row_0.debug(PSTR("row_0"));
|
||||
//row_1.debug(PSTR("row_1"));
|
||||
//row_2.debug(PSTR("row_2"));
|
||||
matrix_3x3 new_matrix;
|
||||
new_matrix.matrix[0] = row_0.x; new_matrix.matrix[1] = row_0.y; new_matrix.matrix[2] = row_0.z;
|
||||
new_matrix.matrix[3] = row_1.x; new_matrix.matrix[4] = row_1.y; new_matrix.matrix[5] = row_1.z;
|
||||
new_matrix.matrix[6] = row_2.x; new_matrix.matrix[7] = row_2.y; new_matrix.matrix[8] = row_2.z;
|
||||
//new_matrix.debug(PSTR("new_matrix"));
|
||||
return new_matrix;
|
||||
}
|
||||
|
||||
void matrix_3x3::set_to_identity() {
|
||||
matrix[0] = 1; matrix[1] = 0; matrix[2] = 0;
|
||||
matrix[3] = 0; matrix[4] = 1; matrix[5] = 0;
|
||||
matrix[6] = 0; matrix[7] = 0; matrix[8] = 1;
|
||||
}
|
||||
|
||||
matrix_3x3 matrix_3x3::create_look_at(vector_3 target) {
|
||||
vector_3 z_row = target.get_normal();
|
||||
vector_3 x_row = vector_3(1, 0, -target.x / target.z).get_normal();
|
||||
vector_3 y_row = vector_3::cross(z_row, x_row).get_normal();
|
||||
|
||||
// x_row.debug(PSTR("x_row"));
|
||||
// y_row.debug(PSTR("y_row"));
|
||||
// z_row.debug(PSTR("z_row"));
|
||||
|
||||
// create the matrix already correctly transposed
|
||||
matrix_3x3 rot = matrix_3x3::create_from_rows(x_row, y_row, z_row);
|
||||
|
||||
// rot.debug(PSTR("rot"));
|
||||
return rot;
|
||||
}
|
||||
|
||||
matrix_3x3 matrix_3x3::transpose(matrix_3x3 original) {
|
||||
matrix_3x3 new_matrix;
|
||||
new_matrix.matrix[0] = original.matrix[0]; new_matrix.matrix[1] = original.matrix[3]; new_matrix.matrix[2] = original.matrix[6];
|
||||
new_matrix.matrix[3] = original.matrix[1]; new_matrix.matrix[4] = original.matrix[4]; new_matrix.matrix[5] = original.matrix[7];
|
||||
new_matrix.matrix[6] = original.matrix[2]; new_matrix.matrix[7] = original.matrix[5]; new_matrix.matrix[8] = original.matrix[8];
|
||||
return new_matrix;
|
||||
}
|
||||
|
||||
void matrix_3x3::debug(const char * const title) {
|
||||
serialprintPGM(title);
|
||||
uint8_t count = 0;
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
for (uint8_t j = 0; j < 3; j++) {
|
||||
if (matrix[count] >= 0.0) SERIAL_PROTOCOLCHAR('+');
|
||||
SERIAL_PROTOCOL_F(matrix[count], 6);
|
||||
SERIAL_PROTOCOLCHAR(' ');
|
||||
count++;
|
||||
}
|
||||
SERIAL_EOL();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_ABL
|
||||
|
83
Marlin/src/libs/vector_3.h
Normal file
83
Marlin/src/libs/vector_3.h
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
vector_3.cpp - Vector library for bed leveling
|
||||
Copyright (c) 2012 Lars Brubaker. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef VECTOR_3_H
|
||||
#define VECTOR_3_H
|
||||
|
||||
#if HAS_ABL
|
||||
|
||||
class matrix_3x3;
|
||||
|
||||
struct vector_3 {
|
||||
float x, y, z;
|
||||
|
||||
vector_3();
|
||||
vector_3(float x, float y, float z);
|
||||
|
||||
static vector_3 cross(vector_3 a, vector_3 b);
|
||||
|
||||
vector_3 operator+(vector_3 v);
|
||||
vector_3 operator-(vector_3 v);
|
||||
void normalize();
|
||||
float get_length();
|
||||
vector_3 get_normal();
|
||||
|
||||
void debug(const char * const title);
|
||||
|
||||
void apply_rotation(matrix_3x3 matrix);
|
||||
};
|
||||
|
||||
struct matrix_3x3 {
|
||||
float matrix[9];
|
||||
|
||||
static matrix_3x3 create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2);
|
||||
static matrix_3x3 create_look_at(vector_3 target);
|
||||
static matrix_3x3 transpose(matrix_3x3 original);
|
||||
|
||||
void set_to_identity();
|
||||
|
||||
void debug(const char * const title);
|
||||
};
|
||||
|
||||
|
||||
void apply_rotation_xyz(matrix_3x3 rotationMatrix, float &x, float &y, float &z);
|
||||
|
||||
#endif // HAS_ABL
|
||||
#endif // VECTOR_3_H
|
Reference in New Issue
Block a user