Skip to content

Commit 1bd922b

Browse files
committed
Add block-programming editor
1 parent 8c0e3cb commit 1bd922b

File tree

13 files changed

+849
-57
lines changed

13 files changed

+849
-57
lines changed

index.html

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -59,42 +59,55 @@
5959
</div>
6060
<div class="bottom-bar"></div>
6161
</header>
62-
<div id="main-content">
63-
<div id="editor-page" class="active">
64-
<div id="editor-bar">
65-
<button class="purple-button btn-new">New<i class="fa-solid fa-plus"></i></button>
66-
<button class="purple-button btn-open">Open<i class="fa-solid fa-folder-open"></i></button>
67-
<button class="purple-button btn-save">Save<i class="fa-solid fa-floppy-disk"></i></button>
68-
<button class="purple-button btn-save-as">Save As<i class="fa-solid fa-download"></i></button>
69-
<div class="file-path"></div>
70-
<button class="purple-button btn-save-run">Save + Run<i class="fa-solid fa-play"></i></button>
71-
</div>
72-
<div id="mobile-editor-bar">
73-
<div id="mobile-menu">
74-
<div class="menu-toggle">
75-
<button id="mobile-menu-button">
76-
<span class="sr-only">Open Mobile Menu</span>
77-
<i class="fa fa-bars" aria-hidden="true"></i>
78-
</button>
62+
<div class="main-container">
63+
<div id="main-content">
64+
<div id="blockly-page" class="active">
65+
<div id="blockly-bar">
66+
<button class="purple-button btn-blockly-new">New<i class="fa-solid fa-plus"></i></button>
67+
<button class="purple-button btn-blockly-open">Open<i class="fa-solid fa-folder-open"></i></button>
68+
<button class="purple-button btn-blockly-save">Save<i class="fa-solid fa-floppy-disk"></i></button>
69+
<button class="purple-button btn-blockly-save-as">Save As<i class="fa-solid fa-download"></i></button>
70+
<button class="purple-button btn-blockly-generate">Generate<i class="fa-solid fa-gears"></i> </button>
71+
</div>
72+
<div id="blockly-workspace"></div>
73+
</div>
74+
<div id="page-separator"></div>
75+
<div id="editor-page" class="active">
76+
<div id="editor-bar">
77+
<button class="purple-button btn-new">New<i class="fa-solid fa-plus"></i></button>
78+
<button class="purple-button btn-open">Open<i class="fa-solid fa-folder-open"></i></button>
79+
<button class="purple-button btn-save">Save<i class="fa-solid fa-floppy-disk"></i></button>
80+
<button class="purple-button btn-save-as">Save As<i class="fa-solid fa-download"></i></button>
81+
<div class="file-path"></div>
82+
<button class="purple-button btn-save-run">Save + Run<i class="fa-solid fa-play"></i></button>
83+
</div>
84+
<div id="mobile-editor-bar">
85+
<div id="mobile-menu">
86+
<div class="menu-toggle">
87+
<button id="mobile-menu-button">
88+
<span class="sr-only">Open Mobile Menu</span>
89+
<i class="fa fa-bars" aria-hidden="true"></i>
90+
</button>
91+
</div>
92+
</div>
93+
<div class="file-path"></div>
94+
<a class="purple-button btn-save-run">Save + Run<i class="fa-solid fa-play"></i></a>
95+
<div class="clear"></div>
96+
<nav id="mobile-menu-contents" role="navigation" class="hidden" aria-expanded="false" aria-label="Mobile Menu">
97+
<ul>
98+
<li><a class="btn-new">New<i class="fa-solid fa-plus"></i></a></li>
99+
<li><a class="btn-open">Open<i class="fa-solid fa-folder-open"></i></a></li>
100+
<li><a class="btn-save">Save<i class="fa-solid fa-floppy-disk"></i></a></li>
101+
<li><a class="btn-save-as">Save As<i class="fa-solid fa-download"></i></a></li>
102+
</ul>
103+
</nav>
79104
</div>
105+
<div id="editor"></div>
80106
</div>
81-
<div class="file-path"></div>
82-
<a class="purple-button btn-save-run">Save + Run<i class="fa-solid fa-play"></i></a>
83-
<div class="clear"></div>
84-
<nav id="mobile-menu-contents" role="navigation" class="hidden" aria-expanded="false" aria-label="Mobile Menu">
85-
<ul>
86-
<li><a class="btn-new">New<i class="fa-solid fa-plus"></i></a></li>
87-
<li><a class="btn-open">Open<i class="fa-solid fa-folder-open"></i></a></li>
88-
<li><a class="btn-save">Save<i class="fa-solid fa-floppy-disk"></i></a></li>
89-
<li><a class="btn-save-as">Save As<i class="fa-solid fa-download"></i></a></li>
90-
</ul>
91-
</nav>
92-
</div>
93-
<div id="editor"></div>
107+
94108
</div>
95-
<div id="page-separator" class=""></div>
96109
<div id="serial-page" class="">
97-
<div id="serial-bar">
110+
<div id="serial-bar" class="active">
98111
<button class="purple-button btn-restart">Restart<i class="fa-solid fa-redo"></i></button>
99112
<button class="purple-button btn-clear">Clear<i class="fa-solid fa-broom"></i></button>
100113
<div id="terminal-title"></div>
@@ -103,6 +116,7 @@
103116
</div>
104117
</div>
105118
<div id="footer-bar">
119+
<button id="btn-mode-blockly" class="mode-button active">Blockly</button>
106120
<button id="btn-mode-editor" class="mode-button active">Editor</button>
107121
<button id="btn-mode-serial" class="mode-button">Serial</button>
108122
<div class="spacer"></div>

