FPGAArrayFXPWriteProperty.cs 4.7 KB

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