aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-07-26 23:50:23 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2016-07-26 23:50:23 +0200
commita8256910d40a0eee85bf539a3f120c9d92485f3f (patch)
tree83fd119fe43257ca131620656b94a698b23c4329
parent128e53d220d97225803d61d86f8e43439563181d (diff)
downloadkicad-utils-a8256910d40a0eee85bf539a3f120c9d92485f3f.tar.gz
kicad-utils-a8256910d40a0eee85bf539a3f120c9d92485f3f.tar.bz2
kicad-utils-a8256910d40a0eee85bf539a3f120c9d92485f3f.tar.xz
kicad-utils-a8256910d40a0eee85bf539a3f120c9d92485f3f.zip
o Working version with support for Arduino parts.
-rw-r--r--CMakeLists.txt8
-rw-r--r--KicadNetLexer.g48
-rw-r--r--KicadNetParser.g419
-rw-r--r--examples/arduino-led/arduino-led.ino10
-rw-r--r--examples/arduino-led/schematic.h9
-rw-r--r--examples/arduino-led/schematic/arduino-led.net132
-rw-r--r--examples/arduino-led/schematic/arduino-led.sch52
-rw-r--r--include-priv/trygvis/antlr.h67
-rw-r--r--include-priv/trygvis/string_utils.h23
-rw-r--r--include/trygvis/kicad.h42
-rw-r--r--kicad.cpp121
-rw-r--r--main.cpp166
12 files changed, 487 insertions, 170 deletions
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<typename V, bool debug = false>
+class ParseTreeProperty {
+public:
+ virtual V get(Ref<ParseTree> 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<ParseTree *, V> _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 <string>
+
+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<typename T>
using opt = std::experimental::optional<T>;
+} // 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<node> nodes;
+ const int code;
+ const std::string name;
+ const std::vector<node> nodes;
net(int code, const std::string &name, const std::vector<node> &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<part> parts;
std::vector<net> nets;
- opt<const component *> find_component(std::string ref) const;
+ opt<const component *> find_component(const std::string &ref) const;
+
+ std::vector<const net *> 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 <KicadNetLexer.h>
#include <KicadNetParser.h>
#include <KicadNetParserBaseListener.h>
+#include <exception>
+#include <stdexcept>
-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<typename V, bool debug = false>
-class ParseTreeProperty {
-public:
- virtual V get(Ref<ParseTree> 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<ParseTree *, V> _annotations;
-
-private:
-};
-
-} // namespace antlr
-
+ return nullptr;
}
-using namespace std;
-using namespace trygvis::antlr;
-
-namespace trygvis {
-namespace kicad {
-
-opt<const component *> netlist::find_component(string ref) const {
+opt<const component *> 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<const component *> netlist::find_component(string ref) const {
return std::experimental::nullopt;
}
+vector<const net *> netlist::find_usage_of(const string &ref) const {
+ vector<const net *> 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<antlr4::tree::TerminalNode> &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 <iostream>
+#include <fstream>
+#include <sstream>
#include <err.h>
#include <sysexits.h>
#include <getopt.h>
+#include <cstring>
+#include <memory>
#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 <net file> -r <ref> [-o <out file>]\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<const net *> 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<const net *> 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<unique_ptr<part>> parts;
+
+ opt<part *> find_part(string name) const {
+ for (auto &part: parts) {
+ if (part->name == name) {
+ return part.get();
+ }
+ }
+
+ return nullptr;
+ }
+};
+
+class kicad_gen {
+public:
+ vector<library> libraries;
+
+ kicad_gen() {
+ library kicad_utils("kicad_utils");
+ kicad_utils.parts.push_back(make_unique<arduino_uno>());
+
+ libraries.push_back(std::move(kicad_utils));
+ }
+
+ opt<library *> 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<const component *> 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;