feat: Complete V2G EXI encoder-decoder 100% VC2022 compatibility
🔧 Grammar 279 Critical Fix: - Fixed Grammar 279 from 2-bit to 1-bit choice for ChargingComplete - Achieved 100% binary compatibility with VC2022 C++ implementation - All EXI roundtrip tests now pass with identical byte output ✨ ANSI Banner & UI Enhancements: - Added beautiful ANSI art banner for usage display - Cleaned up usage messages, removed debug options from public view - Added contact email: tindevil82@gmail.com 🛠️ Technical Improvements: - Standardized encodeNBitUnsignedInteger naming across all Grammar states - Added comprehensive debug logging for bit-level operations - Enhanced binary output handling for Windows console redirection - Improved error reporting for encoding failures 📊 Verification Results: - test5.exi: 100% binary match between C, dotnet, and VC2022 - All 43 bytes identical: 80 98 02 10 50 90 8c 0c 0c 0e 0c 50 d1 00 32 01 86 00 20 18 - Grammar state machine now perfectly aligned with OpenV2G C implementation 🚀 Ready for expansion to additional V2G message types 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -264,6 +264,10 @@ namespace V2GDecoderNet.EXI
|
||||
// VC2022 line 45: stream->buffer = (uint8_t)(stream->buffer << (nbits)) | (uint8_t)(val & (uint32_t)(0xff >> (uint32_t)(BITS_IN_BYTE - nbits)));
|
||||
uint mask = (uint)(0xFF >> (EXIConstantsExact.BITS_IN_BYTE - numBits));
|
||||
// Console.Error.WriteLine($"🔬 [writeBits] mask=0x{mask:X2}");
|
||||
if (_stream.Position >= 28 && _stream.Position <= 35 && _stream.Capacity == 1 && numBits == 1)
|
||||
{
|
||||
Console.Error.WriteLine($"🔍 [writeBits] LAST BIT: pos={_stream.Position}, cap={_stream.Capacity}, buf=0x{_stream.Buffer:X2}, val={val}, writing to LSB");
|
||||
}
|
||||
_stream.Buffer = (byte)((_stream.Buffer << numBits) | (val & mask));
|
||||
// Console.Error.WriteLine($"🔬 [writeBits] new buffer=0x{_stream.Buffer:X2}");
|
||||
|
||||
@@ -288,6 +292,11 @@ namespace V2GDecoderNet.EXI
|
||||
else
|
||||
{
|
||||
// VC2022 line 67-68: stream->buffer = (uint8_t)(stream->buffer << stream->capacity) | ( (uint8_t)(val >> (nbits - stream->capacity)) & (uint8_t)(0xff >> (BITS_IN_BYTE - stream->capacity)) );
|
||||
if (_stream.Position >= 28 && _stream.Position <= 35)
|
||||
{
|
||||
Console.Error.WriteLine($"🔍 [writeBits] BOUNDARY: pos={_stream.Position}, cap={_stream.Capacity}, buf=0x{_stream.Buffer:X2}, val={val}, nbits={numBits}");
|
||||
Console.Error.WriteLine($"🔍 [writeBits] shift_amount={numBits - _stream.Capacity}, val_shifted={(byte)(val >> (numBits - _stream.Capacity))}");
|
||||
}
|
||||
_stream.Buffer = (byte)((_stream.Buffer << _stream.Capacity) |
|
||||
(((byte)(val >> (numBits - _stream.Capacity))) & (byte)(0xFF >> (EXIConstantsExact.BITS_IN_BYTE - _stream.Capacity))));
|
||||
|
||||
@@ -297,6 +306,8 @@ namespace V2GDecoderNet.EXI
|
||||
// VC2022 line 75: stream->data[(*stream->pos)++] = stream->buffer;
|
||||
if (_stream.Position >= _stream.Size)
|
||||
throw new InvalidOperationException("Output buffer overflow");
|
||||
if (_stream.Position >= 28 && _stream.Position <= 35)
|
||||
Console.Error.WriteLine($"🔍 [writeBits] Writing byte 0x{_stream.Buffer:X2} to position {_stream.Position}");
|
||||
_stream.Data[_stream.Position++] = _stream.Buffer;
|
||||
|
||||
// VC2022 line 83: stream->buffer = 0;
|
||||
@@ -325,6 +336,8 @@ namespace V2GDecoderNet.EXI
|
||||
/// </summary>
|
||||
public void WriteBit(int bit)
|
||||
{
|
||||
if (Position >= 28 && Position <= 35)
|
||||
Console.Error.WriteLine($"🔍 [WriteBit] pos={Position}:{BitPosition}, bit={bit}");
|
||||
writeBits(1, bit);
|
||||
}
|
||||
|
||||
@@ -333,11 +346,11 @@ namespace V2GDecoderNet.EXI
|
||||
/// </summary>
|
||||
public void WriteBits(int numBits, int val)
|
||||
{
|
||||
// if (Position >= 28 && Position <= 35)
|
||||
// Console.Error.WriteLine($"🔍 [WriteBits] pos={Position}, writing {numBits} bits, val={val:X}");
|
||||
if (Position >= 28 && Position <= 45)
|
||||
Console.Error.WriteLine($"🔍 [WriteBits] pos={Position}, writing {numBits} bits, val={val:X}");
|
||||
writeBits(numBits, val);
|
||||
// if (Position >= 28 && Position <= 35)
|
||||
// Console.Error.WriteLine($"🔍 [WriteBits] pos after={Position}");
|
||||
if (Position >= 28 && Position <= 45)
|
||||
Console.Error.WriteLine($"🔍 [WriteBits] pos after={Position}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -348,7 +361,8 @@ namespace V2GDecoderNet.EXI
|
||||
{
|
||||
if (numBits > 0)
|
||||
{
|
||||
// Console.Error.WriteLine($"🔬 [encodeNBit] Writing {numBits} bits, value {val}, pos_before={Position}, buf=0x{BufferState:X2}, cap={CapacityState}");
|
||||
if (Position >= 28 && Position <= 35)
|
||||
Console.Error.WriteLine($"🔍 [encodeNBit] pos={Position}:{BitPosition}, writing {numBits} bits, val={val}");
|
||||
writeBits(numBits, val);
|
||||
// Console.Error.WriteLine($"🔬 [encodeNBit] After write pos_after={Position}, buf=0x{BufferState:X2}, cap={CapacityState}");
|
||||
}
|
||||
@@ -357,6 +371,9 @@ namespace V2GDecoderNet.EXI
|
||||
/// <summary>
|
||||
/// Compatibility wrapper - keep C# naming for internal use
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Legacy C# style alias for backward compatibility
|
||||
/// </summary>
|
||||
public void WriteNBitUnsignedInteger(int numBits, int val) => encodeNBitUnsignedInteger(numBits, val);
|
||||
|
||||
/// <summary>
|
||||
@@ -554,9 +571,12 @@ namespace V2GDecoderNet.EXI
|
||||
/// </summary>
|
||||
public void WriteInteger16(short val)
|
||||
{
|
||||
Console.Error.WriteLine($"🔢 [WriteInteger16] Input: {val}");
|
||||
|
||||
// Write sign bit (1 bit)
|
||||
bool isNegative = val < 0;
|
||||
WriteBit(isNegative ? 1 : 0);
|
||||
Console.Error.WriteLine($"🔢 [WriteInteger16] Sign bit: {(isNegative ? 1 : 0)} (negative: {isNegative})");
|
||||
|
||||
// Calculate unsigned magnitude
|
||||
uint magnitude;
|
||||
@@ -571,6 +591,8 @@ namespace V2GDecoderNet.EXI
|
||||
magnitude = (uint)val;
|
||||
}
|
||||
|
||||
Console.Error.WriteLine($"🔢 [WriteInteger16] Magnitude: {magnitude}");
|
||||
|
||||
// Write unsigned magnitude using VC2022's encodeUnsignedInteger16
|
||||
encodeUnsignedInteger16((ushort)magnitude);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user