js/blockly/block-editor.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {defineCircuitPythonBlocks} from './blocks/circuit-python-blocks.js';
2+
import {circuitPythonGenerator} from './generators/circuit-python-generator.js';
3+
import {createWorkspace} from './workspace';
4+
import {defineI2CBlocks} from "./blocks/i2c.js";
5+
import {defineVEML7700Blocks} from "./blocks/veml7700.js";
6+
import {defineLIS3MDLBlocks} from "./blocks/lis3mdl.js";
7+
8+
// Handle code generation
9+
10+
11+
export function loadBlockly() {
12+
console.log("Loading Blockly");
13+
14+
defineCircuitPythonBlocks();
15+
defineI2CBlocks();
16+
defineVEML7700Blocks();
17+
defineLIS3MDLBlocks();
18+
19+
const workspace = createWorkspace('blockly-workspace');
20+
21+
const startBlock = workspace.newBlock('start');
22+
startBlock.initSvg();
23+
startBlock.render();
24+
25+
startBlock.setDeletable(false);
26+
// Set position of start block
27+
startBlock.moveBy(20, 20);
28+
29+
return workspace;
30+
}
31+
32+
export function generateCode(workspace) {
33+
return circuitPythonGenerator.workspaceToCode(workspace);
34+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import * as Blockly from 'blockly';
2+
3+
export function defineCircuitPythonBlocks() {
4+
Blockly.Blocks['sleep_mcu'] = {
5+
init: function () {
6+
this.appendDummyInput()
7+
.appendField('Sleep for')
8+
.appendField(new Blockly.FieldNumber("1.0", 0, null, 0.01), 'DURATION')
9+
.appendField('seconds');
10+
this.setPreviousStatement(true);
11+
this.setNextStatement(true);
12+
this.setColour(230);
13+
this.setTooltip('Pauses the program for the specified duration.');
14+
this.setHelpUrl('');
15+
}
16+
}
17+
18+
// Create a block for the start of the program
19+
Blockly.Blocks['start'] = {
20+
init: function () {
21+
this.appendDummyInput()
22+
.appendField('Start');
23+
this.setNextStatement(true);
24+
this.setColour(230);
25+
this.setTooltip('This block is the start of the program.');
26+
this.setHelpUrl('');
27+
}
28+
}
29+
}

js/blockly/blocks/i2c.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import * as Blockly from 'blockly';
2+
3+
export function defineI2CBlocks() {
4+
5+
Blockly.Blocks['init_i2c'] = {
6+
init: function () {
7+
this.appendDummyInput()
8+
.appendField('Initialize I2C with SDA')
9+
// TODO: Add a dropdown with all available pins
10+
.appendField(new Blockly.FieldTextInput('SDA'), 'SDA')
11+
.appendField('SCL')
12+
.appendField(new Blockly.FieldTextInput('SCL'), 'SCL')
13+
.appendField('and save it to')
14+
.appendField(new Blockly.FieldVariable('i2c'), 'i2c');
15+
this.setPreviousStatement(true);
16+
this.setNextStatement(true);
17+
this.setColour(230);
18+
this.setTooltip('Initializes I2C with the specified pins.');
19+
this.setHelpUrl('');
20+
},
21+
};
22+
23+
Blockly.Blocks['init_board_i2c'] = {
24+
init: function () {
25+
this.appendDummyInput()
26+
.appendField('Initialize board I2C and save it to')
27+
.appendField(new Blockly.FieldVariable('i2c'), 'i2c');
28+
this.setPreviousStatement(true);
29+
this.setNextStatement(true);
30+
this.setColour(230);
31+
this.setTooltip('Initialisiert das Board I2C und speichert es in der Variable.');
32+
this.setHelpUrl('');
33+
},
34+
}
35+
}

js/blockly/blocks/lis3mdl.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import * as Blockly from 'blockly';
2+
3+
export function defineLIS3MDLBlocks() {
4+
Blockly.Blocks['init_lis3mdl'] = {
5+
init: function () {
6+
this.appendDummyInput()
7+
.appendField('Initialize LIS3MDL with I2C')
8+
.appendField(new Blockly.FieldVariable('i2c'), 'i2c')
9+
.appendField('and save it to')
10+
.appendField(new Blockly.FieldVariable('lis3mdl'), 'lis3mdl');
11+
this.setPreviousStatement(true);
12+
this.setNextStatement(true);
13+
this.setColour(230);
14+
this.setTooltip('Initializes the LIS3MDL sensor with the specified I2C bus.');
15+
this.setHelpUrl('');
16+
}
17+
}
18+
19+
// Create a block read_lis3mdl which is a value block
20+
Blockly.Blocks['read_lis3mdl'] = {
21+
init: function () {
22+
this.appendDummyInput()
23+
.appendField('Read from LIS3MDL')
24+
.appendField(new Blockly.FieldVariable('lis3mdl'), 'lis3mdl');
25+
this.setOutput(true, 'Array');
26+
this.setColour(230);
27+
this.setTooltip('Reads the magnetic field from the LIS3MDL sensor.');
28+
this.setHelpUrl('');
29+
}
30+
}
31+
}

js/blockly/blocks/veml7700.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import * as Blockly from 'blockly';
2+
3+
export function defineVEML7700Blocks() {
4+
Blockly.Blocks['init_veml7700'] = {
5+
init: function () {
6+
this.appendDummyInput()
7+
.appendField('Initialize VEML7700 with I2C')
8+
.appendField(new Blockly.FieldVariable('i2c'), 'i2c')
9+
.appendField('and save it to')
10+
.appendField(new Blockly.FieldVariable('veml7700'), 'veml7700');
11+
this.setPreviousStatement(true);
12+
this.setNextStatement(true);
13+
this.setColour(230);
14+
this.setTooltip('Initializes the VEML7700 sensor with the specified I2C bus.');
15+
this.setHelpUrl('');
16+
}
17+
}
18+
19+
// Create a block read_veml7700 which is a value block
20+
Blockly.Blocks['read_veml7700'] = {
21+
init: function () {
22+
this.appendDummyInput()
23+
.appendField('Read from VEML7700')
24+
.appendField(new Blockly.FieldVariable('veml7700'), 'veml7700');
25+
this.setOutput(true, 'Number');
26+
this.setColour(230);
27+
this.setTooltip('Reads the light intensity from the VEML7700 sensor.');
28+
this.setHelpUrl('');
29+
}
30+
}
31+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import {Order, pythonGenerator} from 'blockly/python';
2+
3+
4+
export const circuitPythonGenerator = pythonGenerator;
5+
6+
circuitPythonGenerator.forBlock['toggle_led'] = function (block) {
7+
console.log("Test")
8+
const pin = block.getFieldValue('PIN');
9+
return `import digitalio\nimport board\n` +
10+
`led = digitalio.DigitalInOut(board.${pin})\n` +
11+
`led.direction = digitalio.Direction.OUTPUT\n` +
12+
`led.value = not led.value\n`;
13+
};
14+
15+
circuitPythonGenerator.forBlock['init_i2c'] = function (block) {
16+
const sda = block.getFieldValue('SDA');
17+
const scl = block.getFieldValue('SCL');
18+
19+
circuitPythonGenerator.definitions_['import_busio'] = 'import busio';
20+
circuitPythonGenerator.definitions_['import_board'] = 'import board';
21+
22+
return `i2c = busio.I2C(board.${sda}, board.${scl})\n`;
23+
}
24+
25+
circuitPythonGenerator.forBlock['init_board_i2c'] = function (block) {
26+
const i2c = circuitPythonGenerator.getVariableName(block.getFieldValue('i2c'));
27+
circuitPythonGenerator.definitions_['import_board'] = 'import board';
28+
return `${i2c} = board.I2C()\n`;
29+
}
30+
31+
32+
circuitPythonGenerator.forBlock['init_veml7700'] = function (block) {
33+
const i2c = circuitPythonGenerator.getVariableName(block.getFieldValue('i2c'));
34+
circuitPythonGenerator.definitions_['import_veml7700'] = 'import adafruit_veml7700';
35+
return `veml7700 = adafruit_veml7700.VEML7700(${i2c})\n`;
36+
}
37+
38+
circuitPythonGenerator.forBlock['read_veml7700'] = function (block) {
39+
const sensor = circuitPythonGenerator.getVariableName(block.getFieldValue('veml7700'));
40+
return [`${sensor}.light`, Order.MEMBER];
41+
}
42+
43+
circuitPythonGenerator.forBlock['init_lis3mdl'] = function (block) {
44+
const i2c = circuitPythonGenerator.getVariableName(block.getFieldValue('i2c'));
45+
circuitPythonGenerator.definitions_['import_lis3mdl'] = 'import adafruit_lis3mdl';
46+
return `lis3mdl = adafruit_lis3mdl.LIS3MDL(${i2c})\n`;
47+
}
48+
49+
circuitPythonGenerator.forBlock['read_lis3mdl'] = function (block) {
50+
const sensor = circuitPythonGenerator.getVariableName(block.getFieldValue('lis3mdl'));
51+
return [`${sensor}.magnetic`, Order.MEMBER];
52+
}
53+
54+
circuitPythonGenerator.forBlock['sleep_mcu'] = function (block) {
55+
const duration = block.getFieldValue('DURATION');
56+
circuitPythonGenerator.definitions_[`import_time`] = 'import time';
57+
return `time.sleep(${duration})\n`;
58+
}
59+
60+
circuitPythonGenerator.forBlock['start'] = function () {
61+
return '';
62+
}
63+
64+
console.log(circuitPythonGenerator);

0 commit comments

Comments
 (0)