From a8256910d40a0eee85bf539a3f120c9d92485f3f Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Tue, 26 Jul 2016 23:50:23 +0200 Subject: o Working version with support for Arduino parts. --- CMakeLists.txt | 8 +- KicadNetLexer.g4 | 8 +- KicadNetParser.g4 | 19 ++- examples/arduino-led/arduino-led.ino | 10 +- examples/arduino-led/schematic.h | 9 ++ examples/arduino-led/schematic/arduino-led.net | 132 ++++++++++++-------- examples/arduino-led/schematic/arduino-led.sch | 52 +++++++- include-priv/trygvis/antlr.h | 67 ++++++++++ include-priv/trygvis/string_utils.h | 23 ++++ include/trygvis/kicad.h | 42 +++++-- kicad.cpp | 121 +++++++----------- main.cpp | 166 ++++++++++++++++++++++--- 12 files changed, 487 insertions(+), 170 deletions(-) create mode 100644 examples/arduino-led/schematic.h create mode 100644 include-priv/trygvis/antlr.h create mode 100644 include-priv/trygvis/string_utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 914bfb9..ff91ac6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,9 +6,9 @@ antlr4_add_target(TARGET KicadNet LEXER KicadNetLexer.g4 PARSER KicadNetParser.g set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -set(SOURCE_FILES main.cpp kicad.cpp include/trygvis/kicad.h) +set(SOURCE_FILES main.cpp kicad.cpp include/trygvis/kicad.h include-priv/trygvis/antlr.h include-priv/trygvis/string_utils.h) add_executable(kicad_utils ${SOURCE_FILES}) -target_include_directories(kicad_utils PUBLIC include) +target_include_directories(kicad_utils PUBLIC include PRIVATE include-priv) target_link_libraries(kicad_utils KicadNet Antlr4::antlr4_shared) target_compile_options(kicad_utils PUBLIC --std=c++14) target_compile_options(kicad_utils PUBLIC -Wall -Wextra) @@ -56,9 +56,7 @@ function(kicad_gen) message("NET=${NET}") add_custom_command(OUTPUT ${OUTPUT_FILE} - COMMAND kicad_utils -f ${NET} -r ${REF} > kicad-${TARGET}.tmp - COMMAND cmake -E make_directory -p ${OUTPUT_DIR} - COMMAND cmake -E rename kicad-${TARGET}.tmp ${OUTPUT_FILE} + COMMAND kicad_utils -n ${NET} -r ${REF} -o ${OUTPUT_FILE} MAIN_DEPENDENCY ${NET} DEPENDS kicad_utils COMMENT "Generating ${TARGET}") diff --git a/KicadNetLexer.g4 b/KicadNetLexer.g4 index 55bda85..e10f7e7 100644 --- a/KicadNetLexer.g4 +++ b/KicadNetLexer.g4 @@ -8,23 +8,25 @@ QUOTE: '"'; CODE: 'code'; COMP: 'comp'; FIELD: 'field'; +LIBSOURCE: 'libsource'; +LIBPART: 'libpart'; +LIB: 'lib'; NAME: 'name'; NET: 'net'; NODE: 'node'; NUM: 'num'; +PART: 'part'; PIN: 'pin'; REF: 'ref'; TYPE: 'type'; VALUE: 'value'; - -//STRING: '"' (~[\\"] | '\\' [\\"])* '"'; STRING: '"' ~["]* '"'; INTEGER: [0-9]+; ID - : [/+~\_\-\.\*/a-zA-Z0-9]+ + : [/+~\_\-\.\*\?/a-zA-Z0-9]+ ; BlockComment diff --git a/KicadNetParser.g4 b/KicadNetParser.g4 index dc45c4b..3971111 100644 --- a/KicadNetParser.g4 +++ b/KicadNetParser.g4 @@ -17,6 +17,7 @@ form: | pinDecl #formDecl | ref #formRef | value #formValue + | libpart #formLibpart | keyValue #formKeyValue | string #formString ; @@ -26,7 +27,7 @@ code: ; component: - '(' 'comp' ref value keyValue* ')' + '(' 'comp' ref value libsource keyValue* ')' ; field: @@ -61,6 +62,22 @@ value: '(' 'value' string ')' ; +lib: + '(' 'lib' string ')' + ; + +part: + '(' 'part' string ')' + ; + +libpart: + '(' 'libpart' lib part keyValue* ')' + ; + +libsource: + '(' 'libsource' lib part ')' + ; + keyValue: '(' string form* ')' ; diff --git a/examples/arduino-led/arduino-led.ino b/examples/arduino-led/arduino-led.ino index 01c83ea..9270c7d 100644 --- a/examples/arduino-led/arduino-led.ino +++ b/examples/arduino-led/arduino-led.ino @@ -3,11 +3,13 @@ #include "schematic.h" void setup() { + pinMode(schematic::STATUS_LED, INPUT); } void loop() { - digitalWrite(SCHEMATIC_STATUS_LED, HIGH); - delay(1000); - digitalWrite(SCHEMATIC_STATUS_LED, LOW); - delay(1000); + digitalWrite(schematic::STATUS_LED, HIGH); + delay(1000); + digitalWrite(schematic::STATUS_LED, LOW); + delay(1000); } + diff --git a/examples/arduino-led/schematic.h b/examples/arduino-led/schematic.h new file mode 100644 index 0000000..78ed83c --- /dev/null +++ b/examples/arduino-led/schematic.h @@ -0,0 +1,9 @@ +#ifndef SCHEMATIC_H +#define SCHEMATIC_H + +namespace schematic { +static const int STATUS_LED = 3; +static const int ANALOG_LIGHT_1 = 2; +} // namespace schematic + +#endif // SCHEMATIC_H diff --git a/examples/arduino-led/schematic/arduino-led.net b/examples/arduino-led/schematic/arduino-led.net index f230aaa..54c0ea5 100644 --- a/examples/arduino-led/schematic/arduino-led.net +++ b/examples/arduino-led/schematic/arduino-led.net @@ -1,7 +1,7 @@ (export (version D) (design - (source /home/trygvis/dev/io.trygvis/2016/07/kicad-utils/examples/arduino+led/schematic/arduino+led.sch) - (date "Mon 25 Jul 2016 19:16:49 CEST") + (source /home/trygvis/dev/io.trygvis/2016/07/kicad-utils/examples/arduino-led/schematic/arduino-led.sch) + (date "Tue 26 Jul 2016 21:48:43 CEST") (tool "Eeschema 4.0.2+dfsg1-stable") (sheet (number 1) (name /) (tstamps /) (title_block @@ -9,7 +9,7 @@ (company) (rev) (date) - (source arduino+led.sch) + (source arduino-led.sch) (comment (number 1) (value "")) (comment (number 2) (value "")) (comment (number 3) (value "")) @@ -29,7 +29,17 @@ (value LED) (libsource (lib device) (part LED)) (sheetpath (names /) (tstamps /)) - (tstamp 5791311D))) + (tstamp 5791311D)) + (comp (ref R3) + (value Photores) + (libsource (lib device) (part Photores)) + (sheetpath (names /) (tstamps /)) + (tstamp 5797BF22)) + (comp (ref R2) + (value R) + (libsource (lib device) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 5797BFE1))) (libparts (libpart (lib kicad_utils) (part ARDUINO_UNO) (fields @@ -81,6 +91,16 @@ (pins (pin (num 1) (name K) (type passive)) (pin (num 2) (name A) (type passive)))) + (libpart (lib device) (part Photores) + (footprints + (fp R?) + (fp R?-*)) + (fields + (field (name Reference) R) + (field (name Value) Photores)) + (pins + (pin (num 1) (name ~) (type passive)) + (pin (num 2) (name ~) (type passive)))) (libpart (lib device) (part R) (description Resistor) (footprints @@ -93,74 +113,78 @@ (pin (num 1) (name ~) (type passive)) (pin (num 2) (name ~) (type passive))))) (libraries - (library (logical device) - (uri /usr/share/kicad/library/device.lib)) (library (logical kicad_utils) - (uri /home/trygvis/dev/io.trygvis/2016/07/kicad-utils/kicad/kicad_utils.lib))) + (uri /home/trygvis/dev/io.trygvis/2016/07/kicad-utils/kicad/kicad_utils.lib)) + (library (logical device) + (uri /usr/share/kicad/library/device.lib))) (nets - (net (code 1) (name "Net-(U1-Pad25)") - (node (ref U1) (pin 25))) - (net (code 2) (name "Net-(U1-Pad26)") - (node (ref U1) (pin 26))) - (net (code 3) (name "Net-(U1-Pad17)") - (node (ref U1) (pin 17))) - (net (code 4) (name "Net-(U1-Pad27)") - (node (ref U1) (pin 27))) - (net (code 5) (name "Net-(U1-Pad18)") - (node (ref U1) (pin 18))) - (net (code 6) (name "Net-(U1-Pad28)") - (node (ref U1) (pin 28))) - (net (code 7) (name "Net-(U1-Pad19)") + (net (code 1) (name "Net-(U1-Pad19)") (node (ref U1) (pin 19))) - (net (code 8) (name "Net-(U1-Pad29)") + (net (code 2) (name "Net-(U1-Pad29)") (node (ref U1) (pin 29))) - (net (code 9) (name "Net-(U1-Pad15)") - (node (ref U1) (pin 15))) - (net (code 10) (name GND) + (net (code 3) (name GND) + (node (ref R3) (pin 2)) (node (ref D1) (pin 1))) - (net (code 11) (name "Net-(D1-Pad2)") + (net (code 4) (name "Net-(D1-Pad2)") (node (ref D1) (pin 2)) (node (ref R1) (pin 2))) - (net (code 12) (name /STATUS_LED) - (node (ref U1) (pin 16)) - (node (ref R1) (pin 1))) - (net (code 13) (name "Net-(U1-Pad20)") - (node (ref U1) (pin 20))) - (net (code 14) (name "Net-(U1-Pad2)") + (net (code 5) (name /STATUS_LED) + (node (ref R1) (pin 1)) + (node (ref U1) (pin 16))) + (net (code 6) (name "Net-(U1-Pad28)") + (node (ref U1) (pin 28))) + (net (code 7) (name "Net-(R2-Pad1)") + (node (ref U1) (pin 3)) + (node (ref R2) (pin 1))) + (net (code 8) (name /LIGHT_1) + (node (ref U1) (pin 9)) + (node (ref R3) (pin 1)) + (node (ref R2) (pin 2))) + (net (code 9) (name "Net-(U1-Pad12)") + (node (ref U1) (pin 12))) + (net (code 10) (name "Net-(U1-Pad2)") (node (ref U1) (pin 2))) - (net (code 15) (name "Net-(U1-Pad3)") - (node (ref U1) (pin 3))) - (net (code 16) (name "Net-(U1-Pad4)") + (net (code 11) (name "Net-(U1-Pad4)") (node (ref U1) (pin 4))) - (net (code 17) (name "Net-(U1-Pad5)") + (net (code 12) (name "Net-(U1-Pad5)") (node (ref U1) (pin 5))) - (net (code 18) (name "Net-(U1-Pad6)") + (net (code 13) (name "Net-(U1-Pad6)") (node (ref U1) (pin 6))) - (net (code 19) (name "Net-(U1-Pad7)") + (net (code 14) (name "Net-(U1-Pad7)") (node (ref U1) (pin 7))) - (net (code 20) (name "Net-(U1-Pad8)") + (net (code 15) (name "Net-(U1-Pad8)") (node (ref U1) (pin 8))) - (net (code 21) (name "Net-(U1-Pad9)") - (node (ref U1) (pin 9))) - (net (code 22) (name "Net-(U1-Pad10)") + (net (code 16) (name "Net-(U1-Pad10)") (node (ref U1) (pin 10))) - (net (code 23) (name "Net-(U1-Pad1)") - (node (ref U1) (pin 1))) - (net (code 24) (name "Net-(U1-Pad30)") + (net (code 17) (name "Net-(U1-Pad20)") + (node (ref U1) (pin 20))) + (net (code 18) (name "Net-(U1-Pad30)") (node (ref U1) (pin 30))) - (net (code 25) (name "Net-(U1-Pad11)") + (net (code 19) (name "Net-(U1-Pad11)") (node (ref U1) (pin 11))) - (net (code 26) (name "Net-(U1-Pad21)") + (net (code 20) (name "Net-(U1-Pad21)") (node (ref U1) (pin 21))) - (net (code 27) (name "Net-(U1-Pad12)") - (node (ref U1) (pin 12))) - (net (code 28) (name "Net-(U1-Pad22)") + (net (code 21) (name "Net-(U1-Pad1)") + (node (ref U1) (pin 1))) + (net (code 22) (name "Net-(U1-Pad22)") (node (ref U1) (pin 22))) - (net (code 29) (name "Net-(U1-Pad13)") + (net (code 23) (name "Net-(U1-Pad13)") (node (ref U1) (pin 13))) - (net (code 30) (name "Net-(U1-Pad23)") + (net (code 24) (name "Net-(U1-Pad23)") (node (ref U1) (pin 23))) - (net (code 31) (name "Net-(U1-Pad14)") + (net (code 25) (name "Net-(U1-Pad14)") (node (ref U1) (pin 14))) - (net (code 32) (name "Net-(U1-Pad24)") - (node (ref U1) (pin 24))))) \ No newline at end of file + (net (code 26) (name "Net-(U1-Pad24)") + (node (ref U1) (pin 24))) + (net (code 27) (name "Net-(U1-Pad15)") + (node (ref U1) (pin 15))) + (net (code 28) (name "Net-(U1-Pad25)") + (node (ref U1) (pin 25))) + (net (code 29) (name "Net-(U1-Pad26)") + (node (ref U1) (pin 26))) + (net (code 30) (name "Net-(U1-Pad17)") + (node (ref U1) (pin 17))) + (net (code 31) (name "Net-(U1-Pad27)") + (node (ref U1) (pin 27))) + (net (code 32) (name "Net-(U1-Pad18)") + (node (ref U1) (pin 18))))) \ No newline at end of file diff --git a/examples/arduino-led/schematic/arduino-led.sch b/examples/arduino-led/schematic/arduino-led.sch index 642cd4b..e0889f5 100644 --- a/examples/arduino-led/schematic/arduino-led.sch +++ b/examples/arduino-led/schematic/arduino-led.sch @@ -29,7 +29,7 @@ LIBS:atmel LIBS:contrib LIBS:valves LIBS:kicad_utils -LIBS:arduino+mod-lcd3310-cache +LIBS:arduino-led-cache EELAYER 25 0 EELAYER END $Descr A4 11693 8268 @@ -56,10 +56,10 @@ F 3 "" H 5250 3750 60 0000 C CNN 1 0 0 -1 $EndComp $Comp -L GND #PWR1 +L GND #PWR2 U 1 1 579130D3 P 7100 5200 -F 0 "#PWR1" H 7100 4950 50 0001 C CNN +F 0 "#PWR2" H 7100 4950 50 0001 C CNN F 1 "GND" H 7100 5050 50 0000 C CNN F 2 "" H 7100 5200 50 0000 C CNN F 3 "" H 7100 5200 50 0000 C CNN @@ -98,4 +98,50 @@ Wire Wire Line 7100 4950 7100 5200 Text Label 6400 4050 0 60 ~ 0 STATUS_LED +$Comp +L Photores R3 +U 1 1 5797BF22 +P 3950 4700 +F 0 "R3" V 4030 4700 50 0000 C CNN +F 1 "Photores" V 4160 4700 50 0000 C TNN +F 2 "" V 3880 4700 50 0000 C CNN +F 3 "" H 3950 4700 50 0000 C CNN + 1 3950 4700 + 1 0 0 -1 +$EndComp +$Comp +L GND #PWR1 +U 1 1 5797BFA3 +P 3950 5150 +F 0 "#PWR1" H 3950 4900 50 0001 C CNN +F 1 "GND" H 3950 5000 50 0000 C CNN +F 2 "" H 3950 5150 50 0000 C CNN +F 3 "" H 3950 5150 50 0000 C CNN + 1 3950 5150 + 1 0 0 -1 +$EndComp +Wire Wire Line + 3950 5150 3950 4950 +Wire Wire Line + 3950 4050 4500 4050 +Wire Wire Line + 3950 3350 4500 3350 +Connection ~ 3950 4050 +$Comp +L R R2 +U 1 1 5797BFE1 +P 3950 3700 +F 0 "R2" V 4030 3700 50 0000 C CNN +F 1 "R" V 3950 3700 50 0000 C CNN +F 2 "" V 3880 3700 50 0000 C CNN +F 3 "" H 3950 3700 50 0000 C CNN + 1 3950 3700 + 1 0 0 -1 +$EndComp +Wire Wire Line + 3950 3550 3950 3350 +Wire Wire Line + 3950 3850 3950 4450 +Text Label 4050 4050 0 60 ~ 0 +LIGHT_1 $EndSCHEMATC diff --git a/include-priv/trygvis/antlr.h b/include-priv/trygvis/antlr.h new file mode 100644 index 0000000..f5656ea --- /dev/null +++ b/include-priv/trygvis/antlr.h @@ -0,0 +1,67 @@ +#pragma once + +#include "antlr4-runtime.h" + +namespace trygvis { +namespace antlr { + +// This namespace is shared copied code + +using ParseTree = antlr4::tree::ParseTree; + +class MissingParseTreeProperty : public std::out_of_range { +public: + explicit MissingParseTreeProperty(const std::string &what) : out_of_range(what) { } +}; + +template +class ParseTreeProperty { +public: + virtual V get(Ref node) { + return get(node.get()); + } + + virtual V get(ParseTree *const node) { + if (!debug) { + return _annotations.at(node); + } + + try { +// cerr << "node = " << node->getText() << endl; + return _annotations.at(node); + } catch (std::out_of_range &e) { + std::cerr << "get(" << node << "), text=" << node->getText() << std::endl; + std::stringstream buf; + buf << "out of range: " << node << ", text=" << node->getText(); + auto msg = buf.str(); + std::cerr << msg << std::endl; + throw MissingParseTreeProperty(msg); + } + } + + virtual void put(ParseTree *const node, V value) { + if (debug) { + std::cerr << "put(" << node << ", " << value << "), text: " << node->getText() << std::endl; + } + _annotations[node] = value; + } + + virtual V removeFrom(ParseTree *const node) { + auto it = _annotations.find(node); + + if (it == _annotations.end()) { + throw MissingParseTreeProperty(node->getText()); + } + + return it->second; + } + +protected: + std::map _annotations; + +private: +}; + +} // namespace antlr + +} diff --git a/include-priv/trygvis/string_utils.h b/include-priv/trygvis/string_utils.h new file mode 100644 index 0000000..9902a3f --- /dev/null +++ b/include-priv/trygvis/string_utils.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace trygvis { +namespace string_utils { + +/** + * Check if a starts with b. + */ +static bool startsWith(const std::string &a, const std::string &b) { + return b.length() <= a.length() && a.compare(0, b.length(), b) == 0; +} + +/** + * Check if a ends with b. + */ +static bool endsWith(const std::string &a, const std::string &b) { + return b.length() <= a.length() && a.compare(a.length() - b.length(), b.length(), b) == 0; +} + +} // namespace string_utils +} // namespace trygvis diff --git a/include/trygvis/kicad.h b/include/trygvis/kicad.h index 4cff944..ae67673 100644 --- a/include/trygvis/kicad.h +++ b/include/trygvis/kicad.h @@ -7,16 +7,29 @@ namespace trygvis { namespace kicad { - template using opt = std::experimental::optional; +} // namespace kicad +} // namespace trygvis -class component { -public: - std::string ref; - std::string value; +namespace trygvis { +namespace kicad { +namespace netlist { + +struct lib_source { + const std::string lib; + const std::string part; - component(const std::string &ref, const std::string &value) : ref(ref), value(value) { } + lib_source(const std::string &lib, const std::string &part) : lib(lib), part(part) { } +}; + +struct component { + const std::string ref; + const std::string value; + const lib_source _lib_source; + + component(const std::string &ref, const std::string &value, const lib_source &_lib_source) : + ref(ref), value(value), _lib_source(_lib_source) { } }; struct pin { @@ -31,19 +44,21 @@ struct part { class node { public: - std::string ref; - int pin; + const std::string ref; + const int pin; node(const std::string &ref, int pin) : ref(ref), pin(pin) { } }; class net { public: - int code; - std::string name; - std::vector nodes; + const int code; + const std::string name; + const std::vector nodes; net(int code, const std::string &name, const std::vector &nodes) : code(code), name(name), nodes(nodes) { } + + const node * node_for_ref(const std::string &ref) const; }; struct netlist { @@ -51,7 +66,9 @@ struct netlist { std::vector parts; std::vector nets; - opt find_component(std::string ref) const; + opt find_component(const std::string &ref) const; + + std::vector find_usage_of(const std::string &ref) const; }; class kicad_parse_exception : public std::runtime_error { @@ -76,5 +93,6 @@ private: bool debug_; }; +} // namespace netlist } // namespace kicad } // namespace trygvis diff --git a/kicad.cpp b/kicad.cpp index 2af9bc6..0a6931d 100644 --- a/kicad.cpp +++ b/kicad.cpp @@ -1,79 +1,31 @@ #include "trygvis/kicad.h" +#include "trygvis/antlr.h" +#include "trygvis/string_utils.h" #include #include #include +#include +#include -namespace trygvis { -namespace antlr { - -// This namespace is shared copied code - -using ParseTree = antlr4::tree::ParseTree; - -class MissingParseTreeProperty : public std::out_of_range { -public: - explicit MissingParseTreeProperty(const std::string &what) : out_of_range(what) { } -}; - -template -class ParseTreeProperty { -public: - virtual V get(Ref node) { - return get(node.get()); - } - - virtual V get(ParseTree *const node) { - if (!debug) { - return _annotations.at(node); - } - - try { -// cerr << "node = " << node->getText() << endl; - return _annotations.at(node); - } catch (std::out_of_range &e) { - std::cerr << "get(" << node << "), text=" << node->getText() << std::endl; - std::stringstream buf; - buf << "out of range: " << node << ", text=" << node->getText(); - auto msg = buf.str(); - std::cerr << msg << std::endl; - throw MissingParseTreeProperty(msg); - } - } - - virtual void put(ParseTree *const node, V value) { - if (debug) { - std::cerr << "put(" << node << ", " << value << "), text: " << node->getText() << std::endl; - } - _annotations[node] = value; - } +using namespace std; +using namespace trygvis::antlr; +using namespace trygvis::string_utils; - virtual V removeFrom(ParseTree *const node) { - auto it = _annotations.find(node); +namespace trygvis { +namespace kicad { +namespace netlist { - if (it == _annotations.end()) { - throw MissingParseTreeProperty(node->getText()); +const node *net::node_for_ref(const std::string &ref) const { + for (auto &node: nodes) { + if (node.ref == ref) { + return &node; } - - return it->second; } -protected: - std::map _annotations; - -private: -}; - -} // namespace antlr - + return nullptr; } -using namespace std; -using namespace trygvis::antlr; - -namespace trygvis { -namespace kicad { - -opt netlist::find_component(string ref) const { +opt netlist::find_component(const string &ref) const { for (const component &c :components) { int x = c.ref.compare(ref); if (x == 0) { @@ -83,6 +35,24 @@ opt netlist::find_component(string ref) const { return std::experimental::nullopt; } +vector netlist::find_usage_of(const string &ref) const { + vector usage; + + for (auto &net : nets) { + if (net.nodes.size() <= 1) { + continue; + } + + for (auto &node: net.nodes) { + if (node.ref == ref) { + usage.push_back(&net); + } + } + } + + return usage; +} + static int parse(const Ref &integer) { unsigned long long i = strtoull(integer->getText().c_str(), NULL, 10); @@ -117,14 +87,18 @@ public: auto code = parse(ctx->code()->INTEGER()); auto name = strings.get(ctx->name()->string()); + if (startsWith(name, "/")) { + name = name.substr(1); + } + // cerr << "exitNet: " << "code=" << code << ", name=" << name << ", nodes=" << nodes.size() << endl; - if (nodes.size() > 1) { - cerr << "Net#" << code << ": " << name << endl; - for (auto &node: nodes) { - cerr << " Node: " << node.ref << "#" << node.pin << endl; - } - } +// if (nodes.size() > 1) { +// cerr << "Net#" << code << ": " << name << endl; +// for (auto &node: nodes) { +// cerr << " Node: " << node.ref << "#" << node.pin << endl; +// } +// } nets.emplace_back(code, name, nodes); nodes.clear(); } @@ -142,9 +116,10 @@ public: auto ref = strings.get(ctx->ref()->string()); auto value = strings.get(ctx->value()->string()); - cerr << "exitComponent, ref=" << ref << ", value=" << value << endl; + lib_source ls{strings.get(ctx->libsource()->lib()->string()), + strings.get(ctx->libsource()->part()->string())}; - components.emplace_back(ref, value); + components.emplace_back(ref, value, ls); } virtual void exitStringId(KicadNetParser::StringIdContext *ctx) override { @@ -214,6 +189,6 @@ void kicad_net_loader::setDebug(bool debug) { debug_ = debug; } - +} // namespace netlist } // namespace trygvis } // namespace kicad diff --git a/main.cpp b/main.cpp index b5e998d..cb5750e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,12 +1,21 @@ #include +#include +#include #include #include #include +#include +#include #include "trygvis/kicad.h" using namespace std; using namespace trygvis::kicad; +using trygvis::kicad::netlist::component; +using trygvis::kicad::netlist::kicad_net_loader; +using trygvis::kicad::netlist::kicad_parse_exception; +using trygvis::kicad::netlist::net; + char *program; __attribute__((noreturn)) @@ -14,37 +23,125 @@ void usage(const char *reason = nullptr) { if (reason) { fprintf(stderr, "%s\n", reason); } - fprintf(stderr, "usage: %s -f file -r ref\n", program); + fprintf(stderr, "usage: %s -n -r [-o ]\n", program); exit(EX_USAGE); } -void parse_args(int argc, char **argv, bool *debug, char **filename, char **ref) { +void parse_args(int argc, char **argv, bool *debug, char **net_filename, char **ref, char **out_filename) { *debug = false; - *filename = *ref = nullptr; + *ref = nullptr; + *out_filename = nullptr; + *ref = nullptr; int c; - while ((c = getopt(argc, argv, "Df:r:")) != -1) { + while ((c = getopt(argc, argv, "Dn:r:o:")) != -1) { switch (c) { case 'D': *debug = true; break; - case 'f': - *filename = optarg; + case 'n': + *net_filename = optarg; break; case 'r': *ref = optarg; break; + case 'o': + if (strcmp("-", optarg) != 0) { + *out_filename = optarg; + } + break; default: - abort(); + usage(); } } - if (!*filename) { + if (!*net_filename && !*ref) { usage(); } } -bool generate(const char *ref, const trygvis::kicad::netlist &netlist) { +class part { +public: + part(const string &name) : name(name) { + } + + virtual ~part() { + } + + const string name; + + virtual bool generate(stringstream &out, const string &ref, const vector usages) = 0; +}; + +class arduino_uno : public part { +public: + arduino_uno() : part("ARDUINO_UNO") { } + + ~arduino_uno() { + } + + virtual bool generate(stringstream &out, const string &ref, const vector usages) override { + out << "namespace schematic {" << endl; + for (auto &usage: usages) { + auto node = usage->node_for_ref(ref); + + if (node->pin >= 7 && node->pin <= 12) { + out << "static const int ANALOG_" << usage->name << " = " << (node->pin - 7) << ";" << endl; + } else if (node->pin >= 13 && node->pin <= 26) { + out << "static const int " << usage->name << " = " << (node->pin - 13) << ";" << endl; + } + } + out << "} // namespace schematic" << endl; + + return true; + } +}; + + +class library { +public: + library(const string &name) : name(name) { } + + library(library &&l) : name(std::move(l.name)), parts(std::move(l.parts)) { } + + const string name; + vector> parts; + + opt find_part(string name) const { + for (auto &part: parts) { + if (part->name == name) { + return part.get(); + } + } + + return nullptr; + } +}; + +class kicad_gen { +public: + vector libraries; + + kicad_gen() { + library kicad_utils("kicad_utils"); + kicad_utils.parts.push_back(make_unique()); + + libraries.push_back(std::move(kicad_utils)); + } + + opt find_library(string name) { + for (auto &l : libraries) { + if (l.name == name) { + return &l; + } + } + + return nullptr; + } +}; + +bool generate(const char *ref, const trygvis::kicad::netlist::netlist &netlist, stringstream &out) { + kicad_gen gen; opt componentO = netlist.find_component(ref); if (!componentO) { @@ -54,9 +151,38 @@ bool generate(const char *ref, const trygvis::kicad::netlist &netlist) { const component *c = *componentO; - cerr << "Generating connections for " << ref << endl; + cerr << "Generating connections for " << c->ref << " (" << c->value << ")" << endl; + + auto libraryO = gen.find_library(c->_lib_source.lib); + + if (!libraryO) { + cerr << "kicad_gen does not support library '" << c->_lib_source.lib << "'" << endl; + return false; + } + + const library *library = *libraryO; + + auto partName = c->_lib_source.part; + + auto partO = library->find_part(partName); + + if (!partO) { + cerr << "kicad_gen's library " << library->name << " does not have a component named " << partName << endl; + return false; + } + + part *part = *partO; + + out << "#ifndef SCHEMATIC_H" << endl; + out << "#define SCHEMATIC_H" << endl; + out << endl; + + auto usages = netlist.find_usage_of(ref); + + part->generate(out, ref, usages); - cerr << c->value << endl; + out << endl; + out << "#endif // SCHEMATIC_H" << endl; return true; } @@ -65,18 +191,28 @@ int main(int argc, char **argv) { program = argv[0]; bool debug; - char *filename; + char *net_filename; char *ref; - parse_args(argc, argv, &debug, &filename, &ref); + char *out_filename; + parse_args(argc, argv, &debug, &net_filename, &ref, &out_filename); kicad_net_loader loader; try { - auto netlist = loader.load(filename); + auto netlist = loader.load(net_filename); - auto ok = generate(ref, netlist); + stringstream out; + auto ok = generate(ref, netlist, out); if (ok) { + auto contents = out.str(); + if (out_filename != nullptr) { + ofstream outstream(out_filename); + outstream << contents; + outstream.close(); + } else { + cout << contents << flush; + } return EXIT_SUCCESS; } return EXIT_FAILURE; -- cgit v1.2.3