/// <summary> /// Processes the change of the EAR bit value /// </summary> /// <param name="fromTape"> /// False: EAR bit comes from an OUT instruction, /// True: EAR bit comes from tape /// </param> /// <param name="earBit">EAR bit value</param> public void ProcessEarBitValue(bool fromTape, bool earBit) { if (!fromTape && _useTapeMode) { // --- The EAR bit comes from and OUT instruction, but now we're in tape mode return; } if (earBit == LastEarBit) { // --- The earbit has not changed return; } LastEarBit = earBit; var currentHostTact = HostVm.CurrentFrameTact; var currentTact = currentHostTact <= _frameTacts ? currentHostTact : _frameTacts; var length = currentTact - LastPulseTact; // --- If the first tact changes the pulse, we do // --- not add it if (length > 0) { Pulses.Add(new EarBitPulse { EarBit = !earBit, Lenght = length }); } LastPulseTact = currentTact; }
/// <summary> /// Resets this device /// </summary> public void Reset() { Pulses.Clear(); LastPulseTact = 0; LastEarBit = true; FrameCount = 0; _frameBegins = 0; _useTapeMode = false; _beeperProvider?.Reset(); }
/// <summary> /// Frame is completed /// </summary> public void EndFrame() { // store the last pulse information if (LastPulseTState <= _tStatesPerFrame - 1) { Pulse p = new Pulse { State = LastPulse, Length = _tStatesPerFrame - LastPulseTState }; Pulses.Add(p); } // create the sample array var firstSampleOffset = _frameStart % TStatesPerSample == 0 ? 0 : TStatesPerSample - (_frameStart + TStatesPerSample) % TStatesPerSample; var samplesInFrame = (_tStatesPerFrame - firstSampleOffset - 1) / TStatesPerSample + 1; var samples = new short[samplesInFrame]; // convert pulses to samples var sampleIndex = 0; var currentEnd = _frameStart; foreach (var pulse in Pulses) { var firstSample = currentEnd % TStatesPerSample == 0 ? currentEnd : currentEnd + TStatesPerSample - currentEnd % TStatesPerSample; for (var i = firstSample; i < currentEnd + pulse.Length; i += TStatesPerSample) { samples[sampleIndex++] = pulse.State ? (short)(_volume) : (short)0; } currentEnd += pulse.Length; } // fill the _sampleBuffer for ISoundProvider soundBufferContains = (int)samplesInFrame; if (soundBuffer.Length != soundBufferContains) { soundBuffer = new short[soundBufferContains]; } samples.CopyTo(soundBuffer, 0); _frameStart += _tStatesPerFrame; }
public MainPage() { this.InitializeComponent(); // Initilize data errorCounterTransfer = 0; mcpExecutorCounter = 0; firstStart = true; stopSequenceIsActive = false; globalDataSet = new GlobalDataSet(); // Get things like mcp2515, logic_Mcp2515_Sender, logic_Mcp2515_Receiver //serverComm = new ServerUnit(globalDataSet); clientUnit = new ClientUnit(globalDataSet); diagnose = new Diagnose(globalDataSet); mcp2515 = globalDataSet.Mcp2515; pulses = new Pulses(); clientUnit.newEvent += new ClientUnit.myEvent(this.dataPackageReceived); // USER CONFIGURATION globalDataSet.DebugMode = false; getProgramDuration = false; // Inititalize raspberry pi and gpio init_raspberry_pi_gpio(); init_raspberry_pi_spi(); // Inititalize mcp2515 Task task_initMcp2515 = new Task(globalDataSet.init_mcp2515_task); task_initMcp2515.Start(); task_initMcp2515.Wait(); // Start executor service task_mcpExecutorService = new Task(mcpExecutorService_task); task_mcpExecutorService.Start(); // Inititalize background tasks stateTimer = new Timer(this.StateTimer, null, 0, DELTA_T_TIMER_CALLBACK); // Create timer to display the state of message transmission errorTimer = new Timer(this.ErrorTimer, null, 0, DELTA_T_ERROR_TIMER); // Create timer to display the state of message transmission // Inititalize server //Task<bool> serverStarted = serverComm.StartServer(); clientUnit.StartClient_loop(); }
/// <summary> /// When the pulse value changes it is processed here /// </summary> /// <param name="pulse"></param> public void ProcessPulseValue(bool pulse) { if (!_machine._renderSound) { return; } if (pulse == LastPulse) { // no change detected return; } // set the lastpulse LastPulse = pulse; // get where we are in the frame var currentULACycle = _machine.CurrentFrameCycle; var currentBuzzerCycle = currentULACycle <= _tStatesPerFrame ? currentULACycle : _tStatesPerFrame; var length = currentBuzzerCycle - LastPulseTState; if (length == 0) { // the first T-State has changed the pulse // do not add it } else if (length > 0) { // add the pulse Pulse p = new Pulse { State = !pulse, Length = length }; Pulses.Add(p); } // set the last pulse tstate LastPulseTState = currentBuzzerCycle; }
/// <summary> /// Allow the device to react to the completion of a frame /// </summary> public void OnFrameCompleted() { if (LastPulseTact <= _frameTacts - 1) { // --- We have to store the last pulse information Pulses.Add(new EarBitPulse { EarBit = LastEarBit, Lenght = _frameTacts - LastPulseTact }); } // --- Create the array for the samples var firstSampleOffset = _frameBegins % _tactsPerSample == 0 ? 0 : _tactsPerSample - (_frameBegins + _tactsPerSample) % _tactsPerSample; var samplesInFrame = (_frameTacts - firstSampleOffset - 1) / _tactsPerSample + 1; var samples = new float[samplesInFrame]; // --- Convert pulses to samples var sampleIndex = 0; var currentEnd = _frameBegins; foreach (var pulse in Pulses) { var firstSample = currentEnd % _tactsPerSample == 0 ? currentEnd : currentEnd + _tactsPerSample - currentEnd % _tactsPerSample; for (var i = firstSample; i < currentEnd + pulse.Lenght; i += _tactsPerSample) { samples[sampleIndex++] = pulse.EarBit ? 1.0F : 0.0F; } currentEnd += pulse.Lenght; } _beeperProvider?.AddSoundFrame(samples); _frameBegins += _frameTacts; }
///\brief Checks states / actions and pack data. /// Check inside loop the current action that comes from upper control algorithm. /// Check the states that comes from the client. /// Pack all the control data to byte array package (global data) and fire event. private void packagingLoop() { bool newData = false; Pulses pulses = new Pulses(); int[] pulseData = pulses.Pulse_sinus; Byte[] velocityValueTemp = new Byte[2]; while (!globalDataSet.AbortServerOperation) { // Iterate through motor array for (int motorCounter = 0; motorCounter < globalDataSet.MAX_MOTOR_AMOUNT; motorCounter++) { //Debug.WriteLine("Motor " + motorCounter + ": " + dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.action]); // Send nothing if (((int)globalDataSet.Motor[motorCounter].Action == (int)GlobalDataSet.RobotActions.doNothing)) { // Set indicator led to green globalDataSet.IndicatorLed[motorCounter] = true; dataPackage_out[motorCounter][0] = Convert.ToByte(globalDataSet.Motor[motorCounter].Action); dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.motorId] = (byte)globalDataSet.Motor[motorCounter].Id; newData = true; } if (globalDataSet.Motor[motorCounter].Action != (int)GlobalDataSet.RobotActions.doNothing) { globalDataSet.IndicatorLed[motorCounter] = false; } // Send request to disable pid controller if (((int)globalDataSet.Motor[motorCounter].Action == (int)GlobalDataSet.RobotActions.disablePidController)) { dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.action] = Convert.ToByte(globalDataSet.Motor[motorCounter].Action); dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.motorId] = (byte)globalDataSet.Motor[motorCounter].Id; newData = true; } // Send request to enable pid controller if (((int)globalDataSet.Motor[motorCounter].Action == (int)GlobalDataSet.RobotActions.enablePidController)) { dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.action] = Convert.ToByte(globalDataSet.Motor[motorCounter].Action); dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.motorId] = (byte)globalDataSet.Motor[motorCounter].Id; newData = true; } // Send request to save ref pos if (((int)globalDataSet.Motor[motorCounter].Action == (int)GlobalDataSet.RobotActions.saveRefPosToEeprom)) { dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.action] = Convert.ToByte(globalDataSet.Motor[motorCounter].Action); dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.motorId] = (byte)globalDataSet.Motor[motorCounter].Id; newData = true; } // Send request to save act pos if (((int)globalDataSet.Motor[motorCounter].Action == (int)GlobalDataSet.RobotActions.saveActPosToEeprom)) { dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.action] = Convert.ToByte(globalDataSet.Motor[motorCounter].Action); dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.motorId] = (byte)globalDataSet.Motor[motorCounter].Id; newData = true; } // Send control data if (((int)globalDataSet.Motor[motorCounter].Action == (int)GlobalDataSet.RobotActions.newPosition)) { globalDataSet.Motor[motorCounter].ActionIsSet = true; // Set action dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.action] = Convert.ToByte(globalDataSet.Motor[motorCounter].Action); // Set motor id dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.motorId] = (byte)(globalDataSet.Motor[motorCounter].Id); // Set direction and angle // UPDATE if (globalDataSet.Motor[motorCounter].Angle < 0) { angleValueTemp = (short)(globalDataSet.Motor[motorCounter].Angle * (-1)); dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.motorDir] = (byte)0; } else { angleValueTemp = (short)(globalDataSet.Motor[motorCounter].Angle); dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.motorDir] = (byte)1; } //byte[] angleValue_converted = BitConverter.GetBytes(angleValueTemp); //if (BitConverter.IsLittleEndian) Array.Reverse(angleValue_converted); //dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.angle_1] = angleValue_converted[0]; //dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.angle_2] = angleValue_converted[1]; dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.angle] = (byte)angleValueTemp; // Set velocity velocityValueTemp = BitConverter.GetBytes(globalDataSet.Motor[motorCounter].Velocity); dataPackage_out[motorCounter][(int)GlobalDataSet.Outgoing_Package_Content.velocity] = velocityValueTemp[0]; newData = true; } if (newData & (motorCounter == globalDataSet.Motor.Length - 1)) { newData = false; // ENC28J60 // Copy 2D array to 1D array with 6*5 bytes for (int i = 0; i < this.globalDataSet.MAX_MOTOR_AMOUNT; i++) { for (int j = 0; j < 5; j++) { dataPackage_conc_out[j + (i * 5)] = dataPackage_out[i][j]; } } this.newPackageEvent(dataPackage_conc_out); // RASPBERRY PI //this.newPackageEvent(dataPackage_out); } } } }
/// <summary> /// Allow the device to react to the start of a new frame /// </summary> public void OnNewFrame() { Pulses.Clear(); LastPulseTact = 0; FrameCount++; }
/// <summary> /// New frame starts /// </summary> public void StartFrame() { Pulses.Clear(); LastPulseTState = 0; }