1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using System.Linq; 10 using Antmicro.Renode.Utilities; 11 using Antmicro.Renode.Utilities.Packets; 12 13 namespace Antmicro.Renode.Peripherals.SENT 14 { 15 public class FastMessage 16 { CalculateCRC(IEnumerable<byte> nibbles)17 public static byte CalculateCRC(IEnumerable<byte> nibbles) 18 { 19 // CRCEngine is not used here as it assumes working on bytes instead of nibbles 20 byte value = 5; 21 foreach(var nibble in nibbles) 22 { 23 value = CRCTable[(value << 4) + nibble]; 24 } 25 return CRCTable[value << 4]; 26 } 27 FastMessage(params byte[] nibbles)28 public FastMessage(params byte[] nibbles) 29 { 30 if(nibbles.Length < 1 || nibbles.Length > MaxFastMessageLength) 31 { 32 throw new ArgumentException($"{nameof(nibbles)} Length ({nibbles.Length}) is out of range of [1;{MaxFastMessageLength}]"); 33 } 34 35 Nibbles = new byte[nibbles.Length + 1]; 36 Array.Copy(nibbles, Nibbles, nibbles.Length); 37 Nibbles[Nibbles.Length - 1] = CalculateCRC(nibbles); 38 } 39 40 private static readonly byte[] CRCTable = new byte[256] 41 { 42 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 43 0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 44 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 45 0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 46 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 47 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 48 0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 49 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 50 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE, 51 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 52 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 53 0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 54 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 55 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD, 56 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 57 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 58 }; 59 60 public byte[] Nibbles { get; } 61 62 private const int MaxFastMessageLength = 6; 63 } 64 65 public class SlowMessage : FastMessage 66 { SlowMessage(params byte[] nibbles)67 public SlowMessage(params byte[] nibbles) : base(nibbles) 68 { 69 if(nibbles.Length != ShortMessageNibbles) 70 { 71 throw new ArgumentException($"Invalid nibble count. {ShortMessageNibbles} expected, got {nibbles.Length}"); 72 } 73 } 74 75 public IEnumerable<bool> Bits 76 { 77 get 78 { 79 foreach(var nibble in Nibbles) 80 { 81 for(byte i = 0; i < 4; i++) 82 { 83 // Data from the slow messages is transmitted MSB first 84 yield return BitHelper.IsBitSet(nibble, (byte)(3 - i)); 85 } 86 } 87 } 88 } 89 90 private const int ShortMessageNibbles = 3; 91 } 92 } 93