Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
MarlinKimbra
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
machinery
MarlinKimbra
Commits
b3e49e9a
Commit
b3e49e9a
authored
Jan 08, 2016
by
MagoKimbra
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix
parent
cc967a46
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
38 additions
and
175 deletions
+38
-175
base.h
MarlinKimbra/base.h
+1
-1
Sd2Card.h
MarlinKimbra/module/Sd2Card.h
+1
-0
SdBaseFile.cpp
MarlinKimbra/module/SdBaseFile.cpp
+3
-3
SdBaseFile.h
MarlinKimbra/module/SdBaseFile.h
+5
-5
external_dac.cpp
MarlinKimbra/module/external_dac.cpp
+0
-108
external_dac.h
MarlinKimbra/module/external_dac.h
+0
-11
nextion_lcd.cpp
MarlinKimbra/module/nextion_lcd.cpp
+28
-47
No files found.
MarlinKimbra/base.h
View file @
b3e49e9a
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
#include <string.h>
#include <string.h>
#include <inttypes.h>
#include <inttypes.h>
#ifdef __SAM3X8E__
#ifdef __SAM3X8E__
#include "HAL.h"
#include "
module/
HAL.h"
#else
#else
// Arduino < 1.0.0 does not define this, so we need to do it ourselves
// Arduino < 1.0.0 does not define this, so we need to do it ourselves
#ifndef analogInputToDigitalPin
#ifndef analogInputToDigitalPin
...
...
MarlinKimbra/module/Sd2Card.h
View file @
b3e49e9a
...
@@ -32,6 +32,7 @@
...
@@ -32,6 +32,7 @@
#include "SdFatConfig.h"
#include "SdFatConfig.h"
#include "Sd2PinMap.h"
#include "Sd2PinMap.h"
#include "SdInfo.h"
#include "SdInfo.h"
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// SPI speed is F_CPU/2^(1 + index), 0 <= index <= 6
// SPI speed is F_CPU/2^(1 + index), 0 <= index <= 6
/** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */
/** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */
...
...
MarlinKimbra/module/SdBaseFile.cpp
View file @
b3e49e9a
...
@@ -297,7 +297,7 @@ bool SdBaseFile::getFilename(char* name) {
...
@@ -297,7 +297,7 @@ bool SdBaseFile::getFilename(char* name) {
return
true
;
return
true
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SdBaseFile
::
getpos
(
fp
os_t
*
pos
)
{
void
SdBaseFile
::
getpos
(
FatP
os_t
*
pos
)
{
pos
->
position
=
curPosition_
;
pos
->
position
=
curPosition_
;
pos
->
cluster
=
curCluster_
;
pos
->
cluster
=
curCluster_
;
}
}
...
@@ -928,7 +928,7 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
...
@@ -928,7 +928,7 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
* \return The byte if no error and not at eof else -1;
* \return The byte if no error and not at eof else -1;
*/
*/
int
SdBaseFile
::
peek
()
{
int
SdBaseFile
::
peek
()
{
fp
os_t
pos
;
FatP
os_t
pos
;
getpos
(
&
pos
);
getpos
(
&
pos
);
int
c
=
read
();
int
c
=
read
();
if
(
c
>=
0
)
setpos
(
&
pos
);
if
(
c
>=
0
)
setpos
(
&
pos
);
...
@@ -1484,7 +1484,7 @@ bool SdBaseFile::seekSet(uint32_t pos) {
...
@@ -1484,7 +1484,7 @@ bool SdBaseFile::seekSet(uint32_t pos) {
return
false
;
return
false
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SdBaseFile
::
setpos
(
fp
os_t
*
pos
)
{
void
SdBaseFile
::
setpos
(
FatP
os_t
*
pos
)
{
curPosition_
=
pos
->
position
;
curPosition_
=
pos
->
position
;
curCluster_
=
pos
->
cluster
;
curCluster_
=
pos
->
cluster
;
}
}
...
...
MarlinKimbra/module/SdBaseFile.h
View file @
b3e49e9a
...
@@ -27,16 +27,16 @@
...
@@ -27,16 +27,16 @@
#include "SdVolume.h"
#include "SdVolume.h"
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/**
/**
* \struct
fp
os_t
* \struct
FatP
os_t
* \brief internal type for istream
* \brief internal type for istream
* do not use in user apps
* do not use in user apps
*/
*/
struct
fp
os_t
{
struct
FatP
os_t
{
/** stream position */
/** stream position */
uint32_t
position
;
uint32_t
position
;
/** cluster for position */
/** cluster for position */
uint32_t
cluster
;
uint32_t
cluster
;
fp
os_t
()
:
position
(
0
),
cluster
(
0
)
{}
FatP
os_t
()
:
position
(
0
),
cluster
(
0
)
{}
};
};
// use the gnu style oflag in open()
// use the gnu style oflag in open()
...
@@ -192,11 +192,11 @@ class SdBaseFile {
...
@@ -192,11 +192,11 @@ class SdBaseFile {
/** get position for streams
/** get position for streams
* \param[out] pos struct to receive position
* \param[out] pos struct to receive position
*/
*/
void
getpos
(
fp
os_t
*
pos
);
void
getpos
(
FatP
os_t
*
pos
);
/** set position for streams
/** set position for streams
* \param[out] pos struct with value for new position
* \param[out] pos struct with value for new position
*/
*/
void
setpos
(
fp
os_t
*
pos
);
void
setpos
(
FatP
os_t
*
pos
);
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
close
();
bool
close
();
bool
contiguousRange
(
uint32_t
*
bgnBlock
,
uint32_t
*
endBlock
);
bool
contiguousRange
(
uint32_t
*
bgnBlock
,
uint32_t
*
endBlock
);
...
...
MarlinKimbra/module/external_dac.cpp
deleted
100644 → 0
View file @
cc967a46
/***************************************************************
*
* Externa DAC for Alligator Board
*
****************************************************************/
#include "../base.h"
#if MB(ALLIGATOR)
#include "stepper.h"
#include "external_dac.h"
ExternalDac
::
ExternalDac
()
{
return
;
}
void
ExternalDac
::
begin
()
{
uint8_t
externalDac_buf
[
2
]
=
{
0x20
,
0x00
};
//all off
// All SPI chip-select HIGH
pinMode
(
DAC0_SYNC
,
OUTPUT
);
digitalWrite
(
DAC0_SYNC
,
HIGH
);
#if DRIVER_EXTRUDERS > 1
pinMode
(
DAC1_SYNC
,
OUTPUT
);
digitalWrite
(
DAC1_SYNC
,
HIGH
);
#endif
digitalWrite
(
SPI_EEPROM1_CS
,
HIGH
);
digitalWrite
(
SPI_EEPROM2_CS
,
HIGH
);
digitalWrite
(
SPI_FLASH_CS
,
HIGH
);
digitalWrite
(
SDSS
,
HIGH
);
spiBegin
();
//init onboard DAC
delayMicroseconds
(
2U
);
digitalWrite
(
DAC0_SYNC
,
LOW
);
delayMicroseconds
(
2U
);
digitalWrite
(
DAC0_SYNC
,
HIGH
);
delayMicroseconds
(
2U
);
digitalWrite
(
DAC0_SYNC
,
LOW
);
spiSend
(
SPI_CHAN_DAC
,
externalDac_buf
,
2
);
digitalWrite
(
DAC0_SYNC
,
HIGH
);
#if DRIVER_EXTRUDERS > 1
//init Piggy DAC
delayMicroseconds
(
2U
);
digitalWrite
(
DAC1_SYNC
,
LOW
);
delayMicroseconds
(
2U
);
digitalWrite
(
DAC1_SYNC
,
HIGH
);
delayMicroseconds
(
2U
);
digitalWrite
(
DAC1_SYNC
,
LOW
);
spiSend
(
SPI_CHAN_DAC
,
externalDac_buf
,
2
);
digitalWrite
(
DAC1_SYNC
,
HIGH
);
#endif
return
;
}
void
ExternalDac
::
setValue
(
uint8_t
channel
,
uint8_t
value
)
{
if
(
channel
>=
7
)
// max channel (X,Y,Z,E0,E1,E2,E3)
return
;
if
(
value
>
255
)
value
=
255
;
uint8_t
externalDac_buf
[
2
]
=
{
0x10
,
0x00
};
if
(
channel
>
3
)
externalDac_buf
[
0
]
|=
(
7
-
channel
<<
6
);
else
externalDac_buf
[
0
]
|=
(
3
-
channel
<<
6
);
externalDac_buf
[
0
]
|=
(
value
>>
4
);
externalDac_buf
[
1
]
|=
(
value
<<
4
);
// All SPI chip-select HIGH
digitalWrite
(
DAC0_SYNC
,
HIGH
);
#if DRIVER_EXTRUDERS > 1
digitalWrite
(
DAC1_SYNC
,
HIGH
);
#endif
digitalWrite
(
SPI_EEPROM1_CS
,
HIGH
);
digitalWrite
(
SPI_EEPROM2_CS
,
HIGH
);
digitalWrite
(
SPI_FLASH_CS
,
HIGH
);
digitalWrite
(
SDSS
,
HIGH
);
if
(
channel
>
3
)
{
// DAC Piggy E1,E2,E3
digitalWrite
(
DAC1_SYNC
,
LOW
);
delayMicroseconds
(
2U
);
digitalWrite
(
DAC1_SYNC
,
HIGH
);
delayMicroseconds
(
2U
);
digitalWrite
(
DAC1_SYNC
,
LOW
);
}
else
{
// DAC onboard X,Y,Z,E0
digitalWrite
(
DAC0_SYNC
,
LOW
);
delayMicroseconds
(
2U
);
digitalWrite
(
DAC0_SYNC
,
HIGH
);
delayMicroseconds
(
2U
);
digitalWrite
(
DAC0_SYNC
,
LOW
);
}
delayMicroseconds
(
2U
);
spiSend
(
SPI_CHAN_DAC
,
externalDac_buf
,
2
);
return
;
}
#endif
MarlinKimbra/module/external_dac.h
deleted
100644 → 0
View file @
cc967a46
#ifndef _EXTERNAL_DAC_H
#define _EXTERNAL_DAC_H
class
ExternalDac
{
public
:
ExternalDac
();
static
void
begin
(
void
);
static
void
setValue
(
uint8_t
channel
,
uint8_t
value
);
};
#endif //_EXTERNAL_DAC_H
MarlinKimbra/module/nextion_lcd.cpp
View file @
b3e49e9a
...
@@ -17,10 +17,8 @@
...
@@ -17,10 +17,8 @@
#include "nextion_gfx.h"
#include "nextion_gfx.h"
#include <Nextion.h>
#include <Nextion.h>
const
float
MaxWave
=
0.2
;
bool
NextionON
=
false
;
bool
NextionON
=
false
;
bool
PageInfo
=
false
;
bool
PageInfo
=
false
;
bool
gfxON
=
false
;
char
buffer
[
100
]
=
{
0
};
char
buffer
[
100
]
=
{
0
};
uint32_t
slidermaxval
=
20
;
uint32_t
slidermaxval
=
20
;
char
lcd_status_message
[
30
]
=
WELCOME_MSG
;
char
lcd_status_message
[
30
]
=
WELCOME_MSG
;
...
@@ -28,7 +26,7 @@
...
@@ -28,7 +26,7 @@
static
millis_t
next_lcd_update_ms
;
static
millis_t
next_lcd_update_ms
;
#if ENABLED(NEXTION_GFX)
#if ENABLED(NEXTION_GFX)
GFX
gfx
=
GFX
(
196
,
194
);
GFX
gfx
=
GFX
(
200
,
190
);
#endif
#endif
// Page
// Page
...
@@ -41,10 +39,10 @@
...
@@ -41,10 +39,10 @@
NexPage
Pmove
=
NexPage
(
6
,
0
,
"move"
);
NexPage
Pmove
=
NexPage
(
6
,
0
,
"move"
);
// Text
// Text
NexText
Hotend0
=
NexText
(
1
,
1
,
"t0"
);
NexText
Hotend0
=
NexText
(
1
,
2
,
"t0"
);
NexText
Hotend1
=
NexText
(
1
,
4
,
"t1"
);
NexText
Hotend1
=
NexText
(
1
,
4
,
"t1"
);
NexText
Hotend2
=
NexText
(
1
,
5
,
"t
2"
);
NexText
Hotend2
1
=
NexText
(
1
,
5
,
"h
2"
);
NexText
Hotend2
1
=
NexText
(
1
,
6
,
"h
2"
);
NexText
Hotend2
=
NexText
(
1
,
6
,
"t
2"
);
NexText
LedStatus
=
NexText
(
1
,
7
,
"t4"
);
NexText
LedStatus
=
NexText
(
1
,
7
,
"t4"
);
NexText
LedCoord
=
NexText
(
1
,
8
,
"t5"
);
NexText
LedCoord
=
NexText
(
1
,
8
,
"t5"
);
NexText
set0
=
NexText
(
2
,
2
,
"set0"
);
NexText
set0
=
NexText
(
2
,
2
,
"set0"
);
...
@@ -57,15 +55,15 @@
...
@@ -57,15 +55,15 @@
NexText
sdfolder
=
NexText
(
4
,
23
,
"sdfolder"
);
NexText
sdfolder
=
NexText
(
4
,
23
,
"sdfolder"
);
// Picture
// Picture
NexPicture
Menu
=
NexPicture
(
1
,
10
,
"p0"
);
NexPicture
Menu
=
NexPicture
(
1
,
9
,
"p0"
);
NexPicture
MSD
=
NexPicture
(
1
,
1
1
,
"p1"
);
NexPicture
MSD
=
NexPicture
(
1
,
1
0
,
"p1"
);
NexPicture
MSetup
=
NexPicture
(
1
,
1
2
,
"p2"
);
NexPicture
MSetup
=
NexPicture
(
1
,
1
1
,
"p2"
);
NexPicture
Hend0
=
NexPicture
(
1
,
1
3
,
"p3"
);
NexPicture
Hend0
=
NexPicture
(
1
,
1
2
,
"p3"
);
NexPicture
Hend1
=
NexPicture
(
1
,
14
,
"p4"
);
NexPicture
Hend1
=
NexPicture
(
1
,
14
,
"p4"
);
NexPicture
Hend2
=
NexPicture
(
1
,
1
5
,
"p5"
);
NexPicture
Hend2
=
NexPicture
(
1
,
1
6
,
"p5"
);
NexPicture
Fanpic
=
NexPicture
(
1
,
1
9
,
"p6"
);
NexPicture
Fanpic
=
NexPicture
(
1
,
1
8
,
"p6"
);
NexPicture
NPlay
=
NexPicture
(
1
,
2
7
,
"p7"
);
NexPicture
NPlay
=
NexPicture
(
1
,
2
4
,
"p7"
);
NexPicture
NStop
=
NexPicture
(
1
,
2
8
,
"p8"
);
NexPicture
NStop
=
NexPicture
(
1
,
2
5
,
"p8"
);
NexPicture
Exit1
=
NexPicture
(
3
,
4
,
"p3"
);
NexPicture
Exit1
=
NexPicture
(
3
,
4
,
"p3"
);
NexPicture
Folder0
=
NexPicture
(
4
,
9
,
"p0"
);
NexPicture
Folder0
=
NexPicture
(
4
,
9
,
"p0"
);
NexPicture
Folder1
=
NexPicture
(
4
,
10
,
"p1"
);
NexPicture
Folder1
=
NexPicture
(
4
,
10
,
"p1"
);
...
@@ -86,32 +84,29 @@
...
@@ -86,32 +84,29 @@
NexPicture
ZDown
=
NexPicture
(
6
,
12
,
"p11"
);
NexPicture
ZDown
=
NexPicture
(
6
,
12
,
"p11"
);
// Progress Bar
// Progress Bar
NexProgressBar
sdbar
=
NexProgressBar
(
1
,
2
6
,
"j0"
);
NexProgressBar
sdbar
=
NexProgressBar
(
1
,
2
3
,
"j0"
);
// Slider
// Slider
NexSlider
sdlist
=
NexSlider
(
4
,
1
,
"h0"
);
NexSlider
sdlist
=
NexSlider
(
4
,
1
,
"h0"
);
// Wafeform
// Wafeform
NexWaveform
Graph0
=
NexWaveform
(
1
,
9
,
"s0"
);
NexWaveform
Graph1
=
NexWaveform
(
1
,
24
,
"s1"
);
NexWaveform
Graph2
=
NexWaveform
(
1
,
25
,
"s2"
);
// Touch area
// Touch area
NexHotspot
hot0
=
NexHotspot
(
1
,
1
4
,
"hot0"
);
NexHotspot
hot0
=
NexHotspot
(
1
,
1
3
,
"hot0"
);
NexHotspot
hot1
=
NexHotspot
(
1
,
1
6
,
"hot1"
);
NexHotspot
hot1
=
NexHotspot
(
1
,
1
5
,
"hot1"
);
NexHotspot
hot2
=
NexHotspot
(
1
,
1
8
,
"hot2"
);
NexHotspot
hot2
=
NexHotspot
(
1
,
1
7
,
"hot2"
);
NexHotspot
m11
=
NexHotspot
(
2
,
14
,
"m11"
);
NexHotspot
m11
=
NexHotspot
(
2
,
14
,
"m11"
);
NexHotspot
tup
=
NexHotspot
(
2
,
16
,
"tup"
);
NexHotspot
tup
=
NexHotspot
(
2
,
16
,
"tup"
);
NexHotspot
tdown
=
NexHotspot
(
2
,
17
,
"tdown"
);
NexHotspot
tdown
=
NexHotspot
(
2
,
17
,
"tdown"
);
// Timer
// Timer
NexTimer
startimer
=
NexTimer
(
0
,
1
,
"tm0"
);
NexTimer
startimer
=
NexTimer
(
0
,
1
,
"tm0"
);
NexTimer
fantimer
=
NexTimer
(
1
,
2
3
,
"tm0"
);
NexTimer
fantimer
=
NexTimer
(
1
,
2
2
,
"tm0"
);
// Variable
// Variable
NexVar
Hotend
=
NexVar
(
1
,
20
,
"he"
);
NexVar
Hotend
=
NexVar
(
1
,
19
,
"he"
);
NexVar
Bed
=
NexVar
(
1
,
20
,
"bed"
);
NexVar
set1
=
NexVar
(
2
,
17
,
"set1"
);
NexVar
set1
=
NexVar
(
2
,
17
,
"set1"
);
NexVar
Bed
=
NexVar
(
1
,
21
,
"bed"
);
NexVar
filename0
=
NexVar
(
4
,
19
,
"va0"
);
NexVar
filename0
=
NexVar
(
4
,
19
,
"va0"
);
NexVar
filename1
=
NexVar
(
4
,
20
,
"va1"
);
NexVar
filename1
=
NexVar
(
4
,
20
,
"va1"
);
NexVar
filename2
=
NexVar
(
4
,
21
,
"va2"
);
NexVar
filename2
=
NexVar
(
4
,
21
,
"va2"
);
...
@@ -165,14 +160,6 @@
...
@@ -165,14 +160,6 @@
NULL
NULL
};
};
NexWaveform
*
graph_list
[]
=
{
&
Graph0
,
&
Graph1
,
&
Graph2
,
NULL
};
NexText
*
row_list
[]
=
NexText
*
row_list
[]
=
{
{
&
sdrow0
,
&
sdrow0
,
...
@@ -211,6 +198,10 @@
...
@@ -211,6 +198,10 @@
PageInfo
=
true
;
PageInfo
=
true
;
#if ENABLED(NEXTION_GFX)
gfx_clear
(
X_MAX_POS
,
Y_MAX_POS
,
Z_MAX_POS
);
#endif
#if HAS_TEMP_0
#if HAS_TEMP_0
Hotend
.
setValue
(
1
);
Hotend
.
setValue
(
1
);
#endif
#endif
...
@@ -278,7 +269,6 @@
...
@@ -278,7 +269,6 @@
static
void
setpagesdcard
()
{
static
void
setpagesdcard
()
{
PageInfo
=
false
;
PageInfo
=
false
;
gfxON
=
false
;
Psdcard
.
show
();
Psdcard
.
show
();
uint16_t
fileCnt
=
card
.
getnrfilenames
();
uint16_t
fileCnt
=
card
.
getnrfilenames
();
...
@@ -436,12 +426,10 @@
...
@@ -436,12 +426,10 @@
void
setpagePopCallback
(
void
*
ptr
)
{
void
setpagePopCallback
(
void
*
ptr
)
{
if
(
ptr
==
&
Menu
)
{
if
(
ptr
==
&
Menu
)
{
PageInfo
=
false
;
PageInfo
=
false
;
gfxON
=
false
;
Pmenu
.
show
();
Pmenu
.
show
();
}
}
else
if
(
ptr
==
&
MSetup
)
{
else
if
(
ptr
==
&
MSetup
)
{
PageInfo
=
false
;
PageInfo
=
false
;
gfxON
=
false
;
Psetup
.
show
();
Psetup
.
show
();
}
}
...
@@ -484,7 +472,7 @@
...
@@ -484,7 +472,7 @@
#endif
#endif
void
lcd_init
()
{
void
lcd_init
()
{
delay
_ms
(
1000
);
delay
(
1000
);
NextionON
=
nexInit
();
NextionON
=
nexInit
();
if
(
!
NextionON
)
{
if
(
!
NextionON
)
{
...
@@ -561,11 +549,6 @@
...
@@ -561,11 +549,6 @@
hotend_list
[
h
]
->
setText
(
buffer
);
hotend_list
[
h
]
->
setText
(
buffer
);
hotend_list
[
h
]
->
setColor
(
color
);
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
()
{
static
void
coordtoLCD
()
{
...
@@ -678,19 +661,17 @@
...
@@ -678,19 +661,17 @@
#if ENABLED(NEXTION_GFX)
#if ENABLED(NEXTION_GFX)
void
gfx_clear
(
float
x
,
float
y
,
float
z
)
{
void
gfx_clear
(
float
x
,
float
y
,
float
z
)
{
if
(
PageInfo
)
{
if
(
PageInfo
)
gfx
.
clear
(
x
,
y
,
z
);
gfx
.
clear
(
x
,
y
,
z
);
gfxON
=
true
;
}
}
}
void
gfx_cursor_to
(
float
x
,
float
y
,
float
z
)
{
void
gfx_cursor_to
(
float
x
,
float
y
,
float
z
)
{
if
(
PageInfo
&&
gfxON
)
if
(
PageInfo
)
gfx
.
cursor_to
(
x
,
y
,
z
);
gfx
.
cursor_to
(
x
,
y
,
z
);
}
}
void
gfx_line_to
(
float
x
,
float
y
,
float
z
){
void
gfx_line_to
(
float
x
,
float
y
,
float
z
){
if
(
PageInfo
&&
gfxON
)
if
(
PageInfo
)
gfx
.
line_to
(
VC_TOOL
,
x
,
y
,
z
);
gfx
.
line_to
(
VC_TOOL
,
x
,
y
,
z
);
}
}
#endif
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment