chiark / gitweb /
Add back the ultimaker platform, and made the platform mesh simpler.
[cura.git] / Cura / slice / cura_sf / skeinforge_application / skeinforge_plugins / craft_plugins / export_plugins / binary_16_byte.py
1 """
2 This page is in the table of contents.
3 Binary 16 byte is an export plugin to convert gcode into 16 byte binary segments.
4
5 An export plugin is a script in the export_plugins folder which has the getOutput function, the globalIsReplaceable variable and if it's output is not replaceable, the writeOutput function.  It is meant to be run from the export tool.  To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name.
6
7 The getOutput function of this script takes a gcode text and returns that text converted into 16 byte segments.  The writeOutput function of this script takes a gcode text and writes that in a binary format converted into 16 byte segments.
8
9 This plugin is just a starter to make a real binary converter.
10
11 ==Settings==
12 ===Feed Rate Step Length===
13 Default is 0.1 millimeters/second.
14
15 Defines the feed rate step length.
16
17 ===File Extension===
18 Default is bin.
19
20 Defines the file extension suffix.
21
22 ===Offset===
23 ====X Offset====
24 Default is zero.
25
26 Defines the X Offset.
27
28 ====Y Offset====
29 Default is zero.
30
31 Defines the Y Offset.
32
33 ====Z Offset====
34 Default is zero.
35
36 Defines the Z Offset.
37
38 ===Step Length===
39 ====X Step Length====
40 Default is 0.1 millimeters.
41
42 Defines the X axis step length.
43
44 ====Y Step Length====
45 Default is 0.1 millimeters.
46
47 Defines the Y axis step length.
48
49 ====Z Step Length====
50 Default is 0.01 millimeters.
51
52 Defines the Z axis step length.
53
54 ==Record structure==
55 BinArray(0) = AscW(Inst_Code_Letter)
56 BinArray(1) = cInst_Code
57
58 X Data
59 sInt32_to_Hbytes(iXdim_1)
60 BinArray(2) = lsb 'short lsb
61 BinArray(3) = msb 'short msb
62
63 Y Data
64 sInt32_to_Hbytes(iYdim_2)
65 BinArray(4) = lsb 'short lsb
66 BinArray(5) = msb 'short msb
67
68 Z Data
69 sInt32_to_Hbytes(iZdim_3)
70 BinArray(6) = lsb 'short lsb
71 BinArray(7) = msb 'short msb
72
73 I Data
74 sInt32_to_Hbytes(iIdim_4)
75 BinArray(8) = lsb 'short lsb
76 BinArray(9) = msb 'short msb
77
78 J Data
79 sInt32_to_Hbytes(iJdim_5)
80 BinArray(10) = lsb 'short lsb
81 BinArray(11) = msb 'short msb
82
83 BinArray(12) = FP_Char
84 sInt32_to_Hbytes(iFP_Num)
85 BinArray(13) = lsb 'short lsb
86
87 BinArray(14) = bActiveFlags
88
89 BinArray(15) = AscW("#")End of record filler
90
91 Byte 14 is worth a few extra notes, this byte is used to define which of the axes are active, its used to get round the problem of say a line of code with no mention of z. This would be put into the file as z = 0 as the space for this data is reserved, if we did nothing, this would instruct the machine to go to z = 0. If we use the active flag to define the z axis as inactive the z = 0 is ignored and the value set to the last saved value of z, i.e it does not move.  If the z data is actually set to z = 0 then the axis would be set to active and the move takes place.
92
93 """
94
95 from __future__ import absolute_import
96
97 from fabmetheus_utilities import archive
98 from fabmetheus_utilities import gcodec
99 from fabmetheus_utilities import settings
100 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
101 from skeinforge_application.skeinforge_utilities import skeinforge_profile
102 from struct import Struct
103 import cStringIO
104 import sys
105
106
107 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
108 __date__ = '$Date: 2008/21/04 $'
109 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
110
111
112 # This is true if the output is text and false if it is binary."
113 globalIsReplaceable = False
114
115
116 def getIntegerFlagFromCharacterSplitLine(character, splitLine):
117         "Get the integer flag after the first occurence of the character in the split line."
118         lineFromCharacter = gcodec.getStringFromCharacterSplitLine(character, splitLine)
119         if lineFromCharacter == None:
120                 return 0
121         return 1
122
123 def getIntegerFromCharacterLengthLineOffset( character, offset, splitLine, stepLength ):
124         "Get the integer after the first occurence of the character in the split line."
125         lineFromCharacter = gcodec.getStringFromCharacterSplitLine(character, splitLine)
126         if lineFromCharacter == None:
127                 return 0
128         floatValue = ( float( lineFromCharacter ) + offset ) / stepLength
129         return int( round( floatValue ) )
130
131 def getNewRepository():
132         'Get new repository.'
133         return Binary16ByteRepository()
134
135 def getOutput( gcodeText, binary16ByteRepository = None ):
136         'Get the exported version of a gcode file.'
137         if gcodeText == '':
138                 return ''
139         if binary16ByteRepository == None:
140                 binary16ByteRepository = Binary16ByteRepository()
141                 settings.getReadRepository( binary16ByteRepository )
142         return Binary16ByteSkein().getCraftedGcode( gcodeText, binary16ByteRepository )
143
144 def writeOutput( fileName, gcodeText = ''):
145         "Write the exported version of a gcode file."
146         binary16ByteRepository = Binary16ByteRepository()
147         settings.getReadRepository( binary16ByteRepository )
148         gcodeText = gcodec.getGcodeFileText(fileName, gcodeText)
149         skeinOutput = getOutput( gcodeText, binary16ByteRepository )
150         suffixFileName = fileName[ : fileName.rfind('.') ] + '.' + binary16ByteRepository.fileExtension.value
151         archive.writeFileText( suffixFileName, skeinOutput )
152         print('The converted file is saved as ' + archive.getSummarizedFileName(suffixFileName) )
153
154
155 class Binary16ByteRepository:
156         "A class to handle the export settings."
157         def __init__(self):
158                 "Set the default settings, execute title & settings fileName."
159                 #Set the default settings.
160                 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.export_plugins.binary_16_byte.html', self)
161                 self.fileNameInput = settings.FileNameInput().getFromFileName( [ ('Gcode text files', '*.gcode') ], 'Open File to be Converted to Binary 16 Byte', self, '')
162                 self.feedRateStepLength = settings.FloatSpin().getFromValue( 0.0, 'Feed Rate Step Length (millimeters/second)', self, 1.0, 0.1 )
163                 self.fileExtension = settings.StringSetting().getFromValue('File Extension:', self, 'bin')
164                 settings.LabelDisplay().getFromName('Offset:', self )
165                 self.xOffset = settings.FloatSpin().getFromValue( - 100.0, 'X Offset (millimeters)', self, 100.0, 0.0 )
166                 self.yOffset = settings.FloatSpin().getFromValue( -100.0, 'Y Offset (millimeters)', self, 100.0, 0.0 )
167                 self.zOffset = settings.FloatSpin().getFromValue( - 10.0, 'Z Offset (millimeters)', self, 10.0, 0.0 )
168                 settings.LabelDisplay().getFromName('Step Length:', self )
169                 self.xStepLength = settings.FloatSpin().getFromValue( 0.0, 'X Step Length (millimeters)', self, 1.0, 0.1 )
170                 self.yStepLength = settings.FloatSpin().getFromValue( 0.0, 'Y Step Length (millimeters)', self, 1.0, 0.1 )
171                 self.zStepLength = settings.FloatSpin().getFromValue( 0.0, 'Z Step Length (millimeters)', self, 0.2, 0.01 )
172                 self.executeTitle = 'Convert to Binary 16 Byte'
173
174         def execute(self):
175                 "Convert to binary 16 byte button has been clicked."
176                 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode( self.fileNameInput.value, ['.gcode'], self.fileNameInput.wasCancelled )
177                 for fileName in fileNames:
178                         writeOutput(fileName)
179
180
181 class Binary16ByteSkein:
182         "A class to convert gcode into 16 byte binary segments."
183         def __init__(self):
184                 self.output = cStringIO.StringIO()
185
186         def getCraftedGcode( self, gcodeText, binary16ByteRepository ):
187                 "Parse gcode text and store the gcode."
188                 self.binary16ByteRepository = binary16ByteRepository
189                 lines = archive.getTextLines(gcodeText)
190                 for line in lines:
191                         self.parseLine(line)
192                 return self.output.getvalue()
193
194         def parseLine(self, line):
195                 "Parse a gcode line."
196                 binary16ByteRepository = self.binary16ByteRepository
197                 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
198                 firstWord = gcodec.getFirstWord(splitLine)
199                 if len(firstWord) < 1:
200                         return
201                 firstLetter = firstWord[0]
202                 if firstLetter == '(':
203                         return
204                 feedRateInteger = getIntegerFromCharacterLengthLineOffset('F', 0.0, splitLine, binary16ByteRepository.feedRateStepLength.value )
205                 iInteger = getIntegerFromCharacterLengthLineOffset('I', 0.0, splitLine, binary16ByteRepository.xStepLength.value )
206                 jInteger = getIntegerFromCharacterLengthLineOffset('J', 0.0, splitLine, binary16ByteRepository.yStepLength.value )
207                 xInteger = getIntegerFromCharacterLengthLineOffset('X', binary16ByteRepository.xOffset.value, splitLine, binary16ByteRepository.xStepLength.value )
208                 yInteger = getIntegerFromCharacterLengthLineOffset('Y', binary16ByteRepository.yOffset.value, splitLine, binary16ByteRepository.yStepLength.value )
209                 zInteger = getIntegerFromCharacterLengthLineOffset('Z', binary16ByteRepository.zOffset.value, splitLine, binary16ByteRepository.zStepLength.value )
210                 sixteenByteStruct = Struct('cBhhhhhhBc')
211                 flagInteger = getIntegerFlagFromCharacterSplitLine('X', splitLine )
212                 flagInteger += 2 * getIntegerFlagFromCharacterSplitLine('Y', splitLine )
213                 flagInteger += 4 * getIntegerFlagFromCharacterSplitLine('Z', splitLine )
214                 flagInteger += 8 * getIntegerFlagFromCharacterSplitLine('I', splitLine )
215                 flagInteger += 16 * getIntegerFlagFromCharacterSplitLine('J', splitLine )
216                 flagInteger += 32 * getIntegerFlagFromCharacterSplitLine('F', splitLine )
217                 packedString = sixteenByteStruct.pack( firstLetter, int( firstWord[1 :] ), xInteger, yInteger, zInteger, iInteger, jInteger, feedRateInteger, flagInteger, '#')
218                 self.output.write( packedString )
219
220
221 def main():
222         "Display the export dialog."
223         if len(sys.argv) > 1:
224                 writeOutput(' '.join(sys.argv[1 :]))
225         else:
226                 settings.startMainLoopFromConstructor(getNewRepository())
227
228 if __name__ == "__main__":
229         main()