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.

482 lines
16 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 1992-2011 jean-pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
  5. * Copyright (C) 1992-2011 Wayne Stambaugh <stambaughw@verizon.net>
  6. * Copyright (C) 1992-2015 KiCad Developers, see authors.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. /**
  26. * @file eeschema/sch_reference_list.h
  27. */
  28. #ifndef _SCH_REFERENCE_LIST_H_
  29. #define _SCH_REFERENCE_LIST_H_
  30. #include <macros.h>
  31. #include <class_libentry.h>
  32. #include <sch_sheet_path.h>
  33. #include <sch_component.h>
  34. #include <sch_text.h>
  35. #include <map>
  36. class SCH_REFERENCE;
  37. class SCH_REFERENCE_LIST;
  38. /**
  39. * Class SCH_REFERENCE
  40. * is used as a helper to define a component's reference designator in a schematic. This
  41. * helper is required in a complex hierarchy because a component can be used more than
  42. * once and its reference depends on the sheet path. This class is used to flatten the
  43. * schematic hierarchy for annotation, net list generation, and bill of material
  44. * generation.
  45. */
  46. class SCH_REFERENCE
  47. {
  48. /// Component reference prefix, without number (for IC1, this is IC) )
  49. UTF8 m_Ref; // it's private, use the accessors please
  50. SCH_COMPONENT* m_RootCmp; ///< The component associated the reference object.
  51. LIB_PART* m_Entry; ///< The source component from a library.
  52. wxPoint m_CmpPos; ///< The physical position of the component in schematic
  53. ///< used to annotate by X or Y position
  54. int m_Unit; ///< The unit number for components with multiple parts
  55. ///< per package.
  56. SCH_SHEET_PATH m_SheetPath; ///< The sheet path for this reference.
  57. bool m_IsNew; ///< True if not yet annotated.
  58. int m_SheetNum; ///< The sheet number for the reference.
  59. time_t m_TimeStamp; ///< The time stamp for the reference.
  60. EDA_TEXT* m_Value; ///< The component value of the reference. It is the
  61. ///< same for all instances.
  62. int m_NumRef; ///< The numeric part of the reference designator.
  63. int m_Flag;
  64. friend class SCH_REFERENCE_LIST;
  65. public:
  66. SCH_REFERENCE() :
  67. m_SheetPath()
  68. {
  69. m_RootCmp = NULL;
  70. m_Entry = NULL;
  71. m_Unit = 0;
  72. m_TimeStamp = 0;
  73. m_IsNew = false;
  74. m_Value = NULL;
  75. m_NumRef = 0;
  76. m_Flag = 0;
  77. m_SheetNum = 0;
  78. }
  79. SCH_REFERENCE( SCH_COMPONENT* aComponent, LIB_PART* aLibComponent,
  80. SCH_SHEET_PATH& aSheetPath );
  81. SCH_COMPONENT* GetComp() const { return m_RootCmp; }
  82. LIB_PART* GetLibPart() const { return m_Entry; }
  83. SCH_SHEET_PATH GetSheetPath() const { return m_SheetPath; }
  84. int GetUnit() const { return m_Unit; }
  85. void SetSheetNumber( int aSheetNumber ) { m_SheetNum = aSheetNumber; }
  86. /**
  87. * Function Annotate
  88. * updates the annotation of the component according the the current object state.
  89. */
  90. void Annotate();
  91. /**
  92. * Function Split
  93. * attempts to split the reference designator into a name (U) and number (1). If the
  94. * last character is '?' or not a digit, the reference is tagged as not annotated.
  95. * For components with multiple parts per package that are not already annotated, set
  96. * m_Unit to a max value (0x7FFFFFFF).
  97. */
  98. void Split();
  99. /* Some accessors which hide the strategy of how the reference is stored,
  100. thereby making it easy to change that strategy.
  101. */
  102. void SetRef( const wxString& aReference )
  103. {
  104. m_Ref = aReference;
  105. }
  106. wxString GetRef() const
  107. {
  108. return m_Ref;
  109. }
  110. void SetRefStr( const std::string& aReference )
  111. {
  112. m_Ref = aReference;
  113. }
  114. const char* GetRefStr() const
  115. {
  116. return m_Ref.c_str();
  117. }
  118. int CompareValue( const SCH_REFERENCE& item ) const
  119. {
  120. return m_Value->GetText().Cmp( item.m_Value->GetText() );
  121. }
  122. int CompareRef( const SCH_REFERENCE& item ) const
  123. {
  124. return m_Ref.compare( item.m_Ref );
  125. }
  126. int CompareLibName( const SCH_REFERENCE& item ) const
  127. {
  128. return m_RootCmp->GetLibId().GetLibItemName().compare(
  129. item.m_RootCmp->GetLibId().GetLibItemName() );
  130. }
  131. /**
  132. * Function IsSameInstance
  133. * returns whether this reference refers to the same component instance
  134. * (component and sheet) as another.
  135. */
  136. bool IsSameInstance( const SCH_REFERENCE& other ) const
  137. {
  138. return GetComp() == other.GetComp() && GetSheetPath().Path() == other.GetSheetPath().Path();
  139. }
  140. bool IsUnitsLocked()
  141. {
  142. return m_Entry->UnitsLocked();
  143. }
  144. };
  145. /**
  146. * Class SCH_REFERENCE_LIST
  147. * is used to create a flattened list of components because in a complex hierarchy, a component
  148. * can be used more than once and its reference designator is dependent on the sheet path for
  149. * the same component. This flattened list is used for netlist generation, BOM generation,
  150. * and schematic annotation.
  151. */
  152. class SCH_REFERENCE_LIST
  153. {
  154. private:
  155. std::vector <SCH_REFERENCE> componentFlatList;
  156. public:
  157. /** Constructor
  158. */
  159. SCH_REFERENCE_LIST()
  160. {
  161. }
  162. SCH_REFERENCE& operator[]( int aIndex )
  163. {
  164. return componentFlatList[ aIndex ];
  165. }
  166. /**
  167. * Function GetCount
  168. * @return the number of items in the list
  169. */
  170. unsigned GetCount()
  171. {
  172. return componentFlatList.size();
  173. }
  174. /**
  175. * Function GetItem
  176. * @return the aIdx item
  177. */
  178. SCH_REFERENCE& GetItem( int aIdx )
  179. {
  180. return componentFlatList[aIdx];
  181. }
  182. /**
  183. * Function AddItem
  184. * adds a SCH_REFERENCE object to the list of references.
  185. * @param aItem - a SCH_REFERENCE item to add
  186. */
  187. void AddItem( SCH_REFERENCE& aItem )
  188. {
  189. componentFlatList.push_back( aItem );
  190. }
  191. /**
  192. * Function RemoveItem
  193. * removes an item from the list of references.
  194. *
  195. * @param aIndex is the index of the item to be removed.
  196. */
  197. void RemoveItem( unsigned int aIndex );
  198. /**
  199. * Function RemoveSubComponentsFromList
  200. * Remove sub components from the list, when multiples parts per package are
  201. * found in this list.
  202. * Useful to create BOM, when a component must appear only once
  203. */
  204. void RemoveSubComponentsFromList();
  205. /* Sort functions:
  206. * Sort functions are used to sort components for annotation or BOM generation.
  207. * Because sorting depend on we want to do, there are many sort functions.
  208. * Note:
  209. * When creating BOM, components are fully annotated.
  210. * references are something like U3, U5 or R4, R8
  211. * When annotating, some or all components are not annotated,
  212. * i.e. ref is only U or R, with no number.
  213. */
  214. /**
  215. * Function SplitReferences
  216. * attempts to split all reference designators into a name (U) and number (1). If the
  217. * last character is '?' or not a digit, the reference is tagged as not annotated.
  218. * For components with multiple parts per package that are not already annotated, set
  219. * m_Unit to a max value (0x7FFFFFFF).
  220. * @see SCH_REFERENCE::Split()
  221. */
  222. void SplitReferences()
  223. {
  224. for( unsigned ii = 0; ii < GetCount(); ii++ )
  225. componentFlatList[ii].Split();
  226. }
  227. /**
  228. * function UpdateAnnotation
  229. * Updates the reference components for the schematic project (or the current sheet)
  230. * Note: this function does not calculate the reference numbers stored in m_NumRef
  231. * So, it must be called after calculation of new reference numbers
  232. * @see SCH_REFERENCE::Annotate()
  233. */
  234. void UpdateAnnotation()
  235. {
  236. /* update the reference numbers */
  237. for( unsigned ii = 0; ii < GetCount(); ii++ )
  238. {
  239. componentFlatList[ii].Annotate();
  240. }
  241. }
  242. /**
  243. * Function Annotate
  244. * set the reference designators in the list that have not been annotated.
  245. * @param aUseSheetNum Set to true to start annotation for each sheet at the sheet number
  246. * times \a aSheetIntervalId. Otherwise annotate incrementally.
  247. * @param aSheetIntervalId The per sheet reference designator multiplier.
  248. * @param aLockedUnitMap A SCH_MULTI_UNIT_REFERENCE_MAP of reference designator wxStrings
  249. * to SCH_REFERENCE_LISTs. May be an empty map. If not empty, any multi-unit parts
  250. * found in this map will be annotated as a group rather than individually.
  251. * <p>
  252. * If a the sheet number is 2 and \a aSheetIntervalId is 100, then the first reference
  253. * designator would be 201 and the last reference designator would be 299 when no overlap
  254. * occurs with sheet number 3. If there are 150 items in sheet number 2, then items are
  255. * referenced U201 to U351, and items in sheet 3 start from U352
  256. * </p>
  257. */
  258. void Annotate( bool aUseSheetNum, int aSheetIntervalId, SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap );
  259. /**
  260. * Function CheckAnnotation
  261. * check for annotations errors.
  262. * <p>
  263. * The following annotation error conditions are tested:
  264. * <ul>
  265. * <li>Components not annotated.</li>
  266. * <li>Components having the same reference designator (duplicates).</li>
  267. * <li>Components with multiple parts per package having different reference designators.</li>
  268. * <li>Components with multiple parts per package with invalid part count.</li>
  269. * </ul>
  270. * </p>
  271. * @param aMessageList A wxArrayString to store error messages.
  272. * @return The number of errors found.
  273. */
  274. int CheckAnnotation( wxArrayString* aMessageList );
  275. /**
  276. * Function sortByXCoordinate
  277. * sorts the list of references by X position.
  278. * <p>
  279. * Components are sorted as follows:
  280. * <ul>
  281. * <li>Numeric value of reference designator.</li>
  282. * <li>Sheet number.</li>
  283. * <li>X coordinate position.</li>
  284. * <li>Y coordinate position.</li>
  285. * <li>Time stamp.</li>
  286. * </ul>
  287. * </p>
  288. */
  289. void SortByXCoordinate()
  290. {
  291. sort( componentFlatList.begin(), componentFlatList.end(), sortByXPosition );
  292. }
  293. /**
  294. * Function sortByYCoordinate
  295. * sorts the list of references by Y position.
  296. * <p>
  297. * Components are sorted as follows:
  298. * <ul>
  299. * <li>Numeric value of reference designator.</li>
  300. * <li>Sheet number.</li>
  301. * <li>Y coordinate position.</li>
  302. * <li>X coordinate position.</li>
  303. * <li>Time stamp.</li>
  304. * </ul>
  305. * </p>
  306. */
  307. void SortByYCoordinate()
  308. {
  309. sort( componentFlatList.begin(), componentFlatList.end(), sortByYPosition );
  310. }
  311. /**
  312. * Function SortComponentsByTimeStamp
  313. * sort the flat list by Time Stamp.
  314. * Useful to detect duplicate Time Stamps
  315. */
  316. void SortByTimeStamp()
  317. {
  318. sort( componentFlatList.begin(), componentFlatList.end(), sortByTimeStamp );
  319. }
  320. /**
  321. * Function SortByRefAndValue
  322. * sorts the list of references by value.
  323. * <p>
  324. * Components are sorted in the following order:
  325. * <ul>
  326. * <li>Numeric value of reference designator.</li>
  327. * <li>Value of component.</li>
  328. * <li>Unit number when component has multiple parts.</li>
  329. * <li>Sheet number.</li>
  330. * <li>X coordinate position.</li>
  331. * <li>Y coordinate position.</li>
  332. * </ul>
  333. * </p>
  334. */
  335. void SortByRefAndValue()
  336. {
  337. sort( componentFlatList.begin(), componentFlatList.end(), sortByRefAndValue );
  338. }
  339. /**
  340. * Function SortByReferenceOnly
  341. * sorts the list of references by reference.
  342. * <p>
  343. * Components are sorted in the following order:
  344. * <ul>
  345. * <li>Numeric value of reference designator.</li>
  346. * <li>Unit number when component has multiple parts.</li>
  347. * </ul>
  348. * </p>
  349. */
  350. void SortByReferenceOnly()
  351. {
  352. sort( componentFlatList.begin(), componentFlatList.end(), sortByReferenceOnly );
  353. }
  354. /**
  355. * Function GetUnit
  356. * searches the sorted list of components for a another component with the same
  357. * reference and a given part unit. Use this method to manage components with
  358. * multiple parts per package.
  359. * @param aIndex = index in aComponentsList for of given SCH_REFERENCE item to test.
  360. * @param aUnit = the given unit number to search
  361. * @return index in aComponentsList if found or -1 if not found
  362. */
  363. int FindUnit( size_t aIndex, int aUnit );
  364. /**
  365. * Function GetRefsInUse
  366. * adds all the reference designator numbers greater than \a aMinRefId to \a aIdList
  367. * skipping the reference at \a aIndex.
  368. * @param aIndex = the current component index to use for reference prefix filtering.
  369. * @param aIdList = the buffer to fill
  370. * @param aMinRefId = the min id value to store. all values < aMinRefId are ignored
  371. */
  372. void GetRefsInUse( int aIndex, std::vector< int >& aIdList, int aMinRefId );
  373. /**
  374. * Function GetLastReference
  375. * returns the last used (greatest) reference number in the reference list
  376. * for the prefix reference given by \a aIndex. The component list must be
  377. * sorted.
  378. *
  379. * @param aIndex The index of the reference item used for the search pattern.
  380. * @param aMinValue The minimum value for the current search.
  381. */
  382. int GetLastReference( int aIndex, int aMinValue );
  383. #if defined(DEBUG)
  384. void Show( const char* aPrefix = "" )
  385. {
  386. printf( "%s\n", aPrefix );
  387. for( unsigned i=0; i<componentFlatList.size(); ++i )
  388. {
  389. SCH_REFERENCE& schref = componentFlatList[i];
  390. printf( " [%-2d] ref:%-8s num:%-3d lib_part:%s\n",
  391. i,
  392. schref.m_Ref.c_str(),
  393. schref.m_NumRef,
  394. TO_UTF8( schref.GetLibPart()->GetName() )
  395. );
  396. }
  397. }
  398. #endif
  399. private:
  400. /* sort functions used to sort componentFlatList
  401. */
  402. static bool sortByRefAndValue( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );
  403. static bool sortByXPosition( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );
  404. static bool sortByYPosition( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );
  405. static bool sortByTimeStamp( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );
  406. static bool sortByReferenceOnly( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );
  407. /**
  408. * Function CreateFirstFreeRefId
  409. * searches for the first free reference number in \a aListId of reference numbers in use.
  410. * This function just searches for a hole in a list of incremented numbers, this list must
  411. * be sorted by increasing values and each value can be stored only once. The new value
  412. * is added to the list.
  413. * @see BuildRefIdInUseList to prepare this list
  414. * @param aIdList The buffer that contains the reference numbers in use.
  415. * @param aFirstValue The first expected free value
  416. * @return The first free (not yet used) value.
  417. */
  418. int CreateFirstFreeRefId( std::vector<int>& aIdList, int aFirstValue );
  419. };
  420. #endif // _SCH_REFERENCE_LIST_H_