2012-08-13 20:17:45 +02:00
|
|
|
mesecon:add_rules("microcontroller_all", { --flat rules (looks better with nodebox wires connection)
|
|
|
|
{x = 1, y = 0, z = 0 },
|
|
|
|
{x = 0, y = 0, z = 1 },
|
|
|
|
{x = -1, y = 0, z = 0},
|
|
|
|
{x = 0, y = 0, z = -1}})
|
|
|
|
|
2012-08-08 23:35:36 +02:00
|
|
|
EEPROM_SIZE = 255
|
|
|
|
|
2012-08-09 12:54:31 +02:00
|
|
|
for a = 0, 1 do
|
|
|
|
for b = 0, 1 do
|
|
|
|
for c = 0, 1 do
|
|
|
|
for d = 0, 1 do
|
|
|
|
local nodename = "mesecons_microcontroller:microcontroller"..tostring(d)..tostring(c)..tostring(b)..tostring(a)
|
2012-08-09 13:34:10 +02:00
|
|
|
if tostring(d)..tostring(c)..tostring(b)..tostring(a) ~= "0000" then
|
2012-08-13 20:17:45 +02:00
|
|
|
groups = {dig_immediate=2, not_in_creative_inventory=1, mesecon = 3}
|
2012-08-09 13:34:10 +02:00
|
|
|
else
|
2012-08-13 20:17:45 +02:00
|
|
|
groups = {dig_immediate=2, mesecon = 3}
|
2012-08-09 13:34:10 +02:00
|
|
|
end
|
2012-08-09 12:54:31 +02:00
|
|
|
minetest.register_node(nodename, {
|
2012-08-08 13:26:32 +02:00
|
|
|
description = "Microcontroller",
|
|
|
|
drawtype = "nodebox",
|
2012-08-09 10:13:05 +02:00
|
|
|
tiles = {
|
2012-08-09 12:54:31 +02:00
|
|
|
"jeija_microcontroller_top_"..tostring(d)..tostring(c)..tostring(b)..tostring(a)..".png",
|
2012-08-09 10:13:05 +02:00
|
|
|
"jeija_microcontroller_sides.png",
|
|
|
|
},
|
2012-08-09 21:40:25 +02:00
|
|
|
|
2012-08-08 13:26:32 +02:00
|
|
|
sunlight_propagates = true,
|
|
|
|
paramtype = "light",
|
|
|
|
walkable = true,
|
2012-08-09 13:34:10 +02:00
|
|
|
groups = groups,
|
2012-08-08 13:26:32 +02:00
|
|
|
material = minetest.digprop_constanttime(1.0),
|
2012-08-09 12:54:31 +02:00
|
|
|
drop = '"mesecons_microcontroller:microcontroller0000" 1',
|
2012-08-08 13:26:32 +02:00
|
|
|
selection_box = {
|
|
|
|
type = "fixed",
|
2012-08-12 03:04:05 +02:00
|
|
|
fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 },
|
2012-08-08 13:26:32 +02:00
|
|
|
},
|
|
|
|
node_box = {
|
|
|
|
type = "fixed",
|
2012-08-09 10:13:05 +02:00
|
|
|
fixed = {
|
2012-08-12 03:04:05 +02:00
|
|
|
{ -8/16, -8/16, -8/16, 8/16, -7/16, 8/16 }, -- bottom slab
|
|
|
|
{ -5/16, -7/16, -5/16, 5/16, -6/16, 5/16 }, -- circuit board
|
|
|
|
{ -3/16, -6/16, -3/16, 3/16, -5/16, 3/16 }, -- IC
|
2012-08-09 10:13:05 +02:00
|
|
|
}
|
2012-08-08 13:26:32 +02:00
|
|
|
},
|
|
|
|
on_construct = function(pos)
|
|
|
|
local meta = minetest.env:get_meta(pos)
|
|
|
|
meta:set_string("code", "")
|
2012-08-09 22:39:54 +02:00
|
|
|
meta:set_string("formspec", "size[9,2.5]"..
|
|
|
|
"field[0.256,-0.2;9,2;code;Code:;]"..
|
|
|
|
"button[0 ,0.2;1.5,3;band;AND]"..
|
|
|
|
"button[1.5,0.2;1.5,3;bxor;XOR]"..
|
|
|
|
"button[3 ,0.2;1.5,3;bnot;NOT]"..
|
|
|
|
"button[4.5,0.2;1.5,3;bnand;NAND]"..
|
|
|
|
"button[6 ,0.2;1.5,3;btflop;T-Flop]"..
|
|
|
|
"button[7.5,0.2;1.5,3;brsflop;RS-Flop]"..
|
|
|
|
"button_exit[3.5,1;2,3;program;Program]")
|
2012-08-08 13:26:32 +02:00
|
|
|
meta:set_string("infotext", "Unprogrammed Microcontroller")
|
2012-08-09 21:40:25 +02:00
|
|
|
meta:set_int("heat", 0)
|
2012-08-08 23:35:36 +02:00
|
|
|
local r = ""
|
|
|
|
for i=1, EEPROM_SIZE+1 do r=r.."0" end --Generate a string with EEPROM_SIZE*"0"
|
|
|
|
meta:set_string("eeprom", r)
|
2012-08-08 13:26:32 +02:00
|
|
|
end,
|
|
|
|
on_receive_fields = function(pos, formanme, fields, sender)
|
2012-08-09 22:39:54 +02:00
|
|
|
local meta = minetest.env:get_meta(pos)
|
|
|
|
if fields.band then
|
2012-08-10 09:44:49 +02:00
|
|
|
fields.code = "sbi(C, A&B) :A and B are inputs, C is output"
|
2012-08-09 22:39:54 +02:00
|
|
|
elseif fields.bxor then
|
2012-08-10 09:44:49 +02:00
|
|
|
fields.code = "sbi(C, A~B) :A and B are inputs, C is output"
|
2012-08-09 22:39:54 +02:00
|
|
|
elseif fields.bnot then
|
2012-08-10 09:44:49 +02:00
|
|
|
fields.code = "sbi(B, !A) :A is input, B is output"
|
2012-08-09 22:39:54 +02:00
|
|
|
elseif fields.bnand then
|
2012-08-10 09:44:49 +02:00
|
|
|
fields.code = "sbi(C, !A|!B) :A and B are inputs, C is output"
|
2012-08-09 22:39:54 +02:00
|
|
|
elseif fields.btflop then
|
|
|
|
fields.code = "if(A)sbi(1,1); if(!A&B)off(B)sbi(1,0); if(!A&!B)on(B)sbi(1,0); :A is input, B is output (Q), toggles with falling edge"
|
|
|
|
elseif fields.brsflop then
|
|
|
|
fields.code = "if(A)on(C);if(B)off(C); :A is S (Set), B is R (Reset), C is output (R dominates)"
|
2012-08-09 23:09:02 +02:00
|
|
|
elseif fields.program then --nothing
|
2012-08-09 22:39:54 +02:00
|
|
|
else return nil end
|
|
|
|
|
|
|
|
meta:set_string("code", fields.code)
|
|
|
|
meta:set_string("formspec", "size[9,2.5]"..
|
|
|
|
"field[0.256,-0.2;9,2;code;Code:;"..fields.code.."]"..
|
|
|
|
"button[0 ,0.2;1.5,3;band;AND]"..
|
|
|
|
"button[1.5,0.2;1.5,3;bxor;XOR]"..
|
|
|
|
"button[3 ,0.2;1.5,3;bnot;NOT]"..
|
|
|
|
"button[4.5,0.2;1.5,3;bnand;NAND]"..
|
|
|
|
"button[6 ,0.2;1.5,3;btflop;T-Flop]"..
|
|
|
|
"button[7.5,0.2;1.5,3;brsflop;RS-Flop]"..
|
|
|
|
"button_exit[3.5,1;2,3;program;Program]")
|
2012-08-09 23:09:02 +02:00
|
|
|
meta:set_string("infotext", "Programmed Microcontroller")
|
|
|
|
yc_reset (pos)
|
|
|
|
update_yc(pos)
|
2012-08-09 21:40:25 +02:00
|
|
|
end,
|
2012-08-08 13:26:32 +02:00
|
|
|
})
|
2012-08-13 20:17:45 +02:00
|
|
|
|
2012-08-09 12:54:31 +02:00
|
|
|
local rules={}
|
|
|
|
if (a == 1) then table.insert(rules, {x = -1, y = 0, z = 0}) end
|
|
|
|
if (b == 1) then table.insert(rules, {x = 0, y = 0, z = 1}) end
|
|
|
|
if (c == 1) then table.insert(rules, {x = 1, y = 0, z = 0}) end
|
|
|
|
if (d == 1) then table.insert(rules, {x = 0, y = 0, z = -1}) end
|
|
|
|
mesecon:add_rules(nodename, rules)
|
2012-08-13 20:17:45 +02:00
|
|
|
|
|
|
|
mesecon:register_effector(nodename, nodename, mesecon:get_rules("microcontroller_all"))
|
2012-08-10 11:46:17 +02:00
|
|
|
if nodename ~= "mesecons_microcontroller:microcontroller0000" then
|
|
|
|
mesecon:add_receptor_node(nodename, rules)
|
|
|
|
end
|
2012-08-09 12:54:31 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2012-08-08 13:26:32 +02:00
|
|
|
|
|
|
|
minetest.register_craft({
|
2012-08-09 12:54:31 +02:00
|
|
|
output = 'craft "mesecons_microcontroller:microcontroller0000" 2',
|
2012-08-08 13:26:32 +02:00
|
|
|
recipe = {
|
2012-08-12 02:53:47 +02:00
|
|
|
{'mesecons_materials:silicon', 'mesecons_materials:silicon', 'group:mesecon_conductor_craftable'},
|
|
|
|
{'mesecons_materials:silicon', 'mesecons_materials:silicon', 'group:mesecon_conductor_craftable'},
|
|
|
|
{'group:mesecon_conductor_craftable', 'group:mesecon_conductor_craftable', ''},
|
2012-08-08 13:26:32 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2012-08-09 21:40:25 +02:00
|
|
|
function yc_reset(pos)
|
2012-08-09 12:54:31 +02:00
|
|
|
yc_action(pos, {a=false, b=false, c=false, d=false})
|
2012-08-08 23:35:36 +02:00
|
|
|
local meta = minetest.env:get_meta(pos)
|
2012-08-13 22:55:14 +02:00
|
|
|
meta:set_int("heat", 0)
|
|
|
|
meta:set_int("afterid", 0)
|
2012-08-08 23:35:36 +02:00
|
|
|
local r = ""
|
|
|
|
for i=1, EEPROM_SIZE+1 do r=r.."0" end --Generate a string with EEPROM_SIZE*"0"
|
|
|
|
meta:set_string("eeprom", r)
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function update_yc(pos)
|
|
|
|
local meta = minetest.env:get_meta(pos)
|
2012-08-09 21:40:25 +02:00
|
|
|
yc_heat(meta)
|
|
|
|
minetest.after(0.5, yc_cool, meta)
|
|
|
|
if (yc_overheat(meta)) then
|
|
|
|
minetest.env:remove_node(pos)
|
|
|
|
minetest.after(0.2, yc_overheat_off, pos) --wait for pending parsings
|
|
|
|
minetest.env:add_item(pos, "mesecons_microcontroller:microcontroller0000")
|
2012-08-09 16:25:30 +02:00
|
|
|
end
|
|
|
|
|
2012-08-08 13:26:32 +02:00
|
|
|
local code = meta:get_string("code")
|
2012-08-09 08:27:47 +02:00
|
|
|
code = yc_code_remove_commentary(code)
|
2012-08-08 13:26:32 +02:00
|
|
|
code = string.gsub(code, " ", "") --Remove all spaces
|
|
|
|
code = string.gsub(code, " ", "") --Remove all tabs
|
2012-08-13 22:33:25 +02:00
|
|
|
if yc_parsecode(code, pos) == nil then
|
2012-08-08 13:26:32 +02:00
|
|
|
meta:set_string("infotext", "Code not valid!")
|
|
|
|
else
|
2012-08-09 09:03:22 +02:00
|
|
|
meta:set_string("infotext", "Working Microcontroller")
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-08-09 21:40:25 +02:00
|
|
|
|
|
|
|
--Code Parsing
|
2012-08-09 08:27:47 +02:00
|
|
|
function yc_code_remove_commentary(code)
|
2012-08-10 10:47:40 +02:00
|
|
|
is_string = false
|
2012-08-09 08:27:47 +02:00
|
|
|
for i = 1, #code do
|
2012-08-10 10:47:40 +02:00
|
|
|
if code:sub(i, i) == '"' then
|
|
|
|
is_string = (is_string==false) --toggle is_string
|
|
|
|
end
|
|
|
|
if code:sub(i, i) == ":" and is_string==false then
|
2012-08-09 08:27:47 +02:00
|
|
|
return code:sub(1, i-1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return code
|
|
|
|
end
|
|
|
|
|
2012-08-13 22:33:25 +02:00
|
|
|
function yc_parsecode(code, pos)
|
2012-08-08 13:26:32 +02:00
|
|
|
local endi = 1
|
2012-08-09 12:54:31 +02:00
|
|
|
local Lreal = yc_get_real_portstates(pos)
|
|
|
|
local Lvirtual = yc_get_virtual_portstates(pos)
|
2012-08-09 21:40:25 +02:00
|
|
|
if Lvirtual == nil then return nil end
|
2012-08-08 13:26:32 +02:00
|
|
|
local c
|
2012-08-08 23:35:36 +02:00
|
|
|
local eeprom = minetest.env:get_meta(pos):get_string("eeprom")
|
2012-08-08 13:26:32 +02:00
|
|
|
while true do
|
|
|
|
command, endi = parse_get_command(code, endi)
|
|
|
|
if command == nil then return nil end
|
2012-08-10 10:19:33 +02:00
|
|
|
if command == true then break end --end of code
|
2012-08-08 13:26:32 +02:00
|
|
|
if command == "if" then
|
2012-08-09 12:54:31 +02:00
|
|
|
r, endi = yc_command_if(code, endi, yc_merge_portstates(Lreal, Lvirtual), eeprom)
|
2012-08-08 13:26:32 +02:00
|
|
|
if r == nil then return nil end
|
2012-08-09 13:34:10 +02:00
|
|
|
if r == true then -- nothing
|
2012-08-08 13:26:32 +02:00
|
|
|
elseif r == false then
|
2012-08-10 10:19:33 +02:00
|
|
|
endi_new = yc_skip_to_else (code, endi)
|
|
|
|
if endi_new == nil then --else > not found
|
|
|
|
endi = yc_skip_to_endif(code, endi)
|
|
|
|
else
|
|
|
|
endi = endi_new
|
|
|
|
end
|
2012-08-08 13:26:32 +02:00
|
|
|
if endi == nil then return nil end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
params, endi = parse_get_params(code, endi)
|
|
|
|
if params == nil then return nil end
|
|
|
|
end
|
|
|
|
if command == "on" then
|
2012-08-09 12:54:31 +02:00
|
|
|
L = yc_command_on (params, Lvirtual)
|
2012-08-08 13:26:32 +02:00
|
|
|
elseif command == "off" then
|
2012-08-09 12:54:31 +02:00
|
|
|
L = yc_command_off(params, Lvirtual)
|
2012-08-10 10:47:40 +02:00
|
|
|
elseif command == "print" then
|
2012-08-13 22:33:25 +02:00
|
|
|
local su = yc_command_print(params, eeprom, yc_merge_portstates(Lreal, Lvirtual))
|
2012-08-10 10:47:40 +02:00
|
|
|
if su ~= true then return nil end
|
2012-08-13 22:33:25 +02:00
|
|
|
elseif command == "after" then
|
|
|
|
local su = yc_command_after(params, pos)
|
|
|
|
if su == nil then return nil end
|
2012-08-08 23:35:36 +02:00
|
|
|
elseif command == "sbi" then
|
2012-08-10 09:44:49 +02:00
|
|
|
new_eeprom, Lvirtual = yc_command_sbi (params, eeprom, yc_merge_portstates(Lreal, Lvirtual), Lvirtual)
|
2012-08-09 09:03:22 +02:00
|
|
|
if new_eeprom == nil then return nil
|
|
|
|
else eeprom = new_eeprom end
|
2012-08-08 13:26:32 +02:00
|
|
|
elseif command == "if" then --nothing
|
|
|
|
else
|
|
|
|
return nil
|
|
|
|
end
|
2012-08-09 13:34:10 +02:00
|
|
|
if Lvirtual == nil then return nil end
|
2012-08-08 23:35:36 +02:00
|
|
|
if eeprom == nil then return nil else
|
|
|
|
minetest.env:get_meta(pos):set_string("eeprom", eeprom) end
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
2012-08-09 12:54:31 +02:00
|
|
|
yc_action(pos, Lvirtual)
|
2012-08-08 13:26:32 +02:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function parse_get_command(code, starti)
|
|
|
|
i = starti
|
|
|
|
s = nil
|
|
|
|
while s ~= "" do
|
|
|
|
s = string.sub(code, i, i)
|
2012-08-10 10:19:33 +02:00
|
|
|
if s == "(" then
|
|
|
|
return string.sub(code, starti, i-1), i + 1 -- i: ( i+1 after (
|
|
|
|
end
|
2012-08-08 13:26:32 +02:00
|
|
|
if s == ";" and starti == i then
|
|
|
|
starti = starti + 1
|
|
|
|
i = starti
|
2012-08-10 10:19:33 +02:00
|
|
|
elseif s == ">" then
|
|
|
|
starti = yc_skip_to_endif(code, starti)
|
|
|
|
if starti == nil then return nil end
|
|
|
|
i = starti
|
|
|
|
else
|
|
|
|
i = i + 1
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
|
|
|
end
|
2012-08-10 10:19:33 +02:00
|
|
|
|
2012-08-08 13:26:32 +02:00
|
|
|
if starti == i-1 then
|
|
|
|
return true, true
|
|
|
|
end
|
|
|
|
return nil, nil
|
|
|
|
end
|
|
|
|
|
|
|
|
function parse_get_params(code, starti)
|
|
|
|
i = starti
|
|
|
|
s = nil
|
|
|
|
local params = {}
|
2012-08-10 10:47:40 +02:00
|
|
|
local is_string = false
|
2012-08-08 13:26:32 +02:00
|
|
|
while s ~= "" do
|
|
|
|
s = string.sub(code, i, i)
|
2012-08-10 10:47:40 +02:00
|
|
|
if code:sub(i, i) == '"' then
|
|
|
|
is_string = (is_string==false) --toggle is_string
|
|
|
|
end
|
|
|
|
if s == ")" and is_string == false then
|
2012-08-08 13:26:32 +02:00
|
|
|
table.insert(params, string.sub(code, starti, i-1)) -- i: ) i+1 after )
|
|
|
|
return params, i + 1
|
|
|
|
end
|
2012-08-10 10:47:40 +02:00
|
|
|
if s == "," and is_string == false then
|
2012-08-08 13:26:32 +02:00
|
|
|
table.insert(params, string.sub(code, starti, i-1)) -- i: ) i+1 after )
|
|
|
|
starti = i + 1
|
|
|
|
end
|
|
|
|
i = i + 1
|
|
|
|
end
|
|
|
|
return nil, nil
|
|
|
|
end
|
|
|
|
|
2012-08-09 08:06:23 +02:00
|
|
|
function yc_parse_get_eeprom_param(cond, starti)
|
2012-08-08 23:35:36 +02:00
|
|
|
i = starti
|
|
|
|
s = nil
|
2012-08-09 08:06:23 +02:00
|
|
|
local addr
|
2012-08-08 23:35:36 +02:00
|
|
|
while s ~= "" do
|
2012-08-09 08:06:23 +02:00
|
|
|
s = string.sub(cond, i, i)
|
|
|
|
if string.find("0123456789", s) == nil or s == "" then
|
|
|
|
addr = string.sub(cond, starti, i-1) -- i: last number i+1 after last number
|
|
|
|
return addr, i
|
2012-08-08 23:35:36 +02:00
|
|
|
end
|
|
|
|
if s == "," then return nil, nil end
|
|
|
|
i = i + 1
|
|
|
|
end
|
|
|
|
return nil, nil
|
|
|
|
end
|
|
|
|
|
2012-08-09 21:40:25 +02:00
|
|
|
function yc_skip_to_endif(code, starti)
|
|
|
|
local i = starti
|
|
|
|
local s = false
|
2012-08-10 10:19:33 +02:00
|
|
|
local open_ifs = 1
|
|
|
|
while s ~= nil and s~= "" do
|
|
|
|
s = code:sub(i, i)
|
|
|
|
if s == "i" and code:sub(i+1, i+1) == "f" then --if in µCScript
|
|
|
|
open_ifs = open_ifs + 1
|
|
|
|
end
|
|
|
|
if s == ";" then
|
|
|
|
open_ifs = open_ifs - 1
|
|
|
|
end
|
|
|
|
if open_ifs == 0 then
|
|
|
|
return i + 1
|
|
|
|
end
|
|
|
|
i = i + 1
|
|
|
|
end
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
function yc_skip_to_else(code, starti)
|
|
|
|
local i = starti
|
|
|
|
local s = false
|
|
|
|
local open_ifs = 1
|
2012-08-09 21:40:25 +02:00
|
|
|
while s ~= nil and s~= "" do
|
|
|
|
s = code:sub(i, i)
|
2012-08-10 10:19:33 +02:00
|
|
|
if s == "i" and code:sub(i+1, i+1) == "f" then --if in µCScript
|
|
|
|
open_ifs = open_ifs + 1
|
|
|
|
end
|
2012-08-09 21:40:25 +02:00
|
|
|
if s == ";" then
|
2012-08-10 10:19:33 +02:00
|
|
|
open_ifs = open_ifs - 1
|
|
|
|
end
|
|
|
|
if open_ifs == 1 and s == ">" then
|
2012-08-09 21:40:25 +02:00
|
|
|
return i + 1
|
|
|
|
end
|
|
|
|
i = i + 1
|
|
|
|
end
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
--Commands
|
2012-08-08 13:26:32 +02:00
|
|
|
function yc_command_on(params, L)
|
|
|
|
local rules = {}
|
|
|
|
for i, port in ipairs(params) do
|
|
|
|
L = yc_set_portstate (port, true, L)
|
|
|
|
end
|
|
|
|
return L
|
|
|
|
end
|
|
|
|
|
|
|
|
function yc_command_off(params, L)
|
|
|
|
local rules = {}
|
|
|
|
for i, port in ipairs(params) do
|
|
|
|
L = yc_set_portstate (port, false, L)
|
|
|
|
end
|
|
|
|
return L
|
|
|
|
end
|
|
|
|
|
2012-08-10 10:47:40 +02:00
|
|
|
function yc_command_print(params, eeprom, L)
|
|
|
|
local s = ""
|
|
|
|
for i, param in ipairs(params) do
|
|
|
|
if param:sub(1,1) == '"' and param:sub(#param, #param) == '"' then
|
|
|
|
s = s..param:sub(2, #param-1)
|
|
|
|
else
|
|
|
|
r = yc_command_parsecondition(param, L, eeprom)
|
|
|
|
if r == "1" or r == "0" then
|
|
|
|
s = s..r
|
|
|
|
else return nil end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
print(s) --don't remove
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2012-08-10 09:44:49 +02:00
|
|
|
function yc_command_sbi(params, eeprom, L, Lv)
|
|
|
|
if params[1]==nil or params[2]==nil or params[3] ~=nil then return nil end
|
2012-08-09 09:03:22 +02:00
|
|
|
local status = yc_command_parsecondition(params[2], L, eeprom)
|
2012-08-10 09:44:49 +02:00
|
|
|
|
|
|
|
if status == nil then return nil, nil end
|
|
|
|
|
|
|
|
if string.find("ABCD", params[1])~=nil and #params[1]==1 then --is a port
|
|
|
|
if status == "1" then
|
|
|
|
Lv = yc_set_portstate (params[1], true, Lv)
|
|
|
|
else
|
|
|
|
Lv = yc_set_portstate (params[1], false, Lv)
|
|
|
|
end
|
|
|
|
return eeprom, Lv;
|
|
|
|
end
|
|
|
|
|
|
|
|
--is an eeprom address
|
2012-08-08 23:35:36 +02:00
|
|
|
new_eeprom = "";
|
|
|
|
for i=1, #eeprom do
|
|
|
|
if tonumber(params[1])==i then
|
2012-08-09 09:03:22 +02:00
|
|
|
new_eeprom = new_eeprom..status
|
2012-08-08 23:35:36 +02:00
|
|
|
else
|
|
|
|
new_eeprom = new_eeprom..eeprom:sub(i, i)
|
|
|
|
end
|
|
|
|
end
|
2012-08-10 09:44:49 +02:00
|
|
|
return new_eeprom, Lv
|
2012-08-08 23:35:36 +02:00
|
|
|
end
|
|
|
|
|
2012-08-13 22:33:25 +02:00
|
|
|
-- after (delay)
|
|
|
|
function yc_command_after(params, pos)
|
|
|
|
if params[1] == nil or params[2] == nil or params[3] ~= nil then return nil end
|
|
|
|
|
|
|
|
--get time (maximum time is 200)
|
|
|
|
local time = tonumber(params[1])
|
|
|
|
if time == nil or time > 200 then
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
--get code in quotes "code"
|
|
|
|
if string.sub(params[2], 1, 1) ~= '"' or string.sub(params[2], #params[2], #params[2]) ~= '"' then return nil end
|
|
|
|
local code = string.sub(params[2], 2, #params[2] - 1)
|
|
|
|
|
2012-08-13 22:55:14 +02:00
|
|
|
local afterid = math.random(10000)
|
|
|
|
local meta = minetest.env:get_meta(pos)
|
|
|
|
meta:set_int("afterid", afterid)
|
|
|
|
minetest.after(time, yc_command_after_execute, {pos = pos, code = code, afterid = afterid})
|
2012-08-13 22:33:25 +02:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function yc_command_after_execute(params)
|
2012-08-13 22:55:14 +02:00
|
|
|
local meta = minetest.env:get_meta(params.pos)
|
|
|
|
if meta:get_int("afterid") == params.afterid then --make sure the node has not been changed
|
2012-08-13 22:33:25 +02:00
|
|
|
yc_parsecode(params.code, params.pos)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-08-09 21:40:25 +02:00
|
|
|
--If
|
2012-08-08 23:35:36 +02:00
|
|
|
function yc_command_if(code, starti, L, eeprom)
|
2012-08-08 13:26:32 +02:00
|
|
|
local cond, endi = yc_command_if_getcondition(code, starti)
|
|
|
|
if cond == nil then return nil end
|
2012-08-08 15:09:05 +02:00
|
|
|
|
2012-08-09 09:03:22 +02:00
|
|
|
cond = yc_command_parsecondition(cond, L, eeprom)
|
2012-08-08 15:09:05 +02:00
|
|
|
|
|
|
|
if cond == "0" then result = false
|
|
|
|
elseif cond == "1" then result = true
|
|
|
|
else result = nil end
|
2012-08-09 13:34:10 +02:00
|
|
|
if result == nil then end
|
2012-08-08 15:09:05 +02:00
|
|
|
return result, endi --endi from local cond, endi = yc_command_if_getcondition(code, starti)
|
|
|
|
end
|
|
|
|
|
2012-08-09 21:40:25 +02:00
|
|
|
--Condition parsing
|
2012-08-08 15:09:05 +02:00
|
|
|
function yc_command_if_getcondition(code, starti)
|
|
|
|
i = starti
|
|
|
|
s = nil
|
2012-08-08 23:35:36 +02:00
|
|
|
local brackets = 1 --1 Bracket to close
|
2012-08-08 15:09:05 +02:00
|
|
|
while s ~= "" do
|
|
|
|
s = string.sub(code, i, i)
|
2012-08-08 23:35:36 +02:00
|
|
|
|
2012-08-08 15:09:05 +02:00
|
|
|
if s == ")" then
|
2012-08-08 23:35:36 +02:00
|
|
|
brackets = brackets - 1
|
|
|
|
end
|
|
|
|
|
|
|
|
if s == "(" then
|
|
|
|
brackets = brackets + 1
|
|
|
|
end
|
|
|
|
|
|
|
|
if brackets == 0 then
|
|
|
|
return string.sub(code, starti, i-1), i + 1 -- i: ( i+1 after (
|
2012-08-08 15:09:05 +02:00
|
|
|
end
|
2012-08-08 23:35:36 +02:00
|
|
|
|
2012-08-08 15:09:05 +02:00
|
|
|
i = i + 1
|
|
|
|
end
|
|
|
|
return nil, nil
|
|
|
|
end
|
|
|
|
|
2012-08-09 09:03:22 +02:00
|
|
|
function yc_command_parsecondition(cond, L, eeprom)
|
2012-08-09 12:54:31 +02:00
|
|
|
cond = string.gsub(cond, "A", tonumber(L.a and 1 or 0))
|
2012-08-08 13:26:32 +02:00
|
|
|
cond = string.gsub(cond, "B", tonumber(L.b and 1 or 0))
|
|
|
|
cond = string.gsub(cond, "C", tonumber(L.c and 1 or 0))
|
|
|
|
cond = string.gsub(cond, "D", tonumber(L.d and 1 or 0))
|
|
|
|
|
2012-08-09 16:25:30 +02:00
|
|
|
|
2012-08-08 23:35:36 +02:00
|
|
|
local i = 1
|
|
|
|
local l = string.len(cond)
|
|
|
|
while i<=l do
|
|
|
|
local s = cond:sub(i,i)
|
2012-08-09 08:06:23 +02:00
|
|
|
if s == "#" then
|
|
|
|
addr, endi = yc_parse_get_eeprom_param(cond, i+1)
|
|
|
|
buf = yc_eeprom_read(tonumber(addr), eeprom)
|
2012-08-08 23:35:36 +02:00
|
|
|
if buf == nil then return nil end
|
|
|
|
local call = cond:sub(i, endi-1)
|
|
|
|
cond = string.gsub(cond, call, buf)
|
|
|
|
i = 0
|
|
|
|
l = string.len(cond)
|
|
|
|
end
|
|
|
|
i = i + 1
|
|
|
|
end
|
2012-08-09 09:05:00 +02:00
|
|
|
|
2012-08-09 08:06:23 +02:00
|
|
|
cond = string.gsub(cond, "!0", "1")
|
|
|
|
cond = string.gsub(cond, "!1", "0")
|
2012-08-09 09:05:00 +02:00
|
|
|
|
2012-08-08 15:09:05 +02:00
|
|
|
local i = 2
|
|
|
|
local l = string.len(cond)
|
|
|
|
while i<=l do
|
|
|
|
local s = cond:sub(i,i)
|
|
|
|
local b = tonumber(cond:sub(i-1, i-1))
|
|
|
|
local a = tonumber(cond:sub(i+1, i+1))
|
2012-08-08 20:13:07 +02:00
|
|
|
if cond:sub(i+1, i+1) == nil then break end
|
2012-08-08 15:09:05 +02:00
|
|
|
if s == "=" then
|
2012-08-09 08:06:23 +02:00
|
|
|
if a==nil then return nil end
|
2012-08-08 19:40:39 +02:00
|
|
|
if a == b then buf = "1" end
|
|
|
|
if a ~= b then buf = "0" end
|
2012-08-08 15:33:34 +02:00
|
|
|
cond = string.gsub(cond, b..s..a, buf)
|
2012-08-08 15:09:05 +02:00
|
|
|
i = 1
|
|
|
|
l = string.len(cond)
|
|
|
|
end
|
|
|
|
i = i + 1
|
|
|
|
end
|
2012-08-09 09:05:00 +02:00
|
|
|
|
2012-08-08 23:35:36 +02:00
|
|
|
local i = 2
|
2012-08-08 13:26:32 +02:00
|
|
|
local l = string.len(cond)
|
|
|
|
while i<=l do
|
|
|
|
local s = cond:sub(i,i)
|
|
|
|
local b = tonumber(cond:sub(i-1, i-1))
|
|
|
|
local a = tonumber(cond:sub(i+1, i+1))
|
2012-08-08 20:13:07 +02:00
|
|
|
if cond:sub(i+1, i+1) == nil then break end
|
2012-08-08 13:26:32 +02:00
|
|
|
if s == "&" then
|
2012-08-09 08:06:23 +02:00
|
|
|
if a==nil then return nil end
|
2012-08-08 13:26:32 +02:00
|
|
|
local buf = ((a==1) and (b==1))
|
|
|
|
if buf == true then buf = "1" end
|
|
|
|
if buf == false then buf = "0" end
|
|
|
|
cond = string.gsub(cond, b..s..a, buf)
|
|
|
|
i = 1
|
|
|
|
l = string.len(cond)
|
|
|
|
end
|
|
|
|
if s == "|" then
|
2012-08-09 08:06:23 +02:00
|
|
|
if a==nil then return nil end
|
2012-08-08 13:26:32 +02:00
|
|
|
local buf = ((a == 1) or (b == 1))
|
|
|
|
if buf == true then buf = "1" end
|
|
|
|
if buf == false then buf = "0" end
|
|
|
|
cond = string.gsub(cond, b..s..a, buf)
|
|
|
|
i = 1
|
|
|
|
l = string.len(cond)
|
|
|
|
end
|
|
|
|
if s == "~" then
|
2012-08-09 08:06:23 +02:00
|
|
|
if a==nil then return nil end
|
2012-08-08 13:26:32 +02:00
|
|
|
local buf = (((a == 1) or (b == 1)) and not((a==1) and (b==1)))
|
|
|
|
if buf == true then buf = "1" end
|
|
|
|
if buf == false then buf = "0" end
|
|
|
|
cond = string.gsub(cond, b..s..a, buf)
|
|
|
|
i = 1
|
|
|
|
l = string.len(cond)
|
|
|
|
end
|
|
|
|
i = i + 1
|
|
|
|
end
|
2012-08-09 09:05:00 +02:00
|
|
|
|
2012-08-08 15:09:05 +02:00
|
|
|
return cond
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
|
|
|
|
2012-08-09 21:40:25 +02:00
|
|
|
--Virtual-Hardware functions
|
2012-08-08 23:35:36 +02:00
|
|
|
function yc_eeprom_read(number, eeprom)
|
2012-08-09 08:06:23 +02:00
|
|
|
if number == nil then return nil, nil end
|
|
|
|
value = eeprom:sub(number, number)
|
2012-08-08 23:35:36 +02:00
|
|
|
if value == nil then return nil, nil end
|
|
|
|
return value, endi
|
|
|
|
end
|
|
|
|
|
2012-08-09 21:40:25 +02:00
|
|
|
--Real I/O functions
|
2012-08-09 12:54:31 +02:00
|
|
|
function yc_action(pos, L) --L-->Lvirtual
|
2012-08-09 16:25:30 +02:00
|
|
|
Lv = yc_get_virtual_portstates(pos)
|
2012-08-09 12:54:31 +02:00
|
|
|
local meta = minetest.env:get_meta(pos)
|
|
|
|
local code = meta:get_string("code")
|
2012-08-13 22:55:14 +02:00
|
|
|
local afterid = meta:get_int("afterid")
|
2012-08-09 21:40:25 +02:00
|
|
|
local heat = meta:get_int("heat")
|
2012-08-09 12:54:31 +02:00
|
|
|
local eeprom = meta:get_string("eeprom")
|
|
|
|
local infotext = meta:get_string("infotext")
|
|
|
|
local formspec = meta:get_string("formspec")
|
|
|
|
local name = "mesecons_microcontroller:microcontroller"
|
|
|
|
..tonumber(L.d and 1 or 0)
|
|
|
|
..tonumber(L.c and 1 or 0)
|
|
|
|
..tonumber(L.b and 1 or 0)
|
|
|
|
..tonumber(L.a and 1 or 0)
|
|
|
|
minetest.env:add_node(pos, {name=name})
|
|
|
|
local meta = minetest.env:get_meta(pos)
|
|
|
|
meta:set_string("code", code)
|
2012-08-09 21:40:25 +02:00
|
|
|
meta:set_int("heat", heat)
|
2012-08-13 22:55:14 +02:00
|
|
|
meta:set_int("afterid", afterid)
|
2012-08-09 12:54:31 +02:00
|
|
|
meta:set_string("eeprom", eeprom)
|
|
|
|
meta:set_string("infotext", infotext)
|
|
|
|
meta:set_string("formspec", formspec)
|
2012-08-09 16:25:30 +02:00
|
|
|
|
|
|
|
yc_action_setports(pos, L, Lv)
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
|
|
|
|
2012-08-09 16:25:30 +02:00
|
|
|
function yc_action_setports(pos, L, Lv)
|
|
|
|
local name = "mesecons_microcontroller:microcontroller"
|
2012-08-09 21:40:25 +02:00
|
|
|
local rules
|
|
|
|
if Lv.a ~= L.a then
|
2012-08-09 16:25:30 +02:00
|
|
|
rules = mesecon:get_rules(name.."0001")
|
|
|
|
if L.a == true then mesecon:receptor_on(pos, rules)
|
|
|
|
else mesecon:receptor_off(pos, rules) end
|
2012-08-09 21:40:25 +02:00
|
|
|
end
|
|
|
|
if Lv.b ~= L.b then
|
2012-08-09 16:25:30 +02:00
|
|
|
rules = mesecon:get_rules(name.."0010")
|
|
|
|
if L.b == true then mesecon:receptor_on(pos, rules)
|
|
|
|
else mesecon:receptor_off(pos, rules) end
|
2012-08-09 21:40:25 +02:00
|
|
|
end
|
|
|
|
if Lv.c ~= L.c then
|
2012-08-09 16:25:30 +02:00
|
|
|
rules = mesecon:get_rules(name.."0100")
|
|
|
|
if L.c == true then mesecon:receptor_on(pos, rules)
|
|
|
|
else mesecon:receptor_off(pos, rules) end
|
2012-08-09 21:40:25 +02:00
|
|
|
end
|
|
|
|
if Lv.d ~= L.d then
|
2012-08-09 16:25:30 +02:00
|
|
|
rules = mesecon:get_rules(name.."1000")
|
|
|
|
if L.d == true then mesecon:receptor_on(pos, rules)
|
|
|
|
else mesecon:receptor_off(pos, rules) end
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function yc_set_portstate(port, state, L)
|
|
|
|
if port == "A" then L.a = state
|
|
|
|
elseif port == "B" then L.b = state
|
|
|
|
elseif port == "C" then L.c = state
|
|
|
|
elseif port == "D" then L.d = state
|
|
|
|
else return nil end
|
|
|
|
return L
|
|
|
|
end
|
|
|
|
|
2012-08-09 12:54:31 +02:00
|
|
|
function yc_get_real_portstates(pos)
|
|
|
|
rulesA = mesecon:get_rules("mesecons_microcontroller:microcontroller0001")
|
|
|
|
rulesB = mesecon:get_rules("mesecons_microcontroller:microcontroller0010")
|
|
|
|
rulesC = mesecon:get_rules("mesecons_microcontroller:microcontroller0100")
|
|
|
|
rulesD = mesecon:get_rules("mesecons_microcontroller:microcontroller1000")
|
2012-08-09 16:25:30 +02:00
|
|
|
L = {
|
2012-08-08 13:26:32 +02:00
|
|
|
a = mesecon:is_power_on({x=pos.x+rulesA[1].x, y=pos.y+rulesA[1].y, z=pos.z+rulesA[1].z}),
|
|
|
|
b = mesecon:is_power_on({x=pos.x+rulesB[1].x, y=pos.y+rulesB[1].y, z=pos.z+rulesB[1].z}),
|
|
|
|
c = mesecon:is_power_on({x=pos.x+rulesC[1].x, y=pos.y+rulesC[1].y, z=pos.z+rulesC[1].z}),
|
|
|
|
d = mesecon:is_power_on({x=pos.x+rulesD[1].x, y=pos.y+rulesD[1].y, z=pos.z+rulesD[1].z})
|
|
|
|
}
|
|
|
|
return L
|
|
|
|
end
|
|
|
|
|
2012-08-09 12:54:31 +02:00
|
|
|
function yc_get_virtual_portstates(pos)
|
|
|
|
name = minetest.env:get_node(pos).name
|
|
|
|
b, a = string.find(name, ":microcontroller")
|
|
|
|
if a == nil then return nil end
|
|
|
|
a = a + 1
|
|
|
|
|
2012-08-09 16:25:30 +02:00
|
|
|
Lvirtual = {a=false, b=false, c=false, d=false}
|
2012-08-09 12:54:31 +02:00
|
|
|
if name:sub(a , a ) == "1" then Lvirtual.d = true end
|
|
|
|
if name:sub(a+1, a+1) == "1" then Lvirtual.c = true end
|
|
|
|
if name:sub(a+2, a+2) == "1" then Lvirtual.b = true end
|
2012-08-09 16:25:30 +02:00
|
|
|
if name:sub(a+3, a+3) == "1" then Lvirtual.a = true end
|
2012-08-09 12:54:31 +02:00
|
|
|
return Lvirtual
|
|
|
|
end
|
|
|
|
|
2012-08-09 21:40:25 +02:00
|
|
|
function yc_merge_portstates(Lreal, Lvirtual)
|
2012-08-09 16:25:30 +02:00
|
|
|
local L = {a=false, b=false, c=false, d=false}
|
|
|
|
if Lvirtual.a or Lreal.a then L.a = true end
|
|
|
|
if Lvirtual.b or Lreal.b then L.b = true end
|
|
|
|
if Lvirtual.c or Lreal.c then L.c = true end
|
|
|
|
if Lvirtual.d or Lreal.d then L.d = true end
|
|
|
|
return L
|
2012-08-09 12:54:31 +02:00
|
|
|
end
|
|
|
|
|
2012-08-09 21:40:25 +02:00
|
|
|
--"Overheat" protection
|
|
|
|
function yc_heat(meta)
|
|
|
|
h = meta:get_int("heat")
|
|
|
|
if h ~= nil then
|
|
|
|
meta:set_int("heat", h + 1)
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
2012-08-09 21:40:25 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function yc_cool(meta)
|
|
|
|
h = meta:get_int("heat")
|
|
|
|
if h ~= nil then
|
|
|
|
meta:set_int("heat", h - 1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function yc_overheat(meta)
|
|
|
|
h = meta:get_int("heat")
|
|
|
|
if h == nil then return true end -- if nil the overheat
|
|
|
|
if h>30 then
|
|
|
|
return true
|
|
|
|
else
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function yc_overheat_off(pos)
|
|
|
|
rules = mesecon:get_rules("mesecons_microcontroller:microcontroller1111")
|
|
|
|
mesecon:receptor_off(pos, rules);
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
mesecon:register_on_signal_change(function(pos, node)
|
2012-08-09 12:54:31 +02:00
|
|
|
if string.find(node.name, "mesecons_microcontroller:microcontroller")~=nil then
|
2012-08-09 21:40:25 +02:00
|
|
|
update_yc(pos)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
minetest.register_on_dignode(function(pos, node)
|
|
|
|
if string.find(node.name, "mesecons_microcontroller:microcontroller") then
|
|
|
|
rules = mesecon:get_rules(node.name)
|
|
|
|
mesecon:receptor_off(pos, rules)
|
2012-08-08 13:26:32 +02:00
|
|
|
end
|
|
|
|
end)
|