Skip to content

Commit 487d753

Browse files
adding in additional firmware specific commands
1 parent 86d87cc commit 487d753

6 files changed

Lines changed: 1319 additions & 20 deletions

File tree

gcode-modifier.html

Lines changed: 628 additions & 10 deletions
Large diffs are not rendered by default.

src/firmware.js

Lines changed: 556 additions & 8 deletions
Large diffs are not rendered by default.

src/gcode-dictionary.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,55 @@ const GCODE_COMMANDS = {
3131
'M600': { name: 'Filament Change', params: { X: 'Park X', Y: 'Park Y', Z: 'Park Z lift', E: 'Retract length' } },
3232
'M862': { name: 'Printer Model Check', params: { P: 'Model ID', Q: 'Nozzle diameter' } },
3333
'M900': { name: 'Linear Advance', params: { K: 'K-factor' } },
34+
// Movement (new)
35+
'G5': { name: 'Bézier Spline', params: { X: 'End X', Y: 'End Y', I: 'X control point 1', J: 'Y control point 1', P: 'X control point 2', Q: 'Y control point 2', E: 'Extrude', F: 'Feed rate' } },
36+
'G12': { name: 'Nozzle Clean', params: { P: 'Pattern (0=stroke, 1=zig-zag)', S: 'Strokes', T: 'Triangles' } },
37+
'G20': { name: 'Set Units to Inches', params: {} },
38+
'G27': { name: 'Park Toolhead', params: { P: 'Park mode' } },
39+
// Probing & Leveling (new)
40+
'G30': { name: 'Single Z-Probe', params: { X: 'Probe X', Y: 'Probe Y' } },
41+
'G33': { name: 'Delta Auto Calibration', params: { C: 'Calibration points', V: 'Verbose level' } },
42+
'G34': { name: 'Z Stepper Alignment', params: {} },
43+
'G35': { name: 'Tramming Assistant', params: {} },
44+
'G38.2': { name: 'Probe Toward Target', params: { X: 'Target X', Y: 'Target Y', Z: 'Target Z', F: 'Feed rate' } },
45+
'G38.3': { name: 'Probe Toward (No Error)', params: { X: 'Target X', Y: 'Target Y', Z: 'Target Z', F: 'Feed rate' } },
46+
'G38.4': { name: 'Probe Away from Target', params: { X: 'Target X', Y: 'Target Y', Z: 'Target Z', F: 'Feed rate' } },
47+
'G38.5': { name: 'Probe Away (No Error)', params: { X: 'Target X', Y: 'Target Y', Z: 'Target Z', F: 'Feed rate' } },
48+
// Temperature (new)
49+
'M105': { name: 'Report Temperatures', params: {} },
50+
'M141': { name: 'Set Chamber Temp', params: { S: 'Target temp (°C)' } },
51+
'M191': { name: 'Wait for Chamber Temp', params: { S: 'Target temp (°C)', R: 'Wait for exact temp (°C)' } },
52+
// System & Info (new)
53+
'M17': { name: 'Enable Steppers', params: { X: 'Enable X', Y: 'Enable Y', Z: 'Enable Z', E: 'Enable E' } },
54+
'M80': { name: 'ATX Power On', params: {} },
55+
'M81': { name: 'ATX Power Off', params: {} },
56+
'M85': { name: 'Inactivity Shutdown', params: { S: 'Timeout (s)' } },
57+
'M92': { name: 'Set Steps Per Unit', params: { X: 'X steps/mm', Y: 'Y steps/mm', Z: 'Z steps/mm', E: 'E steps/mm' } },
58+
'M112': { name: 'Emergency Stop', params: {} },
59+
'M114': { name: 'Get Current Position', params: {} },
60+
'M115': { name: 'Firmware Info', params: {} },
61+
'M119': { name: 'Endstop Status', params: {} },
62+
'M155': { name: 'Auto-Report Temperatures', params: { S: 'Interval (s)' } },
63+
// Retraction & Filament (new)
64+
'M200': { name: 'Set Filament Diameter', params: { D: 'Diameter (mm)', T: 'Extruder index' } },
65+
'M207': { name: 'Set Retract Length', params: { S: 'Retract length (mm)', F: 'Retract speed (mm/min)', Z: 'Z lift (mm)' } },
66+
'M208': { name: 'Set Recover Length', params: { S: 'Extra recover length (mm)', F: 'Recover speed (mm/min)' } },
67+
'M412': { name: 'Filament Runout', params: { S: 'Enable (1) / Disable (0)' } },
68+
'M702': { name: 'Unload Filament', params: { T: 'Extruder index', U: 'Unload length (mm)' } },
69+
// Stepper & Motion (new)
70+
'M206': { name: 'Set Home Offset', params: { X: 'X offset (mm)', Y: 'Y offset (mm)', Z: 'Z offset (mm)' } },
71+
'M211': { name: 'Software Endstops', params: { S: 'Enable (1) / Disable (0)' } },
72+
'M290': { name: 'Babystepping', params: { Z: 'Z offset (mm)' } },
73+
'M350': { name: 'Set Microstepping', params: { X: 'X microsteps', Y: 'Y microsteps', Z: 'Z microsteps', E: 'E microsteps' } },
74+
'M420': { name: 'Bed Leveling State', params: { S: 'Enable (1) / Disable (0)', Z: 'Fade height (mm)' } },
75+
'M421': { name: 'Set Mesh Point', params: { I: 'X index', J: 'Y index', Z: 'Z offset (mm)' } },
76+
'M906': { name: 'Set Motor Current', params: { X: 'X current (mA)', Y: 'Y current (mA)', Z: 'Z current (mA)', E: 'E current (mA)' } },
77+
// Hardware & Misc (new)
78+
'M42': { name: 'Switch I/O Pin', params: { P: 'Pin number', S: 'Pin value (0-255)' } },
79+
'M125': { name: 'Park Head', params: { X: 'Park X', Y: 'Park Y', Z: 'Z lift (mm)' } },
80+
'M280': { name: 'Set Servo Position', params: { P: 'Servo index', S: 'Angle (0-180)' } },
81+
'M355': { name: 'Case Light', params: { S: 'On (1) / Off (0)', P: 'Brightness (0-255)' } },
82+
'M911': { name: 'Power Loss Recovery', params: {} },
3483
};
3584

3685
function decodeLine(text) {
@@ -107,3 +156,5 @@ function decodeLine(text) {
107156
params
108157
};
109158
}
159+
160+
export { GCODE_COMMANDS, decodeLine };

src/index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,16 @@
474474
.ref-card-firmware { font-size: 11px; padding: 4px 8px; border-radius: 4px; margin-bottom: 6px; border-left: 3px solid var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--bg-secondary)); color: var(--text-primary); }
475475
.ref-card-insert { font-size: 11px; padding: 3px 10px; border-radius: 4px; border: 1px solid var(--accent); background: transparent; color: var(--accent); cursor: pointer; float: right; }
476476
.ref-card-insert:hover { background: var(--accent); color: #fff; }
477+
.ref-fw-badges { display: flex; gap: 4px; margin-left: auto; flex-shrink: 0; }
478+
.ref-fw-badge { font-size: 9px; font-weight: 600; padding: 1px 6px; border-radius: 8px; line-height: 1.4; white-space: nowrap; }
479+
.ref-fw-badge[data-fw="bambu"] { background: #2d7a3a22; color: #2d7a3a; border: 1px solid #2d7a3a44; }
480+
.ref-fw-badge[data-fw="klipper"] { background: #c4640022; color: #c46400; border: 1px solid #c4640044; }
481+
.ref-fw-badge[data-fw="marlin"] { background: #2563eb22; color: #2563eb; border: 1px solid #2563eb44; }
482+
.ref-fw-badge[data-fw="rrf"] { background: #7c3aed22; color: #7c3aed; border: 1px solid #7c3aed44; }
483+
[data-theme="dark"] .ref-fw-badge[data-fw="bambu"] { background: #4ade8022; color: #4ade80; border-color: #4ade8044; }
484+
[data-theme="dark"] .ref-fw-badge[data-fw="klipper"] { background: #fb923c22; color: #fb923c; border-color: #fb923c44; }
485+
[data-theme="dark"] .ref-fw-badge[data-fw="marlin"] { background: #60a5fa22; color: #60a5fa; border-color: #60a5fa44; }
486+
[data-theme="dark"] .ref-fw-badge[data-fw="rrf"] { background: #a78bfa22; color: #a78bfa; border-color: #a78bfa44; }
477487
.ref-no-results { text-align: center; color: var(--text-secondary); padding: 20px 0; font-size: 13px; }
478488

479489
/* PRINTER PROFILE PANEL */

src/ui.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,8 +2031,18 @@ function renderReference() {
20312031
html += '<div class="ref-category-cards">';
20322032
catMap[cat].forEach(cmd => {
20332033
const fwNote = cmd.firmware[fw];
2034-
html += '<div class="ref-card" data-search="' + (cmd.code + ' ' + cmd.name + ' ' + cmd.description).toLowerCase().replace(/"/g, '&quot;') + '">';
2035-
html += '<div class="ref-card-head"><span class="ref-card-code">' + cmd.code + '</span><span class="ref-card-name">' + cmd.name + '</span>';
2034+
const searchFw = cmd.supportedBy ? ' ' + cmd.supportedBy.join(' ') : '';
2035+
html += '<div class="ref-card" data-search="' + (cmd.code + ' ' + cmd.name + ' ' + cmd.description + searchFw).toLowerCase().replace(/"/g, '&quot;') + '">';
2036+
let badgeHtml = '';
2037+
if (cmd.supportedBy) {
2038+
badgeHtml = '<span class="ref-fw-badges">';
2039+
const FW_NAMES = { bambu: 'Bambu', klipper: 'Klipper', marlin: 'Marlin', rrf: 'RRF' };
2040+
cmd.supportedBy.forEach(fw => {
2041+
badgeHtml += '<span class="ref-fw-badge" data-fw="' + fw + '">' + (FW_NAMES[fw] || fw) + '</span>';
2042+
});
2043+
badgeHtml += '</span>';
2044+
}
2045+
html += '<div class="ref-card-head"><span class="ref-card-code">' + cmd.code + '</span><span class="ref-card-name">' + cmd.name + '</span>' + badgeHtml;
20362046
html += '<button class="ref-card-insert" onclick="insertRefCommand(\'' + cmd.code.replace(/'/g, "\\'") + '\');event.stopPropagation()">Insert</button></div>';
20372047
html += '<div class="ref-card-desc">' + cmd.description + '</div>';
20382048
if (cmd.params.length > 0) {

test/gcode-dictionary.test.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { describe, it } from 'node:test';
2+
import assert from 'node:assert';
3+
import { GCODE_COMMANDS, decodeLine } from '../src/gcode-dictionary.js';
4+
5+
describe('GCODE_COMMANDS dictionary', () => {
6+
it('G5 Bézier spline decodes correctly', () => {
7+
const result = decodeLine('G5 X10 Y20 I1 J2 P3 Q4 E0.5 F1200');
8+
assert.strictEqual(result.command, 'G5');
9+
assert.strictEqual(result.name, 'Bézier Spline');
10+
assert.strictEqual(result.known, true);
11+
assert.strictEqual(result.params.length, 8);
12+
assert.strictEqual(result.params[0].letter, 'X');
13+
assert.strictEqual(result.params[0].value, '10');
14+
});
15+
16+
it('M112 emergency stop decodes correctly', () => {
17+
const result = decodeLine('M112');
18+
assert.strictEqual(result.command, 'M112');
19+
assert.strictEqual(result.name, 'Emergency Stop');
20+
assert.strictEqual(result.known, true);
21+
assert.strictEqual(result.params.length, 0);
22+
});
23+
24+
it('M92 with params decodes with 4 params', () => {
25+
const result = decodeLine('M92 X80 Y80 Z400 E93');
26+
assert.strictEqual(result.command, 'M92');
27+
assert.strictEqual(result.name, 'Set Steps Per Unit');
28+
assert.strictEqual(result.known, true);
29+
assert.strictEqual(result.params.length, 4);
30+
});
31+
32+
it('G38.2 subcommand decodes correctly', () => {
33+
const result = decodeLine('G38.2 X10 Y20 Z-5 F100');
34+
assert.strictEqual(result.command, 'G38.2');
35+
assert.strictEqual(result.name, 'Probe Toward Target');
36+
assert.strictEqual(result.known, true);
37+
assert.strictEqual(result.params.length, 4);
38+
});
39+
40+
it('M906 motor current decodes with 4 params', () => {
41+
const result = decodeLine('M906 X800 Y800 Z800 E450');
42+
assert.strictEqual(result.command, 'M906');
43+
assert.strictEqual(result.name, 'Set Motor Current');
44+
assert.strictEqual(result.known, true);
45+
assert.strictEqual(result.params.length, 4);
46+
});
47+
48+
it('existing command G1 still works', () => {
49+
const result = decodeLine('G1 X100 Y200 Z0.3 E1.5 F3000');
50+
assert.strictEqual(result.command, 'G1');
51+
assert.strictEqual(result.name, 'Linear Move');
52+
assert.strictEqual(result.known, true);
53+
assert.strictEqual(result.params.length, 5);
54+
});
55+
56+
it('unknown command returns known: false', () => {
57+
const result = decodeLine('G999');
58+
assert.strictEqual(result.command, 'G999');
59+
assert.strictEqual(result.name, 'Unknown Command');
60+
assert.strictEqual(result.known, false);
61+
});
62+
});

0 commit comments

Comments
 (0)