Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolay-Kha committed Nov 1, 2015
0 parents commit 8866071
Show file tree
Hide file tree
Showing 44 changed files with 6,170 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.user
24 changes: 24 additions & 0 deletions GerberElement.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef GERBERELEMENT_H
#define GERBERELEMENT_H

enum ElementType {
TYPE_LINE_RECT,
TYPE_LINE_ROUND,
TYPE_RECT,
TYPE_ROUND
};

typedef struct tGerberElement{
ElementType type;
float startX;
float startY;
float endX;
float endY;
float lx;
float ly;
tGerberElement * next;
} GerberElement;

bool intersects(GerberElement *a, GerberElement *b);

#endif // GERBERELEMENT_H
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2015 Nikolay Khabarov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
57 changes: 57 additions & 0 deletions PCBConverter.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#-------------------------------------------------
#
# Project created by QtCreator 2014-02-28T13:52:30
#
#-------------------------------------------------

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = ../../bin/PCBConverter
TEMPLATE = app
win32 {
QMAKE_LFLAGS *= -static -static-libgcc
}

SOURCES += main.cpp\
libgeometry/gline.cpp \
libgeometry/gcircle.cpp \
libgeometry/grect.cpp \
libgeometry/gpoint.cpp \
libgeometry/gshape.cpp \
libgeometry/gintersects.cpp \
gerberreader.cpp \
gerberview.cpp \
pcbconverter.cpp \
gcodeexport.cpp \
drillreader.cpp \
readersstruct.cpp \
pcbpathcontur.cpp \
printingpathcontur.cpp \
pathcontur.cpp \
zoomablegerberview.cpp \
settings.cpp

HEADERS += \
libgeometry/libgeometry.h \
libgeometry/gline.h \
libgeometry/gpoint.h \
libgeometry/gshape.h \
libgeometry/gcircle.h \
libgeometry/grect.h \
libgeometry/gintersects.h \
gerberreader.h \
gerberview.h \
pathcontur.h \
pcbconverter.h \
gcodeexport.h \
drillreader.h \
readersstruct.h \
pcbpathcontur.h \
printingpathcontur.h \
zoomablegerberview.h \
settings.h

FORMS += \
pcbconverter.ui
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# PCBConverter
Util for converting PCB from gerber format to gcode for CNC machines. Tested with KiCAD gerber output. But should work with other software.

![](demo1.png?raw=true)
![](demo2.png?raw=true)

# Features
Util support 4 methods for DIY PCB making technics:
* Milling - engrave PCB by milling workpiece cooper layer with CNC machine and milling tool in it. Util will generate path around all elements of PCB.
* Printing - if your CNC machine has pen with special protective ink, you can plot PCB on workpiece and then make real board with chemical methods.
* 3D Printing - the idea was to cover workpiece with plastic from 3D printer. It can be special electricity conductive material or just protective layer for chemical methods. Actually, it was never tested.
* Laser photoresist - cover workpiece with photoresist film and use 405nm laser to paint a PCB on it.

# Usage
For example, to engrave PCB board on your CNC engraving machinem you need to:
* export PCB in gerber format (for KiCAD: open Pcbnew, "File"->"Plot", choose cooprom layers and generate drills too)
* open gerbers in util
* choose "Method" - "Milling" and other options
* click on generate to see preview
* click on "Write to file" to save it in gcode file
* run this file on your CNC machine

# Preview window usage
Left click - select element on screen
Left hold and move - browse PCB
Right click - change layer
Middle button - show/hide generated route
Wheel - zoom
Binary file added demo1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demo2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
206 changes: 206 additions & 0 deletions drillreader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
#include "drillreader.h"
#include <stdio.h>


DrillReader::DrillReader(char *filename, const GPoint &offset, const GPoint &max, Mirror mirror)
{
mUnits = UNITS_INC;
mCoord = COORD_ABSOLUTE;
mXOffset = offset.x;
mYOffset = offset.y;
mReadX = 0.0f;
mReadY = 0.0f;
mXOffset92 = 0.0f;
mYOffset92 = 0.0f;
mX = 0.0f;
mY = 0.0f;
mFirstDrill = 0;
mLastDrill = 0;

for(int i=0; i<MAXIMUM_TOOL_COUNT; i++)
mTools[i] = 0;

FILE *fl = fopen(filename, "r");
if(fl) {
char lineBuffer[MAX_LINE_LENGTH];
while(fgets(lineBuffer, sizeof lineBuffer, fl)) {
parseLine(lineBuffer);
}
fclose(fl);
}
if(mirror!=M_NO) {
Drill *nextDrill = mFirstDrill;
while(nextDrill) {
GPoint *next = nextDrill->firstPoint;
while(next) {
if(mirror==M_HORIZONTAL || mirror==M_BOTH)
next->x = max.x - next->x;
if(mirror==M_VERTICAL || mirror==M_BOTH)
next->y = max.y - next->y;
next = next->next;
}
nextDrill = nextDrill->next;
}
}
}

