diff --git a/wpilibc/src/main/native/include/frc/AddressableLED.h b/wpilibc/src/main/native/include/frc/AddressableLED.h index 3af9008bfa..f9aae72785 100644 --- a/wpilibc/src/main/native/include/frc/AddressableLED.h +++ b/wpilibc/src/main/native/include/frc/AddressableLED.h @@ -33,6 +33,15 @@ class AddressableLED : public ErrorBase { b = _b; padding = 0; } + + /** + * A helper method to set all values of the LED. + */ + void SetLED(int r, int g, int b) { + this->r = r; + this->g = g; + this->b = b; + } }; /** diff --git a/wpilibcExamples/src/main/cpp/examples/AddressableLED/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/AddressableLED/cpp/Robot.cpp new file mode 100644 index 0000000000..aa758e31a4 --- /dev/null +++ b/wpilibcExamples/src/main/cpp/examples/AddressableLED/cpp/Robot.cpp @@ -0,0 +1,50 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include + +#include +#include +#include + +class Robot : public frc::TimedRobot { + // PWM port 0 + // Must be a PWM header, not MXP or DIO + frc::AddressableLED m_led{0}; + std::array m_ledBuffer; // Reuse the buffer + int m_count = 0; + + public: + void RobotInit() override { + // Default to a length of 12, start empty output + // Length is expensive to set, so only set it once, then just update data + m_led.SetLength(12); + m_led.SetData(m_ledBuffer); + m_led.Start(); + } + + void RobotPeriodic() override { + // Zero out all LEDs + for (auto& ledData : m_ledBuffer) { + ledData.SetLED(0, 0, 0); + } + + // Set 1 single LED to red + m_ledBuffer[m_count].SetLED(50, 0, 0); + + // Continue moving LED + m_count++; + if (m_count >= 12) m_count = 0; + + // Buffer must be written to update. + m_led.SetData(m_ledBuffer); + } +}; + +#ifndef RUNNING_FRC_TESTS +int main() { return frc::StartRobot(); } +#endif diff --git a/wpilibcExamples/src/main/cpp/examples/DMA/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/DMA/cpp/Robot.cpp new file mode 100644 index 0000000000..a4030a5bb5 --- /dev/null +++ b/wpilibcExamples/src/main/cpp/examples/DMA/cpp/Robot.cpp @@ -0,0 +1,82 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +class Robot : public frc::TimedRobot { + frc::DMA m_dma; // DMA object + + // DMA needs a trigger, can use an output as trigger. + // 8 Triggers exist per DMA object, can be triggered on any + // DigitalSource. + frc::DigitalOutput m_dmaTrigger{2}; + + // Analog input to read with DMA + frc::AnalogInput m_analogInput{0}; + + // Encoder to read with DMA + frc::Encoder m_encoder{0, 1}; + + public: + void RobotInit() override { + // Trigger on falling edge of dma trigger output + m_dma.SetExternalTrigger(&m_dmaTrigger, false, true); + + // Add inputs we want to read via DMA + m_dma.AddAnalogInput(&m_analogInput); + m_dma.AddEncoder(&m_encoder); + m_dma.AddEncoderPeriod(&m_encoder); + + // Make sure trigger is set to off. + m_dmaTrigger.Set(true); + + // Start DMA. No triggers or inputs can be added after this call + // unless DMA is stopped. + m_dma.StartDMA(1024); + } + + void RobotPeriodic() override { + // Manually Trigger DMA read + m_dmaTrigger.Set(false); + + // Need to create a sample. + frc::DMASample sample; + int32_t remaining = 0; + int32_t status = 0; + // Update our sample. remaining is the number of samples remaining in the + // buffer status is more specfic error messages if readStatus is not OK. + // Wait 1ms if buffer is empty + HAL_DMAReadStatus readStatus = + sample.Update(&m_dma, 1_ms, &remaining, &status); + + if (readStatus == HAL_DMA_OK) { + // Status value in all these reads should be checked, a non 0 value means + // value could not be read + + // If DMA is good, values exist + auto encoderDistance = sample.GetEncoderDistance(&m_encoder, &status); + // Period is not scaled, and is a raw value + auto encoderPeriod = sample.GetEncoderPeriodRaw(&m_encoder, &status); + auto analogVoltage = + sample.GetAnalogInputVoltage(&m_analogInput, &status); + + frc::SmartDashboard::PutNumber("Distance", encoderDistance); + frc::SmartDashboard::PutNumber("Period", encoderPeriod); + frc::SmartDashboard::PutNumber("Input", analogVoltage); + } + } +}; + +#ifndef RUNNING_FRC_TESTS +int main() { return frc::StartRobot(); } +#endif diff --git a/wpilibcExamples/src/main/cpp/examples/DutyCycleEncoder/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/DutyCycleEncoder/cpp/Robot.cpp new file mode 100644 index 0000000000..dccdab4b00 --- /dev/null +++ b/wpilibcExamples/src/main/cpp/examples/DutyCycleEncoder/cpp/Robot.cpp @@ -0,0 +1,48 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +class Robot : public frc::TimedRobot { + frc::DigitalInput m_input{0}; // Input channel + + // Duty cycle encoder + frc::DutyCycleEncoder m_dutyCycleEncoder{m_input}; + + public: + void RobotInit() override { + // Set to 0.5 units per rotation + m_dutyCycleEncoder.SetDistancePerRotation(0.5); + } + + void RobotPeriodic() override { + // Connected can be checked, and uses the frequency of the encoder + auto connected = m_dutyCycleEncoder.IsConnected(); + + // Duty Cycle Frequency in Hz + auto frequency = m_dutyCycleEncoder.GetFrequency(); + + // Output of encoder + auto output = m_dutyCycleEncoder.Get(); + + // Output scaled by DistancePerPulse + auto distance = m_dutyCycleEncoder.GetDistance(); + + frc::SmartDashboard::PutBoolean("Connected", connected); + frc::SmartDashboard::PutNumber("Frequency", frequency); + frc::SmartDashboard::PutNumber("Output", output.to()); + frc::SmartDashboard::PutNumber("Distance", distance); + } +}; + +#ifndef RUNNING_FRC_TESTS +int main() { return frc::StartRobot(); } +#endif diff --git a/wpilibcExamples/src/main/cpp/examples/DutyCycleInput/cpp/Robot.cpp b/wpilibcExamples/src/main/cpp/examples/DutyCycleInput/cpp/Robot.cpp new file mode 100644 index 0000000000..1a113aebfb --- /dev/null +++ b/wpilibcExamples/src/main/cpp/examples/DutyCycleInput/cpp/Robot.cpp @@ -0,0 +1,35 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +class Robot : public frc::TimedRobot { + frc::DigitalInput m_input{0}; // Input channel + frc::DutyCycle m_dutyCycle{m_input}; // Duty cycle input + + public: + void RobotInit() override {} + + void RobotPeriodic() override { + // Duty Cycle Frequency in Hz + auto frequency = m_dutyCycle.GetFrequency(); + + // Output of duty cycle, ranging from 0 to 1 + // 1 is fully on, 0 is fully off + auto output = m_dutyCycle.GetOutput(); + + frc::SmartDashboard::PutNumber("Frequency", frequency); + frc::SmartDashboard::PutNumber("Duty Cycle", output); + } +}; + +#ifndef RUNNING_FRC_TESTS +int main() { return frc::StartRobot(); } +#endif diff --git a/wpilibcExamples/src/main/cpp/examples/examples.json b/wpilibcExamples/src/main/cpp/examples/examples.json index edcf8ff4b2..8f78436829 100644 --- a/wpilibcExamples/src/main/cpp/examples/examples.json +++ b/wpilibcExamples/src/main/cpp/examples/examples.json @@ -428,5 +428,45 @@ "foldername": "TankDriveXboxController", "gradlebase": "cpp", "commandversion": 1 + }, + { + "name": "Duty Cycle Encoder", + "description": "Demonstrates the use of the Duty Cycle Encoder class", + "tags": [ + "Getting Started with C++" + ], + "foldername": "DutyCycleEncoder", + "gradlebase": "cpp", + "commandversion": 2 + }, + { + "name": "Duty Cycle Input", + "description": "Demonstrates the use of the Duty Cycle class", + "tags": [ + "Getting Started with C++" + ], + "foldername": "DutyCycleInput", + "gradlebase": "cpp", + "commandversion": 2 + }, + { + "name": "Addressable LED", + "description": "Demonstrates the use of the Addressable LED class", + "tags": [ + "Getting Started with C++" + ], + "foldername": "AddressableLED", + "gradlebase": "cpp", + "commandversion": 2 + }, + { + "name": "DMA", + "description": "Demonstrates the use of the DMA class", + "tags": [ + "Advanced C++" + ], + "foldername": "DMA", + "gradlebase": "cpp", + "commandversion": 2 } ] diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AddressableLEDBuffer.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AddressableLEDBuffer.java index 926ec13a40..e7586f3bdd 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AddressableLEDBuffer.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AddressableLEDBuffer.java @@ -37,4 +37,13 @@ public class AddressableLEDBuffer { m_buffer[(index * 4) + 2] = (byte) r; m_buffer[(index * 4) + 3] = 0; } + + /** + * Gets the buffer length. + * + * @return the buffer length + */ + public int getLength() { + return m_buffer.length / 4; + } } diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/addressableled/Main.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/addressableled/Main.java new file mode 100644 index 0000000000..2feaca202a --- /dev/null +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/addressableled/Main.java @@ -0,0 +1,29 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj.examples.addressableled; + +import edu.wpi.first.wpilibj.RobotBase; + +/** + * Do NOT add any static variables to this class, or any initialization at all. + * Unless you know what you are doing, do not modify this file except to + * change the parameter class to the startRobot call. + */ +public final class Main { + private Main() { + } + + /** + * Main initialization function. Do not perform any initialization here. + * + *

If you change your main robot class, change the parameter type. + */ + public static void main(String... args) { + RobotBase.startRobot(Robot::new); + } +} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/addressableled/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/addressableled/Robot.java new file mode 100644 index 0000000000..7e0bb7f54c --- /dev/null +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/addressableled/Robot.java @@ -0,0 +1,57 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj.examples.addressableled; + +import edu.wpi.first.wpilibj.AddressableLED; +import edu.wpi.first.wpilibj.AddressableLEDBuffer; +import edu.wpi.first.wpilibj.TimedRobot; + +public class Robot extends TimedRobot { + private AddressableLED m_led; + private AddressableLEDBuffer m_ledBuffer; + private int m_count; + + @Override + public void robotInit() { + // PWM port 0 + // Must be a PWM header, not MXP or DIO + m_led = new AddressableLED(0); + + // Default to a length of 12, start empty output + // Length is expensive to set, so only set it once, then just update data + m_led.setLength(12); + + // Reuse buffer + m_ledBuffer = new AddressableLEDBuffer(12); + + m_led.setData(m_ledBuffer); + m_led.start(); + + } + + @Override + public void robotPeriodic() { + // Zero out all LEDS + for (int i = 0; i < m_ledBuffer.getLength(); i++) { + m_ledBuffer.setLED(i, 0, 0, 0); + } + + // Set 1 single LED to red + m_ledBuffer.setLED(m_count, 50, 0, 0); + + // Continue moving LED + m_count++; + if (m_count >= 12) { + m_count = 0; + } + + // Buffer must be written to update. + m_led.setData(m_ledBuffer); + } + +} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleencoder/Main.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleencoder/Main.java new file mode 100644 index 0000000000..a051005dad --- /dev/null +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleencoder/Main.java @@ -0,0 +1,29 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj.examples.dutycycleencoder; + +import edu.wpi.first.wpilibj.RobotBase; + +/** + * Do NOT add any static variables to this class, or any initialization at all. + * Unless you know what you are doing, do not modify this file except to + * change the parameter class to the startRobot call. + */ +public final class Main { + private Main() { + } + + /** + * Main initialization function. Do not perform any initialization here. + * + *

If you change your main robot class, change the parameter type. + */ + public static void main(String... args) { + RobotBase.startRobot(Robot::new); + } +} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleencoder/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleencoder/Robot.java new file mode 100644 index 0000000000..1689d17eec --- /dev/null +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleencoder/Robot.java @@ -0,0 +1,49 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj.examples.dutycycleencoder; + +import edu.wpi.first.wpilibj.DigitalInput; +import edu.wpi.first.wpilibj.DutyCycleEncoder; +import edu.wpi.first.wpilibj.TimedRobot; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; + +@SuppressWarnings({"PMD.SingularField"}) +public class Robot extends TimedRobot { + private DigitalInput m_input; + private DutyCycleEncoder m_dutyCycleEncoder; + + @Override + public void robotInit() { + m_input = new DigitalInput(0); + m_dutyCycleEncoder = new DutyCycleEncoder(m_input); + + // Set to 0.5 units per rotation + m_dutyCycleEncoder.setDistancePerRotation(0.5); + } + + @Override + public void robotPeriodic() { + // Connected can be checked, and uses the frequency of the encoder + boolean connected = m_dutyCycleEncoder.isConnected(); + + // Duty Cycle Frequency in Hz + int frequency = m_dutyCycleEncoder.getFrequency(); + + // Output of encoder + double output = m_dutyCycleEncoder.get(); + + // Output scaled by DistancePerPulse + double distance = m_dutyCycleEncoder.getDistance(); + + SmartDashboard.putBoolean("Connected", connected); + SmartDashboard.putNumber("Frequency", frequency); + SmartDashboard.putNumber("Output", output); + SmartDashboard.putNumber("Distance", distance); + } + +} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleinput/Main.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleinput/Main.java new file mode 100644 index 0000000000..a7cbfc09de --- /dev/null +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleinput/Main.java @@ -0,0 +1,29 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj.examples.dutycycleinput; + +import edu.wpi.first.wpilibj.RobotBase; + +/** + * Do NOT add any static variables to this class, or any initialization at all. + * Unless you know what you are doing, do not modify this file except to + * change the parameter class to the startRobot call. + */ +public final class Main { + private Main() { + } + + /** + * Main initialization function. Do not perform any initialization here. + * + *

If you change your main robot class, change the parameter type. + */ + public static void main(String... args) { + RobotBase.startRobot(Robot::new); + } +} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleinput/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleinput/Robot.java new file mode 100644 index 0000000000..657dc9b45f --- /dev/null +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/dutycycleinput/Robot.java @@ -0,0 +1,39 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.first.wpilibj.examples.dutycycleinput; + +import edu.wpi.first.wpilibj.DigitalInput; +import edu.wpi.first.wpilibj.DutyCycle; +import edu.wpi.first.wpilibj.TimedRobot; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; + +@SuppressWarnings({"PMD.SingularField"}) +public class Robot extends TimedRobot { + private DigitalInput m_input; + private DutyCycle m_dutyCycle; + + @Override + public void robotInit() { + m_input = new DigitalInput(0); + m_dutyCycle = new DutyCycle(m_input); + } + + @Override + public void robotPeriodic() { + // Duty Cycle Frequency in Hz + int frequency = m_dutyCycle.getFrequency(); + + // Output of duty cycle, ranging from 0 to 1 + // 1 is fully on, 0 is fully off + double output = m_dutyCycle.getOutput(); + + SmartDashboard.putNumber("Frequency", frequency); + SmartDashboard.putNumber("Duty Cycle", output); + } + +} diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json index 0d6a6e4c4b..212d20bddf 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/examples.json @@ -449,5 +449,38 @@ "gradlebase": "java", "mainclass": "Main", "commandversion": 1 + }, + { + "name": "Duty Cycle Encoder", + "description": "Demonstrates the use of the Duty Cycle Encoder class", + "tags": [ + "Getting Started with Java" + ], + "foldername": "dutycycleencoder", + "gradlebase": "java", + "mainclass": "Main", + "commandversion": 2 + }, + { + "name": "Duty Cycle Input", + "description": "Demonstrates the use of the Duty Cycle class", + "tags": [ + "Getting Started with Java" + ], + "foldername": "dutycycleinput", + "gradlebase": "java", + "mainclass": "Main", + "commandversion": 2 + }, + { + "name": "Addressable LED", + "description": "Demonstrates the use of the Addressable LED class", + "tags": [ + "Getting Started with Java" + ], + "foldername": "addressableled", + "gradlebase": "java", + "mainclass": "Main", + "commandversion": 2 } ]