Skip to content

Commit

Permalink
add ODB++ output
Browse files Browse the repository at this point in the history
  • Loading branch information
carrotIndustries committed Mar 16, 2022
1 parent 56c6fe1 commit d84af5e
Show file tree
Hide file tree
Showing 38 changed files with 3,933 additions and 396 deletions.
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ SRC_COMMON = \
3rd_party/delaunator/delaunator.cpp\
src/board/airwires.cpp\
src/board/gerber_output_settings.cpp\
src/board/odb_output_settings.cpp\
src/board/board_hole.cpp\
src/board/connection_line.cpp\
src/board/step_export_settings.cpp\
Expand Down Expand Up @@ -203,6 +204,18 @@ SRC_EXPORT = \
src/export_pdf/export_pdf_util.cpp\
src/export_pnp/export_pnp.cpp \
src/export_bom/export_bom.cpp\
src/export_odb/odb_export.cpp\
src/export_odb/canvas_odb.cpp\
src/export_odb/db.cpp\
src/export_odb/eda_data.cpp\
src/export_odb/attribute_util.cpp\
src/export_odb/surface_data.cpp\
src/export_odb/features.cpp\
src/export_odb/components.cpp\
src/export_odb/symbol.cpp\
src/export_odb/odb_util.cpp\
src/export_odb/track_graph.cpp\
src/export_odb/structured_text_writer.cpp\

SRC_CANVAS_GL = \
$(SRC_CANVAS) \
Expand Down
1 change: 1 addition & 0 deletions scripts/app_versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ versions:
10: add thermal rules
11: add thermal spoke customisation
12: add net ties
13: add ODB++ export
schematic:
1: add custom values on symbols
2: add hierarchy
Expand Down
32 changes: 26 additions & 6 deletions src/board/board.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ BoardColors::BoardColors() : solder_mask({0, .5, 0}), silkscreen({1, 1, 1}), sub
{
}

static const unsigned int app_version = 12;
const LutEnumStr<Board::OutputFormat> Board::output_format_lut = {
{"gerber", Board::OutputFormat::GERBER},
{"odb", Board::OutputFormat::ODB},
};

static const unsigned int app_version = 13;

unsigned int Board::get_app_version()
{
Expand Down Expand Up @@ -247,6 +252,17 @@ Board::Board(const UUID &uu, const json &j, Block &iblock, IPool &pool)
Logger::log_warning("couldn't load fab output settings", Logger::Domain::BOARD, e.what());
}
}
if (j.count("odb_output_settings")) {
try {
odb_output_settings = ODBOutputSettings(j.at("odb_output_settings"));
}
catch (const std::exception &e) {
Logger::log_warning("couldn't load ODB++ output settings", Logger::Domain::BOARD, e.what());
}
}
if (j.count("output_format")) {
output_format = output_format_lut.lookup(j.at("output_format"));
}
if (j.count("colors")) {
try {
const auto &o = j.at("colors");
Expand Down Expand Up @@ -293,6 +309,7 @@ Board::Board(const UUID &uu, const json &j, Block &iblock, IPool &pool)
}
}
gerber_output_settings.update_for_board(*this);
odb_output_settings.update_for_board(*this);
update_pdf_export_settings(pdf_export_settings);
update_refs(); // fill in smashed texts
}
Expand Down Expand Up @@ -342,11 +359,11 @@ Board::Board(const Board &brd, CopyMode copy_mode)
junctions(brd.junctions), tracks(brd.tracks), texts(brd.texts), lines(brd.lines), arcs(brd.arcs),
planes(brd.planes), keepouts(brd.keepouts), dimensions(brd.dimensions), connection_lines(brd.connection_lines),
included_boards(brd.included_boards), board_panels(brd.board_panels), pictures(brd.pictures), decals(brd.decals),
net_ties(brd.net_ties), warnings(brd.warnings), rules(brd.rules),
gerber_output_settings(brd.gerber_output_settings), grid_settings(brd.grid_settings), airwires(brd.airwires),
stackup(brd.stackup), colors(brd.colors), pdf_export_settings(brd.pdf_export_settings),
step_export_settings(brd.step_export_settings), pnp_export_settings(brd.pnp_export_settings),
version(brd.version), n_inner_layers(brd.n_inner_layers)
net_ties(brd.net_ties), warnings(brd.warnings), output_format(brd.output_format), rules(brd.rules),
gerber_output_settings(brd.gerber_output_settings), odb_output_settings(brd.odb_output_settings),
grid_settings(brd.grid_settings), airwires(brd.airwires), stackup(brd.stackup), colors(brd.colors),
pdf_export_settings(brd.pdf_export_settings), step_export_settings(brd.step_export_settings),
pnp_export_settings(brd.pnp_export_settings), version(brd.version), n_inner_layers(brd.n_inner_layers)
{
if (copy_mode == CopyMode::DEEP) {
packages = brd.packages;
Expand Down Expand Up @@ -518,6 +535,7 @@ void Board::set_n_inner_layers(unsigned int n)
}
map_erase_if(stackup, [this](const auto &x) { return layers.count(x.first) == 0; });
gerber_output_settings.update_for_board(*this);
odb_output_settings.update_for_board(*this);
update_pdf_export_settings(pdf_export_settings);
}

Expand Down Expand Up @@ -1124,6 +1142,8 @@ json Board::serialize() const
j["n_inner_layers"] = n_inner_layers;
j["rules"] = rules.serialize();
j["fab_output_settings"] = gerber_output_settings.serialize();
j["odb_output_settings"] = odb_output_settings.serialize();
j["output_format"] = output_format_lut.lookup_reverse(output_format);
{
json o;
o["solder_mask"] = color_to_json(colors.solder_mask);
Expand Down
6 changes: 6 additions & 0 deletions src/board/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "common/keepout.hpp"
#include "common/pdf_export_settings.hpp"
#include "gerber_output_settings.hpp"
#include "odb_output_settings.hpp"
#include "nlohmann/json_fwd.hpp"
#include "plane.hpp"
#include "track.hpp"
Expand Down Expand Up @@ -117,8 +118,13 @@ class Board : public ObjectProvider, public LayerProvider {

std::vector<Warning> warnings;

enum class OutputFormat { GERBER, ODB };
OutputFormat output_format = OutputFormat::GERBER;
static const LutEnumStr<OutputFormat> output_format_lut;

BoardRules rules;
GerberOutputSettings gerber_output_settings;
ODBOutputSettings odb_output_settings;
GridSettings grid_settings;

std::map<UUID, std::list<Airwire>> airwires;
Expand Down
33 changes: 33 additions & 0 deletions src/board/odb_output_settings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "odb_output_settings.hpp"
#include "common/lut.hpp"
#include "nlohmann/json.hpp"

namespace horizon {

const LutEnumStr<ODBOutputSettings::Format> format_lut = {
{"directory", ODBOutputSettings::Format::DIRECTORY},
{"zip", ODBOutputSettings::Format::ZIP},
{"tgz", ODBOutputSettings::Format::TGZ},
};

ODBOutputSettings::ODBOutputSettings(const json &j)
: format(format_lut.lookup(j.at("format"))), job_name(j.at("job_name").get<std::string>()),
output_filename(j.at("output_filename").get<std::string>()),
output_directory(j.at("output_directory").get<std::string>())
{
}

void ODBOutputSettings::update_for_board(const Board &brd)
{
}

json ODBOutputSettings::serialize() const
{
json j;
j["format"] = format_lut.lookup_reverse(format);
j["job_name"] = job_name;
j["output_filename"] = output_filename;
j["output_directory"] = output_directory;
return j;
}
} // namespace horizon
28 changes: 28 additions & 0 deletions src/board/odb_output_settings.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once
#include "common/common.hpp"
#include "common/lut.hpp"
#include "nlohmann/json_fwd.hpp"
#include "util/uuid.hpp"

namespace horizon {
using json = nlohmann::json;

class ODBOutputSettings {
public:
ODBOutputSettings(const json &);
ODBOutputSettings()
{
}
json serialize() const;
void update_for_board(const class Board &brd);

enum class Format { DIRECTORY, TGZ, ZIP };

Format format = Format::TGZ;

std::string job_name;

std::string output_filename;
std::string output_directory;
};
} // namespace horizon
9 changes: 5 additions & 4 deletions src/core/core_board.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ CoreBoard::CoreBoard(const std::string &board_filename, const std::string &block
const std::string &pictures_dir, IPool &pool, IPool &pool_caching)
: Core(pool, &pool_caching), block(get_flattend_block(blocks_filename, pool_caching)),
brd(Board::new_from_file(board_filename, *block, pool_caching)), rules(brd->rules),
gerber_output_settings(brd->gerber_output_settings), pdf_export_settings(brd->pdf_export_settings),
step_export_settings(brd->step_export_settings), pnp_export_settings(brd->pnp_export_settings),
grid_settings(brd->grid_settings), colors(brd->colors), m_board_filename(board_filename),
m_blocks_filename(blocks_filename), m_pictures_dir(pictures_dir)
gerber_output_settings(brd->gerber_output_settings), odb_output_settings(brd->odb_output_settings),
pdf_export_settings(brd->pdf_export_settings), step_export_settings(brd->step_export_settings),
pnp_export_settings(brd->pnp_export_settings), grid_settings(brd->grid_settings), colors(brd->colors),
m_board_filename(board_filename), m_blocks_filename(blocks_filename), m_pictures_dir(pictures_dir)
{
brd->load_pictures(pictures_dir);
rebuild("init");
Expand Down Expand Up @@ -811,6 +811,7 @@ void CoreBoard::save(const std::string &suffix)
{
brd->rules = rules;
brd->gerber_output_settings = gerber_output_settings;
brd->odb_output_settings = odb_output_settings;
brd->pdf_export_settings = pdf_export_settings;
brd->step_export_settings = step_export_settings;
brd->pnp_export_settings = pnp_export_settings;
Expand Down
5 changes: 5 additions & 0 deletions src/core/core_board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ class CoreBoard : public Core, public DocumentBoard {
{
return gerber_output_settings;
}
ODBOutputSettings &get_odb_output_settings() override
{
return odb_output_settings;
}
PDFExportSettings &get_pdf_export_settings() override
{
return pdf_export_settings;
Expand Down Expand Up @@ -80,6 +84,7 @@ class CoreBoard : public Core, public DocumentBoard {

BoardRules rules;
GerberOutputSettings gerber_output_settings;
ODBOutputSettings odb_output_settings;
PDFExportSettings pdf_export_settings;
STEPExportSettings step_export_settings;
PnPExportSettings pnp_export_settings;
Expand Down
1 change: 1 addition & 0 deletions src/document/idocument_board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class IDocumentBoard : public virtual IDocument {
public:
virtual class Board *get_board() = 0;
virtual class GerberOutputSettings &get_gerber_output_settings() = 0;
virtual class ODBOutputSettings &get_odb_output_settings() = 0;
virtual class PDFExportSettings &get_pdf_export_settings() = 0;
virtual class STEPExportSettings &get_step_export_settings() = 0;
virtual class PnPExportSettings &get_pnp_export_settings() = 0;
Expand Down
82 changes: 82 additions & 0 deletions src/export_odb/attribute_util.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "attribute_util.hpp"
#include <sstream>
#include <iomanip>
#include "util/once.hpp"
#include "odb_util.hpp"

namespace horizon::ODB {

namespace attribute::detail {
std::string make_legal_string_attribute(const std::string &n)
{
std::string out;
out.reserve(n.size());
for (auto c : utf8_to_ascii(n)) {
if (isgraph(c) || c == ' ')
;
else if (isspace(c))
c = ' ';
else
c = '_';
out.append(1, c);
}

return out;
}
} // namespace attribute::detail

std::string AttributeProvider::double_to_string(double v, unsigned int n)
{
std::ostringstream oss;
oss << std::fixed << std::setprecision(n) << v;
return oss.str();
}


static unsigned int get_or_create_text(std::map<std::string, unsigned int> &m, const std::string &t)
{
if (m.count(t)) {
return m.at(t);
}
else {
auto n = m.size();
m.emplace(t, n);
return n;
}
}

unsigned int AttributeProvider::get_or_create_attribute_name(const std::string &name)
{
return get_or_create_text(attribute_names, name);
}

unsigned int AttributeProvider::get_or_create_attribute_text(const std::string &name)
{
return get_or_create_text(attribute_texts, name);
}

void RecordWithAttributes::write_attributes(std::ostream &ost) const
{
Once once;
for (const auto &attr : attributes) {
if (once())
ost << " ;";
else
ost << ",";
ost << attr.first;
if (attr.second.size())
ost << "=" << attr.second;
}
}

void AttributeProvider::write_attributes(std::ostream &ost, const std::string &prefix) const
{
for (const auto &[name, n] : attribute_names) {
ost << prefix << "@" << n << " " << name << endl;
}
for (const auto &[name, n] : attribute_texts) {
ost << prefix << "&" << n << " " << name << endl;
}
}

} // namespace horizon::ODB
64 changes: 64 additions & 0 deletions src/export_odb/attribute_util.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma once
#include "attributes.hpp"
#include <type_traits>
#include <string>
#include <map>
#include <vector>

namespace horizon::ODB {

class AttributeProvider {

public:
template <typename Tr, typename Ta> void add_attribute(Tr &r, Ta v)
{
using Tc = typename Tr::template check_type<Ta>;
static_assert(Tc::value);

const auto id = get_or_create_attribute_name(attribute::attribute_name<Ta>::name);
if constexpr (std::is_enum_v<Ta>)
r.attributes.emplace_back(id, std::to_string(static_cast<int>(v)));
else
r.attributes.emplace_back(id, attr_to_string(v));
}

protected:
unsigned int get_or_create_attribute_name(const std::string &name);

void write_attributes(std::ostream &ost, const std::string &prefix = "") const;


private:
unsigned int get_or_create_attribute_text(const std::string &name);

static std::string double_to_string(double v, unsigned int n);

template <typename T, unsigned int n> std::string attr_to_string(attribute::float_attribute<T, n> a)
{
return double_to_string(a.value, a.ndigits);
}

template <typename T> std::string attr_to_string(attribute::boolean_attribute<T> a)
{
return "";
}

template <typename T> std::string attr_to_string(attribute::text_attribute<T> a)
{
return std::to_string(get_or_create_attribute_text(a.value));
}


std::map<std::string, unsigned int> attribute_names;
std::map<std::string, unsigned int> attribute_texts;
};

class RecordWithAttributes {

protected:
void write_attributes(std::ostream &ost) const;

public:
std::vector<std::pair<unsigned int, std::string>> attributes;
};
} // namespace horizon::ODB
Loading

0 comments on commit d84af5e

Please sign in to comment.