Skip to content

Commit 457e3dd

Browse files
Add support for TF command (FileAttribute) from GerberX2
1 parent d63554d commit 457e3dd

File tree

16 files changed

+612
-18
lines changed

16 files changed

+612
-18
lines changed

gerber/gerber.cabal

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ cabal-version: >= 2.0
1111

1212
library
1313
exposed-modules: Gerber.ApertureDefinition
14+
Gerber.Attribute
15+
Gerber.Attribute.Attribute
16+
Gerber.Attribute.CreationDate
17+
Gerber.Attribute.FileFunction
18+
Gerber.Attribute.FileFunction.Copper
19+
Gerber.Attribute.FileFunction.Drill
20+
Gerber.Attribute.FileFunction.Types
21+
Gerber.Attribute.FilePolarity
22+
Gerber.Attribute.GenerationSoftware
23+
Gerber.Attribute.Part
1424
Gerber.Command
1525
Gerber.DCodeNumber
1626
Gerber.EncodedDecimal
@@ -27,12 +37,16 @@ library
2737
Gerber.StepRepeat
2838
Gerber.Unit
2939
build-depends: base ^>= 4.12 || ^>= 4.13 || ^>= 4.14
30-
, megaparsec ^>= 7.0
31-
, text >=1.2 && <1.3
32-
, generic-deriving
40+
, base16-bytestring < 1
41+
, bytestring
3342
, containers
34-
, monoid-extras
3543
, foldl
44+
, generic-deriving
45+
, megaparsec ^>= 7.0
46+
, monoid-extras
47+
, text >=1.2 && <1.3
48+
, time
49+
, uuid-types
3650
hs-source-dirs: lib
3751
default-language: Haskell2010
3852
ghc-options: -Wall

