You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

518 lines
16 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2023 Alex Shvartzkop <dudesuchamazing@gmail.com>
  5. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include <eda_item.h>
  25. #include <pcb_base_edit_frame.h>
  26. #include <router/pns_meander.h>
  27. #include <router/pns_meander_placer_base.h>
  28. #include <router/pns_router.h>
  29. #include <router/pns_routing_settings.h>
  30. namespace KIGFX
  31. {
  32. class VIEW;
  33. class RENDER_SETTINGS;
  34. }
  35. enum LENGTH_TUNING_MODE
  36. {
  37. SINGLE,
  38. DIFF_PAIR,
  39. DIFF_PAIR_SKEW
  40. };
  41. class TUNING_STATUS_VIEW_ITEM : public EDA_ITEM
  42. {
  43. public:
  44. TUNING_STATUS_VIEW_ITEM( PCB_BASE_EDIT_FRAME* aFrame );
  45. wxString GetClass() const override;
  46. #if defined(DEBUG)
  47. void Show( int nestLevel, std::ostream& os ) const override;
  48. #endif
  49. VECTOR2I GetPosition() const override;
  50. void SetPosition( const VECTOR2I& aPos ) override;
  51. void SetMinMax( const double aMin, const double aMax );
  52. void ClearMinMax();
  53. void SetCurrent( const double aCurrent, const wxString& aLabel );
  54. void SetIsTimeDomain( const bool aIsTimeDomain );
  55. const BOX2I ViewBBox() const override;
  56. std::vector<int> ViewGetLayers() const override;
  57. void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override;
  58. protected:
  59. EDA_DRAW_FRAME* m_frame;
  60. VECTOR2I m_pos;
  61. double m_min;
  62. double m_max;
  63. double m_current;
  64. wxString m_currentLabel;
  65. wxString m_currentText;
  66. wxString m_minText;
  67. wxString m_maxText;
  68. bool m_isTimeDomain;
  69. };
  70. class PCB_TUNING_PATTERN : public PCB_GENERATOR
  71. {
  72. public:
  73. static const wxString GENERATOR_TYPE;
  74. static const wxString DISPLAY_NAME;
  75. PCB_TUNING_PATTERN( BOARD_ITEM* aParent = nullptr, PCB_LAYER_ID aLayer = F_Cu,
  76. LENGTH_TUNING_MODE aMode = LENGTH_TUNING_MODE::SINGLE );
  77. wxString GetGeneratorType() const override { return wxS( "tuning_pattern" ); }
  78. wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override
  79. {
  80. return _( "Tuning Pattern" );
  81. }
  82. wxString GetFriendlyName() const override
  83. {
  84. return _( "Tuning Pattern" );
  85. }
  86. wxString GetPluralName() const override
  87. {
  88. return _( "Tuning Patterns" );
  89. }
  90. wxString GetCommitMessage() const override
  91. {
  92. return _( "Edit Tuning Pattern" );
  93. }
  94. BITMAPS GetMenuImage() const override
  95. {
  96. switch( m_tuningMode )
  97. {
  98. case SINGLE: return BITMAPS::ps_tune_length; break;
  99. case DIFF_PAIR: return BITMAPS::ps_diff_pair_tune_length; break;
  100. case DIFF_PAIR_SKEW: return BITMAPS::ps_diff_pair_tune_phase; break;
  101. }
  102. return BITMAPS::unknown;
  103. }
  104. static PCB_TUNING_PATTERN* CreateNew( GENERATOR_TOOL* aTool, PCB_BASE_EDIT_FRAME* aFrame,
  105. BOARD_CONNECTED_ITEM* aStartItem,
  106. LENGTH_TUNING_MODE aMode );
  107. void EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
  108. bool Update( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
  109. void EditFinish( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
  110. void EditCancel( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
  111. void Remove( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COMMIT* aCommit ) override;
  112. bool MakeEditPoints( EDIT_POINTS& points ) const override;
  113. bool UpdateFromEditPoints( EDIT_POINTS& aEditPoints ) override;
  114. bool UpdateEditPoints( EDIT_POINTS& aEditPoints ) override;
  115. void Move( const VECTOR2I& aMoveVector ) override
  116. {
  117. m_origin += aMoveVector;
  118. m_end += aMoveVector;
  119. if( !this->HasFlag( IN_EDIT ) )
  120. {
  121. PCB_GROUP::Move( aMoveVector );
  122. if( m_baseLine )
  123. m_baseLine->Move( aMoveVector );
  124. if( m_baseLineCoupled )
  125. m_baseLineCoupled->Move( aMoveVector );
  126. }
  127. }
  128. void Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) override
  129. {
  130. if( !this->HasFlag( IN_EDIT ) )
  131. {
  132. PCB_GENERATOR::Rotate( aRotCentre, aAngle );
  133. RotatePoint( m_end, aRotCentre, aAngle );
  134. if( m_baseLine )
  135. m_baseLine->Rotate( aAngle, aRotCentre );
  136. if( m_baseLineCoupled )
  137. m_baseLineCoupled->Rotate( aAngle, aRotCentre );
  138. }
  139. }
  140. void Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) override
  141. {
  142. if( !this->HasFlag( IN_EDIT ) )
  143. {
  144. PCB_GENERATOR::Flip( aCentre, aFlipDirection );
  145. baseMirror( aCentre, aFlipDirection );
  146. }
  147. }
  148. void Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection ) override
  149. {
  150. if( !this->HasFlag( IN_EDIT ) )
  151. {
  152. PCB_GENERATOR::Mirror( aCentre, aFlipDirection );
  153. baseMirror( aCentre, aFlipDirection );
  154. }
  155. }
  156. void SetLayer( PCB_LAYER_ID aLayer ) override
  157. {
  158. PCB_GENERATOR::SetLayer( aLayer );
  159. for( BOARD_ITEM* item : GetBoardItems() )
  160. item->SetLayer( aLayer );
  161. }
  162. PCB_LAYER_ID GetLayer() const override
  163. {
  164. return PCB_GENERATOR::GetLayer();
  165. }
  166. const BOX2I GetBoundingBox() const override
  167. {
  168. return getOutline().BBox();
  169. }
  170. std::vector<int> ViewGetLayers() const override
  171. {
  172. return { LAYER_ANCHOR, GetLayer() };
  173. }
  174. bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override
  175. {
  176. return getOutline().Collide( aPosition, aAccuracy );
  177. }
  178. bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const override
  179. {
  180. BOX2I sel = aRect;
  181. if ( aAccuracy )
  182. sel.Inflate( aAccuracy );
  183. if( aContained )
  184. return sel.Contains( GetBoundingBox() );
  185. return sel.Intersects( GetBoundingBox() );
  186. }
  187. bool HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const override
  188. {
  189. return KIGEOM::ShapeHitTest( aPoly, getOutline(), aContained );
  190. }
  191. const BOX2I ViewBBox() const override { return GetBoundingBox(); }
  192. EDA_ITEM* Clone() const override { return new PCB_TUNING_PATTERN( *this ); }
  193. void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override final;
  194. const VECTOR2I& GetEnd() const { return m_end; }
  195. void SetEnd( const VECTOR2I& aValue ) { m_end = aValue; }
  196. int GetEndX() const { return m_end.x; }
  197. void SetEndX( int aValue ) { m_end.x = aValue; }
  198. int GetEndY() const { return m_end.y; }
  199. void SetEndY( int aValue ) { m_end.y = aValue; }
  200. int GetWidth() const
  201. {
  202. for( BOARD_ITEM* item : GetBoardItems() )
  203. if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
  204. return track->GetWidth();
  205. return m_trackWidth;
  206. }
  207. void SetWidth( int aValue )
  208. {
  209. m_trackWidth = aValue;
  210. for( BOARD_ITEM* item : GetBoardItems() )
  211. if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
  212. track->SetWidth( aValue );
  213. }
  214. int GetNetCode() const
  215. {
  216. for( BOARD_ITEM* item : GetBoardItems() )
  217. if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
  218. return bci->GetNetCode();
  219. return 0;
  220. }
  221. void SetNetCode( int aNetCode )
  222. {
  223. if( BOARD* board = GetBoard() )
  224. {
  225. if( NETINFO_ITEM* net = board->FindNet( aNetCode ) )
  226. m_lastNetName = net->GetNetname();
  227. else
  228. m_lastNetName.clear();
  229. }
  230. for( BOARD_ITEM* item : GetBoardItems() )
  231. if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
  232. bci->SetNetCode( aNetCode );
  233. }
  234. bool HasSolderMask() const
  235. {
  236. for( BOARD_ITEM* item : GetBoardItems() )
  237. if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
  238. return track->HasSolderMask();
  239. return true;
  240. }
  241. void SetHasSolderMask( bool aVal )
  242. {
  243. for( BOARD_ITEM* item : GetBoardItems() )
  244. if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
  245. track->SetHasSolderMask( aVal );
  246. }
  247. std::optional<int> GetLocalSolderMaskMargin() const
  248. {
  249. for( BOARD_ITEM* item : GetBoardItems() )
  250. if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
  251. return track->GetLocalSolderMaskMargin();
  252. return std::optional<int>();
  253. }
  254. void SetLocalSolderMaskMargin( std::optional<int> aMargin )
  255. {
  256. for( BOARD_ITEM* item : GetBoardItems() )
  257. if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
  258. track->SetLocalSolderMaskMargin( aMargin );
  259. }
  260. LENGTH_TUNING_MODE GetTuningMode() const { return m_tuningMode; }
  261. PNS::ROUTER_MODE GetPNSMode()
  262. {
  263. switch( m_tuningMode )
  264. {
  265. case LENGTH_TUNING_MODE::SINGLE: return PNS::PNS_MODE_TUNE_SINGLE;
  266. case LENGTH_TUNING_MODE::DIFF_PAIR: return PNS::PNS_MODE_TUNE_DIFF_PAIR;
  267. case LENGTH_TUNING_MODE::DIFF_PAIR_SKEW: return PNS::PNS_MODE_TUNE_DIFF_PAIR_SKEW;
  268. default: return PNS::PNS_MODE_TUNE_SINGLE;
  269. }
  270. }
  271. PNS::MEANDER_SETTINGS& GetSettings() { return m_settings; }
  272. int GetMinAmplitude() const { return m_settings.m_minAmplitude; }
  273. void SetMinAmplitude( int aValue )
  274. {
  275. aValue = std::max( aValue, 0 );
  276. m_settings.m_minAmplitude = aValue;
  277. if( m_settings.m_maxAmplitude < m_settings.m_minAmplitude )
  278. m_settings.m_maxAmplitude = m_settings.m_minAmplitude;
  279. }
  280. int GetMaxAmplitude() const { return m_settings.m_maxAmplitude; }
  281. void SetMaxAmplitude( int aValue )
  282. {
  283. aValue = std::max( aValue, 0 );
  284. m_settings.m_maxAmplitude = aValue;
  285. if( m_settings.m_maxAmplitude < m_settings.m_minAmplitude )
  286. m_settings.m_minAmplitude = m_settings.m_maxAmplitude;
  287. }
  288. // Update the initial side one time at EditStart based on m_end.
  289. void UpdateSideFromEnd() { m_updateSideFromEnd = true; }
  290. PNS::MEANDER_SIDE GetInitialSide() const { return m_settings.m_initialSide; }
  291. void SetInitialSide( PNS::MEANDER_SIDE aValue ) { m_settings.m_initialSide = aValue; }
  292. int GetSpacing() const { return m_settings.m_spacing; }
  293. void SetSpacing( int aValue ) { m_settings.m_spacing = aValue; }
  294. std::optional<int> GetTargetLength() const
  295. {
  296. if( m_settings.m_targetLength.Opt() == PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED )
  297. return std::optional<int>();
  298. else
  299. return m_settings.m_targetLength.Opt();
  300. }
  301. void SetTargetLength( std::optional<int> aValue )
  302. {
  303. m_settings.m_isTimeDomain = false;
  304. if( aValue.has_value() )
  305. m_settings.SetTargetLength( aValue.value() );
  306. else
  307. m_settings.SetTargetLength( PNS::MEANDER_SETTINGS::LENGTH_UNCONSTRAINED );
  308. }
  309. std::optional<int> GetTargetDelay() const
  310. {
  311. if( m_settings.m_targetLengthDelay.Opt() == PNS::MEANDER_SETTINGS::DELAY_UNCONSTRAINED )
  312. return std::optional<int>();
  313. else
  314. return m_settings.m_targetLengthDelay.Opt();
  315. }
  316. void SetTargetDelay( std::optional<int> aValue )
  317. {
  318. m_settings.m_isTimeDomain = true;
  319. if( aValue.has_value() )
  320. m_settings.SetTargetLengthDelay( aValue.value() );
  321. else
  322. m_settings.SetTargetLengthDelay( PNS::MEANDER_SETTINGS::DELAY_UNCONSTRAINED );
  323. }
  324. int GetTargetSkew() const { return m_settings.m_targetSkew.Opt(); }
  325. void SetTargetSkew( int aValue ) { m_settings.SetTargetSkew( aValue ); }
  326. int GetTargetSkewDelay() const { return m_settings.m_targetSkewDelay.Opt(); }
  327. void SetTargetSkewDelay( int aValue ) { m_settings.SetTargetSkewDelay( aValue ); }
  328. bool GetOverrideCustomRules() const { return m_settings.m_overrideCustomRules; }
  329. void SetOverrideCustomRules( bool aOverride ) { m_settings.m_overrideCustomRules = aOverride; }
  330. int GetCornerRadiusPercentage() const { return m_settings.m_cornerRadiusPercentage; }
  331. void SetCornerRadiusPercentage( int aValue ) { m_settings.m_cornerRadiusPercentage = aValue; }
  332. bool IsSingleSided() const { return m_settings.m_singleSided; }
  333. void SetSingleSided( bool aValue ) { m_settings.m_singleSided = aValue; }
  334. bool IsRounded() const { return m_settings.m_cornerStyle == PNS::MEANDER_STYLE_ROUND; }
  335. void SetRounded( bool aFlag ) { m_settings.m_cornerStyle = aFlag ? PNS::MEANDER_STYLE_ROUND
  336. : PNS::MEANDER_STYLE_CHAMFER; }
  337. std::vector<std::pair<wxString, wxVariant>> GetRowData() override
  338. {
  339. std::vector<std::pair<wxString, wxVariant>> data = PCB_GENERATOR::GetRowData();
  340. data.emplace_back( _HKI( "Net" ), m_lastNetName );
  341. data.emplace_back( _HKI( "Tuning" ), m_tuningInfo );
  342. return data;
  343. }
  344. const STRING_ANY_MAP GetProperties() const override;
  345. void SetProperties( const STRING_ANY_MAP& aProps ) override;
  346. void ShowPropertiesDialog( PCB_BASE_EDIT_FRAME* aEditFrame ) override;
  347. std::vector<EDA_ITEM*> GetPreviewItems( GENERATOR_TOOL* aTool, PCB_BASE_EDIT_FRAME* aFrame,
  348. bool aStatusItemsOnly = false ) override;
  349. void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
  350. protected:
  351. void swapData( BOARD_ITEM* aImage ) override
  352. {
  353. wxASSERT( aImage->Type() == PCB_GENERATOR_T );
  354. std::swap( *this, *static_cast<PCB_TUNING_PATTERN*>( aImage ) );
  355. }
  356. bool recoverBaseline( PNS::ROUTER* aRouter );
  357. bool baselineValid();
  358. bool initBaseLine( PNS::ROUTER* aRouter, int aPNSLayer, BOARD* aBoard, VECTOR2I& aStart,
  359. VECTOR2I& aEnd, NETINFO_ITEM* aNet,
  360. std::optional<SHAPE_LINE_CHAIN>& aBaseLine );
  361. bool initBaseLines( PNS::ROUTER* aRouter, int aPNSLayer, BOARD* aBoard );
  362. bool removeToBaseline( PNS::ROUTER* aRouter, int aPNSLayer, SHAPE_LINE_CHAIN& aBaseLine );
  363. bool resetToBaseline( GENERATOR_TOOL* aTool, int aPNSLayer, SHAPE_LINE_CHAIN& aBaseLine,
  364. bool aPrimary );
  365. SHAPE_LINE_CHAIN getOutline() const;
  366. void baseMirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
  367. {
  368. PCB_GENERATOR::baseMirror( aCentre, aFlipDirection );
  369. if( m_baseLine )
  370. {
  371. m_baseLine->Mirror( aCentre, aFlipDirection );
  372. m_origin = m_baseLine->CPoint( 0 );
  373. m_end = m_baseLine->CLastPoint();
  374. }
  375. if( m_baseLineCoupled )
  376. m_baseLineCoupled->Mirror( aCentre, aFlipDirection );
  377. if( m_settings.m_initialSide == PNS::MEANDER_SIDE_RIGHT )
  378. m_settings.m_initialSide = PNS::MEANDER_SIDE_LEFT;
  379. else
  380. m_settings.m_initialSide = PNS::MEANDER_SIDE_RIGHT;
  381. }
  382. protected:
  383. VECTOR2I m_end;
  384. PNS::MEANDER_SETTINGS m_settings;
  385. std::optional<SHAPE_LINE_CHAIN> m_baseLine;
  386. std::optional<SHAPE_LINE_CHAIN> m_baseLineCoupled;
  387. int m_trackWidth;
  388. int m_diffPairGap;
  389. LENGTH_TUNING_MODE m_tuningMode;
  390. wxString m_lastNetName;
  391. wxString m_tuningInfo;
  392. PNS::MEANDER_PLACER_BASE::TUNING_STATUS m_tuningStatus;
  393. bool m_updateSideFromEnd;
  394. };