Commit 45cf718e authored by MagoKimbra's avatar MagoKimbra

Merge remote-tracking branch 'refs/remotes/origin/master' into dev

parents 47d4feb6 cc967a46
......@@ -107,9 +107,6 @@
*****************************************************************************************/
//#define Z_PROBE_ENDSTOP
// Uncomment to enable autocalibration debug messages
#define DEBUG_MESSAGES
// Speed for autocalibration travel and probing moves
#define AUTOCAL_TRAVELRATE 100 // mm/sec
#define AUTOCAL_PROBERATE 50 // mm/sec
......
......@@ -32,6 +32,7 @@
* MOTION FEATURES:
* - Software endstops
* - Endstops only for homing
* - Abort on endstop hit feature
* - R/C Servo
* - Late Z axis
* - Ahead slowdown
......@@ -580,19 +581,38 @@
**************************************************************************/
#define SOFTWARE_MIN_ENDSTOPS true // If true, axis won't move to coordinates less than HOME_POS.
#define SOFTWARE_MAX_ENDSTOPS true // If true, axis won't move to coordinates greater than the defined lengths below.
/***********************************************************************/
/**************************************************************************/
/**************************************************************************
*********************** Endstops only for homing *************************
**************************************************************************
* *
* If defined the endstops will only be used for homing *
* *
**************************************************************************/
#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing
/***********************************************************************/
#define ENDSTOPS_ONLY_FOR_HOMING
/**************************************************************************/
/***********************************************************************
**************************** R/C Servo ********************************
***********************************************************************/
/**************************************************************************
******************** Abort on endstop hit feature ************************
**************************************************************************
* *
* This option allows you to abort printing when any endstop is triggered.*
* This feature must be enabled with "M540 S1" or from the LCD menu or *
* by define ABORT ON ENDSTOP HIT INIT true. *
* To have any effect, endstops must be enabled during SD printing. *
* With ENDSTOPS ONLY FOR HOMING you must send "M120" to enable endstops. *
* *
**************************************************************************/
//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
//#define ABORT_ON_ENDSTOP_HIT_INIT true
/**************************************************************************
****************************** R/C Servo *********************************
**************************************************************************/
//#define ENABLE_SERVOS
// Number of servos
// If you select a configuration below, this will receive a default value and does not need to be set manually
......@@ -621,7 +641,7 @@
// 300ms is a good value but you can try less delay.
// If the servo can't reach the requested position, increase it.
#define SERVO_DEACTIVATION_DELAY 300
/***********************************************************************/
/**************************************************************************/
/***********************************************************************
......@@ -1026,12 +1046,6 @@
// This allows hosts to request long names for files and folders with M33
//#define LONG_FILENAME_HOST_SUPPORT
// This option allows you to abort SD printing when any endstop is triggered.
// This feature must be enabled with "M540 S1" or from the LCD menu.
// To have any effect, endstops must be enabled during SD printing.
// With ENDSTOPS_ONLY_FOR_HOMING you must send "M120" to enable endstops.
//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
// This enable the firmware to write some configuration that require frequent update, on the SD card
//#define SD_SETTINGS // Uncomment to enable
#define SD_CFG_SECONDS 300 // seconds between update
......
#ifndef CONFIGURATION_VERSION_H
#define CONFIGURATION_VERSION_H
#define BUILD_VERSION "MarlinKimbra 4.2.3 dev"
#define SHORT_BUILD_VERSION "4.2.3 dev"
#define BUILD_VERSION "MarlinKimbra 4.2.4 dev"
#define SHORT_BUILD_VERSION "4.2.4 dev"
#define STRING_DISTRIBUTION_DATE __DATE__ " " __TIME__ // build date and time
// It might also be appropriate to define a location where additional information can be found
#define SOURCE_CODE_URL "https://github.com/MagoKimbra/MarlinKimbra"
......
This diff is collapsed.
......@@ -83,6 +83,8 @@ void clamp_to_software_endstops(float target[3]);
extern millis_t previous_cmd_ms;
void refresh_cmd_timeout();
extern void delay_ms(millis_t ms);
#if ENABLED(FAST_PWM_FAN)
void setPwmFrequency(uint8_t pin, int val);
#endif
......@@ -236,7 +238,6 @@ extern void calculate_volumetric_multipliers();
long code_value_long();
bool code_seen(char );
//
// Utility functions used by M100 to get its work done.
//
......@@ -247,4 +248,5 @@ extern void calculate_volumetric_multipliers();
int how_many_E5s_are_here( unsigned char *);
#endif
#endif //MARLIN_H
......@@ -18,14 +18,14 @@
#endif
#include <util/delay.h>
#include <avr/eeprom.h>
#include "fastio.h"
#include "module/fastio.h"
#endif
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "macros.h"
#include "module/macros.h"
#include "Boards.h"
#include "mechanics.h"
#include "module/mechanics.h"
#include "Configuration_Version.h"
#include "Configuration_Overall.h"
......@@ -49,10 +49,10 @@
#endif
#include "language/language.h"
#include "conditionals.h"
#include "sanitycheck.h"
#include "thermistortables.h"
#include "comunication.h"
#include "module/conditionals.h"
#include "module/sanitycheck.h"
#include "module/thermistortables.h"
#include "module/comunication.h"
typedef unsigned long millis_t;
......
#include "base.h"
#include "Marlin_main.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#include "module/vector_3.h"
#endif
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "temperature.h"
#include "ultralcd.h"
#include "module/planner.h"
#include "module/stepper_indirection.h"
#include "module/stepper.h"
#include "module/temperature.h"
#include "module/ultralcd.h"
#include "configuration_store.h"
#if ENABLED(SDSUPPORT)
#include "cardreader.h"
#include "module/cardreader.h"
#endif
/**
* configuration_store.cpp
......
......@@ -184,11 +184,11 @@
#define SERIAL_T_MINTEMP "MINTEMP triggered"
// Endstop
#define SERIAL_ENDSTOP_X " X:"
#define SERIAL_ENDSTOP_Y " Y:"
#define SERIAL_ENDSTOP_Z " Z:"
#define SERIAL_ENDSTOP_E " E:"
#define SERIAL_ENDSTOP_PROBE " PROBE:"
#define SERIAL_ENDSTOP_X " X="
#define SERIAL_ENDSTOP_Y " Y="
#define SERIAL_ENDSTOP_Z " Z="
#define SERIAL_ENDSTOP_E " E="
#define SERIAL_ENDSTOP_PROBE " PROBE="
// Debug
#define SERIAL_DEBUG_ECHO "DEBUG ECHO ENABLED"
......
......@@ -20,7 +20,7 @@
Modified 28 September 2010 by Mark Sproul
*/
#include "base.h"
#include "../base.h"
#include "MarlinSerial.h"
......
......@@ -17,7 +17,7 @@
* along with the Arduino Sd2Card Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "base.h"
#include "../base.h"
#if ENABLED(SDSUPPORT)
#include "Sd2Card.h"
......
......@@ -18,9 +18,11 @@
* <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#ifndef Sd2Card_h
#define Sd2Card_h
#include "base.h"
#if ENABLED(SDSUPPORT)
/**
......
......@@ -18,9 +18,11 @@
* <http://www.gnu.org/licenses/>.
*/
#include "base.h"
#include "../base.h"
#include "../Marlin_main.h"
#if ENABLED(SDSUPPORT)
#include "Marlin_main.h"
#include <stdint.h>
#include "SdBaseFile.h"
//------------------------------------------------------------------------------
......
......@@ -18,14 +18,18 @@
* <http://www.gnu.org/licenses/>.
*/
#include "../base.h"
#ifndef SdFatUtil_h
#define SdFatUtil_h
/**
* \file
* \brief Useful utility functions.
*/
#include "base.h"
#include "MarlinSerial.h"
/** Store and print a string in flash memory.*/
#define PgmPrint(x) SerialPrint_P(PSTR(x))
/** Store and print a string in flash memory followed by a CR/LF.*/
......
......@@ -17,9 +17,12 @@
* along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "base.h"
#include "../base.h"
#include "../Marlin_main.h"
#if ENABLED(SDSUPPORT)
#include "Marlin_main.h"
#include "SdFile.h"
/** Create a file object and open it in the current working directory.
*
......
......@@ -17,8 +17,10 @@
* along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "base.h"
#include "Marlin_main.h"
#include "../base.h"
#include "../Marlin_main.h"
#if ENABLED(SDSUPPORT)
#include "SdVolume.h"
......
......@@ -17,6 +17,7 @@
* along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef SdVolume_h
#define SdVolume_h
/**
......
......@@ -2,7 +2,7 @@
#if HAS(BUZZER)
#include "buzzer.h"
#include "../ultralcd.h"
#include "ultralcd.h"
void buzz(long duration, uint16_t freq) {
if (freq > 0) {
......
#include "base.h"
#include "../base.h"
#if ENABLED(SDSUPPORT)
#include "Marlin_main.h"
#include "../Marlin_main.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#endif
......@@ -11,7 +11,7 @@
#include "stepper.h"
#include "temperature.h"
#include "ultralcd.h"
#include "module/nextion_lcd.h"
#include "nextion_lcd.h"
#include "cardreader.h"
CardReader::CardReader() {
......
......@@ -221,7 +221,7 @@
#endif
#endif
#include "pins.h"
#include "../Pins.h"
/**
* DONDOLO
......
#include "base.h"
#include "../base.h"
#if ENABLED(DIGIPOT_I2C)
......
......@@ -3,7 +3,7 @@
* Externa DAC for Alligator Board
*
****************************************************************/
#include "base.h"
#include "../base.h"
#if MB(ALLIGATOR)
#include "stepper.h"
......
......@@ -4,19 +4,18 @@
*/
#include "../base.h"
#include "../Marlin_main.h"
#if ENABLED(FIRMWARE_TEST)
#include "firmware_test.h"
#include "../Marlin_main.h"
#include "../planner.h"
#include "../stepper_indirection.h"
#include "../stepper.h"
#include "../temperature.h"
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "temperature.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "../vector_3.h"
#include "vector_3.h"
#endif
static char serial_answer;
......
......@@ -16,10 +16,10 @@
*/
#include "../base.h"
#include "../Marlin_main.h"
#if ENABLED(NEXTION_GFX)
#include "../Marlin_main.h"
#include "../stepper.h"
#include "stepper.h"
#include "nextion_gfx.h"
const int INSIDE = 0; // 0000
......
......@@ -15,7 +15,6 @@
*
*/
#ifndef NEXTION_GFX_H
#define NEXTION_GFX_H
......
#include "../base.h"
#include "../Marlin_main.h"
#include "../configuration_store.h"
#if ENABLED(NEXTION)
#include "../Marlin_main.h"
#include "../cardreader.h"
#include "../temperature.h"
#include "cardreader.h"
#include "temperature.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "../vector_3.h"
#include "vector_3.h"
#endif
#include "../planner.h"
#include "../stepper_indirection.h"
#include "../stepper.h"
#include "../configuration_store.h"
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "nextion_lcd.h"
#include "nextion_gfx.h"
#include <Nextion.h>
const float MaxWave = 0.2;
bool NextionON = false;
bool PageInfo = false;
bool gfxON = false;
char buffer[100] = {0};
uint32_t slidermaxval = 20;
char lcd_status_message[30] = WELCOME_MSG;
......@@ -26,7 +28,7 @@
static millis_t next_lcd_update_ms;
#if ENABLED(NEXTION_GFX)
GFX gfx = GFX(200, 190);
GFX gfx = GFX(196, 194);
#endif
// Page
......@@ -39,10 +41,10 @@
NexPage Pmove = NexPage(6, 0, "move");
// Text
NexText Hotend0 = NexText(1, 2, "t0");
NexText Hotend0 = NexText(1, 1, "t0");
NexText Hotend1 = NexText(1, 4, "t1");
NexText Hotend21 = NexText(1, 5, "h2");
NexText Hotend2 = NexText(1, 6, "t2");
NexText Hotend2 = NexText(1, 5, "t2");
NexText Hotend21 = NexText(1, 6, "h2");
NexText LedStatus = NexText(1, 7, "t4");
NexText LedCoord = NexText(1, 8, "t5");
NexText set0 = NexText(2, 2, "set0");
......@@ -55,15 +57,15 @@
NexText sdfolder = NexText(4, 23, "sdfolder");
// Picture
NexPicture Menu = NexPicture(1, 9, "p0");
NexPicture MSD = NexPicture(1, 10, "p1");
NexPicture MSetup = NexPicture(1, 11, "p2");
NexPicture Hend0 = NexPicture(1, 12, "p3");
NexPicture Menu = NexPicture(1, 10, "p0");
NexPicture MSD = NexPicture(1, 11, "p1");
NexPicture MSetup = NexPicture(1, 12, "p2");
NexPicture Hend0 = NexPicture(1, 13, "p3");
NexPicture Hend1 = NexPicture(1, 14, "p4");
NexPicture Hend2 = NexPicture(1, 16, "p5");
NexPicture Fanpic = NexPicture(1, 18, "p6");
NexPicture NPlay = NexPicture(1, 24, "p7");
NexPicture NStop = NexPicture(1, 25, "p8");
NexPicture Hend2 = NexPicture(1, 15, "p5");
NexPicture Fanpic = NexPicture(1, 19, "p6");
NexPicture NPlay = NexPicture(1, 27, "p7");
NexPicture NStop = NexPicture(1, 28, "p8");
NexPicture Exit1 = NexPicture(3, 4, "p3");
NexPicture Folder0 = NexPicture(4, 9, "p0");
NexPicture Folder1 = NexPicture(4, 10, "p1");
......@@ -84,29 +86,32 @@
NexPicture ZDown = NexPicture(6, 12, "p11");
// Progress Bar
NexProgressBar sdbar = NexProgressBar(1, 23, "j0");
NexProgressBar sdbar = NexProgressBar(1, 26, "j0");
// Slider
NexSlider sdlist = NexSlider(4, 1, "h0");
// Wafeform
NexWaveform Graph0 = NexWaveform(1, 9, "s0");
NexWaveform Graph1 = NexWaveform(1, 24, "s1");
NexWaveform Graph2 = NexWaveform(1, 25, "s2");
// Touch area
NexHotspot hot0 = NexHotspot(1, 13, "hot0");
NexHotspot hot1 = NexHotspot(1, 15, "hot1");
NexHotspot hot2 = NexHotspot(1, 17, "hot2");
NexHotspot hot0 = NexHotspot(1, 14, "hot0");
NexHotspot hot1 = NexHotspot(1, 16, "hot1");
NexHotspot hot2 = NexHotspot(1, 18, "hot2");
NexHotspot m11 = NexHotspot(2, 14, "m11");
NexHotspot tup = NexHotspot(2, 16, "tup");
NexHotspot tdown = NexHotspot(2, 17, "tdown");
// Timer
NexTimer startimer = NexTimer(0, 1, "tm0");
NexTimer fantimer = NexTimer(1, 22, "tm0");
NexTimer fantimer = NexTimer(1, 23, "tm0");
// Variable
NexVar Hotend = NexVar(1, 19, "he");
NexVar Bed = NexVar(1, 20, "bed");
NexVar Hotend = NexVar(1, 20, "he");
NexVar set1 = NexVar(2, 17, "set1");
NexVar Bed = NexVar(1, 21, "bed");
NexVar filename0 = NexVar(4, 19, "va0");
NexVar filename1 = NexVar(4, 20, "va1");
NexVar filename2 = NexVar(4, 21, "va2");
......@@ -160,6 +165,14 @@
NULL
};
NexWaveform *graph_list[] =
{
&Graph0,
&Graph1,
&Graph2,
NULL
};
NexText *row_list[] =
{
&sdrow0,
......@@ -198,10 +211,6 @@
PageInfo = true;
#if ENABLED(NEXTION_GFX)
gfx_clear(X_MAX_POS, Y_MAX_POS, Z_MAX_POS);
#endif
#if HAS_TEMP_0
Hotend.setValue(1);
#endif
......@@ -269,6 +278,7 @@
static void setpagesdcard() {
PageInfo = false;
gfxON = false;
Psdcard.show();
uint16_t fileCnt = card.getnrfilenames();
......@@ -426,10 +436,12 @@
void setpagePopCallback(void *ptr) {
if (ptr == &Menu) {
PageInfo = false;
gfxON = false;
Pmenu.show();
}
else if (ptr == &MSetup) {
PageInfo = false;
gfxON = false;
Psetup.show();
}
......@@ -472,7 +484,7 @@
#endif
void lcd_init() {
delay(1000);
delay_ms(1000);
NextionON = nexInit();
if (!NextionON) {
......@@ -549,6 +561,11 @@
hotend_list[h]->setText(buffer);
hotend_list[h]->setColor(color);
if (!gfxON) {
graph_list[h]->addValue(0, (int)(T1 * MaxWave));
graph_list[h]->addValue(1, (int)(T2 * MaxWave));
}
}
static void coordtoLCD() {
......@@ -661,17 +678,19 @@
#if ENABLED(NEXTION_GFX)
void gfx_clear(float x, float y, float z) {
if (PageInfo)
if (PageInfo) {
gfx.clear(x, y, z);
gfxON = true;
}
}
void gfx_cursor_to(float x, float y, float z) {
if (PageInfo)
if (PageInfo && gfxON)
gfx.cursor_to(x, y, z);
}
void gfx_line_to(float x, float y, float z){
if (PageInfo)
if (PageInfo && gfxON)
gfx.line_to(VC_TOOL, x, y, z);
}
#endif
......
......@@ -48,8 +48,8 @@
*
*/
#include "base.h"
#include "Marlin_main.h"
#include "../base.h"
#include "../Marlin_main.h"
#include "planner.h"
#include "stepper_indirection.h"
......
#include "base.h"
#include "../base.h"
#if ENABLED(AUTO_BED_LEVELING_GRID)
......
......@@ -22,8 +22,8 @@
/* The timer calculations of this module informed by the 'RepRap cartesian firmware' by Zack Smith
and Philipp Tiefenbacher. */
#include "base.h"
#include "Marlin_main.h"
#include "../base.h"
#include "../Marlin_main.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
......@@ -36,7 +36,7 @@
#include "stepper.h"
#include "temperature.h"
#include "ultralcd.h"
#include "module/nextion_lcd.h"
#include "nextion_lcd.h"
#if ENABLED(SDSUPPORT)
#include "cardreader.h"
......@@ -96,7 +96,11 @@ static volatile char endstop_hit_bits = 0; // use X_MIN, Y_MIN, Z_MIN and Z_PROB
old_endstop_bits = 0; // use X_MIN, X_MAX... Z_MAX, Z_PROBE, Z2_MIN, Z2_MAX, E_MIN
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
bool abort_on_endstop_hit = false;
#if ENABLED(ABORT_ON_ENDSTOP_HIT_INIT)
bool abort_on_endstop_hit = ABORT_ON_ENDSTOP_HIT_INIT;
#else
bool abort_on_endstop_hit = false;
#endif
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
......@@ -263,7 +267,16 @@ void endstops_hit_on_purpose() {
void checkHitEndstops() {
if (endstop_hit_bits) {
ECHO_SM(DB, SERIAL_ENDSTOPS_HIT);
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
if (abort_on_endstop_hit)
ECHO_SM(ER, SERIAL_ENDSTOPS_HIT);
else
ECHO_SM(DB, SERIAL_ENDSTOPS_HIT);
#else
ECHO_SM(DB, SERIAL_ENDSTOPS_HIT);
#endif
if (endstop_hit_bits & BIT(X_MIN)) {
ECHO_MV(SERIAL_ENDSTOP_X, (float)endstops_trigsteps[X_AXIS] / axis_steps_per_unit[X_AXIS]);
LCD_MESSAGEPGM(MSG_ENDSTOPS_HIT MSG_ENDSTOP_XS);
......@@ -290,16 +303,19 @@ void checkHitEndstops() {
#endif
ECHO_E;
endstops_hit_on_purpose();
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) && ENABLED(SDSUPPORT)
if (abort_on_endstop_hit) {
card.sdprinting = false;
card.closeFile();
quickStop();
disable_all_heaters(); // switch off all heaters.
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
if (abort_on_endstop_hit && !(endstop_hit_bits & BIT(Z_PROBE)) && !(endstop_hit_bits & BIT(E_MIN))) {
#if ENABLED(SDSUPPORT)
card.sdprinting = false;
card.closeFile();
#endif
for (int i = 0; i < 3; i++) axis_known_position[i] = false; // not homed anymore
quickStop(); // kill the planner buffer
Stop(); // restart by M999
}
#endif
endstops_hit_on_purpose();
}
}
......
......@@ -19,9 +19,9 @@
along with Marlin. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base.h"
#include "../base.h"
#include "stepper_indirection.h"
#if ENABLED(HAVE_TMCDRIVER)
#include <SPI.h>
#include <TMC26XStepper.h>
......
......@@ -18,13 +18,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base.h"
#include "Marlin_main.h"
#include "../base.h"
#include "../Marlin_main.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
#endif
#include "ultralcd.h"
#include "module/nextion_lcd.h"
#include "nextion_lcd.h"
#include "planner.h"
#include "stepper_indirection.h"
#if MB(ALLIGATOR)
......@@ -1101,7 +1102,7 @@ void tp_init() {
TIMSK0 |= BIT(OCIE0B);
// Wait for temperature measurement to settle
delay(250);
delay_ms(250);
#define TEMP_MIN_ROUTINE(NR) \
minttemp[NR] = HEATER_ ## NR ## _MINTEMP; \
......
#include "base.h"
#include "../base.h"
#include "../Marlin_main.h"
#include "../configuration_store.h"
#if ENABLED(ULTRA_LCD)
#include "Marlin_main.h"
#include "cardreader.h"
#include "temperature.h"
......@@ -13,11 +14,10 @@
#include "planner.h"
#include "stepper_indirection.h"
#include "stepper.h"
#include "configuration_store.h"
#include "ultralcd.h"
#if HAS(BUZZER)
#include "module/buzzer.h"
#include "buzzer.h"
#endif
int8_t encoderDiff; // updated from interrupt context and added to encoderPosition every LCD update
......
#ifndef ULTRALCD_H
#define ULTRALCD_H
#include "Marlin_main.h"
#include "../Marlin_main.h"
#if ENABLED(ULTRA_LCD)
#if HAS(BUZZER)
#include "module/buzzer.h"
#include "buzzer.h"
#endif
int lcd_strlen(char* s);
......
......@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <math.h>
#include "base.h"
#include "../base.h"
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h"
......
#include "base.h"
#include "../base.h"
#if ENABLED(USE_WATCHDOG)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment