Commit 3c528981 authored by carlosperate's avatar carlosperate

Update serial blocks & addX functions to main Arduino generator.

Improved the prompt for text input.
Individual functions for addSetup, addFunction, and addInclude created in the main Arduino generator, this should
parent 11d797fb
......@@ -2,13 +2,13 @@
## Linux specific
- [ ] Test load to board in Linux with Arduino 1.6 (current test in raspberry pi and ubuntu to load sketches in the IDE) with python 2
- [ ] Test server components in Linux with python 3
- [ ] Comprehensive test of server with python 3
- [ ] Current port list shows all dev/tty, as all Arduinos should be connected by USB this list can be filtered to only show ttyUSBx ports
## Mac OS X specific
- [ ] Test server components in Mac OS X with python 2
- [ ] Test server components in Mac OS X with python 3
- [ ] Comprehensive test of server with python 2
- [ ] Comprehensive test of server with python 3
## Windows specific
......@@ -48,7 +48,7 @@ There was an error manipulating the sketch data!!
## Arduino generator related code
- [x] ~~Add information for other Arduino boards~~
- [ ] Text trim does not currently generate Arduino valid code
## Arduino blocks
- [x] ~~Add a way to select different Arduino boards (settings menu should trigger arduino generator board change)~~
......@@ -57,7 +57,7 @@ There was an error manipulating the sketch data!!
- [ ] SPI pin reservation log needs to be refactored for the new board settings
- [ ] Create I2C communication blocks
- [ ] Update the serial print block to specify explicit type (hex, str, int, etc)
- [ ]
- [ ] Look into all the serial functions and decide what else might fit in
## Arduino front end
......
......@@ -93,13 +93,8 @@
</block>
<block type="text_length"></block>
<block type="text_isEmpty"></block>
<block type="text_trim"></block>
<block type="text_print"></block>
<block type="text_prompt_ext">
<value name="TEXT">
<block type="text"></block>
</value>
</block>
<!--block type="text_trim"></block Need to update block -->
<!--block type="text_print"></block Part of the serial comms -->
</category>
<sep></sep>
<category name="Variables">
......@@ -185,8 +180,13 @@
</category>
<sep></sep>
<category name="Comms">
<block type="serial_setup"></block>
<block type="serial_print"></block>
<block type="serial_speed"></block>
<block type="text_prompt_ext">
<value name="TEXT">
<block type="text"></block>
</value>
</block>
<block type="spi_config"></block>
<block type="spi_transfer"></block>
</category>
......
<xml>
<block type="serial_speed" id="9" x="314" y="68">
<block type="serial_setup" id="9" x="314" y="68">
<field name="SERIAL_ID">Serial</field>
<field name="SPEED">9600</field>
</block>
......
......@@ -33,8 +33,8 @@ Blockly.Blocks['serial_print'] = {
this.appendValueInput('CONTENT', Blockly.StaticTyping.blocklyType.TEXT)
.setCheck(Blockly.StaticTyping.blocklyType.TEXT);
this.appendDummyInput()
.appendField('with new line')
.appendField(new Blockly.FieldCheckbox('TRUE'), 'NEW_LINE');
.appendField(new Blockly.FieldCheckbox("TRUE"), "NEW_LINE")
.appendField("add new line");
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
......@@ -43,17 +43,14 @@ Blockly.Blocks['serial_print'] = {
},
/**
* Called whenever anything on the workspace changes.
* It checks the instances of serial_speed and attaches a warning to this
* It checks the instances of serial_setup and attaches a warning to this
* block if not valid data is found.
* @this Blockly.Block
*/
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
if (!this.workspace) { return; } // Block has been deleted.
// Get the Serial instance from this block
var InstanceName = null;
var InstanceName = this.getFieldValue('SERIAL_ID');
// Iterate through blocks to find a setup instance for the same serial id.
......@@ -71,10 +68,11 @@ Blockly.Blocks['serial_print'] = {
if (!setupInstancePresent) {
this.setWarningText('A setup block for '+ InstanceName + ' must be ' +
'added to the workspace to use this block!');
'added to the workspace to use this block!',
'serial_setup');
} else {
this.setWarningText(null);
} /* */
this.setWarningText(null, 'serial_setup');
}
},
/** Updates the content of the the serial related fields. */
updateFields: function() {
......@@ -83,7 +81,7 @@ Blockly.Blocks['serial_print'] = {
}
};
Blockly.Blocks['serial_speed'] = {
Blockly.Blocks['serial_setup'] = {
/**
* Block for setting the speed of the serial connection.
* @this Blockly.Block
......@@ -105,14 +103,13 @@ Blockly.Blocks['serial_speed'] = {
this.setTooltip('Selects the speed for a specific Serial peripheral');
},
/**
* Returns the serial_speed instance name, defined in the 'SERIAL_ID' drop
* Returns the serial_setup instance name, defined in the 'SERIAL_ID' drop
* down of this block.
* @return {!Array.<string>} List with the instance name.
* @this Blockly.Block
*/
getSerialSetupInstance: function() {
var instanceName = this.getFieldValue('SERIAL_ID');
return [instanceName];
return this.getFieldValue('SERIAL_ID');;
},
/** Updates the content of the the serial related fields. */
updateFields: function() {
......
......@@ -704,7 +704,8 @@ Blockly.Blocks['text_prompt_ext'] = {
*/
init: function() {
var TYPES =
[[Blockly.Msg.TEXT_PROMPT_TYPE_TEXT, 'TEXT'],
[[Blockly.Msg.TEXT_PROMPT_TYPE_TEXT,
Blockly.StaticTyping.blocklyType.TEXT],
[Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER,
Blockly.StaticTyping.blocklyType.NUMBER]];
// Assign 'this' to a variable for use in the closure below.
......@@ -733,6 +734,6 @@ Blockly.Blocks['text_prompt_ext'] = {
* Assigns a type to the block, prompt always returns a string.
*/
getType: function() {
return Blockly.StaticTyping.blocklyType.TEXT;
return this.getFieldValue('TYPE');
}
};
......@@ -6,7 +6,6 @@
*
* @fileoverview Helper functions for generating Arduino language (C++) for
* blocks.
*
*/
'use strict';
......@@ -21,14 +20,6 @@ goog.require('Blockly.Generator');
*/
Blockly.Arduino = new Blockly.Generator('Arduino');
/**
* As this generator uses static typing, it is created as a member of the
* generator.
* @type !Blockly.StaticTyping
*/
//Blockly.Arduino.StaticTyping = new Blockly.Generator('Arduino');
/**
* List of illegal variable names.
* This is not intended to be a security feature. Blockly is 100% client-side,
......@@ -49,9 +40,7 @@ Blockly.Arduino.addReservedWords(
'lowByte,highByte,bitRead,bitWrite,bitSet,bitClear,bit,attachInterrupt,' +
'detachInterrupt,interrupts,noInterrupts');
/**
* Order of operation ENUMs.
*/
/** Order of operation ENUMs. */
Blockly.Arduino.ORDER_ATOMIC = 0; // 0 "" ...
Blockly.Arduino.ORDER_UNARY_POSTFIX = 1; // expr++ expr-- () [] .
Blockly.Arduino.ORDER_UNARY_PREFIX = 2; // -expr !expr ~expr ++expr --expr
......@@ -75,15 +64,21 @@ Blockly.Arduino.ORDER_NONE = 99; // (...)
* @param {Blockly.Workspace} workspace Workspace to generate code from.
*/
Blockly.Arduino.init = function(workspace) {
// Create a dictionary of definitions to be printed before setups
// Create a dictionary of definitions to be printed at the top of the sketch
Blockly.Arduino.includes_ = Object.create(null);
// Create a dictionary of definitions to be printed after variable definitions
Blockly.Arduino.definitions_ = Object.create(null);
// Create a dictionary of setups to be printed before the code
Blockly.Arduino.setups_ = Object.create(null);
// Create a dictionary of pins to check if their use conflicts
Blockly.Arduino.pins_ = Object.create(null);
// Create a dictionary of functions from the code generator
Blockly.Arduino.codefunctions_ = Object.create(null);
// Create a dictionary of functions created by the user
Blockly.Arduino.userFunctions_ = Object.create(null);
// Create a dictionary mapping desired function names in definitions_
// to actual function names (to avoid collisions with user functions)
Blockly.Arduino.functionNames_ = Object.create(null);
// Create a dictionary of setups to be printed in the setup() function
Blockly.Arduino.setups_ = Object.create(null);
// Create a dictionary of pins to check if their use conflicts
Blockly.Arduino.pins_ = Object.create(null);
if (!Blockly.Arduino.variableDB_) {
Blockly.Arduino.variableDB_ =
......@@ -122,11 +117,13 @@ Blockly.Arduino.init = function(workspace) {
*/
Blockly.Arduino.finish = function(code) {
// Indent every line.
//TODO: revise regexs
code = ' ' + code.replace(/\n/g, '\n ');
code = code.replace(/\n\s+$/, '\n');
code = 'void loop() {\n' + code + '\n}';
// Convert the definitions dictionary into a list
// TODO: remove regex expression once all includes are moved to their own dict
var imports = [];
var definitions = [];
for (var name in Blockly.Arduino.definitions_) {
......@@ -138,17 +135,72 @@ Blockly.Arduino.finish = function(code) {
}
}
// Convert the setups dictionary into a list
var setups = [];
// Convert the includes, functions, and setup dictionaries into lists
var includes = [], functions = [], userFunctions = [], setups = [];
for (var name in Blockly.Arduino.includes_) {
includes.push(Blockly.Arduino.includes_[name]);
}
for (var name in Blockly.Arduino.codefunctions_) {
functions.push(Blockly.Arduino.codefunctions_[name]);
}
for (var name in Blockly.Arduino.userFunctions_) {
userFunctions.push(Blockly.Arduino.userFunctions_[name]);
}
for (var name in Blockly.Arduino.setups_) {
setups.push(Blockly.Arduino.setups_[name]);
}
var allDefs = imports.join('\n') + definitions.join('\n') +
'\n\nvoid setup() {\n '+ setups.join('\n ') + '\n}';
var allDefs = includes.join('\n') + imports.join('\n') +
definitions.join('\n') + functions.join('\n\n') +
userFunctions.join('\n\n') + '\n\nvoid setup() {\n ' +
setups.join('\n ') + '\n}';
return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code;
};
/**
* Adds a string of "include" code to be added to the sketch.
* Once a include is added it will not get overwritten with new code.
* @param {!string} includetag Identifier for this include code.
* @param {!string} code Code to be included in the setup() function.
*/
Blockly.Arduino.addInclude = function(includetag, code) {
if (Blockly.Arduino.includes_[includetag] === undefined) {
Blockly.Arduino.includes_[includetag] = code;
}
};
/**
* Adds a string of code into the Arduino setup() function. It takes an
* identifier to not repeat the same kind of initialisation code from several
* blocks. If overwrite function is set to true it will overwrite whatever
* value the identifier held before.
* @param {!string} setupTag Identifier for the type of set up code.
* @param {!string} code Code to be included in the setup() function.
* @param {boolean=} overwrite Flag to ignore previously set value.
*/
Blockly.Arduino.addSetup = function(setupTag, code, overwrite) {
if (overwrite) {
Blockly.Arduino.setups_[setupTag] = code;
} else if (Blockly.Arduino.setups_[setupTag] === undefined) {
Blockly.Arduino.setups_[setupTag] = code;
}
};
/**
* Adds a string of code as a function. It takes an identifier (meant to be the
* function name) to only keep a single copy even multiple blocks might request
* this function to appear.
* Once a function is added it will not get overwritten with new code.
* @param {!string} functionName Identifier for the function.
* @param {!string} code Code to be included in the setup() function.
* @param {boolean=} overwrite Description.
*/
Blockly.Arduino.addFunction = function(functionName, code) {
if (Blockly.Arduino.codefunctions_[functionName] === undefined) {
Blockly.Arduino.codefunctions_[functionName] = code;
}
};
/**
* Naked values are top-level blocks with outputs that aren't plugged into
* anything. A trailing semicolon is needed to make this legal.
......@@ -161,7 +213,8 @@ Blockly.Arduino.scrubNakedValue = function(line) {
/**
* Encode a string as a properly escaped Arduino string, complete with quotes.
* @return {string} string Arduino string.
* @param {string} string Text to encode.
* @return {string} Arduino string.
* @private
*/
Blockly.Arduino.quote_ = function(string) {
......
......@@ -43,13 +43,11 @@ Blockly.Arduino['serial_print'] = function(block) {
* @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code.
*/
Blockly.Arduino['serial_speed'] = function(block) {
Blockly.Arduino['serial_setup'] = function(block) {
var serialId = block.getFieldValue('SERIAL_ID');
var serialSpeed = block.getFieldValue('SPEED');
Blockly.Arduino.setups_['setup_serial_' + serialId] =
serialId + '.begin(' + serialSpeed + ');\n';
var serialSetupCode = serialId + '.begin(' + serialSpeed + ');\n';
Blockly.Arduino.addSetup('serial_' + serialId, serialSetupCode, true);
var code = '';
return code;
};
......@@ -9,8 +9,8 @@
* TODO: Too many calls to String constructor, which consumes a lot of
* resources. Once type identification is implemented this will need an
* update.
* TODO: Serial peripheral and speed are hard-coded, should require serial
* setup block.
*
* TODO: Trim generator is not correct.
*/
'use strict';
......@@ -26,7 +26,6 @@ goog.require('Blockly.Arduino');
* @return {array} Completed code with order of operation.
*/
Blockly.Arduino['text'] = function(block) {
// Text value.
var code = Blockly.Arduino.quote_(block.getFieldValue('TEXT'));
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
......@@ -58,7 +57,7 @@ Blockly.Arduino['text_join'] = function(block) {
if (argument == '') {
code[n] = '""';
} else {
code[n] = 'String(' + argument +')';
code[n] = 'String(' + argument + ')';
}
}
code = code.join(' + ');
......@@ -118,7 +117,7 @@ Blockly.Arduino['text_isEmpty'] = function(block) {
func.push(' return false;');
func.push(' }');
func.push('}');
Blockly.Arduino.definitions_['is_string_empty'] = func.join('\n');
Blockly.Arduino.addFunction('is_string_empty', func.join('\n'));
var argument0 = Blockly.Arduino.valueToCode(block, 'VALUE',
Blockly.Arduino.ORDER_UNARY_POSTFIX);
if (argument0 == '') {
......@@ -146,7 +145,7 @@ Blockly.Arduino['text_trim'] = function(block) {
};
var mode = block.getFieldValue('MODE');
var operator = Blockly.Arduino.text_trim.OPERATORS[mode];
var argument0 = Blockly.Arduino.valueToCode(this, 'TEXT',
var argument0 = Blockly.Arduino.valueToCode(block, 'TEXT',
Blockly.Arduino.ORDER_UNARY_POSTFIX);
if (argument0 == '') {
argument0 = '""';
......@@ -157,19 +156,17 @@ Blockly.Arduino['text_trim'] = function(block) {
};
/**
* Code generator to trim spaces from a string (X).
* Code generator to print to the serial comm.
* Serial info: http://arduino.cc/en/Reference/Serial
* Arduino code: setup { Serial.begin(9600); }
* loop { Serial.print(String(X)) }
* TODO: The serial peripheral and speed hard-coded into the code.
* Need to change to request a serial setup block.
* @param {!Blockly.Block} block Block to generate the code from.
* @return {string} Completed code.
*/
Blockly.Arduino['text_print'] = function(block) {
var serialId = Blockly.Arduino.Boards.selected.serial[0][1];
Blockly.Arduino.setups_['setup_serial_' + serialId] =
serialId + '.begin(9600);';
var setupCode = serialId + '.begin(9600);';
Blockly.Arduino.addSetup('serial_' + serialId, setupCode, false);
var argument0 = Blockly.Arduino.valueToCode(block, 'TEXT',
Blockly.Arduino.ORDER_NONE);
if (argument0 == '') {
......@@ -185,27 +182,27 @@ Blockly.Arduino['text_print'] = function(block) {
* Serial info: http://arduino.cc/en/Reference/Serial
* Arduino code: getUserInputPrompt(...) { ... }
* loop { getUserInputPrompt("X")) }
* TODO: The serial peripheral and speed hard-coded into the code.
* Need to change to request a serial setup block.
* @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation.
*/
Blockly.Arduino['text_prompt_ext'] = function(block) {
// Get the first Serial peripheral of arduino board
var serialId = Blockly.Arduino.Boards.selected.serial[0][1];
var returnType = block.getFieldValue('TYPE');
var funcName = 'getUserInputPrompt' + returnType;
// The function code changes based on reading a number or string
var func = [];
var toNumber = block.getFieldValue('TYPE') == 'NUMBER';
var toNumber = returnType == Blockly.StaticTyping.blocklyType.NUMBER;
if (toNumber) {
func.push('int getUserInputPrompt(String msg) {');
func.push('int ' + funcName + '(String msg) {');
} else {
func.push('String getUserInputPrompt(String msg) {');
func.push('String ' + funcName + '(String msg) {');
}
func.push(' ' + serialId + '.print(msg+\'\\n\');');
func.push(' ' + serialId + '.println(msg);');
func.push(' boolean stringComplete = false;');
if (toNumber) {
func.push(' int content = ' + serialId + '.parseInt();');
func.push(' int content = 0;');// + serialId + '.parseInt();');
} else {
func.push(' String content = "";');
}
......@@ -216,32 +213,36 @@ Blockly.Arduino['text_prompt_ext'] = function(block) {
func.push(' stringComplete = true;');
} else {
func.push(' char readChar = (char)' + serialId + '.read();');
func.push(' content += readChar;');
func.push(' if (readChar == \'\\n\' || readChar == \'\\r\') {');
func.push(' stringComplete = true;');
func.push(' } else {');
func.push(' content += readChar;');
func.push(' }');
}
func.push(' }');
func.push(' }');
func.push(' // Empty incoming serial buffer');
func.push(' while(Serial.available()) { Serial.read(); };');
func.push(' return content;');
func.push('}\n\n');
func.push('}');
Blockly.Arduino.addFunction(funcName, func.join('\n'));
Blockly.Arduino.definitions_['define_string_return'] = func.join('\n');
Blockly.Arduino.setups_['setup_serial_' + serialId] =
serialId + '.begin(9600);';
// Only overwrite the serial set up if not present already
var setupCode = serialId + '.begin(9600);';
Blockly.Arduino.addSetup('serial_' + serialId, setupCode, false);
var msg = Blockly.Arduino.valueToCode(block, 'TEXT',
Blockly.Arduino.ORDER_NONE) || '""';
var code = 'getUserInputPrompt(' + msg + ')';
var code = funcName + '(' + msg + ')';
return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX];
};
/* ********************************************************************** *
* The rest of the blocks have been left as it is, as they are be removed *
* from the toolbox and not used for Arduino code. *
* ********************************************************************** */
/* ***************************************************************** *
* The rest of the blocks have been left as it is, as they have been *
* block from the toolbox and not used for Arduino code. *
* ***************************************************************** */
Blockly.Arduino['text_endString'] = function(block) {
// Return a leading or trailing substring.
......@@ -318,7 +319,7 @@ Blockly.Arduino['text_charAt'] = function(block) {
case 'RANDOM':
var functionName = Blockly.Arduino.provideFunction_(
'text_random_letter',
[ 'function ' + Blockly.Arduino.FUNCTION_NAME_PLACEHOLDER_ +
['function ' + Blockly.Arduino.FUNCTION_NAME_PLACEHOLDER_ +
'(text) {',
' var x = Math.floor(Math.random() * text.length);',
' return text[x];',
......@@ -344,7 +345,7 @@ Blockly.Arduino['text_getSubstring'] = function(block) {
} else {
var functionName = Blockly.Arduino.provideFunction_(
'text_get_substring',
[ 'function ' + Blockly.Arduino.FUNCTION_NAME_PLACEHOLDER_ +
['function ' + Blockly.Arduino.FUNCTION_NAME_PLACEHOLDER_ +
'(text, where1, at1, where2, at2) {',
' function getAt(where, at) {',
' if (where == \'FROM_START\') {',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment