Skip to content

Commit

Permalink
imp board: add user layers
Browse files Browse the repository at this point in the history
changelog: New Features/Board Editor: add user layers
  • Loading branch information
carrotIndustries committed Jul 26, 2023
1 parent d8adc48 commit d3039e1
Show file tree
Hide file tree
Showing 20 changed files with 848 additions and 125 deletions.
1 change: 1 addition & 0 deletions scripts/app_versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ versions:
18: increase maximum number of inner layers to 8
19: add blind and buried vias
20: add via definitions
21: add user layers
schematic:
1: add custom values on symbols
2: add hierarchy
Expand Down
150 changes: 145 additions & 5 deletions src/board/board.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const LutEnumStr<Board::OutputFormat> Board::output_format_lut = {
{"odb", Board::OutputFormat::ODB},
};

static const unsigned int app_version = 20;
static const unsigned int app_version = 21;

unsigned int Board::get_app_version()
{
Expand All @@ -62,6 +62,14 @@ Board::Board(const UUID &uu, const json &j, Block &iblock, IPool &pool, const st
stackup.emplace(std::piecewise_construct, std::forward_as_tuple(l), std::forward_as_tuple(l, it.value()));
}
}
if (j.count("user_layers")) {
const json &o = j["user_layers"];
for (auto it = o.cbegin(); it != o.cend(); ++it) {
int l = std::stoi(it.key());
user_layers.emplace(std::piecewise_construct, std::forward_as_tuple(l),
std::forward_as_tuple(l, it.value()));
}
}
set_n_inner_layers(n_inner_layers);
if (j.count("polygons")) {
const json &o = j["polygons"];
Expand Down Expand Up @@ -369,7 +377,7 @@ Board::Board(const Board &brd, CopyMode copy_mode)
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), board_directory(brd.board_directory),
n_inner_layers(brd.n_inner_layers)
n_inner_layers(brd.n_inner_layers), user_layers(brd.user_layers)
{
if (copy_mode == CopyMode::DEEP) {
packages = brd.packages;
Expand Down Expand Up @@ -510,6 +518,11 @@ unsigned int Board::get_n_inner_layers() const
void Board::set_n_inner_layers(unsigned int n)
{
n_inner_layers = n;
update_layers();
}

void Board::update_layers()
{
layers.clear();
layers = {{200, {200, "Top Notes"}},
{BoardLayers::OUTLINE_NOTES, {BoardLayers::OUTLINE_NOTES, "Outline Notes"}},
Expand Down Expand Up @@ -539,12 +552,132 @@ void Board::set_n_inner_layers(unsigned int n)
layers.emplace(std::make_pair(-j, Layer(-j, "Inner " + std::to_string(j), false, true)));
stackup.emplace(-j, -j);
}
for (const auto &[i, ul] : user_layers) {
auto &l = layers.emplace(std::piecewise_construct, std::forward_as_tuple(i), std::forward_as_tuple(i, ul.name))
.first->second;
l.position = ul.position;
l.color_layer = ul.id_color;
stackup.emplace(i, i);
}
assign_user_layer_positions();

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);
}

unsigned int Board::count_available_user_layers() const
{
return std::max(0, (int)BoardLayers::max_user_layers - (int)user_layers.size());
}

Board::UserLayer::UserLayer(int l)
: id(l), id_color(l), name("User Layer " + std::to_string(l - BoardLayers::FIRST_USER_LAYER)), position(l),
type(Type::DOCUMENTATION)
{
}

static const LutEnumStr<Board::UserLayer::Type> user_layer_type_lut = {
{"documentation", Board::UserLayer::Type::DOCUMENTATION}, {"stiffener", Board::UserLayer::Type::STIFFENER},
{"bend_area", Board::UserLayer::Type::BEND_AREA}, {"flex_area", Board::UserLayer::Type::FLEX_AREA},
{"rigid_area", Board::UserLayer::Type::RIGID_AREA}, {"carbon_mask", Board::UserLayer::Type::CARBON_MASK},
{"silver_mask", Board::UserLayer::Type::SILVER_MASK}, {"covercoat", Board::UserLayer::Type::COVERCOAT},
{"coverlay", Board::UserLayer::Type::COVERLAY}, {"psa", Board::UserLayer::Type::PSA},
};

Board::UserLayer::UserLayer(int l, const json &j)
: id(l), id_color(j.value("id_color", l)), name(j.at("name").get<std::string>()),
position(j.at("position").get<double>()), type(user_layer_type_lut.lookup(j.at("type")))
{
}

json Board::UserLayer::serialize() const
{
json j;
j["name"] = name;
j["position"] = position;
j["id_color"] = id_color;
j["type"] = user_layer_type_lut.lookup_reverse(type);
return j;
}

int Board::add_user_layer(int other_layer, UserLayerOrder order)
{
if (count_available_user_layers() < 1)
throw std::runtime_error("no more user layers available");
int user_layer;
for (user_layer = BoardLayers::FIRST_USER_LAYER; user_layer <= BoardLayers::LAST_USER_LAYER; user_layer++) {
if (user_layers.count(user_layer) == 0)
break;
}
if (user_layers.count(user_layer))
throw std::runtime_error("no more user layers available");


auto &ul = user_layers.emplace(user_layer, user_layer).first->second;
const double offset = 1.0 / (2 * BoardLayers::max_user_layers);
const auto other_pos = layers.at(other_layer).position;
ul.position = other_pos + offset * static_cast<int>(order);


update_layers();
return user_layer;
}

void Board::delete_user_layer(int layer)
{
user_layers.erase(layer);
update_layers();
}

void Board::assign_user_layer_positions()
{
const auto layers_sorted = get_layers_sorted(LayerSortOrder::BOTTOM_TO_TOP);
const double step = 1.0 / BoardLayers::max_user_layers;
double pos = BoardLayers::BOTTOM_NOTES - 1;
for (const auto &it : layers_sorted) {
if (BoardLayers::is_user(it.index)) {
pos += step;
layers.at(it.index).position = pos;
user_layers.at(it.index).position = pos;
}
else {
layers.at(it.index).position = it.index;
pos = it.index;
}
}
}

void Board::set_user_layer_name(int user_layer, const std::string &name)
{
user_layers.at(user_layer).name = name;
update_layers();
}

void Board::set_user_layer_type(int user_layer, UserLayer::Type type)
{
user_layers.at(user_layer).type = type;
}

void Board::set_user_layer_color(int user_layer, int color_layer)
{
user_layers.at(user_layer).id_color = color_layer;
}

void Board::move_user_layer(int user_layer, int other_layer, UserLayerOrder pos)
{
const double offset = 1.0 / (2 * BoardLayers::max_user_layers) * static_cast<int>(pos);
user_layers.at(user_layer).position = layers.at(other_layer).position + offset;
update_layers();
}


const std::map<int, Board::UserLayer> &Board::get_user_layers() const
{
return user_layers;
}

void Board::update_pdf_export_settings(PDFExportSettings &settings)
{
auto layers_from_board = get_layers();
Expand Down Expand Up @@ -573,9 +706,10 @@ void Board::update_pdf_export_settings(PDFExportSettings &settings)
add_layer(BoardLayers::TOP_PACKAGE, false);
add_layer(BoardLayers::TOP_COPPER, false);
for (const auto &la : layers_from_board) {
if (BoardLayers::is_copper(la.first) && la.first > BoardLayers::BOTTOM_COPPER
&& la.first < BoardLayers::TOP_COPPER)
add_layer(la.first, false);
if ((BoardLayers::is_copper(la.first) && la.first > BoardLayers::BOTTOM_COPPER
&& la.first < BoardLayers::TOP_COPPER)
|| BoardLayers::is_user(la.first))
add_layer(la.first, BoardLayers::is_user(la.first));
}
add_layer(BoardLayers::BOTTOM_COPPER, false);
add_layer(BoardLayers::BOTTOM_MASK, false);
Expand Down Expand Up @@ -1214,6 +1348,12 @@ json Board::serialize() const
j["net_ties"][(std::string)it.first] = it.second.serialize();
}
}
if (user_layers.size()) {
j["user_layers"] = json::object();
for (const auto &it : user_layers) {
j["user_layers"][std::to_string(it.first)] = it.second.serialize();
}
}
return j;
}

