From ef740353ef798f40fef8b3b512ce0994637cc5c1 Mon Sep 17 00:00:00 2001 From: Jeija Date: Wed, 8 Aug 2012 13:26:32 +0200 Subject: [PATCH] Add first experimental version of a (programmable) microcontroller --- mesecons/internal_api.lua | 2 +- mesecons_materials/init.lua | 16 -- mesecons_microcontroller/depends.txt | 1 + mesecons_microcontroller/init.lua | 321 ++++++++++++++++++++++++ mesecons_textures/textures/jeija_ic.png | Bin 302 -> 462 bytes 5 files changed, 323 insertions(+), 17 deletions(-) create mode 100644 mesecons_microcontroller/depends.txt create mode 100644 mesecons_microcontroller/init.lua diff --git a/mesecons/internal_api.lua b/mesecons/internal_api.lua index f2f2ace..ef0c3df 100644 --- a/mesecons/internal_api.lua +++ b/mesecons/internal_api.lua @@ -227,7 +227,7 @@ end function mesecon:is_power_on(pos) local node = minetest.env:get_node(pos) - if node.name == "mesecons:mesecon_on" or mesecon:is_receptor_node(node.name) then + if mesecon:is_conductor_on(node.name) or mesecon:is_receptor_node(node.name) then return true end return false diff --git a/mesecons_materials/init.lua b/mesecons_materials/init.lua index d16642d..64b9ad8 100644 --- a/mesecons_materials/init.lua +++ b/mesecons_materials/init.lua @@ -13,22 +13,6 @@ minetest.register_craft({ } }) --- IC -minetest.register_craftitem("mesecons_materials:ic", { - image = "jeija_ic.png", - on_place_on_ground = minetest.craftitem_place_item, - description="IC", -}) - -minetest.register_craft({ - output = 'craft "mesecons_materials:ic" 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', ''}, - } -}) - -- Silicon minetest.register_craftitem("mesecons_materials:silicon", { image = "jeija_silicon.png", 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")) diff --git a/mesecons_textures/textures/jeija_ic.png b/mesecons_textures/textures/jeija_ic.png index b46daa24f66e35580426f629873c4fa7a54b4a4d..77b551ee6f09c2e0f34936729ef7aa19369c76d5 100644 GIT binary patch delta 408 zcmV;J0cZZM0?q@FBo78+OGiWi{{a60|De66laVeTe+UNW0VOA;=+j0wNJo?chV>^aRwGZ-09mGMPrO0w{C`k5r+`E zIX7)@+jCE^3#!jnR*^>He=cDZ|^v}yr6r1!|8d8 zJo8`Pf5sFFMF5;RL^{p{%jmag$*jC2VpgSXW@w ziwT=2%$&>m26isRD{6 z?F_^BG&{k582;P!?=+A7ewIS*xXGv&Z%koXeg)YNL)$1ZN5)(g22qqsx!B%S)4ghy zQn^SFcvLDC%H~1VQk94E24SB=0Fg5Ci~JcXyIyS@=sy zES;d!zT)NejZXWD*Y}SU=d1ku)X(@=@{;eoHU0wg+VGamkvTsA0000wo@nK}rc>n1NYBKr#r4 z{_zp>>Fm=>-GbY@hj&2`;Y0)xjwx^#gjjF3)RS5tPSq_K4u<3^Fr$=0uaqx;H@of6qm0I5-CSR2U;eu6)#bVN<$-_Z Z4Jb)w;&*=oF$@3z002ovPDHLkV1feNa2Nmp