Commit 2359a28b authored by MagoKimbra's avatar MagoKimbra

Same fix

parent aedb4d4e
......@@ -145,13 +145,13 @@ void Config_PrintSettings()
SERIAL_ECHOPAIR(" M92 X",axis_steps_per_unit[X_AXIS]);
SERIAL_ECHOPAIR(" Y",axis_steps_per_unit[Y_AXIS]);
SERIAL_ECHOPAIR(" Z",axis_steps_per_unit[Z_AXIS]);
SERIAL_ECHOPAIR(" E0 ",axis_steps_per_unit[E_AXIS + 0]);
SERIAL_ECHOPAIR(" E0 S",axis_steps_per_unit[E_AXIS + 0]);
#if EXTRUDERS > 1
SERIAL_ECHOPAIR(" E1 ",axis_steps_per_unit[E_AXIS + 1]);
SERIAL_ECHOPAIR(" E1 S",axis_steps_per_unit[E_AXIS + 1]);
#if EXTRUDERS > 2
SERIAL_ECHOPAIR(" E2 ",axis_steps_per_unit[E_AXIS + 2]);
SERIAL_ECHOPAIR(" E2 S",axis_steps_per_unit[E_AXIS + 2]);
#if EXTRUDERS > 3
SERIAL_ECHOPAIR(" E3 ",axis_steps_per_unit[E_AXIS + 3]);
SERIAL_ECHOPAIR(" E3 S",axis_steps_per_unit[E_AXIS + 3]);
#endif //EXTRUDERS > 3
#endif //EXTRUDERS > 2
#endif //EXTRUDERS > 1
......
......@@ -32,8 +32,7 @@
ring_buffer rx_buffer = { { 0 }, 0, 0 };
#endif
FORCE_INLINE void store_char(unsigned char c)
{
FORCE_INLINE void store_char(unsigned char c) {
int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE;
// if we should be storing the received character into the location
......@@ -51,8 +50,7 @@ FORCE_INLINE void store_char(unsigned char c)
#if defined(M_USARTx_RX_vect)
// fixed by Mark Sproul this is on the 644/644p
//SIGNAL(SIG_USART_RECV)
SIGNAL(M_USARTx_RX_vect)
{
SIGNAL(M_USARTx_RX_vect) {
unsigned char c = M_UDRx;
store_char(c);
}
......@@ -60,26 +58,22 @@ FORCE_INLINE void store_char(unsigned char c)
// Constructors ////////////////////////////////////////////////////////////////
MarlinSerial::MarlinSerial()
{
}
MarlinSerial::MarlinSerial() { }
// Public Methods //////////////////////////////////////////////////////////////
void MarlinSerial::begin(long baud)
{
void MarlinSerial::begin(long baud) {
uint16_t baud_setting;
bool useU2X = true;
#if F_CPU == 16000000UL && SERIAL_PORT == 0
// hard-coded exception for compatibility with the bootloader shipped
// with the Duemilanove and previous boards and the firmware on the 8U2
// on the Uno and Mega 2560.
if (baud == 57600) {
useU2X = false;
}
#endif
#if F_CPU == 16000000UL && SERIAL_PORT == 0
// hard-coded exception for compatibility with the bootloader shipped
// with the Duemilanove and previous boards and the firmware on the 8U2
// on the Uno and Mega 2560.
if (baud == 57600) {
useU2X = false;
}
#endif
if (useU2X) {
M_UCSRxA = 1 << M_U2Xx;
......@@ -98,17 +92,14 @@ void MarlinSerial::begin(long baud)
sbi(M_UCSRxB, M_RXCIEx);
}
void MarlinSerial::end()
{
void MarlinSerial::end() {
cbi(M_UCSRxB, M_RXENx);
cbi(M_UCSRxB, M_TXENx);
cbi(M_UCSRxB, M_RXCIEx);
}
int MarlinSerial::peek(void)
{
int MarlinSerial::peek(void) {
if (rx_buffer.head == rx_buffer.tail) {
return -1;
} else {
......@@ -116,20 +107,19 @@ int MarlinSerial::peek(void)
}
}
int MarlinSerial::read(void)
{
int MarlinSerial::read(void) {
// if the head isn't ahead of the tail, we don't have any characters
if (rx_buffer.head == rx_buffer.tail) {
return -1;
} else {
}
else {
unsigned char c = rx_buffer.buffer[rx_buffer.tail];
rx_buffer.tail = (unsigned int)(rx_buffer.tail + 1) % RX_BUFFER_SIZE;
return c;
}
}
void MarlinSerial::flush()
{
void MarlinSerial::flush() {
// don't reverse this or there may be problems if the RX interrupt
// occurs after reading the value of rx_buffer_head but before writing
// the value to rx_buffer_tail; the previous value of rx_buffer_head
......@@ -143,38 +133,30 @@ void MarlinSerial::flush()
}
/// imports from print.h
void MarlinSerial::print(char c, int base)
{
void MarlinSerial::print(char c, int base) {
print((long) c, base);
}
void MarlinSerial::print(unsigned char b, int base)
{
void MarlinSerial::print(unsigned char b, int base) {
print((unsigned long) b, base);
}
void MarlinSerial::print(int n, int base)
{
void MarlinSerial::print(int n, int base) {
print((long) n, base);
}
void MarlinSerial::print(unsigned int n, int base)
{
void MarlinSerial::print(unsigned int n, int base) {
print((unsigned long) n, base);
}
void MarlinSerial::print(long n, int base)
{
void MarlinSerial::print(long n, int base) {
if (base == 0) {
write(n);
} else if (base == 10) {
}
else if (base == 10) {
if (n < 0) {
print('-');
n = -n;
......@@ -185,81 +167,68 @@ void MarlinSerial::print(long n, int base)
}
}
void MarlinSerial::print(unsigned long n, int base)
{
void MarlinSerial::print(unsigned long n, int base) {
if (base == 0) write(n);
else printNumber(n, base);
}
void MarlinSerial::print(double n, int digits)
{
void MarlinSerial::print(double n, int digits) {
printFloat(n, digits);
}
void MarlinSerial::println(void)
{
void MarlinSerial::println(void) {
print('\r');
print('\n');
}
void MarlinSerial::println(const String &s)
{
void MarlinSerial::println(const String &s) {
print(s);
println();
}
void MarlinSerial::println(const char c[])
{
void MarlinSerial::println(const char c[]) {
print(c);
println();
}
void MarlinSerial::println(char c, int base)
{
void MarlinSerial::println(char c, int base) {
print(c, base);
println();
}
void MarlinSerial::println(unsigned char b, int base)
{
void MarlinSerial::println(unsigned char b, int base) {
print(b, base);
println();
}
void MarlinSerial::println(int n, int base)
{
void MarlinSerial::println(int n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(unsigned int n, int base)
{
void MarlinSerial::println(unsigned int n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(long n, int base)
{
void MarlinSerial::println(long n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(unsigned long n, int base)
{
void MarlinSerial::println(unsigned long n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(double n, int digits)
{
void MarlinSerial::println(double n, int digits) {
print(n, digits);
println();
}
// Private Methods /////////////////////////////////////////////////////////////
void MarlinSerial::printNumber(unsigned long n, uint8_t base)
{
void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
unsigned long i = 0;
......@@ -279,18 +248,16 @@ void MarlinSerial::printNumber(unsigned long n, uint8_t base)
'A' + buf[i - 1] - 10));
}
void MarlinSerial::printFloat(double number, uint8_t digits)
{
void MarlinSerial::printFloat(double number, uint8_t digits) {
// Handle negative numbers
if (number < 0.0)
{
if (number < 0.0) {
print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
for (uint8_t i = 0; i < digits; ++i)
rounding /= 10.0;
number += rounding;
......@@ -305,8 +272,7 @@ void MarlinSerial::printFloat(double number, uint8_t digits)
print(".");
// Extract digits from the remainder one at a time
while (digits-- > 0)
{
while (digits-- > 0) {
remainder *= 10.0;
int toPrint = int(remainder);
print(toPrint);
......
......@@ -23,8 +23,8 @@
#define MarlinSerial_h
#include "Marlin.h"
#if !defined(SERIAL_PORT)
#define SERIAL_PORT 0
#ifndef SERIAL_PORT
#define SERIAL_PORT 0
#endif
// The presence of the UBRRH register is used to detect a UART.
......@@ -36,9 +36,9 @@
// requires two levels of indirection to expand macro values properly)
#define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix)
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
#else
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
#endif
// Registers used by MarlinSerial class (these are expanded
......@@ -57,7 +57,6 @@
#define M_U2Xx SERIAL_REGNAME(U2X,SERIAL_PORT,)
#define DEC 10
#define HEX 16
#define OCT 8
......@@ -73,8 +72,7 @@
#define RX_BUFFER_SIZE 128
struct ring_buffer
{
struct ring_buffer {
unsigned char buffer[RX_BUFFER_SIZE];
int head;
int tail;
......@@ -84,8 +82,7 @@ struct ring_buffer
extern ring_buffer rx_buffer;
#endif
class MarlinSerial //: public Stream
{
class MarlinSerial { //: public Stream
public:
MarlinSerial();
......@@ -94,24 +91,20 @@ class MarlinSerial //: public Stream
int peek(void);
int read(void);
void flush(void);
FORCE_INLINE int available(void)
{
FORCE_INLINE int available(void) {
return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE;
}
FORCE_INLINE void write(uint8_t c)
{
FORCE_INLINE void write(uint8_t c) {
while (!((M_UCSRxA) & (1 << M_UDREx)))
;
M_UDRx = c;
}
FORCE_INLINE void checkRx(void)
{
if((M_UCSRxA & (1<<M_RXCx)) != 0) {
FORCE_INLINE void checkRx(void) {
if ((M_UCSRxA & (1<<M_RXCx)) != 0) {
unsigned char c = M_UDRx;
int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE;
......@@ -125,39 +118,17 @@ class MarlinSerial //: public Stream
}
}
}
private:
private:
void printNumber(unsigned long, uint8_t);
void printFloat(double, uint8_t);
public:
FORCE_INLINE void write(const char *str)
{
while (*str)
write(*str++);
}
public:
FORCE_INLINE void write(const char *str) { while (*str) write(*str++); }
FORCE_INLINE void write(const uint8_t *buffer, size_t size) { while (size--) write(*buffer++); }
FORCE_INLINE void print(const String &s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
FORCE_INLINE void print(const char *str) { write(str); }
FORCE_INLINE void write(const uint8_t *buffer, size_t size)
{
while (size--)
write(*buffer++);
}
FORCE_INLINE void print(const String &s)
{
for (int i = 0; i < (int)s.length(); i++) {
write(s[i]);
}
}
FORCE_INLINE void print(const char *str)
{
write(str);
}
void print(char, int = BYTE);
void print(unsigned char, int = BYTE);
void print(int, int = DEC);
......
......@@ -3907,17 +3907,16 @@ Sigma_Exit:
case 92: // M92
for(int8_t i=0; i < NUM_AXIS; i++)
{
int e = 0;
if(code_seen(axis_codes[i]))
{
if(i == 3) { // E
float value = code_value();
if(value < 20.0) {
float factor = axis_steps_per_unit[i] / value; // increase e constants if M92 E14 is given for netfab.
max_e_jerk *= factor;
max_feedrate[i] *= factor;
axis_steps_per_sqr_second[i] *= factor;
if (i == 3)
{
e = (int)code_value();
if(code_seen('S'))
{
if (e < EXTRUDERS) axis_steps_per_unit[e+3] = code_value();
}
axis_steps_per_unit[i] = value;
}
else {
axis_steps_per_unit[i] = code_value();
......
......@@ -7,16 +7,24 @@
#define BOARD_GEN7_12 11 // Gen7 v1.1, v1.2
#define BOARD_GEN7_13 12 // Gen7 v1.3
#define BOARD_GEN7_14 13 // Gen7 v1.4
#define BOARD_CHEAPTRONIC 2 // Cheaptronic v1.0
#define BOARD_SETHI 20 // Sethi 3D_1
#define BOARD_ELEFU_3 21 // Elefu Ra Board (v3)
#define BOARD_GEN3_MONOLITHIC 22 // Gen3 Monolithic Electronics
#define BOARD_RAMPS_OLD 3 // MEGA/RAMPS up to 1.2
#define BOARD_RAMPS_13_EFB 33 // RAMPS 1.3 / 1.4 (Power outputs: Extruder, Fan, Bed)
#define BOARD_RAMPS_13_EEB 34 // RAMPS 1.3 / 1.4 (Power outputs: Extruder0, Extruder1, Bed)
#define BOARD_RAMPS_13_EFF 35 // RAMPS 1.3 / 1.4 (Power outputs: Extruder, Fan, Fan)
#define BOARD_RAMPS_13_EEF 36 // RAMPS 1.3 / 1.4 (Power outputs: Extruder0, Extruder1, Fan)
#define BOARD_RAMBO 301 // Rambo
#define BOARD_DUEMILANOVE_328P 4 // Duemilanove w/ ATMega328P pin assignment
#define BOARD_GEN6 5 // Gen6
#define BOARD_GEN6_DELUXE 51 // Gen6 deluxe
#define BOARD_SANGUINOLOLU_11 6 // Sanguinololu < 1.2
#define BOARD_SANGUINOLOLU_12 62 // Sanguinololu 1.2 and above
#define BOARD_MELZI 63 // Melzi
......@@ -25,27 +33,28 @@
#define BOARD_MELZI_1284 66 // Melzi with ATmega1284 (MaKr3d version)
#define BOARD_AZTEEG_X3 67 // Azteeg X3
#define BOARD_AZTEEG_X3_PRO 68 // Azteeg X3 Pro
#define BOARD_ULTIMAKER 7 // Ultimaker
#define BOARD_MEGATRONICS 70 // Megatronics
#define BOARD_MEGATRONICS_2 701 // Megatronics v2.0
#define BOARD_MEGATRONICS_1 702 // Minitronics v1.0
#define BOARD_MEGATRONICS_3 703 // Megatronics v3.0
#define BOARD_ULTIMAKER_OLD 71 // Ultimaker (Older electronics. Pre 1.5.4. This is rare)
#define BOARD_ULTIMAIN_2 72 // Ultimainboard 2.x (Uses TEMP_SENSOR 20)
#define BOARD_3DRAG 77 // 3Drag Controller
#define BOARD_K8200 78 // Vellemann K8200 Controller (derived from 3Drag Controller)
#define BOARD_TEENSYLU 8 // Teensylu
#define BOARD_RUMBA 80 // Rumba
#define BOARD_PRINTRBOARD 81 // Printrboard (AT90USB1286)
#define BOARD_BRAINWAVE 82 // Brainwave (AT90USB646)
#define BOARD_SAV_MKI 83 // SAV Mk-I (AT90USB1286)
#define BOARD_TEENSY2 84 // Teensy++2.0 (AT90USB1286) - CLI compile: DEFINES=AT90USBxx_TEENSYPP_ASSIGNMENTS HARDWARE_MOTHERBOARD=84 make
#define BOARD_5DPRINT 88 // 5DPrint D8 Driver Board
#define BOARD_GEN3_PLUS 9 // Gen3+
#define BOARD_GEN3_MONOLITHIC 22 // Gen3 Monolithic Electronics
#define BOARD_MEGATRONICS 70 // Megatronics
#define BOARD_MEGATRONICS_2 701 // Megatronics v2.0
#define BOARD_MEGATRONICS_1 702 // Minitronics v1.0
#define BOARD_OMCA_A 90 // Alpha OMCA board
#define BOARD_OMCA 91 // Final OMCA board
#define BOARD_RAMBO 301 // Rambo
#define BOARD_ELEFU_3 21 // Elefu Ra Board (v3)
#define BOARD_5DPRINT 88 // 5DPrint D8 Driver Board
#define BOARD_LEAPFROG 999 // Leapfrog
#define BOARD_99 99 // This is in pins.h but...?
......
This diff is collapsed.
......@@ -209,6 +209,11 @@ static void updateTemperaturesFromRawValues();
#ifdef FILAMENT_SENSOR
static int meas_shift_index; //used to point to a delayed sample in buffer for filament width sensor
#endif
#ifdef HEATER_0_USES_MAX6675
static int read_max6675();
#endif
//===========================================================================
//============================= functions ============================
//===========================================================================
......@@ -512,6 +517,16 @@ void manage_heater()
return;
updateTemperaturesFromRawValues();
#ifdef HEATER_0_USES_MAX6675
if (current_temperature[0] > 1023 || current_temperature[0] > HEATER_0_MAXTEMP) {
max_temp_error(0);
}
if (current_temperature[0] == 0 || current_temperature[0] < HEATER_0_MINTEMP) {
min_temp_error(0);
}
#endif //HEATER_0_USES_MAX6675
#ifndef SINGLENOZZLE
for(int e = 0; e < EXTRUDERS; e++)
{
......@@ -641,7 +656,7 @@ void manage_heater()
#if TEMP_SENSOR_BED != 0
#ifdef THERMAL_RUNAWAY_PROTECTION_PERIOD && THERMAL_RUNAWAY_PROTECTION_PERIOD > 0
#if defined(THERMAL_RUNAWAY_PROTECTION_BED_PERIOD) && THERMAL_RUNAWAY_PROTECTION_BED_PERIOD > 0
thermal_runaway_protection(&thermal_runaway_bed_state_machine, &thermal_runaway_bed_timer, current_temperature_bed, target_temperature_bed, 9, THERMAL_RUNAWAY_PROTECTION_BED_PERIOD, THERMAL_RUNAWAY_PROTECTION_BED_HYSTERESIS);
#endif
......@@ -826,11 +841,15 @@ static float analog2tempBed(int raw) {
and this function is called from normal context as it is too slow to run in interrupts and will block the stepper routine otherwise */
static void updateTemperaturesFromRawValues()
{
#ifdef HEATER_0_USES_MAX6675
current_temperature_raw[0] = read_max6675();
#endif
#ifndef SINGLENOZZLE
for(uint8_t e=0;e<EXTRUDERS;e++)
{
#else
for(uint8_t e=0;e<1;e++)
uint8_t e=0;
{
#endif // !SINGLENOZZLE
current_temperature[e] = analog2temp(current_temperature_raw[e], e);
......@@ -890,10 +909,10 @@ void tp_init()
// Finish init of mult extruder arrays
#ifndef SINGLENOZZLE
for (int e = 0; e < EXTRUDERS; e++)
for (uint8_t e = 0; e < EXTRUDERS; e++)
{
#else
for (int e = 0; e < 1; e++)
uint8_t e = 0;
{
#endif // !SINGLENOZZLE
// populate with the first value
......@@ -937,6 +956,7 @@ void tp_init()
#endif
#ifdef HEATER_0_USES_MAX6675
#ifndef SDSUPPORT
SET_OUTPUT(SCK_PIN);
WRITE(SCK_PIN,0);
......@@ -946,15 +966,15 @@ void tp_init()
SET_INPUT(MISO_PIN);
WRITE(MISO_PIN,1);
#else
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, HIGH);
#endif
/* Using pinMode and digitalWrite, as that was the only way I could get it to compile */
//Have to toggle SD card CS pin to low first, to enable firmware to talk with SD card
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN,0);
pinMode(MAX6675_SS, OUTPUT);
digitalWrite(MAX6675_SS,1);
#endif
SET_OUTPUT(MAX6675_SS);
WRITE(MAX6675_SS,1);
#endif //HEATER_0_USES_MAX6675
// Set analog inputs
ADCSRA = 1<<ADEN | 1<<ADSC | 1<<ADIF | 0x07;
......@@ -1131,10 +1151,10 @@ void setWatch()
{
#ifdef WATCH_TEMP_PERIOD
#ifndef SINGLENOZZLE
for (int e = 0; e < EXTRUDERS; e++)
for (uint8_t e = 0; e < EXTRUDERS; e++)
{
#else
for (int e = 0; e < 1; e++)
uint8_t e = 0;
{
#endif // !SINGLENOZZLE
if(degHotend(e) < degTargetHotend(e) - (WATCH_TEMP_INCREASE * 2))
......@@ -1211,9 +1231,9 @@ void thermal_runaway_protection(int *state, unsigned long *timer, float temperat
void disable_heater()
{
#ifndef SINGLENOZZLE
for(int i=0;i<EXTRUDERS;i++)
for(uint8_t i=0;i<EXTRUDERS;i++)
#else
for(int i=0;i<1;i++)
uint8_t i=0;
#endif // !SINGLENOZZLE
setTargetHotend(0,i);
setTargetBed(0);
......@@ -1305,7 +1325,7 @@ void bed_max_temp_error(void) {
long max6675_previous_millis = MAX6675_HEAT_INTERVAL;
int max6675_temp = 2000;
int read_max6675()
static int read_max6675()
{
if (millis() - max6675_previous_millis < MAX6675_HEAT_INTERVAL)
return max6675_temp;
......@@ -1313,9 +1333,9 @@ int read_max6675()
max6675_previous_millis = millis();
max6675_temp = 0;
#ifdef PRR
#ifdef PRR
PRR &= ~(1<<PRSPI);
#elif defined PRR0
#elif defined(PRR0)
PRR0 &= ~(1<<PRSPI);
#endif
......@@ -1342,10 +1362,10 @@ int read_max6675()
// disable TT_MAX6675
WRITE(MAX6675_SS, 1);
if (max6675_temp & 4)
if (max6675_temp & 4)
{
// thermocouple open
max6675_temp = 2000;
max6675_temp = 4000;
}
else
{
......@@ -1354,7 +1374,8 @@ int read_max6675()
return max6675_temp;
}
#endif
#endif //HEATER_0_USES_MAX6675
// Timer 0 is shared with millies
......@@ -1760,9 +1781,6 @@ ISR(TIMER0_COMPB_vect)
#if defined(TEMP_0_PIN) && (TEMP_0_PIN > -1)
raw_temp_0_value += ADC;
#endif
#ifdef HEATER_0_USES_MAX6675 // TODO remove the blocking
raw_temp_0_value = read_max6675();
#endif
temp_state = 2;
break;
case 2: // Prepare TEMP_BED
......@@ -1883,7 +1901,9 @@ ISR(TIMER0_COMPB_vect)
{
if (!temp_meas_ready) //Only update the raw values if they have been read. Else we could be updating them during reading.
{
#ifndef HEATER_0_USES_MAX6675
current_temperature_raw[0] = raw_temp_0_value;
#endif
#ifndef SINGLENOZZLE
#if EXTRUDERS > 1
current_temperature_raw[1] = raw_temp_1_value;
......@@ -1920,14 +1940,18 @@ ISR(TIMER0_COMPB_vect)
#else
if(current_temperature_raw[0] >= maxttemp_raw[0]) {
#endif
#ifndef HEATER_0_USES_MAX6675
max_temp_error(0);
#endif
}
#if HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP
if(current_temperature_raw[0] >= minttemp_raw[0]) {
#else
if(current_temperature_raw[0] <= minttemp_raw[0]) {
#endif
#ifndef HEATER_0_USES_MAX6675
min_temp_error(0);
#endif
}
#ifndef SINGLENOZZLE
......
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