/// <summary> /// If a servo motor is attached, set its angle. /// </summary> /// <param name="pin">The id of the pin.</param> /// <param name="angle">The angle to set in [0..180].</param> public void SetPinServoAngle(int pin, int angle) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return; } if (pin < 0 || pin > 2) { return; } if (angle < 0 || angle > 180) { return; } if (_curr.Pins[pin].Busy) { return; } // Don't send the same value over and over. if (_curr.Pins[pin].Mode == EPinOperatingMode.Analog && _curr.Pins[pin].Value == angle) { return; } _curr.Pins[pin].Mode = EPinOperatingMode.Analog; _curr.Pins[pin].Value = angle; MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_SET_PIN_SERVO_VALUE); writer.WriteU8Hex(pin); writer.WriteU8Hex(angle); QueueForSend(writer.ToString()); }
/// <summary> /// Set the pin's PWM pulse frequency, producing a pulse-width-modulated (PWM) signal. (Frequency only). /// Will configure the pin for analog output if necessary. /// </summary> /// <param name="pin">The id of the pin.</param> /// <param name="frequencyHz">The frequency in Hertz.</param> /// <param name="multiplier">The frequency multiplier. Value of 1000 would convert the frequency to KHz, for example.</param> public void SetPinPwmFrequency(int pin, int frequencyHz, int multiplier) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return; } if (pin < 0 || pin > 2) { return; } if (_curr.Pins[pin].Busy) { return; } if (_curr.Pins[pin].Mode == EPinOperatingMode.Analog && _curr.Pins[pin].FrequencyHz == frequencyHz && _curr.Pins[pin].FrequencyMultiplier == multiplier) { return; } _curr.Pins[pin].Mode = EPinOperatingMode.Analog; _curr.Pins[pin].FrequencyHz = frequencyHz; _curr.Pins[pin].FrequencyMultiplier = multiplier; MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_SET_PIN_PWM_OUT); writer.WriteU8Hex(pin); writer.WriteU16Hex(_curr.Pins[pin].FrequencyHz); writer.WriteU16Hex(_curr.Pins[pin].FrequencyMultiplier); writer.WriteU16Hex(_curr.Pins[pin].DutyCycle); QueueForSend(writer.ToString()); }
/// <summary> /// Sets the brightness of a single pixel. /// </summary> /// <param name="x">The pixel x coordinate in [0..4].</param> /// <param name="y">The pixel y coordinate in [0..4].</param> /// <param name="brightness">The pixel brightness in [0..255].</param> public void SetPixel(int x, int y, int brightness) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return; } if (x < 0 || x > 4) { return; } if (y < 0 || y > 4) { return; } if (brightness < 0 || brightness > 0xff) { return; } if (DisplayBusy) { // System.Diagnostics.Debug.WriteLine("Display Busy"); return; } MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_SET_PIXEL); writer.WriteU8Hex(x); writer.WriteU8Hex(y); writer.WriteU8Hex(brightness); QueueForSend(writer.ToString()); }
private void Ping() { // Send a Ping even if the device isn't READY. If we get a response, and // if version numbers match, we'll update the device to the READY state. if (!_port.IsOpen) { return; } MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_PING); QueueForSend(writer.ToString()); }
private void Start() { // A Start command is like a Ping, but also causes the microbit to reset // to the initial state (display blank, pins off). // Send a Start even if the device isn't READY. If we get a response, and // if version numbers match, we'll update the device to the READY state. if (!_port.IsOpen) { return; } MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_START); QueueForSend(writer.ToString()); }
/// <summary> /// Scrolls a series of images across the microbit screen. /// </summary> /// <param name="images">The list of images to scroll.</param> /// <param name="delayMs">The delay between scroll steps.</param> /// <param name="brightness">The brightness of the screen.</param> public void ScrollImages(List <MicroBitImage> images, int delayMs = DefaultScrollSpeed, int brightness = DefaultBrightness) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return; } if (images.Count() == 0 || images.Count() > 0xff) { return; } if (delayMs < 0 || delayMs > 0xffff) { return; } if (brightness < 0 || brightness > 0xff) { return; } if (DisplayBusy) { // System.Diagnostics.Debug.WriteLine("Display Busy"); return; } // Block the display. int durationMs = images.Count * delayMs * 5; _displayFreeTime = DateTime.Now + TimeSpan.FromMilliseconds(durationMs); MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_SCROLL_IMAGES); writer.WriteU16Hex(delayMs); writer.WriteU8Hex(brightness); writer.WriteU8Hex(images.Count()); foreach (MicroBitImage image in images) { string packed = image.Packed; writer.WriteChars(packed); } QueueForSend(writer.ToString()); }
/// <summary> /// If a PC speaker is attached, play musical notes through it. /// </summary> /// <param name="pin">The id of the pin.</param> /// <param name="durationMs">The duration of each note.</param> /// <param name="tones">The list of musical notes to play.</param> public void PlayTones(int pin, int durationMs, int[] tones) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return; } if (pin < 0 || pin > 2) { return; } if (durationMs < 0 || durationMs > 0xffff) { return; } if (tones.Length == 0 || tones.Length > 0xff) { return; } if (_curr.Pins[pin].Busy) { return; } _curr.Pins[pin].Busy = true; MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_PLAY_TONES); writer.WriteU8Hex(pin); writer.WriteU16Hex(durationMs); writer.WriteU8Hex(tones.Length); foreach (int tone in tones) { if (tone >= 0 && tone < 256) { writer.WriteU8Hex(tone); } } QueueForSend(writer.ToString()); }
/// <summary> /// Prints a series of images across the microbit screen, each with its own brightness and duration. /// </summary> /// <param name="frames">The set of display frames to print.</param> public void PrintDisplayFrames(IEnumerable <MicroBitDisplayFrame> frames) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return; } if (frames.Count() == 0 || frames.Count() > 0xff) { return; } if (DisplayBusy) { // System.Diagnostics.Debug.WriteLine("Display Busy"); return; } int totalDurationMs = 0; MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_PRINT_DISPLAY_FRAMES); writer.WriteU8Hex(frames.Count()); foreach (MicroBitDisplayFrame frame in frames) { int durationMs = (int)(frame.Duration * 1000); int brightness = frame.Brightness; string packed = frame.Image.Packed; durationMs = MyMath.Clamp(durationMs, 0, 0xffff); brightness = MyMath.Clamp(brightness, 0, 0xff); writer.WriteU16Hex(durationMs); writer.WriteU8Hex(brightness); writer.WriteChars(packed); totalDurationMs += durationMs; } // Block the display _displayFreeTime = DateTime.Now + TimeSpan.FromMilliseconds(totalDurationMs); QueueForSend(writer.ToString()); }
/// <summary> /// Set the pin's PWM pulse width, producing a pulse-width-modulated (PWM) signal. (Duty cycle only). /// Will configure the pin for analog output if necessary. /// </summary> /// <param name="pin">The id of the pin.</param> /// <param name="dutyCyclePct">Percent of the cycle in which the signal is "on", in [0..1] range, where 0 is never on, and 1 is always on. A value of 0.5 would be 50% on.</param> public void SetPinPwmDutyCycle(int pin, float dutyCyclePct) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return; } if (pin < 0 || pin > 2) { return; } if (_curr.Pins[pin].Busy) { return; } if (dutyCyclePct < 0 || dutyCyclePct > 1) { return; } int dutyCycle = (int)(dutyCyclePct * 1023); if (_curr.Pins[pin].Mode == EPinOperatingMode.Analog && _curr.Pins[pin].DutyCycle == dutyCycle) { return; } _curr.Pins[pin].DutyCycle = dutyCycle; MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_SET_PIN_PWM_OUT); writer.WriteU8Hex(pin); writer.WriteU16Hex(_curr.Pins[pin].FrequencyHz); writer.WriteU16Hex(_curr.Pins[pin].FrequencyMultiplier); writer.WriteU16Hex(_curr.Pins[pin].DutyCycle); QueueForSend(writer.ToString()); }
/// <summary> /// Read the pin's last known value. Will configure the pin for input if necessary. /// </summary> /// <param name="pin">The id of the pin.</param> /// <param name="operatingMode">The operating mode of the pin.</param> /// <param name="pullMode">The pull mode of the pin. Applicable for digital inputs only.</param> /// <returns>The most recent sampled pin value.</returns> public int ReadPinValue(int pin, EPinOperatingMode operatingMode, EPinPullMode pullMode = EPinPullMode.PullNone) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return(0); } if (pin < 0 || pin > 2) { return(0); } // If this pin is already configured for input, return the current value. if (_curr.Pins[pin].Mode == operatingMode) { return(_curr.Pins[pin].Value); } _curr.Pins[pin].Mode = operatingMode; _curr.Pins[pin].Value = 0; MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_CONFIG_INPUT_PIN); writer.WriteU8Hex(pin); if (operatingMode == EPinOperatingMode.Analog) { writer.WriteU8Hex((int)EPinAnalogMode.In); } else { writer.WriteU8Hex((int)EPinDigitalMode.In); writer.WriteU8Hex((int)pullMode); } QueueForSend(writer.ToString()); return(0); }
/// <summary> /// Prints a text string on the microbit screen, one character at a time. /// </summary> /// <param name="str">The string to print.</param> /// <param name="durationMs">The duration of time to display each character.</param> /// <param name="brightness">The brightness of the screen.</param> public void PrintText(string str, int durationMs = DefaultPrintSpeed, int brightness = DefaultBrightness) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return; } if (str.Length == 0 || str.Length > 0xff) { return; } if (durationMs < 0 || durationMs > 0xffff) { return; } if (brightness < 0 || brightness > 0xff) { return; } if (DisplayBusy) { // System.Diagnostics.Debug.WriteLine("Display Busy"); return; } // Block the display int totalDurationMs = str.Length * durationMs; _displayFreeTime = DateTime.Now + TimeSpan.FromMilliseconds(totalDurationMs); MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_PRINT_TEXT); writer.WriteU16Hex(durationMs); writer.WriteU8Hex(brightness); writer.WriteString(str); QueueForSend(writer.ToString()); }
/// <summary> /// Set the pin's output value. Will configure the pin for output if necessary. /// </summary> /// <param name="pin">The id of the pin.</param> /// <param name="value">The value to set.</param> /// <param name="operatingMode">The operating mode of the pin.</param> public void SetPinValue(int pin, int value, EPinOperatingMode operatingMode) { if (!_port.IsOpen || _status != EDeviceStatus.READY) { return; } if (pin < 0 || pin > 2) { return; } if (value < 0 || value > 0xff) { return; } if (_curr.Pins[pin].Busy) { return; } // Don't send the same value over and over. if (_curr.Pins[pin].Mode == operatingMode && _curr.Pins[pin].Value == value) { return; } _curr.Pins[pin].Mode = operatingMode; _curr.Pins[pin].Value = value; MicroBitMessageWriter writer = new MicroBitMessageWriter(); writer.WriteChar(Protocol.CMD_SET_PIN_VALUE); writer.WriteU8Hex(pin); writer.WriteU8Hex(operatingMode == EPinOperatingMode.Digital ? (int)EPinDigitalMode.Out : (int)EPinAnalogMode.Out); writer.WriteU16Hex(value); QueueForSend(writer.ToString()); }