Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
75041a32
"tests/vscode:/vscode.git/clone" did not exist on "315df9ada056841c3acb6e4c1052b60ef61072e8"
Commit
75041a32
authored
Aug 08, 2015
by
devsaurus
Browse files
initial setup of ucg module
Hello World example is working
parent
9b384b4b
Changes
1
Hide whitespace changes
Inline
Side-by-side
app/modules/ucg.c
View file @
75041a32
...
@@ -12,7 +12,30 @@
...
@@ -12,7 +12,30 @@
//#include "u8g_config.h"
//#include "u8g_config.h"
typedef
struct
ucg_t
lucg_userdata_t
;
struct
_lucg_userdata_t
{
ucg_t
ucg
;
ucg_dev_fnptr
dev_cb
;
ucg_dev_fnptr
ext_cb
;
// For Print() function
ucg_int_t
tx
,
ty
;
uint8_t
tdir
;
};
typedef
struct
_lucg_userdata_t
lucg_userdata_t
;
#define delayMicroseconds os_delay_us
static
int16_t
ucg_com_esp8266_hw_spi
(
ucg_t
*
ucg
,
int16_t
msg
,
uint16_t
arg
,
uint8_t
*
data
);
// shorthand macro for the ucg structure inside the userdata
#define LUCG (&(lud->ucg))
// helper function: retrieve and check userdata argument
// helper function: retrieve and check userdata argument
...
@@ -24,7 +47,7 @@ static lucg_userdata_t *get_lud( lua_State *L )
...
@@ -24,7 +47,7 @@ static lucg_userdata_t *get_lud( lua_State *L )
}
}
// helper function: retrieve given number of integer arguments
// helper function: retrieve given number of integer arguments
static
void
lucg_get_int_args
(
lua_State
*
L
,
uint8_t
stack
,
uint8_t
num
,
u
cg_
int_t
*
args
)
static
void
lucg_get_int_args
(
lua_State
*
L
,
uint8_t
stack
,
uint8_t
num
,
uint
8
_t
*
args
)
{
{
while
(
num
--
>
0
)
while
(
num
--
>
0
)
{
{
...
@@ -32,6 +55,223 @@ static void lucg_get_int_args( lua_State *L, uint8_t stack, uint8_t num, ucg_int
...
@@ -32,6 +55,223 @@ static void lucg_get_int_args( lua_State *L, uint8_t stack, uint8_t num, ucg_int
}
}
}
}
// Lua: ucg.begin( self, fontmode )
static
int
lucg_begin
(
lua_State
*
L
)
{
lucg_userdata_t
*
lud
;
if
((
lud
=
get_lud
(
L
))
==
NULL
)
return
0
;
ucg_Init
(
LUCG
,
lud
->
dev_cb
,
lud
->
ext_cb
,
ucg_com_esp8266_hw_spi
);
ucg_int_t
fontmode
=
luaL_checkinteger
(
L
,
2
);
ucg_SetFontMode
(
LUCG
,
fontmode
);
return
0
;
}
// Lua: ucg.clearScreen( self )
static
int
lucg_clearScreen
(
lua_State
*
L
)
{
lucg_userdata_t
*
lud
;
if
((
lud
=
get_lud
(
L
))
==
NULL
)
return
0
;
ucg_ClearScreen
(
LUCG
);
return
0
;
}
// Lua: ucg.setColor( self, [idx], r, g, b )
static
int
lucg_setColor
(
lua_State
*
L
)
{
lucg_userdata_t
*
lud
;
if
((
lud
=
get_lud
(
L
))
==
NULL
)
return
0
;
uint8_t
args
[
3
];
lucg_get_int_args
(
L
,
2
,
3
,
args
);
int16_t
opt
=
luaL_optint
(
L
,
(
1
+
3
)
+
1
,
-
1
);
if
(
opt
<
0
)
ucg_SetColor
(
LUCG
,
0
,
args
[
0
],
args
[
1
],
args
[
2
]
);
else
ucg_SetColor
(
LUCG
,
args
[
0
],
args
[
1
],
args
[
2
],
opt
);
return
0
;
}
// Lua: ucg.setFont( self, font )
static
int
lucg_setFont
(
lua_State
*
L
)
{
lucg_userdata_t
*
lud
;
if
((
lud
=
get_lud
(
L
))
==
NULL
)
return
0
;
ucg_fntpgm_uint8_t
*
font
=
(
ucg_fntpgm_uint8_t
*
)
lua_touserdata
(
L
,
2
);
if
(
font
!=
NULL
)
ucg_SetFont
(
LUCG
,
font
);
return
0
;
}
// Lua: ucg.print( self, str )
static
int
lucg_print
(
lua_State
*
L
)
{
lucg_userdata_t
*
lud
;
if
((
lud
=
get_lud
(
L
))
==
NULL
)
return
0
;
const
char
*
s
=
luaL_checkstring
(
L
,
2
);
if
(
s
==
NULL
)
return
0
;
while
(
*
s
)
{
ucg_int_t
delta
;
delta
=
ucg_DrawGlyph
(
LUCG
,
lud
->
tx
,
lud
->
ty
,
lud
->
tdir
,
*
(
s
++
));
switch
(
lud
->
tdir
)
{
case
0
:
lud
->
tx
+=
delta
;
break
;
case
1
:
lud
->
ty
+=
delta
;
break
;
case
2
:
lud
->
tx
-=
delta
;
break
;
default:
case
3
:
lud
->
ty
-=
delta
;
break
;
}
}
return
0
;
}
// Lua: ucg.setPrintPos( self, x, y )
static
int
lucg_setPrintPos
(
lua_State
*
L
)
{
lucg_userdata_t
*
lud
;
if
((
lud
=
get_lud
(
L
))
==
NULL
)
return
0
;
uint8_t
args
[
2
];
lucg_get_int_args
(
L
,
2
,
2
,
args
);
lud
->
tx
=
args
[
0
];
lud
->
ty
=
args
[
1
];
return
0
;
}
static
int16_t
ucg_com_esp8266_hw_spi
(
ucg_t
*
ucg
,
int16_t
msg
,
uint16_t
arg
,
uint8_t
*
data
)
{
switch
(
msg
)
{
case
UCG_COM_MSG_POWER_UP
:
/* "data" is a pointer to ucg_com_info_t structure with the following information: */
/* ((ucg_com_info_t *)data)->serial_clk_speed value in nanoseconds */
/* ((ucg_com_info_t *)data)->parallel_clk_speed value in nanoseconds */
/* setup pins */
// we assume that the SPI interface was already initialized
// just care for the /CS and D/C pins
//platform_gpio_write( ucg->pin_list[0], value );
if
(
ucg
->
pin_list
[
UCG_PIN_RST
]
!=
UCG_PIN_VAL_NONE
)
platform_gpio_mode
(
ucg
->
pin_list
[
UCG_PIN_RST
],
PLATFORM_GPIO_OUTPUT
,
PLATFORM_GPIO_FLOAT
);
platform_gpio_mode
(
ucg
->
pin_list
[
UCG_PIN_CD
],
PLATFORM_GPIO_OUTPUT
,
PLATFORM_GPIO_FLOAT
);
if
(
ucg
->
pin_list
[
UCG_PIN_CS
]
!=
UCG_PIN_VAL_NONE
)
platform_gpio_mode
(
ucg
->
pin_list
[
UCG_PIN_CS
],
PLATFORM_GPIO_OUTPUT
,
PLATFORM_GPIO_FLOAT
);
break
;
case
UCG_COM_MSG_POWER_DOWN
:
break
;
case
UCG_COM_MSG_DELAY
:
delayMicroseconds
(
arg
);
break
;
case
UCG_COM_MSG_CHANGE_RESET_LINE
:
if
(
ucg
->
pin_list
[
UCG_PIN_RST
]
!=
UCG_PIN_VAL_NONE
)
platform_gpio_write
(
ucg
->
pin_list
[
UCG_PIN_RST
],
arg
);
break
;
case
UCG_COM_MSG_CHANGE_CS_LINE
:
if
(
ucg
->
pin_list
[
UCG_PIN_CS
]
!=
UCG_PIN_VAL_NONE
)
platform_gpio_write
(
ucg
->
pin_list
[
UCG_PIN_CS
],
arg
);
break
;
case
UCG_COM_MSG_CHANGE_CD_LINE
:
platform_gpio_write
(
ucg
->
pin_list
[
UCG_PIN_CD
],
arg
);
break
;
case
UCG_COM_MSG_SEND_BYTE
:
platform_spi_send_recv
(
1
,
arg
);
break
;
case
UCG_COM_MSG_REPEAT_1_BYTE
:
while
(
arg
>
0
)
{
platform_spi_send_recv
(
1
,
data
[
0
]
);
arg
--
;
}
break
;
case
UCG_COM_MSG_REPEAT_2_BYTES
:
while
(
arg
>
0
)
{
platform_spi_send_recv
(
1
,
data
[
0
]
);
platform_spi_send_recv
(
1
,
data
[
1
]
);
arg
--
;
}
break
;
case
UCG_COM_MSG_REPEAT_3_BYTES
:
while
(
arg
>
0
)
{
platform_spi_send_recv
(
1
,
data
[
0
]
);
platform_spi_send_recv
(
1
,
data
[
1
]
);
platform_spi_send_recv
(
1
,
data
[
2
]
);
arg
--
;
}
break
;
case
UCG_COM_MSG_SEND_STR
:
while
(
arg
>
0
)
{
platform_spi_send_recv
(
1
,
*
data
++
);
arg
--
;
}
break
;
case
UCG_COM_MSG_SEND_CD_DATA_SEQUENCE
:
while
(
arg
>
0
)
{
if
(
*
data
!=
0
)
{
/* set the data line directly, ignore the setting from UCG_CFG_CD */
if
(
*
data
==
1
)
{
platform_gpio_write
(
ucg
->
pin_list
[
UCG_PIN_CD
],
0
);
}
else
{
platform_gpio_write
(
ucg
->
pin_list
[
UCG_PIN_CD
],
1
);
}
}
data
++
;
platform_spi_send_recv
(
1
,
*
data
);
data
++
;
arg
--
;
}
break
;
}
return
1
;
}
// device destructor
// device destructor
...
@@ -46,6 +286,46 @@ static int lucg_close_display( lua_State *L )
...
@@ -46,6 +286,46 @@ static int lucg_close_display( lua_State *L )
}
}
static
int
lucg_ili9341_18x240x320_hw_spi
(
lua_State
*
L
)
{
unsigned
cs
=
luaL_checkinteger
(
L
,
1
);
if
(
cs
==
0
)
return
luaL_error
(
L
,
"CS pin required"
);
unsigned
dc
=
luaL_checkinteger
(
L
,
2
);
if
(
dc
==
0
)
return
luaL_error
(
L
,
"D/C pin required"
);
unsigned
res
=
luaL_optinteger
(
L
,
3
,
UCG_PIN_VAL_NONE
);
lucg_userdata_t
*
lud
=
(
lucg_userdata_t
*
)
lua_newuserdata
(
L
,
sizeof
(
lucg_userdata_t
)
);
// do a dummy init so that something usefull is part of the ucg structure
ucg_Init
(
LUCG
,
ucg_dev_default_cb
,
ucg_ext_none
,
(
ucg_com_fnptr
)
0
);
// reset cursor position
lud
->
tx
=
0
;
lud
->
ty
=
0
;
lud
->
tdir
=
0
;
// default direction
uint8_t
i
;
for
(
i
=
0
;
i
<
UCG_PIN_COUNT
;
i
++
)
lud
->
ucg
.
pin_list
[
i
]
=
UCG_PIN_VAL_NONE
;
lud
->
dev_cb
=
ucg_dev_ili9341_18x240x320
;
lud
->
ext_cb
=
ucg_ext_ili9341_18
;
lud
->
ucg
.
pin_list
[
UCG_PIN_RST
]
=
res
;
lud
->
ucg
.
pin_list
[
UCG_PIN_CD
]
=
dc
;
lud
->
ucg
.
pin_list
[
UCG_PIN_CS
]
=
cs
;
/* set its metatable */
luaL_getmetatable
(
L
,
"ucg.display"
);
lua_setmetatable
(
L
,
-
2
);
return
1
;
}
// Module function map
// Module function map
#define MIN_OPT_LEVEL 2
#define MIN_OPT_LEVEL 2
...
@@ -53,58 +333,13 @@ static int lucg_close_display( lua_State *L )
...
@@ -53,58 +333,13 @@ static int lucg_close_display( lua_State *L )
static
const
LUA_REG_TYPE
lucg_display_map
[]
=
static
const
LUA_REG_TYPE
lucg_display_map
[]
=
{
{
#if 0
{
LSTRKEY
(
"begin"
),
LFUNCVAL
(
lucg_begin
)
},
{ LSTRKEY( "begin" ), LFUNCVAL( lu8g_begin ) },
{
LSTRKEY
(
"clearScreen"
),
LFUNCVAL
(
lucg_clearScreen
)
},
{ LSTRKEY( "drawBitmap" ), LFUNCVAL( lu8g_drawBitmap ) },
{
LSTRKEY
(
"setColor"
),
LFUNCVAL
(
lucg_setColor
)
},
{ LSTRKEY( "drawBox" ), LFUNCVAL( lu8g_drawBox ) },
{
LSTRKEY
(
"setFont"
),
LFUNCVAL
(
lucg_setFont
)
},
{ LSTRKEY( "drawCircle" ), LFUNCVAL( lu8g_drawCircle ) },
{
LSTRKEY
(
"print"
),
LFUNCVAL
(
lucg_print
)
},
{ LSTRKEY( "drawDisc" ), LFUNCVAL( lu8g_drawDisc ) },
{
LSTRKEY
(
"setPrintPos"
),
LFUNCVAL
(
lucg_setPrintPos
)
},
{ LSTRKEY( "drawEllipse" ), LFUNCVAL( lu8g_drawEllipse ) },
{ LSTRKEY( "drawFilledEllipse" ), LFUNCVAL( lu8g_drawFilledEllipse ) },
{ LSTRKEY( "drawFrame" ), LFUNCVAL( lu8g_drawFrame ) },
{ LSTRKEY( "drawHLine" ), LFUNCVAL( lu8g_drawHLine ) },
{ LSTRKEY( "drawLine" ), LFUNCVAL( lu8g_drawLine ) },
{ LSTRKEY( "drawPixel" ), LFUNCVAL( lu8g_drawPixel ) },
{ LSTRKEY( "drawRBox" ), LFUNCVAL( lu8g_drawRBox ) },
{ LSTRKEY( "drawRFrame" ), LFUNCVAL( lu8g_drawRFrame ) },
{ LSTRKEY( "drawStr" ), LFUNCVAL( lu8g_drawStr ) },
{ LSTRKEY( "drawStr90" ), LFUNCVAL( lu8g_drawStr90 ) },
{ LSTRKEY( "drawStr180" ), LFUNCVAL( lu8g_drawStr180 ) },
{ LSTRKEY( "drawStr270" ), LFUNCVAL( lu8g_drawStr270 ) },
{ LSTRKEY( "drawTriangle" ), LFUNCVAL( lu8g_drawTriangle ) },
{ LSTRKEY( "drawVLine" ), LFUNCVAL( lu8g_drawVLine ) },
{ LSTRKEY( "drawXBM" ), LFUNCVAL( lu8g_drawXBM ) },
{ LSTRKEY( "firstPage" ), LFUNCVAL( lu8g_firstPage ) },
{ LSTRKEY( "getColorIndex" ), LFUNCVAL( lu8g_getColorIndex ) },
{ LSTRKEY( "getFontAscent" ), LFUNCVAL( lu8g_getFontAscent ) },
{ LSTRKEY( "getFontDescent" ), LFUNCVAL( lu8g_getFontDescent ) },
{ LSTRKEY( "getFontLineSpacing" ), LFUNCVAL( lu8g_getFontLineSpacing ) },
{ LSTRKEY( "getHeight" ), LFUNCVAL( lu8g_getHeight ) },
{ LSTRKEY( "getMode" ), LFUNCVAL( lu8g_getMode ) },
{ LSTRKEY( "getStrWidth" ), LFUNCVAL( lu8g_getStrWidth ) },
{ LSTRKEY( "getWidth" ), LFUNCVAL( lu8g_getWidth ) },
{ LSTRKEY( "nextPage" ), LFUNCVAL( lu8g_nextPage ) },
{ LSTRKEY( "setColorIndex" ), LFUNCVAL( lu8g_setColorIndex ) },
{ LSTRKEY( "setDefaultBackgroundColor" ), LFUNCVAL( lu8g_setDefaultBackgroundColor ) },
{ LSTRKEY( "setDefaultForegroundColor" ), LFUNCVAL( lu8g_setDefaultForegroundColor ) },
{ LSTRKEY( "setFont" ), LFUNCVAL( lu8g_setFont ) },
{ LSTRKEY( "setFontLineSpacingFactor" ), LFUNCVAL( lu8g_setFontLineSpacingFactor ) },
{ LSTRKEY( "setFontPosBaseline" ), LFUNCVAL( lu8g_setFontPosBaseline ) },
{ LSTRKEY( "setFontPosBottom" ), LFUNCVAL( lu8g_setFontPosBottom ) },
{ LSTRKEY( "setFontPosCenter" ), LFUNCVAL( lu8g_setFontPosCenter ) },
{ LSTRKEY( "setFontPosTop" ), LFUNCVAL( lu8g_setFontPosTop ) },
{ LSTRKEY( "setFontRefHeightAll" ), LFUNCVAL( lu8g_setFontRefHeightAll ) },
{ LSTRKEY( "setFontRefHeightExtendedText" ), LFUNCVAL( lu8g_setFontRefHeightExtendedText ) },
{ LSTRKEY( "setFontRefHeightText" ), LFUNCVAL( lu8g_setFontRefHeightText ) },
{ LSTRKEY( "setRot90" ), LFUNCVAL( lu8g_setRot90 ) },
{ LSTRKEY( "setRot180" ), LFUNCVAL( lu8g_setRot180 ) },
{ LSTRKEY( "setRot270" ), LFUNCVAL( lu8g_setRot270 ) },
{ LSTRKEY( "setScale2x2" ), LFUNCVAL( lu8g_setScale2x2 ) },
{ LSTRKEY( "sleepOff" ), LFUNCVAL( lu8g_sleepOff ) },
{ LSTRKEY( "sleepOn" ), LFUNCVAL( lu8g_sleepOn ) },
{ LSTRKEY( "undoRotation" ), LFUNCVAL( lu8g_undoRotation ) },
{ LSTRKEY( "undoScale" ), LFUNCVAL( lu8g_undoScale ) },
#endif
{
LSTRKEY
(
"__gc"
),
LFUNCVAL
(
lucg_close_display
)
},
{
LSTRKEY
(
"__gc"
),
LFUNCVAL
(
lucg_close_display
)
},
#if LUA_OPTIMIZE_MEMORY > 0
#if LUA_OPTIMIZE_MEMORY > 0
{
LSTRKEY
(
"__index"
),
LROVAL
(
lucg_display_map
)
},
{
LSTRKEY
(
"__index"
),
LROVAL
(
lucg_display_map
)
},
...
@@ -114,34 +349,16 @@ static const LUA_REG_TYPE lucg_display_map[] =
...
@@ -114,34 +349,16 @@ static const LUA_REG_TYPE lucg_display_map[] =
const
LUA_REG_TYPE
lucg_map
[]
=
const
LUA_REG_TYPE
lucg_map
[]
=
{
{
#if 0
{
LSTRKEY
(
"ili9341_18x240x320_hw_spi"
),
LFUNCVAL
(
lucg_ili9341_18x240x320_hw_spi
)
},
#undef U8G_DISPLAY_TABLE_ENTRY
#define U8G_DISPLAY_TABLE_ENTRY(device) { LSTRKEY( #device ), LFUNCVAL ( lu8g_ ##device ) },
U8G_DISPLAY_TABLE_I2C
U8G_DISPLAY_TABLE_SPI
#endif
#if LUA_OPTIMIZE_MEMORY > 0
#if LUA_OPTIMIZE_MEMORY > 0
// Register fonts
// Register fonts
#if 0
{
LSTRKEY
(
"font_ncenR12_tr"
),
LUDATA
(
(
void
*
)(
ucg_font_ncenR12_tr
)
)
},
#undef U8G_FONT_TABLE_ENTRY
#define U8G_FONT_TABLE_ENTRY(font) { LSTRKEY( #font ), LUDATA( (void *)(u8g_ ## font) ) },
U8G_FONT_TABLE
#endif
#if 0
// Font modes
// Options for circle/ ellipse drawing
{
LSTRKEY
(
"FONT_MODE_TRANSPARENT"
),
LNUMVAL
(
UCG_FONT_MODE_TRANSPARENT
)
},
{ LSTRKEY( "DRAW_UPPER_RIGHT" ), LNUMVAL( U8G_DRAW_UPPER_RIGHT ) },
{
LSTRKEY
(
"FONT_MODE_SOLID"
),
LNUMVAL
(
UCG_FONT_MODE_SOLID
)
},
{ LSTRKEY( "DRAW_UPPER_LEFT" ), LNUMVAL( U8G_DRAW_UPPER_LEFT ) },
{ LSTRKEY( "DRAW_LOWER_RIGHT" ), LNUMVAL( U8G_DRAW_LOWER_RIGHT ) },
{ LSTRKEY( "DRAW_LOWER_LEFT" ), LNUMVAL( U8G_DRAW_LOWER_LEFT ) },
{ LSTRKEY( "DRAW_ALL" ), LNUMVAL( U8G_DRAW_ALL ) },
// Display modes
{ LSTRKEY( "MODE_BW" ), LNUMVAL( U8G_MODE_BW ) },
{ LSTRKEY( "MODE_GRAY2BIT" ), LNUMVAL( U8G_MODE_GRAY2BIT ) },
#endif
{
LSTRKEY
(
"__metatable"
),
LROVAL
(
lucg_map
)
},
{
LSTRKEY
(
"__metatable"
),
LROVAL
(
lucg_map
)
},
#endif
#endif
...
@@ -164,23 +381,11 @@ LUALIB_API int luaopen_ucg( lua_State *L )
...
@@ -164,23 +381,11 @@ LUALIB_API int luaopen_ucg( lua_State *L )
// Module constants
// Module constants
// Register fonts
// Register fonts
#if 0
MOD_REG_LUDATA
(
L
,
"font_ncenR12_tr"
,
(
void
*
)(
ucg_font_ncenR12_tr
)
);
#undef U8G_FONT_TABLE_ENTRY
#define U8G_FONT_TABLE_ENTRY(font) MOD_REG_LUDATA( L, #font, (void *)(u8g_ ## font) );
U8G_FONT_TABLE
#endif
#if 0
// Options for circle/ ellipse drawing
MOD_REG_NUMBER( L, "DRAW_UPPER_RIGHT", U8G_DRAW_UPPER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_UPPER_LEFT", U8G_DRAW_UPPER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_LOWER_RIGHT", U8G_DRAW_UPPER_RIGHT );
MOD_REG_NUMBER( L, "DRAW_LOWER_LEFT", U8G_DRAW_UPPER_RIGHT );
// Display modes
// Font modes
MOD_REG_NUMBER( L, "MODE_BW", U8G_MODE_BW );
MOD_REG_NUMBER
(
L
,
"FONT_MODE_TRANSPARENT"
,
UCG_FONT_MODE_TRANSPARENT
);
MOD_REG_NUMBER( L, "MODE_GRAY2BIT", U8G_MODE_BW );
MOD_REG_NUMBER
(
L
,
"FONT_MODE_SOLID"
,
UCG_FONT_MODE_SOLID
);
#endif
// create metatable
// create metatable
luaL_newmetatable
(
L
,
"ucg.display"
);
luaL_newmetatable
(
L
,
"ucg.display"
);
...
@@ -189,7 +394,7 @@ LUALIB_API int luaopen_ucg( lua_State *L )
...
@@ -189,7 +394,7 @@ LUALIB_API int luaopen_ucg( lua_State *L )
lua_pushvalue
(
L
,
-
2
);
lua_pushvalue
(
L
,
-
2
);
lua_rawset
(
L
,
-
3
);
lua_rawset
(
L
,
-
3
);
// Setup the methods inside metatable
// Setup the methods inside metatable
luaL_register
(
L
,
NULL
,
ucg_display_map
);
luaL_register
(
L
,
NULL
,
l
ucg_display_map
);
return
1
;
return
1
;
#endif // #if LUA_OPTIMIZE_MEMORY > 0
#endif // #if LUA_OPTIMIZE_MEMORY > 0
...
...
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