diff options
author | Jeija <norrepli@gmail.com> | 2012-08-08 13:26:32 +0200 |
---|---|---|
committer | Jeija <norrepli@gmail.com> | 2012-08-08 13:26:32 +0200 |
commit | ef740353ef798f40fef8b3b512ce0994637cc5c1 (patch) | |
tree | 8ea41e35e27a30d738e1c7f8f526e79584ff62df /mesecons_microcontroller | |
parent | 10fe94dea7829b1b7083d42e2827643f6cabf188 (diff) | |
download | mesecons-ef740353ef798f40fef8b3b512ce0994637cc5c1.tar mesecons-ef740353ef798f40fef8b3b512ce0994637cc5c1.tar.gz mesecons-ef740353ef798f40fef8b3b512ce0994637cc5c1.tar.bz2 mesecons-ef740353ef798f40fef8b3b512ce0994637cc5c1.tar.xz mesecons-ef740353ef798f40fef8b3b512ce0994637cc5c1.zip |
Add first experimental version of a (programmable) microcontroller
Diffstat (limited to 'mesecons_microcontroller')
-rw-r--r-- | mesecons_microcontroller/depends.txt | 1 | ||||
-rw-r--r-- | mesecons_microcontroller/init.lua | 321 |
2 files changed, 322 insertions, 0 deletions
diff --git a/mesecons_microcontroller/depends.txt b/mesecons_microcontroller/depends.txt new file mode 100644 index 0000000..acaa924 --- /dev/null +++ b/mesecons_microcontroller/depends.txt @@ -0,0 +1 @@ +mesecons diff --git a/mesecons_microcontroller/init.lua b/mesecons_microcontroller/init.lua new file mode 100644 index 0000000..d594be5 --- /dev/null +++ b/mesecons_microcontroller/init.lua @@ -0,0 +1,321 @@ +minetest.register_node("mesecons_microcontroller:microcontroller", { + description = "Microcontroller", + drawtype = "nodebox", + tiles = {"jeija_ic.png"}, + inventory_image = {"jeija_ic.png"}, + sunlight_propagates = true, + paramtype = "light", + walkable = true, + groups = {dig_immediate=2}, + material = minetest.digprop_constanttime(1.0), + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -0.35, 0.5}, + }, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -0.35, 0.5}, + }, + on_construct = function(pos) + local meta = minetest.env:get_meta(pos) + meta:set_string("code", "") + meta:set_string("formspec", "size[8,2]".. + "field[0.256,0.5;8,1;code;Code:;]".. + "button_exit[3,0.5;2,2;program;Program]") + meta:set_string("infotext", "Unprogrammed Microcontroller") + end, + on_receive_fields = function(pos, formanme, fields, sender) + if fields.program then + local meta = minetest.env:get_meta(pos) + meta:set_string("infotext", "Programmed Microcontroller") + meta:set_string("code", fields.code) + 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) + update_yc(pos) + end + end +}) + +minetest.register_craft({ + output = 'craft "mesecons_microcontroller:microcontroller" 2', + recipe = { + {'mesecons_materials:silicon', 'mesecons_materials:silicon', 'mesecons:mesecon_off'}, + {'mesecons_materials:silicon', 'mesecons_materials:silicon', 'mesecons:mesecon_off'}, + {'mesecons:mesecon_off', 'mesecons:mesecon_off', ''}, + } +}) + +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")) +end + +function update_yc(pos) + local meta = minetest.env:get_meta(pos) + local code = meta:get_string("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") + end +end + +function parse_yccode(code, pos) + local endi = 1 + local L = yc_get_portstates(pos) + local c + while true do + command, endi = parse_get_command(code, endi) + 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) + if r == nil then return nil end + if r == true then -- nothing + elseif r == false then + endi = yc_skip_to_endif(code, endi) + 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 + L = yc_command_on (params, L) + elseif command == "off" then + L = yc_command_off(params, L) + elseif command == "if" then --nothing + else + return nil + end + if L == nil then return nil end + end + yc_action(pos, L) + return true +end + +function parse_get_command(code, starti) + i = starti + s = nil + while s ~= "" do + s = string.sub(code, i, i) + if s == ";" and starti == i then + starti = starti + 1 + i = starti + s = string.sub(code, i, i) + end + if s == "(" then + return string.sub(code, starti, i-1), i + 1 -- i: ( i+1 after ( + end + i = i + 1 + end + 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 = {} + 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 + end + if s == "," then + 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 + +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 + +function yc_command_if(code, starti, L) + local cond, endi = yc_command_if_getcondition(code, starti) + if cond == nil then return nil end + cond = string.gsub(cond, "A", tostring(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 = 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)) + if a == nil then break end + if s == "&" then + 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 + 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 + 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 + + 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)) + if a == nil then break end + if s == "=" then + cond = string.gsub(cond, b..s..a, tostring(a == b)) + i = 1 + l = string.len(cond) + end + i = i + 1 + end + + if cond == "0" then result = false + elseif cond == "1" then result = true + else result = nil end + return result, endi --endi from local cond, endi = yc_command_if_getcondition(code, starti) +end + +function yc_command_if_getcondition(code, starti) + i = starti + s = nil + while s ~= "" do + s = string.sub(code, i, i) + if s == ")" then + return string.sub(code, starti, i-1), i + 1 -- i: (; i+1 after (; + end + i = i + 1 + end + return nil, nil +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 + +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) +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 + 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 + +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 = { + 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 + +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 + +mesecon:register_on_signal_change(function(pos, node) + if node.name == "mesecons_microcontroller:microcontroller" then + minetest.after(0.5, 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")) |