Expand Down
40 changes: 40 additions & 0 deletions src/board/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,42 @@ class Board : public ObjectProvider, public LayerProvider {
};
std::map<int, StackupLayer> stackup;


class UserLayer {
public:
UserLayer(int l, const json &j);
UserLayer(int l);
json serialize() const;

int id;
int id_color;
std::string name;
double position;
enum class Type {
DOCUMENTATION,
STIFFENER,
COVERLAY,
COVERCOAT,
BEND_AREA,
FLEX_AREA,
RIGID_AREA,
PSA,
SILVER_MASK,
CARBON_MASK
};
Type type;
};
const std::map<int, UserLayer> &get_user_layers() const;

enum class UserLayerOrder : int { ABOVE = 1, BELOW = -1 };
int add_user_layer(int other_layer, UserLayerOrder pos);
void delete_user_layer(int user_layer);
unsigned int count_available_user_layers() const;
void move_user_layer(int user_layer, int other_layer, UserLayerOrder pos);
void set_user_layer_name(int user_layer, const std::string &name);
void set_user_layer_type(int user_layer, UserLayer::Type type);
void set_user_layer_color(int user_layer, int layer_color);

BoardColors colors;
PDFExportSettings pdf_export_settings;
STEPExportSettings step_export_settings;
Expand Down Expand Up @@ -197,6 +233,10 @@ class Board : public ObjectProvider, public LayerProvider {
Board(const Board &brd, CopyMode copy_mode);
void expand_packages();
Outline get_outline(bool with_errors) const;

std::map<int, UserLayer> user_layers;
void update_layers();
void assign_user_layer_positions();
};

