From 29bc318accc5753c940c7752987c6a5c4a3d83fa Mon Sep 17 00:00:00 2001 From: JamesJCode <13408010-JamesJCode@users.noreply.gitlab.com> Date: Mon, 27 Oct 2025 20:57:09 +0000 Subject: [PATCH] Correctly format pad-to-die delays in sexpr format --- common/eda_units.cpp | 17 +++++++++++++++-- include/eda_units.h | 13 +++++++++++-- .../pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp | 6 +++--- pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h | 3 ++- .../kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp | 14 +++++++++++--- .../kicad_sexpr/pcb_io_kicad_sexpr_parser.h | 7 ++++--- 6 files changed, 46 insertions(+), 14 deletions(-) diff --git a/common/eda_units.cpp b/common/eda_units.cpp index bcc94bb74b..d147066152 100644 --- a/common/eda_units.cpp +++ b/common/eda_units.cpp @@ -191,12 +191,13 @@ std::string EDA_UNIT_UTILS::FormatAngle( const EDA_ANGLE& aAngle ) } -std::string EDA_UNIT_UTILS::FormatInternalUnits( const EDA_IU_SCALE& aIuScale, int aValue ) +std::string EDA_UNIT_UTILS::FormatInternalUnits( const EDA_IU_SCALE& aIuScale, const int aValue, + const EDA_DATA_TYPE aDataType ) { std::string buf; double engUnits = aValue; - engUnits /= aIuScale.IU_PER_MM; + engUnits /= GetScaleForInternalUnitType( aIuScale, aDataType ); if( engUnits != 0.0 && fabs( engUnits ) <= 0.0001 ) { @@ -232,6 +233,18 @@ std::string EDA_UNIT_UTILS::FormatInternalUnits( const EDA_IU_SCALE& aIuScale, } +double EDA_UNIT_UTILS::GetScaleForInternalUnitType( const EDA_IU_SCALE& aIuScale, const EDA_DATA_TYPE aDataType ) +{ + switch( aDataType ) + { + case EDA_DATA_TYPE::TIME: return aIuScale.IU_PER_PS; + case EDA_DATA_TYPE::LENGTH_DELAY: return aIuScale.IU_PER_PS_PER_MM; + case EDA_DATA_TYPE::UNITLESS: return 1.0; + default: return aIuScale.IU_PER_MM; + } +} + + #if 0 // No support for std::from_chars on MacOS yet bool EDA_UNIT_UTILS::ParseInternalUnits( const std::string& aInput, const EDA_IU_SCALE& aIuScale, diff --git a/include/eda_units.h b/include/eda_units.h index 5820b2f7d8..59440e83ef 100644 --- a/include/eda_units.h +++ b/include/eda_units.h @@ -129,13 +129,22 @@ namespace EDA_UNIT_UTILS * on how KiCad is built. * * @param aValue A coordinate value to convert. + * @param aDataType The EDA_UNITS data type for @param aValue * @return A std::string object containing the converted value. */ - KICOMMON_API std::string FormatInternalUnits( const EDA_IU_SCALE& aIuScale, int aValue ); + KICOMMON_API std::string FormatInternalUnits( const EDA_IU_SCALE& aIuScale, int aValue, + EDA_DATA_TYPE aDataType = EDA_DATA_TYPE::DISTANCE ); KICOMMON_API std::string FormatInternalUnits( const EDA_IU_SCALE& aIuScale, const VECTOR2I& aPoint ); -#if 0 // No support for std::from_chars on MacOS yet + /** + * Returns the scaling parameter for the given units data type + * + * This should only be used when scaling for writing to files as it assumes metric distances are being used + */ + KICOMMON_API double GetScaleForInternalUnitType( const EDA_IU_SCALE& aIuScale, EDA_DATA_TYPE aDataType ); + +#if 0 // No support for std::from_chars on MacOS yet /** * Convert \a aInput string to internal units when reading from a file. * diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp index f6f00f4633..d1a58c6e31 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp @@ -435,9 +435,9 @@ void PCB_IO_KICAD_SEXPR::Format( const BOARD_ITEM* aItem ) const } -std::string formatInternalUnits( int aValue ) +std::string formatInternalUnits( const int aValue, const EDA_DATA_TYPE aDataType = EDA_DATA_TYPE::DISTANCE ) { - return EDA_UNIT_UTILS::FormatInternalUnits( pcbIUScale, aValue ); + return EDA_UNIT_UTILS::FormatInternalUnits( pcbIUScale, aValue, aDataType ); } @@ -1756,7 +1756,7 @@ void PCB_IO_KICAD_SEXPR::format( const PAD* aPad ) const if( aPad->GetPadToDieDelay() != 0 ) { - m_out->Print( "(die_delay %s)", formatInternalUnits( aPad->GetPadToDieDelay() ).c_str() ); + m_out->Print( "(die_delay %s)", formatInternalUnits( aPad->GetPadToDieDelay(), EDA_DATA_TYPE::TIME ).c_str() ); } if( aPad->GetLocalSolderMaskMargin().has_value() ) diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h index b521a847a1..cfdf24f924 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h @@ -195,7 +195,8 @@ class PCB_IO_KICAD_SEXPR; // forward decl //#define SEXPR_BOARD_FILE_VERSION 20250907 // uuids for tables //#define SEXPR_BOARD_FILE_VERSION 20250909 // footprint unit metadata (units/pins) //#define SEXPR_BOARD_FILE_VERSION 20250914 // Add support for PCB_BARCODE objects -#define SEXPR_BOARD_FILE_VERSION 20250926 // Split via types into blind/buried/through +//#define SEXPR_BOARD_FILE_VERSION 20250926 // Split via types into blind/buried/through +#define SEXPR_BOARD_FILE_VERSION 20251027 // Store pad-to-die delays with correct scaling #define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag #define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp index 080bd1524a..77c70c1896 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp @@ -211,9 +211,11 @@ int PCB_IO_KICAD_SEXPR_PARSER::parseBoardUnits() } -int PCB_IO_KICAD_SEXPR_PARSER::parseBoardUnits( const char* aExpected ) +int PCB_IO_KICAD_SEXPR_PARSER::parseBoardUnits( const char* aExpected, + const EDA_DATA_TYPE aDataType = EDA_DATA_TYPE::DISTANCE ) { - auto retval = parseDouble( aExpected ) * pcbIUScale.IU_PER_MM; + const double scale = EDA_UNIT_UTILS::GetScaleForInternalUnitType( pcbIUScale, aDataType ); + auto retval = parseDouble( aExpected ) * scale; // N.B. we currently represent board units as integers. Any values that are // larger or smaller than those board units represent undefined behavior for @@ -5671,9 +5673,15 @@ PAD* PCB_IO_KICAD_SEXPR_PARSER::parsePAD( FOOTPRINT* aParent ) break; case T_die_delay: - pad->SetPadToDieDelay( parseBoardUnits( T_die_delay ) ); + { + if( m_requiredVersion <= 20250926 ) + pad->SetPadToDieDelay( parseBoardUnits( T_die_delay ) ); + else + pad->SetPadToDieDelay( parseBoardUnits( T_die_delay, EDA_DATA_TYPE::TIME ) ); + NeedRIGHT(); break; + } case T_solder_mask_margin: pad->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) ); diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h index 835d483a8a..dbe689d667 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h @@ -30,6 +30,7 @@ #ifndef _PCBNEW_PARSER_H_ #define _PCBNEW_PARSER_H_ +#include #include #include #include @@ -353,11 +354,11 @@ private: int parseBoardUnits(); - int parseBoardUnits( const char* aExpected ); + int parseBoardUnits( const char* aExpected, EDA_DATA_TYPE aDataType ); - inline int parseBoardUnits( PCB_KEYS_T::T aToken ) + inline int parseBoardUnits( const PCB_KEYS_T::T aToken, const EDA_DATA_TYPE aDataType = EDA_DATA_TYPE::DISTANCE ) { - return parseBoardUnits( GetTokenText( aToken ) ); + return parseBoardUnits( GetTokenText( aToken ), aDataType ); } inline int parseInt()