{-| GCode generation GCode generation functions & shortcuts -} module Data.GCode.Generate where import Data.GCode.Types import Data.GCode.RS274 import Data.GCode.Utils -- |Generate G Code g :: Code g = cls G emptyCode -- |Generate M Code m :: Code m = cls M emptyCode -- |Generate S (set spindle feedrate) Code s :: Code s = emptyCode & cls SStandalone -- |Set GCode number (<#>) :: Code -> Int -> Code (<#>) a n = num n a -- |Set GCode feedrate (F parameter) feed :: Double -> Code -> Code feed = param F -- |Set `x` axis target x :: Double -> Code -> Code x = axis X -- |Set `y` axis target y :: Double -> Code -> Code y = axis Y -- |Set `z` axis target z :: Double -> Code -> Code z = axis Z -- |Set `x`, `y` coordinates for this Code xy :: Double -> Double -> Code -> Code xy xVal yVal = x xVal . y yVal -- |Set `x`, `y` and `z` coordinates xyz :: Double -> Double -> Double -> Code -> Code xyz xVal yVal zVal = x xVal . y yVal . z zVal -- |Set G0 and `x`, `y` coordinates movexy :: Double -> Double -> Code movexy xVal yVal = move & xy xVal yVal -- |Set `i`, `j` parameters for this Code ij :: Double -> Double -> Code -> Code ij iVal jVal = param I iVal . param J jVal arc :: Code arc = arcCW -- |Generate points on a rectangle rectangle :: (Num a, Num b) => a -> b -> [(a, b)] rectangle xv yv = [(0, 0), (xv, 0), (xv, yv), (0, yv), (0,0)] -- |Rotate X/Y coordinates by angle `by` rot :: Floating b => b -> b -> b -> (b, b) rot by xv yv = (xv * (cos by) - yv * (sin by), yv * (cos by) + xv * (sin by)) -- |Generate a list of points laying on a circle with radius `r`, divides circle in `steps` number of points circle :: (Floating b, Enum b) => b -> b -> [(b, b)] circle r steps = map (\step -> rot (step * 2*pi / steps) (r/2) 0) [1..steps] -- |As `circle` with rotated by `rin` circle' :: (Floating b, Enum b) => b -> b -> b -> [(b, b)] circle' rin r steps = map (\step -> rot (rin + step * 2*pi / steps) (r/2) 0) [1..steps] -- |As `circle` but origin is the same as end point closedCircle :: (Floating a, Enum a) => a -> a -> [(a, a)] closedCircle r steps = map (\step -> rot (step * 2*pi / steps) (r/2) 0) [1..(steps+1)] -- |Join list of GCodes with travel moves inbetween travelCat :: Code -> Code -> [GCode] -> [Code] travelCat up down (block:rest) = (travel up down block) ++ (travelCat up down rest) travelCat _ _ [] = [] -- |Join list of drilling GCodes with travel moves inbetween travelCatDrill :: Code -> [GCode] -> [Code] travelCatDrill up (block:rest) = (travelDrills up block) ++ (travelCatDrill up rest) travelCatDrill _ [] = [] -- |Prepend codes with tool up command, rapid move to block start and tool down command -- -- Prepends `up` GCode representing tool moving up before -- rapid move followed by `down` command to move tool down again. travel :: Code -> Code -> GCode -> GCode travel up down (c:rest) = [up, asRapidXY c, down, c] ++ rest travel _ _ [] = [] -- |Prepend drilling codes with tool up command and rapid moves -- -- Prepends `up` GCode representing tool moving up before -- rapid move to start of this block travelDrills :: Code -> GCode -> GCode travelDrills up block = travel up emptyCode block -- |Take X and Y coordinates of this code -- and turn it into rapid move asRapidXY :: Code -> Code asRapidXY c@Code{} = case getAxes [X,Y] c of [Just xv, Just yv] -> rapid & xy xv yv _ -> c asRapidXY c = c