/**
 * @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.Motos');

goog.require('Blockly.Arduino');

// Motor Driver Board blocks share one shield object.  Keeping this definition
// in a helper prevents individual blocks from emitting an undeclared
// `mMotorDriver` when the initialization block is not the first block visited.
function ensureMotorDriverDefinition() {
    Blockly.Arduino.definitions_['define_Emakefun_MotorDriver'] =
        '#include <Emakefun_MotorDriver.h>\nEmakefun_MotorDriver mMotorDriver(0x60);\n';
}

/** Servo */
/**
 * Code generator to attach servo to a arduino Pin (X).
 * Arduino code: #include <Servo.h>
 *               Servo ServoX;
 *               setup { ServoX.attach(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['servo_attach'] = function (block) {
    var pinKey = block.getFieldValue('SERVO_PIN');
    var servoName = block.getFieldValue('SERVO_NAME');
    var servoId = Blockly.Arduino.variableDB_.getName(
        servoName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.reservePin(block, pinKey, Blockly.Arduino.pinTypes.SERVO, 'Servo Write');
    Blockly.Arduino.addInclude('Servo_inc', '#include <Servo.h>');
    Blockly.Arduino.addVariable(servoName, 'Servo ' + servoId + ';', true);


    var code = servoId + '.attach(' + pinKey + ');\n';

    return code;
};


/**
 * Code generator to read an angle value from a servo Pin (X).
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code with order of operation.
 */
