diff --git a/src/components/Blockly/BlocklyComponent.jsx b/src/components/Blockly/BlocklyComponent.jsx index 3bc97aa..631b25d 100644 --- a/src/components/Blockly/BlocklyComponent.jsx +++ b/src/components/Blockly/BlocklyComponent.jsx @@ -27,6 +27,7 @@ import './BlocklyComponent.css'; import Blockly from 'blockly/core'; //import locale from 'blockly/msg/en'; import 'blockly/blocks'; +import Toolbox from './toolbox/Toolbox'; //Blockly.setLocale(locale); @@ -61,13 +62,11 @@ class BlocklyComponent extends React.Component { } render() { - const { children } = this.props; + return
- - {children} - + ; } } diff --git a/src/components/Blockly/blocks/index.js b/src/components/Blockly/blocks/index.js index 3caa84b..e5c75e7 100644 --- a/src/components/Blockly/blocks/index.js +++ b/src/components/Blockly/blocks/index.js @@ -1,4 +1,6 @@ import './loops'; import './sensebox'; import './logic'; -import './sensebox-sensors'; \ No newline at end of file +import './sensebox-sensors'; +import './sensebox-telegram'; +import './io'; \ No newline at end of file diff --git a/src/components/Blockly/blocks/io.js b/src/components/Blockly/blocks/io.js new file mode 100644 index 0000000..f17149d --- /dev/null +++ b/src/components/Blockly/blocks/io.js @@ -0,0 +1,257 @@ +/** + * @license Licensed under the Apache License, Version 2.0 (the "License"): + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @fileoverview Blocks for Arduino Digital and Analogue input and output + * functions. The Arduino function syntax can be found at + * http://arduino.cc/en/Reference/HomePage + * + * TODO: maybe change this to a "PIN" BlocklyType + */ +import { defineBlocksWithJsonArray } from 'blockly'; +import Blockly from 'blockly/core'; +import { selectedBoard } from '../helpers/board' + + +Blockly.Blocks['io_digitalwrite'] = { + /** + * Block for creating a 'set pin' to a state. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/DigitalWrite'); + this.setColour(250); + this.appendValueInput('STATE') + .appendField(Blockly.Msg.ARD_DIGITALWRITE) + .appendField(new Blockly.FieldDropdown( + selectedBoard().digitalPins), 'PIN') + .appendField(Blockly.Msg.ARD_WRITE_TO) + // .setCheck(Blockly.Types.BOOLEAN.checkList); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.ARD_DIGITALWRITE_TIP); + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown( + this, 'PIN', 'digitalPins'); + } +}; + +Blockly.Blocks['io_digitalread'] = { + /** + * Block for creating a 'read pin'. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/DigitalRead'); + this.setColour(250); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_DIGITALREAD) + .appendField(new Blockly.FieldDropdown( + Blockly.Arduino.Boards.selected.digitalPins), 'PIN'); + this.setOutput(true, Blockly.Types.BOOLEAN.output); + this.setTooltip(Blockly.Msg.ARD_DIGITALREAD_TIP); + }, + /** @return {!string} The type of return value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.BOOLEAN; + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown( + this, 'PIN', 'digitalPins'); + } +}; + +Blockly.Blocks['io_builtin_led'] = { + /** + * Block for setting built-in LED to a state. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/DigitalWrite'); + this.setColour(250); + this.appendValueInput('STATE') + .appendField(Blockly.Msg.ARD_BUILTIN_LED) + .appendField(new Blockly.FieldDropdown( + Blockly.Arduino.Boards.selected.builtinLed), 'BUILT_IN_LED') + .appendField(Blockly.Msg.ARD_WRITE_TO) + .setCheck(Blockly.Types.BOOLEAN.checkList); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.ARD_BUILTIN_LED_TIP); + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown( + this, 'BUILT_IN_LED', 'builtinLed'); + }, + /** @return {!string} The type of input value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.BOOLEAN; + }, +}; + +Blockly.Blocks['io_analogwrite'] = { + /** + * Block for creating a 'set pin' to an analogue value. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/AnalogWrite'); + this.setColour(250); + this.appendValueInput('NUM') + .appendField(Blockly.Msg.ARD_ANALOGWRITE) + .appendField(new Blockly.FieldDropdown( + Blockly.Arduino.Boards.selected.pwmPins), 'PIN') + .appendField(Blockly.Msg.ARD_WRITE_TO) + .setCheck(Blockly.Types.NUMBER.output); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.ARD_ANALOGWRITE_TIP); + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown(this, 'PIN', 'pwmPins'); + }, + /** @return {!string} The type of input value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.NUMBER; + }, +}; + +Blockly.Blocks['io_analogread'] = { + /** + * Block for reading an analogue input. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/AnalogRead'); + this.setColour(250); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_ANALOGREAD) + .appendField(new Blockly.FieldDropdown( + Blockly.Arduino.Boards.selected.analogPins), 'PIN'); + this.setOutput(true, Blockly.Types.NUMBER.output); + this.setTooltip(Blockly.Msg.ARD_ANALOGREAD_TIP); + }, + /** @return {!string} The type of return value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.NUMBER; + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown(this, 'PIN', 'analogPins'); + } +}; + +Blockly.Blocks['io_highlow'] = { + /** + * Block for creating a pin state. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/Constants'); + this.setColour(250); + this.appendDummyInput() + .appendField( + new Blockly.FieldDropdown([[Blockly.Msg.ARD_HIGH, 'HIGH'], [Blockly.Msg.ARD_LOW, 'LOW']]), + 'STATE'); + this.setOutput(true, Blockly.Types.BOOLEAN.output); + this.setTooltip(Blockly.Msg.ARD_HIGHLOW_TIP); + }, + /** @return {!string} The type of return value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.BOOLEAN; + } +}; + +Blockly.Blocks['io_pulsein'] = { + /** + * Block for measuring the duration of a pulse in an input pin. + * @this Blockly.Block + */ + init: function () { + this.jsonInit({ + "type": "math_foo", + "message0": Blockly.Msg.ARD_PULSE_READ, + "args0": [{ + "type": "input_value", + "name": "PULSETYPE", + "check": Blockly.Types.BOOLEAN.check + }, { + "type": "field_dropdown", + "name": "PULSEPIN", + "options": Blockly.Arduino.Boards.selected.digitalPins + } + ], + "output": Blockly.Types.NUMBER.output, + "inputsInline": true, + "colour": 250, + "tooltip": Blockly.Msg.ARD_PULSE_TIP, + "helpUrl": 'https://www.arduino.cc/en/Reference/PulseIn' + }); + }, + /** @return {!string} The type of input value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.NUMBER; + } +}; + +Blockly.Blocks['io_pulsetimeout'] = { + /** + * Block for measuring (with a time-out) the duration of a pulse in an input + * pin. + * @this Blockly.Block + */ + init: function () { + this.jsonInit({ + "type": "math_foo", + "message0": Blockly.Msg.ARD_PULSE_READ_TIMEOUT, + "args0": [{ + "type": "input_value", + "name": "PULSETYPE", + "check": Blockly.Types.BOOLEAN.check + }, { + "type": "field_dropdown", + "name": "PULSEPIN", + "options": Blockly.Arduino.Boards.selected.digitalPins + }, { + "type": "input_value", + "name": "TIMEOUT", + "check": Blockly.Types.NUMBER.check + } + ], + "output": Blockly.Types.NUMBER.output, + "inputsInline": true, + "colour": 250, + "tooltip": Blockly.Msg.ARD_PULSETIMEOUT_TIP, + "helpUrl": 'https://www.arduino.cc/en/Reference/PulseIn' + }); + }, + /** @return {!string} The type of input value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.NUMBER; + } +}; diff --git a/src/components/Blockly/blocks/sensebox-telegram.js b/src/components/Blockly/blocks/sensebox-telegram.js new file mode 100644 index 0000000..2ba704d --- /dev/null +++ b/src/components/Blockly/blocks/sensebox-telegram.js @@ -0,0 +1,17 @@ +import Blockly from 'blockly'; + +Blockly.Blocks["sensebox_telegram"] = { + init: function () { + this.setColour(120); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_telegram_init); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField("telegram") + .appendField(new Blockly.FieldTextInput("token"), "telegram_token"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + + diff --git a/src/components/Blockly/blocks/sensebox.js b/src/components/Blockly/blocks/sensebox.js index 18ce462..43ebcbb 100644 --- a/src/components/Blockly/blocks/sensebox.js +++ b/src/components/Blockly/blocks/sensebox.js @@ -1,16 +1,4 @@ import Blockly from 'blockly'; -Blockly.Blocks["sensebox_telegram"] = { - init: function () { - this.setColour(120); - this.appendDummyInput() - .appendField(Blockly.Msg.senseBox_telegram_init); - this.appendDummyInput() - .setAlign(Blockly.ALIGN_LEFT) - .appendField("telegram") - .appendField(new Blockly.FieldTextInput("token"), "telegram_token"); - this.setPreviousStatement(true, null); - this.setNextStatement(true, null); - } -}; + diff --git a/src/components/Blockly/generator/index.js b/src/components/Blockly/generator/index.js index 271af4a..c629df3 100644 --- a/src/components/Blockly/generator/index.js +++ b/src/components/Blockly/generator/index.js @@ -2,4 +2,6 @@ import './generator'; import './loops'; import './sensebox'; import './logic'; +import './math'; +import './io'; diff --git a/src/components/Blockly/generator/io.js b/src/components/Blockly/generator/io.js new file mode 100644 index 0000000..5cef62a --- /dev/null +++ b/src/components/Blockly/generator/io.js @@ -0,0 +1,32 @@ +import * as Blockly from 'blockly/core'; +import { Block } from 'blockly'; + +/** + * Function for 'set pin' (X) to a state (Y). + * Arduino code: setup { pinMode(X, OUTPUT); } + * loop { digitalWrite(X, Y); } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['io_digitalwrite'] = function (block) { + var pin = block.getFieldValue('PIN'); + var stateOutput = Blockly.Arduino.valueToCode( + block, 'STATE', Blockly['Arduino'].ORDER_ATOMIC) || 'LOW'; + Blockly['Arduino'].setupCode_['pinMode'] = 'pinMode(' + pin + ', OUTPUT);'; + var code = 'digitalWrite(' + pin + ', ' + stateOutput + ');\n'; + return code; +}; + +/** + * Function for reading a digital pin (X). + * Arduino code: setup { pinMode(X, INPUT); } + * loop { digitalRead(X) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['io_digitalread'] = function (block) { + var pin = block.getFieldValue('PIN'); + Blockly['Arduino'].setupCode_['pinMode' + pin] = 'pinMode(' + pin + ', INPUT);' + var code = 'digitalRead(' + pin + ')'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; diff --git a/src/components/Blockly/generator/math.js b/src/components/Blockly/generator/math.js new file mode 100644 index 0000000..0832e0c --- /dev/null +++ b/src/components/Blockly/generator/math.js @@ -0,0 +1,344 @@ + +import * as Blockly from 'blockly/core'; +import { Block } from 'blockly'; + +/** + * @license Licensed under the Apache License, Version 2.0 (the "License"): + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @fileoverview Generating Arduino code for the Math blocks. + * + * TODO: Math on list needs lists to be implemented. + * math_constant and math_change needs to be tested in compiler. + */ + +/** + * Generator for a numeric value (X). + * Arduino code: loop { X } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_number'] = function (block) { + // Numeric value. + var code = parseFloat(block.getFieldValue('NUM')); + if (code == Infinity) { + code = 'INFINITY'; + } else if (code == -Infinity) { + code = '-INFINITY'; + } + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +/** + * Generator for a basic arithmetic operators (X and Y) and power function + * (X ^ Y). + * Arduino code: loop { X operator Y } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_arithmetic'] = function (block) { + var OPERATORS = { + ADD: [' + ', Blockly.Arduino.ORDER_ADDITIVE], + MINUS: [' - ', Blockly.Arduino.ORDER_ADDITIVE], + MULTIPLY: [' * ', Blockly.Arduino.ORDER_MULTIPLICATIVE], + DIVIDE: [' / ', Blockly.Arduino.ORDER_MULTIPLICATIVE], + POWER: [null, Blockly.Arduino.ORDER_NONE] // Handle power separately. + }; + var tuple = OPERATORS[block.getFieldValue('OP')]; + var operator = tuple[0]; + var order = tuple[1]; + var argument0 = Blockly.Arduino.valueToCode(block, 'A', order) || '0'; + var argument1 = Blockly.Arduino.valueToCode(block, 'B', order) || '0'; + var code; + // Power in C++ requires a special case since it has no operator. + if (!operator) { + code = 'Math.pow(' + argument0 + ', ' + argument1 + ')'; + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; + } + code = argument0 + operator + argument1; + return [code, order]; +}; + +/** + * Generator for math operators that contain a single operand (X). + * Arduino code: loop { operator(X) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_single'] = function (block) { + var operator = block.getFieldValue('OP'); + var code; + var arg; + if (operator == 'NEG') { + // Negation is a special case given its different operator precedents. + arg = Blockly.Arduino.valueToCode(block, 'NUM', + Blockly.Arduino.ORDER_UNARY_PREFIX) || '0'; + if (arg[0] == '-') { + // --3 is not legal in C++ in this context. + arg = ' ' + arg; + } + code = '-' + arg; + return [code, Blockly.Arduino.ORDER_UNARY_PREFIX]; + } + if (operator == 'ABS' || operator.substring(0, 5) == 'ROUND') { + arg = Blockly.Arduino.valueToCode(block, 'NUM', + Blockly.Arduino.ORDER_UNARY_POSTFIX) || '0'; + } else if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { + arg = Blockly.Arduino.valueToCode(block, 'NUM', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + } else { + arg = Blockly.Arduino.valueToCode(block, 'NUM', + Blockly.Arduino.ORDER_NONE) || '0'; + } + // First, handle cases which generate values that don't need parentheses. + switch (operator) { + case 'ABS': + code = 'abs(' + arg + ')'; + break; + case 'ROOT': + code = 'sqrt(' + arg + ')'; + break; + case 'LN': + code = 'log(' + arg + ')'; + break; + case 'EXP': + code = 'exp(' + arg + ')'; + break; + case 'POW10': + code = 'pow(10,' + arg + ')'; + break; + case 'ROUND': + code = 'round(' + arg + ')'; + break; + case 'ROUNDUP': + code = 'ceil(' + arg + ')'; + break; + case 'ROUNDDOWN': + code = 'floor(' + arg + ')'; + break; + case 'SIN': + code = 'sin(' + arg + ' / 180 * Math.PI)'; + break; + case 'COS': + code = 'cos(' + arg + ' / 180 * Math.PI)'; + break; + case 'TAN': + code = 'tan(' + arg + ' / 180 * Math.PI)'; + break; + } + if (code) { + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; + } + // Second, handle cases which generate values that may need parentheses. + switch (operator) { + case 'LOG10': + code = 'log(' + arg + ') / log(10)'; + break; + case 'ASIN': + code = 'asin(' + arg + ') / M_PI * 180'; + break; + case 'ACOS': + code = 'acos(' + arg + ') / M_PI * 180'; + break; + case 'ATAN': + code = 'atan(' + arg + ') / M_PI * 180'; + break; + default: + throw 'Unknown math operator: ' + operator; + } + return [code, Blockly.Arduino.ORDER_MULTIPLICATIVE]; +}; + +/** + * Generator for math constants (PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), + * INFINITY). + * Arduino code: loop { constant } + * TODO: Might need to include "#define _USE_MATH_DEFINES" + * The arduino header file already includes math.h + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['math_constant'] = function (block) { + var CONSTANTS = { + 'PI': ['M_PI', Blockly.Arduino.ORDER_UNARY_POSTFIX], + 'E': ['M_E', Blockly.Arduino.ORDER_UNARY_POSTFIX], + 'GOLDEN_RATIO': ['(1 + sqrt(5)) / 2', Blockly.Arduino.ORDER_MULTIPLICATIVE], + 'SQRT2': ['M_SQRT2', Blockly.Arduino.ORDER_UNARY_POSTFIX], + 'SQRT1_2': ['M_SQRT1_2', Blockly.Arduino.ORDER_UNARY_POSTFIX], + 'INFINITY': ['INFINITY', Blockly.Arduino.ORDER_ATOMIC] + }; + return CONSTANTS[block.getFieldValue('CONSTANT')]; +}; + +/** + * Generator for math checks: if a number is even, odd, prime, whole, positive, + * negative, or if it is divisible by certain number. Returns true or false. + * Arduino code: complex code, can create external functions. + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_number_property'] = function (block) { + var number_to_check = Blockly.Arduino.valueToCode(block, 'NUMBER_TO_CHECK', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + var dropdown_property = block.getFieldValue('PROPERTY'); + var code; + if (dropdown_property == 'PRIME') { + var func = [ + 'boolean ' + Blockly.Arduino.DEF_FUNC_NAME + '(int n) {', + ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods', + ' if (n == 2 || n == 3) {', + ' return true;', + ' }', + ' // False if n is NaN, negative, is 1.', + ' // And false if n is divisible by 2 or 3.', + ' if (isnan(n) || (n <= 1) || (n == 1) || (n % 2 == 0) || ' + + '(n % 3 == 0)) {', + ' return false;', + ' }', + ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).', + ' for (int x = 6; x <= sqrt(n) + 1; x += 6) {', + ' if (n % (x - 1) == 0 || n % (x + 1) == 0) {', + ' return false;', + ' }', + ' }', + ' return true;', + '}']; + var funcName = Blockly.Arduino.addFunction('mathIsPrime', func.join('\n')); + Blockly.Arduino.addInclude('math', '#include '); + code = funcName + '(' + number_to_check + ')'; + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; + } + switch (dropdown_property) { + case 'EVEN': + code = number_to_check + ' % 2 == 0'; + break; + case 'ODD': + code = number_to_check + ' % 2 == 1'; + break; + case 'WHOLE': + Blockly.Arduino.addInclude('math', '#include '); + code = '(floor(' + number_to_check + ') == ' + number_to_check + ')'; + break; + case 'POSITIVE': + code = number_to_check + ' > 0'; + break; + case 'NEGATIVE': + code = number_to_check + ' < 0'; + break; + case 'DIVISIBLE_BY': + var divisor = Blockly.Arduino.valueToCode(block, 'DIVISOR', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + code = number_to_check + ' % ' + divisor + ' == 0'; + break; + } + return [code, Blockly.Arduino.ORDER_EQUALITY]; +}; + +/** + * Generator to add (Y) to a variable (X). + * If variable X has not been declared before this block it will be declared as + * a (not initialised) global int, however globals are 0 initialised in C/C++. + * Arduino code: loop { X += Y; } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_change'] = function (block) { + var argument0 = Blockly.Arduino.valueToCode(block, 'DELTA', + Blockly.Arduino.ORDER_ADDITIVE) || '0'; + var varName = Blockly.Arduino.variableDB_.getName( + block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + return varName + ' += ' + argument0 + ';\n'; +}; + +/** Rounding functions have a single operand. */ +Blockly.Arduino['math_round'] = Blockly.Arduino['math_single']; + +/** Trigonometry functions have a single operand. */ +Blockly.Arduino['math_trig'] = Blockly.Arduino['math_single']; + +/** + * Generator for the math function to a list. + * Arduino code: ??? + * TODO: List have to be implemented first. Removed from toolbox for now. + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_on_list'] = Blockly.Arduino.noGeneratorCodeInline; + +/** + * Generator for the math modulo function (calculates remainder of X/Y). + * Arduino code: loop { X % Y } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_modulo'] = function (block) { + var argument0 = Blockly.Arduino.valueToCode(block, 'DIVIDEND', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + var argument1 = Blockly.Arduino.valueToCode(block, 'DIVISOR', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + var code = argument0 + ' % ' + argument1; + return [code, Blockly.Arduino.ORDER_MULTIPLICATIVE]; +}; + +/** + * Generator for clipping a number(X) between two limits (Y and Z). + * Arduino code: loop { (X < Y ? Y : ( X > Z ? Z : X)) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_constrain'] = function (block) { + // Constrain a number between two limits. + var argument0 = Blockly.Arduino.valueToCode(block, 'VALUE', + Blockly.Arduino.ORDER_NONE) || '0'; + var argument1 = Blockly.Arduino.valueToCode(block, 'LOW', + Blockly.Arduino.ORDER_NONE) || '0'; + var argument2 = Blockly.Arduino.valueToCode(block, 'HIGH', + Blockly.Arduino.ORDER_NONE) || '0'; + var code = '(' + argument0 + ' < ' + argument1 + ' ? ' + argument1 + + ' : ( ' + argument0 + ' > ' + argument2 + ' ? ' + argument2 + ' : ' + + argument0 + '))'; + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; +}; + +/** + * Generator for a random integer between two numbers (X and Y). + * Arduino code: loop { math_random_int(X, Y); } + * and an aditional math_random_int function + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_random_int'] = function (block) { + var argument0 = Blockly.Arduino.valueToCode(block, 'FROM', + Blockly.Arduino.ORDER_NONE) || '0'; + var argument1 = Blockly.Arduino.valueToCode(block, 'TO', + Blockly.Arduino.ORDER_NONE) || '0'; + var functionName = Blockly.Arduino.variableDB_.getDistinctName( + 'math_random_int', Blockly.Generator.NAME_TYPE); + Blockly.Arduino.setups_['init_rand'] = 'randomSeed(analogRead(0));'; + Blockly.Arduino.math_random_int.random_function = functionName; + var func = [ + 'int ' + Blockly.Arduino.DEF_FUNC_NAME + '(int min, int max) {', + ' if (min > max) {', + ' // Swap min and max to ensure min is smaller.', + ' int temp = min;', + ' min = max;', + ' max = temp;', + ' }', + ' return min + (rand() % (max - min + 1));', + '}']; + var funcName = Blockly.Arduino.addFunction('mathRandomInt', func.join('\n')); + var code = funcName + '(' + argument0 + ', ' + argument1 + ')'; + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; +}; + +/** + * Generator for a random float from 0 to 1. + * Arduino code: loop { (rand() / RAND_MAX) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['math_random_float'] = function (block) { + return ['(rand() / RAND_MAX)', Blockly.Arduino.ORDER_UNARY_POSTFIX]; +}; diff --git a/src/components/Blockly/helpers/board.js b/src/components/Blockly/helpers/board.js new file mode 100644 index 0000000..f6fc279 --- /dev/null +++ b/src/components/Blockly/helpers/board.js @@ -0,0 +1,44 @@ +/** + * Define boards and pins + * + */ +const sensebox_mcu = { + description: 'senseBox Microcontroller Unit based on Microchip SAMD21G18A', + compilerFlag: 'arduino:samd', + digitalPins: [['D1', '1'], ['D2', '2'], ['D3', '3'], ['D4', '4'], ['D5', '5'], ['D6', '6']], + digitalPinsLED: [['BUILTIN_1', '7'], ['BUILTIN_2', '8'], ['D1', '1'], ['D2', '2'], ['D3', '3'], ['D4', '4'], ['D5', '5'], ['D6', '6']], + digitalPinsButton: [['on Board', '0'], ['D1', '1'], ['D2', '2'], ['D3', '3'], ['D4', '4'], ['D5', '5'], ['D6', '6']], + pwmPins: [['D1', '1'], ['D2', '2'], ['D3', '3'], ['D4', '4'], ['D5', '5'], ['D6', '6']], + serial: [['serial', 'SerialUSB'], ['serial_1', 'Serial1'], ['serial_2', 'Serial2']], + serialPins: { + SerialUSB: [['RX', ''], ['TX', '']], + Serial1: [['RX', '11'], ['TX', '10']], + Serial2: [['RX', '13'], ['TX', '12']] + }, + serialSpeed: [['300', '300'], ['600', '600'], ['1200', '1200'], + ['2400', '2400'], ['4800', '4800'], ['9600', '9600'], + ['14400', '14400'], ['19200', '19200'], ['28800', '28800'], + ['31250', '31250'], ['38400', '38400'], ['57600', '57600'], + ['115200', '115200']], + spi: [['SPI', 'SPI']], + spiPins: { SPI: [['MOSI', '19'], ['MISO', '21'], ['SCK', '20']] }, + spiClockDivide: [['2 (8MHz)', 'SPI_CLOCK_DIV2'], + ['4 (4MHz)', 'SPI_CLOCK_DIV4'], + ['8 (2MHz)', 'SPI_CLOCK_DIV8'], + ['16 (1MHz)', 'SPI_CLOCK_DIV16'], + ['32 (500KHz)', 'SPI_CLOCK_DIV32'], + ['64 (250KHz)', 'SPI_CLOCK_DIV64'], + ['128 (125KHz)', 'SPI_CLOCK_DIV128']], + i2c: [['I2C', 'Wire']], + i2cPins: { Wire: [['SDA', '17'], ['SCL', '16']] }, + i2cSpeed: [['100kHz', '100000L'], ['400kHz', '400000L']], + builtinLed: [['BUILTIN_1', '7'], ['BUILTIN_2', '8']], + interrupt: [['interrupt1', '1'], ['interrupt2', '2'], , ['interrupt3', '3'], ['interrupt4', '4'], ['interrupt5', '5'], ['interrupt6', '6']], + analogPins: [['A1', 'A1'], ['A2', 'A2'], ['A3', 'A3'], ['A4', 'A4'], ['A5', 'A5'], ['A6', 'A6']], + serial_baud_rate: 9600, + parseKey: '_*_' +}; + +export const selectedBoard = () => { + return sensebox_mcu; +}; diff --git a/src/components/Blockly/toolbox/Toolbox.js b/src/components/Blockly/toolbox/Toolbox.js new file mode 100644 index 0000000..ccbf34d --- /dev/null +++ b/src/components/Blockly/toolbox/Toolbox.js @@ -0,0 +1,110 @@ +import React, { Component } from 'react'; +import BlocklyComponent, { Block, Value, Field, Shadow, Category } from '../'; + + +class Toolbox extends React.Component { + constructor(props) { + super(props); + } + + render() { + return ( + + + + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + 1 + + + + + 10 + + + + + 1 + + + + + + + + + + + + + + + + 1 + + + + + + + + + 1 + + + + + 100 + + + + + + + 1 + + + + + 100 + + + + + {/* */} + + + + + + + + ); + }; +} + +export default Toolbox; \ No newline at end of file diff --git a/src/components/Home.js b/src/components/Home.js index 289b155..64b4237 100644 --- a/src/components/Home.js +++ b/src/components/Home.js @@ -7,8 +7,9 @@ import BlocklyComponent, { Block, Value, Field, Shadow, Category } from './Block import * as Blockly from 'blockly/core'; import * as De from './Blockly/msg/de'; // de locale files //import * as En from './Blockly/msg/en'; // de locale files -import './Blockly/blocks/index'; -import './Blockly/generator/index'; +import './Blockly/blocks/'; +import './Blockly/generator/'; + @@ -43,27 +44,7 @@ class Home extends React.Component { drag: true, wheel: true }} - initialXml={''}> - - - - - - - - - - - - - - - - - - - - + initialXml={''} />
);