gerber/lib/Gerber/Attribute.hs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{-# language OverloadedStrings #-}
2+
3+
module Gerber.Attribute
4+
( FileAttribute(..)
5+
, parseFileAttribute
6+
) where
7+
8+
-- gerber
9+
import Gerber.Attribute.Attribute ( Attribute( Attribute ) )
10+
import Gerber.Attribute.CreationDate ( CreationDate, parseCreationDate )
11+
import Gerber.Attribute.FileFunction ( FileFunction, parseFileFunction )
12+
import Gerber.Attribute.FilePolarity ( FilePolarity, parseFilePolarity )
13+
import Gerber.Attribute.GenerationSoftware ( GenerationSoftware, parseGenerationSoftware )
14+
import Gerber.Attribute.MD5 ( MD5, parseMD5 )
15+
import Gerber.Attribute.Part ( Part, parsePart )
16+
import Gerber.Attribute.ProjectId ( ProjectId, parseProjectId )
17+
18+
19+
data FileAttribute
20+
= Part !Part
21+
| FileFunction !FileFunction
22+
| FilePolarity !FilePolarity
23+
| GenerationSoftware !GenerationSoftware
24+
| CreationDate !CreationDate
25+
| ProjectId !ProjectId
26+
| MD5 !MD5
27+
| UserAttribute !Attribute
28+
deriving ( Eq, Show )
29+
30+
31+
parseFileAttribute :: MonadFail m => Attribute -> m FileAttribute
32+
parseFileAttribute attribute@(Attribute name fields) = case name of
33+
".Part" -> Part <$> parsePart fields
34+
".FileFunction" -> FileFunction <$> parseFileFunction fields
35+
".FilePolarity" -> FilePolarity <$> parseFilePolarity fields
36+
".GenerationSoftware" -> GenerationSoftware <$> parseGenerationSoftware fields
37+
".CreationDate" -> CreationDate <$> parseCreationDate fields
38+
".ProjectId" -> ProjectId <$> parseProjectId fields
39+
".MD5" -> MD5 <$> parseMD5 fields
40+
_ -> pure (UserAttribute attribute)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module Gerber.Attribute.Attribute
2+
( Attribute(..)
3+
, Field
4+
) where
5+
6+
-- text
7+
import Data.Text ( Text )
8+
9+
10+
data Attribute = Attribute
11+
{ name :: !Text
12+
, value :: ![Field]
13+
}
14+
deriving ( Eq, Show )
15+
16+
17+
type Field = Text
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module Gerber.Attribute.CreationDate
2+
( CreationDate(..), parseCreationDate
3+
) where
4+
5+
-- gerber
6+
import Gerber.Attribute.Attribute ( Field )
7+
8+
-- text
9+
import Data.Text ( unpack )
10+
11+
-- time
12+
import Data.Time.Clock ( UTCTime )
13+
import Data.Time.Format.ISO8601 ( formatParseM, iso8601Format )
14+
15+
16+
newtype CreationDate = CreationDate UTCTime
17+
deriving ( Eq, Show )
18+
19+
20+
parseCreationDate :: MonadFail m => [Field] -> m CreationDate
21+
parseCreationDate fields = case fields of
22+
[field] -> CreationDate <$> formatParseM iso8601Format (unpack field)
23+
_ -> fail "Bad .CreationDate: must have exactly 1 field"
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{-# language OverloadedStrings #-}
2+
3+
module Gerber.Attribute.FileFunction
4+
( FileFunction(..), parseFileFunction
5+
) where
6+
7+
-- gerber
8+
import Gerber.Attribute.Attribute ( Field )
9+
import Gerber.Attribute.FileFunction.Types
10+
( Copper, parseCopper
11+
, Drill, parseDrill
12+
, Mask, parseMask
13+
, Profile, parseProfile
14+
, Side, parseSide
15+
)
16+
17+
-- text
18+
import Data.Text ( unpack )
19+
20+
21+
data FileFunction
22+
= Copper !Copper
23+
| Soldermask !Mask
24+
| Legend !Mask
25+
| Goldmask !Mask
26+
| Silvermask !Mask
27+
| Tinmask !Mask
28+
| Carbonmask !Mask
29+
| Peelablesoldermask !Mask
30+
| Glue !Mask
31+
| Viatenting !Side
32+
| Viafill
33+
| Heatsink !Side
34+
| Paste !Side
35+
| KeepOut !Side
36+
| Pads !Side
37+
| Scoring !Side
38+
| Plated !Drill
39+
| NonPlated !Drill
40+
| Profile !Profile
41+
| Drillmap
42+
| FabricationDrawing
43+
| ArrayDrawing
44+
| AssemblyDrawing !Side
45+
| Drawing !Field
46+
| Other !Field
47+
deriving ( Eq, Show )
48+
49+
50+
parseFileFunction :: MonadFail m => [Field] -> m FileFunction
51+
parseFileFunction [] = fail "Bad .FileFunction: at least 1 field required"
52+
parseFileFunction (name : values) = case name of
53+
"Copper" -> Copper <$> arity2or3 parseCopper
54+
"Soldermask" -> Soldermask <$> arity1or2 parseMask
55+
"Legend" -> Legend <$> arity1or2 parseMask
56+
"Goldmask" -> Goldmask <$> arity1or2 parseMask
57+
"Silvermask" -> Silvermask <$> arity1or2 parseMask
58+
"Tinmask" -> Tinmask <$> arity1or2 parseMask
59+
"Carbonmask" -> Legend <$> arity1or2 parseMask
60+
"Peelablasoldermask" -> Peelablesoldermask <$> arity1or2 parseMask
61+
"Glue" -> Glue <$> arity1or2 parseMask
62+
"Viatenting" -> Viatenting <$> arity1 parseSide
63+
"Viafill" -> arity0 $ pure Viafill
64+
"Heatsink" -> Heatsink <$> arity1 parseSide
65+
"Paste" -> Paste <$> arity1 parseSide
66+
"Keep-out" -> KeepOut <$> arity1 parseSide
67+
"Scoring" -> Scoring <$> arity1 parseSide
68+
"Plated" -> Plated <$> arity3or4 parseDrill
69+
"NonPlated" -> NonPlated <$> arity3or4 parseDrill
70+
"Profile" -> Profile <$> arity1 parseProfile
71+
"Drillmap" -> arity0 $ pure Drillmap
72+
"FabricationDrawing" -> arity0 $ pure FabricationDrawing
73+
"ArrayDrawing" -> arity0 $ pure ArrayDrawing
74+
"AssemblyDrawing" -> AssemblyDrawing <$> arity1 parseSide
75+
"Drawing" -> Drawing <$> arity1 pure
76+
"Other" -> Other <$> arity1 pure
77+
_ -> fail $ "Bad .FileFunction: unknown value " <> unpack name
78+
where
79+
arity0 f = case values of
80+
[] -> f
81+
_ -> fail $ message "0"
82+
83+
arity1 f = case values of
84+
[a] -> f a
85+
_ -> fail $ message "1"
86+
87+
arity1or2 f = case values of
88+
[a, b] -> f a (Just b)
89+
[a] -> f a Nothing
90+
_ -> fail $ message "1 or 2"
91+
92+
arity2or3 f = case values of
93+
[a, b, c] -> f a b (Just c)
94+
[a, b] -> f a b Nothing
95+
_ -> fail $ message "2 or 3"
96+
97+
arity3or4 f = case values of
98+
[a, b, c, d] -> f a b c (Just d)
99+
[a, b, c] -> f a b c Nothing
100+
_ -> fail $ message "3 or 4"
101+
102+
message n =
103+
"Bad .FileFunction: " <>
104+
unpack name <>
105+
" field requires " <>
106+
n <>
107+
" values"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{-# language OverloadedStrings #-}
2+
3+
module Gerber.Attribute.FileFunction.Copper
4+
( Mark(..), parseMark
5+
, Type(..), parseType
6+
) where
7+
8+
-- gerber
9+
import Gerber.Attribute.Attribute ( Field )
10+
11+
-- text
12+
import Data.Text ( unpack )
13+
14+
15+
data Mark = Top | Inner | Bottom
16+
deriving ( Eq, Show )
17+
18+
19+
parseMark :: MonadFail m => Field -> m Mark
20+
parseMark field = case field of
21+
"Top" -> pure Top
22+
"Inr" -> pure Inner
23+
"Bot" -> pure Bottom
24+
_ -> fail $ "Bad Copper.Mark: " <> unpack field
25+
26+
27+
data Type = Plane | Signal | Mixed | Hatched
28+
deriving ( Eq, Show )
29+
30+
31+
parseType :: MonadFail m => Field -> m Type
32+
parseType field = case field of
33+
"Plane" -> pure Plane
34+
"Signal" -> pure Signal
35+
"Mixed" -> pure Mixed
36+
"Hatched" -> pure Hatched
37+
_ -> fail $ "Bad Coppper.Type: " <> unpack field
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{-# language OverloadedStrings #-}
2+
3+
module Gerber.Attribute.FileFunction.Drill
4+
( Type(..), parseType
5+
, Via(..), parseVia
6+
) where
7+
8+
-- gerber
9+
import Gerber.Attribute.Attribute ( Field )
10+
11+
-- text
12+
import Data.Text ( unpack )
13+
14+
15+
data Type = Drill | Route | Mixed
16+
deriving ( Eq, Show )
17+
18+
19+
parseType :: MonadFail m => Field -> m Type
20+
parseType field = case field of
21+
"Drill" -> pure Drill
22+
"Route" -> pure Route
23+
"Mixed" -> pure Mixed
24+
_ -> fail $ "Bad Drill.Type: " <> unpack field
25+
26+
27+
data Via = TH | Blind | Buried
28+
deriving ( Eq, Show )
29+
30+
31+
parseVia :: MonadFail m => Field -> m Via
32+
parseVia field = case field of
33+
"PTH" -> pure TH
34+
"NPTH" -> pure TH
35+
"Blind" -> pure Blind
36+
"Buried" -> pure Buried
37+
_ -> fail $ "Bad Drill.Via: " <> unpack field

0 commit comments

Comments
 (0)