Skip to content
Snippets Groups Projects
Commit c5d0a9da authored by Erik Strand's avatar Erik Strand
Browse files

Lay out the sensor node boards in code

parents 7adb3061 def2b693
Branches
No related tags found
No related merge requests found
cmake_minimum_required(VERSION 3.13) # 3.13 is required for target_link_options
project(NodeBoard CXX)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
include(cmake/shared_settings.cmake)
find_package(PNG REQUIRED)
add_executable(generate_node_board
main.cpp
png_writer.cpp
png_writer.h
)
target_include_directories(generate_node_board PUBLIC ${PNG_INCLUDE_DIR})
target_link_libraries(generate_node_board shared_settings ${PNG_LIBRARY})
target_compile_features(generate_node_board PUBLIC cxx_std_17)
# This file defines an interface library used to add common compile flags to all libraries and
# executables in FunkyCT.
add_library(shared_settings INTERFACE)
# Warning flags
target_compile_options(shared_settings INTERFACE
-Wall
-Wcast-align
-Wcast-qual
-Wextra
-Wundef
-Wuseless-cast
-Wzero-as-null-pointer-constant
-pedantic
)
# Speed flags
target_compile_options(shared_settings INTERFACE -march=native -ffast-math)
# Build type for profile generation
target_compile_options(shared_settings INTERFACE $<$<CONFIG:ProfileGenerate>:
-fprofile-generate
-O3
-DNDEBUG
>)
target_link_options(shared_settings INTERFACE $<$<CONFIG:ProfileGenerate>:-fprofile-generate>)
# Build type for profile use
target_compile_options(shared_settings INTERFACE $<$<CONFIG:ProfileUse>:
-fprofile-use
-O3
-DNDEBUG
>)
target_link_options(shared_settings INTERFACE $<$<CONFIG:ProfileUse>:-fprofile-use>)
#include "png_writer.h"
#include <iostream>
//--------------------------------------------------------------------------------------------------
struct Rectangle {
int32_t x_min;
int32_t x_max;
int32_t y_min;
int32_t y_max;
};
//--------------------------------------------------------------------------------------------------
class Board {
public:
Board(double width, double height, double pix_per_mm, double min_cut_thickness)
: width_(width), height_(height), pix_per_mm_(pix_per_mm),
min_cut_thickness_(min_cut_thickness), width_px_(to_px(width_)), height_px_(to_px(height_)),
min_cut_thickness_px_(to_px(min_cut_thickness_))
{
png_writer_.allocate(width_px_ + 4 * min_cut_thickness_px_,
height_px_ + 4 * min_cut_thickness_px_);
png_writer_.set_all_pixels(255);
draw_int_rectangle(0, width_px_, 0, height_px_, 0);
}
int32_t to_px(double x) {
return static_cast<int32_t>(pix_per_mm_ * x);
}
void set_pixel(int32_t x, int32_t y, uint8_t value = 255) {
x = std::max(-2 * min_cut_thickness_px_, x);
x = std::min(width_px_ + 2 * min_cut_thickness_px_, x);
y = std::max(-2 * min_cut_thickness_px_, y);
y = std::min(height_px_ + 2 * min_cut_thickness_px_, y);
png_writer_.set_pixel(2 * min_cut_thickness_px_ + x,
2 * min_cut_thickness_px_ + height_px_ - y - 1,
value);
}
void draw_int_rectangle(
int32_t x_min, int32_t x_max, int32_t y_min, int32_t y_max, uint8_t value = 255
) {
for (int32_t x = x_min; x < x_max; ++x) {
for (int32_t y = y_min; y < y_max; ++y) {
set_pixel(x, y, value);
}
}
}
void draw_rectangle(
double x_min, double x_max, double y_min, double y_max, uint8_t value = 255
) {
draw_int_rectangle(to_px(x_min), to_px(x_max), to_px(y_min), to_px(y_max), value);
}
void draw_rectangle(Rectangle const& r, uint8_t value = 255) {
draw_int_rectangle(r.x_min, r.x_max, r.y_min, r.y_max, value);
}
void draw_pad(double x_min, double x_max, double y_min, double y_max) {
draw_rectangle(x_min - min_cut_thickness_, x_max + min_cut_thickness_,
y_min - min_cut_thickness_, y_max + min_cut_thickness_,
0);
draw_rectangle(x_min, x_max, y_min, y_max, 255);
}
void save(char const* filename) {
png_writer_.write(filename);
}
void save_outline(char const* filename) {
png_writer_.set_all_pixels_black();
draw_int_rectangle(0, width_px_, 0, height_px_);
save(filename);
}
public:
PngWriter png_writer_;
double width_;
double height_;
double pix_per_mm_;
double min_cut_thickness_;
int32_t width_px_;
int32_t height_px_;
int32_t min_cut_thickness_px_;
};
//--------------------------------------------------------------------------------------------------
// All length measurements are in mm.
int main() {
// reused vars... dirty C style
double pad_x_min;
double pad_x_max;
double pad_y_min;
double pad_y_max;
// board params
// width is deduced later
double const height = 18;
double const ppmm = 50; // equivalent to 1270 ppi
double const min_cut_thickness = 0.38;
double const min_trace_thickness = 0.35;
// SOIC dims
double const pad_width = 0.6;
double const pad_height = 2.4;
double const soic_height = 7;
double const soic_pitch = 1.27;
double const soic_width = 3 * soic_pitch + pad_width;
// deduce width and make the board
double const width = soic_width + 3 * min_cut_thickness + 3 * min_trace_thickness;
std::cout << "Board width: " << width << "mm\n";
Board board(width, height, ppmm, min_cut_thickness);
// SOIC pads
double const soic_x_min = min_trace_thickness + min_cut_thickness;
double const soic_x_max = soic_x_min + 3 * soic_pitch + pad_width;
double const soic_btm_y = 0.5 * (height - soic_height);
double const soic_top_y = height - soic_btm_y;
for (int32_t i = 0; i < 4; ++i) {
pad_x_min = soic_x_min + i * soic_pitch;
pad_x_max = pad_x_min + pad_width;
pad_y_max = soic_btm_y + pad_height;
board.draw_rectangle(pad_x_min, pad_x_max, soic_btm_y, pad_y_max);
pad_y_min = soic_top_y - pad_height;
board.draw_rectangle(pad_x_min, pad_x_max, pad_y_min, soic_top_y);
}
// Ground pads and traces
double const cable_pad_width = (width - 2 * min_cut_thickness) / 3;
double const cable_pad_height = soic_btm_y - min_cut_thickness;
double const bridge_offset = 0.5 * (pad_width - min_trace_thickness);
board.draw_rectangle(0, cable_pad_width, 0, cable_pad_height);
board.draw_rectangle(0, min_trace_thickness, 0, height);
board.draw_rectangle(soic_x_min + bridge_offset,
soic_x_min + bridge_offset + min_trace_thickness,
cable_pad_height,
cable_pad_height + min_cut_thickness);
board.draw_rectangle(0,
cable_pad_width,
soic_top_y + 2 * min_cut_thickness + min_trace_thickness,
height);
// Data pads and traces
double const data_pad_x_min = cable_pad_width + min_cut_thickness;
double const data_pad_x_max = data_pad_x_min + cable_pad_width;
board.draw_rectangle(data_pad_x_min, data_pad_x_max, 0, cable_pad_height);
board.draw_rectangle(data_pad_x_max,
soic_x_max + min_cut_thickness + min_trace_thickness,
cable_pad_height - min_cut_thickness,
cable_pad_height);
board.draw_rectangle(soic_x_max + min_cut_thickness,
soic_x_max + min_cut_thickness + min_trace_thickness,
cable_pad_height,
soic_btm_y + pad_height + min_cut_thickness);
board.draw_rectangle(soic_x_min + bridge_offset,
soic_x_max + min_cut_thickness + min_trace_thickness,
soic_btm_y + pad_height + min_cut_thickness,
soic_btm_y + pad_height + min_cut_thickness + min_trace_thickness);
board.draw_rectangle(soic_x_min + bridge_offset,
soic_x_min + bridge_offset + min_trace_thickness,
soic_btm_y + pad_height + min_cut_thickness,
soic_top_y + min_cut_thickness);
board.draw_rectangle(soic_x_min + bridge_offset,
data_pad_x_max,
soic_top_y + min_cut_thickness,
soic_top_y + min_cut_thickness + min_trace_thickness);
board.draw_rectangle(data_pad_x_min, data_pad_x_max, soic_top_y + min_cut_thickness, height);
// VCC pads and traces
double const vcc_pad_x_min = 2 * (cable_pad_width + min_cut_thickness);
// pad 1
board.draw_rectangle(vcc_pad_x_min,
width,
0,
// Note the fudge factor... It makes mods happy.
cable_pad_height - min_cut_thickness - min_trace_thickness - 0.025);
board.draw_rectangle(width - min_trace_thickness, width, 0, height);
// pad 2
board.draw_rectangle(vcc_pad_x_min,
width,
height - cable_pad_height,
height);
// pad extension
board.draw_rectangle(soic_x_max + min_cut_thickness,
width,
soic_top_y - pad_height - min_cut_thickness,
height - cable_pad_height);
double const vcc_pin_x = soic_x_min + soic_pitch + bridge_offset;
board.draw_rectangle(vcc_pin_x,
width,
soic_top_y - pad_height - min_cut_thickness - min_trace_thickness,
soic_top_y - pad_height - min_cut_thickness);
board.draw_rectangle(vcc_pin_x,
vcc_pin_x + min_trace_thickness,
soic_top_y - pad_height - min_cut_thickness,
soic_top_y);
// Extend pad divisions
board.draw_rectangle(cable_pad_width,
cable_pad_width + min_cut_thickness,
-min_cut_thickness,
0,
0);
board.draw_rectangle(cable_pad_width,
cable_pad_width + min_cut_thickness,
height,
height + min_cut_thickness,
0);
board.draw_rectangle(width - cable_pad_width - min_cut_thickness,
width - cable_pad_width,
-min_cut_thickness,
0,
0);
board.draw_rectangle(width - cable_pad_width - min_cut_thickness,
width - cable_pad_width,
height,
height + min_cut_thickness,
0);
board.save("node_board_traces.png");
board.save_outline("node_board_outline.png");
return 0;
}
#include "png_writer.h"
#include <stdlib.h>
#include <stdio.h>
#include <cstring>
#include <iostream>
//..................................................................................................
PngWriter::PngWriter(): width_(0), height_(0), row_pointers_(nullptr) {}
//..................................................................................................
PngWriter::~PngWriter() {
if (row_pointers_ != nullptr) {
free();
}
}
//..................................................................................................
void PngWriter::free() {
for (int32_t y = 0; y < height_; y++) {
std::free(row_pointers_[y]);
}
std::free(row_pointers_);
width_ = 0;
height_ = 0;
}
//..................................................................................................
void PngWriter::allocate(int32_t width, int32_t height) {
if (row_pointers_ != nullptr) {
free();
}
width_ = width;
height_ = height;
row_pointers_ = (png_bytep*)malloc(sizeof(png_bytep) * height_);
for (int y = 0; y < height_; y++) {
row_pointers_[y] = (png_bytep)malloc(row_size());
}
}
//..................................................................................................
void PngWriter::set_pixel(int32_t x, int32_t y, uint8_t value) {
png_bytep row = row_pointers_[y];
png_bytep px = &(row[x * 3]);
px[0] = value;
px[1] = value;
px[2] = value;
}
//..................................................................................................
void PngWriter::set_all_pixels(uint8_t value) {
for (int y = 0; y < height_; y++) {
png_bytep row = row_pointers_[y];
for (int x = 0; x < width_; x++) {
png_bytep px = &(row[x * 3]);
px[0] = value;
px[1] = value;
px[2] = value;
}
}
}
//..................................................................................................
void PngWriter::set_all_pixels_black() {
for (int y = 0; y < height_; y++) {
std::memset(row_pointers_[y], 0, row_size());
}
}
//..................................................................................................
void PngWriter::write(char const* filename) {
auto fp = fopen(filename, "wb");
if (!fp) {
std::cout << "Couldn't make file\n";
abort();
}
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png) {
std::cout << "Couldn't make png_structp\n";
abort();
}
png_infop info = png_create_info_struct(png);
if (!info) {
std::cout << "Couldn't make png_structp\n";
abort();
}
if (setjmp(png_jmpbuf(png))) {
std::cout << "Couldn't set jump\n";
abort();
}
png_init_io(png, fp);
// Output is 8bit depth, RGB format.
png_set_IHDR(png,
info,
width_,
height_,
8,
PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT
);
png_write_info(png, info);
if (png_get_rowbytes(png, info) != row_size()) {
std::cout << "Allocated bad amount of memory\n";
abort();
}
// To remove the alpha channel for PNG_COLOR_TYPE_RGB format,
// Use png_set_filler().
//png_set_filler(png_, 0, PNG_FILLER_AFTER);
png_write_image(png, row_pointers_);
png_write_end(png, NULL);
if (png && info) {
png_destroy_write_struct(&png, &info);
}
fclose(fp);
}
#include <png.h>
#include <cstdint>
//--------------------------------------------------------------------------------------------------
// This class is derived from code by Guillaume Cottenceau, copyright 2002-2010 and distributed
// under the X11 license. https://gist.github.com/niw/5963798
class PngWriter {
public:
PngWriter();
~PngWriter();
void free();
void allocate(int32_t width, int32_t height);
png_bytep* row_pointers() { return row_pointers_; }
void set_pixel(int32_t x, int32_t y, uint8_t value = 255);
void set_all_pixels(uint8_t value);
void set_all_pixels_black();
void write(char const* filename);
private:
uint32_t row_size() { return 3 * width_; }
int32_t width_;
int32_t height_;
png_bytep* row_pointers_;
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment