public override void Send(Candle.Frame frame, bool blocking = false) { var nativeFrame = new NativeFunctions.CAN_OBJ(); nativeFrame.ID = frame.Identifier; if (frame.Extended) { nativeFrame.ExternFlag = 1; } else { nativeFrame.ExternFlag = 0; } if (frame.RTR) { nativeFrame.RemoteFlag = 1; } else { nativeFrame.RemoteFlag = 0; } nativeFrame.data = new byte[8]; nativeFrame.DataLen = (byte)frame.Data.Length; Buffer.BlockCopy(frame.Data, 0, nativeFrame.data, 0, frame.Data.Length); // Note : this shoud actually increment after we've actully sent (e.g. on thread). But since it's a heuristic this is kind of fine for now var lengthOnBus = frame.LengthOnBus; this.IncrementTx(lengthOnBus); if (blocking) { // Send this one frame this.FDevice.PerformInRightThread(() => { NativeFunctions.Transmit( this.FDevice.DeviceType , this.FDevice.DeviceIndex , this.FChannelIndex , new NativeFunctions.CAN_OBJ[] { nativeFrame } , 1); this.ThreadedUpdate(); }, true); } else { this.FTxQueue.Add(nativeFrame); } }
public void ThreadedUpdate() { // Send frames { var framesToSend = new List <NativeFunctions.CAN_OBJ>(); // Pull them from the queue { NativeFunctions.CAN_OBJ frame; while (this.FTxQueue.TryTake(out frame)) { framesToSend.Add(frame); } } // Send them out if (framesToSend.Count > 0) { var framesSent = NativeFunctions.Transmit( this.FDevice.DeviceType , this.FDevice.DeviceIndex , this.FChannelIndex , framesToSend.ToArray() , (UInt16)framesToSend.Count); // Queue again anything that didn't send for (int i = (int)framesSent; i < framesToSend.Count; i++) { this.FTxQueue.Add(framesToSend[i]); } } // Alternative method : force send everything //int txOffset = 0; //while(txOffset != framesToSend.Count) //{ // var framesSent = NativeFunctions.Transmit( // this.FDevice.DeviceType // , this.FDevice.DeviceIndex // , this.FChannelIndex // , framesToSend.GetRange(txOffset, framesToSend.Count - txOffset).ToArray() // , (UInt16)framesToSend.Count); // txOffset += (int) framesSent; //} } // Receive frames { var rxCountOnDevice = NativeFunctions.GetReceiveNum(this.FDevice.DeviceType , this.FDevice.DeviceIndex , this.FChannelIndex); if (rxCountOnDevice > 0) { var rxBuffer = new NativeFunctions.CAN_OBJ[rxCountOnDevice]; var rxCount = NativeFunctions.ReceiveArray(this.FDevice.DeviceType , this.FDevice.DeviceIndex , this.FChannelIndex , rxBuffer , (UInt32)rxBuffer.Length , 0); for (int i = 0; i < rxCount; i++) { var nativeFrame = rxBuffer[i]; var frame = new Candle.Frame(); { frame.Identifier = nativeFrame.ID; frame.Extended = nativeFrame.ExternFlag == 1; frame.RTR = nativeFrame.RemoteFlag == 1; frame.Error = false; // Not sure how we get error frames with GCAN frame.Data = new byte[nativeFrame.DataLen]; Buffer.BlockCopy(nativeFrame.data, 0, frame.Data, 0, nativeFrame.DataLen); frame.Timestamp = nativeFrame.TimeStamp; } this.IncrementRx(frame.LengthOnBus); this.FRxQueue.Add(frame); } } } }