Skip to content

Commit c7c1408

Browse files
authored
Implement basic support for XL and Mk4 (#120)
* Misc cleanup - Add XL support (Closes #118) - Add MK4 support (Closes #119) - Fixes #75 * Update doc generation, lint workflow * Fix lint errors
1 parent ccae099 commit c7c1408

File tree

120 files changed

+17080
-2157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+17080
-2157
lines changed

.github/workflows/lint.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
# This workflow contains a single job called "build"
1616
cppcheck:
1717
# The type of runner that the job will run on
18-
runs-on: ubuntu-18.04
18+
runs-on: ubuntu-20.04
1919

2020
# Steps represent a sequence of tasks that will be executed as part of the job
2121
steps:
@@ -60,7 +60,7 @@ jobs:
6060
- name: Run CPPCheck
6161
run: |
6262
cd ${{ runner.workspace }}/MINI404
63-
cppcheck --template='::{severity} file={file},line={line}::{message}' --error-exitcode=2 --inline-suppr --enable=warning --suppress='*:hw/arm/prusa/3rdParty/*' hw/arm/prusa
63+
cppcheck --template='::{severity} file={file},line={line}::{message}' -I include --error-exitcode=2 --inline-suppr --enable=warning --suppress='*:hw/arm/prusa/3rdParty/*' --suppress='*:include/*' hw/arm/prusa
6464
6565
# - name: Run Clang-tidy
6666
# run: |

.vscode/tasks.json

+17
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,23 @@
129129
"showReuseMessage": true,
130130
"clear": true
131131
}
132+
},
133+
{
134+
"label": "Build QEMU (16 threads)",
135+
"type": "shell",
136+
"command": "make -j16",
137+
"group": "build",
138+
"problemMatcher": [
139+
"$gcc"
140+
],
141+
"presentation": {
142+
"echo": true,
143+
"reveal": "always",
144+
"focus": false,
145+
"panel": "shared",
146+
"showReuseMessage": true,
147+
"clear": true
148+
}
132149
}
133150
]
134151
}

hw/arm/prusa/launch-xl.sh

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/sh
2+
# This script is an EXAMPLE and specific to my development setup.
3+
# I intend it only as a basic reference on how to bring up all the XL components together
4+
# in the correct sequence.
5+
# You will want to copy it to your binary output folder and adapt it to your needs.
6+
# Note - closing the bed will cause all other instances to be killed too.
7+
case $1 in
8+
v040)
9+
echo "Launching XL v0.4.0"
10+
XL="040"
11+
DWARF="040"
12+
MODBED="060"
13+
;;
14+
v050)
15+
echo "Launching XL v0.5.0"
16+
XL="050"
17+
DWARF="060"
18+
MODBED="070"
19+
;;
20+
*)
21+
echo "Unrecognized HW version $1."
22+
exit 1;
23+
esac
24+
MAIN_FW="public.bin"
25+
MODBED_BL="newbl/bootloader-v296-prusa_modular_bed-1.0.elf"
26+
DWARF_BL="newbl/bootloader-v296-prusa_dwarf-1.0.elf"
27+
ESP_SERIAL="-chardev serial,id=stm32uart7,path=/dev/ttyUSB0"
28+
# ESP_SERIAL="-chardev pty,id=stm32uart7"
29+
clear && ./qemu-system-buddy -machine prusa-xl-${XL} -kernel ${MAIN_FW} ${ESP_SERIAL} -chardev stdio,id=stm32_itm -drive id=usbstick,file=fat:rw:sd2 -device usb-storage,drive=usbstick -icount 1 -S -s & sleep 1 &&
30+
# screen -SDm dwarf5 ./qemu-system-buddy -machine prusa-xl-extruder-g0-4 -kernel newbl/bootloader-v296-prusa_dwarf-1.0.elf -icount 5 &
31+
# screen -SDm dwarf4 ./qemu-system-buddy -machine prusa-xl-extruder-g0-3 -kernel newbl/bootloader-v296-prusa_dwarf-1.0.elf -icount 5 &
32+
# screen -SDm dwarf3 ./qemu-system-buddy -machine prusa-xl-extruder-g0-2 -kernel newbl/bootloader-v296-prusa_dwarf-1.0.elf -icount 5 &
33+
# screen -SDm dwarf2 ./qemu-system-buddy -machine prusa-xl-extruder-g0-1 -kernel newbl/bootloader-v296-prusa_dwarf-1.0.elf -icount 5 &
34+
screen -SDm dwarf ./qemu-system-buddy -machine prusa-xl-extruder-${DWARF}-0 -kernel ${DWARF_BL} -icount 2 &
35+
sleep 2 && screen -SDm modbed ./qemu-system-buddy -machine prusa-xl-bed-${MODBED} -kernel ${MODBED_BL} -icount 6
36+
killall qemu-system-buddy

