Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
3c9d426
Copy Dart code generator to Lisp
lupyuen May 7, 2021
d36c506
Add Lisp to code demo
lupyuen May 7, 2021
5751455
Fixed code generator
lupyuen May 7, 2021
cfa20d1
Add mynewt blocks
lupyuen May 7, 2021
1209e54
Fixing menu
lupyuen May 7, 2021
9dcea56
Fixing blocks
lupyuen May 7, 2021
a383200
Blocks OK
lupyuen May 7, 2021
ad0437e
Fix pin names
lupyuen May 7, 2021
99e6fc7
Create FUNDING.yml
lupyuen May 7, 2021
841dd8b
Add WiFi
lupyuen May 8, 2021
1d25153
Rename mynewt to lisp
lupyuen May 8, 2021
2133f5e
Update doc
lupyuen May 8, 2021
113544f
Update doc
lupyuen May 8, 2021
583725e
Update doc
lupyuen May 8, 2021
afcf500
Fix digital write
lupyuen May 8, 2021
a9e3a9a
Fix loop and delay
lupyuen May 8, 2021
ac78cdc
Add doc
lupyuen May 8, 2021
80f5d3b
Update doc
lupyuen May 8, 2021
fdc389f
Update doc
lupyuen May 8, 2021
33f88e1
Updated doc
lupyuen May 8, 2021
a34f3e7
Fix spacing
lupyuen May 8, 2021
8c30961
Adding run
lupyuen May 8, 2021
6c4bc4b
Reboot command OK
lupyuen May 8, 2021
aa87b9c
Fixing close port
lupyuen May 9, 2021
b765451
Run BL602 command OK
lupyuen May 9, 2021
c1ef692
Clean up
lupyuen May 9, 2021
6cb4f0d
Refactor
lupyuen May 9, 2021
90222c8
Refactor
lupyuen May 9, 2021
e5431f7
Fix on_start
lupyuen May 9, 2021
c111ac2
Refactor
lupyuen May 9, 2021
d3c5ab2
Merge commands
lupyuen May 9, 2021
cb03232
Clean up
lupyuen May 9, 2021
0e2191e
Send Blinky to BL602 OK yay!
lupyuen May 9, 2021
e46219b
Update doc
lupyuen May 9, 2021
1f88a31
Update doc
lupyuen May 9, 2021
3f408e4
Update doc
lupyuen May 9, 2021
f6926b1
Update README.md
lupyuen May 9, 2021
af4a10d
Update README.md
lupyuen May 9, 2021
f911854
Add article
lupyuen May 14, 2021
c80df1f
Add "wasm" branch to support BL602 Simulator in WebAssembly
lupyuen May 20, 2021
d75e49b
Copy demos/code to demos/simulator
lupyuen May 20, 2021
f03d89b
Add canvas for simulator
lupyuen May 20, 2021
52a525a
Copy wasm files from ulisp-bl602/docs
lupyuen May 20, 2021
1cecf0e
Add simulator pic
lupyuen May 20, 2021
c5f4461
Clean up
lupyuen May 20, 2021
8fa87eb
Simulator works OK yay!
lupyuen May 20, 2021
5fb45eb
Merge pull request #2 from AppKaki/wasm
lupyuen May 20, 2021
f921141
Update README.md
lupyuen May 20, 2021
adab14f
Update README.md
lupyuen May 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# These are supported funding model platforms

github: [lupyuen] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ['paypal.me/lupyuen'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
98 changes: 96 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,100 @@
# Blockly for uLisp on RISC-V BL602
# Blockly for uLisp on RISC-V BL602 (Support for BL602 Simulator in WebAssembly)

See https://github.com/lupyuen/bl_iot_sdk/tree/ulisp/customer_app/sdk_app_ulisp
Browser-based graphical development tool that runs uLisp scripts on BL602 RISC-V Board.

Read the article...

- [__uLisp and Blockly on PineCone BL602 RISC-V Board__](https://lupyuen.github.io/articles/lisp)

Watch the demo on YouTube...

- [__LED Demo__](https://youtu.be/RRhzW4j8BtI)

- [__Blinky Demo__](https://youtu.be/LNkmUIv7ZZc)

- [__BL602 Simulator Demo__](https://youtu.be/Ag2CERd1OzQ)

Try it here...

https://appkaki.github.io/blockly-ulisp/demos/code/

uLisp Firmware needs to be installed on the BL602 Board...

https://github.com/lupyuen/bl_iot_sdk/tree/ulisp/customer_app/sdk_app_ulisp

Or try it with the BL602 Simulator in WebAssembly...

https://appkaki.github.io/blockly-ulisp/demos/simulator/

## Lisp Code Generator

The following have been added into the existing [`generators`](generators) folder to generate Lisp code and to add blocks specific to uLisp...

- [`generators/lisp.js`](generators/lisp.js): Main interface for Lisp Code Generator

- [`generators/lisp`](generators/lisp): Lisp Code Generator for various blocks

- [`generators/lisp/lisp_library.xml`](generators/lisp/lisp_library.xml): Blocks XML file used by Block Exporter to generate the custom blocks

The Lisp Code Generator is __incomplete__. The only blocks supported are...

1. Forever

1. On Start

1. Wait

1. GPIO Digital Write

The Lisp Code Generator is based on Visual Embedded Rust...

https://lupyuen.github.io/articles/advanced-topics-for-visual-embedded-rust-programming

## Demo for Lisp Code Generator

Watch the demo on YouTube...

- [__LED Demo__](https://youtu.be/RRhzW4j8BtI)

- [__Blinky Demo__](https://youtu.be/LNkmUIv7ZZc)

- [__BL602 Simulator Demo__](https://youtu.be/Ag2CERd1OzQ)

Try it here...

https://appkaki.github.io/blockly-ulisp/demos/code/

Or try it with the BL602 Simulator in WebAssembly...

https://appkaki.github.io/blockly-ulisp/demos/simulator/

The Blockly demo at [`demos/code`](demos/code) has been customised to include the Lisp Code Generator...

- [`demos/code/index.html`](demos/code/index.html): Customised to load the Lisp Code Generator and Lisp Blocks

- [`demos/code/code.js`](demos/code/code.js): Customised to load the Lisp Code Generator and Lisp Blocks

The Blockly demo calls the [__Web Serial API__](https://web.dev/serial/) to transfer the generated uLisp Script to BL602...

https://github.com/AppKaki/blockly-ulisp/blob/master/demos/code/code.js#L641-L738

We assume that BL602 is running the uLisp Firmware and connected to our computer via USB...

https://github.com/lupyuen/bl_iot_sdk/tree/ulisp/customer_app/sdk_app_ulisp

The BL602 Simulator HTML and JavaScript files are here...

- [`demos/simulator/index.html`](demos/simulator/index.html): Customised to load the Lisp Code Generator, Lisp Blocks and BL602 Simulator

- [`demos/simulator/code.js`](demos/simulator/code.js): Customised to load the Lisp Code Generator, Lisp Blocks and BL602 Simulator

The BL602 Simulator includes uLisp compiled for WebAssembly...

https://github.com/lupyuen/ulisp-bl602/tree/wasm

Inspired by MakeCode for BBC micro:bit...

https://makecode.microbit.org/

# Blockly [![Build Status]( https://travis-ci.org/google/blockly.svg?branch=master)](https://travis-ci.org/google/blockly)

Expand Down
8 changes: 8 additions & 0 deletions core/workspace_svg.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ Blockly.WorkspaceSvg = function(
this.addChangeListener(Blockly.Procedures.mutatorOpenListener);
}

//// TODO
////console.log('Blockly.Widgets.flyoutCategory', Blockly.Widgets.flyoutCategory);
if (Blockly.Widgets && Blockly.Widgets.flyoutCategory) {
this.registerToolboxCategoryCallback("WIDGET", //// TODO
Blockly.Widgets.flyoutCategory);
}
////

/**
* Object in charge of storing and updating the workspace theme.
* @type {!Blockly.ThemeManager}
Expand Down
159 changes: 154 additions & 5 deletions demos/code/code.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,14 @@ Code.LANG = Code.getLang();
* List of tab names.
* @private
*/
Code.TABS_ = ['blocks', 'javascript', 'php', 'python', 'dart', 'lua', 'xml'];
Code.TABS_ = ['blocks', 'lisp', 'javascript', 'php', 'python', 'dart', 'lua', 'xml'];

/**
* List of tab names with casing, for display in the UI.
* @private
*/
Code.TABS_DISPLAY_ = [
'Blocks', 'JavaScript', 'PHP', 'Python', 'Dart', 'Lua', 'XML',
'Blocks', 'Lisp', 'JavaScript', 'PHP', 'Python', 'Dart', 'Lua', 'XML',
];

Code.selected = 'blocks';
Expand Down Expand Up @@ -324,6 +324,8 @@ Code.renderContent = function() {
var xmlText = Blockly.Xml.domToPrettyText(xmlDom);
xmlTextarea.value = xmlText;
xmlTextarea.focus();
} else if (content.id == 'content_lisp') {
Code.attemptCodeGeneration(Blockly.Lisp);
} else if (content.id == 'content_javascript') {
Code.attemptCodeGeneration(Blockly.JavaScript);
} else if (content.id == 'content_python') {
Expand Down Expand Up @@ -449,6 +451,28 @@ Code.init = function() {
Blockly.JavaScript.addReservedWords('code,timeouts,checkTimeout');

Code.loadBlocks('');

//// TODO: Added code here
// Load the Lisp Custom Blocks.
var blocks = lisp_blocks; // lisp_blocks defined in lisp_blocks.js
// For each Block...
blocks.forEach(block => {
// Register the Block with Blockly.
Blockly.Blocks[block.type] = {
init: function() {
this.jsonInit(block);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
/*
this.setTooltip(function() {
return 'Add a number to variable "%1".'.replace('%1',
thisBlock.getFieldValue('VAR'));
});
*/
}
};
});
////

if ('BlocklyStorage' in window) {
// Hook a save function onto unload.
Expand Down Expand Up @@ -546,11 +570,37 @@ Code.initLanguage = function() {
document.getElementById('trashButton').title = MSG['trashTooltip'];
};

//// TODO: Added code for Web Serial API

/**
* Execute the user's code.
* Just a quick and dirty eval. Catch infinite loops.
* Execute the Lisp code on BL602 with Web Serial API
*/
Code.runJS = function() {
var code = Blockly.Lisp.workspaceToCode(Code.workspace);
console.log(code);

// Merge the code lines into commands so that all commands start with "("
var commands = [];
const lines = code.split("\n");
lines.forEach(line => {
// Skip blank lines
if (line.trim() == "") { return; }

if (line[0] == "(") {
// If this line starts with "(", add it as a command
commands.push(line);
} else {
// If this line doesn't start with "(", merge with previous line
const lastIndex = commands.length - 1;
commands[lastIndex] += " " + line;
}
});

// Run the merged commands
runCommands(commands);

/* Previously: Execute the user's code. Just a quick and dirty eval. Catch infinite loops.

Blockly.JavaScript.INFINITE_LOOP_TRAP = 'checkTimeout();\n';
var timeouts = 0;
var checkTimeout = function() {
Expand All @@ -564,7 +614,7 @@ Code.runJS = function() {
eval(code);
} catch (e) {
alert(MSG['badCode'].replace('%1', e));
}
} */
};

/**
Expand All @@ -587,3 +637,102 @@ document.write('<script src="msg/' + Code.LANG + '.js"></script>\n');
document.write('<script src="../../msg/js/' + Code.LANG + '.js"></script>\n');

window.addEventListener('load', Code.init);

///////////////////////////////////////////////////////////////////////////////
// Web Serial Interface

// Run a list of commands on BL602 via Web Serial API
async function runCommands(commands) {
console.log(commands);

// For each merged command...
for (const command of commands) {
// Send an empty command and check that BL602 responds with "#"
await runWebSerialCommand(
"", // Command
"#" // Expected Response
);

// Send the actual command but don't wait for response
await runWebSerialCommand(
command, // Command
null // Don't wait for response
);

// Test the reboot command
/*
await runWebSerialCommand(
"reboot", // Command
"Init CLI" // Expected Response
);
*/

// TODO: Handle no response or invalid response from BL602
// TODO: Show the BL602 response
}
}

// Web Serial Port
var serialPort;

// Run a command on BL602 via Web Serial API and wait for the expectedResponse (if not null)
// Based on https://web.dev/serial/
async function runWebSerialCommand(command, expectedResponse) {
// Check if Web Serial API is supported
if (!("serial" in navigator)) { alert("Web Serial API is not supported"); return; }

// Prompt user to select any serial port
if (!serialPort) { serialPort = await navigator.serial.requestPort(); }
if (!serialPort) { return; }

// Wait for the serial port to open at 2 Mbps
await serialPort.open({ baudRate: 2000000 });

// Capture the events for closing the read and write streams
var writableStreamClosed = null;
var readableStreamClosed = null;

// Send command to BL602
{
// Open a write stream
console.log("Writing to BL602: " + command + "...");
const textEncoder = new TextEncoderStream();
writableStreamClosed = textEncoder.readable.pipeTo(serialPort.writable);
const writer = textEncoder.writable.getWriter();

// Write the command
await writer.write(command + "\r");

// Close the write stream
writer.close();
}

// Read response from BL602
if (expectedResponse) {
// Open a read stream
console.log("Reading from BL602...");
const textDecoder = new TextDecoderStream();
readableStreamClosed = serialPort.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable.getReader();

// Listen to data coming from the serial device
while (true) {
const { value, done } = await reader.read();
if (!done) { console.log(value); }

// If the stream has ended, or the data contains expected response, we stop
if (done || value.indexOf(expectedResponse) >= 0) { break; }
}

// Close the read stream
reader.cancel();
}

// Wait for read and write streams to be closed
if (readableStreamClosed) { await readableStreamClosed.catch(() => { /* Ignore the error */ }); }
if (writableStreamClosed) { await writableStreamClosed; }

// Close the port
await serialPort.close();
console.log("runWebSerial: OK");
}
Loading