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.

714 lines
16 KiB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
11 years ago
12 years ago
12 years ago
11 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  5. * Copyright (C) 2014 KiCad Developers, see change_log.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 <stdarg.h>
  25. #include <assert.h>
  26. #include <layers_id_colors_and_visibility.h>
  27. #include <class_board.h>
  28. LSET::LSET( const LAYER_ID* aArray, unsigned aCount ) :
  29. BASE_SET()
  30. {
  31. for( unsigned i=0; i<aCount; ++i )
  32. set( aArray[i] );
  33. }
  34. LSET::LSET( unsigned aIdCount, LAYER_ID aFirst, ... ) :
  35. BASE_SET()
  36. {
  37. // The constructor, without the mandatory aFirst argument, could have been confused
  38. // by the compiler with the LSET( LAYER_ID ). With aFirst, that ambiguity is not
  39. // present. Therefore aIdCount must always be >=1.
  40. wxASSERT_MSG( aIdCount > 0, wxT( "aIdCount must be >= 1" ) );
  41. set( aFirst );
  42. if( --aIdCount )
  43. {
  44. va_list ap;
  45. va_start( ap, aFirst );
  46. for( unsigned i=0; i<aIdCount; ++i )
  47. {
  48. LAYER_ID id = (LAYER_ID) va_arg( ap, int );
  49. // printf( "%s: id:%d LAYER_ID_COUNT:%d\n", __func__, id, LAYER_ID_COUNT );
  50. assert( unsigned( id ) < LAYER_ID_COUNT );
  51. set( id );
  52. }
  53. va_end( ap );
  54. }
  55. }
  56. const wxChar* LSET::Name( LAYER_ID aLayerId )
  57. {
  58. const wxChar* txt;
  59. // using a switch to explicitly show the mapping more clearly
  60. switch( aLayerId )
  61. {
  62. case F_Cu: txt = wxT( "F.Cu" ); break;
  63. case In1_Cu: txt = wxT( "In1.Cu" ); break;
  64. case In2_Cu: txt = wxT( "In2.Cu" ); break;
  65. case In3_Cu: txt = wxT( "In3.Cu" ); break;
  66. case In4_Cu: txt = wxT( "In4.Cu" ); break;
  67. case In5_Cu: txt = wxT( "In5.Cu" ); break;
  68. case In6_Cu: txt = wxT( "In6.Cu" ); break;
  69. case In7_Cu: txt = wxT( "In7.Cu" ); break;
  70. case In8_Cu: txt = wxT( "In8.Cu" ); break;
  71. case In9_Cu: txt = wxT( "In9.Cu" ); break;
  72. case In10_Cu: txt = wxT( "In10.Cu" ); break;
  73. case In11_Cu: txt = wxT( "In11.Cu" ); break;
  74. case In12_Cu: txt = wxT( "In12.Cu" ); break;
  75. case In13_Cu: txt = wxT( "In13.Cu" ); break;
  76. case In14_Cu: txt = wxT( "In14.Cu" ); break;
  77. case In15_Cu: txt = wxT( "In15.Cu" ); break;
  78. case In16_Cu: txt = wxT( "In16.Cu" ); break;
  79. case In17_Cu: txt = wxT( "In17.Cu" ); break;
  80. case In18_Cu: txt = wxT( "In18.Cu" ); break;
  81. case In19_Cu: txt = wxT( "In19.Cu" ); break;
  82. case In20_Cu: txt = wxT( "In20.Cu" ); break;
  83. case In21_Cu: txt = wxT( "In21.Cu" ); break;
  84. case In22_Cu: txt = wxT( "In22.Cu" ); break;
  85. case In23_Cu: txt = wxT( "In23.Cu" ); break;
  86. case In24_Cu: txt = wxT( "In24.Cu" ); break;
  87. case In25_Cu: txt = wxT( "In25.Cu" ); break;
  88. case In26_Cu: txt = wxT( "In26.Cu" ); break;
  89. case In27_Cu: txt = wxT( "In27.Cu" ); break;
  90. case In28_Cu: txt = wxT( "In28.Cu" ); break;
  91. case In29_Cu: txt = wxT( "In29.Cu" ); break;
  92. case In30_Cu: txt = wxT( "In30.Cu" ); break;
  93. case B_Cu: txt = wxT( "B.Cu" ); break;
  94. // Technicals
  95. case B_Adhes: txt = wxT( "B.Adhes" ); break;
  96. case F_Adhes: txt = wxT( "F.Adhes" ); break;
  97. case B_Paste: txt = wxT( "B.Paste" ); break;
  98. case F_Paste: txt = wxT( "F.Paste" ); break;
  99. case B_SilkS: txt = wxT( "B.SilkS" ); break;
  100. case F_SilkS: txt = wxT( "F.SilkS" ); break;
  101. case B_Mask: txt = wxT( "B.Mask" ); break;
  102. case F_Mask: txt = wxT( "F.Mask" ); break;
  103. // Users
  104. case Dwgs_User: txt = wxT( "Dwgs.User" ); break;
  105. case Cmts_User: txt = wxT( "Cmts.User" ); break;
  106. case Eco1_User: txt = wxT( "Eco1.User" ); break;
  107. case Eco2_User: txt = wxT( "Eco2.User" ); break;
  108. case Edge_Cuts: txt = wxT( "Edge.Cuts" ); break;
  109. case Margin: txt = wxT( "Margin" ); break;
  110. // Footprint
  111. case F_CrtYd: txt = wxT( "F.CrtYd" ); break;
  112. case B_CrtYd: txt = wxT( "B.CrtYd" ); break;
  113. case F_Fab: txt = wxT( "F.Fab" ); break;
  114. case B_Fab: txt = wxT( "B.Fab" ); break;
  115. default:
  116. wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) );
  117. txt = wxT( "BAD INDEX!" ); break;
  118. }
  119. return txt;
  120. }
  121. LSEQ LSET::CuStack() const
  122. {
  123. // desired sequence
  124. static const LAYER_ID sequence[] = {
  125. F_Cu,
  126. In1_Cu,
  127. In2_Cu,
  128. In3_Cu,
  129. In4_Cu,
  130. In5_Cu,
  131. In6_Cu,
  132. In7_Cu,
  133. In8_Cu,
  134. In9_Cu,
  135. In10_Cu,
  136. In11_Cu,
  137. In12_Cu,
  138. In13_Cu,
  139. In14_Cu,
  140. In15_Cu,
  141. In16_Cu,
  142. In17_Cu,
  143. In18_Cu,
  144. In19_Cu,
  145. In20_Cu,
  146. In21_Cu,
  147. In22_Cu,
  148. In23_Cu,
  149. In24_Cu,
  150. In25_Cu,
  151. In26_Cu,
  152. In27_Cu,
  153. In28_Cu,
  154. In29_Cu,
  155. In30_Cu,
  156. B_Cu, // 31
  157. };
  158. return Seq( sequence, DIM( sequence ) );
  159. }
  160. LSEQ LSET::Technicals( LSET aSetToOmit ) const
  161. {
  162. // desired sequence
  163. static const LAYER_ID sequence[] = {
  164. B_Adhes,
  165. F_Adhes,
  166. B_Paste,
  167. F_Paste,
  168. B_SilkS,
  169. F_SilkS,
  170. B_Mask,
  171. F_Mask,
  172. B_CrtYd,
  173. F_CrtYd,
  174. B_Fab,
  175. F_Fab,
  176. };
  177. LSET subset = ~aSetToOmit & *this;
  178. return subset.Seq( sequence, DIM( sequence ) );
  179. }
  180. LSEQ LSET::Users() const
  181. {
  182. // desired
  183. static const LAYER_ID sequence[] = {
  184. Dwgs_User,
  185. Cmts_User,
  186. Eco1_User,
  187. Eco2_User,
  188. Edge_Cuts,
  189. Margin,
  190. };
  191. return Seq( sequence, DIM( sequence ) );
  192. }
  193. std::string LSET::FmtBin() const
  194. {
  195. std::string ret;
  196. int bit_count = size();
  197. for( int bit=0; bit<bit_count; ++bit )
  198. {
  199. if( bit )
  200. {
  201. if( !( bit % 8 ) )
  202. ret += '|';
  203. else if( !( bit % 4 ) )
  204. ret += '_';
  205. }
  206. ret += (*this)[bit] ? '1' : '0';
  207. }
  208. // reverse of string
  209. return std::string( ret.rbegin(), ret.rend() );
  210. }
  211. std::string LSET::FmtHex() const
  212. {
  213. std::string ret;
  214. static const char hex[] = "0123456789abcdef";
  215. int nibble_count = ( size() + 3 ) / 4;
  216. for( int nibble=0; nibble<nibble_count; ++nibble )
  217. {
  218. unsigned ndx = 0;
  219. // test 4 consecutive bits and set ndx to 0-15:
  220. for( int nibble_bit=0; nibble_bit<4; ++nibble_bit )
  221. {
  222. if( (*this)[nibble_bit + nibble*4] )
  223. ndx |= (1 << nibble_bit);
  224. }
  225. if( nibble && !( nibble % 8 ) )
  226. ret += '_';
  227. assert( ndx < DIM( hex ) );
  228. ret += hex[ndx];
  229. }
  230. // reverse of string
  231. return std::string( ret.rbegin(), ret.rend() );
  232. }
  233. int LSET::ParseHex( const char* aStart, int aCount )
  234. {
  235. LSET tmp;
  236. const char* rstart = aStart + aCount - 1;
  237. const char* rend = aStart - 1;
  238. const int bitcount = size();
  239. int nibble_ndx = 0;
  240. while( rstart > rend )
  241. {
  242. int cc = *rstart--;
  243. if( cc == '_' )
  244. continue;
  245. int nibble;
  246. if( cc >= '0' && cc <= '9' )
  247. nibble = cc - '0';
  248. else if( cc >= 'a' && cc <= 'f' )
  249. nibble = cc - 'a' + 10;
  250. else if( cc >= 'A' && cc <= 'F' )
  251. nibble = cc - 'A' + 10;
  252. else
  253. break;
  254. int bit = nibble_ndx * 4;
  255. for( int ndx=0; bit<bitcount && ndx<4; ++bit, ++ndx )
  256. if( nibble & (1<<ndx) )
  257. tmp.set( bit );
  258. if( bit >= bitcount )
  259. break;
  260. ++nibble_ndx;
  261. }
  262. int byte_count = aStart + aCount - 1 - rstart;
  263. assert( byte_count >= 0 );
  264. if( byte_count > 0 )
  265. *this = tmp;
  266. return byte_count;
  267. }
  268. LSEQ LSET::Seq( const LAYER_ID* aWishListSequence, unsigned aCount ) const
  269. {
  270. LSEQ ret;
  271. #if defined(DEBUG) && 0
  272. LSET dup_detector;
  273. for( unsigned i=0; i<aCount; ++i )
  274. {
  275. LAYER_ID id = aWishListSequence[i];
  276. if( test( id ) )
  277. {
  278. wxASSERT_MSG( !dup_detector[id], wxT( "Duplicate in aWishListSequence" ) );
  279. dup_detector[id] = true;
  280. ret.push_back( id );
  281. }
  282. }
  283. #else
  284. for( unsigned i=0; i<aCount; ++i )
  285. {
  286. LAYER_ID id = aWishListSequence[i];
  287. if( test( id ) )
  288. ret.push_back( id );
  289. }
  290. #endif
  291. return ret;
  292. }
  293. LSEQ LSET::Seq() const
  294. {
  295. LSEQ ret;
  296. for( unsigned i=0; i<size(); ++i )
  297. {
  298. if( test(i) )
  299. ret.push_back( LAYER_ID( i ) );
  300. }
  301. return ret;
  302. }
  303. LSEQ LSET::SeqStackupBottom2Top() const
  304. {
  305. // bottom-to-top stack-up layers
  306. static const LAYER_ID sequence[] = {
  307. B_Fab,
  308. B_CrtYd,
  309. B_Adhes,
  310. B_SilkS,
  311. B_Paste,
  312. B_Mask,
  313. B_Cu,
  314. In30_Cu,
  315. In29_Cu,
  316. In28_Cu,
  317. In27_Cu,
  318. In26_Cu,
  319. In25_Cu,
  320. In24_Cu,
  321. In23_Cu,
  322. In22_Cu,
  323. In21_Cu,
  324. In20_Cu,
  325. In19_Cu,
  326. In18_Cu,
  327. In17_Cu,
  328. In16_Cu,
  329. In15_Cu,
  330. In14_Cu,
  331. In13_Cu,
  332. In12_Cu,
  333. In11_Cu,
  334. In10_Cu,
  335. In9_Cu,
  336. In8_Cu,
  337. In7_Cu,
  338. In6_Cu,
  339. In5_Cu,
  340. In4_Cu,
  341. In3_Cu,
  342. In2_Cu,
  343. In1_Cu,
  344. F_Cu,
  345. F_Mask,
  346. F_Paste,
  347. F_SilkS,
  348. F_Adhes,
  349. F_CrtYd,
  350. F_Fab,
  351. Dwgs_User,
  352. Cmts_User,
  353. Eco1_User,
  354. Eco2_User,
  355. Margin,
  356. Edge_Cuts,
  357. };
  358. return Seq( sequence, DIM( sequence ) );
  359. }
  360. LAYER_ID FlipLayer( LAYER_ID aLayerId )
  361. {
  362. switch( aLayerId )
  363. {
  364. case B_Cu: return F_Cu;
  365. case F_Cu: return B_Cu;
  366. case B_SilkS: return F_SilkS;
  367. case F_SilkS: return B_SilkS;
  368. case B_Adhes: return F_Adhes;
  369. case F_Adhes: return B_Adhes;
  370. case B_Mask: return F_Mask;
  371. case F_Mask: return B_Mask;
  372. case B_Paste: return F_Paste;
  373. case F_Paste: return B_Paste;
  374. case B_CrtYd: return F_CrtYd;
  375. case F_CrtYd: return B_CrtYd;
  376. case B_Fab: return F_Fab;
  377. case F_Fab: return B_Fab;
  378. // No change for the other layers
  379. default:
  380. return aLayerId;
  381. }
  382. }
  383. LSET FlipLayerMask( LSET aMask )
  384. {
  385. // layers on physical outside of a board:
  386. const static LSET and_mask( 16, // !! update count
  387. B_Cu, F_Cu,
  388. B_SilkS, F_SilkS,
  389. B_Adhes, F_Adhes,
  390. B_Mask, F_Mask,
  391. B_Paste, F_Paste,
  392. B_Adhes, F_Adhes,
  393. B_CrtYd, F_CrtYd,
  394. B_Fab, F_Fab
  395. );
  396. LSET newMask = aMask & ~and_mask;
  397. if( aMask[B_Cu] )
  398. newMask.set( F_Cu );
  399. if( aMask[F_Cu] )
  400. newMask.set( B_Cu );
  401. if( aMask[B_SilkS] )
  402. newMask.set( F_SilkS );
  403. if( aMask[F_SilkS] )
  404. newMask.set( B_SilkS );
  405. if( aMask[B_Adhes] )
  406. newMask.set( F_Adhes );
  407. if( aMask[F_Adhes] )
  408. newMask.set( B_Adhes );
  409. if( aMask[B_Mask] )
  410. newMask.set( F_Mask );
  411. if( aMask[F_Mask] )
  412. newMask.set( B_Mask );
  413. if( aMask[B_Paste] )
  414. newMask.set( F_Paste );
  415. if( aMask[F_Paste] )
  416. newMask.set( B_Paste );
  417. if( aMask[B_Adhes] )
  418. newMask.set( F_Adhes );
  419. if( aMask[F_Adhes] )
  420. newMask.set( B_Adhes );
  421. if( aMask[B_CrtYd] )
  422. newMask.set( F_CrtYd );
  423. if( aMask[F_CrtYd] )
  424. newMask.set( B_CrtYd );
  425. if( aMask[B_Fab] )
  426. newMask.set( F_Fab );
  427. if( aMask[F_Fab] )
  428. newMask.set( B_Fab );
  429. return newMask;
  430. }
  431. LAYER_ID LSET::ExtractLayer() const
  432. {
  433. unsigned set_count = count();
  434. if( !set_count )
  435. return UNSELECTED_LAYER;
  436. else if( set_count > 1 )
  437. return UNDEFINED_LAYER;
  438. for( unsigned i=0; i < size(); ++i )
  439. {
  440. if( test( i ) )
  441. return LAYER_ID( i );
  442. }
  443. wxASSERT( 0 ); // set_count was verified as 1 above, what did you break?
  444. return UNDEFINED_LAYER;
  445. }
  446. LSET LSET::InternalCuMask()
  447. {
  448. static const LAYER_ID cu_internals[] = {
  449. In1_Cu,
  450. In2_Cu,
  451. In3_Cu,
  452. In4_Cu,
  453. In5_Cu,
  454. In6_Cu,
  455. In7_Cu,
  456. In8_Cu,
  457. In9_Cu,
  458. In10_Cu,
  459. In11_Cu,
  460. In12_Cu,
  461. In13_Cu,
  462. In14_Cu,
  463. In15_Cu,
  464. In16_Cu,
  465. In17_Cu,
  466. In18_Cu,
  467. In19_Cu,
  468. In20_Cu,
  469. In21_Cu,
  470. In22_Cu,
  471. In23_Cu,
  472. In24_Cu,
  473. In25_Cu,
  474. In26_Cu,
  475. In27_Cu,
  476. In28_Cu,
  477. In29_Cu,
  478. In30_Cu,
  479. };
  480. static const LSET saved( cu_internals, DIM( cu_internals ) );
  481. return saved;
  482. }
  483. LSET LSET::AllCuMask( int aCuLayerCount )
  484. {
  485. // retain all in static as the full set, which is a common case.
  486. static const LSET all = InternalCuMask().set( F_Cu ).set( B_Cu );
  487. if( aCuLayerCount == MAX_CU_LAYERS )
  488. return all;
  489. // subtract out some Cu layers not wanted in the mask.
  490. LSET ret = all;
  491. int clear_count = MAX_CU_LAYERS - aCuLayerCount;
  492. clear_count = Clamp( 0, clear_count, MAX_CU_LAYERS - 2 );
  493. for( LAYER_NUM elem=In30_Cu; clear_count; --elem, --clear_count )
  494. {
  495. ret.set( elem, false );
  496. }
  497. return ret;
  498. }
  499. LSET LSET::AllNonCuMask()
  500. {
  501. static const LSET saved = LSET().set() & ~AllCuMask();
  502. return saved;
  503. }
  504. LSET LSET::AllLayersMask()
  505. {
  506. static const LSET saved = LSET().set();
  507. return saved;
  508. }
  509. LSET LSET::BackTechMask()
  510. {
  511. // (SILKSCREEN_LAYER_BACK | SOLDERMASK_LAYER_BACK | ADHESIVE_LAYER_BACK | SOLDERPASTE_LAYER_BACK)
  512. static const LSET saved( 6, B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab );
  513. return saved;
  514. }
  515. LSET LSET::FrontTechMask()
  516. {
  517. // (SILKSCREEN_LAYER_FRONT | SOLDERMASK_LAYER_FRONT | ADHESIVE_LAYER_FRONT | SOLDERPASTE_LAYER_FRONT)
  518. static const LSET saved( 6, F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab );
  519. return saved;
  520. }
  521. LSET LSET::AllTechMask()
  522. {
  523. static const LSET saved = BackTechMask() | FrontTechMask();
  524. return saved;
  525. }
  526. LSET LSET::UserMask()
  527. {
  528. static const LSET saved( 6,
  529. Dwgs_User,
  530. Cmts_User,
  531. Eco1_User,
  532. Eco2_User,
  533. Edge_Cuts,
  534. Margin
  535. );
  536. return saved;
  537. }
  538. LSET LSET::FrontMask()
  539. {
  540. static const LSET saved = FrontTechMask().set( F_Cu );
  541. return saved;
  542. }
  543. LSET LSET::BackMask()
  544. {
  545. static const LSET saved = BackTechMask().set( B_Cu );
  546. return saved;
  547. }
  548. LSEQ LSET::UIOrder() const
  549. {
  550. LAYER_ID order[LAYER_ID_COUNT];
  551. // Assmuming that the LAYER_ID order is according to preferred UI order, as of
  552. // today this is true. When that becomes not true, its easy to change the order
  553. // in here to compensate.
  554. for( unsigned i=0; i<DIM(order); ++i )
  555. order[i] = LAYER_ID( i );
  556. return Seq( order, DIM( order ) );
  557. }
  558. LAYER_ID ToLAYER_ID( int aLayer )
  559. {
  560. wxASSERT( unsigned( aLayer ) < LAYER_ID_COUNT );
  561. return LAYER_ID( aLayer );
  562. }