Skip to content

Commit ea964ca

Browse files
committed
Merge branch 'develop'
2 parents 78b1bdc + 771b47f commit ea964ca

26 files changed

+522
-268
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ Building natively is done using the script `build-local.sh` (or manually). The i
1414
Requirements to build and run the code natively are: cmake (more to come).
1515

1616
## Startup scripts
17-
- [print3d_init](https://github.com/Doodle3D/print3d/blob/master/src/script/print3d_init). A init script that starts the print3d-manager as a deamon.
18-
- [print3d-manager](https://github.com/Doodle3D/print3d/blob/master/src/script/print3d-manager.sh). Uses inotifyd to start `print3d-new-device` when a new device is connected.
19-
- [print3d-new-device](https://github.com/Doodle3D/print3d/blob/master/src/script/print3d-new-device.sh). Figures out whether to start print3d in a seemingly crude way. If appropriate it tries to start `print3d-runner`
20-
- [print3d-runner.sh](https://github.com/Doodle3D/print3d/blob/master/src/script/print3d-runner.sh). Starts the print3d deamon.
17+
The Print3D package includes shell scripts that start print3D when a printer is connected.
18+
- `/etc.init.d/`[print3d](https://github.com/Doodle3D/print3d/blob/master/src/script/print3d_init). A init script that starts the print3d-manager as a deamon.
19+
- `/usr/libexec/`[print3d-manager](https://github.com/Doodle3D/print3d/blob/master/src/script/print3d-manager.sh). Uses inotifyd to start `print3d-new-device` when a new device is connected.
20+
- `/usr/libexec/`[print3d-new-device](https://github.com/Doodle3D/print3d/blob/master/src/script/print3d-new-device.sh). Figures out whether to start print3d in a seemingly crude way. If appropriate it tries to start `print3d-runner`
21+
- `/usr/libexec/`[print3d-runner.sh](https://github.com/Doodle3D/print3d/blob/master/src/script/print3d-runner.sh). Starts the print3d deamon.
2122

2223
## CMDline usage
2324
- **Print3D** is a deamon that communicates with the printer. It sends the printer gcode line for line from it's buffer, it automatically checks the temperature etc. Preverably it's started when a printer is connected.

build-local.sh

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,21 @@ CMAKE_FLAGS=("-G" "Unix Makefiles")
1010
INTERACTIVE_MODE=no
1111
TEST_MODE=no
1212

13+
command cmake --version > /dev/null 2>&1
14+
if [ $? -ne 0 ]; then
15+
echo "Error: this build script needs cmake."
16+
exit 1
17+
fi
18+
1319
for arg in $@; do
1420
case $arg in
1521
-h)
16-
echo "By default, the script builds for target '$BUILD_TARGET', specify one of 'Debug', 'Release', 'RelWithDebInfo' or 'MinSizeRel' to change this. Furthermore, the following arguments are valid:"
17-
echo "\t-h\tshow this help"
18-
echo "\t-i\trun interactive cmake configurator ($CCMAKE)"
22+
echo -e "By default, the script builds for target '$BUILD_TARGET', specify one of 'Debug', 'Release', 'RelWithDebInfo' or 'MinSizeRel' to change this."
23+
echo -e "The Lua front-end can be enabled/disabled by specifying 'Lua' or 'NoLua' correspondingly. Likewise, UCI supoprt can be enabled/disabled using 'Uci' or 'NoUci'."
24+
echo -e "Furthermore, the following arguments are valid:"
25+
echo -e "\t-h\tshow this help"
26+
echo -e "\t-i\trun interactive cmake configurator ($CCMAKE)"
27+
echo -e "\t-D*\tany -D define will be passed to cmake directly"
1928
exit
2029
;;
2130
-i)
@@ -27,15 +36,28 @@ for arg in $@; do
2736
*)
2837
if [ $arg == "Debug" -o $arg == "Release" -o $arg == "RelWithDebInfo" -o $arg == "MinSizeRel" ]; then
2938
BUILD_TARGET=$arg
39+
elif [ $arg == "Lua" ]; then
40+
LUA="ON"
41+
elif [ $arg == "NoLua" ]; then
42+
LUA="OFF"
43+
elif [ $arg == "Uci" ]; then
44+
UCI="ON"
45+
elif [ $arg == "NoUci" ]; then
46+
UCI="OFF"
47+
elif [[ $arg == \-D* ]]; then
48+
echo "adding arg '$arg'"
49+
CMAKE_FLAGS+=("$arg")
3050
else
31-
echo "$0: unknown argument: '$arg'"
51+
echo "$0: unknown argument: '$arg', try using the '-h' argument"
3252
exit 1
3353
fi
3454
;;
3555
esac
3656
done
3757

3858
CMAKE_FLAGS+=("-DCMAKE_BUILD_TYPE:STRING=$BUILD_TARGET")
59+
if [ "x$LUA" != "x" ]; then CMAKE_FLAGS+=("-DLUA_FRONTEND=$LUA"); fi
60+
if [ "x$UCI" != "x" ]; then CMAKE_FLAGS+=("-DENABLE_UCI=$UCI"); fi
3961

4062
if [ $INTERACTIVE_MODE == "yes" ]; then
4163
echo "Building for target '$BUILD_TARGET'... (interactive)"

src/CMakeLists.txt

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,19 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
1212
option(GENERATE_DOCS "generate documentation" OFF)
1313
#option(PRINT3D_DEBUG "debugging support" OFF)
1414

15-
#configure_file( ${CMAKE_SOURCE_DIR}/config.h.in ${CMAKE_SOURCE_DIR}/config.h )
15+
if(CMAKE_SYSTEM_NAME STREQUAL Linux AND CMAKE_CROSSCOMPILING)
16+
option(ENABLE_UCI "include UCI (OpenWrt only)" ON)
17+
else()
18+
option(ENABLE_UCI "disable UCI (OpenWrt only)" OFF)
19+
endif(CMAKE_SYSTEM_NAME STREQUAL Linux AND CMAKE_CROSSCOMPILING)
20+
21+
#define this here to make sure it has been initialized before configure_file()
22+
set(GCODE_BUFFER_MAX_SIZE_KB "3072" CACHE STRING "maximum gcode buffer size (KiB)")
23+
set(GCODE_BUFFER_SPLIT_SIZE_KB "8" CACHE STRING "gcode buffer split size (KiB)")
24+
25+
configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h")
26+
include_directories("${PROJECT_BINARY_DIR}")
27+
1628

1729
add_subdirectory(server)
1830
add_subdirectory(drivers)
@@ -29,9 +41,20 @@ target_link_libraries(logger ipc_shared)
2941
add_library(settings settings.c settings.h)
3042
set_target_properties(settings PROPERTIES COMPILE_FLAGS "-fPIC")
3143

32-
if(CMAKE_SYSTEM_NAME STREQUAL Linux AND CMAKE_CROSSCOMPILING)
33-
target_link_libraries(settings -luci)
34-
endif(CMAKE_SYSTEM_NAME STREQUAL Linux AND CMAKE_CROSSCOMPILING)
44+
if(ENABLE_UCI)
45+
if(CMAKE_SYSTEM_NAME STREQUAL Linux AND CMAKE_CROSSCOMPILING)
46+
target_link_libraries(settings -luci)
47+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUCI_ENABLED=1")
48+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUCI_ENABLED=1")
49+
else()
50+
message(SEND_ERROR "Cannot enable UCI since we're not compiling for OpenWrt")
51+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUCI_ENABLED=0")
52+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUCI_ENABLED=0")
53+
endif(CMAKE_SYSTEM_NAME STREQUAL Linux AND CMAKE_CROSSCOMPILING)
54+
else()
55+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUCI_ENABLED=0")
56+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUCI_ENABLED=0")
57+
endif(ENABLE_UCI)
3558

3659
add_library(timer Timer.cpp Timer.h)
3760

src/config.h.in

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* This file is part of the Doodle3D project (http://doodle3d.com).
3+
*
4+
* Copyright (c) 2013, Doodle3D
5+
* This software is licensed under the terms of the GNU GPL v2 or later.
6+
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
7+
*/
8+
9+
#ifndef CONFIG_H_SEEN
10+
#define CONFIG_H_SEEN
11+
12+
#define GCODE_BUFFER_MAX_SIZE_KB ${GCODE_BUFFER_MAX_SIZE_KB}
13+
#define GCODE_BUFFER_SPLIT_SIZE_KB ${GCODE_BUFFER_SPLIT_SIZE_KB}
14+
15+
#endif /* ! CONFIG_H_SEEN */

src/drivers/AbstractDriver.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <errno.h>
1010
#include <algorithm>
11+
#include <iostream>
1112
#include <sstream>
1213
#include "AbstractDriver.h"
1314
#include "../server/Server.h"
@@ -24,7 +25,8 @@ const string AbstractDriver::STATE_NAMES[] = { "unknown", "disconnected", "conne
2425
const bool AbstractDriver::REQUEST_EXIT_ON_PORT_FAIL = true;
2526

2627
AbstractDriver::AbstractDriver(Server& server, const string& serialPortPath, const uint32_t& baudrate)
27-
: temperature_(0),
28+
: heating_(false),
29+
temperature_(0),
2830
targetTemperature_(0),
2931
bedTemperature_(0),
3032
targetBedTemperature_(0),
@@ -101,7 +103,6 @@ void AbstractDriver::heatup(int temperature) {
101103
sendCode(oss.str());
102104
}
103105

104-
#include <iostream>
105106
/*
106107
* Print control
107108
*/
@@ -140,6 +141,10 @@ bool AbstractDriver::stopPrint() {
140141
/*
141142
* Getters and setters
142143
*/
144+
bool AbstractDriver::isHeating() const {
145+
return heating_;
146+
}
147+
143148
uint16_t AbstractDriver::getTemperature() const {
144149
return temperature_;
145150
}

src/drivers/AbstractDriver.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ class AbstractDriver {
7878

7979
void heatup(int temperature);
8080

81+
/*
82+
* Get cached heating state
83+
*/
84+
bool isHeating() const;
85+
8186
/*
8287
* Get cached extruder temperature
8388
*/
@@ -119,6 +124,7 @@ class AbstractDriver {
119124
protected:
120125
static const bool REQUEST_EXIT_ON_PORT_FAIL;
121126

127+
bool heating_;
122128
uint16_t temperature_;
123129
uint16_t targetTemperature_;
124130
uint16_t bedTemperature_;

src/drivers/GCodeBuffer.cpp

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,57 @@
1010
#include <algorithm>
1111
#include <stdlib.h>
1212
#include <string.h>
13+
#include "config.h"
14+
#include "../utils.h"
1315
using std::string;
1416

1517
//NOTE: see Server.cpp for comments on this macro
1618
#define LOG(lvl, fmt, ...) log_.log(lvl, "[MLD] " fmt, ##__VA_ARGS__)
1719

20+
#ifndef GCODE_BUFFER_MAX_SIZE_KB
21+
# define GCODE_BUFFER_MAX_SIZE_KB 1024 * 3
22+
#endif
23+
#ifndef GCODE_BUFFER_SPLIT_SIZE_KB
24+
# define GCODE_BUFFER_SPLIT_SIZE_KB 8
25+
#endif
26+
1827
//private
1928
const uint32_t GCodeBuffer::MAX_BUCKET_SIZE = 1024 * 50;
20-
const uint32_t GCodeBuffer::MAX_BUFFER_SIZE = 1024 * 1024 * 3;
29+
const uint32_t GCodeBuffer::MAX_BUFFER_SIZE = 1024 * GCODE_BUFFER_MAX_SIZE_KB; //set to 0 to disable (TODO: actually, this isn used at all currently)
30+
const uint32_t GCodeBuffer::BUFFER_SPLIT_SIZE = 1024 * GCODE_BUFFER_SPLIT_SIZE_KB; //append will split its input on the first newline after this size
2131

2232
GCodeBuffer::GCodeBuffer()
2333
: currentLine_(0), bufferedLines_(0), totalLines_(0), bufferSize_(0), log_(Logger::getInstance())
24-
{ /* empty */ }
34+
{
35+
LOG(Logger::VERBOSE, "init: max size: %luKiB, bucket size: %luKiB, split size: %luKiB",
36+
MAX_BUFFER_SIZE, MAX_BUCKET_SIZE, BUFFER_SPLIT_SIZE);
37+
}
2538

2639
void GCodeBuffer::set(const string &gcode) {
2740
clear();
2841
append(gcode);
2942
}
3043

31-
//NOTE: currently this function will never split given gcode into parts for
32-
//separate buckets, so MAX_BUCKET_SIZE is not a strict limit
44+
//NOTE: this function splits given code into chunk of approximately BUFFER_SPLIT_SIZE.
45+
//without this, huge chunks (>1MB) would make repeated erase operations very inefficient.
3346
void GCodeBuffer::append(const string &gcode) {
34-
35-
if (buckets_.size() == 0) buckets_.push_back(new string());
36-
string *b = buckets_.back();
37-
if (b->length() >= MAX_BUCKET_SIZE) {
38-
b = new string();
39-
buckets_.push_back(b);
47+
uint32_t startTime = getMillis();
48+
int count = 0;
49+
size_t size = gcode.size();
50+
size_t start = 0;
51+
52+
while(start < gcode.size()) {
53+
size_t len = BUFFER_SPLIT_SIZE;
54+
size_t nl = gcode.find('\n', start + len);
55+
56+
len = (nl != string::npos) ? nl - start + 1 : gcode.size() - start;
57+
appendChunk(gcode.substr(start, len));
58+
count++;
59+
start += len;
4060
}
4161

42-
size_t pos = b->length();
43-
b->append(gcode);
44-
cleanupGCode(b, pos);
45-
bufferSize_ += gcode.length();
46-
updateStats(b, pos);
62+
LOG(Logger::VERBOSE, "append(): added %zu bytes of gcode (%i chunks) in %lu ms",
63+
size, count, getMillis() - startTime);
4764
}
4865

4966
void GCodeBuffer::clear() {
@@ -137,10 +154,27 @@ bool GCodeBuffer::eraseLine(size_t amount) {
137154
return pos != string::npos;
138155
}
139156

157+
140158
/*********************
141159
* PRIVATE FUNCTIONS *
142160
*********************/
143161

162+
void GCodeBuffer::appendChunk(const string &gcode) {
163+
164+
if (buckets_.size() == 0) buckets_.push_back(new string());
165+
string *b = buckets_.back();
166+
if (b->length() >= MAX_BUCKET_SIZE) {
167+
b = new string();
168+
buckets_.push_back(b);
169+
}
170+
171+
size_t pos = b->length();
172+
b->append(gcode);
173+
cleanupGCode(b, pos);
174+
bufferSize_ += gcode.length();
175+
updateStats(b, pos);
176+
}
177+
144178
void GCodeBuffer::updateStats(string *buffer, size_t pos) {
145179
int32_t addedLineCount = std::count(buffer->begin() + pos, buffer->end(), '\n');
146180
if (buffer->length() > 0 && buffer->at(buffer->length() - 1) != '\n') addedLineCount++;
@@ -150,6 +184,8 @@ void GCodeBuffer::updateStats(string *buffer, size_t pos) {
150184
}
151185

152186
void GCodeBuffer::cleanupGCode(string *buffer, size_t pos) {
187+
uint32_t startTime = getMillis(), commentDelta, doubleNLDelta, endTime;
188+
153189
// LOG(Logger::BULK, "cleanupGCode");
154190
// LOG(Logger::BULK, " pos: %i",pos);
155191
// LOG(Logger::BULK, " ////////// buffer: ");
@@ -174,6 +210,8 @@ void GCodeBuffer::cleanupGCode(string *buffer, size_t pos) {
174210
}
175211
}
176212

213+
commentDelta = getMillis();
214+
177215
//replace \n\n with \n
178216
std::size_t posDoubleNewline = pos;
179217
// -1 to make sure we also check the first line of the part we're checking
@@ -183,20 +221,28 @@ void GCodeBuffer::cleanupGCode(string *buffer, size_t pos) {
183221
buffer->replace(posDoubleNewline, 2, "\n");
184222
}
185223

224+
doubleNLDelta = getMillis();
225+
186226
// remove empty first line
187227
if(buffer->find("\n",0) == 0) {
188228
buffer->erase(0, 1);
189229
LOG(Logger::BULK, " erase first empty line");
190230
}
191231

192-
// Make sure we end with an empty line
193-
char& lastChar = buffer->at(buffer->length()-1);
194-
if(lastChar != '\n') {
195-
buffer->append("\n");
196-
// LOG(Logger::BULK, " add empty line at end");
232+
// Make sure we end with an empty line except when the buffer is empty
233+
if (buffer->length() > 0) {
234+
char lastChar = buffer->at(buffer->length()-1);
235+
if(lastChar != '\n') {
236+
buffer->append("\n");
237+
// LOG(Logger::BULK, " add empty line at end");
238+
}
197239
}
198240
// LOG(Logger::BULK, " ////////// >>>buffer: ");
199241
// LOG(Logger::BULK, " \n%s\n////////// end >>>buffer",buffer->c_str());
200242

201243
bufferSize_ -= (buflen - buffer->length());
244+
245+
endTime = getMillis();
246+
LOG(Logger::BULK, "cleanupGCode(): took %lu ms (%lu removing comments, %lu removing double newlines)",
247+
endTime - startTime, commentDelta - startTime, doubleNLDelta - commentDelta);
202248
}

src/drivers/GCodeBuffer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class GCodeBuffer {
3939
private:
4040
static const uint32_t MAX_BUCKET_SIZE;
4141
static const uint32_t MAX_BUFFER_SIZE;
42+
static const uint32_t BUFFER_SPLIT_SIZE;
4243

4344
deque_stringP buckets_;
4445
int32_t currentLine_;
@@ -48,6 +49,7 @@ class GCodeBuffer {
4849

4950
Logger& log_;
5051

52+
void appendChunk(const std::string &gcode);
5153
void updateStats(std::string *buffer, size_t pos);
5254
void cleanupGCode(std::string *buffer, size_t pos);
5355
};

src/drivers/MakerbotDriver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ const AbstractDriver::DriverInfo& MakerbotDriver::getDriverInfo() {
200200
supportedFirmware.push_back( AbstractDriver::FirmwareDescription("makerbot_replicator2x") );
201201
supportedFirmware.push_back( AbstractDriver::FirmwareDescription("makerbot_thingomatic") );
202202
supportedFirmware.push_back( AbstractDriver::FirmwareDescription("makerbot_generic") );
203+
supportedFirmware.push_back( AbstractDriver::FirmwareDescription("wanhao_duplicator4") );
203204

204205
info.supportedFirmware = supportedFirmware;
205206
info.creator = &MakerbotDriver::create;

0 commit comments

Comments
 (0)