hw/arm/prusa/meson.build

+11-12
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ else
44
# cygwin or native build.
55
libglut = cc.find_library('glut', required: false)
66
endif
7-
if build_machine.system() == 'cygwin' or build_machine.system() == 'windows'
7+
if build_machine.system() == 'cygwin' or build_machine.system() == 'windows' or meson.is_cross_build()
88
message('Cross build, finding opengl32. libglew32 and libglu32')
99
libgl = cc.find_library('libopengl32', required: false)
1010
libglu = cc.find_library('libglu32', required: false)
@@ -27,22 +27,21 @@ else
2727
message('OpenGL libraries not found. Install development packages for freeglut, glew, and mesa and re-run configure.')
2828
endif
2929

30+
pngdep = dependency('libpng', fallback : ['libpng', 'png_dep'])
31+
arm_ss.add(when: 'CONFIG_BUDDYBOARD', if_true: [pngdep])
32+
3033
subdir('stm32_common')
3134
subdir('stm32f407')
35+
subdir('stm32f030')
36+
subdir('stm32g070')
37+
subdir('parts')
3238

3339
arm_ss.add(when: 'CONFIG_BUDDYBOARD', if_true: files(
3440
'prusa-mini.c',
35-
'parts/encoder_input.c',
36-
'parts/fan.c',
37-
'parts/gl_dashboard.c',
38-
'parts/2d-dashboard.c',
39-
'parts/heater.c',
40-
'parts/irsensor.c',
41-
'parts/p404_key_input.c',
42-
'parts/pinda.c',
43-
'parts/st7789v.c',
44-
'parts/thermistor.c',
45-
'parts/tmc2209.c',
41+
'prusa-mk4.c',
42+
'prusa-xl-bed.c',
43+
'prusa-xl-extruder.c',
44+
'prusa-xl.c',
4645
'utility/ArgHelper.cpp',
4746
'utility/IKeyClient.cpp',
4847
'utility/IScriptable.cpp',

hw/arm/prusa/opengl/GLDashboardMgr.cpp

+14-5
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ GLDashboardMgr::GLDashboardMgr(int iType):m_iType(iType) {
7878
}
7979

8080
GLDashboardMgr::~GLDashboardMgr() {
81-
}
81+
}
8282

8383
void GLDashboardMgr::Start() {
8484
auto fcnRun = [](void *p) { return g_pGLDashboardMgr->RunThread(p); };
8585
pthread_cond_init(&m_glReady, nullptr);
8686
pthread_mutex_init(&m_glMtx, nullptr);
8787
pthread_create(&m_glThread, nullptr, fcnRun, nullptr);
88-
// Wait for the GL thread to start so that the script host can be set up.
88+
// Wait for the GL thread to start so that the script host can be set up.
8989
pthread_mutex_lock(&m_glMtx);
9090
pthread_cond_wait(&m_glReady, &m_glMtx);
9191
pthread_mutex_unlock(&m_glMtx);
@@ -94,7 +94,7 @@ void GLDashboardMgr::Start() {
9494
void GLDashboardMgr::UpdateMotor(int motor, int pos) {
9595
if (motor>=0 && motor<DB_MOTOR_COUNT) {
9696
if (m_p3DVis) {
97-
m_p3DVis->OnMotorStep(motor,pos);
97+
m_p3DVis->OnMotorStep(motor,pos<0?0U:pos);
9898
}
9999
} else {
100100
std::cerr << "Error: Invalid motor index: "<< std::to_string(motor) <<"!\n";
@@ -120,14 +120,19 @@ void GLDashboardMgr::SetupHardware() {
120120
{
121121
}
122122
break;
123-
default:
123+
case DB_MK4_LITE:
124+
case DB_MK4_DB:
125+
{
126+
}
127+
break;
128+
default:
124129
std::cerr << "Invalid dashboard type specified!\n";
125130
}
126131
}
127132

128133
void* GLDashboardMgr::RunThread(void *p) {
129134
SetupHardware();
130-
// Also set up the 3D visuals.
135+
// Also set up the 3D visuals.
131136
switch (m_iType) {
132137
case DB_MINI_FULL:
133138
m_p3DVis.reset(new MK3SGL("full",false));
@@ -137,6 +142,10 @@ void* GLDashboardMgr::RunThread(void *p) {
137142
m_p3DVis.reset(new MK3SGL("lite",false));
138143
m_p3DVis->SetStepsPerMM(100*16, 100*16, 400*16, 320*16);
139144
break;
145+
case DB_MK4_LITE:
146+
m_p3DVis.reset(new MK3SGL("lite",false));
147+
m_p3DVis->SetStepsPerMM(200*16, 200*16, 400*16, 320*16);
148+
break;
140149
default:
141150
break;
142151
}

hw/arm/prusa/opengl/MK3SGL.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ MK3SGL::~MK3SGL()
6565
{
6666
m_bQuit = true;
6767
glutLeaveMainLoop();
68+
delete m_Objs;
6869
g_pMK3SGL = nullptr;
6970
}
7071

@@ -159,8 +160,8 @@ MK3SGL::MK3SGL(const std::string &strModel, bool bMMU):Scriptable("3DVisuals"),
159160
if (strModel == "lite")
160161
{
161162
m_Objs = new Mini_Lite();
162-
}
163-
else if (strModel == "full")
163+
}
164+
else if (strModel == "full")
164165
{
165166
m_Objs = new Mini_Full();
166167
}

hw/arm/prusa/opengl/MK3SGL.h

+3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ class MK3SGL: public Scriptable, private IKeyClient
104104

105105
private:
106106

107+
MK3SGL(const MK3SGL& other); // not implemented. this class is a signleton.
108+
MK3SGL& operator=(const MK3SGL& other); // also not implemented.
109+
107110
void OnKeyPress(const Key& key) override;
108111

109112
void TimerCB(int i);

hw/arm/prusa/parts/2d-dashboard.c

+30-17
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
#define LINE_HEIGHT (FONT_HEIGHT)
3838

3939
// 3 extra lines for fan, therm, indicators.
40-
#define DPY_MAX_ROWS (LINE_HEIGHT *(N_MOTORS + 3U))
40+
#define DPY_MAX_ROWS (LINE_HEIGHT *(N_MOTORS + 4U))
4141
#define DPY_MAX_COLS 480
4242
#define LED_HT LINE_HEIGHT
4343

@@ -59,6 +59,7 @@ struct Dashboard2DState {
5959
uint32_t framebuffer[DPY_MAX_ROWS * DPY_MAX_COLS];
6060

6161
char* ind_labels;
62+
char* title;
6263

6364
pixman_color_t leds[N_LEDS];
6465
uint32_t led_colours[N_LEDS];
@@ -101,7 +102,7 @@ static pixman_color_t attr_disabled[2] = {
101102

102103
static pixman_color_t* dashboard_2d_get_attr(const p404_motorif_status_t *s)
103104
{
104-
return s->status.stalled ? attr_stall :
105+
return s->status.stalled ? attr_stall :
105106
(!s->status.enabled? attr_disabled :
106107
( s->status.stealth ? attr_stealth : attr_norm )
107108
);
@@ -112,10 +113,10 @@ static void dashboard_2d_update_display(void *opaque)
112113
Dashboard2DState *s = DB2D_DISPLAY(opaque);
113114
DisplaySurface *surface = qemu_console_surface(s->con);
114115
uint8_t *dest = NULL;
115-
116+
116117
const p404_motorif_status_t* m[10] = {NULL};
117118

118-
int motor_count = 0;
119+
int motor_count = 1;
119120

120121
for (int i=0; i<N_MOTORS; i++)
121122
{
@@ -128,7 +129,7 @@ static void dashboard_2d_update_display(void *opaque)
128129
s->redraw = true;
129130
if (m[i]->max_pos>0) // negative max pos means no endstop...
130131
{
131-
int row = FONT_HEIGHT*i;
132+
int row = FONT_HEIGHT*(i+1);
132133
int offset = FONT_WIDTH + (FONT_WIDTH/2);
133134
int index = (DPY_MAX_COLS*row)+offset;
134135
uint16_t scale = (m[i]->max_pos<=200 ? 2 : 1);
@@ -145,11 +146,9 @@ static void dashboard_2d_update_display(void *opaque)
145146
}
146147
}
147148
}
148-
149149
}
150150
}
151-
152-
if (!s->redraw)
151+
if (!s->redraw)
153152
return;
154153

155154
dest = surface_data(surface);
@@ -160,11 +159,11 @@ static void dashboard_2d_update_display(void *opaque)
160159
if (m[i] && m[i]->status.changed)
161160
{
162161
char pos[9];
163-
vga_putcharxy(s->con, 0, i, m[i]->label, dashboard_2d_get_attr(m[i]) );
162+
vga_putcharxy(s->con, 0, i+1, m[i]->label, dashboard_2d_get_attr(m[i]) );
164163
snprintf(pos, sizeof(pos),"%8.3f", m[i]->current_pos);
165164
for (int j=0; j<8; j++)
166165
{
167-
vga_putcharxy(s->con, (60-8)+j, i, pos[j], attr_norm);
166+
vga_putcharxy(s->con, (60-8)+j, i+1, pos[j], attr_norm);
168167
}
169168
}
170169
}
@@ -192,7 +191,7 @@ static void dashboard_2d_update_display(void *opaque)
192191
QEMU_RGB(0xFF*light, 0xFF*light, 0xFF*light),
193192
QEMU_RGB(s->therm_pwms[i], 0,0),
194193
};
195-
194+
196195
vga_putcharxy(s->con, (10*i) + 0, motor_count + 1 , 'T', attr_norm);
197196
vga_putcharxy(s->con, (10*i) + 1, motor_count + 1 , '0' + i, attr_norm);
198197
vga_putcharxy(s->con, (10*i) + 2, motor_count + 1 , ':', attr_norm);
@@ -203,14 +202,20 @@ static void dashboard_2d_update_display(void *opaque)
203202
}
204203

205204
for (int i=0; i<MIN(strlen(s->ind_labels), N_LEDS); i++)
206-
{
205+
{
207206
bool light = s->leds[i].red<(128<<8) && s->leds[i].green<(128<<8) && s->leds[i].blue<(128<<8);
208207
pixman_color_t fg = QEMU_RGB(255*light, 255*light, 255*light);
209208
vga_putcharxy_s(s->con, (4*i) +1 , motor_count + 2 , s->ind_labels[i], &fg, &s->leds[i]);
210209
vga_putcharxy_s(s->con, (4*i) +0 , motor_count + 2 , ' ', &fg, &s->leds[i]);
211210
vga_putcharxy_s(s->con, (4*i) +2 , motor_count + 2 , ' ', &fg, &s->leds[i]);
212211
}
213-
212+
if (s->title != NULL)
213+
{
214+
for (int i=0; i<strlen(s->title); i++)
215+
{
216+
vga_putcharxy(s->con, i, 0, s->title[i], attr_norm);
217+
}
218+
}
214219
s->redraw = false;
215220
dpy_gfx_update(s->con, 0, 0, DPY_MAX_COLS , DPY_MAX_ROWS + LED_HT);
216221
}
@@ -234,6 +239,14 @@ static void dashboard_2d_wled_in(void *opaque, int n, int level)
234239
s->leds[n].blue = level<<8;
235240
}
236241

242+
static void dashboard_2d_rgbled_in(void *opaque, int n, int level)
243+
{
244+
Dashboard2DState *s = DB2D_DISPLAY(opaque);
245+
s->leds[n].red = (level & 0xFF0000) >> 8;
246+
s->leds[n].green = (level & 0x00FF00);
247+
s->leds[n].blue = (level & 0x0000FF) << 8;
248+
}
249+
237250
static void dashboard_2d_rled_in(void *opaque, int n, int level)
238251
{
239252
Dashboard2DState *s = DB2D_DISPLAY(opaque);
@@ -269,7 +282,6 @@ static void dashboard_2d_bled_in(void *opaque, int n, int level)
269282
static void dashboard_2d_digital_led_in(void *opaque, int n, int level)
270283
{
271284
Dashboard2DState *s = DB2D_DISPLAY(opaque);
272-
273285
s->leds[n].red = (level*255)<<8;
274286
s->leds[n].green = (level*255)<<8;
275287
}
@@ -310,6 +322,7 @@ static void dashboard_2d_init(Object *obj)
310322
DeviceState *dev = DEVICE(obj);
311323

312324
qdev_init_gpio_in_named(dev, dashboard_2d_wled_in, "led-w", N_LEDS);
325+
qdev_init_gpio_in_named(dev, dashboard_2d_rgbled_in, "led-rgb", N_LEDS);
313326
qdev_init_gpio_in_named(dev, dashboard_2d_rled_in, "led-r", N_LEDS);
314327
qdev_init_gpio_in_named(dev, dashboard_2d_gled_in, "led-g", N_LEDS);
315328
qdev_init_gpio_in_named(dev, dashboard_2d_bled_in, "led-b", N_LEDS);
@@ -328,16 +341,15 @@ static void dashboard_2d_realize(DeviceState *dev, Error **errp)
328341
Dashboard2DState *s = DB2D_DISPLAY(dev);
329342

330343
// Calculate total rows:
331-
int i = 0;
344+
int i = 1;
332345
for (i=0; i<N_MOTORS; i++)
333346
{
334347
if (s->motors[i] == NULL)
335348
break;
336349
}
337-
338350
s->current_rows = LINE_HEIGHT * i;
339351

340-
s->current_rows += (3 * LINE_HEIGHT);
352+
s->current_rows += (4 * LINE_HEIGHT);
341353
s->con = graphic_console_init(dev, 0, &dashboard_2d_ops, s);
342354
qemu_console_resize(s->con, DPY_MAX_COLS, s->current_rows);
343355
}
@@ -367,6 +379,7 @@ static Property dashboard_2d_properties[] = {
367379
DEFINE_PROP_UINT8("fans", Dashboard2DState, fan_count, 0),
368380
DEFINE_PROP_UINT8("thermistors", Dashboard2DState, therm_count, 0),
369381
DEFINE_PROP_STRING("indicators", Dashboard2DState, ind_labels),
382+
DEFINE_PROP_STRING("title", Dashboard2DState, title),
370383
DEFINE_PROP_END_OF_LIST()
371384
};
372385

0 commit comments

Comments
 (0)