eris2206

Documentation: http://frombelow.net/projects/eris2206/
Clone: git clone https://git.frombelow.net/eris2206.git
Log | Files | Refs | Submodules | README | LICENSE

commit 5295ea4d583a4b09a273b34acc0694fb8072247d
Author: Gerd Beuster <gerd@frombelow.net>
Date:   Sat, 29 Oct 2022 16:35:03 +0200

Initial version

Diffstat:
A.gitignore | 9+++++++++
A.gitmodules | 3+++
ACOPYING | 674+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AREADME | 1+
Aboard/circuit.fzz | 0
Acase/Makefile | 23+++++++++++++++++++++++
Acase/case.scad | 542+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acase/dst/labeled/box_right_side/box_right_side.svg | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acase/dst/labeled/box_right_side/polarity/polarity.svg | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acase/dst/labeled/control_panel/control_panel.svg | 332+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acase/dst/labeled/top_plate/acryl_top_plate.svg | 781+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acase/dst/stl/.gitkeep | 0
Acase/dst/svg/.gitkeep | 0
Acase/lasercut | 1+
Adoc/README.md | 371+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adoc/bom.txt | 19+++++++++++++++++++
Adoc/schematic.dia | 0
Asrc/Makefile | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ecpu.pcf | 36++++++++++++++++++++++++++++++++++++
Asrc/ecpu.v | 581+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ecpu_tb.gtkw | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ecpu_tb.v | 38++++++++++++++++++++++++++++++++++++++
Asrc/main.v | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/roms/rom.asm | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/roms/rom_leds.asm | 16++++++++++++++++
Asrc/roms/rom_opcode_test_0.asm | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/roms/rom_opcode_test_1.asm | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/roms/rom_uart.asm | 25+++++++++++++++++++++++++
Asrc/tools/eras.pl | 276+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tools/mc_compiler.py | 342+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tools/send_serial.py | 26++++++++++++++++++++++++++
Asrc/uart.v | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ws2811.v | 396+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33 files changed, 5301 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,9 @@ +**.bin +**.out +**.vcd +src/tools/*.dat +src/roms/*.dat +src/roms/*.s +src/tools/opcodes.pl +case/dst/stl/*.stl +case/dst/svg/*.svg diff --git a/.gitmodules b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "case/lasercut"] + path = case/lasercut + url = https://github.com/bmsleight/lasercut.git diff --git a/COPYING b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<https://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<https://www.gnu.org/licenses/why-not-lgpl.html>. diff --git a/README b/README @@ -0,0 +1 @@ +See doc/README.md diff --git a/board/circuit.fzz b/board/circuit.fzz Binary files differ. diff --git a/case/Makefile b/case/Makefile @@ -0,0 +1,23 @@ +SVG=acryl_top_plate.svg matrix_back.svg control_panel.svg \ + box_left_side.svg box_right_side.svg box_front.svg box_back.svg \ + bottom_screw_mount_front.svg bottom_screw_mount_back.svg box_bottom.svg +STL=circuit_board_holder.stl icestick_base.stl icestick_strap.stl + +DST_STL=./dst/stl +DST_SVG=./dst/svg + +ALL_TARGETS=$(addprefix $(DST_STL)/, $(STL)) $(addprefix $(DST_SVG)/, $(SVG)) + + +all: $(SVG) $(STL) + +%.svg: case.scad + openscad -o $(DST_SVG)/$@ -D "mode=\"`basename -s .svg $@`\"" ./case.scad + +%.stl: case.scad + openscad -o $(DST_STL)/$@ -D "mode=\"`basename -s .stl $@`\"" ./case.scad + +clean: + rm -f $(DST_SVG)/*.svg $(DST_STL)/*.gcode $(DST_STL)/*.g3drem $(DST_STL)/*.stl + +.phony: all clean diff --git a/case/case.scad b/case/case.scad @@ -0,0 +1,542 @@ +/* + * Copyright 2022 Gerd Beuster (gerd@frombelow.net). This design is + * free under the GNU GPL v3 license or any later version. See + * COPYING in the root directory for details. + */ + +include <lasercut/lasercut.scad> + +$fn=30; + +// Thickness of boards +board_thickness = 4; +// Width and depth of LED matrix +matrix_side = 160; +matrix_height = 2; +// Additional border of back plate of LED matrix. +matrix_back_border = 20; +matrix_back_side = matrix_side + matrix_back_border*2; +// Distance from side of LED matrix back plate to screw holes +matrix_back_screw_holes_distance = matrix_back_border / 2; +// Diameter of holes to screw matrix back screw to acryl plate +matrix_back_screw_hole = 4; +// Screw holes for bottom plate are somewhat larger, because +// we use claw nuts +bottom_screw_hole = 5; +// Depth of control panel +panel_depth = 60; +// Diameter of holes for switches +switch = 6.6; +// Diameter of holes for dial +dial = 6.6; +// Diameter of holes for push buttons +button = 7.2; +// Hole for USB connector +usb_width = 18; +usb_height = 13; +// Diameter of hole for power supply +power_supply = 8; + +box_height = 60; +// Distance from floor to bottom panel +bottom_panel_height = 5; + +// Circuit board +circuit_board_width = 145; +circuit_board_depth = 65; +circuit_board_height = 1; +// Icestick +icestick_base_width = 80; +icestick_base_depth = 25; +icestick_base_height = 4; +icestick_strap_width = 20; +icestick_strap_depth = 60; +icestick_strap_height = 2; + +module matrix() { + translate([matrix_back_border, + matrix_back_border, + board_thickness]) + cube([matrix_side, matrix_side, 2]); +} + +// The LED matrix is fit in between the acryl plate on top +// and the back plate below. These three plates are hold +// together by screws. The acryl plate and the back plate (but +// not the LED matrix itself) need screw holes. +module acryl_plate_holder_screw_holes() { + // Screw holes in four corners + union () { + translate([matrix_back_border/2, + matrix_back_border/2, + 0]) + cylinder(h=board_thickness, d=matrix_back_screw_hole, + center=false); + translate([matrix_back_side-matrix_back_border/2, + matrix_back_border/2, + 0]) + cylinder(h=board_thickness, d=matrix_back_screw_hole, + center=false); + translate([matrix_back_border/2, + matrix_back_side-matrix_back_border/2, + 0]) + cylinder(h=board_thickness, d=matrix_back_screw_hole, + center=false); + translate([matrix_back_side-matrix_back_border/2, + matrix_back_side-matrix_back_border/2, + 0]) + cylinder(h=board_thickness, d=matrix_back_screw_hole, + center=false); + } +} + +module matrix_back() { + difference() { + lasercutoutSquare(thickness=board_thickness, + x=matrix_back_side, y=matrix_back_side, + finger_joints=[ + [UP, 0, 4], + [LEFT, 1, 4], + [RIGHT, 0, 4] + ]); + // Cutout for power supply + { translate([matrix_back_side-matrix_back_border*2-25, + matrix_back_side-matrix_back_border*2-30, 0]) + cube([15, 20, board_thickness]); + } + acryl_plate_holder_screw_holes(); + } +} + +module acryl_top_plate() { + translate([0, 0, matrix_height+board_thickness]) { + difference () { + cube([matrix_back_side, matrix_back_side, board_thickness]); + acryl_plate_holder_screw_holes(); + } + } + } + +module box_left_side() { + difference () { + translate([-board_thickness, + -panel_depth, + board_thickness*2+matrix_height]) { + rotate([0, 90, 0]) { + lasercutoutSquare(thickness=board_thickness, + x=box_height, + y=matrix_side+matrix_back_border*2+panel_depth, + finger_joints=[ + [UP, 1, 2], + [DOWN, 0, 2], + ]); + } + } + union () { + // Cutout for fingers + matrix_back(); + control_panel(); + bottom_screw_mount_front(); + bottom_screw_mount_back(); + } + } +} + +module box_right_side() { + difference () { + translate([matrix_back_side, + -panel_depth, + board_thickness*2+matrix_height]) { + rotate([0, 90, 0]) { + lasercutoutSquare(thickness=board_thickness, + x=box_height, + y=matrix_side+matrix_back_border*2+panel_depth, + finger_joints=[ + [UP, 1, 2], + [DOWN, 0, 2], + ]); + } + } + union () { + // Cutout for fingers + matrix_back(); + control_panel(); + bottom_screw_mount_front(); + bottom_screw_mount_back(); + // Cutout for USB connector + translate([matrix_back_side, + circuit_board_depth+usb_width*2, + -box_height+usb_height+bottom_panel_height+1]) { + cube([board_thickness, usb_width, usb_height]); + } + } + } +} + +module box_front() { + difference () { + translate([-board_thickness, + -panel_depth, + board_thickness*2+matrix_height]) { + rotate([90, 90, 0]) { + lasercutoutSquare(thickness=board_thickness, + x=box_height, + y=matrix_back_side+board_thickness*2, + finger_joints=[ + ]); + } + } + // Cutout for fingers + union () { + box_left_side(); + box_right_side(); + control_panel(); + bottom_screw_mount_front(); + } + } +} + +module box_back() { + difference () { + translate([-board_thickness, + matrix_side+matrix_back_border*2+board_thickness, + board_thickness*2+matrix_height]) { + rotate([90, 90, 0]) { + lasercutoutSquare(thickness=board_thickness, + x=box_height, + y=matrix_back_side+board_thickness*2, + finger_joints=[ + ]); + } + } + // Cutout for fingers + union () { + box_left_side(); + box_right_side(); + matrix_back(); + bottom_screw_mount_back(); + } + } +} + + +module control_panel() { + translate([0, -panel_depth, matrix_height+board_thickness]) { + difference() { + lasercutoutSquare(thickness=board_thickness, + x=matrix_back_side, y=panel_depth, + finger_joints=[ + [LEFT, 0, 2], + [RIGHT, 1, 2], + [DOWN, 0, 4] + ]); + // Reset Button + translate([matrix_back_side/10*(1-.2), + panel_depth/4*(3.2-.2), + 0 ]) + cylinder(h=board_thickness, d=button, + center=false); + // Speed dial + translate([matrix_back_side/10*(2-.2), + panel_depth/4*(3.2-.2), + 0 ]) + cylinder(h=board_thickness, d=dial, + center=false); + // Run/Single/Enter switch + translate([matrix_back_side/10*(3-.2), + panel_depth/4*(3.2-.2), + 0 ]) + cylinder(h=board_thickness, d=switch, + center=false); + // Step Button + translate([matrix_back_side/10*(4-.2), + panel_depth/4*(3.2-.2), + 0 ]) + cylinder(h=board_thickness, d=button, + center=false); + // Skip Button + translate([matrix_back_side/10*(5-.2), + panel_depth/4*(3.2-.2), + 0 ]) + cylinder(h=board_thickness, d=button, + center=false); + // Data switches + for(p = [2-.2:9-.2]) { + translate([matrix_back_side/10*p, + panel_depth/4*(.8+.2), + 0 ]) { + cylinder(h=board_thickness, d=switch, + center=false); + } + } + } + } +} + + +module bottom_screw_mount_front() { + translate([0, -panel_depth, -box_height+board_thickness*3.5+bottom_panel_height]) { + difference() { + lasercutoutSquare(thickness=board_thickness, + x=matrix_back_side, y=matrix_back_border, + finger_joints=[ + [DOWN, 0, 4], + [LEFT, 1, 2], + [RIGHT, 0, 2] + ]); + translate([matrix_back_border/2, matrix_back_border/2, 0]) + cylinder(h=board_thickness, d=bottom_screw_hole, + center=false); + translate([matrix_back_side-matrix_back_border/2, matrix_back_border/2, 0]) + cylinder(h=board_thickness, d=bottom_screw_hole, + center=false); + } + } + +} + +module bottom_screw_mount_back() { + translate([0, matrix_side+matrix_back_border, -box_height+board_thickness*3.5+bottom_panel_height]) { + difference() { + lasercutoutSquare(thickness=board_thickness, + x=matrix_back_side, y=matrix_back_border, + finger_joints=[ + [UP, 0, 4], + [LEFT, 1, 2], + [RIGHT, 0, 2] + ]); + translate([matrix_back_border/2, matrix_back_border/2, 0]) + cylinder(h=board_thickness, d=bottom_screw_hole, + center=false); + translate([matrix_back_side-matrix_back_border/2, matrix_back_border/2, 0]) + cylinder(h=board_thickness, d=bottom_screw_hole, + center=false); + } + } + +} + +module box_bottom() { + difference() { + translate([0, -panel_depth, -box_height+2.5*board_thickness+bottom_panel_height]) { + difference() { + // Plate + cube([matrix_back_side, matrix_side+panel_depth+matrix_back_border*2, board_thickness]); + // Screw holes for bottom + translate([matrix_back_border/2, matrix_back_border/2, 0]) + cylinder(h=board_thickness, d=bottom_screw_hole, + center=false); + translate([matrix_back_side-matrix_back_border/2, matrix_back_border/2, 0]) + cylinder(h=board_thickness, d=bottom_screw_hole, + center=false); + translate([matrix_back_border/2, + matrix_side+panel_depth+matrix_back_border*1.5, 0]) + cylinder(h=board_thickness, d=bottom_screw_hole, + center=false); + translate([matrix_back_side-matrix_back_border/2, + matrix_side+panel_depth+matrix_back_border*1.5, 0]) + cylinder(h=board_thickness, d=bottom_screw_hole, + center=false); + } + } + // Screw holes for circuit holder and icestick + circuit_board_holder_mount_holes(); + icestick_strap_mount_holes(); + } +} + +module circuit_board_vitamin() { + translate([(matrix_back_side-circuit_board_width)/2, + 0, + -box_height+bottom_panel_height+board_thickness*3+matrix_height]) { + cube([circuit_board_width, circuit_board_depth, circuit_board_height]); + } +} + +module circuit_board_holder_mount_holes() { + translate([(matrix_back_side-circuit_board_width)/2-10, + -10, + -box_height+bottom_panel_height+board_thickness*3+matrix_height]) { + translate([10, 5, -board_thickness]) { + cylinder(h=2+board_thickness, d=matrix_back_screw_hole, center=false); + } + translate([10, circuit_board_depth+15, -board_thickness]) { + cylinder(h=2+board_thickness, d=matrix_back_screw_hole, center=false); + } + } + translate([(matrix_back_side+circuit_board_width)/2-10, + -10, + -box_height+bottom_panel_height+board_thickness*3+matrix_height]) { + translate([10, 5, -board_thickness]) { + cylinder(h=2+board_thickness, d=matrix_back_screw_hole, center=false); + } + translate([10, circuit_board_depth+15, -board_thickness]) { + cylinder(h=2+board_thickness, d=matrix_back_screw_hole, center=false); + } + } +} + +module circuit_board_holder() { + difference() { + // From left and right holders ... + union() { + // Left holder + translate([(matrix_back_side-circuit_board_width)/2-10, + -10, + -box_height+bottom_panel_height+board_thickness*3+matrix_height]) { + cube([20, circuit_board_depth+20, 2]); + } + // Right holder + translate([(matrix_back_side+circuit_board_width)/2-10, + -10, + -box_height+bottom_panel_height+board_thickness*3+matrix_height]) { + cube([20, circuit_board_depth+20, 2]); + } + } + union () { + // ... remove mount holes ... + circuit_board_holder_mount_holes(); + // ... remove the edges of the circuit board + circuit_board_vitamin(); + } + } +} + +module icestick_base() { + translate([matrix_back_side-icestick_base_width-20, + circuit_board_depth+usb_width*2, + -box_height+bottom_panel_height+board_thickness*3+matrix_height]) { + cube([icestick_base_width, usb_width, icestick_base_height]); + } +}; + +module icestick_strap() { + difference() { + translate([matrix_back_side-icestick_strap_width*2, + circuit_board_depth+usb_width*2.5-icestick_strap_depth/2, + -box_height+bottom_panel_height+board_thickness*3+matrix_height]) { + cube([icestick_strap_width, icestick_strap_depth, icestick_strap_height]); + } + icestick_strap_mount_holes(); + } +}; + +module icestick_strap_mount_holes() { + translate([matrix_back_side-icestick_strap_width*1.5, + circuit_board_depth+usb_width*2.5-icestick_strap_depth/2.5, + -box_height+bottom_panel_height+board_thickness*2+matrix_height]) { + cylinder(h=board_thickness+icestick_strap_height, d=matrix_back_screw_hole, center=false); + } + translate([matrix_back_side-icestick_strap_width*1.5, + circuit_board_depth+usb_width*2.5+icestick_strap_depth/2.5, + -box_height+bottom_panel_height+board_thickness*2+matrix_height]) { + cylinder(h=board_thickness+icestick_strap_height, d=matrix_back_screw_hole, center=false); + } +}; + +mode = "all"; +// mode = "acryl_top_plate"; +// mode = "matrix"; +// mode = "matrix_back"; +// mode = "control_panel"; +// mode = "box_left_side"; +// mode = "box_right_side"; +// mode = "box_front"; +// mode = "box_back"; +// mode = "bottom_screw_mount_front"; +// mode = "bottom_screw_mount_back"; +// mode = "box_bottom"; +// mode = "circuit_board_holder"; +// mode = "icestick_base"; +// mode = "icestick_strap"; + + +if (mode == "all") { + acryl_top_plate(); + matrix(); + matrix_back(); + control_panel(); + box_left_side(); + box_right_side(); + box_front(); + box_back(); + bottom_screw_mount_front(); + bottom_screw_mount_back(); + box_bottom(); + circuit_board_holder(); + icestick_base(); + icestick_strap(); +} + +if (mode == "acryl_top_plate") { + projection() + acryl_top_plate(); +} +if (mode == "matrix") { + projection() + matrix(); +} +if (mode == "matrix_back") { + projection() + matrix_back(); +} +if (mode == "control_panel") { + projection() + control_panel(); +} +if (mode == "box_left_side") { + projection() + rotate([0, 90, 0]) + box_left_side(); +} +if (mode == "box_right_side") { + projection() + rotate([0, -90, 0]) + box_right_side(); +} +if (mode == "box_front") { + projection() + rotate([-90, 0, 0]) + box_front(); +} +if (mode == "box_back") { + projection() + rotate([90, 0, 0]) + box_back(); +} +if (mode == "bottom_screw_mount_front") { + projection() + bottom_screw_mount_front(); +} +if (mode == "bottom_screw_mount_back") { + projection() + bottom_screw_mount_back(); +} +if (mode == "box_bottom") { + projection() + rotate([180, 0, 0]) + box_bottom(); +} +if (mode == "circuit_board_holder") { + circuit_board_holder(); +} +if (mode == "icestick_base") { + icestick_base(); +} +if (mode == "icestick_strap") { + icestick_strap(); +} + +// Acryl top plates with markings for LED matrix. We use this as a +// template to add labels to the top plate. +/* +projection() +difference() { + acryl_top_plate(); + union() { + matrix(); + translate([0,0,2]) matrix(); + translate([0,0,4]) matrix(); + } +} +*/ diff --git a/case/dst/labeled/box_right_side/box_right_side.svg b/case/dst/labeled/box_right_side/box_right_side.svg @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="268mm" + height="60mm" + viewBox="-10 -204 268 60" + version="1.1" + id="svg88" + sodipodi:docname="box_right_side.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata94"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title>OpenSCAD Model</dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs92" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1502" + inkscape:window-height="938" + id="namedview90" + showgrid="false" + inkscape:zoom="0.62618858" + inkscape:cx="456.73142" + inkscape:cy="217.98545" + inkscape:window-x="1970" + inkscape:window-y="27" + inkscape:window-maximized="0" + inkscape:current-layer="layer2" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm" /> + <title + id="title84">OpenSCAD Model</title> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="Cut" + style="display:inline"> + <path + d="m -5.714743,-188.70912 v 15 h -4 v 15 h 4 v 2 h 5 v 4 h -5 v 9 H 254.28526 v -15 h 4 v -15 h -4 v -15 h 4 v -15 H 54.285257 v 4 h -15 v -4 h -15 v 4 h -15 v -4 h -19 v 15 z m 250.000003,32 h 5 v 4 h -5 z m -10,0 h 5 v 4 h -5 z m -30,-41 h 25 v 4 h -25 z m -50,0 h 25 v 4 h -25 z m 1,32 h 18 v 13 h -18 z m -51,-32 h 25 v 4 h -25 z m -50.000003,0 h 25 v 4 h -25 z m -50,41 h 5 v 4 h -5 z" + stroke="#000000" + fill="#d3d3d3" + stroke-width="0.5" + id="path601" /> + </g> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Labels" + style="display:inline"> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;line-height:58.1025px;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="14.26072" + y="-152.9451" + id="text351"><tspan + sodipodi:role="line" + id="tspan349" + x="14.26072" + y="-152.9451" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">© 2022 Gerd Beuster</tspan></text> + </g> +</svg> diff --git a/case/dst/labeled/box_right_side/polarity/polarity.svg b/case/dst/labeled/box_right_side/polarity/polarity.svg @@ -0,0 +1,155 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + viewBox="0 0 210 297" + version="1.1" + id="svg8" + inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)" + sodipodi:docname="polarity.svg"> + <defs + id="defs2" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="5.6" + inkscape:cx="298.76497" + inkscape:cy="995.68575" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1920" + inkscape:window-height="1141" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:snap-to-guides="false" + inkscape:snap-grids="false" + inkscape:snap-others="false" + inkscape:snap-nodes="false"> + <sodipodi:guide + position="76.776414,257.85063" + orientation="0,1" + id="guide819" + inkscape:locked="false" /> + </sodipodi:namedview> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:58.10250092px;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="61.799107" + y="37.89732" + id="text817"><tspan + sodipodi:role="line" + id="tspan815" + x="61.799107" + y="37.89732" + style="stroke-width:0.26458332px">- +</tspan></text> + <path + style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.5;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + id="path823" + sodipodi:type="arc" + sodipodi:cx="62.637741" + sodipodi:cy="36.657082" + sodipodi:rx="2.279669" + sodipodi:ry="2.279669" + sodipodi:start="6.1609599" + sodipodi:end="6.1600349" + sodipodi:open="true" + d="m 64.900403,36.379141 a 2.279669,2.279669 0 0 1 -1.984198,2.540538 2.279669,2.279669 0 0 1 -2.540997,-1.983611 2.279669,2.279669 0 0 1 1.983023,-2.541455 2.279669,2.279669 0 0 1 2.541914,1.982436" /> + <path + style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.5;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + id="path823-1" + sodipodi:type="arc" + sodipodi:cx="79.871094" + sodipodi:cy="36.686977" + sodipodi:rx="2.279669" + sodipodi:ry="2.279669" + sodipodi:start="6.1609599" + sodipodi:end="6.1600349" + sodipodi:open="true" + d="m 82.133756,36.409037 a 2.279669,2.279669 0 0 1 -1.984199,2.540538 2.279669,2.279669 0 0 1 -2.540997,-1.983611 2.279669,2.279669 0 0 1 1.983024,-2.541455 2.279669,2.279669 0 0 1 2.541914,1.982435" /> + <path + style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.5;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + id="path823-2" + sodipodi:type="arc" + sodipodi:cx="71.661575" + sodipodi:cy="36.670086" + sodipodi:rx="2.279669" + sodipodi:ry="2.279669" + sodipodi:start="6.1609599" + sodipodi:end="6.1600349" + sodipodi:open="true" + d="m 73.924238,36.392146 a 2.279669,2.279669 0 0 1 -1.984199,2.540538 2.279669,2.279669 0 0 1 -2.540997,-1.983611 2.279669,2.279669 0 0 1 1.983023,-2.541456 2.279669,2.279669 0 0 1 2.541914,1.982436" /> + <rect + style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.1;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + id="rect855" + width="2.1548605" + height="5.6794777" + x="72.663902" + y="33.856441" /> + <path + style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.02973792;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + id="path823-8" + sodipodi:type="arc" + sodipodi:cx="71.544708" + sodipodi:cy="36.579254" + sodipodi:rx="0.67792612" + sodipodi:ry="0.67792612" + sodipodi:start="6.1609599" + sodipodi:end="6.1600349" + sodipodi:open="true" + d="m 72.217577,36.496601 a 0.67792612,0.67792612 0 0 1 -0.59006,0.755503 0.67792612,0.67792612 0 0 1 -0.755639,-0.589885 0.67792612,0.67792612 0 0 1 0.58971,-0.755776 0.67792612,0.67792612 0 0 1 0.755912,0.589535" /> + <path + style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.45176813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 77.614899,36.595957 H 71.628232" + id="path891" + inkscape:connector-curvature="0" /> + <path + style="opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 69.402894,36.605179 h -4.50182" + id="path891-6" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:58.10250092px;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="60.661377" + y="43.404289" + id="text910"><tspan + sodipodi:role="line" + id="tspan908" + x="60.661377" + y="43.404289" + style="stroke-width:0.26458332px">3.3 – 15 V</tspan></text> + </g> +</svg> diff --git a/case/dst/labeled/control_panel/control_panel.svg b/case/dst/labeled/control_panel/control_panel.svg @@ -0,0 +1,332 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="208mm" + height="64mm" + viewBox="-4 0 208 64" + version="1.1" + id="svg6" + sodipodi:docname="control_panel.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title>OpenSCAD Model</dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs10" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1680" + inkscape:window-height="986" + id="namedview8" + showgrid="true" + showguides="true" + inkscape:guide-bbox="true" + inkscape:zoom="1.352795" + inkscape:cx="639.41692" + inkscape:cy="212.52297" + inkscape:window-x="1920" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm"> + <inkscape:grid + type="xygrid" + id="grid822" /> + <sodipodi:guide + position="194.99792,45.772915" + orientation="1,0" + id="guide80" + inkscape:locked="false" /> + <sodipodi:guide + position="29.104166,56.740934" + orientation="0,1" + id="guide897" + inkscape:locked="false" /> + <sodipodi:guide + position="79.374999,40.882247" + orientation="0,1" + id="guide899" + inkscape:locked="false" /> + <sodipodi:guide + position="42.333333,8.4374999" + orientation="0,-1" + id="guide58" + inkscape:locked="false" /> + </sodipodi:namedview> + <title + id="title2">OpenSCAD Model</title> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Cuts" + style="display:inline"> + <path + d="m 25.11332,60.188897 h 24.999997 v 4 h 25 v -4 h 25.000003 v 4 h 25 v -4 h 25 v 4 h 25 v -4 h 25 v -15 h 4 v -15 h -4 V 15.1889 h 4 v -15 H -3.8866803 v 15 H 0.11331967 V 30.188897 H -3.8866803 v 15 h 3.99999997 v 19 H 25.11332 Z M 75.737017,18.7692 l -0.7362,-0.1565 -0.6875,-0.3061 -0.6089,-0.4424 -0.5036,-0.5593 -0.3763,-0.6518 -0.2325,-0.7157 -0.0787,-0.7485 0.0787,-0.7485 0.2325,-0.7158 0.3763,-0.6517 0.5036,-0.5593 0.6089,-0.4424 0.6875,-0.3061 0.7362,-0.1565 h 0.7526 l 0.7362,0.1565 0.6875,0.3061 0.6089,0.4424 0.5036,0.5593 0.3763,0.6517 0.2325,0.7158 0.0787,0.7485 -0.0787,0.7485 -0.2325,0.7157 -0.3763,0.6518 -0.5036,0.5593 -0.6089,0.4424 -0.6875,0.3061 -0.7362,0.1565 z m 20,0 -0.7362,-0.1565 -0.6875,-0.3061 -0.6089,-0.4424 -0.5036,-0.5593 -0.3763,-0.6518 -0.2325,-0.7157 -0.0787,-0.7485 0.0787,-0.7485 0.2325,-0.7158 0.3763,-0.6517 0.5036,-0.5593 0.6089,-0.4424 0.6875,-0.3061 0.7362,-0.1565 h 0.7526 l 0.7362,0.1565 0.6875,0.3061 0.6089,0.4424 0.5036,0.5593 0.3763,0.6517 0.2325,0.7158 0.0787,0.7485 -0.0787,0.7485 -0.2325,0.7157 -0.3763,0.6518 -0.5036,0.5593 -0.6089,0.4424 -0.6875,0.3061 -0.7362,0.1565 z m -42.2935,-1.6406 -0.3449,-0.5975 -0.2132,-0.6561 -0.0721,-0.6861 0.0721,-0.6861 0.2132,-0.6561 0.3449,-0.5975 0.4617,-0.5127 0.5581,-0.4055 0.6302,-0.2806 0.6748,-0.1434 h 0.6899 l 0.6748,0.1434 0.6303,0.2806 0.5581,0.4055 0.4617,0.5127 0.3449,0.5975 0.2132,0.6561 0.0721,0.6861 -0.0721,0.6861 -0.2132,0.6561 -0.3449,0.5975 -0.4617,0.5127 -0.5581,0.4055 -0.6303,0.2806 -0.6748,0.1434 h -0.6899 l -0.6748,-0.1434 -0.6302,-0.2806 -0.5581,-0.4055 z m 102.324803,31.342197 -0.675,-0.1434 -0.63,-0.2806 -0.558,-0.4055 -0.462,-0.5127 -0.345,-0.5975 -0.213,-0.6561 -0.072,-0.6861 0.072,-0.6861 0.213,-0.6561 0.345,-0.5975 0.462,-0.5127 0.558,-0.4055 0.63,-0.2806 0.675,-0.1434 h 0.69 l 0.675,0.1434 0.63,0.2806 0.558,0.4055 0.462,0.5127 0.345,0.5975 0.213,0.6561 0.072,0.6861 -0.072,0.6861 -0.213,0.6561 -0.345,0.5975 -0.462,0.5127 -0.558,0.4055 -0.63,0.2806 -0.675,0.1434 z m -20,0 -0.675,-0.1434 -0.63,-0.2806 -0.558,-0.4055 -0.462,-0.5127 -0.345,-0.5975 -0.213,-0.6561 -0.072,-0.6861 0.072,-0.6861 0.213,-0.6561 0.345,-0.5975 0.462,-0.5127 0.558,-0.4055 0.63,-0.2806 0.675,-0.1434 h 0.69 l 0.675,0.1434 0.63,0.2806 0.558,0.4055 0.462,0.5127 0.345,0.5975 0.213,0.6561 0.072,0.6861 -0.072,0.6861 -0.213,0.6561 -0.345,0.5975 -0.462,0.5127 -0.558,0.4055 -0.63,0.2806 -0.675,0.1434 z m -20,0 -0.675,-0.1434 -0.63,-0.2806 -0.558,-0.4055 -0.462,-0.5127 -0.345,-0.5975 -0.213,-0.6561 -0.072,-0.6861 0.072,-0.6861 0.213,-0.6561 0.345,-0.5975 0.462,-0.5127 0.558,-0.4055 0.63,-0.2806 0.675,-0.1434 h 0.69 l 0.675,0.1434 0.63,0.2806 0.558,0.4055 0.462,0.5127 0.345,0.5975 0.213,0.6561 0.072,0.6861 -0.072,0.6861 -0.213,0.6561 -0.345,0.5975 -0.462,0.5127 -0.558,0.4055 -0.63,0.2806 -0.675,0.1434 z m -60.000003,0 -0.6748,-0.1434 -0.6302,-0.2806 -0.5581,-0.4055 -0.4617,-0.5127 -0.3449,-0.5975 -0.2132,-0.6561 -0.0721,-0.6861 0.0721,-0.6861 0.2132,-0.6561 0.3449,-0.5975 0.4617,-0.5127 0.5581,-0.4055 0.6302,-0.2806 0.6748,-0.1434 h 0.6899 l 0.6748,0.1434 0.6303,0.2806 0.5581,0.4055 0.4617,0.5127 0.3449,0.5975 0.2132,0.6561 0.0721,0.6861 -0.0721,0.6861 -0.2132,0.6561 -0.3449,0.5975 -0.4617,0.5127 -0.5581,0.4055 -0.6303,0.2806 -0.6748,0.1434 z m 20.0001,0 -0.6749,-0.1434 -0.6302,-0.2806 -0.5581,-0.4055 -0.4617,-0.5127 -0.3449,-0.5975 -0.2132,-0.6561 -0.0721,-0.6861 0.0721,-0.6861 0.2132,-0.6561 0.3449,-0.5975 0.4617,-0.5127 0.5581,-0.4055 0.6302,-0.2806 0.6749,-0.1434 h 0.6898 l 0.6748,0.1434 0.6303,0.2806 0.5581,0.4055 0.4617,0.5127 0.3449,0.5975 0.2132,0.6561 0.0721,0.6861 -0.0721,0.6861 -0.2132,0.6561 -0.3449,0.5975 -0.4617,0.5127 -0.5581,0.4055 -0.6303,0.2806 -0.6748,0.1434 z m 99.999903,0 -0.675,-0.1434 -0.63,-0.2806 -0.558,-0.4055 -0.462,-0.5127 -0.345,-0.5975 -0.213,-0.6561 -0.072,-0.6861 0.072,-0.6861 0.213,-0.6561 0.345,-0.5975 0.462,-0.5127 0.558,-0.4055 0.63,-0.2806 0.675,-0.1434 h 0.69 l 0.675,0.1434 0.63,0.2806 0.558,0.4055 0.462,0.5127 0.345,0.5975 0.213,0.6561 0.072,0.6861 -0.072,0.6861 -0.213,0.6561 -0.345,0.5975 -0.462,0.5127 -0.558,0.4055 -0.63,0.2806 -0.675,0.1434 z m -79.999903,0 -0.6749,-0.1434 -0.6302,-0.2806 -0.5581,-0.4055 -0.4617,-0.5127 -0.3449,-0.5975 -0.2132,-0.6561 -0.0721,-0.6861 0.0721,-0.6861 0.2132,-0.6561 0.3449,-0.5975 0.4617,-0.5127 0.5581,-0.4055 0.6302,-0.2806 0.6749,-0.1434 h 0.6898 l 0.6748,0.1434 0.6303,0.2806 0.5581,0.4055 0.4617,0.5127 0.3449,0.5975 0.2132,0.6561 0.0721,0.6861 -0.0721,0.6861 -0.2132,0.6561 -0.3449,0.5975 -0.4617,0.5127 -0.5581,0.4055 -0.6303,0.2806 -0.6748,0.1434 z m -60.0001,0 -0.6748,-0.1434 -0.6302,-0.2806 -0.5581,-0.4055 -0.4617,-0.5127 -0.3449,-0.5975 -0.2132,-0.6561 -0.0721,-0.6861 0.0721,-0.6861 0.2132,-0.6561 0.3449,-0.5975 0.4617,-0.5127 0.5581,-0.4055 0.6302,-0.2806 0.6748,-0.1434 h 0.6899 l 0.6748,0.1434 0.6303,0.2806 0.5581,0.4055 0.4617,0.5127 0.3449,0.5975 0.2132,0.6561 0.0721,0.6861 -0.0721,0.6861 -0.2132,0.6561 -0.3449,0.5975 -0.4617,0.5127 -0.5581,0.4055 -0.6303,0.2806 -0.6748,0.1434 z M 19.40212,16.6531 l -0.3763,0.6518 -0.5036,0.5593 -0.6089,0.4424 -0.6875,0.3061 -0.7362,0.1565 h -0.7526 l -0.7362,-0.1565 -0.6875,-0.3061 -0.6089,-0.4424 -0.5036,-0.5593 -0.3763,-0.6518 -0.2325,-0.7157 -0.0787,-0.7485 0.0787,-0.7485 0.2325,-0.7158 0.3763,-0.6517 0.5036,-0.5593 0.6089,-0.4424 0.6875,-0.3061 0.7362,-0.1565 h 0.7526 l 0.7362,0.1565 0.6875,0.3061 0.6089,0.4424 0.5036,0.5593 0.3763,0.6517 0.2325,0.7158 0.0787,0.7485 -0.0787,0.7485 z m 13.696497,-2.8064 0.3449,-0.5975 0.4617,-0.5127 0.5581,-0.4055 0.6302,-0.2806 0.6748,-0.1434 h 0.6899 l 0.6748,0.1434 0.6303,0.2806 0.5581,0.4055 0.4617,0.5127 0.3449,0.5975 0.2132,0.6561 0.0721,0.6861 -0.0721,0.6861 -0.2132,0.6561 -0.3449,0.5975 -0.4617,0.5127 -0.5581,0.4055 -0.6303,0.2806 -0.6748,0.1434 h -0.6899 l -0.6748,-0.1434 -0.6302,-0.2806 -0.5581,-0.4055 -0.4617,-0.5127 -0.3449,-0.5975 -0.2132,-0.6561 -0.0721,-0.6861 0.0721,-0.6861 z" + stroke="#000000" + fill="#d3d3d3" + stroke-width="0.5" + id="path116" /> + </g> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="Labels" + style="display:inline"> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="10.982465" + y="7.1965952" + id="text851"><tspan + sodipodi:role="line" + id="tspan849" + x="10.982465" + y="7.1965952" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Reset</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="30.483782" + y="7.1797137" + id="text855"><tspan + sodipodi:role="line" + id="tspan853" + x="30.483782" + y="7.1797137" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Speed</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="52.565861" + y="7.1780019" + id="text859"><tspan + sodipodi:role="line" + id="tspan857" + x="52.565861" + y="7.1780019" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Run</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="53.047592" + y="26.508728" + id="text863"><tspan + sodipodi:role="line" + id="tspan861" + x="53.047592" + y="26.508728" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Set</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="61.776833" + y="16.893724" + id="text871"><tspan + sodipodi:role="line" + id="tspan869" + x="61.776833" + y="16.893724" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Step</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="92.310364" + y="26.518877" + id="text875"><tspan + sodipodi:role="line" + id="tspan873" + x="92.310364" + y="26.518877" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Skip</tspan></text> + <path + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 187.43845,13.880819 c -0.15848,0 -0.29892,0.02544 -0.42065,0.07596 -0.12058,0.04938 -0.21572,0.123852 -0.28577,0.223759 -0.0701,0.09991 -0.11007,0.206304 -0.12041,0.318844 -0.009,0.111391 -0.0139,0.332681 -0.0139,0.664559 v 0.386023 c 0,0.307761 0.005,0.514869 0.0155,0.621667 0.0115,0.106798 0.0494,0.209347 0.11369,0.306958 0.0655,0.09646 0.15808,0.170532 0.27751,0.222209 0.11942,0.05168 0.27273,0.07751 0.45992,0.07751 0.15043,0 0.28175,-0.02239 0.39429,-0.06718 0.11369,-0.04479 0.20286,-0.107716 0.26716,-0.188102 0.0655,-0.08153 0.10549,-0.169786 0.12041,-0.2651 0.0149,-0.09532 0.0222,-0.24041 0.0222,-0.435632 v -0.222209 c 0,-0.164216 -0.0129,-0.294728 -0.0393,-0.391191 -0.0264,-0.09646 -0.0884,-0.179145 -0.18604,-0.248047 -0.0976,-0.0689 -0.21049,-0.103353 -0.33796,-0.103352 -0.10106,0 -0.18586,0.01895 -0.25477,0.05684 -0.0689,0.03675 -0.12098,0.09227 -0.15658,0.166915 v -0.444418 c 0,-0.104501 0.002,-0.173805 0.005,-0.208256 0.003,-0.03445 0.0163,-0.06241 0.0393,-0.08423 0.023,-0.02182 0.0523,-0.03307 0.0879,-0.03307 0.0425,0 0.0761,0.01166 0.10025,0.03462 0.0253,0.02297 0.039,0.05185 0.0413,0.0863 0.003,0.0333 0.005,0.114664 0.005,0.244429 h 0.69556 c 0,-0.174551 -0.0266,-0.319245 -0.0806,-0.434082 -0.054,-0.114836 -0.14355,-0.204007 -0.26872,-0.267167 -0.12517,-0.06316 -0.28537,-0.09457 -0.48059,-0.09457 z m -36.37194,0.0015 -0.83199,2.895947 h 0.5271 l 0.82682,-2.895947 z m 1.39526,0 -0.83199,2.895947 h 0.5271 l 0.82682,-2.895947 z m 22.34334,0 -0.83199,2.895947 h 0.5271 l 0.82682,-2.895947 z m 7.08122,0 c -0.14125,0 -0.26223,0.02239 -0.36328,0.06718 -0.10106,0.04479 -0.18334,0.111161 -0.2465,0.198437 -0.0632,0.08728 -0.10278,0.17593 -0.11886,0.26665 -0.0161,0.08957 -0.0243,0.212793 -0.0243,0.36897 v 0.101286 h 0.62373 v -0.2651 c 0,-0.122875 0.0125,-0.205156 0.0377,-0.246497 0.0264,-0.04134 0.066,-0.06201 0.11886,-0.06201 0.0528,0 0.092,0.01895 0.11731,0.05684 0.0264,0.03675 0.0398,0.09319 0.0398,0.168982 0,0.09876 -0.0431,0.236563 -0.12919,0.413411 -0.085,0.1757 -0.35462,0.6343 -0.80822,1.376144 v 0.397961 h 1.53169 V 16.24915 h -0.76327 c 0.39045,-0.577628 0.62512,-0.955268 0.70435,-1.133264 0.0804,-0.177997 0.12093,-0.346807 0.12093,-0.506429 0,-0.210151 -0.0716,-0.383726 -0.21394,-0.520382 -0.14125,-0.137804 -0.35008,-0.206706 -0.62684,-0.206706 z m 1.77095,0 c -0.14125,0 -0.26223,0.02239 -0.36328,0.06718 -0.10106,0.04479 -0.18334,0.111161 -0.2465,0.198437 -0.0632,0.08728 -0.10278,0.17593 -0.11885,0.26665 -0.0161,0.08957 -0.0243,0.212793 -0.0243,0.36897 v 0.101286 h 0.62373 v -0.2651 c 0,-0.122875 0.0125,-0.205156 0.0377,-0.246497 0.0264,-0.04134 0.066,-0.06201 0.11885,-0.06201 0.0528,0 0.092,0.01895 0.11731,0.05684 0.0264,0.03675 0.0398,0.09319 0.0398,0.168982 0,0.09876 -0.0431,0.236563 -0.12919,0.413411 -0.085,0.1757 -0.35462,0.6343 -0.80822,1.376144 v 0.397961 h 1.53169 V 16.24915 h -0.76326 c 0.39044,-0.577628 0.62511,-0.955268 0.70435,-1.133264 0.0804,-0.177997 0.12092,-0.346807 0.12092,-0.506429 0,-0.210151 -0.0715,-0.383726 -0.21394,-0.520382 -0.14125,-0.137804 -0.35009,-0.206706 -0.62684,-0.206706 z m 1.85674,0 c -0.18719,0 -0.34647,0.03882 -0.47853,0.115756 -0.13091,0.07694 -0.21876,0.178972 -0.26355,0.306441 -0.0436,0.127468 -0.0656,0.319073 -0.0656,0.575158 v 0.973584 c 0,0.196371 0.0138,0.339745 0.0414,0.430465 0.0276,0.08957 0.0741,0.175298 0.13952,0.256832 0.0655,0.08153 0.15331,0.141823 0.26355,0.180867 0.11024,0.0379 0.24845,0.05684 0.41496,0.05684 0.12632,0 0.24093,-0.01854 0.34313,-0.05529 0.10221,-0.03675 0.18914,-0.09704 0.26149,-0.180868 0.0723,-0.08383 0.12017,-0.173805 0.14314,-0.270267 0.023,-0.09646 0.0346,-0.250689 0.0346,-0.461988 v -0.930176 c 0,-0.211299 -0.0113,-0.365007 -0.0331,-0.46147 -0.0207,-0.09646 -0.0607,-0.182992 -0.1204,-0.259933 -0.0597,-0.07694 -0.14969,-0.141995 -0.27027,-0.19482 -0.12058,-0.05397 -0.25758,-0.08113 -0.41031,-0.08113 z m 3.72225,0 -0.83199,2.895947 h 0.5271 l 0.82682,-2.895947 z m -47.101,0.05374 v 2.788514 h 0.69608 v -1.630908 c 0,-0.115985 0.007,-0.1935 0.0222,-0.232544 0.0149,-0.03904 0.0438,-0.05891 0.0863,-0.05891 0.0459,0 0.0752,0.01895 0.0879,0.05684 0.0138,0.0379 0.0207,0.123621 0.0207,0.256832 v 1.60869 h 0.69557 v -1.576131 c 0,-0.214744 -0.009,-0.361965 -0.0289,-0.44235 -0.0184,-0.08153 -0.071,-0.153479 -0.1571,-0.215491 -0.085,-0.06201 -0.18833,-0.09302 -0.31006,-0.09302 -0.0792,0 -0.15371,0.01378 -0.22375,0.04134 -0.0689,0.02756 -0.13304,0.0689 -0.19276,0.124024 v -0.626832 z m 11.62565,0 c -0.15503,0 -0.26964,0.01034 -0.34313,0.03101 -0.0735,0.02067 -0.13075,0.05076 -0.17209,0.09095 -0.0402,0.03904 -0.0656,0.08383 -0.076,0.134359 -0.0103,0.05053 -0.0155,0.151354 -0.0155,0.30179 h -0.14263 v 0.361735 h 0.14263 v 1.86867 h 0.69608 v -1.86862 h 0.16536 v -0.361735 h -0.293 v -0.07235 c 0,-0.06201 0.013,-0.09951 0.0382,-0.112138 0.0264,-0.01378 0.11122,-0.02067 0.25476,-0.02067 v -0.35295 z m 6.17326,0 v 2.788514 h 0.65113 l 0.045,-0.172082 c 0.0586,0.0712 0.12271,0.124597 0.19276,0.160196 0.0712,0.0356 0.14791,0.05323 0.22944,0.05323 0.11369,0 0.21187,-0.02969 0.29456,-0.0894 0.0827,-0.06086 0.13476,-0.13189 0.15658,-0.213424 0.023,-0.08268 0.0346,-0.208026 0.0346,-0.375687 v -1.029912 c 0,-0.168809 -0.004,-0.279052 -0.0124,-0.330729 -0.007,-0.05168 -0.0284,-0.104674 -0.0651,-0.158646 -0.0367,-0.05397 -0.0901,-0.09572 -0.1602,-0.125574 -0.07,-0.02986 -0.15273,-0.04496 -0.24805,-0.04496 -0.0827,0 -0.15979,0.01682 -0.23099,0.05013 -0.07,0.03215 -0.13379,0.08119 -0.19121,0.147795 v -0.659397 z m 3.63647,0 v 2.788514 h 0.71624 v -2.78846 z m 14.96705,0 v 0.363285 h 0.71675 v -0.363231 z m -34.51779,0.19792 v 0.360185 h -0.14986 v 0.361735 h 0.14986 v 1.160653 c 0,0.227376 0.006,0.37207 0.0186,0.434082 0.0126,0.06086 0.045,0.115583 0.0966,0.163814 0.0517,0.04708 0.11156,0.07769 0.17932,0.09147 0.0678,0.01263 0.18052,0.0186 0.33899,0.0186 h 0.28112 v -0.368453 c -0.11369,0 -0.17874,-0.0086 -0.19482,-0.02584 -0.0149,-0.01723 -0.0222,-0.101229 -0.0222,-0.251664 v -1.222608 h 0.18759 v -0.361735 h -0.18759 v -0.360185 z m 1.07487,0 v 0.360185 h -0.14986 v 0.361735 h 0.14986 v 1.160653 c 0,0.227376 0.006,0.37207 0.0186,0.434082 0.0126,0.06086 0.045,0.115583 0.0966,0.163814 0.0517,0.04708 0.11156,0.07769 0.17932,0.09147 0.0678,0.01263 0.18052,0.0186 0.33899,0.0186 h 0.28112 v -0.368453 c -0.11369,0 -0.17874,-0.0086 -0.19482,-0.02584 -0.0149,-0.01723 -0.0222,-0.101229 -0.0222,-0.251664 v -1.222608 h 0.18759 v -0.361735 h -0.18759 v -0.360185 z m 27.943,0 v 0.360185 h -0.14987 v 0.361735 h 0.14987 v 1.160653 c 0,0.227376 0.006,0.37207 0.0191,0.434082 0.0126,0.06086 0.0444,0.115583 0.0961,0.163814 0.0517,0.04708 0.11157,0.07769 0.17932,0.09147 0.0677,0.01263 0.18104,0.0186 0.33952,0.0186 h 0.2806 v -0.368453 c -0.11369,0 -0.17874,-0.0086 -0.19482,-0.02584 -0.0149,-0.01723 -0.0222,-0.101229 -0.0222,-0.251664 v -1.222608 h 0.18758 v -0.361735 h -0.18758 v -0.360185 z m 12.49174,0.177251 c 0.0528,0 0.0865,0.01895 0.10025,0.05684 0.0149,0.03675 0.0222,0.129363 0.0222,0.277502 v 1.381311 c 0,0.136656 -0.008,0.224506 -0.0243,0.26355 -0.0161,0.03904 -0.0496,0.05891 -0.10129,0.05891 -0.0517,0 -0.0857,-0.01682 -0.1018,-0.05013 -0.0149,-0.0333 -0.0222,-0.131086 -0.0222,-0.293005 v -1.360641 c 0,-0.143545 0.008,-0.234841 0.0238,-0.273885 0.0172,-0.04019 0.0517,-0.06046 0.10335,-0.06046 z m -38.2509,0.0863 c -0.0884,0 -0.16978,0.02027 -0.24442,0.06046 -0.0747,0.04019 -0.14315,0.100884 -0.20516,0.182418 l 0.0124,-0.201539 h -0.70796 v 2.611211 h 0.69556 v -0.523483 c 0.0609,0.07924 0.12804,0.139125 0.20154,0.179318 0.0735,0.04019 0.15365,0.05994 0.23978,0.05994 0.10794,0 0.19964,-0.02584 0.27543,-0.07751 0.0769,-0.05282 0.1273,-0.12253 0.15142,-0.209806 0.0253,-0.08842 0.0382,-0.236563 0.0382,-0.444417 v -0.963249 c 0,-0.181442 -0.01,-0.309714 -0.0295,-0.385506 -0.0195,-0.07579 -0.0691,-0.14257 -0.14831,-0.199988 -0.0781,-0.05857 -0.17111,-0.08785 -0.27906,-0.08785 z m 1.35393,0 c -0.15274,0 -0.28709,0.02371 -0.40308,0.0708 -0.11483,0.04708 -0.1962,0.114262 -0.24443,0.201538 -0.0482,0.08613 -0.0723,0.220486 -0.0723,0.403076 0,0.128617 0.0224,0.239664 0.0672,0.33383 0.0448,0.09302 0.16921,0.197289 0.37362,0.312126 0.24346,0.135507 0.37874,0.216868 0.40515,0.244429 0.0253,0.02756 0.0377,0.09606 0.0377,0.205156 0,0.07924 -0.01,0.131316 -0.0294,0.156579 -0.0195,0.02412 -0.054,0.03617 -0.10336,0.03617 -0.0459,0 -0.0769,-0.01855 -0.093,-0.05529 -0.0149,-0.03675 -0.0222,-0.116387 -0.0222,-0.239262 v -0.144694 h -0.6165 v 0.110071 c 0,0.190629 0.0232,0.333198 0.0703,0.427364 0.0471,0.09417 0.13321,0.168637 0.25838,0.223759 0.12632,0.05512 0.2779,0.08268 0.45475,0.08268 0.15962,0 0.2957,-0.02492 0.40824,-0.07545 0.11369,-0.05168 0.19465,-0.124942 0.24288,-0.219108 0.0482,-0.09531 0.0724,-0.235645 0.0724,-0.42168 0,-0.166513 -0.0314,-0.29358 -0.0946,-0.380855 -0.0632,-0.08728 -0.19579,-0.180294 -0.39791,-0.279053 -0.15158,-0.07464 -0.25189,-0.131488 -0.30127,-0.170532 -0.0482,-0.03904 -0.0775,-0.07482 -0.0879,-0.106971 -0.009,-0.0333 -0.0139,-0.08498 -0.0139,-0.155029 0,-0.05168 0.01,-0.08997 0.0294,-0.115238 0.0195,-0.02641 0.0488,-0.03979 0.0879,-0.03979 0.0482,0 0.0779,0.0147 0.0894,0.04341 0.0126,0.02756 0.0191,0.09382 0.0191,0.199471 v 0.124023 h 0.6165 v -0.132291 c 0,-0.114837 -0.006,-0.199241 -0.0191,-0.253215 -0.0115,-0.05397 -0.0459,-0.11254 -0.10335,-0.1757 -0.0563,-0.06316 -0.13763,-0.114032 -0.24443,-0.151928 -0.10565,-0.03904 -0.23444,-0.0584 -0.38602,-0.0584 z m 6.62336,0 c -0.19177,0.01263 -0.33819,0.126321 -0.43924,0.341065 l 0.0274,-0.299724 h -0.69608 v 2.285702 h 0.69608 v -0.90227 c 0,-0.221635 0.007,-0.362884 0.0207,-0.423747 0.0138,-0.06201 0.0504,-0.110243 0.11006,-0.144694 0.0597,-0.03445 0.15366,-0.05168 0.28112,-0.05168 z m 0.90951,0 c -0.18603,0 -0.33894,0.03617 -0.45837,0.108521 -0.11943,0.07235 -0.20211,0.168408 -0.24805,0.287838 -0.0459,0.11943 -0.0687,0.285197 -0.0687,0.497643 v 0.585495 c 0,0.194073 0.0125,0.340088 0.0377,0.437699 0.0253,0.09646 0.067,0.179145 0.12557,0.248047 0.0597,0.06775 0.14332,0.119028 0.25012,0.153479 0.10679,0.0333 0.23679,0.04961 0.39067,0.04961 0.1378,0 0.2597,-0.01935 0.36535,-0.05839 0.1068,-0.04019 0.19425,-0.101803 0.262,-0.184485 0.0678,-0.08383 0.11162,-0.173403 0.13229,-0.268718 0.0207,-0.09646 0.031,-0.247128 0.031,-0.452685 v -0.560173 c 0,-0.161919 -0.0112,-0.282497 -0.0341,-0.361735 -0.0218,-0.07924 -0.0632,-0.155833 -0.12402,-0.230476 -0.0609,-0.07464 -0.14791,-0.134933 -0.26045,-0.180868 -0.11139,-0.04708 -0.24483,-0.0708 -0.40101,-0.0708 z m 2.17196,0 c -0.0953,0 -0.18012,0.02199 -0.25476,0.06563 -0.0747,0.04249 -0.13878,0.106626 -0.19276,0.192754 l 0.0119,-0.217042 h -0.6873 v 2.285701 h 0.67541 v -1.584399 c 0,-0.110243 8.1e-4,-0.182188 0.003,-0.215491 0.002,-0.03445 0.0144,-0.06333 0.0362,-0.0863 0.0218,-0.02412 0.0486,-0.03617 0.0796,-0.03617 0.0494,0 0.0791,0.02239 0.0894,0.06718 0.0115,0.04479 0.017,0.179145 0.017,0.403076 v 1.452104 h 0.67541 v -1.489831 c 0,-0.196371 0.007,-0.317351 0.0207,-0.363286 0.0149,-0.04593 0.0473,-0.06925 0.0966,-0.06925 0.0482,0 0.0783,0.02371 0.0909,0.0708 0.0138,0.04594 0.0207,0.166514 0.0207,0.361736 v 1.489831 h 0.67541 v -1.62419 c 0,-0.187184 -0.0107,-0.321944 -0.0326,-0.404627 -0.0218,-0.08383 -0.0718,-0.154455 -0.14986,-0.211873 -0.0769,-0.05742 -0.17472,-0.0863 -0.293,-0.0863 -0.0896,0 -0.17094,0.02199 -0.24443,0.06563 -0.0735,0.04249 -0.13987,0.106626 -0.19844,0.192754 -0.1068,-0.172255 -0.25321,-0.258383 -0.43925,-0.258383 z m 4.17907,0 c -0.15962,0 -0.30087,0.03101 -0.42374,0.09302 -0.12288,0.06086 -0.21164,0.149115 -0.26562,0.2651 -0.054,0.114837 -0.0806,0.272507 -0.0806,0.472323 v 0.666625 c -1e-5,0.169958 0.012,0.299552 0.0362,0.389124 0.0241,0.08842 0.0672,0.169786 0.12919,0.24443 0.0632,0.0735 0.15101,0.13166 0.26355,0.174149 0.11254,0.04249 0.24213,0.06356 0.38912,0.06356 0.15159,0 0.27733,-0.02107 0.37724,-0.06356 0.10106,-0.04364 0.18414,-0.108693 0.2496,-0.19482 0.0655,-0.08613 0.1068,-0.167087 0.12402,-0.242879 0.0184,-0.07579 0.0279,-0.184313 0.0279,-0.325562 v -0.168465 h -0.65991 v 0.301274 c 0,0.113688 -0.009,0.1908 -0.0274,0.230993 -0.0172,0.03904 -0.0526,0.05839 -0.10542,0.05839 -0.0425,0 -0.0709,-0.0151 -0.0858,-0.04496 -0.0149,-0.02986 -0.0227,-0.09612 -0.0227,-0.199471 v -0.494543 h 0.90124 v -0.303341 c 0,-0.221634 -0.0258,-0.39297 -0.0775,-0.514697 -0.0505,-0.122875 -0.1397,-0.22106 -0.26716,-0.294556 -0.12632,-0.07464 -0.28692,-0.112138 -0.48215,-0.112138 z m 2.77503,0 c -0.18604,0 -0.33894,0.03617 -0.45837,0.108521 -0.11943,0.07235 -0.20211,0.168408 -0.24805,0.287838 -0.0459,0.11943 -0.0687,0.285197 -0.0687,0.497643 v 0.585495 c 0,0.194073 0.0125,0.340088 0.0377,0.437699 0.0253,0.09646 0.0675,0.179145 0.12609,0.248047 0.0597,0.06775 0.1428,0.119028 0.24959,0.153479 0.1068,0.0333 0.23731,0.04961 0.39119,0.04961 0.13781,0 0.25919,-0.01935 0.36484,-0.05839 0.1068,-0.04019 0.19424,-0.101803 0.262,-0.184485 0.0677,-0.08383 0.11214,-0.173403 0.13281,-0.268718 0.0207,-0.09646 0.031,-0.247128 0.031,-0.452685 v -0.560173 c 0,-0.161919 -0.0117,-0.282497 -0.0346,-0.361735 -0.0218,-0.07924 -0.0632,-0.155833 -0.12402,-0.230476 -0.0609,-0.07464 -0.14739,-0.134933 -0.25994,-0.180868 -0.11139,-0.04708 -0.24534,-0.0708 -0.40152,-0.0708 z m 5.19503,0 c -0.0953,0 -0.17972,0.02107 -0.25321,0.06356 -0.0724,0.04134 -0.13396,0.104272 -0.18449,0.188103 l 0.0124,-0.210324 h -0.70796 v 2.285704 h 0.69556 v -1.545125 c 0,-0.172255 0.006,-0.277732 0.0191,-0.316777 0.0126,-0.04019 0.0436,-0.06046 0.093,-0.06046 0.0471,0 0.076,0.01722 0.0863,0.05168 0.0103,0.03445 0.0155,0.130512 0.0155,0.287838 v 1.582844 h 0.69557 v -1.601969 c 0,-0.199816 -0.0107,-0.341869 -0.0326,-0.426848 -0.0218,-0.08613 -0.0705,-0.15767 -0.14624,-0.21394 -0.0758,-0.05627 -0.17358,-0.08423 -0.29301,-0.08423 z m 1.46089,0 c -0.15962,0 -0.30087,0.03101 -0.42374,0.09302 -0.12288,0.06086 -0.21165,0.149115 -0.26562,0.2651 -0.054,0.114837 -0.0806,0.272507 -0.0806,0.472323 v 0.666625 c 0,0.169958 0.0121,0.299552 0.0362,0.389124 0.0241,0.08842 0.0672,0.169786 0.12919,0.24443 0.0632,0.0735 0.15101,0.13166 0.26355,0.174149 0.11254,0.04249 0.24213,0.06356 0.38912,0.06356 0.15159,0 0.27733,-0.02107 0.37724,-0.06356 0.10106,-0.04364 0.18414,-0.108693 0.2496,-0.19482 0.0654,-0.08613 0.1068,-0.167087 0.12402,-0.242879 0.0184,-0.07579 0.0279,-0.184313 0.0279,-0.325562 v -0.168465 h -0.65991 v 0.301274 c 0,0.113688 -0.009,0.1908 -0.0274,0.230993 -0.0172,0.03904 -0.0526,0.05839 -0.10542,0.05839 -0.0425,0 -0.0709,-0.0151 -0.0858,-0.04496 -0.0149,-0.02986 -0.0227,-0.09612 -0.0227,-0.199471 v -0.494543 h 0.90124 v -0.303341 c 0,-0.221634 -0.0258,-0.39297 -0.0775,-0.514697 -0.0505,-0.122875 -0.1397,-0.22106 -0.26716,-0.294556 -0.12632,-0.07464 -0.28692,-0.112138 -0.48215,-0.112138 z m 4.27365,0 c -0.15963,0 -0.30088,0.03101 -0.42375,0.09302 -0.12288,0.06086 -0.21165,0.149115 -0.26562,0.2651 -0.054,0.114837 -0.0806,0.272507 -0.0806,0.472323 v 0.666625 c 0,0.169958 0.012,0.299552 0.0362,0.389124 0.0241,0.08842 0.0672,0.169786 0.12919,0.24443 0.0632,0.0735 0.15101,0.13166 0.26355,0.174149 0.11254,0.04249 0.24213,0.06356 0.38912,0.06356 0.15159,0 0.27733,-0.02107 0.37724,-0.06356 0.10106,-0.04364 0.18414,-0.108693 0.2496,-0.19482 0.0654,-0.08613 0.1068,-0.167087 0.12402,-0.242879 0.0184,-0.07579 0.0279,-0.184313 0.0279,-0.325562 v -0.168465 h -0.65991 v 0.301274 c 0,0.113688 -0.009,0.1908 -0.0274,0.230993 -0.0172,0.03904 -0.0526,0.05839 -0.10542,0.05839 -0.0425,0 -0.0709,-0.0151 -0.0858,-0.04496 -0.0149,-0.02986 -0.0227,-0.09612 -0.0227,-0.199471 v -0.494543 h 0.90124 v -0.303341 c 0,-0.221634 -0.0258,-0.39297 -0.0775,-0.514697 -0.0505,-0.122875 -0.1397,-0.22106 -0.26717,-0.294556 -0.12632,-0.07464 -0.28691,-0.112138 -0.48213,-0.112138 z m 2.16162,0 c -0.19178,0.01263 -0.33819,0.126321 -0.43925,0.341065 l 0.0274,-0.299724 h -0.69557 v 2.285702 h 0.69557 v -0.90227 c 0,-0.221635 0.007,-0.362884 0.0207,-0.423747 0.0138,-0.06201 0.0509,-0.110243 0.11059,-0.144694 0.0597,-0.03445 0.15313,-0.05168 0.2806,-0.05168 z m 1.78955,0 c -0.15273,0 -0.28709,0.02371 -0.40307,0.0708 -0.11484,0.04708 -0.1962,0.114262 -0.24443,0.201538 -0.0482,0.08613 -0.0724,0.220486 -0.0724,0.403076 0,0.128617 0.0224,0.239664 0.0672,0.33383 0.0448,0.09302 0.16921,0.197289 0.37362,0.312126 0.24345,0.135507 0.37873,0.216868 0.40514,0.244429 0.0253,0.02756 0.0377,0.09606 0.0377,0.205156 0,0.07924 -0.01,0.131316 -0.0295,0.156579 -0.0195,0.02412 -0.054,0.03617 -0.10335,0.03617 -0.0459,0 -0.0769,-0.01855 -0.093,-0.05529 -0.0149,-0.03675 -0.0222,-0.116387 -0.0222,-0.239262 v -0.144694 h -0.6165 v 0.110071 c 0,0.190629 0.0232,0.333198 0.0703,0.427364 0.0471,0.09417 0.13321,0.168637 0.25838,0.223759 0.12632,0.05512 0.27791,0.08268 0.45476,0.08268 0.15962,0 0.2957,-0.02492 0.40824,-0.07545 0.11369,-0.05168 0.19465,-0.124942 0.24288,-0.219108 0.0482,-0.09531 0.0724,-0.235645 0.0724,-0.42168 0,-0.166513 -0.0314,-0.29358 -0.0946,-0.380855 -0.0632,-0.08728 -0.1958,-0.180294 -0.39791,-0.279053 -0.15158,-0.07464 -0.2519,-0.131488 -0.30127,-0.170532 -0.0482,-0.03904 -0.0775,-0.07482 -0.0879,-0.106971 -0.009,-0.0333 -0.014,-0.08498 -0.014,-0.155029 0,-0.05168 0.01,-0.08997 0.0295,-0.115238 0.0195,-0.02641 0.0488,-0.03979 0.0878,-0.03979 0.0482,0 0.0779,0.0147 0.0894,0.04341 0.0126,0.02756 0.0191,0.09382 0.0191,0.199471 v 0.124023 h 0.6165 v -0.132291 c 0,-0.114837 -0.006,-0.199241 -0.0191,-0.253215 -0.0115,-0.05397 -0.0459,-0.11254 -0.10335,-0.1757 -0.0563,-0.06316 -0.13763,-0.114032 -0.24443,-0.151928 -0.10565,-0.03904 -0.23444,-0.0584 -0.38603,-0.0584 z m -13.96607,0.04134 0.29456,2.285649 h 0.75602 l 0.0775,-0.496094 c 0.0333,-0.204409 0.0591,-0.406349 0.0775,-0.606164 0.054,0.455901 0.10181,0.823205 0.14315,1.102258 h 0.75605 l 0.27751,-2.285649 h -0.59945 c -0.0838,0.490352 -0.13683,0.926157 -0.15865,1.307414 l -0.14108,-1.307414 h -0.57722 c -0.0965,0.788927 -0.14814,1.224733 -0.15503,1.307414 -0.0965,-0.811893 -0.14682,-1.247698 -0.15141,-1.307414 z m 12.33155,0 v 2.285703 h 0.71675 v -2.285649 z m -31.60014,0.363286 c 0.0471,0 0.076,0.0151 0.0863,0.04496 0.0103,0.02986 0.0155,0.115583 0.0155,0.256832 v 0.979785 c 0,0.121727 -0.006,0.19884 -0.0171,0.230994 -0.0103,0.03101 -0.0379,0.04651 -0.0827,0.04651 -0.0459,0 -0.0761,-0.01723 -0.0899,-0.05168 -0.0138,-0.03445 -0.0207,-0.120578 -0.0207,-0.258382 v -0.947229 c 0,-0.132062 0.006,-0.215663 0.0191,-0.250114 0.0138,-0.03445 0.0435,-0.05168 0.0894,-0.05168 z m 9.25163,0 c 0.0413,0 0.0685,0.0155 0.0811,0.04651 0.0126,0.02986 0.0191,0.103526 0.0191,0.220659 v 1.054199 c 0,0.09876 -0.007,0.162896 -0.0207,0.192753 -0.0126,0.02986 -0.0398,0.04496 -0.0811,0.04496 -0.0402,0 -0.0674,-0.0159 -0.0811,-0.04806 -0.0138,-0.0333 -0.0207,-0.103928 -0.0207,-0.211874 v -1.031978 c 0,-0.117133 0.007,-0.190801 0.0207,-0.220659 0.0138,-0.03101 0.0413,-0.04651 0.0827,-0.04651 z m 4.54288,0 c 0.0436,0 0.0729,0.01855 0.0879,0.05529 0.0149,0.0356 0.0222,0.112712 0.0222,0.230993 v 0.962732 c 0,0.135507 -0.007,0.221233 -0.0207,0.256832 -0.0126,0.0356 -0.0406,0.05323 -0.0842,0.05323 -0.0425,0 -0.0714,-0.01723 -0.0863,-0.05168 -0.0138,-0.03445 -0.0207,-0.113286 -0.0207,-0.236161 v -0.984953 c 1e-5,-0.127468 0.006,-0.206706 0.0191,-0.237711 0.0126,-0.03215 0.0402,-0.04858 0.0827,-0.04858 z m 1.81694,0 c 0.0391,0 0.0649,0.01722 0.0775,0.05168 0.0126,0.03445 0.0191,0.111162 0.0191,0.229444 v 0.166914 H 162.442 V 15.08328 c 0,-0.128617 0.006,-0.207453 0.0176,-0.236162 0.0115,-0.02986 0.0412,-0.04496 0.0894,-0.04496 z m 2.76676,0 c 0.0413,0 0.068,0.0155 0.0806,0.04651 0.0126,0.02986 0.0191,0.103526 0.0191,0.220659 v 1.054199 c 0,0.09876 -0.007,0.162896 -0.0207,0.192753 -0.0126,0.02986 -0.0398,0.04496 -0.0811,0.04496 -0.0402,0 -0.0668,-0.0159 -0.0806,-0.04806 -0.0138,-0.0333 -0.0207,-0.103928 -0.0207,-0.211874 v -1.031978 c 0,-0.117133 0.007,-0.190801 0.0207,-0.220659 0.0138,-0.03101 0.0414,-0.04651 0.0827,-0.04651 z m 6.66419,0 c 0.039,0 0.0649,0.01722 0.0775,0.05168 0.0126,0.03445 0.0191,0.111162 0.0191,0.229444 v 0.166914 h -0.2036 V 15.08328 c 0,-0.128617 0.006,-0.207453 0.0176,-0.236162 0.0115,-0.02986 0.0412,-0.04496 0.0894,-0.04496 z m 4.27364,0 c 0.039,0 0.0649,0.01722 0.0775,0.05168 0.0126,0.03445 0.0191,0.111162 0.0191,0.229444 v 0.166914 h -0.20361 V 15.08328 c 0,-0.128617 0.006,-0.207453 0.0176,-0.236162 0.0115,-0.02986 0.0412,-0.04496 0.0894,-0.04496 z m -26.62887,0.10697 v 0.56689 h 0.52555 v -0.56689 z m 37.80855,0.378788 c 0.0494,0 0.0846,0.01855 0.10645,0.05529 0.0218,0.03675 0.0331,0.104329 0.0331,0.203088 v 0.521932 c 0,0.128617 -0.0164,0.207855 -0.0486,0.237712 -0.0322,0.02871 -0.0632,0.04341 -0.093,0.04341 -0.0494,0 -0.0846,-0.01895 -0.10645,-0.05684 -0.0207,-0.0379 -0.031,-0.118454 -0.031,-0.241329 v -0.504879 c 0,-0.102204 0.0107,-0.170187 0.0326,-0.204638 0.023,-0.0356 0.0587,-0.05374 0.10697,-0.05374 z m -37.80855,0.868218 v 0.568441 h 0.52555 v -0.568441 z m 19.01538,0 v 0.568441 h 0.52504 v -0.568441 z" + id="text987" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="148.69678" + y="11.622226" + id="text987-3"><tspan + sodipodi:role="line" + id="tspan985-6" + x="148.69678" + y="11.622226" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:11.2889px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Eris 2206</tspan></text> + <g + id="g72395" + transform="translate(-0.44679485,4.632698)"> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:3.70417px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="165.07814" + y="21.829409" + id="text991"><tspan + sodipodi:role="line" + id="tspan989" + x="165.07814" + y="21.829409" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Demo:</tspan><tspan + sodipodi:role="line" + x="165.07814" + y="26.062738" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px" + id="tspan1007">Load:</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:3.70417px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="177.38087" + y="22.135914" + id="text991-3"><tspan + sodipodi:role="line" + id="tspan989-6" + x="177.38087" + y="22.135914" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$1D $80</tspan><tspan + sodipodi:role="line" + x="177.38087" + y="26.369244" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px" + id="tspan1009-7">$1D $C0</tspan><tspan + sodipodi:role="line" + x="177.38087" + y="30.337994" + id="tspan1007-5" /></text> + </g> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="101.60313" + y="36.656078" + id="text947"><tspan + sodipodi:role="line" + id="tspan945" + x="101.60313" + y="36.656078" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Data</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 99.407531,34.895833 h -63 l 0,3.46875" + id="path949" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 113.40753,34.895833 h 63 l 0,3.46875" + id="path951" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="175.50789" + y="55.514313" + id="text955"><tspan + sodipodi:role="line" + id="tspan953" + x="175.50789" + y="55.514313" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">0</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="155.22534" + y="55.523407" + id="text959"><tspan + sodipodi:role="line" + id="tspan957" + x="155.22534" + y="55.523407" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">1</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="135.08871" + y="55.521759" + id="text963"><tspan + sodipodi:role="line" + id="tspan961" + x="135.08871" + y="55.521759" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">2</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="115.10616" + y="55.470818" + id="text967"><tspan + sodipodi:role="line" + id="tspan965" + x="115.10616" + y="55.470818" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">3</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="94.920792" + y="55.559963" + id="text971"><tspan + sodipodi:role="line" + id="tspan969" + x="94.920792" + y="55.559963" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">4</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="75.036369" + y="55.445679" + id="text975"><tspan + sodipodi:role="line" + id="tspan973" + x="75.036369" + y="55.445679" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">5</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="54.947971" + y="55.459869" + id="text979"><tspan + sodipodi:role="line" + id="tspan977" + x="54.947971" + y="55.459869" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">6</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="35.208584" + y="55.515778" + id="text983"><tspan + sodipodi:role="line" + id="tspan981" + x="35.208584" + y="55.515778" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">7</tspan></text> + </g> +</svg> diff --git a/case/dst/labeled/top_plate/acryl_top_plate.svg b/case/dst/labeled/top_plate/acryl_top_plate.svg @@ -0,0 +1,781 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="200mm" + height="200mm" + viewBox="0 -200 200 200" + version="1.1" + id="svg2589" + sodipodi:docname="acryl_top_plate.svg" + inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata2595"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title>OpenSCAD Model</dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs2593" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1680" + inkscape:window-height="986" + id="namedview2591" + showgrid="true" + showguides="true" + inkscape:guide-bbox="true" + inkscape:zoom="9.9906665" + inkscape:cx="200.68731" + inkscape:cy="47.194048" + inkscape:window-x="1920" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer2" + inkscape:snap-bbox="true" + inkscape:bbox-paths="true" + inkscape:bbox-nodes="true" + inkscape:snap-bbox-edge-midpoints="true" + inkscape:snap-bbox-midpoints="true" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm"> + <sodipodi:guide + position="32.359124,181.42083" + orientation="0,1" + id="guide3294" + inkscape:locked="false" /> + <inkscape:grid + type="xygrid" + id="grid3296" /> + <sodipodi:guide + position="16.737288,126.48305" + orientation="1,0" + id="guide3817" + inkscape:locked="false" /> + <sodipodi:guide + position="182.83898,101.95975" + orientation="1,0" + id="guide3819" + inkscape:locked="false" /> + </sodipodi:namedview> + <title + id="title2585">OpenSCAD Model</title> + <g + inkscape:groupmode="layer" + id="layer3" + inkscape:label="Aux" + style="display:none"> + <path + inkscape:connector-curvature="0" + style="fill:#d3d3d3;stroke:#000000;stroke-width:0.5" + d="M 200,-200 H 0 V 2.3706049e-7 H 200 Z M 9.79094,-188.011 9.38196,-188.098 9,-188.268 8.66173,-188.514 8.38196,-188.824 8.1729,-189.187 8.0437,-189.584 8,-190 l 0.0437,-0.416 0.1292,-0.397 0.20906,-0.363 0.27977,-0.31 0.33827,-0.246 0.38196,-0.17 0.40898,-0.087 H 10.209 l 0.409,0.087 0.382,0.17 0.3383,0.246 0.2797,0.31 0.2091,0.363 0.1292,0.397 L 12,-190 l -0.0437,0.416 -0.1292,0.397 -0.2091,0.363 -0.2797,0.31 -0.3383,0.246 -0.382,0.17 -0.409,0.087 z m 180.00006,0 -0.409,-0.087 -0.382,-0.17 -0.338,-0.246 -0.28,-0.31 -0.209,-0.363 -0.129,-0.397 L 188,-190 l 0.044,-0.416 0.129,-0.397 0.209,-0.363 0.28,-0.31 0.338,-0.246 0.382,-0.17 0.409,-0.087 h 0.418 l 0.409,0.087 0.382,0.17 0.338,0.246 0.28,0.31 0.209,0.363 0.129,0.397 0.044,0.416 -0.044,0.416 -0.129,0.397 -0.209,0.363 -0.28,0.31 -0.338,0.246 -0.382,0.17 -0.409,0.087 z M 20,-20.000002 V -180 h 160 v 159.999998 z m 169.791,11.9890402 -0.409,-0.0869 -0.382,-0.17005 -0.338,-0.24576 -0.28,-0.31072 -0.209,-0.3621 -0.129,-0.39765 -0.044,-0.4158602 0.044,-0.4158 0.129,-0.3977 0.209,-0.3621 0.28,-0.3107 0.338,-0.2457 0.382,-0.1701 0.409,-0.0869 h 0.418 l 0.409,0.0869 0.382,0.1701 0.338,0.2457 0.28,0.3107 0.209,0.3621 0.129,0.3977 0.044,0.4158 -0.044,0.4158302 -0.129,0.39765 -0.209,0.3621 -0.28,0.31072 -0.338,0.24576 -0.382,0.17005 -0.409,0.0869 z m -180.00006,0 -0.40898,-0.0869 L 9,-8.2679118 8.66173,-8.5136718 8.38196,-8.8243918 8.1729,-9.1864918 8.0437,-9.5841418 8,-10.000002 l 0.0437,-0.4158 0.1292,-0.3977 0.20906,-0.3621 0.27977,-0.3107 0.33827,-0.2457 0.38196,-0.1701 0.40898,-0.0869 H 10.209 l 0.409,0.0869 0.382,0.1701 0.3383,0.2457 0.2797,0.3107 0.2091,0.3621 0.1292,0.3977 0.0437,0.4158 -0.0437,0.4158302 -0.1292,0.39765 -0.2091,0.3621 -0.2797,0.31072 -0.3383,0.24576 -0.382,0.17005 -0.409,0.0869 z" + id="path2587-4" /> + </g> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:58.10250092px;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="40" + y="50" + id="text3851"><tspan + sodipodi:role="line" + x="40" + y="80.150925" + id="tspan3861" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:4.23333311px;line-height:4.76249981px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" /></text> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="Cut" + style="display:inline"> + <path + inkscape:connector-curvature="0" + style="fill:#d3d3d3;stroke:#000000;stroke-width:0.5" + d="M 200,-200 H 3.9999996e-8 V 6e-6 H 200 Z m -10.209,11.989 -0.409,-0.087 -0.382,-0.17 -0.338,-0.246 -0.28,-0.31 -0.209,-0.363 -0.129,-0.397 L 188,-190 l 0.044,-0.416 0.129,-0.397 0.209,-0.363 0.28,-0.31 0.338,-0.246 0.382,-0.17 0.409,-0.087 h 0.418 l 0.409,0.087 0.382,0.17 0.338,0.246 0.28,0.31 0.209,0.363 0.129,0.397 0.044,0.416 -0.044,0.416 -0.129,0.397 -0.209,0.363 -0.28,0.31 -0.338,0.246 -0.382,0.17 -0.409,0.087 z m -180.00006,0 -0.4089799,-0.087 -0.3819599,-0.17 -0.3382703,-0.246 -0.2797699,-0.31 -0.20906,-0.363 -0.1292,-0.397 L 8,-190 l 0.0437,-0.416 0.1292,-0.397 0.20906,-0.363 0.2797699,-0.31 0.3382703,-0.246 0.3819599,-0.17 0.4089799,-0.087 H 10.209 l 0.409,0.087 0.382,0.17 0.3383,0.246 0.2797,0.31 0.2091,0.363 0.1292,0.397 L 12,-190 l -0.0437,0.416 -0.1292,0.397 -0.2091,0.363 -0.2797,0.31 -0.3383,0.246 -0.382,0.17 -0.409,0.087 z M 189.791,-8.010953 l -0.409,-0.08693 -0.382,-0.17005 -0.338,-0.245759 -0.28,-0.310721 -0.209,-0.362098 -0.129,-0.39765 -0.044,-0.41583 0.044,-0.415801 0.129,-0.397701 0.209,-0.362101 0.28,-0.3107 0.338,-0.2457 0.382,-0.170098 0.409,-0.0869 h 0.418 l 0.409,0.0869 0.382,0.170098 0.338,0.2457 0.28,0.3107 0.209,0.362101 0.129,0.397701 0.044,0.415801 -0.044,0.41583 -0.129,0.39765 -0.209,0.362098 -0.28,0.310721 -0.338,0.245759 -0.382,0.17005 -0.409,0.08693 z m -180.00006,0 L 9.3819601,-8.097883 9.0000002,-8.267935 8.6617299,-8.513693 8.38196,-8.824414 8.1729,-9.186513 8.0437,-9.584163 8,-9.999993 l 0.0437,-0.4158 0.1292,-0.397701 0.20906,-0.362101 0.2797699,-0.3107 0.3382703,-0.2457 0.3819599,-0.170098 0.4089799,-0.0869 H 10.209 l 0.409,0.0869 0.382,0.170098 0.3383,0.2457 0.2797,0.3107 0.2091,0.362101 0.1292,0.397701 0.0437,0.4158 -0.0437,0.41583 -0.1292,0.39765 -0.2091,0.362099 -0.2797,0.310721 -0.3383,0.245758 -0.382,0.170051 -0.409,0.08693 z" + id="path4413" /> + </g> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Label" + style="display:inline"> + <path + inkscape:connector-curvature="0" + d="M 19.989559,-20.398378 V -180.01045 H 179.89291 v 159.612072 z" + style="fill:none;stroke:#000000;stroke-width:0.09319773" + id="path24" /> + <path + inkscape:connector-curvature="0" + d="M 19.989559,-20.398378 H 179.89291 V -180.01046 H 19.989559 Z" + style="fill:none;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none" + id="path62" /> + <path + inkscape:connector-curvature="0" + d="M 99.941239,-20.398378 V -180.01046" + style="fill:none;stroke:#000000;stroke-width:0.09319773" + id="path64" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.06989" + y="28.481983" + id="text3292" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290" + x="181.06989" + y="28.481983" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Clk</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-170 H 180" + id="path3331" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-160.00001 H 180" + id="path3333" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-150.00001 H 180" + id="path3335" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-140.00001 H 180" + id="path3337" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-130.00001 H 180" + id="path3339" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-120 H 180" + id="path3341" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-110.00001 H 180" + id="path3343" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-100.00001 H 180" + id="path3345" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-90.00001 H 180" + id="path3347" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-80.00001 H 180" + id="path3349" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-70.00001 H 180" + id="path3351" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-60.00001 H 180" + id="path3353" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-50.00001 H 180" + id="path3355" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-40.00001 H 180" + id="path3357" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 19.999999,-30.00001 H 180" + id="path3359" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.50000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="m 99.999999,-180.00001 -0.0588,159.601632" + id="path3361" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.07356" + y="38.583694" + id="text3292-5" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290-3" + x="181.07356" + y="38.583694" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">PCS </tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.12363" + y="48.325733" + id="text3292-51" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290-1" + x="181.12363" + y="48.325733" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">PCS0</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.07356" + y="58.067772" + id="text3292-0" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290-0" + x="181.07356" + y="58.067772" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">PCS0</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.165;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 51.461458,-194.04687 6.614584,-3.96875" + id="path3397" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.0368" + y="68.169487" + id="text3292-7" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290-08" + x="181.0368" + y="68.169487" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">PCI</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.07356" + y="77.911522" + id="text3292-1" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290-6" + x="181.07356" + y="77.911522" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">DPS</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.07356" + y="88.494858" + id="text3292-4" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290-14" + x="181.07356" + y="88.494858" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">DPG</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.07356" + y="98.114944" + id="text3292-9" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290-8" + x="181.07356" + y="98.114944" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">MIPS</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 29.999999,-180.00001 V -170" + id="path3450" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 39.999999,-180.00001 V -170" + id="path3452" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 49.999999,-180.00001 V -170" + id="path3454" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 59.999999,-180.00001 V -170" + id="path3456" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 69.999999,-180.00001 V -170" + id="path3458" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 79.999999,-180.00001 V -170" + id="path3460" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 89.999999,-180.00001 V -170" + id="path3462" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 130,-180.00001 V -170" + id="path3464" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 140,-180.00001 V -170" + id="path3466" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 150,-180.00001 V -170" + id="path3468" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:7.40833px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="115.09582" + y="-189.02806" + id="text3474"><tspan + sodipodi:role="line" + id="tspan3472" + x="115.09582" + y="-189.02806" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;stroke-width:0.264583px">Acc</tspan><tspan + sodipodi:role="line" + x="115.09582" + y="-181.61974" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;stroke-width:0.264583px" + id="tspan3476">Cmd</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.47044" + y="138.28407" + id="text3292-9-0" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290-8-1" + x="181.47044" + y="138.28407" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">AccG</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="181.1319" + y="148.33823" + id="text3292-9-5" + transform="rotate(-90)"><tspan + sodipodi:role="line" + id="tspan3290-8-0" + x="181.1319" + y="148.33823" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">MmS</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:7.40833px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="164.21013" + y="-189.02806" + id="text3474-6"><tspan + sodipodi:role="line" + id="tspan3472-9" + x="164.21013" + y="-189.02806" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;stroke-width:0.264583px">ALU</tspan><tspan + sodipodi:role="line" + x="164.21013" + y="-181.61974" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;stroke-width:0.264583px" + id="tspan3476-7">Get</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.536915" + y="-161.51346" + id="text3527"><tspan + sodipodi:role="line" + id="tspan3525" + x="17.536915" + y="-161.51346" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">Addr</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.49171" + y="-161.51346" + id="text3531"><tspan + sodipodi:role="line" + id="tspan3529" + x="182.49171" + y="-161.51346" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">Data</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.660936" + y="-151.15131" + id="text3527-8"><tspan + sodipodi:role="line" + id="tspan3525-9" + x="17.660936" + y="-151.15131" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">Acc</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.87669" + y="-151.21538" + id="text3527-9"><tspan + sodipodi:role="line" + id="tspan3525-8" + x="182.87669" + y="-151.21538" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">ALU</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.014275" + y="-141.09093" + id="text3527-8-9"><tspan + sodipodi:role="line" + id="tspan3525-9-3" + x="17.014275" + y="-141.09093" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">PC</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.47981" + y="-141.35551" + id="text3527-8-6"><tspan + sodipodi:role="line" + id="tspan3525-9-36" + x="182.47981" + y="-141.35551" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">DP</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.03908" + y="-131.07811" + id="text3527-8-9-0"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4" + x="17.03908" + y="-131.07811" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$00</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="16.871323" + y="-121.28853" + id="text3527-8-9-0-4"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-9" + x="16.871323" + y="-121.28853" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$02</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="16.786898" + y="-111.23436" + id="text3527-8-9-0-6"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-6" + x="16.786898" + y="-111.23436" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$04</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.014275" + y="-101.44478" + id="text3527-8-9-0-41"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-98" + x="17.014275" + y="-101.44478" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$06</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.014275" + y="-91.39061" + id="text3527-8-9-0-0"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-4" + x="17.014275" + y="-91.39061" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$08</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.148308" + y="-81.607224" + id="text3527-8-9-0-9"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-0" + x="17.148308" + y="-81.607224" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$0A</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.014275" + y="-71.54686" + id="text3527-8-9-0-5"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-5" + x="17.014275" + y="-71.54686" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$0C</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="16.890251" + y="-61.228107" + id="text3527-8-9-0-01"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-60" + x="16.890251" + y="-61.228107" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$0E</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.03908" + y="-51.703106" + id="text3527-8-9-0-2"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-8" + x="17.03908" + y="-51.703106" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$10</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="16.891994" + y="-41.384357" + id="text3527-8-9-0-8"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-49" + x="16.891994" + y="-41.384357" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$12</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="16.786898" + y="-31.85936" + id="text3527-8-9-0-83"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-44" + x="16.786898" + y="-31.85936" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$14</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="17.014275" + y="-21.805191" + id="text3527-8-9-0-91"><tspan + sodipodi:role="line" + id="tspan3525-9-3-4-7" + x="17.014275" + y="-21.805191" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.264583px">$16</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.61574" + y="-131.60727" + id="text3527-8-6-5"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7" + x="182.61574" + y="-131.60727" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$01</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.60384" + y="-121.55311" + id="text3527-8-6-5-6"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-2" + x="182.60384" + y="-121.55311" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$03</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.61574" + y="-111.23436" + id="text3527-8-6-5-4"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-25" + x="182.61574" + y="-111.23436" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$05</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.61574" + y="-101.45097" + id="text3527-8-6-5-5"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-0" + x="182.61574" + y="-101.45097" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$07</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.61574" + y="-91.65519" + id="text3527-8-6-5-52"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-9" + x="182.61574" + y="-91.65519" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$09</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.60384" + y="-81.336441" + id="text3527-8-6-5-7"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-7" + x="182.60384" + y="-81.336441" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$0B</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.61574" + y="-71.54686" + id="text3527-8-6-5-68"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-1" + x="182.61574" + y="-71.54686" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$0D</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.60384" + y="-61.492691" + id="text3527-8-6-5-2"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-03" + x="182.60384" + y="-61.492691" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$0F</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.60384" + y="-51.70311" + id="text3527-8-6-5-28"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-74" + x="182.60384" + y="-51.70311" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$11</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.60384" + y="-41.384357" + id="text3527-8-6-5-63"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-8" + x="182.60384" + y="-41.384357" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$13</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.60384" + y="-31.330193" + id="text3527-8-6-5-0"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-4" + x="182.60384" + y="-31.330193" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$15</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;line-height:58.1025px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="182.61574" + y="-21.540609" + id="text3527-8-6-5-9"><tspan + sodipodi:role="line" + id="tspan3525-9-36-7-79" + x="182.61574" + y="-21.540609" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:8.46667px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px">$17</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:5.64444px;line-height:4.7625px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="101.1039" + y="-14.973572" + id="text3474-4"><tspan + sodipodi:role="line" + x="101.1039" + y="-14.973572" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:5.64444px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px" + id="tspan3476-4">NOP $00 LDA $02 LDA# $08 LDA() $0B STA $12 STA() $17 JMP $1D JNZ $21</tspan><tspan + sodipodi:role="line" + x="101.1039" + y="-10.211072" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:5.64444px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px" + id="tspan3888">JZE $25 ADD $29 ADD() $30 ADD# $38 SUB $3C SUB() $43 SUB# $4B</tspan><tspan + sodipodi:role="line" + x="101.1039" + y="-5.4485717" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:5.64444px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px" + id="tspan3890">AND $4F AND() $56 AND# $5E ORA $62 ORA() $69 ORA# $71 XOR $75</tspan><tspan + sodipodi:role="line" + x="101.1039" + y="-0.68607211" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:5.64444px;font-family:Impact;-inkscape-font-specification:'Impact, Condensed';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.264583px" + id="tspan126050">XOR() $7C XOR# $84 INC $88 DEC $8A ROL $8C ROR $8E INV $90</tspan></text> + </g> +</svg> diff --git a/case/dst/stl/.gitkeep b/case/dst/stl/.gitkeep diff --git a/case/dst/svg/.gitkeep b/case/dst/svg/.gitkeep diff --git a/case/lasercut b/case/lasercut @@ -0,0 +1 @@ +Subproject commit 024df03077871597195a3ef78026bf80a475035d diff --git a/doc/README.md b/doc/README.md @@ -0,0 +1,371 @@ +Eris 2206 +--------- + +1. Introduction +2. Operating Eris 2206 +3. Programming +3.1 Memory +3.2 Assembler +3.3 Example +3.4 I/O and UART +3. Hardware +3.1 SOC +3.2 CPU +3.4 LED Matrix Monitor +4. Case and Electronics +4.1 Case +4.2 Electronics +5. License + + +Introduction +============ + +[Watch the video!](https://frombelow.net/projects/eris2206/images/eris2206_demo.mp4) + +Eris 2206 is a front-panel programmable 8 bit computer with lots of +Blinkenlights, implemented on an FPGA. It is not directly based on an +existing computer design (contemporary or historic), but it takes +inspiration from minicomputers and early microcomputers. The most +prominent feature of Eris 2206 is its 16x16 LED display, which shows +the internal state of the CPU and the first 24 memory addresses. The +main mode of programming Eris 2206 is by directly writing to its 128 +bytes of RAM via front-panel switches. The 125 bytes ROM contain a +small bootloader to load programs and data via a serial connection. + + +Operating Eris 2206 +=================== + +Eris 2206 knows three operation modes: run mode, step mode, and memory +set mode. The mode is chosen by a three way switch. In run mode, +execution speed is set by the speed dial next to the mode switch, +while in step mode the step button triggers execution of the next +micro instruction. + +Eris 2206 powers on when connected to a USB power supply. On power up +in run or step mode, it starts executing the program located at the +first ROM address, $80, which computes Fibonacci numbers. + +The 16x16 LED matrix shows the internal state of the CPU and the first +RAM cells: + + Row | Left Side | Right Side +----:|:-----------------:|:------------------: +0 | Micro Instruction | Micro Instruction +1 | Address Bus | Data Bus +2 | Accumulator | ALU +3 | Program Counter | Data Pointer +4-15 | RAM | RAM + + +Programming +=========== + +The main mode of programming Eris 2206 is by front panel switches. For +this, the mode switch has to be set to memory set mode. Pushing the +reset button sets the memory address to the first address, $00. Now +the data bus can be set via switches. Pushing the step button writes +the current value on the data bus to the current memory address and +advances the memory pointer. Pushing the skip button advances the +memory pointer without writing to memory. When program and data have +been written to memory, execution is started by setting the mode +button to step mode and pushing the reset button. Now the program is +executed by pushing the step button repeatedly or by switching to run +mode. + +Alternatively, programs can be uploaded via the serial UART provided +by the USB interface. For this, a minimal first-stage boot loader has +to be programmed and executed via the front panel. This first-stage +boot loader jumps to the second stage serial boot loader at ROM +address $C0. The host program for serial upload is located in +directory `src/tools/send_serial.py`. It expects hex code input. + + +Memory +------ + +Since we have an 8 bit address bus, a total of 256 memory addresses +are available. The lower 128 bytes are RAM. The upper 125 bytes are +RAM. The uppermost three bytes provide memory mapped access +to I/O and the UART. + +Address | Assignment +:-------|:-------------------- +$FF | UART - Clear/Status +$FE | UART - Send/Receive +$FD | I/O (0..5: LEDs) +$C0-$FC | ROM (Serial boot loader) +$80-$BF | ROM (Fibonacci numbers) +$00-$7F | RAM + + +Assembler +--------- + +`src/tools/eras.pl` provides a macro assembler using CPP for macro +processing. The directory also contains a number of example programs. + +The CPU knows four addressing modes: + +- Implicit + +The argument is given implicitly, e.g. INC, which adds one to the +accumulator. + +- Immediate + +The argument is the actual value. This mode is indicated by a +"#". Example: LDA #$5C loads the value $5C into the accumulator. + +- Direct + +The argument is the memory location of the actual value. Example: LDA +$5C loads the value stored at memory address $5C into the accumulator. + +- Indirect + +The argument is the memory address where the memory address of the +actual value is located. This mode is indicated by "()". Example: If +memory address $5C contains value $3B, and memory address $3B contains +value $67, LDA ($5C) loads $67 into the accumulator. + +Op. | Imp. | Imm. | Dir. | Ind. | Description +----|------|------|------|------|:------------------------------------ +NOP | $00 | | | | No operation +LDA | | $08 | $02 | $0B | Load accumulator +STA | | | $12 | $17 | Store accumulator +JMP | | | $1D | | Jump to address +JNZ | | | $21 | | Jump if accumulator != 0 +JZE | | | $25 | | Jump if accumulator == 0 +ADD | | $38 | $29 | $30 | Add value to accumulator +SUB | | $4B | $3C | $43 | Subtract value from accumulator +AND | | $5E | $4F | $56 | Logical AND of accumulator and value +ORA | | $71 | $62 | $69 | Logical OR of accumulator and value +XOR | | $84 | $75 | $7C | Logical XOR of accumulator and value +INC | $88 | | | | Increment accumulator +DEC | $8A | | | | Decrement accumulator +ROL | $8C | | | | Rotate accumulator 1 bit left +ROR | $8E | | | | Rotate accumulator 1 bit right +INV | $90 | | | | Invert accumulator + + +Example +------- + +We write a program that adds $05 and $06: + +``` +start: + LDA #$05 + ADD #$06 + STA :result + JMP :start +result: +``` + +The assembler generates the following machine code for this: + +``` +08 05 +38 06 +12 08 +1D 00 +``` + +In order to enter the machine code, we set the mode switch to "set", +and push the reset button. Now we enter each byte, followed by pushing +"step". Once we are done, we set the mode switch to step, push reset, +and set the mode switch to run. After a number of steps, the result is +shown memory address $08. + +If we want to add different numbers, we set the mode to set again, +push reset, push skip once in order to advance to memory address $01 +without overwriting the LDA instruction, set the first new number, push +step, push skip in order to advance to memory address $03, set the +second new number, and set the mode switch to run. + + +I/O and UART +------------ + +The I/O register simply maps the lowest 5 bits to the LEDs on the +iCEstick (which are not visible, since the iCEstick is in the +case). + +The UART utilizes two addresses: One address for sending and receiving +data, and a second address for status information and to clear the +input buffer. + +The byte written to address $FE is send. While the bit is transmitted, +bit 0 of $FF is 1 (tx_busy). In order to receive a byte, the receiver +buffer must be cleared by writing any value to $FF. Once a byte is +received, bit 1 of $FF is 1 (recv_buffer_full). Now the byte can be +read from $FE. In order to receive the next byte, the receive buffer +has to be cleared again. See `src/roms/rom_uart.asm` for an example. + + +Hardware +======== + +Eris2206 is implemented on an iCEstick FPGA Evaluation Kit. It is +synthesized using the free tools of project +[IceStorm](https://clifford.at/icestorm). + +The GPIO pins of the FPGA connect to the 16x16 (WS2811) matrix display +and the buttons/switches. Beside some pull-down resistors, the only +additional hardware is an NE555 multivibrator circuit providing the +bus clock. The speed dial changes the frequency of the multivibrator. + + +SOC +--- + +See `doc/schematic.dia` for an overview of the SOC. Besides the CPU core, +the main peripherals are memory (RAM and ROM), the UART, and a system +monitor providing output to a matrix of WS2811 LEDs. + + +CPU +--- + +The following description of the internal works of the CPU should help +you to understand the implementation in `src/ecpu.v`. It is not +necessary to operate Eris 2206. + +An instance of module control_logic orchestras the components of the +CPU. (These control lines are not shown in the schematic.) Microcode +implementations of the opcodes govern the operation of the control +logic. The microcode for the assembler opcodes is defined in and +generated by `src/tools/mc_compiler.py`. + +The CPU has two counters and three registers: + +The program counter (PC) points to the next instruction/argument to +be processed. The micro instruction pointer (MIP) points to the next +micro instruction to be executed. These counters can be set or +incremented. + +The three registers are the data pointer (DP), the accumulator, and +the output of the arithmetic-logic unit (ALU). + +The accumulator is the only register visible to the user. It reads +from and writes to external memory (and memory mapped I/O modules) via +the data bus. In addition to read and write operations, the +accumulator can be incremented, decremented, rotated (left and right), +and inverted. + +The ALU operates on the current value of the accumulator and the +current value on the data base, and writes back to the data bus. + +Like the PC, the DP does not write to the data bus, but to the address +bus. It is used to dereference addresses in direct and indirect +addressing mode. + +A zero flag, i.e. a wire indicating whether the register value is +zero, is available for the accumulator. This flag is used by the +comparator in order to implement the conditional jump on (not) zero +instructions. + +A little bit of glue logic multiplexes the data and address line: +Only the active component may write to the buses. + +Micro instructions consist of 15 bits: + + Bit | Operation +-----:|:--------------------------------------------------------------------- + 0 | Write data bus to PC + 1 | Write data bus to PC if zero flag 1 + 2 | Write data bus to PC if zero flag 1 + 3 | Increment PC + 4 | Write data bus to DP + 5 | Write DP to address bus (write PC to address bus if bit 5 = 0) + 6 | Set memory address on address bus to value on data bus + 7 | Write accumulator to data bus + 8-10 | Set/increment/decrement/rotate/invert accumulator + 11 | Set MIP to value on data bus (increment MIP if bit 11 = 0) +12-14 | Add/subtract/and/or/xor data bus to accumulator and write to data bus + +The implementation of the opcodes as micro instructions is given in +`src/tools/mc_compiler.py`. `mc_compiler.py` compiles a ROM file of +the micro instruction implementations of all opcodes. The machine code +(= byte value) of an opcodes is the entry points for the microcode of +its implementation in this ROM file. Therefore in order to decode an +opcode, its byte code is read from the data bus and written into the +MIP. + +On negative edges of the clock, the next micro instruction is set, +i.e. components are turned on/off according to the micro +instruction. The components operate on positive clock edges. + +There is a separate clock port for the UART, because the UART must be +run at 12 MHz for timing reasons, while the rest of the SOC may run at +a lower speed. + + +LED Matrix Monitor +------------------ + +A 16x16 LED matrix provides a monitor view into the internals of the +SOC. The LEDs are driven by WS2811 controllers. The control logic is +implemented in `src/ws2811.v`. On each iteration of the internal (12 +MHz) clock of the FPGA, one 8 bit element of the monitor is updated, +i.e. it takes 32 cycles to update the complete LED matrix. The WS2811 +driver allows to set the three color channels of each LED on or +off. The intensity is fixed for all LEDs and color channels. + + +Case and Electronics +==================== + +Case +---- + +The case has been designed in OpenSCAD. The main design file is +`case/case.scad`. Most elements of the case can be cut from 6 mm ply +wood with a laser cutter. Running make in directory case generates +cutouts for a laser cutter in `case/dst/svg/`. Three elements are not +only cut, but also engraved. Engravings have been added manually using +Inkscape. These files for laser cutting are located in +`case/dst/labeled`. Note that for +`case/dst/labeled/top_plate/acryl_top_plate.svg` not 6 mm plywood, but +an acryl plate should be cutted. + +The holders for the iCEstick and the circuit board are 3D printed. +After running make in directory case/, the 3D print files are located +in directory case/dst/stl. + +The case is partly glued and partly held together by M4 screws. Most +M4 screws have nuts as counterparts, except the four screws in the +bottom. These are held by claw nuts. + +Electronics +----------- + +The NE555 multivibrator is housed on a small circuit board, together +with a bunch of pull-down resistors for the switches. A Fritzing +design file is given in board/circuit.fzz. See src/ecpu.pcf for how to +connect the hardware components to the GPIO I/O pins. + +License +======= + +See case/lasercut/LICENSE for author, copyright, and licensing +information of the lasercut library. + +Everything else: + +Copyright © 2022 Gerd Beuster <gerd@frombelow.net> + +This project is free soft- and hardware: you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This project is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this project. If not, see <http://www.gnu.org/licenses/>. diff --git a/doc/bom.txt b/doc/bom.txt @@ -0,0 +1,19 @@ +- 1x iCEstick FPGA Evaluation Kit +- 6 mm Plywood +- 4 mm Acryl Plate +- 3x Push Buttons - 7.2 mm diameter mounting hole +- 8x 2 Way Switches - 6.6 mm mounting hole +- 1x 3 Way Switch - 6.6 mm mounting hole +- 1x Potentiometer 500 KΩ - 6.6 mm mounting hole +- 2x 1.24 kΩ Resistors +- 4x 3.3 kΩ Resistors +- 3x Capacitors 100 nF +- 1x Capacitor 2.2 µF +- 1x NE555 +- 1x Diode +- 1x 16x16 WS2811 matrix +- M4 screws 10 mm +- M4 screws 12 mm +- M4 screws 18 mm +- 10x M4 Nuts +- 4x M4 Claw Nuts diff --git a/doc/schematic.dia b/doc/schematic.dia Binary files differ. diff --git a/src/Makefile b/src/Makefile @@ -0,0 +1,51 @@ +TARGET=ecpu +INC=-I../inc +ROMS=roms/rom.dat roms/rom_opcode_test_0.dat roms/rom_opcode_test_1.dat \ + roms/rom_leds.dat roms/rom_uart.dat + +all: binary simulation + +binary: $(TARGET).bin + +%.s: %.asm + cpp -nostdinc -C -P -o $@ $< + +# Assemble programs for SOC +%.dat: %.s tools/opcodes.pl + tools/eras.pl $< $@ + +tools/opcodes.pl: + cd tools; python3 ./mc_compiler.py opcodes + +%.s: %.asm + cpp -nostdinc -C -P -o $@ $< + +# Synthesize +%.blif: %.v main.v uart.v $(ROMS) + cd tools; python3 ./mc_compiler.py microcode + yosys -p "read_verilog $(INC) main.v; synth_ice40 -blif $@" + +# Place and route +%.txt: %.blif + arachne-pnr -d 1k -p $(TARGET).pcf $< -o $@ + +# Convert to bitstream +%.bin: %.txt + icepack $< $@ + +# Upload +upload: $(TARGET).bin + iceprog ${ICEPROG_ARGS} $< + +# Simulation +simulation: $(TARGET).v $(ROMS) + cd tools; python3 ./mc_compiler.py microcode + iverilog $(INC) -o $(TARGET).out $(TARGET)_tb.v + ./$(TARGET).out + gtkwave $(TARGET)_tb.vcd $(TARGET)_tb.gtkw + +clean: + rm -f *.txt *.bin *.blif *.out *.vcd roms/*.s $(ROMS) tools/opcodes.pl \ + tools/microcode_rom_lsb.dat tools/microcode_rom_msb.dat + +.PHONY: all clean upload simulation binary diff --git a/src/ecpu.pcf b/src/ecpu.pcf @@ -0,0 +1,36 @@ +set_io CLK_IN 21 +set_io GREEN 95 +set_io RED_N 99 +set_io RED_E 98 +set_io RED_S 97 +set_io RED_W 96 +set_io DTR 3 +set_io RTS 7 +set_io TX 8 +set_io RX 9 +set_io PMOD_1 78 +set_io PMOD_2 79 +set_io PMOD_3 80 +set_io PMOD_4 81 +set_io PMOD_7 87 +set_io PMOD_8 88 +set_io PMOD_9 90 +set_io PMOD_10 91 +set_io WS2811_DOUT 112 +set_io SWITCH_PROGRAM 113 +set_io BUTTON_STEP 114 +set_io BUTTON_RESET 115 +set_io SWITCH_SINGLE_CONT 116 +set_io BUTTON_SKIP 117 +set_io USER_CLOCK 118 +set_io SWITCH_D0 44 +set_io SWITCH_D1 45 +set_io SWITCH_D2 47 +set_io SWITCH_D3 48 +set_io SWITCH_D4 56 +set_io SWITCH_D5 60 +set_io SWITCH_D6 61 +set_io SWITCH_D7 62 + + + diff --git a/src/ecpu.v b/src/ecpu.v @@ -0,0 +1,581 @@ +/* + * Copyright 2022 Gerd Beuster (gerd@frombelow.net). This is free + * soft-/hardware under the GNU GPL v3 license or any later + * version. See COPYING in the root directory for details. + */ + +`ifndef ecpu_v + `define ecpu_v + + `include "uart.v" + `include "ws2811.v" + +module esoc( // System operates at this clock speed in run mode + input slow_clk, + // Resets counters and registers, RAM is not deleted! + input reset_in, + // Switch between memory set mode andexecution mode + input program_mode, + // Single step mode or continous execution + input single_cont, + // Step trigger in single step mode, write data in + // set memory mode. + input step, + // Skip memory cell in set memory mode + input skip, + input [7:0] din, // Data bus input in set memory mode + // GPIO (LEDs) + output green, output red_n, output red_e, output red_s, + output red_w, + // Fast clock for timing sensitive modules (UART & WS2811) + input fast_clk, + // UART + output tx, input rx, + // WS2811 + output ws2811_dout); + + // The default ROM contains two programs: + // + // - Computation of Fibonacci numbers (at $80) + // + // This program is located at the start of the ROM, and thus gets + // executed on power on + // + // - Second stage bootloader (at $C0) + // + // The bootloader loads a program via the serial line. (See + // tools/send_serial.py for the upload program.) In order to use it, + // the user has to ener a minimal first stage bootloader, which + // jumps into this second stage bootloader, via the front panel + // switches. + parameter rom_file = "roms/rom.dat"; + + // This ROM shows a sequence on the built-in LEDs of the + // iCEstick. Since the iCEstick is embedded in the case, the LEDs + // are only visible when the cas is opened. + // parameter rom_file = "roms/rom_leds.dat"; + + // A serial echo program to test the UART. + // parameter rom_file = "roms/rom_uart.dat"; + + // The program to test all opcodes had to be split in two parts. As + // the result of each opcode test, the value $FF should be written + // to memory. + // parameter rom_file = "roms/rom_opcode_test_0.dat"; + // parameter rom_file = "roms/rom_opcode_test_1.dat"; + + // + // Operation modes + // + + // There are two main modes: + // + // - In execution mode, the CPU runs all components + // + // - In memory set mode, modul manual_programmer controls the + // address bus and the memory write line. Data input comes straight + // from the switches set by the user. + wire [7:0] data_bus, address_bus, cpu_address_bus, programmer_address_bus; + wire mem_set, cpu_mem_set, programmer_mem_set; + wire cpu_clk; + // In programming mode, the CPU clock is stopped. In exeuction mode, it + // normally runs on the slow clock, unless we are in singel step mode. + assign cpu_clk = program_mode ? 0 : + ((single_cont | reset_in) ? slow_clk : step); + assign mem_set = program_mode ? programmer_mem_set : cpu_mem_set; + assign data_bus = program_mode ? din : cpu_dout; + assign address_bus = program_mode ? programmer_address_bus : cpu_address_bus; + + manual_programmer mp(.clk(fast_clk), .res(reset_in), + .step(step), .skip(skip), + .mem_set(programmer_mem_set), + .aout(programmer_address_bus)); + + // + // Glue logic: Memory mapping of peripherals + // + + // The CPU addresses a flat memory space. Here we define glue logic + // to map this flat memory space to access to RAM, ROM, UART, and + // GPIO. + // + // The lower 5 bits of $FD turn the LEDs of the iCEstick on and off. + + // hFF : UART - Write: Clear recv_buffer_full + // - Read: Status (0: TX busy, 1: recv_buffer_full) + // hFE : UART - Write: Send Data - Read: Received Data + // $FD : I/O (0..5: LEDs) + // h80-hFC : ROM + // h00-h7F : RAM + + // Data input for the CPU may come from ROM, RAM, or UART. + wire [7:0] mem_dout; // CPU data (memory) input + // Data output of ROM, RAM, and UART + wire [7:0] rom_dout, ram_dout, uart_dout; + // Map data output to CPU data input according to memory map + assign mem_dout = (address_bus < 8'h80) ? ram_dout : + ((address_bus < 8'hFE) ? rom_dout : uart_dout); + wire [7:0] cpu_dout; + // Set correct device to write mode + wire ram_set, gpio_set, uart_set; + assign ram_set = (address_bus < 8'h80) ? mem_set : 0; + assign gpio_set = (address_bus == 8'hFD) ? mem_set : 0; + assign uart_set = (address_bus > 8'hFD) ? mem_set : 0; + + // + // CPU and peripherals definitions + // + + wire [15:0] control_logic; + wire [7:0] reg_a_value; + wire [7:0] alu_value; + wire [7:0] pc_value; + wire [7:0] dp_value; + ecpu e(.clk(cpu_clk), + .reset_in(reset_in), + .mem_dout(mem_dout), + .mem_set(cpu_mem_set), + .data_bus(cpu_dout), + .address_bus(cpu_address_bus), + .ctrl_logic_mon(control_logic), + .reg_a_value(reg_a_value), + .alu_value(alu_value), + .pc_value(pc_value), + .dp_value(dp_value)); + + ram ram_mem(.clk(fast_clk), .set(ram_set), + .din(data_bus), .dout(ram_dout), .ain(address_bus[6:0])); + + rom + #(.rom_file(rom_file)) + rom_mem(.clk(fast_clk), .dout(rom_dout), .ain(address_bus[6:0])); + + + gpio g(.clk(fast_clk), .din(data_bus[4:0]), .write(gpio_set), + .green(green), .red_n(red_n), .red_e(red_e), + .red_s(red_s), .red_w(red_w)); + + // UART reg_select is connected to the LSB of the address bus, thus + // mapping the two UART registers to two consequtive memory addresses. + // The start wire connects to the write signal of the CPU: Writing + // data two the UART starts transmission. + // The UART must be driven by a 12 Mhz clock. + uart u(.clk(fast_clk), .din(data_bus), .dout(uart_dout), + .reg_select(address_bus[0]), .write(uart_set), .tx(tx), .rx(rx)); + + // Monitor: Show internal state of system on LED matrix + `define VRAM_SIZE 32 + led_monitor #(.vram_size(`VRAM_SIZE)) + led_mon (.fast_clk(fast_clk), + .data_bus(data_bus), + .address_bus(address_bus), + .mem_set(mem_set), + .control_logic(control_logic), + .reg_a(reg_a_value), + .alu(alu_value), + // We set value to address bus in program mode in order + // to highlight the address currently manipulated + .pc(program_mode ? address_bus : pc_value), + .dp(dp_value), + .ws2811_dout(ws2811_dout)); + +endmodule // esoc + +module ecpu(input clk, + input reset_in, + input [7:0] mem_dout, + output mem_set, + output [7:0] data_bus, + output [7:0] address_bus, + output [15:0] ctrl_logic_mon, // Monitor output + output [7:0] reg_a_value, + output [7:0] alu_value, + output [7:0] pc_value, + output [7:0] dp_value); + + // While the control logic of the CPU operates on negative clock + // edges, the components operate on positive edges. + + // Enable/disable lines for components + // PC + wire pc_set, pc_inc; + // The comperator connects microcode for conditional + // (pc_set_if_zero, pc_set_if_nonzero) and unconditional + // (pc_set_uncond) jumps to the set signal of the PC (pc_set). + wire pc_set_if_zero, pc_set_if_nonzero, pc_set_uncond; + // MIP + wire mip_set; + // DP + wire dp_set, dp_get; + // Accumulator + wire reg_a_get, reg_a_zero; + // Accumulator does not only allow setting, but more + // commands (inc, dec, ...). + wire [2:0] reg_a_cmd; + // ALU + // Three bits determine which result we get from the ALU: + `define alu_off 3'b000 + `define alu_add 3'b001 + `define alu_sub 3'b010 + // Multiplication and division occpuy too many PLBs +/* -----\/----- EXCLUDED -----\/----- + `define alu_mul 3'b011 + `define alu_div 3'b100 + -----/\----- EXCLUDED -----/\----- */ + `define alu_and 3'b101 + `define alu_or 3'b110 + `define alu_xor 3'b111 + wire [2:0] alu_get; + + // Glue logic: Since all components may write to the buses, write + // access to the buses must be multiplexed. + wire [7:0] pc_dout, dp_dout, mip_dout, reg_a_dout, alu_dout; + // Multiplexer for address bus: + // If dp_get is set, the data pointer is loaded on the address bus. + // Otherwise the program counter is loaded on the address bus. + assign address_bus = dp_get ? dp_dout : pc_dout; + // Multiplexer for data bus + // Unless the data bus is explicitly loaded with the accumulator + // or the ALU, it is loaded from memory. + wire [7:0] alu_sum; + wire [7:0] alu_difference; + wire [7:0] alu_and; + wire [7:0] alu_or; + wire [7:0] alu_xor; + assign alu_value = (alu_get == `alu_add) ? alu_sum : + ((alu_get == `alu_sub) ? alu_difference : + ((alu_get == `alu_and) ? alu_and : + ((alu_get == `alu_or) ? alu_or : + ((alu_get == `alu_xor) ? alu_xor : + alu_sum)))); + assign data_bus = reg_a_get ? reg_a_dout : + ((alu_get == `alu_off) ? mem_dout : alu_value); + // Monitor output + assign ctrl_logic_mon = { clk, pc_set_uncond, pc_set_if_zero, + pc_set_if_nonzero, + pc_inc, dp_set, dp_get, + mip_set, reg_a_cmd, reg_a_get, + mem_set, alu_get } ; + assign reg_a_value = reg_a_dout; + assign pc_value = pc_dout; + assign dp_value = dp_dout; + + // Reset logic + reg res = 1; + always @(posedge(clk)) + res <= reset_in; + + + control_logic ctrl (.clk(clk), + .res(res), + .pc_set_uncond(pc_set_uncond), + .pc_set_if_zero(pc_set_if_zero), + .pc_set_if_nonzero(pc_set_if_nonzero), + .pc_inc(pc_inc), + .dp_set(dp_set), .dp_get(dp_get), + .mip_set(mip_set), + .mip_value(mip_dout), + .reg_a_cmd(reg_a_cmd), .reg_a_get(reg_a_get), + .mem_set(mem_set), + .alu_get(alu_get)); + + + // Program Counter + counter + #(.start_value(8'h80)) // Start execution in ROM + pc (.clk(clk), .res(res), + .set(pc_set), .inc(pc_inc), + .din(data_bus), .dout(pc_dout)); + + // The micro instruction pointer (mip) keeps track of the current + // micro instruction. It is updated from the data bus (when the + // next opcode is read, because opcode = pointer to begin of + // microcode implementation of opcode) and read by the control + // logic. + // + // The increment input is fixed to high, because the MIP shall + // always step to the next instruction always, unless a new + // value is set. + counter mip (.clk(clk), .res(res), + .set(mip_set), .inc(1'b1), + .din(data_bus), .dout(mip_dout)); + + // The data pointer reads from data bus and writes to the address + // bus. It is used to dereference memory addresses. + register dp (.clk(clk), .res(res), + .set(dp_set), .inc(1'b0), .dec(1'b0), + .rol(1'b0), .ror(1'b0), .inv(1'b0), + .din(data_bus), .dout(dp_dout)); + + // Accumulator + // The accumulator supports additional operations besides setting. + // We demultiplex the reg_a_cmd for this + wire reg_a_set, reg_a_inc, reg_a_dec, reg_a_rol, + reg_a_ror, reg_a_inv; + assign reg_a_set = (reg_a_cmd == 3'b001); + assign reg_a_inc = (reg_a_cmd == 3'b010); + assign reg_a_dec = (reg_a_cmd == 3'b011); + assign reg_a_rol = (reg_a_cmd == 3'b100); + assign reg_a_ror = (reg_a_cmd == 3'b101); + assign reg_a_inv = (reg_a_cmd == 3'b110); + register reg_a (.clk(clk), .res(res), + .set(reg_a_set), .inc(reg_a_inc), .dec(reg_a_dec), + .rol(reg_a_rol), .ror(reg_a_ror), .inv(reg_a_inv), + .din(data_bus), .dout(reg_a_dout), .zero(reg_a_zero)); + + // Comperator + // The program counter is set from the data bus (i.e. a jump is + // executed) when we execute the microcode for an unconditional + // jump (pc_set_uncond) or when we execute the microcode for a + // conditional jump (pc_set_if_zero) and the zero flag of the + // accumulator is set. + assign pc_set = pc_set_uncond | (pc_set_if_zero & reg_a_zero) | + (pc_set_if_nonzero & !reg_a_zero); + + // ALU + // The ALU consists of an adder and a register. The adders gets the + // accumulator and the data bus as input and updates the register. + // The register writes to the data bus. + alu a(.clk(clk), .din_a(reg_a_dout), .din_b(data_bus), .sum(alu_sum), + .difference(alu_difference), .band(alu_and), .bor(alu_or), + .bxor(alu_xor)); +endmodule + +module counter(input clk, + input res, + input set, + input inc, + input [7:0] din, + output [7:0] dout); + + // Start value is only set on initialization. Reset + // always sets counter to 0, not back to start value. + // By setting the start value of the PC to the first + // ROM address, the SOC will run from ROM on power-up, + // but can be programmed starting from address h00 + // on reset. + parameter start_value = 8'h00; + reg [7:0] value; + reg init = 0; + + assign dout = value; + always @(posedge(clk)) + if (init == 0) + begin + value <= start_value; + init <= 1; + end + else + if (res) + value <= 8'h00; + else if (set) + value <= din; + else if (inc) + // Only increment value if no new value is set. This order is + // important for two reasons: + // - Conditional jumps always increment the PC. + // This should only have an effect if no new address is set. + // - For the MIP, inc is fixed to high. If mip_set sets a new + // new address, the new address should not increment immediately. + value <= value + 1; +endmodule + +module alu(input clk, input [7:0] din_a, input [7:0] din_b, + output reg [7:0] sum, + output reg [7:0] difference, + output reg [7:0] band, + output reg [7:0] bor, + output reg [7:0] bxor); + always @(posedge(clk)) + begin + sum <= din_a + din_b; + difference <= din_a - din_b; + // Multiplication and division occpuy too many PLBs +/* -----\/----- EXCLUDED -----\/----- + product <= din_a * din_b; + quotient <= din_a / din_b; + -----/\----- EXCLUDED -----/\----- */ + band <= din_a & din_b; + bor <= din_a | din_b; + bxor <= din_a ^ din_b; + end +endmodule + +module register(input clk, + input res, + input set, + input inc, + input dec, + input rol, + input ror, + input inv, + input [7:0] din, + output [7:0] dout, + output zero); + + reg [7:0] value; + + assign dout = value; + assign zero = (value == 0); + always @(posedge(clk)) + if (res) + value <= 8'b00000000; + else if (set) + value <= din; + else if (inc) + value <= value + 1; + else if (dec) + value <= value - 1; + else if (rol) + value <= { value[6], value[5], value[4], value[3], + value[2], value[1], value[0], value[7] }; + else if (ror) + value <= { value[0], value[7], value[6], value[5], + value[4], value[3], value[2], value[1] }; + else if (inv) + value <= value ^ 8'b11111111; +endmodule + +// 128 byte RAM module +module ram(input clk, + input set, // Write din to memory cell + input [7:0] din, + output reg [7:0] dout, + input [6:0] ain); + + reg [7:0] mem [0:127]; + always @(posedge(clk)) + begin + if (set) + mem[ain] <= din; + dout <= mem[ain]; + end +endmodule + +// 128 byte ROM module +module rom(input clk, + output reg [7:0] dout, + input [6:0] ain); + + parameter rom_file = "roms/rom.dat"; + + reg [7:0] mem [0:127]; + + always @(posedge(clk)) + begin + dout <= mem[ain]; + end + + initial + $readmemh(rom_file, mem); +endmodule + +module gpio(input clk, input [4:0] din, + input write, + output reg green, output reg red_n, output reg red_e, + output reg red_s, output reg red_w); + + always @(posedge(clk)) + if (write) + { red_n, red_e, red_s, red_w, green} <= din; +endmodule + +// All microcode is stored in array microcode_(lsb|msb). The data for +// this arrays is generated by tools/mc_compiler.py. Pointers to the +// microcode for an opcode are stored in array ptr_opcode_microcode. +// These arrays are initialized upon reset. +module control_logic(input clk, input res, + output reg pc_set_uncond, + output reg pc_set_if_zero, + output reg pc_set_if_nonzero, + output reg pc_inc, + output reg dp_set, dp_get, + output reg mip_set, + input [7:0] mip_value, + output reg mem_set, + output reg reg_a_get, + output reg [2:0] reg_a_cmd, + output reg [2:0] alu_get); + + // Used to set all enable/disable signals in one go + `define execute_microcode {alu_get, \ + mip_set, \ + reg_a_cmd, reg_a_get, \ + mem_set, \ + dp_get, dp_set, \ + pc_inc, \ + pc_set_if_nonzero, pc_set_if_zero, pc_set_uncond} + + reg [7:0] microcode_lsb [0:145]; + reg [6:0] microcode_msb [0:145]; + + // Microcode for the assembler opcodes is defined in + // tools/mc_compiler.py. During synthesis, + // mc_compiler.py writes the microcode for the assembler + // opcodes into a ROM file, which is read here. + initial + begin + $readmemh("tools/microcode_rom_lsb.dat", microcode_lsb); + $readmemh("tools/microcode_rom_msb.dat", microcode_msb); + end + + always @(negedge(clk)) + if (res) + `execute_microcode <= 0; + else + `execute_microcode <= { microcode_msb[mip_value], + microcode_lsb[mip_value] }; + +endmodule + +module manual_programmer(input clk, input res, + input step, + input skip, + output reg mem_set, + output reg [7:0] aout); + reg state; + // The monitor (LED matrix) does not access the system memory. + // Instead it listens to the address and data busses and maintainces + // its own memory. Since the monitor update operation either updates + // the registers or the memory, it may miss a memory updates if we + // update the memory too fast here. In order to fix this problem, the + // write signal is kept up for time given by write_delay. + reg [3:0] write_delay; + `define state_set_data 0 + `define state_write_or_skip_data 1 + initial + begin + state <= `state_set_data; + aout <= 8'h00; + mem_set <= 0; + end + always @(posedge(clk)) + if (res) + begin + state <= `state_set_data; + aout <= 8'h00; + mem_set <= 0; + end + else + case (state) + `state_set_data: + if (step || skip) + begin + state <= `state_write_or_skip_data; + mem_set <= !skip; + write_delay <= -1; + end + `state_write_or_skip_data: + begin + if (write_delay == 0) + begin + mem_set <= 0; + state <= `state_set_data; + aout <= aout + 1; + end + write_delay <= write_delay - 1; + end + endcase +endmodule + +`endif diff --git a/src/ecpu_tb.gtkw b/src/ecpu_tb.gtkw @@ -0,0 +1,68 @@ +[*] +[*] GTKWave Analyzer v3.3.103 (w)1999-2019 BSI +[*] Sun Aug 7 09:08:48 2022 +[*] +[dumpfile] "/media/gb/m/projects/20210624_icestick/eris2206/src/ecpu_tb.vcd" +[dumpfile_mtime] "Sun Aug 7 08:55:25 2022" +[dumpfile_size] 1479207 +[savefile] "/media/gb/m/projects/20210624_icestick/eris2206/src/ecpu_tb.gtkw" +[timestart] 0 +[size] 1920 1016 +[pos] 3 0 +*-1.320806 7 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] ecpu_tb. +[treeopen] ecpu_tb.s. +[treeopen] ecpu_tb.s.e. +[treeopen] ecpu_tb.s.led_mon. +[sst_width] 233 +[signals_width] 247 +[sst_expanded] 1 +[sst_vpaned_height] 334 +@200 +-Clock & Busses +@28 +ecpu_tb.s.e.clk +@22 +ecpu_tb.s.e.address_bus[7:0] +ecpu_tb.s.e.data_bus[7:0] +ecpu_tb.s.e.pc_dout[7:0] +ecpu_tb.s.e.mip_dout[7:0] +@200 +-Control +@28 +ecpu_tb.s.e.mip_set +ecpu_tb.s.e.pc_set +ecpu_tb.s.e.pc_inc +ecpu_tb.s.e.dp_get +ecpu_tb.s.e.dp_set +ecpu_tb.s.e.mem_set +@29 +ecpu_tb.s.e.reg_a_set +@28 +ecpu_tb.s.e.ctrl.reg_a_get +ecpu_tb.s.e.pc_set_if_nonzero +ecpu_tb.s.e.pc_set_if_zero +ecpu_tb.s.e.pc_set_uncond +@200 +-Accumulator +@22 +ecpu_tb.s.e.reg_a.value[7:0] +@200 +-ALU +-PC +@22 +ecpu_tb.s.e.pc.value[7:0] +@200 +-DP +@22 +ecpu_tb.s.e.dp.value[7:0] +@200 +-GPIO +@28 +ecpu_tb.s.g.green +ecpu_tb.s.g.red_e +ecpu_tb.s.g.red_n +ecpu_tb.s.g.red_s +ecpu_tb.s.g.red_w +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/src/ecpu_tb.v b/src/ecpu_tb.v @@ -0,0 +1,38 @@ +/* + * Copyright 2022 Gerd Beuster (gerd@frombelow.net). This is free + * soft-/hardware under the GNU GPL v3 license or any later + * version. See COPYING in the root directory for details. + */ + +`include "ecpu.v" + +module ecpu_tb; + + wire green, red_n, red_e, red_s, red_w; + + reg clk; + initial clk = 0; + integer clk_ctr; + initial clk_ctr = 0; + + always #1 clk = ~clk; + always @(posedge(clk)) + clk_ctr <= clk_ctr +1; + + esoc s (.slow_clk(clk), .fast_clk(clk), + .reset_in(1'b0), + .program_mode(1'b0), + .single_cont(1'b1), + .step(1'b0), + .skip(1'b0), + .din(8'b00000000), + .green(green), .red_n(red_n), .red_e(red_e), .red_s(red_s), + .red_w(red_w)); + +initial begin + $dumpfile("ecpu_tb.vcd"); + $dumpvars(0, ecpu_tb); + # 8192 $finish; +end + +endmodule diff --git a/src/main.v b/src/main.v @@ -0,0 +1,86 @@ +/* + * Copyright 2022 Gerd Beuster (gerd@frombelow.net). This is free + * soft-/hardware under the GNU GPL v3 license or any later + * version. See COPYING in the root directory for details. + */ + +`include "ecpu.v" + +module main(input CLK_IN, // System clock (12 Mhz) + // External clock generated by NE555; user can set frequency. + // This clock is used by the CPU. + input USER_CLOCK, + // Switch to choose between continously running clock and single stepping + input SWITCH_SINGLE_CONT, + // Single step (exeuction mode) / write (programming mode) signal + input BUTTON_STEP, + input BUTTON_SKIP, // Skip memory cell (programming mode) signal + input BUTTON_RESET, + input SWITCH_PROGRAM, // Program or execute mode + // Manual input to data bus + input SWITCH_D0, SWITCH_D1, SWITCH_D2, SWITCH_D3, + input SWITCH_D4, SWITCH_D5, SWITCH_D6, SWITCH_D7, + output GREEN, output RED_N, output RED_E, + output RED_S, output RED_W, input RX, output TX, + output WS2811_DOUT); + + wire button_step_debounced, button_skip_debounced; + debouncer deb0(.clk(CLK_IN), .button(BUTTON_STEP), .debounced(button_step_debounced)); + debouncer deb1(.clk(CLK_IN), .button(BUTTON_SKIP), .debounced(button_skip_debounced)); + + // The SOC uses two clocks: The internal 12 Mhz clock of the + // iCEstick is used for updating the WS2811 LED matrix and for + // timing serial communication. An external, user-supplied clock + // generated by an NE555 is used for running the CPU. The speed of + // this clock can be set via the speed dial. Since the high and low + // phases of the external clock have different length, we use a prescaler + // to "convert" some to same length phases. + wire slow_clk; + prescaler #(.bits(1)) B1(.clk_in(USER_CLOCK), .clk_out(slow_clk)); + + esoc s(.slow_clk(slow_clk), .fast_clk(CLK_IN), + .reset_in(BUTTON_RESET), + .program_mode(SWITCH_PROGRAM), + .single_cont(SWITCH_SINGLE_CONT), + .step(button_step_debounced), + .skip(button_skip_debounced), + .din({ !SWITCH_D7, !SWITCH_D6, !SWITCH_D5, !SWITCH_D4, + !SWITCH_D3, !SWITCH_D2, !SWITCH_D1, !SWITCH_D0 }), + .green(GREEN), .red_n(RED_N), .red_e(RED_E), .red_s(RED_S), + .red_w(RED_W), + .tx(TX), .rx(RX), .ws2811_dout(WS2811_DOUT)); + +endmodule + +module debouncer(input clk, input button, output reg debounced); + + parameter delay = 20; + + reg [delay:0] debounce_timer; + always @(posedge(clk)) + begin + if (button && (debounce_timer == 0)) + begin + debounced <= 1; + debounce_timer <= -1; + end + else + begin + if (debounce_timer > 0) + debounce_timer <= debounce_timer - 1; + debounced <= 0; + end + end +endmodule + +module prescaler(input clk_in, output clk_out); + + parameter bits = 24; + reg [bits-1:0] c = 0; + + assign clk_out = c[bits-1]; + + always @(posedge(clk_in)) + c <= c + 1; + +endmodule diff --git a/src/roms/rom.asm b/src/roms/rom.asm @@ -0,0 +1,93 @@ +// +// Fibonacci numbers +// + +#define DATA_PTR_0 $15 +#define DATA_PTR_1 $16 +#define DATA_PTR_2 $17 + .set_address $80 + // Set initial values + LDA #$00 + STA $00 + LDA #$01 + STA $01 +initialize_data_pointers: + LDA #$00 + STA DATA_PTR_0 + LDA #$01 + STA DATA_PTR_1 + LDA #$02 + STA DATA_PTR_2 +loop: + // Compute next value + LDA (DATA_PTR_0) + ADD (DATA_PTR_1) + STA (DATA_PTR_2) + // Increment pointers + // DATA_PTR_0 + LDA DATA_PTR_0 + // Check if we have reached + // the end of visible RAM + ADD #$EC // (-20 % 255) + 1 + JNZ :DATA_PTR_0_in_range + LDA #$EB // Set accumulator to #$EB + #$16 = 00 +DATA_PTR_0_in_range: + ADD #$15 // Increment accumulator by #$EC + #$15 - 1 = 1 + STA DATA_PTR_0 + // DATA_PTR_1 + LDA DATA_PTR_1 + // Check if we have reached + // the end of visible RAM + ADD #$EC // (-20 % 255) + 1 + JNZ :DATA_PTR_1_in_range + LDA #$EB // Set accumulator to #$EB + #$16 = 00 +DATA_PTR_1_in_range: + ADD #$15 // Increment accumulator by #$EC + #$15 - 1 = 1 + STA DATA_PTR_1 + // DATA_PTR_2 + LDA DATA_PTR_2 + // Check if we have reached + // the end of visible RAM + ADD #$EC // (-20 % 255) + 1 + JNZ :DATA_PTR_2_in_range + LDA #$EB // Set accumulator to #$EB + #$16 = 00 +DATA_PTR_2_in_range: + ADD #$15 // Increment accumulator by #$EC + #$15 - 1 = 1 + STA DATA_PTR_2 + JMP :loop + +// +// Load RAM from serial line +// + +#define UART_STATUS $FF +#define UART_DATA $FE +#define DATA_PTR $7F +#define MASK_RECV_BUFFER_FULL $FE +#define MASK_TX_BUSY $FF +start: + // Start writing serial data at begin of RAM + LDA #$00 + STA DATA_PTR + STA UART_STATUS // Clear recv_buffer_full; ready to receive next byte. +receive_loop: + LDA UART_STATUS + AND #$02 + JZE :receive_loop + // Byte received. + // Store it in RAM and advance data pointer. + LDA UART_DATA + STA (DATA_PTR) + LDA DATA_PTR + INC + STA DATA_PTR + STA UART_STATUS // Clear recv_buffer_full + // Confirm reception of byte + LDA #$AA + STA UART_DATA + // Wait until byte sent +send_loop: + LDA UART_STATUS + AND #$01 + JNZ :send_loop + JMP :receive_loop diff --git a/src/roms/rom_leds.asm b/src/roms/rom_leds.asm @@ -0,0 +1,16 @@ +#define LEDS $FD +#define START_VALUE $00 +#define COUNTER $01 + .set_address $80 + LDA #$20 + STA START_VALUE +start: + LDA START_VALUE + STA COUNTER +loop: + LDA COUNTER + ADD #$FF + STA COUNTER + STA LEDS + JNZ :loop + JZE :start diff --git a/src/roms/rom_opcode_test_0.asm b/src/roms/rom_opcode_test_0.asm @@ -0,0 +1,61 @@ + // Test all opcodes + .set_address $80 + // LDA, STA & NOP + // Result should be $FF in $00..$03 + LDA #$FF + STA $00 + LDA #$00 + LDA $00 + STA $01 + LDA #$01 + NOP + STA $7F + NOP + LDA ($7F) + NOP + STA $02 + NOP + LDA #$03 + STA $7F + NOP + LDA #$FF + NOP + STA ($7F) + // STA + LDA #$FF + // ADD + // Result should be $FF in $04..$06 + LDA #$FE + ADD #$01 + STA $04 + LDA #$01 + STA $7F + LDA #$FE + ADD $7F + STA $05 + LDA #$02 + STA $7E + LDA #$7E + STA $7F + LDA #$FD + ADD ($7F) + STA $06 + // Test rest of ALU + // Result should be $FF in $07..$0A + LDA #$04 + SUB #$05 + STA $07 + LDA #$FF + AND #$0F + ADD #$F0 + STA $08 + LDA #$0F + ORA #$F0 + STA $09 + LDA #$05 + XOR #$0F + SUB #$0B + STA $0A +end: + LDA $0B + JMP :end diff --git a/src/roms/rom_opcode_test_1.asm b/src/roms/rom_opcode_test_1.asm @@ -0,0 +1,56 @@ + // Test all opcodes + .set_address $80 + // Accumulator manipulation + LDA #$FE + INC + STA $00 + LDA #$00 + DEC + STA $01 + LDA #$FE + ROL + ORA #$02 + STA $02 + LDA #$FB + ROR + ORA #$02 + STA $03 + LDA #$00 + INV + STA $04 + // Jump commands + // Result should be $FF in $05..$07 + // JMP + LDA #$FF + JMP :skip1 + LDA #$01 +skip1: + STA $05 + // JNZ + JNZ :skip2 + LDA #$01 +skip2: + STA $06 + // JZE + JZE :skip3 + STA $07 + JMP :skip4 +skip3: + LDA #$01 + STA $07 +skip4: + // Program execution from RAM + // Result should be $FF in $08 + LDA #$1D // JMP + STA $7E + LDA #:skip6 + STA $7F + JMP $7E +skip5: + JMP :skip5 +skip6: + LDA #$FF + STA $08 +end: + LDA $09 + JMP :end diff --git a/src/roms/rom_uart.asm b/src/roms/rom_uart.asm @@ -0,0 +1,25 @@ +#define UART_STATUS $FF +#define UART_DATA $FE +#define LEDS $FD +.set_address $80 +start: + STA UART_STATUS // Clear recv_buffer_full; ready to receive next byte +receive_loop: + LDA UART_STATUS + STA LEDS + ADD :mask_recv_buffer_full // A is 0 if recv_buffer_full + JNZ :receive_loop + LDA UART_DATA + // Echo byte + STA UART_DATA + // Wait until byte sent +send_loop: + LDA UART_STATUS + ADD :mask_tx_busy_and_recv_buffer_full // A is 0 if tx_busy and recv_buffer_full + JZE :send_loop + // Start over + JMP :start +mask_recv_buffer_full: + $FE +mask_tx_busy_and_recv_buffer_full: + $FD diff --git a/src/tools/eras.pl b/src/tools/eras.pl @@ -0,0 +1,276 @@ +#!/usr/bin/env -S swipl --quiet + +% This is an assembler for the Eris SOC. The program takes two command +% line arguments: The first argument is the assembler program. Second +% argument is the target binary. +% +% Besides writing the target file, the assembler outputs the +% result. Lines in the output start with the current memory +% adress. Opcodes are followed by their binary representation in round +% brackets. Label references are followed by their memory location in +% square brackets. +% +% The assembler knows one directive: .start_of_rom sets the +% current memory address to $80. This is the start address of the ROM. +% In order to assemble a program stored in ROM, this directive should +% precede the actual code. +% +% Copyright 2022 Gerd Beuster (gerd@frombelow.net). This is free soft +% under the GNU GPL v3 license or any later version. See COPYING in +% the root directory for details. + + +% +% Load opcodes generated by microcode compiler. +% + +:- consult("opcodes.pl"). + + +:- use_module(library(dcg/basics)). + +% The actual main predicate. The output file is only written if the +% assembly was successful. +assemble_file(SourceFile, TargetFile) :- + read_file_to_string(SourceFile, S, []), + string_to_list(S, L), + % Step 1: Tokenize the input + tokenize(1, _, Parsed, L, []), + % Step 2: Assemble it + assemble(Assembled, labels{}, Labels, 0, _, Parsed, []), + % Step 3: De-reference labels + dereferenceLabels(Assembled, Final, Labels), + !, + % Write result + get_binary(Final, Binary), + !, + check_for_errors(Binary), + save_binary(TargetFile, Binary), + write("$00: "), + print_map(Final, []). + +% We write a hex file as output. +save_binary(TargetFile, Binary) :- + open(TargetFile, write, S), + write_hex(S, Binary), + close(S). +write_hex(_, []). +write_hex(S, [F|R]) :- + format(S, '~|~`0t~16R~2+ ', F), + write_hex(S, R). + +% If the list of binary values resulting from assembly contains +% the atom 'error', then an error occured in the assembly process. +check_for_errors([]). +check_for_errors([error|_]) :- !, fail. +check_for_errors([_|R]) :- check_for_errors(R). + +% Write source code together with binary representation to standard +% out. +print_map --> print_command, print_map. +print_map --> print_command. +print_command --> [(newline, _, bytePosition(BytePos), _)], + { format('\n$~|~`0t~16R~2+: ', [BytePos]) }. +print_command --> [(labelDefinition(L), _, _, _)], + { format('~w:', L) }. +print_command --> [(opcode(P), _, _, assembly(A))], + { format(' ~w [$~|~`0t~16R~2+]', [P, A]) }. +print_command --> [(number(N, direct), _, _, _)], + { format(' $~|~`0t~16R~2+', [N]) }. +print_command --> [(number(N, immediate), _, _, _)], + { format(' #$~|~`0t~16R~2+', [N]) }. +print_command --> [(number(N, indirect), _, _, _)], + { format(' ($~|~`0t~16R~2+)', [N]) }. +print_command --> [(comment(C), _, _, _)], + { format(' //~w', [C]) }. +print_command --> [(labelReference(E, direct), _, _, assembly(A))], + { format(' :~w [$~|~`0t~16R~2+]', [E, A]) }. +print_command --> [(labelReference(E, immediate), _, _, assembly(A))], + { format(' #:~w [$~|~`0t~16R~2+]', [E, A]) }. +print_command --> [(labelReference(E, indirect), _, _, assembly(A))], + { format(' (:~w [$~|~`0t~16R~2+])', [E, A]) }. +print_command --> [(assembler_directive(D), _, _, _)], + { format('.~w', [D]) }. + +% The result of the assembly is a list of tokens augmented by their +% binary representation. Here we remove everything but the binary +% representation from the list elements, resulting in a sequence of +% bytes. +get_binary([], []). +get_binary([(_, _, _, assembly(A))|R], [A|B]) :- + get_binary(R, B). +get_binary([(_, _, _, assembly())|R], B) :- + get_binary(R, B). + + +% Predicate assemble is the parser. It takes the tuples returned +% by the tokenizer and augments them by the corresponding byte +% representation in term assembly/1. +% +% When translating the tokens to their byte representation, a list of +% labels and their representation in memory is created. These +% variables have names like L0 and L1, for the labels before/after a +% token is processed. In order to associate the labels with their +% memory location, we keep track of the current memory location in the +% way in varaibles named like B0 (processing the next token) and B1 +% (processing the next token). The actual variable names may vary. + +assemble(A, L0, L2, B0, B2) --> + command(F, L0, L1, B0, B1), + assemble(R, L1, L2, B1, B2), + { append(F, R, A) }. +assemble(F, L0, L1, B0, B1) --> command(F, L0, L1, B0, B1). + +% Newslines and comments do not generate assembler code. +command([(newline, lineNumber(N), bytePosition(B), assembly())], + L, L, B, B) --> + [(newline, lineNumber(N))]. +command([(comment(S), lineNumber(N), bytePosition(B), assembly())], + L, L, B, B) --> + [(comment(S), lineNumber(N))]. +% Label references are replaced by the (1 byte) address of the label, +% therefore the byte counter advances by 1. The symbolic label is +% stored as the "byte code" in assembly/1. In the second pass, these +% references are resolved by the number representing the absolute +% position. +command([(labelReference(S, M), lineNumber(N), bytePosition(B), assembly(S))], + L, L, B, B1) --> + [(labelReference(S, M), lineNumber(N))], + { B1 is B + 1 }. +% Number are very similar to label references. The difference is that +% we can already generate assemble code for them; no future +% de-referencing required. +command([(number(X, M), lineNumber(N), bytePosition(B), assembly(X))], + L, L, B, B1) --> + [(number(X, M), lineNumber(N))], + { B1 is B + 1 }. +% Label definitions refer to the current byte position. We store the +% association of label and byte position. +command([(labelDefinition(S), lineNumber(N), bytePosition(B), assembly())], + L, L.put(S, B), B, B) --> + [(labelDefinition(S), lineNumber(N))]. +% Opcodes may or may not be followed by an argument (number or label +% reference). Since the argument indicates the addressing mode of the +% opcode, we have to parse them together. +% - Two byte opcodes +command([(opcode(S), lineNumber(LN0), bytePosition(B), assembly(OpByte)), + (number(X, M), lineNumber(LN1), bytePosition(B1), assembly(X))], + L, L, B, B2) --> + [(opcode(S), lineNumber(LN0)), + (number(X, M), lineNumber(LN1))], + { opcode_to_byte(S, M, OpByte), + B1 is B + 1, + B2 is B + 2 }. +command([(opcode(S), lineNumber(LN0), bytePosition(B), assembly(OpByte)), + (labelReference(X, M), lineNumber(LN1), bytePosition(B1), assembly(X))], + L, L, B, B2) --> + [(opcode(S), lineNumber(LN0)), + (labelReference(X, M), lineNumber(LN1))], + { opcode_to_byte(S, M, OpByte), + B1 is B + 1, + B2 is B + 2 }. +% - One byte opcodes +command([(opcode(S), lineNumber(LN0), bytePosition(B), assembly(OpByte))], + L, L, B, B1) --> + [(opcode(S), lineNumber(LN0))], + { opcode_to_byte(S, OpByte), + B1 is B + 1 }. +% - Unkown opcodes +command([(opcode(S), lineNumber(LN0), bytePosition(B), assembly(error))], + L, L, B, B) --> + [(opcode(S), lineNumber(LN0))], + { format('ERROR: Unknown opcode/addressing mode "~w" (line ~w)\n', [S, LN0]) }. +% Compiler directive set_address changes the current byte address. It +% does not generate any assembly code on its own. +command([(assembler_directive("set_address"), lineNumber(LN0), bytePosition(B1), + assembly()), + (number(B2, direct), lineNumber(LN1), bytePosition(B1), assembly())], + L, L, B1, B2) --> + [(assembler_directive("set_address"), lineNumber(LN0)), + (number(B2, direct), lineNumber(LN1))]. + +% At this point, the assembly code is a list of bytes interspersed +% with label references. Here we replace the label references by the +% corresponding memory location. +dereferenceLabels([], [], _). +dereferenceLabels([(labelReference(L, M), lineNumber(N), bytePosition(P), + assembly(L))|RL], + [(labelReference(L, M), lineNumber(N), bytePosition(P), + assembly(B))|R], + Labels) :- + get_dict(L, Labels, B), + dereferenceLabels(RL, R, Labels). +dereferenceLabels([(labelReference(L, M), lineNumber(N), assembly(L))|RL], + [(labelReference(L, M), lineNumber(N), assembly(error))|R], + Labels) :- + format('ERROR: Unknown label "~w" (line ~w)\n', [L, N]), + dereferenceLabels(RL, R, Labels). +dereferenceLabels([F|R], [F|RD], L) :- + dereferenceLabels(R, RD, L). + +% The tokenizer knows the following tokens: +% newline, comment, labelReference, labelDefinition, number, and +% opcode. The differen tokens are identified as follows: +% - Comments start with '//' and end at the end of the line. +% - Labels end with ':'. +% - Label references begin with ':'. +% - Numbers begin with '$'. +% - Everything else is an opcode. +% We store the line number of the token with the token for error reporting. + +% LNum0 and LNum1 keep track of line numbers: LNum0 is the line number +% before parsing the next token, LNum1 is the line number after +% parsing the next token. +tokenize(LNum0, LNum1, [T]) --> token(LNum0, LNum1, T). +tokenize(LNum0, LNum2, [T|R]) --> + token(LNum0, LNum1, T), tokenize(LNum1, LNum2, R). +% When we parse a new line, the line number is incremented. +token(LNum0, LNum1, (newline, lineNumber(LNum0))) --> + whites, [10], {LNum1 is LNum0 + 1}. +% Parse assembler directives +token(LNum, LNum, (assembler_directive(A), lineNumber(LNum))) --> + whites, [0'.], string_without("\n \t", L), { string_to_list(A, L) }. +% Parse comments +token(LNum, LNum, (comment(C), lineNumber(LNum))) --> + whites, [0'/], [0'/], string_without("\n", L), { string_to_list(C, L) }. +% Label references - direct addressing +token(LNum, LNum, (labelReference(A, direct), lineNumber(LNum))) --> + whites, [0':], string_without("\n \t", L), + { string_to_list(S, L), atom_string(A, S) }. +% Label references - immediate addressing +token(LNum, LNum, (labelReference(A, immediate), lineNumber(LNum))) --> + whites, [0'#], [0':], string_without("\n \t", L), + { string_to_list(S, L), atom_string(A, S) }. +% Label references - indirect addressing +token(LNum, LNum, (labelReference(A, indirect), lineNumber(LNum))) --> + whites, [0'(], [0':], string_without("\n \t", L), [0')], + { string_to_list(S, L), atom_string(A, S) }. +% Label definitions +token(LNum, LNum, (labelDefinition(A), lineNumber(LNum))) --> + whites, string_without("\r\n \t:", L), [0':], + { string_to_list(S, L), atom_string(A, S) }. +% Parse numbers - direct addressing mode +token(LNum, LNum, (number(N, direct), lineNumber(LNum))) --> + whites, [0'$], xinteger(N). +% Parse numbers - immediate addressing mode +token(LNum, LNum, (number(N, immediate), lineNumber(LNum))) --> + whites, [0'#], [0'$], xinteger(N). +% Parse numbers - indirect addressing mode +token(LNum, LNum, (number(N, indirect), lineNumber(LNum))) --> + whites, [0'(], [0'$], xinteger(N), [0')]. +% Everything not parsed yet is an opcode +token(LNum, LNum, (opcode(P), lineNumber(LNum))) --> + whites, string_without("\n \t", L), { string_to_list(P, L) }. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +:- initialization(main, main). + +main([Source, Binary]) :- + !, + assemble_file(Source, Binary), + nl. + +main(_) :- + writeln('Usage: eras.pl <SOURCE> <BINARY>'). diff --git a/src/tools/mc_compiler.py b/src/tools/mc_compiler.py @@ -0,0 +1,342 @@ +#!/usr/bin/env python3 + +# Copyright 2022 Gerd Beuster (gerd@frombelow.net). This is free soft +# under the GNU GPL v3 license or any later version. See COPYING in +# the root directory for details. + +import sys + +pc_set_uncond = 1 << 0 +pc_set_if_zero = 1 << 1 +pc_set_if_nonzero = 1 << 2 +pc_inc = 1 << 3 +dp_set = 1 << 4 +dp_get = 1 << 5 +mem_set = 1 << 6 +reg_a_get = 1 << 7 +reg_a_set = 0b001 << 8 +reg_a_inc = 0b010 << 8 +reg_a_dec = 0b011 << 8 +reg_a_rol = 0b100 << 8 +reg_a_ror = 0b101 << 8 +reg_a_inv = 0b110 << 8 +mip_set = 1 << 11 +alu_add = 0b001 << 12 +alu_sub = 0b010 << 12 +# Multiplication and division occpuy too many PLBs +# alu_mul = 0b011 << 12 +# alu_div = 0b100 << 12 +alu_and = 0b101 << 12 +alu_or = 0b110 << 12 +alu_xor = 0b111 << 12 + +# Loading the address bus +# +# In every cycle, the CPU loads the address bus with either +# the value of the program counter or the data pointer. +# Therefore we only need dp_get, a flag indicating if the address bus +# loads the data pointer. If this flag is not set, the address bus +# loads the program counter. + +# Loading the data bus +# +# In every cycle, the CPU loads the data bus with either +# the value from accumulator, the memory, or the alu. +# Accumulator access has priority. If reg_a_get is not set, +# the data bus is loaded from the ALU if alu_... is set and from memory +# otherwise. + +# Summary: + +# - Unless dp_get is set, the address bus is loaded from the PC on every +# instruction. +# - If neither alu_... nor reg_a_get is set, the data bus is loaded +# from memory on every instructions +# +# Therefore microcode 0 loads the data bus with the memory location +# given by the PC. + +opcode = [['NOP', + [ + # First instruction implicitly loads address bus with PC + # and reads memory at that location. The memory content is loaded on the data bus in the next step, + # and the MIP is set from the data bus. + # The PC is incremented such that the operand of the + # next instruction can be fetched in the next step + 0, + pc_inc | mip_set, + ]], + ['LDA', 'direct', + [ + # We want to load from the memory address pointed to + # by the PC. We read the memory address (i.e. the pointer value) ... + 0, + # ... and store it DP. + dp_set, + # Now we transfer this value to the address bus, read this memory + # address ... + dp_get, + # ... and store it in the accumulator. We also increment + # the PC such that we can fetch the next instruction + # and the following step. + dp_get | reg_a_set | pc_inc, + # We are done. Fetch next instruction and increment PC such that + # the next instruction can load its argument. + 0, + pc_inc | mip_set, + ]], + ['LDA', 'immediate', + [ + reg_a_set | pc_inc, + 0, + pc_inc | mip_set, + ]], + ['LDA', 'indirect', + [ + 0, + dp_set, + dp_get | dp_set, + dp_get, + dp_get | reg_a_set | pc_inc, + 0, + pc_inc | mip_set, + ]], + ['STA', 'direct', + [ + 0, + dp_set, + dp_get | mem_set | reg_a_get | pc_inc, + 0, + pc_inc | mip_set, + ]], + ['STA', 'indirect', + [ + 0, + dp_set, + dp_get | dp_set, + dp_get | mem_set |reg_a_get | pc_inc, + 0, + pc_inc | mip_set, + ]], + ['JMP', 'direct', + [ + 0, + pc_set_uncond, + 0, + pc_inc | mip_set, + ]], + ['JNZ', 'direct', + [ + 0, + pc_inc | pc_set_if_nonzero, + 0, + pc_inc | mip_set, + ]], + ['JZE', 'direct', + [ + 0, + pc_inc | pc_set_if_zero, + 0, + pc_inc | mip_set, + ]], + ['ADD', 'direct', + [ + 0, + dp_set, + dp_get, + dp_get, + alu_add | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['ADD', 'indirect', + [ + 0, + dp_set, + dp_get | dp_set, + dp_get, + dp_get, + pc_inc | alu_add | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['ADD', 'immediate', + [ + 0, + alu_add | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['SUB', 'direct', + [ + 0, + dp_set, + dp_get, + dp_get, + alu_sub | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['SUB', 'indirect', + [ + 0, + dp_set, + dp_get | dp_set, + dp_get, + dp_get, + pc_inc | alu_sub | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['SUB', 'immediate', + [ + 0, + alu_sub | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['AND', 'direct', + [ + 0, + dp_set, + dp_get, + dp_get, + alu_and | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['AND', 'indirect', + [ + 0, + dp_set, + dp_get | dp_set, + dp_get, + dp_get, + pc_inc | alu_and | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['AND', 'immediate', + [ + 0, + alu_and | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['ORA', 'direct', + [ + 0, + dp_set, + dp_get, + dp_get, + alu_or | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['ORA', 'indirect', + [ + 0, + dp_set, + dp_get | dp_set, + dp_get, + dp_get, + pc_inc | alu_or | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['ORA', 'immediate', + [ + 0, + alu_or | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['XOR', 'direct', + [ + 0, + dp_set, + dp_get, + dp_get, + alu_xor | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['XOR', 'indirect', + [ + 0, + dp_set, + dp_get | dp_set, + dp_get, + dp_get, + pc_inc | alu_xor | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['XOR', 'immediate', + [ + 0, + alu_xor | pc_inc | reg_a_set, + 0, + pc_inc | mip_set, + ]], + ['INC', + [ + reg_a_inc, + pc_inc | mip_set, + ]], + ['DEC', + [ + reg_a_dec, + pc_inc | mip_set, + ]], + ['ROL', + [ + reg_a_rol, + pc_inc | mip_set, + ]], + ['ROR', + [ + reg_a_ror, + pc_inc | mip_set, + ]], + ['INV', + [ + reg_a_inv, + pc_inc | mip_set, + ]], +] + +if len(sys.argv) != 2: + sys.stderr.write("Usage: mc_compiler.py microcode|opcode\n") + sys.exit(-1) + +if sys.argv[1] == 'microcode': + # Since ROM data has a width of 8 bit, we split the microcode into two + # rom files. + with open('microcode_rom_lsb.dat', 'w') as r_lsb: + r_lsb.write('// Microcode - LSB\n') + with open('microcode_rom_msb.dat', 'w') as r_msb: + r_msb.write('// Microcode - MSB\n') + byte_count = 0 + for o in opcode: + r_lsb.write('// {}\n'.format(o[0])) + r_msb.write('// {}\n'.format(o[0])) + r_lsb.write("".join(["{:02X} ".format(x & 0xFF) for x in o[-1]]) + "\n") + r_msb.write("".join(["{:02X} ".format(x >> 8) for x in o[-1]]) + "\n") + byte_count += len(o[1]) + r_lsb.write('// Number of instructions: {}\n'.format(byte_count)) + r_msb.write('// Number of instructions: {}\n'.format(byte_count)) + + +if sys.argv[1] == 'opcodes': + byte_count = 0 + with open('opcodes.pl', 'w') as f: + f.write(':- discontiguous opcode_to_byte/2.\n') + for o in opcode: + if(len(o) == 2): + # Opcode without addressing mode + f.write('opcode_to_byte("{}", {}).\n'.format(o[0], byte_count)) + else: + # Opcode with addressing mode + f.write('opcode_to_byte("{}", {}, {}).\n'.format(o[0], o[1], byte_count)) + byte_count += len(o[-1]) diff --git a/src/tools/send_serial.py b/src/tools/send_serial.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 + +# Copyright 2022 Gerd Beuster (gerd@frombelow.net). This is free soft +# under the GNU GPL v3 license or any later version. See COPYING in +# the root directory for details. + +import sys +import serial +import time + +PORT = '/dev/ttyUSB1' +SPEED = 115200 + +def send_file(filename): + s = serial.Serial(PORT, SPEED) + with open(filename, "r") as f: + for line in f: + line_as_bytes = map(lambda x: int(x, 16), filter(lambda x: x != '', line.split(" "))) + for b in line_as_bytes: + print("{:02X}".format(b)) + time.sleep(.1) + s.write(bytes([b])) + assert(s.read(1) == b'\xaa') + +if __name__ == '__main__': + send_file(filename=sys.argv[1]) diff --git a/src/uart.v b/src/uart.v @@ -0,0 +1,155 @@ +/* + * Copyright 2022 Gerd Beuster (gerd@frombelow.net). This is free + * soft-/hardware under the GNU GPL v3 license or any later + * version. See COPYING in the root directory for details. + */ + +`ifndef uart_v + `define uart_v + +// In order to send a byte, din is set to the byte to be send and +// write is set to 1. While transmitting, bit 0 of the status register +// is 1. +// +// In order to receive a byte, the receive buffer must be cleared by +// writing to the status register. Once the byte is received, bit 1 of +// the status register is set to 1. + +module uart(input clk, // 12 Mhz system clock + // Data to be send via the serial line is read from din. + input [7:0] din, + // When reg_select is set to 0 (see below), dout carries + // the last byte received via the serial line. + // When reg_select is set to 1, dout carries the current bits: + // Bit 0: The UART is in the process of sending the byte at din + // Bit 1: The UART received a byte. + output [7:0] dout, + // When reg_select is set to 0 (see below), setting write to 1 + // starts serial transmission of din. + // When reg_select is set to 1, setting write to 1 clears + // the receive buffer. + input write, + // 0: Data Register + // 1: Status register + input reg_select, + // Connections to hardware lines + output reg tx, + input rx); + + reg [9:0] tx_buffer; // Internal transmit buffer (start bit, data, stop bit) + reg [7:0] rx_buffer; // Internal receive buffer + reg [7:0] received_byte; // Last complete byte received + reg [7:0] bit_time_tx; // Clock ticks until bit transmitted + reg [3:0] curr_bit_tx; // Index of bit currently transmitted + reg rx_busy; + reg tx_busy; + wire recv_buffer_full; + + parameter ticks_per_bit = 104; // Clock ticks per bit for 115200 bps @ 12 Mhz + + assign dout = reg_select ? {6'b000000, recv_buffer_full, tx_busy} : received_byte; + + initial + begin + tx_busy <= 0; + tx <= 1; + curr_bit_tx <= 0; + rx_busy <= 0; + end + + /* + * Transmitter + * + */ + + always @(posedge(clk)) + begin + // Begin of transmission + if (write && !reg_select && !tx_busy) + // Transmissions starts on write operation to data register: + // Fill the internal transmit buffer, and get busy. + begin + tx_buffer <= {1'b1, din, 1'b0}; + curr_bit_tx <= 0; + bit_time_tx <= ticks_per_bit; + tx_busy <= 1; + end + // End of transmission + if (curr_bit_tx == 10) + begin + // Keep tx high will not transmitting. + tx <= 1; + // If the CPU clock is significangtly slower than the + // system clock, write may still be high. In order to + // avoid sending the same byte again, we only set tx_busy + // to low when write is low as well. + if(!write) + begin + tx_busy <= 0; + curr_bit_tx <= 0; + end + end // if (curr_bit_tx == 10) + else + // In transmission + begin + if (tx_busy) + // Output current bit + begin + tx <= tx_buffer[curr_bit_tx]; + bit_time_tx <= bit_time_tx - 1; + end + if (bit_time_tx == 0) + // Switch to next bit + begin + curr_bit_tx <= curr_bit_tx + 1; + bit_time_tx <= ticks_per_bit; + end + end + end // always @ (posedge(clk)) + + /* + * Receiver + * + */ + + reg [7:0] bit_time_rx; // Clock ticks until bit received + reg [3:0] curr_bit_rx; // Index of bit currently received + + assign recv_buffer_full = (curr_bit_rx == 9); + always @(posedge(clk)) + begin + if (write && reg_select) + curr_bit_rx <= 0; + else + begin + if (!rx_busy && !rx) + begin + // Start receving once we get the start bit + rx_busy <= 1; + curr_bit_rx <= 0; + // bit_time_rx hits 0 in the middle + // of the first data bit + bit_time_rx <= ticks_per_bit * 1.5; + end + else if ((curr_bit_rx == 9) && rx) + begin + // If this is the stop bit, we are done + rx_busy <= 0; + received_byte <= rx_buffer; + end + else if ((rx_busy) && (bit_time_rx == 0)) + // We are in the middle of the next bit. + begin + // Read it + rx_buffer[curr_bit_rx] <= rx; + curr_bit_rx <= curr_bit_rx + 1; + bit_time_rx <= ticks_per_bit; + end + else + bit_time_rx <= bit_time_rx - 1; + end + end // always @ (posedge(clk)) + +endmodule + +`endif diff --git a/src/ws2811.v b/src/ws2811.v @@ -0,0 +1,396 @@ +/* + * Copyright 2022 Gerd Beuster (gerd@frombelow.net). This is free + * soft-/hardware under the GNU GPL v3 license or any later + * version. See COPYING in the root directory for details. + */ + +`ifndef ws2811_v + `define ws2811_v + +// Module led_monitor uses a number of sub-modules: +// +// - Module vram listens to the CPU internals and the busses in order +// to keep track of the system state, including memory value. (System +// memory is not tapped but mirrored by listening to the busses and +// write operations.) +// +// - Module bit2pixel converts 3 bit GRB data to 24 bits GRB data +// suitable for the WS2811 LED matrix. +// +// - Module ws2811 sends the sequence of 24 bits GRB data to the LED +// matrix in WS2811 protocol. + +module led_monitor(input fast_clk, + // Memory content is mirrored for monitoring + // purposes by listening to data and address bus + input [7:0] data_bus, + input [7:0] address_bus, + input mem_set, + // Input of CPU debugging output + input [15:0] control_logic, + input [7:0] reg_a, + input [7:0] alu, + input [7:0] pc, + input [7:0] dp, + // Data line of WS2811 matrix + output ws2811_dout); + + // Each row of the 16x16 matrix represents two bytes, + // therefore the size of the video RAM of the matrix + // is 32 bytes + parameter vram_size = 32; + // WS2811 timing + parameter cycles_t0h = 4; // 0: Cycles for high + parameter cycles_t0l = 13; // 0: Cycles for low + parameter cycles_t1h = 13; // 1: Cycles for high + parameter cycles_t1l = 4; // 1: Cycles for low + parameter cycles_reset = 4000; // Cycles for rest + + // The output of the video RAM is fed into bit2pixel in order to + // convert video RAM data into pixel values for the LED matrix. + wire [2:0] vram_dout; + // vram_next requests the next bit from video ram. Video ram sets + // vram_eod when video ram transfer is completed. + wire vram_next, vram_eod; + vram #(.size(vram_size)) + vram_mem (.din(data_bus), + .ain(address_bus), + .mem_set(mem_set), + .control_logic(control_logic), + .reg_a(reg_a), + .alu(alu), + .pc(pc), + .dp(dp), + .vclk(fast_clk), + .veod(vram_eod), .vnext(vram_next), + .vout(vram_dout)); + // bs_next requests to set bs_dout to the next pixel. bs_eod + // indicates that all pixels have been transmitted. + wire bs_next, bs_dout, bs_eod; + bit2pixel b2p (.clk(fast_clk), + .vram_din(vram_dout), .vram_eod(vram_eod), + .vram_next(vram_next), + .dout_next(bs_next), .dout(bs_dout), + .dout_eod(bs_eod)); + // ws2811 translates the bit values of pixels to the high/low + // signals of the WS2811 protocol. + ws2811 #(.cycles_t0h(cycles_t0h), .cycles_t0l(cycles_t0l), + .cycles_t1h(cycles_t1h), .cycles_t1l(cycles_t1l), + .cycles_reset(cycles_reset)) + ws (.clk(fast_clk), + .din(bs_dout), + .next(bs_next), + .eod(bs_eod), .dout(ws2811_dout)); +endmodule + +// The input interface of the VRAM connects to the databus, the output +// interface to WS2811. The output interface is not random access but +// provides a bitstream. +module vram(// VRAM input interfaces to read internal state + input [7:0] din, + input [7:0] ain, + input mem_set, // Write din to memory cell + input [15:0] control_logic, // All control logic flags + input [7:0] reg_a, + input [7:0] alu, + input [7:0] pc, + input [7:0] dp, + // VRAM interface for video output + input vclk, + input vnext, // Dump next bit + output reg veod, + output reg [2:0] vout // Stream output + ); + + parameter size = 32; + + reg [7:0] mem [0:size-1]; + reg [$clog2(size)-1:0] v_byte_ptr = 0; + reg [2:0] v_bit_ptr = 0; + reg [7:0] byte_out; + + // The LED matrix is wired in snake wiring, ain_snake allows us to + // access memory cells in the usual left-to-right, row-by-row + // order. We still have to remember that the order of LEDs in the + // memory cells in every other row is reversed. + wire [7:0] ain_snake; + assign ain_snake = (((ain % 4) == 0) ? + (ain + 9) + : (((ain % 4) == 1) ? + (ain + 7) + : (ain + 8))); + wire [$clog2(size)-1:0] v_byte_ptr_snake; + assign v_byte_ptr_snake = (((v_byte_ptr % 4) == 0) ? + (v_byte_ptr - 7) + : (((v_byte_ptr % 4) == 1) ? + (v_byte_ptr - 9) + : (v_byte_ptr - 8))); + + // When using BRAM, we can only write one cell on each + // cycle. Therefore we have to split VRAM updates into a number of + // cycles. The output will only be accurate if the bus clock is + // much slower than the VRAM clock that all VRAM parts are updated + // in one bus clock cycle. + `define state_update_control_logic_0 0 + `define state_update_control_logic_1 1 + `define state_update_address_bus 2 + `define state_update_data_bus 3 + `define state_update_accumulator 4 + `define state_update_alu 5 + `define state_update_pc 6 + `define state_update_dp 7 + `define state_update_mem 8 + reg [3:0] state = `state_update_control_logic_0; + always @(posedge(vclk)) + case (state) + `state_update_control_logic_0: + begin + mem[0] <= control_logic[7:0]; + state <= `state_update_control_logic_1; + end + `state_update_control_logic_1: + begin + mem[1] <= { 1'b0, control_logic[15:8] }; + state <= `state_update_address_bus; + end + `state_update_address_bus: + begin + mem[2] <= { ain[0], ain[1], ain[2], ain[3], ain[4], ain[5], ain[6], ain[7] }; + state <= `state_update_data_bus; + end + `state_update_data_bus: + begin + mem[3] <= { din[0], din[1], din[2], din[3], din[4], din[5], din[6], din[7] }; + state <= `state_update_accumulator; + end + `state_update_alu: + begin + mem[4] <= alu; + state <= `state_update_pc; + end + `state_update_accumulator: + begin + mem[5] <= reg_a; + state <= `state_update_alu; + end + `state_update_pc: + begin + mem[6] <= { pc[0], pc[1], pc[2], pc[3], pc[4], pc[5], pc[6], pc[7] }; + state <= `state_update_dp; + end + `state_update_dp: + begin + mem[7] <= { dp[0], dp[1], dp[2], dp[3], dp[4], dp[5], dp[6], dp[7] }; + state <= `state_update_mem; + end + `state_update_mem: + begin + if (mem_set && (ain <= (size - 9))) + // We are in the phase for updating memory, and + // the memory in the range shown is written. Therefore we update it. + if ((ain % 4) > 1) + // While ain_snake de-mangles the order of memory cells, we still have + // to reverse the bit order of the memory cells in every other row due + // to the snake wiring. + mem[ain_snake] <= {din[0], din[1], din[2], din[3], + din[4], din[5], din[6], din[7] }; + else + mem[ain_snake] <= din; + state <= `state_update_control_logic_0; + end + endcase + + + // Output interface: Dump memory as bitstream for output on LED array. + always @(posedge(vclk)) + begin + byte_out <= mem[v_byte_ptr]; + vout <= ((v_byte_ptr < 2) ? + // First row shows bits of control logic + ((v_bit_ptr % 2 == 0) ? + // Alternate colors when showing control logic bits + { 1'b0, byte_out[v_bit_ptr], 1'b0 } + : { 1'b0, 1'b0 , byte_out[v_bit_ptr] }) + : ((v_byte_ptr < 8) ? + // Registers & busses + ((v_byte_ptr % 2 == 0) ? + // In alternating colors + { 1'b0, byte_out[v_bit_ptr], 1'b0 } + : { 1'b0, 1'b0, byte_out[v_bit_ptr] }) + : + // Memory content shown in blue. In order to + // indicate the location of the PC and the DP, + // non-set bits of the memory cell pointed to by + // the PC and DP are colored in the respective + // color. + { byte_out[v_bit_ptr], + ((v_byte_ptr_snake == pc) && (byte_out[v_bit_ptr] == 1'b0)) ? 1'b1 : 1'b0, + ((v_byte_ptr_snake == dp) && (byte_out[v_bit_ptr] == 1'b0)) ? 1'b1 : 1'b0 + })); + veod <= ((v_bit_ptr == 7) && (v_byte_ptr == (size - 1))); + // Advance to next output bit + if (vnext) + begin + // Memory is organized as bytes, so we may have to + // advance to the next byte when all bits of the current + // bit have been output. + // Note that we do not set v_byte_ptr and v_bit_ptr explicitly + // back to 0 when a complete byte has been output; we simply let + // it overflow. + if (v_bit_ptr == 7) + v_byte_ptr <= v_byte_ptr + 1; + v_bit_ptr <= v_bit_ptr + 1; + end + end // always @ (posedge(vclk)) +endmodule + +// Takes a stream of bit triples representing 3 bit GRB color values. +// These triplets are translated to a 24 bit GRB value as input for +// the ws2811 input stream by module ws2811. +module bit2pixel(input clk, + // Interface to VRAM + input [2:0] vram_din, + input vram_eod, + output reg vram_next, + // Interface to WS2811 + output reg dout, + output reg dout_eod, + input dout_next); + + parameter LED_INTENSITY = 3; // Intensity of LED; range [1..7] + reg init = 0; + // Color of output bit + reg [1:0] dout_color; + // Position of output bit in output byte + reg [2:0] dout_bit; + + always @(posedge(clk)) + if (init == 0) + begin + init <= 1; + dout_eod <= 0; + dout <= 0; + dout_color <= 0; + dout_bit <= 0; + end + else + begin + // Each input bit is translated to 3 colors of 8 bits + // intensity. We output 0 unless we output the desired color + // in the desired intensity. + dout <= (dout_bit == 8-LED_INTENSITY) ? vram_din[dout_color] : 0; + dout_eod <= ((vram_eod) && (dout_color == 2) && + (dout_bit == 7)); + if (dout_next) + begin + if (dout_bit == 7) + // 8 bit have been output. Switch to next color + // channel. + if(dout_color == 2) + begin + dout_color <= 0; + // Since all colors have been output, the output + // for this bit from VRAM is complete and we + // request the next one. + vram_next <= 1; + end + else + dout_color <= dout_color + 1; + // Since width of dout_bit is 3 bit, it runs + // over bits 0..7 + dout_bit <= dout_bit + 1; + end // if (dout_next) + else + vram_next <= 0; + end + +endmodule + +module ws2811(input clk, input din, input eod, output reg next, output reg dout); + + // One clock cycle @ 12 Mhz: + // 83.3333 ns + + // Protocol + + // https://www.tme.eu/Document/26d574b43ad9ddaffa4d5bcd140ec145/WS2811.pdf + // Send order: GRB, MSB First + // 0: High 220 ns ~ 380 ns | Low 580 ns ~ 1600 ns + // 1: High 580 ns ~ 1600 ns | Low 220 ns ~ 420 ns + // Frame length: 800 ns ~ 1980 ns + // Reset: > 280000 ns + parameter cycles_t0h = 4; // 0: Cycles for high + parameter cycles_t0l = 13; // 0: Cycles for low + parameter cycles_t1h = 13; // 1: Cycles for high + parameter cycles_t1l = 4; // 1: Cycles for low + parameter cycles_reset = 4000; // Cycles for rest + + `define state_reset 0 + `define state_high 1 + `define state_low 2 + reg [1:0] state_ptr; + reg [15:0] cycles_counter; + + reg init = 0; + + always @(posedge(clk)) + if (init == 0) + begin + init <= 1; + state_ptr <= `state_reset; + cycles_counter <= cycles_reset; + dout <= 0; + next <= 0; + end + else + begin + cycles_counter <= cycles_counter + 1; + next <= 0; + // In state_reset, dout is kept low in order to initate + // a new transmission of color values for all LEDs. After + // that, we alternate between state_high and state_low, + // sending each color value bit by PWM. Each cycle + // represents a bit: The length of the high/low phases + // depends on the bit value. + case (state_ptr) + `state_reset: + if (cycles_counter == cycles_reset) + begin + state_ptr <= `state_high; + cycles_counter <= 0; + dout <= 1; + end + `state_high: + if (cycles_counter == ((din == 1'b1) ? + cycles_t1h-1 : cycles_t0h-1)) + begin + state_ptr <= `state_low; + cycles_counter <= 0; + dout <= 0; + end + `state_low: + if (cycles_counter == ((din == 1'b1) ? + cycles_t1l-1 : cycles_t0l-1)) + begin + if (eod) + // When all bits are send, we are done and start over. + begin + state_ptr <= `state_reset; + cycles_counter <= 0; + dout <= 0; + end + else + // Transmit next bit + begin + state_ptr <= `state_high; + cycles_counter <= 0; + dout <= 1; + end // else: !if(eod) + next <= 1; + end + endcase // case (state_ptr) + end + +endmodule + +`endif