Blockly.Arduino['servo_read'] = function (block) {
    var servoName = block.getFieldValue('SERVO_NAME');
    var servoId = Blockly.Arduino.variableDB_.getName(
        servoName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.addInclude('Servo_inc', '#include <Servo.h>');
    Blockly.Arduino.addVariable(servoName, 'Servo ' + servoId + ';', true);

    var code = servoId + '.read()';
    return [code, Blockly.Arduino.ORDER_NONE];
};

/**
 * Code generator to set an angle (Y) value to a servo Pin (X).
 * Arduino code: #include <Servo.h>
 *               Servo servo_X;
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */

Blockly.Arduino['servo_write'] = function (block) {
    var servoName = block.getFieldValue('SERVO_NAME');
    var servoAngle = Blockly.Arduino.valueToCode(
        block, 'SERVO_ANGLE', Blockly.Arduino.ORDER_ATOMIC);
    var servoId = Blockly.Arduino.variableDB_.getName(
        servoName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.addInclude('Servo_inc', '#include <Servo.h>');
    Blockly.Arduino.addVariable(servoName, 'Servo ' + servoId + ';', true);

    var code = servoId + '.write(' + servoAngle + ');\n';
    return code;
};

/**
 * Code generator to set an writeMicroseconds (Y) value to a servo Pin (X).
 * Arduino code: #include <Servo.h>
 *               Servo servo_X;
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['servo_pwm'] = function (block) {
    var servoName = block.getFieldValue('SERVO_NAME');
    var servoPWM = Blockly.Arduino.valueToCode(
        block, 'SERVO_PWM', Blockly.Arduino.ORDER_ATOMIC);
    var servoId = Blockly.Arduino.variableDB_.getName(
        servoName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.addInclude('Servo_inc', '#include <Servo.h>');
    Blockly.Arduino.addVariable(servoName, 'Servo ' + servoId + ';', true);

    var code = servoId + '.writeMicroseconds(' + servoPWM + ');\n';
    return code;
};

/**
 * Code generator to set an angle (Y) value to a servo Pin (X).
 * Arduino code: #include <Servo.h>
 *               Servo servo_X;
 *               setup { myServoX.attach(X); }
 *               loop  { myServoX.write(Y);  }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['servo_write_angle'] = function (block) {
    var pinKey = block.getFieldValue('SERVO_PIN');
    var servoAngle = block.getFieldValue('SERVO_ANGLE');
    var servoName = 'myServo' + pinKey;
    var servoDelay = block.getFieldValue('SERVO_DELAY');
    var servoDelayVar = 'servo' + pinKey + 'delaytime';

    Blockly.Arduino.reservePin(
        block, pinKey, Blockly.Arduino.pinTypes.SERVO, 'Servo Write');

    Blockly.Arduino.addInclude('Servo_inc', '#include <Servo.h>');
    Blockly.Arduino.addDeclaration('servo_' + pinKey, 'Servo ' + servoName + ';');

    var code = servoName + '.attach(' + pinKey + ');\n' +
        servoName + '.write(' + servoName + '.read());\n' +
        servoDelayVar + ' = abs(' + servoName + '.read()-' + servoAngle + ')*' + servoDelay + ';\n' +
        servoName + '.write(' + servoAngle + ');\n';
    return code;
};

/**
 * Code generator to detach to a servo Pin (X).
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['servo_detach'] = function (block) {
    var servoName = block.getFieldValue('SERVO_NAME');
    var servoId = Blockly.Arduino.variableDB_.getName(
        servoName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.addInclude('Servo_inc', '#include <Servo.h>');
    Blockly.Arduino.addVariable(servoName, 'Servo ' + servoId + ';', true);

    var code = servoId + '.detach();\n';
    return code;
};

/** PWM Servo */
/**
 * Code generator to attach servo to a arduino Pin (X).
 * Arduino code: #include <Servo.h>
 *               Servo ServoX;
 *               setup { ServoX.attach(X); }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['pwm_servo_attach'] = function (block) {
    var pinKey = block.getFieldValue('SERVO_PIN');
    var servoName = block.getFieldValue('SERVO_NAME');
    var servoId = Blockly.Arduino.variableDB_.getName(
        servoName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.reservePin(block, pinKey, Blockly.Arduino.pinTypes.SERVO, 'Servo Write');
    Blockly.Arduino.addInclude('PWMServo_inc', '#include <PWMServo.h>');
    Blockly.Arduino.addVariable(servoName, 'PWMServo ' + servoId + ';', true);

    var code = servoId + '.attach(' + pinKey + ');\n';

    return code;
};


/**
 * Code generator to read an angle value from a servo Pin (X).
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {(string|number)[]} Completed code with order of operation.
 */
Blockly.Arduino['pwm_servo_read'] = function (block) {
    var servoName = block.getFieldValue('SERVO_NAME');
    var servoId = Blockly.Arduino.variableDB_.getName(
        servoName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.addInclude('PWMServo_inc', '#include <PWMServo.h>');
    Blockly.Arduino.addVariable(servoName, 'PWMServo ' + servoId + ';', true);

    var code = servoId + '.read()';
    return [code, Blockly.Arduino.ORDER_NONE];
};

/**
 * Code generator to set an angle (Y) value to a servo Pin (X).
 * Arduino code: #include <Servo.h>
 *               Servo servo_X;
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */

Blockly.Arduino['pwm_servo_write'] = function (block) {
    var servoName = block.getFieldValue('SERVO_NAME');
    var servoAngle = Blockly.Arduino.valueToCode(
        block, 'SERVO_ANGLE', Blockly.Arduino.ORDER_ATOMIC);
    var servoId = Blockly.Arduino.variableDB_.getName(
        servoName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.addInclude('PWMServo_inc', '#include <PWMServo.h>');
    Blockly.Arduino.addVariable(servoName, 'PWMServo ' + servoId + ';', true);

    var code = servoId + '.write(' + servoAngle + ');\n';
    return code;
};

/**
 * Code generator to set an angle (Y) value to a servo Pin (X).
 * Arduino code: #include <Servo.h>
 *               Servo servo_X;
 *               setup { myServoX.attach(X); }
 *               loop  { myServoX.write(Y);  }
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['pwm_servo_write_angle'] = function (block) {
    var pinKey = block.getFieldValue('SERVO_PIN');
    var servoAngle = block.getFieldValue('SERVO_ANGLE');
    var servoName = 'myServo' + pinKey;
    var servoDelay = block.getFieldValue('SERVO_DELAY');
    var servoDelayVar = 'pwmservo' + pinKey + 'delaytime';

    Blockly.Arduino.reservePin(
        block, pinKey, Blockly.Arduino.pinTypes.SERVO, 'Servo Write');

    Blockly.Arduino.addInclude('PWMServo_inc', '#include <PWMServo.h>');
    Blockly.Arduino.addDeclaration('pwmservo_' + pinKey, 'PWMServo ' + servoName + ';');

    var code = servoName + '.attach(' + pinKey + ');\n' +
        servoName + '.write(' + servoName + '.read());\n' +
        servoDelayVar + ' = abs(' + servoName + '.read()-' + servoAngle + ')*' + servoDelay + ';\n' +
        servoName + '.write(' + servoAngle + ');\n';
    return code;
};

/**
 * Code generator to detach to a servo Pin (X).
 * @param {!Blockly.Block} block Block to generate the code from.
 * @return {string} Completed code.
 */
Blockly.Arduino['pwm_servo_detach'] = function (block) {
    var servoName = block.getFieldValue('SERVO_NAME');
    var servoId = Blockly.Arduino.variableDB_.getName(
        servoName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);

    Blockly.Arduino.addInclude('PWMServo_inc', '#include <PWMServo.h>');
    Blockly.Arduino.addVariable(servoName, 'PWMServo ' + servoId + ';', true);

    var code = servoId + '.detach();\n';
    return code;
};

/** afmotor*/
Blockly.Arduino['afmotor'] = function (block) {
    var afmotor_control = block.getFieldValue('afmotor_control');
    var afmotor_channel = block.getFieldValue('afmotor_channel');
    var motorName = 'motor_dc_' + afmotor_channel;
    var feqName;
    switch (parseInt(afmotor_channel)) {
        case 1:
        case 2:
            feqName = 'MOTOR12_64KHZ';
            break;
        case 3:
        case 4:
            feqName = 'MOTOR34_64KHZ';
            break;
        default:
            feqName = '';
    }
    var afmotor_speed = block.getFieldValue('afmotor_speed');

    Blockly.Arduino.addInclude('AFMotor_inc', '#include <AFMotor.h>');
    Blockly.Arduino.addDeclaration('AF_DCMotor_' + afmotor_channel, 'AF_DCMotor ' + motorName + '(' + afmotor_channel + ', ' + feqName + ');');

    var code = motorName + '.setSpeed(' + afmotor_speed + ');\n' +
        motorName + '.run(' + afmotor_control + ');\n';
    return code;
};

/** afmotor*/
Blockly.Arduino['afmotor_var'] = function (block) {
    var afmotor_control = block.getFieldValue('afmotor_control');
    var afmotor_channel = block.getFieldValue('afmotor_channel');
    var motorName = 'motor_dc_' + afmotor_channel;
    var feqName;
    switch (parseInt(afmotor_channel)) {
        case 1:
        case 2:
            feqName = 'MOTOR12_64KHZ';
            break;
        case 3:
        case 4:
            feqName = 'MOTOR34_64KHZ';
            break;
        default:
            feqName = '';
    }
    var afmotor_speed = Blockly.Arduino.valueToCode(
        block, 'afmotor_speed', Blockly.Arduino.ORDER_ATOMIC) || 255;

    Blockly.Arduino.addInclude('AFMotor_inc', '#include <AFMotor.h>');
    Blockly.Arduino.addDeclaration('AFMotor_declar_' + afmotor_channel, 'AF_DCMotor ' + motorName + '(' + afmotor_channel + ', ' + feqName + ');');

    var code = motorName + '.setSpeed(' + afmotor_speed + ');\n' +
        motorName + '.run(' + afmotor_control + ');\n';
    return code;
};

/** stepper */
Blockly.Arduino["stepper_setup_2pin"] = function (block) {
    var stepperName = block.getFieldValue('STEPPER_NAME');
    var stepperId = Blockly.Arduino.variableDB_.getName(
        stepperName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var pin1 = Blockly.Arduino.valueToCode(block, 'PIN1', Blockly.Arduino.ORDER_ATOMIC);
    var pin2 = Blockly.Arduino.valueToCode(block, 'PIN2', Blockly.Arduino.ORDER_ATOMIC);
    var steps = Blockly.Arduino.valueToCode(block, 'STEPS', Blockly.Arduino.ORDER_ATOMIC);
    var speed = Blockly.Arduino.valueToCode(block, 'SPEED', Blockly.Arduino.ORDER_ATOMIC);
    Blockly.Arduino.addInclude('Stepper_inc', '#include <Stepper.h>');
    Blockly.Arduino.addVariable(stepperName, 'Stepper ' + stepperId + '(' + steps + ',' + pin1 + ',' + pin2 + ');', true);
    Blockly.Arduino.addSetup('setup_stepper_' + stepperId, stepperId + '.setSpeed(' + speed + ');');
    return '';
};

Blockly.Arduino["stepper_setup_4pin"] = function (block) {
    var stepperName = block.getFieldValue('STEPPER_NAME');
    var stepperId = Blockly.Arduino.variableDB_.getName(
        stepperName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var pin1 = Blockly.Arduino.valueToCode(block, 'PIN1', Blockly.Arduino.ORDER_ATOMIC);
    var pin2 = Blockly.Arduino.valueToCode(block, 'PIN2', Blockly.Arduino.ORDER_ATOMIC);
    var pin3 = Blockly.Arduino.valueToCode(block, 'PIN3', Blockly.Arduino.ORDER_ATOMIC);
    var pin4 = Blockly.Arduino.valueToCode(block, 'PIN4', Blockly.Arduino.ORDER_ATOMIC);
    var steps = Blockly.Arduino.valueToCode(block, 'STEPS', Blockly.Arduino.ORDER_ATOMIC);
    var speed = Blockly.Arduino.valueToCode(block, 'SPEED', Blockly.Arduino.ORDER_ATOMIC);
    Blockly.Arduino.addInclude('Stepper_inc', '#include <Stepper.h>');
    Blockly.Arduino.addVariable(stepperName, 'Stepper ' + stepperId + '(' + steps + ',' + pin1 + ',' + pin3 + ',' + pin2 + ',' + pin4 + ');', true);
    Blockly.Arduino.addSetup('setup_stepper_' + stepperId, stepperId + '.setSpeed(' + speed + ');');
    return '';
};

Blockly.Arduino["stepper_speed"] = function (block) {
    var stepperName = block.getFieldValue('STEPPER_NAME');
    var stepperId = Blockly.Arduino.variableDB_.getName(
        stepperName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var speed = Blockly.Arduino.valueToCode(block, 'SPEED', Blockly.Arduino.ORDER_ATOMIC);
    var code = stepperId + '.setSpeed(' + speed + ');\n';
    return code;
};

Blockly.Arduino["stepper_move"] = function (block) {
    var stepperName = block.getFieldValue('STEPPER_NAME');
    var stepperId = Blockly.Arduino.variableDB_.getName(
        stepperName,
        Blockly.Variables.NAME_TYPE/*blocklyArray_NAME_TYPE*/);
    var step = Blockly.Arduino.valueToCode(this, 'STEP', Blockly.Arduino.ORDER_ATOMIC);
    Blockly.Arduino.addInclude('Stepper_inc', '#include <Stepper.h>');
    return stepperId + '.step(' + step + ');\n';
};

//MotorDriverBoard
Blockly.Arduino.md_setup = function () {
    ensureMotorDriverDefinition();
    Blockly.Arduino.setups_['setup_md_setup1'] = 'Serial.begin(9600);\n'
    var code = '';
    return code;
};

Blockly.Arduino.md_setFreq = function () {
    ensureMotorDriverDefinition();
    var freq = Blockly.Arduino.valueToCode(this, 'freq', Blockly.Arduino.ORDER_ATOMIC);
    var code = 'mMotorDriver.begin(' + freq + ');\n'
    return code;
};

Blockly.Arduino.md_gpio = function () {
    ensureMotorDriverDefinition();
    var gpio = this.getFieldValue('mdGpio');
    var gpioMode = this.getFieldValue('mdGpioMode');
    var code = 'mMotorDriver.setPin(' + gpio + ', ' + gpioMode + ');\n'
    return code;
};

Blockly.Arduino.md_pwm = function () {
    ensureMotorDriverDefinition();
    Blockly.Arduino.setups_['setup_md_pwm_begin'] = 'mMotorDriver.begin(1600);\n';
    var gpio = this.getFieldValue('mdGpio');
    var gpioPWM = Blockly.Arduino.valueToCode(this, 'pwm', Blockly.Arduino.ORDER_ATOMIC) || '0';
    var code = 'mMotorDriver.setPWM(' + gpio + ', constrain((int)(' + gpioPWM + '), 0, 4096));\n'
    return code;
};

Blockly.Arduino.md_initdcmotor = function () {
    ensureMotorDriverDefinition();
    var dropdown_DCPorts = this.getFieldValue('DCPorts');
    Blockly.Arduino.definitions_['object_dc_' + dropdown_DCPorts + ''] = 'Emakefun_DCMotor *DCmotor_' + dropdown_DCPorts + ' = mMotorDriver.getMotor(' + dropdown_DCPorts + ');\n'
    Blockly.Arduino.setups_['md_m4init'] = 'mMotorDriver.begin(1600);\n'
    var code = ''
    return code;
};

Blockly.Arduino.md_dcmotor = function () {
    var dropdown_DCPorts = this.getFieldValue('DCPorts');
    var dropdown_DCDirections = this.getFieldValue('DCDirections');
    var value_Speed = Blockly.Arduino.valueToCode(this, 'Speed', Blockly.Arduino.ORDER_ATOMIC);
    var code = 'DCmotor_' + dropdown_DCPorts + '->setSpeed(' + value_Speed + ');\n'
        + 'DCmotor_' + dropdown_DCPorts + '->run(' + dropdown_DCDirections + ');\n';
    return code;
};

Blockly.Arduino.md_stopDCmotor = function () {
    var dropdown_DCPorts = this.getFieldValue('DCPorts');
    var code = 'DCmotor_' + dropdown_DCPorts + '->run(BRAKE);\n'
    return code;
};

Blockly.Arduino.md_initENmotor = function () {
    var dropdown_ENPorts = this.getFieldValue('ENPorts');
    ensureMotorDriverDefinition();
    Blockly.Arduino.definitions_['object_en_' + dropdown_ENPorts + ''] = 'Emakefun_EncoderMotor *EncodeMotor_' + dropdown_ENPorts + ' = mMotorDriver.getEncoderMotor(E' + dropdown_ENPorts + ');\n'
    Blockly.Arduino.definitions_['objectStaticFunc_' + dropdown_ENPorts] = 'static void encoder' + dropdown_ENPorts + '(void){\n  if(digitalRead(EncodeMotor_' + dropdown_ENPorts + '->ENCODER2pin) == LOW) {\n    EncodeMotor_' + dropdown_ENPorts + '->EncoderPulse++;\n  } else {\n    EncodeMotor_' + dropdown_ENPorts + '->EncoderPulse--;\n  }\n}\n';
    Blockly.Arduino.setups_['md_encoder_' + dropdown_ENPorts] = "mMotorDriver.begin();\n  EncodeMotor_" + dropdown_ENPorts + "->init(encoder" + dropdown_ENPorts + ");\n";
    var code = ''
    return code;
};

Blockly.Arduino.md_enmotor = function () {
    var dropdown_ENPorts = this.getFieldValue('ENPorts');
    var dropdown_ENDirections = this.getFieldValue('ENDirections');
    var value_Speed = Blockly.Arduino.valueToCode(this, 'Speed', Blockly.Arduino.ORDER_ATOMIC);
    ensureMotorDriverDefinition();
    Blockly.Arduino.definitions_['object_en_' + dropdown_ENPorts + ''] = 'Emakefun_EncoderMotor *EncodeMotor_' + dropdown_ENPorts + ' = mMotorDriver.getEncoderMotor(E' + dropdown_ENPorts + ');\n';
    Blockly.Arduino.definitions_['objectStaticFunc_' + dropdown_ENPorts] = 'static void encoder' + dropdown_ENPorts + '(void){\n  if(digitalRead(EncodeMotor_' + dropdown_ENPorts + '->ENCODER2pin) == LOW) {\n    EncodeMotor_' + dropdown_ENPorts + '->EncoderPulse++;\n  } else {\n    EncodeMotor_' + dropdown_ENPorts + '->EncoderPulse--;\n  }\n}\n';
    Blockly.Arduino.setups_['md_encoder_' + dropdown_ENPorts] = 'mMotorDriver.begin(50);\n  EncodeMotor_' + dropdown_ENPorts + '->init(encoder' + dropdown_ENPorts + ');\n';
    var code = 'EncodeMotor_' + dropdown_ENPorts + '->setSpeed(' + value_Speed + ');\n'
        + 'EncodeMotor_' + dropdown_ENPorts + '->run(' + dropdown_ENDirections + ');\n';
    return code;
};

Blockly.Arduino.md_stopENmotor = function () {
    var dropdown_ENPorts = this.getFieldValue('ENPorts');
    var code = 'EncodeMotor_' + dropdown_ENPorts + '->run(BRAKE);\n'
    return code;
};

Blockly.Arduino.md_initstmotor = function () {
    var value_Steps = Blockly.Arduino.valueToCode(this, 'Steps', Blockly.Arduino.ORDER_ATOMIC);
    var value_freq = Blockly.Arduino.valueToCode(this, 'freq', Blockly.Arduino.ORDER_ATOMIC);
    var dropdown_STPorts = this.getFieldValue('STPorts');
    ensureMotorDriverDefinition();
    Blockly.Arduino.definitions_['object_st_' + dropdown_STPorts + ''] = '#include<Emakefun_MotorDriver.h>\nEmakefun_StepperMotor *StepperMotor_' + dropdown_STPorts + ' = mMotorDriver.getStepper(' + dropdown_STPorts + ', ' + value_Steps + ');\n'
    Blockly.Arduino.setups_['md_begin'] = "mMotorDriver.begin(1600);\n  StepperMotor_" + dropdown_STPorts + "->setSpeed(" + value_freq + ");\n";
    var code = ''
    return code;
};

Blockly.Arduino.md_stmotor = function () {
    var dropdown_STPorts = this.getFieldValue('STPorts');
    var dropdown_STDirections = this.getFieldValue('STDirections');
    var value_doubleSingle = this.getFieldValue('doubleSingle');
    var value_Steps = Blockly.Arduino.valueToCode(this, 'Steps', Blockly.Arduino.ORDER_ATOMIC);
    ensureMotorDriverDefinition();
    //  var value_doubleSingle = Blockly.Arduino.valueToCode(this,'doubleSingle',Blockly.Arduino.ORDER_ATOMIC);
    // Blockly.Arduino.setups_['md_m4init'] ='mMotorDriver.begin(1526);\n';
    var code = 'StepperMotor_' + dropdown_STPorts + '->step(' + value_Steps + ', ' + dropdown_STDirections + ', ' + value_doubleSingle + ');\nStepperMotor_' + dropdown_STPorts + '->release();';
    return code;
};

Blockly.Arduino.md_stopstmotor = function () {
    var dropdown_STTPorts = this.getFieldValue('STTPorts');
    var code = 'StepperMotor_' + dropdown_STTPorts + '->release();\n';
    return code;
};

Blockly.Arduino.md_initRGB = function () {
    //var dropdown_RGB = this.getFieldValue('RGB');
    //var dropdown_RGBCOLOR = this.getFieldValue('RGBCOLOR');
    var analogPins = (Blockly.Arduino.Boards.selected.analogPins || []);
    var rgbPin = analogPins[1] ? analogPins[1][1] : 'A1';
    Blockly.Arduino.definitions_['object55'] = '#include <RGBLed.h>\n';
    Blockly.Arduino.definitions_['rgbPinInit'] = "#define RGB_PIN " + rgbPin + "\nRGBLed rgb(RGB_PIN, 1);\n";
    Blockly.Arduino.setups_['md_rgbSetUp'] = 'pinMode(RGB_PIN, OUTPUT);\n'
    var code = '';
    return code;
};

Blockly.Arduino.md_RGB = function () {
    var value_brightnesss = Blockly.Arduino.valueToCode(this, 'brightnesss', Blockly.Arduino.ORDER_ATOMIC);
    var dropdown_RGBCOLOR = this.getFieldValue('RGBCOLOR');
    //Blockly.Arduino.definitions_['object5'] = 'Emakefun_Sensor *rgb = mMotorDriver.getSensor(E_RGB);\n'
    var code = 'rgb.setBrightness(' + value_brightnesss + ');\nrgb.setColor((E_RGB_INDEX)0, ' + dropdown_RGBCOLOR + ');\nrgb.show();\n';
    return code;
};

Blockly.Arduino.md_setColor = function () {
    var value_red = Blockly.Arduino.valueToCode(this, 'red', Blockly.Arduino.ORDER_ATOMIC);
    var value_green = Blockly.Arduino.valueToCode(this, 'green', Blockly.Arduino.ORDER_ATOMIC);
    var value_blue = Blockly.Arduino.valueToCode(this, 'blue', Blockly.Arduino.ORDER_ATOMIC);
    var value_brightnessss = Blockly.Arduino.valueToCode(this, 'brightnessss', Blockly.Arduino.ORDER_ATOMIC);
    //Blockly.Arduino.definitions_['object55'] = '#include<RGBLed.h>\nRGBLed rgbled_A3(A1, 2);\n'
    var code = 'rgb.setBrightness(' + value_brightnessss + ');\nrgb.setColor((E_RGB_INDEX)0, ' + value_red + ',' + value_green + ',' + value_blue + ');\n' + 'rgb.show();\n';
    return code;
};

Blockly.Arduino.md_initSounds = function () {
    var analogPins = (Blockly.Arduino.Boards.selected.analogPins || []);
    var buzzerPin = analogPins[0] ? analogPins[0][1] : 'A0';
    Blockly.Arduino.definitions_['object6'] = '#include<Buzzer.h>\n#include<Sounds.h>\n';
    Blockly.Arduino.definitions_['buzzerPinInit'] = "#define BUZZER_PIN " + buzzerPin + "\nBuzzer buzzer(BUZZER_PIN);\n";
    var code = '';
    return code;
};
Blockly.Arduino.md_playSounds = function () {
    var dropdown_Sounds = this.getFieldValue('Sounds');
    var code = "";
    if (dropdown_Sounds == "0") {
        code = "buzzer._tone(note_E5, 50, 30);\nbuzzer._tone(note_E6, 55, 25);\nbuzzer._tone(note_A6, 60, 10);\n";
    } else if (dropdown_Sounds == "1") {
        code = "buzzer._tone(note_E5, 50, 30);\nbuzzer._tone(note_A6, 55, 25);\nbuzzer._tone(note_E6, 50, 10);\n";
    } else if (dropdown_Sounds == "2") {
        code = "buzzer.bendTones (note_E6, note_G6, 1.03, 20, 2);\ndelay(30);\nbuzzer.bendTones (note_E6, note_D7, 1.04, 10, 2);\n";
    } else if (dropdown_Sounds == "3") {
        code = "buzzer.bendTones (note_E6, note_A6, 1.02, 30, 10);\n";
    } else if (dropdown_Sounds == "4") {
        code = "buzzer.bendTones (note_G6, note_D7, 1.03, 30, 10);\n";
    } else if (dropdown_Sounds == "5") {
        code = "buzzer._tone(note_E6, 50, 100);\nbuzzer._tone(note_G6, 50, 80);\nbuzzer._tone(note_D7, 300, 0);\n";
    } else if (dropdown_Sounds == "6") {
        code = "buzzer.bendTones(800, 2150, 1.02, 10, 1);\nbuzzer.bendTones(2149, 800, 1.03, 7, 1);\n";
    } else if (dropdown_Sounds == "7") {
        code = "buzzer.bendTones(880, 2000, 1.04, 8, 3);\ndelay(200);\nfor (int i = 880; i < 2000; i = i * 1.04) {\n  buzzer._tone(note_B5, 5, 10);\n}\n";
    } else if (dropdown_Sounds == "8") {
        code = "buzzer.bendTones(1880, 3000, 1.03, 8, 3);\ndelay(200);\nfor (int i = 1880; i < 3000; i = i * 1.03) {\n  buzzer._tone(note_C6, 10, 10);\n}\n";
    } else if (dropdown_Sounds == "9") {
        code = "buzzer.bendTones(700, 900, 1.03, 16, 4);\nbuzzer.bendTones(899, 650, 1.01, 18, 7);\n";
    } else if (dropdown_Sounds == "10") {
        code = "buzzer.bendTones(100, 500, 1.04, 10, 10);\ndelay(500);\nbuzzer.bendTones(400, 100, 1.04, 10, 1);\n";
    } else if (dropdown_Sounds == "11") {
        code = "buzzer.bendTones(1500, 2500, 1.05, 20, 8);\nbuzzer.bendTones(2499, 1500, 1.05, 25, 8);\n";
    } else if (dropdown_Sounds == "12") {
        code = "buzzer.bendTones(2000, 6000, 1.05, 8, 3);\ndelay(50);\nbuzzer.bendTones(5999, 2000, 1.05, 13, 2);\n";
    } else if (dropdown_Sounds == "13") {
        code = "buzzer.bendTones(1500, 2000, 1.05, 15, 8);\ndelay(100);\nbuzzer.bendTones(1900, 2500, 1.05, 10, 8);\n";
    } else if (dropdown_Sounds == "14") {
        code = "buzzer.bendTones(880, 669, 1.02, 20, 200);\n";
    } else if (dropdown_Sounds == "15") {
        code = "buzzer.bendTones(1000, 1700, 1.03, 8, 2);\nbuzzer.bendTones(1699, 500, 1.04, 8, 3);\nbuzzer.bendTones(1000, 1700, 1.05, 9, 10);\n";
    } else if (dropdown_Sounds == "16") {
        code = "buzzer.bendTones(1600, 3000, 1.02, 2, 15);\n";
    } else if (dropdown_Sounds == "17") {
        code = "buzzer.bendTones(2000, 6000, 1.02, 2, 20);\n";
    } else if (dropdown_Sounds == "18") {
        code = "buzzer.bendTones(1600, 4000, 1.02, 2, 20);\nbuzzer.bendTones(4000, 3000, 1.02, 2, 20);\n";
    } else if (dropdown_Sounds == "19") {
        code = "buzzer._tone(note_C7, 50, 100);\ndelay(110);\nbuzzer._tone(note_C6, 50, 100);\n";
    }
    //Blockly.Arduino.definitions_['object6'] = 'Emakefun_Sensor *buzzer = mMotorDriver.getSensor(E_BUZZER);\n'

    return code;
};

Blockly.Arduino.md_initultrasonic = function () {
    // Keep the original A2/A3 defaults for Uno while selecting valid ADC
    // GPIOs for ESP32 variants from the active board profile.
    var analogPins = (Blockly.Arduino.Boards.selected.analogPins || []);
    var trigPin = analogPins[2] ? analogPins[2][1] : 'A2';
    var echoPin = analogPins[3] ? analogPins[3][1] : 'A3';
    Blockly.Arduino.reservePin(this, trigPin, Blockly.Arduino.pinTypes.OUTPUT, 'Ultrasonic TRIG');
    Blockly.Arduino.reservePin(this, echoPin, Blockly.Arduino.pinTypes.INPUT, 'Ultrasonic ECHO');
    Blockly.Arduino.definitions_['ultrasonicPinInit'] = "#define ECHO_PIN " + echoPin + "\n#define TRIG_PIN " + trigPin + "\n\nuint16_t GetUltrasonicDistance() {\n  pinMode(TRIG_PIN, OUTPUT);\n  pinMode(ECHO_PIN, INPUT);\n  digitalWrite(TRIG_PIN, LOW);\n  delayMicroseconds(2);\n  digitalWrite(TRIG_PIN, HIGH);\n  delayMicroseconds(10);\n  digitalWrite(TRIG_PIN, LOW);\n  return pulseIn(ECHO_PIN, HIGH, 30000) / 58.00;\n}\n";
    var code = '';
    return code;
};

Blockly.Arduino.md_readUltrasonicDistance = function () {
    var code = 'GetUltrasonicDistance()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_initirremote = function () {
    Blockly.Arduino.definitions_['define_KeyMap'] = '#include<Keymap.h>\n#include<IRremote.h>\n#define IR_PIN 8\nIRremote ir(IR_PIN);\n';
    Blockly.Arduino.setups_['md_m4init'] = 'pinMode(IR_PIN, INPUT);\n';
    //Blockly.Arduino.definitions_['object8'] = ''
    var code = '';
    return code;
};
//if irremote pressed
Blockly.Arduino.md_isirremote = function () {
    //Blockly.Arduino.definitions_['define_KeyMap'] = '#include<KeyMap.h>\n#include<IRremote.h>\nEmakefun_Sensor *ir = mMotorDriver.getSensor(E_IR);\n';
    //Blockly.Arduino.definitions_['object8'] = ''
    Blockly.Arduino.definitions_['object9'] = 'byte irKeyCode;\n'
    var code = 'irKeyCode = ir.getCode()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
//����ʮһ��ͼ�ο�ת��ΪC���� ����ң�ذ���������������boolean��
Blockly.Arduino.md_irKeyPress = function () {
    var dropdown_Irkeys = this.getFieldValue('Irkeys');
    Blockly.Arduino.definitions_['object9'] = 'byte irKeyCode;\n'
    var code = '(E_EM_IR_KEYCODE)ir.getIrKey(irKeyCode,2) == ' + dropdown_Irkeys + '';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_irKeyPress2 = function () {
    var dropdown_Irkeys2 = this.getFieldValue('Irkeys2');
    Blockly.Arduino.definitions_['object9'] = 'byte irKeyCode;\n'
    var code = '(E_NORMAL_IR_KEYCODE)ir.getIrKey(irKeyCode) == ' + dropdown_Irkeys2 + '';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

//����ʮ����ͼ�ο�ת��ΪC���� NRF24L01��ʼ��    field��name��ȷ��ʹNUM������
Blockly.Arduino.md_initnrf24l01 = function () {
    Blockly.Arduino.definitions_['md_initnrf24l01'] = '#include<nRF24L01.h>\nNrf24l Mirf = Nrf24l(10, 9);\n'
    //Blockly.Arduino.setups_['md_initnrf24l01'] ='\t'+'Serial.begin(9600);\nMirf.spi = &MirfHardwareSpi;\nMirf.init();\nMirf.channel = 90;\nMirf.config();\n'
    var code = '';
    return code;
};
//����ʮ����ͼ�ο�ת��ΪC���� NRF24L01�������ݵ�ַvalue ����value
Blockly.Arduino.md_nrf24l01send = function () {

    var value_address = Blockly.Arduino.valueToCode(this, 'address', Blockly.Arduino.ORDER_ATOMIC);
    var value_channel = Blockly.Arduino.valueToCode(this, 'channel', Blockly.Arduino.ORDER_ATOMIC);
    var value_arr = Blockly.Arduino.valueToCode(this, 'arr', Blockly.Arduino.ORDER_ATOMIC);
    //Blockly.Arduino.definitions_['md_nrf24l01send123'] = ''
    Blockly.Arduino.definitions_['md_nrf24l01send123'] = '#include<nRF24L01.h>\nNrf24l Mirf = Nrf24l(10, 9);\n'
    Blockly.Arduino.setups_['md_nrf24l01send123'] = 'Serial.begin(9600);\n  Mirf.spi = &MirfHardwareSpi;\n  Mirf.init();\n  Mirf.setRADDR(' + value_address + ');\n  Mirf.payload = sizeof(' + value_arr + ');\n  Mirf.channel = ' + value_channel + ';\n  Mirf.config();\n'
    var code = '';
    return code;
};
//��������
Blockly.Arduino.md_nrf24l01rec = function () {

    var value_address2 = Blockly.Arduino.valueToCode(this, 'address2', Blockly.Arduino.ORDER_ATOMIC);
    var value_channel2 = Blockly.Arduino.valueToCode(this, 'channel2', Blockly.Arduino.ORDER_ATOMIC);
    var value_arr2 = Blockly.Arduino.valueToCode(this, 'arr2', Blockly.Arduino.ORDER_ATOMIC);
    //Blockly.Arduino.definitions_['md_nrf24l01send123'] = ''
    Blockly.Arduino.definitions_['md_nrf24l01rec'] = '#include<nRF24L01.h>\nNrf24l Mirf = Nrf24l(10, 9);\n'
    Blockly.Arduino.setups_['md_nrf24l01rec'] = 'Serial.begin(9600);\n  Mirf.spi = &MirfHardwareSpi;\n  Mirf.init();\n  Mirf.setRADDR(' + value_address2 + ');\n  Mirf.payload = sizeof(' + value_arr2 + ');\n  Mirf.channel = ' + value_channel2 + ';\n  Mirf.config();\n'
    var code = '';
    return code;
};
//nrfadd��������
Blockly.Arduino.md_nrf24l01senddatass = function () {
    var value_nrfdatass = Blockly.Arduino.valueToCode(this, 'nrfdatass', Blockly.Arduino.ORDER_ATOMIC);
    //Blockly.Arduino.definitions_['md_initnrf24l01'] = '#include<nRF24L01.h>\nNrf24l Mirf = Nrf24l(10, 9);\n'
    //Blockly.Arduino.setups_['md_initnrf24l01'] ='\t'+'Serial.begin(9600);\nMirf.spi = &MirfHardwareSpi;\nMirf.init();\nMirf.channel = 90;\nMirf.config();\n'
    var code = 'Mirf.send(' + value_nrfdatass + '); \n';
    return code;
};
//��������
Blockly.Arduino.md_nrfissend = function () {
    var code = 'Mirf.isSending()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
//׼����������
Blockly.Arduino.md_nrfdataradys = function () {
    var code = 'Mirf.dataReady()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
//nrfadd��������
Blockly.Arduino.md_nrfrecdatas = function () {
    var value_md_nrfdatasss = Blockly.Arduino.valueToCode(this, 'nrfdatasss', Blockly.Arduino.ORDER_ATOMIC);
    //Blockly.Arduino.definitions_['md_initnrf24l01'] = '#include<nRF24L01.h>\nNrf24l Mirf = Nrf24l(10, 9);\n'
    //Blockly.Arduino.setups_['md_initnrf24l01'] ='\t'+'Serial.begin(9600);\nMirf.spi = &MirfHardwareSpi;\nMirf.init();\nMirf.channel = 90;\nMirf.config();\n'
    var code = 'Mirf.getData(' + value_md_nrfdatasss + '); \n';
    return code;
};
//����ʮ�ĸ�ͼ�ο�ת��ΪC���� NRF24L01�������ݵ�ַvalue
Blockly.Arduino.md_nrf24l01receive = function () {
    var value_address = Blockly.Arduino.valueToCode(this, 'address', Blockly.Arduino.ORDER_ATOMIC);
    Blockly.Arduino.definitions_['md_nrf24l01receive'] = 'byte value;\n'
    Blockly.Arduino.setups_['setup_md_setup1'] = 'Serial.begin(9600);\n Mirf.spi = &MirfHardwareSpi;\n  Mirf.init();\n  Mirf.setRADDR((byte *)\"' + value_address + '\");\n   Mirf.payload = sizeof(value);\n  Mirf.channel = 90; \n  Mirf.config();\n  Serial.println("Listening...");\n';
    var code = 'while (Mirf.dataReady()) {\n    Mirf.getData(&value);\n    Serial.print("Got MotorDriver data: ");\n   Serial.println(value);\n}\n';
    return code; //��codeΪ����ʽʱ�ô˷��ط�ʽ
};
//����ʮ����ͼ�ο�ת��ΪC���� NRF24L01���ݲ�Ϊ��
Blockly.Arduino.md_NRF24L01isnotnull = function () {
    var code = 'NrfData != NULL';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
//����ʮ����ͼ�ο�ת��ΪC���� ��ȡNRF24L01����
Blockly.Arduino.md_getNRF24L01 = function () {
    var code = 'NrfData';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
function mdEnsurePS2Definitions() {
    Blockly.Arduino.definitions_['define_PS2X'] =
        '#include <PS2X_lib.h>\n' +
        '#include <math.h>\n' +
        '#define PS2_DAT 12\n' +
        '#define PS2_CMD 11\n' +
        '#define PS2_SEL 10\n' +
        '#define PS2_CLK 13\n' +
        'PS2X ps2x;\n' +
        'byte md_ps2_error_code = 255;\n' +
        'bool md_ps2_read_ok = false;\n';
    Blockly.Arduino.setups_['setup_PS2init'] =
        'delay(300);\n' +
        'md_ps2_error_code = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, false, false);\n';
}

Blockly.Arduino.md_PS2init = function () {
    mdEnsurePS2Definitions();
    return '';
};

Blockly.Arduino.md_ps2getvalue = function (block) {
    mdEnsurePS2Definitions();
    var ps2ErrorCode = block.getFieldValue('VAR_ERROR');
    var ps2ErrorCodeId = Blockly.Arduino.variableDB_.getName(
        ps2ErrorCode,
        Blockly.Variables.NAME_TYPE);
    Blockly.Arduino.addVariable(ps2ErrorCode, 'int ' + ps2ErrorCodeId + ';', true);
    return ps2ErrorCodeId + ' = md_ps2_error_code;\n';
};

Blockly.Arduino.md_WhichPS2KeyPressed = function () {
    mdEnsurePS2Definitions();
    return ['ps2x.ButtonDataByte()', Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_ps2keypress = function () {
    mdEnsurePS2Definitions();
    var dropdown_PS2keys = this.getFieldValue('PS2keys');
    return ['ps2x.ButtonPressed(' + dropdown_PS2keys + ')', Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_ps2keyhold = function () {
    mdEnsurePS2Definitions();
    var dropdown_PS2keys = this.getFieldValue('PS2keys');
    return ['ps2x.Button(' + dropdown_PS2keys + ')', Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_ps2keyunpress = function () {
    mdEnsurePS2Definitions();
    var dropdown_PS2keys = this.getFieldValue('PS2keys');
    return ['ps2x.ButtonReleased(' + dropdown_PS2keys + ')', Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_ps2getvibrate = function () {
    mdEnsurePS2Definitions();
    var dropdown_Vibrate = this.getFieldValue('Vibrate');
    return ['ps2x.Analog(' + dropdown_Vibrate + ')', Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_ps2getvibrate2 = function () {
    mdEnsurePS2Definitions();
    Blockly.Arduino.definitions_['function_md_ps2_stick_angle'] =
        'int mdPs2StickAngle(int rawX, int rawY) {\n' +
        '  int x = rawX - 128;\n' +
        '  int y = 128 - rawY;\n' +
        '  if (abs(x) < 10 && abs(y) < 10) return -1;\n' +
        '  float angle = atan2((float)y, (float)x) * 57.2957795f;\n' +
        '  if (angle < 0.0f) angle += 360.0f;\n' +
        '  return ((int)(angle + 0.5f)) % 360;\n' +
        '}\n';
    var stick = this.getFieldValue('Vibrate2');
    var xAxis = stick === 'RIGHT' ? 'PSS_RX' : 'PSS_LX';
    var yAxis = stick === 'RIGHT' ? 'PSS_RY' : 'PSS_LY';
    return ['mdPs2StickAngle(ps2x.Analog(' + xAxis + '), ps2x.Analog(' + yAxis + '))', Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_ps2status = function () {
    mdEnsurePS2Definitions();
    return 'md_ps2_read_ok = ps2x.read_gamepad(false, 0);\n';
};

Blockly.Arduino.md_ps2readok = function () {
    mdEnsurePS2Definitions();
    return ['md_ps2_read_ok', Blockly.Arduino.ORDER_ATOMIC];
};
//���ڶ�ʮ�ĸ�ͼ�ο�ת��ΪC���� ���� �ӿ�����  �Ƕ�value
Blockly.Arduino.md_initservo = function () {
    var dropdown_Servoports = this.getFieldValue('Servoports');
    ensureMotorDriverDefinition();
    //var value_angle = Blockly.Arduino.valueToCode(this,'angle',Blockly.Arduino.ORDER_ATOMIC);
    //Blockly.Arduino.setups_['setup_md_setup5'] ='\t'+'mMotorDriver.begin(50);\n'
    //Blockly.Arduino.definitions_['object666'+dropdown_Servoports+''] = 'Emakefun_Servo *servo'+dropdown_Servoports+' = mMotorDriver.getServo('+dropdown_Servoports+');\n'
    Blockly.Arduino.setups_['md_m4init'] = 'mMotorDriver.begin(50);\n'
    Blockly.Arduino.definitions_['object66' + dropdown_Servoports + ''] = 'Emakefun_Servo *servo' + dropdown_Servoports + ' = mMotorDriver.getServo(' + dropdown_Servoports + ');\n'
    var code = '';
    return code;
};
Blockly.Arduino.md_servo = function () {
    var dropdown_Servoports = this.getFieldValue('Servoports');
    var value_angle = Blockly.Arduino.valueToCode(this, 'angle', Blockly.Arduino.ORDER_ATOMIC);
    ensureMotorDriverDefinition();
    //var value_speed = Blockly.Arduino.valueToCode(this, 'speed', Blockly.Arduino.ORDER_ATOMIC);
    //var code = ' servo' + dropdown_Servoports + '->writeServo(' + value_angle + ', ' + value_speed + ');\n';
    var code = 'servo' + dropdown_Servoports + '->writeServo(' + value_angle + ', 10);\n';
    return code;
};

Blockly.Arduino.md_readservo = function () {
    var dropdown_Servoports = this.getFieldValue('Servoports');
    ensureMotorDriverDefinition();
    var code = 'servo' + dropdown_Servoports + '->readDegrees()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
//��������ʼ��
Blockly.Arduino.md_m4init = function () {
    var dropdown_M4Ports1 = this.getFieldValue('M4Ports1');
    var dropdown_M4Ports2 = this.getFieldValue('M4Ports2');
    var dropdown_M4Ports3 = this.getFieldValue('M4Ports3');
    var dropdown_M4Ports4 = this.getFieldValue('M4Ports4');
    ensureMotorDriverDefinition();
    // The four-wheel blocks address these role names.  The old generator
    // declared DCmotor_1..4 instead, leaving every movement block undefined.
    Blockly.Arduino.definitions_['Amd_m4init2'] =
        'Emakefun_DCMotor *LeftForward = mMotorDriver.getMotor(' + dropdown_M4Ports1 + ');\n' +
        'Emakefun_DCMotor *RightForward = mMotorDriver.getMotor(' + dropdown_M4Ports2 + ');\n' +
        'Emakefun_DCMotor *LeftBackward = mMotorDriver.getMotor(' + dropdown_M4Ports3 + ');\n' +
        'Emakefun_DCMotor *RightBackward = mMotorDriver.getMotor(' + dropdown_M4Ports4 + ');\n';
    Blockly.Arduino.setups_['md_m4init'] = '\t' + 'mMotorDriver.begin(50);\n'
    var code = ''
    return code;
};
//ǰ��
Blockly.Arduino.md_m4goforward = function () {
    var value_m4speed1 = Blockly.Arduino.valueToCode(this, 'm4speed1', Blockly.Arduino.ORDER_ATOMIC);
    var code = '    LeftForward->setSpeed(' + value_m4speed1 + ');\n    RightForward->setSpeed(' + value_m4speed1 + ');\n    LeftBackward->setSpeed(' + value_m4speed1 + ');\n    RightBackward->setSpeed(' + value_m4speed1 + ');\n    LeftForward->run(FORWARD);\n    RightForward->run(FORWARD);\n    LeftBackward->run(FORWARD);\n    RightBackward->run(FORWARD);\n';
    return code;
};
//����
Blockly.Arduino.md_m4backforward = function () {
    var value_m4speed2 = Blockly.Arduino.valueToCode(this, 'm4speed2', Blockly.Arduino.ORDER_ATOMIC);
    var code = '    LeftForward->setSpeed(' + value_m4speed2 + ');\n    RightForward->setSpeed(' + value_m4speed2 + ');\n    LeftBackward->setSpeed(' + value_m4speed2 + ');\n    RightBackward->setSpeed(' + value_m4speed2 + ');\n    LeftForward->run(BACKWARD);\n    RightForward->run(BACKWARD);\n    LeftBackward->run(BACKWARD);\n    RightBackward->run(BACKWARD);\n';
    return code;
};
//��ת
Blockly.Arduino.md_m4turnleft = function () {
    var value_m4speed3 = Blockly.Arduino.valueToCode(this, 'm4speed3', Blockly.Arduino.ORDER_ATOMIC);
    var code = '    LeftForward->setSpeed(' + value_m4speed3 + '/2);\n    RightForward->setSpeed(' + value_m4speed3 + ');\n    LeftBackward->setSpeed(' + value_m4speed3 + '/2);\n    RightBackward->setSpeed(' + value_m4speed3 + ');\n    LeftForward->run(FORWARD);\n    RightForward->run(FORWARD);\n    LeftBackward->run(FORWARD);\n    RightBackward->run(FORWARD);\n';
    return code;
};
//��ת
Blockly.Arduino.md_m4turnright = function () {
    var value_m4speed4 = Blockly.Arduino.valueToCode(this, 'm4speed4', Blockly.Arduino.ORDER_ATOMIC);
    var code = '    LeftForward->setSpeed(' + value_m4speed4 + ');\n    RightForward->setSpeed(' + value_m4speed4 + '/2);\n    LeftBackward->setSpeed(' + value_m4speed4 + ');\n    RightBackward->setSpeed(' + value_m4speed4 + '/2);\n    LeftForward->run(FORWARD);\n    RightForward->run(FORWARD);\n    LeftBackward->run(FORWARD);\n    RightBackward->run(FORWARD);\n';
    return code;
};
//������
Blockly.Arduino.md_m4turnlefts = function () {
    var value_m4speed33 = Blockly.Arduino.valueToCode(this, 'm4speed33', Blockly.Arduino.ORDER_ATOMIC);
    var code = '    LeftForward->setSpeed(' + value_m4speed33 + ');\n    RightForward->setSpeed(' + value_m4speed33 + ');\n    LeftBackward->setSpeed(' + value_m4speed33 + ');\n    RightBackward->setSpeed(' + value_m4speed33 + ');\n    LeftForward->run(BACKWARD);\n    RightForward->run(FORWARD);\n    LeftBackward->run(BACKWARD);\n    RightBackward->run(FORWARD);\n';
    return code;
};
//������
Blockly.Arduino.md_m4turnrights = function () {
    var value_m4speed44 = Blockly.Arduino.valueToCode(this, 'm4speed44', Blockly.Arduino.ORDER_ATOMIC);
    var code = '    LeftForward->setSpeed(' + value_m4speed44 + ');\n    RightForward->setSpeed(' + value_m4speed44 + ');\n    LeftBackward->setSpeed(' + value_m4speed44 + ');\n    RightBackward->setSpeed(' + value_m4speed44 + ');\n    LeftForward->run(FORWARD);\n    RightForward->run(BACKWARD);\n    LeftBackward->run(FORWARD);\n    RightBackward->run(BACKWARD);\n';
    return code;
};
//��ʻ�Ƕ�
Blockly.Arduino.md_m4godegree = function () {
    var value_m4godegree = Blockly.Arduino.valueToCode(this, 'm4godegree', Blockly.Arduino.ORDER_ATOMIC);
    var value_m4gospeed = Blockly.Arduino.valueToCode(this, 'm4gospeed', Blockly.Arduino.ORDER_ATOMIC);
    // The angle input may be a variable or sensor expression.  The old
    // generator compared the JavaScript source string during code generation,
    // so every non-literal angle silently became BRAKE.  Keep the original
    // steering curve, but evaluate it on the board at runtime.
    var suffix = String(this.id || 'block').replace(/[^a-zA-Z0-9_]/g, '_');
    var degreeVar = 'taoyuanM4Degree_' + suffix;
    return '  const float ' + degreeVar + ' = constrain((float)(' + value_m4godegree + '), 0.0f, 360.0f);\n' +
        '  if (' + degreeVar + ' <= 90.0f) {\n' +
        '    LeftForward->setSpeed(' + value_m4gospeed + ');\n' +
        '    RightForward->setSpeed(' + value_m4gospeed + ' * (' + degreeVar + ' / 90.0f));\n' +
        '    LeftBackward->setSpeed(' + value_m4gospeed + ');\n' +
        '    RightBackward->setSpeed(' + value_m4gospeed + ' * (' + degreeVar + ' / 90.0f));\n' +
        '    LeftForward->run(FORWARD); RightForward->run(FORWARD);\n' +
        '    LeftBackward->run(FORWARD); RightBackward->run(FORWARD);\n' +
        '  } else if (' + degreeVar + ' <= 180.0f) {\n' +
        '    LeftForward->setSpeed(' + value_m4gospeed + ' * ((180.0f - ' + degreeVar + ') / 90.0f));\n' +
        '    RightForward->setSpeed(' + value_m4gospeed + ');\n' +
        '    LeftBackward->setSpeed(' + value_m4gospeed + ' * ((180.0f - ' + degreeVar + ') / 90.0f));\n' +
        '    RightBackward->setSpeed(' + value_m4gospeed + ');\n' +
        '    LeftForward->run(FORWARD); RightForward->run(FORWARD);\n' +
        '    LeftBackward->run(FORWARD); RightBackward->run(FORWARD);\n' +
        '  } else if (' + degreeVar + ' <= 270.0f) {\n' +
        '    LeftForward->setSpeed(' + value_m4gospeed + ' * ((' + degreeVar + ' - 180.0f) / 90.0f));\n' +
        '    RightForward->setSpeed(' + value_m4gospeed + ');\n' +
        '    LeftBackward->setSpeed(' + value_m4gospeed + ' * ((' + degreeVar + ' - 180.0f) / 90.0f));\n' +
        '    RightBackward->setSpeed(' + value_m4gospeed + ');\n' +
        '    LeftForward->run(BACKWARD); RightForward->run(BACKWARD);\n' +
        '    LeftBackward->run(BACKWARD); RightBackward->run(BACKWARD);\n' +
        '  } else {\n' +
        '    LeftForward->setSpeed(' + value_m4gospeed + ');\n' +
        '    RightForward->setSpeed(' + value_m4gospeed + ' * ((360.0f - ' + degreeVar + ') / 90.0f));\n' +
        '    LeftBackward->setSpeed(' + value_m4gospeed + ');\n' +
        '    RightBackward->setSpeed(' + value_m4gospeed + ' * ((360.0f - ' + degreeVar + ') / 90.0f));\n' +
        '    LeftForward->run(BACKWARD); RightForward->run(BACKWARD);\n' +
        '    LeftBackward->run(BACKWARD); RightBackward->run(BACKWARD);\n' +
        '  }\n';
};
//ֹͣ
Blockly.Arduino.md_m4stop = function () {
    var code = '    LeftForward->run(BRAKE);\n    RightForward->run(BRAKE);\n    LeftBackward->run(BRAKE);\n    RightBackward->run(BRAKE);\n';
    return code;
};
Blockly.Arduino.md_bluetoothinit = function () {
    //var dropdown_DCPorts = this.getFieldValue('DCPorts');
    Blockly.Arduino.definitions_['md_bluetoothinit'] = '#include<ProtocolParser.h>\n#include<BluetoothHandle.h>\nProtocolParser *mProtocol = new ProtocolParser();\n'
    var code = ''
    return code;
};
Blockly.Arduino.md_receivedata = function () {
    var code = 'mProtocol->RecevData();\n';
    return code;
};
Blockly.Arduino.md_receiveddata = function () {
    var code = 'mProtocol->ParserPackage()';
    return [code, Blockly.Arduino.ORDER_ATOMIC]; //��codeΪ����ʽʱ�ô˷��ط�ʽ
};
Blockly.Arduino.md_bluetoothKeyPress = function () {
    var dropdown_BLUETOOTHKEY = this.getFieldValue('BLUETOOTHKEY');
    var code = 'mProtocol->GetBluetoothButton()==' + dropdown_BLUETOOTHKEY + '';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.md_bluetoothstyle = function () {
    var dropdown_BLUETOOTHSTYLE = this.getFieldValue('BLUETOOTHSTYLE');
    var code = 'mProtocol->GetRobotControlFun()==' + dropdown_BLUETOOTHSTYLE + '';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.md_bluetoothgetdegree = function () {
    var code = 'mProtocol->GetRobotDegree()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.md_bluetoothgetspeed = function () {
    var code = 'mProtocol->GetRobotSpeed()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
Blockly.Arduino.md_nrfinit = function () {
    Blockly.Arduino.definitions_['md_nrfinit'] = '#include<ProtocolParser.h>\n#include<BluetoothHandle.h>\n#include<nRF24L01.h>\nNrf24l  *Nrf24L01 = mMotorDriver.getSensor(E_NRF24L01);\nProtocolParser *mProtocol = new ProtocolParser();\n';
    var value_nrfadd = Blockly.Arduino.valueToCode(this, 'nrfadd', Blockly.Arduino.ORDER_ATOMIC);
    Blockly.Arduino.setups_['md_nrfinit'] = 'Nrf24L01->setRADDR(' + value_nrfadd + ');\n'
    var code = 'byte value[12] = {0};\nbool godata = false;\n';
    return code;
};

Blockly.Arduino.md_nrfdataready = function () {
    var code = 'Nrf24L01->dataReady()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_nrfvalue = function () {
    //var value_nrfadd = Blockly.Arduino.valueToCode(this, 'nrfadd', Blockly.Arduino.ORDER_ATOMIC);
    var code = 'byte value[12] = {0};\nbool godata = false;\n';
    return code;
};

Blockly.Arduino.md_nrfgetdata = function () {
    //var value_nrfadd = Blockly.Arduino.valueToCode(this, 'nrfadd', Blockly.Arduino.ORDER_ATOMIC);
    var code = 'Nrf24L01->getData(value);\nmProtocol->RecevData(value, 12);\n';
    return code;
};

Blockly.Arduino.md_nrfgetpackage = function () {
    var code = 'mProtocol->ParserPackage()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_nrfnewob = function () {
    //var value_nrfadd = Blockly.Arduino.valueToCode(this, 'nrfadd', Blockly.Arduino.ORDER_ATOMIC);
    var code = 'E_CONTOROL_FUNC fun = mProtocol->GetRobotControlFun();\n';
    return code;
};

Blockly.Arduino.md_nrfdatafun = function () {
    var dropdown_datafun = this.getFieldValue('datafun');
    var code = 'mProtocol->GetRobotControlFun() == ' + dropdown_datafun + '';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_nrfbuttons = function () {
    var dropdown_nrfbuttons = this.getFieldValue('nrfbuttons');
    var code = 'mProtocol->GetBluetoothButton() == ' + dropdown_nrfbuttons + '';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_nrfgetdegree = function () {
    //var value_nrfadd = Blockly.Arduino.valueToCode(this, 'nrfadd', Blockly.Arduino.ORDER_ATOMIC);
    var code = 'mProtocol->GetRobotDegree()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};

Blockly.Arduino.md_nrfgetspeed = function () {
    //var value_nrfadd = Blockly.Arduino.valueToCode(this, 'nrfadd', Blockly.Arduino.ORDER_ATOMIC);
    var code = 'mProtocol->GetRobotSpeed()';
    return [code, Blockly.Arduino.ORDER_ATOMIC];
};