inline Board::ExpandFlags operator|(Board::ExpandFlags a, Board::ExpandFlags b)
Expand Down
53 changes: 44 additions & 9 deletions src/board/board_layers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,55 @@ std::string BoardLayers::get_layer_name(int l)

case BOTTOM_NOTES:
return "Bottom Notes";

case USER1:
case USER2:
case USER3:
case USER4:
case USER5:
case USER6:
case USER7:
case USER8:
return "User " + std::to_string(l - FIRST_USER_LAYER + 1);
}
return "Invalid layer " + std::to_string(l);
}

static const std::vector<int> layers = {
BoardLayers::TOP_NOTES, BoardLayers::OUTLINE_NOTES, BoardLayers::L_OUTLINE,
BoardLayers::TOP_COURTYARD, BoardLayers::TOP_ASSEMBLY, BoardLayers::TOP_PACKAGE,
BoardLayers::TOP_PASTE, BoardLayers::TOP_SILKSCREEN, BoardLayers::TOP_MASK,
BoardLayers::TOP_COPPER, BoardLayers::IN1_COPPER, BoardLayers::IN2_COPPER,
BoardLayers::IN3_COPPER, BoardLayers::IN4_COPPER, BoardLayers::IN5_COPPER,
BoardLayers::IN6_COPPER, BoardLayers::IN7_COPPER, BoardLayers::IN8_COPPER,
BoardLayers::BOTTOM_COPPER, BoardLayers::BOTTOM_MASK, BoardLayers::BOTTOM_SILKSCREEN,
BoardLayers::BOTTOM_PASTE, BoardLayers::BOTTOM_PACKAGE, BoardLayers::BOTTOM_ASSEMBLY,
BoardLayers::BOTTOM_COURTYARD, BoardLayers::BOTTOM_NOTES,
BoardLayers::TOP_NOTES,
BoardLayers::OUTLINE_NOTES,
BoardLayers::L_OUTLINE,
BoardLayers::TOP_COURTYARD,
BoardLayers::TOP_ASSEMBLY,
BoardLayers::TOP_PACKAGE,
BoardLayers::TOP_PASTE,
BoardLayers::TOP_SILKSCREEN,
BoardLayers::TOP_MASK,
BoardLayers::TOP_COPPER,
BoardLayers::IN1_COPPER,
BoardLayers::IN2_COPPER,
BoardLayers::IN3_COPPER,
BoardLayers::IN4_COPPER,
BoardLayers::IN5_COPPER,
BoardLayers::IN6_COPPER,
BoardLayers::IN7_COPPER,
BoardLayers::IN8_COPPER,
BoardLayers::BOTTOM_COPPER,
BoardLayers::BOTTOM_MASK,
BoardLayers::BOTTOM_SILKSCREEN,
BoardLayers::BOTTOM_PASTE,
BoardLayers::BOTTOM_PACKAGE,
BoardLayers::BOTTOM_ASSEMBLY,
BoardLayers::BOTTOM_COURTYARD,
BoardLayers::BOTTOM_NOTES,
BoardLayers::USER1,
BoardLayers::USER2,
BoardLayers::USER3,
BoardLayers::USER4,
BoardLayers::USER5,
BoardLayers::USER6,
BoardLayers::USER7,
BoardLayers::USER8,
};

