FPGAArrayFXPWriteProperty.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using FxpConvert.Common;
  2. using NIFPGA.lvbitx;
  3. using System.Buffers.Binary;
  4. using System.Reflection;
  5. using System.Runtime.CompilerServices;
  6. namespace NIFPGA
  7. {
  8. public sealed class FPGAArrayFXPWriteProperty : FPGABaseProperty
  9. {
  10. Interop.NiFpgaDll_ReadArrayU8 Read;
  11. Interop.NiFpgaDll_WriteArrayU8 Write;
  12. private object _Locker = new object();
  13. private NiFpga_FxpTypeInfo _TypeInfo;
  14. private IFxpConvert _Convert;
  15. private uint bytescount = 0;
  16. private ulong[] tempbuffer = new ulong[0];
  17. private double[] doubles = new double[0];
  18. private ulong[] tempvalue = new ulong[0];
  19. internal FPGAArrayFXPWriteProperty(FPGASession session, Register indicator, IFxpConvert convert) : base(session, indicator)
  20. {
  21. _Convert = convert;
  22. Count = indicator.Size;
  23. doubles = new double[Count];
  24. tempvalue = new ulong[Count];
  25. _TypeInfo = indicator.FxpTypeInfo;
  26. tempbuffer = new ulong[(int)Math.Ceiling(_TypeInfo.wordLength * Count / 64.0)];
  27. bytescount = (uint)Math.Ceiling(_TypeInfo.wordLength * Count / 8.0);
  28. Read = _Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU8>();
  29. Write = _Session.GetDelegate<Interop.NiFpgaDll_WriteArrayU8>();
  30. }
  31. private double[] GetData()
  32. {
  33. lock (_Locker)
  34. {
  35. _Session.CheckResult(Read(_Session.Session, Register, ref Unsafe.As <ulong,byte>(ref tempbuffer[0]), bytescount));
  36. for(int i = 0; i < tempbuffer.Length;i++)
  37. {
  38. tempbuffer[i] = BinaryPrimitives.ReverseEndianness(tempbuffer[i]);
  39. }
  40. int tempdatalen = Unsafe.SizeOf<ulong>() * 8;
  41. ulong mask = (1ul << _TypeInfo.wordLength) - 1;
  42. for (int i = 0; i < Count; i++)
  43. {
  44. int index = i * _TypeInfo.wordLength / tempdatalen;
  45. int bitindex =tempdatalen - (i * _TypeInfo.wordLength % tempdatalen);
  46. if (bitindex >= _TypeInfo.wordLength)
  47. {
  48. tempvalue[i] = (tempbuffer[index] >> (bitindex-_TypeInfo.wordLength)) & mask;
  49. }
  50. else
  51. {
  52. tempvalue[i] = (((tempbuffer[index] & ((1ul << bitindex) - 1)) << (_TypeInfo.wordLength - bitindex)) | (tempbuffer[index + 1] >> (tempdatalen - (_TypeInfo.wordLength - bitindex))));
  53. }
  54. }
  55. _Convert.FxpConvertToDouble(ref tempvalue[0], _TypeInfo, ref doubles[0], Count);
  56. return doubles;
  57. }
  58. }
  59. private void SetData(double[] values)
  60. {
  61. lock (_Locker)
  62. {
  63. if (values.Length != Count || Count == 0) return;
  64. _Convert.DoubleConvertToDxp(ref values[0], _TypeInfo, ref tempvalue[0], Count);
  65. int tempdatalen = Unsafe.SizeOf<ulong>() * 8;
  66. tempbuffer = new ulong[tempbuffer.Length];
  67. for (int i = 0; i < Count; i++)
  68. {
  69. int index = i * _TypeInfo.wordLength / tempdatalen;
  70. int bitindex = tempdatalen - (i * _TypeInfo.wordLength % tempdatalen);
  71. var b = (tempvalue[i] & ((1ul << _TypeInfo.wordLength) - 1));
  72. if (bitindex >= _TypeInfo.wordLength)
  73. {
  74. tempbuffer[index] |= (b << (bitindex - _TypeInfo.wordLength));
  75. }
  76. else
  77. {
  78. tempbuffer[index] |= (b >> (_TypeInfo.wordLength - bitindex));
  79. tempbuffer[index + 1] |= ((b & ((1ul << (_TypeInfo.wordLength - bitindex)) - 1)) << (tempdatalen - (_TypeInfo.wordLength - bitindex)));
  80. }
  81. }
  82. ulong[] oldvalues = new ulong[tempbuffer.Length];
  83. _Session.CheckResult(Read(_Session.Session, Register, ref Unsafe.As<ulong, byte>(ref oldvalues[0]), bytescount));
  84. for (int i = 0; i < tempbuffer.Length; i++)
  85. {
  86. tempbuffer[i] = BinaryPrimitives.ReverseEndianness(tempbuffer[i]);
  87. }
  88. bool changed = Enumerable.Range(0, oldvalues.Length).Any(x => oldvalues[x] != tempbuffer[x]);
  89. if (!changed) return;
  90. _Session.CheckResult(Write(_Session.Session, Register, ref Unsafe.As<ulong, byte>(ref tempbuffer[0]), bytescount));
  91. }
  92. }
  93. public override bool IsArray => true;
  94. public uint Count { get; }
  95. public double[] Value { get => GetData(); set => SetData(value); }
  96. }
  97. }