diff options
Diffstat (limited to 'mesecons_microcontroller')
-rw-r--r-- | mesecons_microcontroller/init.lua | 328 |
1 files changed, 231 insertions, 97 deletions
diff --git a/mesecons_microcontroller/init.lua b/mesecons_microcontroller/init.lua index 89a7736..f555557 100644 --- a/mesecons_microcontroller/init.lua +++ b/mesecons_microcontroller/init.lua @@ -1,22 +1,41 @@ EEPROM_SIZE = 255 -minetest.register_node("mesecons_microcontroller:microcontroller", { +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) +if tostring(d)..tostring(c)..tostring(b)..tostring(a) ~= "0000" then + groups = {dig_immediate=2, not_in_creative_inventory=1} +else + groups = {dig_immediate=2} +end +minetest.register_node(nodename, { description = "Microcontroller", drawtype = "nodebox", - tiles = {"jeija_ic.png"}, - inventory_image = {"jeija_ic.png"}, + tiles = { + "jeija_microcontroller_top_"..tostring(d)..tostring(c)..tostring(b)..tostring(a)..".png", + "jeija_microcontroller_sides.png", + }, + --inventory_image = "jeija_microcontroller_top_0000.png", + sunlight_propagates = true, paramtype = "light", walkable = true, - groups = {dig_immediate=2}, + groups = groups, material = minetest.digprop_constanttime(1.0), + drop = '"mesecons_microcontroller:microcontroller0000" 1', selection_box = { type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, -0.35, 0.5}, + fixed = { -8/16, -8/16, -8/16, 8/16, -4/16, 8/16 }, }, node_box = { type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, -0.35, 0.5}, + fixed = { + { -8/16, -8/16, -8/16, 8/16, -6/16, 8/16 }, -- bottom slab + { -5/16, -6/16, -5/16, 5/16, -5/16, 5/16 }, -- circuit board + { -3/16, -5/16, -3/16, 3/16, -4/16, 3/16 }, -- IC + } }, on_construct = function(pos) local meta = minetest.env:get_meta(pos) @@ -25,6 +44,7 @@ minetest.register_node("mesecons_microcontroller:microcontroller", { "field[0.256,0.5;8,1;code;Code:;]".. "button_exit[3,0.5;2,2;program;Program]") meta:set_string("infotext", "Unprogrammed Microcontroller") + meta:set_int("heat", 0) 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) @@ -37,14 +57,26 @@ minetest.register_node("mesecons_microcontroller:microcontroller", { meta:set_string("formspec", "size[8,2]".. "field[0.256,0.5;8,1;code;Code:;"..fields.code.."]".. "button_exit[3,0.5;2,2;program;Program]") - reset_yc (pos) + meta:set_int("heat", 0) + yc_reset (pos) update_yc(pos) end - end + end, }) +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) +mesecon:add_receptor_node(nodename, rules) +end +end +end +end minetest.register_craft({ - output = 'craft "mesecons_microcontroller:microcontroller" 2', + output = 'craft "mesecons_microcontroller:microcontroller0000" 2', recipe = { {'mesecons_materials:silicon', 'mesecons_materials:silicon', 'mesecons:mesecon_off'}, {'mesecons_materials:silicon', 'mesecons_materials:silicon', 'mesecons:mesecon_off'}, @@ -52,11 +84,8 @@ minetest.register_craft({ } }) -function reset_yc(pos) - mesecon:receptor_off(pos, mesecon:get_rules("microcontrollerA")) - mesecon:receptor_off(pos, mesecon:get_rules("microcontrollerB")) - mesecon:receptor_off(pos, mesecon:get_rules("microcontrollerC")) - mesecon:receptor_off(pos, mesecon:get_rules("microcontrollerD")) +function yc_reset(pos) + yc_action(pos, {a=false, b=false, c=false, d=false}) local meta = minetest.env:get_meta(pos) local r = "" for i=1, EEPROM_SIZE+1 do r=r.."0" end --Generate a string with EEPROM_SIZE*"0" @@ -65,19 +94,43 @@ end function update_yc(pos) local meta = minetest.env:get_meta(pos) + 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") + end + local code = meta:get_string("code") + code = yc_code_remove_commentary(code) code = string.gsub(code, " ", "") --Remove all spaces code = string.gsub(code, " ", "") --Remove all tabs if parse_yccode(code, pos) == nil then meta:set_string("infotext", "Code not valid!") else - meta:set_string("infotext", "Programmed Microcontroller") + meta:set_string("infotext", "Working Microcontroller") end + timer = minetest.env:get_node_timer(pos) --action places a new node! + timer:start(0.5) +end + + +--Code Parsing +function yc_code_remove_commentary(code) + for i = 1, #code do + if code:sub(i, i) == ":" then + return code:sub(1, i-1) + end + end + return code end function parse_yccode(code, pos) local endi = 1 - local L = yc_get_portstates(pos) + local Lreal = yc_get_real_portstates(pos) + local Lvirtual = yc_get_virtual_portstates(pos) + if Lvirtual == nil then return nil end local c local eeprom = minetest.env:get_meta(pos):get_string("eeprom") while true do @@ -85,9 +138,9 @@ function parse_yccode(code, pos) if command == nil then return nil end if command == true then break end if command == "if" then - r, endi = yc_command_if(code, endi, L, eeprom) + r, endi = yc_command_if(code, endi, yc_merge_portstates(Lreal, Lvirtual), eeprom) if r == nil then return nil end - if r == true then -- nothing + if r == true then -- nothing elseif r == false then endi = yc_skip_to_endif(code, endi) if endi == nil then return nil end @@ -97,20 +150,22 @@ function parse_yccode(code, pos) if params == nil then return nil end end if command == "on" then - L = yc_command_on (params, L) + L = yc_command_on (params, Lvirtual) elseif command == "off" then - L = yc_command_off(params, L) + L = yc_command_off(params, Lvirtual) elseif command == "sbi" then - eeprom = yc_command_sbi (params, eeprom) + new_eeprom = yc_command_sbi (params, eeprom, yc_merge_portstates(Lreal, Lvirtual)) + if new_eeprom == nil then return nil + else eeprom = new_eeprom end elseif command == "if" then --nothing else return nil end - if L == nil then return nil end + if Lvirtual == nil then return nil end if eeprom == nil then return nil else minetest.env:get_meta(pos):set_string("eeprom", eeprom) end end - yc_action(pos, L) + yc_action(pos, Lvirtual) return true end @@ -154,15 +209,15 @@ function parse_get_params(code, starti) return nil, nil end -function yc_parse_get_eeprom_params(code, starti) +function yc_parse_get_eeprom_param(cond, starti) i = starti s = nil - local params = {} + local addr while s ~= "" do - s = string.sub(code, i, i) - if s == ">" then - table.insert(params, string.sub(code, starti, i-1)) -- i: ) i+1 after ) - return params, i + 1 + 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 end if s == "," then return nil, nil end i = i + 1 @@ -170,6 +225,20 @@ function yc_parse_get_eeprom_params(code, starti) return nil, nil end +function yc_skip_to_endif(code, starti) + local i = starti + local s = false + while s ~= nil and s~= "" do + s = code:sub(i, i) + if s == ";" then + return i + 1 + end + i = i + 1 + end + return nil +end + +--Commands function yc_command_on(params, L) local rules = {} for i, port in ipairs(params) do @@ -186,13 +255,14 @@ function yc_command_off(params, L) return L end -function yc_command_sbi(params, eeprom) - if params[1]==nil or params[2]==nil or params[3] ~=nil or tonumber(params[1])==nil or tonumber(params[2])==nil then return nil end - if tonumber(params[1])>EEPROM_SIZE or tonumber(params[1])<1 or (tonumber(params[2])~=1 and tonumber(params[2]~=0)) then return nil end +function yc_command_sbi(params, eeprom, L) + if params[1]==nil or params[2]==nil or params[3] ~=nil or tonumber(params[1])==nil then return nil end + local status = yc_command_parsecondition(params[2], L, eeprom) + if tonumber(params[1])>EEPROM_SIZE or tonumber(params[1])<1 or (status ~= "0" and status ~= "1") then return nil end new_eeprom = ""; for i=1, #eeprom do if tonumber(params[1])==i then - new_eeprom = new_eeprom..params[2] + new_eeprom = new_eeprom..status else new_eeprom = new_eeprom..eeprom:sub(i, i) end @@ -200,18 +270,21 @@ function yc_command_sbi(params, eeprom) return new_eeprom end +--If function yc_command_if(code, starti, L, eeprom) local cond, endi = yc_command_if_getcondition(code, starti) if cond == nil then return nil end - cond = yc_command_if_parsecondition(cond, L, eeprom) + cond = yc_command_parsecondition(cond, L, eeprom) if cond == "0" then result = false elseif cond == "1" then result = true else result = nil end + if result == nil then end return result, endi --endi from local cond, endi = yc_command_if_getcondition(code, starti) end +--Condition parsing function yc_command_if_getcondition(code, starti) i = starti s = nil @@ -236,22 +309,20 @@ function yc_command_if_getcondition(code, starti) return nil, nil end -function yc_command_if_parsecondition(cond, L, eeprom) - cond = string.gsub(cond, "A", tostring(L.a and 1 or 0)) +function yc_command_parsecondition(cond, L, eeprom) + cond = string.gsub(cond, "A", tonumber(L.a and 1 or 0)) 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)) - cond = string.gsub(cond, "!0", "1") - cond = string.gsub(cond, "!1", "0") local i = 1 local l = string.len(cond) while i<=l do local s = cond:sub(i,i) - if s == "<" then - params, endi = yc_parse_get_eeprom_params(cond, i+1) - buf = yc_eeprom_read(tonumber(params[1]), eeprom) + if s == "#" then + addr, endi = yc_parse_get_eeprom_param(cond, i+1) + buf = yc_eeprom_read(tonumber(addr), eeprom) if buf == nil then return nil end local call = cond:sub(i, endi-1) cond = string.gsub(cond, call, buf) @@ -261,6 +332,9 @@ function yc_command_if_parsecondition(cond, L, eeprom) i = i + 1 end + cond = string.gsub(cond, "!0", "1") + cond = string.gsub(cond, "!1", "0") + local i = 2 local l = string.len(cond) while i<=l do @@ -269,6 +343,7 @@ function yc_command_if_parsecondition(cond, L, eeprom) local a = tonumber(cond:sub(i+1, i+1)) if cond:sub(i+1, i+1) == nil then break end if s == "=" then + if a==nil then return nil end if a == b then buf = "1" end if a ~= b then buf = "0" end cond = string.gsub(cond, b..s..a, buf) @@ -286,6 +361,7 @@ function yc_command_if_parsecondition(cond, L, eeprom) local a = tonumber(cond:sub(i+1, i+1)) if cond:sub(i+1, i+1) == nil then break end if s == "&" then + if a==nil then return nil end local buf = ((a==1) and (b==1)) if buf == true then buf = "1" end if buf == false then buf = "0" end @@ -294,6 +370,7 @@ function yc_command_if_parsecondition(cond, L, eeprom) l = string.len(cond) end if s == "|" then + if a==nil then return nil end local buf = ((a == 1) or (b == 1)) if buf == true then buf = "1" end if buf == false then buf = "0" end @@ -302,6 +379,7 @@ function yc_command_if_parsecondition(cond, L, eeprom) l = string.len(cond) end if s == "~" then + if a==nil then return nil end 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 @@ -311,47 +389,65 @@ function yc_command_if_parsecondition(cond, L, eeprom) end i = i + 1 end + return cond end +--Virtual-Hardware functions function yc_eeprom_read(number, eeprom) - if params == nil then return nil, nil end - value = eeprom:sub(params[1], number) + if number == nil then return nil, nil end + value = eeprom:sub(number, number) if value == nil then return nil, nil end return value, endi end -function yc_get_port_rules(port) - local rules = nil - if port == "A" then - rules = mesecon:get_rules("microcontrollerA") - elseif port == "B" then - rules = mesecon:get_rules("microcontrollerB") - elseif port == "C" then - rules = mesecon:get_rules("microcontrollerC") - elseif port == "D" then - rules = mesecon:get_rules("microcontrollerD") - end - return rules -end +--Real I/O functions +function yc_action(pos, L) --L-->Lvirtual + Lv = yc_get_virtual_portstates(pos) + local meta = minetest.env:get_meta(pos) + local code = meta:get_string("code") + local heat = meta:get_int("heat") + 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) + meta:set_int("heat", heat) + meta:set_string("eeprom", eeprom) + meta:set_string("infotext", infotext) + meta:set_string("formspec", formspec) -function yc_action(pos, L) - yc_action_setport("A", L.a, pos) - yc_action_setport("B", L.b, pos) - yc_action_setport("C", L.c, pos) - yc_action_setport("D", L.d, pos) + yc_action_setports(pos, L, Lv) end -function yc_action_setport(port, state, pos) - local rules = mesecon:get_rules("microcontroller"..port) - if state == false then - if mesecon:is_power_on({x=pos.x+rules[1].x, y=pos.y+rules[1].y, z=pos.z+rules[1].z}) then - mesecon:turnoff(pos, rules[1].x, rules[1].y, rules[1].z, false) - end - elseif state == true then - if mesecon:is_power_off({x=pos.x+rules[1].x, y=pos.y+rules[1].y, z=pos.z+rules[1].z}) then - mesecon:turnon(pos, rules[1].x, rules[1].y, rules[1].z, false) - end +function yc_action_setports(pos, L, Lv) + local name = "mesecons_microcontroller:microcontroller" + local rules + if Lv.a ~= L.a then + rules = mesecon:get_rules(name.."0001") + if L.a == true then mesecon:receptor_on(pos, rules) + else mesecon:receptor_off(pos, rules) end + end + if Lv.b ~= L.b then + rules = mesecon:get_rules(name.."0010") + if L.b == true then mesecon:receptor_on(pos, rules) + else mesecon:receptor_off(pos, rules) end + end + if Lv.c ~= L.c then + rules = mesecon:get_rules(name.."0100") + if L.c == true then mesecon:receptor_on(pos, rules) + else mesecon:receptor_off(pos, rules) end + end + if Lv.d ~= L.d then + rules = mesecon:get_rules(name.."1000") + if L.d == true then mesecon:receptor_on(pos, rules) + else mesecon:receptor_off(pos, rules) end end end @@ -364,12 +460,12 @@ function yc_set_portstate(port, state, L) return L end -function yc_get_portstates(pos) - rulesA = mesecon:get_rules("microcontrollerA") - rulesB = mesecon:get_rules("microcontrollerB") - rulesC = mesecon:get_rules("microcontrollerC") - rulesD = mesecon:get_rules("microcontrollerD") - local L = { +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") + L = { 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}), @@ -378,30 +474,68 @@ function yc_get_portstates(pos) return L end -function yc_skip_to_endif(code, starti) - local i = starti - local s = false - while s ~= nil and s~= "" do - s = code:sub(i, i) - if s == ";" then - return i + 1 - end - i = i + 1 +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 + + Lvirtual = {a=false, b=false, c=false, d=false} + 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 + if name:sub(a+3, a+3) == "1" then Lvirtual.a = true end + return Lvirtual +end + +function yc_merge_portstates(Lreal, Lvirtual) + 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 +end + +--"Overheat" protection +function yc_heat(meta) + h = meta:get_int("heat") + if h ~= nil then + meta:set_int("heat", h + 1) + end +end + +function yc_cool(meta) + h = meta:get_int("heat") + if h ~= nil then + meta:set_int("heat", h - 1) end - return nil +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); end mesecon:register_on_signal_change(function(pos, node) - if node.name == "mesecons_microcontroller:microcontroller" then - minetest.after(0.5, update_yc, pos) + if string.find(node.name, "mesecons_microcontroller:microcontroller")~=nil then + update_yc(pos) end end) - -mesecon:add_rules("microcontrollerA", {{x = -1, y = 0, z = 0}}) -mesecon:add_rules("microcontrollerB", {{x = 0, y = 0, z = 1}}) -mesecon:add_rules("microcontrollerC", {{x = 1, y = 0, z = 0}}) -mesecon:add_rules("microcontrollerD", {{x = 0, y = 0, z = -1}}) -mesecon:add_rules("microcontroller_default", {}) -mesecon:add_receptor_node("mesecons_microcontroller:microcontroller", mesecon:get_rules("microcontroller_default")) -mesecon:add_receptor_node("mesecons_microcontroller:microcontroller", mesecon:get_rules("microcontroller_default")) +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) + end +end) |