From 5adc95b6e19c4828430743c3eb187bc55d0cf638 Mon Sep 17 00:00:00 2001 From: Mena Date: Sun, 7 Jul 2024 13:16:40 -0400 Subject: [PATCH 1/2] [SC64][HW] Update design of `sc64_shell_button_b3fs-105x_with_end_stop.step` (#74) button redesign to stop rattle --- ..._shell_button_b3fs-105x_with_end_stop.step | 2340 ++++++++++------- 1 file changed, 1317 insertions(+), 1023 deletions(-) diff --git a/hw/shell/button/sc64_shell_button_b3fs-105x_with_end_stop.step b/hw/shell/button/sc64_shell_button_b3fs-105x_with_end_stop.step index 6c2f52b..02e00b6 100644 --- a/hw/shell/button/sc64_shell_button_b3fs-105x_with_end_stop.step +++ b/hw/shell/button/sc64_shell_button_b3fs-105x_with_end_stop.step @@ -9,12 +9,12 @@ FILE_DESCRIPTION( /* implementation_level */ '2;1'); FILE_NAME( -/* name */ 'sc64_button with end stop.step', -/* time_stamp */ '2024-02-29T20:34:23-06:00', +/* name */ 'button v1.step', +/* time_stamp */ '2024-07-07T13:11:13-04:00', /* author */ (''), /* organization */ (''), /* preprocessor_version */ 'ST-DEVELOPER v20', -/* originating_system */ 'Autodesk Translation Framework v12.14.0.127', +/* originating_system */ 'Autodesk Translation Framework v13.14.0.145', /* authorisation */ ''); @@ -22,1052 +22,1346 @@ FILE_SCHEMA (('AUTOMOTIVE_DESIGN { 1 0 10303 214 3 1 1 }')); ENDSEC; DATA; -#10=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#13),#932); -#11=SHAPE_REPRESENTATION_RELATIONSHIP('SRR','None',#938,#12); -#12=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#14),#931); -#13=STYLED_ITEM('',(#950),#14); -#14=MANIFOLD_SOLID_BREP('ButtonCap',#527); -#15=ELLIPSE('',#564,57.3219678278922,3.); -#16=ELLIPSE('',#566,57.3219678278922,3.); -#17=ELLIPSE('',#567,57.3219678278922,3.); -#18=ELLIPSE('',#569,57.3219678278922,3.); -#19=CYLINDRICAL_SURFACE('',#563,3.); -#20=B_SPLINE_CURVE_WITH_KNOTS('',3,(#822,#823,#824,#825,#826,#827,#828, -#829,#830,#831),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,4),(0.152690815970772,0.170769832092777, -0.189403419448823,0.208859780179844,0.228997077857732),.UNSPECIFIED.); -#21=B_SPLINE_CURVE_WITH_KNOTS('',3,(#834,#835,#836,#837,#838,#839,#840, -#841,#842,#843),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,4),(0.0765657026251719,0.0967030003030594, -0.11615936103408,0.134792948390126,0.152871964512132),.UNSPECIFIED.); -#22=B_SPLINE_CURVE_WITH_KNOTS('',3,(#850,#851,#852,#853,#854,#855,#856, -#857,#858,#859),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,4),(0.152690815970771,0.170769832092777, -0.189403419448823,0.208859780179844,0.228997077857731),.UNSPECIFIED.); -#23=B_SPLINE_CURVE_WITH_KNOTS('',3,(#861,#862,#863,#864,#865,#866,#867, -#868,#869,#870),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,4),(0.0765657026251716,0.0967030003030594, -0.11615936103408,0.134792948390127,0.152871964512132),.UNSPECIFIED.); -#24=TOROIDAL_SURFACE('',#550,3.5,0.5); -#25=TOROIDAL_SURFACE('',#555,3.5,0.5); -#26=TOROIDAL_SURFACE('',#558,2.5,0.5); -#27=CONICAL_SURFACE('',#534,4.,0.0872664625997165); -#28=CONICAL_SURFACE('',#547,4.,0.0872664625997165); -#29=CIRCLE('',#531,3.5); -#30=CIRCLE('',#533,3.5); -#31=CIRCLE('',#535,4.); -#32=CIRCLE('',#536,4.06561649764444); -#33=CIRCLE('',#539,3.5); -#34=CIRCLE('',#542,3.5); -#35=CIRCLE('',#544,3.5); -#36=CIRCLE('',#546,4.06561649764444); -#37=CIRCLE('',#548,4.); -#38=CIRCLE('',#551,3.5); -#39=CIRCLE('',#552,3.); -#40=CIRCLE('',#553,3.); -#41=CIRCLE('',#556,3.); -#42=CIRCLE('',#559,2.5); -#43=CIRCLE('',#560,0.5); -#44=CIRCLE('',#561,3.); -#45=CIRCLE('',#565,3.); -#46=CIRCLE('',#568,3.); -#47=FACE_OUTER_BOUND('',#77,.T.); -#48=FACE_OUTER_BOUND('',#78,.T.); -#49=FACE_OUTER_BOUND('',#79,.T.); -#50=FACE_OUTER_BOUND('',#80,.T.); -#51=FACE_OUTER_BOUND('',#81,.T.); -#52=FACE_OUTER_BOUND('',#82,.T.); -#53=FACE_OUTER_BOUND('',#83,.T.); -#54=FACE_OUTER_BOUND('',#84,.T.); -#55=FACE_OUTER_BOUND('',#85,.T.); -#56=FACE_OUTER_BOUND('',#86,.T.); -#57=FACE_OUTER_BOUND('',#87,.T.); -#58=FACE_OUTER_BOUND('',#88,.T.); -#59=FACE_OUTER_BOUND('',#89,.T.); -#60=FACE_OUTER_BOUND('',#90,.T.); -#61=FACE_OUTER_BOUND('',#91,.T.); -#62=FACE_OUTER_BOUND('',#92,.T.); -#63=FACE_OUTER_BOUND('',#93,.T.); -#64=FACE_OUTER_BOUND('',#94,.T.); -#65=FACE_OUTER_BOUND('',#95,.T.); -#66=FACE_OUTER_BOUND('',#96,.T.); -#67=FACE_OUTER_BOUND('',#97,.T.); -#68=FACE_OUTER_BOUND('',#98,.T.); -#69=FACE_OUTER_BOUND('',#99,.T.); -#70=FACE_OUTER_BOUND('',#100,.T.); -#71=FACE_OUTER_BOUND('',#101,.T.); -#72=FACE_OUTER_BOUND('',#102,.T.); -#73=FACE_OUTER_BOUND('',#103,.T.); -#74=FACE_OUTER_BOUND('',#104,.T.); -#75=FACE_OUTER_BOUND('',#105,.T.); -#76=FACE_OUTER_BOUND('',#106,.T.); -#77=EDGE_LOOP('',(#323,#324,#325,#326,#327,#328,#329,#330)); -#78=EDGE_LOOP('',(#331,#332,#333,#334)); -#79=EDGE_LOOP('',(#335,#336,#337,#338)); -#80=EDGE_LOOP('',(#339,#340,#341,#342)); -#81=EDGE_LOOP('',(#343,#344,#345,#346)); -#82=EDGE_LOOP('',(#347,#348,#349,#350)); -#83=EDGE_LOOP('',(#351,#352,#353,#354,#355,#356,#357,#358)); -#84=EDGE_LOOP('',(#359,#360,#361,#362)); -#85=EDGE_LOOP('',(#363,#364,#365,#366)); -#86=EDGE_LOOP('',(#367,#368)); -#87=EDGE_LOOP('',(#369,#370,#371,#372)); -#88=EDGE_LOOP('',(#373,#374,#375,#376)); -#89=EDGE_LOOP('',(#377,#378,#379,#380,#381,#382,#383)); -#90=EDGE_LOOP('',(#384,#385,#386,#387)); -#91=EDGE_LOOP('',(#388,#389,#390,#391,#392,#393)); -#92=EDGE_LOOP('',(#394,#395)); -#93=EDGE_LOOP('',(#396,#397,#398,#399)); -#94=EDGE_LOOP('',(#400)); -#95=EDGE_LOOP('',(#401,#402,#403,#404,#405,#406,#407,#408,#409,#410,#411, -#412)); -#96=EDGE_LOOP('',(#413,#414,#415,#416)); -#97=EDGE_LOOP('',(#417,#418,#419,#420,#421,#422,#423,#424,#425,#426)); -#98=EDGE_LOOP('',(#427,#428,#429,#430)); -#99=EDGE_LOOP('',(#431,#432,#433,#434,#435,#436,#437,#438,#439,#440)); -#100=EDGE_LOOP('',(#441,#442,#443,#444)); -#101=EDGE_LOOP('',(#445,#446,#447,#448,#449)); -#102=EDGE_LOOP('',(#450,#451,#452,#453,#454)); -#103=EDGE_LOOP('',(#455,#456,#457,#458)); -#104=EDGE_LOOP('',(#459,#460,#461,#462,#463)); -#105=EDGE_LOOP('',(#464,#465,#466,#467,#468)); -#106=EDGE_LOOP('',(#469,#470,#471,#472)); -#107=LINE('',#740,#152); -#108=LINE('',#746,#153); -#109=LINE('',#748,#154); -#110=LINE('',#750,#155); -#111=LINE('',#752,#156); -#112=LINE('',#753,#157); -#113=LINE('',#758,#158); -#114=LINE('',#759,#159); -#115=LINE('',#764,#160); -#116=LINE('',#765,#161); -#117=LINE('',#771,#162); -#118=LINE('',#773,#163); -#119=LINE('',#774,#164); -#120=LINE('',#784,#165); -#121=LINE('',#786,#166); -#122=LINE('',#788,#167); -#123=LINE('',#790,#168); -#124=LINE('',#792,#169); -#125=LINE('',#797,#170); -#126=LINE('',#802,#171); -#127=LINE('',#803,#172); -#128=LINE('',#808,#173); -#129=LINE('',#809,#174); -#130=LINE('',#816,#175); -#131=LINE('',#818,#176); -#132=LINE('',#819,#177); -#133=LINE('',#881,#178); -#134=LINE('',#895,#179); -#135=LINE('',#897,#180); -#136=LINE('',#899,#181); -#137=LINE('',#900,#182); -#138=LINE('',#903,#183); -#139=LINE('',#904,#184); -#140=LINE('',#905,#185); -#141=LINE('',#907,#186); -#142=LINE('',#908,#187); -#143=LINE('',#910,#188); -#144=LINE('',#913,#189); -#145=LINE('',#915,#190); -#146=LINE('',#916,#191); -#147=LINE('',#917,#192); -#148=LINE('',#920,#193); -#149=LINE('',#922,#194); -#150=LINE('',#924,#195); -#151=LINE('',#927,#196); -#152=VECTOR('',#585,10.); -#153=VECTOR('',#586,10.); -#154=VECTOR('',#587,10.); -#155=VECTOR('',#588,10.); -#156=VECTOR('',#589,10.); -#157=VECTOR('',#590,10.); -#158=VECTOR('',#595,10.); -#159=VECTOR('',#596,10.); -#160=VECTOR('',#601,10.); -#161=VECTOR('',#602,10.); -#162=VECTOR('',#611,10.); -#163=VECTOR('',#612,10.); -#164=VECTOR('',#613,10.); -#165=VECTOR('',#620,10.); -#166=VECTOR('',#621,10.); -#167=VECTOR('',#622,10.); -#168=VECTOR('',#623,10.); -#169=VECTOR('',#624,10.); -#170=VECTOR('',#625,10.); -#171=VECTOR('',#630,10.); -#172=VECTOR('',#631,10.); -#173=VECTOR('',#636,10.); -#174=VECTOR('',#637,10.); -#175=VECTOR('',#648,10.); -#176=VECTOR('',#649,10.); -#177=VECTOR('',#650,10.); -#178=VECTOR('',#679,3.); -#179=VECTOR('',#694,10.); -#180=VECTOR('',#695,10.); -#181=VECTOR('',#696,10.); -#182=VECTOR('',#697,10.); -#183=VECTOR('',#700,10.); -#184=VECTOR('',#701,10.); -#185=VECTOR('',#702,10.); -#186=VECTOR('',#703,10.); -#187=VECTOR('',#704,10.); -#188=VECTOR('',#707,10.); -#189=VECTOR('',#710,10.); -#190=VECTOR('',#711,10.); -#191=VECTOR('',#712,10.); -#192=VECTOR('',#713,10.); -#193=VECTOR('',#718,10.); -#194=VECTOR('',#721,10.); -#195=VECTOR('',#724,10.); -#196=VECTOR('',#729,10.); -#197=( -BOUNDED_CURVE() -B_SPLINE_CURVE(2,(#736,#737,#738),.UNSPECIFIED.,.F.,.F.) -B_SPLINE_CURVE_WITH_KNOTS((3,3),(178.46477889567,178.853392228292), - .UNSPECIFIED.) -CURVE() -GEOMETRIC_REPRESENTATION_ITEM() -RATIONAL_B_SPLINE_CURVE((13.687831583365,13.6241212154299,13.5600732229849)) -REPRESENTATION_ITEM('') +#10=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#17),#1253); +#11=ITEM_DEFINED_TRANSFORMATION($,$,#760,#822); +#12=( +REPRESENTATION_RELATIONSHIP($,$,#1264,#1263) +REPRESENTATION_RELATIONSHIP_WITH_TRANSFORMATION(#11) +SHAPE_REPRESENTATION_RELATIONSHIP() ); -#198=( -BOUNDED_CURVE() -B_SPLINE_CURVE(2,(#742,#743,#744),.UNSPECIFIED.,.F.,.F.) -B_SPLINE_CURVE_WITH_KNOTS((3,3),(31.4120598130892,31.8006731457097), - .UNSPECIFIED.) -CURVE() -GEOMETRIC_REPRESENTATION_ITEM() -RATIONAL_B_SPLINE_CURVE((13.5600732229849,13.6241212154297,13.6878315833646)) -REPRESENTATION_ITEM('') +#13=CONTEXT_DEPENDENT_SHAPE_REPRESENTATION(#12,#1262); +#14=NEXT_ASSEMBLY_USAGE_OCCURRENCE('SC64_SHELL_BUTTON-20240702:1', +'SC64_SHELL_BUTTON-20240702:1','SC64_SHELL_BUTTON-20240702:1',#1266,#1267, +'SC64_SHELL_BUTTON-20240702:1'); +#15=SHAPE_REPRESENTATION_RELATIONSHIP('SRR','None',#1264,#16); +#16=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#18),#1252); +#17=STYLED_ITEM('',(#1278),#18); +#18=MANIFOLD_SOLID_BREP('Body1',#746); +#19=TOROIDAL_SURFACE('',#818,2.8,0.2); +#20=FACE_BOUND('',#91,.T.); +#21=FACE_BOUND('',#94,.T.); +#22=PLANE('',#764); +#23=PLANE('',#768); +#24=PLANE('',#773); +#25=PLANE('',#777); +#26=PLANE('',#779); +#27=PLANE('',#781); +#28=PLANE('',#782); +#29=PLANE('',#783); +#30=PLANE('',#786); +#31=PLANE('',#790); +#32=PLANE('',#791); +#33=PLANE('',#792); +#34=PLANE('',#793); +#35=PLANE('',#796); +#36=PLANE('',#800); +#37=PLANE('',#801); +#38=PLANE('',#802); +#39=PLANE('',#803); +#40=PLANE('',#806); +#41=PLANE('',#810); +#42=PLANE('',#811); +#43=PLANE('',#812); +#44=PLANE('',#813); +#45=PLANE('',#814); +#46=PLANE('',#815); +#47=PLANE('',#816); +#48=PLANE('',#817); +#49=PLANE('',#821); +#50=FACE_OUTER_BOUND('',#89,.T.); +#51=FACE_OUTER_BOUND('',#90,.T.); +#52=FACE_OUTER_BOUND('',#92,.T.); +#53=FACE_OUTER_BOUND('',#93,.T.); +#54=FACE_OUTER_BOUND('',#95,.T.); +#55=FACE_OUTER_BOUND('',#96,.T.); +#56=FACE_OUTER_BOUND('',#97,.T.); +#57=FACE_OUTER_BOUND('',#98,.T.); +#58=FACE_OUTER_BOUND('',#99,.T.); +#59=FACE_OUTER_BOUND('',#100,.T.); +#60=FACE_OUTER_BOUND('',#101,.T.); +#61=FACE_OUTER_BOUND('',#102,.T.); +#62=FACE_OUTER_BOUND('',#103,.T.); +#63=FACE_OUTER_BOUND('',#104,.T.); +#64=FACE_OUTER_BOUND('',#105,.T.); +#65=FACE_OUTER_BOUND('',#106,.T.); +#66=FACE_OUTER_BOUND('',#107,.T.); +#67=FACE_OUTER_BOUND('',#108,.T.); +#68=FACE_OUTER_BOUND('',#109,.T.); +#69=FACE_OUTER_BOUND('',#110,.T.); +#70=FACE_OUTER_BOUND('',#111,.T.); +#71=FACE_OUTER_BOUND('',#112,.T.); +#72=FACE_OUTER_BOUND('',#113,.T.); +#73=FACE_OUTER_BOUND('',#114,.T.); +#74=FACE_OUTER_BOUND('',#115,.T.); +#75=FACE_OUTER_BOUND('',#116,.T.); +#76=FACE_OUTER_BOUND('',#117,.T.); +#77=FACE_OUTER_BOUND('',#118,.T.); +#78=FACE_OUTER_BOUND('',#119,.T.); +#79=FACE_OUTER_BOUND('',#120,.T.); +#80=FACE_OUTER_BOUND('',#121,.T.); +#81=FACE_OUTER_BOUND('',#122,.T.); +#82=FACE_OUTER_BOUND('',#123,.T.); +#83=FACE_OUTER_BOUND('',#124,.T.); +#84=FACE_OUTER_BOUND('',#125,.T.); +#85=FACE_OUTER_BOUND('',#126,.T.); +#86=FACE_OUTER_BOUND('',#127,.T.); +#87=FACE_OUTER_BOUND('',#128,.T.); +#88=FACE_OUTER_BOUND('',#129,.T.); +#89=EDGE_LOOP('',(#489,#490,#491,#492)); +#90=EDGE_LOOP('',(#493)); +#91=EDGE_LOOP('',(#494)); +#92=EDGE_LOOP('',(#495,#496,#497,#498)); +#93=EDGE_LOOP('',(#499)); +#94=EDGE_LOOP('',(#500,#501,#502,#503,#504,#505,#506,#507,#508,#509,#510, +#511,#512,#513,#514,#515)); +#95=EDGE_LOOP('',(#516,#517,#518,#519,#520,#521,#522,#523,#524)); +#96=EDGE_LOOP('',(#525,#526,#527,#528)); +#97=EDGE_LOOP('',(#529,#530,#531,#532)); +#98=EDGE_LOOP('',(#533,#534,#535,#536,#537,#538,#539,#540,#541)); +#99=EDGE_LOOP('',(#542,#543,#544,#545)); +#100=EDGE_LOOP('',(#546,#547,#548)); +#101=EDGE_LOOP('',(#549,#550,#551,#552,#553,#554,#555,#556,#557,#558,#559, +#560)); +#102=EDGE_LOOP('',(#561,#562,#563,#564,#565,#566,#567,#568,#569)); +#103=EDGE_LOOP('',(#570,#571,#572,#573)); +#104=EDGE_LOOP('',(#574,#575,#576,#577,#578,#579,#580,#581,#582)); +#105=EDGE_LOOP('',(#583,#584,#585,#586)); +#106=EDGE_LOOP('',(#587,#588,#589,#590)); +#107=EDGE_LOOP('',(#591,#592,#593)); +#108=EDGE_LOOP('',(#594,#595,#596,#597)); +#109=EDGE_LOOP('',(#598,#599,#600,#601,#602,#603,#604,#605,#606)); +#110=EDGE_LOOP('',(#607,#608,#609,#610)); +#111=EDGE_LOOP('',(#611,#612,#613,#614,#615,#616,#617,#618,#619)); +#112=EDGE_LOOP('',(#620,#621,#622,#623)); +#113=EDGE_LOOP('',(#624,#625,#626,#627)); +#114=EDGE_LOOP('',(#628,#629,#630)); +#115=EDGE_LOOP('',(#631,#632,#633,#634)); +#116=EDGE_LOOP('',(#635,#636,#637,#638,#639,#640,#641,#642,#643)); +#117=EDGE_LOOP('',(#644,#645,#646,#647)); +#118=EDGE_LOOP('',(#648,#649,#650,#651,#652,#653,#654,#655,#656)); +#119=EDGE_LOOP('',(#657,#658,#659,#660)); +#120=EDGE_LOOP('',(#661,#662,#663,#664)); +#121=EDGE_LOOP('',(#665,#666,#667)); +#122=EDGE_LOOP('',(#668,#669,#670,#671)); +#123=EDGE_LOOP('',(#672,#673,#674,#675)); +#124=EDGE_LOOP('',(#676,#677,#678,#679)); +#125=EDGE_LOOP('',(#680,#681,#682,#683)); +#126=EDGE_LOOP('',(#684,#685,#686,#687)); +#127=EDGE_LOOP('',(#688,#689,#690,#691)); +#128=EDGE_LOOP('',(#692,#693,#694,#695)); +#129=EDGE_LOOP('',(#696)); +#130=LINE('',#1039,#212); +#131=LINE('',#1047,#213); +#132=LINE('',#1051,#214); +#133=LINE('',#1053,#215); +#134=LINE('',#1055,#216); +#135=LINE('',#1059,#217); +#136=LINE('',#1061,#218); +#137=LINE('',#1063,#219); +#138=LINE('',#1067,#220); +#139=LINE('',#1069,#221); +#140=LINE('',#1071,#222); +#141=LINE('',#1075,#223); +#142=LINE('',#1077,#224); +#143=LINE('',#1079,#225); +#144=LINE('',#1084,#226); +#145=LINE('',#1086,#227); +#146=LINE('',#1088,#228); +#147=LINE('',#1090,#229); +#148=LINE('',#1092,#230); +#149=LINE('',#1093,#231); +#150=LINE('',#1095,#232); +#151=LINE('',#1096,#233); +#152=LINE('',#1101,#234); +#153=LINE('',#1106,#235); +#154=LINE('',#1109,#236); +#155=LINE('',#1111,#237); +#156=LINE('',#1112,#238); +#157=LINE('',#1113,#239); +#158=LINE('',#1114,#240); +#159=LINE('',#1120,#241); +#160=LINE('',#1121,#242); +#161=LINE('',#1123,#243); +#162=LINE('',#1125,#244); +#163=LINE('',#1127,#245); +#164=LINE('',#1129,#246); +#165=LINE('',#1131,#247); +#166=LINE('',#1133,#248); +#167=LINE('',#1135,#249); +#168=LINE('',#1136,#250); +#169=LINE('',#1139,#251); +#170=LINE('',#1140,#252); +#171=LINE('',#1142,#253); +#172=LINE('',#1144,#254); +#173=LINE('',#1146,#255); +#174=LINE('',#1148,#256); +#175=LINE('',#1149,#257); +#176=LINE('',#1153,#258); +#177=LINE('',#1157,#259); +#178=LINE('',#1158,#260); +#179=LINE('',#1160,#261); +#180=LINE('',#1161,#262); +#181=LINE('',#1162,#263); +#182=LINE('',#1170,#264); +#183=LINE('',#1171,#265); +#184=LINE('',#1173,#266); +#185=LINE('',#1175,#267); +#186=LINE('',#1177,#268); +#187=LINE('',#1179,#269); +#188=LINE('',#1181,#270); +#189=LINE('',#1182,#271); +#190=LINE('',#1186,#272); +#191=LINE('',#1190,#273); +#192=LINE('',#1191,#274); +#193=LINE('',#1193,#275); +#194=LINE('',#1194,#276); +#195=LINE('',#1195,#277); +#196=LINE('',#1203,#278); +#197=LINE('',#1204,#279); +#198=LINE('',#1206,#280); +#199=LINE('',#1208,#281); +#200=LINE('',#1210,#282); +#201=LINE('',#1212,#283); +#202=LINE('',#1214,#284); +#203=LINE('',#1215,#285); +#204=LINE('',#1219,#286); +#205=LINE('',#1223,#287); +#206=LINE('',#1224,#288); +#207=LINE('',#1226,#289); +#208=LINE('',#1227,#290); +#209=LINE('',#1228,#291); +#210=LINE('',#1235,#292); +#211=LINE('',#1240,#293); +#212=VECTOR('',#831,3.); +#213=VECTOR('',#842,4.); +#214=VECTOR('',#845,1.073213749462); +#215=VECTOR('',#846,0.8); +#216=VECTOR('',#847,1.073213749462); +#217=VECTOR('',#850,1.073213749462); +#218=VECTOR('',#851,0.8); +#219=VECTOR('',#852,1.073213749462); +#220=VECTOR('',#855,1.073213749462); +#221=VECTOR('',#856,0.8); +#222=VECTOR('',#857,1.073213749462); +#223=VECTOR('',#860,1.073213749462); +#224=VECTOR('',#861,0.8); +#225=VECTOR('',#862,1.073213749462); +#226=VECTOR('',#867,3.2); +#227=VECTOR('',#868,1.559591794228); +#228=VECTOR('',#869,2.); +#229=VECTOR('',#870,0.9); +#230=VECTOR('',#871,1.9); +#231=VECTOR('',#872,0.848528137423803); +#232=VECTOR('',#873,1.3); +#233=VECTOR('',#874,1.013621955235); +#234=VECTOR('',#879,3.2); +#235=VECTOR('',#886,1.013621955235); +#236=VECTOR('',#889,0.848528137423843); +#237=VECTOR('',#890,1.9); +#238=VECTOR('',#891,0.9); +#239=VECTOR('',#892,1.559591794228); +#240=VECTOR('',#893,1.3); +#241=VECTOR('',#900,0.9); +#242=VECTOR('',#901,0.8); +#243=VECTOR('',#902,0.8); +#244=VECTOR('',#903,0.9); +#245=VECTOR('',#904,0.9); +#246=VECTOR('',#905,0.8); +#247=VECTOR('',#906,0.9); +#248=VECTOR('',#907,0.9); +#249=VECTOR('',#908,0.8); +#250=VECTOR('',#909,0.9); +#251=VECTOR('',#912,0.848528137423903); +#252=VECTOR('',#913,1.9); +#253=VECTOR('',#914,2.); +#254=VECTOR('',#915,1.559591794228); +#255=VECTOR('',#916,3.2); +#256=VECTOR('',#917,1.013621955235); +#257=VECTOR('',#918,1.3); +#258=VECTOR('',#923,1.3); +#259=VECTOR('',#926,3.2); +#260=VECTOR('',#927,1.559591794228); +#261=VECTOR('',#928,1.9); +#262=VECTOR('',#929,0.848528137423843); +#263=VECTOR('',#930,1.013621955235); +#264=VECTOR('',#943,0.848528137423843); +#265=VECTOR('',#944,0.8); +#266=VECTOR('',#947,1.9); +#267=VECTOR('',#948,2.); +#268=VECTOR('',#949,1.559591794228); +#269=VECTOR('',#950,3.2); +#270=VECTOR('',#951,1.013621955235); +#271=VECTOR('',#952,1.3); +#272=VECTOR('',#957,1.3); +#273=VECTOR('',#960,3.2); +#274=VECTOR('',#961,1.559591794228); +#275=VECTOR('',#962,1.9); +#276=VECTOR('',#963,0.848528137423843); +#277=VECTOR('',#964,1.013621955235); +#278=VECTOR('',#977,0.848528137423843); +#279=VECTOR('',#978,0.8); +#280=VECTOR('',#981,1.9); +#281=VECTOR('',#982,2.); +#282=VECTOR('',#983,1.559591794228); +#283=VECTOR('',#984,3.2); +#284=VECTOR('',#985,1.013621955235); +#285=VECTOR('',#986,1.3); +#286=VECTOR('',#991,1.3); +#287=VECTOR('',#994,3.2); +#288=VECTOR('',#995,1.559591794228); +#289=VECTOR('',#996,1.9); +#290=VECTOR('',#997,0.848528137423843); +#291=VECTOR('',#998,1.013621955235); +#292=VECTOR('',#1011,0.8); +#293=VECTOR('',#1020,0.8); +#294=CIRCLE('',#762,3.); +#295=CIRCLE('',#763,3.); +#296=CIRCLE('',#765,4.); +#297=CIRCLE('',#767,4.); +#298=CIRCLE('',#769,3.); +#299=CIRCLE('',#770,3.); +#300=CIRCLE('',#771,3.); +#301=CIRCLE('',#772,3.); +#302=CIRCLE('',#775,2.); +#303=CIRCLE('',#776,2.); +#304=CIRCLE('',#778,3.); +#305=CIRCLE('',#785,3.); +#306=CIRCLE('',#788,2.); +#307=CIRCLE('',#789,2.); +#308=CIRCLE('',#795,3.); +#309=CIRCLE('',#798,2.); +#310=CIRCLE('',#799,2.); +#311=CIRCLE('',#805,3.); +#312=CIRCLE('',#808,2.); +#313=CIRCLE('',#809,2.); +#314=CIRCLE('',#819,2.8); +#315=CIRCLE('',#820,0.2); +#316=VERTEX_POINT('',#1036); +#317=VERTEX_POINT('',#1038); +#318=VERTEX_POINT('',#1042); +#319=VERTEX_POINT('',#1045); +#320=VERTEX_POINT('',#1049); +#321=VERTEX_POINT('',#1050); +#322=VERTEX_POINT('',#1052); +#323=VERTEX_POINT('',#1054); +#324=VERTEX_POINT('',#1056); +#325=VERTEX_POINT('',#1058); +#326=VERTEX_POINT('',#1060); +#327=VERTEX_POINT('',#1062); +#328=VERTEX_POINT('',#1064); +#329=VERTEX_POINT('',#1066); +#330=VERTEX_POINT('',#1068); +#331=VERTEX_POINT('',#1070); +#332=VERTEX_POINT('',#1072); +#333=VERTEX_POINT('',#1074); +#334=VERTEX_POINT('',#1076); +#335=VERTEX_POINT('',#1078); +#336=VERTEX_POINT('',#1082); +#337=VERTEX_POINT('',#1083); +#338=VERTEX_POINT('',#1085); +#339=VERTEX_POINT('',#1087); +#340=VERTEX_POINT('',#1089); +#341=VERTEX_POINT('',#1091); +#342=VERTEX_POINT('',#1094); +#343=VERTEX_POINT('',#1098); +#344=VERTEX_POINT('',#1100); +#345=VERTEX_POINT('',#1104); +#346=VERTEX_POINT('',#1108); +#347=VERTEX_POINT('',#1110); +#348=VERTEX_POINT('',#1118); +#349=VERTEX_POINT('',#1119); +#350=VERTEX_POINT('',#1122); +#351=VERTEX_POINT('',#1124); +#352=VERTEX_POINT('',#1126); +#353=VERTEX_POINT('',#1128); +#354=VERTEX_POINT('',#1130); +#355=VERTEX_POINT('',#1132); +#356=VERTEX_POINT('',#1134); +#357=VERTEX_POINT('',#1138); +#358=VERTEX_POINT('',#1141); +#359=VERTEX_POINT('',#1143); +#360=VERTEX_POINT('',#1145); +#361=VERTEX_POINT('',#1147); +#362=VERTEX_POINT('',#1151); +#363=VERTEX_POINT('',#1155); +#364=VERTEX_POINT('',#1156); +#365=VERTEX_POINT('',#1159); +#366=VERTEX_POINT('',#1169); +#367=VERTEX_POINT('',#1174); +#368=VERTEX_POINT('',#1176); +#369=VERTEX_POINT('',#1178); +#370=VERTEX_POINT('',#1180); +#371=VERTEX_POINT('',#1184); +#372=VERTEX_POINT('',#1188); +#373=VERTEX_POINT('',#1189); +#374=VERTEX_POINT('',#1192); +#375=VERTEX_POINT('',#1202); +#376=VERTEX_POINT('',#1207); +#377=VERTEX_POINT('',#1209); +#378=VERTEX_POINT('',#1211); +#379=VERTEX_POINT('',#1213); +#380=VERTEX_POINT('',#1217); +#381=VERTEX_POINT('',#1221); +#382=VERTEX_POINT('',#1222); +#383=VERTEX_POINT('',#1225); +#384=VERTEX_POINT('',#1243); +#385=EDGE_CURVE('',#316,#316,#294,.T.); +#386=EDGE_CURVE('',#316,#317,#130,.T.); +#387=EDGE_CURVE('',#317,#317,#295,.T.); +#388=EDGE_CURVE('',#318,#318,#296,.T.); +#389=EDGE_CURVE('',#319,#319,#297,.T.); +#390=EDGE_CURVE('',#319,#318,#131,.T.); +#391=EDGE_CURVE('',#320,#321,#132,.T.); +#392=EDGE_CURVE('',#322,#320,#133,.T.); +#393=EDGE_CURVE('',#323,#322,#134,.T.); +#394=EDGE_CURVE('',#324,#323,#298,.T.); +#395=EDGE_CURVE('',#325,#324,#135,.T.); +#396=EDGE_CURVE('',#326,#325,#136,.T.); +#397=EDGE_CURVE('',#327,#326,#137,.T.); +#398=EDGE_CURVE('',#328,#327,#299,.T.); +#399=EDGE_CURVE('',#329,#328,#138,.T.); +#400=EDGE_CURVE('',#330,#329,#139,.T.); +#401=EDGE_CURVE('',#331,#330,#140,.T.); +#402=EDGE_CURVE('',#332,#331,#300,.T.); +#403=EDGE_CURVE('',#333,#332,#141,.T.); +#404=EDGE_CURVE('',#334,#333,#142,.T.); +#405=EDGE_CURVE('',#335,#334,#143,.T.); +#406=EDGE_CURVE('',#321,#335,#301,.T.); +#407=EDGE_CURVE('',#336,#337,#144,.T.); +#408=EDGE_CURVE('',#337,#338,#145,.T.); +#409=EDGE_CURVE('',#338,#339,#146,.T.); +#410=EDGE_CURVE('',#339,#340,#147,.T.); +#411=EDGE_CURVE('',#341,#340,#148,.T.); +#412=EDGE_CURVE('',#320,#341,#149,.T.); +#413=EDGE_CURVE('',#321,#342,#150,.T.); +#414=EDGE_CURVE('',#342,#336,#151,.T.); +#415=EDGE_CURVE('',#336,#343,#302,.T.); +#416=EDGE_CURVE('',#344,#343,#152,.T.); +#417=EDGE_CURVE('',#344,#337,#303,.T.); +#418=EDGE_CURVE('',#345,#342,#304,.T.); +#419=EDGE_CURVE('',#343,#345,#153,.T.); +#420=EDGE_CURVE('',#346,#334,#154,.T.); +#421=EDGE_CURVE('',#346,#347,#155,.T.); +#422=EDGE_CURVE('',#339,#347,#156,.T.); +#423=EDGE_CURVE('',#338,#344,#157,.T.); +#424=EDGE_CURVE('',#345,#335,#158,.T.); +#425=EDGE_CURVE('',#348,#349,#159,.T.); +#426=EDGE_CURVE('',#340,#349,#160,.T.); +#427=EDGE_CURVE('',#350,#347,#161,.T.); +#428=EDGE_CURVE('',#351,#350,#162,.T.); +#429=EDGE_CURVE('',#351,#352,#163,.T.); +#430=EDGE_CURVE('',#353,#352,#164,.T.); +#431=EDGE_CURVE('',#354,#353,#165,.T.); +#432=EDGE_CURVE('',#354,#355,#166,.T.); +#433=EDGE_CURVE('',#356,#355,#167,.T.); +#434=EDGE_CURVE('',#348,#356,#168,.T.); +#435=EDGE_CURVE('',#357,#322,#169,.T.); +#436=EDGE_CURVE('',#357,#349,#170,.T.); +#437=EDGE_CURVE('',#358,#348,#171,.T.); +#438=EDGE_CURVE('',#359,#358,#172,.T.); +#439=EDGE_CURVE('',#359,#360,#173,.T.); +#440=EDGE_CURVE('',#360,#361,#174,.T.); +#441=EDGE_CURVE('',#361,#323,#175,.T.); +#442=EDGE_CURVE('',#361,#362,#305,.T.); +#443=EDGE_CURVE('',#324,#362,#176,.T.); +#444=EDGE_CURVE('',#363,#364,#177,.T.); +#445=EDGE_CURVE('',#358,#364,#178,.T.); +#446=EDGE_CURVE('',#365,#356,#179,.T.); +#447=EDGE_CURVE('',#325,#365,#180,.T.); +#448=EDGE_CURVE('',#362,#363,#181,.T.); +#449=EDGE_CURVE('',#363,#360,#306,.T.); +#450=EDGE_CURVE('',#359,#364,#307,.T.); +#451=EDGE_CURVE('',#366,#326,#182,.T.); +#452=EDGE_CURVE('',#366,#365,#183,.T.); +#453=EDGE_CURVE('',#366,#355,#184,.T.); +#454=EDGE_CURVE('',#367,#354,#185,.T.); +#455=EDGE_CURVE('',#368,#367,#186,.T.); +#456=EDGE_CURVE('',#368,#369,#187,.T.); +#457=EDGE_CURVE('',#369,#370,#188,.T.); +#458=EDGE_CURVE('',#370,#327,#189,.T.); +#459=EDGE_CURVE('',#370,#371,#308,.T.); +#460=EDGE_CURVE('',#328,#371,#190,.T.); +#461=EDGE_CURVE('',#372,#373,#191,.T.); +#462=EDGE_CURVE('',#367,#373,#192,.T.); +#463=EDGE_CURVE('',#374,#353,#193,.T.); +#464=EDGE_CURVE('',#329,#374,#194,.T.); +#465=EDGE_CURVE('',#371,#372,#195,.T.); +#466=EDGE_CURVE('',#372,#369,#309,.T.); +#467=EDGE_CURVE('',#368,#373,#310,.T.); +#468=EDGE_CURVE('',#375,#330,#196,.T.); +#469=EDGE_CURVE('',#375,#374,#197,.T.); +#470=EDGE_CURVE('',#375,#352,#198,.T.); +#471=EDGE_CURVE('',#376,#351,#199,.T.); +#472=EDGE_CURVE('',#376,#377,#200,.T.); +#473=EDGE_CURVE('',#377,#378,#201,.T.); +#474=EDGE_CURVE('',#378,#379,#202,.T.); +#475=EDGE_CURVE('',#379,#331,#203,.T.); +#476=EDGE_CURVE('',#379,#380,#311,.T.); +#477=EDGE_CURVE('',#332,#380,#204,.T.); +#478=EDGE_CURVE('',#381,#382,#205,.T.); +#479=EDGE_CURVE('',#382,#376,#206,.T.); +#480=EDGE_CURVE('',#383,#350,#207,.T.); +#481=EDGE_CURVE('',#333,#383,#208,.T.); +#482=EDGE_CURVE('',#380,#381,#209,.T.); +#483=EDGE_CURVE('',#381,#378,#312,.T.); +#484=EDGE_CURVE('',#377,#382,#313,.T.); +#485=EDGE_CURVE('',#346,#383,#210,.T.); +#486=EDGE_CURVE('',#357,#341,#211,.T.); +#487=EDGE_CURVE('',#384,#384,#314,.T.); +#488=EDGE_CURVE('',#384,#316,#315,.T.); +#489=ORIENTED_EDGE('',*,*,#385,.T.); +#490=ORIENTED_EDGE('',*,*,#386,.T.); +#491=ORIENTED_EDGE('',*,*,#387,.T.); +#492=ORIENTED_EDGE('',*,*,#386,.F.); +#493=ORIENTED_EDGE('',*,*,#388,.F.); +#494=ORIENTED_EDGE('',*,*,#387,.F.); +#495=ORIENTED_EDGE('',*,*,#389,.T.); +#496=ORIENTED_EDGE('',*,*,#390,.T.); +#497=ORIENTED_EDGE('',*,*,#388,.T.); +#498=ORIENTED_EDGE('',*,*,#390,.F.); +#499=ORIENTED_EDGE('',*,*,#389,.F.); +#500=ORIENTED_EDGE('',*,*,#391,.F.); +#501=ORIENTED_EDGE('',*,*,#392,.F.); +#502=ORIENTED_EDGE('',*,*,#393,.F.); +#503=ORIENTED_EDGE('',*,*,#394,.F.); +#504=ORIENTED_EDGE('',*,*,#395,.F.); +#505=ORIENTED_EDGE('',*,*,#396,.F.); +#506=ORIENTED_EDGE('',*,*,#397,.F.); +#507=ORIENTED_EDGE('',*,*,#398,.F.); +#508=ORIENTED_EDGE('',*,*,#399,.F.); +#509=ORIENTED_EDGE('',*,*,#400,.F.); +#510=ORIENTED_EDGE('',*,*,#401,.F.); +#511=ORIENTED_EDGE('',*,*,#402,.F.); +#512=ORIENTED_EDGE('',*,*,#403,.F.); +#513=ORIENTED_EDGE('',*,*,#404,.F.); +#514=ORIENTED_EDGE('',*,*,#405,.F.); +#515=ORIENTED_EDGE('',*,*,#406,.F.); +#516=ORIENTED_EDGE('',*,*,#407,.T.); +#517=ORIENTED_EDGE('',*,*,#408,.T.); +#518=ORIENTED_EDGE('',*,*,#409,.T.); +#519=ORIENTED_EDGE('',*,*,#410,.T.); +#520=ORIENTED_EDGE('',*,*,#411,.F.); +#521=ORIENTED_EDGE('',*,*,#412,.F.); +#522=ORIENTED_EDGE('',*,*,#391,.T.); +#523=ORIENTED_EDGE('',*,*,#413,.T.); +#524=ORIENTED_EDGE('',*,*,#414,.T.); +#525=ORIENTED_EDGE('',*,*,#415,.T.); +#526=ORIENTED_EDGE('',*,*,#416,.F.); +#527=ORIENTED_EDGE('',*,*,#417,.T.); +#528=ORIENTED_EDGE('',*,*,#407,.F.); +#529=ORIENTED_EDGE('',*,*,#415,.F.); +#530=ORIENTED_EDGE('',*,*,#414,.F.); +#531=ORIENTED_EDGE('',*,*,#418,.F.); +#532=ORIENTED_EDGE('',*,*,#419,.F.); +#533=ORIENTED_EDGE('',*,*,#405,.T.); +#534=ORIENTED_EDGE('',*,*,#420,.F.); +#535=ORIENTED_EDGE('',*,*,#421,.T.); +#536=ORIENTED_EDGE('',*,*,#422,.F.); +#537=ORIENTED_EDGE('',*,*,#409,.F.); +#538=ORIENTED_EDGE('',*,*,#423,.T.); +#539=ORIENTED_EDGE('',*,*,#416,.T.); +#540=ORIENTED_EDGE('',*,*,#419,.T.); +#541=ORIENTED_EDGE('',*,*,#424,.T.); +#542=ORIENTED_EDGE('',*,*,#406,.T.); +#543=ORIENTED_EDGE('',*,*,#424,.F.); +#544=ORIENTED_EDGE('',*,*,#418,.T.); +#545=ORIENTED_EDGE('',*,*,#413,.F.); +#546=ORIENTED_EDGE('',*,*,#408,.F.); +#547=ORIENTED_EDGE('',*,*,#417,.F.); +#548=ORIENTED_EDGE('',*,*,#423,.F.); +#549=ORIENTED_EDGE('',*,*,#425,.T.); +#550=ORIENTED_EDGE('',*,*,#426,.F.); +#551=ORIENTED_EDGE('',*,*,#410,.F.); +#552=ORIENTED_EDGE('',*,*,#422,.T.); +#553=ORIENTED_EDGE('',*,*,#427,.F.); +#554=ORIENTED_EDGE('',*,*,#428,.F.); +#555=ORIENTED_EDGE('',*,*,#429,.T.); +#556=ORIENTED_EDGE('',*,*,#430,.F.); +#557=ORIENTED_EDGE('',*,*,#431,.F.); +#558=ORIENTED_EDGE('',*,*,#432,.T.); +#559=ORIENTED_EDGE('',*,*,#433,.F.); +#560=ORIENTED_EDGE('',*,*,#434,.F.); +#561=ORIENTED_EDGE('',*,*,#393,.T.); +#562=ORIENTED_EDGE('',*,*,#435,.F.); +#563=ORIENTED_EDGE('',*,*,#436,.T.); +#564=ORIENTED_EDGE('',*,*,#425,.F.); +#565=ORIENTED_EDGE('',*,*,#437,.F.); +#566=ORIENTED_EDGE('',*,*,#438,.F.); +#567=ORIENTED_EDGE('',*,*,#439,.T.); +#568=ORIENTED_EDGE('',*,*,#440,.T.); +#569=ORIENTED_EDGE('',*,*,#441,.T.); +#570=ORIENTED_EDGE('',*,*,#394,.T.); +#571=ORIENTED_EDGE('',*,*,#441,.F.); +#572=ORIENTED_EDGE('',*,*,#442,.T.); +#573=ORIENTED_EDGE('',*,*,#443,.F.); +#574=ORIENTED_EDGE('',*,*,#444,.T.); +#575=ORIENTED_EDGE('',*,*,#445,.F.); +#576=ORIENTED_EDGE('',*,*,#437,.T.); +#577=ORIENTED_EDGE('',*,*,#434,.T.); +#578=ORIENTED_EDGE('',*,*,#446,.F.); +#579=ORIENTED_EDGE('',*,*,#447,.F.); +#580=ORIENTED_EDGE('',*,*,#395,.T.); +#581=ORIENTED_EDGE('',*,*,#443,.T.); +#582=ORIENTED_EDGE('',*,*,#448,.T.); +#583=ORIENTED_EDGE('',*,*,#449,.T.); +#584=ORIENTED_EDGE('',*,*,#439,.F.); +#585=ORIENTED_EDGE('',*,*,#450,.T.); +#586=ORIENTED_EDGE('',*,*,#444,.F.); +#587=ORIENTED_EDGE('',*,*,#449,.F.); +#588=ORIENTED_EDGE('',*,*,#448,.F.); +#589=ORIENTED_EDGE('',*,*,#442,.F.); +#590=ORIENTED_EDGE('',*,*,#440,.F.); +#591=ORIENTED_EDGE('',*,*,#438,.T.); +#592=ORIENTED_EDGE('',*,*,#445,.T.); +#593=ORIENTED_EDGE('',*,*,#450,.F.); +#594=ORIENTED_EDGE('',*,*,#451,.T.); +#595=ORIENTED_EDGE('',*,*,#396,.T.); +#596=ORIENTED_EDGE('',*,*,#447,.T.); +#597=ORIENTED_EDGE('',*,*,#452,.F.); +#598=ORIENTED_EDGE('',*,*,#397,.T.); +#599=ORIENTED_EDGE('',*,*,#451,.F.); +#600=ORIENTED_EDGE('',*,*,#453,.T.); +#601=ORIENTED_EDGE('',*,*,#432,.F.); +#602=ORIENTED_EDGE('',*,*,#454,.F.); +#603=ORIENTED_EDGE('',*,*,#455,.F.); +#604=ORIENTED_EDGE('',*,*,#456,.T.); +#605=ORIENTED_EDGE('',*,*,#457,.T.); +#606=ORIENTED_EDGE('',*,*,#458,.T.); +#607=ORIENTED_EDGE('',*,*,#398,.T.); +#608=ORIENTED_EDGE('',*,*,#458,.F.); +#609=ORIENTED_EDGE('',*,*,#459,.T.); +#610=ORIENTED_EDGE('',*,*,#460,.F.); +#611=ORIENTED_EDGE('',*,*,#461,.T.); +#612=ORIENTED_EDGE('',*,*,#462,.F.); +#613=ORIENTED_EDGE('',*,*,#454,.T.); +#614=ORIENTED_EDGE('',*,*,#431,.T.); +#615=ORIENTED_EDGE('',*,*,#463,.F.); +#616=ORIENTED_EDGE('',*,*,#464,.F.); +#617=ORIENTED_EDGE('',*,*,#399,.T.); +#618=ORIENTED_EDGE('',*,*,#460,.T.); +#619=ORIENTED_EDGE('',*,*,#465,.T.); +#620=ORIENTED_EDGE('',*,*,#466,.T.); +#621=ORIENTED_EDGE('',*,*,#456,.F.); +#622=ORIENTED_EDGE('',*,*,#467,.T.); +#623=ORIENTED_EDGE('',*,*,#461,.F.); +#624=ORIENTED_EDGE('',*,*,#466,.F.); +#625=ORIENTED_EDGE('',*,*,#465,.F.); +#626=ORIENTED_EDGE('',*,*,#459,.F.); +#627=ORIENTED_EDGE('',*,*,#457,.F.); +#628=ORIENTED_EDGE('',*,*,#467,.F.); +#629=ORIENTED_EDGE('',*,*,#455,.T.); +#630=ORIENTED_EDGE('',*,*,#462,.T.); +#631=ORIENTED_EDGE('',*,*,#468,.T.); +#632=ORIENTED_EDGE('',*,*,#400,.T.); +#633=ORIENTED_EDGE('',*,*,#464,.T.); +#634=ORIENTED_EDGE('',*,*,#469,.F.); +#635=ORIENTED_EDGE('',*,*,#401,.T.); +#636=ORIENTED_EDGE('',*,*,#468,.F.); +#637=ORIENTED_EDGE('',*,*,#470,.T.); +#638=ORIENTED_EDGE('',*,*,#429,.F.); +#639=ORIENTED_EDGE('',*,*,#471,.F.); +#640=ORIENTED_EDGE('',*,*,#472,.T.); +#641=ORIENTED_EDGE('',*,*,#473,.T.); +#642=ORIENTED_EDGE('',*,*,#474,.T.); +#643=ORIENTED_EDGE('',*,*,#475,.T.); +#644=ORIENTED_EDGE('',*,*,#402,.T.); +#645=ORIENTED_EDGE('',*,*,#475,.F.); +#646=ORIENTED_EDGE('',*,*,#476,.T.); +#647=ORIENTED_EDGE('',*,*,#477,.F.); +#648=ORIENTED_EDGE('',*,*,#478,.T.); +#649=ORIENTED_EDGE('',*,*,#479,.T.); +#650=ORIENTED_EDGE('',*,*,#471,.T.); +#651=ORIENTED_EDGE('',*,*,#428,.T.); +#652=ORIENTED_EDGE('',*,*,#480,.F.); +#653=ORIENTED_EDGE('',*,*,#481,.F.); +#654=ORIENTED_EDGE('',*,*,#403,.T.); +#655=ORIENTED_EDGE('',*,*,#477,.T.); +#656=ORIENTED_EDGE('',*,*,#482,.T.); +#657=ORIENTED_EDGE('',*,*,#483,.T.); +#658=ORIENTED_EDGE('',*,*,#473,.F.); +#659=ORIENTED_EDGE('',*,*,#484,.T.); +#660=ORIENTED_EDGE('',*,*,#478,.F.); +#661=ORIENTED_EDGE('',*,*,#483,.F.); +#662=ORIENTED_EDGE('',*,*,#482,.F.); +#663=ORIENTED_EDGE('',*,*,#476,.F.); +#664=ORIENTED_EDGE('',*,*,#474,.F.); +#665=ORIENTED_EDGE('',*,*,#484,.F.); +#666=ORIENTED_EDGE('',*,*,#472,.F.); +#667=ORIENTED_EDGE('',*,*,#479,.F.); +#668=ORIENTED_EDGE('',*,*,#420,.T.); +#669=ORIENTED_EDGE('',*,*,#404,.T.); +#670=ORIENTED_EDGE('',*,*,#481,.T.); +#671=ORIENTED_EDGE('',*,*,#485,.F.); +#672=ORIENTED_EDGE('',*,*,#485,.T.); +#673=ORIENTED_EDGE('',*,*,#480,.T.); +#674=ORIENTED_EDGE('',*,*,#427,.T.); +#675=ORIENTED_EDGE('',*,*,#421,.F.); +#676=ORIENTED_EDGE('',*,*,#469,.T.); +#677=ORIENTED_EDGE('',*,*,#463,.T.); +#678=ORIENTED_EDGE('',*,*,#430,.T.); +#679=ORIENTED_EDGE('',*,*,#470,.F.); +#680=ORIENTED_EDGE('',*,*,#452,.T.); +#681=ORIENTED_EDGE('',*,*,#446,.T.); +#682=ORIENTED_EDGE('',*,*,#433,.T.); +#683=ORIENTED_EDGE('',*,*,#453,.F.); +#684=ORIENTED_EDGE('',*,*,#486,.T.); +#685=ORIENTED_EDGE('',*,*,#411,.T.); +#686=ORIENTED_EDGE('',*,*,#426,.T.); +#687=ORIENTED_EDGE('',*,*,#436,.F.); +#688=ORIENTED_EDGE('',*,*,#435,.T.); +#689=ORIENTED_EDGE('',*,*,#392,.T.); +#690=ORIENTED_EDGE('',*,*,#412,.T.); +#691=ORIENTED_EDGE('',*,*,#486,.F.); +#692=ORIENTED_EDGE('',*,*,#487,.T.); +#693=ORIENTED_EDGE('',*,*,#488,.T.); +#694=ORIENTED_EDGE('',*,*,#385,.F.); +#695=ORIENTED_EDGE('',*,*,#488,.F.); +#696=ORIENTED_EDGE('',*,*,#487,.F.); +#697=CYLINDRICAL_SURFACE('',#761,3.); +#698=CYLINDRICAL_SURFACE('',#766,4.); +#699=CYLINDRICAL_SURFACE('',#774,2.); +#700=CYLINDRICAL_SURFACE('',#780,3.); +#701=CYLINDRICAL_SURFACE('',#784,3.); +#702=CYLINDRICAL_SURFACE('',#787,2.); +#703=CYLINDRICAL_SURFACE('',#794,3.); +#704=CYLINDRICAL_SURFACE('',#797,2.); +#705=CYLINDRICAL_SURFACE('',#804,3.); +#706=CYLINDRICAL_SURFACE('',#807,2.); +#707=ADVANCED_FACE('',(#50),#697,.T.); +#708=ADVANCED_FACE('',(#51,#20),#22,.F.); +#709=ADVANCED_FACE('',(#52),#698,.T.); +#710=ADVANCED_FACE('',(#53,#21),#23,.F.); +#711=ADVANCED_FACE('',(#54),#24,.F.); +#712=ADVANCED_FACE('',(#55),#699,.F.); +#713=ADVANCED_FACE('',(#56),#25,.T.); +#714=ADVANCED_FACE('',(#57),#26,.F.); +#715=ADVANCED_FACE('',(#58),#700,.F.); +#716=ADVANCED_FACE('',(#59),#27,.T.); +#717=ADVANCED_FACE('',(#60),#28,.F.); +#718=ADVANCED_FACE('',(#61),#29,.T.); +#719=ADVANCED_FACE('',(#62),#701,.F.); +#720=ADVANCED_FACE('',(#63),#30,.T.); +#721=ADVANCED_FACE('',(#64),#702,.F.); +#722=ADVANCED_FACE('',(#65),#31,.T.); +#723=ADVANCED_FACE('',(#66),#32,.F.); +#724=ADVANCED_FACE('',(#67),#33,.T.); +#725=ADVANCED_FACE('',(#68),#34,.T.); +#726=ADVANCED_FACE('',(#69),#703,.F.); +#727=ADVANCED_FACE('',(#70),#35,.T.); +#728=ADVANCED_FACE('',(#71),#704,.F.); +#729=ADVANCED_FACE('',(#72),#36,.T.); +#730=ADVANCED_FACE('',(#73),#37,.F.); +#731=ADVANCED_FACE('',(#74),#38,.T.); +#732=ADVANCED_FACE('',(#75),#39,.F.); +#733=ADVANCED_FACE('',(#76),#705,.F.); +#734=ADVANCED_FACE('',(#77),#40,.F.); +#735=ADVANCED_FACE('',(#78),#706,.F.); +#736=ADVANCED_FACE('',(#79),#41,.T.); +#737=ADVANCED_FACE('',(#80),#42,.T.); +#738=ADVANCED_FACE('',(#81),#43,.T.); +#739=ADVANCED_FACE('',(#82),#44,.F.); +#740=ADVANCED_FACE('',(#83),#45,.F.); +#741=ADVANCED_FACE('',(#84),#46,.F.); +#742=ADVANCED_FACE('',(#85),#47,.F.); +#743=ADVANCED_FACE('',(#86),#48,.T.); +#744=ADVANCED_FACE('',(#87),#19,.T.); +#745=ADVANCED_FACE('',(#88),#49,.T.); +#746=CLOSED_SHELL('',(#707,#708,#709,#710,#711,#712,#713,#714,#715,#716, +#717,#718,#719,#720,#721,#722,#723,#724,#725,#726,#727,#728,#729,#730,#731, +#732,#733,#734,#735,#736,#737,#738,#739,#740,#741,#742,#743,#744,#745)); +#747=DERIVED_UNIT_ELEMENT(#749,1.); +#748=DERIVED_UNIT_ELEMENT(#1255,-3.); +#749=( +MASS_UNIT() +NAMED_UNIT(*) +SI_UNIT(.KILO.,.GRAM.) ); -#199=( -BOUNDED_CURVE() -B_SPLINE_CURVE(2,(#780,#781,#782),.UNSPECIFIED.,.F.,.F.) -B_SPLINE_CURVE_WITH_KNOTS((3,3),(31.4120598130698,31.8006731456901), - .UNSPECIFIED.) -CURVE() -GEOMETRIC_REPRESENTATION_ITEM() -RATIONAL_B_SPLINE_CURVE((13.5600732229924,13.6241212154372,13.6878315833722)) -REPRESENTATION_ITEM('') -); -#200=( -BOUNDED_CURVE() -B_SPLINE_CURVE(2,(#794,#795,#796),.UNSPECIFIED.,.F.,.F.) -B_SPLINE_CURVE_WITH_KNOTS((3,3),(178.464778895689,178.853392228311), - .UNSPECIFIED.) -CURVE() -GEOMETRIC_REPRESENTATION_ITEM() -RATIONAL_B_SPLINE_CURVE((13.6878315833726,13.6241212154374,13.5600732229924)) -REPRESENTATION_ITEM('') -); -#201=VERTEX_POINT('',#734); -#202=VERTEX_POINT('',#735); -#203=VERTEX_POINT('',#739); -#204=VERTEX_POINT('',#741); -#205=VERTEX_POINT('',#745); -#206=VERTEX_POINT('',#747); -#207=VERTEX_POINT('',#749); -#208=VERTEX_POINT('',#751); -#209=VERTEX_POINT('',#755); -#210=VERTEX_POINT('',#757); -#211=VERTEX_POINT('',#761); -#212=VERTEX_POINT('',#763); -#213=VERTEX_POINT('',#770); -#214=VERTEX_POINT('',#772); -#215=VERTEX_POINT('',#778); -#216=VERTEX_POINT('',#779); -#217=VERTEX_POINT('',#783); -#218=VERTEX_POINT('',#785); -#219=VERTEX_POINT('',#787); -#220=VERTEX_POINT('',#789); -#221=VERTEX_POINT('',#791); -#222=VERTEX_POINT('',#793); -#223=VERTEX_POINT('',#799); -#224=VERTEX_POINT('',#801); -#225=VERTEX_POINT('',#805); -#226=VERTEX_POINT('',#807); -#227=VERTEX_POINT('',#815); -#228=VERTEX_POINT('',#817); -#229=VERTEX_POINT('',#821); -#230=VERTEX_POINT('',#833); -#231=VERTEX_POINT('',#844); -#232=VERTEX_POINT('',#849); -#233=VERTEX_POINT('',#860); -#234=VERTEX_POINT('',#874); -#235=VERTEX_POINT('',#876); -#236=VERTEX_POINT('',#882); -#237=VERTEX_POINT('',#884); -#238=VERTEX_POINT('',#887); -#239=VERTEX_POINT('',#889); -#240=VERTEX_POINT('',#893); -#241=VERTEX_POINT('',#894); -#242=VERTEX_POINT('',#896); -#243=VERTEX_POINT('',#898); -#244=VERTEX_POINT('',#902); -#245=VERTEX_POINT('',#906); -#246=VERTEX_POINT('',#912); -#247=VERTEX_POINT('',#914); -#248=EDGE_CURVE('',#201,#202,#197,.F.); -#249=EDGE_CURVE('',#203,#201,#107,.T.); -#250=EDGE_CURVE('',#204,#203,#198,.F.); -#251=EDGE_CURVE('',#205,#204,#108,.T.); -#252=EDGE_CURVE('',#206,#205,#109,.T.); -#253=EDGE_CURVE('',#207,#206,#110,.T.); -#254=EDGE_CURVE('',#208,#207,#111,.T.); -#255=EDGE_CURVE('',#202,#208,#112,.T.); -#256=EDGE_CURVE('',#208,#209,#29,.T.); -#257=EDGE_CURVE('',#207,#210,#113,.T.); -#258=EDGE_CURVE('',#210,#209,#114,.F.); -#259=EDGE_CURVE('',#211,#205,#30,.T.); -#260=EDGE_CURVE('',#211,#212,#115,.T.); -#261=EDGE_CURVE('',#212,#206,#116,.T.); -#262=EDGE_CURVE('',#202,#204,#31,.T.); -#263=EDGE_CURVE('',#201,#203,#32,.F.); -#264=EDGE_CURVE('',#206,#213,#117,.T.); -#265=EDGE_CURVE('',#213,#214,#118,.T.); -#266=EDGE_CURVE('',#214,#207,#119,.T.); -#267=EDGE_CURVE('',#205,#208,#33,.T.); -#268=EDGE_CURVE('',#215,#216,#199,.F.); -#269=EDGE_CURVE('',#217,#215,#120,.T.); -#270=EDGE_CURVE('',#218,#217,#121,.T.); -#271=EDGE_CURVE('',#219,#218,#122,.T.); -#272=EDGE_CURVE('',#220,#219,#123,.T.); -#273=EDGE_CURVE('',#221,#220,#124,.T.); -#274=EDGE_CURVE('',#222,#221,#200,.F.); -#275=EDGE_CURVE('',#216,#222,#125,.T.); -#276=EDGE_CURVE('',#220,#223,#34,.T.); -#277=EDGE_CURVE('',#219,#224,#126,.T.); -#278=EDGE_CURVE('',#224,#223,#127,.F.); -#279=EDGE_CURVE('',#225,#217,#35,.T.); -#280=EDGE_CURVE('',#225,#226,#128,.T.); -#281=EDGE_CURVE('',#226,#218,#129,.T.); -#282=EDGE_CURVE('',#222,#216,#36,.F.); -#283=EDGE_CURVE('',#221,#215,#37,.T.); -#284=EDGE_CURVE('',#218,#227,#130,.T.); -#285=EDGE_CURVE('',#227,#228,#131,.T.); -#286=EDGE_CURVE('',#228,#219,#132,.T.); -#287=EDGE_CURVE('',#229,#225,#20,.T.); -#288=EDGE_CURVE('',#217,#220,#38,.T.); -#289=EDGE_CURVE('',#223,#230,#21,.T.); -#290=EDGE_CURVE('',#230,#231,#39,.T.); -#291=EDGE_CURVE('',#231,#229,#40,.T.); -#292=EDGE_CURVE('',#232,#211,#22,.T.); -#293=EDGE_CURVE('',#209,#233,#23,.T.); -#294=EDGE_CURVE('',#233,#232,#41,.T.); -#295=EDGE_CURVE('',#234,#234,#42,.T.); -#296=EDGE_CURVE('',#234,#235,#43,.T.); -#297=EDGE_CURVE('',#235,#235,#44,.T.); -#298=EDGE_CURVE('',#235,#231,#133,.T.); -#299=EDGE_CURVE('',#230,#236,#15,.T.); -#300=EDGE_CURVE('',#236,#237,#45,.T.); -#301=EDGE_CURVE('',#237,#232,#16,.T.); -#302=EDGE_CURVE('',#233,#238,#17,.T.); -#303=EDGE_CURVE('',#238,#239,#46,.T.); -#304=EDGE_CURVE('',#239,#229,#18,.T.); -#305=EDGE_CURVE('',#240,#241,#134,.T.); -#306=EDGE_CURVE('',#242,#240,#135,.T.); -#307=EDGE_CURVE('',#243,#242,#136,.T.); -#308=EDGE_CURVE('',#241,#243,#137,.T.); -#309=EDGE_CURVE('',#210,#244,#138,.T.); -#310=EDGE_CURVE('',#214,#240,#139,.T.); -#311=EDGE_CURVE('',#227,#241,#140,.T.); -#312=EDGE_CURVE('',#245,#226,#141,.T.); -#313=EDGE_CURVE('',#244,#245,#142,.T.); -#314=EDGE_CURVE('',#213,#242,#143,.T.); -#315=EDGE_CURVE('',#246,#212,#144,.T.); -#316=EDGE_CURVE('',#247,#246,#145,.T.); -#317=EDGE_CURVE('',#224,#247,#146,.T.); -#318=EDGE_CURVE('',#228,#243,#147,.T.); -#319=EDGE_CURVE('',#244,#238,#148,.F.); -#320=EDGE_CURVE('',#237,#246,#149,.F.); -#321=EDGE_CURVE('',#239,#245,#150,.F.); -#322=EDGE_CURVE('',#247,#236,#151,.F.); -#323=ORIENTED_EDGE('',*,*,#248,.F.); -#324=ORIENTED_EDGE('',*,*,#249,.F.); -#325=ORIENTED_EDGE('',*,*,#250,.F.); -#326=ORIENTED_EDGE('',*,*,#251,.F.); -#327=ORIENTED_EDGE('',*,*,#252,.F.); -#328=ORIENTED_EDGE('',*,*,#253,.F.); -#329=ORIENTED_EDGE('',*,*,#254,.F.); -#330=ORIENTED_EDGE('',*,*,#255,.F.); -#331=ORIENTED_EDGE('',*,*,#256,.F.); -#332=ORIENTED_EDGE('',*,*,#254,.T.); -#333=ORIENTED_EDGE('',*,*,#257,.T.); -#334=ORIENTED_EDGE('',*,*,#258,.T.); -#335=ORIENTED_EDGE('',*,*,#259,.F.); -#336=ORIENTED_EDGE('',*,*,#260,.T.); -#337=ORIENTED_EDGE('',*,*,#261,.T.); -#338=ORIENTED_EDGE('',*,*,#252,.T.); -#339=ORIENTED_EDGE('',*,*,#248,.T.); -#340=ORIENTED_EDGE('',*,*,#262,.T.); -#341=ORIENTED_EDGE('',*,*,#250,.T.); -#342=ORIENTED_EDGE('',*,*,#263,.F.); -#343=ORIENTED_EDGE('',*,*,#253,.T.); -#344=ORIENTED_EDGE('',*,*,#264,.T.); -#345=ORIENTED_EDGE('',*,*,#265,.T.); -#346=ORIENTED_EDGE('',*,*,#266,.T.); -#347=ORIENTED_EDGE('',*,*,#255,.T.); -#348=ORIENTED_EDGE('',*,*,#267,.F.); -#349=ORIENTED_EDGE('',*,*,#251,.T.); -#350=ORIENTED_EDGE('',*,*,#262,.F.); -#351=ORIENTED_EDGE('',*,*,#268,.F.); -#352=ORIENTED_EDGE('',*,*,#269,.F.); -#353=ORIENTED_EDGE('',*,*,#270,.F.); -#354=ORIENTED_EDGE('',*,*,#271,.F.); -#355=ORIENTED_EDGE('',*,*,#272,.F.); -#356=ORIENTED_EDGE('',*,*,#273,.F.); -#357=ORIENTED_EDGE('',*,*,#274,.F.); -#358=ORIENTED_EDGE('',*,*,#275,.F.); -#359=ORIENTED_EDGE('',*,*,#276,.F.); -#360=ORIENTED_EDGE('',*,*,#272,.T.); -#361=ORIENTED_EDGE('',*,*,#277,.T.); -#362=ORIENTED_EDGE('',*,*,#278,.T.); -#363=ORIENTED_EDGE('',*,*,#279,.F.); -#364=ORIENTED_EDGE('',*,*,#280,.T.); -#365=ORIENTED_EDGE('',*,*,#281,.T.); -#366=ORIENTED_EDGE('',*,*,#270,.T.); -#367=ORIENTED_EDGE('',*,*,#275,.T.); -#368=ORIENTED_EDGE('',*,*,#282,.T.); -#369=ORIENTED_EDGE('',*,*,#268,.T.); -#370=ORIENTED_EDGE('',*,*,#282,.F.); -#371=ORIENTED_EDGE('',*,*,#274,.T.); -#372=ORIENTED_EDGE('',*,*,#283,.T.); -#373=ORIENTED_EDGE('',*,*,#271,.T.); -#374=ORIENTED_EDGE('',*,*,#284,.T.); -#375=ORIENTED_EDGE('',*,*,#285,.T.); -#376=ORIENTED_EDGE('',*,*,#286,.T.); -#377=ORIENTED_EDGE('',*,*,#287,.T.); -#378=ORIENTED_EDGE('',*,*,#279,.T.); -#379=ORIENTED_EDGE('',*,*,#288,.T.); -#380=ORIENTED_EDGE('',*,*,#276,.T.); -#381=ORIENTED_EDGE('',*,*,#289,.T.); -#382=ORIENTED_EDGE('',*,*,#290,.T.); -#383=ORIENTED_EDGE('',*,*,#291,.T.); -#384=ORIENTED_EDGE('',*,*,#269,.T.); -#385=ORIENTED_EDGE('',*,*,#283,.F.); -#386=ORIENTED_EDGE('',*,*,#273,.T.); -#387=ORIENTED_EDGE('',*,*,#288,.F.); -#388=ORIENTED_EDGE('',*,*,#292,.T.); -#389=ORIENTED_EDGE('',*,*,#259,.T.); -#390=ORIENTED_EDGE('',*,*,#267,.T.); -#391=ORIENTED_EDGE('',*,*,#256,.T.); -#392=ORIENTED_EDGE('',*,*,#293,.T.); -#393=ORIENTED_EDGE('',*,*,#294,.T.); -#394=ORIENTED_EDGE('',*,*,#249,.T.); -#395=ORIENTED_EDGE('',*,*,#263,.T.); -#396=ORIENTED_EDGE('',*,*,#295,.T.); -#397=ORIENTED_EDGE('',*,*,#296,.T.); -#398=ORIENTED_EDGE('',*,*,#297,.T.); -#399=ORIENTED_EDGE('',*,*,#296,.F.); -#400=ORIENTED_EDGE('',*,*,#295,.F.); -#401=ORIENTED_EDGE('',*,*,#297,.F.); -#402=ORIENTED_EDGE('',*,*,#298,.T.); -#403=ORIENTED_EDGE('',*,*,#290,.F.); -#404=ORIENTED_EDGE('',*,*,#299,.T.); -#405=ORIENTED_EDGE('',*,*,#300,.T.); -#406=ORIENTED_EDGE('',*,*,#301,.T.); -#407=ORIENTED_EDGE('',*,*,#294,.F.); -#408=ORIENTED_EDGE('',*,*,#302,.T.); -#409=ORIENTED_EDGE('',*,*,#303,.T.); -#410=ORIENTED_EDGE('',*,*,#304,.T.); -#411=ORIENTED_EDGE('',*,*,#291,.F.); -#412=ORIENTED_EDGE('',*,*,#298,.F.); -#413=ORIENTED_EDGE('',*,*,#305,.F.); -#414=ORIENTED_EDGE('',*,*,#306,.F.); -#415=ORIENTED_EDGE('',*,*,#307,.F.); -#416=ORIENTED_EDGE('',*,*,#308,.F.); -#417=ORIENTED_EDGE('',*,*,#309,.F.); -#418=ORIENTED_EDGE('',*,*,#257,.F.); -#419=ORIENTED_EDGE('',*,*,#266,.F.); -#420=ORIENTED_EDGE('',*,*,#310,.T.); -#421=ORIENTED_EDGE('',*,*,#305,.T.); -#422=ORIENTED_EDGE('',*,*,#311,.F.); -#423=ORIENTED_EDGE('',*,*,#284,.F.); -#424=ORIENTED_EDGE('',*,*,#281,.F.); -#425=ORIENTED_EDGE('',*,*,#312,.F.); -#426=ORIENTED_EDGE('',*,*,#313,.F.); -#427=ORIENTED_EDGE('',*,*,#265,.F.); -#428=ORIENTED_EDGE('',*,*,#314,.T.); -#429=ORIENTED_EDGE('',*,*,#306,.T.); -#430=ORIENTED_EDGE('',*,*,#310,.F.); -#431=ORIENTED_EDGE('',*,*,#315,.F.); -#432=ORIENTED_EDGE('',*,*,#316,.F.); -#433=ORIENTED_EDGE('',*,*,#317,.F.); -#434=ORIENTED_EDGE('',*,*,#277,.F.); -#435=ORIENTED_EDGE('',*,*,#286,.F.); -#436=ORIENTED_EDGE('',*,*,#318,.T.); -#437=ORIENTED_EDGE('',*,*,#307,.T.); -#438=ORIENTED_EDGE('',*,*,#314,.F.); -#439=ORIENTED_EDGE('',*,*,#264,.F.); -#440=ORIENTED_EDGE('',*,*,#261,.F.); -#441=ORIENTED_EDGE('',*,*,#285,.F.); -#442=ORIENTED_EDGE('',*,*,#311,.T.); -#443=ORIENTED_EDGE('',*,*,#308,.T.); -#444=ORIENTED_EDGE('',*,*,#318,.F.); -#445=ORIENTED_EDGE('',*,*,#309,.T.); -#446=ORIENTED_EDGE('',*,*,#319,.T.); -#447=ORIENTED_EDGE('',*,*,#302,.F.); -#448=ORIENTED_EDGE('',*,*,#293,.F.); -#449=ORIENTED_EDGE('',*,*,#258,.F.); -#450=ORIENTED_EDGE('',*,*,#315,.T.); -#451=ORIENTED_EDGE('',*,*,#260,.F.); -#452=ORIENTED_EDGE('',*,*,#292,.F.); -#453=ORIENTED_EDGE('',*,*,#301,.F.); -#454=ORIENTED_EDGE('',*,*,#320,.T.); -#455=ORIENTED_EDGE('',*,*,#313,.T.); -#456=ORIENTED_EDGE('',*,*,#321,.F.); -#457=ORIENTED_EDGE('',*,*,#303,.F.); -#458=ORIENTED_EDGE('',*,*,#319,.F.); -#459=ORIENTED_EDGE('',*,*,#312,.T.); -#460=ORIENTED_EDGE('',*,*,#280,.F.); -#461=ORIENTED_EDGE('',*,*,#287,.F.); -#462=ORIENTED_EDGE('',*,*,#304,.F.); -#463=ORIENTED_EDGE('',*,*,#321,.T.); -#464=ORIENTED_EDGE('',*,*,#317,.T.); -#465=ORIENTED_EDGE('',*,*,#322,.T.); -#466=ORIENTED_EDGE('',*,*,#299,.F.); -#467=ORIENTED_EDGE('',*,*,#289,.F.); -#468=ORIENTED_EDGE('',*,*,#278,.F.); -#469=ORIENTED_EDGE('',*,*,#316,.T.); -#470=ORIENTED_EDGE('',*,*,#320,.F.); -#471=ORIENTED_EDGE('',*,*,#300,.F.); -#472=ORIENTED_EDGE('',*,*,#322,.F.); -#473=PLANE('',#529); -#474=PLANE('',#530); -#475=PLANE('',#532); -#476=PLANE('',#537); -#477=PLANE('',#538); -#478=PLANE('',#540); -#479=PLANE('',#541); -#480=PLANE('',#543); -#481=PLANE('',#545); -#482=PLANE('',#549); -#483=PLANE('',#554); -#484=PLANE('',#557); -#485=PLANE('',#562); -#486=PLANE('',#570); -#487=PLANE('',#571); -#488=PLANE('',#572); -#489=PLANE('',#573); -#490=PLANE('',#574); -#491=PLANE('',#575); -#492=PLANE('',#576); -#493=PLANE('',#577); -#494=PLANE('',#578); -#495=PLANE('',#579); -#496=PLANE('',#580); -#497=ADVANCED_FACE('',(#47),#473,.F.); -#498=ADVANCED_FACE('',(#48),#474,.F.); -#499=ADVANCED_FACE('',(#49),#475,.F.); -#500=ADVANCED_FACE('',(#50),#27,.T.); -#501=ADVANCED_FACE('',(#51),#476,.F.); -#502=ADVANCED_FACE('',(#52),#477,.F.); -#503=ADVANCED_FACE('',(#53),#478,.F.); -#504=ADVANCED_FACE('',(#54),#479,.F.); -#505=ADVANCED_FACE('',(#55),#480,.F.); -#506=ADVANCED_FACE('',(#56),#481,.T.); -#507=ADVANCED_FACE('',(#57),#28,.T.); -#508=ADVANCED_FACE('',(#58),#482,.F.); -#509=ADVANCED_FACE('',(#59),#24,.F.); -#510=ADVANCED_FACE('',(#60),#483,.F.); -#511=ADVANCED_FACE('',(#61),#25,.F.); -#512=ADVANCED_FACE('',(#62),#484,.T.); -#513=ADVANCED_FACE('',(#63),#26,.T.); -#514=ADVANCED_FACE('',(#64),#485,.T.); -#515=ADVANCED_FACE('',(#65),#19,.T.); -#516=ADVANCED_FACE('',(#66),#486,.F.); -#517=ADVANCED_FACE('',(#67),#487,.F.); -#518=ADVANCED_FACE('',(#68),#488,.F.); -#519=ADVANCED_FACE('',(#69),#489,.F.); -#520=ADVANCED_FACE('',(#70),#490,.F.); -#521=ADVANCED_FACE('',(#71),#491,.F.); -#522=ADVANCED_FACE('',(#72),#492,.F.); -#523=ADVANCED_FACE('',(#73),#493,.F.); -#524=ADVANCED_FACE('',(#74),#494,.F.); -#525=ADVANCED_FACE('',(#75),#495,.F.); -#526=ADVANCED_FACE('',(#76),#496,.F.); -#527=CLOSED_SHELL('',(#497,#498,#499,#500,#501,#502,#503,#504,#505,#506, -#507,#508,#509,#510,#511,#512,#513,#514,#515,#516,#517,#518,#519,#520,#521, -#522,#523,#524,#525,#526)); -#528=AXIS2_PLACEMENT_3D('',#732,#581,#582); -#529=AXIS2_PLACEMENT_3D('',#733,#583,#584); -#530=AXIS2_PLACEMENT_3D('',#754,#591,#592); -#531=AXIS2_PLACEMENT_3D('',#756,#593,#594); -#532=AXIS2_PLACEMENT_3D('',#760,#597,#598); -#533=AXIS2_PLACEMENT_3D('',#762,#599,#600); -#534=AXIS2_PLACEMENT_3D('',#766,#603,#604); -#535=AXIS2_PLACEMENT_3D('',#767,#605,#606); -#536=AXIS2_PLACEMENT_3D('',#768,#607,#608); -#537=AXIS2_PLACEMENT_3D('',#769,#609,#610); -#538=AXIS2_PLACEMENT_3D('',#775,#614,#615); -#539=AXIS2_PLACEMENT_3D('',#776,#616,#617); -#540=AXIS2_PLACEMENT_3D('',#777,#618,#619); -#541=AXIS2_PLACEMENT_3D('',#798,#626,#627); -#542=AXIS2_PLACEMENT_3D('',#800,#628,#629); -#543=AXIS2_PLACEMENT_3D('',#804,#632,#633); -#544=AXIS2_PLACEMENT_3D('',#806,#634,#635); -#545=AXIS2_PLACEMENT_3D('',#810,#638,#639); -#546=AXIS2_PLACEMENT_3D('',#811,#640,#641); -#547=AXIS2_PLACEMENT_3D('',#812,#642,#643); -#548=AXIS2_PLACEMENT_3D('',#813,#644,#645); -#549=AXIS2_PLACEMENT_3D('',#814,#646,#647); -#550=AXIS2_PLACEMENT_3D('',#820,#651,#652); -#551=AXIS2_PLACEMENT_3D('',#832,#653,#654); -#552=AXIS2_PLACEMENT_3D('',#845,#655,#656); -#553=AXIS2_PLACEMENT_3D('',#846,#657,#658); -#554=AXIS2_PLACEMENT_3D('',#847,#659,#660); -#555=AXIS2_PLACEMENT_3D('',#848,#661,#662); -#556=AXIS2_PLACEMENT_3D('',#871,#663,#664); -#557=AXIS2_PLACEMENT_3D('',#872,#665,#666); -#558=AXIS2_PLACEMENT_3D('',#873,#667,#668); -#559=AXIS2_PLACEMENT_3D('',#875,#669,#670); -#560=AXIS2_PLACEMENT_3D('',#877,#671,#672); -#561=AXIS2_PLACEMENT_3D('',#878,#673,#674); -#562=AXIS2_PLACEMENT_3D('',#879,#675,#676); -#563=AXIS2_PLACEMENT_3D('',#880,#677,#678); -#564=AXIS2_PLACEMENT_3D('',#883,#680,#681); -#565=AXIS2_PLACEMENT_3D('',#885,#682,#683); -#566=AXIS2_PLACEMENT_3D('',#886,#684,#685); -#567=AXIS2_PLACEMENT_3D('',#888,#686,#687); -#568=AXIS2_PLACEMENT_3D('',#890,#688,#689); -#569=AXIS2_PLACEMENT_3D('',#891,#690,#691); -#570=AXIS2_PLACEMENT_3D('',#892,#692,#693); -#571=AXIS2_PLACEMENT_3D('',#901,#698,#699); -#572=AXIS2_PLACEMENT_3D('',#909,#705,#706); -#573=AXIS2_PLACEMENT_3D('',#911,#708,#709); -#574=AXIS2_PLACEMENT_3D('',#918,#714,#715); -#575=AXIS2_PLACEMENT_3D('',#919,#716,#717); -#576=AXIS2_PLACEMENT_3D('',#921,#719,#720); -#577=AXIS2_PLACEMENT_3D('',#923,#722,#723); -#578=AXIS2_PLACEMENT_3D('',#925,#725,#726); -#579=AXIS2_PLACEMENT_3D('',#926,#727,#728); -#580=AXIS2_PLACEMENT_3D('',#928,#730,#731); -#581=DIRECTION('axis',(0.,0.,1.)); -#582=DIRECTION('refdir',(1.,0.,0.)); -#583=DIRECTION('center_axis',(0.998629534754574,0.,0.0523359562429438)); -#584=DIRECTION('ref_axis',(0.0523359562429438,0.,-0.998629534754574)); -#585=DIRECTION('',(0.,1.,0.)); -#586=DIRECTION('',(0.,-1.,0.)); -#587=DIRECTION('',(0.,-1.,0.)); -#588=DIRECTION('',(0.,-1.,0.)); -#589=DIRECTION('',(0.,-1.,0.)); -#590=DIRECTION('',(0.,-1.,0.)); -#591=DIRECTION('center_axis',(0.,0.,1.)); -#592=DIRECTION('ref_axis',(0.,-1.,0.)); -#593=DIRECTION('center_axis',(0.,0.,1.)); -#594=DIRECTION('ref_axis',(1.,0.,0.)); -#595=DIRECTION('',(-1.,0.,0.)); -#596=DIRECTION('',(0.,-1.,0.)); -#597=DIRECTION('center_axis',(0.,0.,1.)); -#598=DIRECTION('ref_axis',(0.,-1.,0.)); -#599=DIRECTION('center_axis',(0.,0.,1.)); -#600=DIRECTION('ref_axis',(1.,0.,0.)); -#601=DIRECTION('',(0.,1.,0.)); -#602=DIRECTION('',(1.,0.,0.)); -#603=DIRECTION('center_axis',(0.,0.,-1.)); -#604=DIRECTION('ref_axis',(1.,0.,0.)); -#605=DIRECTION('center_axis',(0.,0.,-1.)); -#606=DIRECTION('ref_axis',(1.,0.,0.)); -#607=DIRECTION('center_axis',(0.,0.,1.)); -#608=DIRECTION('ref_axis',(1.,0.,0.)); -#609=DIRECTION('center_axis',(0.,0.,-1.)); -#610=DIRECTION('ref_axis',(1.,0.,0.)); -#611=DIRECTION('',(1.,0.,0.)); -#612=DIRECTION('',(0.,1.,0.)); -#613=DIRECTION('',(-1.,0.,0.)); -#614=DIRECTION('center_axis',(0.,0.,-1.)); -#615=DIRECTION('ref_axis',(1.,0.,0.)); -#616=DIRECTION('center_axis',(0.,0.,1.)); -#617=DIRECTION('ref_axis',(1.,0.,0.)); -#618=DIRECTION('center_axis',(-0.998629534754574,0.,0.0523359562429438)); -#619=DIRECTION('ref_axis',(0.0523359562429438,0.,0.998629534754574)); -#620=DIRECTION('',(0.,1.,0.)); -#621=DIRECTION('',(0.,1.,0.)); -#622=DIRECTION('',(0.,1.,0.)); -#623=DIRECTION('',(0.,1.,0.)); -#624=DIRECTION('',(0.,1.,0.)); -#625=DIRECTION('',(0.,-1.,0.)); -#626=DIRECTION('center_axis',(0.,0.,1.)); -#627=DIRECTION('ref_axis',(0.,1.,0.)); -#628=DIRECTION('center_axis',(0.,0.,1.)); -#629=DIRECTION('ref_axis',(-1.,0.,0.)); -#630=DIRECTION('',(1.,0.,0.)); -#631=DIRECTION('',(0.,1.,0.)); -#632=DIRECTION('center_axis',(0.,0.,1.)); -#633=DIRECTION('ref_axis',(0.,1.,0.)); -#634=DIRECTION('center_axis',(0.,0.,1.)); -#635=DIRECTION('ref_axis',(-1.,0.,0.)); -#636=DIRECTION('',(0.,-1.,0.)); -#637=DIRECTION('',(-1.,0.,0.)); -#638=DIRECTION('center_axis',(0.,0.,-1.)); -#639=DIRECTION('ref_axis',(1.,0.,0.)); -#640=DIRECTION('center_axis',(0.,0.,1.)); -#641=DIRECTION('ref_axis',(1.,0.,0.)); -#642=DIRECTION('center_axis',(0.,0.,-1.)); -#643=DIRECTION('ref_axis',(-1.,-8.75931951708652E-15,0.)); -#644=DIRECTION('center_axis',(0.,0.,-1.)); -#645=DIRECTION('ref_axis',(1.,0.,0.)); -#646=DIRECTION('center_axis',(0.,0.,-1.)); -#647=DIRECTION('ref_axis',(1.,0.,0.)); -#648=DIRECTION('',(-1.,0.,0.)); -#649=DIRECTION('',(0.,-1.,0.)); -#650=DIRECTION('',(1.,0.,0.)); -#651=DIRECTION('center_axis',(0.,0.,1.)); -#652=DIRECTION('ref_axis',(-1.,0.,0.)); -#653=DIRECTION('center_axis',(0.,0.,1.)); -#654=DIRECTION('ref_axis',(-1.,0.,0.)); -#655=DIRECTION('center_axis',(0.,0.,-1.)); -#656=DIRECTION('ref_axis',(-1.,0.,0.)); -#657=DIRECTION('center_axis',(0.,0.,-1.)); -#658=DIRECTION('ref_axis',(-1.,0.,0.)); -#659=DIRECTION('center_axis',(0.,0.,-1.)); -#660=DIRECTION('ref_axis',(1.,0.,0.)); -#661=DIRECTION('center_axis',(0.,0.,1.)); -#662=DIRECTION('ref_axis',(1.,0.,0.)); -#663=DIRECTION('center_axis',(0.,0.,-1.)); -#664=DIRECTION('ref_axis',(1.,0.,0.)); -#665=DIRECTION('center_axis',(0.,0.,-1.)); -#666=DIRECTION('ref_axis',(1.,0.,0.)); -#667=DIRECTION('center_axis',(0.,0.,1.)); -#668=DIRECTION('ref_axis',(1.,0.,0.)); -#669=DIRECTION('center_axis',(0.,0.,-1.)); -#670=DIRECTION('ref_axis',(1.,0.,0.)); -#671=DIRECTION('center_axis',(0.,-1.,0.)); -#672=DIRECTION('ref_axis',(-1.,0.,0.)); -#673=DIRECTION('center_axis',(0.,0.,1.)); -#674=DIRECTION('ref_axis',(1.,0.,0.)); -#675=DIRECTION('center_axis',(0.,0.,1.)); -#676=DIRECTION('ref_axis',(1.,0.,0.)); -#677=DIRECTION('center_axis',(0.,0.,1.)); -#678=DIRECTION('ref_axis',(1.,0.,0.)); -#679=DIRECTION('',(0.,0.,-1.)); -#680=DIRECTION('center_axis',(-0.998629534754574,0.,0.0523359562429438)); -#681=DIRECTION('ref_axis',(0.0523359562429438,0.,0.998629534754574)); -#682=DIRECTION('center_axis',(0.,0.,1.)); -#683=DIRECTION('ref_axis',(1.,0.,0.)); -#684=DIRECTION('center_axis',(0.998629534754574,0.,0.0523359562429438)); -#685=DIRECTION('ref_axis',(0.0523359562429438,0.,-0.998629534754574)); -#686=DIRECTION('center_axis',(0.998629534754574,0.,0.0523359562429438)); -#687=DIRECTION('ref_axis',(0.0523359562429438,0.,-0.998629534754574)); -#688=DIRECTION('center_axis',(0.,0.,1.)); -#689=DIRECTION('ref_axis',(1.,0.,0.)); -#690=DIRECTION('center_axis',(-0.998629534754574,0.,0.0523359562429438)); -#691=DIRECTION('ref_axis',(0.0523359562429438,0.,0.998629534754574)); -#692=DIRECTION('center_axis',(0.,0.,1.)); -#693=DIRECTION('ref_axis',(1.,0.,0.)); -#694=DIRECTION('',(-1.,0.,0.)); -#695=DIRECTION('',(0.,1.,0.)); -#696=DIRECTION('',(1.,0.,0.)); -#697=DIRECTION('',(0.,-1.,0.)); -#698=DIRECTION('center_axis',(0.,1.,0.)); -#699=DIRECTION('ref_axis',(-1.,0.,0.)); -#700=DIRECTION('',(-0.0523359562429438,0.,0.998629534754574)); -#701=DIRECTION('',(0.,0.,1.)); -#702=DIRECTION('',(0.,0.,1.)); -#703=DIRECTION('',(-0.0523359562429438,0.,-0.998629534754574)); -#704=DIRECTION('',(-1.,0.,0.)); -#705=DIRECTION('center_axis',(1.,0.,0.)); -#706=DIRECTION('ref_axis',(0.,1.,0.)); -#707=DIRECTION('',(0.,0.,1.)); -#708=DIRECTION('center_axis',(0.,-1.,0.)); -#709=DIRECTION('ref_axis',(1.,0.,0.)); -#710=DIRECTION('',(0.0523359562429438,0.,-0.998629534754574)); -#711=DIRECTION('',(1.,0.,0.)); -#712=DIRECTION('',(0.0523359562429438,0.,0.998629534754574)); -#713=DIRECTION('',(0.,0.,1.)); -#714=DIRECTION('center_axis',(-1.,0.,0.)); -#715=DIRECTION('ref_axis',(0.,-1.,0.)); -#716=DIRECTION('center_axis',(0.998629534754574,0.,0.0523359562429438)); -#717=DIRECTION('ref_axis',(0.,1.,0.)); -#718=DIRECTION('',(0.,-1.,0.)); -#719=DIRECTION('center_axis',(0.998629534754574,0.,0.0523359562429438)); -#720=DIRECTION('ref_axis',(0.,1.,0.)); -#721=DIRECTION('',(0.,-1.,0.)); -#722=DIRECTION('center_axis',(0.,0.,1.)); -#723=DIRECTION('ref_axis',(1.,0.,0.)); -#724=DIRECTION('',(0.,1.,0.)); -#725=DIRECTION('center_axis',(-0.998629534754574,0.,0.0523359562429438)); -#726=DIRECTION('ref_axis',(0.,-1.,0.)); -#727=DIRECTION('center_axis',(-0.998629534754574,0.,0.0523359562429438)); -#728=DIRECTION('ref_axis',(0.,-1.,0.)); -#729=DIRECTION('',(0.,1.,0.)); -#730=DIRECTION('center_axis',(0.,0.,1.)); -#731=DIRECTION('ref_axis',(1.,0.,0.)); -#732=CARTESIAN_POINT('',(0.,0.,0.)); -#733=CARTESIAN_POINT('Origin',(-31.3972446899932,39.,6.59725906950915)); -#734=CARTESIAN_POINT('',(-31.2532669430451,44.1197408428233,3.85)); -#735=CARTESIAN_POINT('',(-31.2925727775074,44.0634131040819,4.6)); -#736=CARTESIAN_POINT('Ctrl Pts',(-31.2925727775077,44.0634131040822,4.6000000000019)); -#737=CARTESIAN_POINT('Ctrl Pts',(-31.2730639423025,44.0913973222213,4.22774924883471)); -#738=CARTESIAN_POINT('Ctrl Pts',(-31.2532669430453,44.1197408428237,3.85000000000001)); -#739=CARTESIAN_POINT('',(-31.2532669430451,36.3802591571767,3.85)); -#740=CARTESIAN_POINT('',(-31.2532669430451,39.625,3.85)); -#741=CARTESIAN_POINT('',(-31.2925727775074,36.4365868959181,4.6)); -#742=CARTESIAN_POINT('Ctrl Pts',(-31.2532669430453,36.3802591571764,3.85000000000001)); -#743=CARTESIAN_POINT('Ctrl Pts',(-31.2730639423025,36.4086026777788,4.22774924883371)); -#744=CARTESIAN_POINT('Ctrl Pts',(-31.2925727775076,36.4365868959177,4.59999999999993)); -#745=CARTESIAN_POINT('',(-31.2925727775074,36.9648638532956,4.6)); -#746=CARTESIAN_POINT('',(-31.2925727775074,39.625,4.6)); -#747=CARTESIAN_POINT('',(-31.2925727775074,39.,4.6)); -#748=CARTESIAN_POINT('',(-31.2925727775074,40.875,4.6)); -#749=CARTESIAN_POINT('',(-31.2925727775074,41.5,4.6)); -#750=CARTESIAN_POINT('',(-31.2925727775074,39.625,4.6)); -#751=CARTESIAN_POINT('',(-31.2925727775074,43.5351361467044,4.6)); -#752=CARTESIAN_POINT('',(-31.2925727775074,40.875,4.6)); -#753=CARTESIAN_POINT('',(-31.2925727775074,39.625,4.6)); -#754=CARTESIAN_POINT('Origin',(-31.4165727775074,44.1004786005849,4.6)); -#755=CARTESIAN_POINT('',(-31.3117572189413,43.5421237967704,4.6)); -#756=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#757=CARTESIAN_POINT('',(-31.3117572189413,41.5,4.6)); -#758=CARTESIAN_POINT('',(-31.875,41.5,4.6)); -#759=CARTESIAN_POINT('',(-31.3117572189413,38.8190911978746,4.6)); -#760=CARTESIAN_POINT('Origin',(-31.4165727775074,44.1004786005849,4.6)); -#761=CARTESIAN_POINT('',(-31.3117572189413,36.9578762032296,4.6)); -#762=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#763=CARTESIAN_POINT('',(-31.3117572189413,39.,4.6)); -#764=CARTESIAN_POINT('',(-31.3117572189413,38.8190911978746,4.6)); -#765=CARTESIAN_POINT('',(-33.125,39.,4.6)); -#766=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#767=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#768=CARTESIAN_POINT('Origin',(-32.5,40.25,3.85)); -#769=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#770=CARTESIAN_POINT('',(-31.25,39.,4.6)); -#771=CARTESIAN_POINT('',(-33.125,39.,4.6)); -#772=CARTESIAN_POINT('',(-31.25,41.5,4.6)); -#773=CARTESIAN_POINT('',(-31.25,39.625,4.6)); -#774=CARTESIAN_POINT('',(-31.875,41.5,4.6)); -#775=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#776=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#777=CARTESIAN_POINT('Origin',(-33.6027553100068,37.4524679709498,6.59725906950915)); -#778=CARTESIAN_POINT('',(-33.7074272224926,44.0634131040819,4.6)); -#779=CARTESIAN_POINT('',(-33.7467330569549,44.1197408428233,3.85)); -#780=CARTESIAN_POINT('Ctrl Pts',(-33.7467330569546,44.1197408428226,3.85000000000001)); -#781=CARTESIAN_POINT('Ctrl Pts',(-33.7269360576974,44.0913973222202,4.22774924883367)); -#782=CARTESIAN_POINT('Ctrl Pts',(-33.7074272224924,44.0634131040812,4.59999999999986)); -#783=CARTESIAN_POINT('',(-33.7074272224926,43.5351361467044,4.6)); -#784=CARTESIAN_POINT('',(-33.7074272224926,38.8512339854749,4.6)); -#785=CARTESIAN_POINT('',(-33.7074272224926,41.5,4.6)); -#786=CARTESIAN_POINT('',(-33.7074272224926,38.8512339854749,4.6)); -#787=CARTESIAN_POINT('',(-33.7074272224926,39.,4.6)); -#788=CARTESIAN_POINT('',(-33.7074272224926,38.8512339854749,4.6)); -#789=CARTESIAN_POINT('',(-33.7074272224926,36.9648638532956,4.6)); -#790=CARTESIAN_POINT('',(-33.7074272224926,38.8512339854749,4.6)); -#791=CARTESIAN_POINT('',(-33.7074272224926,36.4365868959181,4.6)); -#792=CARTESIAN_POINT('',(-33.7074272224926,38.8512339854749,4.6)); -#793=CARTESIAN_POINT('',(-33.7467330569549,36.3802591571767,3.85)); -#794=CARTESIAN_POINT('Ctrl Pts',(-33.7074272224923,36.4365868959189,4.60000000000185)); -#795=CARTESIAN_POINT('Ctrl Pts',(-33.7269360576974,36.4086026777799,4.22774924883469)); -#796=CARTESIAN_POINT('Ctrl Pts',(-33.7467330569546,36.3802591571774,3.85000000000002)); -#797=CARTESIAN_POINT('',(-33.7467330569549,38.8512339854749,3.85)); -#798=CARTESIAN_POINT('Origin',(-33.5834272224926,36.3995213994151,4.6)); -#799=CARTESIAN_POINT('',(-33.6882427810587,36.9578762032296,4.6)); -#800=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#801=CARTESIAN_POINT('',(-33.6882427810587,39.,4.6)); -#802=CARTESIAN_POINT('',(-33.125,39.,4.6)); -#803=CARTESIAN_POINT('',(-33.6882427810587,41.6809088021254,4.6)); -#804=CARTESIAN_POINT('Origin',(-33.5834272224926,36.3995213994151,4.6)); -#805=CARTESIAN_POINT('',(-33.6882427810587,43.5421237967704,4.6)); -#806=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#807=CARTESIAN_POINT('',(-33.6882427810587,41.5,4.6)); -#808=CARTESIAN_POINT('',(-33.6882427810587,41.6809088021254,4.6)); -#809=CARTESIAN_POINT('',(-31.875,41.5,4.6)); -#810=CARTESIAN_POINT('Origin',(-32.5,40.25,3.85)); -#811=CARTESIAN_POINT('Origin',(-32.5,40.25,3.85)); -#812=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#813=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#814=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#815=CARTESIAN_POINT('',(-33.75,41.5,4.6)); -#816=CARTESIAN_POINT('',(-31.875,41.5,4.6)); -#817=CARTESIAN_POINT('',(-33.75,39.,4.6)); -#818=CARTESIAN_POINT('',(-33.75,40.875,4.6)); -#819=CARTESIAN_POINT('',(-33.125,39.,4.6)); -#820=CARTESIAN_POINT('Origin',(-32.5,40.25,5.1)); -#821=CARTESIAN_POINT('',(-33.6620388914172,43.0158028879213,5.10000000000001)); -#822=CARTESIAN_POINT('Ctrl Pts',(-33.6620388914172,43.0158028879213,5.1)); -#823=CARTESIAN_POINT('Ctrl Pts',(-33.6651920712123,43.01447809447,5.03983374532976)); -#824=CARTESIAN_POINT('Ctrl Pts',(-33.6689112159236,43.0278824868506,4.96886823673186)); -#825=CARTESIAN_POINT('Ctrl Pts',(-33.6748289210536,43.0746859130229,4.85595169626728)); -#826=CARTESIAN_POINT('Ctrl Pts',(-33.6780423060377,43.1169412026611,4.79463665815568)); -#827=CARTESIAN_POINT('Ctrl Pts',(-33.6826780062787,43.2079072106537,4.70618222821446)); -#828=CARTESIAN_POINT('Ctrl Pts',(-33.6848769587568,43.2734163503024,4.66422371540944)); -#829=CARTESIAN_POINT('Ctrl Pts',(-33.6874521920649,43.3958794376124,4.61508533665515)); -#830=CARTESIAN_POINT('Ctrl Pts',(-33.6882427810587,43.4749994711774,4.6)); -#831=CARTESIAN_POINT('Ctrl Pts',(-33.6882427810587,43.5421237967704,4.6)); -#832=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#833=CARTESIAN_POINT('',(-33.6620388914172,37.4841971120787,5.10000000000001)); -#834=CARTESIAN_POINT('Ctrl Pts',(-33.6882427810587,36.9578762032296,4.6)); -#835=CARTESIAN_POINT('Ctrl Pts',(-33.6882427810587,37.0250005288226,4.6)); -#836=CARTESIAN_POINT('Ctrl Pts',(-33.6874521920649,37.1041205623876,4.61508533665515)); -#837=CARTESIAN_POINT('Ctrl Pts',(-33.6848769587568,37.2265836496976,4.66422371540945)); -#838=CARTESIAN_POINT('Ctrl Pts',(-33.6826780062787,37.2920927893463,4.70618222821446)); -#839=CARTESIAN_POINT('Ctrl Pts',(-33.6780423060377,37.3830587973389,4.79463665815568)); -#840=CARTESIAN_POINT('Ctrl Pts',(-33.6748289210536,37.4253140869771,4.85595169626728)); -#841=CARTESIAN_POINT('Ctrl Pts',(-33.6689112159236,37.4721175131494,4.96886823673186)); -#842=CARTESIAN_POINT('Ctrl Pts',(-33.6651920712123,37.48552190553,5.03983374532976)); -#843=CARTESIAN_POINT('Ctrl Pts',(-33.6620388914172,37.4841971120787,5.1)); -#844=CARTESIAN_POINT('',(-35.5,40.25,5.09999999999999)); -#845=CARTESIAN_POINT('Origin',(-32.5,40.25,5.1)); -#846=CARTESIAN_POINT('Origin',(-32.5,40.25,5.1)); -#847=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#848=CARTESIAN_POINT('Origin',(-32.5,40.25,5.1)); -#849=CARTESIAN_POINT('',(-31.3379611085828,37.4841971120787,5.10000000000001)); -#850=CARTESIAN_POINT('Ctrl Pts',(-31.3379611085828,37.4841971120787,5.1)); -#851=CARTESIAN_POINT('Ctrl Pts',(-31.3348079287877,37.48552190553,5.03983374532976)); -#852=CARTESIAN_POINT('Ctrl Pts',(-31.3310887840764,37.4721175131494,4.96886823673186)); -#853=CARTESIAN_POINT('Ctrl Pts',(-31.3251710789464,37.4253140869771,4.85595169626728)); -#854=CARTESIAN_POINT('Ctrl Pts',(-31.3219576939623,37.3830587973389,4.79463665815568)); -#855=CARTESIAN_POINT('Ctrl Pts',(-31.3173219937213,37.2920927893463,4.70618222821446)); -#856=CARTESIAN_POINT('Ctrl Pts',(-31.3151230412432,37.2265836496976,4.66422371540944)); -#857=CARTESIAN_POINT('Ctrl Pts',(-31.3125478079351,37.1041205623876,4.61508533665515)); -#858=CARTESIAN_POINT('Ctrl Pts',(-31.3117572189413,37.0250005288226,4.6)); -#859=CARTESIAN_POINT('Ctrl Pts',(-31.3117572189413,36.9578762032296,4.6)); -#860=CARTESIAN_POINT('',(-31.3379611085828,43.0158028879213,5.10000000000001)); -#861=CARTESIAN_POINT('Ctrl Pts',(-31.3117572189413,43.5421237967704,4.6)); -#862=CARTESIAN_POINT('Ctrl Pts',(-31.3117572189413,43.4749994711774,4.6)); -#863=CARTESIAN_POINT('Ctrl Pts',(-31.3125478079351,43.3958794376124,4.61508533665515)); -#864=CARTESIAN_POINT('Ctrl Pts',(-31.3151230412432,43.2734163503024,4.66422371540944)); -#865=CARTESIAN_POINT('Ctrl Pts',(-31.3173219937213,43.2079072106537,4.70618222821446)); -#866=CARTESIAN_POINT('Ctrl Pts',(-31.3219576939623,43.1169412026611,4.79463665815568)); -#867=CARTESIAN_POINT('Ctrl Pts',(-31.3251710789464,43.0746859130229,4.85595169626728)); -#868=CARTESIAN_POINT('Ctrl Pts',(-31.3310887840764,43.0278824868506,4.96886823673186)); -#869=CARTESIAN_POINT('Ctrl Pts',(-31.3348079287877,43.01447809447,5.03983374532976)); -#870=CARTESIAN_POINT('Ctrl Pts',(-31.3379611085828,43.0158028879213,5.1)); -#871=CARTESIAN_POINT('Origin',(-32.5,40.25,5.1)); -#872=CARTESIAN_POINT('Origin',(-32.5,40.25,3.85)); -#873=CARTESIAN_POINT('Origin',(-32.5,40.25,12.6)); -#874=CARTESIAN_POINT('',(-35.,40.25,13.1)); -#875=CARTESIAN_POINT('Origin',(-32.5,40.25,13.1)); -#876=CARTESIAN_POINT('',(-35.5,40.25,12.6)); -#877=CARTESIAN_POINT('Origin',(-35.,40.25,12.6)); -#878=CARTESIAN_POINT('Origin',(-32.5,40.25,12.6)); -#879=CARTESIAN_POINT('Origin',(-32.5,40.25,13.1)); -#880=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); -#881=CARTESIAN_POINT('',(-35.5,40.25,4.6)); -#882=CARTESIAN_POINT('',(-33.5834272224926,37.4524679709498,6.6)); -#883=CARTESIAN_POINT('Origin',(-32.5,40.25,27.2730229235879)); -#884=CARTESIAN_POINT('',(-31.4165727775074,37.4524679709498,6.6)); -#885=CARTESIAN_POINT('Origin',(-32.5,40.25,6.6)); -#886=CARTESIAN_POINT('Origin',(-32.5,40.25,27.2730229235879)); -#887=CARTESIAN_POINT('',(-31.4165727775074,43.0475320290502,6.6)); -#888=CARTESIAN_POINT('Origin',(-32.5,40.25,27.2730229235879)); -#889=CARTESIAN_POINT('',(-33.5834272224926,43.0475320290502,6.6)); -#890=CARTESIAN_POINT('Origin',(-32.5,40.25,6.6)); -#891=CARTESIAN_POINT('Origin',(-32.5,40.25,27.2730229235879)); -#892=CARTESIAN_POINT('Origin',(-32.5,40.25,8.6)); -#893=CARTESIAN_POINT('',(-31.25,41.5,8.6)); -#894=CARTESIAN_POINT('',(-33.75,41.5,8.6)); -#895=CARTESIAN_POINT('',(-33.75,41.5,8.6)); -#896=CARTESIAN_POINT('',(-31.25,39.,8.6)); -#897=CARTESIAN_POINT('',(-31.25,41.5,8.6)); -#898=CARTESIAN_POINT('',(-33.75,39.,8.6)); -#899=CARTESIAN_POINT('',(-31.25,39.,8.6)); -#900=CARTESIAN_POINT('',(-33.75,39.,8.6)); -#901=CARTESIAN_POINT('Origin',(-31.25,41.5,4.6)); -#902=CARTESIAN_POINT('',(-31.4165727775074,41.5,6.6)); -#903=CARTESIAN_POINT('',(-31.3118701541713,41.5,4.60215493256167)); -#904=CARTESIAN_POINT('',(-31.25,41.5,4.6)); -#905=CARTESIAN_POINT('',(-33.75,41.5,4.6)); -#906=CARTESIAN_POINT('',(-33.5834272224926,41.5,6.6)); -#907=CARTESIAN_POINT('',(-33.6847060304338,41.5,4.66748522210396)); -#908=CARTESIAN_POINT('',(-31.875,41.5,6.6)); -#909=CARTESIAN_POINT('Origin',(-31.25,39.,4.6)); -#910=CARTESIAN_POINT('',(-31.25,39.,4.6)); -#911=CARTESIAN_POINT('Origin',(-33.75,39.,4.6)); -#912=CARTESIAN_POINT('',(-31.4165727775074,39.,6.6)); -#913=CARTESIAN_POINT('',(-31.3152939695662,39.,4.66748522210396)); -#914=CARTESIAN_POINT('',(-33.5834272224926,39.,6.6)); -#915=CARTESIAN_POINT('',(-33.125,39.,6.6)); -#916=CARTESIAN_POINT('',(-33.6881298458287,39.,4.60215493256167)); -#917=CARTESIAN_POINT('',(-33.75,39.,4.6)); -#918=CARTESIAN_POINT('Origin',(-33.75,41.5,4.6)); -#919=CARTESIAN_POINT('Origin',(-31.312152245655,37.3881823957492,4.60753755871915)); -#920=CARTESIAN_POINT('',(-31.4165727775074,38.8190911978746,6.6)); -#921=CARTESIAN_POINT('Origin',(-31.312152245655,37.3881823957492,4.60753755871915)); -#922=CARTESIAN_POINT('',(-31.4165727775074,38.8190911978746,6.6)); -#923=CARTESIAN_POINT('Origin',(-32.5,40.25,6.6)); -#924=CARTESIAN_POINT('',(-33.5834272224926,41.6809088021254,6.6)); -#925=CARTESIAN_POINT('Origin',(-33.687847754345,43.1118176042508,4.60753755871915)); -#926=CARTESIAN_POINT('Origin',(-33.687847754345,43.1118176042508,4.60753755871915)); -#927=CARTESIAN_POINT('',(-33.5834272224926,41.6809088021254,6.6)); -#928=CARTESIAN_POINT('Origin',(-32.5,40.25,6.6)); -#929=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#933, +#750=DERIVED_UNIT((#747,#748)); +#751=MEASURE_REPRESENTATION_ITEM('density measure', +POSITIVE_RATIO_MEASURE(7850.),#750); +#752=PROPERTY_DEFINITION_REPRESENTATION(#757,#754); +#753=PROPERTY_DEFINITION_REPRESENTATION(#758,#755); +#754=REPRESENTATION('material name',(#756),#1252); +#755=REPRESENTATION('density',(#751),#1252); +#756=DESCRIPTIVE_REPRESENTATION_ITEM('Steel','Steel'); +#757=PROPERTY_DEFINITION('material property','material name',#1267); +#758=PROPERTY_DEFINITION('material property','density of part',#1267); +#759=AXIS2_PLACEMENT_3D('',#1033,#823,#824); +#760=AXIS2_PLACEMENT_3D('',#1034,#825,#826); +#761=AXIS2_PLACEMENT_3D('',#1035,#827,#828); +#762=AXIS2_PLACEMENT_3D('',#1037,#829,#830); +#763=AXIS2_PLACEMENT_3D('',#1040,#832,#833); +#764=AXIS2_PLACEMENT_3D('',#1041,#834,#835); +#765=AXIS2_PLACEMENT_3D('',#1043,#836,#837); +#766=AXIS2_PLACEMENT_3D('',#1044,#838,#839); +#767=AXIS2_PLACEMENT_3D('',#1046,#840,#841); +#768=AXIS2_PLACEMENT_3D('',#1048,#843,#844); +#769=AXIS2_PLACEMENT_3D('',#1057,#848,#849); +#770=AXIS2_PLACEMENT_3D('',#1065,#853,#854); +#771=AXIS2_PLACEMENT_3D('',#1073,#858,#859); +#772=AXIS2_PLACEMENT_3D('',#1080,#863,#864); +#773=AXIS2_PLACEMENT_3D('',#1081,#865,#866); +#774=AXIS2_PLACEMENT_3D('',#1097,#875,#876); +#775=AXIS2_PLACEMENT_3D('',#1099,#877,#878); +#776=AXIS2_PLACEMENT_3D('',#1102,#880,#881); +#777=AXIS2_PLACEMENT_3D('',#1103,#882,#883); +#778=AXIS2_PLACEMENT_3D('',#1105,#884,#885); +#779=AXIS2_PLACEMENT_3D('',#1107,#887,#888); +#780=AXIS2_PLACEMENT_3D('',#1115,#894,#895); +#781=AXIS2_PLACEMENT_3D('',#1116,#896,#897); +#782=AXIS2_PLACEMENT_3D('',#1117,#898,#899); +#783=AXIS2_PLACEMENT_3D('',#1137,#910,#911); +#784=AXIS2_PLACEMENT_3D('',#1150,#919,#920); +#785=AXIS2_PLACEMENT_3D('',#1152,#921,#922); +#786=AXIS2_PLACEMENT_3D('',#1154,#924,#925); +#787=AXIS2_PLACEMENT_3D('',#1163,#931,#932); +#788=AXIS2_PLACEMENT_3D('',#1164,#933,#934); +#789=AXIS2_PLACEMENT_3D('',#1165,#935,#936); +#790=AXIS2_PLACEMENT_3D('',#1166,#937,#938); +#791=AXIS2_PLACEMENT_3D('',#1167,#939,#940); +#792=AXIS2_PLACEMENT_3D('',#1168,#941,#942); +#793=AXIS2_PLACEMENT_3D('',#1172,#945,#946); +#794=AXIS2_PLACEMENT_3D('',#1183,#953,#954); +#795=AXIS2_PLACEMENT_3D('',#1185,#955,#956); +#796=AXIS2_PLACEMENT_3D('',#1187,#958,#959); +#797=AXIS2_PLACEMENT_3D('',#1196,#965,#966); +#798=AXIS2_PLACEMENT_3D('',#1197,#967,#968); +#799=AXIS2_PLACEMENT_3D('',#1198,#969,#970); +#800=AXIS2_PLACEMENT_3D('',#1199,#971,#972); +#801=AXIS2_PLACEMENT_3D('',#1200,#973,#974); +#802=AXIS2_PLACEMENT_3D('',#1201,#975,#976); +#803=AXIS2_PLACEMENT_3D('',#1205,#979,#980); +#804=AXIS2_PLACEMENT_3D('',#1216,#987,#988); +#805=AXIS2_PLACEMENT_3D('',#1218,#989,#990); +#806=AXIS2_PLACEMENT_3D('',#1220,#992,#993); +#807=AXIS2_PLACEMENT_3D('',#1229,#999,#1000); +#808=AXIS2_PLACEMENT_3D('',#1230,#1001,#1002); +#809=AXIS2_PLACEMENT_3D('',#1231,#1003,#1004); +#810=AXIS2_PLACEMENT_3D('',#1232,#1005,#1006); +#811=AXIS2_PLACEMENT_3D('',#1233,#1007,#1008); +#812=AXIS2_PLACEMENT_3D('',#1234,#1009,#1010); +#813=AXIS2_PLACEMENT_3D('',#1236,#1012,#1013); +#814=AXIS2_PLACEMENT_3D('',#1237,#1014,#1015); +#815=AXIS2_PLACEMENT_3D('',#1238,#1016,#1017); +#816=AXIS2_PLACEMENT_3D('',#1239,#1018,#1019); +#817=AXIS2_PLACEMENT_3D('',#1241,#1021,#1022); +#818=AXIS2_PLACEMENT_3D('',#1242,#1023,#1024); +#819=AXIS2_PLACEMENT_3D('',#1244,#1025,#1026); +#820=AXIS2_PLACEMENT_3D('',#1245,#1027,#1028); +#821=AXIS2_PLACEMENT_3D('',#1246,#1029,#1030); +#822=AXIS2_PLACEMENT_3D('',#1247,#1031,#1032); +#823=DIRECTION('axis',(0.,0.,1.)); +#824=DIRECTION('refdir',(1.,0.,0.)); +#825=DIRECTION('axis',(0.,0.,1.)); +#826=DIRECTION('refdir',(1.,0.,0.)); +#827=DIRECTION('center_axis',(0.,0.,1.)); +#828=DIRECTION('ref_axis',(1.,0.,0.)); +#829=DIRECTION('center_axis',(0.,0.,-1.)); +#830=DIRECTION('ref_axis',(1.,0.,0.)); +#831=DIRECTION('',(0.,0.,-1.)); +#832=DIRECTION('center_axis',(0.,0.,1.)); +#833=DIRECTION('ref_axis',(-1.,0.,0.)); +#834=DIRECTION('center_axis',(0.,0.,-1.)); +#835=DIRECTION('ref_axis',(-1.,0.,0.)); +#836=DIRECTION('center_axis',(0.,0.,-1.)); +#837=DIRECTION('ref_axis',(-1.,0.,0.)); +#838=DIRECTION('center_axis',(0.,0.,-1.)); +#839=DIRECTION('ref_axis',(-1.,0.,0.)); +#840=DIRECTION('center_axis',(0.,0.,1.)); +#841=DIRECTION('ref_axis',(1.,0.,0.)); +#842=DIRECTION('',(0.,0.,1.)); +#843=DIRECTION('center_axis',(0.,0.,1.)); +#844=DIRECTION('ref_axis',(1.,0.,0.)); +#845=DIRECTION('',(1.456554222731E-13,1.,0.)); +#846=DIRECTION('',(1.,-3.5527136788E-14,0.)); +#847=DIRECTION('',(1.522761232855E-13,-1.,0.)); +#848=DIRECTION('center_axis',(0.,0.,-1.)); +#849=DIRECTION('ref_axis',(-0.991071249821237,0.133333333333305,0.)); +#850=DIRECTION('',(-1.,1.522761232855E-13,0.)); +#851=DIRECTION('',(0.,1.,0.)); +#852=DIRECTION('',(1.,1.456554222731E-13,0.)); +#853=DIRECTION('center_axis',(0.,0.,-1.)); +#854=DIRECTION('ref_axis',(-0.133333333333305,-0.991071249821237,0.)); +#855=DIRECTION('',(-1.522761232855E-13,-1.,0.)); +#856=DIRECTION('',(-1.,0.,0.)); +#857=DIRECTION('',(-1.456554222731E-13,1.,0.)); +#858=DIRECTION('center_axis',(0.,0.,-1.)); +#859=DIRECTION('ref_axis',(0.991071249821237,-0.133333333333305,0.)); +#860=DIRECTION('',(1.,-1.456554222731E-13,0.)); +#861=DIRECTION('',(0.,-1.,0.)); +#862=DIRECTION('',(-1.,-1.522761232855E-13,0.)); +#863=DIRECTION('center_axis',(0.,0.,-1.)); +#864=DIRECTION('ref_axis',(0.133333333333305,0.991071249821237,0.)); +#865=DIRECTION('center_axis',(-1.,0.,0.)); +#866=DIRECTION('ref_axis',(0.,1.,0.)); +#867=DIRECTION('',(0.,0.,1.)); +#868=DIRECTION('',(1.457905051083E-13,-1.,0.)); +#869=DIRECTION('',(0.,0.,-1.)); +#870=DIRECTION('',(0.,1.,0.)); +#871=DIRECTION('',(0.,0.,1.)); +#872=DIRECTION('',(0.,-0.707106781186498,0.707106781186598)); +#873=DIRECTION('',(0.,0.,1.)); +#874=DIRECTION('',(-3.785366677674E-13,-1.,0.)); +#875=DIRECTION('center_axis',(0.,0.,-1.)); +#876=DIRECTION('ref_axis',(-1.,0.,0.)); +#877=DIRECTION('center_axis',(0.,0.,-1.)); +#878=DIRECTION('ref_axis',(0.199999999999994,0.979795897113273,0.)); +#879=DIRECTION('',(0.,0.,-1.)); +#880=DIRECTION('center_axis',(0.,0.,1.)); +#881=DIRECTION('ref_axis',(0.979795897113273,0.199999999999994,0.)); +#882=DIRECTION('center_axis',(0.,0.,-1.)); +#883=DIRECTION('ref_axis',(-1.,0.,0.)); +#884=DIRECTION('center_axis',(0.,0.,1.)); +#885=DIRECTION('ref_axis',(0.991071249821237,0.133333333333305,0.)); +#886=DIRECTION('',(1.,3.855466060594E-13,0.)); +#887=DIRECTION('center_axis',(0.,-1.,0.)); +#888=DIRECTION('ref_axis',(-1.,0.,0.)); +#889=DIRECTION('',(0.707106781186547,0.,-0.707106781186547)); +#890=DIRECTION('',(0.,0.,1.)); +#891=DIRECTION('',(1.,0.,0.)); +#892=DIRECTION('',(1.,-1.457905051083E-13,0.)); +#893=DIRECTION('',(0.,0.,-1.)); +#894=DIRECTION('center_axis',(0.,0.,-1.)); +#895=DIRECTION('ref_axis',(-1.,0.,0.)); +#896=DIRECTION('center_axis',(0.,0.,-1.)); +#897=DIRECTION('ref_axis',(-1.,0.,0.)); +#898=DIRECTION('center_axis',(0.,0.,1.)); +#899=DIRECTION('ref_axis',(1.,0.,0.)); +#900=DIRECTION('',(0.,1.,0.)); +#901=DIRECTION('',(-1.,0.,0.)); +#902=DIRECTION('',(0.,1.,0.)); +#903=DIRECTION('',(1.,0.,0.)); +#904=DIRECTION('',(0.,-1.,0.)); +#905=DIRECTION('',(1.,0.,0.)); +#906=DIRECTION('',(0.,-1.,0.)); +#907=DIRECTION('',(-1.,0.,0.)); +#908=DIRECTION('',(0.,-1.,0.)); +#909=DIRECTION('',(-1.,0.,0.)); +#910=DIRECTION('center_axis',(-1.,0.,0.)); +#911=DIRECTION('ref_axis',(0.,1.,0.)); +#912=DIRECTION('',(0.,0.707106781186498,-0.707106781186597)); +#913=DIRECTION('',(0.,0.,1.)); +#914=DIRECTION('',(0.,0.,-1.)); +#915=DIRECTION('',(-1.457905051083E-13,-1.,0.)); +#916=DIRECTION('',(0.,0.,-1.)); +#917=DIRECTION('',(-3.855466060594E-13,1.,0.)); +#918=DIRECTION('',(0.,0.,-1.)); +#919=DIRECTION('center_axis',(0.,0.,-1.)); +#920=DIRECTION('ref_axis',(-1.,0.,0.)); +#921=DIRECTION('center_axis',(0.,0.,1.)); +#922=DIRECTION('ref_axis',(-0.133333333333305,0.991071249821237,0.)); +#923=DIRECTION('',(0.,0.,1.)); +#924=DIRECTION('center_axis',(0.,1.,0.)); +#925=DIRECTION('ref_axis',(1.,0.,0.)); +#926=DIRECTION('',(0.,0.,1.)); +#927=DIRECTION('',(-1.,-1.457905051083E-13,0.)); +#928=DIRECTION('',(0.,0.,1.)); +#929=DIRECTION('',(0.707106781186547,0.,0.707106781186547)); +#930=DIRECTION('',(1.,-3.855466060594E-13,0.)); +#931=DIRECTION('center_axis',(0.,0.,1.)); +#932=DIRECTION('ref_axis',(1.,0.,0.)); +#933=DIRECTION('center_axis',(0.,0.,-1.)); +#934=DIRECTION('ref_axis',(-0.979795897113273,0.199999999999994,0.)); +#935=DIRECTION('center_axis',(0.,0.,1.)); +#936=DIRECTION('ref_axis',(-0.199999999999994,0.979795897113273,0.)); +#937=DIRECTION('center_axis',(0.,0.,-1.)); +#938=DIRECTION('ref_axis',(-1.,0.,0.)); +#939=DIRECTION('center_axis',(0.,0.,1.)); +#940=DIRECTION('ref_axis',(1.,0.,0.)); +#941=DIRECTION('center_axis',(0.707106781186548,0.,-0.707106781186548)); +#942=DIRECTION('ref_axis',(0.707106781186548,0.,0.707106781186548)); +#943=DIRECTION('',(-0.707106781186547,0.,-0.707106781186547)); +#944=DIRECTION('',(0.,1.,0.)); +#945=DIRECTION('center_axis',(0.,-1.,0.)); +#946=DIRECTION('ref_axis',(-1.,0.,0.)); +#947=DIRECTION('',(0.,0.,1.)); +#948=DIRECTION('',(0.,0.,-1.)); +#949=DIRECTION('',(1.,-1.457905051083E-13,0.)); +#950=DIRECTION('',(0.,0.,-1.)); +#951=DIRECTION('',(-1.,-3.785366677674E-13,0.)); +#952=DIRECTION('',(0.,0.,-1.)); +#953=DIRECTION('center_axis',(0.,0.,-1.)); +#954=DIRECTION('ref_axis',(-1.,0.,0.)); +#955=DIRECTION('center_axis',(0.,0.,1.)); +#956=DIRECTION('ref_axis',(-0.991071249821237,-0.133333333333305,0.)); +#957=DIRECTION('',(0.,0.,1.)); +#958=DIRECTION('center_axis',(-1.,0.,0.)); +#959=DIRECTION('ref_axis',(0.,1.,0.)); +#960=DIRECTION('',(0.,0.,1.)); +#961=DIRECTION('',(1.457905051083E-13,-1.,0.)); +#962=DIRECTION('',(0.,0.,1.)); +#963=DIRECTION('',(0.,0.707106781186547,0.707106781186547)); +#964=DIRECTION('',(3.855466060594E-13,1.,0.)); +#965=DIRECTION('center_axis',(0.,0.,1.)); +#966=DIRECTION('ref_axis',(1.,0.,0.)); +#967=DIRECTION('center_axis',(0.,0.,-1.)); +#968=DIRECTION('ref_axis',(-0.199999999999994,-0.979795897113273,0.)); +#969=DIRECTION('center_axis',(0.,0.,1.)); +#970=DIRECTION('ref_axis',(-0.979795897113273,-0.199999999999994,0.)); +#971=DIRECTION('center_axis',(0.,0.,-1.)); +#972=DIRECTION('ref_axis',(-1.,0.,0.)); +#973=DIRECTION('center_axis',(0.,0.,1.)); +#974=DIRECTION('ref_axis',(1.,0.,0.)); +#975=DIRECTION('center_axis',(0.,0.707106781186548,-0.707106781186548)); +#976=DIRECTION('ref_axis',(0.,0.707106781186548,0.707106781186548)); +#977=DIRECTION('',(0.,-0.707106781186547,-0.707106781186547)); +#978=DIRECTION('',(-1.,0.,0.)); +#979=DIRECTION('center_axis',(-1.,0.,0.)); +#980=DIRECTION('ref_axis',(0.,1.,0.)); +#981=DIRECTION('',(0.,0.,1.)); +#982=DIRECTION('',(0.,0.,-1.)); +#983=DIRECTION('',(-1.457905051083E-13,-1.,0.)); +#984=DIRECTION('',(0.,0.,-1.)); +#985=DIRECTION('',(3.785366677674E-13,-1.,0.)); +#986=DIRECTION('',(0.,0.,-1.)); +#987=DIRECTION('center_axis',(0.,0.,-1.)); +#988=DIRECTION('ref_axis',(-1.,0.,0.)); +#989=DIRECTION('center_axis',(0.,0.,1.)); +#990=DIRECTION('ref_axis',(0.133333333333305,-0.991071249821237,0.)); +#991=DIRECTION('',(0.,0.,1.)); +#992=DIRECTION('center_axis',(0.,1.,0.)); +#993=DIRECTION('ref_axis',(1.,0.,0.)); +#994=DIRECTION('',(0.,0.,1.)); +#995=DIRECTION('',(-1.,-1.457905051083E-13,0.)); +#996=DIRECTION('',(0.,0.,1.)); +#997=DIRECTION('',(-0.707106781186547,0.,0.707106781186547)); +#998=DIRECTION('',(-1.,3.785366677674E-13,0.)); +#999=DIRECTION('center_axis',(0.,0.,-1.)); +#1000=DIRECTION('ref_axis',(-1.,0.,0.)); +#1001=DIRECTION('center_axis',(0.,0.,-1.)); +#1002=DIRECTION('ref_axis',(0.979795897113273,-0.199999999999994,0.)); +#1003=DIRECTION('center_axis',(0.,0.,1.)); +#1004=DIRECTION('ref_axis',(0.199999999999994,-0.979795897113273,0.)); +#1005=DIRECTION('center_axis',(0.,0.,-1.)); +#1006=DIRECTION('ref_axis',(-1.,0.,0.)); +#1007=DIRECTION('center_axis',(0.,0.,-1.)); +#1008=DIRECTION('ref_axis',(-1.,0.,0.)); +#1009=DIRECTION('center_axis',(-0.707106781186548,0.,-0.707106781186548)); +#1010=DIRECTION('ref_axis',(-0.707106781186548,0.,0.707106781186548)); +#1011=DIRECTION('',(0.,-1.,0.)); +#1012=DIRECTION('center_axis',(1.,0.,0.)); +#1013=DIRECTION('ref_axis',(0.,-1.,0.)); +#1014=DIRECTION('center_axis',(0.,-1.,0.)); +#1015=DIRECTION('ref_axis',(-1.,0.,0.)); +#1016=DIRECTION('center_axis',(-1.,0.,0.)); +#1017=DIRECTION('ref_axis',(0.,1.,0.)); +#1018=DIRECTION('center_axis',(0.,1.,0.)); +#1019=DIRECTION('ref_axis',(1.,0.,0.)); +#1020=DIRECTION('',(1.,1.7763568394E-14,-3.663735981263E-14)); +#1021=DIRECTION('center_axis',(0.,-0.707106781186598,-0.707106781186498)); +#1022=DIRECTION('ref_axis',(0.,-0.707106781186498,0.707106781186598)); +#1023=DIRECTION('center_axis',(0.,0.,1.)); +#1024=DIRECTION('ref_axis',(1.,0.,0.)); +#1025=DIRECTION('center_axis',(0.,0.,-1.)); +#1026=DIRECTION('ref_axis',(-1.,0.,0.)); +#1027=DIRECTION('center_axis',(0.,-1.,0.)); +#1028=DIRECTION('ref_axis',(-1.,0.,0.)); +#1029=DIRECTION('center_axis',(0.,0.,1.)); +#1030=DIRECTION('ref_axis',(1.,0.,0.)); +#1031=DIRECTION('',(0.,0.,1.)); +#1032=DIRECTION('',(1.,0.,0.)); +#1033=CARTESIAN_POINT('',(0.,0.,0.)); +#1034=CARTESIAN_POINT('',(0.,0.,0.)); +#1035=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1036=CARTESIAN_POINT('',(-35.5,40.25,9.9)); +#1037=CARTESIAN_POINT('Origin',(-32.5,40.25,9.9)); +#1038=CARTESIAN_POINT('',(-35.5,40.25,6.9)); +#1039=CARTESIAN_POINT('',(-35.5,40.25,4.6)); +#1040=CARTESIAN_POINT('Origin',(-32.5,40.25,6.9)); +#1041=CARTESIAN_POINT('Origin',(0.,0.,6.9)); +#1042=CARTESIAN_POINT('',(-28.5,40.25,6.9)); +#1043=CARTESIAN_POINT('Origin',(-32.5,40.25,6.9)); +#1044=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1045=CARTESIAN_POINT('',(-28.5,40.25,4.6)); +#1046=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1047=CARTESIAN_POINT('',(-28.5,40.25,4.6)); +#1048=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1049=CARTESIAN_POINT('',(-32.1,42.15,4.6)); +#1050=CARTESIAN_POINT('',(-32.1,43.22321374946,4.6)); +#1051=CARTESIAN_POINT('',(-32.1,42.15,4.6)); +#1052=CARTESIAN_POINT('',(-32.9,42.15,4.6)); +#1053=CARTESIAN_POINT('',(-32.9,42.15,4.6)); +#1054=CARTESIAN_POINT('',(-32.9,43.22321374946,4.6)); +#1055=CARTESIAN_POINT('',(-32.9,43.22321374946,4.6)); +#1056=CARTESIAN_POINT('',(-35.47321374946,40.65,4.6)); +#1057=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1058=CARTESIAN_POINT('',(-34.4,40.65,4.6)); +#1059=CARTESIAN_POINT('',(-34.4,40.65,4.6)); +#1060=CARTESIAN_POINT('',(-34.4,39.85,4.6)); +#1061=CARTESIAN_POINT('',(-34.4,39.85,4.6)); +#1062=CARTESIAN_POINT('',(-35.47321374946,39.85,4.6)); +#1063=CARTESIAN_POINT('',(-35.47321374946,39.85,4.6)); +#1064=CARTESIAN_POINT('',(-32.9,37.27678625054,4.6)); +#1065=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1066=CARTESIAN_POINT('',(-32.9,38.35,4.6)); +#1067=CARTESIAN_POINT('',(-32.9,38.35,4.6)); +#1068=CARTESIAN_POINT('',(-32.1,38.35,4.6)); +#1069=CARTESIAN_POINT('',(-32.1,38.35,4.6)); +#1070=CARTESIAN_POINT('',(-32.1,37.27678625054,4.6)); +#1071=CARTESIAN_POINT('',(-32.1,37.27678625054,4.6)); +#1072=CARTESIAN_POINT('',(-29.52678625054,39.85,4.6)); +#1073=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1074=CARTESIAN_POINT('',(-30.6,39.85,4.6)); +#1075=CARTESIAN_POINT('',(-30.6,39.85,4.6)); +#1076=CARTESIAN_POINT('',(-30.6,40.65,4.6)); +#1077=CARTESIAN_POINT('',(-30.6,40.65,4.6)); +#1078=CARTESIAN_POINT('',(-29.52678625054,40.65,4.6)); +#1079=CARTESIAN_POINT('',(-29.52678625054,40.65,4.6)); +#1080=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1081=CARTESIAN_POINT('Origin',(-32.1,40.65,4.6)); +#1082=CARTESIAN_POINT('',(-32.1,42.20959179423,5.9)); +#1083=CARTESIAN_POINT('',(-32.1,42.20959179423,9.1)); +#1084=CARTESIAN_POINT('',(-32.1,42.20959179423,5.9)); +#1085=CARTESIAN_POINT('',(-32.1,40.65,9.1)); +#1086=CARTESIAN_POINT('',(-32.1,42.20959179423,9.1)); +#1087=CARTESIAN_POINT('',(-32.1,40.65,7.1)); +#1088=CARTESIAN_POINT('',(-32.1,40.65,9.1)); +#1089=CARTESIAN_POINT('',(-32.1,41.55,7.1)); +#1090=CARTESIAN_POINT('',(-32.1,40.65,7.1)); +#1091=CARTESIAN_POINT('',(-32.1,41.55,5.2)); +#1092=CARTESIAN_POINT('',(-32.1,41.55,5.2)); +#1093=CARTESIAN_POINT('',(-32.1,42.15,4.6)); +#1094=CARTESIAN_POINT('',(-32.1,43.22321374946,5.9)); +#1095=CARTESIAN_POINT('',(-32.1,43.22321374946,4.6)); +#1096=CARTESIAN_POINT('',(-32.1,43.22321374946,5.9)); +#1097=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1098=CARTESIAN_POINT('',(-30.54040820577,40.65,5.9)); +#1099=CARTESIAN_POINT('Origin',(-32.5,40.25,5.9)); +#1100=CARTESIAN_POINT('',(-30.54040820577,40.65,9.1)); +#1101=CARTESIAN_POINT('',(-30.54040820577,40.65,9.1)); +#1102=CARTESIAN_POINT('Origin',(-32.5,40.25,9.1)); +#1103=CARTESIAN_POINT('Origin',(0.,0.,5.9)); +#1104=CARTESIAN_POINT('',(-29.52678625054,40.65,5.9)); +#1105=CARTESIAN_POINT('Origin',(-32.5,40.25,5.9)); +#1106=CARTESIAN_POINT('',(-30.54040820577,40.65,5.9)); +#1107=CARTESIAN_POINT('Origin',(-30.54040820577,40.65,4.6)); +#1108=CARTESIAN_POINT('',(-31.2,40.65,5.2)); +#1109=CARTESIAN_POINT('',(-31.2,40.65,5.2)); +#1110=CARTESIAN_POINT('',(-31.2,40.65,7.1)); +#1111=CARTESIAN_POINT('',(-31.2,40.65,5.2)); +#1112=CARTESIAN_POINT('',(-32.1,40.65,7.1)); +#1113=CARTESIAN_POINT('',(-32.1,40.65,9.1)); +#1114=CARTESIAN_POINT('',(-29.52678625054,40.65,5.9)); +#1115=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1116=CARTESIAN_POINT('Origin',(0.,0.,9.1)); +#1117=CARTESIAN_POINT('Origin',(0.,0.,7.1)); +#1118=CARTESIAN_POINT('',(-32.9,40.65,7.1)); +#1119=CARTESIAN_POINT('',(-32.9,41.55,7.1)); +#1120=CARTESIAN_POINT('',(-32.9,40.65,7.1)); +#1121=CARTESIAN_POINT('',(-32.1,41.55,7.1)); +#1122=CARTESIAN_POINT('',(-31.2,39.85,7.1)); +#1123=CARTESIAN_POINT('',(-31.2,39.85,7.1)); +#1124=CARTESIAN_POINT('',(-32.1,39.85,7.1)); +#1125=CARTESIAN_POINT('',(-32.1,39.85,7.1)); +#1126=CARTESIAN_POINT('',(-32.1,38.95,7.1)); +#1127=CARTESIAN_POINT('',(-32.1,39.85,7.1)); +#1128=CARTESIAN_POINT('',(-32.9,38.95,7.1)); +#1129=CARTESIAN_POINT('',(-32.9,38.95,7.1)); +#1130=CARTESIAN_POINT('',(-32.9,39.85,7.1)); +#1131=CARTESIAN_POINT('',(-32.9,39.85,7.1)); +#1132=CARTESIAN_POINT('',(-33.8,39.85,7.1)); +#1133=CARTESIAN_POINT('',(-32.9,39.85,7.1)); +#1134=CARTESIAN_POINT('',(-33.8,40.65,7.1)); +#1135=CARTESIAN_POINT('',(-33.8,40.65,7.1)); +#1136=CARTESIAN_POINT('',(-32.9,40.65,7.1)); +#1137=CARTESIAN_POINT('Origin',(-32.9,40.65,4.6)); +#1138=CARTESIAN_POINT('',(-32.9,41.55,5.2)); +#1139=CARTESIAN_POINT('',(-32.9,41.55,5.2)); +#1140=CARTESIAN_POINT('',(-32.9,41.55,5.2)); +#1141=CARTESIAN_POINT('',(-32.9,40.65,9.1)); +#1142=CARTESIAN_POINT('',(-32.9,40.65,9.1)); +#1143=CARTESIAN_POINT('',(-32.9,42.20959179423,9.1)); +#1144=CARTESIAN_POINT('',(-32.9,42.20959179423,9.1)); +#1145=CARTESIAN_POINT('',(-32.9,42.20959179423,5.9)); +#1146=CARTESIAN_POINT('',(-32.9,42.20959179423,9.1)); +#1147=CARTESIAN_POINT('',(-32.9,43.22321374946,5.9)); +#1148=CARTESIAN_POINT('',(-32.9,42.20959179423,5.9)); +#1149=CARTESIAN_POINT('',(-32.9,43.22321374946,5.9)); +#1150=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1151=CARTESIAN_POINT('',(-35.47321374946,40.65,5.9)); +#1152=CARTESIAN_POINT('Origin',(-32.5,40.25,5.9)); +#1153=CARTESIAN_POINT('',(-35.47321374946,40.65,4.6)); +#1154=CARTESIAN_POINT('Origin',(-34.45959179423,40.65,4.6)); +#1155=CARTESIAN_POINT('',(-34.45959179423,40.65,5.9)); +#1156=CARTESIAN_POINT('',(-34.45959179423,40.65,9.1)); +#1157=CARTESIAN_POINT('',(-34.45959179423,40.65,5.9)); +#1158=CARTESIAN_POINT('',(-32.9,40.65,9.1)); +#1159=CARTESIAN_POINT('',(-33.8,40.65,5.2)); +#1160=CARTESIAN_POINT('',(-33.8,40.65,5.2)); +#1161=CARTESIAN_POINT('',(-34.4,40.65,4.6)); +#1162=CARTESIAN_POINT('',(-35.47321374946,40.65,5.9)); +#1163=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1164=CARTESIAN_POINT('Origin',(-32.5,40.25,5.9)); +#1165=CARTESIAN_POINT('Origin',(-32.5,40.25,9.1)); +#1166=CARTESIAN_POINT('Origin',(0.,0.,5.9)); +#1167=CARTESIAN_POINT('Origin',(-65.,0.,9.1)); +#1168=CARTESIAN_POINT('Origin',(-34.1,40.25,4.9)); +#1169=CARTESIAN_POINT('',(-33.8,39.85,5.2)); +#1170=CARTESIAN_POINT('',(-33.8,39.85,5.2)); +#1171=CARTESIAN_POINT('',(-33.8,39.85,5.2)); +#1172=CARTESIAN_POINT('Origin',(-32.9,39.85,4.6)); +#1173=CARTESIAN_POINT('',(-33.8,39.85,5.2)); +#1174=CARTESIAN_POINT('',(-32.9,39.85,9.1)); +#1175=CARTESIAN_POINT('',(-32.9,39.85,9.1)); +#1176=CARTESIAN_POINT('',(-34.45959179423,39.85,9.1)); +#1177=CARTESIAN_POINT('',(-34.45959179423,39.85,9.1)); +#1178=CARTESIAN_POINT('',(-34.45959179423,39.85,5.9)); +#1179=CARTESIAN_POINT('',(-34.45959179423,39.85,9.1)); +#1180=CARTESIAN_POINT('',(-35.47321374946,39.85,5.9)); +#1181=CARTESIAN_POINT('',(-34.45959179423,39.85,5.9)); +#1182=CARTESIAN_POINT('',(-35.47321374946,39.85,5.9)); +#1183=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1184=CARTESIAN_POINT('',(-32.9,37.27678625054,5.9)); +#1185=CARTESIAN_POINT('Origin',(-32.5,40.25,5.9)); +#1186=CARTESIAN_POINT('',(-32.9,37.27678625054,4.6)); +#1187=CARTESIAN_POINT('Origin',(-32.9,38.29040820577,4.6)); +#1188=CARTESIAN_POINT('',(-32.9,38.29040820577,5.9)); +#1189=CARTESIAN_POINT('',(-32.9,38.29040820577,9.1)); +#1190=CARTESIAN_POINT('',(-32.9,38.29040820577,5.9)); +#1191=CARTESIAN_POINT('',(-32.9,39.85,9.1)); +#1192=CARTESIAN_POINT('',(-32.9,38.95,5.2)); +#1193=CARTESIAN_POINT('',(-32.9,38.95,5.2)); +#1194=CARTESIAN_POINT('',(-32.9,38.35,4.6)); +#1195=CARTESIAN_POINT('',(-32.9,37.27678625054,5.9)); +#1196=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1197=CARTESIAN_POINT('Origin',(-32.5,40.25,5.9)); +#1198=CARTESIAN_POINT('Origin',(-32.5,40.25,9.1)); +#1199=CARTESIAN_POINT('Origin',(0.,0.,5.9)); +#1200=CARTESIAN_POINT('Origin',(-65.,0.,9.1)); +#1201=CARTESIAN_POINT('Origin',(-32.5,38.65,4.9)); +#1202=CARTESIAN_POINT('',(-32.1,38.95,5.2)); +#1203=CARTESIAN_POINT('',(-32.1,38.95,5.2)); +#1204=CARTESIAN_POINT('',(-32.1,38.95,5.2)); +#1205=CARTESIAN_POINT('Origin',(-32.1,38.29040820577,4.6)); +#1206=CARTESIAN_POINT('',(-32.1,38.95,5.2)); +#1207=CARTESIAN_POINT('',(-32.1,39.85,9.1)); +#1208=CARTESIAN_POINT('',(-32.1,39.85,9.1)); +#1209=CARTESIAN_POINT('',(-32.1,38.29040820577,9.1)); +#1210=CARTESIAN_POINT('',(-32.1,39.85,9.1)); +#1211=CARTESIAN_POINT('',(-32.1,38.29040820577,5.9)); +#1212=CARTESIAN_POINT('',(-32.1,38.29040820577,9.1)); +#1213=CARTESIAN_POINT('',(-32.1,37.27678625054,5.9)); +#1214=CARTESIAN_POINT('',(-32.1,38.29040820577,5.9)); +#1215=CARTESIAN_POINT('',(-32.1,37.27678625054,5.9)); +#1216=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1217=CARTESIAN_POINT('',(-29.52678625054,39.85,5.9)); +#1218=CARTESIAN_POINT('Origin',(-32.5,40.25,5.9)); +#1219=CARTESIAN_POINT('',(-29.52678625054,39.85,4.6)); +#1220=CARTESIAN_POINT('Origin',(-32.1,39.85,4.6)); +#1221=CARTESIAN_POINT('',(-30.54040820577,39.85,5.9)); +#1222=CARTESIAN_POINT('',(-30.54040820577,39.85,9.1)); +#1223=CARTESIAN_POINT('',(-30.54040820577,39.85,5.9)); +#1224=CARTESIAN_POINT('',(-30.54040820577,39.85,9.1)); +#1225=CARTESIAN_POINT('',(-31.2,39.85,5.2)); +#1226=CARTESIAN_POINT('',(-31.2,39.85,5.2)); +#1227=CARTESIAN_POINT('',(-30.6,39.85,4.6)); +#1228=CARTESIAN_POINT('',(-29.52678625054,39.85,5.9)); +#1229=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6)); +#1230=CARTESIAN_POINT('Origin',(-32.5,40.25,5.9)); +#1231=CARTESIAN_POINT('Origin',(-32.5,40.25,9.1)); +#1232=CARTESIAN_POINT('Origin',(0.,0.,5.9)); +#1233=CARTESIAN_POINT('Origin',(0.,0.,9.1)); +#1234=CARTESIAN_POINT('Origin',(-30.9,40.25,4.9)); +#1235=CARTESIAN_POINT('',(-31.2,40.65,5.2)); +#1236=CARTESIAN_POINT('Origin',(-31.2,41.55,4.6)); +#1237=CARTESIAN_POINT('Origin',(-31.2,38.95,4.6)); +#1238=CARTESIAN_POINT('Origin',(-33.8,38.95,4.6)); +#1239=CARTESIAN_POINT('Origin',(-33.8,41.55,4.6)); +#1240=CARTESIAN_POINT('',(-32.9,41.55,5.2)); +#1241=CARTESIAN_POINT('Origin',(-32.5,41.85,4.9)); +#1242=CARTESIAN_POINT('Origin',(-32.5,40.25,9.9)); +#1243=CARTESIAN_POINT('',(-35.3,40.25,10.1)); +#1244=CARTESIAN_POINT('Origin',(-32.5,40.25,10.1)); +#1245=CARTESIAN_POINT('Origin',(-35.3,40.25,9.9)); +#1246=CARTESIAN_POINT('Origin',(-32.5,40.25,10.1)); +#1247=CARTESIAN_POINT('',(58.1672236319,12.16722114154,-9.067222041201)); +#1248=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#1254, 'DISTANCE_ACCURACY_VALUE', 'Maximum model space distance between geometric entities at asserted c onnectivities'); -#930=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#933, +#1249=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#1254, 'DISTANCE_ACCURACY_VALUE', 'Maximum model space distance between geometric entities at asserted c onnectivities'); -#931=( +#1250=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#1254, +'DISTANCE_ACCURACY_VALUE', +'Maximum model space distance between geometric entities at asserted c +onnectivities'); +#1251=( GEOMETRIC_REPRESENTATION_CONTEXT(3) -GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#929)) -GLOBAL_UNIT_ASSIGNED_CONTEXT((#933,#934,#935)) +GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#1248)) +GLOBAL_UNIT_ASSIGNED_CONTEXT((#1254,#1256,#1257)) REPRESENTATION_CONTEXT('','3D') ); -#932=( +#1252=( GEOMETRIC_REPRESENTATION_CONTEXT(3) -GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#930)) -GLOBAL_UNIT_ASSIGNED_CONTEXT((#933,#934,#935)) +GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#1249)) +GLOBAL_UNIT_ASSIGNED_CONTEXT((#1254,#1256,#1257)) REPRESENTATION_CONTEXT('','3D') ); -#933=( +#1253=( +GEOMETRIC_REPRESENTATION_CONTEXT(3) +GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#1250)) +GLOBAL_UNIT_ASSIGNED_CONTEXT((#1254,#1256,#1257)) +REPRESENTATION_CONTEXT('','3D') +); +#1254=( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) ); -#934=( +#1255=( +LENGTH_UNIT() +NAMED_UNIT(*) +SI_UNIT($,.METRE.) +); +#1256=( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) ); -#935=( +#1257=( NAMED_UNIT(*) SI_UNIT($,.STERADIAN.) SOLID_ANGLE_UNIT() ); -#936=SHAPE_DEFINITION_REPRESENTATION(#937,#938); -#937=PRODUCT_DEFINITION_SHAPE('',$,#940); -#938=SHAPE_REPRESENTATION('',(#528),#931); -#939=PRODUCT_DEFINITION_CONTEXT('part definition',#944,'design'); -#940=PRODUCT_DEFINITION('sc64_shell reworked','sc64_shell reworked v13', -#941,#939); -#941=PRODUCT_DEFINITION_FORMATION('',$,#946); -#942=PRODUCT_RELATED_PRODUCT_CATEGORY('sc64_shell reworked v13', -'sc64_shell reworked v13',(#946)); -#943=APPLICATION_PROTOCOL_DEFINITION('international standard', -'automotive_design',2009,#944); -#944=APPLICATION_CONTEXT( +#1258=SHAPE_DEFINITION_REPRESENTATION(#1260,#1263); +#1259=SHAPE_DEFINITION_REPRESENTATION(#1261,#1264); +#1260=PRODUCT_DEFINITION_SHAPE('',$,#1266); +#1261=PRODUCT_DEFINITION_SHAPE('',$,#1267); +#1262=PRODUCT_DEFINITION_SHAPE($,$,#14); +#1263=SHAPE_REPRESENTATION('',(#759,#822),#1251); +#1264=SHAPE_REPRESENTATION('',(#760),#1252); +#1265=PRODUCT_DEFINITION_CONTEXT('part definition',#1273,'design'); +#1266=PRODUCT_DEFINITION('button','button v1',#1268,#1265); +#1267=PRODUCT_DEFINITION('SC64_SHELL_BUTTON-20240702', +'SC64_SHELL_BUTTON-20240702',#1269,#1265); +#1268=PRODUCT_DEFINITION_FORMATION('',$,#1275); +#1269=PRODUCT_DEFINITION_FORMATION('',$,#1276); +#1270=PRODUCT_RELATED_PRODUCT_CATEGORY('button v1','button v1',(#1275)); +#1271=PRODUCT_RELATED_PRODUCT_CATEGORY('SC64_SHELL_BUTTON-20240702', +'SC64_SHELL_BUTTON-20240702',(#1276)); +#1272=APPLICATION_PROTOCOL_DEFINITION('international standard', +'automotive_design',2009,#1273); +#1273=APPLICATION_CONTEXT( 'Core Data for Automotive Mechanical Design Process'); -#945=PRODUCT_CONTEXT('part definition',#944,'mechanical'); -#946=PRODUCT('sc64_shell reworked','sc64_shell reworked v13',$,(#945)); -#947=PRESENTATION_STYLE_ASSIGNMENT((#951)); -#948=PRESENTATION_STYLE_ASSIGNMENT((#952)); -#949=PRESENTATION_STYLE_ASSIGNMENT((#953)); -#950=PRESENTATION_STYLE_ASSIGNMENT((#954)); -#951=SURFACE_STYLE_USAGE(.BOTH.,#955); -#952=SURFACE_STYLE_USAGE(.BOTH.,#956); -#953=SURFACE_STYLE_USAGE(.BOTH.,#957); -#954=SURFACE_STYLE_USAGE(.BOTH.,#958); -#955=SURFACE_SIDE_STYLE('',(#959)); -#956=SURFACE_SIDE_STYLE('',(#960)); -#957=SURFACE_SIDE_STYLE('',(#961)); -#958=SURFACE_SIDE_STYLE('',(#962)); -#959=SURFACE_STYLE_FILL_AREA(#963); -#960=SURFACE_STYLE_FILL_AREA(#964); -#961=SURFACE_STYLE_FILL_AREA(#965); -#962=SURFACE_STYLE_FILL_AREA(#966); -#963=FILL_AREA_STYLE('Steel - Satin',(#967)); -#964=FILL_AREA_STYLE('Plastic - Translucent Matte (Blue)',(#968)); -#965=FILL_AREA_STYLE('Powder Coat - Rough (White)',(#969)); -#966=FILL_AREA_STYLE('Plastic - Glossy (Black)',(#970)); -#967=FILL_AREA_STYLE_COLOUR('Steel - Satin',#971); -#968=FILL_AREA_STYLE_COLOUR('Plastic - Translucent Matte (Blue)',#972); -#969=FILL_AREA_STYLE_COLOUR('Powder Coat - Rough (White)',#973); -#970=FILL_AREA_STYLE_COLOUR('Plastic - Glossy (Black)',#974); -#971=COLOUR_RGB('Steel - Satin',0.627450980392157,0.627450980392157,0.627450980392157); -#972=COLOUR_RGB('Plastic - Translucent Matte (Blue)',0.188235294117647, -0.231372549019608,0.588235294117647); -#973=COLOUR_RGB('Powder Coat - Rough (White)',0.964705882352941,0.964705882352941, -0.952941176470588); -#974=COLOUR_RGB('Plastic - Glossy (Black)',0.0980392156862745,0.0980392156862745, -0.0980392156862745); +#1274=PRODUCT_CONTEXT('part definition',#1273,'mechanical'); +#1275=PRODUCT('button','button v1',$,(#1274)); +#1276=PRODUCT('SC64_SHELL_BUTTON-20240702','SC64_SHELL_BUTTON-20240702', +$,(#1274)); +#1277=PRESENTATION_STYLE_ASSIGNMENT((#1279)); +#1278=PRESENTATION_STYLE_ASSIGNMENT((#1280)); +#1279=SURFACE_STYLE_USAGE(.BOTH.,#1281); +#1280=SURFACE_STYLE_USAGE(.BOTH.,#1282); +#1281=SURFACE_SIDE_STYLE('',(#1283)); +#1282=SURFACE_SIDE_STYLE('',(#1284)); +#1283=SURFACE_STYLE_FILL_AREA(#1285); +#1284=SURFACE_STYLE_FILL_AREA(#1286); +#1285=FILL_AREA_STYLE('Steel - Satin',(#1287)); +#1286=FILL_AREA_STYLE('Opaque(211,255,71)',(#1288)); +#1287=FILL_AREA_STYLE_COLOUR('Steel - Satin',#1289); +#1288=FILL_AREA_STYLE_COLOUR('Opaque(211,255,71)',#1290); +#1289=COLOUR_RGB('Steel - Satin',0.627450980392157,0.627450980392157,0.627450980392157); +#1290=COLOUR_RGB('Opaque(211,255,71)',0.827450980392157,1.,0.27843137254902); ENDSEC; END-ISO-10303-21; From 5e33e516a292262af63856e6fec64cedcdabf815 Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Sun, 21 Jul 2024 10:48:20 +0200 Subject: [PATCH 2/2] [SC64][SW] Implement new libftdi backend in the sc64deployer (#72) --- .github/workflows/build.yml | 8 +- fw/rtl/mcu/mcu_top.sv | 20 +- fw/rtl/memory/memory_dma.sv | 16 +- fw/rtl/usb/usb_ft1248.sv | 62 +-- sw/controller/src/fpga.h | 5 +- sw/controller/src/usb.c | 136 +++--- sw/deployer/Cargo.lock | 828 +++++++++++++++++++++++++++------ sw/deployer/Cargo.toml | 22 +- sw/deployer/src/debug.rs | 12 +- sw/deployer/src/main.rs | 54 ++- sw/deployer/src/sc64/error.rs | 6 - sw/deployer/src/sc64/ftdi.rs | 540 +++++++++++++++++++++ sw/deployer/src/sc64/link.rs | 501 ++++++++++++-------- sw/deployer/src/sc64/mod.rs | 21 +- sw/deployer/src/sc64/serial.rs | 159 +++++++ sw/deployer/src/sc64/server.rs | 380 ++++++--------- sw/deployer/src/sc64/types.rs | 51 +- 17 files changed, 2074 insertions(+), 747 deletions(-) create mode 100644 sw/deployer/src/sc64/ftdi.rs create mode 100644 sw/deployer/src/sc64/serial.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc16f03..af4ea64 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,7 +71,7 @@ jobs: - version: linux os: ubuntu-latest - linux-packages: libudev-dev + apt-packages: libudev-dev executable: target/release/sc64deployer package-name: sc64-deployer-linux package-params: -czf @@ -98,11 +98,11 @@ jobs: string: '${{ github.ref_name }}' replace-with: '-' - - name: Install linux packages - if: matrix.linux-packages + - name: Install apt packages + if: matrix.apt-packages run: | sudo apt-get update - sudo apt-get -y install ${{ matrix.linux-packages }} + sudo apt-get -y install ${{ matrix.apt-packages }} - name: Build deployer run: cargo b -r ${{ matrix.build-params }} diff --git a/fw/rtl/mcu/mcu_top.sv b/fw/rtl/mcu/mcu_top.sv index a0540d5..41b9627 100644 --- a/fw/rtl/mcu/mcu_top.sv +++ b/fw/rtl/mcu/mcu_top.sv @@ -394,13 +394,13 @@ module mcu_top ( REG_USB_SCR: begin reg_rdata <= { - 2'd0, + 1'd0, + usb_scb.fifo_flush_busy, usb_scb.pwrsav, usb_scb.reset_state, usb_scb.tx_count, usb_scb.rx_count, - 2'b00, - usb_scb.reset_pending, + 3'b000, ~fifo_bus.tx_full, ~fifo_bus.rx_empty, 1'b0 @@ -681,9 +681,10 @@ module mcu_top ( mem_start <= 1'b0; mem_stop <= 1'b0; - usb_scb.write_buffer_flush <= 1'b0; - usb_scb.reset_ack <= 1'b0; usb_scb.fifo_flush <= 1'b0; + usb_scb.write_buffer_flush <= 1'b0; + usb_scb.reset_on_ack <= 1'b0; + usb_scb.reset_off_ack <= 1'b0; usb_dma_scb.start <= 1'b0; usb_dma_scb.stop <= 1'b0; @@ -770,11 +771,10 @@ module mcu_top ( end REG_USB_SCR: begin - { - usb_scb.write_buffer_flush, - usb_scb.reset_ack, - usb_scb.fifo_flush - } <= {reg_wdata[5:4], reg_wdata[0]}; + usb_scb.write_buffer_flush <= reg_wdata[5]; + usb_scb.reset_off_ack <= reg_wdata[4]; + usb_scb.reset_on_ack <= reg_wdata[3]; + usb_scb.fifo_flush <= reg_wdata[0]; end REG_USB_DMA_ADDRESS: begin diff --git a/fw/rtl/memory/memory_dma.sv b/fw/rtl/memory/memory_dma.sv index b401ddf..bfd15d6 100644 --- a/fw/rtl/memory/memory_dma.sv +++ b/fw/rtl/memory/memory_dma.sv @@ -45,12 +45,26 @@ module memory_dma ( logic dma_start; logic dma_stop; + logic dma_stop_requested; always_comb begin dma_start = dma_scb.start && !dma_scb.stop && !dma_scb.busy; dma_stop = dma_scb.stop; end + always_ff @(posedge clk) begin + if (reset) begin + dma_stop_requested <= 1'b0; + end else begin + if (dma_stop) begin + dma_stop_requested <= 1'b1; + end + if (dma_start) begin + dma_stop_requested <= 1'b0; + end + end + end + // Remaining counter and FIFO enable @@ -197,7 +211,7 @@ module memory_dma ( remaining <= dma_scb.transfer_length; end - if ((mem_bus.write && rx_rdata_pop) || (!mem_bus.write && tx_wdata_push)) begin + if (!dma_stop_requested && ((mem_bus.write && rx_rdata_pop) || (!mem_bus.write && tx_wdata_push))) begin remaining <= remaining - 1'd1; end end diff --git a/fw/rtl/usb/usb_ft1248.sv b/fw/rtl/usb/usb_ft1248.sv index 9b2153b..d60d8ad 100644 --- a/fw/rtl/usb/usb_ft1248.sv +++ b/fw/rtl/usb/usb_ft1248.sv @@ -1,34 +1,37 @@ interface usb_scb (); logic fifo_flush; - logic reset_pending; - logic reset_ack; + logic fifo_flush_busy; logic write_buffer_flush; logic [10:0] rx_count; logic [10:0] tx_count; logic pwrsav; logic reset_state; + logic reset_on_ack; + logic reset_off_ack; modport controller ( output fifo_flush, - input reset_pending, - output reset_ack, + input fifo_flush_busy, output write_buffer_flush, input rx_count, input tx_count, input pwrsav, - input reset_state + input reset_state, + output reset_on_ack, + output reset_off_ack ); modport usb ( input fifo_flush, - output reset_pending, - input reset_ack, + output fifo_flush_busy, input write_buffer_flush, output rx_count, output tx_count, output pwrsav, - output reset_state + output reset_state, + input reset_on_ack, + input reset_off_ack ); endinterface @@ -59,9 +62,11 @@ module usb_ft1248 ( logic tx_read; logic [7:0] tx_rdata; + logic fifo_flush; + fifo_8kb fifo_8kb_rx_inst ( .clk(clk), - .reset(reset || usb_scb.fifo_flush), + .reset(reset || fifo_flush), .empty(fifo_bus.rx_empty), .almost_empty(fifo_bus.rx_almost_empty), @@ -78,7 +83,7 @@ module usb_ft1248 ( fifo_8kb fifo_8kb_tx_inst ( .clk(clk), - .reset(reset || usb_scb.fifo_flush), + .reset(reset || fifo_flush), .empty(tx_empty), .almost_empty(tx_almost_empty), @@ -142,7 +147,6 @@ module usb_ft1248 ( logic [3:0] phase; logic last_tx_failed; logic reset_reply; - logic last_reset_status; logic [4:0] modem_status_counter; logic write_modem_status_pending; logic write_buffer_flush_pending; @@ -152,7 +156,7 @@ module usb_ft1248 ( cmd <= next_cmd; usb_scb.pwrsav <= !ft_pwrsav; - usb_scb.reset_state <= last_reset_status; + fifo_flush <= 1'b0; phase <= {phase[2:0], phase[3]}; if (state == STATE_IDLE) begin @@ -160,25 +164,38 @@ module usb_ft1248 ( end if (reset) begin + usb_scb.fifo_flush_busy <= 1'b0; + usb_scb.reset_state <= 1'b0; last_tx_failed <= 1'b0; - usb_scb.reset_pending <= 1'b0; - last_reset_status <= 1'b0; + reset_reply <= 1'b0; modem_status_counter <= 5'd0; - write_modem_status_pending <= 1'b0; + write_modem_status_pending <= 1'b1; write_buffer_flush_pending <= 1'b0; end else begin - if (usb_scb.reset_ack) begin - usb_scb.reset_pending <= 1'b0; + if (usb_scb.fifo_flush) begin + usb_scb.fifo_flush_busy <= 1'b1; + end + + if (usb_scb.reset_on_ack) begin reset_reply <= 1'b1; write_modem_status_pending <= 1'b1; end + if (usb_scb.reset_off_ack) begin + reset_reply <= 1'b0; + write_modem_status_pending <= 1'b1; + end + if (usb_scb.write_buffer_flush) begin write_buffer_flush_pending <= 1'b1; end if (state == STATE_IDLE) begin modem_status_counter <= modem_status_counter + 1'd1; + if (usb_scb.fifo_flush_busy) begin + usb_scb.fifo_flush_busy <= 1'b0; + fifo_flush <= 1'b1; + end end if ((state == STATE_DATA) && (cmd == CMD_WRITE) && phase[3]) begin @@ -187,14 +204,7 @@ module usb_ft1248 ( if (!ft_miso && (state == STATE_DATA) && phase[3]) begin if (cmd == CMD_READ_MODEM_STATUS) begin - last_reset_status <= ft_miosi_in[0]; - if (!last_reset_status && ft_miosi_in[0]) begin - usb_scb.reset_pending <= 1'b1; - end - if (last_reset_status && !ft_miosi_in[0]) begin - reset_reply <= 1'b0; - write_modem_status_pending <= 1'b1; - end + usb_scb.reset_state <= ft_miosi_in[0]; end if (cmd == CMD_WRITE_MODEM_STATUS) begin write_modem_status_pending <= 1'b0; @@ -283,7 +293,7 @@ module usb_ft1248 ( end else begin case (state) STATE_IDLE: begin - if (ft_pwrsav) begin + if (ft_pwrsav && !(usb_scb.fifo_flush || usb_scb.fifo_flush_busy || fifo_flush)) begin if (write_modem_status_pending) begin next_state = STATE_SELECT; next_cmd = CMD_WRITE_MODEM_STATUS; diff --git a/sw/controller/src/fpga.h b/sw/controller/src/fpga.h index 7c3f0d5..652cf54 100644 --- a/sw/controller/src/fpga.h +++ b/sw/controller/src/fpga.h @@ -79,8 +79,8 @@ typedef enum { #define USB_SCR_FIFO_FLUSH (1 << 0) #define USB_SCR_RXNE (1 << 1) #define USB_SCR_TXE (1 << 2) -#define USB_SCR_RESET_PENDING (1 << 3) -#define USB_SCR_RESET_ACK (1 << 4) +#define USB_SCR_RESET_ON_ACK (1 << 3) +#define USB_SCR_RESET_OFF_ACK (1 << 4) #define USB_SCR_WRITE_FLUSH (1 << 5) #define USB_SCR_RX_COUNT_BIT (6) #define USB_SCR_RX_COUNT_MASK (0x7FF << USB_SCR_RX_COUNT_BIT) @@ -88,6 +88,7 @@ typedef enum { #define USB_SCR_TX_COUNT_MASK (0x7FF << USB_SCR_TX_COUNT_BIT) #define USB_SCR_RESET_STATE (1 << 28) #define USB_SCR_PWRSAV (1 << 29) +#define USB_SCR_FIFO_FLUSH_BUSY (1 << 30) #define DMA_SCR_START (1 << 0) #define DMA_SCR_STOP (1 << 1) diff --git a/sw/controller/src/usb.c b/sw/controller/src/usb.c index 760f68d..3287b98 100644 --- a/sw/controller/src/usb.c +++ b/sw/controller/src/usb.c @@ -43,6 +43,8 @@ enum tx_state { struct process { + bool last_reset_state; + enum rx_state rx_state; uint8_t rx_counter; uint8_t rx_cmd; @@ -80,10 +82,6 @@ static const uint32_t ERR_TOKEN = (0x45525200UL); static const uint32_t PKT_TOKEN = (0x504B5400UL); -static bool usb_dma_ready (void) { - return !((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY)); -} - static bool usb_rx_byte (uint8_t *data) { if (fpga_usb_status_get() & USB_STATUS_RXNE) { *data = fpga_usb_pop(); @@ -149,6 +147,59 @@ static bool usb_rx_cmd (uint8_t *cmd) { return false; } +static void usb_reset (void) { + fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_STOP); + while (fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY); + fpga_reg_set(REG_USB_SCR, USB_SCR_FIFO_FLUSH); + while (fpga_reg_get(REG_USB_SCR) & USB_SCR_FIFO_FLUSH_BUSY); + + p.rx_state = RX_STATE_IDLE; + p.tx_state = TX_STATE_IDLE; + + p.response_pending = false; + p.packet_pending = false; + + p.read_ready = true; + p.read_length = 0; + p.read_address = 0; + + usb_rx_word_counter = 0; + usb_rx_word_buffer = 0; + usb_tx_word_counter = 0; + usb_rx_cmd_counter = 0; +} + +static void usb_flush_packet (void) { + if (p.packet_pending && p.packet_info.done_callback) { + p.packet_pending = false; + p.packet_info.done_callback(); + } + if (p.tx_state != TX_STATE_IDLE && p.tx_info.done_callback) { + p.tx_info.done_callback(); + p.tx_info.done_callback = NULL; + } +} + +static bool usb_is_active (void) { + uint32_t scr = fpga_reg_get(REG_USB_SCR); + bool reset_state = (scr & USB_SCR_RESET_STATE); + if (p.last_reset_state != reset_state) { + p.last_reset_state = reset_state; + if (reset_state) { + usb_flush_packet(); + usb_reset(); + fpga_reg_set(REG_USB_SCR, USB_SCR_WRITE_FLUSH); + } + fpga_reg_set(REG_USB_SCR, reset_state ? USB_SCR_RESET_ON_ACK : USB_SCR_RESET_OFF_ACK); + return false; + } + return !(reset_state || (scr & USB_SCR_PWRSAV)); +} + +static bool usb_dma_ready (void) { + return !((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY)); +} + static bool usb_validate_address_length (uint32_t address, uint32_t length, bool exclude_bootloader) { if ((address >= MEMORY_LENGTH) || (length > MEMORY_LENGTH)) { return true; @@ -410,27 +461,34 @@ static void usb_rx_process (void) { } if (p.rx_state == RX_STATE_FLUSH) { - if (usb_dma_ready()) { - if (p.rx_args[1] != 0) { + if (p.rx_args[1] > 0) { + if (usb_dma_ready()) { uint32_t length = (p.rx_args[1] > RX_FLUSH_LENGTH) ? RX_FLUSH_LENGTH : p.rx_args[1]; - fpga_reg_set(REG_USB_DMA_ADDRESS, RX_FLUSH_ADDRESS); - fpga_reg_set(REG_USB_DMA_LENGTH, length); - fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_DIRECTION | DMA_SCR_START); - p.rx_args[1] -= length; - } else { - if (p.flush_response) { - p.rx_state = RX_STATE_IDLE; - p.response_pending = true; - p.response_error = true; - } else if (p.flush_packet) { - usb_tx_info_t packet_info; - usb_create_packet(&packet_info, PACKET_CMD_DATA_FLUSHED); - if (usb_enqueue_packet(&packet_info)) { - p.rx_state = RX_STATE_IDLE; - } + if (!p.rx_dma_running) { + fpga_reg_set(REG_USB_DMA_ADDRESS, RX_FLUSH_ADDRESS); + fpga_reg_set(REG_USB_DMA_LENGTH, length); + fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_DIRECTION | DMA_SCR_START); + p.rx_dma_running = true; } else { + p.rx_args[1] -= length; + p.rx_dma_running = false; + } + } + } + + if (p.rx_args[1] == 0) { + if (p.flush_response) { + p.rx_state = RX_STATE_IDLE; + p.response_pending = true; + p.response_error = true; + } else if (p.flush_packet) { + usb_tx_info_t packet_info; + usb_create_packet(&packet_info, PACKET_CMD_DATA_FLUSHED); + if (usb_enqueue_packet(&packet_info)) { p.rx_state = RX_STATE_IDLE; } + } else { + p.rx_state = RX_STATE_IDLE; } } } @@ -556,42 +614,16 @@ void usb_get_read_info (uint32_t *args) { void usb_init (void) { - fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_STOP); - fpga_reg_set(REG_USB_SCR, USB_SCR_FIFO_FLUSH); - - p.rx_state = RX_STATE_IDLE; - p.tx_state = TX_STATE_IDLE; - - p.response_pending = false; - p.packet_pending = false; - - p.read_ready = true; - p.read_length = 0; - p.read_address = 0; - - usb_rx_word_counter = 0; - usb_rx_word_buffer = 0; - usb_tx_word_counter = 0; - usb_rx_cmd_counter = 0; + p.last_reset_state = false; + usb_reset(); } void usb_process (void) { - uint32_t scr = fpga_reg_get(REG_USB_SCR); - if (scr & (USB_SCR_PWRSAV | USB_SCR_RESET_STATE | USB_SCR_RESET_PENDING)) { - if (p.packet_pending && p.packet_info.done_callback) { - p.packet_pending = false; - p.packet_info.done_callback(); - } - if (scr & USB_SCR_RESET_PENDING) { - if (p.tx_state != TX_STATE_IDLE && p.tx_info.done_callback) { - p.tx_info.done_callback(); - } - usb_init(); - fpga_reg_set(REG_USB_SCR, USB_SCR_RESET_ACK); - } - } else { + if (usb_is_active()) { usb_rx_process(); usb_tx_process(); + } else { + usb_flush_packet(); } } diff --git a/sw/deployer/Cargo.lock b/sw/deployer/Cargo.lock index 29aa09d..6712a7e 100644 --- a/sw/deployer/Cargo.lock +++ b/sw/deployer/Cargo.lock @@ -27,13 +27,19 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -51,57 +57,110 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", ] [[package]] -name = "autocfg" -version = "1.1.0" +name = "anyhow" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +dependencies = [ + "arrayvec", +] [[package]] name = "bit_field" @@ -117,21 +176,33 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitstream-io" version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "415f8399438eb5e4b2f73ed3152a3448b98149dda642a957ee704e1daa5cf1d8" + +[[package]] +name = "built" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6a6c0b39c38fd754ac338b00a88066436389c0f029da5d37d1e01091d9b7c17" [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "byteorder" @@ -140,10 +211,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "cc" -version = "1.0.90" +name = "byteorder-lite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "cc" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2755ff20a1d93490d26ba33a6f092a38a508398a5320df5d4b3014fcccce9410" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] [[package]] name = "cfg-if" @@ -159,23 +251,23 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] name = "clap" -version = "4.5.2" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" +checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" dependencies = [ "clap_builder", "clap_derive", @@ -192,9 +284,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" dependencies = [ "anstream", "anstyle", @@ -204,21 +296,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "color_quant" @@ -228,9 +320,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "colored" @@ -250,9 +342,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -278,9 +370,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -306,19 +398,25 @@ checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "exr" version = "1.72.0" @@ -346,9 +444,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -365,9 +463,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -386,9 +484,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "cfg-if", "crunchy", @@ -404,10 +502,16 @@ dependencies = [ ] [[package]] -name = "heck" -version = "0.4.1" +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex" @@ -440,22 +544,43 @@ dependencies = [ [[package]] name = "image" -version = "0.24.9" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" dependencies = [ "bytemuck", "byteorder", "color_quant", "exr", "gif", - "jpeg-decoder", + "image-webp", "num-traits", "png", "qoi", + "ravif", + "rayon", + "rgb", "tiff", + "zune-core", + "zune-jpeg", ] +[[package]] +name = "image-webp" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d730b085583c4d789dfd07fdcf185be59501666a90c97c40162b37e4fdad272d" +dependencies = [ + "byteorder-lite", + "thiserror", +] + +[[package]] +name = "imgref" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" + [[package]] name = "include-flate" version = "0.2.0" @@ -491,23 +616,65 @@ dependencies = [ ] [[package]] -name = "io-kit-sys" -version = "0.4.0" +name = "indexmap" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4769cb30e5dcf1710fc6730d3e94f78c47723a014a567de385e113c737394640" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "io-kit-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" dependencies = [ "core-foundation-sys", "mach2", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" -dependencies = [ - "rayon", -] [[package]] name = "js-sys" @@ -520,9 +687,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lebe" @@ -532,9 +699,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libflate" @@ -556,6 +723,38 @@ dependencies = [ "rle-decode-fast", ] +[[package]] +name = "libftdi1-source-lgpl" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4412918d38c7b78f59c5b0cefec46e2099876dfd95f07f9bb2269d1d7b09fdb1" + +[[package]] +name = "libftdi1-sys" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575286f9af093f56c7805f4f94874871b84216d1545f499d2cbad9e370000fe7" +dependencies = [ + "cc", + "cfg-if", + "libc", + "libftdi1-source-lgpl", + "libusb1-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + [[package]] name = "libudev" version = "0.3.0" @@ -577,10 +776,22 @@ dependencies = [ ] [[package]] -name = "lock_api" -version = "0.4.11" +name = "libusb1-sys" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "17f6bace2f39082e9787c851afce469e7b2fe0f1cc64bbc68ca96653b63d8f17" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -588,9 +799,18 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] [[package]] name = "mach2" @@ -601,6 +821,16 @@ dependencies = [ "libc", ] +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + [[package]] name = "md5" version = "0.7.0" @@ -609,20 +839,32 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "simd-adler32", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nix" version = "0.26.4" @@ -640,17 +882,74 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "cfg-if", "cfg_aliases", "libc", ] [[package]] -name = "num-traits" -version = "0.2.18" +name = "nom" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -668,7 +967,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" dependencies = [ "dlv-list", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -677,6 +976,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384e52fd8fbd4cbe3c317e8216260c21a0f9134de108cea8a4dd4e7e152c472d" +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pkg-config" version = "0.3.30" @@ -710,13 +1015,32 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +dependencies = [ + "quote", + "syn 2.0.68", +] + [[package]] name = "qoi" version = "0.4.1" @@ -727,10 +1051,16 @@ dependencies = [ ] [[package]] -name = "quote" -version = "1.0.35" +name = "quick-error" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -766,10 +1096,60 @@ dependencies = [ ] [[package]] -name = "rayon" -version = "1.9.0" +name = "rav1e" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67376f469e7e7840d0040bbf4b9b3334005bb167f814621326e4c7ab8cd6e944" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -787,9 +1167,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -799,9 +1179,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -810,9 +1190,18 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rgb" +version = "0.8.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7439be6844e40133eda024efd85bf07f59d0dd2f59b10c00dd6cfb92cc5c741" +dependencies = [ + "bytemuck", +] [[package]] name = "rle-decode-fast" @@ -844,6 +1233,8 @@ dependencies = [ "hex", "image", "include-flate", + "libftdi1-sys", + "libusb1-sys", "md5", "panic-message", "rand", @@ -859,10 +1250,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "serial2" -version = "0.2.20" +name = "serde" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532d7a51dc8416e952987dbd39dd5e24fb9d1cbe86f1263521ec5032cb7ff0fb" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "serde_spanned" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +dependencies = [ + "serde", +] + +[[package]] +name = "serial2" +version = "0.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f39915da34f43a64c66d53c228b8ba9a4e21fed4894af24304e47f96996acafd" dependencies = [ "cfg-if", "libc", @@ -871,11 +1291,11 @@ dependencies = [ [[package]] name = "serialport" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828" +checksum = "de7c4f0cce25b9b3518eea99618112f9ee4549f974480c8f43d3c06f03c131a0" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "cfg-if", "core-foundation-sys", "io-kit-sys", @@ -895,10 +1315,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] -name = "smallvec" -version = "1.13.1" +name = "simd_helpers" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "spin" @@ -911,9 +1340,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" @@ -928,9 +1357,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -938,23 +1367,42 @@ dependencies = [ ] [[package]] -name = "thiserror" -version = "1.0.58" +name = "system-deps" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", ] [[package]] @@ -969,10 +1417,44 @@ dependencies = [ ] [[package]] -name = "unescaper" -version = "0.1.4" +name = "toml" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0adf6ad32eb5b3cadff915f7b770faaac8f7ff0476633aa29eb0d9584d889d34" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unescaper" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c878a167baa8afd137494101a688ef8c67125089ff2249284bd2b5f9bfedb815" dependencies = [ "thiserror", ] @@ -985,9 +1467,32 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" @@ -1022,7 +1527,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -1044,7 +1549,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1089,7 +1594,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -1107,7 +1612,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -1127,17 +1632,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -1148,9 +1654,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -1160,9 +1666,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -1172,9 +1678,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -1184,9 +1696,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -1196,9 +1708,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -1208,9 +1720,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -1220,9 +1732,24 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +dependencies = [ + "memchr", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" [[package]] name = "zune-inflate" @@ -1232,3 +1759,12 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] + +[[package]] +name = "zune-jpeg" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" +dependencies = [ + "zune-core", +] diff --git a/sw/deployer/Cargo.toml b/sw/deployer/Cargo.toml index 7eac40d..b6f5ff0 100644 --- a/sw/deployer/Cargo.toml +++ b/sw/deployer/Cargo.toml @@ -7,22 +7,24 @@ description = "SummerCart64 loader and control software" documentation = "https://github.com/Polprzewodnikowy/SummerCart64" [dependencies] -chrono = "0.4.23" -clap = { version = "4.1.6", features = ["derive"] } -clap-num = "1.0.2" -colored = "2.0.0" -crc32fast = "1.3.2" -ctrlc = "3.2.5" -encoding_rs = "0.8.32" +chrono = "0.4.38" +clap = { version = "4.5.8", features = ["derive"] } +clap-num = "1.1.1" +colored = "2.1.0" +crc32fast = "1.4.2" +ctrlc = "3.4.4" +encoding_rs = "0.8.34" hex = "0.4.3" -image = "0.24.5" +image = "0.25.1" include-flate = { version = "0.2.0", features = ["stable"] } +libftdi1-sys = { version = "1.1.3", features = ["libusb1-sys", "vendored"] } +libusb1-sys = { version = "0.6.5", features = ["vendored"] } md5 = "0.7.0" panic-message = "0.3.0" rand = "0.8.5" rust-ini = "0.18.0" -serial2 = "0.2.20" -serialport = "4.3.0" +serial2 = "0.2.26" +serialport = "4.4.0" [profile.release] lto = true diff --git a/sw/deployer/src/debug.rs b/sw/deployer/src/debug.rs index d78244b..35f29af 100644 --- a/sw/deployer/src/debug.rs +++ b/sw/deployer/src/debug.rs @@ -291,17 +291,7 @@ impl Handler { let filename = &if let Some(path) = path { path.to_string_lossy().to_string() } else { - generate_filename( - "save", - match save_writeback.save { - sc64::SaveType::Eeprom4k | sc64::SaveType::Eeprom16k => "eep", - sc64::SaveType::Sram | sc64::SaveType::SramBanked | sc64::SaveType::Sram1m => { - "srm" - } - sc64::SaveType::Flashram => "fla", - _ => "sav", - }, - ) + generate_filename("save", "sav") }; match File::create(filename) { Ok(mut file) => { diff --git a/sw/deployer/src/main.rs b/sw/deployer/src/main.rs index a346caa..f538822 100644 --- a/sw/deployer/src/main.rs +++ b/sw/deployer/src/main.rs @@ -25,7 +25,7 @@ struct Cli { #[command(subcommand)] command: Commands, - /// Connect to SC64 device on provided serial port + /// Connect to SC64 device on provided local port #[arg(short, long)] port: Option, @@ -350,7 +350,13 @@ fn handle_list_command() -> Result<(), sc64::Error> { println!("{}", "Found devices:".bold()); for (i, d) in devices.iter().enumerate() { - println!(" {i}: [{}] at port [{}]", d.serial_number, d.port); + let index = i + 1; + println!( + " {index}: [{}] at port [{}] (using \"{}\" backend)", + d.serial.bold(), + d.port.bold(), + d.backend.to_string().bold() + ); } Ok(()) @@ -733,35 +739,35 @@ fn handle_info_command(connection: Connection) -> Result<(), sc64::Error> { let datetime = state.datetime.format("%Y-%m-%d %H:%M:%S"); println!("{}", "SummerCart64 state information:".bold()); - println!(" Firmware version: v{}.{}.{}", major, minor, revision); - println!(" RTC datetime: {}", datetime); - println!(" Boot mode: {}", state.boot_mode); - println!(" Save type: {}", state.save_type); - println!(" CIC seed: {}", state.cic_seed); - println!(" TV type: {}", state.tv_type); - println!(" Bootloader switch: {}", state.bootloader_switch); - println!(" ROM write: {}", state.rom_write_enable); - println!(" ROM shadow: {}", state.rom_shadow_enable); - println!(" ROM extended: {}", state.rom_extended_enable); - println!(" 64DD mode: {}", state.dd_mode); - println!(" 64DD SD card mode: {}", state.dd_sd_enable); - println!(" 64DD drive type: {}", state.dd_drive_type); - println!(" 64DD disk state: {}", state.dd_disk_state); - println!(" Button mode: {}", state.button_mode); - println!(" Button state: {}", state.button_state); - println!(" LED blink: {}", state.led_enable); - println!(" IS-Viewer 64 offset: 0x{:08X}", state.isv_address); + println!(" Firmware version: v{}.{}.{}", major, minor, revision); + println!(" RTC datetime: {}", datetime); + println!(" Boot mode: {}", state.boot_mode); + println!(" Save type: {}", state.save_type); + println!(" CIC seed: {}", state.cic_seed); + println!(" TV type: {}", state.tv_type); + println!(" Bootloader switch: {}", state.bootloader_switch); + println!(" ROM write: {}", state.rom_write_enable); + println!(" ROM shadow: {}", state.rom_shadow_enable); + println!(" ROM extended: {}", state.rom_extended_enable); + println!(" 64DD mode: {}", state.dd_mode); + println!(" 64DD SD card mode: {}", state.dd_sd_enable); + println!(" 64DD drive type: {}", state.dd_drive_type); + println!(" 64DD disk state: {}", state.dd_disk_state); + println!(" Button mode: {}", state.button_mode); + println!(" Button state: {}", state.button_state); + println!(" LED blink: {}", state.led_enable); + println!(" IS-Viewer 64: {}", state.isviewer); println!("{}", "SummerCart64 diagnostic information:".bold()); println!( - " Last PI address: 0x{:08X}", + " Last PI address: 0x{:08X}", state.fpga_debug_data.last_pi_address ); println!( - " PI FIFO flags: {}", + " PI FIFO flags: {}", state.fpga_debug_data.pi_fifo_flags ); - println!(" Current CIC step: {}", state.fpga_debug_data.cic_step); - println!(" Diagnostic data: {}", state.diagnostic_data); + println!(" Current CIC step: {}", state.fpga_debug_data.cic_step); + println!(" Diagnostic data: {}", state.diagnostic_data); Ok(()) } diff --git a/sw/deployer/src/sc64/error.rs b/sw/deployer/src/sc64/error.rs index 416bebb..0702fd5 100644 --- a/sw/deployer/src/sc64/error.rs +++ b/sw/deployer/src/sc64/error.rs @@ -26,9 +26,3 @@ impl From for Error { Error::new(format!("IO error: {}", value).as_str()) } } - -impl From for Error { - fn from(value: serialport::Error) -> Self { - Error::new(format!("SerialPort error: {}", value.description).as_str()) - } -} diff --git a/sw/deployer/src/sc64/ftdi.rs b/sw/deployer/src/sc64/ftdi.rs new file mode 100644 index 0000000..f99c728 --- /dev/null +++ b/sw/deployer/src/sc64/ftdi.rs @@ -0,0 +1,540 @@ +pub struct DeviceInfo { + pub description: String, + pub serial: String, + pub port: String, +} + +#[allow(dead_code)] +enum InterfaceIndex { + Any, + A, + B, + C, + D, +} + +#[allow(dead_code)] +enum ModuleDetachMode { + AutoDetach, + DontDetach, + AutoDetachReattach, +} + +struct ModemStatus { + dsr: bool, +} + +struct Wrapper { + context: *mut libftdi1_sys::ftdi_context, + unclog_buffer: std::collections::VecDeque, + write_buffer: Vec, + read_timeout: std::time::Duration, + write_timeout: std::time::Duration, + read_chunksize: usize, + write_chunksize: usize, +} + +impl Wrapper { + const DEFAULT_POLL_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(16); + const DEFAULT_RW_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5); + const WRITE_CHUNK_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(100); + + fn new( + read_timeout: Option, + write_timeout: Option, + ) -> std::io::Result { + let context = unsafe { libftdi1_sys::ftdi_new() }; + if context.is_null() { + return Err(std::io::ErrorKind::OutOfMemory.into()); + } + let mut wrapper = Self { + context, + unclog_buffer: std::collections::VecDeque::new(), + write_buffer: vec![], + read_timeout: Self::DEFAULT_RW_TIMEOUT, + write_timeout: Self::DEFAULT_RW_TIMEOUT, + read_chunksize: 4096, + write_chunksize: 4096, + }; + wrapper.set_timeouts(read_timeout, write_timeout)?; + wrapper.read_data_set_chunksize(wrapper.read_chunksize)?; + wrapper.write_data_set_chunksize(wrapper.write_chunksize)?; + Ok(wrapper) + } + + fn list_devices(vendor: u16, product: u16) -> std::io::Result> { + let wrapper = Self::new(None, None)?; + + let mut device_list: *mut libftdi1_sys::ftdi_device_list = std::ptr::null_mut(); + let devices = unsafe { + libftdi1_sys::ftdi_usb_find_all( + wrapper.context, + &mut device_list, + vendor as i32, + product as i32, + ) + }; + + let result = if devices > 0 { + let mut list: Vec = vec![]; + + let mut description = [0i8; 128]; + let mut serial = [0i8; 128]; + + let mut device = device_list; + let mut index = 0; + while !device.is_null() { + let result = unsafe { + libftdi1_sys::ftdi_usb_get_strings( + wrapper.context, + (*device).dev, + std::ptr::null_mut(), + 0, + description.as_mut_ptr(), + description.len() as i32, + serial.as_mut_ptr(), + serial.len() as i32, + ) + }; + + let description = unsafe { std::ffi::CStr::from_ptr(description.as_ptr()) } + .to_string_lossy() + .into_owned(); + let serial = unsafe { std::ffi::CStr::from_ptr(serial.as_ptr()) } + .to_string_lossy() + .into_owned(); + let port = if list.binary_search_by(|d| d.serial.cmp(&serial)).is_ok() { + format!("i:0x{vendor:04X}:0x{product:04X}:{index}") + } else { + format!("s:0x{vendor:04X}:0x{product:04X}:{serial}") + }; + + if result == 0 { + list.push(DeviceInfo { + description, + serial, + port, + }); + } + + device = unsafe { (*device).next }; + index += 1; + } + + list.sort_by(|a, b| a.serial.cmp(&b.serial)); + + Ok(list) + } else { + match devices { + 0 => Ok(vec![]), + -3 => Err(std::io::ErrorKind::OutOfMemory.into()), + -5 => Err(std::io::ErrorKind::BrokenPipe.into()), + -6 => Err(std::io::ErrorKind::BrokenPipe.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_usb_find_all: {result}" + ))), + } + }; + + unsafe { libftdi1_sys::ftdi_list_free(&mut device_list) } + + result + } + + fn libusb_convert_result(&self, result: i32) -> std::io::Error { + if result == libusb1_sys::constants::LIBUSB_ERROR_OVERFLOW { + return std::io::Error::other("libusb overflow"); + } + match result { + libusb1_sys::constants::LIBUSB_ERROR_IO => std::io::ErrorKind::UnexpectedEof, + libusb1_sys::constants::LIBUSB_ERROR_INVALID_PARAM => std::io::ErrorKind::InvalidInput, + libusb1_sys::constants::LIBUSB_ERROR_ACCESS => std::io::ErrorKind::PermissionDenied, + libusb1_sys::constants::LIBUSB_ERROR_NO_DEVICE => std::io::ErrorKind::NotConnected, + libusb1_sys::constants::LIBUSB_ERROR_NOT_FOUND => std::io::ErrorKind::NotFound, + libusb1_sys::constants::LIBUSB_ERROR_BUSY => std::io::ErrorKind::WouldBlock, + libusb1_sys::constants::LIBUSB_ERROR_TIMEOUT => std::io::ErrorKind::TimedOut, + libusb1_sys::constants::LIBUSB_ERROR_PIPE => std::io::ErrorKind::BrokenPipe, + libusb1_sys::constants::LIBUSB_ERROR_INTERRUPTED => std::io::ErrorKind::Interrupted, + libusb1_sys::constants::LIBUSB_ERROR_NO_MEM => std::io::ErrorKind::OutOfMemory, + libusb1_sys::constants::LIBUSB_ERROR_NOT_SUPPORTED => std::io::ErrorKind::Unsupported, + _ => std::io::ErrorKind::Other, + } + .into() + } + + fn set_timeouts( + &mut self, + read_timeout: Option, + write_timeout: Option, + ) -> std::io::Result<()> { + let read_timeout = read_timeout.unwrap_or(Self::DEFAULT_RW_TIMEOUT); + let write_timeout = write_timeout.unwrap_or(Self::DEFAULT_RW_TIMEOUT); + unsafe { + (*self.context).usb_read_timeout = i32::try_from(read_timeout.as_millis()) + .map_err(|_| std::io::ErrorKind::InvalidInput)?; + (*self.context).usb_write_timeout = i32::try_from(write_timeout.as_millis()) + .map_err(|_| std::io::ErrorKind::InvalidInput)?; + } + self.read_timeout = read_timeout; + self.write_timeout = write_timeout; + Ok(()) + } + + fn set_module_detach_mode(&mut self, mode: ModuleDetachMode) { + let mode = match mode { + ModuleDetachMode::AutoDetach => { + libftdi1_sys::ftdi_module_detach_mode::AUTO_DETACH_SIO_MODULE + } + ModuleDetachMode::DontDetach => { + libftdi1_sys::ftdi_module_detach_mode::DONT_DETACH_SIO_MODULE + } + ModuleDetachMode::AutoDetachReattach => { + libftdi1_sys::ftdi_module_detach_mode::AUTO_DETACH_REATACH_SIO_MODULE + } + }; + unsafe { + (*self.context).module_detach_mode = mode; + }; + } + + fn set_interface(&mut self, interface: InterfaceIndex) -> std::io::Result<()> { + let interface = match interface { + InterfaceIndex::Any => libftdi1_sys::ftdi_interface::INTERFACE_ANY, + InterfaceIndex::A => libftdi1_sys::ftdi_interface::INTERFACE_A, + InterfaceIndex::B => libftdi1_sys::ftdi_interface::INTERFACE_B, + InterfaceIndex::C => libftdi1_sys::ftdi_interface::INTERFACE_C, + InterfaceIndex::D => libftdi1_sys::ftdi_interface::INTERFACE_D, + }; + match unsafe { libftdi1_sys::ftdi_set_interface(self.context, interface) } { + 0 => Ok(()), + -1 => Err(std::io::ErrorKind::InvalidInput.into()), + -2 => Err(std::io::ErrorKind::NotConnected.into()), + -3 => Err(std::io::ErrorKind::InvalidData.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_set_interface: {result}" + ))), + } + } + + fn usb_open_string(&mut self, description: &str) -> std::io::Result<()> { + let description = std::ffi::CString::new(description) + .unwrap_or_default() + .into_raw(); + match unsafe { libftdi1_sys::ftdi_usb_open_string(self.context, description) } { + 0 => Ok(()), + -2 => Err(std::io::ErrorKind::ConnectionRefused.into()), + -3 => Err(std::io::ErrorKind::NotFound.into()), + -4 => Err(std::io::ErrorKind::PermissionDenied.into()), + -5 => Err(std::io::ErrorKind::PermissionDenied.into()), + -6 => Err(std::io::ErrorKind::ConnectionRefused.into()), + -7 => Err(std::io::ErrorKind::ConnectionRefused.into()), + -8 => Err(std::io::ErrorKind::ConnectionRefused.into()), + -9 => Err(std::io::ErrorKind::ConnectionRefused.into()), + -10 => Err(std::io::ErrorKind::BrokenPipe.into()), + -11 => Err(std::io::ErrorKind::InvalidInput.into()), + -12 => Err(std::io::ErrorKind::InvalidData.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_usb_open_string: {result}" + ))), + } + } + + fn usb_reset(&mut self) -> std::io::Result<()> { + match unsafe { libftdi1_sys::ftdi_usb_reset(self.context) } { + 0 => Ok(()), + -1 => Err(std::io::ErrorKind::BrokenPipe.into()), + -2 => Err(std::io::ErrorKind::NotConnected.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_usb_reset: {result}" + ))), + } + } + + fn set_latency_timer(&mut self, latency: Option) -> std::io::Result<()> { + let latency = u8::try_from(latency.unwrap_or(Self::DEFAULT_POLL_TIMEOUT).as_millis()) + .map_err(|_| std::io::ErrorKind::InvalidInput)?; + match unsafe { libftdi1_sys::ftdi_set_latency_timer(self.context, latency) } { + 0 => Ok(()), + -1 => Err(std::io::ErrorKind::InvalidInput.into()), + -2 => Err(std::io::ErrorKind::BrokenPipe.into()), + -3 => Err(std::io::ErrorKind::NotConnected.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_set_latency_timer: {result}" + ))), + } + } + + fn read_data_set_chunksize(&mut self, chunksize: usize) -> std::io::Result<()> { + match unsafe { + libftdi1_sys::ftdi_read_data_set_chunksize( + self.context, + u32::try_from(chunksize).map_err(|_| std::io::ErrorKind::InvalidInput)?, + ) + } { + 0 => { + self.read_chunksize = chunksize; + Ok(()) + } + -1 => Err(std::io::ErrorKind::NotConnected.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_read_data_set_chunksize: {result}" + ))), + } + } + + fn write_data_set_chunksize(&mut self, chunksize: usize) -> std::io::Result<()> { + match unsafe { + libftdi1_sys::ftdi_write_data_set_chunksize( + self.context, + u32::try_from(chunksize).map_err(|_| std::io::ErrorKind::InvalidInput)?, + ) + } { + 0 => { + self.write_chunksize = chunksize; + self.commit_write() + } + -1 => Err(std::io::ErrorKind::NotConnected.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_write_data_set_chunksize: {result}" + ))), + } + } + + pub fn set_dtr(&mut self, value: bool) -> std::io::Result<()> { + let state = if value { 1 } else { 0 }; + match unsafe { libftdi1_sys::ftdi_setdtr(self.context, state) } { + 0 => Ok(()), + -1 => Err(std::io::ErrorKind::BrokenPipe.into()), + -2 => Err(std::io::ErrorKind::NotConnected.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_setdtr: {result}" + ))), + } + } + + fn poll_modem_status(&mut self) -> std::io::Result { + const DSR_BIT: u16 = 1 << 5; + + let mut status = 0; + + match unsafe { libftdi1_sys::ftdi_poll_modem_status(self.context, &mut status) } { + 0 => Ok(ModemStatus { + dsr: (status & DSR_BIT) != 0, + }), + -1 => Err(std::io::ErrorKind::BrokenPipe.into()), + -2 => Err(std::io::ErrorKind::NotConnected.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_poll_modem_status: {result}" + ))), + } + } + + fn tciflush(&mut self) -> std::io::Result<()> { + let timeout = std::time::Instant::now(); + loop { + match self.read(&mut vec![0u8; self.read_chunksize]) { + Ok(_) => {} + Err(error) => match error.kind() { + std::io::ErrorKind::Interrupted + | std::io::ErrorKind::TimedOut + | std::io::ErrorKind::WouldBlock => { + return Ok(()); + } + _ => return Err(error), + }, + }; + if timeout.elapsed() > self.read_timeout { + return Err(std::io::ErrorKind::TimedOut.into()); + } + } + } + + fn tcoflush(&mut self) -> std::io::Result<()> { + self.write_buffer.clear(); + match unsafe { libftdi1_sys::ftdi_tcoflush(self.context) } { + 0 => Ok(()), + -1 => Err(std::io::ErrorKind::BrokenPipe.into()), + -2 => Err(std::io::ErrorKind::BrokenPipe.into()), + -3 => Err(std::io::ErrorKind::NotConnected.into()), + result => Err(std::io::Error::other(format!( + "Unexpected response from ftdi_tcoflush: {result}" + ))), + } + } + + pub fn read_data(&mut self, buffer: &mut [u8]) -> std::io::Result { + let length = i32::try_from(buffer.len()).map_err(|_| std::io::ErrorKind::InvalidInput)?; + let result = + unsafe { libftdi1_sys::ftdi_read_data(self.context, buffer.as_mut_ptr(), length) }; + match result { + 1.. => Ok(result as usize), + 0 => Err(std::io::ErrorKind::WouldBlock.into()), + -666 => Err(std::io::ErrorKind::NotConnected.into()), + result => Err(self.libusb_convert_result(result)), + } + } + + fn write_data(&mut self, buffer: &[u8], written: &mut usize) -> std::io::Result<()> { + let mut transferred = 0; + let result = unsafe { + // NOTE: Nasty hack to overcome libftdi1 API limitation. + // Write can partially succeed, but the default ftdi_write_data + // function doesn't report number of transferred bytes in that case. + libusb1_sys::libusb_bulk_transfer( + (*self.context).usb_dev, + (*self.context).in_ep as u8, + Vec::from(buffer).as_mut_ptr(), + buffer.len() as i32, + &mut transferred, + Self::WRITE_CHUNK_TIMEOUT.as_millis() as u32, + ) + }; + *written = transferred as usize; + if result < 0 { + return Err(self.libusb_convert_result(result)); + } + Ok(()) + } + + fn unclog_pipe(&mut self) -> std::io::Result<()> { + let mut buffer = vec![0u8; self.read_chunksize]; + let read = match self.read_data(&mut buffer) { + Ok(read) => read, + Err(error) => match error.kind() { + std::io::ErrorKind::Interrupted | std::io::ErrorKind::WouldBlock => 0, + _ => return Err(error), + }, + }; + self.unclog_buffer.extend(buffer[0..read].iter()); + Ok(()) + } + + fn commit_write(&mut self) -> std::io::Result<()> { + let timeout = std::time::Instant::now(); + while !self.write_buffer.is_empty() { + let mut written = 0; + let result = self.write_data(&self.write_buffer.clone(), &mut written); + self.write_buffer.drain(..written); + if let Err(error) = result { + match error.kind() { + std::io::ErrorKind::TimedOut => self.unclog_pipe()?, + _ => return Err(error), + } + } + if timeout.elapsed() > self.write_timeout { + return Err(std::io::ErrorKind::TimedOut.into()); + } + } + Ok(()) + } + + fn read(&mut self, buffer: &mut [u8]) -> std::io::Result { + if buffer.is_empty() { + Err(std::io::ErrorKind::InvalidInput.into()) + } else if self.unclog_buffer.is_empty() { + self.read_data(buffer) + } else { + for (index, item) in buffer.iter_mut().enumerate() { + if let Some(byte) = self.unclog_buffer.pop_front() { + *item = byte; + } else { + return Ok(index); + } + } + Ok(buffer.len()) + } + } + + fn write(&mut self, buffer: &[u8]) -> std::io::Result { + let remaining_space = self.write_chunksize - self.write_buffer.len(); + let length = buffer.len().min(remaining_space); + self.write_buffer.extend(&buffer[..length]); + if self.write_buffer.len() >= self.write_chunksize { + self.commit_write()? + } + Ok(length) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.commit_write() + } +} + +impl Drop for Wrapper { + fn drop(&mut self) { + unsafe { libftdi1_sys::ftdi_free(self.context) } + } +} + +pub struct FtdiDevice { + wrapper: Wrapper, +} + +impl FtdiDevice { + pub fn list(vendor: u16, product: u16) -> std::io::Result> { + Wrapper::list_devices(vendor, product) + } + + pub fn open( + description: &str, + poll_timeout: Option, + read_timeout: Option, + write_timeout: Option, + ) -> std::io::Result { + let mut wrapper = Wrapper::new(read_timeout, write_timeout)?; + + wrapper.set_module_detach_mode(ModuleDetachMode::AutoDetachReattach); + wrapper.set_interface(InterfaceIndex::A)?; + + const CHUNK_SIZE: usize = 16 * 1024; + + wrapper.read_data_set_chunksize(CHUNK_SIZE)?; + wrapper.write_data_set_chunksize(CHUNK_SIZE)?; + + wrapper.usb_open_string(description)?; + + wrapper.usb_reset()?; + + wrapper.set_latency_timer(poll_timeout)?; + + Ok(FtdiDevice { wrapper }) + } + + pub fn set_dtr(&mut self, value: bool) -> std::io::Result<()> { + self.wrapper.set_dtr(value) + } + + pub fn read_dsr(&mut self) -> std::io::Result { + Ok(self.wrapper.poll_modem_status()?.dsr) + } + + pub fn discard_input(&mut self) -> std::io::Result<()> { + self.wrapper.tciflush() + } + + pub fn discard_output(&mut self) -> std::io::Result<()> { + self.wrapper.tcoflush() + } +} + +impl std::io::Read for FtdiDevice { + fn read(&mut self, buffer: &mut [u8]) -> std::io::Result { + self.wrapper.read(buffer) + } +} + +impl std::io::Write for FtdiDevice { + fn write(&mut self, buffer: &[u8]) -> std::io::Result { + self.wrapper.write(buffer) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.wrapper.flush() + } +} + +impl Drop for FtdiDevice { + fn drop(&mut self) { + unsafe { libftdi1_sys::ftdi_usb_close(self.wrapper.context) }; + } +} diff --git a/sw/deployer/src/sc64/link.rs b/sw/deployer/src/sc64/link.rs index 88fe748..029870e 100644 --- a/sw/deployer/src/sc64/link.rs +++ b/sw/deployer/src/sc64/link.rs @@ -1,10 +1,9 @@ -use super::error::Error; -use serial2::SerialPort; +use super::{error::Error, ftdi::FtdiDevice, serial::SerialDevice}; use std::{ collections::VecDeque, - io::{BufReader, BufWriter, ErrorKind, Read, Write}, + fmt::Display, + io::{BufReader, BufWriter, Read, Write}, net::TcpStream, - thread, time::{Duration, Instant}, }; @@ -51,82 +50,97 @@ pub struct Response { pub error: bool, } -pub struct Packet { +pub struct AsynchronousPacket { pub id: u8, pub data: Vec, } -pub struct Serial { - serial: SerialPort, +pub enum UsbPacket { + Response(Response), + AsynchronousPacket(AsynchronousPacket), } -impl Serial { - fn reset(&self) -> Result<(), Error> { - const RESET_WAIT_DURATION: Duration = Duration::from_millis(10); - const RESET_RETRY_COUNT: i32 = 100; - const FLUSH_TIMEOUT: Duration = Duration::from_secs(1); +const SERIAL_PREFIX: &str = "serial://"; +const FTDI_PREFIX: &str = "ftdi://"; - self.serial.set_dtr(true)?; - for n in 0..=RESET_RETRY_COUNT { - self.serial.discard_buffers()?; - thread::sleep(RESET_WAIT_DURATION); - if self.serial.read_dsr()? { - break; - } - if n == RESET_RETRY_COUNT { - return Err(Error::new("Couldn't reset SC64 device (on)")); - } - } +const RESET_TIMEOUT: Duration = Duration::from_secs(1); +const POLL_TIMEOUT: Duration = Duration::from_millis(5); +const READ_TIMEOUT: Duration = Duration::from_secs(5); +const WRITE_TIMEOUT: Duration = Duration::from_secs(5); - let flush_timeout = Instant::now(); +pub trait Backend { + fn read(&mut self, buffer: &mut [u8]) -> std::io::Result; + fn write_all(&mut self, buffer: &[u8]) -> std::io::Result<()>; + + fn flush(&mut self) -> std::io::Result<()>; + + fn discard_input(&mut self) -> std::io::Result<()> { + Ok(()) + } + + fn discard_output(&mut self) -> std::io::Result<()> { + Ok(()) + } + + fn set_dtr(&mut self, _value: bool) -> std::io::Result<()> { + Ok(()) + } + + fn read_dsr(&mut self) -> std::io::Result { + Ok(false) + } + + fn close(&mut self) {} + + fn reset(&mut self) -> std::io::Result<()> { + self.discard_output()?; + + let timeout = Instant::now(); + self.set_dtr(true)?; loop { - match self.serial.read(&mut vec![0; 1]) { - Ok(length) => match length { - 0 => break, - _ => {} - }, - Err(error) => match error.kind() { - ErrorKind::TimedOut => break, - _ => { - return Err(Error::new( - format!("Couldn't flush SC64 serial buffer: {error}").as_str(), - )) - } - }, + if self.read_dsr()? { + break; } - if flush_timeout.elapsed() >= FLUSH_TIMEOUT { - return Err(Error::new("SC64 serial buffer flush took too long")); + if timeout.elapsed() > RESET_TIMEOUT { + return Err(std::io::Error::new( + std::io::ErrorKind::TimedOut, + "Couldn't reset SC64 device (on)", + )); } } - self.serial.set_dtr(false)?; - for n in 0..=RESET_RETRY_COUNT { - thread::sleep(RESET_WAIT_DURATION); - if !self.serial.read_dsr()? { + self.discard_input()?; + + let timeout = Instant::now(); + self.set_dtr(false)?; + loop { + if !self.read_dsr()? { break; } - if n == RESET_RETRY_COUNT { - return Err(Error::new("Couldn't reset SC64 device (off)")); + if timeout.elapsed() > RESET_TIMEOUT { + return Err(std::io::Error::new( + std::io::ErrorKind::TimedOut, + "Couldn't reset SC64 device (off)", + )); } } Ok(()) } - fn read_data(&self, buffer: &mut [u8], block: bool) -> Result, Error> { - let timeout = Instant::now(); + fn try_read_exact(&mut self, buffer: &mut [u8], block: bool) -> std::io::Result> { let mut position = 0; let length = buffer.len(); + let timeout = Instant::now(); while position < length { - if timeout.elapsed() > Duration::from_secs(10) { - return Err(Error::new("Serial read timeout")); - } - match self.serial.read(&mut buffer[position..length]) { - Ok(0) => return Err(Error::new("Unexpected end of serial data")), + match self.read(&mut buffer[position..length]) { + Ok(0) => return Err(std::io::ErrorKind::UnexpectedEof.into()), Ok(bytes) => position += bytes, Err(error) => match error.kind() { - ErrorKind::Interrupted | ErrorKind::TimedOut | ErrorKind::WouldBlock => { + std::io::ErrorKind::Interrupted + | std::io::ErrorKind::TimedOut + | std::io::ErrorKind::WouldBlock => { if !block && position == 0 { return Ok(None); } @@ -134,48 +148,53 @@ impl Serial { _ => return Err(error.into()), }, } + if timeout.elapsed() > READ_TIMEOUT { + return Err(std::io::ErrorKind::TimedOut.into()); + } } Ok(Some(())) } - fn read_exact(&self, buffer: &mut [u8]) -> Result<(), Error> { - match self.read_data(buffer, true)? { + fn try_read_header(&mut self, block: bool) -> std::io::Result> { + let mut header = [0u8; 4]; + Ok(self.try_read_exact(&mut header, block)?.map(|_| header)) + } + + fn read_exact(&mut self, buffer: &mut [u8]) -> std::io::Result<()> { + match self.try_read_exact(buffer, true)? { Some(()) => Ok(()), - None => Err(Error::new("Unexpected end of serial data")), + None => Err(std::io::ErrorKind::UnexpectedEof.into()), } } - fn read_header(&self, block: bool) -> Result, Error> { - let mut header = [0u8; 4]; - Ok(self.read_data(&mut header, block)?.map(|_| header)) - } + fn send_command(&mut self, command: &Command) -> std::io::Result<()> { + self.write_all(b"CMD")?; + self.write_all(&command.id.to_be_bytes())?; - pub fn send_command(&self, command: &Command) -> Result<(), Error> { - self.serial.write_all(b"CMD")?; - self.serial.write_all(&command.id.to_be_bytes())?; - self.serial.write_all(&command.args[0].to_be_bytes())?; - self.serial.write_all(&command.args[1].to_be_bytes())?; + self.write_all(&command.args[0].to_be_bytes())?; + self.write_all(&command.args[1].to_be_bytes())?; - self.serial.write_all(&command.data)?; + self.write_all(&command.data)?; - self.serial.flush()?; + self.flush()?; Ok(()) } - pub fn process_incoming_data( - &self, + fn process_incoming_data( + &mut self, data_type: DataType, - packets: &mut VecDeque, - ) -> Result, Error> { + packets: &mut VecDeque, + ) -> std::io::Result> { let block = matches!(data_type, DataType::Response); - while let Some(header) = self.read_header(block)? { - let (packet_token, error) = (match &header[0..3] { - b"CMP" => Ok((false, false)), - b"PKT" => Ok((true, false)), - b"ERR" => Ok((false, true)), - _ => Err(Error::new("Unknown response token")), - })?; + + while let Some(header) = self.try_read_header(block)? { + let (packet_token, error) = match &header[0..3] { + b"CMP" => (false, false), + b"PKT" => (true, false), + b"ERR" => (false, true), + _ => return Err(std::io::ErrorKind::InvalidData.into()), + }; let id = header[3]; let mut buffer = [0u8; 4]; @@ -187,7 +206,7 @@ impl Serial { self.read_exact(&mut data)?; if packet_token { - packets.push_back(Packet { id, data }); + packets.push_back(AsynchronousPacket { id, data }); if matches!(data_type, DataType::Packet) { break; } @@ -200,48 +219,94 @@ impl Serial { } } -pub fn new_serial(port: &str) -> Result { - let mut serial = SerialPort::open(port, 115_200)?; - serial.set_write_timeout(Duration::from_secs(10))?; - serial.set_read_timeout(Duration::from_millis(10))?; - let backend = Serial { serial }; - backend.reset()?; - Ok(backend) -} - -trait Backend { - fn send_command(&mut self, command: &Command) -> Result<(), Error>; - fn process_incoming_data( - &mut self, - data_type: DataType, - packets: &mut VecDeque, - ) -> Result, Error>; - fn close(&self) {} -} - -struct SerialBackend { - inner: Serial, +pub struct SerialBackend { + device: SerialDevice, } impl Backend for SerialBackend { - fn send_command(&mut self, command: &Command) -> Result<(), Error> { - self.inner.send_command(command) + fn read(&mut self, buffer: &mut [u8]) -> std::io::Result { + self.device.read(buffer) } - fn process_incoming_data( - &mut self, - data_type: DataType, - packets: &mut VecDeque, - ) -> Result, Error> { - self.inner.process_incoming_data(data_type, packets) + fn write_all(&mut self, buffer: &[u8]) -> std::io::Result<()> { + self.device.write_all(buffer) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.device.flush() + } + + fn discard_input(&mut self) -> std::io::Result<()> { + self.device.discard_input() + } + + fn discard_output(&mut self) -> std::io::Result<()> { + self.device.discard_output() + } + + fn set_dtr(&mut self, value: bool) -> std::io::Result<()> { + self.device.set_dtr(value) + } + + fn read_dsr(&mut self) -> std::io::Result { + self.device.read_dsr() } } -fn new_serial_backend(port: &str) -> Result { - let backend = SerialBackend { - inner: new_serial(port)?, - }; - Ok(backend) +fn new_serial_backend(port: &str) -> std::io::Result { + Ok(SerialBackend { + device: SerialDevice::new( + port, + Some(POLL_TIMEOUT), + Some(READ_TIMEOUT), + Some(WRITE_TIMEOUT), + )?, + }) +} + +struct FtdiBackend { + device: FtdiDevice, +} + +impl Backend for FtdiBackend { + fn read(&mut self, buffer: &mut [u8]) -> std::io::Result { + self.device.read(buffer) + } + + fn write_all(&mut self, buffer: &[u8]) -> std::io::Result<()> { + self.device.write_all(buffer) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.device.flush() + } + + fn discard_input(&mut self) -> std::io::Result<()> { + self.device.discard_input() + } + + fn discard_output(&mut self) -> std::io::Result<()> { + self.device.discard_output() + } + + fn set_dtr(&mut self, value: bool) -> std::io::Result<()> { + self.device.set_dtr(value) + } + + fn read_dsr(&mut self) -> std::io::Result { + self.device.read_dsr() + } +} + +fn new_ftdi_backend(port: &str) -> std::io::Result { + Ok(FtdiBackend { + device: FtdiDevice::open( + port, + Some(POLL_TIMEOUT), + Some(READ_TIMEOUT), + Some(WRITE_TIMEOUT), + )?, + }) } struct TcpBackend { @@ -250,58 +315,36 @@ struct TcpBackend { writer: BufWriter, } -impl TcpBackend { - fn read_data(&mut self, buffer: &mut [u8], block: bool) -> Result, Error> { - let timeout = Instant::now(); - let mut position = 0; - let length = buffer.len(); - while position < length { - if timeout.elapsed() > Duration::from_secs(10) { - return Err(Error::new("Stream read timeout")); - } - match self.reader.read(&mut buffer[position..length]) { - Ok(0) => return Err(Error::new("Unexpected end of stream data")), - Ok(bytes) => position += bytes, - Err(error) => match error.kind() { - ErrorKind::Interrupted | ErrorKind::TimedOut | ErrorKind::WouldBlock => { - if !block && position == 0 { - return Ok(None); - } - } - _ => return Err(error.into()), - }, - } - } - Ok(Some(())) - } - - fn read_exact(&mut self, buffer: &mut [u8]) -> Result<(), Error> { - match self.read_data(buffer, true)? { - Some(()) => Ok(()), - None => Err(Error::new("Unexpected end of stream data")), - } - } - - fn read_header(&mut self, block: bool) -> Result, Error> { - let mut header = [0u8; 4]; - Ok(self.read_data(&mut header, block)?.map(|_| header)) - } -} - impl Backend for TcpBackend { - fn send_command(&mut self, command: &Command) -> Result<(), Error> { - let payload_data_type: u32 = DataType::Command.into(); - self.writer.write_all(&payload_data_type.to_be_bytes())?; + fn read(&mut self, buffer: &mut [u8]) -> std::io::Result { + self.reader.read(buffer) + } - self.writer.write_all(&command.id.to_be_bytes())?; - self.writer.write_all(&command.args[0].to_be_bytes())?; - self.writer.write_all(&command.args[1].to_be_bytes())?; + fn write_all(&mut self, buffer: &[u8]) -> std::io::Result<()> { + self.writer.write_all(buffer) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.writer.flush() + } + + fn close(&mut self) { + self.stream.shutdown(std::net::Shutdown::Both).ok(); + } + + fn send_command(&mut self, command: &Command) -> std::io::Result<()> { + let payload_data_type: u32 = DataType::Command.into(); + self.write_all(&payload_data_type.to_be_bytes())?; + + self.write_all(&command.id.to_be_bytes())?; + self.write_all(&command.args[0].to_be_bytes())?; + self.write_all(&command.args[1].to_be_bytes())?; let command_data_length = command.data.len() as u32; - self.writer.write_all(&command_data_length.to_be_bytes())?; - self.writer.write_all(&command.data)?; + self.write_all(&command_data_length.to_be_bytes())?; + self.write_all(&command.data)?; - self.writer.flush()?; + self.flush()?; Ok(()) } @@ -309,11 +352,13 @@ impl Backend for TcpBackend { fn process_incoming_data( &mut self, data_type: DataType, - packets: &mut VecDeque, - ) -> Result, Error> { + packets: &mut VecDeque, + ) -> std::io::Result> { let block = matches!(data_type, DataType::Response); - while let Some(header) = self.read_header(block)? { - let payload_data_type: DataType = u32::from_be_bytes(header).try_into()?; + while let Some(header) = self.try_read_header(block)? { + let payload_data_type: DataType = u32::from_be_bytes(header) + .try_into() + .map_err(|_| std::io::ErrorKind::InvalidData)?; let mut buffer = [0u8; 4]; match payload_data_type { DataType::Response => { @@ -342,7 +387,7 @@ impl Backend for TcpBackend { let mut data = vec![0u8; packet_data_length]; self.read_exact(&mut data)?; - packets.push_back(Packet { + packets.push_back(AsynchronousPacket { id: packet_info[0], data, }); @@ -351,31 +396,20 @@ impl Backend for TcpBackend { } } DataType::KeepAlive => {} - _ => return Err(Error::new("Unexpected payload data type received")), + _ => return Err(std::io::ErrorKind::InvalidData.into()), }; } Ok(None) } - - fn close(&self) { - self.stream.shutdown(std::net::Shutdown::Both).ok(); - } } fn new_tcp_backend(address: &str) -> Result { - let stream = match TcpStream::connect(address) { - Ok(stream) => { - stream.set_write_timeout(Some(Duration::from_secs(10)))?; - stream.set_read_timeout(Some(Duration::from_millis(10)))?; - stream - } - Err(error) => { - return Err(Error::new( - format!("Couldn't connect to [{address}]: {error}").as_str(), - )) - } - }; + let stream = TcpStream::connect(address).map_err(|error| { + Error::new(format!("Couldn't connect to [{address}]: {error}").as_str()) + })?; + stream.set_read_timeout(Some(POLL_TIMEOUT))?; + stream.set_write_timeout(Some(WRITE_TIMEOUT))?; let reader = BufReader::new(stream.try_clone()?); let writer = BufWriter::new(stream.try_clone()?); Ok(TcpBackend { @@ -385,9 +419,29 @@ fn new_tcp_backend(address: &str) -> Result { }) } +fn new_local_backend(port: &str) -> Result, Error> { + let mut backend: Box = if port.starts_with(SERIAL_PREFIX) { + Box::new(new_serial_backend( + port.strip_prefix(SERIAL_PREFIX).unwrap_or_default(), + )?) + } else if port.starts_with(FTDI_PREFIX) { + Box::new(new_ftdi_backend( + port.strip_prefix(FTDI_PREFIX).unwrap_or_default(), + )?) + } else { + return Err(Error::new("Invalid port prefix provided")); + }; + backend.reset()?; + Ok(backend) +} + +fn new_remote_backend(address: &str) -> Result, Error> { + Ok(Box::new(new_tcp_backend(address)?)) +} + pub struct Link { backend: Box, - packets: VecDeque, + packets: VecDeque, } impl Link { @@ -415,7 +469,7 @@ impl Link { Ok(response.data) } - fn receive_response(&mut self) -> Result { + pub fn receive_response(&mut self) -> Result { match self .backend .process_incoming_data(DataType::Response, &mut self.packets) @@ -430,7 +484,7 @@ impl Link { } } - pub fn receive_packet(&mut self) -> Result, Error> { + pub fn receive_packet(&mut self) -> Result, Error> { if self.packets.len() == 0 { let response = self .backend @@ -441,6 +495,19 @@ impl Link { } Ok(self.packets.pop_front()) } + + pub fn receive_response_or_packet(&mut self) -> Result, Error> { + let response = self + .backend + .process_incoming_data(DataType::Packet, &mut self.packets)?; + if let Some(response) = response { + return Ok(Some(UsbPacket::Response(response))); + } + if let Some(packet) = self.packets.pop_front() { + return Ok(Some(UsbPacket::AsynchronousPacket(packet))); + } + Ok(None) + } } impl Drop for Link { @@ -451,45 +518,75 @@ impl Drop for Link { pub fn new_local(port: &str) -> Result { Ok(Link { - backend: Box::new(new_serial_backend(port)?), + backend: new_local_backend(port)?, packets: VecDeque::new(), }) } pub fn new_remote(address: &str) -> Result { Ok(Link { - backend: Box::new(new_tcp_backend(address)?), + backend: new_remote_backend(address)?, packets: VecDeque::new(), }) } -pub struct LocalDevice { - pub port: String, - pub serial_number: String, +pub enum BackendType { + Serial, + Ftdi, } -pub fn list_local_devices() -> Result, Error> { +impl Display for BackendType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Self::Serial => "serial", + Self::Ftdi => "libftdi", + }) + } +} + +pub struct DeviceInfo { + pub backend: BackendType, + pub port: String, + pub serial: String, +} + +pub fn list_local_devices() -> Result, Error> { const SC64_VID: u16 = 0x0403; const SC64_PID: u16 = 0x6014; - const SC64_SID: &str = "SC64"; + const SC64_SERIAL_PREFIX: &str = "SC64"; + const SC64_DESCRIPTION: &str = "SC64"; - let mut serial_devices: Vec = Vec::new(); + let mut devices: Vec = Vec::new(); - for device in serialport::available_ports()?.into_iter() { - if let serialport::SerialPortType::UsbPort(info) = device.port_type { - let serial_number = info.serial_number.unwrap_or("".to_string()); - if info.vid == SC64_VID && info.pid == SC64_PID && serial_number.starts_with(SC64_SID) { - serial_devices.push(LocalDevice { - port: device.port_name, - serial_number, + if let Ok(list) = FtdiDevice::list(SC64_VID, SC64_PID) { + for device in list.into_iter() { + if device.description == SC64_DESCRIPTION { + devices.push(DeviceInfo { + backend: BackendType::Ftdi, + port: format!("{FTDI_PREFIX}{}", device.port), + serial: device.serial, + }) + } + } + } + + if let Ok(list) = SerialDevice::list(SC64_VID, SC64_PID) { + for device in list.into_iter() { + let is_sc64_device = device.description == SC64_DESCRIPTION + || device.serial.starts_with(SC64_SERIAL_PREFIX); + if is_sc64_device { + devices.push(DeviceInfo { + backend: BackendType::Serial, + port: format!("{SERIAL_PREFIX}{}", device.port), + serial: device.serial, }); } } } - if serial_devices.len() == 0 { + if devices.len() == 0 { return Err(Error::new("No SC64 devices found")); } - return Ok(serial_devices); + return Ok(devices); } diff --git a/sw/deployer/src/sc64/mod.rs b/sw/deployer/src/sc64/mod.rs index a1ac764..9a8064c 100644 --- a/sw/deployer/src/sc64/mod.rs +++ b/sw/deployer/src/sc64/mod.rs @@ -1,7 +1,9 @@ mod cic; mod error; pub mod firmware; +mod ftdi; mod link; +mod serial; pub mod server; mod time; mod types; @@ -12,8 +14,8 @@ pub use self::{ server::ServerEvent, types::{ BootMode, ButtonMode, ButtonState, CicSeed, DataPacket, DdDiskState, DdDriveType, DdMode, - DebugPacket, DiagnosticData, DiskPacket, DiskPacketKind, FpgaDebugData, MemoryTestPattern, - MemoryTestPatternResult, SaveType, SaveWriteback, Switch, TvType, + DebugPacket, DiagnosticData, DiskPacket, DiskPacketKind, FpgaDebugData, ISViewer, + MemoryTestPattern, MemoryTestPatternResult, SaveType, SaveWriteback, Switch, TvType, }, }; @@ -43,7 +45,7 @@ pub struct DeviceState { pub rom_write_enable: Switch, pub rom_shadow_enable: Switch, pub dd_mode: DdMode, - pub isv_address: u32, + pub isviewer: ISViewer, pub boot_mode: BootMode, pub save_type: SaveType, pub cic_seed: CicSeed, @@ -547,7 +549,7 @@ impl SC64 { rom_write_enable: get_config!(self, RomWriteEnable)?, rom_shadow_enable: get_config!(self, RomShadowEnable)?, dd_mode: get_config!(self, DdMode)?, - isv_address: get_config!(self, IsvAddress)?, + isviewer: get_config!(self, ISViewer)?, boot_mode: get_config!(self, BootMode)?, save_type: get_config!(self, SaveType)?, cic_seed: get_config!(self, CicSeed)?, @@ -597,10 +599,10 @@ impl SC64 { } } self.command_config_set(Config::RomWriteEnable(Switch::On))?; - self.command_config_set(Config::IsvAddress(offset))?; + self.command_config_set(Config::ISViewer(ISViewer::Enabled(offset)))?; } else { self.command_config_set(Config::RomWriteEnable(Switch::Off))?; - self.command_config_set(Config::IsvAddress(0))?; + self.command_config_set(Config::ISViewer(ISViewer::Disabled))?; } Ok(()) } @@ -875,13 +877,8 @@ impl SC64 { impl SC64 { pub fn open_local(port: Option) -> Result { - let port = if let Some(port) = port { - port - } else { - list_local_devices()?[0].port.clone() - }; let mut sc64 = SC64 { - link: link::new_local(&port)?, + link: link::new_local(&port.unwrap_or(list_local_devices()?[0].port.clone()))?, }; sc64.check_device()?; Ok(sc64) diff --git a/sw/deployer/src/sc64/serial.rs b/sw/deployer/src/sc64/serial.rs new file mode 100644 index 0000000..0c040ac --- /dev/null +++ b/sw/deployer/src/sc64/serial.rs @@ -0,0 +1,159 @@ +pub struct DeviceInfo { + pub description: String, + pub serial: String, + pub port: String, +} + +pub struct SerialDevice { + serial: serial2::SerialPort, + unclog_buffer: std::collections::VecDeque, + poll_timeout: std::time::Duration, + read_timeout: std::time::Duration, + write_timeout: std::time::Duration, +} + +impl SerialDevice { + const DEFAULT_POLL_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(16); + const DEFAULT_RW_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5); + const WRITE_CHUNK_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(100); + const BUFFER_SIZE: usize = 16 * 1024; + + pub fn new( + port: &str, + poll_timeout: Option, + read_timeout: Option, + write_timeout: Option, + ) -> std::io::Result { + let mut device = Self { + serial: serial2::SerialPort::open(port, 115_200)?, + unclog_buffer: std::collections::VecDeque::new(), + poll_timeout: poll_timeout.unwrap_or(Self::DEFAULT_POLL_TIMEOUT), + read_timeout: read_timeout.unwrap_or(Self::DEFAULT_RW_TIMEOUT), + write_timeout: write_timeout.unwrap_or(Self::DEFAULT_RW_TIMEOUT), + }; + device.serial.set_read_timeout(device.poll_timeout)?; + device.serial.set_write_timeout(Self::WRITE_CHUNK_TIMEOUT)?; + Ok(device) + } + + pub fn list(vendor: u16, product: u16) -> std::io::Result> { + let mut devices = vec![]; + + for port in serialport::available_ports()? { + if let serialport::SerialPortType::UsbPort(info) = port.port_type { + if info.vid == vendor && info.pid == product { + devices.push(DeviceInfo { + description: info.product.unwrap_or_default(), + serial: info.serial_number.unwrap_or_default(), + port: port.port_name, + }) + } + } + } + + devices.sort_by(|a, b| a.serial.cmp(&b.serial)); + + Ok(devices) + } + + pub fn set_dtr(&mut self, value: bool) -> std::io::Result<()> { + self.serial.set_dtr(value) + } + + pub fn read_dsr(&mut self) -> std::io::Result { + self.serial.read_dsr() + } + + pub fn discard_input(&mut self) -> std::io::Result<()> { + let timeout = std::time::Instant::now(); + self.serial.discard_input_buffer()?; + loop { + match self.serial.read(&mut vec![0u8; Self::BUFFER_SIZE]) { + Ok(_) => {} + Err(error) => match error.kind() { + std::io::ErrorKind::Interrupted + | std::io::ErrorKind::TimedOut + | std::io::ErrorKind::WouldBlock => { + return Ok(()); + } + _ => return Err(error), + }, + }; + if timeout.elapsed() > self.read_timeout { + return Err(std::io::ErrorKind::TimedOut.into()); + } + } + } + + pub fn discard_output(&mut self) -> std::io::Result<()> { + self.serial.discard_output_buffer() + } + + fn unclog_pipe(&mut self) -> std::io::Result<()> { + let mut buffer = vec![0u8; Self::BUFFER_SIZE]; + let read = match self.serial.read(&mut buffer) { + Ok(read) => read, + Err(error) => match error.kind() { + std::io::ErrorKind::Interrupted + | std::io::ErrorKind::TimedOut + | std::io::ErrorKind::WouldBlock => 0, + _ => return Err(error), + }, + }; + self.unclog_buffer.extend(buffer[0..read].iter()); + Ok(()) + } +} + +impl std::io::Read for SerialDevice { + fn read(&mut self, buffer: &mut [u8]) -> std::io::Result { + if buffer.is_empty() { + Err(std::io::ErrorKind::InvalidInput.into()) + } else if self.unclog_buffer.is_empty() { + self.serial.read(buffer) + } else { + for (index, item) in buffer.iter_mut().enumerate() { + if let Some(byte) = self.unclog_buffer.pop_front() { + *item = byte; + } else { + return Ok(index); + } + } + Ok(buffer.len()) + } + } +} + +impl std::io::Write for SerialDevice { + fn write(&mut self, buffer: &[u8]) -> std::io::Result { + let timeout = std::time::Instant::now(); + loop { + match self.serial.write(buffer) { + Ok(bytes) => return Ok(bytes), + Err(error) => match error.kind() { + std::io::ErrorKind::TimedOut => self.unclog_pipe()?, + _ => return Err(error), + }, + }; + if timeout.elapsed() > self.write_timeout { + return Err(std::io::ErrorKind::TimedOut.into()); + } + } + } + + fn flush(&mut self) -> std::io::Result<()> { + let timeout = std::time::Instant::now(); + loop { + match self.serial.flush() { + Ok(()) => return Ok(()), + Err(error) => match error.kind() { + std::io::ErrorKind::TimedOut => self.unclog_pipe()?, + _ => return Err(error), + }, + }; + if timeout.elapsed() > self.write_timeout { + return Err(std::io::ErrorKind::TimedOut.into()); + } + } + } +} diff --git a/sw/deployer/src/sc64/server.rs b/sw/deployer/src/sc64/server.rs index ae52a15..735d70f 100644 --- a/sw/deployer/src/sc64/server.rs +++ b/sw/deployer/src/sc64/server.rs @@ -1,19 +1,10 @@ use super::{ error::Error, - link::{list_local_devices, new_serial, Command, DataType, Packet, Response, Serial}, -}; -use std::{ - collections::VecDeque, - io::{BufReader, BufWriter, ErrorKind, Read, Write}, - net::{TcpListener, TcpStream}, - sync::{ - atomic::{AtomicBool, Ordering}, - mpsc::{channel, Receiver, Sender}, - Arc, + link::{ + list_local_devices, new_local, AsynchronousPacket, Command, DataType, Response, UsbPacket, }, - thread, - time::{Duration, Instant}, }; +use std::io::{Read, Write}; pub enum ServerEvent { Listening(String), @@ -22,237 +13,160 @@ pub enum ServerEvent { Err(String), } +struct StreamHandler { + stream: std::net::TcpStream, + reader: std::io::BufReader, + writer: std::io::BufWriter, +} + +const READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5); +const WRITE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5); +const KEEPALIVE_PERIOD: std::time::Duration = std::time::Duration::from_secs(5); + +impl StreamHandler { + fn new(stream: std::net::TcpStream) -> std::io::Result { + let reader = std::io::BufReader::new(stream.try_clone()?); + let writer = std::io::BufWriter::new(stream.try_clone()?); + stream.set_read_timeout(Some(READ_TIMEOUT))?; + stream.set_write_timeout(Some(WRITE_TIMEOUT))?; + Ok(StreamHandler { + stream, + reader, + writer, + }) + } + + fn try_read_header(&mut self) -> std::io::Result> { + self.stream.set_nonblocking(true)?; + let mut header = [0u8; 4]; + let result = match self.reader.read_exact(&mut header) { + Ok(()) => Ok(Some(header)), + Err(error) => match error.kind() { + std::io::ErrorKind::WouldBlock => Ok(None), + _ => Err(error), + }, + }; + self.stream.set_nonblocking(false)?; + result + } + + fn receive_command(&mut self) -> std::io::Result> { + if let Some(header) = self.try_read_header()? { + if let Ok(data_type) = TryInto::::try_into(u32::from_be_bytes(header)) { + if !matches!(data_type, DataType::Command) { + return Err(std::io::Error::other( + "Received data type was not a command data type", + )); + } + } + + let mut buffer = [0u8; 4]; + let mut id_buffer = [0u8; 1]; + let mut args = [0u32; 2]; + + self.reader.read_exact(&mut id_buffer)?; + let id = id_buffer[0]; + + self.reader.read_exact(&mut buffer)?; + args[0] = u32::from_be_bytes(buffer); + self.reader.read_exact(&mut buffer)?; + args[1] = u32::from_be_bytes(buffer); + + self.reader.read_exact(&mut buffer)?; + let command_data_length = u32::from_be_bytes(buffer) as usize; + let mut data = vec![0u8; command_data_length]; + self.reader.read_exact(&mut data)?; + + Ok(Some(Command { id, args, data })) + } else { + Ok(None) + } + } + + fn send_response(&mut self, response: Response) -> std::io::Result<()> { + self.writer + .write_all(&u32::to_be_bytes(DataType::Response.into()))?; + self.writer.write_all(&[response.id])?; + self.writer.write_all(&[response.error as u8])?; + self.writer + .write_all(&(response.data.len() as u32).to_be_bytes())?; + self.writer.write_all(&response.data)?; + self.writer.flush()?; + Ok(()) + } + + fn send_packet(&mut self, packet: AsynchronousPacket) -> std::io::Result<()> { + self.writer + .write_all(&u32::to_be_bytes(DataType::Packet.into()))?; + self.writer.write_all(&[packet.id])?; + self.writer + .write_all(&(packet.data.len() as u32).to_be_bytes())?; + self.writer.write_all(&packet.data)?; + self.writer.flush()?; + Ok(()) + } + + fn send_keepalive(&mut self) -> std::io::Result<()> { + self.writer + .write_all(&u32::to_be_bytes(DataType::KeepAlive.into()))?; + self.writer.flush()?; + Ok(()) + } +} + +fn server_accept_connection(port: String, connection: &mut StreamHandler) -> Result<(), Error> { + let mut link = new_local(&port)?; + + let mut keepalive = std::time::Instant::now(); + + loop { + match connection.receive_command() { + Ok(Some(command)) => { + link.execute_command_raw(&command, true, true)?; + } + Ok(None) => {} + Err(error) => match error.kind() { + std::io::ErrorKind::UnexpectedEof => return Ok(()), + _ => return Err(error.into()), + }, + }; + + if let Some(usb_packet) = link.receive_response_or_packet()? { + match usb_packet { + UsbPacket::Response(response) => connection.send_response(response)?, + UsbPacket::AsynchronousPacket(packet) => connection.send_packet(packet)?, + } + } + + if keepalive.elapsed() > KEEPALIVE_PERIOD { + keepalive = std::time::Instant::now(); + connection.send_keepalive().ok(); + } + } +} + pub fn run( port: Option, address: String, event_callback: fn(ServerEvent), ) -> Result<(), Error> { - let port = if let Some(port) = port { - port - } else { - list_local_devices()?[0].port.clone() - }; - let listener = TcpListener::bind(address)?; + let port = port.unwrap_or(list_local_devices()?[0].port.clone()); + let listener = std::net::TcpListener::bind(address)?; let listening_address = listener.local_addr()?; + event_callback(ServerEvent::Listening(listening_address.to_string())); - for stream in listener.incoming() { - match stream { - Ok(mut stream) => { - let peer = stream.peer_addr()?.to_string(); - event_callback(ServerEvent::Connected(peer.clone())); - match server_accept_connection(port.clone(), &mut stream) { - Ok(()) => event_callback(ServerEvent::Disconnected(peer.clone())), - Err(error) => event_callback(ServerEvent::Err(error.to_string())), - } - } - Err(error) => match error.kind() { - _ => return Err(error.into()), - }, + for incoming in listener.incoming() { + let stream = incoming?; + let peer = stream.peer_addr()?.to_string(); + + event_callback(ServerEvent::Connected(peer.clone())); + + match server_accept_connection(port.clone(), &mut StreamHandler::new(stream)?) { + Ok(()) => event_callback(ServerEvent::Disconnected(peer.clone())), + Err(error) => event_callback(ServerEvent::Err(error.to_string())), } } Ok(()) } - -enum Event { - Command(Command), - Response(Response), - Packet(Packet), - KeepAlive, - Closed(Option), -} - -fn server_accept_connection(port: String, stream: &mut TcpStream) -> Result<(), Error> { - let (event_sender, event_receiver) = channel::(); - let exit_flag = Arc::new(AtomicBool::new(false)); - - let mut stream_writer = BufWriter::new(stream.try_clone()?); - let mut stream_reader = stream.try_clone()?; - - let serial = Arc::new(new_serial(&port)?); - let serial_writer = serial.clone(); - let serial_reader = serial.clone(); - - let stream_event_sender = event_sender.clone(); - let stream_exit_flag = exit_flag.clone(); - let stream_thread = thread::spawn(move || { - let closed_sender = stream_event_sender.clone(); - match server_stream_thread(&mut stream_reader, stream_event_sender, stream_exit_flag) { - Ok(()) => closed_sender.send(Event::Closed(None)), - Err(error) => closed_sender.send(Event::Closed(Some(error))), - } - .ok(); - }); - - let serial_event_sender = event_sender.clone(); - let serial_exit_flag = exit_flag.clone(); - let serial_thread = thread::spawn(move || { - let closed_sender = serial_event_sender.clone(); - match server_serial_thread(serial_reader, serial_event_sender, serial_exit_flag) { - Ok(()) => closed_sender.send(Event::Closed(None)), - Err(error) => closed_sender.send(Event::Closed(Some(error))), - } - .ok(); - }); - - let keepalive_event_sender = event_sender.clone(); - let keepalive_exit_flag = exit_flag.clone(); - let keepalive_thread = thread::spawn(move || { - server_keepalive_thread(keepalive_event_sender, keepalive_exit_flag); - }); - - let result = server_process_events(&mut stream_writer, serial_writer, event_receiver); - - exit_flag.store(true, Ordering::Relaxed); - stream_thread.join().ok(); - serial_thread.join().ok(); - keepalive_thread.join().ok(); - - result -} - -fn server_process_events( - stream_writer: &mut BufWriter, - serial_writer: Arc, - event_receiver: Receiver, -) -> Result<(), Error> { - for event in event_receiver.into_iter() { - match event { - Event::Command(command) => { - serial_writer.send_command(&command)?; - } - Event::Response(response) => { - stream_writer.write_all(&u32::to_be_bytes(DataType::Response.into()))?; - stream_writer.write_all(&[response.id])?; - stream_writer.write_all(&[response.error as u8])?; - stream_writer.write_all(&(response.data.len() as u32).to_be_bytes())?; - stream_writer.write_all(&response.data)?; - stream_writer.flush()?; - } - Event::Packet(packet) => { - stream_writer.write_all(&u32::to_be_bytes(DataType::Packet.into()))?; - stream_writer.write_all(&[packet.id])?; - stream_writer.write_all(&(packet.data.len() as u32).to_be_bytes())?; - stream_writer.write_all(&packet.data)?; - stream_writer.flush()?; - } - Event::KeepAlive => { - stream_writer.write_all(&u32::to_be_bytes(DataType::KeepAlive.into()))?; - stream_writer.flush()?; - } - Event::Closed(result) => match result { - Some(error) => return Err(error), - None => { - break; - } - }, - } - } - - Ok(()) -} - -fn server_stream_thread( - stream: &mut TcpStream, - event_sender: Sender, - exit_flag: Arc, -) -> Result<(), Error> { - let mut stream_reader = BufReader::new(stream.try_clone()?); - - let mut header = [0u8; 4]; - let header_length = header.len(); - - loop { - let mut header_position = 0; - - let timeout = stream.read_timeout()?; - stream.set_read_timeout(Some(Duration::from_millis(10)))?; - while header_position < header_length { - if exit_flag.load(Ordering::Relaxed) { - return Ok(()); - } - match stream_reader.read(&mut header[header_position..header_length]) { - Ok(0) => return Ok(()), - Ok(bytes) => header_position += bytes, - Err(error) => match error.kind() { - ErrorKind::Interrupted | ErrorKind::TimedOut | ErrorKind::WouldBlock => {} - _ => return Err(error.into()), - }, - } - } - stream.set_read_timeout(timeout)?; - - let data_type: DataType = u32::from_be_bytes(header).try_into()?; - if !matches!(data_type, DataType::Command) { - return Err(Error::new("Received data type was not a command data type")); - } - - let mut buffer = [0u8; 4]; - let mut id_buffer = [0u8; 1]; - let mut args = [0u32; 2]; - - stream_reader.read_exact(&mut id_buffer)?; - let id = id_buffer[0]; - - stream_reader.read_exact(&mut buffer)?; - args[0] = u32::from_be_bytes(buffer); - stream_reader.read_exact(&mut buffer)?; - args[1] = u32::from_be_bytes(buffer); - - stream_reader.read_exact(&mut buffer)?; - let command_data_length = u32::from_be_bytes(buffer) as usize; - let mut data = vec![0u8; command_data_length]; - stream_reader.read_exact(&mut data)?; - - if event_sender - .send(Event::Command(Command { id, args, data })) - .is_err() - { - break; - } - } - - Ok(()) -} - -fn server_serial_thread( - serial_reader: Arc, - event_sender: Sender, - exit_flag: Arc, -) -> Result<(), Error> { - let mut packets: VecDeque = VecDeque::new(); - - while !exit_flag.load(Ordering::Relaxed) { - let response = serial_reader.process_incoming_data(DataType::Packet, &mut packets)?; - - if let Some(response) = response { - if event_sender.send(Event::Response(response)).is_err() { - break; - } - } - - if let Some(packet) = packets.pop_front() { - if event_sender.send(Event::Packet(packet)).is_err() { - break; - } - } - } - - Ok(()) -} - -fn server_keepalive_thread(event_sender: Sender, exit_flag: Arc) { - let mut keepalive = Instant::now(); - - while !exit_flag.load(Ordering::Relaxed) { - if keepalive.elapsed() >= Duration::from_secs(5) { - keepalive = Instant::now(); - if event_sender.send(Event::KeepAlive).is_err() { - break; - } - } else { - thread::sleep(Duration::from_millis(10)); - } - } -} diff --git a/sw/deployer/src/sc64/types.rs b/sw/deployer/src/sc64/types.rs index 8699207..d9e5e09 100644 --- a/sw/deployer/src/sc64/types.rs +++ b/sw/deployer/src/sc64/types.rs @@ -1,4 +1,4 @@ -use super::{link::Packet, Error}; +use super::{link::AsynchronousPacket, Error}; use std::fmt::Display; #[derive(Clone, Copy)] @@ -7,7 +7,7 @@ pub enum ConfigId { RomWriteEnable, RomShadowEnable, DdMode, - IsvAddress, + ISViewer, BootMode, SaveType, CicSeed, @@ -25,7 +25,7 @@ pub enum Config { RomWriteEnable(Switch), RomShadowEnable(Switch), DdMode(DdMode), - IsvAddress(u32), + ISViewer(ISViewer), BootMode(BootMode), SaveType(SaveType), CicSeed(CicSeed), @@ -45,7 +45,7 @@ impl From for u32 { ConfigId::RomWriteEnable => 1, ConfigId::RomShadowEnable => 2, ConfigId::DdMode => 3, - ConfigId::IsvAddress => 4, + ConfigId::ISViewer => 4, ConfigId::BootMode => 5, ConfigId::SaveType => 6, ConfigId::CicSeed => 7, @@ -69,7 +69,7 @@ impl TryFrom<(ConfigId, u32)> for Config { ConfigId::RomWriteEnable => Self::RomWriteEnable(config.try_into()?), ConfigId::RomShadowEnable => Self::RomShadowEnable(config.try_into()?), ConfigId::DdMode => Self::DdMode(config.try_into()?), - ConfigId::IsvAddress => Self::IsvAddress(config), + ConfigId::ISViewer => Self::ISViewer(config.try_into()?), ConfigId::BootMode => Self::BootMode(config.try_into()?), ConfigId::SaveType => Self::SaveType(config.try_into()?), ConfigId::CicSeed => Self::CicSeed(config.try_into()?), @@ -91,7 +91,7 @@ impl From for [u32; 2] { Config::RomWriteEnable(val) => [ConfigId::RomWriteEnable.into(), val.into()], Config::RomShadowEnable(val) => [ConfigId::RomShadowEnable.into(), val.into()], Config::DdMode(val) => [ConfigId::DdMode.into(), val.into()], - Config::IsvAddress(val) => [ConfigId::IsvAddress.into(), val.into()], + Config::ISViewer(val) => [ConfigId::ISViewer.into(), val.into()], Config::BootMode(val) => [ConfigId::BootMode.into(), val.into()], Config::SaveType(val) => [ConfigId::SaveType.into(), val.into()], Config::CicSeed(val) => [ConfigId::CicSeed.into(), val.into()], @@ -199,6 +199,41 @@ impl From for u32 { } } +pub enum ISViewer { + Disabled, + Enabled(u32), +} + +impl Display for ISViewer { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Disabled => f.write_str("Not listening"), + Self::Enabled(offset) => { + f.write_fmt(format_args!("Listening at 0x{:08X}", 0x1000_0000 + offset)) + } + } + } +} + +impl TryFrom for ISViewer { + type Error = Error; + fn try_from(value: u32) -> Result { + Ok(match value { + 0 => Self::Disabled, + offset => Self::Enabled(offset), + }) + } +} + +impl From for u32 { + fn from(value: ISViewer) -> Self { + match value { + ISViewer::Disabled => 0, + ISViewer::Enabled(offset) => offset, + } + } +} + pub enum BootMode { Menu, Rom, @@ -588,9 +623,9 @@ pub enum DataPacket { UpdateStatus(UpdateStatus), } -impl TryFrom for DataPacket { +impl TryFrom for DataPacket { type Error = Error; - fn try_from(value: Packet) -> Result { + fn try_from(value: AsynchronousPacket) -> Result { Ok(match value.id { b'B' => Self::Button, b'G' => Self::DataFlushed,