From 07d074075c82dd762fa9d6d3b1b5a466a77f177b Mon Sep 17 00:00:00 2001 From: sfan5 Date: Sat, 28 Jan 2017 11:33:13 +0100 Subject: [PATCH] FPGAs (#315) --- documentation.json | 2 + .../textures/jeija_microcontroller_LED_A.png | Bin .../textures/jeija_microcontroller_LED_B.png | Bin .../textures/jeija_microcontroller_LED_C.png | Bin .../textures/jeija_microcontroller_LED_D.png | Bin mesecons_fpga/depends.txt | 1 + mesecons_fpga/doc/fpga/description.html | 5 + mesecons_fpga/doc/fpga/preview.png | Bin 0 -> 21329 bytes mesecons_fpga/doc/fpga/recipe.png | Bin 0 -> 3210 bytes mesecons_fpga/doc/programmer/description.html | 3 + mesecons_fpga/doc/programmer/preview.png | Bin 0 -> 598 bytes mesecons_fpga/doc/programmer/recipe.png | Bin 0 -> 1908 bytes mesecons_fpga/init.lua | 374 ++++++++++++++++++ mesecons_fpga/logic.lua | 210 ++++++++++ .../textures/jeija_fpga_programmer.png | Bin 0 -> 311 bytes mesecons_fpga/textures/jeija_fpga_sides.png | Bin 0 -> 536 bytes mesecons_fpga/textures/jeija_fpga_top.png | Bin 0 -> 816 bytes mesecons_fpga/tool.lua | 62 +++ 18 files changed, 657 insertions(+) rename {mesecons_microcontroller => mesecons}/textures/jeija_microcontroller_LED_A.png (100%) rename {mesecons_microcontroller => mesecons}/textures/jeija_microcontroller_LED_B.png (100%) rename {mesecons_microcontroller => mesecons}/textures/jeija_microcontroller_LED_C.png (100%) rename {mesecons_microcontroller => mesecons}/textures/jeija_microcontroller_LED_D.png (100%) create mode 100644 mesecons_fpga/depends.txt create mode 100644 mesecons_fpga/doc/fpga/description.html create mode 100644 mesecons_fpga/doc/fpga/preview.png create mode 100644 mesecons_fpga/doc/fpga/recipe.png create mode 100644 mesecons_fpga/doc/programmer/description.html create mode 100644 mesecons_fpga/doc/programmer/preview.png create mode 100644 mesecons_fpga/doc/programmer/recipe.png create mode 100644 mesecons_fpga/init.lua create mode 100644 mesecons_fpga/logic.lua create mode 100644 mesecons_fpga/textures/jeija_fpga_programmer.png create mode 100644 mesecons_fpga/textures/jeija_fpga_sides.png create mode 100644 mesecons_fpga/textures/jeija_fpga_top.png create mode 100644 mesecons_fpga/tool.lua diff --git a/documentation.json b/documentation.json index 711f7d2..f318501 100644 --- a/documentation.json +++ b/documentation.json @@ -42,6 +42,8 @@ }, "Logic" : { "Luacontroller" : "mesecons_luacontroller/doc/luacontroller", + "FPGA" : "mesecons_fpga/doc/fpga", + "FPGA Programmer" : "mesecons_fpga/doc/programmer", "Torch" : "mesecons_torch/doc/torch", "Delayer" : "mesecons_delayer/doc/delayer", "Gates" : { diff --git a/mesecons_microcontroller/textures/jeija_microcontroller_LED_A.png b/mesecons/textures/jeija_microcontroller_LED_A.png similarity index 100% rename from mesecons_microcontroller/textures/jeija_microcontroller_LED_A.png rename to mesecons/textures/jeija_microcontroller_LED_A.png diff --git a/mesecons_microcontroller/textures/jeija_microcontroller_LED_B.png b/mesecons/textures/jeija_microcontroller_LED_B.png similarity index 100% rename from mesecons_microcontroller/textures/jeija_microcontroller_LED_B.png rename to mesecons/textures/jeija_microcontroller_LED_B.png diff --git a/mesecons_microcontroller/textures/jeija_microcontroller_LED_C.png b/mesecons/textures/jeija_microcontroller_LED_C.png similarity index 100% rename from mesecons_microcontroller/textures/jeija_microcontroller_LED_C.png rename to mesecons/textures/jeija_microcontroller_LED_C.png diff --git a/mesecons_microcontroller/textures/jeija_microcontroller_LED_D.png b/mesecons/textures/jeija_microcontroller_LED_D.png similarity index 100% rename from mesecons_microcontroller/textures/jeija_microcontroller_LED_D.png rename to mesecons/textures/jeija_microcontroller_LED_D.png diff --git a/mesecons_fpga/depends.txt b/mesecons_fpga/depends.txt new file mode 100644 index 0000000..acaa924 --- /dev/null +++ b/mesecons_fpga/depends.txt @@ -0,0 +1 @@ +mesecons diff --git a/mesecons_fpga/doc/fpga/description.html b/mesecons_fpga/doc/fpga/description.html new file mode 100644 index 0000000..be6bd65 --- /dev/null +++ b/mesecons_fpga/doc/fpga/description.html @@ -0,0 +1,5 @@ +FPGAs can be used to chain multiple logic gates together in a compact manner. +They come with 4 I/O ports and 10 internal registers, +which can then be connected with eachother to form logic circuits.
+Supported gate types: AND, OR, NOT, XOR, NAND, XNOR, Buffer (=)
+I/O ports: A B C D; Registers: numbered 0 to 9 diff --git a/mesecons_fpga/doc/fpga/preview.png b/mesecons_fpga/doc/fpga/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..c1563211c914cc71d20fb936604c94d2820805c4 GIT binary patch literal 21329 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∋wfdZFXofW3b%J%J>f$+S`8f~` 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 Z5o^{f?o~DW3bHSO3pN<*MoV1E{{eN^P=Wve literal 0 HcmV?d00001 diff --git a/mesecons_fpga/doc/fpga/recipe.png b/mesecons_fpga/doc/fpga/recipe.png new file mode 100644 index 0000000000000000000000000000000000000000..1140bfac90b3b46f7de1d97fefdb7fafd1491f75 GIT binary patch literal 3210 zcmZve2{@G7AIIMr%P4Dp-tUREFwoEQuM=Jd7kvPLp6%#?01vY`!AY2}p{Xv60^wpp!YXeQgaH8h$il>0 z7XpDmp-`$LXsD^FX=rF@L16R@Ol*uytfx-H*;qMFvvHn2!*zxoeum>L2Ny3V2%HxV zhx365A^G|F1q9CvoR<_55)u{`K97(-kCYP;5fKFuM~aHeh)T$bff(?K8So=O#HA4i z{Nf-|XmKNcabp1_h=~Bw6l~`tK)~J%Y=RQzf)W;jk{~D*NpNsMP|{LR3Pe^xN={Kq z9wP;sRzlJsvKVQUinO(m42Ybfj2uQr9wQ4PuOh2}kyTKYwH1~FL93uZ&=?e26@^wq zq1ENl%JPb;3d$M^7!5Q=OG#N(Sy^3KRa;q2S6NLDqpFKh*Hr=0G*Q*iRns<7*VI$j zGStvE(9$!|(bd;AFx3Y!vM?~VFgCL?F|jZMv9PhQw!2`1wY0)oTHD*$VeLV%j#w<# z(Z$Wp9dL8Ud4OE^#N+Y4zP`77{X#-QLPJ9d1PFluC4@u63DEFxNH{o%fJB5tBfvfa z>?0x~p^=f0$S6ouRMee2ccNo}`w2jNB9QO^NK67ABm+r*0Ldx9A0VkfN*a)w4y1u( z0O=2b46tQ_#QU2ju1hc?CdzAy7~R6cz)8B|uRLP+SU>fs_M}DuAl0 zs_N?Mnwpy0+S)ZEOTlCMG8*r>3T6W@hH+=NA?hmY0`TR#sM5 zSJ&3o*4NiJHa5O}`?kHky|c5kySux;zkhIWaCmsAu=_0stYgR(V||^s&mcKGV4=Gi z>S$W~zy6$k>AHg(7lBXYc2<#TcXR5vskL;MPz+1qJpoB4){ivFBpmdMrWRdP4-NdI zs3ljSfh)HO{8fw7>!_WKMvaJhYiK?Cr4Y#jzk3QgdH=78TCF5`@4e@}yTPobW-g@% zpIm+fNLs#9`zt7`Z_V$`=6+Uk7{Geq!czsLgPZ%-f_zum$b3%IKK_AyrU_J) zR4TRaNX7WvK@EbZ=!{VuQI}lcywX6?`g9iYp@)Z^F^(vYba8K_9gS&}8l!Tz2VJo< z8kdMyrC&1pW!o}x05?x<3kL$=h9egP%7FFrYrA?jy#Q){;WKZ@m&p$S;3u&mnZP#JW zJC1-tUX=eWvXO175H@<`1Wek*4tx2=z;RGrGHch*Af`WqP!x0=v)4Ale2&&m)!Zwi zjK^o@wALDM(MeAc6P_`l_8`}bkJ33x06f%j9@ln!6Bf1~@|IATS+W&#`G+VgIqdNy@yCkg7MJ> zRDnK;#nn|_b=FX)@{8)JhM{wVt6m(3i)VKDt@7Iu=+(M&8Up*KjG5#l`6=Ks@a7CJ z{`dpM+`C2KB2)~qBA5>$iZ39cum+h^h$bZIUE% zqFs|VuQZMaQw-_$uS_g^1tYBOcB!*6T(9Lx)Dv$MyQWo2LXes{-BCpSctpxA!jDCU zI;!hs)%cwXmS($~oqdquZ>Yd6fUGOIU(1v)j%T!|!&jJFg!2J?6pf8Zv=eVqH=b6@ zZz@V@j(KpE(&fbM!RUY+@Wh#=a(~LVCx-~&%KUErmLGtcZxk6rc_CCh51zkUdA<-` zjpnOBBlLd{xMPYJ$hyP$!O#VSR(1<5FuPyM#kv60ebR1{UyG8e6!whYY?7^ znyRNgzn3Zb>=OfNy8)~A;yEl)8m64aE}6_yVl+b9`~Hl5mb+a&WP&!zEXlZ21acX= zV~0hk)@6>sj~r8};1FB8t@h;kM5a~0b9L5u2TMn{)}4`0ca)85)Uzc6po*dM1|koc zCA(0r{k6@H@L00Tw9z5!q8!ixOOJfdUCX@aNyvrlK^A=gb3ZP*K!Uq<*<(vFzbClZ zn=UQHz!v8i!zoGv@FRn+-e$F)?lNExG={9^bO~8E(bY6QGLegJ!4+1tdYhYnSNlF~ zSmlhz%{bL>#(uz9Pu}4ED1SM!r4cIigfl0I$G+{$Y&P`{_U(pBgGPAVx(s7N5R)T~ zf6!~!jdRYOe-=NTU1|W(kYM)3CP^xNW|q?NkG(gz)*?4=IHnuLiIp`xe$PC~pW!eZ zPAWUEO!C?nsWdTuM|5FZ$YGAVcCuRr_(I#K7dUl&X z#i%i^$HiaKW0tP0g#3}TYs)yz>^vVfs6V0Jml`KqCDc1}PKpXi4A=GX=a|{%sgEzO zg5SqJ39LzR+xC*HqxtdlSrVCtN$<_8@!T=zggyZ}dNXeLn=@?hm1;^iA4HSVTCw&{ z?bY=BsJTnUy}^C&$j^&Ord!DUY^u>`>-pFCPJ|gvgr00nosSmKXfD3yD`EO)5e_dO*-nD%&wuiMQ*T9sQaGKH}It85{17=lZ{KY9nkRD#Hv|Sy0!w-M3Tfj1LE({#H=Qo z1Q~xRK)V*Zic7RPm(%U@G3U%;Qb0LvEvD=|vJ%xg)TdvlC0QdRd0rfvlevl>!Y@X8 zc^A_ajRIeb65`l5g6-8*Ut zFvsDrgB<;Z4MV3tX^1*;~vq-MPKNZ=-+HXk&5Tndss0MYyBXJEgdQ zC@6QqO}fEj;B)5Q+C_FF_%M(Bw68h#jnV6f`y6QyHJv;3Ua-yl{&F<^lM@7WvNE4@ce%3gVtmQUF0Ao`x4%vk?smXRpBtaUR7d9`Iq_x}k?SEA^Lwo4Yr^2MW%RSQPNrv+^L-FT+AU zQd%0$x8Gwe^{38jin1XK_RUDE1$Pjmlj%E8DLa-wrqqgdIwX94z}U(f`rrDnH1I{4X*7KjQ54Zt$B-%->r4#G{e+(r@qGIDScIhCO zzvZ|R{#bMF#OgnfDp5_kdK|UDIo9cCkdmK4ytoUhhy8Xtl#cEkczeA`FI=Cg`5XHp r25L?`S>FW)KLAMMN9w$lbx1|7*r^D6!zvHnzW_sBGo8m;P7(hB`L3i_ literal 0 HcmV?d00001 diff --git a/mesecons_fpga/doc/programmer/description.html b/mesecons_fpga/doc/programmer/description.html new file mode 100644 index 0000000..39e2374 --- /dev/null +++ b/mesecons_fpga/doc/programmer/description.html @@ -0,0 +1,3 @@ +The FPGA programmer can be used to copy gate configurations from one FPGA to another.
+Shift+Right-Click an FPGA to read its configuration and "remember" it. +Left-click (punch) FPGAs to write the saved configuration to them. diff --git a/mesecons_fpga/doc/programmer/preview.png b/mesecons_fpga/doc/programmer/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..7437d3968ac796be45bf0e2f4d6c5295f485b088 GIT binary patch literal 598 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fo`_;1OBOz`*0jz`!lcSgN~o zKTwdp#M9T6{UM{IAS3_OzuUF~h3o@-LR|m<{|{u!$jGRvsp;n513{3Aag=(X zhH{9yN~nfvq>lQE6)RS*T)Ar1s@1DkuUWHZ?b@~L)~(yHVZ(w;#URreOM?7@862M7 zNCR<_yxmoh;O%J@}*FuwEkY*@( zQ1GR(jaE(`{R^a0c#%TSFo~xjULI%2l)z4*}Q$iB}LSvt! literal 0 HcmV?d00001 diff --git a/mesecons_fpga/doc/programmer/recipe.png b/mesecons_fpga/doc/programmer/recipe.png new file mode 100644 index 0000000000000000000000000000000000000000..778ec5fc6232a39b20b8126fe1af83b0cc45ba3c GIT binary patch literal 1908 zcmd6nX;4#F6vtmeWf71yhRuMoBuapg5CU02@<~c5E-=^ zLBJUpR0xS^r7Qxq&#G;)*ito9HR!8tiCU1hV3f7j5!-(9bANO1yUV;Y_nbNB{FQMc zf%S5iwZg%Ag}t4li=%^+BhDGO(glZKg?A=6xe(mk+}r_P zWDgII)t)}9ef+(=yu7`=eE{nyK4cn^NF)J#$t2%Ek{@mD+O_Kdz7$_T0D}w=t?~2o z^9Ka6{o_3Y0My_BT1Wt$6_DUXp|U7J>_7l5B#_1mq_e01I-45Iq6Twl00x^TAqD{$ ztRMy_h`|kF@aPOCJ%kg?3=3w3F<9$EnH(mQ$K*sXxiFI($>P8)9?TAp;e^55hz-2( zNZ$IWun6J$NFg5N7sPm&}gN)p7WVxm_P$vY`U zk}AncBNHVONmkC*tsmxY+n)b%;cl4>Ba>lea;#j2mCG@5uqnrs%dzF)TaGQSz*baX zDioM==gzgYwY9gmtJUg`jt-4Rqt$9VJ3AK_7b8jzTY;2d-j5dWOJYa5<{)U<{wRL9 zxcJ_-5x`8cMd^%B6v9>*!1ydUZ=OY_QsP>CegNsU4S2`r6Q#CT~MR zH=?K4ygg(icd&C#^R{+xf~Bn_Sed$B!)GJao^u&f1-Buze0NSu*52ccreafK)q*qr zyl4(Tzp7QG81qb@e6i;$+Npc4q62fOMo}_ewEDrsbQOz^{$^pE)pvDex9fa&J2SFE z&@*k(Nc>T^%L}gac015B3x~{ah4&Op8H7E0|J^OG?FST_H0YMr{M!oPM#lAu5d;q_ zwcT4S*n?jzAi2oJ(41VP+Kb&6Z!}Z5k{=xIt!+~Uf($()v)Q3h8KvaL$Zu88)9i7!YIBF-#NwHn`pLOU!O%?W(;{6;@_yE-i}k{j(h1}tKTGg2PBb*57uDU>rKnUy z^Vqb2QSJ%Rvr6yEznr3V8O0RRLeC1Dhxx~DgK}u9yjjSe}9V~VrDy0D7j;9oOJ~@!_)o)efM^$GN+CtM^u*89%{Xj^W+cH z{!5GbdCxNL9qS(dfROWK#u85>I2p|(WXlyuD1BhkmCl?zOt*qI&uAjn>pl+GW5sG)d!@Rh~^kx`l_)QJgq%8Iau@+ zL;O-l;)vC|kZa5O7ma>3r=Lmp6_$M}I%*4;?0r=Z&_ZKfs?KvC!-iVLep zb%_L*bs#``raM<3yUm$*{_$PIb<&a2l>_)4)*9N(P9+6RR|sNbPF<7;L-Nq&O?gp0 zPmoPF&wfrHytjj?)*`vYQDeNPqWU{*W4^I7)*WPca<4)?(_n^7<5v7U4>@GUpjS_a z>$%3xwV$0ZJNTy8nr4MV#7*{Z%29EOn7)fuHut*?r3C${;mZ-Ac!&Z{T^bhZ3&<9~ zFN5-*>I^l8qs=AF1udw;B00000 literal 0 HcmV?d00001 diff --git a/mesecons_fpga/init.lua b/mesecons_fpga/init.lua new file mode 100644 index 0000000..03beafc --- /dev/null +++ b/mesecons_fpga/init.lua @@ -0,0 +1,374 @@ +local plg = {} +plg.rules = {} + +local lcore = dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/logic.lua") +dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/tool.lua")(plg) + + +plg.register_nodes = function(template) + -- each loop is for one of the 4 IO ports + for a = 0, 1 do + for b = 0, 1 do + for c = 0, 1 do + for d = 0, 1 do + local ndef = table.copy(template) + local nodename = "mesecons_fpga:fpga" + .. tostring(d) .. tostring(c) .. tostring(b) .. tostring(a) + + -- build top texture string + local texture = "jeija_fpga_top.png" + if a == 1 then texture = texture .. "^jeija_microcontroller_LED_A.png" end + if b == 1 then texture = texture .. "^jeija_microcontroller_LED_B.png" end + if c == 1 then texture = texture .. "^jeija_microcontroller_LED_C.png" end + if d == 1 then texture = texture .. "^jeija_microcontroller_LED_D.png" end + ndef.tiles[1] = texture + ndef.inventory_image = texture + + if (a + b + c + d) > 0 then + ndef.groups["not_in_creative_inventory"] = 1 + end + + -- interaction with mesecons (input / output) + local rules_out = {} + if a == 1 then table.insert(rules_out, {x = -1, y = 0, z = 0}) end + if b == 1 then table.insert(rules_out, {x = 0, y = 0, z = 1}) end + if c == 1 then table.insert(rules_out, {x = 1, y = 0, z = 0}) end + if d == 1 then table.insert(rules_out, {x = 0, y = 0, z = -1}) end + plg.rules[nodename] = rules_out + + local rules_in = {} + if a == 0 then table.insert(rules_in, {x = -1, y = 0, z = 0}) end + if b == 0 then table.insert(rules_in, {x = 0, y = 0, z = 1}) end + if c == 0 then table.insert(rules_in, {x = 1, y = 0, z = 0}) end + if d == 0 then table.insert(rules_in, {x = 0, y = 0, z = -1}) end + ndef.mesecons.effector.rules = rules_in + + if (a + b + c + d) > 0 then + ndef.mesecons.receptor = { + state = mesecon.state.on, + rules = rules_out, + } + end + + minetest.register_node(nodename, ndef) + end + end + end + end +end + +plg.register_nodes({ + description = "FPGA", + drawtype = "nodebox", + tiles = { + "", -- replaced later + "jeija_microcontroller_bottom.png", + "jeija_fpga_sides.png", + "jeija_fpga_sides.png", + "jeija_fpga_sides.png", + "jeija_fpga_sides.png" + }, + inventory_image = "", -- replaced later + sunlight_propagates = true, + paramtype = "light", + walkable = true, + groups = {dig_immediate = 2, mesecon = 3}, + drop = "mesecons_fpga:fpga0000", + selection_box = { + type = "fixed", + fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 }, + }, + node_box = { + type = "fixed", + fixed = { + { -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 + } + }, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local is = { {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} } + + meta:set_string("instr", lcore.serialize(is)) + meta:set_int("valid", 0) + meta:set_string("formspec", plg.to_formspec_string(is)) + meta:set_string("infotext", "FPGA") + end, + on_receive_fields = function(pos, formname, fields, sender) + if fields.program == nil then return end -- we only care when the user clicks "Program" + local meta = minetest.get_meta(pos) + local is = plg.from_formspec_fields(fields) + + meta:set_string("instr", lcore.serialize(is)) + plg.update_formspec(pos, is) + end, + sounds = default.node_sound_stone_defaults(), + mesecons = { + effector = { + rules = {}, -- replaced later + action_change = function(pos, node, rule, newstate) + plg.ports_changed(pos, rule, newstate) + plg.update(pos) + end + } + }, + after_dig_node = function(pos, node) + mesecon.receptor_off(pos, plg.rules[node.name]) + end, +}) + + +plg.to_formspec_string = function(is) + local function dropdown_op(x, y, name, val) + local s = "dropdown[" .. tostring(x) .. "," .. tostring(y) .. ";" + .. "0.75,0.5;" .. name .. ";" -- the height seems to be ignored? + s = s .. " ,A,B,C,D,0,1,2,3,4,5,6,7,8,9;" + if val == nil then + s = s .. "0" -- actually selects no field at all + elseif val.type == "io" then + local mapping = { + ["A"] = 1, + ["B"] = 2, + ["C"] = 3, + ["D"] = 4, + } + s = s .. tostring(1 + mapping[val.port]) + else -- "reg" + s = s .. tostring(6 + val.n) + end + return s .. "]" + end + local function dropdown_action(x, y, name, val) + local s = "dropdown[" .. tostring(x) .. "," .. tostring(y) .. ";" + .. "1.125,0.5;" .. name .. ";" -- the height seems to be ignored? + s = s .. " , AND, OR, NOT, XOR,NAND, =,XNOR;" + if val == nil then + return s .. "0]" -- actually selects no field at all + end + local mapping = { + ["and"] = 1, + ["or"] = 2, + ["not"] = 3, + ["xor"] = 4, + ["nand"] = 5, + ["buf"] = 6, + ["xnor"] = 7, + } + return s .. tostring(1 + mapping[val]) .. "]" + end + local s = "size[9,9]".. + "label[3.4,-0.15;FPGA gate configuration]".. + "button_exit[7,7.5;2,2.5;program;Program]".. + "box[4.2,0.5;0.03,7;#ffffff]".. + "label[0.25,0.25;op. 1]".. + "label[1.0,0.25;gate type]".. + "label[2.125,0.25;op. 2]".. + "label[3.15,0.25;dest]".. + "label[4.5,0.25;op. 1]".. + "label[5.25,0.25;gate type]".. + "label[6.375,0.25;op. 2]".. + "label[7.4,0.25;dest]" + local x = 1 - 0.75 + local y = 1 - 0.25 + for i = 1, 14 do + local cur = is[i] + s = s .. dropdown_op (x , y, tostring(i).."op1", cur.op1) + s = s .. dropdown_action(x+0.75 , y, tostring(i).."act", cur.action) + s = s .. dropdown_op (x+1.875, y, tostring(i).."op2", cur.op2) + s = s .. "label[" .. tostring(x+2.625) .. "," .. tostring(y+0.1) .. "; ->]" + s = s .. dropdown_op (x+2.9 , y, tostring(i).."dst", cur.dst) + y = y + 1 + + if i == 7 then + x = 4.5 + y = 1 - 0.25 + end + end + return s +end + +plg.from_formspec_fields = function(fields) + local function read_op(s) + if s == nil or s == " " then + return nil + elseif s == "A" or s == "B" or s == "C" or s == "D" then + return {type = "io", port = s} + else + return {type = "reg", n = tonumber(s)} + end + end + local function read_action(s) + if s == nil or s == " " then + return nil + end + local mapping = { + [" AND"] = "and", + [" OR"] = "or", + [" NOT"] = "not", + [" XOR"] = "xor", + ["NAND"] = "nand", + [" ="] = "buf", + ["XNOR"] = "xnor", + } + return mapping[s] + end + local is = {} + for i = 1, 14 do + local cur = {} + cur.op1 = read_op(fields[tonumber(i) .. "op1"]) + cur.action = read_action(fields[tonumber(i) .. "act"]) + cur.op2 = read_op(fields[tonumber(i) .. "op2"]) + cur.dst = read_op(fields[tonumber(i) .. "dst"]) + is[#is + 1] = cur + end + return is +end + +plg.update_formspec = function(pos, is) + if type(is) == "string" then -- serialized string + is = lcore.deserialize(is) + end + local meta = minetest.get_meta(pos) + local form = plg.to_formspec_string(is) + + local err = lcore.validate(is) + if err == nil then + meta:set_int("valid", 1) + meta:set_string("infotext", "FPGA (functional)") + else + meta:set_int("valid", 0) + meta:set_string("infotext", "FPGA") + local fmsg = minetest.colorize("#ff0000", minetest.formspec_escape(err.msg)) + form = form .. plg.red_box_around(err.i) .. + "label[0.25,8.25;The gate configuration is erroneous in the marked area:]".. + "label[0.25,8.5;" .. fmsg .. "]" + end + + meta:set_string("formspec", form) + + -- reset ports and run programmed logic + plg.setports(pos, false, false, false, false) + plg.update(pos) +end + +plg.red_box_around = function(i) + local x, y + if i > 7 then + x = 4.5 + y = 0.75 + (i - 8) + else + x = 0.25 + y = 0.75 + (i - 1) + end + return string.format("box[%f,%f;3.8,0.8;#ff0000]", x-0.1, y-0.05) +end + + +plg.update = function(pos) + local meta = minetest.get_meta(pos) + if meta:get_int("valid") ~= 1 then + return + end + + local is = lcore.deserialize(meta:get_string("instr")) + local A, B, C, D = plg.getports(pos) + A, B, C, D = lcore.interpret(is, A, B, C, D) + plg.setports(pos, A, B, C, D) +end + +plg.ports_changed = function(pos, rule, newstate) + if rule == nil then return end + local meta = minetest.get_meta(pos) + local states + + local s = meta:get_string("portstates") + if s == nil then + states = {false, false, false, false} + else + states = { + s:sub(1, 1) == "1", + s:sub(2, 2) == "1", + s:sub(3, 3) == "1", + s:sub(4, 4) == "1", + } + end + + -- trick to transform rules (see register_node) into port number + local portno = ({4, 1, nil, 3, 2})[3 + rule.x + 2*rule.z] + states[portno] = (newstate == "on") + + meta:set_string("portstates", + (states[1] and "1" or "0") .. (states[2] and "1" or "0") .. + (states[3] and "1" or "0") .. (states[4] and "1" or "0") + ) +end + +plg.getports = function(pos) -- gets merged states of INPUT & OUTPUT + local sin, sout + + local s = minetest.get_meta(pos):get_string("portstates") + if s == nil then + sin = {false, false, false, false} + else + sin = { + s:sub(1, 1) == "1", + s:sub(2, 2) == "1", + s:sub(3, 3) == "1", + s:sub(4, 4) == "1", + } + end + + local name = minetest.get_node(pos).name + assert(name:find("mesecons_fpga:fpga") == 1) + local off = #"mesecons_fpga:fpga" + sout = { + name:sub(off+4, off+4) == "1", + name:sub(off+3, off+3) == "1", + name:sub(off+2, off+2) == "1", + name:sub(off+1, off+1) == "1", + } + + return unpack({ + sin[1] or sout[1], + sin[2] or sout[2], + sin[3] or sout[3], + sin[4] or sout[4], + }) +end + +plg.setports = function(pos, A, B, C, D) -- sets states of OUTPUT + local base = "mesecons_fpga:fpga" + + local name = base + .. (D and "1" or "0") .. (C and "1" or "0") + .. (B and "1" or "0") .. (A and "1" or "0") + minetest.swap_node(pos, {name = name, param2 = minetest.get_node(pos).param2}) + + if A ~= nil then + local ru = plg.rules[base .. "0001"] + if A then mesecon.receptor_on(pos, ru) else mesecon.receptor_off(pos, ru) end + end + if B ~= nil then + local ru = plg.rules[base .. "0010"] + if B then mesecon.receptor_on(pos, ru) else mesecon.receptor_off(pos, ru) end + end + if C ~= nil then + local ru = plg.rules[base .. "0100"] + if C then mesecon.receptor_on(pos, ru) else mesecon.receptor_off(pos, ru) end + end + if D ~= nil then + local ru = plg.rules[base .. "1000"] + if D then mesecon.receptor_on(pos, ru) else mesecon.receptor_off(pos, ru) end + end +end + + +minetest.register_craft({ + output = "mesecons_fpga:fpga0000 2", + recipe = { + {'group:mesecon_conductor_craftable', 'group:mesecon_conductor_craftable'}, + {'mesecons_materials:silicon', 'mesecons_materials:silicon'}, + {'group:mesecon_conductor_craftable', 'group:mesecon_conductor_craftable'}, + } +}) diff --git a/mesecons_fpga/logic.lua b/mesecons_fpga/logic.lua new file mode 100644 index 0000000..3dca154 --- /dev/null +++ b/mesecons_fpga/logic.lua @@ -0,0 +1,210 @@ +local lg = {} + +-- (de)serialize +lg.serialize = function(t) + local function _op(t) + if t == nil then + return " " + elseif t.type == "io" then + return t.port + else -- t.type == "reg" + return tostring(t.n) + end + end + local function _action(s) + if s == nil then + return " " + end + local mapping = { + ["and"] = "&", + ["or"] = "|", + ["not"] = "~", + ["xor"] = "^", + ["nand"] = "?", --dunno + ["buf"] = "_", + ["xnor"] = "=", + } + return mapping[s] + end + + local s = "" + for i = 1, 14 do + local cur = t[i] + if next(cur) ~= nil then + s = s .. _op(cur.op1) .. _action(cur.action) .. _op(cur.op2) .. _op(cur.dst) + end + s = s .. "/" + end + return s +end + +lg.deserialize = function(s) + local function _op(c) + if c == "A" or c == "B" or c == "C" or c == "D" then + return {type = "io", port = c} + elseif c == " " then + return nil + else + return {type = "reg", n = tonumber(c)} + end + end + local function _action(c) + local mapping = { + ["&"] = "and", + ["|"] = "or", + ["~"] = "not", + ["^"] = "xor", + ["?"] = "nand", + ["_"] = "buf", + ["="] = "xnor", + [" "] = nil, + } + return mapping[c] + end + + local ret = {} + for part in s:gmatch("(.-)/") do + local parsed + if part == "" then + parsed = {} + else + parsed = { + action = _action( part:sub(2,2) ), + op1 = _op( part:sub(1,1) ), + op2 = _op( part:sub(3,3) ), + dst = _op( part:sub(4,4) ), + } + end + ret[#ret + 1] = parsed + end + -- More than 14 instructions (write to all 10 regs + 4 outputs) + -- will not pass the write-once requirement of the validator + assert(#ret == 14) + return ret +end + +-- validation +lg.validate_single = function(t, i) + local function is_reg_written_to(t, n, max) + for i = 1, max-1 do + if next(t[i]) ~= nil + and t[i].dst and t[i].dst.type == "reg" + and t[i].dst.n == n then + return true + end + end + return false + end + local function compare_op(t1, t2, allow_same_io) + if t1 == nil or t2 == nil then + return false + elseif t1.type ~= t2.type then + return false + end + if t1.type == "reg" and t1.n == t2.n then + return true + elseif t1.type == "io" and t1.port == t2.port then + return not allow_same_io + end + return false + end + local elem = t[i] + -- check for completeness + if elem.action == nil then + return {i = i, msg = "Gate type required"} + elseif elem.action == "not" or elem.action == "buf" then + if elem.op1 ~= nil or elem.op2 == nil or elem.dst == nil then + return {i = i, msg = "Second operand (only) and destination required"} + end + else + if elem.op1 == nil or elem.op2 == nil or elem.dst == nil then + return {i = i, msg = "Operands and destination required"} + end + end + -- check whether operands/destination are identical + if compare_op(elem.op1, elem.op2) then + return {i = i, msg = "Operands cannot be identical"} + end + if compare_op(elem.op1, elem.dst, true) or compare_op(elem.op2, elem.dst, true) then + return {i = i, msg = "Destination and operands must be different"} + end + -- check whether operands point to defined registers + if elem.op1 ~= nil and elem.op1.type == "reg" + and not is_reg_written_to(t, elem.op1.n, i) then + return {i = i, msg = "First operand is undefined register"} + end + if elem.op2.type == "reg" and not is_reg_written_to(t, elem.op2.n, i) then + return {i = i, msg = "Second operand is undefined register"} + end + -- check whether destination points to undefined register + if elem.dst.type == "reg" and is_reg_written_to(t, elem.dst.n, i) then + return {i = i, msg = "Destination is already used register"} + end + + return nil +end + +lg.validate = function(t) + for i = 1, 14 do + if next(t[i]) ~= nil then + local r = lg.validate_single(t, i) + if r ~= nil then + return r + end + end + end + return nil +end + +-- interpreter +lg.interpret = function(t, a, b, c, d) + local function _action(s, v1, v2) + if s == "and" then + return v1 and v2 + elseif s == "or" then + return v1 or v2 + elseif s == "not" then + return not v2 + elseif s == "xor" then + return v1 ~= v2 + elseif s == "nand" then + return not (v1 and v2) + elseif s == "buf" then + return v2 + else -- s == "xnor" + return v1 == v2 + end + end + local function _op(t, regs, io_in) + if t.type == "reg" then + return regs[t.n] + else -- t.type == "io" + return io_in[t.port] + end + end + + local io_in = {A=a, B=b, C=c, D=d} + local regs = {} + local io_out = {} + for i = 1, 14 do + local cur = t[i] + if next(cur) ~= nil then + local v1, v2 + if cur.op1 ~= nil then + v1 = _op(cur.op1, regs, io_in) + end + v2 = _op(cur.op2, regs, io_in) + + local result = _action(cur.action, v1, v2) + + if cur.dst.type == "reg" then + regs[cur.dst.n] = result + else -- cur.dst.type == "io" + io_out[cur.dst.port] = result + end + end + end + return io_out.A, io_out.B, io_out.C, io_out.D +end + +return lg diff --git a/mesecons_fpga/textures/jeija_fpga_programmer.png b/mesecons_fpga/textures/jeija_fpga_programmer.png new file mode 100644 index 0000000000000000000000000000000000000000..9c0ba8f77b084732731cf7bd000abb72da2de9d5 GIT binary patch literal 311 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJXMsm#F#`j)FbFd;%$g$s6l5>) z^mS!_$S5hGU~GPV>ocH`cYsfbE0C6vky*KNey7)B`n?L)2A5HB=*Y)K{!n0aU+g)hf7_b?eq`*s$Tj&;i2iaxJ< j`nkoC{r<*dE9TcQ%H*=eSt#VxfE?iI>gTe~DWM4fI$vgN literal 0 HcmV?d00001 diff --git a/mesecons_fpga/textures/jeija_fpga_sides.png b/mesecons_fpga/textures/jeija_fpga_sides.png new file mode 100644 index 0000000000000000000000000000000000000000..e2d8e15daaeafde621172d4cdb8b8946957f4284 GIT binary patch literal 536 zcmV+z0_XjSP)a^d zQY0@@Brj7WFH|HjRV6T1B{5bdF;^xsS0*x8CNfzkGg>D!TPUcgsHv%`s;a81tE;T6 ztgWrBuCA`HudlGMu(7eRva+(Xv$M3cw6(Rhx3{;rxVX8wxw^W#ySux*yu7`=y}rJ_ zzrVl0z`()5!NS7A!^6YG#KgtL#m2_Q$H&LW$jHgb$;->j%*@RH|Nn^c@4x^600Cl4 zM?^K=w%Ka{008_+L_t&-8HK^iZqq;%0MK)}!~pTg)(VrO!+TI{^I2s^1Ge);VyW=(Z+b(Ib_tM5`r8SRZYszNiOAutK4qg;Gu zmO9GWUA0NgU@;(V(pl;#f4vBVCah9ZR29`t>L_8cM?<%f@<(E z_%C&o)!inLRt&;JwMZRha8^B3gN7P4vp3(+keWo37BpX^j`D7`B7`QrKbR>sHmu_0I910t*x!E zudlGMu(7eRv$M0cwY9gmx4F5wy1Kf&yu7`=y}rJ_zrVl0z`()5!NS7A!^6YG#KgtL z#mC3T$;rw8|Nj(``r|km zgkCFD!qm|}*VhlWrlL2vN8L6MXnb*T*=II<{AZZGoASDXt=slvGK8k4Svs? zS(!vqzi=l>HFkbA^UzLb-aWT!qb^Tg{<-3j(!tsj@pqO!e;8?b&JgxSgVD}XDxasX z;`Xb1&1K4&PaJ$B)mpmvAWGHNnA-c$C_%V3tS+pYxPL#iF07Rf)}DCR1EU!ATGw_O zJDr_OuapU|eeWX&UpulFtwLd8@Z+h?@TnjAwM`+Fctb1PAPS9KkN#{>Y%24obFEq@ z(F!++PAHuk4f4PGSry|+sJ!%)-_J{gwCI%j~!^7$p+5Fg4c=u2v>u uX;h=O)GS|)qav-0SQrrg@6x@wss8{QA-HSxTlm%h0000