/**
 * @license Licensed under the Apache License, Version 2.0 (the "License"):
 *          https://www.apache.org/licenses/LICENSE-2.0
 */

/**
 * @fileOverview Arduino code generator for the Servo library blocks.
 *     The Arduino Servo library docs: https://arduino.cc/en/reference/servo
 *
 * TODO: If angle selector added to blocks edit code here.
 */
'use strict';

goog.provide('Blockly.Arduino.Sensors');

goog.require('Blockly.Arduino');

// Keep generated object names valid even when a variable/expression is used
// as a sensor pin (e.g. "pin + 1").  The expression itself is still emitted
// unchanged as the constructor argument.
function taoyuanSensorIdentifier(value, fallback) {
    var id = String(value == null ? '' : value)
        .replace(/[^a-zA-Z0-9_]/g, '_')
        .replace(/^([0-9])/, '_$1');
    return id || fallback;
}

/**
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {array} Completed code with order of operation.
 */
Blockly.Arduino['ultrasonic_distance'] = function (block) {
    var trigPin = block.getFieldValue('TRIG_PIN') || '2';
    var echoPin = block.getFieldValue('ECHO_PIN') || '3';
    var dUnit = block.getFieldValue('DISTANCE_UNIT') || 'cm';
    var comm = '';

    if (dUnit === 'cm') {
        comm = '(sonic_duration / 2.0) / 29.1';
    } else if (dUnit === 'inch') {
        comm = '(sonic_duration / 2.0) / 74.0';
    }
    // Keep a deterministic function name for each unit and fall back to cm
    // if an old project contains an unknown dropdown value.
    if (!comm) {
        dUnit = 'cm';
        comm = '(sonic_duration / 2.0) / 29.1';
    }
    var udName = 'ultrasonic_distance_' + dUnit;

    Blockly.Arduino.addSetup(udName + '_' + trigPin + '_setup_trig', 'pinMode(' + trigPin + ', OUTPUT);', true);
    Blockly.Arduino.addSetup(udName + '_' + echoPin + '_setup_echo', 'pinMode(' + echoPin + ', INPUT);', true);

    var fCode = 'float ' + Blockly.Arduino.DEF_FUNC_NAME + '(int trigPin, int echoPin){\n' +
        '  digitalWrite(trigPin, LOW);\n' +
  '  // Echo is an input; do not drive it before measuring.\n' +
        '  delayMicroseconds(5);\n' +
        '  digitalWrite(trigPin, HIGH);\n' +
        '  delayMicroseconds(10);\n' +
        '  digitalWrite(trigPin, LOW);\n' +
        '  unsigned long sonic_duration = pulseIn(echoPin, HIGH, 30000);\n' +
        '  float distance_' + dUnit + ' = ' + comm + ';\n\n' +
        '  return distance_' + dUnit + ';\n' +
        '}';

    var functionName = Blockly.Arduino.addFunction(udName, fCode);

    var code = functionName + '(' + trigPin + ', ' + echoPin + ')';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino['tcrt5000'] = function (block) {
    var analog_pin = block.getFieldValue('ANALOG_PIN') || 'A0';

    var code = '(1023 - analogRead(' + analog_pin + '))';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino['tcrt5000_var'] = function (block) {
    var analog_pin = Blockly.Arduino.valueToCode(
        block, 'ANALOG_PIN', Blockly.Arduino.ORDER_ATOMIC) || '0';

    var code = '(1023 - analogRead(' + analog_pin + '))';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['logic_nan'] = function (block) {
    Blockly.Arduino.addInclude('math_inc', '#include <math.h>');
    var value = Blockly.Arduino.valueToCode(
        block, 'VALUE', Blockly.Arduino.ORDER_ATOMIC) || 'NAN';
    var code = 'isnan(' + value + ')';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['DHT11_readTemp'] = function (block) {
    var dataPin = block.getFieldValue('DATAPIN') || 'A3';
    var dhtId = "dht" + taoyuanSensorIdentifier(dataPin, '0');
    var dht11_tag = "dht11_tag_" + taoyuanSensorIdentifier(dataPin, '0');
    var dht11DefineCode = "#define DHTTYPE DHT11";
    var dht11DeclareCode = "DHT " + dhtId + "(" + dataPin + ", DHTTYPE);\n";
    Blockly.Arduino.addInclude("DHT_inc", '#include <DHT.h>');
    Blockly.Arduino.addDefine("dht11_def", dht11DefineCode);
    Blockly.Arduino.addSetup(dht11_tag, dhtId + ".begin();", false);
    Blockly.Arduino.addDeclaration(dht11_tag, dht11DeclareCode)
    var code = dhtId + '.readTemperature()';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['DHT11_readTemp_var'] = function (block) {
    var dataPin = Blockly.Arduino.valueToCode(
        block, 'DATAPIN', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var dhtId = "dht" + taoyuanSensorIdentifier(dataPin, '0');
    var dht11_tag = "dht11_tag_" + taoyuanSensorIdentifier(dataPin, '0');
    var dht11DefineCode = "#define DHTTYPE DHT11";
    var dht11DeclareCode = "DHT " + dhtId + "(" + dataPin + ", DHTTYPE);\n";
    Blockly.Arduino.addInclude("DHT_inc", '#include <DHT.h>');
    Blockly.Arduino.addDefine("dht11_def", dht11DefineCode);
    Blockly.Arduino.addSetup(dht11_tag, dhtId + ".begin();", false);
    Blockly.Arduino.addDeclaration(dht11_tag, dht11DeclareCode)
    var code = dhtId + '.readTemperature()';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino['DHT11_readHumi'] = function (block) {
    var dataPin = block.getFieldValue('DATAPIN') || 'A3';
    var dhtId = "dht" + taoyuanSensorIdentifier(dataPin, '0');
    var dht11_tag = "dht11_tag_" + taoyuanSensorIdentifier(dataPin, '0');
    var dht11DefineCode = "#define DHTTYPE DHT11";
    var dht11DeclareCode = "DHT " + dhtId + "(" + dataPin + ", DHTTYPE);\n";
    Blockly.Arduino.addInclude("DHT_inc", '#include <DHT.h>');
    Blockly.Arduino.addDefine("dht11_def", dht11DefineCode);
    Blockly.Arduino.addSetup(dht11_tag, dhtId + ".begin();", false);
    Blockly.Arduino.addDeclaration(dht11_tag, dht11DeclareCode)
    var code = dhtId + '.readHumidity()';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino['DHT11_readHumi_var'] = function (block) {
    var dataPin = Blockly.Arduino.valueToCode(
        block, 'DATAPIN', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var dhtId = "dht" + taoyuanSensorIdentifier(dataPin, '0');
    var dht11_tag = "dht11_tag_" + taoyuanSensorIdentifier(dataPin, '0');
    var dht11DefineCode = "#define DHTTYPE DHT11";
    var dht11DeclareCode = "DHT " + dhtId + "(" + dataPin + ", DHTTYPE);\n";
    Blockly.Arduino.addInclude("DHT_inc", '#include <DHT.h>');
    Blockly.Arduino.addDefine("dht11_def", dht11DefineCode);
    Blockly.Arduino.addSetup(dht11_tag, dhtId + ".begin();", false);
    Blockly.Arduino.addDeclaration(dht11_tag, dht11DeclareCode)
    var code = dhtId + '.readHumidity()';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['DS18B20_readTemp'] = function (block) {
    var pin = block.getFieldValue('DATAPIN') || '3';
    var pinId = taoyuanSensorIdentifier(pin, '0');
    var oneWireId = 'oneWire_' + pinId;
    var sensorId = 'DS18B20_' + pinId;

    // prefixCode is not consumed by Blockly 13's generator.  Use the comma
    // operator so every value read actually requests a fresh conversion.
    var code = '(' + sensorId + '.requestTemperatures(), ' + sensorId + '.getTempCByIndex(0))';

    Blockly.Arduino.addInclude('OneWire_inc', '#include <OneWire.h>');
    Blockly.Arduino.addInclude('DallasTemperature_inc', '#include <DallasTemperature.h>');
    Blockly.Arduino.addDeclaration(sensorId, 'OneWire ' + oneWireId + '(' + pin + '); \nDallasTemperature ' + sensorId + '(&' + oneWireId + ');');
    Blockly.Arduino.addSetup(sensorId, sensorId + '.begin();', false);

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['DS18B20_readTemp_var'] = function (block) {
    var pin = Blockly.Arduino.valueToCode(
        block, 'DATAPIN', Blockly.Arduino.ORDER_ATOMIC) || '0';

    var pinId = taoyuanSensorIdentifier(pin, '0');
    var oneWireId = 'oneWire_' + pinId;
    var sensorId = 'DS18B20_' + pinId;
    var code = '(' + sensorId + '.requestTemperatures(), ' + sensorId + '.getTempCByIndex(0))';

    Blockly.Arduino.addInclude('OneWire_inc', '#include <OneWire.h>');
    Blockly.Arduino.addInclude('DallasTemperature_inc', '#include <DallasTemperature.h>');
    Blockly.Arduino.addDeclaration(sensorId, 'OneWire ' + oneWireId + '(' + pin + '); \nDallasTemperature ' + sensorId + '(&' + oneWireId + ');');
    Blockly.Arduino.addSetup(sensorId, sensorId + '.begin();', false);

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['photocells_read'] = function (block) {
    var pin = block.getFieldValue('DATAPIN') || 'A2';

    var code = 'analogRead(' + pin + ')';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['photocells_read_var'] = function (block) {
    var pin = Blockly.Arduino.valueToCode(
        block, 'DATAPIN', Blockly.Arduino.ORDER_ATOMIC) || '0';

    var code = 'analogRead(' + pin + ')';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { read lm35; }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['lm35_read'] = function (block) {
    var pin = block.getFieldValue('DATAPIN') || 'A2';

    var code = '((analogRead(' + pin + ') - 102.0) * 100.0 / 207.0)';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['lm35_read_var'] = function (block) {
    var pin = Blockly.Arduino.valueToCode(
        block, 'DATAPIN', Blockly.Arduino.ORDER_ATOMIC) || '0';

    var code = '((analogRead(' + pin + ') - 102.0) * 100.0 / 207.0)';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator for block for setting the serial com speed.
 * Arduino code: setup{ irrecv_Ax.enableIRIn(); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['irrecv_setup'] = function (block) {
    var irrecvName = block.getFieldValue('DATAPIN') || 'A3';
    var irrecvId = 'irrecv_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var decodeId = 'results_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var irrecvVarCode = 'IRrecv ' + irrecvId + '(' + irrecvName + ');';
    var decodeVarCode = 'decode_results ' + decodeId + ';';
    var irrecvSetupCode = irrecvId + '.enableIRIn();';

    Blockly.Arduino.addInclude('IRremote_inc', '#include <IRremote.h>');
    Blockly.Arduino.addVariable(irrecvId, irrecvVarCode, true);
    Blockly.Arduino.addVariable(decodeId, decodeVarCode, true);
    Blockly.Arduino.addSetup('irrecv_' + irrecvId, irrecvSetupCode, true);
    var code = '';
    return code;
};

/**
 * Code generator for block for setting the serial com speed.
 * Arduino code: setup{ irrecv_Ax.enableIRIn(); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['irrecv_setup_var'] = function (block) {
    var irrecvName = Blockly.Arduino.valueToCode(
        block, 'DATAPIN', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var irrecvId = 'irrecv_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var decodeId = 'results_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var irrecvVarCode = 'IRrecv ' + irrecvId + '(' + irrecvName + ');';
    var decodeVarCode = 'decode_results ' + decodeId + ';';
    var irrecvSetupCode = irrecvId + '.enableIRIn();';

    Blockly.Arduino.addInclude('IRremote_inc', '#include <IRremote.h>');
    Blockly.Arduino.addVariable(irrecvId, irrecvVarCode, true);
    Blockly.Arduino.addVariable(decodeId, decodeVarCode, true);
    Blockly.Arduino.addSetup('irrecv_' + irrecvId, irrecvSetupCode, true);
    var code = '';
    return code;
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['irrecv_available'] = function (block) {
    var irrecvName = block.getFieldValue('DATAPIN') || 'A3';
    var irrecvId = 'irrecv_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var decodeId = 'results_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var code = irrecvId + '.decode(&' + decodeId + ')';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['irrecv_available_var'] = function (block) {
    var irrecvName = Blockly.Arduino.valueToCode(
        block, 'DATAPIN', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var irrecvId = 'irrecv_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var decodeId = 'results_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var code = irrecvId + '.decode(&' + decodeId + ')';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['irrecv_read'] = function (block) {
    var irrecvName = block.getFieldValue('DATAPIN') || 'A3';
    var decodeId = 'results_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var code = decodeId + '.value';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code.
 */
Blockly.Arduino['irrecv_read_var'] = function (block) {
    var irrecvName = Blockly.Arduino.valueToCode(
        block, 'DATAPIN', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var decodeId = 'results_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var code = decodeId + '.value';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['irrecv_resume'] = function (block) {
    var irrecvName = block.getFieldValue('DATAPIN') || 'A3';
    var irrecvId = 'irrecv_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var code = irrecvId + '.resume();\n';

    return code;
};

/**
 * Code generator of block for writing to the serial com.
 * Arduino code: loop { Serial.print(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['irrecv_resume_var'] = function (block) {
    var irrecvName = Blockly.Arduino.valueToCode(
        block, 'DATAPIN', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var irrecvId = 'irrecv_' + Blockly.Arduino.variableDB_.getName(
        irrecvName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var code = irrecvId + '.resume();\n';

    return code;
};

/**
 * @param {!Blockly.Block} block Block to generate the code from.
 */
Blockly.Arduino['hx711_setup'] = function (block) {
    var dataPin = block.getFieldValue('DATA_PIN') || '6';
    var clkPin = block.getFieldValue('CLK_PIN') || '5';
    var hx711Id = Blockly.Arduino.variableDB_.getName(
        "hx711_scale",
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.addInclude('HX711_inc', '#include "HX711.h"');
    Blockly.Arduino.addDeclaration('HX711_declar_' + hx711Id, 'HX711 ' + hx711Id + ';');
    Blockly.Arduino.addSetup('HX711_setup_' + hx711Id, hx711Id + '.begin(' + dataPin + ', ' + clkPin + ');', true);

    return "";
};

/** . */
Blockly.Arduino['hx711_set_scale'] = function (block) {
    var scaleValue = Blockly.Arduino.valueToCode(
        block, 'HX711_SET_SCALE', Blockly.Arduino.ORDER_ATOMIC) || '';
    var hx711Id = Blockly.Arduino.variableDB_.getName(
        "hx711_scale",
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    var code = hx711Id + '.set_scale(' + scaleValue + ');\n';

    return code;
};

/** . */
Blockly.Arduino['hx711_tare'] = function (block) {
    var hx711Id = Blockly.Arduino.variableDB_.getName(
        "hx711_scale",
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    var code = hx711Id + '.tare();\n';

    return code;
};

/** . */
Blockly.Arduino['hx711_get_units'] = function (block) {
    var unitsValue = Blockly.Arduino.valueToCode(
        block, 'HX711_GET_UNITS', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var hx711Id = Blockly.Arduino.variableDB_.getName(
        "hx711_scale",
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    var code = hx711Id + '.get_units(' + unitsValue + ')';

    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

/** . */
Blockly.Arduino['hx711_power_down'] = function (block) {
    var hx711Id = Blockly.Arduino.variableDB_.getName(
        "hx711_scale",
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    var code = hx711Id + '.power_down();\n';

    return code;
};

/** . */
Blockly.Arduino['hx711_power_up'] = function (block) {
    var hx711Id = Blockly.Arduino.variableDB_.getName(
        "hx711_scale",
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    var code = hx711Id + '.power_up();\n';

    return code;
};

/**
 * Code generator for block for setting the serial com speed.
 * Arduino code: setup{ Serial.begin(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['I2C_QMC5883L_SETUP'] = function (block) {
    var i2cAddr = block.getFieldValue('QMC5883L_ADDR') || '0x0D';
    var i2cQMC5883LDeclareCode =
        'QMC5883LCompass compass;';
    var i2cQMC5883LSetupCode = 'compass.setADDR(' + i2cAddr + ');\n  compass.init();';

    Blockly.Arduino.addInclude('QMC5883L_inc', '#include <QMC5883LCompass.h>');

    if (Blockly.Arduino.definitions_['QMC5883L_tag'] !== undefined) {
        Blockly.Arduino.definitions_['QMC5883L_tag'] = i2cQMC5883LDeclareCode;
    } else {
        Blockly.Arduino.addDeclaration('QMC5883L_tag', i2cQMC5883LDeclareCode);
    }

    Blockly.Arduino.addSetup('QMC5883L_tag', i2cQMC5883LSetupCode, true);

    var i2cPins = (((Blockly.Arduino.Boards || {}).selected || {}).i2cPins || {}).Wire || [];
    for (var i = 0; i < i2cPins.length; i++) {
        Blockly.Arduino.reservePin(block, i2cPins[i][1],
            Blockly.Arduino.pinTypes.I2C, 'I2C ' + i2cPins[i][0]);
    }
    var code = '';
    return code;
};

//
Blockly.Arduino["I2C_QMC5883L_READ"] = function (block) {
    var code = 'compass.read();\n';
    return code;
}

//
Blockly.Arduino["I2C_QMC5883L_FUN"] = function (block) {
    var fun = block.getFieldValue('FUN') || 'X';
    var code = 'compass.get' + fun + '()';
    return code;
}

//
Blockly.Arduino["I2C_QMC5883L_AZIUMTH"] = function (block) {
    var code = 'compass.getAzimuth()';
    return code;
}

//
Blockly.Arduino["I2C_QMC5883L_BEARING"] = function (block) {
    var azimuthVar = Blockly.Arduino.valueToCode(
        block, 'AZIMUTH', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var code = 'compass.getBearing(' + azimuthVar + ')';
    return code;
}

//
Blockly.Arduino["I2C_QMC5883L_DIRECTION"] = function (block) {
    var azimuthVar = Blockly.Arduino.valueToCode(
        block, 'AZIMUTH', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var arrayVar = Blockly.Arduino.valueToCode(
        block, 'ARRAY', Blockly.Arduino.ORDER_ATOMIC) || 'qmc_direction';
    if (arrayVar === 'qmc_direction') {
        Blockly.Arduino.addDeclaration(
            'qmc_direction', 'char qmc_direction[4] = "";');
    }
    var code = 'compass.getDirection(' + arrayVar + ', ' + azimuthVar + ');\n';
    return code;
}

//
Blockly.Arduino["I2C_QMC5883L_SMOOTHING"] = function (block) {
    var steps = block.getFieldValue('STEPS') || '3';
    var advanced = block.getFieldValue('ADVANCED') || 'false';
    var code = 'compass.setSmoothing(' + steps + ', ' + advanced + ');\n';
    return code;
}

//
Blockly.Arduino["I2C_QMC5883L_SETUP_MODE"] = function (block) {
    var mode = block.getFieldValue('MODE') || '0x01';
    var odr = block.getFieldValue('ODR') || '0x0C';
    var rng = block.getFieldValue('RNG') || '0x10';
    var osr = block.getFieldValue('OSR') || '0x00';
    var code = 'compass.setMode(' + mode + ', ' + odr + ', ' + rng + ', ' + osr + ');\n';
    return code;
}
