215 lines
8.9 KiB
JavaScript
215 lines
8.9 KiB
JavaScript
import { arduinoGenerator, Order } from '../generators/arduino.js';
|
|
|
|
// ─── Pin I/O ──────────────────────────────────────────────
|
|
|
|
arduinoGenerator.forBlock['pin_set_mode'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
const mode = block.getFieldValue('MODE');
|
|
const modeMap = { OUT: 'OUTPUT', IN: 'INPUT', IN_PULLUP: 'INPUT_PULLUP' };
|
|
arduinoGenerator.addSetupCode(`pinMode(${pin}, ${modeMap[mode] || 'OUTPUT'});`);
|
|
return '';
|
|
};
|
|
|
|
arduinoGenerator.forBlock['pin_digital_write'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
const value = block.getFieldValue('VALUE');
|
|
return `digitalWrite(${pin}, ${value === '1' ? 'HIGH' : 'LOW'});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['pin_digital_read'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
return [`digitalRead(${pin})`, Order.FUNCTION_CALL];
|
|
};
|
|
|
|
// ─── PWM ──────────────────────────────────────────────────
|
|
|
|
arduinoGenerator.forBlock['pwm_init'] = function () {
|
|
return '';
|
|
};
|
|
|
|
arduinoGenerator.forBlock['pwm_set_duty'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
const duty = arduinoGenerator.valueToCode(block, 'DUTY', Order.NONE) || '0';
|
|
return `analogWrite(${pin}, ${duty});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['pwm_set_freq'] = function () {
|
|
return '// PWM frequency change not supported on AVR\n';
|
|
};
|
|
|
|
// ─── ADC ──────────────────────────────────────────────────
|
|
|
|
arduinoGenerator.forBlock['adc_read'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
return [`analogRead(${pin})`, Order.FUNCTION_CALL];
|
|
};
|
|
|
|
// ─── Sensors (sonar / HC-SR04) ────────────────────────────
|
|
|
|
arduinoGenerator.forBlock['sonar_distance'] = function (block) {
|
|
const trig = arduinoGenerator.valueToCode(block, 'TRIG', Order.NONE) || '2';
|
|
const echo = arduinoGenerator.valueToCode(block, 'ECHO', Order.NONE) || '3';
|
|
|
|
arduinoGenerator.addDeclaration('sonar_helper',
|
|
'float _sonar_cm(int trigPin, int echoPin) {\n' +
|
|
' pinMode(trigPin, OUTPUT);\n' +
|
|
' pinMode(echoPin, INPUT);\n' +
|
|
' digitalWrite(trigPin, LOW);\n' +
|
|
' delayMicroseconds(2);\n' +
|
|
' digitalWrite(trigPin, HIGH);\n' +
|
|
' delayMicroseconds(10);\n' +
|
|
' digitalWrite(trigPin, LOW);\n' +
|
|
' long d = pulseIn(echoPin, HIGH, 30000);\n' +
|
|
' return d > 0 ? d / 58.0 : -1;\n' +
|
|
'}'
|
|
);
|
|
|
|
return [`_sonar_cm(${trig}, ${echo})`, Order.FUNCTION_CALL];
|
|
};
|
|
|
|
// ─── Time ─────────────────────────────────────────────────
|
|
|
|
arduinoGenerator.forBlock['sleep_seconds'] = function (block) {
|
|
const seconds = arduinoGenerator.valueToCode(block, 'SECONDS', Order.MULTIPLICATIVE) || '1';
|
|
return `delay(${seconds} * 1000);\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['sleep_ms'] = function (block) {
|
|
const ms = arduinoGenerator.valueToCode(block, 'MS', Order.NONE) || '100';
|
|
return `delay(${ms});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['ticks_ms'] = function () {
|
|
return ['millis()', Order.FUNCTION_CALL];
|
|
};
|
|
|
|
// ─── Random ───────────────────────────────────────────────
|
|
|
|
arduinoGenerator.forBlock['random_int'] = function (block) {
|
|
const from_ = arduinoGenerator.valueToCode(block, 'FROM', Order.NONE) || '0';
|
|
const to = arduinoGenerator.valueToCode(block, 'TO', Order.ADDITIVE) || '10';
|
|
return [`random(${from_}, ${to} + 1)`, Order.FUNCTION_CALL];
|
|
};
|
|
|
|
arduinoGenerator.forBlock['random_float'] = function () {
|
|
return ['(random(10001) / 10000.0)', Order.MULTIPLICATIVE];
|
|
};
|
|
|
|
arduinoGenerator.forBlock['random_uniform'] = function (block) {
|
|
const low = arduinoGenerator.valueToCode(block, 'LOW', Order.NONE) || '0';
|
|
const high = arduinoGenerator.valueToCode(block, 'HIGH', Order.NONE) || '1';
|
|
return [`(${low} + (random(10001) / 10000.0) * (${high} - ${low}))`, Order.ADDITIVE];
|
|
};
|
|
|
|
arduinoGenerator.forBlock['random_seed'] = function (block) {
|
|
const seed = arduinoGenerator.valueToCode(block, 'SEED', Order.NONE) || '0';
|
|
return `randomSeed(${seed});\n`;
|
|
};
|
|
|
|
// ─── Print ────────────────────────────────────────────────
|
|
|
|
arduinoGenerator.forBlock['print_text'] = function (block) {
|
|
arduinoGenerator.addSetupCode('Serial.begin(9600);');
|
|
const text = arduinoGenerator.valueToCode(block, 'TEXT', Order.NONE) || '""';
|
|
return `Serial.println(${text});\n`;
|
|
};
|
|
|
|
// ─── Sound (shared blocks) ────────────────────────────────
|
|
|
|
arduinoGenerator.forBlock['sound_play_tone'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
const freq = arduinoGenerator.valueToCode(block, 'FREQ', Order.NONE) || '440';
|
|
const duration = arduinoGenerator.valueToCode(block, 'DURATION', Order.NONE) || '500';
|
|
return `tone(${pin}, ${freq}, ${duration});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['sound_stop'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
return `noTone(${pin});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['sound_play_tone_speaker'] = function () {
|
|
return '// Built-in speaker not available on Arduino\n';
|
|
};
|
|
|
|
arduinoGenerator.forBlock['sound_stop_speaker'] = function () {
|
|
return '// Built-in speaker not available on Arduino\n';
|
|
};
|
|
|
|
// ─── Arduino-specific blocks ──────────────────────────────
|
|
|
|
arduinoGenerator.forBlock['arduino_builtin_led'] = function (block) {
|
|
const state = block.getFieldValue('STATE');
|
|
arduinoGenerator.addSetupCode('pinMode(LED_BUILTIN, OUTPUT);');
|
|
return `digitalWrite(LED_BUILTIN, ${state === '1' ? 'HIGH' : 'LOW'});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['arduino_analog_write'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
const value = arduinoGenerator.valueToCode(block, 'VALUE', Order.NONE) || '0';
|
|
return `analogWrite(${pin}, ${value});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['arduino_analog_read'] = function (block) {
|
|
const ch = block.getFieldValue('CHANNEL');
|
|
return [`analogRead(A${ch})`, Order.FUNCTION_CALL];
|
|
};
|
|
|
|
arduinoGenerator.forBlock['arduino_servo_attach'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
arduinoGenerator.addInclude('include_servo', '#include <Servo.h>');
|
|
arduinoGenerator.addDeclaration(`servo_decl_${pin}`, `Servo servo_${pin};`);
|
|
arduinoGenerator.addSetupCode(`servo_${pin}.attach(${pin});`);
|
|
return '';
|
|
};
|
|
|
|
arduinoGenerator.forBlock['arduino_servo_write'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
const angle = arduinoGenerator.valueToCode(block, 'ANGLE', Order.NONE) || '90';
|
|
arduinoGenerator.addInclude('include_servo', '#include <Servo.h>');
|
|
arduinoGenerator.addDeclaration(`servo_decl_${pin}`, `Servo servo_${pin};`);
|
|
arduinoGenerator.addSetupCode(`servo_${pin}.attach(${pin});`);
|
|
return `servo_${pin}.write(${angle});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['arduino_tone'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
const freq = arduinoGenerator.valueToCode(block, 'FREQ', Order.NONE) || '440';
|
|
const duration = arduinoGenerator.valueToCode(block, 'DURATION', Order.NONE) || '500';
|
|
return `tone(${pin}, ${freq}, ${duration});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['arduino_no_tone'] = function (block) {
|
|
const pin = block.getFieldValue('PIN');
|
|
return `noTone(${pin});\n`;
|
|
};
|
|
|
|
arduinoGenerator.forBlock['arduino_map'] = function (block) {
|
|
const value = arduinoGenerator.valueToCode(block, 'VALUE', Order.NONE) || '0';
|
|
const fromLow = arduinoGenerator.valueToCode(block, 'FROM_LOW', Order.NONE) || '0';
|
|
const fromHigh = arduinoGenerator.valueToCode(block, 'FROM_HIGH', Order.NONE) || '1023';
|
|
const toLow = arduinoGenerator.valueToCode(block, 'TO_LOW', Order.NONE) || '0';
|
|
const toHigh = arduinoGenerator.valueToCode(block, 'TO_HIGH', Order.NONE) || '255';
|
|
return [`map(${value}, ${fromLow}, ${fromHigh}, ${toLow}, ${toHigh})`, Order.FUNCTION_CALL];
|
|
};
|
|
|
|
// ─── Blocks not applicable to Arduino ─────────────────────
|
|
|
|
const unsupportedBlocks = [
|
|
'wifi_connect', 'wifi_get_ip',
|
|
'neopixel_init', 'neopixel_set_color', 'neopixel_show',
|
|
'colour_rgb', 'tuple_create_3',
|
|
'i2c_init', 'i2c_scan', 'i2c_writeto', 'i2c_readfrom',
|
|
'hid_key_press', 'hid_key_down', 'hid_key_up', 'hid_keyboard_type',
|
|
'hid_mouse_move', 'hid_mouse_click', 'hid_mouse_scroll',
|
|
'hid_gamepad_button', 'hid_gamepad_axis',
|
|
'microbit_display_all',
|
|
'superbit_motor_run', 'superbit_motor_stop_all',
|
|
];
|
|
|
|
for (const blockType of unsupportedBlocks) {
|
|
arduinoGenerator.forBlock[blockType] = function () {
|
|
return '// Block not supported on Arduino\n';
|
|
};
|
|
}
|