DrillReader::~DrillReader() {
while(mFirstDrill) {
while(mFirstDrill->firstPoint) {
GPoint *next = mFirstDrill->firstPoint->next;
delete mFirstDrill->firstPoint;
mFirstDrill->firstPoint = next;
}
Drill *nextDrill = mFirstDrill->next;
delete mFirstDrill;
mFirstDrill = nextDrill;
}
}

Drill *DrillReader::firstDrill() {
return mFirstDrill;
}

char *DrillReader::readCoord(char *ptr, float base, float *result)
{
float v = 0;
char *res = Readers::readArgf(ptr, &v);
if(mUnits==UNITS_INC)
v *=25.4f;
v-=base;
*result = v;
return res;
}

void DrillReader::parseLine(char *line) {
if(mCoord == COORD_RELATIVE) {
mReadX = 0.0f;
mReadY = 0.0f;
}
int tmp;
int readT = -1;
float readC = 0.0f;
bool needD = false;
bool need92 = false;
if(line[0]=='M' && line[1]=='E' && line[2]=='T' && line[3]=='R' && line[4]=='I' && line[5]=='C')
mUnits = UNITS_MM;
if(line[0]=='I' && line[1]=='N' && line[2]=='C' && line[3]=='H')
mUnits = UNITS_INC;
while (*line && *line!='*' && *line!='\r' && *line!='\n') {
switch(*line) {
case '(': // comment
while(*line!=')') {
line++;
if(*line==0 || *line=='\r' || *line=='\n')
goto gofromwhile;
}
break;
case ';': // comment
return;
case 'M':
case 'm':
line = Readers::readArgi(line+1, &tmp)-1;
switch(tmp) {
// avoid drill patterm
case 71: // mm
mUnits = UNITS_MM;
break;
case 72: // inch
mUnits = UNITS_INC;
break;
}
break;
case 'g':
case 'G':
line = Readers::readArgi(line+1, &tmp)-1;
switch(tmp) {
case 5:
case 81: // drill mode, fuck them
break;
case 90: // absolute mode
mCoord = COORD_ABSOLUTE;
break;
case 91: // relative mode
mCoord = COORD_RELATIVE;
break;
case 92: // set zero
case 93: // set zero
need92 = true;
break;
}
break;
case '%':
return;
case 't':
case 'T':
line = Readers::readArgi(line+1, &readT)-1;
break;
case 'c':
case 'C':
line = Readers::readArgf(line+1, &readC)-1;
break;
case 'x':
case 'X':
line = readCoord(line+1, mXOffset, &mReadX)-1;
needD = true;
break;
case 'y':
case 'Y':
line = readCoord(line+1, mYOffset, &mReadY)-1;
needD = true;
break;
}

line++;
}
gofromwhile:
if(readT!=-1) {
if(readC!=0.0f) {
Drill *newdrill = new Drill;
newdrill->next = 0;
newdrill->firstPoint = 0;
newdrill->diameter = readC;
if(mUnits == UNITS_INC)
newdrill->diameter *= 25.4f;
if(mFirstDrill==0)
mFirstDrill = newdrill;
else
mLastDrill->next = newdrill;
mLastDrill = newdrill;
mTools[readT] = newdrill;
}
mCurrentDrill = mTools[readT];
if(mCurrentDrill) {
mCurrentDrillLastPoint = mCurrentDrill->firstPoint;
if(mCurrentDrillLastPoint) {
while(mCurrentDrillLastPoint->next)
mCurrentDrillLastPoint = mCurrentDrillLastPoint->next;
}
} else {
mCurrentDrillLastPoint = 0;
}
}
if(need92) {
mXOffset92 = mReadX;
mXOffset92 = mReadY;
}
if(needD && mCurrentDrill) {
GPoint *newpoint = new GPoint(mReadX,mReadY);
if(mCoord == COORD_RELATIVE) {
newpoint->x += mX;
newpoint->y += mY;
} else if(mCoord == COORD_ABSOLUTE) {
newpoint->x += mXOffset92;
newpoint->y += mXOffset92;
}
mX = newpoint->x;
mY = newpoint->y;
newpoint->next = 0;
if(mCurrentDrillLastPoint)
mCurrentDrillLastPoint->next = newpoint;

else
mCurrentDrill->firstPoint = newpoint;
mCurrentDrillLastPoint = newpoint;
}
}
34 changes: 34 additions & 0 deletions drillreader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef DRILLREADER_H
#define DRILLREADER_H
#include "readersstruct.h"

class DrillReader
{
public:
DrillReader(char *filename, const GPoint &offset, const GPoint &max, Mirror mirror);
~DrillReader();
Drill *firstDrill();

private:
Units mUnits;
Coord mCoord;
double mXOffset;
double mYOffset;
double mXOffset92;
double mYOffset92;
Drill *mFirstDrill;
Drill *mLastDrill;
Drill *mTools[MAXIMUM_TOOL_COUNT];
float mReadX;
float mReadY;
float mX;
float mY;
Drill *mCurrentDrill;
GPoint *mCurrentDrillLastPoint;

void parseLine(char *line);
char *readCoord(char *ptr, float base, float *result);

};

#endif // DRILLREADER_H
Loading

0 comments on commit 8866071

Please sign in to comment.