const std::vector<int> &BoardLayers::get_layers()
Expand Down
17 changes: 17 additions & 0 deletions src/board/board_layers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ namespace horizon {
class BoardLayers {
public:
enum Layer {
LAST_USER_LAYER = 1007,
FIRST_USER_LAYER = 1000,
USER1 = FIRST_USER_LAYER + 0,
USER2 = FIRST_USER_LAYER + 1,
USER3 = FIRST_USER_LAYER + 2,
USER4 = FIRST_USER_LAYER + 3,
USER5 = FIRST_USER_LAYER + 4,
USER6 = FIRST_USER_LAYER + 5,
USER7 = FIRST_USER_LAYER + 6,
USER8 = FIRST_USER_LAYER + 7,
TOP_NOTES = 200,
OUTLINE_NOTES = 110,
L_OUTLINE = 100,
Expand Down Expand Up @@ -35,6 +45,8 @@ class BoardLayers {
BOTTOM_NOTES = -200
};

static const unsigned int max_user_layers = LAST_USER_LAYER - FIRST_USER_LAYER + 1;

static const LayerRange layer_range_through;

static bool is_copper(int l)
Expand All @@ -52,6 +64,11 @@ class BoardLayers {
return l == TOP_SILKSCREEN || l == BOTTOM_SILKSCREEN;
}

static bool is_user(int l)
{
return l <= LAST_USER_LAYER && l >= FIRST_USER_LAYER;
}

static const unsigned int max_inner_layers;

static std::string get_layer_name(int l);
Expand Down
5 changes: 3 additions & 2 deletions src/board/gerber_output_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@ void GerberOutputSettings::update_for_board(const Board &brd)
add_layer(BoardLayers::TOP_MASK);
add_layer(BoardLayers::TOP_COPPER);
for (const auto &la : layers_from_board) {
if (BoardLayers::is_copper(la.first) && la.first > BoardLayers::BOTTOM_COPPER
&& la.first < BoardLayers::TOP_COPPER)
if ((BoardLayers::is_copper(la.first) && la.first > BoardLayers::BOTTOM_COPPER
&& la.first < BoardLayers::TOP_COPPER)
|| BoardLayers::is_user(la.first))
add_layer(la.first);
}
add_layer(BoardLayers::BOTTOM_COPPER);
Expand Down
9 changes: 9 additions & 0 deletions src/canvas/appearance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ Appearance::Appearance()
layer_colors[BoardLayers::BOTTOM_COURTYARD] = {.5, .5, .5};

layer_colors[BoardLayers::BOTTOM_NOTES] = {1, 1, 1};
layer_colors[BoardLayers::USER1] = {.25, 1, 1};
layer_colors[BoardLayers::USER2] = {.25, 1, 1};
layer_colors[BoardLayers::USER3] = {.25, 1, 1};
layer_colors[BoardLayers::USER4] = {.25, 1, 1};
layer_colors[BoardLayers::USER5] = {.25, 1, 1};
layer_colors[BoardLayers::USER6] = {.25, 1, 1};
layer_colors[BoardLayers::USER7] = {.25, 1, 1};
layer_colors[BoardLayers::USER8] = {.25, 1, 1};

layer_colors[10000] = {1, 1, 1};
}
} // namespace horizon
Loading

0 comments on commit d3039e1

Please sign in to comment.